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.mjs CHANGED
@@ -1079,7 +1079,7 @@ var Input = forwardRef(
1079
1079
  const renderInput = (inputProps, localType = type || "text") => /* @__PURE__ */ jsxs11(
1080
1080
  "div",
1081
1081
  {
1082
- className: `${label ? "space-y-2" : ""} group ${containerClassName} `,
1082
+ className: `${label ? "space-y-2" : ""} group relative ${containerClassName} `,
1083
1083
  children: [
1084
1084
  label && /* @__PURE__ */ jsxs11(
1085
1085
  "label",
@@ -1135,7 +1135,7 @@ var Input = forwardRef(
1135
1135
  }
1136
1136
  )
1137
1137
  ] }),
1138
- message && /* @__PURE__ */ jsx16("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
1138
+ /* @__PURE__ */ jsx16("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ jsx16("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
1139
1139
  ]
1140
1140
  }
1141
1141
  );
@@ -1241,7 +1241,7 @@ var PhoneInput = forwardRef2(
1241
1241
  }
1242
1242
  message = currentError?.message || message;
1243
1243
  }
1244
- const renderInput = (onChangeHandler, currentValue) => /* @__PURE__ */ jsxs12("div", { className: `space-y-2 group ${containerClassName}`, children: [
1244
+ const renderInput = (onChangeHandler, currentValue) => /* @__PURE__ */ jsxs12("div", { className: `space-y-2 group relative ${containerClassName}`, children: [
1245
1245
  /* @__PURE__ */ jsxs12(
1246
1246
  "label",
1247
1247
  {
@@ -1284,7 +1284,7 @@ var PhoneInput = forwardRef2(
1284
1284
  }
1285
1285
  )
1286
1286
  ] }),
1287
- message && /* @__PURE__ */ jsx17("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
1287
+ /* @__PURE__ */ jsx17("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ jsx17("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
1288
1288
  ] });
1289
1289
  if (form && name) {
1290
1290
  return /* @__PURE__ */ jsx17(
@@ -1306,65 +1306,120 @@ var PhoneInput = forwardRef2(
1306
1306
  PhoneInput.displayName = "PhoneInput";
1307
1307
 
1308
1308
  // src/components/Fields/select.tsx
1309
- import { forwardRef as forwardRef3, useState as useState9, useEffect as useEffect6, useRef as useRef3 } from "react";
1309
+ import React6, {
1310
+ createContext as createContext3,
1311
+ useContext as useContext3,
1312
+ useState as useState9,
1313
+ useRef as useRef3,
1314
+ useEffect as useEffect6,
1315
+ forwardRef as forwardRef3
1316
+ } from "react";
1310
1317
  import { createPortal } from "react-dom";
1311
1318
  import { ChevronDown as ChevronDown2, Check as Check2 } from "lucide-react";
1312
1319
  import { Controller as Controller3 } from "react-hook-form";
1313
- import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
1314
- var SelectContent = ({
1315
- label,
1316
- options,
1317
- icon,
1320
+ import { Fragment as Fragment3, jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
1321
+ var SelectContext = createContext3(void 0);
1322
+ var useSelectContext = () => {
1323
+ const context = useContext3(SelectContext);
1324
+ if (!context)
1325
+ throw new Error("Select components must be used within a SelectProvider");
1326
+ return context;
1327
+ };
1328
+ var Select = forwardRef3((props, ref) => {
1329
+ const { form, name, onChange, value, children, options = [] } = props;
1330
+ if (form && name) {
1331
+ return /* @__PURE__ */ jsx18(
1332
+ Controller3,
1333
+ {
1334
+ name,
1335
+ control: form.control,
1336
+ render: ({
1337
+ field: {
1338
+ onChange: formOnChange,
1339
+ value: formValue,
1340
+ ref: fieldRef,
1341
+ onBlur
1342
+ }
1343
+ }) => /* @__PURE__ */ jsx18(
1344
+ SelectRoot,
1345
+ {
1346
+ ...props,
1347
+ options,
1348
+ currentValue: formValue,
1349
+ onChangeHandler: (val) => {
1350
+ formOnChange(val);
1351
+ onChange?.(val);
1352
+ },
1353
+ fieldInternalProps: { ref: fieldRef, onBlur },
1354
+ children
1355
+ }
1356
+ )
1357
+ }
1358
+ );
1359
+ }
1360
+ return /* @__PURE__ */ jsx18(
1361
+ SelectRoot,
1362
+ {
1363
+ ...props,
1364
+ options,
1365
+ currentValue: value,
1366
+ onChangeHandler: onChange || (() => {
1367
+ }),
1368
+ children
1369
+ }
1370
+ );
1371
+ });
1372
+ Select.displayName = "Select";
1373
+ var SelectRoot = ({
1374
+ children,
1375
+ currentValue,
1376
+ onChangeHandler,
1377
+ form,
1378
+ name,
1318
1379
  error,
1380
+ options: initialOptions,
1381
+ fieldInternalProps,
1382
+ label,
1319
1383
  containerClassName = "",
1320
- name,
1321
- form,
1322
- onChangeHandler,
1323
- currentValue,
1324
- onFocus,
1325
- onBlur,
1326
- className = "",
1327
1384
  variant = "default",
1328
- fieldInternalProps,
1385
+ icon,
1386
+ placeholder = "Select...",
1387
+ required,
1388
+ disabled,
1389
+ id,
1390
+ className = "",
1329
1391
  ...props
1330
1392
  }) => {
1331
1393
  const [isOpen, setIsOpen] = useState9(false);
1332
1394
  const [isFocused, setIsFocused] = useState9(false);
1333
- const [dropdownStyle, setDropdownStyle] = useState9({});
1395
+ const [activeIndex, setActiveIndex] = useState9(-1);
1396
+ const [registeredOptions, setRegisteredOptions] = useState9([]);
1334
1397
  const { theme } = useWarqadConfig();
1335
1398
  const primaryColor = theme?.primaryColor;
1336
1399
  const containerRef = useRef3(null);
1337
1400
  const dropdownAnchorRef = useRef3(null);
1338
1401
  const dropdownContentRef = useRef3(null);
1339
- const lastFocusTime = useRef3(0);
1340
- const updateDropdownPosition = () => {
1341
- if (dropdownAnchorRef.current) {
1342
- const rect = dropdownAnchorRef.current.getBoundingClientRect();
1343
- const style = {
1344
- position: "fixed",
1345
- top: `${rect.bottom + 4}px`,
1346
- left: `${rect.left}px`,
1347
- width: `${rect.width}px`,
1348
- zIndex: 999999
1349
- };
1350
- if (rect.bottom + 240 > window.innerHeight) {
1351
- style.top = "auto";
1352
- style.bottom = `${window.innerHeight - rect.top + 4}px`;
1402
+ const registerOption = (opt) => {
1403
+ setRegisteredOptions((prev) => {
1404
+ const index = prev.findIndex((p) => p.value === opt.value);
1405
+ if (index >= 0) {
1406
+ if (prev[index].label !== opt.label || prev[index].disabled !== opt.disabled) {
1407
+ const newOpts = [...prev];
1408
+ newOpts[index] = opt;
1409
+ return newOpts;
1410
+ }
1411
+ return prev;
1353
1412
  }
1354
- setDropdownStyle(style);
1355
- }
1413
+ return [...prev, opt];
1414
+ });
1356
1415
  };
1357
- useEffect6(() => {
1358
- if (isOpen) {
1359
- updateDropdownPosition();
1360
- window.addEventListener("scroll", updateDropdownPosition, true);
1361
- window.addEventListener("resize", updateDropdownPosition);
1362
- return () => {
1363
- window.removeEventListener("scroll", updateDropdownPosition, true);
1364
- window.removeEventListener("resize", updateDropdownPosition);
1365
- };
1416
+ const setSelectedValue = (val) => {
1417
+ onChangeHandler(val);
1418
+ if (form && name) {
1419
+ form.setValue(name, val, { shouldValidate: true, shouldDirty: true });
1420
+ form.clearErrors(name);
1366
1421
  }
1367
- }, [isOpen]);
1422
+ };
1368
1423
  useEffect6(() => {
1369
1424
  const handleClickOutside = (event) => {
1370
1425
  const target = event.target;
@@ -1377,20 +1432,6 @@ var SelectContent = ({
1377
1432
  document.addEventListener("mousedown", handleClickOutside);
1378
1433
  return () => document.removeEventListener("mousedown", handleClickOutside);
1379
1434
  }, [fieldInternalProps]);
1380
- const handleSelect = (option) => {
1381
- if (option.disabled) return;
1382
- onChangeHandler(option.value);
1383
- if (form && name) {
1384
- form.setValue(name, option.value, {
1385
- shouldValidate: true,
1386
- shouldDirty: true
1387
- });
1388
- form.clearErrors(name);
1389
- }
1390
- setIsOpen(false);
1391
- fieldInternalProps?.onBlur?.();
1392
- };
1393
- const displayValue = options.find((o) => o.value === currentValue)?.label || "Select...";
1394
1435
  let message = error;
1395
1436
  if (form && name) {
1396
1437
  const {
@@ -1403,11 +1444,31 @@ var SelectContent = ({
1403
1444
  }
1404
1445
  message = currentError?.message || message;
1405
1446
  }
1406
- return /* @__PURE__ */ jsxs13(
1447
+ const allOptions = initialOptions?.length ? initialOptions : registeredOptions;
1448
+ const valueCtx = {
1449
+ isOpen,
1450
+ setIsOpen,
1451
+ selectedValue: currentValue,
1452
+ setSelectedValue,
1453
+ activeIndex,
1454
+ setActiveIndex,
1455
+ isFocused,
1456
+ setIsFocused,
1457
+ dropdownAnchorRef,
1458
+ dropdownContentRef,
1459
+ containerRef,
1460
+ primaryColor,
1461
+ options: allOptions,
1462
+ registerOption,
1463
+ fieldInternalProps,
1464
+ disabled
1465
+ };
1466
+ const hasChildren = React6.Children.count(children) > 0;
1467
+ return /* @__PURE__ */ jsx18(SelectContext.Provider, { value: valueCtx, children: /* @__PURE__ */ jsxs13(
1407
1468
  "div",
1408
1469
  {
1409
1470
  ref: containerRef,
1410
- className: `${label ? "space-y-2" : ""} group ${containerClassName}`,
1471
+ className: `${label ? "space-y-2" : ""} group relative ${containerClassName}`,
1411
1472
  children: [
1412
1473
  label && /* @__PURE__ */ jsxs13(
1413
1474
  "label",
@@ -1416,172 +1477,246 @@ var SelectContent = ({
1416
1477
  style: { color: isFocused || isOpen ? primaryColor : void 0 },
1417
1478
  children: [
1418
1479
  label,
1419
- props.required && /* @__PURE__ */ jsx18("span", { className: "text-red-500 ml-1", children: "*" })
1480
+ required && /* @__PURE__ */ jsx18("span", { className: "text-red-500 ml-1", children: "*" })
1420
1481
  ]
1421
1482
  }
1422
1483
  ),
1423
- /* @__PURE__ */ jsxs13("div", { className: "relative", ref: dropdownAnchorRef, children: [
1424
- /* @__PURE__ */ jsxs13(
1425
- "div",
1484
+ hasChildren ? children : /* @__PURE__ */ jsxs13(Fragment3, { children: [
1485
+ /* @__PURE__ */ jsx18(
1486
+ SelectTrigger,
1426
1487
  {
1427
- id: props.id,
1428
- 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}`,
1429
- style: variant === "default" ? {
1430
- borderColor: isFocused || isOpen ? primaryColor : void 0,
1431
- boxShadow: isFocused || isOpen ? `${primaryColor}33 0px 0px 0px 2px` : void 0,
1432
- backgroundColor: isFocused || isOpen ? "var(--tw-colors-white, white)" : void 0
1433
- } : void 0,
1434
- onClick: () => {
1435
- if (props.disabled) return;
1436
- if (Date.now() - lastFocusTime.current < 150) {
1437
- return;
1438
- }
1439
- setIsOpen(!isOpen);
1440
- setIsFocused(true);
1441
- onFocus?.(null);
1442
- },
1443
- onKeyDown: (e) => {
1444
- if (e.key === "Enter" || e.key === " ") {
1445
- e.preventDefault();
1446
- if (props.disabled) return;
1447
- setIsOpen(!isOpen);
1448
- setIsFocused(true);
1449
- } else if (e.key === "ArrowDown" || e.key === "ArrowUp") {
1450
- e.preventDefault();
1451
- setIsOpen(true);
1452
- }
1453
- },
1454
- onFocus: () => {
1455
- setIsFocused(true);
1456
- setIsOpen(true);
1457
- lastFocusTime.current = Date.now();
1458
- },
1459
- tabIndex: props.disabled ? -1 : 0,
1460
- onBlur: (e) => {
1461
- if (!dropdownContentRef.current?.contains(e.relatedTarget) && !containerRef.current?.contains(e.relatedTarget)) {
1462
- setIsOpen(false);
1463
- setIsFocused(false);
1464
- fieldInternalProps?.onBlur?.();
1465
- onBlur?.(null);
1466
- }
1467
- },
1468
- children: [
1469
- icon && /* @__PURE__ */ jsx18(
1470
- "div",
1471
- {
1472
- className: `pl-2.5 pr-2 flex items-center transition-colors duration-200`,
1473
- style: { color: isFocused || isOpen ? primaryColor : "#9ca3af" },
1474
- children: icon
1475
- }
1476
- ),
1477
- /* @__PURE__ */ jsx18(
1478
- "div",
1479
- {
1480
- className: `flex-1 truncate text-sm ${icon ? "" : "pl-2.5"} ${!currentValue && currentValue !== 0 && currentValue !== false ? "text-gray-400 dark:text-zinc-500" : ""}`,
1481
- children: displayValue
1482
- }
1483
- ),
1484
- /* @__PURE__ */ jsx18("div", { className: "pr-2.5 flex items-center gap-1 shrink-0", children: /* @__PURE__ */ jsx18(
1485
- ChevronDown2,
1486
- {
1487
- className: `h-4 w-4 text-gray-400 transition-transform ${isOpen ? "rotate-180" : ""}`
1488
- }
1489
- ) })
1490
- ]
1488
+ id,
1489
+ icon,
1490
+ placeholder,
1491
+ variant,
1492
+ className,
1493
+ ...props
1491
1494
  }
1492
1495
  ),
1493
- isOpen && typeof document !== "undefined" && createPortal(
1494
- /* @__PURE__ */ jsx18(
1495
- "div",
1496
- {
1497
- ref: dropdownContentRef,
1498
- 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",
1499
- style: dropdownStyle,
1500
- children: /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-0.5", children: [
1501
- options.map((option, index) => {
1502
- const isSelected = currentValue === option.value;
1503
- return /* @__PURE__ */ jsxs13(
1504
- "button",
1505
- {
1506
- type: "button",
1507
- disabled: option.disabled,
1508
- 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"}`,
1509
- style: isSelected && !option.disabled && primaryColor ? {
1510
- color: primaryColor
1511
- } : void 0,
1512
- onClick: (e) => {
1513
- e.stopPropagation();
1514
- handleSelect(option);
1515
- },
1516
- children: [
1517
- /* @__PURE__ */ jsx18("span", { className: "whitespace-nowrap truncate flex-1", children: option.label }),
1518
- isSelected && /* @__PURE__ */ jsx18(
1519
- Check2,
1520
- {
1521
- className: "h-4 w-4 shrink-0 ml-2",
1522
- style: { color: primaryColor }
1523
- }
1524
- )
1525
- ]
1526
- },
1527
- String(option.value) || index
1528
- );
1529
- }),
1530
- options.length === 0 && /* @__PURE__ */ jsx18("div", { className: "p-3 text-center text-sm text-gray-500", children: "No options available" })
1531
- ] })
1532
- }
1533
- ),
1534
- document.body
1535
- )
1496
+ allOptions && allOptions.length > 0 && /* @__PURE__ */ jsx18(SelectContent, { children: allOptions.map((opt, index) => /* @__PURE__ */ jsx18(
1497
+ SelectItem,
1498
+ {
1499
+ value: opt.value,
1500
+ label: opt.label,
1501
+ disabled: opt.disabled
1502
+ },
1503
+ String(opt.value) || index
1504
+ )) })
1536
1505
  ] }),
1537
- message && /* @__PURE__ */ jsx18("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
1506
+ /* @__PURE__ */ jsx18("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ jsx18("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
1538
1507
  ]
1539
1508
  }
1540
- );
1509
+ ) });
1541
1510
  };
1542
- var Select = forwardRef3(
1543
- (props, ref) => {
1544
- const { form, name, onChange, value } = props;
1545
- if (form && name) {
1546
- return /* @__PURE__ */ jsx18(
1547
- Controller3,
1548
- {
1549
- name,
1550
- control: form.control,
1551
- render: ({
1552
- field: {
1553
- onChange: formOnChange,
1554
- value: formValue,
1555
- ref: fieldRef,
1556
- onBlur
1557
- }
1558
- }) => /* @__PURE__ */ jsx18(
1559
- SelectContent,
1511
+ var SelectTrigger = forwardRef3(
1512
+ ({
1513
+ className = "",
1514
+ variant = "default",
1515
+ icon,
1516
+ placeholder = "Select...",
1517
+ id,
1518
+ children,
1519
+ ...props
1520
+ }, ref) => {
1521
+ const {
1522
+ isOpen,
1523
+ setIsOpen,
1524
+ isFocused,
1525
+ setIsFocused,
1526
+ primaryColor,
1527
+ dropdownAnchorRef,
1528
+ dropdownContentRef,
1529
+ containerRef,
1530
+ selectedValue,
1531
+ options,
1532
+ fieldInternalProps,
1533
+ disabled
1534
+ } = useSelectContext();
1535
+ const lastFocusTime = useRef3(0);
1536
+ const displayOption = options.find((o) => o.value === selectedValue);
1537
+ const displayValue = displayOption ? displayOption.label : selectedValue != null && selectedValue !== "" ? String(selectedValue) : placeholder;
1538
+ return /* @__PURE__ */ jsx18("div", { className: "relative", ref: dropdownAnchorRef, children: /* @__PURE__ */ jsx18(
1539
+ "div",
1540
+ {
1541
+ id,
1542
+ 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}`,
1543
+ style: variant === "default" ? {
1544
+ borderColor: isFocused || isOpen ? primaryColor : void 0,
1545
+ boxShadow: isFocused || isOpen ? `${primaryColor}33 0px 0px 0px 2px` : void 0,
1546
+ backgroundColor: isFocused || isOpen ? "var(--tw-colors-white, white)" : void 0
1547
+ } : void 0,
1548
+ onMouseDown: (e) => {
1549
+ if (disabled) return;
1550
+ e.preventDefault();
1551
+ },
1552
+ onClick: (e) => {
1553
+ if (disabled) return;
1554
+ if (Date.now() - lastFocusTime.current < 150) return;
1555
+ e.stopPropagation();
1556
+ setIsOpen(!isOpen);
1557
+ setIsFocused(true);
1558
+ },
1559
+ onKeyDown: (e) => {
1560
+ if (e.key === "Enter" || e.key === " ") {
1561
+ e.preventDefault();
1562
+ e.stopPropagation();
1563
+ if (disabled) return;
1564
+ setIsOpen(!isOpen);
1565
+ setIsFocused(true);
1566
+ } else if (e.key === "ArrowDown" || e.key === "ArrowUp") {
1567
+ e.preventDefault();
1568
+ e.stopPropagation();
1569
+ setIsOpen(true);
1570
+ } else if (e.key === "Escape") {
1571
+ setIsOpen(false);
1572
+ }
1573
+ },
1574
+ onFocus: () => {
1575
+ setIsFocused(true);
1576
+ lastFocusTime.current = Date.now();
1577
+ },
1578
+ tabIndex: disabled ? -1 : 0,
1579
+ onBlur: (e) => {
1580
+ if (!dropdownContentRef.current?.contains(e.relatedTarget) && !containerRef.current?.contains(e.relatedTarget)) {
1581
+ setIsFocused(false);
1582
+ setIsOpen(false);
1583
+ fieldInternalProps?.onBlur?.();
1584
+ }
1585
+ },
1586
+ ...props,
1587
+ children: children ? children : /* @__PURE__ */ jsxs13(Fragment3, { children: [
1588
+ icon && /* @__PURE__ */ jsx18(
1589
+ "div",
1560
1590
  {
1561
- ...props,
1562
- currentValue: formValue,
1563
- onChangeHandler: (val) => {
1564
- formOnChange(val);
1565
- onChange?.(val);
1591
+ className: `pl-2.5 pr-2 flex items-center transition-colors duration-200`,
1592
+ style: {
1593
+ color: isFocused || isOpen ? primaryColor : "#9ca3af"
1566
1594
  },
1567
- fieldInternalProps: { ref: fieldRef, onBlur }
1595
+ children: icon
1568
1596
  }
1569
- )
1597
+ ),
1598
+ /* @__PURE__ */ jsx18(
1599
+ "div",
1600
+ {
1601
+ className: `flex-1 truncate text-sm ${icon ? "" : "pl-2.5"} ${!selectedValue && selectedValue !== 0 && selectedValue !== false ? "text-gray-400 dark:text-zinc-500" : ""}`,
1602
+ children: displayValue
1603
+ }
1604
+ ),
1605
+ /* @__PURE__ */ jsx18("div", { className: "pr-2.5 flex items-center gap-1 shrink-0", children: /* @__PURE__ */ jsx18(
1606
+ ChevronDown2,
1607
+ {
1608
+ className: `h-4 w-4 text-gray-400 transition-transform ${isOpen ? "rotate-180" : ""}`
1609
+ }
1610
+ ) })
1611
+ ] })
1612
+ }
1613
+ ) });
1614
+ }
1615
+ );
1616
+ SelectTrigger.displayName = "SelectTrigger";
1617
+ var SelectContent = forwardRef3(
1618
+ ({ children, className = "", style, ...props }, ref) => {
1619
+ const { isOpen, setIsOpen, dropdownAnchorRef, dropdownContentRef } = useSelectContext();
1620
+ const [dropdownStyle, setDropdownStyle] = useState9({});
1621
+ const updateDropdownPosition = () => {
1622
+ if (dropdownAnchorRef.current) {
1623
+ const rect = dropdownAnchorRef.current.getBoundingClientRect();
1624
+ const newStyle = {
1625
+ position: "fixed",
1626
+ top: `${rect.bottom + 4}px`,
1627
+ left: `${rect.left}px`,
1628
+ width: `${rect.width}px`,
1629
+ zIndex: 999999
1630
+ };
1631
+ if (rect.bottom + 240 > window.innerHeight) {
1632
+ newStyle.top = "auto";
1633
+ newStyle.bottom = `${window.innerHeight - rect.top + 4}px`;
1570
1634
  }
1571
- );
1572
- }
1573
- return /* @__PURE__ */ jsx18(
1574
- SelectContent,
1635
+ setDropdownStyle(newStyle);
1636
+ }
1637
+ };
1638
+ useEffect6(() => {
1639
+ if (isOpen) {
1640
+ updateDropdownPosition();
1641
+ window.addEventListener("scroll", updateDropdownPosition, true);
1642
+ window.addEventListener("resize", updateDropdownPosition);
1643
+ return () => {
1644
+ window.removeEventListener("scroll", updateDropdownPosition, true);
1645
+ window.removeEventListener("resize", updateDropdownPosition);
1646
+ };
1647
+ }
1648
+ }, [isOpen]);
1649
+ if (!isOpen || typeof document === "undefined") return null;
1650
+ return createPortal(
1651
+ /* @__PURE__ */ jsx18(
1652
+ "div",
1653
+ {
1654
+ ref: dropdownContentRef,
1655
+ 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}`,
1656
+ style: { ...dropdownStyle, ...style },
1657
+ onMouseDown: (e) => e.stopPropagation(),
1658
+ ...props,
1659
+ children: /* @__PURE__ */ jsx18("div", { className: "flex flex-col gap-0.5", children: React6.Children.count(children) === 0 ? /* @__PURE__ */ jsx18("div", { className: "p-3 text-center text-sm text-gray-500", children: "No options available" }) : children })
1660
+ }
1661
+ ),
1662
+ document.body
1663
+ );
1664
+ }
1665
+ );
1666
+ SelectContent.displayName = "SelectContent";
1667
+ var SelectItem = forwardRef3(
1668
+ ({ value, label, disabled, children, className = "", ...props }, ref) => {
1669
+ const {
1670
+ selectedValue,
1671
+ setSelectedValue,
1672
+ setIsOpen,
1673
+ primaryColor,
1674
+ fieldInternalProps,
1675
+ registerOption
1676
+ } = useSelectContext();
1677
+ const isSelected = selectedValue === value;
1678
+ const displayLabel = label || children || value;
1679
+ useEffect6(() => {
1680
+ if (value !== void 0) {
1681
+ registerOption({ value, label: String(displayLabel), disabled });
1682
+ }
1683
+ }, [value, displayLabel, disabled]);
1684
+ const handleSelect = () => {
1685
+ if (disabled) return;
1686
+ setSelectedValue(value);
1687
+ setIsOpen(false);
1688
+ fieldInternalProps?.onBlur?.();
1689
+ };
1690
+ return /* @__PURE__ */ jsxs13(
1691
+ "button",
1575
1692
  {
1693
+ ref,
1694
+ type: "button",
1695
+ disabled,
1696
+ 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}`,
1697
+ style: isSelected && !disabled && primaryColor ? { color: primaryColor } : void 0,
1698
+ onMouseDown: (e) => e.stopPropagation(),
1699
+ onClick: (e) => {
1700
+ e.stopPropagation();
1701
+ e.preventDefault();
1702
+ handleSelect();
1703
+ },
1576
1704
  ...props,
1577
- currentValue: value,
1578
- onChangeHandler: onChange || (() => {
1579
- })
1705
+ children: [
1706
+ /* @__PURE__ */ jsx18("span", { className: "whitespace-nowrap truncate flex-1", children: children || label }),
1707
+ isSelected && /* @__PURE__ */ jsx18(
1708
+ Check2,
1709
+ {
1710
+ className: "h-4 w-4 shrink-0 ml-2",
1711
+ style: { color: primaryColor }
1712
+ }
1713
+ )
1714
+ ]
1580
1715
  }
1581
1716
  );
1582
1717
  }
1583
1718
  );
1584
- Select.displayName = "Select";
1719
+ SelectItem.displayName = "SelectItem";
1585
1720
 
1586
1721
  // src/components/Fields/textArea.tsx
1587
1722
  import { forwardRef as forwardRef4, useState as useState10 } from "react";
@@ -1612,7 +1747,7 @@ var Textarea = forwardRef4(
1612
1747
  const errorObj = name.split(".").reduce((acc, current) => acc?.[current], errors);
1613
1748
  message = errorObj?.message;
1614
1749
  }
1615
- const renderInput = (inputProps, ref2) => /* @__PURE__ */ jsxs14("div", { className: `space-y-2 group w-full! ${containerClassName}`, children: [
1750
+ const renderInput = (inputProps, ref2) => /* @__PURE__ */ jsxs14("div", { className: `space-y-2 group w-full! relative ${containerClassName}`, children: [
1616
1751
  /* @__PURE__ */ jsxs14(
1617
1752
  "label",
1618
1753
  {
@@ -1646,7 +1781,7 @@ var Textarea = forwardRef4(
1646
1781
  ...inputProps
1647
1782
  }
1648
1783
  ) }),
1649
- message && /* @__PURE__ */ jsx19("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
1784
+ /* @__PURE__ */ jsx19("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ jsx19("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
1650
1785
  ] });
1651
1786
  if (form && name) {
1652
1787
  return /* @__PURE__ */ jsx19(
@@ -1676,7 +1811,14 @@ var Textarea = forwardRef4(
1676
1811
  );
1677
1812
 
1678
1813
  // src/components/Fields/searchApi.tsx
1679
- import { useState as useState12, useEffect as useEffect7, useRef as useRef4, forwardRef as forwardRef5 } from "react";
1814
+ import React7, {
1815
+ createContext as createContext4,
1816
+ useContext as useContext4,
1817
+ useState as useState12,
1818
+ useRef as useRef4,
1819
+ useEffect as useEffect7,
1820
+ forwardRef as forwardRef5
1821
+ } from "react";
1680
1822
  import { createPortal as createPortal2 } from "react-dom";
1681
1823
  import { Search, Loader2 as Loader22, ChevronDown as ChevronDown3, Check as Check3, X as X2 } from "lucide-react";
1682
1824
 
@@ -1848,28 +1990,78 @@ var useApis_default = useApi;
1848
1990
 
1849
1991
  // src/components/Fields/searchApi.tsx
1850
1992
  import { Controller as Controller5 } from "react-hook-form";
1851
- import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
1852
- var SearchApiContent = ({
1853
- label,
1854
- api,
1855
- placeholder = "Search...",
1993
+ import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
1994
+ var SearchApiContext = createContext4(
1995
+ void 0
1996
+ );
1997
+ var useSearchApiContext = () => {
1998
+ const context = useContext4(SearchApiContext);
1999
+ if (!context)
2000
+ throw new Error(
2001
+ "SearchApi components must be used within a SearchApiProvider"
2002
+ );
2003
+ return context;
2004
+ };
2005
+ var SearchApi = forwardRef5(
2006
+ (props, _) => {
2007
+ const { form, name, onChange, value, children } = props;
2008
+ if (form && name) {
2009
+ return /* @__PURE__ */ jsx20(
2010
+ Controller5,
2011
+ {
2012
+ name,
2013
+ control: form.control,
2014
+ render: ({ field }) => /* @__PURE__ */ jsx20(
2015
+ SearchApiRoot,
2016
+ {
2017
+ ...props,
2018
+ currentValue: field.value !== void 0 && field.value !== "" ? field.value : value,
2019
+ onChangeHandler: (val) => {
2020
+ field.onChange(val);
2021
+ if (onChange) onChange(val);
2022
+ },
2023
+ fieldInternalProps: { ref: field.ref, onBlur: field.onBlur },
2024
+ children
2025
+ }
2026
+ )
2027
+ }
2028
+ );
2029
+ }
2030
+ return /* @__PURE__ */ jsx20(
2031
+ SearchApiRoot,
2032
+ {
2033
+ ...props,
2034
+ currentValue: value,
2035
+ onChangeHandler: onChange || (() => {
2036
+ }),
2037
+ children
2038
+ }
2039
+ );
2040
+ }
2041
+ );
2042
+ SearchApi.displayName = "SearchApi";
2043
+ var SearchApiRoot = ({
2044
+ children,
1856
2045
  currentValue,
1857
2046
  onChangeHandler,
2047
+ form,
2048
+ name,
2049
+ obj,
2050
+ error,
2051
+ api = "",
1858
2052
  queryKey = "search",
1859
2053
  labelKey = "name",
1860
2054
  valueKey = "_id",
1861
- error,
1862
- containerClassName = "",
1863
- className = "",
1864
- disabled,
1865
- name,
1866
- obj,
1867
- form,
1868
2055
  filter = [],
1869
2056
  required,
1870
2057
  v = 2,
1871
2058
  variant = "default",
1872
2059
  fieldInternalProps,
2060
+ label,
2061
+ containerClassName = "",
2062
+ placeholder = "Search...",
2063
+ disabled,
2064
+ className = "",
1873
2065
  ...props
1874
2066
  }) => {
1875
2067
  const [searchTerm, setSearchTerm] = useState12("");
@@ -1883,51 +2075,13 @@ var SearchApiContent = ({
1883
2075
  const [hasAttemptedHydration, setHasAttemptedHydration] = useState12(false);
1884
2076
  const containerRef = useRef4(null);
1885
2077
  const dropdownAnchorRef = useRef4(null);
1886
- const dropdownRef = useRef4(null);
2078
+ const dropdownContentRef = useRef4(null);
1887
2079
  const inputRef = useRef4(null);
1888
2080
  const prevApiRef = useRef4(api);
1889
- const [dropdownStyle, setDropdownStyle] = useState12({});
1890
- const updateDropdownPosition = () => {
1891
- if (dropdownAnchorRef.current) {
1892
- const rect = dropdownAnchorRef.current.getBoundingClientRect();
1893
- const style = {
1894
- position: "fixed",
1895
- top: `${rect.bottom + 4}px`,
1896
- left: `${rect.left}px`,
1897
- width: `${rect.width}px`,
1898
- zIndex: 999999
1899
- };
1900
- if (rect.bottom + 240 > window.innerHeight) {
1901
- style.top = "auto";
1902
- style.bottom = `${window.innerHeight - rect.top + 4}px`;
1903
- }
1904
- setDropdownStyle(style);
1905
- }
1906
- };
1907
- useEffect7(() => {
1908
- if (isOpen) {
1909
- updateDropdownPosition();
1910
- window.addEventListener("scroll", updateDropdownPosition, true);
1911
- window.addEventListener("resize", updateDropdownPosition);
1912
- return () => {
1913
- window.removeEventListener("scroll", updateDropdownPosition, true);
1914
- window.removeEventListener("resize", updateDropdownPosition);
1915
- };
1916
- }
1917
- }, [isOpen]);
1918
- const setInputRef = (element) => {
1919
- inputRef.current = element;
1920
- if (fieldInternalProps?.ref) {
1921
- if (typeof fieldInternalProps.ref === "function") {
1922
- fieldInternalProps.ref(element);
1923
- } else {
1924
- fieldInternalProps.ref.current = element;
1925
- }
1926
- }
1927
- };
1928
2081
  const { get, isLoading, error: errorMessage } = useApis_default();
1929
2082
  const fetchOptions = async (query) => {
1930
2083
  try {
2084
+ if (!api) return;
1931
2085
  const params = {};
1932
2086
  if (query) params[queryKey] = query;
1933
2087
  const response = await get({
@@ -1991,7 +2145,10 @@ var SearchApiContent = ({
1991
2145
  if (found) {
1992
2146
  setSelectedObject(found);
1993
2147
  if (form && obj) {
1994
- form.setValue(obj, found);
2148
+ form.setValue(obj, found, {
2149
+ shouldValidate: true,
2150
+ shouldDirty: true
2151
+ });
1995
2152
  }
1996
2153
  }
1997
2154
  }
@@ -2024,7 +2181,7 @@ var SearchApiContent = ({
2024
2181
  useEffect7(() => {
2025
2182
  const handleClickOutside = (event) => {
2026
2183
  const target = event.target;
2027
- if (containerRef.current && !containerRef.current.contains(target) && !(dropdownRef.current && dropdownRef.current.contains(target))) {
2184
+ if (containerRef.current && !containerRef.current.contains(target) && !(dropdownContentRef.current && dropdownContentRef.current.contains(target))) {
2028
2185
  setIsOpen(false);
2029
2186
  setIsFocused(false);
2030
2187
  setSearchTerm("");
@@ -2045,42 +2202,21 @@ var SearchApiContent = ({
2045
2202
  return currentValue || "";
2046
2203
  };
2047
2204
  const handleSelect = (option) => {
2048
- const value = getOptionValue(option);
2205
+ const val = getOptionValue(option);
2206
+ setIsOpen(false);
2207
+ inputRef.current?.blur();
2049
2208
  setSelectedObject(option);
2050
- onChangeHandler(value);
2209
+ setTimeout(() => {
2210
+ onChangeHandler(val);
2211
+ }, 0);
2051
2212
  if (form) {
2052
2213
  if (obj) form.setValue(obj, option);
2053
2214
  if (name) form.clearErrors(name);
2054
2215
  }
2055
- setIsOpen(false);
2056
2216
  setSearchTerm("");
2057
2217
  setActiveIndex(-1);
2058
2218
  fieldInternalProps?.onBlur?.();
2059
2219
  };
2060
- const handleKeyDown = (e) => {
2061
- if (!isOpen) {
2062
- if (e.key === "ArrowDown" || e.key === "Enter") setIsOpen(true);
2063
- return;
2064
- }
2065
- switch (e.key) {
2066
- case "ArrowDown":
2067
- e.preventDefault();
2068
- setActiveIndex((prev) => prev < options.length - 1 ? prev + 1 : prev);
2069
- break;
2070
- case "ArrowUp":
2071
- e.preventDefault();
2072
- setActiveIndex((prev) => prev > 0 ? prev - 1 : prev);
2073
- break;
2074
- case "Enter":
2075
- e.preventDefault();
2076
- if (activeIndex >= 0 && activeIndex < options.length)
2077
- handleSelect(options[activeIndex]);
2078
- break;
2079
- case "Escape":
2080
- setIsOpen(false);
2081
- break;
2082
- }
2083
- };
2084
2220
  const clearSelection = (e) => {
2085
2221
  e.stopPropagation();
2086
2222
  if (form) {
@@ -2102,13 +2238,7 @@ var SearchApiContent = ({
2102
2238
  const filteredOptions = options.filter(
2103
2239
  (option) => !filter.includes(getOptionValue(option))
2104
2240
  );
2105
- useEffect7(() => {
2106
- if (form && name && !form.watch(name)) {
2107
- form.setValue(name, void 0);
2108
- if (obj) form.setValue(obj, void 0);
2109
- }
2110
- }, [form, name, obj]);
2111
- let message = error;
2241
+ let message = error || errorMessage;
2112
2242
  if (form && name) {
2113
2243
  const {
2114
2244
  formState: { errors }
@@ -2120,11 +2250,46 @@ var SearchApiContent = ({
2120
2250
  }
2121
2251
  message = currentError?.message || message;
2122
2252
  }
2123
- return /* @__PURE__ */ jsxs15(
2253
+ const valueCtx = {
2254
+ isOpen,
2255
+ setIsOpen,
2256
+ searchTerm,
2257
+ setSearchTerm,
2258
+ selectedValue: currentValue,
2259
+ setSelectedValue: onChangeHandler,
2260
+ // alias
2261
+ activeIndex,
2262
+ setActiveIndex,
2263
+ isFocused,
2264
+ setIsFocused,
2265
+ dropdownAnchorRef,
2266
+ dropdownContentRef,
2267
+ containerRef,
2268
+ inputRef,
2269
+ primaryColor,
2270
+ options: filteredOptions,
2271
+ setOptions,
2272
+ fieldInternalProps,
2273
+ disabled,
2274
+ isLoading,
2275
+ clearSelection,
2276
+ handleSelect,
2277
+ getDisplayValue,
2278
+ placeholder,
2279
+ variant,
2280
+ labelKey,
2281
+ valueKey,
2282
+ form,
2283
+ name,
2284
+ obj,
2285
+ error: message
2286
+ };
2287
+ const hasChildren = React7.Children.count(children) > 0;
2288
+ return /* @__PURE__ */ jsx20(SearchApiContext.Provider, { value: valueCtx, children: /* @__PURE__ */ jsxs15(
2124
2289
  "div",
2125
2290
  {
2126
2291
  ref: containerRef,
2127
- className: `${label ? "space-y-2" : ""} group ${containerClassName}`,
2292
+ className: `${label ? "space-y-2" : ""} group relative ${containerClassName}`,
2128
2293
  children: [
2129
2294
  label && /* @__PURE__ */ jsxs15(
2130
2295
  "label",
@@ -2137,153 +2302,280 @@ var SearchApiContent = ({
2137
2302
  ]
2138
2303
  }
2139
2304
  ),
2140
- /* @__PURE__ */ jsxs15("div", { className: "relative", ref: dropdownAnchorRef, children: [
2141
- /* @__PURE__ */ jsxs15(
2305
+ hasChildren ? children : /* @__PURE__ */ jsxs15(Fragment4, { children: [
2306
+ /* @__PURE__ */ jsx20(SearchApiTrigger, { className, children: /* @__PURE__ */ jsx20(SearchApiInput, { ...props }) }),
2307
+ /* @__PURE__ */ jsx20(SearchApiContent, { children: filteredOptions.map((opt, index) => /* @__PURE__ */ jsx20(
2308
+ SearchApiItem,
2309
+ {
2310
+ option: opt,
2311
+ index
2312
+ },
2313
+ String(getOptionValue(opt)) || index
2314
+ )) })
2315
+ ] }),
2316
+ /* @__PURE__ */ jsx20("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ jsx20("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
2317
+ ]
2318
+ }
2319
+ ) });
2320
+ };
2321
+ var SearchApiTrigger = forwardRef5(
2322
+ ({ className = "", children, ...props }, ref) => {
2323
+ const {
2324
+ isOpen,
2325
+ setIsOpen,
2326
+ isFocused,
2327
+ setIsFocused,
2328
+ primaryColor,
2329
+ dropdownAnchorRef,
2330
+ disabled,
2331
+ isLoading,
2332
+ clearSelection,
2333
+ selectedValue,
2334
+ variant,
2335
+ inputRef
2336
+ } = useSearchApiContext();
2337
+ return /* @__PURE__ */ jsx20("div", { className: "relative", ref: dropdownAnchorRef, children: /* @__PURE__ */ jsxs15(
2338
+ "div",
2339
+ {
2340
+ 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}`,
2341
+ style: variant === "default" ? {
2342
+ borderColor: isFocused || isOpen ? primaryColor : void 0,
2343
+ boxShadow: isFocused || isOpen ? `${primaryColor}33 0px 0px 0px 2px` : void 0
2344
+ } : void 0,
2345
+ onClick: () => {
2346
+ if (disabled) return;
2347
+ inputRef.current?.focus();
2348
+ setIsOpen(true);
2349
+ },
2350
+ ...props,
2351
+ children: [
2352
+ /* @__PURE__ */ jsx20(
2142
2353
  "div",
2143
2354
  {
2144
- 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}`,
2145
- style: variant === "default" ? {
2146
- borderColor: isFocused || isOpen ? primaryColor : void 0,
2147
- boxShadow: isFocused || isOpen ? `${primaryColor}33 0px 0px 0px 2px` : void 0
2148
- } : void 0,
2149
- onClick: () => {
2150
- if (disabled) return;
2151
- inputRef.current?.focus();
2152
- setIsOpen(true);
2153
- },
2154
- children: [
2155
- /* @__PURE__ */ jsx20(
2156
- "div",
2157
- {
2158
- className: `${variant === "ghost" ? "pl-0" : "pl-2.5"} text-gray-400`,
2159
- children: /* @__PURE__ */ jsx20(Search, { className: "h-4 w-4" })
2160
- }
2161
- ),
2162
- /* @__PURE__ */ jsxs15("div", { className: "flex-1 relative ms-2", children: [
2163
- !isOpen && currentValue && /* @__PURE__ */ jsx20("div", { className: "absolute inset-0 flex items-center ms-1 truncate select-none", children: getDisplayValue() }),
2164
- /* @__PURE__ */ jsx20(
2165
- "input",
2166
- {
2167
- ref: setInputRef,
2168
- type: "text",
2169
- 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"}`,
2170
- placeholder: !currentValue ? placeholder : "",
2171
- value: searchTerm,
2172
- onChange: (e) => setSearchTerm(e.target.value),
2173
- onFocus: () => {
2174
- setIsFocused(true);
2175
- setIsOpen(true);
2176
- },
2177
- onKeyDown: handleKeyDown,
2178
- disabled,
2179
- ...props
2180
- }
2181
- )
2182
- ] }),
2183
- /* @__PURE__ */ jsx20("div", { className: "pr-2.5 w-16! flex items-center gap-1 shrink-0 min-w-10 justify-end", children: isLoading ? /* @__PURE__ */ jsx20(Loader22, { className: "h-4 w-4 animate-spin text-blue-500 shrink-0" }) : /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1", children: [
2184
- currentValue && !disabled && /* @__PURE__ */ jsx20(
2185
- "button",
2186
- {
2187
- onClick: clearSelection,
2188
- type: "button",
2189
- 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",
2190
- children: /* @__PURE__ */ jsx20(X2, { className: "h-3 w-3" })
2191
- }
2192
- ),
2193
- /* @__PURE__ */ jsx20(
2194
- ChevronDown3,
2195
- {
2196
- className: `h-4 w-4 text-gray-400 transition-transform ${isOpen ? "rotate-180" : ""}`
2197
- }
2198
- )
2199
- ] }) })
2200
- ]
2355
+ className: `${variant === "ghost" ? "pl-0" : "pl-2.5"} text-gray-400`,
2356
+ children: /* @__PURE__ */ jsx20(Search, { className: "h-4 w-4" })
2201
2357
  }
2202
2358
  ),
2203
- isOpen && typeof document !== "undefined" && createPortal2(
2204
- /* @__PURE__ */ jsx20(
2205
- "div",
2359
+ /* @__PURE__ */ jsx20("div", { className: "flex-1 relative ms-2", children }),
2360
+ /* @__PURE__ */ jsx20("div", { className: "pr-2.5 w-16! flex items-center gap-1 shrink-0 min-w-10 justify-end", children: isLoading ? /* @__PURE__ */ jsx20(Loader22, { className: "h-4 w-4 animate-spin text-blue-500 shrink-0" }) : /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1", children: [
2361
+ selectedValue && !disabled && /* @__PURE__ */ jsx20(
2362
+ "button",
2206
2363
  {
2207
- ref: dropdownRef,
2208
- 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",
2209
- style: dropdownStyle,
2210
- children: isLoading && options.length === 0 ? /* @__PURE__ */ jsxs15("div", { className: "p-4 text-center text-sm text-gray-500", children: [
2211
- /* @__PURE__ */ jsx20(Loader22, { className: "h-5 w-5 animate-spin mx-auto mb-2" }),
2212
- "Loading options..."
2213
- ] }) : filteredOptions.length > 0 ? /* @__PURE__ */ jsx20("div", { className: "py-1", children: filteredOptions.map((option, index) => {
2214
- const optValue = getOptionValue(option);
2215
- const isSelected = currentValue === optValue;
2216
- const isHighlighted = index === activeIndex;
2217
- return /* @__PURE__ */ jsxs15(
2218
- "button",
2219
- {
2220
- type: "button",
2221
- 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"}`,
2222
- style: {
2223
- backgroundColor: isSelected ? `${primaryColor}1A` : void 0,
2224
- color: isSelected ? primaryColor : void 0
2225
- },
2226
- onClick: () => handleSelect(option),
2227
- onMouseEnter: () => setActiveIndex(index),
2228
- children: [
2229
- /* @__PURE__ */ jsx20("span", { className: "truncate", children: option[labelKey] }),
2230
- isSelected && /* @__PURE__ */ jsx20(
2231
- Check3,
2232
- {
2233
- className: "h-4 w-4",
2234
- style: { color: primaryColor }
2235
- }
2236
- )
2237
- ]
2238
- },
2239
- optValue || index
2240
- );
2241
- }) }) : /* @__PURE__ */ jsx20("div", { className: "p-4 text-center text-sm text-gray-500", children: errorMessage || (searchTerm ? `No results for "${searchTerm}"` : "No options available") })
2364
+ onClick: clearSelection,
2365
+ type: "button",
2366
+ 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",
2367
+ children: /* @__PURE__ */ jsx20(X2, { className: "h-3 w-3" })
2242
2368
  }
2243
2369
  ),
2244
- document.body
2245
- )
2246
- ] }),
2247
- message && /* @__PURE__ */ jsx20("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
2248
- ]
2249
- }
2250
- );
2251
- };
2252
- var SearchApi = forwardRef5(
2253
- (props, _) => {
2254
- const { form, name, onChange, value } = props;
2255
- if (form && name) {
2256
- return /* @__PURE__ */ jsx20(
2257
- Controller5,
2370
+ /* @__PURE__ */ jsx20(
2371
+ ChevronDown3,
2372
+ {
2373
+ className: `h-4 w-4 text-gray-400 transition-transform ${isOpen ? "rotate-180" : ""}`
2374
+ }
2375
+ )
2376
+ ] }) })
2377
+ ]
2378
+ }
2379
+ ) });
2380
+ }
2381
+ );
2382
+ SearchApiTrigger.displayName = "SearchApiTrigger";
2383
+ var SearchApiInput = forwardRef5(
2384
+ ({ className = "", ...props }, ref) => {
2385
+ const {
2386
+ isOpen,
2387
+ setIsOpen,
2388
+ isFocused,
2389
+ setIsFocused,
2390
+ searchTerm,
2391
+ setSearchTerm,
2392
+ disabled,
2393
+ selectedValue,
2394
+ getDisplayValue,
2395
+ placeholder,
2396
+ variant,
2397
+ activeIndex,
2398
+ setActiveIndex,
2399
+ options,
2400
+ handleSelect,
2401
+ inputRef,
2402
+ fieldInternalProps
2403
+ } = useSearchApiContext();
2404
+ const setInternalInputRef = (element) => {
2405
+ inputRef.current = element;
2406
+ if (fieldInternalProps?.ref) {
2407
+ if (typeof fieldInternalProps.ref === "function") {
2408
+ fieldInternalProps.ref(element);
2409
+ } else {
2410
+ fieldInternalProps.ref.current = element;
2411
+ }
2412
+ }
2413
+ };
2414
+ const handleKeyDown = (e) => {
2415
+ if (!isOpen) {
2416
+ if (e.key === "ArrowDown" || e.key === "Enter") setIsOpen(true);
2417
+ return;
2418
+ }
2419
+ switch (e.key) {
2420
+ case "ArrowDown":
2421
+ e.preventDefault();
2422
+ e.stopPropagation();
2423
+ setActiveIndex(
2424
+ activeIndex < options.length - 1 ? activeIndex + 1 : activeIndex
2425
+ );
2426
+ break;
2427
+ case "ArrowUp":
2428
+ e.preventDefault();
2429
+ e.stopPropagation();
2430
+ setActiveIndex(activeIndex > 0 ? activeIndex - 1 : activeIndex);
2431
+ break;
2432
+ case "Enter":
2433
+ e.preventDefault();
2434
+ e.stopPropagation();
2435
+ if (activeIndex >= 0 && activeIndex < options.length)
2436
+ handleSelect(options[activeIndex]);
2437
+ break;
2438
+ case "Escape":
2439
+ e.preventDefault();
2440
+ e.stopPropagation();
2441
+ setIsOpen(false);
2442
+ break;
2443
+ }
2444
+ };
2445
+ return /* @__PURE__ */ jsxs15(Fragment4, { children: [
2446
+ !isOpen && selectedValue && /* @__PURE__ */ jsx20("div", { className: "absolute inset-0 flex items-center ms-1 truncate select-none", children: getDisplayValue() }),
2447
+ /* @__PURE__ */ jsx20(
2448
+ "input",
2258
2449
  {
2259
- name,
2260
- control: form.control,
2261
- render: ({
2262
- field: { onChange: formOnChange, value: formValue, ref, onBlur }
2263
- }) => /* @__PURE__ */ jsx20(
2264
- SearchApiContent,
2265
- {
2266
- ...props,
2267
- currentValue: formValue,
2268
- onChangeHandler: formOnChange,
2269
- fieldInternalProps: { ref, onBlur }
2270
- }
2271
- )
2450
+ ref: setInternalInputRef,
2451
+ type: "text",
2452
+ 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}`,
2453
+ placeholder: !selectedValue ? placeholder : "",
2454
+ value: searchTerm,
2455
+ onChange: (e) => setSearchTerm(e.target.value),
2456
+ onFocus: () => {
2457
+ setIsFocused(true);
2458
+ setIsOpen(true);
2459
+ },
2460
+ onKeyDown: handleKeyDown,
2461
+ disabled,
2462
+ ...props
2272
2463
  }
2273
- );
2274
- }
2275
- return /* @__PURE__ */ jsx20(
2276
- SearchApiContent,
2464
+ )
2465
+ ] });
2466
+ }
2467
+ );
2468
+ SearchApiInput.displayName = "SearchApiInput";
2469
+ var SearchApiContent = forwardRef5(
2470
+ ({ children, className = "", style, ...props }, ref) => {
2471
+ const {
2472
+ isOpen,
2473
+ setIsOpen,
2474
+ dropdownAnchorRef,
2475
+ dropdownContentRef,
2476
+ isLoading,
2477
+ searchTerm,
2478
+ options,
2479
+ error
2480
+ } = useSearchApiContext();
2481
+ const [dropdownStyle, setDropdownStyle] = useState12({});
2482
+ const updateDropdownPosition = () => {
2483
+ if (dropdownAnchorRef.current) {
2484
+ const rect = dropdownAnchorRef.current.getBoundingClientRect();
2485
+ const newStyle = {
2486
+ position: "fixed",
2487
+ top: `${rect.bottom + 4}px`,
2488
+ left: `${rect.left}px`,
2489
+ width: `${rect.width}px`,
2490
+ zIndex: 999999
2491
+ };
2492
+ if (rect.bottom + 240 > window.innerHeight) {
2493
+ newStyle.top = "auto";
2494
+ newStyle.bottom = `${window.innerHeight - rect.top + 4}px`;
2495
+ }
2496
+ setDropdownStyle(newStyle);
2497
+ }
2498
+ };
2499
+ useEffect7(() => {
2500
+ if (isOpen) {
2501
+ updateDropdownPosition();
2502
+ window.addEventListener("scroll", updateDropdownPosition, true);
2503
+ window.addEventListener("resize", updateDropdownPosition);
2504
+ return () => {
2505
+ window.removeEventListener("scroll", updateDropdownPosition, true);
2506
+ window.removeEventListener("resize", updateDropdownPosition);
2507
+ };
2508
+ }
2509
+ }, [isOpen]);
2510
+ if (!isOpen || typeof document === "undefined") return null;
2511
+ return createPortal2(
2512
+ /* @__PURE__ */ jsx20(
2513
+ "div",
2514
+ {
2515
+ ref: dropdownContentRef,
2516
+ 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}`,
2517
+ style: { ...dropdownStyle, ...style },
2518
+ onMouseDown: (e) => e.stopPropagation(),
2519
+ ...props,
2520
+ children: isLoading && options.length === 0 ? /* @__PURE__ */ jsxs15("div", { className: "p-4 text-center text-sm text-gray-500", children: [
2521
+ /* @__PURE__ */ jsx20(Loader22, { className: "h-5 w-5 animate-spin mx-auto mb-2" }),
2522
+ "Loading options..."
2523
+ ] }) : React7.Children.count(children) > 0 ? /* @__PURE__ */ jsx20("div", { className: "py-1", children }) : /* @__PURE__ */ jsx20("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" })
2524
+ }
2525
+ ),
2526
+ document.body
2527
+ );
2528
+ }
2529
+ );
2530
+ SearchApiContent.displayName = "SearchApiContent";
2531
+ var SearchApiItem = forwardRef5(
2532
+ ({ option, index, className = "", ...props }, ref) => {
2533
+ const {
2534
+ selectedValue,
2535
+ activeIndex,
2536
+ setActiveIndex,
2537
+ handleSelect,
2538
+ primaryColor,
2539
+ labelKey,
2540
+ valueKey
2541
+ } = useSearchApiContext();
2542
+ const getOptionValue = (opt) => {
2543
+ if (valueKey === "_id" && opt._id === void 0 && opt.id !== void 0) {
2544
+ return opt.id;
2545
+ }
2546
+ return opt[valueKey];
2547
+ };
2548
+ const optValue = getOptionValue(option);
2549
+ const isSelected = selectedValue === optValue;
2550
+ const isHighlighted = index === activeIndex;
2551
+ return /* @__PURE__ */ jsxs15(
2552
+ "button",
2277
2553
  {
2554
+ ref,
2555
+ type: "button",
2556
+ 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}`,
2557
+ style: isSelected && primaryColor ? {
2558
+ backgroundColor: `${primaryColor}1A`,
2559
+ color: primaryColor
2560
+ } : void 0,
2561
+ onMouseDown: (e) => e.stopPropagation(),
2562
+ onClick: (e) => {
2563
+ e.stopPropagation();
2564
+ e.preventDefault();
2565
+ handleSelect(option);
2566
+ },
2567
+ onMouseEnter: () => setActiveIndex(index),
2278
2568
  ...props,
2279
- currentValue: value,
2280
- onChangeHandler: onChange || (() => {
2281
- })
2282
- }
2569
+ children: [
2570
+ /* @__PURE__ */ jsx20("span", { className: "truncate", children: option[labelKey] }),
2571
+ isSelected && /* @__PURE__ */ jsx20(Check3, { className: "h-4 w-4", style: { color: primaryColor } })
2572
+ ]
2573
+ },
2574
+ optValue || index
2283
2575
  );
2284
2576
  }
2285
2577
  );
2286
- SearchApi.displayName = "SearchApi";
2578
+ SearchApiItem.displayName = "SearchApiItem";
2287
2579
 
2288
2580
  // src/components/Fields/date.tsx
2289
2581
  import { forwardRef as forwardRef6, useState as useState13 } from "react";
@@ -2370,15 +2662,18 @@ var DateInput = forwardRef6(
2370
2662
  }
2371
2663
  );
2372
2664
  };
2373
- return /* @__PURE__ */ jsxs16("div", { className: `space-y-2 group ${containerClassName}`, children: [
2374
- label && /* @__PURE__ */ jsx21(
2665
+ return /* @__PURE__ */ jsxs16("div", { className: `space-y-2 group relative ${containerClassName}`, children: [
2666
+ label && /* @__PURE__ */ jsxs16(
2375
2667
  "label",
2376
2668
  {
2377
2669
  className: "block text-xs font-medium transition-colors duration-200",
2378
2670
  style: {
2379
2671
  color: message ? "#ef4444" : isFocused ? primaryColor : void 0
2380
2672
  },
2381
- children: label
2673
+ children: [
2674
+ label,
2675
+ props.required && /* @__PURE__ */ jsx21("span", { className: "text-red-500 ml-1", children: "*" })
2676
+ ]
2382
2677
  }
2383
2678
  ),
2384
2679
  form && name ? /* @__PURE__ */ jsx21(
@@ -2394,7 +2689,7 @@ var DateInput = forwardRef6(
2394
2689
  )
2395
2690
  }
2396
2691
  ) : renderDatePicker(value, onChange, onBlur, ref),
2397
- message && /* @__PURE__ */ jsx21("p", { className: "text-sm text-red-600 dark:text-red-400", children: message })
2692
+ /* @__PURE__ */ jsx21("div", { className: "min-h-[20px]", children: message && /* @__PURE__ */ jsx21("p", { className: "text-sm text-red-600 dark:text-red-400", children: message }) })
2398
2693
  ] });
2399
2694
  }
2400
2695
  );
@@ -2404,8 +2699,15 @@ var Fields = {
2404
2699
  Input,
2405
2700
  PhoneInput,
2406
2701
  Select,
2702
+ SelectTrigger,
2703
+ SelectContent,
2704
+ SelectItem,
2407
2705
  Textarea,
2408
2706
  SearchApi,
2707
+ SearchApiTrigger,
2708
+ SearchApiInput,
2709
+ SearchApiContent,
2710
+ SearchApiItem,
2409
2711
  DateInput
2410
2712
  };
2411
2713
  var Fields_default = Fields;
@@ -2422,7 +2724,7 @@ import {
2422
2724
  flexRender
2423
2725
  } from "@tanstack/react-table";
2424
2726
  import { ChevronDown as ChevronDown4, Search as Search2 } from "lucide-react";
2425
- import { Fragment as Fragment3, jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
2727
+ import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
2426
2728
  function DataTable({
2427
2729
  columns: userColumns,
2428
2730
  data,
@@ -2689,7 +2991,7 @@ function DataTable({
2689
2991
  }
2690
2992
  ) }) }),
2691
2993
  /* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between px-2", children: [
2692
- /* @__PURE__ */ jsx22("div", { className: "flex-1 text-xs text-gray-500", children: selectable && /* @__PURE__ */ jsxs17(Fragment3, { children: [
2994
+ /* @__PURE__ */ jsx22("div", { className: "flex-1 text-xs text-gray-500", children: selectable && /* @__PURE__ */ jsxs17(Fragment5, { children: [
2693
2995
  table.getFilteredSelectedRowModel().rows.length,
2694
2996
  " of",
2695
2997
  " ",
@@ -2739,7 +3041,7 @@ import {
2739
3041
  flexRender as flexRender2
2740
3042
  } from "@tanstack/react-table";
2741
3043
  import { Plus, Edit2, Trash2, Check as Check4, X as X3, ChevronDown as ChevronDown5 } from "lucide-react";
2742
- import { Fragment as Fragment4, jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
3044
+ import { Fragment as Fragment6, jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
2743
3045
  function PostTable({
2744
3046
  columns: userColumns,
2745
3047
  data: controlledData,
@@ -3069,7 +3371,7 @@ function PostTable({
3069
3371
  "py-1! text-sm align-middle transition-colors duration-200",
3070
3372
  verticalLines ? "border-x border-gray-200 dark:border-zinc-800" : ""
3071
3373
  ),
3072
- children: /* @__PURE__ */ jsx23("div", { className: "flex items-center gap-2", children: editingIndex !== null ? /* @__PURE__ */ jsxs18(Fragment4, { children: [
3374
+ children: /* @__PURE__ */ jsx23("div", { className: "flex items-center gap-2", children: editingIndex !== null ? /* @__PURE__ */ jsxs18(Fragment6, { children: [
3073
3375
  /* @__PURE__ */ jsx23(
3074
3376
  "button",
3075
3377
  {
@@ -3090,7 +3392,7 @@ function PostTable({
3090
3392
  children: /* @__PURE__ */ jsx23(X3, { size: 16, strokeWidth: 2.5 })
3091
3393
  }
3092
3394
  )
3093
- ] }) : /* @__PURE__ */ jsx23(Fragment4, { children: renderAddButton ? renderAddButton(
3395
+ ] }) : /* @__PURE__ */ jsx23(Fragment6, { children: renderAddButton ? renderAddButton(
3094
3396
  entryData,
3095
3397
  handleSaveField,
3096
3398
  isSavingAsync
@@ -4025,7 +4327,14 @@ export {
4025
4327
  PhoneInput,
4026
4328
  PostTable,
4027
4329
  SearchApi,
4330
+ SearchApiContent,
4331
+ SearchApiInput,
4332
+ SearchApiItem,
4333
+ SearchApiTrigger,
4028
4334
  Select,
4335
+ SelectContent,
4336
+ SelectItem,
4337
+ SelectTrigger,
4029
4338
  SimpleTable,
4030
4339
  Textarea,
4031
4340
  ThemeProvider,
@@ -4035,6 +4344,8 @@ export {
4035
4344
  useA4DataView_default as useA4StatementView,
4036
4345
  useApis_default as useApi,
4037
4346
  useModal,
4347
+ useSearchApiContext,
4348
+ useSelectContext,
4038
4349
  useTheme,
4039
4350
  useTransaction_default as useTransaction,
4040
4351
  useWarqadConfig