@expcat/tigercat-core 1.3.4 → 1.4.0

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.
Files changed (71) hide show
  1. package/dist/icons/registry.cjs +1 -3
  2. package/dist/icons/registry.js +1 -3
  3. package/dist/index.cjs +526 -190
  4. package/dist/index.d.cts +366 -268
  5. package/dist/index.d.ts +366 -268
  6. package/dist/index.js +508 -189
  7. package/dist/{locale-BuZwW3Ok.d.ts → locale-9tTj1QdZ.d.ts} +166 -1
  8. package/dist/{locale-DDFn0b6z.d.cts → locale-DxwhmqfF.d.cts} +166 -1
  9. package/dist/locales/ar-SA.cjs +61 -2
  10. package/dist/locales/ar-SA.d.cts +1 -1
  11. package/dist/locales/ar-SA.d.ts +1 -1
  12. package/dist/locales/ar-SA.js +61 -2
  13. package/dist/locales/de-DE.cjs +61 -2
  14. package/dist/locales/de-DE.d.cts +1 -1
  15. package/dist/locales/de-DE.d.ts +1 -1
  16. package/dist/locales/de-DE.js +61 -2
  17. package/dist/locales/en-US.cjs +61 -1
  18. package/dist/locales/en-US.d.cts +1 -1
  19. package/dist/locales/en-US.d.ts +1 -1
  20. package/dist/locales/en-US.js +59 -1
  21. package/dist/locales/es-ES.cjs +61 -2
  22. package/dist/locales/es-ES.d.cts +1 -1
  23. package/dist/locales/es-ES.d.ts +1 -1
  24. package/dist/locales/es-ES.js +61 -2
  25. package/dist/locales/fr-FR.cjs +61 -2
  26. package/dist/locales/fr-FR.d.cts +1 -1
  27. package/dist/locales/fr-FR.d.ts +1 -1
  28. package/dist/locales/fr-FR.js +61 -2
  29. package/dist/locales/id-ID.cjs +2 -1
  30. package/dist/locales/id-ID.d.cts +1 -1
  31. package/dist/locales/id-ID.d.ts +1 -1
  32. package/dist/locales/id-ID.js +2 -1
  33. package/dist/locales/ja-JP.cjs +2 -1
  34. package/dist/locales/ja-JP.d.cts +1 -1
  35. package/dist/locales/ja-JP.d.ts +1 -1
  36. package/dist/locales/ja-JP.js +2 -1
  37. package/dist/locales/ko-KR.cjs +2 -1
  38. package/dist/locales/ko-KR.d.cts +1 -1
  39. package/dist/locales/ko-KR.d.ts +1 -1
  40. package/dist/locales/ko-KR.js +2 -1
  41. package/dist/locales/pt-BR.cjs +61 -2
  42. package/dist/locales/pt-BR.d.cts +1 -1
  43. package/dist/locales/pt-BR.d.ts +1 -1
  44. package/dist/locales/pt-BR.js +61 -2
  45. package/dist/locales/th-TH.cjs +2 -1
  46. package/dist/locales/th-TH.d.cts +1 -1
  47. package/dist/locales/th-TH.d.ts +1 -1
  48. package/dist/locales/th-TH.js +2 -1
  49. package/dist/locales/vi-VN.cjs +2 -1
  50. package/dist/locales/vi-VN.d.cts +1 -1
  51. package/dist/locales/vi-VN.d.ts +1 -1
  52. package/dist/locales/vi-VN.js +2 -1
  53. package/dist/locales/zh-CN.cjs +61 -1
  54. package/dist/locales/zh-CN.d.cts +1 -1
  55. package/dist/locales/zh-CN.d.ts +1 -1
  56. package/dist/locales/zh-CN.js +59 -1
  57. package/dist/locales/zh-TW.cjs +2 -1
  58. package/dist/locales/zh-TW.d.cts +1 -1
  59. package/dist/locales/zh-TW.d.ts +1 -1
  60. package/dist/locales/zh-TW.js +2 -1
  61. package/dist/{table-export-DOqFkseW.d.cts → table-export-BMBH75rj.d.cts} +1 -1
  62. package/dist/{table-export-CZ7wtGf4.d.ts → table-export-GRimhvlM.d.ts} +1 -1
  63. package/dist/tailwind/modern.cjs +1 -1
  64. package/dist/tailwind/modern.js +1 -1
  65. package/dist/utils/table-export.cjs +7 -0
  66. package/dist/utils/table-export.d.cts +2 -2
  67. package/dist/utils/table-export.d.ts +2 -2
  68. package/dist/utils/table-export.js +7 -0
  69. package/package.json +2 -10
  70. package/tokens/tailwind-tokens.js +3 -6
  71. package/tokens/tokens.css +15 -30
package/dist/index.js CHANGED
@@ -585,6 +585,10 @@ function normalizeStringOption(options, key) {
585
585
  }
586
586
  return options;
587
587
  }
588
+ function createInstanceCounter() {
589
+ let counter = 0;
590
+ return () => ++counter;
591
+ }
588
592
 
589
593
  // src/utils/icons/common.ts
590
594
  var closeIconViewBox = "0 0 24 24";
@@ -659,9 +663,7 @@ var iconRegistry = {
659
663
  "arrow-right": stroke24("M13.5 4.5 21 12m0 0-7.5 7.5M21 12H3"),
660
664
  "arrow-up": stroke24("M4.5 10.5 12 3m0 0 7.5 7.5M12 3v18"),
661
665
  "arrow-down": stroke24("M19.5 13.5 12 21m0 0-7.5-7.5M12 21V3"),
662
- search: stroke24(
663
- "m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"
664
- ),
666
+ search: stroke24("m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"),
665
667
  plus: stroke24("M12 4.5v15m7.5-7.5h-15"),
666
668
  minus: stroke24("M5 12h14"),
667
669
  edit: stroke24(
@@ -838,6 +840,14 @@ function getFocusableElements(container) {
838
840
  );
839
841
  }
840
842
  function createFocusTrap(container, options = {}) {
843
+ if (!isBrowser()) {
844
+ return {
845
+ activate() {
846
+ },
847
+ deactivate() {
848
+ }
849
+ };
850
+ }
841
851
  const {
842
852
  initialFocus = null,
843
853
  returnFocusOnDeactivate = true,
@@ -920,6 +930,7 @@ function getOrCreateLiveRegion(level) {
920
930
  return el;
921
931
  }
922
932
  function announceToScreenReader(message, level = "polite") {
933
+ if (!isBrowser()) return;
923
934
  const region = getOrCreateLiveRegion(level);
924
935
  region.textContent = "";
925
936
  requestAnimationFrame(() => {
@@ -927,6 +938,16 @@ function announceToScreenReader(message, level = "polite") {
927
938
  });
928
939
  }
929
940
  function manageLiveRegion(level = "polite") {
941
+ if (!isBrowser()) {
942
+ return {
943
+ announce() {
944
+ },
945
+ clear() {
946
+ },
947
+ destroy() {
948
+ }
949
+ };
950
+ }
930
951
  const region = getOrCreateLiveRegion(level);
931
952
  return {
932
953
  announce(message) {
@@ -953,8 +974,8 @@ function getActiveElement(doc) {
953
974
  const active = doc?.activeElement;
954
975
  return isHTMLElement(active) ? active : null;
955
976
  }
956
- function captureActiveElement(doc = document) {
957
- return getActiveElement(doc);
977
+ function captureActiveElement(doc) {
978
+ return getActiveElement(doc ?? (isBrowser() ? document : void 0));
958
979
  }
959
980
  function focusElement(element, options) {
960
981
  if (!element) return false;
@@ -985,7 +1006,8 @@ function getMenuItems(container) {
985
1006
  function handleMenuNavigation(container, event) {
986
1007
  const items = getMenuItems(container);
987
1008
  if (items.length === 0) return false;
988
- const currentIndex = items.indexOf(document.activeElement);
1009
+ const activeElement = container.ownerDocument?.activeElement ?? (isBrowser() ? document.activeElement : null);
1010
+ const currentIndex = items.indexOf(activeElement);
989
1011
  let nextIndex = -1;
990
1012
  switch (event.key) {
991
1013
  case "ArrowDown":
@@ -1135,8 +1157,10 @@ var TIGER_LOCALE_KEYS = [
1135
1157
  "pagination",
1136
1158
  "table",
1137
1159
  "datePicker",
1160
+ "timePicker",
1138
1161
  "formWizard",
1139
- "taskBoard"
1162
+ "taskBoard",
1163
+ "formValidation"
1140
1164
  ];
1141
1165
  function isRecord3(value) {
1142
1166
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1182,8 +1206,10 @@ function mergeTigerLocale(base, override) {
1182
1206
  pagination: { ...base?.pagination, ...override?.pagination },
1183
1207
  table: { ...base?.table, ...override?.table },
1184
1208
  datePicker: { ...base?.datePicker, ...override?.datePicker },
1209
+ timePicker: { ...base?.timePicker, ...override?.timePicker },
1185
1210
  formWizard: { ...base?.formWizard, ...override?.formWizard },
1186
- taskBoard: { ...base?.taskBoard, ...override?.taskBoard }
1211
+ taskBoard: { ...base?.taskBoard, ...override?.taskBoard },
1212
+ formValidation: { ...base?.formValidation, ...override?.formValidation }
1187
1213
  };
1188
1214
  }
1189
1215
  var RTL_LANGUAGE_CODES = /* @__PURE__ */ new Set(["ar", "fa", "he", "iw", "ps", "ur"]);
@@ -1369,6 +1395,118 @@ function getTaskBoardLabels(locale, overrides) {
1369
1395
  boardAriaLabel: overrides?.boardAriaLabel ?? locale?.taskBoard?.boardAriaLabel ?? defaultLabels.boardAriaLabel
1370
1396
  };
1371
1397
  }
1398
+ var DEFAULT_FORM_VALIDATION_LABELS = {
1399
+ required: "This field is required",
1400
+ typeString: "Value must be a string",
1401
+ typeNumber: "Value must be a number",
1402
+ typeBoolean: "Value must be a boolean",
1403
+ typeArray: "Value must be an array",
1404
+ typeObject: "Value must be an object",
1405
+ email: "Please enter a valid email address",
1406
+ phone: "Please enter a valid phone number",
1407
+ url: "Please enter a valid URL",
1408
+ date: "Please enter a valid date",
1409
+ idCard: "Please enter a valid ID card number",
1410
+ minLength: "Minimum length is {min} characters",
1411
+ maxLength: "Maximum length is {max} characters",
1412
+ minValue: "Minimum value is {min}",
1413
+ maxValue: "Maximum value is {max}",
1414
+ minItems: "Minimum {min} items required",
1415
+ maxItems: "Maximum {max} items allowed",
1416
+ patternMismatch: "Value does not match the required pattern",
1417
+ validatorFailed: "Validation failed",
1418
+ validatorError: "Validation error occurred"
1419
+ };
1420
+ var ZH_CN_FORM_VALIDATION_LABELS = {
1421
+ required: "\u6B64\u5B57\u6BB5\u4E3A\u5FC5\u586B\u9879",
1422
+ typeString: "\u503C\u5FC5\u987B\u662F\u5B57\u7B26\u4E32",
1423
+ typeNumber: "\u503C\u5FC5\u987B\u662F\u6570\u5B57",
1424
+ typeBoolean: "\u503C\u5FC5\u987B\u662F\u5E03\u5C14\u503C",
1425
+ typeArray: "\u503C\u5FC5\u987B\u662F\u6570\u7EC4",
1426
+ typeObject: "\u503C\u5FC5\u987B\u662F\u5BF9\u8C61",
1427
+ email: "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u90AE\u7BB1\u5730\u5740",
1428
+ phone: "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u7535\u8BDD\u53F7\u7801",
1429
+ url: "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u7F51\u5740",
1430
+ date: "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u65E5\u671F",
1431
+ idCard: "\u8BF7\u8F93\u5165\u6709\u6548\u7684\u8EAB\u4EFD\u8BC1\u53F7\u7801",
1432
+ minLength: "\u957F\u5EA6\u4E0D\u80FD\u5C11\u4E8E {min} \u4E2A\u5B57\u7B26",
1433
+ maxLength: "\u957F\u5EA6\u4E0D\u80FD\u8D85\u8FC7 {max} \u4E2A\u5B57\u7B26",
1434
+ minValue: "\u6570\u503C\u4E0D\u80FD\u5C0F\u4E8E {min}",
1435
+ maxValue: "\u6570\u503C\u4E0D\u80FD\u5927\u4E8E {max}",
1436
+ minItems: "\u81F3\u5C11\u9700\u8981 {min} \u9879",
1437
+ maxItems: "\u6700\u591A\u5141\u8BB8 {max} \u9879",
1438
+ patternMismatch: "\u683C\u5F0F\u4E0D\u6B63\u786E",
1439
+ validatorFailed: "\u6821\u9A8C\u672A\u901A\u8FC7",
1440
+ validatorError: "\u6821\u9A8C\u65F6\u53D1\u751F\u9519\u8BEF"
1441
+ };
1442
+ function getFormValidationLabels(locale, overrides) {
1443
+ const isZh = !!locale?.locale?.startsWith("zh");
1444
+ const defaultLabels = isZh ? ZH_CN_FORM_VALIDATION_LABELS : DEFAULT_FORM_VALIDATION_LABELS;
1445
+ const fv = locale?.formValidation;
1446
+ const resolved = {};
1447
+ for (const key of Object.keys(defaultLabels)) {
1448
+ resolved[key] = overrides?.[key] ?? fv?.[key] ?? defaultLabels[key];
1449
+ }
1450
+ return resolved;
1451
+ }
1452
+ var DEFAULT_TIME_PICKER_LABELS = {
1453
+ hour: "Hour",
1454
+ minute: "Min",
1455
+ second: "Sec",
1456
+ now: "Now",
1457
+ ok: "OK",
1458
+ start: "Start",
1459
+ end: "End",
1460
+ clear: "Clear time",
1461
+ toggle: "Toggle time picker",
1462
+ dialog: "Time picker",
1463
+ selectTime: "Select time",
1464
+ selectTimeRange: "Select time range"
1465
+ };
1466
+ var ZH_CN_TIME_PICKER_LABELS = {
1467
+ hour: "\u65F6",
1468
+ minute: "\u5206",
1469
+ second: "\u79D2",
1470
+ now: "\u73B0\u5728",
1471
+ ok: "\u786E\u5B9A",
1472
+ start: "\u5F00\u59CB",
1473
+ end: "\u7ED3\u675F",
1474
+ clear: "\u6E05\u9664\u65F6\u95F4",
1475
+ toggle: "\u6253\u5F00\u65F6\u95F4\u9009\u62E9\u5668",
1476
+ dialog: "\u65F6\u95F4\u9009\u62E9\u5668",
1477
+ selectTime: "\u8BF7\u9009\u62E9\u65F6\u95F4",
1478
+ selectTimeRange: "\u8BF7\u9009\u62E9\u65F6\u95F4\u8303\u56F4"
1479
+ };
1480
+ var DEFAULT_UPLOAD_LABELS = {
1481
+ dragAreaAriaLabel: "Upload file by clicking or dragging",
1482
+ buttonAriaLabel: "Upload file",
1483
+ clickToUploadText: "Click to upload",
1484
+ dragAndDropText: "or drag and drop",
1485
+ acceptInfoText: "Accepted: {accept}",
1486
+ maxSizeInfoText: "Max size: {maxSize}",
1487
+ selectFileText: "Select File",
1488
+ uploadedFilesAriaLabel: "Uploaded files",
1489
+ successAriaLabel: "Success",
1490
+ errorAriaLabel: "Error",
1491
+ uploadingAriaLabel: "Uploading",
1492
+ removeFileAriaLabel: "Remove {fileName}",
1493
+ previewFileAriaLabel: "Preview {fileName}"
1494
+ };
1495
+ var ZH_CN_UPLOAD_LABELS = {
1496
+ dragAreaAriaLabel: "\u70B9\u51FB\u6216\u62D6\u62FD\u4E0A\u4F20\u6587\u4EF6",
1497
+ buttonAriaLabel: "\u4E0A\u4F20\u6587\u4EF6",
1498
+ clickToUploadText: "\u70B9\u51FB\u4E0A\u4F20",
1499
+ dragAndDropText: "\u6216\u62D6\u62FD\u5230\u6B64\u5904",
1500
+ acceptInfoText: "\u652F\u6301\uFF1A{accept}",
1501
+ maxSizeInfoText: "\u6700\u5927\u5927\u5C0F\uFF1A{maxSize}",
1502
+ selectFileText: "\u9009\u62E9\u6587\u4EF6",
1503
+ uploadedFilesAriaLabel: "\u5DF2\u4E0A\u4F20\u6587\u4EF6",
1504
+ successAriaLabel: "\u6210\u529F",
1505
+ errorAriaLabel: "\u9519\u8BEF",
1506
+ uploadingAriaLabel: "\u4E0A\u4F20\u4E2D",
1507
+ removeFileAriaLabel: "\u79FB\u9664 {fileName}",
1508
+ previewFileAriaLabel: "\u9884\u89C8 {fileName}"
1509
+ };
1372
1510
 
1373
1511
  // src/utils/datepicker-i18n.ts
1374
1512
  var EN_US_DATEPICKER_LOCALE = {
@@ -1469,35 +1607,104 @@ function getDatePickerLabels(locale, overrides) {
1469
1607
  };
1470
1608
  }
1471
1609
 
1610
+ // src/utils/picker-utils.ts
1611
+ var defaultIsDisabled = (item) => !!item?.disabled;
1612
+ function findFirstEnabledIndex(items, isDisabled = defaultIsDisabled) {
1613
+ for (let i = 0; i < items.length; i++) {
1614
+ if (!isDisabled(items[i])) return i;
1615
+ }
1616
+ return -1;
1617
+ }
1618
+ function findLastEnabledIndex(items, isDisabled = defaultIsDisabled) {
1619
+ for (let i = items.length - 1; i >= 0; i--) {
1620
+ if (!isDisabled(items[i])) return i;
1621
+ }
1622
+ return -1;
1623
+ }
1624
+ function findNextEnabledIndex(items, current, direction, isDisabled = defaultIsDisabled) {
1625
+ if (items.length === 0) return -1;
1626
+ const start = current < 0 ? direction === 1 ? 0 : items.length - 1 : current + direction;
1627
+ for (let i = start; i >= 0 && i < items.length; i += direction) {
1628
+ if (!isDisabled(items[i])) return i;
1629
+ }
1630
+ return current;
1631
+ }
1632
+ function getCyclicIndex(length, current, direction) {
1633
+ if (length <= 0) return -1;
1634
+ return (current + direction + length) % length;
1635
+ }
1636
+ function getInitialPickerActiveIndex(items, activeFirst, isDisabled = defaultIsDisabled) {
1637
+ return activeFirst ? findFirstEnabledIndex(items, isDisabled) : -1;
1638
+ }
1639
+ function getPickerNavigationIndex(items, current, key, isDisabled = defaultIsDisabled) {
1640
+ switch (key) {
1641
+ case "ArrowDown":
1642
+ return findNextEnabledIndex(items, current, 1, isDisabled);
1643
+ case "ArrowUp":
1644
+ return findNextEnabledIndex(items, current, -1, isDisabled);
1645
+ case "Home":
1646
+ return findFirstEnabledIndex(items, isDisabled);
1647
+ case "End":
1648
+ return findLastEnabledIndex(items, isDisabled);
1649
+ default:
1650
+ return current;
1651
+ }
1652
+ }
1653
+ function getPickerOptionId(listboxId, index) {
1654
+ return `${listboxId}-option-${index}`;
1655
+ }
1656
+ function getDisclosureStateAttr(open) {
1657
+ return { "data-state": open ? "open" : "closed" };
1658
+ }
1659
+ function getPickerComboboxAria({
1660
+ expanded,
1661
+ listboxId,
1662
+ activeIndex = -1,
1663
+ activeOptionId
1664
+ }) {
1665
+ return {
1666
+ role: "combobox",
1667
+ "aria-expanded": expanded,
1668
+ "aria-haspopup": "listbox",
1669
+ "aria-controls": expanded ? listboxId : void 0,
1670
+ "aria-activedescendant": expanded ? activeOptionId ?? (activeIndex >= 0 ? getPickerOptionId(listboxId, activeIndex) : void 0) : void 0,
1671
+ "data-state": expanded ? "open" : "closed"
1672
+ };
1673
+ }
1674
+ function getPickerListboxAria({ id, label } = {}) {
1675
+ return {
1676
+ id,
1677
+ role: "listbox",
1678
+ "aria-label": label
1679
+ };
1680
+ }
1681
+ function getPickerOptionAria({
1682
+ selected = false,
1683
+ disabled = false
1684
+ }) {
1685
+ return {
1686
+ role: "option",
1687
+ "aria-selected": selected,
1688
+ "aria-disabled": disabled || void 0
1689
+ };
1690
+ }
1691
+ function getPickerTriggerKeyAction(key, expanded) {
1692
+ switch (key) {
1693
+ case "Enter":
1694
+ case " ":
1695
+ return "toggle";
1696
+ case "ArrowDown":
1697
+ return expanded ? "none" : "open";
1698
+ case "Escape":
1699
+ return expanded ? "close" : "none";
1700
+ default:
1701
+ return "none";
1702
+ }
1703
+ }
1704
+
1472
1705
  // src/utils/timepicker-utils.ts
1473
- var ZH_LABELS = {
1474
- hour: "\u65F6",
1475
- minute: "\u5206",
1476
- second: "\u79D2",
1477
- now: "\u73B0\u5728",
1478
- ok: "\u786E\u5B9A",
1479
- start: "\u5F00\u59CB",
1480
- end: "\u7ED3\u675F",
1481
- clear: "\u6E05\u9664\u65F6\u95F4",
1482
- toggle: "\u6253\u5F00\u65F6\u95F4\u9009\u62E9\u5668",
1483
- dialog: "\u65F6\u95F4\u9009\u62E9\u5668",
1484
- selectTime: "\u8BF7\u9009\u62E9\u65F6\u95F4",
1485
- selectTimeRange: "\u8BF7\u9009\u62E9\u65F6\u95F4\u8303\u56F4"
1486
- };
1487
- var EN_LABELS = {
1488
- hour: "Hour",
1489
- minute: "Min",
1490
- second: "Sec",
1491
- now: "Now",
1492
- ok: "OK",
1493
- start: "Start",
1494
- end: "End",
1495
- clear: "Clear time",
1496
- toggle: "Toggle time picker",
1497
- dialog: "Time picker",
1498
- selectTime: "Select time",
1499
- selectTimeRange: "Select time range"
1500
- };
1706
+ var EN_LABELS = DEFAULT_TIME_PICKER_LABELS;
1707
+ var ZH_LABELS = ZH_CN_TIME_PICKER_LABELS;
1501
1708
  var TIME_PICKER_LABELS_BY_LANGUAGE = {
1502
1709
  en: EN_LABELS,
1503
1710
  zh: ZH_LABELS,
@@ -1572,26 +1779,59 @@ var TIME_PICKER_LABELS_BY_LANGUAGE = {
1572
1779
  selectTimeRange: "\u0627\u062E\u062A\u0631 \u0646\u0637\u0627\u0642 \u0627\u0644\u0648\u0642\u062A"
1573
1780
  }
1574
1781
  };
1782
+ function getTimePickerLocaleCode(locale) {
1783
+ return typeof locale === "string" ? locale : locale?.locale;
1784
+ }
1575
1785
  function isZhLocale(locale) {
1576
- return (locale ?? "").toLowerCase().startsWith("zh");
1786
+ return (getTimePickerLocaleCode(locale) ?? "").toLowerCase().startsWith("zh");
1577
1787
  }
1578
1788
  function getTimePickerLabels(locale, overrides) {
1579
- const language = (locale ?? "").split("-")[0]?.toLowerCase();
1789
+ const localeCode = getTimePickerLocaleCode(locale);
1790
+ const language = (localeCode ?? "").split("-")[0]?.toLowerCase();
1580
1791
  const base = language ? TIME_PICKER_LABELS_BY_LANGUAGE[language] ?? EN_LABELS : EN_LABELS;
1581
- return { ...base, ...overrides ?? {} };
1792
+ const localeLabels = typeof locale === "string" ? void 0 : locale?.timePicker;
1793
+ return { ...base, ...localeLabels ?? {}, ...overrides ?? {} };
1582
1794
  }
1583
1795
  function pluralizeEn(value, singular) {
1584
1796
  return getIntlPluralCategory(value, "en") === "one" ? singular : `${singular}s`;
1585
1797
  }
1586
1798
  function getTimePickerOptionAriaLabel(value, unit, locale, labelOverrides) {
1587
1799
  const labels = getTimePickerLabels(locale, labelOverrides);
1800
+ const localeCode = getTimePickerLocaleCode(locale);
1588
1801
  const unitLabel = unit === "hour" ? labels.hour : unit === "minute" ? labels.minute : labels.second;
1589
- if (isZhLocale(locale)) return `${formatIntlNumber(value, locale)}${unitLabel}`;
1590
- const lc = (locale ?? "").toLowerCase();
1802
+ if (isZhLocale(locale)) return `${formatIntlNumber(value, localeCode)}${unitLabel}`;
1803
+ const lc = (localeCode ?? "").toLowerCase();
1591
1804
  if (lc.startsWith("en") || !lc && !labelOverrides) {
1592
- return `${formatIntlNumber(value, locale)} ${pluralizeEn(value, unit)}`;
1805
+ return `${formatIntlNumber(value, localeCode)} ${pluralizeEn(value, unit)}`;
1806
+ }
1807
+ return `${formatIntlNumber(value, localeCode)} ${unitLabel}`;
1808
+ }
1809
+ function focusTimePickerOption(panel, unit, action) {
1810
+ if (!panel) return;
1811
+ const nodes = Array.from(
1812
+ panel.querySelectorAll(`button[data-tiger-timepicker-unit="${unit}"]`)
1813
+ ).filter((button) => !button.disabled);
1814
+ if (nodes.length === 0) return;
1815
+ const active = panel.ownerDocument.activeElement;
1816
+ const activeIndex = active ? nodes.indexOf(active) : -1;
1817
+ const selectedIndex = nodes.findIndex((button) => button.getAttribute("aria-selected") === "true");
1818
+ const baseIndex = activeIndex >= 0 ? activeIndex : Math.max(0, selectedIndex);
1819
+ let nextIndex = baseIndex;
1820
+ switch (action) {
1821
+ case "prev":
1822
+ nextIndex = findNextEnabledIndex(nodes, baseIndex, -1);
1823
+ break;
1824
+ case "next":
1825
+ nextIndex = findNextEnabledIndex(nodes, baseIndex, 1);
1826
+ break;
1827
+ case "first":
1828
+ nextIndex = findFirstEnabledIndex(nodes);
1829
+ break;
1830
+ case "last":
1831
+ nextIndex = findLastEnabledIndex(nodes);
1832
+ break;
1593
1833
  }
1594
- return `${formatIntlNumber(value, locale)} ${unitLabel}`;
1834
+ nodes[nextIndex]?.focus();
1595
1835
  }
1596
1836
  var timePickerBaseClasses = "relative inline-block w-full max-w-xs";
1597
1837
  var timePickerInputWrapperClasses = "relative flex items-center";
@@ -1728,67 +1968,67 @@ function interpolateUploadLabel(template, params) {
1728
1968
  function getUploadLabels(locale, overrides) {
1729
1969
  return {
1730
1970
  dragAreaAriaLabel: resolveLocaleText(
1731
- "Upload file by clicking or dragging",
1971
+ DEFAULT_UPLOAD_LABELS.dragAreaAriaLabel,
1732
1972
  overrides?.dragAreaAriaLabel,
1733
1973
  locale?.upload?.dragAreaAriaLabel
1734
1974
  ),
1735
1975
  buttonAriaLabel: resolveLocaleText(
1736
- "Upload file",
1976
+ DEFAULT_UPLOAD_LABELS.buttonAriaLabel,
1737
1977
  overrides?.buttonAriaLabel,
1738
1978
  locale?.upload?.buttonAriaLabel
1739
1979
  ),
1740
1980
  clickToUploadText: resolveLocaleText(
1741
- "Click to upload",
1981
+ DEFAULT_UPLOAD_LABELS.clickToUploadText,
1742
1982
  overrides?.clickToUploadText,
1743
1983
  locale?.upload?.clickToUploadText
1744
1984
  ),
1745
1985
  dragAndDropText: resolveLocaleText(
1746
- "or drag and drop",
1986
+ DEFAULT_UPLOAD_LABELS.dragAndDropText,
1747
1987
  overrides?.dragAndDropText,
1748
1988
  locale?.upload?.dragAndDropText
1749
1989
  ),
1750
1990
  acceptInfoText: resolveLocaleText(
1751
- "Accepted: {accept}",
1991
+ DEFAULT_UPLOAD_LABELS.acceptInfoText,
1752
1992
  overrides?.acceptInfoText,
1753
1993
  locale?.upload?.acceptInfoText
1754
1994
  ),
1755
1995
  maxSizeInfoText: resolveLocaleText(
1756
- "Max size: {maxSize}",
1996
+ DEFAULT_UPLOAD_LABELS.maxSizeInfoText,
1757
1997
  overrides?.maxSizeInfoText,
1758
1998
  locale?.upload?.maxSizeInfoText
1759
1999
  ),
1760
2000
  selectFileText: resolveLocaleText(
1761
- "Select File",
2001
+ DEFAULT_UPLOAD_LABELS.selectFileText,
1762
2002
  overrides?.selectFileText,
1763
2003
  locale?.upload?.selectFileText
1764
2004
  ),
1765
2005
  uploadedFilesAriaLabel: resolveLocaleText(
1766
- "Uploaded files",
2006
+ DEFAULT_UPLOAD_LABELS.uploadedFilesAriaLabel,
1767
2007
  overrides?.uploadedFilesAriaLabel,
1768
2008
  locale?.upload?.uploadedFilesAriaLabel
1769
2009
  ),
1770
2010
  successAriaLabel: resolveLocaleText(
1771
- "Success",
2011
+ DEFAULT_UPLOAD_LABELS.successAriaLabel,
1772
2012
  overrides?.successAriaLabel,
1773
2013
  locale?.upload?.successAriaLabel
1774
2014
  ),
1775
2015
  errorAriaLabel: resolveLocaleText(
1776
- "Error",
2016
+ DEFAULT_UPLOAD_LABELS.errorAriaLabel,
1777
2017
  overrides?.errorAriaLabel,
1778
2018
  locale?.upload?.errorAriaLabel
1779
2019
  ),
1780
2020
  uploadingAriaLabel: resolveLocaleText(
1781
- "Uploading",
2021
+ DEFAULT_UPLOAD_LABELS.uploadingAriaLabel,
1782
2022
  overrides?.uploadingAriaLabel,
1783
2023
  locale?.upload?.uploadingAriaLabel
1784
2024
  ),
1785
2025
  removeFileAriaLabel: resolveLocaleText(
1786
- "Remove {fileName}",
2026
+ DEFAULT_UPLOAD_LABELS.removeFileAriaLabel,
1787
2027
  overrides?.removeFileAriaLabel,
1788
2028
  locale?.upload?.removeFileAriaLabel
1789
2029
  ),
1790
2030
  previewFileAriaLabel: resolveLocaleText(
1791
- "Preview {fileName}",
2031
+ DEFAULT_UPLOAD_LABELS.previewFileAriaLabel,
1792
2032
  overrides?.previewFileAriaLabel,
1793
2033
  locale?.upload?.previewFileAriaLabel
1794
2034
  )
@@ -1804,7 +2044,10 @@ var enUS = {
1804
2044
  cancelText: "Cancel",
1805
2045
  closeText: "Close",
1806
2046
  loadingText: "Loading...",
1807
- emptyText: "No data"
2047
+ emptyText: "No data",
2048
+ noMoreText: "No more data",
2049
+ searchPlaceholder: "Search",
2050
+ clearText: "Clear"
1808
2051
  },
1809
2052
  modal: {
1810
2053
  closeAriaLabel: "Close",
@@ -1814,6 +2057,7 @@ var enUS = {
1814
2057
  drawer: {
1815
2058
  closeAriaLabel: "Close"
1816
2059
  },
2060
+ upload: DEFAULT_UPLOAD_LABELS,
1817
2061
  pagination: {
1818
2062
  totalText: "Total {total} items",
1819
2063
  itemsPerPageText: "/ page",
@@ -1843,6 +2087,7 @@ var enUS = {
1843
2087
  lockColumnAriaLabel: "Lock column {column}",
1844
2088
  unlockColumnAriaLabel: "Unlock column {column}"
1845
2089
  },
2090
+ timePicker: DEFAULT_TIME_PICKER_LABELS,
1846
2091
  formWizard: {
1847
2092
  prevText: "Previous",
1848
2093
  nextText: "Next",
@@ -1854,6 +2099,28 @@ var enUS = {
1854
2099
  wipLimitText: "WIP limit: {limit}",
1855
2100
  dragHintText: "Drag to move",
1856
2101
  boardAriaLabel: "Task Board"
2102
+ },
2103
+ formValidation: {
2104
+ required: "This field is required",
2105
+ typeString: "Value must be a string",
2106
+ typeNumber: "Value must be a number",
2107
+ typeBoolean: "Value must be a boolean",
2108
+ typeArray: "Value must be an array",
2109
+ typeObject: "Value must be an object",
2110
+ email: "Please enter a valid email address",
2111
+ phone: "Please enter a valid phone number",
2112
+ url: "Please enter a valid URL",
2113
+ date: "Please enter a valid date",
2114
+ idCard: "Please enter a valid ID card number",
2115
+ minLength: "Minimum length is {min} characters",
2116
+ maxLength: "Maximum length is {max} characters",
2117
+ minValue: "Minimum value is {min}",
2118
+ maxValue: "Maximum value is {max}",
2119
+ minItems: "Minimum {min} items required",
2120
+ maxItems: "Maximum {max} items allowed",
2121
+ patternMismatch: "Value does not match the required pattern",
2122
+ validatorFailed: "Validation failed",
2123
+ validatorError: "Validation error occurred"
1857
2124
  }
1858
2125
  };
1859
2126
 
@@ -2106,6 +2373,18 @@ function isAtMax(value, max = Infinity) {
2106
2373
  if (value === null || value === void 0) return false;
2107
2374
  return value >= max;
2108
2375
  }
2376
+ function formatInputNumberDisplay(value, options = {}) {
2377
+ if (value === null || value === void 0) return "";
2378
+ if (options.formatter) return options.formatter(value);
2379
+ if (options.precision !== void 0) return value.toFixed(options.precision);
2380
+ return String(value);
2381
+ }
2382
+ function parseInputNumberValue(str, options = {}) {
2383
+ if (str === "" || str === "-") return null;
2384
+ if (options.parser) return options.parser(str);
2385
+ const num = Number(str);
2386
+ return Number.isNaN(num) ? null : num;
2387
+ }
2109
2388
 
2110
2389
  // src/utils/form-item-styles.ts
2111
2390
  var FORM_ITEM_SPACING = {
@@ -2500,128 +2779,128 @@ function isEmpty(value) {
2500
2779
  }
2501
2780
  return false;
2502
2781
  }
2503
- function validateType(value, type, customMessage) {
2782
+ function validateType(value, type, customMessage, messages = DEFAULT_FORM_VALIDATION_LABELS) {
2504
2783
  switch (type) {
2505
2784
  case "string":
2506
2785
  if (typeof value !== "string") {
2507
- return customMessage || "Value must be a string";
2786
+ return customMessage || messages.typeString;
2508
2787
  }
2509
2788
  break;
2510
2789
  case "number":
2511
2790
  if (typeof value !== "number" && isNaN(Number(value))) {
2512
- return customMessage || "Value must be a number";
2791
+ return customMessage || messages.typeNumber;
2513
2792
  }
2514
2793
  break;
2515
2794
  case "boolean":
2516
2795
  if (typeof value !== "boolean") {
2517
- return customMessage || "Value must be a boolean";
2796
+ return customMessage || messages.typeBoolean;
2518
2797
  }
2519
2798
  break;
2520
2799
  case "array":
2521
2800
  if (!Array.isArray(value)) {
2522
- return customMessage || "Value must be an array";
2801
+ return customMessage || messages.typeArray;
2523
2802
  }
2524
2803
  break;
2525
2804
  case "object":
2526
2805
  if (typeof value !== "object" || Array.isArray(value)) {
2527
- return customMessage || "Value must be an object";
2806
+ return customMessage || messages.typeObject;
2528
2807
  }
2529
2808
  break;
2530
2809
  case "email":
2531
2810
  if (typeof value === "string" && !EMAIL_PATTERN.test(value)) {
2532
- return customMessage || "Please enter a valid email address";
2811
+ return customMessage || messages.email;
2533
2812
  }
2534
2813
  break;
2535
2814
  case "phone":
2536
2815
  if (typeof value === "string") {
2537
2816
  const digits = value.replace(/\D/g, "");
2538
2817
  if (!PHONE_PATTERN.test(value) || digits.length < 7) {
2539
- return customMessage || "Please enter a valid phone number";
2818
+ return customMessage || messages.phone;
2540
2819
  }
2541
2820
  }
2542
2821
  break;
2543
2822
  case "url":
2544
2823
  if (typeof value === "string" && !URL_PATTERN.test(value)) {
2545
- return customMessage || "Please enter a valid URL";
2824
+ return customMessage || messages.url;
2546
2825
  }
2547
2826
  break;
2548
2827
  case "date":
2549
2828
  if (!(value instanceof Date) && isNaN(Date.parse(String(value)))) {
2550
- return customMessage || "Please enter a valid date";
2829
+ return customMessage || messages.date;
2551
2830
  }
2552
2831
  break;
2553
2832
  case "id-card":
2554
2833
  if (typeof value === "string" && !ID_CARD_PATTERN.test(value)) {
2555
- return customMessage || "Please enter a valid ID card number";
2834
+ return customMessage || messages.idCard;
2556
2835
  }
2557
2836
  break;
2558
2837
  }
2559
2838
  return null;
2560
2839
  }
2561
- function validateRange(value, min, max, customMessage) {
2840
+ function validateRange(value, min, max, customMessage, messages = DEFAULT_FORM_VALIDATION_LABELS) {
2562
2841
  if (typeof value === "string") {
2563
2842
  if (min !== void 0 && value.length < min) {
2564
- return customMessage || `Minimum length is ${min} characters`;
2843
+ return customMessage || messages.minLength.replace("{min}", String(min));
2565
2844
  }
2566
2845
  if (max !== void 0 && value.length > max) {
2567
- return customMessage || `Maximum length is ${max} characters`;
2846
+ return customMessage || messages.maxLength.replace("{max}", String(max));
2568
2847
  }
2569
2848
  }
2570
2849
  if (typeof value === "number") {
2571
2850
  if (min !== void 0 && value < min) {
2572
- return customMessage || `Minimum value is ${min}`;
2851
+ return customMessage || messages.minValue.replace("{min}", String(min));
2573
2852
  }
2574
2853
  if (max !== void 0 && value > max) {
2575
- return customMessage || `Maximum value is ${max}`;
2854
+ return customMessage || messages.maxValue.replace("{max}", String(max));
2576
2855
  }
2577
2856
  }
2578
2857
  if (Array.isArray(value)) {
2579
2858
  if (min !== void 0 && value.length < min) {
2580
- return customMessage || `Minimum ${min} items required`;
2859
+ return customMessage || messages.minItems.replace("{min}", String(min));
2581
2860
  }
2582
2861
  if (max !== void 0 && value.length > max) {
2583
- return customMessage || `Maximum ${max} items allowed`;
2862
+ return customMessage || messages.maxItems.replace("{max}", String(max));
2584
2863
  }
2585
2864
  }
2586
2865
  return null;
2587
2866
  }
2588
- async function validateRule(value, rule, allValues) {
2867
+ async function validateRule(value, rule, allValues, messages = DEFAULT_FORM_VALIDATION_LABELS) {
2589
2868
  if (!rule.required && isEmpty(value)) {
2590
2869
  return null;
2591
2870
  }
2592
2871
  const transformedValue = rule.transform ? rule.transform(value) : value;
2593
2872
  if (rule.required && isEmpty(transformedValue)) {
2594
- return rule.message || "This field is required";
2873
+ return rule.message || messages.required;
2595
2874
  }
2596
2875
  if (rule.type && !isEmpty(transformedValue)) {
2597
- const typeError = validateType(transformedValue, rule.type, rule.message);
2876
+ const typeError = validateType(transformedValue, rule.type, rule.message, messages);
2598
2877
  if (typeError) return typeError;
2599
2878
  }
2600
2879
  if (!isEmpty(transformedValue)) {
2601
- const rangeError = validateRange(transformedValue, rule.min, rule.max, rule.message);
2880
+ const rangeError = validateRange(transformedValue, rule.min, rule.max, rule.message, messages);
2602
2881
  if (rangeError) return rangeError;
2603
2882
  }
2604
2883
  if (rule.pattern && typeof transformedValue === "string") {
2605
2884
  if (!rule.pattern.test(transformedValue)) {
2606
- return rule.message || "Value does not match the required pattern";
2885
+ return rule.message || messages.patternMismatch;
2607
2886
  }
2608
2887
  }
2609
2888
  if (rule.validator) {
2610
2889
  try {
2611
2890
  const result = await rule.validator(transformedValue, allValues);
2612
2891
  if (result === false) {
2613
- return rule.message || "Validation failed";
2892
+ return rule.message || messages.validatorFailed;
2614
2893
  }
2615
2894
  if (typeof result === "string") {
2616
2895
  return result;
2617
2896
  }
2618
2897
  } catch {
2619
- return rule.message || "Validation error occurred";
2898
+ return rule.message || messages.validatorError;
2620
2899
  }
2621
2900
  }
2622
2901
  return null;
2623
2902
  }
2624
- async function validateField(fieldName, value, rules, allValues, trigger) {
2903
+ async function validateField(fieldName, value, rules, allValues, trigger, messages = DEFAULT_FORM_VALIDATION_LABELS) {
2625
2904
  if (!rules) {
2626
2905
  return null;
2627
2906
  }
@@ -2634,18 +2913,18 @@ async function validateField(fieldName, value, rules, allValues, trigger) {
2634
2913
  continue;
2635
2914
  }
2636
2915
  }
2637
- const error = await validateRule(value, rule, allValues);
2916
+ const error = await validateRule(value, rule, allValues, messages);
2638
2917
  if (error) {
2639
2918
  return error;
2640
2919
  }
2641
2920
  }
2642
2921
  return null;
2643
2922
  }
2644
- async function validateForm(values, rules) {
2923
+ async function validateForm(values, rules, messages = DEFAULT_FORM_VALIDATION_LABELS) {
2645
2924
  const errors = [];
2646
2925
  for (const [fieldName, fieldRules] of Object.entries(rules)) {
2647
2926
  const value = getValueByPath(values, fieldName);
2648
- const error = await validateField(fieldName, value, fieldRules, values);
2927
+ const error = await validateField(fieldName, value, fieldRules, values, void 0, messages);
2649
2928
  if (error) {
2650
2929
  errors.push({
2651
2930
  field: fieldName,
@@ -2658,14 +2937,14 @@ async function validateForm(values, rules) {
2658
2937
  errors
2659
2938
  };
2660
2939
  }
2661
- async function validateFormFields(values, rules, fieldNames, trigger) {
2940
+ async function validateFormFields(values, rules, fieldNames, trigger, messages = DEFAULT_FORM_VALIDATION_LABELS) {
2662
2941
  const errors = [];
2663
2942
  const uniqueFieldNames = Array.from(new Set(fieldNames));
2664
2943
  for (const fieldName of uniqueFieldNames) {
2665
2944
  const fieldRules = rules[fieldName];
2666
2945
  if (!fieldRules) continue;
2667
2946
  const value = getValueByPath(values, fieldName);
2668
- const error = await validateField(fieldName, value, fieldRules, values, trigger);
2947
+ const error = await validateField(fieldName, value, fieldRules, values, trigger, messages);
2669
2948
  if (error) {
2670
2949
  errors.push({ field: fieldName, message: error });
2671
2950
  }
@@ -2813,6 +3092,23 @@ function normalizeDate(date) {
2813
3092
  normalized.setHours(0, 0, 0, 0);
2814
3093
  return normalized;
2815
3094
  }
3095
+ function addDays(date, days) {
3096
+ const next = new Date(date);
3097
+ next.setDate(next.getDate() + days);
3098
+ return next;
3099
+ }
3100
+ function addMonths(date, months) {
3101
+ const next = new Date(date);
3102
+ const day = next.getDate();
3103
+ next.setDate(1);
3104
+ next.setMonth(next.getMonth() + months);
3105
+ const maxDay = getDaysInMonth(next.getFullYear(), next.getMonth());
3106
+ next.setDate(Math.min(day, maxDay));
3107
+ return next;
3108
+ }
3109
+ function addYears(date, years) {
3110
+ return addMonths(date, years * 12);
3111
+ }
2816
3112
  function isDateInRange(date, minDate, maxDate) {
2817
3113
  if (isNaN(date.getTime())) return false;
2818
3114
  const normalizedDate = normalizeDate(date);
@@ -4794,6 +5090,75 @@ function getVisibleTreeItems(treeData, expandedKeys = /* @__PURE__ */ new Set(),
4794
5090
  traverse(treeData, 1);
4795
5091
  return result;
4796
5092
  }
5093
+ function getFirstVisibleChildKey(visibleItems, parentKey) {
5094
+ const index = visibleItems.findIndex((item) => item.key === parentKey);
5095
+ if (index < 0) return void 0;
5096
+ const base = visibleItems[index];
5097
+ for (let i = index + 1; i < visibleItems.length; i++) {
5098
+ const item = visibleItems[i];
5099
+ if (item.level <= base.level) break;
5100
+ if (item.parentKey === parentKey && !item.node.disabled) return item.key;
5101
+ }
5102
+ return void 0;
5103
+ }
5104
+ function getTreeKeyboardAction(ctx) {
5105
+ const {
5106
+ key,
5107
+ nodeKey,
5108
+ currentKey,
5109
+ focusableKeys,
5110
+ parentKey,
5111
+ firstChildKey,
5112
+ isExpandable,
5113
+ isExpanded,
5114
+ isParentExpanded,
5115
+ isChecked,
5116
+ selectable,
5117
+ checkable
5118
+ } = ctx;
5119
+ const currentIndex = focusableKeys.findIndex((k) => k === currentKey);
5120
+ const focusAt = (index) => ({
5121
+ type: "focus",
5122
+ key: focusableKeys[index] ?? currentKey
5123
+ });
5124
+ switch (key) {
5125
+ case "ArrowDown":
5126
+ return focusAt(currentIndex + 1);
5127
+ case "ArrowUp":
5128
+ return focusAt(currentIndex - 1);
5129
+ case "Home":
5130
+ return focusAt(0);
5131
+ case "End":
5132
+ return focusAt(focusableKeys.length - 1);
5133
+ case "ArrowRight":
5134
+ if (isExpandable && !isExpanded) return { type: "toggleExpand", key: nodeKey };
5135
+ if (isExpandable && isExpanded) return { type: "focus", key: firstChildKey ?? currentKey };
5136
+ return { type: "none" };
5137
+ case "ArrowLeft":
5138
+ if (isExpandable && isExpanded) return { type: "toggleExpand", key: nodeKey };
5139
+ return { type: "focus", key: parentKey ?? currentKey };
5140
+ case "Escape":
5141
+ if (isExpandable && isExpanded) return { type: "toggleExpand", key: nodeKey };
5142
+ if (parentKey !== void 0) {
5143
+ return {
5144
+ type: "collapseAndFocus",
5145
+ collapseKey: isParentExpanded ? parentKey : void 0,
5146
+ focusKey: parentKey
5147
+ };
5148
+ }
5149
+ return { type: "none" };
5150
+ case "Enter":
5151
+ if (selectable) return { type: "select", key: nodeKey };
5152
+ if (isExpandable) return { type: "toggleExpand", key: nodeKey };
5153
+ return { type: "none" };
5154
+ case " ":
5155
+ if (checkable) return { type: "check", key: nodeKey, checked: !isChecked };
5156
+ if (isExpandable) return { type: "toggleExpand", key: nodeKey };
5157
+ return { type: "none" };
5158
+ default:
5159
+ return null;
5160
+ }
5161
+ }
4797
5162
  var treeBaseClasses = "w-full bg-white rounded-[var(--tiger-radius-md,0.5rem)]";
4798
5163
  var treeNodeWrapperClasses = "select-none";
4799
5164
  var treeNodeContentClasses = "flex items-center px-2 py-1.5 cursor-pointer rounded transition-colors duration-200";
@@ -5551,6 +5916,10 @@ function createSubmenuHeightTransitionController(element, options) {
5551
5916
  }
5552
5917
  };
5553
5918
  }
5919
+ function getMenuNavigationKeys(mode, isRoot) {
5920
+ const isHorizontalRoot = isRoot && mode === "horizontal";
5921
+ return isHorizontalRoot ? { nextKey: "ArrowRight", prevKey: "ArrowLeft" } : { nextKey: "ArrowDown", prevKey: "ArrowUp" };
5922
+ }
5554
5923
  function getMenuButtons(container) {
5555
5924
  return Array.from(
5556
5925
  container.querySelectorAll('button[data-tiger-menuitem="true"]')
@@ -7076,7 +7445,7 @@ function getCodeBlockCopyButtonClasses(isCopied, ...classes) {
7076
7445
  );
7077
7446
  }
7078
7447
 
7079
- // src/theme/colors.ts
7448
+ // src/theme-runtime/colors.ts
7080
7449
  var defaultThemeColors = {
7081
7450
  primary: {
7082
7451
  bg: "bg-[var(--tiger-primary,#2563eb)]",
@@ -7554,6 +7923,9 @@ function getInitialCropRect(imageWidth, imageHeight, aspectRatio) {
7554
7923
  };
7555
7924
  }
7556
7925
  function cropCanvas(image, cropRect, displayWidth, displayHeight, outputType = "image/png", quality = 0.92) {
7926
+ if (!isBrowser()) {
7927
+ throw new Error("Image canvas cropping is only available in the browser");
7928
+ }
7557
7929
  const scaleX = image.naturalWidth / displayWidth;
7558
7930
  const scaleY = image.naturalHeight / displayHeight;
7559
7931
  const sx = cropRect.x * scaleX;
@@ -7894,6 +8266,9 @@ function getAnchorLinkClasses(active, className) {
7894
8266
  return [anchorLinkBaseClasses, active && anchorLinkActiveClasses, className].filter(Boolean).join(" ");
7895
8267
  }
7896
8268
  function getAnchorTargetElement(href) {
8269
+ if (!isBrowser()) {
8270
+ return null;
8271
+ }
7897
8272
  if (!href || !href.startsWith("#")) {
7898
8273
  return null;
7899
8274
  }
@@ -7904,18 +8279,27 @@ function getAnchorTargetElement(href) {
7904
8279
  return document.getElementById(id);
7905
8280
  }
7906
8281
  function getContainerScrollTop(container) {
8282
+ if (!isBrowser()) {
8283
+ return container?.scrollTop ?? 0;
8284
+ }
7907
8285
  if (container === window) {
7908
8286
  return window.scrollY || document.documentElement.scrollTop;
7909
8287
  }
7910
8288
  return container.scrollTop;
7911
8289
  }
7912
8290
  function getContainerHeight(container) {
8291
+ if (!isBrowser()) {
8292
+ return container?.clientHeight ?? 0;
8293
+ }
7913
8294
  if (container === window) {
7914
8295
  return window.innerHeight;
7915
8296
  }
7916
8297
  return container.clientHeight;
7917
8298
  }
7918
8299
  function getElementOffsetTop(element, container) {
8300
+ if (!isBrowser()) {
8301
+ return 0;
8302
+ }
7919
8303
  if (container === window) {
7920
8304
  const rect = element.getBoundingClientRect();
7921
8305
  return rect.top + window.scrollY;
@@ -7935,6 +8319,9 @@ function getElementOffsetTop(element, container) {
7935
8319
  return offset2;
7936
8320
  }
7937
8321
  function scrollToAnchor(href, container, targetOffset = 0) {
8322
+ if (!isBrowser()) {
8323
+ return;
8324
+ }
7938
8325
  const element = getAnchorTargetElement(href);
7939
8326
  if (!element) {
7940
8327
  return;
@@ -7947,6 +8334,9 @@ function findActiveAnchor(links, container, bounds = 5, targetOffset = 0) {
7947
8334
  if (links.length === 0) {
7948
8335
  return "";
7949
8336
  }
8337
+ if (!isBrowser()) {
8338
+ return links[0] || "";
8339
+ }
7950
8340
  const scrollTop = getContainerScrollTop(container);
7951
8341
  for (let i = links.length - 1; i >= 0; i--) {
7952
8342
  const href = links[i];
@@ -7961,11 +8351,11 @@ function findActiveAnchor(links, container, bounds = 5, targetOffset = 0) {
7961
8351
  return links[0] || "";
7962
8352
  }
7963
8353
  function createAnchorObserver(links, options) {
8354
+ if (!isBrowser()) return () => {
8355
+ };
7964
8356
  if (typeof IntersectionObserver === "undefined") return () => {
7965
8357
  };
7966
8358
  const { offsetTop = 0, root = null, onChange } = options;
7967
- if (!isBrowser()) return () => {
7968
- };
7969
8359
  const targets = /* @__PURE__ */ new Map();
7970
8360
  for (const href of links) {
7971
8361
  const el = getAnchorTargetElement(href);
@@ -11442,97 +11832,6 @@ function clampCronNumber(value, min, max) {
11442
11832
  return Math.max(min, Math.min(max, Math.round(value)));
11443
11833
  }
11444
11834
 
11445
- // src/utils/picker-utils.ts
11446
- var defaultIsDisabled = (item) => !!item?.disabled;
11447
- function findFirstEnabledIndex(items, isDisabled = defaultIsDisabled) {
11448
- for (let i = 0; i < items.length; i++) {
11449
- if (!isDisabled(items[i])) return i;
11450
- }
11451
- return -1;
11452
- }
11453
- function findLastEnabledIndex(items, isDisabled = defaultIsDisabled) {
11454
- for (let i = items.length - 1; i >= 0; i--) {
11455
- if (!isDisabled(items[i])) return i;
11456
- }
11457
- return -1;
11458
- }
11459
- function findNextEnabledIndex(items, current, direction, isDisabled = defaultIsDisabled) {
11460
- if (items.length === 0) return -1;
11461
- const start = current < 0 ? direction === 1 ? 0 : items.length - 1 : current + direction;
11462
- for (let i = start; i >= 0 && i < items.length; i += direction) {
11463
- if (!isDisabled(items[i])) return i;
11464
- }
11465
- return current;
11466
- }
11467
- function getInitialPickerActiveIndex(items, activeFirst, isDisabled = defaultIsDisabled) {
11468
- return activeFirst ? findFirstEnabledIndex(items, isDisabled) : -1;
11469
- }
11470
- function getPickerNavigationIndex(items, current, key, isDisabled = defaultIsDisabled) {
11471
- switch (key) {
11472
- case "ArrowDown":
11473
- return findNextEnabledIndex(items, current, 1, isDisabled);
11474
- case "ArrowUp":
11475
- return findNextEnabledIndex(items, current, -1, isDisabled);
11476
- case "Home":
11477
- return findFirstEnabledIndex(items, isDisabled);
11478
- case "End":
11479
- return findLastEnabledIndex(items, isDisabled);
11480
- default:
11481
- return current;
11482
- }
11483
- }
11484
- function getPickerOptionId(listboxId, index) {
11485
- return `${listboxId}-option-${index}`;
11486
- }
11487
- function getDisclosureStateAttr(open) {
11488
- return { "data-state": open ? "open" : "closed" };
11489
- }
11490
- function getPickerComboboxAria({
11491
- expanded,
11492
- listboxId,
11493
- activeIndex = -1,
11494
- activeOptionId
11495
- }) {
11496
- return {
11497
- role: "combobox",
11498
- "aria-expanded": expanded,
11499
- "aria-haspopup": "listbox",
11500
- "aria-controls": expanded ? listboxId : void 0,
11501
- "aria-activedescendant": expanded ? activeOptionId ?? (activeIndex >= 0 ? getPickerOptionId(listboxId, activeIndex) : void 0) : void 0,
11502
- "data-state": expanded ? "open" : "closed"
11503
- };
11504
- }
11505
- function getPickerListboxAria({ id, label } = {}) {
11506
- return {
11507
- id,
11508
- role: "listbox",
11509
- "aria-label": label
11510
- };
11511
- }
11512
- function getPickerOptionAria({
11513
- selected = false,
11514
- disabled = false
11515
- }) {
11516
- return {
11517
- role: "option",
11518
- "aria-selected": selected,
11519
- "aria-disabled": disabled || void 0
11520
- };
11521
- }
11522
- function getPickerTriggerKeyAction(key, expanded) {
11523
- switch (key) {
11524
- case "Enter":
11525
- case " ":
11526
- return "toggle";
11527
- case "ArrowDown":
11528
- return expanded ? "none" : "open";
11529
- case "Escape":
11530
- return expanded ? "close" : "none";
11531
- default:
11532
- return "none";
11533
- }
11534
- }
11535
-
11536
11835
  // src/utils/spotlight-utils.ts
11537
11836
  var spotlightRootClasses = "fixed inset-0 flex items-start justify-center px-4 py-6 sm:py-10";
11538
11837
  var spotlightMaskClasses = "absolute inset-0 bg-black/35";
@@ -12783,6 +13082,7 @@ function exportTableToExcel(columns, data) {
12783
13082
  return `<!doctype html><html><head><meta charset="utf-8"></head><body><table><thead><tr>${headerCells}</tr></thead><tbody>${bodyRows}</tbody></table></body></html>`;
12784
13083
  }
12785
13084
  function downloadCsv(csvContent, filename = "export") {
13085
+ if (!isBrowser()) return;
12786
13086
  const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
12787
13087
  const url = URL.createObjectURL(blob);
12788
13088
  const link = document.createElement("a");
@@ -12795,6 +13095,7 @@ function downloadCsv(csvContent, filename = "export") {
12795
13095
  URL.revokeObjectURL(url);
12796
13096
  }
12797
13097
  function downloadExcel(excelContent, filename = "export") {
13098
+ if (!isBrowser()) return;
12798
13099
  const blob = new Blob([excelContent], { type: "application/vnd.ms-excel;charset=utf-8;" });
12799
13100
  const url = URL.createObjectURL(blob);
12800
13101
  const link = document.createElement("a");
@@ -14256,7 +14557,6 @@ var kanbanSwimlaneDotClasses = "w-2.5 h-2.5 rounded-full shrink-0";
14256
14557
  var kanbanSwimlaneCollapsedClasses = "hidden";
14257
14558
  var kanbanFilterHighlightClasses = "bg-[var(--tiger-warning,#fbbf24)]/20";
14258
14559
  var kanbanAddColumnClasses = "flex items-center justify-center shrink-0 w-76 min-h-[120px] rounded-[var(--tiger-radius-lg,0.75rem)] border-2 border-dashed border-[var(--tiger-border,#e5e7eb)] bg-[var(--tiger-surface-muted,#f9fafb)]/40 text-sm font-medium text-[var(--tiger-text-muted,#6b7280)] hover:border-[var(--tiger-primary,#2563eb)]/80 hover:text-[var(--tiger-primary,#2563eb)] hover:bg-[var(--tiger-surface,#ffffff)] hover:shadow-sm cursor-pointer transition-all duration-300 active:scale-98";
14259
- var kanbanAddCardClasses = taskBoardAddCardClasses;
14260
14560
  function filterCards(cards, filterText) {
14261
14561
  if (!filterText.trim()) return cards;
14262
14562
  const lower = filterText.toLowerCase();
@@ -15277,6 +15577,7 @@ function getChartSvgDataUrl(svg) {
15277
15577
  return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(serializeChartSvg(svg))}`;
15278
15578
  }
15279
15579
  function downloadChartSvg(svg, filename = "chart") {
15580
+ if (!isBrowser()) return;
15280
15581
  downloadChartBlob(
15281
15582
  new Blob([serializeChartSvg(svg)], { type: "image/svg+xml;charset=utf-8" }),
15282
15583
  `${filename}.svg`
@@ -15316,6 +15617,7 @@ async function exportChartPng(svg, options = {}) {
15316
15617
  });
15317
15618
  }
15318
15619
  async function downloadChartPng(svg, options = {}) {
15620
+ if (!isBrowser()) return;
15319
15621
  const blob = await exportChartPng(svg, options);
15320
15622
  downloadChartBlob(blob, `${options.filename ?? "chart"}.png`);
15321
15623
  }
@@ -15492,7 +15794,7 @@ async function getCropperResult(cropper) {
15492
15794
  return await cropper.getCropResult();
15493
15795
  }
15494
15796
 
15495
- // src/theme/checkbox.ts
15797
+ // src/theme-runtime/checkbox.ts
15496
15798
  var checkboxSizeClasses2 = {
15497
15799
  sm: "w-4 h-4",
15498
15800
  md: "w-5 h-5",
@@ -15517,7 +15819,7 @@ function getCheckboxLabelClasses(size = "md", disabled = false) {
15517
15819
  return [baseClasses2, sizeClass, disabledClasses].filter(Boolean).join(" ");
15518
15820
  }
15519
15821
 
15520
- // src/theme/switch.ts
15822
+ // src/theme-runtime/switch.ts
15521
15823
  var switchBaseClasses = "relative inline-flex items-center rounded-full transition-all duration-150 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--tiger-focus-ring,var(--tiger-primary,#2563eb))] active:scale-[0.98]";
15522
15824
  var switchSizeClasses = {
15523
15825
  sm: "h-5 w-9",
@@ -15552,7 +15854,7 @@ function getSwitchThumbClasses(size = "md", checked = false) {
15552
15854
  return classNames(baseClasses2, sizeClass, translateClass);
15553
15855
  }
15554
15856
 
15555
- // src/theme/slider.ts
15857
+ // src/theme-runtime/slider.ts
15556
15858
  var sliderBaseClasses = "relative w-full";
15557
15859
  var sliderTrackClasses = "bg-[var(--tiger-border,#e5e7eb)] rounded-full";
15558
15860
  var sliderRangeClasses = "bg-[var(--tiger-primary,#2563eb)] rounded-full absolute h-full";
@@ -15591,7 +15893,7 @@ function getSliderTooltipClasses(size = "md") {
15591
15893
  return [sliderTooltipClasses, sizeClass].filter(Boolean).join(" ");
15592
15894
  }
15593
15895
 
15594
- // src/theme/index.ts
15896
+ // src/theme-runtime/index.ts
15595
15897
  var THEME_CSS_VARS = {
15596
15898
  // Primary colors
15597
15899
  primary: "--tiger-primary",
@@ -17154,7 +17456,7 @@ var designTokens = {
17154
17456
  };
17155
17457
 
17156
17458
  // src/index.ts
17157
- var version = "1.2.0";
17459
+ var version = "1.4.0";
17158
17460
  export {
17159
17461
  ANIMATION_DURATION_FAST_MS,
17160
17462
  ANIMATION_DURATION_MS,
@@ -17169,12 +17471,15 @@ export {
17169
17471
  ClockIconPath,
17170
17472
  CloseIconPath,
17171
17473
  DEFAULT_CHART_COLORS,
17474
+ DEFAULT_FORM_VALIDATION_LABELS,
17172
17475
  DEFAULT_FORM_WIZARD_LABELS,
17173
17476
  DEFAULT_HEATMAP_CANVAS_THRESHOLD,
17174
17477
  DEFAULT_PAGINATION_LABELS,
17175
17478
  DEFAULT_TABLE_LABELS,
17176
17479
  DEFAULT_TASK_BOARD_LABELS,
17480
+ DEFAULT_TIME_PICKER_LABELS,
17177
17481
  DEFAULT_UPLOAD_CHUNK_SIZE,
17482
+ DEFAULT_UPLOAD_LABELS,
17178
17483
  DONUT_BASE_SHADOW,
17179
17484
  DONUT_EMPHASIS_SHADOW,
17180
17485
  DROPDOWN_CHEVRON_PATH,
@@ -17232,10 +17537,13 @@ export {
17232
17537
  VIEW_TRANSITION_CSS,
17233
17538
  WEEKDAYS,
17234
17539
  ZH_CN_DATEPICKER_LOCALE,
17540
+ ZH_CN_FORM_VALIDATION_LABELS,
17235
17541
  ZH_CN_FORM_WIZARD_LABELS,
17236
17542
  ZH_CN_PAGINATION_LABELS,
17237
17543
  ZH_CN_TABLE_LABELS,
17238
17544
  ZH_CN_TASK_BOARD_LABELS,
17545
+ ZH_CN_TIME_PICKER_LABELS,
17546
+ ZH_CN_UPLOAD_LABELS,
17239
17547
  activeOpacityClasses,
17240
17548
  activePressClasses,
17241
17549
  activityItemActionsClasses,
@@ -17245,6 +17553,9 @@ export {
17245
17553
  activityItemHeaderClasses,
17246
17554
  activityItemLayoutClasses,
17247
17555
  activityItemTitleGroupClasses,
17556
+ addDays,
17557
+ addMonths,
17558
+ addYears,
17248
17559
  affixWrapperClasses,
17249
17560
  alertBannerClasses,
17250
17561
  alertBaseClasses,
@@ -17524,6 +17835,7 @@ export {
17524
17835
  createImageAnnotationBox,
17525
17836
  createImageAnnotationPath,
17526
17837
  createInfiniteScrollObserver,
17838
+ createInstanceCounter,
17527
17839
  createLinePath,
17528
17840
  createLinearScale,
17529
17841
  createLongPressController,
@@ -17719,6 +18031,7 @@ export {
17719
18031
  focusMenuEdge,
17720
18032
  focusRingClasses,
17721
18033
  focusRingInsetClasses,
18034
+ focusTimePickerOption,
17722
18035
  formatActivityTime,
17723
18036
  formatBadgeContent,
17724
18037
  formatChatTime,
@@ -17730,6 +18043,7 @@ export {
17730
18043
  formatFileSize,
17731
18044
  formatFileSizeLabel,
17732
18045
  formatGanttDate,
18046
+ formatInputNumberDisplay,
17733
18047
  formatIntlNumber,
17734
18048
  formatMonthYear,
17735
18049
  formatPageAriaLabel,
@@ -17865,6 +18179,7 @@ export {
17865
18179
  getCropperResult,
17866
18180
  getCurrentActiveTourStep,
17867
18181
  getCurrentTime,
18182
+ getCyclicIndex,
17868
18183
  getDatePickerDayCellClasses,
17869
18184
  getDatePickerIconButtonClasses,
17870
18185
  getDatePickerInputClasses,
@@ -17916,6 +18231,7 @@ export {
17916
18231
  getFileListItemClasses,
17917
18232
  getFileManagerContainerClasses,
17918
18233
  getFirstDayOfMonth,
18234
+ getFirstVisibleChildKey,
17919
18235
  getFixedColumnOffsets,
17920
18236
  getFixedColumnPosition,
17921
18237
  getFixedColumnStyle,
@@ -17931,6 +18247,7 @@ export {
17931
18247
  getFormItemErrorClasses,
17932
18248
  getFormItemFieldClasses,
17933
18249
  getFormItemLabelClasses,
18250
+ getFormValidationLabels,
17934
18251
  getFormWizardLabels,
17935
18252
  getFunnelGradientPrefix,
17936
18253
  getGanttDependencyPath,
@@ -18010,6 +18327,7 @@ export {
18010
18327
  getMenuItemClasses,
18011
18328
  getMenuItemIndent,
18012
18329
  getMenuItems,
18330
+ getMenuNavigationKeys,
18013
18331
  getMessageIconPath,
18014
18332
  getMessageTypeClasses,
18015
18333
  getModalContainerClasses,
@@ -18232,6 +18550,7 @@ export {
18232
18550
  getTransferItemClasses,
18233
18551
  getTransformOrigin,
18234
18552
  getTransitionClasses,
18553
+ getTreeKeyboardAction,
18235
18554
  getTreeMapGradientPrefix,
18236
18555
  getTreeNodeClasses,
18237
18556
  getTreeNodeExpandIconClasses,
@@ -18406,7 +18725,6 @@ export {
18406
18725
  isValidHex,
18407
18726
  isValidUrl,
18408
18727
  isWipExceeded,
18409
- kanbanAddCardClasses,
18410
18728
  kanbanAddColumnClasses,
18411
18729
  kanbanCardCountClasses,
18412
18730
  kanbanFilterHighlightClasses,
@@ -18579,6 +18897,7 @@ export {
18579
18897
  parseDragData,
18580
18898
  parseHeight,
18581
18899
  parseHotkey,
18900
+ parseInputNumberValue,
18582
18901
  parseInputValue,
18583
18902
  parseHeight as parseMarkdownHeight,
18584
18903
  parsePaneSize,