/* This file is part of GNU Taler (C) 2022 Taler Systems S.A. GNU Taler is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Taler; see the file COPYING. If not, see */ import { css } from "@linaria/core"; import { ComponentChildren, createContext, h, VNode } from "preact"; import { useContext, useMemo, useState } from "preact/hooks"; // eslint-disable-next-line import/extensions import { Colors } from "../style.js"; export interface Props { color: Colors; disabled: boolean; error?: string | Error; focused: boolean; fullWidth: boolean; hiddenLabel: boolean; required: boolean; variant: "filled" | "outlined" | "standard"; margin: "none" | "normal" | "dense"; size: "medium" | "small"; children: ComponentChildren; } export const root = css` display: inline-flex; flex-direction: column; position: relative; min-width: 0px; padding: 0px; margin: 0px; border: 0px; vertical-align: top; `; const marginVariant = { none: "", normal: css` margin-top: 16px; margin-bottom: 8px; `, dense: css` margin-top: 8px; margin-bottom: 4px; `, }; const fullWidthStyle = css` width: 100%; `; export const FormControlContext = createContext(null); export function FormControl({ color = "primary", disabled = false, error = undefined, focused: visuallyFocused, fullWidth = false, hiddenLabel = false, margin = "none", required = false, size = "medium", variant = "filled", children, }: Partial): VNode { const [filled, setFilled] = useState(false); const [focusedState, setFocused] = useState(visuallyFocused); const focused = focusedState !== undefined && !disabled ? focusedState : false; const value: FCCProps = { color, disabled, error, filled, focused, fullWidth, hiddenLabel, size, onBlur: () => { setFocused(false); }, onEmpty: () => { setFilled(false); }, onFilled: () => { setFilled(true); }, onFocus: () => { setFocused(true); }, required, variant, }; return (
{children}
); } export interface FCCProps { // adornedStart, // setAdornedStart, color: Colors; disabled: boolean; error: string | undefined | Error; filled: boolean; focused: boolean; fullWidth: boolean; hiddenLabel: boolean; size: "medium" | "small"; onBlur: () => void; onEmpty: () => void; onFilled: () => void; onFocus: () => void; // registerEffect, required: boolean; variant: "filled" | "outlined" | "standard"; } const defaultContextValue: FCCProps = { color: "primary", disabled: false, error: undefined, filled: false, focused: false, fullWidth: false, hiddenLabel: false, size: "medium", onBlur: () => null, onEmpty: () => null, onFilled: () => null, onFocus: () => null, required: false, variant: "filled", }; function withoutUndefinedProperties(obj: any): any { return Object.keys(obj).reduce((acc, key) => { const _acc: any = acc; if (obj[key] !== undefined && obj[key] !== false) _acc[key] = obj[key]; return _acc; }, {}); } export function useFormControl(props: Partial = {}): FCCProps { const ctx = useContext(FormControlContext); const cleanedProps = withoutUndefinedProperties(props); return useMemo(() => { return !ctx ? { ...defaultContextValue, ...cleanedProps } : { ...ctx, ...cleanedProps }; }, [cleanedProps, ctx]); }