@js-empire/emperor-ui 1.2.5 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -2
- package/src/components/atoms/color-picker/color-picker.tsx +0 -1
- package/src/components/atoms/color-picker/free-color-picker.tsx +8 -10
- package/src/components/atoms/color-picker/preset-color-picker.tsx +5 -3
- package/src/components/atoms/color-picker/stories/color-picker.stories.tsx +25 -11
- package/src/components/atoms/field/field.tsx +75 -5
- package/src/components/atoms/field/index.ts +2 -0
- package/src/components/atoms/field/units/autocomplete-field.tsx +49 -0
- package/src/components/atoms/field/units/checkbox-field.tsx +35 -0
- package/src/components/atoms/field/units/index.ts +7 -0
- package/src/components/atoms/field/units/input-field.tsx +35 -0
- package/src/components/atoms/field/units/radio-field.tsx +43 -0
- package/src/components/atoms/field/units/select-field.tsx +50 -0
- package/src/components/atoms/field/units/switch-field.tsx +35 -0
- package/src/components/atoms/field/units/textarea-field.tsx +37 -0
- package/src/components/atoms/filter/filter.tsx +2 -1
- package/src/components/atoms/filter/stories/filter.stories.tsx +148 -7
- package/src/components/atoms/filter/units/autocomplete-filter.tsx +38 -11
- package/src/components/atoms/filter/units/checkbox-filter.tsx +16 -6
- package/src/components/atoms/filter/units/checkbox-group-filter.tsx +40 -9
- package/src/components/atoms/filter/units/date-filter.tsx +18 -22
- package/src/components/atoms/filter/units/numeric-filter.tsx +12 -7
- package/src/components/atoms/filter/units/range-filter.tsx +42 -13
- package/src/components/atoms/filter/units/search-filter.tsx +8 -7
- package/src/components/atoms/filter/units/select-filter.tsx +17 -9
- package/src/components/atoms/filter/units/switch-filter.tsx +6 -4
- package/src/components/atoms/uploader/{avatar-label.tsx → components/avatar-label.tsx} +17 -5
- package/src/components/atoms/uploader/components/index.ts +8 -0
- package/src/components/atoms/uploader/components/upload-file-error-box.tsx +40 -0
- package/src/components/atoms/uploader/{upload-file-label.tsx → components/upload-file-label.tsx} +18 -11
- package/src/components/atoms/uploader/index.ts +1 -8
- package/src/components/atoms/uploader/stories/uploader.stories.tsx +17 -10
- package/src/components/molecules/item-card/index.ts +2 -0
- package/src/components/molecules/item-card/item-actions-buttons.tsx +43 -0
- package/src/components/molecules/item-card/item-actions-overlay.tsx +41 -0
- package/src/components/molecules/item-card/item-card-body.tsx +8 -2
- package/src/components/molecules/item-card/item-card-footer.tsx +22 -1
- package/src/components/molecules/item-card/item-card-header.tsx +8 -2
- package/src/components/molecules/item-card/item-card.tsx +39 -1
- package/src/components/molecules/item-card/stories/item-card.stories.tsx +36 -0
- package/src/components/organisms/deletion-confirmor/deletion-confirmor.tsx +114 -0
- package/src/components/organisms/deletion-confirmor/index.ts +3 -0
- package/src/components/organisms/deletion-confirmor/stories/components.tsx +22 -0
- package/src/components/organisms/deletion-confirmor/stories/deletion-confirmor.stories.tsx +78 -0
- package/src/components/organisms/deletion-confirmor/styles/classes.ts +28 -0
- package/src/components/organisms/{filters → deletion-confirmor}/styles/index.ts +1 -0
- package/src/components/organisms/deletion-confirmor/styles/styles.ts +4 -0
- package/src/components/organisms/form-builder/form-builder.stories.tsx +144 -0
- package/src/components/organisms/form-builder/form-builder.tsx +75 -0
- package/src/components/organisms/form-builder/index.ts +1 -0
- package/src/components/organisms/index.ts +2 -1
- package/src/constants/card.tsx +5 -2
- package/src/constants/defaults.ts +40 -0
- package/src/context/form-builder-context.tsx +8 -0
- package/src/context/index.ts +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-filters.ts +2 -2
- package/src/hooks/use-form-builder-context.ts +16 -0
- package/src/hooks/use-uploader.tsx +21 -9
- package/src/i18n/locales/atoms/ar.ts +1 -1
- package/src/i18n/locales/atoms/en.ts +1 -1
- package/src/i18n/locales/organisms/ar.ts +4 -0
- package/src/i18n/locales/organisms/en.ts +4 -0
- package/src/mocks/deletion-confirmor.ts +16 -0
- package/src/mocks/index.ts +2 -0
- package/src/mocks/locales/index.ts +1 -0
- package/src/mocks/locales/uploader.ts +33 -0
- package/src/providers/config-provider.tsx +8 -0
- package/src/providers/form-builder-provider-context.tsx +18 -0
- package/src/providers/index.ts +1 -0
- package/src/styles/globals.css +26 -1
- package/src/styles/hero.ts +1 -0
- package/src/styles/index.css +0 -5
- package/src/types/components/atoms/color-picker/color-picker.ts +10 -1
- package/src/types/components/atoms/field/field.ts +53 -1
- package/src/types/components/atoms/filter/filter.ts +26 -17
- package/src/types/components/atoms/uploader.ts +4 -0
- package/src/types/components/molecules/item-card/item-card.ts +14 -4
- package/src/types/components/organisms/deletion-confirmor/deletion-confirmor.ts +22 -0
- package/src/types/components/organisms/deletion-confirmor/index.ts +1 -0
- package/src/types/components/organisms/form-builder/context.ts +6 -0
- package/src/types/components/organisms/form-builder/form-builder.ts +39 -0
- package/src/types/components/organisms/form-builder/index.ts +2 -0
- package/src/types/components/organisms/index.ts +2 -0
- package/src/types/context/config.ts +2 -0
- package/src/types/context/index.ts +1 -0
- package/src/types/context/theme.ts +33 -0
- package/src/utils/uploader.ts +25 -7
- package/dist/emperor-ui.js +0 -123
- package/dist/emperor-ui.umd.cjs +0 -63
- package/dist/globals.css +0 -1
- package/dist/icons/emperor-ui-logo.ico +0 -0
- package/dist/images/avatar-female.jpg +0 -0
- package/dist/images/avatar-male.jpg +0 -0
- package/dist/images/emperor-ui-logo.png +0 -0
- package/dist/index-BXtdEByK.js +0 -5
- package/dist/index-CDB93OLO.js +0 -55965
- package/dist/index-CYORMghp.js +0 -290
- package/dist/index.d.ts +0 -1090
- package/dist/src-UW24ZMRV-C1Pn8-w8.js +0 -5
- package/src/components/atoms/color-picker/styles/color-picker.css +0 -23
- package/src/components/atoms/field/field.stories.tsx +0 -27
- package/src/components/atoms/uploader/upload-file-error-box.tsx +0 -29
- package/src/components/organisms/filters/filters.stories.tsx +0 -32
- package/src/components/organisms/filters/filters.tsx +0 -36
- package/src/components/organisms/filters/index.ts +0 -1
- package/src/components/organisms/filters/styles/classes.ts +0 -9
- /package/src/components/atoms/uploader/{upload-file-input.tsx → components/upload-file-input.tsx} +0 -0
- /package/src/components/atoms/uploader/{upload-file-listing.tsx → components/upload-file-listing.tsx} +0 -0
- /package/src/components/atoms/uploader/{uploader-title.tsx → components/uploader-title.tsx} +0 -0
- /package/src/components/atoms/uploader/{uploader.tsx → components/uploader.tsx} +0 -0
- /package/src/components/atoms/uploader/{view-image-modal.tsx → components/view-image-modal.tsx} +0 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@js-empire/emperor-ui",
|
|
3
3
|
"description": "They provide the atoms, we provide the empire.",
|
|
4
|
-
"version": "1.2.
|
|
4
|
+
"version": "1.2.7",
|
|
5
5
|
"author": "JS Empire - Mustafa Alhasanat",
|
|
6
6
|
"license": "ISC",
|
|
7
7
|
"type": "module",
|
|
@@ -73,6 +73,8 @@
|
|
|
73
73
|
"@heroui/system": "^2.4.27",
|
|
74
74
|
"@heroui/theme": "^2.4.25",
|
|
75
75
|
"@heroui/toast": "^2.0.21",
|
|
76
|
+
"@heroui/tooltip": "^2.2.28",
|
|
77
|
+
"@hookform/resolvers": "^5.2.2",
|
|
76
78
|
"@internationalized/date": "^3.11.0",
|
|
77
79
|
"@storybook/react": "^10.1.8",
|
|
78
80
|
"@tailwindcss/vite": "^4.1.17",
|
|
@@ -96,7 +98,8 @@
|
|
|
96
98
|
"tailwindcss": "^4.1.17",
|
|
97
99
|
"use-debounce": "^10.1.0",
|
|
98
100
|
"vite-tsconfig-paths": "^5.1.4",
|
|
99
|
-
"xlsx": "^0.18.5"
|
|
101
|
+
"xlsx": "^0.18.5",
|
|
102
|
+
"zod": "^4.3.6"
|
|
100
103
|
},
|
|
101
104
|
"devDependencies": {
|
|
102
105
|
"@chromatic-com/storybook": "^4.1.3",
|
|
@@ -7,13 +7,12 @@ import type { ColorPickerProps } from "@/types";
|
|
|
7
7
|
import { CopyButton } from "@/components";
|
|
8
8
|
import { useEmperorUI } from "@/hooks";
|
|
9
9
|
|
|
10
|
-
const HEX_COLOR_REGEX = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;
|
|
11
|
-
|
|
12
10
|
export function FreeColorPicker({
|
|
13
11
|
className,
|
|
14
12
|
classNames,
|
|
15
13
|
value = "#000000",
|
|
16
|
-
|
|
14
|
+
onChange,
|
|
15
|
+
defaultValue,
|
|
17
16
|
inputType = "free",
|
|
18
17
|
...props
|
|
19
18
|
}: ColorPickerProps) {
|
|
@@ -26,12 +25,10 @@ export function FreeColorPicker({
|
|
|
26
25
|
|
|
27
26
|
const isInvalid = useMemo(() => {
|
|
28
27
|
if (!value) return true;
|
|
29
|
-
|
|
30
|
-
}, [value]);
|
|
28
|
+
const HEX_COLOR_REGEX = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/;
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
30
|
+
return !HEX_COLOR_REGEX.test(value);
|
|
31
|
+
}, [value]);
|
|
35
32
|
|
|
36
33
|
return (
|
|
37
34
|
<Input
|
|
@@ -39,8 +36,9 @@ export function FreeColorPicker({
|
|
|
39
36
|
variant="faded"
|
|
40
37
|
className={cn(className)}
|
|
41
38
|
classNames={{ label: "font-bold", input: "h-12", ...classNames }}
|
|
39
|
+
defaultValue={defaultValue}
|
|
42
40
|
value={value}
|
|
43
|
-
onValueChange={
|
|
41
|
+
onValueChange={onChange}
|
|
44
42
|
isInvalid={isInvalid}
|
|
45
43
|
errorMessage={isInvalid ? errorMessage : undefined}
|
|
46
44
|
endContent={<CopyButton value={value} />}
|
|
@@ -50,7 +48,7 @@ export function FreeColorPicker({
|
|
|
50
48
|
className="color-swatch"
|
|
51
49
|
value={value}
|
|
52
50
|
onChange={(e) => {
|
|
53
|
-
|
|
51
|
+
onChange?.(e.target.value as string);
|
|
54
52
|
}}
|
|
55
53
|
/>
|
|
56
54
|
}
|
|
@@ -9,7 +9,8 @@ export function PresetColorPicker({
|
|
|
9
9
|
className,
|
|
10
10
|
classNames,
|
|
11
11
|
value = "#000000",
|
|
12
|
-
|
|
12
|
+
onChange,
|
|
13
|
+
defaultValue,
|
|
13
14
|
inputType,
|
|
14
15
|
presets = [],
|
|
15
16
|
...props
|
|
@@ -30,8 +31,9 @@ export function PresetColorPicker({
|
|
|
30
31
|
trigger: "min-w-52",
|
|
31
32
|
...classNames,
|
|
32
33
|
}}
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
selectedKeys={value ? [value] : undefined}
|
|
35
|
+
defaultSelectedKeys={defaultValue ? [defaultValue] : undefined}
|
|
36
|
+
onSelectionChange={(value) => onChange?.(value?.currentKey ?? "")}
|
|
35
37
|
endContent={<CopyButton value={value} />}
|
|
36
38
|
renderValue={() => {
|
|
37
39
|
return (
|
|
@@ -24,9 +24,21 @@ export default meta;
|
|
|
24
24
|
type Story = StoryObj<typeof meta>;
|
|
25
25
|
|
|
26
26
|
export const Default: Story = {
|
|
27
|
-
render: (
|
|
27
|
+
render: () => {
|
|
28
28
|
const [value, setValue] = useState("#000000");
|
|
29
|
-
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<section className="flex flex-col gap-4">
|
|
32
|
+
<ColorPicker
|
|
33
|
+
inputType="free"
|
|
34
|
+
value={value}
|
|
35
|
+
onChange={setValue}
|
|
36
|
+
defaultValue="#000000"
|
|
37
|
+
/>
|
|
38
|
+
|
|
39
|
+
<p className="text-xs text-gray-500">Value: {value}</p>
|
|
40
|
+
</section>
|
|
41
|
+
);
|
|
30
42
|
},
|
|
31
43
|
};
|
|
32
44
|
|
|
@@ -35,15 +47,17 @@ export const WithPresets: Story = {
|
|
|
35
47
|
const [value, setValue] = useState("#000000");
|
|
36
48
|
|
|
37
49
|
return (
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
setValue
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
<section className="flex flex-col gap-4">
|
|
51
|
+
<ColorPicker
|
|
52
|
+
inputType="preset"
|
|
53
|
+
presets={["#000000", "#FFFFFF", "#FF0000", "#00FF00", "#0000FF"]}
|
|
54
|
+
value={value}
|
|
55
|
+
onChange={setValue}
|
|
56
|
+
defaultValue="#000000"
|
|
57
|
+
/>
|
|
58
|
+
|
|
59
|
+
<p className="text-xs text-gray-500">Value: {value}</p>
|
|
60
|
+
</section>
|
|
47
61
|
);
|
|
48
62
|
},
|
|
49
63
|
};
|
|
@@ -1,11 +1,81 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AutocompleteField,
|
|
3
|
+
CheckboxField,
|
|
4
|
+
InputField,
|
|
5
|
+
RadioField,
|
|
6
|
+
SelectField,
|
|
7
|
+
SwitchField,
|
|
8
|
+
TextareaField,
|
|
9
|
+
fieldClasses,
|
|
10
|
+
} from "@/components";
|
|
11
|
+
import type { FieldProps, FieldType } from "@/types";
|
|
1
12
|
import { cn } from "@/utils";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
13
|
+
import type { FieldValues } from "react-hook-form";
|
|
14
|
+
import type { ReactNode } from "react";
|
|
15
|
+
|
|
16
|
+
export function Field<TSchema extends FieldValues>({
|
|
17
|
+
className,
|
|
18
|
+
classNames,
|
|
19
|
+
name,
|
|
20
|
+
type,
|
|
21
|
+
inputProps,
|
|
22
|
+
textareaProps,
|
|
23
|
+
checkboxProps,
|
|
24
|
+
selectProps,
|
|
25
|
+
selectItemProps,
|
|
26
|
+
autocompleteProps,
|
|
27
|
+
autocompleteItemProps,
|
|
28
|
+
switchProps,
|
|
29
|
+
radioGroupProps,
|
|
30
|
+
options,
|
|
31
|
+
children,
|
|
32
|
+
}: FieldProps<TSchema>) {
|
|
33
|
+
const components: Record<FieldType, ReactNode> = {
|
|
34
|
+
input: <InputField<TSchema> name={name} inputProps={inputProps} />,
|
|
35
|
+
textarea: (
|
|
36
|
+
<TextareaField<TSchema> name={name} textareaProps={textareaProps} />
|
|
37
|
+
),
|
|
38
|
+
checkbox: (
|
|
39
|
+
<CheckboxField<TSchema> name={name} checkboxProps={checkboxProps}>
|
|
40
|
+
{children}
|
|
41
|
+
</CheckboxField>
|
|
42
|
+
),
|
|
43
|
+
select: (
|
|
44
|
+
<SelectField<TSchema>
|
|
45
|
+
name={name}
|
|
46
|
+
options={options}
|
|
47
|
+
selectProps={selectProps}
|
|
48
|
+
selectItemProps={selectItemProps}
|
|
49
|
+
/>
|
|
50
|
+
),
|
|
51
|
+
autocomplete: (
|
|
52
|
+
<AutocompleteField<TSchema>
|
|
53
|
+
name={name}
|
|
54
|
+
options={options}
|
|
55
|
+
autocompleteProps={autocompleteProps}
|
|
56
|
+
autocompleteItemProps={autocompleteItemProps}
|
|
57
|
+
/>
|
|
58
|
+
),
|
|
59
|
+
switch: (
|
|
60
|
+
<SwitchField<TSchema> name={name} switchProps={switchProps}>
|
|
61
|
+
{children}
|
|
62
|
+
</SwitchField>
|
|
63
|
+
),
|
|
64
|
+
radio: (
|
|
65
|
+
<RadioField<TSchema>
|
|
66
|
+
name={name}
|
|
67
|
+
options={options}
|
|
68
|
+
radioGroupProps={radioGroupProps}
|
|
69
|
+
/>
|
|
70
|
+
),
|
|
71
|
+
};
|
|
4
72
|
|
|
5
|
-
export function Field({ className, classNames, ...props }: FieldProps) {
|
|
6
73
|
return (
|
|
7
|
-
<div
|
|
8
|
-
|
|
74
|
+
<div
|
|
75
|
+
data-slot="emperor-ui-field"
|
|
76
|
+
className={cn(fieldClasses({}), className, classNames?.base)}
|
|
77
|
+
>
|
|
78
|
+
{components[type]}
|
|
9
79
|
</div>
|
|
10
80
|
);
|
|
11
81
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { FieldProps } from "@/types";
|
|
4
|
+
import { Controller, type FieldValues } from "react-hook-form";
|
|
5
|
+
import { Autocomplete, AutocompleteItem } from "@heroui/autocomplete";
|
|
6
|
+
import { useEmperorUI, useFormBuilder } from "@/hooks";
|
|
7
|
+
|
|
8
|
+
export function AutocompleteField<TSchema extends FieldValues>({
|
|
9
|
+
autocompleteItemProps,
|
|
10
|
+
autocompleteProps,
|
|
11
|
+
options,
|
|
12
|
+
name,
|
|
13
|
+
}: Pick<
|
|
14
|
+
FieldProps<TSchema>,
|
|
15
|
+
"autocompleteItemProps" | "autocompleteProps" | "options" | "name"
|
|
16
|
+
>) {
|
|
17
|
+
const { config } = useEmperorUI();
|
|
18
|
+
|
|
19
|
+
const theme = config?.theme?.components?.autocomplete;
|
|
20
|
+
|
|
21
|
+
if (!options?.length) {
|
|
22
|
+
throw new Error("Field with type 'autocomplete' must include 'options'.");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { control } = useFormBuilder<TSchema>();
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Controller
|
|
29
|
+
control={control}
|
|
30
|
+
name={name}
|
|
31
|
+
render={({ field }) => (
|
|
32
|
+
<Autocomplete
|
|
33
|
+
{...theme}
|
|
34
|
+
{...autocompleteProps}
|
|
35
|
+
selectedKey={field.value ? String(field.value) : null}
|
|
36
|
+
onSelectionChange={(selectedKey) =>
|
|
37
|
+
field.onChange(selectedKey ? String(selectedKey) : "")
|
|
38
|
+
}
|
|
39
|
+
>
|
|
40
|
+
{options.map((option) => (
|
|
41
|
+
<AutocompleteItem key={option.key} {...autocompleteItemProps}>
|
|
42
|
+
{option.label}
|
|
43
|
+
</AutocompleteItem>
|
|
44
|
+
))}
|
|
45
|
+
</Autocomplete>
|
|
46
|
+
)}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { FieldProps } from "@/types";
|
|
4
|
+
import { Controller, type FieldValues } from "react-hook-form";
|
|
5
|
+
import { Checkbox } from "@heroui/checkbox";
|
|
6
|
+
import { useEmperorUI, useFormBuilder } from "@/hooks";
|
|
7
|
+
|
|
8
|
+
export function CheckboxField<TSchema extends FieldValues>({
|
|
9
|
+
checkboxProps,
|
|
10
|
+
name,
|
|
11
|
+
children,
|
|
12
|
+
}: Pick<FieldProps<TSchema>, "checkboxProps" | "name" | "children">) {
|
|
13
|
+
const { config } = useEmperorUI();
|
|
14
|
+
|
|
15
|
+
const theme = config?.theme?.components?.checkbox;
|
|
16
|
+
|
|
17
|
+
const { control } = useFormBuilder<TSchema>();
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Controller
|
|
21
|
+
control={control}
|
|
22
|
+
name={name}
|
|
23
|
+
render={({ field: { value, onChange } }) => (
|
|
24
|
+
<Checkbox
|
|
25
|
+
{...theme}
|
|
26
|
+
{...checkboxProps}
|
|
27
|
+
isSelected={Boolean(value)}
|
|
28
|
+
onValueChange={onChange}
|
|
29
|
+
>
|
|
30
|
+
{children}
|
|
31
|
+
</Checkbox>
|
|
32
|
+
)}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { FieldProps } from "@/types";
|
|
4
|
+
import { Controller, type FieldValues } from "react-hook-form";
|
|
5
|
+
import { Input } from "@heroui/input";
|
|
6
|
+
import { useEmperorUI, useFormBuilder } from "@/hooks";
|
|
7
|
+
|
|
8
|
+
export function InputField<TSchema extends FieldValues>({
|
|
9
|
+
inputProps,
|
|
10
|
+
name,
|
|
11
|
+
}: Pick<FieldProps<TSchema>, "inputProps" | "name">) {
|
|
12
|
+
const { config } = useEmperorUI();
|
|
13
|
+
|
|
14
|
+
const theme = config?.theme?.components?.input;
|
|
15
|
+
|
|
16
|
+
const { control } = useFormBuilder<TSchema>();
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Controller
|
|
20
|
+
control={control}
|
|
21
|
+
name={name}
|
|
22
|
+
render={({ field, fieldState }) => (
|
|
23
|
+
<Input
|
|
24
|
+
{...theme}
|
|
25
|
+
{...inputProps}
|
|
26
|
+
value={field.value ? String(field.value) : ""}
|
|
27
|
+
onBlur={field.onBlur}
|
|
28
|
+
onValueChange={field.onChange}
|
|
29
|
+
isInvalid={inputProps?.isInvalid ?? Boolean(fieldState.error)}
|
|
30
|
+
errorMessage={inputProps?.errorMessage ?? fieldState.error?.message}
|
|
31
|
+
/>
|
|
32
|
+
)}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { FieldProps } from "@/types";
|
|
4
|
+
import { Controller, type FieldValues } from "react-hook-form";
|
|
5
|
+
import { Radio, RadioGroup } from "@heroui/radio";
|
|
6
|
+
import { useEmperorUI, useFormBuilder } from "@/hooks";
|
|
7
|
+
|
|
8
|
+
export function RadioField<TSchema extends FieldValues>({
|
|
9
|
+
options,
|
|
10
|
+
radioGroupProps,
|
|
11
|
+
name,
|
|
12
|
+
}: Pick<FieldProps<TSchema>, "options" | "radioGroupProps" | "name">) {
|
|
13
|
+
const { config } = useEmperorUI();
|
|
14
|
+
|
|
15
|
+
const theme = config?.theme?.components?.radio;
|
|
16
|
+
|
|
17
|
+
const { control } = useFormBuilder<TSchema>();
|
|
18
|
+
|
|
19
|
+
if (!options?.length) {
|
|
20
|
+
throw new Error("Field with type 'radio' must include 'options'.");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Controller
|
|
25
|
+
control={control}
|
|
26
|
+
name={name}
|
|
27
|
+
render={({ field }) => (
|
|
28
|
+
<RadioGroup
|
|
29
|
+
{...theme}
|
|
30
|
+
{...radioGroupProps}
|
|
31
|
+
value={field.value ? String(field.value) : ""}
|
|
32
|
+
onValueChange={field.onChange}
|
|
33
|
+
>
|
|
34
|
+
{options.map((option) => (
|
|
35
|
+
<Radio key={option.key} value={option.key}>
|
|
36
|
+
{option.label}
|
|
37
|
+
</Radio>
|
|
38
|
+
))}
|
|
39
|
+
</RadioGroup>
|
|
40
|
+
)}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { FieldProps } from "@/types";
|
|
4
|
+
import { Controller, type FieldValues } from "react-hook-form";
|
|
5
|
+
import { Select, SelectItem } from "@heroui/select";
|
|
6
|
+
import { useEmperorUI, useFormBuilder } from "@/hooks";
|
|
7
|
+
|
|
8
|
+
export function SelectField<TSchema extends FieldValues>({
|
|
9
|
+
options,
|
|
10
|
+
selectItemProps,
|
|
11
|
+
selectProps,
|
|
12
|
+
name,
|
|
13
|
+
}: Pick<
|
|
14
|
+
FieldProps<TSchema>,
|
|
15
|
+
"options" | "selectItemProps" | "selectProps" | "name"
|
|
16
|
+
>) {
|
|
17
|
+
const { config } = useEmperorUI();
|
|
18
|
+
|
|
19
|
+
const theme = config?.theme?.components?.select;
|
|
20
|
+
|
|
21
|
+
if (!options?.length) {
|
|
22
|
+
throw new Error("Field with type 'select' must include 'options'.");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { control } = useFormBuilder<TSchema>();
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Controller
|
|
29
|
+
control={control}
|
|
30
|
+
name={name}
|
|
31
|
+
render={({ field }) => (
|
|
32
|
+
<Select
|
|
33
|
+
{...theme}
|
|
34
|
+
{...selectProps}
|
|
35
|
+
selectedKeys={field.value ? [String(field.value)] : []}
|
|
36
|
+
onSelectionChange={(keys) => {
|
|
37
|
+
const selectedKey = Array.from(keys)[0];
|
|
38
|
+
field.onChange(selectedKey ? String(selectedKey) : "");
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
41
|
+
{options.map((option) => (
|
|
42
|
+
<SelectItem key={option.key} {...selectItemProps}>
|
|
43
|
+
{option.label}
|
|
44
|
+
</SelectItem>
|
|
45
|
+
))}
|
|
46
|
+
</Select>
|
|
47
|
+
)}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { FieldProps } from "@/types";
|
|
4
|
+
import { Controller, type FieldValues } from "react-hook-form";
|
|
5
|
+
import { Switch } from "@heroui/switch";
|
|
6
|
+
import { useEmperorUI, useFormBuilder } from "@/hooks";
|
|
7
|
+
|
|
8
|
+
export function SwitchField<TSchema extends FieldValues>({
|
|
9
|
+
switchProps,
|
|
10
|
+
name,
|
|
11
|
+
children,
|
|
12
|
+
}: Pick<FieldProps<TSchema>, "switchProps" | "name" | "children">) {
|
|
13
|
+
const { config } = useEmperorUI();
|
|
14
|
+
|
|
15
|
+
const theme = config?.theme?.components?.switch;
|
|
16
|
+
|
|
17
|
+
const { control } = useFormBuilder<TSchema>();
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Controller
|
|
21
|
+
control={control}
|
|
22
|
+
name={name}
|
|
23
|
+
render={({ field }) => (
|
|
24
|
+
<Switch
|
|
25
|
+
{...theme}
|
|
26
|
+
{...switchProps}
|
|
27
|
+
isSelected={Boolean(field.value)}
|
|
28
|
+
onValueChange={field.onChange}
|
|
29
|
+
>
|
|
30
|
+
{children}
|
|
31
|
+
</Switch>
|
|
32
|
+
)}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type { FieldProps } from "@/types";
|
|
4
|
+
import { Controller, type FieldValues } from "react-hook-form";
|
|
5
|
+
import { Textarea } from "@heroui/input";
|
|
6
|
+
import { useEmperorUI, useFormBuilder } from "@/hooks";
|
|
7
|
+
|
|
8
|
+
export function TextareaField<TSchema extends FieldValues>({
|
|
9
|
+
textareaProps,
|
|
10
|
+
name,
|
|
11
|
+
}: Pick<FieldProps<TSchema>, "textareaProps" | "name">) {
|
|
12
|
+
const { config } = useEmperorUI();
|
|
13
|
+
|
|
14
|
+
const theme = config?.theme?.components?.textarea;
|
|
15
|
+
|
|
16
|
+
const { control } = useFormBuilder<TSchema>();
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Controller
|
|
20
|
+
control={control}
|
|
21
|
+
name={name}
|
|
22
|
+
render={({ field, fieldState }) => (
|
|
23
|
+
<Textarea
|
|
24
|
+
{...theme}
|
|
25
|
+
{...textareaProps}
|
|
26
|
+
value={field.value ? String(field.value) : ""}
|
|
27
|
+
onBlur={field.onBlur}
|
|
28
|
+
onValueChange={field.onChange}
|
|
29
|
+
isInvalid={textareaProps?.isInvalid ?? Boolean(fieldState.error)}
|
|
30
|
+
errorMessage={
|
|
31
|
+
textareaProps?.errorMessage ?? fieldState.error?.message
|
|
32
|
+
}
|
|
33
|
+
/>
|
|
34
|
+
)}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -48,6 +48,7 @@ export function Filter({
|
|
|
48
48
|
autocomplete: (
|
|
49
49
|
<AutocompleteFilter
|
|
50
50
|
autocompleteProps={autocompleteProps}
|
|
51
|
+
options={options}
|
|
51
52
|
{...sharedProps}
|
|
52
53
|
{...props}
|
|
53
54
|
/>
|
|
@@ -66,6 +67,7 @@ export function Filter({
|
|
|
66
67
|
checkboxGroup: (
|
|
67
68
|
<CheckboxGroupFilter
|
|
68
69
|
checkboxGroupProps={checkboxGroupProps}
|
|
70
|
+
options={options}
|
|
69
71
|
{...sharedProps}
|
|
70
72
|
{...props}
|
|
71
73
|
/>
|
|
@@ -84,7 +86,6 @@ export function Filter({
|
|
|
84
86
|
className,
|
|
85
87
|
props?.classNames?.base,
|
|
86
88
|
)}
|
|
87
|
-
{...props}
|
|
88
89
|
>
|
|
89
90
|
{components[type]}
|
|
90
91
|
</div>
|