@dragonmastery/zinia-forms-core 0.3.15 → 0.3.17

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 CHANGED
@@ -1170,6 +1170,14 @@ interface DeleteModalProps<FormType = any> {
1170
1170
  interface DataTableProps<FormType> {
1171
1171
  class?: string;
1172
1172
  name?: string;
1173
+ /**
1174
+ * Height behavior for the table container
1175
+ * - 'auto' (default): Table expands to fill available space with a minimum height to prevent squishing
1176
+ * - 'fixed': Uses fixed height (850px, max 90vh) - original behavior
1177
+ * - number: Fixed pixel height (e.g., 600)
1178
+ * - string: Custom CSS height value (e.g., '50vh', '600px')
1179
+ */
1180
+ height?: 'auto' | 'fixed' | number | string;
1173
1181
  }
1174
1182
 
1175
1183
  /**
@@ -1508,7 +1516,7 @@ declare function useForm<T extends z.ZodObject<any>, CalcType = (values: z.infer
1508
1516
  timestamp: number;
1509
1517
  timeoutId?: number;
1510
1518
  }[]>;
1511
- fieldsMetadata: Record<string, FieldMetadata>;
1519
+ readonly fieldsMetadata: Record<string, FieldMetadata>;
1512
1520
  validate: (options?: {
1513
1521
  markErrorsAsTouched: boolean;
1514
1522
  }) => boolean;
@@ -2048,9 +2056,10 @@ interface ColumnDefinition<TData, TField extends keyof TData> {
2048
2056
  textWrap?: 'truncate' | 'wrap';
2049
2057
  format?: (value: TData[TField], row: TData) => string;
2050
2058
  render?: (value: TData[TField], row: TData) => any;
2051
- filterType?: 'text' | 'select' | 'number' | 'boolean';
2059
+ filterType?: 'text' | 'select' | 'number' | 'boolean' | 'combobox';
2052
2060
  filterOptions?: FilterOptionItem[];
2053
2061
  filterOptionsLoader?: () => Promise<FilterOptionItem[]>;
2062
+ filterAllowCreate?: boolean;
2054
2063
  sortLabels?: {
2055
2064
  asc: string;
2056
2065
  desc: string;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { watch, provide, ref, computed, unref, inject, getCurrentInstance, reactive, nextTick, Teleport } from 'vue';
1
+ import { reactive, watch, provide, ref, computed, unref, inject, getCurrentInstance, nextTick, Teleport } from 'vue';
2
2
  import { z } from 'zod';
3
3
  import { jsxs, jsx, Fragment } from 'vue/jsx-runtime';
4
4
 
@@ -651,6 +651,12 @@ var SchemaCache = class {
651
651
  if (debug) {
652
652
  console.log(`[SchemaCache] More segments remaining, continuing to next segment`);
653
653
  }
654
+ if (!(currentSchema instanceof z.ZodObject)) {
655
+ if (debug) {
656
+ console.log(`[SchemaCache] ERROR: Element schema is not a ZodObject after unwrap, cannot access nested fields`);
657
+ }
658
+ return null;
659
+ }
654
660
  continue;
655
661
  }
656
662
  if (debug) {
@@ -1058,6 +1064,11 @@ function extractFieldMetadata(schema, path = "", parentSchema, schemaId) {
1058
1064
  metadata.isArray = true;
1059
1065
  if (schema._def.minLength) {
1060
1066
  metadata.min = schema._def.minLength.value;
1067
+ if (schema._def.minLength.value > 0) ; else {
1068
+ metadata.isRequired = false;
1069
+ }
1070
+ } else {
1071
+ metadata.isRequired = false;
1061
1072
  }
1062
1073
  if (schema._def.maxLength) {
1063
1074
  metadata.max = schema._def.maxLength.value;
@@ -1174,9 +1185,7 @@ function extractFieldMetadata(schema, path = "", parentSchema, schemaId) {
1174
1185
  } else if (customMetadata.options) {
1175
1186
  metadata.options = customMetadata.options;
1176
1187
  } else {
1177
- metadata.options = [
1178
- { value: "", label: "Select an option" }
1179
- ];
1188
+ metadata.options = [{ value: "", label: "Select an option" }];
1180
1189
  }
1181
1190
  }
1182
1191
  }
@@ -1815,6 +1824,83 @@ function useFormValidation(schema, formState, options) {
1815
1824
  validateField: validateField2
1816
1825
  };
1817
1826
  }
1827
+
1828
+ // src/metadata/resolveMetadataPath.ts
1829
+ function resolveMetadataPath(fieldsMetadata, path) {
1830
+ if (path in fieldsMetadata) {
1831
+ return fieldsMetadata[path];
1832
+ }
1833
+ return resolveMetadataPathRecursive(fieldsMetadata, path.split("."), 0);
1834
+ }
1835
+ function resolveMetadataPathRecursive(fieldsMetadata, segments, startIndex, currentMetadata) {
1836
+ if (startIndex >= segments.length) {
1837
+ return void 0;
1838
+ }
1839
+ if (currentMetadata) {
1840
+ const segment = segments[startIndex];
1841
+ if (!isNaN(Number(segment))) {
1842
+ if (currentMetadata.arrayOf) {
1843
+ return resolveMetadataPathRecursive(fieldsMetadata, segments, startIndex + 1, currentMetadata.arrayOf);
1844
+ }
1845
+ return void 0;
1846
+ } else {
1847
+ if (currentMetadata.children) {
1848
+ const childMetadata = currentMetadata.children[segment];
1849
+ if (childMetadata) {
1850
+ if (startIndex + 1 < segments.length) {
1851
+ return resolveMetadataPathRecursive(fieldsMetadata, segments, startIndex + 1, childMetadata);
1852
+ }
1853
+ return {
1854
+ ...childMetadata,
1855
+ path: segments.join(".")
1856
+ };
1857
+ }
1858
+ }
1859
+ return void 0;
1860
+ }
1861
+ } else {
1862
+ const segment = segments[startIndex];
1863
+ const rootMetadata = fieldsMetadata[segment];
1864
+ if (!rootMetadata) {
1865
+ return void 0;
1866
+ }
1867
+ if (startIndex + 1 < segments.length) {
1868
+ return resolveMetadataPathRecursive(fieldsMetadata, segments, startIndex + 1, rootMetadata);
1869
+ }
1870
+ return {
1871
+ ...rootMetadata,
1872
+ path: segments.join(".")
1873
+ };
1874
+ }
1875
+ }
1876
+ function createMetadataProxy(fieldsMetadata) {
1877
+ return new Proxy(fieldsMetadata, {
1878
+ get(target, prop) {
1879
+ if (typeof prop !== "string") {
1880
+ return Reflect.get(target, prop);
1881
+ }
1882
+ return resolveMetadataPath(fieldsMetadata, prop);
1883
+ },
1884
+ has(target, prop) {
1885
+ if (typeof prop !== "string") {
1886
+ return prop in target;
1887
+ }
1888
+ if (prop in target) {
1889
+ return true;
1890
+ }
1891
+ return resolveMetadataPath(fieldsMetadata, prop) !== void 0;
1892
+ },
1893
+ ownKeys(target) {
1894
+ return Reflect.ownKeys(target);
1895
+ },
1896
+ getOwnPropertyDescriptor(target, prop) {
1897
+ if (prop in target) {
1898
+ return Reflect.getOwnPropertyDescriptor(target, prop);
1899
+ }
1900
+ return void 0;
1901
+ }
1902
+ });
1903
+ }
1818
1904
  function setupLocalStoragePersistence(formData, options) {
1819
1905
  const { storeName, enabled = true, initialValues = {}, debug = false } = options;
1820
1906
  const logger = Logger.getLogger("LocalStoragePersistence");
@@ -2059,7 +2145,11 @@ function useForm(schema, options) {
2059
2145
  get pendingOperations() {
2060
2146
  return formState.state.pendingOperations;
2061
2147
  },
2062
- fieldsMetadata,
2148
+ // Create a Proxy for fieldsMetadata that automatically resolves nested array paths
2149
+ // This allows fieldsMetadata[path] to work for nested array paths like "items.0.fieldName"
2150
+ get fieldsMetadata() {
2151
+ return createMetadataProxy(fieldsMetadata);
2152
+ },
2063
2153
  // Form methods
2064
2154
  validate: validation.validate,
2065
2155
  validateField: validation.validateField,
@@ -5261,7 +5351,7 @@ function createDaisyUIComboboxField() {
5261
5351
  class: inputClass,
5262
5352
  placeholder: isBeingPopulated.value ? "Loading..." : isLoadingOptions.value ? "Loading options..." : parentFieldName.value && !parentValue.value ? "Select parent field first" : props.placeholder || "Search or type new value",
5263
5353
  disabled: isDisabled.value,
5264
- autocomplete: "off",
5354
+ autocomplete: "nope",
5265
5355
  "data-testid": `${formState.storeName}-combobox-field-${String(props.name)}`,
5266
5356
  ...inputProps
5267
5357
  }
@@ -7749,6 +7839,8 @@ function getFilterType(field, column, fieldsMetadata) {
7749
7839
  return "number";
7750
7840
  case "checkbox":
7751
7841
  return "boolean";
7842
+ case "combobox":
7843
+ return "combobox";
7752
7844
  case "select":
7753
7845
  case "radio":
7754
7846
  return column.filterOptions || fieldMetadata?.options ? "select" : "text";
@@ -8242,6 +8334,366 @@ var BooleanFilter = (props) => {
8242
8334
  }
8243
8335
  );
8244
8336
  };
8337
+ var comboboxState = reactive({});
8338
+ var ComboboxFilter = (props) => {
8339
+ if (!comboboxState[props.field]) {
8340
+ comboboxState[props.field] = {
8341
+ isOpen: false,
8342
+ selectedIndex: -1
8343
+ };
8344
+ }
8345
+ const state = comboboxState[props.field];
8346
+ const searchQuery = computed(() => props.filterInputValues.value[props.field] || "");
8347
+ const selectedOption = computed(() => {
8348
+ if (!props.value) return "";
8349
+ return props.options.find((opt) => opt.value === props.value)?.label || String(props.value);
8350
+ });
8351
+ if (!(props.field in props.filterInputValues.value) && props.value) {
8352
+ const label = selectedOption.value;
8353
+ if (label) {
8354
+ props.filterInputValues.value[props.field] = label;
8355
+ }
8356
+ }
8357
+ const filteredOptions = computed(() => {
8358
+ const query = searchQuery.value.trim().toLowerCase();
8359
+ if (!query) {
8360
+ return props.options;
8361
+ }
8362
+ return props.options.filter((opt) => opt.label.toLowerCase().includes(query));
8363
+ });
8364
+ const isNewValue = computed(() => {
8365
+ if (!props.allowCreate || !searchQuery.value.trim()) return false;
8366
+ const query = searchQuery.value.trim();
8367
+ return !props.options.some((opt) => opt.label.toLowerCase() === query.toLowerCase());
8368
+ });
8369
+ const isInvalidValue = computed(() => {
8370
+ if (!searchQuery.value.trim()) return false;
8371
+ if (props.allowCreate) return false;
8372
+ const query = searchQuery.value.trim();
8373
+ return !props.options.some((opt) => opt.label.toLowerCase() === query.toLowerCase());
8374
+ });
8375
+ const handleInput = (e) => {
8376
+ const value = e.target.value;
8377
+ props.filterInputValues.value[props.field] = value;
8378
+ state.isOpen = true;
8379
+ state.selectedIndex = -1;
8380
+ const exactMatch = props.options.find((opt) => opt.label.toLowerCase() === value.toLowerCase().trim());
8381
+ if (exactMatch) {
8382
+ props.onFilterChange(props.field, exactMatch.value, "eq");
8383
+ }
8384
+ };
8385
+ const handleSelectOption = (option) => {
8386
+ props.filterInputValues.value[props.field] = option.label;
8387
+ props.onFilterChange(props.field, option.value, "eq");
8388
+ state.isOpen = false;
8389
+ state.selectedIndex = -1;
8390
+ };
8391
+ const handleSelectNewValue = () => {
8392
+ const newValue = searchQuery.value.trim();
8393
+ if (newValue) {
8394
+ props.onFilterChange(props.field, newValue, "eq");
8395
+ state.isOpen = false;
8396
+ state.selectedIndex = -1;
8397
+ }
8398
+ };
8399
+ const handleKeyDown = (e) => {
8400
+ if (e.key === "Escape") {
8401
+ e.preventDefault();
8402
+ e.stopPropagation();
8403
+ state.isOpen = false;
8404
+ state.selectedIndex = -1;
8405
+ if (props.value) {
8406
+ props.filterInputValues.value[props.field] = selectedOption.value;
8407
+ } else {
8408
+ props.filterInputValues.value[props.field] = "";
8409
+ }
8410
+ return;
8411
+ }
8412
+ if (e.key === "Enter") {
8413
+ e.preventDefault();
8414
+ e.stopPropagation();
8415
+ if (state.selectedIndex >= 0 && state.selectedIndex < filteredOptions.value.length) {
8416
+ handleSelectOption(filteredOptions.value[state.selectedIndex]);
8417
+ return;
8418
+ }
8419
+ if (state.selectedIndex === filteredOptions.value.length && isNewValue.value && props.allowCreate) {
8420
+ handleSelectNewValue();
8421
+ return;
8422
+ }
8423
+ if (searchQuery.value.trim() === "") {
8424
+ state.isOpen = false;
8425
+ state.selectedIndex = -1;
8426
+ if (props.value) {
8427
+ props.onFilterChange(props.field, "", "eq");
8428
+ props.filterInputValues.value[props.field] = "";
8429
+ }
8430
+ return;
8431
+ }
8432
+ const currentLabel = selectedOption.value;
8433
+ const queryMatchesCurrentValue = currentLabel && searchQuery.value.trim().toLowerCase() === currentLabel.toLowerCase();
8434
+ if (queryMatchesCurrentValue) {
8435
+ state.isOpen = false;
8436
+ state.selectedIndex = -1;
8437
+ return;
8438
+ }
8439
+ if (isInvalidValue.value) {
8440
+ state.isOpen = false;
8441
+ state.selectedIndex = -1;
8442
+ const currentLabel2 = selectedOption.value;
8443
+ if (currentLabel2) {
8444
+ props.filterInputValues.value[props.field] = currentLabel2;
8445
+ } else {
8446
+ props.filterInputValues.value[props.field] = "";
8447
+ }
8448
+ return;
8449
+ }
8450
+ if (isNewValue.value && state.selectedIndex < 0 && props.allowCreate) {
8451
+ handleSelectNewValue();
8452
+ return;
8453
+ }
8454
+ const matchingOption = props.options.find(
8455
+ (opt) => opt.label.toLowerCase() === searchQuery.value.trim().toLowerCase()
8456
+ );
8457
+ if (matchingOption) {
8458
+ handleSelectOption(matchingOption);
8459
+ return;
8460
+ }
8461
+ state.isOpen = false;
8462
+ state.selectedIndex = -1;
8463
+ return;
8464
+ }
8465
+ if (e.key === "ArrowDown") {
8466
+ e.preventDefault();
8467
+ e.stopPropagation();
8468
+ state.isOpen = true;
8469
+ const totalOptions = filteredOptions.value.length + (isNewValue.value && props.allowCreate ? 1 : 0);
8470
+ if (totalOptions > 0) {
8471
+ const currentIndex = state.selectedIndex;
8472
+ const newIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % totalOptions;
8473
+ state.selectedIndex = newIndex;
8474
+ nextTick(() => {
8475
+ scrollToSelectedOption(newIndex);
8476
+ });
8477
+ }
8478
+ return;
8479
+ }
8480
+ if (e.key === "ArrowUp") {
8481
+ e.preventDefault();
8482
+ e.stopPropagation();
8483
+ state.isOpen = true;
8484
+ const totalOptions = filteredOptions.value.length + (isNewValue.value && props.allowCreate ? 1 : 0);
8485
+ if (totalOptions > 0) {
8486
+ const currentIndex = state.selectedIndex;
8487
+ const newIndex = currentIndex < 0 ? totalOptions - 1 : (currentIndex - 1 + totalOptions) % totalOptions;
8488
+ state.selectedIndex = newIndex;
8489
+ nextTick(() => {
8490
+ scrollToSelectedOption(newIndex);
8491
+ });
8492
+ }
8493
+ return;
8494
+ }
8495
+ };
8496
+ const handleFocus = () => {
8497
+ state.isOpen = true;
8498
+ };
8499
+ const scrollToSelectedOption = (index) => {
8500
+ const container = document.querySelector(`[data-combobox-dropdown="${props.field}"]`);
8501
+ if (!container) return;
8502
+ const optionId = index === filteredOptions.value.length ? "option-new" : `option-${index}`;
8503
+ const selectedElement = container.querySelector(`#${optionId}`);
8504
+ if (!selectedElement) return;
8505
+ const elementTop = selectedElement.offsetTop;
8506
+ const elementHeight = selectedElement.offsetHeight;
8507
+ const containerHeight = container.clientHeight;
8508
+ const containerScrollTop = container.scrollTop;
8509
+ if (elementTop < containerScrollTop) {
8510
+ container.scrollTop = elementTop;
8511
+ } else if (elementTop + elementHeight > containerScrollTop + containerHeight) {
8512
+ container.scrollTop = elementTop + elementHeight - containerHeight;
8513
+ }
8514
+ };
8515
+ const handleBlur = (e) => {
8516
+ const relatedTarget = e.relatedTarget || document.activeElement;
8517
+ const container = document.querySelector(`[data-combobox-container="${props.field}"]`);
8518
+ if (container && container.contains(relatedTarget)) {
8519
+ return;
8520
+ }
8521
+ state.isOpen = false;
8522
+ const currentQuery = searchQuery.value.trim();
8523
+ const currentValue = props.value;
8524
+ const currentLabel = selectedOption.value;
8525
+ if (currentQuery === "") {
8526
+ if (currentValue) {
8527
+ props.onFilterChange(props.field, "", "eq");
8528
+ props.filterInputValues.value[props.field] = "";
8529
+ }
8530
+ } else {
8531
+ const queryMatchesCurrentValue = currentLabel && currentQuery.toLowerCase() === currentLabel.toLowerCase();
8532
+ if (isInvalidValue.value) {
8533
+ if (currentLabel) {
8534
+ props.filterInputValues.value[props.field] = currentLabel;
8535
+ } else {
8536
+ props.filterInputValues.value[props.field] = "";
8537
+ }
8538
+ return;
8539
+ }
8540
+ if (!queryMatchesCurrentValue) {
8541
+ const matchingOption = props.options.find((opt) => opt.label.toLowerCase() === currentQuery.toLowerCase());
8542
+ if (matchingOption) {
8543
+ props.onFilterChange(props.field, matchingOption.value, "eq");
8544
+ } else if (props.allowCreate) {
8545
+ props.onFilterChange(props.field, currentQuery, "eq");
8546
+ } else {
8547
+ if (currentLabel) {
8548
+ props.filterInputValues.value[props.field] = currentLabel;
8549
+ }
8550
+ }
8551
+ } else {
8552
+ if (currentLabel && currentQuery !== currentLabel) {
8553
+ props.filterInputValues.value[props.field] = currentLabel;
8554
+ }
8555
+ }
8556
+ }
8557
+ };
8558
+ return /* @__PURE__ */ jsxs("div", { class: "relative w-full", "data-combobox-container": props.field, children: [
8559
+ /* @__PURE__ */ jsx(
8560
+ "input",
8561
+ {
8562
+ type: "text",
8563
+ value: searchQuery.value,
8564
+ onInput: handleInput,
8565
+ onKeydown: handleKeyDown,
8566
+ onFocus: handleFocus,
8567
+ onBlur: handleBlur,
8568
+ placeholder: props.isOptionsLoading ? "Loading options..." : `Search ${props.label}`,
8569
+ class: "input input-bordered input-sm w-full",
8570
+ disabled: props.isLoading || props.isOptionsLoading,
8571
+ "data-testid": `datatable-filter-${props.field}-input`
8572
+ }
8573
+ ),
8574
+ /* @__PURE__ */ jsx("div", { class: "absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none", children: /* @__PURE__ */ jsx(
8575
+ "svg",
8576
+ {
8577
+ xmlns: "http://www.w3.org/2000/svg",
8578
+ class: "h-4 w-4 text-base-content/50",
8579
+ fill: "none",
8580
+ viewBox: "0 0 24 24",
8581
+ stroke: "currentColor",
8582
+ "stroke-width": "2",
8583
+ children: /* @__PURE__ */ jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M8 9l4-4 4 4m0 6l-4 4-4-4" })
8584
+ }
8585
+ ) }),
8586
+ state.isOpen && /* @__PURE__ */ jsx(
8587
+ "div",
8588
+ {
8589
+ "data-combobox-dropdown": props.field,
8590
+ class: "absolute z-50 mt-1 bg-base-100 border border-base-300 rounded-box shadow-lg max-h-60 overflow-auto w-full",
8591
+ children: /* @__PURE__ */ jsx("ul", { class: "menu w-full", role: "listbox", id: `combobox-listbox-${props.field}`, children: props.isOptionsLoading ? /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("span", { class: "text-sm text-base-content/70 p-2", children: "Loading options..." }) }) : filteredOptions.value.length === 0 && !isNewValue.value && !isInvalidValue.value ? /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("span", { class: "text-sm text-base-content/70 p-2", children: "No options available" }) }) : isInvalidValue.value ? /* @__PURE__ */ jsx("li", { class: "bg-error/10 border-l-4 border-error", children: /* @__PURE__ */ jsx("div", { class: "p-2", children: /* @__PURE__ */ jsxs("div", { class: "flex items-center gap-2", children: [
8592
+ /* @__PURE__ */ jsx(
8593
+ "svg",
8594
+ {
8595
+ xmlns: "http://www.w3.org/2000/svg",
8596
+ class: "h-4 w-4 text-error flex-shrink-0",
8597
+ fill: "none",
8598
+ viewBox: "0 0 24 24",
8599
+ stroke: "currentColor",
8600
+ "stroke-width": "2",
8601
+ children: /* @__PURE__ */ jsx(
8602
+ "path",
8603
+ {
8604
+ "stroke-linecap": "round",
8605
+ "stroke-linejoin": "round",
8606
+ d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
8607
+ }
8608
+ )
8609
+ }
8610
+ ),
8611
+ /* @__PURE__ */ jsxs("div", { class: "text-sm", children: [
8612
+ /* @__PURE__ */ jsx("p", { class: "font-medium text-error", children: "Invalid value" }),
8613
+ /* @__PURE__ */ jsxs("p", { class: "text-error/80", children: [
8614
+ '"',
8615
+ searchQuery.value,
8616
+ '" is not a valid option. Please select from the list.'
8617
+ ] })
8618
+ ] })
8619
+ ] }) }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
8620
+ filteredOptions.value.map((option, index) => /* @__PURE__ */ jsx(
8621
+ "li",
8622
+ {
8623
+ id: `option-${index}`,
8624
+ role: "option",
8625
+ "aria-selected": index === state.selectedIndex,
8626
+ class: index === state.selectedIndex ? "bg-base-200" : "",
8627
+ children: /* @__PURE__ */ jsx(
8628
+ "a",
8629
+ {
8630
+ href: "#",
8631
+ tabindex: 0,
8632
+ onClick: (e) => {
8633
+ e.preventDefault();
8634
+ e.stopPropagation();
8635
+ handleSelectOption(option);
8636
+ },
8637
+ onMousedown: (e) => {
8638
+ e.preventDefault();
8639
+ },
8640
+ class: "w-full",
8641
+ children: option.label
8642
+ }
8643
+ )
8644
+ },
8645
+ option.value
8646
+ )),
8647
+ isNewValue.value && props.allowCreate && /* @__PURE__ */ jsx(
8648
+ "li",
8649
+ {
8650
+ id: "option-new",
8651
+ role: "option",
8652
+ "aria-selected": state.selectedIndex === filteredOptions.value.length,
8653
+ class: state.selectedIndex === filteredOptions.value.length ? "bg-base-200" : "",
8654
+ children: /* @__PURE__ */ jsx(
8655
+ "a",
8656
+ {
8657
+ href: "#",
8658
+ tabindex: 0,
8659
+ onClick: (e) => {
8660
+ e.preventDefault();
8661
+ e.stopPropagation();
8662
+ handleSelectNewValue();
8663
+ },
8664
+ onMousedown: (e) => {
8665
+ e.preventDefault();
8666
+ },
8667
+ class: "w-full",
8668
+ children: /* @__PURE__ */ jsxs("div", { class: "flex items-center gap-2", children: [
8669
+ /* @__PURE__ */ jsx(
8670
+ "svg",
8671
+ {
8672
+ xmlns: "http://www.w3.org/2000/svg",
8673
+ class: "h-4 w-4 text-success",
8674
+ fill: "none",
8675
+ viewBox: "0 0 24 24",
8676
+ stroke: "currentColor",
8677
+ "stroke-width": "2",
8678
+ children: /* @__PURE__ */ jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M12 4v16m8-8H4" })
8679
+ }
8680
+ ),
8681
+ /* @__PURE__ */ jsxs("span", { class: "text-sm", children: [
8682
+ /* @__PURE__ */ jsx("span", { class: "font-medium text-success", children: "New value:" }),
8683
+ ' "',
8684
+ searchQuery.value,
8685
+ '"'
8686
+ ] })
8687
+ ] })
8688
+ }
8689
+ )
8690
+ }
8691
+ )
8692
+ ] }) })
8693
+ }
8694
+ )
8695
+ ] });
8696
+ };
8245
8697
  var FilterDrawer = (props) => {
8246
8698
  const injectedFilterOptionsState = inject(
8247
8699
  ZINIA_DATA_TABLE_FILTER_OPTIONS_STATE_KEY,
@@ -8270,8 +8722,7 @@ var FilterDrawer = (props) => {
8270
8722
  /* @__PURE__ */ jsxs(
8271
8723
  "aside",
8272
8724
  {
8273
- class: "absolute top-0 left-0 h-full w-full md:w-80 bg-base-100 flex flex-col shadow-xl transform transition-transform duration-300 ease-out translate-x-0 pointer-events-auto",
8274
- style: { maxHeight: "100%" },
8725
+ class: "absolute top-0 left-0 h-full h-[600px] max-h-[90vh] w-full md:w-80 bg-base-100 flex flex-col shadow-xl transform transition-transform duration-300 ease-out translate-x-0 pointer-events-auto",
8275
8726
  onClick: (e) => e.stopPropagation(),
8276
8727
  "data-testid": `${props.tableName || "datatable"}-filter-drawer`,
8277
8728
  children: [
@@ -8388,6 +8839,25 @@ var FilterDrawer = (props) => {
8388
8839
  isLoading: props.isLoading,
8389
8840
  onFilterChange: props.onFilterChange
8390
8841
  }
8842
+ ),
8843
+ filterType === "combobox" && /* @__PURE__ */ jsx(
8844
+ ComboboxFilter,
8845
+ {
8846
+ field,
8847
+ value: currentValue,
8848
+ options: getFilterOptions(
8849
+ field,
8850
+ column,
8851
+ props.fieldsMetadata,
8852
+ filterOptionsState?.value || {}
8853
+ ),
8854
+ label: column.label,
8855
+ isLoading: props.isLoading,
8856
+ isOptionsLoading: filterOptionsLoading?.value?.[field] ?? false,
8857
+ allowCreate: column.filterAllowCreate ?? false,
8858
+ filterInputValues: props.filterInputValues,
8859
+ onFilterChange: props.onFilterChange
8860
+ }
8391
8861
  )
8392
8862
  ]
8393
8863
  },
@@ -9014,6 +9484,27 @@ function createDaisyUIDataTable() {
9014
9484
  });
9015
9485
  const selectionMode = computed(() => options.selection?.mode ?? "none");
9016
9486
  const hasSelection = computed(() => selectionMode.value !== "none");
9487
+ const containerHeightClasses = computed(() => {
9488
+ const height = props.height ?? "auto";
9489
+ if (height === "fixed") {
9490
+ return "relative h-[850px] max-h-[90vh] flex flex-col";
9491
+ } else if (height === "auto") {
9492
+ return "relative flex-1 min-h-[670px] flex flex-col";
9493
+ } else if (typeof height === "number") {
9494
+ return `relative flex flex-col`;
9495
+ } else {
9496
+ return "relative flex flex-col";
9497
+ }
9498
+ });
9499
+ const containerHeightStyle = computed(() => {
9500
+ const height = props.height;
9501
+ if (typeof height === "number") {
9502
+ return { height: `${height}px` };
9503
+ } else if (typeof height === "string" && height !== "auto" && height !== "fixed") {
9504
+ return { height };
9505
+ }
9506
+ return {};
9507
+ });
9017
9508
  if (filterInputValues && Object.keys(filterInputValues.value).length === 0) {
9018
9509
  Object.entries(columns).forEach(([field, column]) => {
9019
9510
  if (column?.filterable) {
@@ -9065,7 +9556,7 @@ function createDaisyUIDataTable() {
9065
9556
  triggerBulkAction: table.triggerBulkAction
9066
9557
  }
9067
9558
  ),
9068
- /* @__PURE__ */ jsxs("div", { class: "relative h-[600px] max-h-[90vh] flex flex-col", children: [
9559
+ /* @__PURE__ */ jsxs("div", { class: containerHeightClasses.value, style: containerHeightStyle.value, children: [
9069
9560
  Object.values(columns).some((col) => col?.filterable) && filterInputValues && filterOperators && /* @__PURE__ */ jsx(
9070
9561
  FiltersRow,
9071
9562
  {
@@ -9086,7 +9577,7 @@ function createDaisyUIDataTable() {
9086
9577
  onCloseFilterDrawer: () => table.ui.closeFilterDrawer()
9087
9578
  }
9088
9579
  ),
9089
- /* @__PURE__ */ jsx("div", { class: "w-full overflow-auto", style: { maxHeight: "calc(100% - 80px)" }, children: table.isLoading ? /* @__PURE__ */ jsx(
9580
+ /* @__PURE__ */ jsx("div", { class: "w-full flex-1 min-h-0 overflow-auto", children: table.isLoading ? /* @__PURE__ */ jsx(
9090
9581
  LoadingSkeletons,
9091
9582
  {
9092
9583
  pageSize: table.pagination.pageSize,
@@ -9206,7 +9697,7 @@ function createDaisyUIDataTable() {
9206
9697
  ] })
9207
9698
  ] });
9208
9699
  };
9209
- DaisyUIDataTable.props = ["class"];
9700
+ DaisyUIDataTable.props = ["class", "name", "height"];
9210
9701
  return DaisyUIDataTable;
9211
9702
  }
9212
9703