From ae1ccd1ff127663075447cd4dda359ef58e18b2b Mon Sep 17 00:00:00 2001 From: Christian Gil Date: Mon, 26 Feb 2024 13:01:29 -0600 Subject: [PATCH] feat: New FormField component --- src/runtime/components/forms/Combobox.vue | 32 ++++-------- src/runtime/components/forms/FormField.vue | 57 +++++++++++++++++++++ src/runtime/components/forms/FormInput.vue | 58 ++++++---------------- src/runtime/types/combobox.d.ts | 11 +--- src/runtime/types/formField.d.ts | 14 ++++++ src/runtime/types/formInput.d.ts | 17 +++---- src/runtime/types/index.d.ts | 1 + src/runtime/ui.config/combobox.ts | 4 +- src/runtime/ui.config/formField.ts | 4 ++ src/runtime/ui.config/formInput.ts | 22 +++----- src/runtime/ui.config/index.ts | 1 + src/runtime/utils/forms.ts | 13 +++++ 12 files changed, 132 insertions(+), 102 deletions(-) create mode 100644 src/runtime/components/forms/FormField.vue create mode 100644 src/runtime/types/formField.d.ts create mode 100644 src/runtime/ui.config/formField.ts create mode 100644 src/runtime/utils/forms.ts diff --git a/src/runtime/components/forms/Combobox.vue b/src/runtime/components/forms/Combobox.vue index 5bf1c3c..e9bd839 100644 --- a/src/runtime/components/forms/Combobox.vue +++ b/src/runtime/components/forms/Combobox.vue @@ -15,12 +15,14 @@ type UiConfig = Partial & { strategy?: Strategy }; + + + + diff --git a/src/runtime/components/forms/FormInput.vue b/src/runtime/components/forms/FormInput.vue index 2ba77e2..cf507e4 100644 --- a/src/runtime/components/forms/FormInput.vue +++ b/src/runtime/components/forms/FormInput.vue @@ -15,27 +15,25 @@ type UiConfig = Partial & { strategy?: Strategy }; diff --git a/src/runtime/types/combobox.d.ts b/src/runtime/types/combobox.d.ts index 50f9b0c..49209e6 100644 --- a/src/runtime/types/combobox.d.ts +++ b/src/runtime/types/combobox.d.ts @@ -1,3 +1,4 @@ +import type { FormFieldProps } from '#ui/types'; import type { ComboboxContentProps, ComboboxRootProps } from 'radix-vue'; export interface ComboboxItem { @@ -8,19 +9,12 @@ export interface ComboboxItem { export type ComboboxOptions = Record | ComboboxItem[]; -export interface ComboboxProps { - name: string; - label?: string; - message?: string; +export interface ComboboxProps extends Omit { emptyMsg?: string; placeholder?: string; searchPlaceholder?: string; - error?: boolean; multiple?: boolean; - readOnly?: boolean; - disabled?: boolean; - mandatory?: boolean; prefixIcon?: string; prefixText?: string; @@ -30,7 +24,6 @@ export interface ComboboxProps { loadingIcon?: string; indicatorIcon?: string; - class?: any; ui?: UiConfig; options?: ComboboxOptions; diff --git a/src/runtime/types/formField.d.ts b/src/runtime/types/formField.d.ts new file mode 100644 index 0000000..3ae7cba --- /dev/null +++ b/src/runtime/types/formField.d.ts @@ -0,0 +1,14 @@ +import type { PrimitiveProps } from 'radix-vue'; + +export interface FormFieldProps extends PrimitiveProps { + name: string; + label?: string; + error?: boolean; + message?: string; + disabled?: boolean; + readOnly?: boolean; + mandatory?: boolean; + + ui?: UiConfig; + class?: any; +} diff --git a/src/runtime/types/formInput.d.ts b/src/runtime/types/formInput.d.ts index 34ee0a5..46759b8 100644 --- a/src/runtime/types/formInput.d.ts +++ b/src/runtime/types/formInput.d.ts @@ -1,24 +1,19 @@ +import type { FormFieldProps } from '#ui/types'; import type { InputHTMLAttributes } from 'vue'; -import type { PrimitiveProps } from 'radix-vue'; -export interface InputProps extends PrimitiveProps { - name: string; - label?: string; - error?: boolean; - message?: string; - readOnly?: boolean; - disabled?: boolean; - mandatory?: boolean; +export interface InputProps extends Omit { prefixIcon?: string; prefixText?: string; suffixIcon?: string; suffixText?: string; placeholder?: string; + type?: InputHTMLAttributes['type']; + /** Controlled input value */ modelValue?: string | number; + /** Uncontrolled default value */ defaultValue?: string | number; - type?: InputHTMLAttributes['type']; + ui?: UiConfig; - class?: any; } diff --git a/src/runtime/types/index.d.ts b/src/runtime/types/index.d.ts index dc5684e..5e50bc4 100644 --- a/src/runtime/types/index.d.ts +++ b/src/runtime/types/index.d.ts @@ -2,6 +2,7 @@ export * from './badge'; export * from './button'; export * from './combobox'; export * from './dropdown'; +export * from './formField'; export * from './formInput'; export * from './link'; export * from './utils'; diff --git a/src/runtime/ui.config/combobox.ts b/src/runtime/ui.config/combobox.ts index e11efd8..7ef75f8 100644 --- a/src/runtime/ui.config/combobox.ts +++ b/src/runtime/ui.config/combobox.ts @@ -2,21 +2,19 @@ import type { ComboboxContentProps } from 'radix-vue'; export default /*ui*/ { anchor: { - wrapper: 'flex flex-col gap-y-1 data-[disabled-mode=disabled]:opacity-70', base: 'flex w-full items-center bg-white group-data-[error]:bg-red-50', rounded: 'rounded-lg', ring: 'focus-within:ring-2 focus-within:ring-primary-600 group-data-[error]:focus-within:ring-red-400', border: 'border border-gray-900/10 group-data-[error]:border-red-800', + icon: 'size-4 text-gray-600 group-data-[error]:text-red-600', font: { value: 'text-sm text-left truncate text-gray-900 group-data-[error]:text-red-800', - message: 'text-xs text-gray-500 group-data-[error]:text-red-600', addons: 'text-sm select-none text-gray-500 group-data-[error]:text-red-600', }, value: { base: 'block h-8 w-full flex-1', padding: 'px-2 py-1.5', }, - icon: 'size-4 text-gray-600 group-data-[error]:text-red-600', }, input: { diff --git a/src/runtime/ui.config/formField.ts b/src/runtime/ui.config/formField.ts new file mode 100644 index 0000000..2103c19 --- /dev/null +++ b/src/runtime/ui.config/formField.ts @@ -0,0 +1,4 @@ +export default /*ui*/ { + wrapper: 'flex flex-col gap-y-1 data-[disabled-mode=disabled]:opacity-70', + message: 'text-xs text-gray-500 group-data-[error]:text-red-600', +}; diff --git a/src/runtime/ui.config/formInput.ts b/src/runtime/ui.config/formInput.ts index 5051b1a..18409e9 100644 --- a/src/runtime/ui.config/formInput.ts +++ b/src/runtime/ui.config/formInput.ts @@ -1,20 +1,14 @@ export default /*ui*/ { - wrapper: 'flex flex-col gap-y-1 data-[disabled-mode=disabled]:opacity-70', - container: { - base: 'flex w-full items-center bg-white group-data-[error]:bg-red-50', - rounded: 'rounded-lg', - ring: 'focus-within:ring-2 focus-within:ring-primary-600 group-data-[error]:focus-within:ring-red-400', - border: 'border border-gray-900/10 group-data-[error]:border-red-800', - }, - font: { - input: - 'text-sm text-gray-900 placeholder:text-gray-400 group-data-[error]:text-red-800 group-data-[error]:placeholder:text-red-500', - addons: 'text-sm select-none text-gray-500 peer-focus:text-primary-600 group-data-[error]:text-red-600', - message: 'text-xs text-gray-500 group-data-[error]:text-red-600', - }, + base: 'flex w-full items-center bg-white group-data-[error]:bg-red-50', + rounded: 'rounded-lg', + ring: 'focus-within:ring-2 focus-within:ring-primary-600 group-data-[error]:focus-within:ring-red-400', + border: 'border border-gray-900/10 group-data-[error]:border-red-800', + icon: 'size-4 text-gray-600 peer-focus:text-primary-600 group-data-[error]:text-red-600 group-data-[error]:peer-focus:text-red-600', + addons: 'text-sm select-none text-gray-500 peer-focus:text-primary-600 group-data-[error]:text-red-600', input: { base: 'block w-full flex-1 border-0 bg-transparent focus:ring-0 group-data-[disabled-mode=disabled]:cursor-not-allowed', padding: 'px-2 py-1.5', + font: + 'text-sm text-gray-900 placeholder:text-gray-400 group-data-[error]:text-red-800 group-data-[error]:placeholder:text-red-500', }, - icon: 'size-4 text-gray-600 peer-focus:text-primary-600 group-data-[error]:text-red-600 group-data-[error]:peer-focus:text-red-600', }; diff --git a/src/runtime/ui.config/index.ts b/src/runtime/ui.config/index.ts index 65228c3..7ec9a34 100644 --- a/src/runtime/ui.config/index.ts +++ b/src/runtime/ui.config/index.ts @@ -14,6 +14,7 @@ export { default as tooltip } from './tooltip'; // Forms export { default as checkbox } from './checkbox'; export { default as combobox } from './combobox'; +export { default as formField } from './formField'; export { default as formInput } from './formInput'; export { default as formLabel } from './formLabel'; export { default as formRadioGroupItem } from './formRadioGroupItem'; diff --git a/src/runtime/utils/forms.ts b/src/runtime/utils/forms.ts new file mode 100644 index 0000000..8489e44 --- /dev/null +++ b/src/runtime/utils/forms.ts @@ -0,0 +1,13 @@ +import UiFormField from '#ui/components/forms/FormField.vue'; +import type { FormFieldProps } from '#ui/types'; + +export const getUiFormFieldProps = (props: any): FormFieldProps => { + const keys = Object.keys(UiFormField.props); + + return keys.reduce((acc, key) => { + if (props[key] !== undefined) { + acc[key] = props[key]; + } + return acc; + }, {}) as FormFieldProps; +};