@twintag/twintag-form 1.4.0-beta.1 → 1.4.0-beta.2
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/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +6 -0
- package/README.md +2 -2
- package/dev/main.tsx +222 -2
- package/dist/components/config.d.ts +2 -2
- package/dist/components/containers/accordion.d.ts +2 -4
- package/dist/components/fields/checkbox.d.ts +1 -1
- package/dist/components/fields/date-picker.d.ts +1 -1
- package/dist/components/fields/file.d.ts +1 -1
- package/dist/components/fields/input.d.ts +1 -1
- package/dist/components/fields/radiogroup.d.ts +3 -1
- package/dist/components/fields/textarea.d.ts +1 -1
- package/dist/components/fields/toggle.d.ts +1 -1
- package/dist/components/fields/tri-toggle.d.ts +1 -1
- package/dist/components/provider.d.ts +3 -3
- package/dist/twintag-form.react.js +1634 -1625
- package/dist/types/index.d.ts +37 -22
- package/dist/utils/data.d.ts +5 -1
- package/index.html +1 -0
- package/lib/components/config.tsx +2 -2
- package/lib/components/containers/accordion.tsx +32 -17
- package/lib/components/fields/checkbox.tsx +1 -1
- package/lib/components/fields/date-picker.tsx +5 -1
- package/lib/components/fields/file.tsx +83 -83
- package/lib/components/fields/input.tsx +1 -1
- package/lib/components/fields/radiogroup.tsx +5 -1
- package/lib/components/fields/textarea.tsx +1 -1
- package/lib/components/fields/toggle.tsx +1 -1
- package/lib/components/fields/tri-toggle.tsx +1 -1
- package/lib/components/provider.tsx +8 -4
- package/lib/types/index.ts +80 -49
- package/lib/utils/data.ts +5 -2
- package/package.json +3 -3
package/dist/types/index.d.ts
CHANGED
|
@@ -1,41 +1,56 @@
|
|
|
1
1
|
import { ElementType } from 'react';
|
|
2
2
|
|
|
3
|
-
export type
|
|
3
|
+
export type InputCompConfig = {
|
|
4
4
|
defaultValue?: unknown;
|
|
5
5
|
component: ElementType;
|
|
6
6
|
};
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
comp?: ElementType;
|
|
12
|
-
};
|
|
13
|
-
export type RawJsonComponent = RawProps & Record<string, unknown> & {
|
|
14
|
-
type: string;
|
|
15
|
-
children?: RawJsonComponent[];
|
|
16
|
-
} & {
|
|
17
|
-
props?: RawProps;
|
|
18
|
-
};
|
|
19
|
-
type RawProps = Partial<{
|
|
7
|
+
type CompType = 'input' | 'item' | 'accordion' | 'category';
|
|
8
|
+
type StringLiteral<T> = T extends string ? string extends T ? never : T : never;
|
|
9
|
+
type RawProps<TType extends string = string, TSubtype extends string = string> = TType extends 'input' | 'item' ? {
|
|
10
|
+
type: TType;
|
|
20
11
|
bind: string;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
options: Partial<{
|
|
12
|
+
label?: string;
|
|
13
|
+
subtype?: string;
|
|
14
|
+
options?: Partial<{
|
|
25
15
|
description: string;
|
|
26
16
|
placeholder: string;
|
|
27
17
|
error: string;
|
|
28
18
|
optionalField: boolean;
|
|
29
19
|
}>;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
20
|
+
} : TType extends 'accordion' ? TSubtype extends 'item' ? {
|
|
21
|
+
type: TType;
|
|
22
|
+
subtype: TSubtype;
|
|
23
|
+
value?: string;
|
|
24
|
+
label: string;
|
|
25
|
+
icon: string;
|
|
26
|
+
} : TSubtype extends 'multiple' | 'single' ? {
|
|
27
|
+
type: TType;
|
|
28
|
+
subtype: TSubtype;
|
|
29
|
+
defaultValue?: string;
|
|
30
|
+
} : never : {
|
|
31
|
+
type: TType;
|
|
32
|
+
label?: string;
|
|
33
|
+
subtype?: string;
|
|
34
|
+
};
|
|
35
|
+
export type RawJsonComponent = CompType extends infer T ? T extends CompType ? {
|
|
36
|
+
type: StringLiteral<T>;
|
|
37
|
+
props?: Omit<RawProps<StringLiteral<T>>, 'type'>;
|
|
38
|
+
children?: RawJsonComponent[];
|
|
39
|
+
} : never : never;
|
|
40
|
+
export type ParsedJsonComponent<TType extends string = string> = RawProps<TType> & {
|
|
41
|
+
id: string;
|
|
42
|
+
type: string;
|
|
43
|
+
subtype?: string;
|
|
44
|
+
comp?: ElementType;
|
|
33
45
|
items?: ParsedJsonComponent[];
|
|
34
46
|
};
|
|
47
|
+
export type Props<TType extends string = string, TSubtype extends string = string> = Omit<RawProps<TType, TSubtype>, 'type'> & {
|
|
48
|
+
items?: (Props<'input'> & ParsedJsonComponent)[];
|
|
49
|
+
};
|
|
35
50
|
export type TwintagFormContext = {
|
|
36
51
|
variant?: 'default' | 'beta';
|
|
37
52
|
size?: 'base' | 'sm';
|
|
38
|
-
inputs: Map<string,
|
|
53
|
+
inputs: Map<string, InputCompConfig>;
|
|
39
54
|
components: Map<string, ElementType>;
|
|
40
55
|
config: ParsedJsonComponent[] | ParsedJsonComponent;
|
|
41
56
|
resetValues: Record<string, unknown>;
|
package/dist/utils/data.d.ts
CHANGED
package/index.html
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ElementType, FC } from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { InputCompConfig } from '../types';
|
|
3
3
|
|
|
4
4
|
import { Accordion } from './containers/accordion';
|
|
5
5
|
import { Category } from './containers/category';
|
|
@@ -13,7 +13,7 @@ import { DEFAULT_TEXTAREA_VALUE, Textarea } from './fields/textarea';
|
|
|
13
13
|
import { DEFAULT_TOGGLE_VALUE, Toggle } from './fields/toggle';
|
|
14
14
|
import { DEFAULT_TRI_TOGGLE_VALUE, TriToggle } from './fields/tri-toggle';
|
|
15
15
|
|
|
16
|
-
export const Inputs = new Map<string,
|
|
16
|
+
export const Inputs = new Map<string, InputCompConfig>()
|
|
17
17
|
.set('simple', {
|
|
18
18
|
defaultValue: DEFAULT_INPUT_VALUE,
|
|
19
19
|
component: InputField,
|
|
@@ -15,7 +15,8 @@ import { useTwintagForm } from '@twintag/twintag-form/components/provider';
|
|
|
15
15
|
import { camelize } from '@twintag/twintag-form/utils/string';
|
|
16
16
|
|
|
17
17
|
type AccordionRootProps = {
|
|
18
|
-
multiple
|
|
18
|
+
type: 'single' | 'multiple';
|
|
19
|
+
defaultValue?: string;
|
|
19
20
|
} & WithChildren;
|
|
20
21
|
|
|
21
22
|
const accordionRootVariants = tv({
|
|
@@ -30,17 +31,19 @@ const accordionRootVariants = tv({
|
|
|
30
31
|
variant: 'default',
|
|
31
32
|
},
|
|
32
33
|
});
|
|
33
|
-
const AccordionRoot: FC<AccordionRootProps> = ({
|
|
34
|
-
multiple = true,
|
|
35
|
-
children,
|
|
36
|
-
}) => {
|
|
34
|
+
const AccordionRoot: FC<AccordionRootProps> = ({ type, defaultValue, children }) => {
|
|
37
35
|
const { variant } = useTwintagForm();
|
|
38
36
|
|
|
37
|
+
if (type === 'single') {
|
|
38
|
+
return (
|
|
39
|
+
<AccordionPrimitive type='single' defaultValue={defaultValue} collapsible>
|
|
40
|
+
<div className={accordionRootVariants({ variant })}>{children}</div>
|
|
41
|
+
</AccordionPrimitive>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
39
45
|
return (
|
|
40
|
-
<AccordionPrimitive
|
|
41
|
-
type={multiple ? 'multiple' : 'single'}
|
|
42
|
-
collapsible={multiple ? undefined : true}
|
|
43
|
-
>
|
|
46
|
+
<AccordionPrimitive type='multiple'>
|
|
44
47
|
<div className={accordionRootVariants({ variant })}>{children}</div>
|
|
45
48
|
</AccordionPrimitive>
|
|
46
49
|
);
|
|
@@ -80,11 +83,15 @@ const accordionItemVariants = tv({
|
|
|
80
83
|
},
|
|
81
84
|
});
|
|
82
85
|
|
|
83
|
-
type AccordionItemProps = Omit<Props, '
|
|
86
|
+
type AccordionItemProps = Omit<Props<'accordion', 'item'>, 'subtype'> & {
|
|
87
|
+
value?: string;
|
|
88
|
+
} & WithChildren;
|
|
84
89
|
const AccordionItem: FC<AccordionItemProps> = ({
|
|
85
90
|
label = '',
|
|
91
|
+
value = '',
|
|
86
92
|
icon,
|
|
87
93
|
children,
|
|
94
|
+
...rest
|
|
88
95
|
}) => {
|
|
89
96
|
const { variant, size } = useTwintagForm();
|
|
90
97
|
|
|
@@ -96,7 +103,11 @@ const AccordionItem: FC<AccordionItemProps> = ({
|
|
|
96
103
|
} = accordionItemVariants({ size, variant });
|
|
97
104
|
|
|
98
105
|
return (
|
|
99
|
-
<AccordionItemPrimitive
|
|
106
|
+
<AccordionItemPrimitive
|
|
107
|
+
value={value ?? camelize(label)}
|
|
108
|
+
className={item()}
|
|
109
|
+
{...rest}
|
|
110
|
+
>
|
|
100
111
|
<AccordionTrigger className='text-category'>
|
|
101
112
|
<span className={trigger()}>
|
|
102
113
|
{icon ? <Icon name={icon} className={iconVariants()} /> : <></>}
|
|
@@ -109,14 +120,18 @@ const AccordionItem: FC<AccordionItemProps> = ({
|
|
|
109
120
|
};
|
|
110
121
|
AccordionItem.displayName = 'AccordionItem';
|
|
111
122
|
|
|
112
|
-
type AccordionProps =
|
|
113
|
-
|
|
114
|
-
label?: string;
|
|
115
|
-
} & WithChildren;
|
|
123
|
+
type AccordionProps = Props<'accordion', 'item' | 'multiple' | 'single'> &
|
|
124
|
+
WithChildren;
|
|
116
125
|
const Accordion: FC<AccordionProps> = ({ subtype = 'single', ...rest }) => {
|
|
117
|
-
if (subtype === 'item')
|
|
126
|
+
if (subtype === 'item') {
|
|
127
|
+
return (
|
|
128
|
+
<AccordionItem
|
|
129
|
+
{...(rest as Omit<Props<'accordion', 'item'>, 'subtype'>)}
|
|
130
|
+
/>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
118
133
|
|
|
119
|
-
return <AccordionRoot {...rest} />;
|
|
134
|
+
return <AccordionRoot type={subtype} {...rest} />;
|
|
120
135
|
};
|
|
121
136
|
|
|
122
137
|
export { Accordion };
|
|
@@ -17,7 +17,7 @@ import { useTwintagForm } from '@twintag/twintag-form/components/provider';
|
|
|
17
17
|
|
|
18
18
|
export const DEFAULT_CHECKBOX_VALUE = false;
|
|
19
19
|
|
|
20
|
-
export const Checkbox: FC<Props
|
|
20
|
+
export const Checkbox: FC<Props<'input'>> = ({ label, bind, options }) => {
|
|
21
21
|
const { control } = useFormContext();
|
|
22
22
|
const { variant, size } = useTwintagForm();
|
|
23
23
|
|
|
@@ -65,7 +65,11 @@ const datePickerTriggerVariants = tv({
|
|
|
65
65
|
|
|
66
66
|
export const DEFAULT_DATE_PICKER_VALUE = null;
|
|
67
67
|
|
|
68
|
-
export const DatePicker: React.FC<Props
|
|
68
|
+
export const DatePicker: React.FC<Props<'input'>> = ({
|
|
69
|
+
label,
|
|
70
|
+
bind,
|
|
71
|
+
options,
|
|
72
|
+
}) => {
|
|
69
73
|
const { variant, size } = useTwintagForm();
|
|
70
74
|
const { control } = useFormContext();
|
|
71
75
|
|
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
import type { FC } from 'react';
|
|
2
|
-
import type { Props } from '@twintag/twintag-form/types';
|
|
3
|
-
|
|
4
|
-
import { AsteriskIcon } from 'lucide-react';
|
|
5
|
-
import { useFormContext } from 'react-hook-form';
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
FormControl,
|
|
9
|
-
FormDescription,
|
|
10
|
-
FormField,
|
|
11
|
-
FormItem,
|
|
12
|
-
FormLabel,
|
|
13
|
-
FormMessage,
|
|
14
|
-
} from '@twintag/twintag-form/common/form';
|
|
15
|
-
import { Input } from '@twintag/twintag-form/common/input';
|
|
16
|
-
import { useTwintagForm } from '@twintag/twintag-form/components/provider';
|
|
17
|
-
|
|
18
|
-
export const DEFAULT_FILE_VALUE = '';
|
|
19
|
-
|
|
20
|
-
export const File: FC<Props
|
|
21
|
-
const { control } = useFormContext();
|
|
22
|
-
const { variant, size } = useTwintagForm();
|
|
23
|
-
|
|
24
|
-
const isOptional = options?.optionalField;
|
|
25
|
-
|
|
26
|
-
return (
|
|
27
|
-
<FormField
|
|
28
|
-
defaultValue={DEFAULT_FILE_VALUE}
|
|
29
|
-
control={control}
|
|
30
|
-
name={bind}
|
|
31
|
-
rules={{
|
|
32
|
-
required: isOptional ? false : options?.error ?? true,
|
|
33
|
-
}}
|
|
34
|
-
render={({ field, formState }) => (
|
|
35
|
-
<FormItem variant={variant}>
|
|
36
|
-
<div className='space-y-1'>
|
|
37
|
-
<FormLabel htmlFor={bind} size={size}>
|
|
38
|
-
{label}
|
|
39
|
-
{!isOptional ? (
|
|
40
|
-
<span className='ml-0.5 inline-block'>
|
|
41
|
-
<AsteriskIcon className='h-3 w-3 text-destructive' />
|
|
42
|
-
</span>
|
|
43
|
-
) : (
|
|
44
|
-
<></>
|
|
45
|
-
)}
|
|
46
|
-
</FormLabel>
|
|
47
|
-
{options?.description ? (
|
|
48
|
-
<FormDescription size={size}>
|
|
49
|
-
{options.description}
|
|
50
|
-
</FormDescription>
|
|
51
|
-
) : (
|
|
52
|
-
<></>
|
|
53
|
-
)}
|
|
54
|
-
</div>
|
|
55
|
-
<FormControl>
|
|
56
|
-
<Input
|
|
57
|
-
ref={(el) => {
|
|
58
|
-
field.ref(el);
|
|
59
|
-
|
|
60
|
-
if (el && formState.isSubmitSuccessful) {
|
|
61
|
-
el.value = '';
|
|
62
|
-
}
|
|
63
|
-
}}
|
|
64
|
-
id={bind}
|
|
65
|
-
type='file'
|
|
66
|
-
name={field.name}
|
|
67
|
-
size={size}
|
|
68
|
-
variant={variant}
|
|
69
|
-
multiple
|
|
70
|
-
onBlur={field.onBlur}
|
|
71
|
-
onChange={(e) => {
|
|
72
|
-
if (e.target.files) {
|
|
73
|
-
field.onChange(e.target.files);
|
|
74
|
-
}
|
|
75
|
-
}}
|
|
76
|
-
/>
|
|
77
|
-
</FormControl>
|
|
78
|
-
<FormMessage size={size} className='pt-1.5' />
|
|
79
|
-
</FormItem>
|
|
80
|
-
)}
|
|
81
|
-
/>
|
|
82
|
-
);
|
|
83
|
-
};
|
|
1
|
+
import type { FC } from 'react';
|
|
2
|
+
import type { Props } from '@twintag/twintag-form/types';
|
|
3
|
+
|
|
4
|
+
import { AsteriskIcon } from 'lucide-react';
|
|
5
|
+
import { useFormContext } from 'react-hook-form';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
FormControl,
|
|
9
|
+
FormDescription,
|
|
10
|
+
FormField,
|
|
11
|
+
FormItem,
|
|
12
|
+
FormLabel,
|
|
13
|
+
FormMessage,
|
|
14
|
+
} from '@twintag/twintag-form/common/form';
|
|
15
|
+
import { Input } from '@twintag/twintag-form/common/input';
|
|
16
|
+
import { useTwintagForm } from '@twintag/twintag-form/components/provider';
|
|
17
|
+
|
|
18
|
+
export const DEFAULT_FILE_VALUE = '';
|
|
19
|
+
|
|
20
|
+
export const File: FC<Props<'input'>> = ({ label, bind, options }) => {
|
|
21
|
+
const { control } = useFormContext();
|
|
22
|
+
const { variant, size } = useTwintagForm();
|
|
23
|
+
|
|
24
|
+
const isOptional = options?.optionalField;
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<FormField
|
|
28
|
+
defaultValue={DEFAULT_FILE_VALUE}
|
|
29
|
+
control={control}
|
|
30
|
+
name={bind}
|
|
31
|
+
rules={{
|
|
32
|
+
required: isOptional ? false : options?.error ?? true,
|
|
33
|
+
}}
|
|
34
|
+
render={({ field, formState }) => (
|
|
35
|
+
<FormItem variant={variant}>
|
|
36
|
+
<div className='space-y-1'>
|
|
37
|
+
<FormLabel htmlFor={bind} size={size}>
|
|
38
|
+
{label}
|
|
39
|
+
{!isOptional ? (
|
|
40
|
+
<span className='ml-0.5 inline-block'>
|
|
41
|
+
<AsteriskIcon className='h-3 w-3 text-destructive' />
|
|
42
|
+
</span>
|
|
43
|
+
) : (
|
|
44
|
+
<></>
|
|
45
|
+
)}
|
|
46
|
+
</FormLabel>
|
|
47
|
+
{options?.description ? (
|
|
48
|
+
<FormDescription size={size}>
|
|
49
|
+
{options.description}
|
|
50
|
+
</FormDescription>
|
|
51
|
+
) : (
|
|
52
|
+
<></>
|
|
53
|
+
)}
|
|
54
|
+
</div>
|
|
55
|
+
<FormControl>
|
|
56
|
+
<Input
|
|
57
|
+
ref={(el) => {
|
|
58
|
+
field.ref(el);
|
|
59
|
+
|
|
60
|
+
if (el && formState.isSubmitSuccessful) {
|
|
61
|
+
el.value = '';
|
|
62
|
+
}
|
|
63
|
+
}}
|
|
64
|
+
id={bind}
|
|
65
|
+
type='file'
|
|
66
|
+
name={field.name}
|
|
67
|
+
size={size}
|
|
68
|
+
variant={variant}
|
|
69
|
+
multiple
|
|
70
|
+
onBlur={field.onBlur}
|
|
71
|
+
onChange={(e) => {
|
|
72
|
+
if (e.target.files) {
|
|
73
|
+
field.onChange(e.target.files);
|
|
74
|
+
}
|
|
75
|
+
}}
|
|
76
|
+
/>
|
|
77
|
+
</FormControl>
|
|
78
|
+
<FormMessage size={size} className='pt-1.5' />
|
|
79
|
+
</FormItem>
|
|
80
|
+
)}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
};
|
|
@@ -17,7 +17,7 @@ import { useTwintagForm } from '@twintag/twintag-form/components/provider';
|
|
|
17
17
|
|
|
18
18
|
export const DEFAULT_INPUT_VALUE = '';
|
|
19
19
|
|
|
20
|
-
export const Input: FC<Props
|
|
20
|
+
export const Input: FC<Props<'input'>> = ({ label, bind, options }) => {
|
|
21
21
|
const { control } = useFormContext();
|
|
22
22
|
|
|
23
23
|
const { variant, size } = useTwintagForm();
|
|
@@ -20,7 +20,11 @@ import { useTwintagForm } from '@twintag/twintag-form/components/provider';
|
|
|
20
20
|
|
|
21
21
|
export const DEFAULT_RADIOGROUP_VALUE = '';
|
|
22
22
|
|
|
23
|
-
export const RadioGroup: FC<
|
|
23
|
+
export const RadioGroup: FC<
|
|
24
|
+
Props<'input'> & {
|
|
25
|
+
items: Props<'input'>[];
|
|
26
|
+
}
|
|
27
|
+
> = ({ label, bind, items, options }) => {
|
|
24
28
|
const { control } = useFormContext();
|
|
25
29
|
const { size } = useTwintagForm();
|
|
26
30
|
|
|
@@ -17,7 +17,7 @@ import { useTwintagForm } from '@twintag/twintag-form/components/provider';
|
|
|
17
17
|
|
|
18
18
|
export const DEFAULT_TEXTAREA_VALUE = '';
|
|
19
19
|
|
|
20
|
-
export const Textarea: FC<Props
|
|
20
|
+
export const Textarea: FC<Props<'input'>> = ({ label, bind, options }) => {
|
|
21
21
|
const { control } = useFormContext();
|
|
22
22
|
const { variant, size } = useTwintagForm();
|
|
23
23
|
|
|
@@ -17,7 +17,7 @@ import { useTwintagForm } from '@twintag/twintag-form/components/provider';
|
|
|
17
17
|
|
|
18
18
|
export const DEFAULT_TOGGLE_VALUE = false;
|
|
19
19
|
|
|
20
|
-
export const Toggle: FC<Props
|
|
20
|
+
export const Toggle: FC<Props<'input'>> = ({ label, bind, options }) => {
|
|
21
21
|
const { control } = useFormContext();
|
|
22
22
|
const { variant, size } = useTwintagForm();
|
|
23
23
|
|
|
@@ -88,7 +88,7 @@ Slider.displayName = SliderPrimitive.Root.displayName;
|
|
|
88
88
|
|
|
89
89
|
export const DEFAULT_TRI_TOGGLE_VALUE = null;
|
|
90
90
|
|
|
91
|
-
export const TriToggle: FC<Props
|
|
91
|
+
export const TriToggle: FC<Props<'input'>> = ({ label, bind, options }) => {
|
|
92
92
|
const { control } = useFormContext();
|
|
93
93
|
const { variant, size } = useTwintagForm();
|
|
94
94
|
|
|
@@ -81,7 +81,7 @@ const format = (component: RawJsonComponent, components: Components) => {
|
|
|
81
81
|
};
|
|
82
82
|
|
|
83
83
|
export const getResetValues = (
|
|
84
|
-
config:
|
|
84
|
+
config: ParsedJsonComponent | ParsedJsonComponent[],
|
|
85
85
|
inputs: Inputs,
|
|
86
86
|
) => {
|
|
87
87
|
const stack = Array.isArray(config) ? [...config] : [config];
|
|
@@ -96,15 +96,19 @@ export const getResetValues = (
|
|
|
96
96
|
for (const [key, value] of Object.entries(currentObj)) {
|
|
97
97
|
if (Array.isArray(value)) {
|
|
98
98
|
for (const item of value) {
|
|
99
|
-
stack.push(item
|
|
99
|
+
stack.push(item);
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
if (typeof value === 'object' && value !== null) {
|
|
104
|
-
stack.push(value as unknown as
|
|
104
|
+
stack.push(value as unknown as ParsedJsonComponent);
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
if (
|
|
107
|
+
if (
|
|
108
|
+
key === 'subtype' &&
|
|
109
|
+
'bind' in currentObj &&
|
|
110
|
+
typeof currentObj.bind === 'string'
|
|
111
|
+
) {
|
|
108
112
|
resetValues.set(
|
|
109
113
|
currentObj.bind,
|
|
110
114
|
inputs.get(value as string)?.defaultValue,
|
package/lib/types/index.ts
CHANGED
|
@@ -1,49 +1,80 @@
|
|
|
1
|
-
import type { ElementType } from 'react';
|
|
2
|
-
|
|
3
|
-
export type
|
|
4
|
-
defaultValue?: unknown;
|
|
5
|
-
component: ElementType;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
};
|
|
49
|
-
|
|
1
|
+
import type { ElementType } from 'react';
|
|
2
|
+
|
|
3
|
+
export type InputCompConfig = {
|
|
4
|
+
defaultValue?: unknown;
|
|
5
|
+
component: ElementType;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type CompType = 'input' | 'item' | 'accordion' | 'category';
|
|
9
|
+
type StringLiteral<T> = T extends string
|
|
10
|
+
? string extends T
|
|
11
|
+
? never
|
|
12
|
+
: T
|
|
13
|
+
: never;
|
|
14
|
+
|
|
15
|
+
type RawProps<
|
|
16
|
+
TType extends string = string,
|
|
17
|
+
TSubtype extends string = string,
|
|
18
|
+
> = TType extends 'input' | 'item'
|
|
19
|
+
? {
|
|
20
|
+
type: TType;
|
|
21
|
+
bind: string;
|
|
22
|
+
label?: string;
|
|
23
|
+
subtype?: string;
|
|
24
|
+
options?: Partial<{
|
|
25
|
+
description: string;
|
|
26
|
+
placeholder: string;
|
|
27
|
+
error: string;
|
|
28
|
+
optionalField: boolean;
|
|
29
|
+
}>;
|
|
30
|
+
}
|
|
31
|
+
: TType extends 'accordion'
|
|
32
|
+
?
|
|
33
|
+
TSubtype extends 'item'
|
|
34
|
+
? {
|
|
35
|
+
type: TType;
|
|
36
|
+
subtype: TSubtype;
|
|
37
|
+
value?: string;
|
|
38
|
+
label: string;
|
|
39
|
+
icon: string;
|
|
40
|
+
}
|
|
41
|
+
:TSubtype extends 'multiple' | 'single'
|
|
42
|
+
? { type: TType; subtype: TSubtype; defaultValue?: string }
|
|
43
|
+
: never
|
|
44
|
+
: {
|
|
45
|
+
type: TType;
|
|
46
|
+
label?: string;
|
|
47
|
+
subtype?: string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type RawJsonComponent =
|
|
51
|
+
CompType extends infer T ? T extends CompType ? {
|
|
52
|
+
type: StringLiteral<T>;
|
|
53
|
+
props?: Omit<RawProps<StringLiteral<T>>, 'type'>;
|
|
54
|
+
children?: RawJsonComponent[];
|
|
55
|
+
} : never : never
|
|
56
|
+
|
|
57
|
+
export type ParsedJsonComponent<TType extends string = string> =
|
|
58
|
+
RawProps<TType> & {
|
|
59
|
+
id: string;
|
|
60
|
+
type: string;
|
|
61
|
+
subtype?: string;
|
|
62
|
+
comp?: ElementType;
|
|
63
|
+
items?: ParsedJsonComponent[];
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export type Props<
|
|
67
|
+
TType extends string = string,
|
|
68
|
+
TSubtype extends string = string,
|
|
69
|
+
> = Omit<RawProps<TType, TSubtype>, 'type'> & {
|
|
70
|
+
items?: (Props<'input'> & ParsedJsonComponent)[];
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export type TwintagFormContext = {
|
|
74
|
+
variant?: 'default' | 'beta';
|
|
75
|
+
size?: 'base' | 'sm';
|
|
76
|
+
inputs: Map<string, InputCompConfig>;
|
|
77
|
+
components: Map<string, ElementType>;
|
|
78
|
+
config: ParsedJsonComponent[] | ParsedJsonComponent;
|
|
79
|
+
resetValues: Record<string, unknown>;
|
|
80
|
+
};
|
package/lib/utils/data.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { Props } from '@twintag/twintag-form/types';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
type Items = (Props<'input'> & {
|
|
4
|
+
items?: Items[];
|
|
5
|
+
})[];
|
|
6
|
+
export const getBindSetFromItems = (items: Items): Set<string> => {
|
|
4
7
|
const binds = new Set<string>();
|
|
5
8
|
|
|
6
9
|
items.forEach((item) => {
|
|
@@ -9,7 +12,7 @@ export const getBindSetFromItems = (items: Props[]): Set<string> => {
|
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
if (item.items) {
|
|
12
|
-
const subBinds = getBindSetFromItems(item.items);
|
|
15
|
+
const subBinds = getBindSetFromItems(item.items as unknown as Items);
|
|
13
16
|
subBinds.forEach((bind) => binds.add(bind));
|
|
14
17
|
}
|
|
15
18
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twintag/twintag-form",
|
|
3
|
-
"version": "1.4.0-beta.
|
|
3
|
+
"version": "1.4.0-beta.2",
|
|
4
4
|
"author": "Twintag",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
"tailwindcss": "^3.3.6",
|
|
50
50
|
"vite": "^5.2.11",
|
|
51
51
|
"vite-plugin-dts": "^3.9.1",
|
|
52
|
-
"eslint-config-custom": "1.0.0",
|
|
53
52
|
"tsconfig": "0.0.0",
|
|
54
|
-
"twintag-types": "0.2.0"
|
|
53
|
+
"twintag-types": "0.2.0",
|
|
54
|
+
"eslint-config-custom": "1.0.0"
|
|
55
55
|
},
|
|
56
56
|
"publishConfig": {
|
|
57
57
|
"access": "public"
|