warqadui 0.0.19 → 0.0.21

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
@@ -57,7 +57,14 @@ __export(index_exports, {
57
57
  PhoneInput: () => PhoneInput,
58
58
  PostTable: () => PostTable,
59
59
  SearchApi: () => SearchApi,
60
+ SearchApiContent: () => SearchApiContent,
61
+ SearchApiInput: () => SearchApiInput,
62
+ SearchApiItem: () => SearchApiItem,
63
+ SearchApiTrigger: () => SearchApiTrigger,
60
64
  Select: () => Select,
65
+ SelectContent: () => SelectContent,
66
+ SelectItem: () => SelectItem,
67
+ SelectTrigger: () => SelectTrigger,
61
68
  SimpleTable: () => SimpleTable,
62
69
  Textarea: () => Textarea,
63
70
  ThemeProvider: () => ThemeProvider,
@@ -67,6 +74,8 @@ __export(index_exports, {
67
74
  useA4StatementView: () => useA4DataView_default,
68
75
  useApi: () => useApis_default,
69
76
  useModal: () => useModal,
77
+ useSearchApiContext: () => useSearchApiContext,
78
+ useSelectContext: () => useSelectContext,
70
79
  useTheme: () => useTheme,
71
80
  useTransaction: () => useTransaction_default,
72
81
  useWarqadConfig: () => useWarqadConfig
@@ -1147,7 +1156,7 @@ var Input = (0, import_react8.forwardRef)(
1147
1156
  const renderInput = (inputProps, localType = type || "text") => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1148
1157
  "div",
1149
1158
  {
1150
- className: `${label ? "space-y-2" : ""} group ${containerClassName} `,
1159
+ className: `${label ? "space-y-2" : ""} group relative ${containerClassName} `,
1151
1160
  children: [
1152
1161
  label && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
1153
1162
  "label",
@@ -1203,7 +1212,7 @@ var Input = (0, import_react8.forwardRef)(
1203
1212
  }
1204
1213
  )
1205
1214
  ] }),
1206
- message && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
1215
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
1207
1216
  ]
1208
1217
  }
1209
1218
  );
@@ -1307,7 +1316,7 @@ var PhoneInput = (0, import_react9.forwardRef)(
1307
1316
  }
1308
1317
  message = currentError?.message || message;
1309
1318
  }
1310
- const renderInput = (onChangeHandler, currentValue) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: `space-y-2 group ${containerClassName}`, children: [
1319
+ const renderInput = (onChangeHandler, currentValue) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: `space-y-2 group relative ${containerClassName}`, children: [
1311
1320
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1312
1321
  "label",
1313
1322
  {
@@ -1350,7 +1359,7 @@ var PhoneInput = (0, import_react9.forwardRef)(
1350
1359
  }
1351
1360
  )
1352
1361
  ] }),
1353
- message && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
1362
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
1354
1363
  ] });
1355
1364
  if (form && name) {
1356
1365
  return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
@@ -1372,65 +1381,113 @@ var PhoneInput = (0, import_react9.forwardRef)(
1372
1381
  PhoneInput.displayName = "PhoneInput";
1373
1382
 
1374
1383
  // src/components/Fields/select.tsx
1375
- var import_react10 = require("react");
1384
+ var import_react10 = __toESM(require("react"));
1376
1385
  var import_react_dom = require("react-dom");
1377
1386
  var import_lucide_react7 = require("lucide-react");
1378
1387
  var import_react_hook_form3 = require("react-hook-form");
1379
1388
  var import_jsx_runtime18 = require("react/jsx-runtime");
1380
- var SelectContent = ({
1381
- label,
1382
- options,
1383
- icon,
1389
+ var SelectContext = (0, import_react10.createContext)(void 0);
1390
+ var useSelectContext = () => {
1391
+ const context = (0, import_react10.useContext)(SelectContext);
1392
+ if (!context)
1393
+ throw new Error("Select components must be used within a SelectProvider");
1394
+ return context;
1395
+ };
1396
+ var Select = (0, import_react10.forwardRef)((props, ref) => {
1397
+ const { form, name, onChange, value, children, options = [] } = props;
1398
+ if (form && name) {
1399
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1400
+ import_react_hook_form3.Controller,
1401
+ {
1402
+ name,
1403
+ control: form.control,
1404
+ render: ({
1405
+ field: {
1406
+ onChange: formOnChange,
1407
+ value: formValue,
1408
+ ref: fieldRef,
1409
+ onBlur
1410
+ }
1411
+ }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1412
+ SelectRoot,
1413
+ {
1414
+ ...props,
1415
+ options,
1416
+ currentValue: formValue,
1417
+ onChangeHandler: (val) => {
1418
+ formOnChange(val);
1419
+ onChange?.(val);
1420
+ },
1421
+ fieldInternalProps: { ref: fieldRef, onBlur },
1422
+ children
1423
+ }
1424
+ )
1425
+ }
1426
+ );
1427
+ }
1428
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1429
+ SelectRoot,
1430
+ {
1431
+ ...props,
1432
+ options,
1433
+ currentValue: value,
1434
+ onChangeHandler: onChange || (() => {
1435
+ }),
1436
+ children
1437
+ }
1438
+ );
1439
+ });
1440
+ Select.displayName = "Select";
1441
+ var SelectRoot = ({
1442
+ children,
1443
+ currentValue,
1444
+ onChangeHandler,
1445
+ form,
1446
+ name,
1384
1447
  error,
1448
+ options: initialOptions,
1449
+ fieldInternalProps,
1450
+ label,
1385
1451
  containerClassName = "",
1386
- name,
1387
- form,
1388
- onChangeHandler,
1389
- currentValue,
1390
- onFocus,
1391
- onBlur,
1392
- className = "",
1393
1452
  variant = "default",
1394
- fieldInternalProps,
1453
+ icon,
1454
+ placeholder = "Select...",
1455
+ required,
1456
+ disabled,
1457
+ id,
1458
+ className = "",
1395
1459
  ...props
1396
1460
  }) => {
1397
1461
  const [isOpen, setIsOpen] = (0, import_react10.useState)(false);
1398
1462
  const [isFocused, setIsFocused] = (0, import_react10.useState)(false);
1399
- const [dropdownStyle, setDropdownStyle] = (0, import_react10.useState)({});
1463
+ const [activeIndex, setActiveIndex] = (0, import_react10.useState)(-1);
1464
+ const [registeredOptions, setRegisteredOptions] = (0, import_react10.useState)([]);
1400
1465
  const { theme } = useWarqadConfig();
1401
1466
  const primaryColor = theme?.primaryColor;
1402
1467
  const containerRef = (0, import_react10.useRef)(null);
1403
1468
  const dropdownAnchorRef = (0, import_react10.useRef)(null);
1404
1469
  const dropdownContentRef = (0, import_react10.useRef)(null);
1405
- const lastFocusTime = (0, import_react10.useRef)(0);
1406
- const updateDropdownPosition = () => {
1407
- if (dropdownAnchorRef.current) {
1408
- const rect = dropdownAnchorRef.current.getBoundingClientRect();
1409
- const style = {
1410
- position: "fixed",
1411
- top: `${rect.bottom + 4}px`,
1412
- left: `${rect.left}px`,
1413
- width: `${rect.width}px`,
1414
- zIndex: 999999
1415
- };
1416
- if (rect.bottom + 240 > window.innerHeight) {
1417
- style.top = "auto";
1418
- style.bottom = `${window.innerHeight - rect.top + 4}px`;
1470
+ const registerOption = (opt) => {
1471
+ setRegisteredOptions((prev) => {
1472
+ const index = prev.findIndex((p) => p.value === opt.value);
1473
+ if (index >= 0) {
1474
+ if (prev[index].label !== opt.label || prev[index].disabled !== opt.disabled) {
1475
+ const newOpts = [...prev];
1476
+ newOpts[index] = opt;
1477
+ return newOpts;
1478
+ }
1479
+ return prev;
1419
1480
  }
1420
- setDropdownStyle(style);
1421
- }
1481
+ return [...prev, opt];
1482
+ });
1422
1483
  };
1423
- (0, import_react10.useEffect)(() => {
1424
- if (isOpen) {
1425
- updateDropdownPosition();
1426
- window.addEventListener("scroll", updateDropdownPosition, true);
1427
- window.addEventListener("resize", updateDropdownPosition);
1428
- return () => {
1429
- window.removeEventListener("scroll", updateDropdownPosition, true);
1430
- window.removeEventListener("resize", updateDropdownPosition);
1431
- };
1484
+ const setSelectedValue = (val) => {
1485
+ onChangeHandler(val);
1486
+ if (form && name) {
1487
+ form.setValue(name, val, { shouldValidate: true, shouldDirty: true });
1488
+ form.clearErrors(name);
1432
1489
  }
1433
- }, [isOpen]);
1490
+ };
1434
1491
  (0, import_react10.useEffect)(() => {
1435
1492
  const handleClickOutside = (event) => {
1436
1493
  const target = event.target;
@@ -1443,20 +1500,6 @@ var SelectContent = ({
1443
1500
  document.addEventListener("mousedown", handleClickOutside);
1444
1501
  return () => document.removeEventListener("mousedown", handleClickOutside);
1445
1502
  }, [fieldInternalProps]);
1446
- const handleSelect = (option) => {
1447
- if (option.disabled) return;
1448
- onChangeHandler(option.value);
1449
- if (form && name) {
1450
- form.setValue(name, option.value, {
1451
- shouldValidate: true,
1452
- shouldDirty: true
1453
- });
1454
- form.clearErrors(name);
1455
- }
1456
- setIsOpen(false);
1457
- fieldInternalProps?.onBlur?.();
1458
- };
1459
- const displayValue = options.find((o) => o.value === currentValue)?.label || "Select...";
1460
1503
  let message = error;
1461
1504
  if (form && name) {
1462
1505
  const {
@@ -1469,11 +1512,31 @@ var SelectContent = ({
1469
1512
  }
1470
1513
  message = currentError?.message || message;
1471
1514
  }
1472
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1515
+ const allOptions = initialOptions?.length ? initialOptions : registeredOptions;
1516
+ const valueCtx = {
1517
+ isOpen,
1518
+ setIsOpen,
1519
+ selectedValue: currentValue,
1520
+ setSelectedValue,
1521
+ activeIndex,
1522
+ setActiveIndex,
1523
+ isFocused,
1524
+ setIsFocused,
1525
+ dropdownAnchorRef,
1526
+ dropdownContentRef,
1527
+ containerRef,
1528
+ primaryColor,
1529
+ options: allOptions,
1530
+ registerOption,
1531
+ fieldInternalProps,
1532
+ disabled
1533
+ };
1534
+ const hasChildren = import_react10.default.Children.count(children) > 0;
1535
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SelectContext.Provider, { value: valueCtx, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1473
1536
  "div",
1474
1537
  {
1475
1538
  ref: containerRef,
1476
- className: `${label ? "space-y-2" : ""} group ${containerClassName}`,
1539
+ className: `${label ? "space-y-2" : ""} group relative ${containerClassName}`,
1477
1540
  children: [
1478
1541
  label && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1479
1542
  "label",
@@ -1482,172 +1545,246 @@ var SelectContent = ({
1482
1545
  style: { color: isFocused || isOpen ? primaryColor : void 0 },
1483
1546
  children: [
1484
1547
  label,
1485
- props.required && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-red-500 ml-1", children: "*" })
1548
+ required && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-red-500 ml-1", children: "*" })
1486
1549
  ]
1487
1550
  }
1488
1551
  ),
1489
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "relative", ref: dropdownAnchorRef, children: [
1490
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1491
- "div",
1552
+ hasChildren ? children : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
1553
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1554
+ SelectTrigger,
1492
1555
  {
1493
- id: props.id,
1494
- className: `flex items-center w-full select-none text-gray-900 dark:text-white transition-all duration-200 outline-none focus:outline-none focus:ring-0 py-1 ${props.disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"} ${variant === "ghost" ? "bg-transparent border-transparent shadow-none px-0 h-full border-none ring-0 focus:border-none focus:ring-0" : isFocused || isOpen ? "ring-0 border rounded-xl h-9" : "border-gray-200 dark:border-zinc-800 border rounded-xl bg-white dark:bg-zinc-900/50 h-9"} ${className}`,
1495
- style: variant === "default" ? {
1496
- borderColor: isFocused || isOpen ? primaryColor : void 0,
1497
- boxShadow: isFocused || isOpen ? `${primaryColor}33 0px 0px 0px 2px` : void 0,
1498
- backgroundColor: isFocused || isOpen ? "var(--tw-colors-white, white)" : void 0
1499
- } : void 0,
1500
- onClick: () => {
1501
- if (props.disabled) return;
1502
- if (Date.now() - lastFocusTime.current < 150) {
1503
- return;
1504
- }
1505
- setIsOpen(!isOpen);
1506
- setIsFocused(true);
1507
- onFocus?.(null);
1508
- },
1509
- onKeyDown: (e) => {
1510
- if (e.key === "Enter" || e.key === " ") {
1511
- e.preventDefault();
1512
- if (props.disabled) return;
1513
- setIsOpen(!isOpen);
1514
- setIsFocused(true);
1515
- } else if (e.key === "ArrowDown" || e.key === "ArrowUp") {
1516
- e.preventDefault();
1517
- setIsOpen(true);
1518
- }
1519
- },
1520
- onFocus: () => {
1521
- setIsFocused(true);
1522
- setIsOpen(true);
1523
- lastFocusTime.current = Date.now();
1524
- },
1525
- tabIndex: props.disabled ? -1 : 0,
1526
- onBlur: (e) => {
1527
- if (!dropdownContentRef.current?.contains(e.relatedTarget) && !containerRef.current?.contains(e.relatedTarget)) {
1528
- setIsOpen(false);
1529
- setIsFocused(false);
1530
- fieldInternalProps?.onBlur?.();
1531
- onBlur?.(null);
1532
- }
1533
- },
1534
- children: [
1535
- icon && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1536
- "div",
1537
- {
1538
- className: `pl-2.5 pr-2 flex items-center transition-colors duration-200`,
1539
- style: { color: isFocused || isOpen ? primaryColor : "#9ca3af" },
1540
- children: icon
1541
- }
1542
- ),
1543
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1544
- "div",
1545
- {
1546
- className: `flex-1 truncate text-sm ${icon ? "" : "pl-2.5"} ${!currentValue && currentValue !== 0 && currentValue !== false ? "text-gray-400 dark:text-zinc-500" : ""}`,
1547
- children: displayValue
1548
- }
1549
- ),
1550
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "pr-2.5 flex items-center gap-1 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1551
- import_lucide_react7.ChevronDown,
1552
- {
1553
- className: `h-4 w-4 text-gray-400 transition-transform ${isOpen ? "rotate-180" : ""}`
1554
- }
1555
- ) })
1556
- ]
1556
+ id,
1557
+ icon,
1558
+ placeholder,
1559
+ variant,
1560
+ className,
1561
+ ...props
1557
1562
  }
1558
1563
  ),
1559
- isOpen && typeof document !== "undefined" && (0, import_react_dom.createPortal)(
1560
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1561
- "div",
1562
- {
1563
- ref: dropdownContentRef,
1564
- className: "bg-white dark:bg-zinc-950 rounded-xl border border-gray-200 dark:border-zinc-800 shadow-xl max-h-60 overflow-y-auto overflow-x-hidden p-1.5",
1565
- style: dropdownStyle,
1566
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex flex-col gap-0.5", children: [
1567
- options.map((option, index) => {
1568
- const isSelected = currentValue === option.value;
1569
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1570
- "button",
1571
- {
1572
- type: "button",
1573
- disabled: option.disabled,
1574
- className: `w-full text-left px-3 py-2 rounded-md text-sm flex items-center justify-between transition-colors ${option.disabled ? "opacity-50 cursor-not-allowed text-gray-400" : isSelected ? "bg-gray-100 dark:bg-zinc-800 text-gray-900 dark:text-gray-100" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-zinc-800"}`,
1575
- style: isSelected && !option.disabled && primaryColor ? {
1576
- color: primaryColor
1577
- } : void 0,
1578
- onClick: (e) => {
1579
- e.stopPropagation();
1580
- handleSelect(option);
1581
- },
1582
- children: [
1583
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "whitespace-nowrap truncate flex-1", children: option.label }),
1584
- isSelected && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1585
- import_lucide_react7.Check,
1586
- {
1587
- className: "h-4 w-4 shrink-0 ml-2",
1588
- style: { color: primaryColor }
1589
- }
1590
- )
1591
- ]
1592
- },
1593
- String(option.value) || index
1594
- );
1595
- }),
1596
- options.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "p-3 text-center text-sm text-gray-500", children: "No options available" })
1597
- ] })
1598
- }
1599
- ),
1600
- document.body
1601
- )
1564
+ allOptions && allOptions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SelectContent, { children: allOptions.map((opt, index) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1565
+ SelectItem,
1566
+ {
1567
+ value: opt.value,
1568
+ label: opt.label,
1569
+ disabled: opt.disabled
1570
+ },
1571
+ String(opt.value) || index
1572
+ )) })
1602
1573
  ] }),
1603
- message && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
1574
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
1604
1575
  ]
1605
1576
  }
1606
- );
1577
+ ) });
1607
1578
  };
1608
- var Select = (0, import_react10.forwardRef)(
1609
- (props, ref) => {
1610
- const { form, name, onChange, value } = props;
1611
- if (form && name) {
1612
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1613
- import_react_hook_form3.Controller,
1614
- {
1615
- name,
1616
- control: form.control,
1617
- render: ({
1618
- field: {
1619
- onChange: formOnChange,
1620
- value: formValue,
1621
- ref: fieldRef,
1622
- onBlur
1623
- }
1624
- }) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1625
- SelectContent,
1579
+ var SelectTrigger = (0, import_react10.forwardRef)(
1580
+ ({
1581
+ className = "",
1582
+ variant = "default",
1583
+ icon,
1584
+ placeholder = "Select...",
1585
+ id,
1586
+ children,
1587
+ ...props
1588
+ }, ref) => {
1589
+ const {
1590
+ isOpen,
1591
+ setIsOpen,
1592
+ isFocused,
1593
+ setIsFocused,
1594
+ primaryColor,
1595
+ dropdownAnchorRef,
1596
+ dropdownContentRef,
1597
+ containerRef,
1598
+ selectedValue,
1599
+ options,
1600
+ fieldInternalProps,
1601
+ disabled
1602
+ } = useSelectContext();
1603
+ const lastFocusTime = (0, import_react10.useRef)(0);
1604
+ const displayOption = options.find((o) => o.value === selectedValue);
1605
+ const displayValue = displayOption ? displayOption.label : selectedValue != null && selectedValue !== "" ? String(selectedValue) : placeholder;
1606
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "relative", ref: dropdownAnchorRef, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1607
+ "div",
1608
+ {
1609
+ id,
1610
+ className: `flex items-center w-full select-none text-gray-900 dark:text-white transition-all duration-200 outline-none focus:outline-none focus:ring-0 py-1 ${disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"} ${variant === "ghost" ? "bg-transparent border-transparent shadow-none px-0 h-full border-none ring-0 focus:border-none focus:ring-0" : isFocused || isOpen ? "ring-0 border rounded-xl h-9" : "border-gray-200 dark:border-zinc-800 border rounded-xl bg-white dark:bg-zinc-900/50 h-9"} ${className}`,
1611
+ style: variant === "default" ? {
1612
+ borderColor: isFocused || isOpen ? primaryColor : void 0,
1613
+ boxShadow: isFocused || isOpen ? `${primaryColor}33 0px 0px 0px 2px` : void 0,
1614
+ backgroundColor: isFocused || isOpen ? "var(--tw-colors-white, white)" : void 0
1615
+ } : void 0,
1616
+ onMouseDown: (e) => {
1617
+ if (disabled) return;
1618
+ e.preventDefault();
1619
+ },
1620
+ onClick: (e) => {
1621
+ if (disabled) return;
1622
+ if (Date.now() - lastFocusTime.current < 150) return;
1623
+ e.stopPropagation();
1624
+ setIsOpen(!isOpen);
1625
+ setIsFocused(true);
1626
+ },
1627
+ onKeyDown: (e) => {
1628
+ if (e.key === "Enter" || e.key === " ") {
1629
+ e.preventDefault();
1630
+ e.stopPropagation();
1631
+ if (disabled) return;
1632
+ setIsOpen(!isOpen);
1633
+ setIsFocused(true);
1634
+ } else if (e.key === "ArrowDown" || e.key === "ArrowUp") {
1635
+ e.preventDefault();
1636
+ e.stopPropagation();
1637
+ setIsOpen(true);
1638
+ } else if (e.key === "Escape") {
1639
+ setIsOpen(false);
1640
+ }
1641
+ },
1642
+ onFocus: () => {
1643
+ setIsFocused(true);
1644
+ lastFocusTime.current = Date.now();
1645
+ },
1646
+ tabIndex: disabled ? -1 : 0,
1647
+ onBlur: (e) => {
1648
+ if (!dropdownContentRef.current?.contains(e.relatedTarget) && !containerRef.current?.contains(e.relatedTarget)) {
1649
+ setIsFocused(false);
1650
+ setIsOpen(false);
1651
+ fieldInternalProps?.onBlur?.();
1652
+ }
1653
+ },
1654
+ ...props,
1655
+ children: children ? children : /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
1656
+ icon && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1657
+ "div",
1626
1658
  {
1627
- ...props,
1628
- currentValue: formValue,
1629
- onChangeHandler: (val) => {
1630
- formOnChange(val);
1631
- onChange?.(val);
1659
+ className: `pl-2.5 pr-2 flex items-center transition-colors duration-200`,
1660
+ style: {
1661
+ color: isFocused || isOpen ? primaryColor : "#9ca3af"
1632
1662
  },
1633
- fieldInternalProps: { ref: fieldRef, onBlur }
1663
+ children: icon
1634
1664
  }
1635
- )
1665
+ ),
1666
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1667
+ "div",
1668
+ {
1669
+ className: `flex-1 truncate text-sm ${icon ? "" : "pl-2.5"} ${!selectedValue && selectedValue !== 0 && selectedValue !== false ? "text-gray-400 dark:text-zinc-500" : ""}`,
1670
+ children: displayValue
1671
+ }
1672
+ ),
1673
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "pr-2.5 flex items-center gap-1 shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1674
+ import_lucide_react7.ChevronDown,
1675
+ {
1676
+ className: `h-4 w-4 text-gray-400 transition-transform ${isOpen ? "rotate-180" : ""}`
1677
+ }
1678
+ ) })
1679
+ ] })
1680
+ }
1681
+ ) });
1682
+ }
1683
+ );
1684
+ SelectTrigger.displayName = "SelectTrigger";
1685
+ var SelectContent = (0, import_react10.forwardRef)(
1686
+ ({ children, className = "", style, ...props }, ref) => {
1687
+ const { isOpen, setIsOpen, dropdownAnchorRef, dropdownContentRef } = useSelectContext();
1688
+ const [dropdownStyle, setDropdownStyle] = (0, import_react10.useState)({});
1689
+ const updateDropdownPosition = () => {
1690
+ if (dropdownAnchorRef.current) {
1691
+ const rect = dropdownAnchorRef.current.getBoundingClientRect();
1692
+ const newStyle = {
1693
+ position: "fixed",
1694
+ top: `${rect.bottom + 4}px`,
1695
+ left: `${rect.left}px`,
1696
+ width: `${rect.width}px`,
1697
+ zIndex: 999999
1698
+ };
1699
+ if (rect.bottom + 240 > window.innerHeight) {
1700
+ newStyle.top = "auto";
1701
+ newStyle.bottom = `${window.innerHeight - rect.top + 4}px`;
1636
1702
  }
1637
- );
1638
- }
1639
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1640
- SelectContent,
1703
+ setDropdownStyle(newStyle);
1704
+ }
1705
+ };
1706
+ (0, import_react10.useEffect)(() => {
1707
+ if (isOpen) {
1708
+ updateDropdownPosition();
1709
+ window.addEventListener("scroll", updateDropdownPosition, true);
1710
+ window.addEventListener("resize", updateDropdownPosition);
1711
+ return () => {
1712
+ window.removeEventListener("scroll", updateDropdownPosition, true);
1713
+ window.removeEventListener("resize", updateDropdownPosition);
1714
+ };
1715
+ }
1716
+ }, [isOpen]);
1717
+ if (!isOpen || typeof document === "undefined") return null;
1718
+ return (0, import_react_dom.createPortal)(
1719
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1720
+ "div",
1721
+ {
1722
+ ref: dropdownContentRef,
1723
+ className: `bg-white dark:bg-zinc-950 rounded-xl border border-gray-200 dark:border-zinc-800 shadow-xl max-h-60 overflow-y-auto overflow-x-hidden p-1.5 ${className}`,
1724
+ style: { ...dropdownStyle, ...style },
1725
+ onMouseDown: (e) => e.stopPropagation(),
1726
+ ...props,
1727
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex flex-col gap-0.5", children: import_react10.default.Children.count(children) === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "p-3 text-center text-sm text-gray-500", children: "No options available" }) : children })
1728
+ }
1729
+ ),
1730
+ document.body
1731
+ );
1732
+ }
1733
+ );
1734
+ SelectContent.displayName = "SelectContent";
1735
+ var SelectItem = (0, import_react10.forwardRef)(
1736
+ ({ value, label, disabled, children, className = "", ...props }, ref) => {
1737
+ const {
1738
+ selectedValue,
1739
+ setSelectedValue,
1740
+ setIsOpen,
1741
+ primaryColor,
1742
+ fieldInternalProps,
1743
+ registerOption
1744
+ } = useSelectContext();
1745
+ const isSelected = selectedValue === value;
1746
+ const displayLabel = label || children || value;
1747
+ (0, import_react10.useEffect)(() => {
1748
+ if (value !== void 0) {
1749
+ registerOption({ value, label: String(displayLabel), disabled });
1750
+ }
1751
+ }, [value, displayLabel, disabled]);
1752
+ const handleSelect = () => {
1753
+ if (disabled) return;
1754
+ setSelectedValue(value);
1755
+ setIsOpen(false);
1756
+ fieldInternalProps?.onBlur?.();
1757
+ };
1758
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1759
+ "button",
1641
1760
  {
1761
+ ref,
1762
+ type: "button",
1763
+ disabled,
1764
+ className: `w-full text-left px-3 py-2 rounded-md text-sm flex items-center justify-between transition-colors ${disabled ? "opacity-50 cursor-not-allowed text-gray-400" : isSelected ? "bg-gray-100 dark:bg-zinc-800 text-gray-900 dark:text-gray-100" : "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-zinc-800"} ${className}`,
1765
+ style: isSelected && !disabled && primaryColor ? { color: primaryColor } : void 0,
1766
+ onMouseDown: (e) => e.stopPropagation(),
1767
+ onClick: (e) => {
1768
+ e.stopPropagation();
1769
+ e.preventDefault();
1770
+ handleSelect();
1771
+ },
1642
1772
  ...props,
1643
- currentValue: value,
1644
- onChangeHandler: onChange || (() => {
1645
- })
1773
+ children: [
1774
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "whitespace-nowrap truncate flex-1", children: children || label }),
1775
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1776
+ import_lucide_react7.Check,
1777
+ {
1778
+ className: "h-4 w-4 shrink-0 ml-2",
1779
+ style: { color: primaryColor }
1780
+ }
1781
+ )
1782
+ ]
1646
1783
  }
1647
1784
  );
1648
1785
  }
1649
1786
  );
1650
- Select.displayName = "Select";
1787
+ SelectItem.displayName = "SelectItem";
1651
1788
 
1652
1789
  // src/components/Fields/textArea.tsx
1653
1790
  var import_react11 = require("react");
@@ -1676,7 +1813,7 @@ var Textarea = (0, import_react11.forwardRef)(
1676
1813
  const errorObj = name.split(".").reduce((acc, current) => acc?.[current], errors);
1677
1814
  message = errorObj?.message;
1678
1815
  }
1679
- const renderInput = (inputProps, ref2) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: `space-y-2 group w-full! ${containerClassName}`, children: [
1816
+ const renderInput = (inputProps, ref2) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: `space-y-2 group w-full! relative ${containerClassName}`, children: [
1680
1817
  /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1681
1818
  "label",
1682
1819
  {
@@ -1710,7 +1847,7 @@ var Textarea = (0, import_react11.forwardRef)(
1710
1847
  ...inputProps
1711
1848
  }
1712
1849
  ) }),
1713
- message && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
1850
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
1714
1851
  ] });
1715
1852
  if (form && name) {
1716
1853
  return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
@@ -1740,7 +1877,7 @@ var Textarea = (0, import_react11.forwardRef)(
1740
1877
  );
1741
1878
 
1742
1879
  // src/components/Fields/searchApi.tsx
1743
- var import_react13 = require("react");
1880
+ var import_react13 = __toESM(require("react"));
1744
1881
  var import_react_dom2 = require("react-dom");
1745
1882
  var import_lucide_react8 = require("lucide-react");
1746
1883
 
@@ -1913,27 +2050,77 @@ var useApis_default = useApi;
1913
2050
  // src/components/Fields/searchApi.tsx
1914
2051
  var import_react_hook_form5 = require("react-hook-form");
1915
2052
  var import_jsx_runtime20 = require("react/jsx-runtime");
1916
- var SearchApiContent = ({
1917
- label,
1918
- api,
1919
- placeholder = "Search...",
2053
+ var SearchApiContext = (0, import_react13.createContext)(
2054
+ void 0
2055
+ );
2056
+ var useSearchApiContext = () => {
2057
+ const context = (0, import_react13.useContext)(SearchApiContext);
2058
+ if (!context)
2059
+ throw new Error(
2060
+ "SearchApi components must be used within a SearchApiProvider"
2061
+ );
2062
+ return context;
2063
+ };
2064
+ var SearchApi = (0, import_react13.forwardRef)(
2065
+ (props, _) => {
2066
+ const { form, name, onChange, value, children } = props;
2067
+ if (form && name) {
2068
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2069
+ import_react_hook_form5.Controller,
2070
+ {
2071
+ name,
2072
+ control: form.control,
2073
+ render: ({ field }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2074
+ SearchApiRoot,
2075
+ {
2076
+ ...props,
2077
+ currentValue: field.value !== void 0 && field.value !== "" ? field.value : value,
2078
+ onChangeHandler: (val) => {
2079
+ field.onChange(val);
2080
+ if (onChange) onChange(val);
2081
+ },
2082
+ fieldInternalProps: { ref: field.ref, onBlur: field.onBlur },
2083
+ children
2084
+ }
2085
+ )
2086
+ }
2087
+ );
2088
+ }
2089
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2090
+ SearchApiRoot,
2091
+ {
2092
+ ...props,
2093
+ currentValue: value,
2094
+ onChangeHandler: onChange || (() => {
2095
+ }),
2096
+ children
2097
+ }
2098
+ );
2099
+ }
2100
+ );
2101
+ SearchApi.displayName = "SearchApi";
2102
+ var SearchApiRoot = ({
2103
+ children,
1920
2104
  currentValue,
1921
2105
  onChangeHandler,
2106
+ form,
2107
+ name,
2108
+ obj,
2109
+ error,
2110
+ api = "",
1922
2111
  queryKey = "search",
1923
2112
  labelKey = "name",
1924
2113
  valueKey = "_id",
1925
- error,
1926
- containerClassName = "",
1927
- className = "",
1928
- disabled,
1929
- name,
1930
- obj,
1931
- form,
1932
2114
  filter = [],
1933
2115
  required,
1934
2116
  v = 2,
1935
2117
  variant = "default",
1936
2118
  fieldInternalProps,
2119
+ label,
2120
+ containerClassName = "",
2121
+ placeholder = "Search...",
2122
+ disabled,
2123
+ className = "",
1937
2124
  ...props
1938
2125
  }) => {
1939
2126
  const [searchTerm, setSearchTerm] = (0, import_react13.useState)("");
@@ -1947,51 +2134,13 @@ var SearchApiContent = ({
1947
2134
  const [hasAttemptedHydration, setHasAttemptedHydration] = (0, import_react13.useState)(false);
1948
2135
  const containerRef = (0, import_react13.useRef)(null);
1949
2136
  const dropdownAnchorRef = (0, import_react13.useRef)(null);
1950
- const dropdownRef = (0, import_react13.useRef)(null);
2137
+ const dropdownContentRef = (0, import_react13.useRef)(null);
1951
2138
  const inputRef = (0, import_react13.useRef)(null);
1952
2139
  const prevApiRef = (0, import_react13.useRef)(api);
1953
- const [dropdownStyle, setDropdownStyle] = (0, import_react13.useState)({});
1954
- const updateDropdownPosition = () => {
1955
- if (dropdownAnchorRef.current) {
1956
- const rect = dropdownAnchorRef.current.getBoundingClientRect();
1957
- const style = {
1958
- position: "fixed",
1959
- top: `${rect.bottom + 4}px`,
1960
- left: `${rect.left}px`,
1961
- width: `${rect.width}px`,
1962
- zIndex: 999999
1963
- };
1964
- if (rect.bottom + 240 > window.innerHeight) {
1965
- style.top = "auto";
1966
- style.bottom = `${window.innerHeight - rect.top + 4}px`;
1967
- }
1968
- setDropdownStyle(style);
1969
- }
1970
- };
1971
- (0, import_react13.useEffect)(() => {
1972
- if (isOpen) {
1973
- updateDropdownPosition();
1974
- window.addEventListener("scroll", updateDropdownPosition, true);
1975
- window.addEventListener("resize", updateDropdownPosition);
1976
- return () => {
1977
- window.removeEventListener("scroll", updateDropdownPosition, true);
1978
- window.removeEventListener("resize", updateDropdownPosition);
1979
- };
1980
- }
1981
- }, [isOpen]);
1982
- const setInputRef = (element) => {
1983
- inputRef.current = element;
1984
- if (fieldInternalProps?.ref) {
1985
- if (typeof fieldInternalProps.ref === "function") {
1986
- fieldInternalProps.ref(element);
1987
- } else {
1988
- fieldInternalProps.ref.current = element;
1989
- }
1990
- }
1991
- };
1992
2140
  const { get, isLoading, error: errorMessage } = useApis_default();
1993
2141
  const fetchOptions = async (query) => {
1994
2142
  try {
2143
+ if (!api) return;
1995
2144
  const params = {};
1996
2145
  if (query) params[queryKey] = query;
1997
2146
  const response = await get({
@@ -2055,7 +2204,10 @@ var SearchApiContent = ({
2055
2204
  if (found) {
2056
2205
  setSelectedObject(found);
2057
2206
  if (form && obj) {
2058
- form.setValue(obj, found);
2207
+ form.setValue(obj, found, {
2208
+ shouldValidate: true,
2209
+ shouldDirty: true
2210
+ });
2059
2211
  }
2060
2212
  }
2061
2213
  }
@@ -2088,7 +2240,7 @@ var SearchApiContent = ({
2088
2240
  (0, import_react13.useEffect)(() => {
2089
2241
  const handleClickOutside = (event) => {
2090
2242
  const target = event.target;
2091
- if (containerRef.current && !containerRef.current.contains(target) && !(dropdownRef.current && dropdownRef.current.contains(target))) {
2243
+ if (containerRef.current && !containerRef.current.contains(target) && !(dropdownContentRef.current && dropdownContentRef.current.contains(target))) {
2092
2244
  setIsOpen(false);
2093
2245
  setIsFocused(false);
2094
2246
  setSearchTerm("");
@@ -2109,42 +2261,21 @@ var SearchApiContent = ({
2109
2261
  return currentValue || "";
2110
2262
  };
2111
2263
  const handleSelect = (option) => {
2112
- const value = getOptionValue(option);
2264
+ const val = getOptionValue(option);
2265
+ setIsOpen(false);
2266
+ inputRef.current?.blur();
2113
2267
  setSelectedObject(option);
2114
- onChangeHandler(value);
2268
+ setTimeout(() => {
2269
+ onChangeHandler(val);
2270
+ }, 0);
2115
2271
  if (form) {
2116
2272
  if (obj) form.setValue(obj, option);
2117
2273
  if (name) form.clearErrors(name);
2118
2274
  }
2119
- setIsOpen(false);
2120
2275
  setSearchTerm("");
2121
2276
  setActiveIndex(-1);
2122
2277
  fieldInternalProps?.onBlur?.();
2123
2278
  };
2124
- const handleKeyDown = (e) => {
2125
- if (!isOpen) {
2126
- if (e.key === "ArrowDown" || e.key === "Enter") setIsOpen(true);
2127
- return;
2128
- }
2129
- switch (e.key) {
2130
- case "ArrowDown":
2131
- e.preventDefault();
2132
- setActiveIndex((prev) => prev < options.length - 1 ? prev + 1 : prev);
2133
- break;
2134
- case "ArrowUp":
2135
- e.preventDefault();
2136
- setActiveIndex((prev) => prev > 0 ? prev - 1 : prev);
2137
- break;
2138
- case "Enter":
2139
- e.preventDefault();
2140
- if (activeIndex >= 0 && activeIndex < options.length)
2141
- handleSelect(options[activeIndex]);
2142
- break;
2143
- case "Escape":
2144
- setIsOpen(false);
2145
- break;
2146
- }
2147
- };
2148
2279
  const clearSelection = (e) => {
2149
2280
  e.stopPropagation();
2150
2281
  if (form) {
@@ -2166,13 +2297,7 @@ var SearchApiContent = ({
2166
2297
  const filteredOptions = options.filter(
2167
2298
  (option) => !filter.includes(getOptionValue(option))
2168
2299
  );
2169
- (0, import_react13.useEffect)(() => {
2170
- if (form && name && !form.watch(name)) {
2171
- form.setValue(name, void 0);
2172
- if (obj) form.setValue(obj, void 0);
2173
- }
2174
- }, [form, name, obj]);
2175
- let message = error;
2300
+ let message = error || errorMessage;
2176
2301
  if (form && name) {
2177
2302
  const {
2178
2303
  formState: { errors }
@@ -2184,11 +2309,46 @@ var SearchApiContent = ({
2184
2309
  }
2185
2310
  message = currentError?.message || message;
2186
2311
  }
2187
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2312
+ const valueCtx = {
2313
+ isOpen,
2314
+ setIsOpen,
2315
+ searchTerm,
2316
+ setSearchTerm,
2317
+ selectedValue: currentValue,
2318
+ setSelectedValue: onChangeHandler,
2319
+ // alias
2320
+ activeIndex,
2321
+ setActiveIndex,
2322
+ isFocused,
2323
+ setIsFocused,
2324
+ dropdownAnchorRef,
2325
+ dropdownContentRef,
2326
+ containerRef,
2327
+ inputRef,
2328
+ primaryColor,
2329
+ options: filteredOptions,
2330
+ setOptions,
2331
+ fieldInternalProps,
2332
+ disabled,
2333
+ isLoading,
2334
+ clearSelection,
2335
+ handleSelect,
2336
+ getDisplayValue,
2337
+ placeholder,
2338
+ variant,
2339
+ labelKey,
2340
+ valueKey,
2341
+ form,
2342
+ name,
2343
+ obj,
2344
+ error: message
2345
+ };
2346
+ const hasChildren = import_react13.default.Children.count(children) > 0;
2347
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SearchApiContext.Provider, { value: valueCtx, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2188
2348
  "div",
2189
2349
  {
2190
2350
  ref: containerRef,
2191
- className: `${label ? "space-y-2" : ""} group ${containerClassName}`,
2351
+ className: `${label ? "space-y-2" : ""} group relative ${containerClassName}`,
2192
2352
  children: [
2193
2353
  label && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2194
2354
  "label",
@@ -2201,153 +2361,280 @@ var SearchApiContent = ({
2201
2361
  ]
2202
2362
  }
2203
2363
  ),
2204
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "relative", ref: dropdownAnchorRef, children: [
2205
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2364
+ hasChildren ? children : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
2365
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SearchApiTrigger, { className, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SearchApiInput, { ...props }) }),
2366
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SearchApiContent, { children: filteredOptions.map((opt, index) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2367
+ SearchApiItem,
2368
+ {
2369
+ option: opt,
2370
+ index
2371
+ },
2372
+ String(getOptionValue(opt)) || index
2373
+ )) })
2374
+ ] }),
2375
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
2376
+ ]
2377
+ }
2378
+ ) });
2379
+ };
2380
+ var SearchApiTrigger = (0, import_react13.forwardRef)(
2381
+ ({ className = "", children, ...props }, ref) => {
2382
+ const {
2383
+ isOpen,
2384
+ setIsOpen,
2385
+ isFocused,
2386
+ setIsFocused,
2387
+ primaryColor,
2388
+ dropdownAnchorRef,
2389
+ disabled,
2390
+ isLoading,
2391
+ clearSelection,
2392
+ selectedValue,
2393
+ variant,
2394
+ inputRef
2395
+ } = useSearchApiContext();
2396
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "relative", ref: dropdownAnchorRef, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2397
+ "div",
2398
+ {
2399
+ className: `flex items-center w-full px-0 text-gray-900 dark:text-white transition-all duration-200 cursor-text py-1 ${variant === "ghost" ? "bg-transparent border-transparent shadow-none px-0 h-full" : isFocused || isOpen ? "ring-2 bg-white dark:bg-zinc-900 border rounded-xl h-9" : "border-gray-200 dark:border-zinc-800 border rounded-xl bg-white dark:bg-zinc-900/50 h-9"} ${className}`,
2400
+ style: variant === "default" ? {
2401
+ borderColor: isFocused || isOpen ? primaryColor : void 0,
2402
+ boxShadow: isFocused || isOpen ? `${primaryColor}33 0px 0px 0px 2px` : void 0
2403
+ } : void 0,
2404
+ onClick: () => {
2405
+ if (disabled) return;
2406
+ inputRef.current?.focus();
2407
+ setIsOpen(true);
2408
+ },
2409
+ ...props,
2410
+ children: [
2411
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2206
2412
  "div",
2207
2413
  {
2208
- className: `flex items-center w-full px-0 text-gray-900 dark:text-white transition-all duration-200 cursor-text py-1 ${variant === "ghost" ? "bg-transparent border-transparent shadow-none px-0 h-full" : isFocused || isOpen ? "ring-2 bg-white dark:bg-zinc-900 border rounded-xl h-9" : "border-gray-200 dark:border-zinc-800 border rounded-xl bg-white dark:bg-zinc-900/50 h-9"} ${className}`,
2209
- style: variant === "default" ? {
2210
- borderColor: isFocused || isOpen ? primaryColor : void 0,
2211
- boxShadow: isFocused || isOpen ? `${primaryColor}33 0px 0px 0px 2px` : void 0
2212
- } : void 0,
2213
- onClick: () => {
2214
- if (disabled) return;
2215
- inputRef.current?.focus();
2216
- setIsOpen(true);
2217
- },
2218
- children: [
2219
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2220
- "div",
2221
- {
2222
- className: `${variant === "ghost" ? "pl-0" : "pl-2.5"} text-gray-400`,
2223
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.Search, { className: "h-4 w-4" })
2224
- }
2225
- ),
2226
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex-1 relative ms-2", children: [
2227
- !isOpen && currentValue && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "absolute inset-0 flex items-center ms-1 truncate select-none", children: getDisplayValue() }),
2228
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2229
- "input",
2230
- {
2231
- ref: setInputRef,
2232
- type: "text",
2233
- className: `block w-full bg-transparent border-none focus:ring-0 py-1 focus:outline-none text-sm placeholder-gray-400 dark:placeholder-zinc-500 ${!isOpen && currentValue ? "opacity-0" : "opacity-100"} ${variant === "ghost" ? "h-full" : "h-9"}`,
2234
- placeholder: !currentValue ? placeholder : "",
2235
- value: searchTerm,
2236
- onChange: (e) => setSearchTerm(e.target.value),
2237
- onFocus: () => {
2238
- setIsFocused(true);
2239
- setIsOpen(true);
2240
- },
2241
- onKeyDown: handleKeyDown,
2242
- disabled,
2243
- ...props
2244
- }
2245
- )
2246
- ] }),
2247
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "pr-2.5 w-16! flex items-center gap-1 shrink-0 min-w-10 justify-end", children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.Loader2, { className: "h-4 w-4 animate-spin text-blue-500 shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1", children: [
2248
- currentValue && !disabled && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2249
- "button",
2250
- {
2251
- onClick: clearSelection,
2252
- type: "button",
2253
- className: "p-0.5 hover:bg-gray-200 dark:hover:bg-zinc-700 rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-300",
2254
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.X, { className: "h-3 w-3" })
2255
- }
2256
- ),
2257
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2258
- import_lucide_react8.ChevronDown,
2259
- {
2260
- className: `h-4 w-4 text-gray-400 transition-transform ${isOpen ? "rotate-180" : ""}`
2261
- }
2262
- )
2263
- ] }) })
2264
- ]
2414
+ className: `${variant === "ghost" ? "pl-0" : "pl-2.5"} text-gray-400`,
2415
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.Search, { className: "h-4 w-4" })
2265
2416
  }
2266
2417
  ),
2267
- isOpen && typeof document !== "undefined" && (0, import_react_dom2.createPortal)(
2268
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2269
- "div",
2418
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex-1 relative ms-2", children }),
2419
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "pr-2.5 w-16! flex items-center gap-1 shrink-0 min-w-10 justify-end", children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.Loader2, { className: "h-4 w-4 animate-spin text-blue-500 shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1", children: [
2420
+ selectedValue && !disabled && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2421
+ "button",
2270
2422
  {
2271
- ref: dropdownRef,
2272
- className: "bg-white dark:bg-zinc-900 rounded-xl border border-gray-200 dark:border-zinc-800 shadow-lg max-h-60 overflow-y-auto overflow-x-hidden",
2273
- style: dropdownStyle,
2274
- children: isLoading && options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "p-4 text-center text-sm text-gray-500", children: [
2275
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.Loader2, { className: "h-5 w-5 animate-spin mx-auto mb-2" }),
2276
- "Loading options..."
2277
- ] }) : filteredOptions.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "py-1", children: filteredOptions.map((option, index) => {
2278
- const optValue = getOptionValue(option);
2279
- const isSelected = currentValue === optValue;
2280
- const isHighlighted = index === activeIndex;
2281
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2282
- "button",
2283
- {
2284
- type: "button",
2285
- className: `w-full text-left px-3 py-2 text-sm flex items-center justify-between transition-colors ${isSelected ? "font-medium" : isHighlighted ? "bg-gray-100 dark:bg-zinc-800 text-gray-900 dark:text-gray-100" : "text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-zinc-800"}`,
2286
- style: {
2287
- backgroundColor: isSelected ? `${primaryColor}1A` : void 0,
2288
- color: isSelected ? primaryColor : void 0
2289
- },
2290
- onClick: () => handleSelect(option),
2291
- onMouseEnter: () => setActiveIndex(index),
2292
- children: [
2293
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "truncate", children: option[labelKey] }),
2294
- isSelected && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2295
- import_lucide_react8.Check,
2296
- {
2297
- className: "h-4 w-4",
2298
- style: { color: primaryColor }
2299
- }
2300
- )
2301
- ]
2302
- },
2303
- optValue || index
2304
- );
2305
- }) }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "p-4 text-center text-sm text-gray-500", children: errorMessage || (searchTerm ? `No results for "${searchTerm}"` : "No options available") })
2423
+ onClick: clearSelection,
2424
+ type: "button",
2425
+ className: "p-0.5 hover:bg-gray-200 dark:hover:bg-zinc-700 rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-300",
2426
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.X, { className: "h-3 w-3" })
2306
2427
  }
2307
2428
  ),
2308
- document.body
2309
- )
2310
- ] }),
2311
- message && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
2312
- ]
2313
- }
2314
- );
2315
- };
2316
- var SearchApi = (0, import_react13.forwardRef)(
2317
- (props, _) => {
2318
- const { form, name, onChange, value } = props;
2319
- if (form && name) {
2320
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2321
- import_react_hook_form5.Controller,
2429
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2430
+ import_lucide_react8.ChevronDown,
2431
+ {
2432
+ className: `h-4 w-4 text-gray-400 transition-transform ${isOpen ? "rotate-180" : ""}`
2433
+ }
2434
+ )
2435
+ ] }) })
2436
+ ]
2437
+ }
2438
+ ) });
2439
+ }
2440
+ );
2441
+ SearchApiTrigger.displayName = "SearchApiTrigger";
2442
+ var SearchApiInput = (0, import_react13.forwardRef)(
2443
+ ({ className = "", ...props }, ref) => {
2444
+ const {
2445
+ isOpen,
2446
+ setIsOpen,
2447
+ isFocused,
2448
+ setIsFocused,
2449
+ searchTerm,
2450
+ setSearchTerm,
2451
+ disabled,
2452
+ selectedValue,
2453
+ getDisplayValue,
2454
+ placeholder,
2455
+ variant,
2456
+ activeIndex,
2457
+ setActiveIndex,
2458
+ options,
2459
+ handleSelect,
2460
+ inputRef,
2461
+ fieldInternalProps
2462
+ } = useSearchApiContext();
2463
+ const setInternalInputRef = (element) => {
2464
+ inputRef.current = element;
2465
+ if (fieldInternalProps?.ref) {
2466
+ if (typeof fieldInternalProps.ref === "function") {
2467
+ fieldInternalProps.ref(element);
2468
+ } else {
2469
+ fieldInternalProps.ref.current = element;
2470
+ }
2471
+ }
2472
+ };
2473
+ const handleKeyDown = (e) => {
2474
+ if (!isOpen) {
2475
+ if (e.key === "ArrowDown" || e.key === "Enter") setIsOpen(true);
2476
+ return;
2477
+ }
2478
+ switch (e.key) {
2479
+ case "ArrowDown":
2480
+ e.preventDefault();
2481
+ e.stopPropagation();
2482
+ setActiveIndex(
2483
+ activeIndex < options.length - 1 ? activeIndex + 1 : activeIndex
2484
+ );
2485
+ break;
2486
+ case "ArrowUp":
2487
+ e.preventDefault();
2488
+ e.stopPropagation();
2489
+ setActiveIndex(activeIndex > 0 ? activeIndex - 1 : activeIndex);
2490
+ break;
2491
+ case "Enter":
2492
+ e.preventDefault();
2493
+ e.stopPropagation();
2494
+ if (activeIndex >= 0 && activeIndex < options.length)
2495
+ handleSelect(options[activeIndex]);
2496
+ break;
2497
+ case "Escape":
2498
+ e.preventDefault();
2499
+ e.stopPropagation();
2500
+ setIsOpen(false);
2501
+ break;
2502
+ }
2503
+ };
2504
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
2505
+ !isOpen && selectedValue && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "absolute inset-0 flex items-center ms-1 truncate select-none", children: getDisplayValue() }),
2506
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2507
+ "input",
2322
2508
  {
2323
- name,
2324
- control: form.control,
2325
- render: ({
2326
- field: { onChange: formOnChange, value: formValue, ref, onBlur }
2327
- }) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2328
- SearchApiContent,
2329
- {
2330
- ...props,
2331
- currentValue: formValue,
2332
- onChangeHandler: formOnChange,
2333
- fieldInternalProps: { ref, onBlur }
2334
- }
2335
- )
2509
+ ref: setInternalInputRef,
2510
+ type: "text",
2511
+ className: `block w-full bg-transparent border-none focus:ring-0 py-1 focus:outline-none text-sm placeholder-gray-400 dark:placeholder-zinc-500 ${!isOpen && selectedValue ? "opacity-0" : "opacity-100"} ${variant === "ghost" ? "h-full" : "h-9"} ${className}`,
2512
+ placeholder: !selectedValue ? placeholder : "",
2513
+ value: searchTerm,
2514
+ onChange: (e) => setSearchTerm(e.target.value),
2515
+ onFocus: () => {
2516
+ setIsFocused(true);
2517
+ setIsOpen(true);
2518
+ },
2519
+ onKeyDown: handleKeyDown,
2520
+ disabled,
2521
+ ...props
2336
2522
  }
2337
- );
2338
- }
2339
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2340
- SearchApiContent,
2523
+ )
2524
+ ] });
2525
+ }
2526
+ );
2527
+ SearchApiInput.displayName = "SearchApiInput";
2528
+ var SearchApiContent = (0, import_react13.forwardRef)(
2529
+ ({ children, className = "", style, ...props }, ref) => {
2530
+ const {
2531
+ isOpen,
2532
+ setIsOpen,
2533
+ dropdownAnchorRef,
2534
+ dropdownContentRef,
2535
+ isLoading,
2536
+ searchTerm,
2537
+ options,
2538
+ error
2539
+ } = useSearchApiContext();
2540
+ const [dropdownStyle, setDropdownStyle] = (0, import_react13.useState)({});
2541
+ const updateDropdownPosition = () => {
2542
+ if (dropdownAnchorRef.current) {
2543
+ const rect = dropdownAnchorRef.current.getBoundingClientRect();
2544
+ const newStyle = {
2545
+ position: "fixed",
2546
+ top: `${rect.bottom + 4}px`,
2547
+ left: `${rect.left}px`,
2548
+ width: `${rect.width}px`,
2549
+ zIndex: 999999
2550
+ };
2551
+ if (rect.bottom + 240 > window.innerHeight) {
2552
+ newStyle.top = "auto";
2553
+ newStyle.bottom = `${window.innerHeight - rect.top + 4}px`;
2554
+ }
2555
+ setDropdownStyle(newStyle);
2556
+ }
2557
+ };
2558
+ (0, import_react13.useEffect)(() => {
2559
+ if (isOpen) {
2560
+ updateDropdownPosition();
2561
+ window.addEventListener("scroll", updateDropdownPosition, true);
2562
+ window.addEventListener("resize", updateDropdownPosition);
2563
+ return () => {
2564
+ window.removeEventListener("scroll", updateDropdownPosition, true);
2565
+ window.removeEventListener("resize", updateDropdownPosition);
2566
+ };
2567
+ }
2568
+ }, [isOpen]);
2569
+ if (!isOpen || typeof document === "undefined") return null;
2570
+ return (0, import_react_dom2.createPortal)(
2571
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2572
+ "div",
2573
+ {
2574
+ ref: dropdownContentRef,
2575
+ className: `bg-white dark:bg-zinc-900 rounded-xl border border-gray-200 dark:border-zinc-800 shadow-lg max-h-60 overflow-y-auto overflow-x-hidden ${className}`,
2576
+ style: { ...dropdownStyle, ...style },
2577
+ onMouseDown: (e) => e.stopPropagation(),
2578
+ ...props,
2579
+ children: isLoading && options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "p-4 text-center text-sm text-gray-500", children: [
2580
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.Loader2, { className: "h-5 w-5 animate-spin mx-auto mb-2" }),
2581
+ "Loading options..."
2582
+ ] }) : import_react13.default.Children.count(children) > 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "py-1", children }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "p-4 text-center text-sm text-gray-500", children: error && options.length === 0 ? error : searchTerm ? `No results for "${searchTerm}"` : "No options available" })
2583
+ }
2584
+ ),
2585
+ document.body
2586
+ );
2587
+ }
2588
+ );
2589
+ SearchApiContent.displayName = "SearchApiContent";
2590
+ var SearchApiItem = (0, import_react13.forwardRef)(
2591
+ ({ option, index, className = "", ...props }, ref) => {
2592
+ const {
2593
+ selectedValue,
2594
+ activeIndex,
2595
+ setActiveIndex,
2596
+ handleSelect,
2597
+ primaryColor,
2598
+ labelKey,
2599
+ valueKey
2600
+ } = useSearchApiContext();
2601
+ const getOptionValue = (opt) => {
2602
+ if (valueKey === "_id" && opt._id === void 0 && opt.id !== void 0) {
2603
+ return opt.id;
2604
+ }
2605
+ return opt[valueKey];
2606
+ };
2607
+ const optValue = getOptionValue(option);
2608
+ const isSelected = selectedValue === optValue;
2609
+ const isHighlighted = index === activeIndex;
2610
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
2611
+ "button",
2341
2612
  {
2613
+ ref,
2614
+ type: "button",
2615
+ className: `w-full text-left px-3 py-2 text-sm flex items-center justify-between transition-colors ${isSelected ? "font-medium" : isHighlighted ? "bg-gray-100 dark:bg-zinc-800 text-gray-900 dark:text-gray-100" : "text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-zinc-800"} ${className}`,
2616
+ style: isSelected && primaryColor ? {
2617
+ backgroundColor: `${primaryColor}1A`,
2618
+ color: primaryColor
2619
+ } : void 0,
2620
+ onMouseDown: (e) => e.stopPropagation(),
2621
+ onClick: (e) => {
2622
+ e.stopPropagation();
2623
+ e.preventDefault();
2624
+ handleSelect(option);
2625
+ },
2626
+ onMouseEnter: () => setActiveIndex(index),
2342
2627
  ...props,
2343
- currentValue: value,
2344
- onChangeHandler: onChange || (() => {
2345
- })
2346
- }
2628
+ children: [
2629
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "truncate", children: option[labelKey] }),
2630
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.Check, { className: "h-4 w-4", style: { color: primaryColor } })
2631
+ ]
2632
+ },
2633
+ optValue || index
2347
2634
  );
2348
2635
  }
2349
2636
  );
2350
- SearchApi.displayName = "SearchApi";
2637
+ SearchApiItem.displayName = "SearchApiItem";
2351
2638
 
2352
2639
  // src/components/Fields/date.tsx
2353
2640
  var import_react14 = require("react");
@@ -2432,15 +2719,18 @@ var DateInput = (0, import_react14.forwardRef)(
2432
2719
  }
2433
2720
  );
2434
2721
  };
2435
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `space-y-2 group ${containerClassName}`, children: [
2436
- label && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
2722
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: `space-y-2 group relative ${containerClassName}`, children: [
2723
+ label && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
2437
2724
  "label",
2438
2725
  {
2439
2726
  className: "block text-xs font-medium transition-colors duration-200",
2440
2727
  style: {
2441
2728
  color: message ? "#ef4444" : isFocused ? primaryColor : void 0
2442
2729
  },
2443
- children: label
2730
+ children: [
2731
+ label,
2732
+ props.required && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-red-500 ml-1", children: "*" })
2733
+ ]
2444
2734
  }
2445
2735
  ),
2446
2736
  form && name ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
@@ -2456,7 +2746,7 @@ var DateInput = (0, import_react14.forwardRef)(
2456
2746
  )
2457
2747
  }
2458
2748
  ) : renderDatePicker(value, onChange, onBlur, ref),
2459
- message && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
2749
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
2460
2750
  ] });
2461
2751
  }
2462
2752
  );
@@ -2466,8 +2756,15 @@ var Fields = {
2466
2756
  Input,
2467
2757
  PhoneInput,
2468
2758
  Select,
2759
+ SelectTrigger,
2760
+ SelectContent,
2761
+ SelectItem,
2469
2762
  Textarea,
2470
2763
  SearchApi,
2764
+ SearchApiTrigger,
2765
+ SearchApiInput,
2766
+ SearchApiContent,
2767
+ SearchApiItem,
2471
2768
  DateInput
2472
2769
  };
2473
2770
  var Fields_default = Fields;
@@ -4069,7 +4366,14 @@ var generatePdf = async (elementId, options = {}) => {
4069
4366
  PhoneInput,
4070
4367
  PostTable,
4071
4368
  SearchApi,
4369
+ SearchApiContent,
4370
+ SearchApiInput,
4371
+ SearchApiItem,
4372
+ SearchApiTrigger,
4072
4373
  Select,
4374
+ SelectContent,
4375
+ SelectItem,
4376
+ SelectTrigger,
4073
4377
  SimpleTable,
4074
4378
  Textarea,
4075
4379
  ThemeProvider,
@@ -4079,6 +4383,8 @@ var generatePdf = async (elementId, options = {}) => {
4079
4383
  useA4StatementView,
4080
4384
  useApi,
4081
4385
  useModal,
4386
+ useSearchApiContext,
4387
+ useSelectContext,
4082
4388
  useTheme,
4083
4389
  useTransaction,
4084
4390
  useWarqadConfig