@dragonmastery/zinia-forms-core 0.4.4 → 0.4.7

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
@@ -8423,14 +8423,50 @@ var BooleanFilter = (props) => {
8423
8423
  );
8424
8424
  };
8425
8425
  var comboboxState = reactive({});
8426
+ var DROPDOWN_MAX_HEIGHT = 240;
8427
+ var MIN_SPACE_BELOW = 100;
8426
8428
  var ComboboxFilter = (props) => {
8427
8429
  if (!comboboxState[props.field]) {
8428
8430
  comboboxState[props.field] = {
8429
8431
  isOpen: false,
8430
- selectedIndex: -1
8432
+ selectedIndex: -1,
8433
+ position: { top: 0, left: 0, width: 0, openUpward: false }
8431
8434
  };
8432
8435
  }
8433
8436
  const state = comboboxState[props.field];
8437
+ const updateDropdownPosition = () => {
8438
+ const input = document.querySelector(`[data-combobox-input="${props.field}"]`);
8439
+ if (!input) return;
8440
+ const rect = input.getBoundingClientRect();
8441
+ const spaceBelow = window.innerHeight - rect.bottom;
8442
+ const spaceAbove = rect.top;
8443
+ const openUpward = spaceBelow < MIN_SPACE_BELOW && spaceAbove > spaceBelow;
8444
+ state.position = {
8445
+ top: openUpward ? rect.top - 4 : rect.bottom + 4,
8446
+ // 4px gap
8447
+ left: rect.left,
8448
+ width: rect.width,
8449
+ openUpward
8450
+ };
8451
+ };
8452
+ const handleScrollOrResize = () => {
8453
+ if (state.isOpen) {
8454
+ updateDropdownPosition();
8455
+ }
8456
+ };
8457
+ let cleanupFns = [];
8458
+ const setupEventListeners = () => {
8459
+ window.addEventListener("scroll", handleScrollOrResize, true);
8460
+ window.addEventListener("resize", handleScrollOrResize);
8461
+ cleanupFns.push(() => {
8462
+ window.removeEventListener("scroll", handleScrollOrResize, true);
8463
+ window.removeEventListener("resize", handleScrollOrResize);
8464
+ });
8465
+ };
8466
+ const cleanupEventListeners = () => {
8467
+ cleanupFns.forEach((fn) => fn());
8468
+ cleanupFns = [];
8469
+ };
8434
8470
  const searchQuery = computed(() => props.filterInputValues.value[props.field] || "");
8435
8471
  const selectedOption = computed(() => {
8436
8472
  if (!props.value) return "";
@@ -8465,6 +8501,7 @@ var ComboboxFilter = (props) => {
8465
8501
  props.filterInputValues.value[props.field] = value;
8466
8502
  state.isOpen = true;
8467
8503
  state.selectedIndex = -1;
8504
+ updateDropdownPosition();
8468
8505
  };
8469
8506
  const handleSelectOption = (option) => {
8470
8507
  props.filterInputValues.value[props.field] = option.label;
@@ -8549,7 +8586,10 @@ var ComboboxFilter = (props) => {
8549
8586
  if (e.key === "ArrowDown") {
8550
8587
  e.preventDefault();
8551
8588
  e.stopPropagation();
8552
- state.isOpen = true;
8589
+ if (!state.isOpen) {
8590
+ state.isOpen = true;
8591
+ updateDropdownPosition();
8592
+ }
8553
8593
  const totalOptions = filteredOptions.value.length + (isNewValue.value && props.allowCreate ? 1 : 0);
8554
8594
  if (totalOptions > 0) {
8555
8595
  const currentIndex = state.selectedIndex;
@@ -8564,7 +8604,10 @@ var ComboboxFilter = (props) => {
8564
8604
  if (e.key === "ArrowUp") {
8565
8605
  e.preventDefault();
8566
8606
  e.stopPropagation();
8567
- state.isOpen = true;
8607
+ if (!state.isOpen) {
8608
+ state.isOpen = true;
8609
+ updateDropdownPosition();
8610
+ }
8568
8611
  const totalOptions = filteredOptions.value.length + (isNewValue.value && props.allowCreate ? 1 : 0);
8569
8612
  if (totalOptions > 0) {
8570
8613
  const currentIndex = state.selectedIndex;
@@ -8579,6 +8622,8 @@ var ComboboxFilter = (props) => {
8579
8622
  };
8580
8623
  const handleFocus = () => {
8581
8624
  state.isOpen = true;
8625
+ updateDropdownPosition();
8626
+ setupEventListeners();
8582
8627
  };
8583
8628
  const scrollToSelectedOption = (index) => {
8584
8629
  const container = document.querySelector(`[data-combobox-dropdown="${props.field}"]`);
@@ -8599,10 +8644,12 @@ var ComboboxFilter = (props) => {
8599
8644
  const handleBlur = (e) => {
8600
8645
  const relatedTarget = e.relatedTarget || document.activeElement;
8601
8646
  const container = document.querySelector(`[data-combobox-container="${props.field}"]`);
8602
- if (container && container.contains(relatedTarget)) {
8647
+ const dropdown = document.querySelector(`[data-combobox-dropdown="${props.field}"]`);
8648
+ if (container && container.contains(relatedTarget) || dropdown && dropdown.contains(relatedTarget)) {
8603
8649
  return;
8604
8650
  }
8605
8651
  state.isOpen = false;
8652
+ cleanupEventListeners();
8606
8653
  const currentQuery = searchQuery.value.trim();
8607
8654
  const currentValue = props.value;
8608
8655
  const currentLabel = selectedOption.value;
@@ -8639,6 +8686,18 @@ var ComboboxFilter = (props) => {
8639
8686
  }
8640
8687
  }
8641
8688
  };
8689
+ const dropdownStyle = computed(() => {
8690
+ const pos = state.position;
8691
+ return {
8692
+ position: "fixed",
8693
+ top: pos.openUpward ? "auto" : `${pos.top}px`,
8694
+ bottom: pos.openUpward ? `${window.innerHeight - pos.top}px` : "auto",
8695
+ left: `${pos.left}px`,
8696
+ width: `${pos.width}px`,
8697
+ maxHeight: `${DROPDOWN_MAX_HEIGHT}px`,
8698
+ zIndex: 9999
8699
+ };
8700
+ });
8642
8701
  return /* @__PURE__ */ jsxs("div", { class: "relative w-full", "data-combobox-container": props.field, children: [
8643
8702
  /* @__PURE__ */ jsx(
8644
8703
  "input",
@@ -8652,7 +8711,8 @@ var ComboboxFilter = (props) => {
8652
8711
  placeholder: props.isOptionsLoading ? "Loading options..." : `Search ${props.label}`,
8653
8712
  class: "input input-bordered input-sm w-full",
8654
8713
  disabled: props.isLoading || props.isOptionsLoading,
8655
- "data-testid": `datatable-filter-${props.field}-input`
8714
+ "data-testid": `datatable-filter-${props.field}-input`,
8715
+ "data-combobox-input": props.field
8656
8716
  }
8657
8717
  ),
8658
8718
  /* @__PURE__ */ jsx("div", { class: "absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none", children: /* @__PURE__ */ jsx(
@@ -8667,11 +8727,15 @@ var ComboboxFilter = (props) => {
8667
8727
  children: /* @__PURE__ */ jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M8 9l4-4 4 4m0 6l-4 4-4-4" })
8668
8728
  }
8669
8729
  ) }),
8670
- state.isOpen && /* @__PURE__ */ jsx(
8730
+ state.isOpen && /* @__PURE__ */ jsx(Teleport, { to: "body", children: /* @__PURE__ */ jsx(
8671
8731
  "div",
8672
8732
  {
8673
8733
  "data-combobox-dropdown": props.field,
8674
- class: "absolute z-50 mt-1 bg-base-100 border border-base-300 rounded-box shadow-lg max-h-60 overflow-auto w-full",
8734
+ class: "bg-base-100 border border-base-300 rounded-box shadow-lg overflow-auto",
8735
+ style: dropdownStyle.value,
8736
+ onMousedown: (e) => {
8737
+ e.preventDefault();
8738
+ },
8675
8739
  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: [
8676
8740
  /* @__PURE__ */ jsx(
8677
8741
  "svg",
@@ -8775,7 +8839,7 @@ var ComboboxFilter = (props) => {
8775
8839
  )
8776
8840
  ] }) })
8777
8841
  }
8778
- )
8842
+ ) })
8779
8843
  ] });
8780
8844
  };
8781
8845
  var FilterDrawer = (props) => {
@@ -9332,7 +9396,8 @@ var MobileCards = (props) => {
9332
9396
  if (!column) return null;
9333
9397
  const value = row[field];
9334
9398
  const formattedValue = formatCellValue(value, field, row, column);
9335
- if (!value && value !== 0 && value !== false) return null;
9399
+ const hasCustomSlot = !!props.slots[`cell-${field}`];
9400
+ if (!hasCustomSlot && !value && value !== 0 && value !== false) return null;
9336
9401
  return /* @__PURE__ */ jsxs("div", { class: "flex justify-between items-center", children: [
9337
9402
  /* @__PURE__ */ jsxs("span", { class: "text-sm font-medium text-base-content/70 min-w-0 flex-shrink-0 mr-2", children: [
9338
9403
  column.label,