avt-rct-lib 1.0.3 → 1.0.5

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.cjs CHANGED
@@ -1212,130 +1212,6 @@ function SidebarItem({
1212
1212
  }
1213
1213
  );
1214
1214
  }
1215
- function SidebarSubMenu({
1216
- icon,
1217
- label,
1218
- badge,
1219
- defaultOpen = false,
1220
- open: controlledOpen,
1221
- onOpenChange,
1222
- activeChild = false,
1223
- children,
1224
- className
1225
- }) {
1226
- const { collapsed } = useSidebar();
1227
- const [internalOpen, setInternalOpen] = React3.useState(defaultOpen);
1228
- const isOpen = controlledOpen ?? internalOpen;
1229
- const toggle = () => {
1230
- const next = !isOpen;
1231
- setInternalOpen(next);
1232
- onOpenChange?.(next);
1233
- };
1234
- if (collapsed) {
1235
- return /* @__PURE__ */ jsxRuntime.jsx(
1236
- "button",
1237
- {
1238
- type: "button",
1239
- title: label,
1240
- onClick: toggle,
1241
- className: cn(
1242
- "mx-auto flex h-10 w-10 min-h-[44px] min-w-[44px] items-center justify-center rounded-xl",
1243
- "select-none outline-none transition-all duration-150",
1244
- "focus-visible:ring-2 focus-visible:ring-[#007AFF]/30",
1245
- activeChild ? "bg-[#007AFF] text-white shadow-[0_2px_8px_rgba(0,122,255,0.28)]" : "text-[#3C3C43] hover:bg-[#007AFF]/8 hover:text-[#007AFF]",
1246
- className
1247
- ),
1248
- children: icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-shrink-0", !activeChild && "text-[#8E8E93]"), children: icon })
1249
- }
1250
- );
1251
- }
1252
- const triggerActive = activeChild && !isOpen;
1253
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("space-y-0.5", className), children: [
1254
- /* @__PURE__ */ jsxRuntime.jsxs(
1255
- "button",
1256
- {
1257
- type: "button",
1258
- onClick: toggle,
1259
- className: cn(
1260
- "flex w-full items-center gap-2.5 rounded-xl px-3 py-2.5 min-h-[44px]",
1261
- "text-[13px] font-medium select-none outline-none transition-all duration-150",
1262
- "focus-visible:ring-2 focus-visible:ring-[#007AFF]/30",
1263
- triggerActive ? "bg-[#007AFF] text-white shadow-[0_2px_8px_rgba(0,122,255,0.28)]" : "text-[#3C3C43] hover:bg-[#007AFF]/8 hover:text-[#007AFF]"
1264
- ),
1265
- children: [
1266
- icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-shrink-0", !triggerActive && "text-[#8E8E93]"), children: icon }),
1267
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-left", children: label }),
1268
- badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
1269
- "span",
1270
- {
1271
- className: cn(
1272
- "flex h-5 min-w-5 items-center justify-center rounded-full px-1.5 text-[10px] font-bold",
1273
- triggerActive ? "bg-white/20 text-white" : "bg-[#E5E5EA] text-[#8E8E93]"
1274
- ),
1275
- children: badge
1276
- }
1277
- ),
1278
- /* @__PURE__ */ jsxRuntime.jsx(
1279
- "svg",
1280
- {
1281
- className: cn(
1282
- "h-3.5 w-3.5 flex-shrink-0 transition-transform duration-200",
1283
- triggerActive ? "text-white/60" : "text-[#C7C7CC]",
1284
- isOpen && "rotate-90"
1285
- ),
1286
- viewBox: "0 0 24 24",
1287
- fill: "none",
1288
- stroke: "currentColor",
1289
- strokeWidth: "2.5",
1290
- strokeLinecap: "round",
1291
- strokeLinejoin: "round",
1292
- children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 18l6-6-6-6" })
1293
- }
1294
- )
1295
- ]
1296
- }
1297
- ),
1298
- /* @__PURE__ */ jsxRuntime.jsx(
1299
- "div",
1300
- {
1301
- className: cn(
1302
- "overflow-hidden transition-all duration-200 ease-[cubic-bezier(0.16,1,0.3,1)]",
1303
- isOpen ? "max-h-96 opacity-100" : "max-h-0 opacity-0 pointer-events-none"
1304
- ),
1305
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-3 space-y-0.5 border-l border-[#E5E5EA] py-0.5 pl-2", children })
1306
- }
1307
- )
1308
- ] });
1309
- }
1310
- function SidebarSubMenuItem({
1311
- icon,
1312
- label,
1313
- active = false,
1314
- href,
1315
- as: Tag = "button",
1316
- className,
1317
- ...props
1318
- }) {
1319
- const tagProps = href ? { href } : { type: "button" };
1320
- return /* @__PURE__ */ jsxRuntime.jsxs(
1321
- Tag,
1322
- {
1323
- ...tagProps,
1324
- className: cn(
1325
- "flex w-full items-center gap-2 rounded-lg px-2.5 py-2 min-h-[36px]",
1326
- "text-[12px] font-medium select-none outline-none transition-all duration-150",
1327
- "focus-visible:ring-2 focus-visible:ring-[#007AFF]/30",
1328
- active ? "bg-[#007AFF] text-white shadow-[0_2px_8px_rgba(0,122,255,0.20)]" : "text-[#3C3C43] hover:bg-[#007AFF]/8 hover:text-[#007AFF]",
1329
- className
1330
- ),
1331
- ...props,
1332
- children: [
1333
- icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-shrink-0", !active && "text-[#8E8E93]"), children: icon }),
1334
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-left", children: label })
1335
- ]
1336
- }
1337
- );
1338
- }
1339
1215
  function SidebarFooter({ className, ...props }) {
1340
1216
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex-shrink-0 p-3", className), ...props });
1341
1217
  }
@@ -1401,6 +1277,925 @@ function SidebarToggle({ collapsed, className, ...props }) {
1401
1277
  }
1402
1278
  );
1403
1279
  }
1280
+ function useAnchoredPosition(anchorRef, open, {
1281
+ align = "start",
1282
+ sideOffset = 6,
1283
+ minWidth = 180,
1284
+ matchWidth = true,
1285
+ maxHeight = 280,
1286
+ viewportPadding = 8
1287
+ } = {}) {
1288
+ const [pos, setPos] = React3.useState(null);
1289
+ const update = React3.useCallback(() => {
1290
+ const el = anchorRef.current;
1291
+ if (!el) return;
1292
+ const rect = el.getBoundingClientRect();
1293
+ const vw = window.innerWidth;
1294
+ const vh = window.innerHeight;
1295
+ const width = matchWidth ? Math.max(minWidth, rect.width) : minWidth;
1296
+ let left;
1297
+ if (align === "end") left = rect.right - width;
1298
+ else if (align === "center") left = rect.left + rect.width / 2 - width / 2;
1299
+ else left = rect.left;
1300
+ left = Math.max(viewportPadding, Math.min(left, vw - width - viewportPadding));
1301
+ const spaceBelow = vh - rect.bottom - sideOffset - viewportPadding;
1302
+ const spaceAbove = rect.top - sideOffset - viewportPadding;
1303
+ const flipUp = spaceBelow < Math.min(maxHeight, 180) && spaceAbove > spaceBelow;
1304
+ const available = Math.max(120, flipUp ? spaceAbove : spaceBelow);
1305
+ const height = Math.min(maxHeight, available);
1306
+ const top = flipUp ? rect.top - sideOffset - height : rect.bottom + sideOffset;
1307
+ setPos({
1308
+ top,
1309
+ left,
1310
+ width,
1311
+ maxHeight: height,
1312
+ placement: flipUp ? "top" : "bottom"
1313
+ });
1314
+ }, [anchorRef, align, sideOffset, minWidth, matchWidth, maxHeight, viewportPadding]);
1315
+ React3.useEffect(() => {
1316
+ if (!open) {
1317
+ setPos(null);
1318
+ return;
1319
+ }
1320
+ update();
1321
+ window.addEventListener("scroll", update, true);
1322
+ window.addEventListener("resize", update);
1323
+ return () => {
1324
+ window.removeEventListener("scroll", update, true);
1325
+ window.removeEventListener("resize", update);
1326
+ };
1327
+ }, [open, update]);
1328
+ return pos;
1329
+ }
1330
+ var stack = [];
1331
+ var bound = false;
1332
+ function onGlobalKeydown(e) {
1333
+ if (e.key !== "Escape") return;
1334
+ const top = stack[stack.length - 1];
1335
+ if (!top) return;
1336
+ e.stopPropagation();
1337
+ top();
1338
+ }
1339
+ function bind() {
1340
+ if (bound || typeof document === "undefined") return;
1341
+ document.addEventListener("keydown", onGlobalKeydown, true);
1342
+ bound = true;
1343
+ }
1344
+ function unbind() {
1345
+ if (!bound || typeof document === "undefined") return;
1346
+ document.removeEventListener("keydown", onGlobalKeydown, true);
1347
+ bound = false;
1348
+ }
1349
+ function useEscapeDismiss(enabled, onDismiss) {
1350
+ const handlerRef = React3.useRef(onDismiss);
1351
+ handlerRef.current = onDismiss;
1352
+ React3.useEffect(() => {
1353
+ if (!enabled) return;
1354
+ const entry = () => handlerRef.current();
1355
+ stack.push(entry);
1356
+ bind();
1357
+ return () => {
1358
+ const i = stack.lastIndexOf(entry);
1359
+ if (i >= 0) stack.splice(i, 1);
1360
+ if (stack.length === 0) unbind();
1361
+ };
1362
+ }, [enabled]);
1363
+ }
1364
+ var triggerBase = [
1365
+ "flex w-full items-center gap-2 rounded-xl bg-[#F2F2F7] text-left",
1366
+ "border-0 outline-none select-none text-[#1C1C1E]",
1367
+ "transition-all duration-150",
1368
+ "focus-visible:bg-white focus-visible:shadow-[0_0_0_2px_rgba(0,122,255,0.22)]",
1369
+ "disabled:cursor-not-allowed disabled:opacity-50"
1370
+ ].join(" ");
1371
+ var triggerSizes = {
1372
+ sm: "h-9 px-3 text-[13px]",
1373
+ md: "h-11 px-4 text-sm",
1374
+ lg: "h-12 px-5 text-[15px]"
1375
+ };
1376
+ var panelBase = [
1377
+ "fixed z-[9999] flex flex-col overflow-hidden avt-animate-slide-up",
1378
+ "rounded-xl border border-[#E5E5EA]/60 bg-white/95 backdrop-blur-2xl",
1379
+ "shadow-[0_8px_24px_rgba(0,0,0,0.10),_0_0_1px_rgba(0,0,0,0.06)]"
1380
+ ].join(" ");
1381
+ function optionRowClass(state, className) {
1382
+ return cn(
1383
+ "flex w-full items-center gap-2.5 px-3.5 py-2.5 text-[13px] font-medium",
1384
+ "cursor-pointer select-none text-left outline-none",
1385
+ "transition-colors duration-100",
1386
+ // Mobile: jaga target sentuh minimal
1387
+ "min-h-[44px] sm:min-h-0",
1388
+ state.disabled ? "pointer-events-none opacity-40" : state.active ? "bg-[#F2F2F7]" : "hover:bg-[#F2F2F7]",
1389
+ state.selected ? "text-[#007AFF]" : "text-[#1C1C1E]",
1390
+ className
1391
+ );
1392
+ }
1393
+ var groupLabelClass = "px-3.5 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wider text-[#8E8E93]";
1394
+ var ChevronDownIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsx(
1395
+ "svg",
1396
+ {
1397
+ className,
1398
+ viewBox: "0 0 24 24",
1399
+ fill: "none",
1400
+ stroke: "currentColor",
1401
+ strokeWidth: "2.5",
1402
+ strokeLinecap: "round",
1403
+ strokeLinejoin: "round",
1404
+ "aria-hidden": "true",
1405
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 9l6 6 6-6" })
1406
+ }
1407
+ );
1408
+ var CheckIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsx(
1409
+ "svg",
1410
+ {
1411
+ className,
1412
+ viewBox: "0 0 24 24",
1413
+ fill: "none",
1414
+ stroke: "currentColor",
1415
+ strokeWidth: "3",
1416
+ strokeLinecap: "round",
1417
+ strokeLinejoin: "round",
1418
+ "aria-hidden": "true",
1419
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6L9 17l-5-5" })
1420
+ }
1421
+ );
1422
+ var SearchIcon2 = ({ className }) => /* @__PURE__ */ jsxRuntime.jsxs(
1423
+ "svg",
1424
+ {
1425
+ className,
1426
+ viewBox: "0 0 24 24",
1427
+ fill: "none",
1428
+ stroke: "currentColor",
1429
+ strokeWidth: "2.5",
1430
+ strokeLinecap: "round",
1431
+ "aria-hidden": "true",
1432
+ children: [
1433
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "7" }),
1434
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 20l-3.5-3.5" })
1435
+ ]
1436
+ }
1437
+ );
1438
+ var ClearIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsx(
1439
+ "svg",
1440
+ {
1441
+ className,
1442
+ viewBox: "0 0 24 24",
1443
+ fill: "none",
1444
+ stroke: "currentColor",
1445
+ strokeWidth: "2.5",
1446
+ strokeLinecap: "round",
1447
+ "aria-hidden": "true",
1448
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12" })
1449
+ }
1450
+ );
1451
+ var SpinnerIcon = ({ className }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: cn("animate-spin", className), viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [
1452
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "3" }),
1453
+ /* @__PURE__ */ jsxRuntime.jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" })
1454
+ ] });
1455
+ function groupOptions(options) {
1456
+ const groups = [];
1457
+ const byName = /* @__PURE__ */ new Map();
1458
+ for (const option of options) {
1459
+ const key = option.group ?? "";
1460
+ let bucket = byName.get(key);
1461
+ if (!bucket) {
1462
+ bucket = { group: option.group, items: [], offset: 0 };
1463
+ byName.set(key, bucket);
1464
+ groups.push(bucket);
1465
+ }
1466
+ bucket.items.push(option);
1467
+ }
1468
+ let offset = 0;
1469
+ for (const bucket of groups) {
1470
+ bucket.offset = offset;
1471
+ offset += bucket.items.length;
1472
+ }
1473
+ return groups;
1474
+ }
1475
+ function nextEnabledIndex(options, from, dir) {
1476
+ const n = options.length;
1477
+ if (n === 0) return -1;
1478
+ let i = from < 0 ? dir === 1 ? -1 : 0 : from;
1479
+ for (let step = 0; step < n; step++) {
1480
+ i = (i + dir + n) % n;
1481
+ if (!options[i].disabled) return i;
1482
+ }
1483
+ return -1;
1484
+ }
1485
+ function defaultFilter(option, query) {
1486
+ const q = query.trim().toLowerCase();
1487
+ if (!q) return true;
1488
+ return option.label.toLowerCase().includes(q) || (option.description?.toLowerCase().includes(q) ?? false) || String(option.value).toLowerCase().includes(q);
1489
+ }
1490
+ var Select = React3__default.default.forwardRef(function Select2({
1491
+ options,
1492
+ value: controlledValue,
1493
+ defaultValue = null,
1494
+ onChange,
1495
+ placeholder = "Pilih\u2026",
1496
+ label,
1497
+ hint,
1498
+ error,
1499
+ size = "md",
1500
+ disabled = false,
1501
+ clearable = false,
1502
+ name,
1503
+ align = "start",
1504
+ maxHeight = 280,
1505
+ emptyText = "Tidak ada pilihan",
1506
+ containerClassName,
1507
+ panelClassName,
1508
+ onOpenChange,
1509
+ renderOption,
1510
+ searchable = false,
1511
+ searchPlaceholder = "Cari\u2026",
1512
+ filter = defaultFilter,
1513
+ onSearchChange,
1514
+ manualFilter = false,
1515
+ loading = false,
1516
+ loadingText = "Memuat\u2026",
1517
+ className,
1518
+ id,
1519
+ ...props
1520
+ }, ref) {
1521
+ const reactId = React3__default.default.useId();
1522
+ const uid = id ?? `avt-select-${reactId}`;
1523
+ const listboxId = `${uid}-listbox`;
1524
+ const labelId = `${uid}-label`;
1525
+ const [open, setOpen] = React3.useState(false);
1526
+ const [query, setQuery] = React3.useState("");
1527
+ const [activeIndex, setActiveIndex] = React3.useState(-1);
1528
+ const [internalValue, setInternalValue] = React3.useState(defaultValue);
1529
+ const triggerRef = React3.useRef(null);
1530
+ const panelRef = React3.useRef(null);
1531
+ const listRef = React3.useRef(null);
1532
+ const typeahead = React3.useRef({ text: "", at: 0 });
1533
+ const focusOnMount = React3.useCallback((el) => {
1534
+ el?.focus();
1535
+ }, []);
1536
+ React3__default.default.useImperativeHandle(ref, () => triggerRef.current, []);
1537
+ const isControlled = controlledValue !== void 0;
1538
+ const value = isControlled ? controlledValue : internalValue;
1539
+ const selected = React3.useMemo(
1540
+ () => value == null ? null : options.find((o) => o.value === value) ?? null,
1541
+ [options, value]
1542
+ );
1543
+ const visible = React3.useMemo(() => {
1544
+ if (!searchable || manualFilter || !query.trim()) return options;
1545
+ return options.filter((o) => filter(o, query));
1546
+ }, [options, searchable, manualFilter, query, filter]);
1547
+ const groups = React3.useMemo(() => groupOptions(visible), [visible]);
1548
+ const flat = React3.useMemo(() => groups.flatMap((g) => g.items), [groups]);
1549
+ const changeOpen = React3.useCallback(
1550
+ (next) => {
1551
+ setOpen(next);
1552
+ onOpenChange?.(next);
1553
+ },
1554
+ [onOpenChange]
1555
+ );
1556
+ const dismiss = React3.useCallback(() => {
1557
+ changeOpen(false);
1558
+ triggerRef.current?.focus();
1559
+ }, [changeOpen]);
1560
+ useEscapeDismiss(open, dismiss);
1561
+ React3.useEffect(() => {
1562
+ if (!open) return;
1563
+ const handler = (e) => {
1564
+ const target = e.target;
1565
+ if (triggerRef.current?.contains(target)) return;
1566
+ if (panelRef.current?.contains(target)) return;
1567
+ changeOpen(false);
1568
+ };
1569
+ document.addEventListener("mousedown", handler, true);
1570
+ document.addEventListener("touchstart", handler, true);
1571
+ return () => {
1572
+ document.removeEventListener("mousedown", handler, true);
1573
+ document.removeEventListener("touchstart", handler, true);
1574
+ };
1575
+ }, [open, changeOpen]);
1576
+ React3.useEffect(() => {
1577
+ if (!open) setQuery("");
1578
+ }, [open]);
1579
+ React3.useEffect(() => {
1580
+ if (!open) {
1581
+ setActiveIndex(-1);
1582
+ return;
1583
+ }
1584
+ const pick = flat.findIndex((o) => value != null && o.value === value && !o.disabled);
1585
+ setActiveIndex(pick >= 0 ? pick : nextEnabledIndex(flat, -1, 1));
1586
+ }, [open, query]);
1587
+ React3.useEffect(() => {
1588
+ if (!open || activeIndex < 0) return;
1589
+ listRef.current?.querySelector(`[data-index="${activeIndex}"]`)?.scrollIntoView({ block: "nearest" });
1590
+ }, [open, activeIndex]);
1591
+ const commit = React3.useCallback(
1592
+ (option) => {
1593
+ if (option.disabled) return;
1594
+ if (!isControlled) setInternalValue(option.value);
1595
+ onChange?.(option.value, option);
1596
+ changeOpen(false);
1597
+ triggerRef.current?.focus();
1598
+ },
1599
+ [isControlled, onChange, changeOpen]
1600
+ );
1601
+ const clear = React3.useCallback(
1602
+ (e) => {
1603
+ e.stopPropagation();
1604
+ if (!isControlled) setInternalValue(null);
1605
+ onChange?.(null, null);
1606
+ },
1607
+ [isControlled, onChange]
1608
+ );
1609
+ const move = React3.useCallback(
1610
+ (dir) => setActiveIndex((i) => nextEnabledIndex(flat, i, dir)),
1611
+ [flat]
1612
+ );
1613
+ const runTypeahead = React3.useCallback(
1614
+ (char) => {
1615
+ const now = Date.now();
1616
+ const text = now - typeahead.current.at > 600 ? char : typeahead.current.text + char;
1617
+ typeahead.current = { text, at: now };
1618
+ const q = text.toLowerCase();
1619
+ const hit = flat.findIndex((o) => !o.disabled && o.label.toLowerCase().startsWith(q));
1620
+ if (hit >= 0) setActiveIndex(hit);
1621
+ },
1622
+ [flat]
1623
+ );
1624
+ const onNavKeyDown = React3.useCallback(
1625
+ (e) => {
1626
+ switch (e.key) {
1627
+ case "ArrowDown":
1628
+ e.preventDefault();
1629
+ move(1);
1630
+ return;
1631
+ case "ArrowUp":
1632
+ e.preventDefault();
1633
+ move(-1);
1634
+ return;
1635
+ case "Home":
1636
+ e.preventDefault();
1637
+ setActiveIndex(nextEnabledIndex(flat, -1, 1));
1638
+ return;
1639
+ case "End":
1640
+ e.preventDefault();
1641
+ setActiveIndex(nextEnabledIndex(flat, 0, -1));
1642
+ return;
1643
+ case "Enter":
1644
+ e.preventDefault();
1645
+ if (activeIndex >= 0 && flat[activeIndex]) commit(flat[activeIndex]);
1646
+ return;
1647
+ case "Tab":
1648
+ changeOpen(false);
1649
+ return;
1650
+ }
1651
+ },
1652
+ [move, flat, activeIndex, commit, changeOpen]
1653
+ );
1654
+ const onTriggerKeyDown = (e) => {
1655
+ if (disabled) return;
1656
+ if (!open) {
1657
+ if (e.key === "ArrowDown" || e.key === "ArrowUp" || e.key === "Enter" || e.key === " ") {
1658
+ e.preventDefault();
1659
+ changeOpen(true);
1660
+ }
1661
+ return;
1662
+ }
1663
+ if (e.key === " " && !searchable) {
1664
+ e.preventDefault();
1665
+ if (activeIndex >= 0 && flat[activeIndex]) commit(flat[activeIndex]);
1666
+ return;
1667
+ }
1668
+ onNavKeyDown(e);
1669
+ if (!searchable && e.key.length === 1 && !e.metaKey && !e.ctrlKey && !e.altKey) {
1670
+ runTypeahead(e.key);
1671
+ }
1672
+ };
1673
+ const showClear = clearable && selected != null && !disabled;
1674
+ const activeId = open && activeIndex >= 0 ? `${uid}-opt-${activeIndex}` : void 0;
1675
+ const comboProps = searchable ? { "aria-haspopup": "listbox" } : {
1676
+ role: "combobox",
1677
+ "aria-controls": open ? listboxId : void 0,
1678
+ "aria-activedescendant": activeId,
1679
+ "aria-haspopup": "listbox"
1680
+ };
1681
+ const pos = useAnchoredPosition(triggerRef, open, {
1682
+ align,
1683
+ matchWidth: true,
1684
+ maxHeight
1685
+ });
1686
+ const panel = open && pos && typeof document !== "undefined" ? reactDom.createPortal(
1687
+ /* @__PURE__ */ jsxRuntime.jsxs(
1688
+ "div",
1689
+ {
1690
+ ref: panelRef,
1691
+ className: cn(panelBase, panelClassName),
1692
+ style: {
1693
+ top: pos.top,
1694
+ left: pos.left,
1695
+ width: pos.width,
1696
+ maxHeight: pos.maxHeight
1697
+ },
1698
+ children: [
1699
+ searchable && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center border-b border-[#F2F2F7] px-3", children: [
1700
+ /* @__PURE__ */ jsxRuntime.jsx(SearchIcon2, { className: "pointer-events-none absolute left-3 h-3.5 w-3.5 text-[#8E8E93]" }),
1701
+ /* @__PURE__ */ jsxRuntime.jsx(
1702
+ "input",
1703
+ {
1704
+ ref: focusOnMount,
1705
+ type: "text",
1706
+ role: "combobox",
1707
+ "aria-expanded": true,
1708
+ "aria-controls": listboxId,
1709
+ "aria-activedescendant": activeId,
1710
+ "aria-autocomplete": "list",
1711
+ "aria-label": searchPlaceholder,
1712
+ autoComplete: "off",
1713
+ spellCheck: false,
1714
+ value: query,
1715
+ placeholder: searchPlaceholder,
1716
+ onChange: (e) => {
1717
+ setQuery(e.target.value);
1718
+ onSearchChange?.(e.target.value);
1719
+ },
1720
+ onKeyDown: onNavKeyDown,
1721
+ className: cn(
1722
+ "h-10 w-full border-0 bg-transparent pl-6 pr-2 text-[13px] text-[#1C1C1E]",
1723
+ "outline-none placeholder:text-[#8E8E93]"
1724
+ )
1725
+ }
1726
+ ),
1727
+ loading && /* @__PURE__ */ jsxRuntime.jsx(SpinnerIcon, { className: "absolute right-3 h-3.5 w-3.5 text-[#8E8E93]" })
1728
+ ] }),
1729
+ /* @__PURE__ */ jsxRuntime.jsx(
1730
+ "div",
1731
+ {
1732
+ ref: listRef,
1733
+ id: listboxId,
1734
+ role: "listbox",
1735
+ "aria-labelledby": label ? labelId : void 0,
1736
+ className: "avt-scroll min-h-0 flex-1 overflow-y-auto py-1.5",
1737
+ children: flat.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3.5 py-6 text-center text-[13px] text-[#8E8E93]", children: loading ? loadingText : emptyText }) : groups.map((group) => /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "group", "aria-label": group.group, children: [
1738
+ group.group && /* @__PURE__ */ jsxRuntime.jsx("div", { className: groupLabelClass, children: group.group }),
1739
+ group.items.map((option, i) => {
1740
+ const index = group.offset + i;
1741
+ const state = {
1742
+ selected: value != null && option.value === value,
1743
+ active: index === activeIndex
1744
+ };
1745
+ return /* @__PURE__ */ jsxRuntime.jsx(
1746
+ "div",
1747
+ {
1748
+ id: `${uid}-opt-${index}`,
1749
+ "data-index": index,
1750
+ role: "option",
1751
+ "aria-selected": state.selected,
1752
+ "aria-disabled": option.disabled || void 0,
1753
+ className: optionRowClass({
1754
+ ...state,
1755
+ disabled: option.disabled
1756
+ }),
1757
+ onMouseEnter: () => !option.disabled && setActiveIndex(index),
1758
+ onClick: () => commit(option),
1759
+ children: renderOption ? renderOption(option, state) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1760
+ option.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-[#8E8E93]", children: option.icon }),
1761
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1", children: [
1762
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate", children: option.label }),
1763
+ option.description && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block truncate text-[11px] font-normal text-[#8E8E93]", children: option.description })
1764
+ ] }),
1765
+ state.selected && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "h-4 w-4 flex-shrink-0 text-[#007AFF]" })
1766
+ ] })
1767
+ },
1768
+ option.value
1769
+ );
1770
+ })
1771
+ ] }, group.group ?? "__default"))
1772
+ }
1773
+ )
1774
+ ]
1775
+ }
1776
+ ),
1777
+ document.body
1778
+ ) : null;
1779
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-1.5", containerClassName), ...props, children: [
1780
+ label && /* @__PURE__ */ jsxRuntime.jsx("label", { id: labelId, htmlFor: uid, className: "text-[13px] font-medium text-[#3C3C43]", children: label }),
1781
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1782
+ /* @__PURE__ */ jsxRuntime.jsxs(
1783
+ "button",
1784
+ {
1785
+ ref: triggerRef,
1786
+ id: uid,
1787
+ type: "button",
1788
+ disabled,
1789
+ "aria-expanded": open,
1790
+ "aria-invalid": error ? true : void 0,
1791
+ className: cn(
1792
+ triggerBase,
1793
+ triggerSizes[size],
1794
+ "pr-9",
1795
+ showClear && "pr-14",
1796
+ error && "bg-[#FF3B30]/6 focus-visible:shadow-[0_0_0_2px_rgba(255,59,48,0.22)]",
1797
+ open && "bg-white shadow-[0_0_0_2px_rgba(0,122,255,0.22)]",
1798
+ className
1799
+ ),
1800
+ onClick: () => changeOpen(!open),
1801
+ onKeyDown: onTriggerKeyDown,
1802
+ ...comboProps,
1803
+ children: [
1804
+ selected?.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0 text-[#8E8E93]", children: selected.icon }),
1805
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("flex-1 truncate", !selected && "text-[#8E8E93]"), children: selected ? selected.label : placeholder }),
1806
+ /* @__PURE__ */ jsxRuntime.jsx(
1807
+ ChevronDownIcon,
1808
+ {
1809
+ className: cn(
1810
+ "absolute right-3.5 h-4 w-4 flex-shrink-0 text-[#8E8E93]",
1811
+ "transition-transform duration-150",
1812
+ open && "rotate-180"
1813
+ )
1814
+ }
1815
+ )
1816
+ ]
1817
+ }
1818
+ ),
1819
+ showClear && /* @__PURE__ */ jsxRuntime.jsx(
1820
+ "button",
1821
+ {
1822
+ type: "button",
1823
+ tabIndex: -1,
1824
+ "aria-label": "Hapus pilihan",
1825
+ onClick: clear,
1826
+ className: cn(
1827
+ "absolute right-8 top-1/2 flex h-5 w-5 -translate-y-1/2 items-center justify-center",
1828
+ "rounded-full bg-[#E5E5EA] text-[#8E8E93] transition-colors duration-150",
1829
+ "hover:bg-[#D1D1D6] hover:text-[#1C1C1E]"
1830
+ ),
1831
+ children: /* @__PURE__ */ jsxRuntime.jsx(ClearIcon, { className: "h-2.5 w-2.5" })
1832
+ }
1833
+ )
1834
+ ] }),
1835
+ name && /* @__PURE__ */ jsxRuntime.jsx("input", { type: "hidden", name, value: value ?? "", readOnly: true }),
1836
+ error ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-[#FF3B30]", children: error }) : hint ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-[#8E8E93]", children: hint }) : null,
1837
+ panel
1838
+ ] });
1839
+ });
1840
+ Select.displayName = "Select";
1841
+ var SelectSearch = React3__default.default.forwardRef(
1842
+ function SelectSearch2(props, ref) {
1843
+ return /* @__PURE__ */ jsxRuntime.jsx(Select, { ref, searchable: true, ...props });
1844
+ }
1845
+ );
1846
+ SelectSearch.displayName = "SelectSearch";
1847
+ var FOCUSABLE = [
1848
+ "a[href]",
1849
+ "button:not([disabled])",
1850
+ "input:not([disabled])",
1851
+ "select:not([disabled])",
1852
+ "textarea:not([disabled])",
1853
+ '[tabindex]:not([tabindex="-1"])'
1854
+ ].join(",");
1855
+ function useFocusTrap(containerRef, enabled = true, initialFocusRef) {
1856
+ React3.useEffect(() => {
1857
+ if (!enabled) return;
1858
+ const container = containerRef.current;
1859
+ if (!container) return;
1860
+ const previouslyFocused = document.activeElement;
1861
+ const focusables = () => Array.from(container.querySelectorAll(FOCUSABLE)).filter(
1862
+ (el) => el.getClientRects().length > 0
1863
+ );
1864
+ const raf = requestAnimationFrame(() => {
1865
+ const target = initialFocusRef?.current ?? focusables()[0] ?? container;
1866
+ target.focus();
1867
+ });
1868
+ const onKeyDown = (e) => {
1869
+ if (e.key !== "Tab") return;
1870
+ const items = focusables();
1871
+ if (items.length === 0) {
1872
+ e.preventDefault();
1873
+ return;
1874
+ }
1875
+ const first = items[0];
1876
+ const last = items[items.length - 1];
1877
+ const active = document.activeElement;
1878
+ const inside = container.contains(active);
1879
+ if (e.shiftKey) {
1880
+ if (active === first || !inside) {
1881
+ e.preventDefault();
1882
+ last.focus();
1883
+ }
1884
+ } else if (active === last || !inside) {
1885
+ e.preventDefault();
1886
+ first.focus();
1887
+ }
1888
+ };
1889
+ document.addEventListener("keydown", onKeyDown);
1890
+ return () => {
1891
+ cancelAnimationFrame(raf);
1892
+ document.removeEventListener("keydown", onKeyDown);
1893
+ previouslyFocused?.focus?.();
1894
+ };
1895
+ }, [containerRef, enabled, initialFocusRef]);
1896
+ }
1897
+ var sizes2 = {
1898
+ sm: "max-w-sm",
1899
+ md: "max-w-md",
1900
+ lg: "max-w-lg",
1901
+ xl: "max-w-2xl",
1902
+ full: "max-w-[calc(100vw-2rem)]"
1903
+ };
1904
+ var lockCount = 0;
1905
+ var previousOverflow = "";
1906
+ function useBodyScrollLock(enabled) {
1907
+ React3.useEffect(() => {
1908
+ if (!enabled) return;
1909
+ if (lockCount === 0) {
1910
+ previousOverflow = document.body.style.overflow;
1911
+ document.body.style.overflow = "hidden";
1912
+ }
1913
+ lockCount++;
1914
+ return () => {
1915
+ lockCount--;
1916
+ if (lockCount === 0) document.body.style.overflow = previousOverflow;
1917
+ };
1918
+ }, [enabled]);
1919
+ }
1920
+ function Modal({
1921
+ open,
1922
+ onClose,
1923
+ title,
1924
+ description,
1925
+ footer,
1926
+ size = "md",
1927
+ closeOnOverlay = true,
1928
+ closeOnEscape = true,
1929
+ showClose = true,
1930
+ initialFocusRef,
1931
+ overlayClassName,
1932
+ bodyClassName,
1933
+ role = "dialog",
1934
+ className,
1935
+ children,
1936
+ ...props
1937
+ }) {
1938
+ const reactId = React3__default.default.useId();
1939
+ const titleId = `avt-modal-${reactId}-title`;
1940
+ const descId = `avt-modal-${reactId}-desc`;
1941
+ const panelRef = React3.useRef(null);
1942
+ useEscapeDismiss(open && closeOnEscape, onClose);
1943
+ useBodyScrollLock(open);
1944
+ useFocusTrap(panelRef, open, initialFocusRef);
1945
+ if (!open || typeof document === "undefined") return null;
1946
+ const hasHeader = Boolean(title || description || showClose);
1947
+ return reactDom.createPortal(
1948
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-[1000] flex items-center justify-center p-4 sm:p-6", children: [
1949
+ /* @__PURE__ */ jsxRuntime.jsx(
1950
+ "div",
1951
+ {
1952
+ className: cn(
1953
+ "avt-animate-fade-in absolute inset-0 bg-black/30 backdrop-blur-[2px]",
1954
+ overlayClassName
1955
+ ),
1956
+ onClick: closeOnOverlay ? onClose : void 0,
1957
+ "aria-hidden": "true"
1958
+ }
1959
+ ),
1960
+ /* @__PURE__ */ jsxRuntime.jsxs(
1961
+ "div",
1962
+ {
1963
+ ref: panelRef,
1964
+ role,
1965
+ "aria-modal": "true",
1966
+ "aria-labelledby": title ? titleId : void 0,
1967
+ "aria-describedby": description ? descId : void 0,
1968
+ tabIndex: -1,
1969
+ className: cn(
1970
+ "avt-animate-modal relative z-10 flex w-full flex-col overflow-hidden outline-none",
1971
+ "rounded-2xl bg-white/95 backdrop-blur-2xl",
1972
+ "border border-[#E5E5EA]/60 shadow-[0_16px_48px_rgba(0,0,0,0.16)]",
1973
+ "max-h-[calc(100vh-2rem)]",
1974
+ sizes2[size],
1975
+ className
1976
+ ),
1977
+ ...props,
1978
+ children: [
1979
+ hasHeader && /* @__PURE__ */ jsxRuntime.jsxs(ModalHeader, { showClose, onClose, children: [
1980
+ title && /* @__PURE__ */ jsxRuntime.jsx(ModalTitle, { id: titleId, children: title }),
1981
+ description && /* @__PURE__ */ jsxRuntime.jsx(ModalDescription, { id: descId, children: description })
1982
+ ] }),
1983
+ /* @__PURE__ */ jsxRuntime.jsx(ModalBody, { className: bodyClassName, children }),
1984
+ footer && /* @__PURE__ */ jsxRuntime.jsx(ModalFooter, { children: footer })
1985
+ ]
1986
+ }
1987
+ )
1988
+ ] }),
1989
+ document.body
1990
+ );
1991
+ }
1992
+ function ModalHeader({
1993
+ showClose,
1994
+ onClose,
1995
+ className,
1996
+ children,
1997
+ ...props
1998
+ }) {
1999
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2000
+ "div",
2001
+ {
2002
+ className: cn(
2003
+ "flex items-start justify-between border-b border-[#F2F2F7] px-6 pb-4 pt-6",
2004
+ className
2005
+ ),
2006
+ ...props,
2007
+ children: [
2008
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1 pr-3", children }),
2009
+ showClose && onClose && /* @__PURE__ */ jsxRuntime.jsx(
2010
+ "button",
2011
+ {
2012
+ type: "button",
2013
+ onClick: onClose,
2014
+ "aria-label": "Tutup",
2015
+ className: cn(
2016
+ "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full",
2017
+ "bg-[#F2F2F7] text-[#8E8E93] hover:bg-[#E5E5EA] hover:text-[#1C1C1E]",
2018
+ "transition-colors duration-150",
2019
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#007AFF]/40"
2020
+ ),
2021
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2022
+ "svg",
2023
+ {
2024
+ className: "h-3.5 w-3.5",
2025
+ viewBox: "0 0 24 24",
2026
+ fill: "none",
2027
+ stroke: "currentColor",
2028
+ strokeWidth: "2.5",
2029
+ strokeLinecap: "round",
2030
+ "aria-hidden": "true",
2031
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12" })
2032
+ }
2033
+ )
2034
+ }
2035
+ )
2036
+ ]
2037
+ }
2038
+ );
2039
+ }
2040
+ function ModalTitle({ className, ...props }) {
2041
+ return /* @__PURE__ */ jsxRuntime.jsx(
2042
+ "h2",
2043
+ {
2044
+ className: cn("text-[15px] font-semibold tracking-[-0.01em] text-[#1C1C1E]", className),
2045
+ ...props
2046
+ }
2047
+ );
2048
+ }
2049
+ function ModalDescription({
2050
+ className,
2051
+ ...props
2052
+ }) {
2053
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("mt-0.5 text-[13px] text-[#8E8E93]", className), ...props });
2054
+ }
2055
+ function ModalBody({ className, ...props }) {
2056
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("avt-scroll flex-1 overflow-y-auto px-6 py-5", className), ...props });
2057
+ }
2058
+ function ModalFooter({ className, ...props }) {
2059
+ return /* @__PURE__ */ jsxRuntime.jsx(
2060
+ "div",
2061
+ {
2062
+ className: cn(
2063
+ "flex items-center justify-end gap-2 px-6 py-4",
2064
+ "border-t border-[#F2F2F7] bg-[#FAFAFA]",
2065
+ className
2066
+ ),
2067
+ ...props
2068
+ }
2069
+ );
2070
+ }
2071
+ var accents = {
2072
+ info: { bg: "bg-[#007AFF]/10", fg: "text-[#007AFF]", confirm: "primary" },
2073
+ success: { bg: "bg-[#34C759]/10", fg: "text-[#34C759]", confirm: "primary" },
2074
+ warning: { bg: "bg-[#FF9500]/10", fg: "text-[#FF9500]", confirm: "primary" },
2075
+ danger: {
2076
+ bg: "bg-[#FF3B30]/10",
2077
+ fg: "text-[#FF3B30]",
2078
+ confirm: "destructive"
2079
+ },
2080
+ question: { bg: "bg-[#5856D6]/10", fg: "text-[#5856D6]", confirm: "primary" }
2081
+ };
2082
+ var iconProps = {
2083
+ className: "h-5 w-5",
2084
+ viewBox: "0 0 24 24",
2085
+ fill: "none",
2086
+ stroke: "currentColor",
2087
+ strokeWidth: "2.2",
2088
+ strokeLinecap: "round",
2089
+ strokeLinejoin: "round",
2090
+ "aria-hidden": true
2091
+ };
2092
+ var icons = {
2093
+ info: /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...iconProps, children: [
2094
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
2095
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 11v5M12 8h.01" })
2096
+ ] }),
2097
+ success: /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...iconProps, children: [
2098
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
2099
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8.5 12.5l2.5 2.5 4.5-5" })
2100
+ ] }),
2101
+ warning: /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...iconProps, children: [
2102
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10.3 4.3L2.6 17.6A2 2 0 004.3 20.6h15.4a2 2 0 001.7-3L13.7 4.3a2 2 0 00-3.4 0z" }),
2103
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 9v4M12 17h.01" })
2104
+ ] }),
2105
+ danger: /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...iconProps, children: [
2106
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
2107
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 9l-6 6M9 9l6 6" })
2108
+ ] }),
2109
+ question: /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...iconProps, children: [
2110
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
2111
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.5 9.5a2.5 2.5 0 113.4 2.3c-.6.2-.9.8-.9 1.4v.3M12 17h.01" })
2112
+ ] })
2113
+ };
2114
+ function Dialog({
2115
+ open,
2116
+ onClose,
2117
+ variant = "question",
2118
+ title,
2119
+ description,
2120
+ confirmText = "Konfirmasi",
2121
+ cancelText = "Batal",
2122
+ onConfirm,
2123
+ onCancel,
2124
+ loading = false,
2125
+ closeOnConfirm = true,
2126
+ hideCancel = false,
2127
+ closeOnOverlay = true,
2128
+ closeOnEscape = true,
2129
+ size = "sm",
2130
+ icon,
2131
+ children,
2132
+ className
2133
+ }) {
2134
+ const reactId = React3__default.default.useId();
2135
+ const titleId = `avt-dialog-${reactId}-title`;
2136
+ const descId = `avt-dialog-${reactId}-desc`;
2137
+ const [busy, setBusy] = React3.useState(false);
2138
+ const isBusy = loading || busy;
2139
+ const accent = accents[variant];
2140
+ const handleCancel = React3.useCallback(() => {
2141
+ if (isBusy) return;
2142
+ onCancel?.();
2143
+ onClose();
2144
+ }, [isBusy, onCancel, onClose]);
2145
+ const handleConfirm = React3.useCallback(async () => {
2146
+ if (isBusy) return;
2147
+ if (!onConfirm) {
2148
+ if (closeOnConfirm) onClose();
2149
+ return;
2150
+ }
2151
+ setBusy(true);
2152
+ try {
2153
+ await onConfirm();
2154
+ if (closeOnConfirm) onClose();
2155
+ } catch {
2156
+ } finally {
2157
+ setBusy(false);
2158
+ }
2159
+ }, [isBusy, onConfirm, closeOnConfirm, onClose]);
2160
+ return /* @__PURE__ */ jsxRuntime.jsx(
2161
+ Modal,
2162
+ {
2163
+ open,
2164
+ onClose: handleCancel,
2165
+ role: "alertdialog",
2166
+ size,
2167
+ showClose: false,
2168
+ closeOnOverlay: closeOnOverlay && !isBusy,
2169
+ closeOnEscape: closeOnEscape && !isBusy,
2170
+ "aria-labelledby": titleId,
2171
+ "aria-describedby": description ? descId : void 0,
2172
+ bodyClassName: "px-6 pb-2 pt-6",
2173
+ className,
2174
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2175
+ !hideCancel && /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "secondary", onClick: handleCancel, disabled: isBusy, children: cancelText }),
2176
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: accent.confirm, onClick: handleConfirm, loading: isBusy, children: confirmText })
2177
+ ] }),
2178
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
2179
+ /* @__PURE__ */ jsxRuntime.jsx(
2180
+ "div",
2181
+ {
2182
+ className: cn(
2183
+ "flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full",
2184
+ accent.bg,
2185
+ accent.fg
2186
+ ),
2187
+ children: icon ?? icons[variant]
2188
+ }
2189
+ ),
2190
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 pt-0.5", children: [
2191
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { id: titleId, className: "text-[15px] font-semibold tracking-[-0.01em] text-[#1C1C1E]", children: title }),
2192
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { id: descId, className: "mt-1 text-[13px] leading-relaxed text-[#8E8E93]", children: description }),
2193
+ children && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3.5", children })
2194
+ ] })
2195
+ ] })
2196
+ }
2197
+ );
2198
+ }
1404
2199
  function useClickOutside(ref, handler, enabled = true) {
1405
2200
  React3.useEffect(() => {
1406
2201
  if (!enabled) return;
@@ -1427,6 +2222,7 @@ exports.CardFooter = CardFooter;
1427
2222
  exports.CardHeader = CardHeader;
1428
2223
  exports.CardTitle = CardTitle;
1429
2224
  exports.DataTable = DataTable;
2225
+ exports.Dialog = Dialog;
1430
2226
  exports.Drawer = Drawer;
1431
2227
  exports.Input = Input;
1432
2228
  exports.Menu = MenuRoot;
@@ -1438,6 +2234,12 @@ exports.MenuLabel = MenuLabel;
1438
2234
  exports.MenuRoot = MenuRoot;
1439
2235
  exports.MenuSeparator = MenuSeparator;
1440
2236
  exports.MenuTrigger = MenuTrigger;
2237
+ exports.Modal = Modal;
2238
+ exports.ModalBody = ModalBody;
2239
+ exports.ModalDescription = ModalDescription;
2240
+ exports.ModalFooter = ModalFooter;
2241
+ exports.ModalHeader = ModalHeader;
2242
+ exports.ModalTitle = ModalTitle;
1441
2243
  exports.Navbar = Navbar;
1442
2244
  exports.NavbarBrand = NavbarBrand;
1443
2245
  exports.NavbarCenter = NavbarCenter;
@@ -1447,6 +2249,8 @@ exports.NavbarLeft = NavbarLeft;
1447
2249
  exports.NavbarRight = NavbarRight;
1448
2250
  exports.NavbarSearch = NavbarSearch;
1449
2251
  exports.Scrollbar = Scrollbar;
2252
+ exports.Select = Select;
2253
+ exports.SelectSearch = SelectSearch;
1450
2254
  exports.Sheet = Sheet;
1451
2255
  exports.SheetContent = SheetContent;
1452
2256
  exports.SheetDescription = SheetDescription;
@@ -1461,8 +2265,6 @@ exports.SidebarFooter = SidebarFooter;
1461
2265
  exports.SidebarGroup = SidebarGroup;
1462
2266
  exports.SidebarHeader = SidebarHeader;
1463
2267
  exports.SidebarItem = SidebarItem;
1464
- exports.SidebarSubMenu = SidebarSubMenu;
1465
- exports.SidebarSubMenuItem = SidebarSubMenuItem;
1466
2268
  exports.SidebarToggle = SidebarToggle;
1467
2269
  exports.SidebarUser = SidebarUser;
1468
2270
  exports.Table = Table;
@@ -1486,7 +2288,10 @@ exports.colors = colors;
1486
2288
  exports.dismissToast = dismissToast;
1487
2289
  exports.generateId = generateId;
1488
2290
  exports.toast = toast;
2291
+ exports.useAnchoredPosition = useAnchoredPosition;
1489
2292
  exports.useClickOutside = useClickOutside;
2293
+ exports.useEscapeDismiss = useEscapeDismiss;
2294
+ exports.useFocusTrap = useFocusTrap;
1490
2295
  exports.useKeydown = useKeydown;
1491
2296
  exports.useToast = useToast;
1492
2297
  exports.withScrollbar = withScrollbar;