@twintag/twintag-form 1.3.0 → 1.4.0-beta.1
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 +6 -6
- package/CHANGELOG.md +12 -0
- package/README.md +121 -62
- package/dev/main.tsx +233 -210
- package/dist/common/button.d.ts +17 -30
- package/dist/common/calendar.d.ts +212 -4
- package/dist/common/form.d.ts +151 -9
- package/dist/common/icon.d.ts +2 -1
- package/dist/common/input.d.ts +276 -2
- package/dist/common/label.d.ts +39 -1
- package/dist/common/slider.d.ts +4 -0
- package/dist/common/textarea.d.ts +139 -2
- package/dist/components/config.d.ts +4 -2
- package/dist/components/containers/accordion.d.ts +3 -2
- package/dist/components/containers/category.d.ts +3 -2
- package/dist/components/fields/checkbox.d.ts +4 -2
- package/dist/components/fields/date-picker.d.ts +3 -1
- package/dist/components/fields/file.d.ts +4 -2
- package/dist/components/fields/input.d.ts +4 -2
- package/dist/components/fields/radiogroup.d.ts +4 -2
- package/dist/components/fields/submit.d.ts +3 -2
- package/dist/components/fields/textarea.d.ts +4 -2
- package/dist/components/fields/toggle.d.ts +4 -2
- package/dist/components/fields/tri-toggle.d.ts +5 -0
- package/dist/components/form.d.ts +2 -2
- package/dist/components/provider.d.ts +21 -0
- package/dist/components/renderer.d.ts +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/twintag-form.react.js +12868 -12156
- package/dist/types/index.d.ts +25 -16
- package/dist/utils/data.d.ts +2 -1
- package/dist/utils/style.d.ts +2 -1
- package/index.html +5 -3
- package/lib/common/button.tsx +4 -5
- package/lib/common/calendar.tsx +25 -5
- package/lib/common/form.tsx +40 -19
- package/lib/common/input.tsx +20 -10
- package/lib/common/label.tsx +16 -3
- package/lib/common/slider.tsx +38 -0
- package/lib/common/textarea.tsx +17 -9
- package/lib/components/config.tsx +46 -17
- package/lib/components/containers/accordion.tsx +24 -7
- package/lib/components/containers/category.tsx +16 -7
- package/lib/components/fields/checkbox.tsx +12 -6
- package/lib/components/fields/date-picker.tsx +54 -18
- package/lib/components/fields/file.tsx +83 -76
- package/lib/components/fields/input.tsx +15 -6
- package/lib/components/fields/radiogroup.tsx +13 -7
- package/lib/components/fields/submit.tsx +5 -2
- package/lib/components/fields/textarea.tsx +14 -6
- package/lib/components/fields/toggle.tsx +12 -6
- package/lib/components/fields/tri-toggle.tsx +141 -0
- package/lib/components/form.tsx +5 -7
- package/lib/components/provider.tsx +159 -0
- package/lib/components/{Render/index.tsx → renderer.tsx} +19 -2
- package/lib/index.tsx +41 -36
- package/lib/types/index.ts +49 -39
- package/package.json +5 -7
- package/dist/components/Render/index.d.ts +0 -7
- package/dist/components/Render/useJson.d.ts +0 -2
- package/dist/components/index.d.ts +0 -7
- package/dist/provider.d.ts +0 -8
- package/lib/components/Render/useJson.ts +0 -76
- package/lib/components/index.tsx +0 -24
- package/lib/provider.tsx +0 -36
package/dist/types/index.d.ts
CHANGED
|
@@ -1,7 +1,20 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { ElementType } from 'react';
|
|
2
|
+
|
|
3
|
+
export type ComponentConfig = {
|
|
4
|
+
defaultValue?: unknown;
|
|
5
|
+
component: ElementType;
|
|
6
|
+
};
|
|
7
|
+
export type ParsedJsonComponent = Props & {
|
|
8
|
+
id: string;
|
|
9
|
+
type: string;
|
|
10
|
+
subtype?: string;
|
|
11
|
+
comp?: ElementType;
|
|
12
|
+
};
|
|
13
|
+
export type RawJsonComponent = RawProps & Record<string, unknown> & {
|
|
14
|
+
type: string;
|
|
15
|
+
children?: RawJsonComponent[];
|
|
16
|
+
} & {
|
|
17
|
+
props?: RawProps;
|
|
5
18
|
};
|
|
6
19
|
type RawProps = Partial<{
|
|
7
20
|
bind: string;
|
|
@@ -15,20 +28,16 @@ type RawProps = Partial<{
|
|
|
15
28
|
optionalField: boolean;
|
|
16
29
|
}>;
|
|
17
30
|
}>;
|
|
18
|
-
export type RawJsonComponent = RawProps & Record<string, unknown> & {
|
|
19
|
-
type: string;
|
|
20
|
-
children?: RawJsonComponent[];
|
|
21
|
-
} & {
|
|
22
|
-
props?: RawProps;
|
|
23
|
-
};
|
|
24
|
-
export type ParsedJsonComponent = Props & {
|
|
25
|
-
id: string;
|
|
26
|
-
type: string;
|
|
27
|
-
subtype?: string;
|
|
28
|
-
comp?: ElementType;
|
|
29
|
-
};
|
|
30
31
|
export type Props = Omit<RawProps, 'subtype'> & {
|
|
31
32
|
bind: string;
|
|
32
33
|
items?: ParsedJsonComponent[];
|
|
33
34
|
};
|
|
35
|
+
export type TwintagFormContext = {
|
|
36
|
+
variant?: 'default' | 'beta';
|
|
37
|
+
size?: 'base' | 'sm';
|
|
38
|
+
inputs: Map<string, ComponentConfig>;
|
|
39
|
+
components: Map<string, ElementType>;
|
|
40
|
+
config: ParsedJsonComponent[] | ParsedJsonComponent;
|
|
41
|
+
resetValues: Record<string, unknown>;
|
|
42
|
+
};
|
|
34
43
|
export {};
|
package/dist/utils/data.d.ts
CHANGED
package/dist/utils/style.d.ts
CHANGED
package/index.html
CHANGED
package/lib/common/button.tsx
CHANGED
|
@@ -6,7 +6,7 @@ import { tv } from 'tailwind-variants';
|
|
|
6
6
|
|
|
7
7
|
const buttonVariants = tv({
|
|
8
8
|
base: [
|
|
9
|
-
'inline-flex items-center justify-center whitespace-nowrap rounded-md
|
|
9
|
+
'inline-flex items-center justify-center whitespace-nowrap rounded-md font-medium transition-colors',
|
|
10
10
|
'ring-offset-background focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
11
11
|
'disabled:pointer-events-none disabled:opacity-50',
|
|
12
12
|
],
|
|
@@ -19,14 +19,13 @@ const buttonVariants = tv({
|
|
|
19
19
|
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
20
20
|
},
|
|
21
21
|
size: {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
lg: 'h-10 rounded-md px-8',
|
|
22
|
+
sm: 'h-9 rounded-md px-3 text-sm',
|
|
23
|
+
base: 'h-10 px-3 py-2 text-base',
|
|
25
24
|
},
|
|
26
25
|
},
|
|
27
26
|
defaultVariants: {
|
|
28
27
|
variant: 'default',
|
|
29
|
-
size: '
|
|
28
|
+
size: 'base',
|
|
30
29
|
},
|
|
31
30
|
});
|
|
32
31
|
|
package/lib/common/calendar.tsx
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { VariantProps } from 'tailwind-variants';
|
|
2
|
+
|
|
1
3
|
import * as React from 'react';
|
|
2
4
|
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
3
5
|
import { DayPicker } from 'react-day-picker';
|
|
@@ -5,8 +7,6 @@ import { tv } from 'tailwind-variants';
|
|
|
5
7
|
|
|
6
8
|
import { buttonVariants } from '@twintag/twintag-form/common/button';
|
|
7
9
|
|
|
8
|
-
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
|
|
9
|
-
|
|
10
10
|
const calendarVariants = tv({
|
|
11
11
|
slots: {
|
|
12
12
|
picker: 'p-3',
|
|
@@ -14,7 +14,7 @@ const calendarVariants = tv({
|
|
|
14
14
|
month: 'space-y-4',
|
|
15
15
|
caption: 'relative flex items-center justify-center pt-1',
|
|
16
16
|
caption_dropdowns: '',
|
|
17
|
-
caption_label: '
|
|
17
|
+
caption_label: 'font-semibold',
|
|
18
18
|
nav: 'flex items-center space-x-1',
|
|
19
19
|
nav_button: buttonVariants({
|
|
20
20
|
variant: 'outline',
|
|
@@ -26,7 +26,7 @@ const calendarVariants = tv({
|
|
|
26
26
|
head_row: 'flex',
|
|
27
27
|
head_cell: 'w-9 rounded-md text-[0.8rem] font-normal text-muted-foreground',
|
|
28
28
|
row: 'mt-2 flex w-full',
|
|
29
|
-
cell: 'relative h-9 w-9 p-0 text-center
|
|
29
|
+
cell: 'relative h-9 w-9 p-0 text-center focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-transparent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-muted/50 [&:has([aria-selected].day-range-end)]:rounded-r-md',
|
|
30
30
|
day: buttonVariants({
|
|
31
31
|
variant: 'ghost',
|
|
32
32
|
className: 'h-9 w-9 p-0 font-normal aria-selected:opacity-100',
|
|
@@ -49,21 +49,41 @@ const calendarVariants = tv({
|
|
|
49
49
|
caption_dropdowns: [
|
|
50
50
|
'flex w-4/6 justify-center gap-1',
|
|
51
51
|
'[&>*>span]:hidden [&>*]:flex-1 [&>.rdp-vhidden]:hidden ',
|
|
52
|
-
'[&>*>select]:h-7 [&>*>select]:min-w-[3.6rem] [&>*>select]:rounded-md [&>*>select]:border [&>*>select]:border-input [&>*>select]:bg-background [&>*>select]:px-1
|
|
52
|
+
'[&>*>select]:h-7 [&>*>select]:min-w-[3.6rem] [&>*>select]:rounded-md [&>*>select]:border [&>*>select]:border-input [&>*>select]:bg-background [&>*>select]:px-1',
|
|
53
53
|
'[&>*>select]:ring-offset-background [&>*>select]:focus-visible:outline-none [&>*>select]:focus-visible:ring-1 [&>*>select]:focus-visible:ring-ring',
|
|
54
54
|
],
|
|
55
55
|
},
|
|
56
56
|
},
|
|
57
|
+
size: {
|
|
58
|
+
sm: {
|
|
59
|
+
caption_label: 'text-sm',
|
|
60
|
+
caption_dropdowns: '[&>*>select]:text-sm',
|
|
61
|
+
cell: 'text-sm',
|
|
62
|
+
},
|
|
63
|
+
base: {
|
|
64
|
+
caption_label: 'text-base',
|
|
65
|
+
caption_dropdowns: '[&>*>select]:text-base',
|
|
66
|
+
cell: 'text-base',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
defaultVariants: {
|
|
71
|
+
size: 'base',
|
|
57
72
|
},
|
|
58
73
|
});
|
|
59
74
|
|
|
75
|
+
export type CalendarProps = React.ComponentProps<typeof DayPicker> &
|
|
76
|
+
VariantProps<typeof calendarVariants>;
|
|
77
|
+
|
|
60
78
|
function Calendar({
|
|
79
|
+
size,
|
|
61
80
|
className,
|
|
62
81
|
classNames,
|
|
63
82
|
showOutsideDays = true,
|
|
64
83
|
...props
|
|
65
84
|
}: CalendarProps) {
|
|
66
85
|
const slots = calendarVariants({
|
|
86
|
+
size,
|
|
67
87
|
variant:
|
|
68
88
|
props.captionLayout === 'dropdown-buttons' ? 'dropdown' : undefined,
|
|
69
89
|
});
|
package/lib/common/form.tsx
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import type * as LabelPrimitive from '@radix-ui/react-label';
|
|
2
1
|
import type { ControllerProps, FieldPath, FieldValues } from 'react-hook-form';
|
|
2
|
+
import type { VariantProps } from 'tailwind-variants';
|
|
3
3
|
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { Slot } from '@radix-ui/react-slot';
|
|
6
6
|
import { Controller, FormProvider, useFormContext } from 'react-hook-form';
|
|
7
7
|
import { tv } from 'tailwind-variants';
|
|
8
8
|
|
|
9
|
-
import { useTwintagForm } from '../provider';
|
|
10
9
|
import { Label } from './label';
|
|
11
10
|
|
|
12
11
|
const Form = FormProvider;
|
|
@@ -67,22 +66,23 @@ const FormItemContext = React.createContext<FormItemContextValue>(
|
|
|
67
66
|
);
|
|
68
67
|
|
|
69
68
|
const formItemVariants = tv({
|
|
70
|
-
base: '
|
|
69
|
+
base: '',
|
|
71
70
|
variants: {
|
|
72
71
|
variant: {
|
|
73
|
-
default: '',
|
|
72
|
+
default: 'space-y-2',
|
|
74
73
|
beta: 'space-y-1',
|
|
75
74
|
},
|
|
76
75
|
},
|
|
76
|
+
defaultVariants: {
|
|
77
|
+
variant: 'default',
|
|
78
|
+
},
|
|
77
79
|
});
|
|
78
80
|
const FormItem = React.forwardRef<
|
|
79
81
|
HTMLDivElement,
|
|
80
|
-
React.HTMLAttributes<HTMLDivElement>
|
|
81
|
-
>(({ className, ...props }, ref) => {
|
|
82
|
+
React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof formItemVariants>
|
|
83
|
+
>(({ variant, className, ...props }, ref) => {
|
|
82
84
|
const id = React.useId();
|
|
83
85
|
|
|
84
|
-
const { variant } = useTwintagForm();
|
|
85
|
-
|
|
86
86
|
return (
|
|
87
87
|
<FormItemContext.Provider value={{ id }}>
|
|
88
88
|
<div
|
|
@@ -104,14 +104,15 @@ const formLabelVariants = tv({
|
|
|
104
104
|
},
|
|
105
105
|
});
|
|
106
106
|
const FormLabel = React.forwardRef<
|
|
107
|
-
React.ElementRef<typeof
|
|
108
|
-
React.ComponentPropsWithoutRef<typeof
|
|
109
|
-
>(({ className, ...props }, ref) => {
|
|
107
|
+
React.ElementRef<typeof Label>,
|
|
108
|
+
React.ComponentPropsWithoutRef<typeof Label>
|
|
109
|
+
>(({ size, className, ...props }, ref) => {
|
|
110
110
|
const { error, formItemId } = useFormField();
|
|
111
111
|
|
|
112
112
|
return (
|
|
113
113
|
<Label
|
|
114
114
|
ref={ref}
|
|
115
|
+
size={size}
|
|
115
116
|
className={formLabelVariants({
|
|
116
117
|
error: !!error,
|
|
117
118
|
className,
|
|
@@ -147,19 +148,29 @@ const FormControl = React.forwardRef<
|
|
|
147
148
|
FormControl.displayName = 'FormControl';
|
|
148
149
|
|
|
149
150
|
const formDescriptionVariants = tv({
|
|
150
|
-
base: 'text-
|
|
151
|
+
base: 'text-muted-foreground',
|
|
152
|
+
variants: {
|
|
153
|
+
size: {
|
|
154
|
+
sm: 'text-[0.8rem] leading-none',
|
|
155
|
+
base: 'text-[0.9rem] leading-none',
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
defaultVariants: {
|
|
159
|
+
size: 'base',
|
|
160
|
+
},
|
|
151
161
|
});
|
|
152
162
|
const FormDescription = React.forwardRef<
|
|
153
163
|
HTMLParagraphElement,
|
|
154
|
-
React.HTMLAttributes<HTMLParagraphElement>
|
|
155
|
-
>
|
|
164
|
+
React.HTMLAttributes<HTMLParagraphElement> &
|
|
165
|
+
VariantProps<typeof formDescriptionVariants>
|
|
166
|
+
>(({ size, className, ...props }, ref) => {
|
|
156
167
|
const { formDescriptionId } = useFormField();
|
|
157
168
|
|
|
158
169
|
return (
|
|
159
170
|
<p
|
|
160
171
|
ref={ref}
|
|
161
172
|
id={formDescriptionId}
|
|
162
|
-
className={formDescriptionVariants({ className })}
|
|
173
|
+
className={formDescriptionVariants({ size, className })}
|
|
163
174
|
{...props}
|
|
164
175
|
/>
|
|
165
176
|
);
|
|
@@ -167,12 +178,22 @@ const FormDescription = React.forwardRef<
|
|
|
167
178
|
FormDescription.displayName = 'FormDescription';
|
|
168
179
|
|
|
169
180
|
const formMessageVariants = tv({
|
|
170
|
-
base: '
|
|
181
|
+
base: 'font-medium text-destructive',
|
|
182
|
+
variants: {
|
|
183
|
+
size: {
|
|
184
|
+
sm: 'text-[0.8rem]',
|
|
185
|
+
base: 'text-[0.9rem]',
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
defaultVariants: {
|
|
189
|
+
size: 'base',
|
|
190
|
+
},
|
|
171
191
|
});
|
|
172
192
|
const FormMessage = React.forwardRef<
|
|
173
193
|
HTMLParagraphElement,
|
|
174
|
-
React.HTMLAttributes<HTMLParagraphElement>
|
|
175
|
-
>
|
|
194
|
+
React.HTMLAttributes<HTMLParagraphElement> &
|
|
195
|
+
VariantProps<typeof formMessageVariants>
|
|
196
|
+
>(({ size, className, children, ...props }, ref) => {
|
|
176
197
|
const { error, formMessageId } = useFormField();
|
|
177
198
|
const body = error ? String(error?.message) : children;
|
|
178
199
|
|
|
@@ -184,7 +205,7 @@ const FormMessage = React.forwardRef<
|
|
|
184
205
|
<p
|
|
185
206
|
ref={ref}
|
|
186
207
|
id={formMessageId}
|
|
187
|
-
className={formMessageVariants({ className })}
|
|
208
|
+
className={formMessageVariants({ size, className })}
|
|
188
209
|
{...props}
|
|
189
210
|
>
|
|
190
211
|
{body}
|
package/lib/common/input.tsx
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
+
import type { VariantProps } from 'tailwind-variants';
|
|
2
|
+
|
|
1
3
|
import * as React from 'react';
|
|
2
4
|
import { tv } from 'tailwind-variants';
|
|
3
5
|
|
|
4
|
-
import { useTwintagForm } from '@twintag/twintag-form/provider';
|
|
5
|
-
|
|
6
|
-
export type InputProps = React.InputHTMLAttributes<HTMLInputElement>;
|
|
7
|
-
|
|
8
6
|
const inputVariants = tv({
|
|
9
7
|
slots: {
|
|
10
8
|
root: 'relative',
|
|
11
9
|
input: [
|
|
12
|
-
'flex h-10 w-full border-input bg-background py-2 text-
|
|
13
|
-
'file:border-0 file:bg-transparent file:px-0 file:
|
|
10
|
+
'flex h-10 w-full border-input bg-background py-2 text-primary-foreground placeholder:text-muted-foreground focus-visible:outline-none',
|
|
11
|
+
'file:border-0 file:bg-transparent file:px-0 file:font-medium file:text-primary-foreground',
|
|
14
12
|
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
15
13
|
],
|
|
16
14
|
},
|
|
@@ -25,17 +23,29 @@ const inputVariants = tv({
|
|
|
25
23
|
input: 'border-b px-1',
|
|
26
24
|
},
|
|
27
25
|
},
|
|
26
|
+
size: {
|
|
27
|
+
sm: {
|
|
28
|
+
input: 'text-sm file:text-sm',
|
|
29
|
+
},
|
|
30
|
+
base: {
|
|
31
|
+
input: 'text-base file:text-base',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
28
34
|
},
|
|
29
35
|
defaultVariants: {
|
|
30
36
|
variant: 'default',
|
|
37
|
+
size: 'base',
|
|
31
38
|
},
|
|
32
39
|
});
|
|
33
40
|
|
|
41
|
+
export type InputProps = Omit<
|
|
42
|
+
React.InputHTMLAttributes<HTMLInputElement>,
|
|
43
|
+
'size'
|
|
44
|
+
> &
|
|
45
|
+
VariantProps<typeof inputVariants>;
|
|
34
46
|
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
35
|
-
({ className, type, ...props }, ref) => {
|
|
36
|
-
const {
|
|
37
|
-
|
|
38
|
-
const { root, input } = inputVariants({ variant });
|
|
47
|
+
({ variant, size, className, type, ...props }, ref) => {
|
|
48
|
+
const { root, input } = inputVariants({ variant, size });
|
|
39
49
|
|
|
40
50
|
return (
|
|
41
51
|
<div className={root()}>
|
package/lib/common/label.tsx
CHANGED
|
@@ -1,21 +1,34 @@
|
|
|
1
|
+
import type { VariantProps } from 'tailwind-variants';
|
|
2
|
+
|
|
1
3
|
import * as React from 'react';
|
|
2
4
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
3
5
|
import { tv } from 'tailwind-variants';
|
|
4
6
|
|
|
5
7
|
const labelVariants = tv({
|
|
6
8
|
base: [
|
|
7
|
-
'text-
|
|
9
|
+
'text-label',
|
|
8
10
|
'peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
|
9
11
|
],
|
|
12
|
+
variants: {
|
|
13
|
+
size: {
|
|
14
|
+
sm: 'text-sm leading-none',
|
|
15
|
+
base: 'text-base leading-none',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
defaultVariants: {
|
|
19
|
+
size: 'base',
|
|
20
|
+
},
|
|
10
21
|
});
|
|
11
22
|
|
|
12
23
|
const Label = React.forwardRef<
|
|
13
24
|
React.ElementRef<typeof LabelPrimitive.Root>,
|
|
14
|
-
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
|
|
15
|
-
>
|
|
25
|
+
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
|
|
26
|
+
VariantProps<typeof labelVariants>
|
|
27
|
+
>(({ size, className, ...props }, ref) => (
|
|
16
28
|
<LabelPrimitive.Root
|
|
17
29
|
ref={ref}
|
|
18
30
|
className={labelVariants({
|
|
31
|
+
size,
|
|
19
32
|
className,
|
|
20
33
|
})}
|
|
21
34
|
{...props}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
3
|
+
import { tv } from 'tailwind-variants';
|
|
4
|
+
|
|
5
|
+
const sliderVariants = tv({
|
|
6
|
+
slots: {
|
|
7
|
+
root: 'relative flex w-full touch-none select-none items-center',
|
|
8
|
+
track: 'relative h-2 w-full grow overflow-hidden rounded-full bg-muted',
|
|
9
|
+
range: 'absolute h-full bg-accent',
|
|
10
|
+
thumb:
|
|
11
|
+
'block h-5 w-5 rounded-full border-2 border-accent bg-background ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const Slider = React.forwardRef<
|
|
16
|
+
React.ElementRef<typeof SliderPrimitive.Root>,
|
|
17
|
+
React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
|
|
18
|
+
>(({ className, ...props }, ref) => {
|
|
19
|
+
const { root, track, range, thumb } = sliderVariants();
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<SliderPrimitive.Root
|
|
23
|
+
ref={ref}
|
|
24
|
+
className={root({
|
|
25
|
+
className,
|
|
26
|
+
})}
|
|
27
|
+
{...props}
|
|
28
|
+
>
|
|
29
|
+
<SliderPrimitive.Track className={track()}>
|
|
30
|
+
<SliderPrimitive.Range className={range()} />
|
|
31
|
+
</SliderPrimitive.Track>
|
|
32
|
+
<SliderPrimitive.Thumb className={thumb()} />
|
|
33
|
+
</SliderPrimitive.Root>
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
Slider.displayName = SliderPrimitive.Root.displayName;
|
|
37
|
+
|
|
38
|
+
export { Slider };
|
package/lib/common/textarea.tsx
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
|
+
import type { VariantProps } from 'tailwind-variants';
|
|
2
|
+
|
|
1
3
|
import * as React from 'react';
|
|
2
4
|
import { tv } from 'tailwind-variants';
|
|
3
5
|
|
|
4
|
-
import { useTwintagForm } from '@twintag/twintag-form/provider';
|
|
5
|
-
|
|
6
|
-
type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
|
|
7
|
-
|
|
8
6
|
const textareaVariants = tv({
|
|
9
7
|
slots: {
|
|
10
8
|
root: 'relative',
|
|
11
9
|
textarea: [
|
|
12
|
-
'flex min-h-[60px] w-full border-input bg-background py-2 text-
|
|
10
|
+
'flex min-h-[60px] w-full border-input bg-background py-2 text-primary-foreground shadow-sm placeholder:text-muted-foreground focus-visible:outline-none',
|
|
13
11
|
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
14
12
|
],
|
|
15
13
|
},
|
|
@@ -24,16 +22,26 @@ const textareaVariants = tv({
|
|
|
24
22
|
textarea: 'border-b px-1',
|
|
25
23
|
},
|
|
26
24
|
},
|
|
25
|
+
size: {
|
|
26
|
+
sm: {
|
|
27
|
+
textarea: 'text-sm',
|
|
28
|
+
},
|
|
29
|
+
base: {
|
|
30
|
+
textarea: 'text-base',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
27
33
|
},
|
|
28
34
|
defaultVariants: {
|
|
29
35
|
variant: 'default',
|
|
36
|
+
size: 'base',
|
|
30
37
|
},
|
|
31
38
|
});
|
|
32
|
-
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
33
|
-
({ className, ...props }, ref) => {
|
|
34
|
-
const { variant } = useTwintagForm();
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> &
|
|
41
|
+
VariantProps<typeof textareaVariants>;
|
|
42
|
+
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
43
|
+
({ variant, size, className, ...props }, ref) => {
|
|
44
|
+
const { root, textarea } = textareaVariants({ size, variant });
|
|
37
45
|
|
|
38
46
|
return (
|
|
39
47
|
<div className={root()}>
|
|
@@ -1,25 +1,54 @@
|
|
|
1
1
|
import type { ElementType, FC } from 'react';
|
|
2
|
+
import type { ComponentConfig } from '../types';
|
|
2
3
|
|
|
3
4
|
import { Accordion } from './containers/accordion';
|
|
4
5
|
import { Category } from './containers/category';
|
|
5
|
-
import { Checkbox } from './fields/checkbox';
|
|
6
|
-
import { DatePicker } from './fields/date-picker';
|
|
7
|
-
import { File } from './fields/file';
|
|
8
|
-
import { Input as InputField } from './fields/input';
|
|
9
|
-
import { RadioGroup } from './fields/radiogroup';
|
|
6
|
+
import { Checkbox, DEFAULT_CHECKBOX_VALUE } from './fields/checkbox';
|
|
7
|
+
import { DatePicker, DEFAULT_DATE_PICKER_VALUE } from './fields/date-picker';
|
|
8
|
+
import { DEFAULT_FILE_VALUE, File } from './fields/file';
|
|
9
|
+
import { DEFAULT_INPUT_VALUE, Input as InputField } from './fields/input';
|
|
10
|
+
import { DEFAULT_RADIOGROUP_VALUE, RadioGroup } from './fields/radiogroup';
|
|
10
11
|
import { Submit } from './fields/submit';
|
|
11
|
-
import { Textarea } from './fields/textarea';
|
|
12
|
-
import { Toggle } from './fields/toggle';
|
|
12
|
+
import { DEFAULT_TEXTAREA_VALUE, Textarea } from './fields/textarea';
|
|
13
|
+
import { DEFAULT_TOGGLE_VALUE, Toggle } from './fields/toggle';
|
|
14
|
+
import { DEFAULT_TRI_TOGGLE_VALUE, TriToggle } from './fields/tri-toggle';
|
|
13
15
|
|
|
14
|
-
export const Inputs = new Map<string,
|
|
15
|
-
.set('simple',
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
.set('
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
export const Inputs = new Map<string, ComponentConfig>()
|
|
17
|
+
.set('simple', {
|
|
18
|
+
defaultValue: DEFAULT_INPUT_VALUE,
|
|
19
|
+
component: InputField,
|
|
20
|
+
})
|
|
21
|
+
.set('textarea', {
|
|
22
|
+
defaultValue: DEFAULT_TEXTAREA_VALUE,
|
|
23
|
+
component: Textarea,
|
|
24
|
+
})
|
|
25
|
+
.set('toggle', {
|
|
26
|
+
defaultValue: DEFAULT_TOGGLE_VALUE,
|
|
27
|
+
component: Toggle,
|
|
28
|
+
})
|
|
29
|
+
.set('file', {
|
|
30
|
+
defaultValue: DEFAULT_FILE_VALUE,
|
|
31
|
+
component: File,
|
|
32
|
+
})
|
|
33
|
+
.set('submit', {
|
|
34
|
+
component: Submit,
|
|
35
|
+
})
|
|
36
|
+
.set('checkbox', {
|
|
37
|
+
defaultValue: DEFAULT_CHECKBOX_VALUE,
|
|
38
|
+
component: Checkbox,
|
|
39
|
+
})
|
|
40
|
+
.set('radiogroup', {
|
|
41
|
+
defaultValue: DEFAULT_RADIOGROUP_VALUE,
|
|
42
|
+
component: RadioGroup,
|
|
43
|
+
})
|
|
44
|
+
.set('datepicker', {
|
|
45
|
+
defaultValue: DEFAULT_DATE_PICKER_VALUE,
|
|
46
|
+
component: DatePicker,
|
|
47
|
+
})
|
|
48
|
+
.set('tri-toggle', {
|
|
49
|
+
defaultValue: DEFAULT_TRI_TOGGLE_VALUE,
|
|
50
|
+
component: TriToggle,
|
|
51
|
+
});
|
|
23
52
|
|
|
24
53
|
type InputProps = {
|
|
25
54
|
subtype?: string;
|
|
@@ -27,7 +56,7 @@ type InputProps = {
|
|
|
27
56
|
bind?: string;
|
|
28
57
|
};
|
|
29
58
|
const Input: FC<InputProps> = ({ subtype = 'simple', ...rest }) => {
|
|
30
|
-
const Comp = Inputs.get(subtype);
|
|
59
|
+
const Comp = Inputs.get(subtype)?.component;
|
|
31
60
|
|
|
32
61
|
if (!Comp) return <></>;
|
|
33
62
|
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
AccordionTrigger,
|
|
12
12
|
} from '@twintag/twintag-form/common/accordion';
|
|
13
13
|
import { Icon } from '@twintag/twintag-form/common/icon';
|
|
14
|
-
import { useTwintagForm } from '@twintag/twintag-form/provider';
|
|
14
|
+
import { useTwintagForm } from '@twintag/twintag-form/components/provider';
|
|
15
15
|
import { camelize } from '@twintag/twintag-form/utils/string';
|
|
16
16
|
|
|
17
17
|
type AccordionRootProps = {
|
|
@@ -51,20 +51,32 @@ const accordionItemVariants = tv({
|
|
|
51
51
|
slots: {
|
|
52
52
|
item: 'px-5 last:border-none',
|
|
53
53
|
trigger: 'flex flex-1 items-center gap-2.5 font-tf-font',
|
|
54
|
-
|
|
54
|
+
icon: 'shrink-0',
|
|
55
|
+
content: 'space-y-3',
|
|
55
56
|
},
|
|
56
57
|
variants: {
|
|
57
58
|
variant: {
|
|
58
59
|
default: {
|
|
59
|
-
trigger: '
|
|
60
|
+
trigger: 'font-medium',
|
|
60
61
|
},
|
|
61
62
|
beta: {
|
|
62
|
-
trigger: '
|
|
63
|
+
trigger: '',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
size: {
|
|
67
|
+
sm: {
|
|
68
|
+
item: 'text-sm',
|
|
69
|
+
icon: 'h-4 w-4',
|
|
70
|
+
},
|
|
71
|
+
base: {
|
|
72
|
+
item: 'text-base',
|
|
73
|
+
icon: 'h-5 w-5',
|
|
63
74
|
},
|
|
64
75
|
},
|
|
65
76
|
},
|
|
66
77
|
defaultVariants: {
|
|
67
78
|
variant: 'default',
|
|
79
|
+
size: 'base',
|
|
68
80
|
},
|
|
69
81
|
});
|
|
70
82
|
|
|
@@ -74,15 +86,20 @@ const AccordionItem: FC<AccordionItemProps> = ({
|
|
|
74
86
|
icon,
|
|
75
87
|
children,
|
|
76
88
|
}) => {
|
|
77
|
-
const { variant } = useTwintagForm();
|
|
89
|
+
const { variant, size } = useTwintagForm();
|
|
78
90
|
|
|
79
|
-
const {
|
|
91
|
+
const {
|
|
92
|
+
item,
|
|
93
|
+
trigger,
|
|
94
|
+
icon: iconVariants,
|
|
95
|
+
content,
|
|
96
|
+
} = accordionItemVariants({ size, variant });
|
|
80
97
|
|
|
81
98
|
return (
|
|
82
99
|
<AccordionItemPrimitive value={camelize(label)} className={item()}>
|
|
83
100
|
<AccordionTrigger className='text-category'>
|
|
84
101
|
<span className={trigger()}>
|
|
85
|
-
{icon ? <Icon name={icon} className=
|
|
102
|
+
{icon ? <Icon name={icon} className={iconVariants()} /> : <></>}
|
|
86
103
|
{label}
|
|
87
104
|
</span>
|
|
88
105
|
</AccordionTrigger>
|