@datum-cloud/datum-ui 0.6.0-alpha.b8a44ac → 0.6.0
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/README.md +1 -0
- package/dist/autocomplete/index.mjs +1 -1
- package/dist/{autocomplete-V5-qslzS.mjs → autocomplete-CkYJueBL.mjs} +2 -2
- package/dist/autosearch/index.mjs +199 -0
- package/dist/{calendar-date-picker-DWK94_DC.mjs → calendar-date-picker-CDT-8Ha8.mjs} +2 -1
- package/dist/combobox/index.mjs +1 -1
- package/dist/{combobox-cKTFK4uN.mjs → combobox-B-C9lJeD.mjs} +3 -2
- package/dist/components/features/autocomplete/autocomplete.d.ts +1 -1
- package/dist/components/features/autocomplete/autocomplete.d.ts.map +1 -1
- package/dist/components/features/autocomplete/autocomplete.types.d.ts +2 -0
- package/dist/components/features/autocomplete/autocomplete.types.d.ts.map +1 -1
- package/dist/components/features/autosearch/autosearch.d.ts +35 -0
- package/dist/components/features/autosearch/autosearch.d.ts.map +1 -0
- package/dist/components/features/autosearch/autosearch.types.d.ts +51 -0
- package/dist/components/features/autosearch/autosearch.types.d.ts.map +1 -0
- package/dist/components/features/autosearch/index.d.ts +3 -0
- package/dist/components/features/autosearch/index.d.ts.map +1 -0
- package/dist/components/features/calendar-date-picker/calendar-date-picker.d.ts +2 -1
- package/dist/components/features/calendar-date-picker/calendar-date-picker.d.ts.map +1 -1
- package/dist/components/features/combobox/combobox.d.ts +1 -1
- package/dist/components/features/combobox/combobox.d.ts.map +1 -1
- package/dist/components/features/combobox/types.d.ts +6 -0
- package/dist/components/features/combobox/types.d.ts.map +1 -1
- package/dist/components/features/date-time-picker/date-time-picker.d.ts +1 -1
- package/dist/components/features/date-time-picker/date-time-picker.d.ts.map +1 -1
- package/dist/components/features/date-time-picker/types.d.ts +6 -0
- package/dist/components/features/date-time-picker/types.d.ts.map +1 -1
- package/dist/components/features/form/adapter-types.d.ts +6 -0
- package/dist/components/features/form/adapter-types.d.ts.map +1 -1
- package/dist/components/features/form/adapters/conform/conform-adapter.d.ts.map +1 -1
- package/dist/components/features/form/adapters/rhf/rhf-adapter.d.ts.map +1 -1
- package/dist/components/features/form/components/form-autocomplete.d.ts.map +1 -1
- package/dist/components/features/form/components/form-autosearch.d.ts +23 -11
- package/dist/components/features/form/components/form-autosearch.d.ts.map +1 -1
- package/dist/components/features/form/components/form-checkbox.d.ts.map +1 -1
- package/dist/components/features/form/components/form-combobox.d.ts +5 -1
- package/dist/components/features/form/components/form-combobox.d.ts.map +1 -1
- package/dist/components/features/form/components/form-date-picker.d.ts +3 -1
- package/dist/components/features/form/components/form-date-picker.d.ts.map +1 -1
- package/dist/components/features/form/components/form-date-time-picker.d.ts +3 -1
- package/dist/components/features/form/components/form-date-time-picker.d.ts.map +1 -1
- package/dist/components/features/form/components/form-field.d.ts.map +1 -1
- package/dist/components/features/form/components/form-radio-group.d.ts.map +1 -1
- package/dist/components/features/form/components/form-root.d.ts.map +1 -1
- package/dist/components/features/form/components/form-switch.d.ts.map +1 -1
- package/dist/components/features/form/components/form-time-picker.d.ts.map +1 -1
- package/dist/components/features/form/components/form-transfer.d.ts.map +1 -1
- package/dist/components/features/form/components/stepper/form-stepper.d.ts +3 -1
- package/dist/components/features/form/components/stepper/form-stepper.d.ts.map +1 -1
- package/dist/components/features/form/hooks/use-display-touched.d.ts +20 -0
- package/dist/components/features/form/hooks/use-display-touched.d.ts.map +1 -0
- package/dist/components/features/form/hooks/use-field.d.ts +4 -0
- package/dist/components/features/form/hooks/use-field.d.ts.map +1 -1
- package/dist/components/features/form/types/index.d.ts +10 -0
- package/dist/components/features/form/types/index.d.ts.map +1 -1
- package/dist/data-table/index.mjs +1 -1
- package/dist/date-picker/index.mjs +1 -1
- package/dist/date-time-picker/index.mjs +1 -1
- package/dist/{date-time-picker-Dy2jrJoN.mjs → date-time-picker-BomrW07W.mjs} +49 -46
- package/dist/form/adapters/conform/index.mjs +10 -3
- package/dist/form/adapters/rhf/index.mjs +11 -8
- package/dist/form/index.mjs +1 -1
- package/dist/form/stepper/index.mjs +19 -41
- package/dist/{form-mlNLKaB5.mjs → form-B3rQ4CH9.mjs} +130 -46
- package/dist/index.mjs +3 -3
- package/dist/transfer/index.mjs +1 -1
- package/dist/{transfer-B2n8pgEQ.mjs → transfer-46C-rFFW.mjs} +12 -8
- package/dist/{get-field-constraints-BicgDkfH.mjs → use-display-touched-I39aXEBD.mjs} +33 -1
- package/package.json +6 -1
|
@@ -6,7 +6,6 @@ import { t as defineStepper } from "../../stepper-DvIOp0hh.mjs";
|
|
|
6
6
|
import { CheckIcon } from "lucide-react";
|
|
7
7
|
import * as React$1 from "react";
|
|
8
8
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import { z } from "zod";
|
|
10
9
|
//#region src/components/features/form/components/stepper/form-stepper.tsx
|
|
11
10
|
const FormStepperContext = React$1.createContext(null);
|
|
12
11
|
function useFormStepperContext() {
|
|
@@ -15,39 +14,6 @@ function useFormStepperContext() {
|
|
|
15
14
|
return context;
|
|
16
15
|
}
|
|
17
16
|
/**
|
|
18
|
-
* Recursively unwrap ZodIntersection (from .and()) to extract the base ZodObject.
|
|
19
|
-
*
|
|
20
|
-
* Zod v4 schema types use `def.type` as a string discriminant:
|
|
21
|
-
* - "intersection" (from .and()): merge left + right base objects
|
|
22
|
-
* - "object": return directly
|
|
23
|
-
*
|
|
24
|
-
* Note: In Zod v4, .superRefine() and .refine() return `this` (no wrapper),
|
|
25
|
-
* so only ZodIntersection needs unwrapping.
|
|
26
|
-
*/
|
|
27
|
-
function getBaseObject(schema) {
|
|
28
|
-
if (schema.def.type === "intersection") {
|
|
29
|
-
const intersectionDef = schema.def;
|
|
30
|
-
const left = getBaseObject(intersectionDef.left);
|
|
31
|
-
const right = getBaseObject(intersectionDef.right);
|
|
32
|
-
return left.merge(right);
|
|
33
|
-
}
|
|
34
|
-
if (schema.def.type !== "object") return z.object({});
|
|
35
|
-
return schema;
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Merge multiple zod schemas into one ZodObject for HTML constraint generation.
|
|
39
|
-
* Handles ZodIntersection (.and()) by unwrapping to base ZodObject shapes.
|
|
40
|
-
* Per-step validation still uses the original schemas with all refinements intact.
|
|
41
|
-
*/
|
|
42
|
-
function mergeSchemas(steps) {
|
|
43
|
-
if (steps.length === 0) throw new Error("Form.Stepper requires at least one step");
|
|
44
|
-
return steps.reduce((acc, step, index) => {
|
|
45
|
-
const base = getBaseObject(step.schema);
|
|
46
|
-
if (index === 0) return base;
|
|
47
|
-
return acc.merge(base);
|
|
48
|
-
}, {});
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
17
|
* Convert StepConfig[] to Stepperize step format
|
|
52
18
|
*/
|
|
53
19
|
function toStepperizeSteps(steps) {
|
|
@@ -89,7 +55,7 @@ function toStepperizeSteps(steps) {
|
|
|
89
55
|
* </Form.Stepper>
|
|
90
56
|
* ```
|
|
91
57
|
*/
|
|
92
|
-
function FormStepper({ steps, children, onComplete, onStepChange, initialStep, className, defaultValues, id, formComponent }) {
|
|
58
|
+
function FormStepper({ steps, children, onComplete, onStepChange, initialStep, className, defaultValues, id, formComponent, mode = "onSubmit" }) {
|
|
93
59
|
const stepperDef = React$1.useMemo(() => {
|
|
94
60
|
return defineStepper(...toStepperizeSteps(steps));
|
|
95
61
|
}, [steps]);
|
|
@@ -111,19 +77,19 @@ function FormStepper({ steps, children, onComplete, onStepChange, initialStep, c
|
|
|
111
77
|
defaultValues,
|
|
112
78
|
id,
|
|
113
79
|
formComponent,
|
|
80
|
+
mode,
|
|
114
81
|
children
|
|
115
82
|
})
|
|
116
83
|
});
|
|
117
84
|
}
|
|
118
85
|
FormStepper.displayName = "Form.Stepper";
|
|
119
|
-
function FormStepperContent({ steps, stepperDef, children, onComplete, onStepChange, className, defaultValues, id, formComponent }) {
|
|
86
|
+
function FormStepperContent({ steps, stepperDef, children, onComplete, onStepChange, className, defaultValues, id, formComponent, mode }) {
|
|
120
87
|
const { useStepper } = stepperDef;
|
|
121
88
|
const stepper = useStepper();
|
|
122
89
|
return /* @__PURE__ */ jsx(StepForm, {
|
|
123
90
|
steps,
|
|
124
91
|
stepper,
|
|
125
92
|
currentStepConfig: React$1.useMemo(() => steps.find((s) => s.id === stepper.state.current.data.id) ?? steps[0], [steps, stepper.state.current.data.id]),
|
|
126
|
-
combinedSchema: React$1.useMemo(() => mergeSchemas(steps), [steps]),
|
|
127
93
|
storedValues: React$1.useMemo(() => {
|
|
128
94
|
const allMetadata = steps.reduce((acc, step) => ({
|
|
129
95
|
...acc,
|
|
@@ -144,15 +110,20 @@ function FormStepperContent({ steps, stepperDef, children, onComplete, onStepCha
|
|
|
144
110
|
className,
|
|
145
111
|
id,
|
|
146
112
|
formComponent,
|
|
113
|
+
mode,
|
|
147
114
|
children
|
|
148
115
|
}, stepper.state.current.data.id);
|
|
149
116
|
}
|
|
150
|
-
function StepForm({ steps, stepper, currentStepConfig,
|
|
117
|
+
function StepForm({ steps, stepper, currentStepConfig, storedValues, children, onComplete, onStepChange, className, id, formComponent: FormComp = "form", mode }) {
|
|
151
118
|
const adapter = useAdapter();
|
|
152
119
|
const [isSubmitting, setIsSubmitting] = React$1.useState(false);
|
|
120
|
+
const [isSubmitted, setIsSubmitted] = React$1.useState(false);
|
|
121
|
+
const [submitCount, setSubmitCount] = React$1.useState(0);
|
|
153
122
|
const formRef = React$1.useRef(null);
|
|
154
123
|
const currentIndex = stepper.lookup.getIndex(stepper.state.current.data.id);
|
|
155
124
|
const handleStepSubmit = React$1.useCallback(async (data) => {
|
|
125
|
+
setIsSubmitted(true);
|
|
126
|
+
setSubmitCount((prev) => prev + 1);
|
|
156
127
|
stepper.metadata.set(stepper.state.current.data.id, data);
|
|
157
128
|
if (stepper.state.isLast) {
|
|
158
129
|
setIsSubmitting(true);
|
|
@@ -183,7 +154,7 @@ function StepForm({ steps, stepper, currentStepConfig, combinedSchema: _combined
|
|
|
183
154
|
const instance = adapter.useCreateForm({
|
|
184
155
|
schema: currentStepConfig.schema,
|
|
185
156
|
defaultValues: storedValues,
|
|
186
|
-
mode
|
|
157
|
+
mode,
|
|
187
158
|
id: `${id ?? "stepper"}-${currentStepConfig.id}`,
|
|
188
159
|
onSubmit: handleStepSubmit,
|
|
189
160
|
formRef
|
|
@@ -253,16 +224,23 @@ function StepForm({ steps, stepper, currentStepConfig, combinedSchema: _combined
|
|
|
253
224
|
isSubmitting,
|
|
254
225
|
isDirty: instance.formState.isDirty,
|
|
255
226
|
isValid: instance.formState.isValid,
|
|
256
|
-
isSubmitted
|
|
257
|
-
submitCount
|
|
227
|
+
isSubmitted,
|
|
228
|
+
submitCount,
|
|
258
229
|
dirtyFields: instance.formState.dirtyFields,
|
|
259
230
|
touchedFields: instance.formState.touchedFields,
|
|
231
|
+
mode,
|
|
232
|
+
displayTouchedFields: instance.touchedFields,
|
|
233
|
+
markFieldTouched: instance.markFieldTouched,
|
|
234
|
+
markAllFieldsTouched: instance.markAllFieldsTouched,
|
|
260
235
|
submit: () => formRef.current?.requestSubmit(),
|
|
261
236
|
reset: () => instance.reset(),
|
|
262
237
|
formId: instance.id
|
|
263
238
|
}), [
|
|
264
239
|
instance,
|
|
265
240
|
isSubmitting,
|
|
241
|
+
isSubmitted,
|
|
242
|
+
submitCount,
|
|
243
|
+
mode,
|
|
266
244
|
instance.formState
|
|
267
245
|
]);
|
|
268
246
|
const renderProps = {
|
|
@@ -10,17 +10,18 @@ import { i as SelectItem, l as SelectTrigger, n as SelectContent, t as Select, u
|
|
|
10
10
|
import { t as Tooltip } from "./tooltip-Cruvl5F6.mjs";
|
|
11
11
|
import { t as Switch } from "./switch-DQJQhPIQ.mjs";
|
|
12
12
|
import { t as Textarea } from "./textarea-BwD-MmTV.mjs";
|
|
13
|
-
import { t as Autocomplete } from "./autocomplete-
|
|
14
|
-
import { t as CalendarDatePicker } from "./calendar-date-picker-
|
|
13
|
+
import { t as Autocomplete } from "./autocomplete-CkYJueBL.mjs";
|
|
14
|
+
import { t as CalendarDatePicker } from "./calendar-date-picker-CDT-8Ha8.mjs";
|
|
15
15
|
import { t as toast } from "./toast-BWnN5fax.mjs";
|
|
16
|
+
import { Autosearch } from "./autosearch/index.mjs";
|
|
16
17
|
import { n as useFormContext$1, t as FormProvider } from "./form-context-Ccxm-wqL.mjs";
|
|
17
|
-
import { t as Combobox } from "./combobox-
|
|
18
|
+
import { t as Combobox } from "./combobox-B-C9lJeD.mjs";
|
|
18
19
|
import { t as useCopyToClipboard } from "./use-copy-to-clipboard-uNeeVHC4.mjs";
|
|
19
|
-
import { t as DateTimePicker } from "./date-time-picker-
|
|
20
|
+
import { t as DateTimePicker } from "./date-time-picker-BomrW07W.mjs";
|
|
20
21
|
import { n as useAdapter } from "./adapter-context-rWveHhDd.mjs";
|
|
21
22
|
import { InputWithAddons } from "./input-with-addons/index.mjs";
|
|
22
23
|
import { t as TimePicker } from "./time-picker-BoF7pZZ2.mjs";
|
|
23
|
-
import { t as Transfer } from "./transfer-
|
|
24
|
+
import { t as Transfer } from "./transfer-46C-rFFW.mjs";
|
|
24
25
|
import { CheckIcon, CircleHelp, CopyIcon } from "lucide-react";
|
|
25
26
|
import * as React$1 from "react";
|
|
26
27
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -94,7 +95,10 @@ function FormAutocomplete({ disabled, className, ...props }) {
|
|
|
94
95
|
name: fieldState?.name,
|
|
95
96
|
id,
|
|
96
97
|
value,
|
|
97
|
-
onValueChange: (val) =>
|
|
98
|
+
onValueChange: (val) => {
|
|
99
|
+
fieldState?.change(val);
|
|
100
|
+
fieldState?.blur();
|
|
101
|
+
},
|
|
98
102
|
disabled: isDisabled,
|
|
99
103
|
triggerClassName: cn(hasErrors && "border-destructive", props.triggerClassName),
|
|
100
104
|
className
|
|
@@ -104,23 +108,54 @@ FormAutocomplete.displayName = "Form.Autocomplete";
|
|
|
104
108
|
//#endregion
|
|
105
109
|
//#region src/components/features/form/components/form-autosearch.tsx
|
|
106
110
|
/**
|
|
107
|
-
* Form.Autosearch -
|
|
111
|
+
* Form.Autosearch - Search-first input with dropdown results
|
|
108
112
|
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
113
|
+
* Automatically wired to the parent Form.Field context.
|
|
114
|
+
* Shows a text input that triggers search and displays results in a popover.
|
|
115
|
+
* Different from Form.Autocomplete which shows all options upfront.
|
|
111
116
|
*
|
|
112
117
|
* @example Basic usage
|
|
113
118
|
* ```tsx
|
|
114
|
-
* <Form.Field name="
|
|
119
|
+
* <Form.Field name="userId" label="User" required>
|
|
120
|
+
* <Form.Autosearch
|
|
121
|
+
* options={users}
|
|
122
|
+
* onSearch={handleSearch}
|
|
123
|
+
* loading={isSearching}
|
|
124
|
+
* placeholder="Search users..."
|
|
125
|
+
* />
|
|
126
|
+
* </Form.Field>
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
* @example With debounce control
|
|
130
|
+
* ```tsx
|
|
131
|
+
* <Form.Field name="email" label="Email">
|
|
115
132
|
* <Form.Autosearch
|
|
116
|
-
* options={
|
|
117
|
-
*
|
|
133
|
+
* options={searchResults}
|
|
134
|
+
* onSearch={debouncedSearch}
|
|
135
|
+
* searchDebounceMs={500}
|
|
136
|
+
* placeholder="Type email to search..."
|
|
118
137
|
* />
|
|
119
138
|
* </Form.Field>
|
|
120
139
|
* ```
|
|
121
140
|
*/
|
|
122
|
-
function FormAutosearch(props) {
|
|
123
|
-
|
|
141
|
+
function FormAutosearch({ disabled, className, inputClassName, ...props }) {
|
|
142
|
+
const { id, errors, disabled: fieldDisabled, fieldState } = useFieldContext$1();
|
|
143
|
+
const isDisabled = disabled ?? fieldDisabled;
|
|
144
|
+
const hasErrors = errors && errors.length > 0;
|
|
145
|
+
const value = fieldState?.value != null ? String(fieldState.value) : "";
|
|
146
|
+
return /* @__PURE__ */ jsx(Autosearch, {
|
|
147
|
+
...props,
|
|
148
|
+
name: fieldState?.name,
|
|
149
|
+
id,
|
|
150
|
+
value,
|
|
151
|
+
onValueChange: (val) => {
|
|
152
|
+
fieldState?.change(val);
|
|
153
|
+
fieldState?.blur();
|
|
154
|
+
},
|
|
155
|
+
disabled: isDisabled,
|
|
156
|
+
inputClassName: cn(hasErrors && "border-destructive", inputClassName),
|
|
157
|
+
className
|
|
158
|
+
});
|
|
124
159
|
}
|
|
125
160
|
FormAutosearch.displayName = "Form.Autosearch";
|
|
126
161
|
//#endregion
|
|
@@ -180,7 +215,10 @@ function FormCheckbox({ label, disabled, className }) {
|
|
|
180
215
|
children: [/* @__PURE__ */ jsx(Checkbox, {
|
|
181
216
|
id,
|
|
182
217
|
checked,
|
|
183
|
-
onCheckedChange: (value) =>
|
|
218
|
+
onCheckedChange: (value) => {
|
|
219
|
+
fieldState?.change(Boolean(value));
|
|
220
|
+
fieldState?.blur();
|
|
221
|
+
},
|
|
184
222
|
disabled: isDisabled,
|
|
185
223
|
"aria-invalid": hasErrors || void 0,
|
|
186
224
|
"aria-describedby": hasErrors ? `${id}-error` : void 0
|
|
@@ -194,12 +232,13 @@ function FormCheckbox({ label, disabled, className }) {
|
|
|
194
232
|
FormCheckbox.displayName = "Form.Checkbox";
|
|
195
233
|
//#endregion
|
|
196
234
|
//#region src/components/features/form/components/form-combobox.tsx
|
|
197
|
-
function FormCombobox({ options, placeholder, searchPlaceholder, emptyMessage, disabled, className, triggerClassName, contentClassName, searchable = true, showDropdownArrow = true, clearable = false, "data-testid": testId }) {
|
|
235
|
+
function FormCombobox({ options, placeholder, searchPlaceholder, emptyMessage, disabled, className, triggerClassName, contentClassName, searchable = true, showDropdownArrow = true, clearable = false, "data-testid": testId, modal }) {
|
|
198
236
|
const { id, errors, disabled: fieldDisabled, fieldState } = useFieldContext$1();
|
|
199
237
|
const isDisabled = disabled ?? fieldDisabled;
|
|
200
238
|
const hasErrors = errors && errors.length > 0;
|
|
201
239
|
const handleChange = React$1.useCallback((value) => {
|
|
202
240
|
fieldState?.change(value ?? "");
|
|
241
|
+
fieldState?.blur();
|
|
203
242
|
}, [fieldState]);
|
|
204
243
|
return /* @__PURE__ */ jsx(Combobox, {
|
|
205
244
|
id,
|
|
@@ -213,6 +252,7 @@ function FormCombobox({ options, placeholder, searchPlaceholder, emptyMessage, d
|
|
|
213
252
|
searchable,
|
|
214
253
|
showDropdownArrow,
|
|
215
254
|
clearable,
|
|
255
|
+
modal,
|
|
216
256
|
className,
|
|
217
257
|
triggerClassName: cn(hasErrors && "border-destructive", triggerClassName),
|
|
218
258
|
contentClassName,
|
|
@@ -329,7 +369,7 @@ function FormCustom({ children }) {
|
|
|
329
369
|
FormCustom.displayName = "Form.Custom";
|
|
330
370
|
//#endregion
|
|
331
371
|
//#region src/components/features/form/components/form-date-picker.tsx
|
|
332
|
-
function FormDatePicker({ placeholder, disabled, className, triggerClassName, numberOfMonths = 1, minDate: minDateProp, maxDate: maxDateProp, disableFuture, disablePast }) {
|
|
372
|
+
function FormDatePicker({ placeholder, disabled, className, triggerClassName, numberOfMonths = 1, minDate: minDateProp, maxDate: maxDateProp, disableFuture, disablePast, modal }) {
|
|
333
373
|
const { id, errors, disabled: fieldDisabled, fieldState } = useFieldContext$1();
|
|
334
374
|
const isDisabled = disabled ?? fieldDisabled;
|
|
335
375
|
const hasErrors = errors && errors.length > 0;
|
|
@@ -364,6 +404,7 @@ function FormDatePicker({ placeholder, disabled, className, triggerClassName, nu
|
|
|
364
404
|
onDateSelect: React$1.useCallback((range) => {
|
|
365
405
|
if (!range) {
|
|
366
406
|
fieldState?.change(void 0);
|
|
407
|
+
fieldState?.blur();
|
|
367
408
|
return;
|
|
368
409
|
}
|
|
369
410
|
if (numberOfMonths === 1) fieldState?.change(range.from.toISOString());
|
|
@@ -371,6 +412,7 @@ function FormDatePicker({ placeholder, disabled, className, triggerClassName, nu
|
|
|
371
412
|
from: range.from.toISOString(),
|
|
372
413
|
to: range.to?.toISOString()
|
|
373
414
|
});
|
|
415
|
+
fieldState?.blur();
|
|
374
416
|
}, [fieldState, numberOfMonths]),
|
|
375
417
|
numberOfMonths,
|
|
376
418
|
placeholder,
|
|
@@ -380,6 +422,7 @@ function FormDatePicker({ placeholder, disabled, className, triggerClassName, nu
|
|
|
380
422
|
disableFuture,
|
|
381
423
|
disablePast,
|
|
382
424
|
variant: "outline",
|
|
425
|
+
modal,
|
|
383
426
|
className: cn(className),
|
|
384
427
|
triggerClassName: cn(triggerClassName),
|
|
385
428
|
"aria-invalid": hasErrors || void 0,
|
|
@@ -389,7 +432,7 @@ function FormDatePicker({ placeholder, disabled, className, triggerClassName, nu
|
|
|
389
432
|
FormDatePicker.displayName = "Form.DatePicker";
|
|
390
433
|
//#endregion
|
|
391
434
|
//#region src/components/features/form/components/form-date-time-picker.tsx
|
|
392
|
-
function FormDateTimePicker({ minDate: minDateProp, maxDate: maxDateProp, disabledDates, timezone, showTimezoneIndicator, placeholder, disabled, className }) {
|
|
435
|
+
function FormDateTimePicker({ minDate: minDateProp, maxDate: maxDateProp, disabledDates, timezone, showTimezoneIndicator, placeholder, disabled, className, modal }) {
|
|
393
436
|
const { id, errors, disabled: fieldDisabled, fieldState } = useFieldContext$1();
|
|
394
437
|
const isDisabled = disabled ?? fieldDisabled;
|
|
395
438
|
const hasErrors = errors && errors.length > 0;
|
|
@@ -404,6 +447,7 @@ function FormDateTimePicker({ minDate: minDateProp, maxDate: maxDateProp, disabl
|
|
|
404
447
|
value: currentValue,
|
|
405
448
|
onChange: React$1.useCallback((value) => {
|
|
406
449
|
fieldState?.change(value);
|
|
450
|
+
fieldState?.blur();
|
|
407
451
|
}, [fieldState]),
|
|
408
452
|
minDate,
|
|
409
453
|
maxDate,
|
|
@@ -412,6 +456,7 @@ function FormDateTimePicker({ minDate: minDateProp, maxDate: maxDateProp, disabl
|
|
|
412
456
|
showTimezoneIndicator,
|
|
413
457
|
placeholder,
|
|
414
458
|
disabled: isDisabled,
|
|
459
|
+
modal,
|
|
415
460
|
className: cn(className),
|
|
416
461
|
"aria-invalid": hasErrors || void 0,
|
|
417
462
|
"aria-describedby": hasErrors ? `${id}-error` : void 0
|
|
@@ -661,10 +706,33 @@ function FieldLabel({ htmlFor, label, hasErrors, required, tooltip, className })
|
|
|
661
706
|
*/
|
|
662
707
|
function FormField({ name, children, label, description, tooltip, required = false, disabled = false, className, labelClassName }) {
|
|
663
708
|
const adapter = useAdapter();
|
|
664
|
-
const { fields, isSubmitting, form } = useFormContext$1();
|
|
709
|
+
const { fields, isSubmitting, form, mode, displayTouchedFields, markFieldTouched } = useFormContext$1();
|
|
665
710
|
const fieldState = adapter.useField(name);
|
|
666
|
-
const
|
|
711
|
+
const isDisplayTouched = displayTouchedFields.includes(name);
|
|
712
|
+
const rawErrors = fieldState.errors;
|
|
713
|
+
const errors = isDisplayTouched ? rawErrors : [];
|
|
667
714
|
const hasErrors = errors.length > 0;
|
|
715
|
+
const hasFocusedRef = React$1.useRef(false);
|
|
716
|
+
React$1.useEffect(() => {
|
|
717
|
+
hasFocusedRef.current = false;
|
|
718
|
+
}, [name]);
|
|
719
|
+
const handleFocus = React$1.useCallback((e) => {
|
|
720
|
+
if (e.target.type !== "hidden") hasFocusedRef.current = true;
|
|
721
|
+
}, []);
|
|
722
|
+
const handleChange = React$1.useCallback(() => {
|
|
723
|
+
if (mode === "onChange" && hasFocusedRef.current) markFieldTouched(name);
|
|
724
|
+
}, [
|
|
725
|
+
mode,
|
|
726
|
+
name,
|
|
727
|
+
markFieldTouched
|
|
728
|
+
]);
|
|
729
|
+
const handleBlur = React$1.useCallback(() => {
|
|
730
|
+
if ((mode === "onChange" || mode === "onBlur") && hasFocusedRef.current) markFieldTouched(name);
|
|
731
|
+
}, [
|
|
732
|
+
mode,
|
|
733
|
+
name,
|
|
734
|
+
markFieldTouched
|
|
735
|
+
]);
|
|
668
736
|
const fieldId = fieldState.id;
|
|
669
737
|
const descriptionId = description ? `${fieldId}-description` : void 0;
|
|
670
738
|
const errorId = hasErrors ? `${fieldId}-error` : void 0;
|
|
@@ -711,6 +779,9 @@ function FormField({ name, children, label, description, tooltip, required = fal
|
|
|
711
779
|
value: contextValue,
|
|
712
780
|
children: /* @__PURE__ */ jsxs("div", {
|
|
713
781
|
className: cn("flex flex-col space-y-2", className),
|
|
782
|
+
onFocusCapture: handleFocus,
|
|
783
|
+
onChange: handleChange,
|
|
784
|
+
onBlur: handleBlur,
|
|
714
785
|
children: [
|
|
715
786
|
label && /* @__PURE__ */ jsx(FieldLabel, {
|
|
716
787
|
htmlFor: fieldId,
|
|
@@ -866,7 +937,10 @@ function FormRadioGroup({ orientation = "vertical", disabled, className, childre
|
|
|
866
937
|
const hasErrors = errors && errors.length > 0;
|
|
867
938
|
return /* @__PURE__ */ jsx(RadioGroup, {
|
|
868
939
|
value: fieldState?.value != null ? String(fieldState.value) : void 0,
|
|
869
|
-
onValueChange: (val) =>
|
|
940
|
+
onValueChange: (val) => {
|
|
941
|
+
fieldState?.change(val);
|
|
942
|
+
fieldState?.blur();
|
|
943
|
+
},
|
|
870
944
|
disabled: isDisabled,
|
|
871
945
|
"aria-invalid": hasErrors || void 0,
|
|
872
946
|
"aria-describedby": hasErrors ? `${id}-error` : void 0,
|
|
@@ -931,7 +1005,7 @@ FormRadioItem.displayName = "Form.RadioItem";
|
|
|
931
1005
|
* </Form.Root>
|
|
932
1006
|
* ```
|
|
933
1007
|
*/
|
|
934
|
-
function FormRoot({ schema, children, onSubmit, action, method = "POST", formComponent: FormComp = "form", id, name, defaultValues, mode = "
|
|
1008
|
+
function FormRoot({ schema, children, onSubmit, action, method = "POST", formComponent: FormComp = "form", id, name, defaultValues, mode = "onChange", isSubmitting: externalIsSubmitting, onError, onSuccess, telemetry, className }) {
|
|
935
1009
|
const adapter = useAdapter();
|
|
936
1010
|
const [internalIsSubmitting, setInternalIsSubmitting] = React$1.useState(false);
|
|
937
1011
|
const isSubmitting = externalIsSubmitting ?? internalIsSubmitting;
|
|
@@ -991,6 +1065,10 @@ function FormRoot({ schema, children, onSubmit, action, method = "POST", formCom
|
|
|
991
1065
|
submitCount,
|
|
992
1066
|
dirtyFields: formState.dirtyFields,
|
|
993
1067
|
touchedFields: formState.touchedFields,
|
|
1068
|
+
mode,
|
|
1069
|
+
displayTouchedFields: instance.touchedFields,
|
|
1070
|
+
markFieldTouched: instance.markFieldTouched,
|
|
1071
|
+
markAllFieldsTouched: instance.markAllFieldsTouched,
|
|
994
1072
|
submit: () => formRef.current?.requestSubmit(),
|
|
995
1073
|
reset: () => instance.reset(),
|
|
996
1074
|
formId: instance.id
|
|
@@ -999,31 +1077,26 @@ function FormRoot({ schema, children, onSubmit, action, method = "POST", formCom
|
|
|
999
1077
|
isSubmitting,
|
|
1000
1078
|
formState,
|
|
1001
1079
|
isSubmitted,
|
|
1002
|
-
submitCount
|
|
1003
|
-
]);
|
|
1004
|
-
const isRenderFunction = typeof children === "function";
|
|
1005
|
-
const renderProps = React$1.useMemo(() => ({
|
|
1006
|
-
form: instance,
|
|
1007
|
-
fields: instance.fields,
|
|
1008
|
-
isSubmitting,
|
|
1009
|
-
isDirty: formState.isDirty,
|
|
1010
|
-
isValid: formState.isValid,
|
|
1011
|
-
isSubmitted,
|
|
1012
1080
|
submitCount,
|
|
1013
|
-
|
|
1014
|
-
touchedFields: formState.touchedFields,
|
|
1015
|
-
submit: () => formRef.current?.requestSubmit(),
|
|
1016
|
-
reset: () => instance.reset()
|
|
1017
|
-
}), [
|
|
1018
|
-
instance,
|
|
1019
|
-
isSubmitting,
|
|
1020
|
-
formState,
|
|
1021
|
-
isSubmitted,
|
|
1022
|
-
submitCount
|
|
1081
|
+
mode
|
|
1023
1082
|
]);
|
|
1083
|
+
const isRenderFunction = typeof children === "function";
|
|
1024
1084
|
const renderChildren = () => {
|
|
1025
|
-
if (isRenderFunction) return children
|
|
1026
|
-
return children
|
|
1085
|
+
if (!isRenderFunction) return children;
|
|
1086
|
+
return children({
|
|
1087
|
+
form: instance,
|
|
1088
|
+
fields: instance.fields,
|
|
1089
|
+
isSubmitting,
|
|
1090
|
+
isDirty: formState.isDirty,
|
|
1091
|
+
isValid: formState.isValid,
|
|
1092
|
+
isSubmitted,
|
|
1093
|
+
submitCount,
|
|
1094
|
+
dirtyFields: formState.dirtyFields,
|
|
1095
|
+
touchedFields: formState.touchedFields,
|
|
1096
|
+
mode,
|
|
1097
|
+
submit: () => formRef.current?.requestSubmit(),
|
|
1098
|
+
reset: () => instance.reset()
|
|
1099
|
+
});
|
|
1027
1100
|
};
|
|
1028
1101
|
return /* @__PURE__ */ jsx(FormProvider, {
|
|
1029
1102
|
value: contextValue,
|
|
@@ -1038,7 +1111,9 @@ function FormRoot({ schema, children, onSubmit, action, method = "POST", formCom
|
|
|
1038
1111
|
autoComplete: "off",
|
|
1039
1112
|
noValidate: true,
|
|
1040
1113
|
onSubmit: (e) => {
|
|
1114
|
+
const submitter = e.nativeEvent.submitter;
|
|
1041
1115
|
e.stopPropagation();
|
|
1116
|
+
if (submitter && !submitter.hidden) instance.markAllFieldsTouched();
|
|
1042
1117
|
telemetry?.onSubmit?.({
|
|
1043
1118
|
formName: name ?? "",
|
|
1044
1119
|
formId: id
|
|
@@ -1153,7 +1228,10 @@ function FormSwitch({ label, disabled, className }) {
|
|
|
1153
1228
|
children: [/* @__PURE__ */ jsx(Switch, {
|
|
1154
1229
|
id,
|
|
1155
1230
|
checked,
|
|
1156
|
-
onCheckedChange: (value) =>
|
|
1231
|
+
onCheckedChange: (value) => {
|
|
1232
|
+
fieldState?.change(Boolean(value));
|
|
1233
|
+
fieldState?.blur();
|
|
1234
|
+
},
|
|
1157
1235
|
disabled: isDisabled,
|
|
1158
1236
|
"aria-invalid": hasErrors || void 0,
|
|
1159
1237
|
"aria-describedby": hasErrors ? `${id}-error` : void 0
|
|
@@ -1210,6 +1288,7 @@ function FormTimePicker({ min, max, step, placeholder, disabled, className }) {
|
|
|
1210
1288
|
value: fieldState?.value ?? "",
|
|
1211
1289
|
onChange: React$1.useCallback((value) => {
|
|
1212
1290
|
fieldState?.change(value || void 0);
|
|
1291
|
+
fieldState?.blur();
|
|
1213
1292
|
}, [fieldState]),
|
|
1214
1293
|
min,
|
|
1215
1294
|
max,
|
|
@@ -1250,6 +1329,7 @@ function FormTransfer({ disabled, minItems, maxItems, ...props }) {
|
|
|
1250
1329
|
const value = Array.isArray(fieldState?.value) ? fieldState.value : [];
|
|
1251
1330
|
const handleChange = React$1.useCallback((newValue) => {
|
|
1252
1331
|
fieldState?.change(newValue);
|
|
1332
|
+
fieldState?.blur();
|
|
1253
1333
|
}, [fieldState]);
|
|
1254
1334
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
1255
1335
|
"aria-invalid": hasErrors || void 0,
|
|
@@ -1261,7 +1341,7 @@ function FormTransfer({ disabled, minItems, maxItems, ...props }) {
|
|
|
1261
1341
|
disabled: isDisabled
|
|
1262
1342
|
})
|
|
1263
1343
|
}), (minItems != null || maxItems != null) && /* @__PURE__ */ jsx("p", {
|
|
1264
|
-
className: "text-
|
|
1344
|
+
className: "text-ring text-xs text-wrap mt-2",
|
|
1265
1345
|
children: minItems != null && maxItems != null ? `Select between ${minItems} and ${maxItems} items` : minItems != null ? `Select at least ${minItems} items` : `Select up to ${maxItems} items`
|
|
1266
1346
|
})] });
|
|
1267
1347
|
}
|
|
@@ -1348,6 +1428,10 @@ FormWhen.displayName = "Form.When";
|
|
|
1348
1428
|
* Hook to access and control a specific field.
|
|
1349
1429
|
* Delegates to the active adapter's useField implementation.
|
|
1350
1430
|
*
|
|
1431
|
+
* Note: `meta.disabled` is always `false` because this hook operates
|
|
1432
|
+
* independently of Form.Field. If you need disabled state, read it
|
|
1433
|
+
* from your component props or from the Form.Field context via `useFieldContext()`.
|
|
1434
|
+
*
|
|
1351
1435
|
* @example
|
|
1352
1436
|
* ```tsx
|
|
1353
1437
|
* function MyCustomInput({ name }: { name: string }) {
|
package/dist/index.mjs
CHANGED
|
@@ -39,9 +39,9 @@ import { a as ListItem, c as Title, d as titleVariants, i as List, l as paragrap
|
|
|
39
39
|
import { t as VisuallyHidden } from "./visuallyhidden-BLUsJpYH.mjs";
|
|
40
40
|
import { n as NavMenu, t as AppNavigation } from "./app-navigation-84ro28PU.mjs";
|
|
41
41
|
import { t as LoaderOverlay } from "./loader-overlay-BTFdkp7W.mjs";
|
|
42
|
-
import { t as Autocomplete } from "./autocomplete-
|
|
42
|
+
import { t as Autocomplete } from "./autocomplete-CkYJueBL.mjs";
|
|
43
43
|
import { n as avatarStackVariants, t as AvatarStack } from "./avatar-stack-oVr8tsU7.mjs";
|
|
44
|
-
import { t as CalendarDatePicker } from "./calendar-date-picker-
|
|
44
|
+
import { t as CalendarDatePicker } from "./calendar-date-picker-CDT-8Ha8.mjs";
|
|
45
45
|
import { i as ClientOnly, n as useTheme, r as ThemeScript, t as ThemeProvider } from "./themes-DG1md8FI.mjs";
|
|
46
46
|
import { a as formatJson, c as isValidYaml, d as CodeEditor, i as CodeEditorTabs, l as jsonToYaml, n as jsonSchema, o as formatYaml, r as yamlSchema, s as isValidJson, t as createCodeEditorSchema, u as yamlToJson } from "./types-BZNk3q65.mjs";
|
|
47
47
|
import { t as toast } from "./toast-BWnN5fax.mjs";
|
|
@@ -49,7 +49,7 @@ import { n as Toaster, t as useToast } from "./toast-DpxlFNNx.mjs";
|
|
|
49
49
|
import { a as DropdownMenuItem, c as DropdownMenuRadioGroup, d as DropdownMenuShortcut, f as DropdownMenuSub, h as DropdownMenuTrigger, i as DropdownMenuGroup, l as DropdownMenuRadioItem, m as DropdownMenuSubTrigger, n as DropdownMenuCheckboxItem, o as DropdownMenuLabel, p as DropdownMenuSubContent, r as DropdownMenuContent, s as DropdownMenuPortal, t as DropdownMenu, u as DropdownMenuSeparator } from "./dropdown-DZiAt-jS.mjs";
|
|
50
50
|
import { i as FileInputButton, n as DropzoneContent, r as DropzoneEmptyState, t as Dropzone } from "./dropzone-ogtpQ4fy.mjs";
|
|
51
51
|
import { t as EmptyContent } from "./empty-content-C63GPJ5d.mjs";
|
|
52
|
-
import { A as FormCheckbox, C as FormDialog, D as FormCustom, E as FormDatePicker, M as FormAutosearch, N as FormAutocomplete, O as FormCopyBox, S as FormError, T as FormDateTimePicker, _ as FormRadioGroup, a as useField, b as FormFieldArray, c as useWatchAll, d as FormTextarea, f as FormSwitch, g as FormRoot, h as FormSelectItem, i as useFieldContext, j as FormButton, k as FormCombobox, l as FormTransfer, m as FormSelect, n as useFormState, o as FormWhen, p as FormSubmit, r as useFormContext, s as useWatch, t as Form, u as FormTimePicker, v as FormRadioItem, w as FormDescription, x as FormField, y as FormInput } from "./form-
|
|
52
|
+
import { A as FormCheckbox, C as FormDialog, D as FormCustom, E as FormDatePicker, M as FormAutosearch, N as FormAutocomplete, O as FormCopyBox, S as FormError, T as FormDateTimePicker, _ as FormRadioGroup, a as useField, b as FormFieldArray, c as useWatchAll, d as FormTextarea, f as FormSwitch, g as FormRoot, h as FormSelectItem, i as useFieldContext, j as FormButton, k as FormCombobox, l as FormTransfer, m as FormSelect, n as useFormState, o as FormWhen, p as FormSubmit, r as useFormContext, s as useWatch, t as Form, u as FormTimePicker, v as FormRadioItem, w as FormDescription, x as FormField, y as FormInput } from "./form-B3rQ4CH9.mjs";
|
|
53
53
|
import { t as useCopyToClipboard } from "./use-copy-to-clipboard-uNeeVHC4.mjs";
|
|
54
54
|
import { n as useAdapter, t as FormAdapterProvider } from "./adapter-context-rWveHhDd.mjs";
|
|
55
55
|
import { InputWithAddons } from "./input-with-addons/index.mjs";
|
package/dist/transfer/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as Transfer } from "../transfer-
|
|
1
|
+
import { t as Transfer } from "../transfer-46C-rFFW.mjs";
|
|
2
2
|
export { Transfer };
|
|
@@ -203,22 +203,26 @@ function Transfer({ items, value, onChange, itemKey, itemLabel, itemGroup, searc
|
|
|
203
203
|
itemLabel,
|
|
204
204
|
itemGroup
|
|
205
205
|
});
|
|
206
|
-
const handleSelect = (key) => {
|
|
206
|
+
const handleSelect = React$1.useCallback((key) => {
|
|
207
207
|
if (value.includes(key)) return;
|
|
208
208
|
onChange([...value, key]);
|
|
209
|
-
};
|
|
210
|
-
const handleDeselect = (key) => {
|
|
209
|
+
}, [value, onChange]);
|
|
210
|
+
const handleDeselect = React$1.useCallback((key) => {
|
|
211
211
|
onChange(value.filter((k) => k !== key));
|
|
212
|
-
};
|
|
213
|
-
const handleSelectAll = () => {
|
|
212
|
+
}, [value, onChange]);
|
|
213
|
+
const handleSelectAll = React$1.useCallback(() => {
|
|
214
214
|
const sourceKeys = state.filteredSourceItems.map((item) => item.key);
|
|
215
215
|
const existing = new Set(value);
|
|
216
216
|
const newKeys = sourceKeys.filter((k) => !existing.has(k));
|
|
217
217
|
onChange([...value, ...newKeys]);
|
|
218
|
-
}
|
|
219
|
-
|
|
218
|
+
}, [
|
|
219
|
+
state.filteredSourceItems,
|
|
220
|
+
value,
|
|
221
|
+
onChange
|
|
222
|
+
]);
|
|
223
|
+
const handleClearAll = React$1.useCallback(() => {
|
|
220
224
|
onChange([]);
|
|
221
|
-
};
|
|
225
|
+
}, [onChange]);
|
|
222
226
|
return /* @__PURE__ */ jsxs("div", {
|
|
223
227
|
className: cn("flex h-[400px]", className),
|
|
224
228
|
children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as React$1 from "react";
|
|
1
2
|
import "zod";
|
|
2
3
|
//#region src/components/features/form/utils/zod-helpers.ts
|
|
3
4
|
/**
|
|
@@ -48,4 +49,35 @@ function isRequired(schema) {
|
|
|
48
49
|
return true;
|
|
49
50
|
}
|
|
50
51
|
//#endregion
|
|
51
|
-
|
|
52
|
+
//#region src/components/features/form/hooks/use-display-touched.ts
|
|
53
|
+
/**
|
|
54
|
+
* Shared display-level touched tracking, independent of adapter-specific blur tracking.
|
|
55
|
+
*
|
|
56
|
+
* "Display-touched" controls whether a field's errors are shown in the UI.
|
|
57
|
+
* This is separate from the adapter's `isTouched` (which tracks focusout events).
|
|
58
|
+
*
|
|
59
|
+
* Used by both RHF and Conform adapters to provide consistent error display
|
|
60
|
+
* behaviour across validation modes (onChange, onBlur, onSubmit).
|
|
61
|
+
*/
|
|
62
|
+
function useDisplayTouched(schema) {
|
|
63
|
+
const [touchedSet, setTouchedSet] = React$1.useState(/* @__PURE__ */ new Set());
|
|
64
|
+
const markFieldTouched = React$1.useCallback((fieldName) => {
|
|
65
|
+
setTouchedSet((prev) => {
|
|
66
|
+
if (prev.has(fieldName)) return prev;
|
|
67
|
+
const next = new Set(prev);
|
|
68
|
+
next.add(fieldName);
|
|
69
|
+
return next;
|
|
70
|
+
});
|
|
71
|
+
}, []);
|
|
72
|
+
const markAllFieldsTouched = React$1.useCallback(() => {
|
|
73
|
+
const allFieldNames = Object.keys(getFieldConstraints(schema));
|
|
74
|
+
setTouchedSet(new Set(allFieldNames));
|
|
75
|
+
}, [schema]);
|
|
76
|
+
return {
|
|
77
|
+
displayTouchedFields: React$1.useMemo(() => Array.from(touchedSet), [touchedSet]),
|
|
78
|
+
markFieldTouched,
|
|
79
|
+
markAllFieldsTouched
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { getFieldConstraints as n, getObjectShape as r, useDisplayTouched as t };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datum-cloud/datum-ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.6.0
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "https://github.com/datum-cloud/datum-ui"
|
|
@@ -204,6 +204,11 @@
|
|
|
204
204
|
"types": "./dist/components/features/autocomplete/index.d.ts",
|
|
205
205
|
"default": "./dist/autocomplete/index.mjs"
|
|
206
206
|
},
|
|
207
|
+
"./autosearch": {
|
|
208
|
+
"source": "./src/components/features/autosearch/index.ts",
|
|
209
|
+
"types": "./dist/components/features/autosearch/index.d.ts",
|
|
210
|
+
"default": "./dist/autosearch/index.mjs"
|
|
211
|
+
},
|
|
207
212
|
"./combobox": {
|
|
208
213
|
"source": "./src/components/features/combobox/index.ts",
|
|
209
214
|
"types": "./dist/components/features/combobox/index.d.ts",
|