@dragonmastery/zinia-forms-core 0.3.11 → 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.js CHANGED
@@ -58,14 +58,16 @@ function createBaseComponents(schema, styleName) {
58
58
  };
59
59
  }
60
60
 
61
- // src/components/createTypedSelectField.ts
62
- function createTypedSelectField(baseSelectField, fieldPath) {
63
- return (props, context) => {
64
- const fullProps = {
65
- ...props,
66
- name: fieldPath
67
- };
68
- return baseSelectField(fullProps, context || { attrs: {} });
61
+ // src/components/createBaseDisplayComponents.ts
62
+ function createBaseDisplayComponents(schema, styleName) {
63
+ const styleToUse = styleName || getDefaultStyle();
64
+ const styleCreators = getRegisteredStyle(styleToUse);
65
+ if (!styleCreators) {
66
+ throw new Error(`Render style "${styleToUse}" is not registered. Make sure to register it with the ZiniaPlugin.`);
67
+ }
68
+ const ZiniaDisplay = styleCreators.createDisplay();
69
+ return {
70
+ ZiniaDisplay
69
71
  };
70
72
  }
71
73
 
@@ -124,6 +126,28 @@ function createTypedArrayField(baseArrayField, fieldPath, metadata) {
124
126
  return TypedArrayField;
125
127
  }
126
128
 
129
+ // src/components/createTypedComboboxField.ts
130
+ function createTypedComboboxField(baseComboboxField, fieldPath) {
131
+ return (props, context) => {
132
+ const fullProps = {
133
+ ...props,
134
+ name: fieldPath
135
+ };
136
+ return baseComboboxField(fullProps, context || { attrs: {} });
137
+ };
138
+ }
139
+
140
+ // src/components/createTypedSelectField.ts
141
+ function createTypedSelectField(baseSelectField, fieldPath) {
142
+ return (props, context) => {
143
+ const fullProps = {
144
+ ...props,
145
+ name: fieldPath
146
+ };
147
+ return baseSelectField(fullProps, context || { attrs: {} });
148
+ };
149
+ }
150
+
127
151
  // src/metadata/createMetadataProps.ts
128
152
  function createMetadataProps(metadata) {
129
153
  return {
@@ -160,6 +184,79 @@ function pathToPascalCase(path) {
160
184
  return convertToPascalCase(path);
161
185
  }
162
186
 
187
+ // src/components/generateDisplayComponents.ts
188
+ function generateDisplayComponents(schema, fieldsMetadata, styleName) {
189
+ const styleToUse = styleName || getDefaultStyle();
190
+ const styleCreators = getRegisteredStyle(styleToUse);
191
+ if (!styleCreators) {
192
+ throw new Error(
193
+ `Render style "${styleToUse}" is not registered. Make sure to register it with the ZiniaPlugin.`
194
+ );
195
+ }
196
+ const DisplayField = styleCreators.createDisplayField();
197
+ const fields = {};
198
+ const components = {};
199
+ const typedComponents = components;
200
+ Object.entries(fieldsMetadata).forEach(([path, metadata]) => {
201
+ const fieldMeta = metadata;
202
+ const typedPath = path;
203
+ const componentName = pathToPascalCase(typedPath).replace("Field", "Display");
204
+ const displayFieldComponent = (props, context) => {
205
+ const metadataProps = createMetadataProps(fieldMeta);
206
+ let defaultFormat = props.format || "default";
207
+ if (!props.format) {
208
+ if (fieldMeta.inputType === "email") defaultFormat = "email";
209
+ else if (fieldMeta.inputType === "url") defaultFormat = "url";
210
+ else if (fieldMeta.inputType === "tel") defaultFormat = "phone";
211
+ else if (fieldMeta.inputType === "date") defaultFormat = "date";
212
+ else if (fieldMeta.inputType === "currency") defaultFormat = "currency";
213
+ else if (fieldMeta.inputType === "number") defaultFormat = "number";
214
+ else if (fieldMeta.type === "boolean") defaultFormat = "boolean";
215
+ else if (fieldMeta.type === "date") defaultFormat = "date";
216
+ else if (fieldMeta.type === "number") defaultFormat = "number";
217
+ }
218
+ let valueToLabel = props.valueToLabel;
219
+ if (fieldMeta.type === "enum" && fieldMeta.options && !valueToLabel) {
220
+ valueToLabel = {};
221
+ fieldMeta.options.forEach((option) => {
222
+ if (typeof option === "object" && option.value && option.label) {
223
+ valueToLabel[option.value] = option.label;
224
+ } else if (typeof option === "string") {
225
+ valueToLabel[option] = option;
226
+ }
227
+ });
228
+ }
229
+ return DisplayField(
230
+ {
231
+ ...metadataProps,
232
+ ...props,
233
+ name: props.name || typedPath,
234
+ format: defaultFormat,
235
+ valueToLabel
236
+ },
237
+ context || { attrs: {} }
238
+ );
239
+ };
240
+ fields[typedPath] = displayFieldComponent;
241
+ components[componentName] = displayFieldComponent;
242
+ });
243
+ const field = (path) => {
244
+ return fields[path];
245
+ };
246
+ const returnObj = {
247
+ // Original display field component
248
+ DisplayField,
249
+ // Dictionary of pre-generated display field components
250
+ fields,
251
+ // Helper function for cleaner syntax
252
+ field
253
+ };
254
+ return {
255
+ generic: returnObj,
256
+ typed: typedComponents
257
+ };
258
+ }
259
+
163
260
  // src/components/generateFieldComponents.ts
164
261
  function generateFieldComponents(schema, fieldsMetadata, styleName) {
165
262
  const styleToUse = styleName || getDefaultStyle();
@@ -196,6 +293,9 @@ function generateFieldComponents(schema, fieldsMetadata, styleName) {
196
293
  const typedSelectFieldFactory = (fieldPath) => {
197
294
  return createTypedSelectField(baseSelectField, fieldPath);
198
295
  };
296
+ const typedComboboxFieldFactory = (fieldPath) => {
297
+ return createTypedComboboxField(ComboboxField, fieldPath);
298
+ };
199
299
  const typedArrayFieldFactory = (fieldPath, metadata) => {
200
300
  return createTypedArrayField(ArrayField, fieldPath, metadata);
201
301
  };
@@ -277,10 +377,7 @@ function generateFieldComponents(schema, fieldsMetadata, styleName) {
277
377
  return;
278
378
  // Skip the type-based switch below
279
379
  case "combobox":
280
- const comboboxFieldComponent = (props, context) => {
281
- const metadataProps = createMetadataProps(fieldMeta);
282
- return ComboboxField({ ...metadataProps, ...props, name: typedPath }, context || { attrs: {} });
283
- };
380
+ const comboboxFieldComponent = typedComboboxFieldFactory(typedPath);
284
381
  fields[typedPath] = comboboxFieldComponent;
285
382
  components[componentName] = comboboxFieldComponent;
286
383
  return;
@@ -406,92 +503,6 @@ function generateFieldComponents(schema, fieldsMetadata, styleName) {
406
503
  };
407
504
  }
408
505
 
409
- // src/components/createBaseDisplayComponents.ts
410
- function createBaseDisplayComponents(schema, styleName) {
411
- const styleToUse = styleName || getDefaultStyle();
412
- const styleCreators = getRegisteredStyle(styleToUse);
413
- if (!styleCreators) {
414
- throw new Error(`Render style "${styleToUse}" is not registered. Make sure to register it with the ZiniaPlugin.`);
415
- }
416
- const ZiniaDisplay = styleCreators.createDisplay();
417
- return {
418
- ZiniaDisplay
419
- };
420
- }
421
-
422
- // src/components/generateDisplayComponents.ts
423
- function generateDisplayComponents(schema, fieldsMetadata, styleName) {
424
- const styleToUse = styleName || getDefaultStyle();
425
- const styleCreators = getRegisteredStyle(styleToUse);
426
- if (!styleCreators) {
427
- throw new Error(
428
- `Render style "${styleToUse}" is not registered. Make sure to register it with the ZiniaPlugin.`
429
- );
430
- }
431
- const DisplayField = styleCreators.createDisplayField();
432
- const fields = {};
433
- const components = {};
434
- const typedComponents = components;
435
- Object.entries(fieldsMetadata).forEach(([path, metadata]) => {
436
- const fieldMeta = metadata;
437
- const typedPath = path;
438
- const componentName = pathToPascalCase(typedPath).replace("Field", "Display");
439
- const displayFieldComponent = (props, context) => {
440
- const metadataProps = createMetadataProps(fieldMeta);
441
- let defaultFormat = props.format || "default";
442
- if (!props.format) {
443
- if (fieldMeta.inputType === "email") defaultFormat = "email";
444
- else if (fieldMeta.inputType === "url") defaultFormat = "url";
445
- else if (fieldMeta.inputType === "tel") defaultFormat = "phone";
446
- else if (fieldMeta.inputType === "date") defaultFormat = "date";
447
- else if (fieldMeta.inputType === "currency") defaultFormat = "currency";
448
- else if (fieldMeta.inputType === "number") defaultFormat = "number";
449
- else if (fieldMeta.type === "boolean") defaultFormat = "boolean";
450
- else if (fieldMeta.type === "date") defaultFormat = "date";
451
- else if (fieldMeta.type === "number") defaultFormat = "number";
452
- }
453
- let valueToLabel = props.valueToLabel;
454
- if (fieldMeta.type === "enum" && fieldMeta.options && !valueToLabel) {
455
- valueToLabel = {};
456
- fieldMeta.options.forEach((option) => {
457
- if (typeof option === "object" && option.value && option.label) {
458
- valueToLabel[option.value] = option.label;
459
- } else if (typeof option === "string") {
460
- valueToLabel[option] = option;
461
- }
462
- });
463
- }
464
- return DisplayField(
465
- {
466
- ...metadataProps,
467
- ...props,
468
- name: props.name || typedPath,
469
- format: defaultFormat,
470
- valueToLabel
471
- },
472
- context || { attrs: {} }
473
- );
474
- };
475
- fields[typedPath] = displayFieldComponent;
476
- components[componentName] = displayFieldComponent;
477
- });
478
- const field = (path) => {
479
- return fields[path];
480
- };
481
- const returnObj = {
482
- // Original display field component
483
- DisplayField,
484
- // Dictionary of pre-generated display field components
485
- fields,
486
- // Helper function for cleaner syntax
487
- field
488
- };
489
- return {
490
- generic: returnObj,
491
- typed: typedComponents
492
- };
493
- }
494
-
495
506
  // src/utils/objectPath.ts
496
507
  function getValueByPath(obj, path) {
497
508
  const segments = path.split(".");
@@ -4661,24 +4672,6 @@ function createDaisyUICheckboxField() {
4661
4672
  return DaisyUICheckboxField;
4662
4673
  }
4663
4674
 
4664
- // src/fields/types/ComboboxFieldProps.ts
4665
- var COMBOBOX_FIELD_PROP_NAMES = [
4666
- "name",
4667
- "options",
4668
- "placeholder",
4669
- "disabled",
4670
- "readonly",
4671
- "class",
4672
- "label",
4673
- "hideLabel",
4674
- "description",
4675
- "required",
4676
- "size",
4677
- "variant",
4678
- "allowCreate",
4679
- "filterFn"
4680
- ];
4681
-
4682
4675
  // src/utils/propNormalization.ts
4683
4676
  function camelToKebab(str) {
4684
4677
  return str.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase();
@@ -4721,6 +4714,29 @@ function normalizePropsFromAttrs(props, propsDefinition, attrs) {
4721
4714
  }
4722
4715
  return normalized;
4723
4716
  }
4717
+
4718
+ // src/fields/types/ComboboxFieldProps.ts
4719
+ var COMBOBOX_FIELD_PROP_NAMES = [
4720
+ "name",
4721
+ "selectOptions",
4722
+ "placeholder",
4723
+ "disabled",
4724
+ "readonly",
4725
+ "class",
4726
+ "label",
4727
+ "hideLabel",
4728
+ "description",
4729
+ "required",
4730
+ "size",
4731
+ "variant",
4732
+ "valueToLabel",
4733
+ "useSchemaOptions",
4734
+ "dependsOn",
4735
+ "optionFilterFn",
4736
+ "autoReset",
4737
+ "allowCreate",
4738
+ "filterFn"
4739
+ ];
4724
4740
  function createDaisyUIComboboxField() {
4725
4741
  const propsDefinition = [...COMBOBOX_FIELD_PROP_NAMES];
4726
4742
  const DaisyUIComboboxField = (props, { attrs }) => {
@@ -4731,15 +4747,13 @@ function createDaisyUIComboboxField() {
4731
4747
  }
4732
4748
  const fieldMetadata = formState.fieldsMetadata[props.name] || {};
4733
4749
  const normalizedProps = normalizePropsFromAttrs(props, propsDefinition, attrs);
4734
- const normalizeOption = (option) => {
4735
- if (typeof option === "string") {
4736
- return { label: option, value: option };
4737
- }
4738
- return option;
4739
- };
4750
+ const allowCreate = computed(() => normalizedProps.allowCreate === true);
4740
4751
  const getOptions = computed(() => {
4741
- if (normalizedProps.options) {
4742
- return normalizedProps.options.map(normalizeOption);
4752
+ if (normalizedProps.selectOptions) {
4753
+ return normalizedProps.selectOptions;
4754
+ }
4755
+ if (normalizedProps.useSchemaOptions === false) {
4756
+ return [];
4743
4757
  }
4744
4758
  const schemaOptions = fieldMetadata?.options || [];
4745
4759
  return schemaOptions.map((opt) => ({
@@ -4753,16 +4767,12 @@ function createDaisyUIComboboxField() {
4753
4767
  return getOptions.value;
4754
4768
  }
4755
4769
  const filterFn = normalizedProps.filterFn || ((q, opt) => {
4756
- const normalized = normalizeOption(opt);
4757
- return normalized.label.toLowerCase().includes(q.toLowerCase()) || normalized.value.toLowerCase().includes(q.toLowerCase());
4758
- });
4759
- return getOptions.value.filter((opt) => {
4760
- const originalOpt = opt.label === opt.value ? opt.label : opt;
4761
- return filterFn(query, originalOpt);
4770
+ return opt.label.toLowerCase().includes(q.toLowerCase()) || opt.value.toLowerCase().includes(q.toLowerCase());
4762
4771
  });
4772
+ return getOptions.value.filter((opt) => filterFn(query, opt));
4763
4773
  });
4764
4774
  const isNewValue = computed(() => {
4765
- if (!normalizedProps.allowCreate) return false;
4775
+ if (!allowCreate.value) return false;
4766
4776
  const currentText = String(displayText.value || "").trim().toLowerCase();
4767
4777
  if (!currentText) return false;
4768
4778
  return !getOptions.value.some(
@@ -4797,7 +4807,7 @@ function createDaisyUIComboboxField() {
4797
4807
  const showDropdown = computed(() => {
4798
4808
  if (!isFocused.value) return false;
4799
4809
  if (getOptions.value.length > 0) return true;
4800
- if (normalizedProps.allowCreate) {
4810
+ if (allowCreate.value) {
4801
4811
  return String(formState.getValue(props.name) || "").trim().length > 0;
4802
4812
  }
4803
4813
  return false;
@@ -4838,7 +4848,7 @@ function createDaisyUIComboboxField() {
4838
4848
  if (matchingOption) {
4839
4849
  formState.setValue(props.name, matchingOption.value);
4840
4850
  displayText.value = matchingOption.label;
4841
- } else if (normalizedProps.allowCreate && displayValue) {
4851
+ } else if (allowCreate.value && displayValue) {
4842
4852
  formState.setValue(props.name, displayValue);
4843
4853
  displayText.value = displayValue;
4844
4854
  } else if (!displayValue) {
@@ -4849,6 +4859,23 @@ function createDaisyUIComboboxField() {
4849
4859
  }
4850
4860
  formState.touchField(props.name);
4851
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
+ }
4852
4879
  formState.setFocus(props.name, false);
4853
4880
  },
4854
4881
  onFocus: () => {
@@ -4981,6 +5008,9 @@ function createDaisyUIComboboxField() {
4981
5008
  displayText.value = option.label;
4982
5009
  formState.touchField(props.name);
4983
5010
  formState.validateField(props.name);
5011
+ if (formState.errors[props.name]?.includes("is not a valid option")) {
5012
+ delete formState.errors[props.name];
5013
+ }
4984
5014
  formState.setSelectedIndex(props.name, -1);
4985
5015
  formState.setFocus(props.name, false);
4986
5016
  } else if (selectedIndex.value === filteredOptions.value.length && isNewValue.value) {
@@ -4988,6 +5018,18 @@ function createDaisyUIComboboxField() {
4988
5018
  formState.setValue(props.name, displayValue);
4989
5019
  formState.touchField(props.name);
4990
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
+ }
4991
5033
  formState.setSelectedIndex(props.name, -1);
4992
5034
  formState.setFocus(props.name, false);
4993
5035
  } else if (isNewValue.value && selectedIndex.value < 0) {
@@ -4995,6 +5037,18 @@ function createDaisyUIComboboxField() {
4995
5037
  formState.setValue(props.name, displayValue);
4996
5038
  formState.touchField(props.name);
4997
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
+ }
4998
5052
  formState.setSelectedIndex(props.name, -1);
4999
5053
  formState.setFocus(props.name, false);
5000
5054
  }
@@ -5012,108 +5066,132 @@ function createDaisyUIComboboxField() {
5012
5066
  props.label || fieldMetadata.label,
5013
5067
  fieldMetadata.isRequired && /* @__PURE__ */ jsx("span", { class: "text-error", children: " *" })
5014
5068
  ] }),
5015
- /* @__PURE__ */ jsxs("div", { class: "relative inline-block max-w-full", style: "min-width: clamp(3rem, 20rem, 100%);", role: "combobox", "aria-expanded": showDropdown.value, "aria-haspopup": "listbox", children: [
5016
- /* @__PURE__ */ jsx(
5017
- "input",
5018
- {
5019
- ref: inputElement,
5020
- class: inputClass,
5021
- placeholder: props.placeholder || "Search or type new value",
5022
- disabled: props.disabled,
5023
- autocomplete: "off",
5024
- "data-testid": `${formState.storeName}-combobox-field-${String(props.name)}`,
5025
- ...inputProps
5026
- }
5027
- ),
5028
- /* @__PURE__ */ jsx("div", { class: "absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none", children: /* @__PURE__ */ jsx(
5029
- "svg",
5030
- {
5031
- xmlns: "http://www.w3.org/2000/svg",
5032
- class: "h-5 w-5 text-base-content/50",
5033
- fill: "none",
5034
- viewBox: "0 0 24 24",
5035
- stroke: "currentColor",
5036
- "stroke-width": "2",
5037
- children: /* @__PURE__ */ jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M8 9l4-4 4 4m0 6l-4 4-4-4" })
5038
- }
5039
- ) }),
5040
- showDropdown.value && /* @__PURE__ */ jsx("div", { ref: dropdownPanel, class: "absolute z-50 mt-1 bg-base-100 border border-base-300 rounded-box shadow-lg max-h-60 overflow-auto", style: "min-width: 100%;", children: filteredOptions.value.length > 0 || isNewValue.value ? /* @__PURE__ */ jsxs("ul", { id: "combobox-listbox", class: "menu w-full", role: "listbox", children: [
5041
- filteredOptions.value.map((option, index) => /* @__PURE__ */ jsx(
5042
- "li",
5043
- {
5044
- id: `option-${index}`,
5045
- role: "option",
5046
- "aria-selected": index === selectedIndex.value,
5047
- children: /* @__PURE__ */ jsx(
5048
- "a",
5049
- {
5050
- href: "#",
5051
- class: `w-full ${index === selectedIndex.value ? "menu-focus" : ""}`,
5052
- onClick: (e) => {
5053
- e.preventDefault();
5054
- e.stopPropagation();
5055
- formState.setValue(props.name, option.value);
5056
- displayText.value = option.label;
5057
- formState.touchField(props.name);
5058
- formState.validateField(props.name);
5059
- formState.setSelectedIndex(props.name, -1);
5060
- formState.setFocus(props.name, false);
5061
- },
5062
- children: option.label
5063
- }
5064
- )
5065
- },
5066
- option.value
5067
- )),
5068
- isNewValue.value && /* @__PURE__ */ jsx(
5069
- "li",
5070
- {
5071
- id: `option-new`,
5072
- role: "option",
5073
- "aria-selected": selectedIndex.value === filteredOptions.value.length,
5074
- children: /* @__PURE__ */ jsx(
5075
- "a",
5076
- {
5077
- href: "#",
5078
- class: `w-full ${selectedIndex.value === filteredOptions.value.length ? "menu-focus" : ""}`,
5079
- onClick: (e) => {
5080
- e.preventDefault();
5081
- e.stopPropagation();
5082
- const displayValue = String(displayText.value || "").trim();
5083
- formState.setValue(props.name, displayValue);
5084
- formState.touchField(props.name);
5085
- formState.validateField(props.name);
5086
- formState.setSelectedIndex(props.name, -1);
5087
- formState.setFocus(props.name, false);
5088
- },
5089
- children: /* @__PURE__ */ jsxs("div", { class: "flex items-start gap-2", children: [
5090
- /* @__PURE__ */ jsx(
5091
- "svg",
5092
- {
5093
- xmlns: "http://www.w3.org/2000/svg",
5094
- class: "h-5 w-5 text-success mt-0.5 flex-shrink-0",
5095
- fill: "none",
5096
- viewBox: "0 0 24 24",
5097
- stroke: "currentColor",
5098
- "stroke-width": "2",
5099
- children: /* @__PURE__ */ jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M12 4v16m8-8H4" })
5100
- }
5101
- ),
5102
- /* @__PURE__ */ jsxs("div", { class: "text-sm", children: [
5103
- /* @__PURE__ */ jsx("p", { class: "font-medium text-success", children: "New value" }),
5104
- /* @__PURE__ */ jsxs("p", { class: "text-base-content/70", children: [
5105
- '"',
5106
- displayText.value,
5107
- '" will be saved.'
5108
- ] })
5109
- ] })
5110
- ] })
5111
- }
5112
- )
5113
- }
5114
- )
5115
- ] }) : null })
5116
- ] }),
5069
+ /* @__PURE__ */ jsxs(
5070
+ "div",
5071
+ {
5072
+ class: "relative inline-block max-w-full",
5073
+ style: "min-width: clamp(3rem, 20rem, 100%);",
5074
+ role: "combobox",
5075
+ "aria-expanded": showDropdown.value,
5076
+ "aria-haspopup": "listbox",
5077
+ children: [
5078
+ /* @__PURE__ */ jsx(
5079
+ "input",
5080
+ {
5081
+ ref: inputElement,
5082
+ class: inputClass,
5083
+ placeholder: props.placeholder || "Search or type new value",
5084
+ disabled: props.disabled,
5085
+ autocomplete: "off",
5086
+ "data-testid": `${formState.storeName}-combobox-field-${String(props.name)}`,
5087
+ ...inputProps
5088
+ }
5089
+ ),
5090
+ /* @__PURE__ */ jsx("div", { class: "absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none", children: /* @__PURE__ */ jsx(
5091
+ "svg",
5092
+ {
5093
+ xmlns: "http://www.w3.org/2000/svg",
5094
+ class: "h-5 w-5 text-base-content/50",
5095
+ fill: "none",
5096
+ viewBox: "0 0 24 24",
5097
+ stroke: "currentColor",
5098
+ "stroke-width": "2",
5099
+ children: /* @__PURE__ */ jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M8 9l4-4 4 4m0 6l-4 4-4-4" })
5100
+ }
5101
+ ) }),
5102
+ showDropdown.value && /* @__PURE__ */ jsx(
5103
+ "div",
5104
+ {
5105
+ ref: dropdownPanel,
5106
+ class: "absolute z-50 mt-1 bg-base-100 border border-base-300 rounded-box shadow-lg max-h-60 overflow-auto",
5107
+ style: "min-width: 100%;",
5108
+ children: filteredOptions.value.length > 0 || isNewValue.value ? /* @__PURE__ */ jsxs("ul", { id: "combobox-listbox", class: "menu w-full", role: "listbox", children: [
5109
+ filteredOptions.value.map((option, index) => /* @__PURE__ */ jsx(
5110
+ "li",
5111
+ {
5112
+ id: `option-${index}`,
5113
+ role: "option",
5114
+ "aria-selected": index === selectedIndex.value,
5115
+ children: /* @__PURE__ */ jsx(
5116
+ "a",
5117
+ {
5118
+ href: "#",
5119
+ class: `w-full ${index === selectedIndex.value ? "menu-focus" : ""}`,
5120
+ onClick: (e) => {
5121
+ e.preventDefault();
5122
+ e.stopPropagation();
5123
+ formState.setValue(props.name, option.value);
5124
+ displayText.value = option.label;
5125
+ if (formState.errors[props.name]) {
5126
+ delete formState.errors[props.name];
5127
+ }
5128
+ formState.touchField(props.name);
5129
+ formState.validateField(props.name);
5130
+ formState.setSelectedIndex(props.name, -1);
5131
+ formState.setFocus(props.name, false);
5132
+ },
5133
+ children: option.label
5134
+ }
5135
+ )
5136
+ },
5137
+ option.value
5138
+ )),
5139
+ isNewValue.value && allowCreate.value && /* @__PURE__ */ jsx(
5140
+ "li",
5141
+ {
5142
+ id: `option-new`,
5143
+ role: "option",
5144
+ "aria-selected": selectedIndex.value === filteredOptions.value.length,
5145
+ children: /* @__PURE__ */ jsx(
5146
+ "a",
5147
+ {
5148
+ href: "#",
5149
+ class: `w-full ${selectedIndex.value === filteredOptions.value.length ? "menu-focus" : ""}`,
5150
+ onClick: (e) => {
5151
+ e.preventDefault();
5152
+ e.stopPropagation();
5153
+ const displayValue = String(displayText.value || "").trim();
5154
+ formState.setValue(props.name, displayValue);
5155
+ if (formState.errors[props.name]) {
5156
+ delete formState.errors[props.name];
5157
+ }
5158
+ formState.touchField(props.name);
5159
+ formState.validateField(props.name);
5160
+ formState.setSelectedIndex(props.name, -1);
5161
+ formState.setFocus(props.name, false);
5162
+ },
5163
+ children: /* @__PURE__ */ jsxs("div", { class: "flex items-start gap-2", children: [
5164
+ /* @__PURE__ */ jsx(
5165
+ "svg",
5166
+ {
5167
+ xmlns: "http://www.w3.org/2000/svg",
5168
+ class: "h-5 w-5 text-success mt-0.5 flex-shrink-0",
5169
+ fill: "none",
5170
+ viewBox: "0 0 24 24",
5171
+ stroke: "currentColor",
5172
+ "stroke-width": "2",
5173
+ children: /* @__PURE__ */ jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M12 4v16m8-8H4" })
5174
+ }
5175
+ ),
5176
+ /* @__PURE__ */ jsxs("div", { class: "text-sm", children: [
5177
+ /* @__PURE__ */ jsx("p", { class: "font-medium text-success", children: "New value" }),
5178
+ /* @__PURE__ */ jsxs("p", { class: "text-base-content/70", children: [
5179
+ '"',
5180
+ displayText.value,
5181
+ '" will be saved.'
5182
+ ] })
5183
+ ] })
5184
+ ] })
5185
+ }
5186
+ )
5187
+ }
5188
+ )
5189
+ ] }) : null
5190
+ }
5191
+ )
5192
+ ]
5193
+ }
5194
+ ),
5117
5195
  props.description && /* @__PURE__ */ jsx("p", { class: "text-sm mt-1", children: props.description }),
5118
5196
  isTouched2 && hasErrors && /* @__PURE__ */ jsx("p", { class: "text-error text-xs", children: formState.getError(props.name) }),
5119
5197
  isNewValue.value && displayText.value && !hasErrors && /* @__PURE__ */ jsxs("p", { class: "text-success text-xs", children: [
@@ -9964,6 +10042,6 @@ var ActionIcons = {
9964
10042
  dotsHorizontal: `<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z" /></svg>`
9965
10043
  };
9966
10044
 
9967
- export { ActionIcons, COMBOBOX_FIELD_PROP_NAMES, DEBUG_CONFIG, ErrorDisplay, LoadingDisplay, NoDataDisplay, SCHEMA_ID_SYMBOL, SELECT_FIELD_PROP_NAMES, ZINIA_DATA_TABLE_ACTIONS_KEY, ZINIA_DATA_TABLE_COLUMNS_KEY, ZINIA_DATA_TABLE_FILTER_INPUTS_KEY, ZINIA_DATA_TABLE_FILTER_OPERATORS_KEY, ZINIA_DATA_TABLE_FILTER_OPTIONS_LOADING_KEY, ZINIA_DATA_TABLE_FILTER_OPTIONS_STATE_KEY, ZINIA_DATA_TABLE_KEY, ZINIA_DATA_TABLE_NAME_KEY, ZINIA_DATA_TABLE_OPTIONS_KEY, ZINIA_DATA_TABLE_SEARCH_INPUT_KEY, ZINIA_DELETE_MODAL_FIELDS_GENERIC_KEY, ZINIA_DELETE_MODAL_FIELDS_KEY, ZINIA_DELETE_MODAL_KEY, ZINIA_DELETE_MODAL_SCHEMA_KEY, ZINIA_DISPLAY_FIELDS_GENERIC_KEY, ZINIA_DISPLAY_FIELDS_KEY, ZINIA_DISPLAY_KEY, ZINIA_DISPLAY_SCHEMA_KEY, ZINIA_FIELDS_GENERIC_KEY, ZINIA_FIELDS_KEY, ZINIA_FORM_KEY, ZINIA_FORM_SCHEMA_KEY, ZiniaPlugin, clearAllMetadata, clearSchemaMetadata, createBaseComponents, createBaseDisplayComponents, createPartialStyle, createStyleTemplate, createTypedArrayField, createTypedSelectField, daisyUIStyle, extendStyle, generateDisplayComponents, generateFieldComponents, getAllSchemaMetadata, getDefaultStyle, getFieldMetadata, getRegisteredStyle, getRegisteredStyleNames, getSchemaId, hasRegisteredStyle, hasSchemaMetadata, isDebugEnabled, mergeStyles, plainStyle, registerSchemaMetadata, registerStyle, setSchemaMetadata, useCursorDataTable, useDataTable, useDeleteModal, useDisplay, useForm, withMetadata };
10045
+ export { ActionIcons, COMBOBOX_FIELD_PROP_NAMES, DEBUG_CONFIG, ErrorDisplay, LoadingDisplay, NoDataDisplay, SCHEMA_ID_SYMBOL, SELECT_FIELD_PROP_NAMES, ZINIA_DATA_TABLE_ACTIONS_KEY, ZINIA_DATA_TABLE_COLUMNS_KEY, ZINIA_DATA_TABLE_FILTER_INPUTS_KEY, ZINIA_DATA_TABLE_FILTER_OPERATORS_KEY, ZINIA_DATA_TABLE_FILTER_OPTIONS_LOADING_KEY, ZINIA_DATA_TABLE_FILTER_OPTIONS_STATE_KEY, ZINIA_DATA_TABLE_KEY, ZINIA_DATA_TABLE_NAME_KEY, ZINIA_DATA_TABLE_OPTIONS_KEY, ZINIA_DATA_TABLE_SEARCH_INPUT_KEY, ZINIA_DELETE_MODAL_FIELDS_GENERIC_KEY, ZINIA_DELETE_MODAL_FIELDS_KEY, ZINIA_DELETE_MODAL_KEY, ZINIA_DELETE_MODAL_SCHEMA_KEY, ZINIA_DISPLAY_FIELDS_GENERIC_KEY, ZINIA_DISPLAY_FIELDS_KEY, ZINIA_DISPLAY_KEY, ZINIA_DISPLAY_SCHEMA_KEY, ZINIA_FIELDS_GENERIC_KEY, ZINIA_FIELDS_KEY, ZINIA_FORM_KEY, ZINIA_FORM_SCHEMA_KEY, ZiniaPlugin, clearAllMetadata, clearSchemaMetadata, createBaseComponents, createBaseDisplayComponents, createPartialStyle, createStyleTemplate, createTypedArrayField, createTypedComboboxField, createTypedSelectField, daisyUIStyle, extendStyle, generateDisplayComponents, generateFieldComponents, getAllSchemaMetadata, getDefaultStyle, getFieldMetadata, getRegisteredStyle, getRegisteredStyleNames, getSchemaId, hasRegisteredStyle, hasSchemaMetadata, isDebugEnabled, mergeStyles, plainStyle, registerSchemaMetadata, registerStyle, setSchemaMetadata, useCursorDataTable, useDataTable, useDeleteModal, useDisplay, useForm, withMetadata };
9968
10046
  //# sourceMappingURL=index.js.map
9969
10047
  //# sourceMappingURL=index.js.map