@dragonmastery/zinia-forms-core 0.3.12 → 0.3.13
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/dist/index.d.ts +195 -190
- package/dist/index.js +55 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -148,40 +148,6 @@ interface CheckboxFieldProps<FormType> {
|
|
|
148
148
|
variant?: string;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
interface DateFieldProps<FormType> {
|
|
152
|
-
name: FlexiblePath<FormType>;
|
|
153
|
-
label?: string;
|
|
154
|
-
hideLabel?: boolean;
|
|
155
|
-
description?: string;
|
|
156
|
-
required?: boolean;
|
|
157
|
-
placeholder?: string;
|
|
158
|
-
disabled?: boolean;
|
|
159
|
-
readonly?: boolean;
|
|
160
|
-
class?: string | string[];
|
|
161
|
-
size?: string;
|
|
162
|
-
variant?: string;
|
|
163
|
-
min?: string;
|
|
164
|
-
max?: string;
|
|
165
|
-
formatter?: (date: string) => unknown;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
interface NumberFieldProps<FormType> {
|
|
169
|
-
name: FlexiblePath<FormType>;
|
|
170
|
-
label?: string;
|
|
171
|
-
hideLabel?: boolean;
|
|
172
|
-
description?: string;
|
|
173
|
-
required?: boolean;
|
|
174
|
-
placeholder?: string;
|
|
175
|
-
disabled?: boolean;
|
|
176
|
-
readonly?: boolean;
|
|
177
|
-
class?: string | string[];
|
|
178
|
-
size?: string;
|
|
179
|
-
variant?: string;
|
|
180
|
-
min?: number;
|
|
181
|
-
max?: number;
|
|
182
|
-
step?: number;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
151
|
/**
|
|
186
152
|
* Option item for select fields
|
|
187
153
|
* @template TData - Type of the optional data object for storing additional metadata
|
|
@@ -368,6 +334,186 @@ interface SelectFieldProps<FormType, P extends Path<FormType> = Path<FormType>,
|
|
|
368
334
|
*/
|
|
369
335
|
declare const SELECT_FIELD_PROP_NAMES: readonly ["name", "selectOptions", "placeholder", "disabled", "readonly", "class", "label", "hideLabel", "description", "required", "size", "variant", "valueToLabel", "useSchemaOptions", "dependsOn", "optionFilterFn", "autoReset"];
|
|
370
336
|
|
|
337
|
+
/**
|
|
338
|
+
* Props for the ComboboxField component
|
|
339
|
+
* @template FormType - The form type
|
|
340
|
+
* @template P - The field path in the form
|
|
341
|
+
* @template TData - The type of the data property in SelectOption (for cascading dropdowns)
|
|
342
|
+
*/
|
|
343
|
+
interface ComboboxFieldProps<FormType, P extends Path<FormType> = Path<FormType>, TData = any> {
|
|
344
|
+
/**
|
|
345
|
+
* Field name (path in the form state)
|
|
346
|
+
* Accepts both static paths and dynamic paths for use in array fields
|
|
347
|
+
*/
|
|
348
|
+
name: FlexiblePath<FormType>;
|
|
349
|
+
/**
|
|
350
|
+
* Field label
|
|
351
|
+
*/
|
|
352
|
+
label?: string;
|
|
353
|
+
/**
|
|
354
|
+
* Whether to hide the label
|
|
355
|
+
*/
|
|
356
|
+
hideLabel?: boolean;
|
|
357
|
+
/**
|
|
358
|
+
* Field description
|
|
359
|
+
*/
|
|
360
|
+
description?: string;
|
|
361
|
+
/**
|
|
362
|
+
* Whether the field is required
|
|
363
|
+
*/
|
|
364
|
+
required?: boolean;
|
|
365
|
+
/**
|
|
366
|
+
* Placeholder text
|
|
367
|
+
*/
|
|
368
|
+
placeholder?: string;
|
|
369
|
+
/**
|
|
370
|
+
* Whether the field is disabled
|
|
371
|
+
*/
|
|
372
|
+
disabled?: boolean;
|
|
373
|
+
/**
|
|
374
|
+
* Whether the field is readonly
|
|
375
|
+
*/
|
|
376
|
+
readonly?: boolean;
|
|
377
|
+
/**
|
|
378
|
+
* CSS classes to apply to the field
|
|
379
|
+
*/
|
|
380
|
+
class?: string | string[];
|
|
381
|
+
/**
|
|
382
|
+
* Field size
|
|
383
|
+
*/
|
|
384
|
+
size?: string;
|
|
385
|
+
/**
|
|
386
|
+
* Field variant
|
|
387
|
+
*/
|
|
388
|
+
variant?: string;
|
|
389
|
+
/**
|
|
390
|
+
* Combobox options (overrides options from schema)
|
|
391
|
+
* Using selectOptions instead of options to avoid conflicts with HTML select element
|
|
392
|
+
*
|
|
393
|
+
* For async loading, use form-level dataLoaders and pass options via extraData:
|
|
394
|
+
* ```ts
|
|
395
|
+
* useForm(schema, {
|
|
396
|
+
* dataLoaders: { products: loadProducts },
|
|
397
|
+
* });
|
|
398
|
+
* // Then: :selectOptions="form.extraData.products || []"
|
|
399
|
+
* ```
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* // With typed data
|
|
403
|
+
* interface CityData { country: string; }
|
|
404
|
+
* const options: SelectOption<CityData>[] = [
|
|
405
|
+
* { value: 'nyc', label: 'New York', data: { country: 'usa' } }
|
|
406
|
+
* ];
|
|
407
|
+
*/
|
|
408
|
+
selectOptions?: SelectOption<TData>[];
|
|
409
|
+
/**
|
|
410
|
+
* Custom mapping function to convert values to labels
|
|
411
|
+
* This is useful when you want to customize how labels are displayed
|
|
412
|
+
* without providing a full options array
|
|
413
|
+
*
|
|
414
|
+
* Can be provided as either:
|
|
415
|
+
* 1. A function that takes a value and returns a label
|
|
416
|
+
* 2. An object map where keys are enum values and values are labels
|
|
417
|
+
*/
|
|
418
|
+
valueToLabel?: ValueToLabelMapping<FieldPathToEnum$1<FormType, P>>;
|
|
419
|
+
/**
|
|
420
|
+
* Whether to use options from the schema (default: true)
|
|
421
|
+
* Set to false to ignore schema options even when no options prop is provided
|
|
422
|
+
*/
|
|
423
|
+
useSchemaOptions?: boolean;
|
|
424
|
+
/**
|
|
425
|
+
* Field path that this field depends on for cascading dropdowns
|
|
426
|
+
* When the parent field changes, this field's options will be filtered
|
|
427
|
+
* and the field will be reset (unless autoReset is false)
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* // City field depends on country field
|
|
431
|
+
* <ComboboxField name="city" dependsOn="country" :optionFilterFn="filterCitiesByCountry" />
|
|
432
|
+
*/
|
|
433
|
+
dependsOn?: FlexiblePath<FormType>;
|
|
434
|
+
/**
|
|
435
|
+
* Function to filter options based on the parent field's value
|
|
436
|
+
* Receives the parent field value and all available options
|
|
437
|
+
* Should return the filtered options array
|
|
438
|
+
*
|
|
439
|
+
* The function signature is tied to the TData type parameter, ensuring type safety
|
|
440
|
+
* between selectOptions and optionFilterFn
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* // With typed data - both props must use the same data type
|
|
444
|
+
* interface CityData { country: string; }
|
|
445
|
+
* const filterCitiesByCountry = (
|
|
446
|
+
* countryValue: string,
|
|
447
|
+
* allOptions: SelectOption<CityData>[]
|
|
448
|
+
* ): SelectOption<CityData>[] => {
|
|
449
|
+
* return allOptions.filter(opt => opt.data?.country === countryValue);
|
|
450
|
+
* };
|
|
451
|
+
*/
|
|
452
|
+
optionFilterFn?: (parentValue: any, allOptions: SelectOption<TData>[]) => SelectOption<TData>[];
|
|
453
|
+
/**
|
|
454
|
+
* Whether to automatically reset this field when the parent field changes (default: true)
|
|
455
|
+
* Set to false if you want to preserve the value when parent changes
|
|
456
|
+
*/
|
|
457
|
+
autoReset?: boolean;
|
|
458
|
+
/**
|
|
459
|
+
* Whether to allow creating new values that don't exist in the options
|
|
460
|
+
* Default: false (must be explicitly set to true to allow creation)
|
|
461
|
+
*
|
|
462
|
+
* Note: This is specific to ComboboxField and not available in SelectField
|
|
463
|
+
*/
|
|
464
|
+
allowCreate?: boolean;
|
|
465
|
+
/**
|
|
466
|
+
* Custom filter function for filtering options as user types
|
|
467
|
+
* Default: filters by case-insensitive substring match
|
|
468
|
+
*
|
|
469
|
+
* Note: This is specific to ComboboxField and not available in SelectField
|
|
470
|
+
* This is different from optionFilterFn which filters based on parent field values
|
|
471
|
+
*/
|
|
472
|
+
filterFn?: (query: string, option: SelectOption<TData>) => boolean;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Array of prop names for ComboboxField component.
|
|
476
|
+
* This is derived from ComboboxFieldProps interface and ensures type safety.
|
|
477
|
+
* Used for prop normalization and filtering in component implementations.
|
|
478
|
+
*
|
|
479
|
+
* TypeScript ensures all entries are valid keys of ComboboxFieldProps.
|
|
480
|
+
*/
|
|
481
|
+
declare const COMBOBOX_FIELD_PROP_NAMES: readonly ["name", "selectOptions", "placeholder", "disabled", "readonly", "class", "label", "hideLabel", "description", "required", "size", "variant", "valueToLabel", "useSchemaOptions", "dependsOn", "optionFilterFn", "autoReset", "allowCreate", "filterFn"];
|
|
482
|
+
|
|
483
|
+
interface DateFieldProps<FormType> {
|
|
484
|
+
name: FlexiblePath<FormType>;
|
|
485
|
+
label?: string;
|
|
486
|
+
hideLabel?: boolean;
|
|
487
|
+
description?: string;
|
|
488
|
+
required?: boolean;
|
|
489
|
+
placeholder?: string;
|
|
490
|
+
disabled?: boolean;
|
|
491
|
+
readonly?: boolean;
|
|
492
|
+
class?: string | string[];
|
|
493
|
+
size?: string;
|
|
494
|
+
variant?: string;
|
|
495
|
+
min?: string;
|
|
496
|
+
max?: string;
|
|
497
|
+
formatter?: (date: string) => unknown;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
interface NumberFieldProps<FormType> {
|
|
501
|
+
name: FlexiblePath<FormType>;
|
|
502
|
+
label?: string;
|
|
503
|
+
hideLabel?: boolean;
|
|
504
|
+
description?: string;
|
|
505
|
+
required?: boolean;
|
|
506
|
+
placeholder?: string;
|
|
507
|
+
disabled?: boolean;
|
|
508
|
+
readonly?: boolean;
|
|
509
|
+
class?: string | string[];
|
|
510
|
+
size?: string;
|
|
511
|
+
variant?: string;
|
|
512
|
+
min?: number;
|
|
513
|
+
max?: number;
|
|
514
|
+
step?: number;
|
|
515
|
+
}
|
|
516
|
+
|
|
371
517
|
/**
|
|
372
518
|
* Type to convert underscores to PascalCase
|
|
373
519
|
* This helper type processes a single segment by capitalizing after underscores
|
|
@@ -429,11 +575,11 @@ type EnumFieldComponent<T, P extends Path<T>> = (props: Omit<SelectFieldProps<T>
|
|
|
429
575
|
valueToLabel: Record<FieldPathToEnum<T, P>, string>;
|
|
430
576
|
}, context?: any) => any;
|
|
431
577
|
/**
|
|
432
|
-
* Type for
|
|
433
|
-
* Uses
|
|
434
|
-
*
|
|
578
|
+
* Type for combobox field components (searchable select with optional creation)
|
|
579
|
+
* Uses ComboboxFieldProps<T, P, TData> which extends SelectFieldProps with allowCreate and filterFn
|
|
580
|
+
* Preserves path-specific typing for props like dependsOn and ensures type safety
|
|
435
581
|
*/
|
|
436
|
-
type
|
|
582
|
+
type ComboboxFieldComponent<T, P extends Path<T>> = <TData = any>(props: Omit<ComboboxFieldProps<T, P, TData>, 'name'>, context?: any) => any;
|
|
437
583
|
/**
|
|
438
584
|
* Type for number field components
|
|
439
585
|
*/
|
|
@@ -461,14 +607,19 @@ type GenericFieldComponent = (props: any, context?: any) => any;
|
|
|
461
607
|
type UnwrapOptional<T> = Exclude<T, undefined | null>;
|
|
462
608
|
/**
|
|
463
609
|
* Maps a field path to its component type based on the field's actual type
|
|
464
|
-
*
|
|
465
|
-
*
|
|
610
|
+
* FieldType can be 'enum', 'combobox', or 'string' (default)
|
|
611
|
+
* - 'enum': Uses EnumFieldComponent (requires valueToLabel)
|
|
612
|
+
* - 'combobox': Uses ComboboxFieldComponent (includes allowCreate and filterFn)
|
|
613
|
+
* - 'string': Uses ComboboxFieldComponent (superset of SelectField with allowCreate and filterFn)
|
|
614
|
+
*
|
|
615
|
+
* We use ComboboxFieldComponent for all string fields because:
|
|
616
|
+
* 1. ComboboxFieldProps includes all SelectFieldProps (it's a superset)
|
|
617
|
+
* 2. This allows allowCreate to be available in types even if the field uses SelectField at runtime
|
|
618
|
+
* 3. ComboboxField can handle all SelectField use cases, so it's safe to use as the default
|
|
466
619
|
*
|
|
467
|
-
*
|
|
468
|
-
* all TextField functionality plus additional props like dependsOn for cascading dropdowns.
|
|
469
|
-
* This provides better type safety and autocomplete.
|
|
620
|
+
* Everything else is inferred from the actual TypeScript type at the path
|
|
470
621
|
*/
|
|
471
|
-
type FieldComponentType<T, P extends Path<T>, FieldType extends string = 'string'> = FieldType extends 'enum' ? EnumFieldComponent<T, P> : P extends keyof T ? UnwrapOptional<T[P]> extends Array<any> | ReadonlyArray<any> ? ArrayFieldComponent<T, P> : UnwrapOptional<T[P]> extends number ? NumberFieldComponent<T> : UnwrapOptional<T[P]> extends boolean ? CheckboxFieldComponent<T> : UnwrapOptional<T[P]> extends Date ? DateFieldComponent<T> : UnwrapOptional<T[P]> extends string ?
|
|
622
|
+
type FieldComponentType<T, P extends Path<T>, FieldType extends string = 'string'> = FieldType extends 'enum' ? EnumFieldComponent<T, P> : FieldType extends 'combobox' ? ComboboxFieldComponent<T, P> : P extends keyof T ? UnwrapOptional<T[P]> extends Array<any> | ReadonlyArray<any> ? ArrayFieldComponent<T, P> : UnwrapOptional<T[P]> extends number ? NumberFieldComponent<T> : UnwrapOptional<T[P]> extends boolean ? CheckboxFieldComponent<T> : UnwrapOptional<T[P]> extends Date ? DateFieldComponent<T> : UnwrapOptional<T[P]> extends string ? ComboboxFieldComponent<T, P> : GenericFieldComponent : GenericFieldComponent;
|
|
472
623
|
/**
|
|
473
624
|
* Type for the components object with PascalCase keys derived from field paths
|
|
474
625
|
* Each component gets the right type based on what the field actually is
|
|
@@ -580,152 +731,6 @@ type MetadataRegistry = Record<string, SchemaFieldMetadata>;
|
|
|
580
731
|
*/
|
|
581
732
|
type PathsOf<T extends z.ZodTypeAny> = Path<z.infer<T>>;
|
|
582
733
|
|
|
583
|
-
/**
|
|
584
|
-
* Props for the ComboboxField component
|
|
585
|
-
* @template FormType - The form type
|
|
586
|
-
* @template P - The field path in the form
|
|
587
|
-
* @template TData - The type of the data property in SelectOption (for cascading dropdowns)
|
|
588
|
-
*/
|
|
589
|
-
interface ComboboxFieldProps<FormType, P extends Path<FormType> = Path<FormType>, TData = any> {
|
|
590
|
-
/**
|
|
591
|
-
* Field name (path in the form state)
|
|
592
|
-
* Accepts both static paths and dynamic paths for use in array fields
|
|
593
|
-
*/
|
|
594
|
-
name: FlexiblePath<FormType>;
|
|
595
|
-
/**
|
|
596
|
-
* Field label
|
|
597
|
-
*/
|
|
598
|
-
label?: string;
|
|
599
|
-
/**
|
|
600
|
-
* Whether to hide the label
|
|
601
|
-
*/
|
|
602
|
-
hideLabel?: boolean;
|
|
603
|
-
/**
|
|
604
|
-
* Field description
|
|
605
|
-
*/
|
|
606
|
-
description?: string;
|
|
607
|
-
/**
|
|
608
|
-
* Whether the field is required
|
|
609
|
-
*/
|
|
610
|
-
required?: boolean;
|
|
611
|
-
/**
|
|
612
|
-
* Placeholder text
|
|
613
|
-
*/
|
|
614
|
-
placeholder?: string;
|
|
615
|
-
/**
|
|
616
|
-
* Whether the field is disabled
|
|
617
|
-
*/
|
|
618
|
-
disabled?: boolean;
|
|
619
|
-
/**
|
|
620
|
-
* Whether the field is readonly
|
|
621
|
-
*/
|
|
622
|
-
readonly?: boolean;
|
|
623
|
-
/**
|
|
624
|
-
* CSS classes to apply to the field
|
|
625
|
-
*/
|
|
626
|
-
class?: string | string[];
|
|
627
|
-
/**
|
|
628
|
-
* Field size
|
|
629
|
-
*/
|
|
630
|
-
size?: string;
|
|
631
|
-
/**
|
|
632
|
-
* Field variant
|
|
633
|
-
*/
|
|
634
|
-
variant?: string;
|
|
635
|
-
/**
|
|
636
|
-
* Combobox options (overrides options from schema)
|
|
637
|
-
* Using selectOptions instead of options to avoid conflicts with HTML select element
|
|
638
|
-
*
|
|
639
|
-
* For async loading, use form-level dataLoaders and pass options via extraData:
|
|
640
|
-
* ```ts
|
|
641
|
-
* useForm(schema, {
|
|
642
|
-
* dataLoaders: { products: loadProducts },
|
|
643
|
-
* });
|
|
644
|
-
* // Then: :selectOptions="form.extraData.products || []"
|
|
645
|
-
* ```
|
|
646
|
-
*
|
|
647
|
-
* @example
|
|
648
|
-
* // With typed data
|
|
649
|
-
* interface CityData { country: string; }
|
|
650
|
-
* const options: SelectOption<CityData>[] = [
|
|
651
|
-
* { value: 'nyc', label: 'New York', data: { country: 'usa' } }
|
|
652
|
-
* ];
|
|
653
|
-
*/
|
|
654
|
-
selectOptions?: SelectOption<TData>[];
|
|
655
|
-
/**
|
|
656
|
-
* Custom mapping function to convert values to labels
|
|
657
|
-
* This is useful when you want to customize how labels are displayed
|
|
658
|
-
* without providing a full options array
|
|
659
|
-
*
|
|
660
|
-
* Can be provided as either:
|
|
661
|
-
* 1. A function that takes a value and returns a label
|
|
662
|
-
* 2. An object map where keys are enum values and values are labels
|
|
663
|
-
*/
|
|
664
|
-
valueToLabel?: ValueToLabelMapping<FieldPathToEnum$1<FormType, P>>;
|
|
665
|
-
/**
|
|
666
|
-
* Whether to use options from the schema (default: true)
|
|
667
|
-
* Set to false to ignore schema options even when no options prop is provided
|
|
668
|
-
*/
|
|
669
|
-
useSchemaOptions?: boolean;
|
|
670
|
-
/**
|
|
671
|
-
* Field path that this field depends on for cascading dropdowns
|
|
672
|
-
* When the parent field changes, this field's options will be filtered
|
|
673
|
-
* and the field will be reset (unless autoReset is false)
|
|
674
|
-
*
|
|
675
|
-
* @example
|
|
676
|
-
* // City field depends on country field
|
|
677
|
-
* <ComboboxField name="city" dependsOn="country" :optionFilterFn="filterCitiesByCountry" />
|
|
678
|
-
*/
|
|
679
|
-
dependsOn?: FlexiblePath<FormType>;
|
|
680
|
-
/**
|
|
681
|
-
* Function to filter options based on the parent field's value
|
|
682
|
-
* Receives the parent field value and all available options
|
|
683
|
-
* Should return the filtered options array
|
|
684
|
-
*
|
|
685
|
-
* The function signature is tied to the TData type parameter, ensuring type safety
|
|
686
|
-
* between selectOptions and optionFilterFn
|
|
687
|
-
*
|
|
688
|
-
* @example
|
|
689
|
-
* // With typed data - both props must use the same data type
|
|
690
|
-
* interface CityData { country: string; }
|
|
691
|
-
* const filterCitiesByCountry = (
|
|
692
|
-
* countryValue: string,
|
|
693
|
-
* allOptions: SelectOption<CityData>[]
|
|
694
|
-
* ): SelectOption<CityData>[] => {
|
|
695
|
-
* return allOptions.filter(opt => opt.data?.country === countryValue);
|
|
696
|
-
* };
|
|
697
|
-
*/
|
|
698
|
-
optionFilterFn?: (parentValue: any, allOptions: SelectOption<TData>[]) => SelectOption<TData>[];
|
|
699
|
-
/**
|
|
700
|
-
* Whether to automatically reset this field when the parent field changes (default: true)
|
|
701
|
-
* Set to false if you want to preserve the value when parent changes
|
|
702
|
-
*/
|
|
703
|
-
autoReset?: boolean;
|
|
704
|
-
/**
|
|
705
|
-
* Whether to allow creating new values that don't exist in the options
|
|
706
|
-
* Default: true
|
|
707
|
-
*
|
|
708
|
-
* Note: This is specific to ComboboxField and not available in SelectField
|
|
709
|
-
*/
|
|
710
|
-
allowCreate?: boolean;
|
|
711
|
-
/**
|
|
712
|
-
* Custom filter function for filtering options as user types
|
|
713
|
-
* Default: filters by case-insensitive substring match
|
|
714
|
-
*
|
|
715
|
-
* Note: This is specific to ComboboxField and not available in SelectField
|
|
716
|
-
* This is different from optionFilterFn which filters based on parent field values
|
|
717
|
-
*/
|
|
718
|
-
filterFn?: (query: string, option: SelectOption<TData>) => boolean;
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* Array of prop names for ComboboxField component.
|
|
722
|
-
* This is derived from ComboboxFieldProps interface and ensures type safety.
|
|
723
|
-
* Used for prop normalization and filtering in component implementations.
|
|
724
|
-
*
|
|
725
|
-
* TypeScript ensures all entries are valid keys of ComboboxFieldProps.
|
|
726
|
-
*/
|
|
727
|
-
declare const COMBOBOX_FIELD_PROP_NAMES: readonly ["name", "selectOptions", "placeholder", "disabled", "readonly", "class", "label", "hideLabel", "description", "required", "size", "variant", "valueToLabel", "useSchemaOptions", "dependsOn", "optionFilterFn", "autoReset", "allowCreate", "filterFn"];
|
|
728
|
-
|
|
729
734
|
interface CurrencyFieldProps<FormType> {
|
|
730
735
|
name: FlexiblePath<FormType>;
|
|
731
736
|
label?: string;
|
package/dist/index.js
CHANGED
|
@@ -4747,6 +4747,7 @@ function createDaisyUIComboboxField() {
|
|
|
4747
4747
|
}
|
|
4748
4748
|
const fieldMetadata = formState.fieldsMetadata[props.name] || {};
|
|
4749
4749
|
const normalizedProps = normalizePropsFromAttrs(props, propsDefinition, attrs);
|
|
4750
|
+
const allowCreate = computed(() => normalizedProps.allowCreate === true);
|
|
4750
4751
|
const getOptions = computed(() => {
|
|
4751
4752
|
if (normalizedProps.selectOptions) {
|
|
4752
4753
|
return normalizedProps.selectOptions;
|
|
@@ -4771,7 +4772,7 @@ function createDaisyUIComboboxField() {
|
|
|
4771
4772
|
return getOptions.value.filter((opt) => filterFn(query, opt));
|
|
4772
4773
|
});
|
|
4773
4774
|
const isNewValue = computed(() => {
|
|
4774
|
-
if (!
|
|
4775
|
+
if (!allowCreate.value) return false;
|
|
4775
4776
|
const currentText = String(displayText.value || "").trim().toLowerCase();
|
|
4776
4777
|
if (!currentText) return false;
|
|
4777
4778
|
return !getOptions.value.some(
|
|
@@ -4806,7 +4807,7 @@ function createDaisyUIComboboxField() {
|
|
|
4806
4807
|
const showDropdown = computed(() => {
|
|
4807
4808
|
if (!isFocused.value) return false;
|
|
4808
4809
|
if (getOptions.value.length > 0) return true;
|
|
4809
|
-
if (
|
|
4810
|
+
if (allowCreate.value) {
|
|
4810
4811
|
return String(formState.getValue(props.name) || "").trim().length > 0;
|
|
4811
4812
|
}
|
|
4812
4813
|
return false;
|
|
@@ -4847,7 +4848,7 @@ function createDaisyUIComboboxField() {
|
|
|
4847
4848
|
if (matchingOption) {
|
|
4848
4849
|
formState.setValue(props.name, matchingOption.value);
|
|
4849
4850
|
displayText.value = matchingOption.label;
|
|
4850
|
-
} else if (
|
|
4851
|
+
} else if (allowCreate.value && displayValue) {
|
|
4851
4852
|
formState.setValue(props.name, displayValue);
|
|
4852
4853
|
displayText.value = displayValue;
|
|
4853
4854
|
} else if (!displayValue) {
|
|
@@ -4858,6 +4859,23 @@ function createDaisyUIComboboxField() {
|
|
|
4858
4859
|
}
|
|
4859
4860
|
formState.touchField(props.name);
|
|
4860
4861
|
formState.validateField(props.name);
|
|
4862
|
+
if (!allowCreate.value && displayValue) {
|
|
4863
|
+
const currentValue = formState.getValue(props.name);
|
|
4864
|
+
const isValidOption = getOptions.value.some(
|
|
4865
|
+
(opt) => opt.value === currentValue || opt.label === currentValue || opt.value.toLowerCase() === String(currentValue).toLowerCase() || opt.label.toLowerCase() === String(currentValue).toLowerCase()
|
|
4866
|
+
);
|
|
4867
|
+
if (!isValidOption) {
|
|
4868
|
+
formState.errors[props.name] = `"${displayValue}" is not a valid option. Please select from the list.`;
|
|
4869
|
+
} else {
|
|
4870
|
+
if (formState.errors[props.name]?.includes("is not a valid option")) {
|
|
4871
|
+
delete formState.errors[props.name];
|
|
4872
|
+
}
|
|
4873
|
+
}
|
|
4874
|
+
} else if (allowCreate.value || !displayValue) {
|
|
4875
|
+
if (formState.errors[props.name]?.includes("is not a valid option")) {
|
|
4876
|
+
delete formState.errors[props.name];
|
|
4877
|
+
}
|
|
4878
|
+
}
|
|
4861
4879
|
formState.setFocus(props.name, false);
|
|
4862
4880
|
},
|
|
4863
4881
|
onFocus: () => {
|
|
@@ -4990,6 +5008,9 @@ function createDaisyUIComboboxField() {
|
|
|
4990
5008
|
displayText.value = option.label;
|
|
4991
5009
|
formState.touchField(props.name);
|
|
4992
5010
|
formState.validateField(props.name);
|
|
5011
|
+
if (formState.errors[props.name]?.includes("is not a valid option")) {
|
|
5012
|
+
delete formState.errors[props.name];
|
|
5013
|
+
}
|
|
4993
5014
|
formState.setSelectedIndex(props.name, -1);
|
|
4994
5015
|
formState.setFocus(props.name, false);
|
|
4995
5016
|
} else if (selectedIndex.value === filteredOptions.value.length && isNewValue.value) {
|
|
@@ -4997,6 +5018,18 @@ function createDaisyUIComboboxField() {
|
|
|
4997
5018
|
formState.setValue(props.name, displayValue);
|
|
4998
5019
|
formState.touchField(props.name);
|
|
4999
5020
|
formState.validateField(props.name);
|
|
5021
|
+
if (!allowCreate.value) {
|
|
5022
|
+
const isValidOption = getOptions.value.some(
|
|
5023
|
+
(opt) => opt.value === displayValue || opt.label === displayValue || opt.value.toLowerCase() === displayValue.toLowerCase() || opt.label.toLowerCase() === displayValue.toLowerCase()
|
|
5024
|
+
);
|
|
5025
|
+
if (!isValidOption) {
|
|
5026
|
+
formState.errors[props.name] = `"${displayValue}" is not a valid option. Please select from the list.`;
|
|
5027
|
+
}
|
|
5028
|
+
} else {
|
|
5029
|
+
if (formState.errors[props.name]?.includes("is not a valid option")) {
|
|
5030
|
+
delete formState.errors[props.name];
|
|
5031
|
+
}
|
|
5032
|
+
}
|
|
5000
5033
|
formState.setSelectedIndex(props.name, -1);
|
|
5001
5034
|
formState.setFocus(props.name, false);
|
|
5002
5035
|
} else if (isNewValue.value && selectedIndex.value < 0) {
|
|
@@ -5004,6 +5037,18 @@ function createDaisyUIComboboxField() {
|
|
|
5004
5037
|
formState.setValue(props.name, displayValue);
|
|
5005
5038
|
formState.touchField(props.name);
|
|
5006
5039
|
formState.validateField(props.name);
|
|
5040
|
+
if (!allowCreate.value) {
|
|
5041
|
+
const isValidOption = getOptions.value.some(
|
|
5042
|
+
(opt) => opt.value === displayValue || opt.label === displayValue || opt.value.toLowerCase() === displayValue.toLowerCase() || opt.label.toLowerCase() === displayValue.toLowerCase()
|
|
5043
|
+
);
|
|
5044
|
+
if (!isValidOption) {
|
|
5045
|
+
formState.errors[props.name] = `"${displayValue}" is not a valid option. Please select from the list.`;
|
|
5046
|
+
}
|
|
5047
|
+
} else {
|
|
5048
|
+
if (formState.errors[props.name]?.includes("is not a valid option")) {
|
|
5049
|
+
delete formState.errors[props.name];
|
|
5050
|
+
}
|
|
5051
|
+
}
|
|
5007
5052
|
formState.setSelectedIndex(props.name, -1);
|
|
5008
5053
|
formState.setFocus(props.name, false);
|
|
5009
5054
|
}
|
|
@@ -5077,6 +5122,9 @@ function createDaisyUIComboboxField() {
|
|
|
5077
5122
|
e.stopPropagation();
|
|
5078
5123
|
formState.setValue(props.name, option.value);
|
|
5079
5124
|
displayText.value = option.label;
|
|
5125
|
+
if (formState.errors[props.name]) {
|
|
5126
|
+
delete formState.errors[props.name];
|
|
5127
|
+
}
|
|
5080
5128
|
formState.touchField(props.name);
|
|
5081
5129
|
formState.validateField(props.name);
|
|
5082
5130
|
formState.setSelectedIndex(props.name, -1);
|
|
@@ -5088,7 +5136,7 @@ function createDaisyUIComboboxField() {
|
|
|
5088
5136
|
},
|
|
5089
5137
|
option.value
|
|
5090
5138
|
)),
|
|
5091
|
-
isNewValue.value && /* @__PURE__ */ jsx(
|
|
5139
|
+
isNewValue.value && allowCreate.value && /* @__PURE__ */ jsx(
|
|
5092
5140
|
"li",
|
|
5093
5141
|
{
|
|
5094
5142
|
id: `option-new`,
|
|
@@ -5104,6 +5152,9 @@ function createDaisyUIComboboxField() {
|
|
|
5104
5152
|
e.stopPropagation();
|
|
5105
5153
|
const displayValue = String(displayText.value || "").trim();
|
|
5106
5154
|
formState.setValue(props.name, displayValue);
|
|
5155
|
+
if (formState.errors[props.name]) {
|
|
5156
|
+
delete formState.errors[props.name];
|
|
5157
|
+
}
|
|
5107
5158
|
formState.touchField(props.name);
|
|
5108
5159
|
formState.validateField(props.name);
|
|
5109
5160
|
formState.setSelectedIndex(props.name, -1);
|