@geektech/one 0.0.1 → 0.1.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 (63) hide show
  1. package/README-zh.md +155 -3
  2. package/README.md +158 -3
  3. package/dist/alert/OneAlert.d.ts +21 -0
  4. package/dist/alert/index.d.ts +2 -0
  5. package/dist/badge/OneBadge.d.ts +18 -0
  6. package/dist/badge/index.d.ts +2 -0
  7. package/dist/breadcrumb/OneBreadcrumb.d.ts +38 -0
  8. package/dist/breadcrumb/index.d.ts +1 -0
  9. package/dist/categories.d.ts +7 -3
  10. package/dist/checkbox/OneCheckboxGroup.d.ts +2 -0
  11. package/dist/data-display/index.d.ts +2 -0
  12. package/dist/data-display/types.d.ts +2 -0
  13. package/dist/dialog/DialogOverlay.d.ts +30 -0
  14. package/dist/dialog/OneDialog.d.ts +20 -0
  15. package/dist/dialog/focus-manager.d.ts +10 -0
  16. package/dist/dialog/index.d.ts +7 -0
  17. package/dist/dialog/scroll-lock.d.ts +2 -0
  18. package/dist/dialog/service.d.ts +22 -0
  19. package/dist/dialog/types.d.ts +14 -0
  20. package/dist/empty/OneEmpty.d.ts +12 -0
  21. package/dist/empty/index.d.ts +2 -0
  22. package/dist/form/OneForm.d.ts +1 -1
  23. package/dist/form/OneFormItem.d.ts +1 -1
  24. package/dist/index.d.ts +26 -1
  25. package/dist/index.js +3663 -78
  26. package/dist/index.js.map +47 -15
  27. package/dist/message/MessageOverlay.d.ts +25 -0
  28. package/dist/message/OneMessage.d.ts +19 -0
  29. package/dist/message/index.d.ts +6 -0
  30. package/dist/message/normalize.d.ts +8 -0
  31. package/dist/message/service.d.ts +17 -0
  32. package/dist/message/timer.d.ts +21 -0
  33. package/dist/message/types.d.ts +14 -0
  34. package/dist/navigation/index.d.ts +2 -0
  35. package/dist/navigation/normalize.d.ts +3 -0
  36. package/dist/navigation/types.d.ts +4 -0
  37. package/dist/overlay/container.d.ts +2 -0
  38. package/dist/overlay/errors.d.ts +9 -0
  39. package/dist/overlay/host.d.ts +16 -0
  40. package/dist/overlay/index.d.ts +7 -0
  41. package/dist/overlay/mount-controller.d.ts +13 -0
  42. package/dist/overlay/positioner.d.ts +36 -0
  43. package/dist/overlay/types.d.ts +32 -0
  44. package/dist/pagination/OnePagination.d.ts +42 -0
  45. package/dist/pagination/index.d.ts +2 -0
  46. package/dist/pagination/tokens.d.ts +2 -0
  47. package/dist/styles/shared.d.ts +13 -0
  48. package/dist/tabs/OneTabs.d.ts +34 -0
  49. package/dist/tabs/index.d.ts +2 -0
  50. package/dist/tag/OneTag.d.ts +21 -0
  51. package/dist/tag/index.d.ts +2 -0
  52. package/dist/theme/OneThemeService.d.ts +14 -0
  53. package/dist/theme/default-theme.d.ts +2 -0
  54. package/dist/theme/errors.d.ts +9 -0
  55. package/dist/theme/index.d.ts +4 -0
  56. package/dist/theme/normalize.d.ts +6 -0
  57. package/dist/theme/types.d.ts +57 -0
  58. package/dist/theme/variables.d.ts +6 -0
  59. package/dist/tooltip/OneTooltip.d.ts +45 -0
  60. package/dist/tooltip/TooltipBubble.d.ts +29 -0
  61. package/dist/tooltip/index.d.ts +4 -0
  62. package/dist/tooltip/types.d.ts +17 -0
  63. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7,6 +7,10 @@ var ONE_THEME_DEFAULTS = {
7
7
  colorPrimaryHover: "#4bc944",
8
8
  colorDanger: "#b83232",
9
9
  colorDangerHover: "#9f2d2d",
10
+ colorInfo: "#2563eb",
11
+ colorSuccess: "#2f7c39",
12
+ colorWarning: "#9a6700",
13
+ colorOverlay: "rgba(22, 32, 24, 0.48)",
10
14
  colorSurface: "#ffffff",
11
15
  colorText: "#162018",
12
16
  colorMuted: "#647268",
@@ -22,8 +26,19 @@ var ONE_THEME_DEFAULTS = {
22
26
  fontSizeMd: "14px",
23
27
  fontSizeLg: "16px",
24
28
  shadowCard: "0 12px 30px rgba(32, 74, 38, 0.1)",
29
+ shadowOverlay: "0 18px 48px rgba(22, 32, 24, 0.2)",
30
+ zIndexDialog: "1000",
31
+ zIndexMessage: "1100",
32
+ zIndexTooltip: "1200",
25
33
  fontFamily: "Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
26
34
  };
35
+ var ONE_THEME_TYPOGRAPHY_PROPERTIES = Object.freeze({
36
+ fontFamily: `var(--one-font-family, ${ONE_THEME_DEFAULTS.fontFamily})`,
37
+ lineHeight: "var(--one-line-height, 1.5)"
38
+ });
39
+ function oneThemeBorder(color = `var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder})`) {
40
+ return `var(--one-border-width, 1px) var(--one-border-style, solid) ${color}`;
41
+ }
27
42
  var ONE_SIZES = ["sm", "md", "lg"];
28
43
  function normalizeOneSize(value) {
29
44
  return ONE_SIZES.includes(value) ? value : "md";
@@ -45,15 +60,14 @@ var ONE_BUTTON_STYLES = [
45
60
  name: "one-button-base",
46
61
  selector: ".one-button",
47
62
  properties: {
63
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
48
64
  display: "inline-flex",
49
65
  alignItems: "center",
50
66
  justifyContent: "center",
51
67
  gap: `var(--one-button-gap, var(--one-space-sm, ${ONE_THEME_DEFAULTS.spaceSm}))`,
52
- border: "1px solid transparent",
68
+ border: oneThemeBorder("transparent"),
53
69
  borderRadius: `var(--one-radius-md, ${ONE_THEME_DEFAULTS.radiusMd})`,
54
- fontFamily: `var(--one-font-family, ${ONE_THEME_DEFAULTS.fontFamily})`,
55
70
  fontWeight: "500",
56
- lineHeight: "1.5",
57
71
  cursor: "pointer",
58
72
  transition: "150ms ease"
59
73
  }
@@ -209,14 +223,13 @@ var ONE_INPUT_STYLES = [
209
223
  name: "one-input-base",
210
224
  selector: ".one-input",
211
225
  properties: {
226
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
212
227
  boxSizing: "border-box",
213
228
  width: "100%",
214
- border: `1px solid var(--one-input-border-color, var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder}))`,
229
+ border: oneThemeBorder(`var(--one-input-border-color, var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder}))`),
215
230
  borderRadius: `var(--one-radius-md, ${ONE_THEME_DEFAULTS.radiusMd})`,
216
231
  color: `var(--one-input-color, var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText}))`,
217
232
  backgroundColor: `var(--one-input-background, var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface}))`,
218
- fontFamily: `var(--one-font-family, ${ONE_THEME_DEFAULTS.fontFamily})`,
219
- lineHeight: "1.5",
220
233
  transition: "150ms ease"
221
234
  }
222
235
  },
@@ -516,6 +529,7 @@ var ONE_FORM_STYLES = [
516
529
  name: "one-form-base",
517
530
  selector: ".one-form",
518
531
  properties: {
532
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
519
533
  display: "grid",
520
534
  gap: "16px"
521
535
  }
@@ -578,6 +592,7 @@ var ONE_FORM_ITEM_STYLES = [
578
592
  name: "one-form-item-base",
579
593
  selector: ".one-form-item",
580
594
  properties: {
595
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
581
596
  display: "grid",
582
597
  gap: "6px"
583
598
  }
@@ -723,6 +738,7 @@ var ONE_CHECKBOX_STYLES = [
723
738
  name: "one-checkbox-base",
724
739
  selector: ".one-checkbox",
725
740
  properties: {
741
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
726
742
  display: "inline-flex",
727
743
  gap: "8px",
728
744
  alignItems: "center",
@@ -839,13 +855,25 @@ class OneCheckbox extends Component5 {
839
855
  }
840
856
  // lib/checkbox/OneCheckboxGroup.ts
841
857
  import { Component as Component6 } from "@geektech/tsone";
858
+ var ONE_CHECKBOX_GROUP_STYLES = [
859
+ {
860
+ name: "one-checkbox-group-base",
861
+ selector: ".one-checkbox-group",
862
+ properties: {
863
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES
864
+ }
865
+ }
866
+ ];
867
+
842
868
  class OneCheckboxGroup extends Component6 {
843
869
  fieldContext;
844
870
  unsubscribe;
845
871
  initState() {
846
872
  return { internalValue: [...this.props.defaultValue ?? []], revision: 0 };
847
873
  }
848
- initStyles() {}
874
+ initStyles() {
875
+ ONE_CHECKBOX_GROUP_STYLES.forEach(({ name, ...style }) => this.styleManager.addStyle(name, style));
876
+ }
849
877
  beforeMount() {
850
878
  this.fieldContext = this.inject(ONE_FORM_FIELD_KEY);
851
879
  this.fieldContext?.model.ensureValue(this.fieldContext.name, this.props.value ?? this.props.defaultValue ?? []);
@@ -924,6 +952,7 @@ var ONE_SWITCH_STYLES = [
924
952
  name: "one-switch-base",
925
953
  selector: ".one-switch",
926
954
  properties: {
955
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
927
956
  display: "inline-flex",
928
957
  alignItems: "center",
929
958
  position: "relative",
@@ -1095,7 +1124,11 @@ var ONE_SELECT_STYLES = [
1095
1124
  {
1096
1125
  name: "one-select-base",
1097
1126
  selector: ".one-select",
1098
- properties: { position: "relative", width: "100%" }
1127
+ properties: {
1128
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
1129
+ position: "relative",
1130
+ width: "100%"
1131
+ }
1099
1132
  },
1100
1133
  {
1101
1134
  name: "one-select-trigger",
@@ -1104,7 +1137,7 @@ var ONE_SELECT_STYLES = [
1104
1137
  width: "100%",
1105
1138
  minHeight: "40px",
1106
1139
  textAlign: "left",
1107
- border: `1px solid var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder})`,
1140
+ border: oneThemeBorder(),
1108
1141
  borderRadius: `var(--one-radius-md, ${ONE_THEME_DEFAULTS.radiusMd})`,
1109
1142
  backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`
1110
1143
  }
@@ -1118,7 +1151,7 @@ var ONE_SELECT_STYLES = [
1118
1151
  width: "100%",
1119
1152
  marginTop: "4px",
1120
1153
  padding: "4px",
1121
- border: `1px solid var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder})`,
1154
+ border: oneThemeBorder(),
1122
1155
  borderRadius: `var(--one-radius-md, ${ONE_THEME_DEFAULTS.radiusMd})`,
1123
1156
  backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`
1124
1157
  }
@@ -1349,128 +1382,3680 @@ class OneSelect extends Component8 {
1349
1382
  }
1350
1383
  }
1351
1384
  }
1352
- // lib/categories.ts
1353
- var ONE_COMPONENT_CATEGORIES = [
1354
- { id: "basic", label: "基础", components: ["OneButton", "OneInput"] },
1385
+ // lib/tabs/OneTabs.ts
1386
+ import { Component as Component9, slot as slot4 } from "@geektech/tsone";
1387
+ var tabsInstanceId = 0;
1388
+ function createTabsId() {
1389
+ tabsInstanceId += 1;
1390
+ return `one-tabs-${tabsInstanceId}`;
1391
+ }
1392
+ function normalizeId(value) {
1393
+ return typeof value === "string" && /^[A-Za-z_][A-Za-z0-9_-]*$/.test(value) ? value : createTabsId();
1394
+ }
1395
+ var ONE_TABS_STYLES = [
1355
1396
  {
1356
- id: "form",
1357
- label: "表单",
1358
- components: [
1359
- "OneForm",
1360
- "OneFormItem",
1361
- "OneSelect",
1362
- "OneCheckbox",
1363
- "OneCheckboxGroup",
1364
- "OneSwitch"
1365
- ]
1397
+ name: "one-tabs-base",
1398
+ selector: ".one-tabs",
1399
+ properties: {
1400
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
1401
+ color: `var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText})`
1402
+ }
1366
1403
  },
1367
- { id: "data-display", label: "数据展示", components: ["OneCard"] },
1368
- { id: "feedback", label: "反馈与浮层", components: [] }
1369
- ];
1370
- // lib/card/OneCard.ts
1371
- import { Component as Component9, slot as slot4 } from "@geektech/tsone";
1372
- var ONE_CARD_STYLES = [
1373
1404
  {
1374
- name: "one-card-base",
1375
- selector: ".one-card",
1405
+ name: "one-tabs-list",
1406
+ selector: ".one-tabs__list",
1376
1407
  properties: {
1377
- overflow: "hidden",
1378
- color: `var(--one-card-color, var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText}))`,
1379
- backgroundColor: `var(--one-card-background, var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface}))`,
1380
- border: `1px solid var(--one-card-border-color, var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder}))`,
1381
- borderRadius: `var(--one-card-radius, var(--one-radius-md, ${ONE_THEME_DEFAULTS.radiusMd}))`,
1382
- boxShadow: `var(--one-card-shadow, var(--one-shadow-card, ${ONE_THEME_DEFAULTS.shadowCard}))`
1408
+ display: "flex",
1409
+ overflowX: "auto",
1410
+ borderBottom: oneThemeBorder()
1383
1411
  }
1384
1412
  },
1385
1413
  {
1386
- name: "one-card-header",
1387
- selector: ".one-card__header",
1414
+ name: "one-tabs-tab",
1415
+ selector: ".one-tabs__tab",
1388
1416
  properties: {
1389
- padding: `var(--one-card-header-padding, var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg}))`,
1390
- borderBottom: `1px solid var(--one-card-border-color, var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder}))`,
1391
- fontWeight: "500"
1417
+ position: "relative",
1418
+ flex: "0 0 auto",
1419
+ padding: `${ONE_THEME_DEFAULTS.spaceSm} ${ONE_THEME_DEFAULTS.spaceMd}`,
1420
+ color: "inherit",
1421
+ backgroundColor: "transparent",
1422
+ border: "0",
1423
+ cursor: "pointer",
1424
+ font: "inherit"
1425
+ },
1426
+ hover: {
1427
+ color: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`
1392
1428
  }
1393
1429
  },
1394
1430
  {
1395
- name: "one-card-body",
1396
- selector: ".one-card__body",
1431
+ name: "one-tabs-tab-selected",
1432
+ selector: '.one-tabs__tab[aria-selected="true"]',
1397
1433
  properties: {
1398
- padding: `var(--one-card-body-padding, var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg}))`
1434
+ color: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`
1399
1435
  }
1400
1436
  },
1401
1437
  {
1402
- name: "one-card-footer",
1403
- selector: ".one-card__footer",
1438
+ name: "one-tabs-tab-selected-indicator",
1439
+ selector: '.one-tabs__tab[aria-selected="true"]::after',
1404
1440
  properties: {
1405
- padding: `var(--one-card-footer-padding, var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg}))`,
1406
- borderTop: `1px solid var(--one-card-border-color, var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder}))`
1441
+ position: "absolute",
1442
+ right: "0",
1443
+ bottom: "-1px",
1444
+ left: "0",
1445
+ height: "2px",
1446
+ backgroundColor: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`,
1447
+ content: '""'
1448
+ }
1449
+ },
1450
+ {
1451
+ name: "one-tabs-tab-disabled",
1452
+ selector: ".one-tabs__tab:disabled",
1453
+ properties: {
1454
+ color: `var(--one-color-muted, ${ONE_THEME_DEFAULTS.colorMuted})`,
1455
+ cursor: "not-allowed"
1456
+ }
1457
+ },
1458
+ {
1459
+ name: "one-tabs-tab-focus-visible",
1460
+ selector: ".one-tabs__tab:focus-visible",
1461
+ properties: {
1462
+ outline: `2px solid var(--one-color-focus, ${ONE_THEME_DEFAULTS.colorFocus})`,
1463
+ outlineOffset: "-2px"
1464
+ }
1465
+ },
1466
+ {
1467
+ name: "one-tabs-panel",
1468
+ selector: ".one-tabs__panel",
1469
+ properties: {
1470
+ padding: `${ONE_THEME_DEFAULTS.spaceLg} 0`
1407
1471
  }
1408
1472
  }
1409
1473
  ];
1410
- function hasNamedSlot(children, name) {
1411
- return children.some((child) => typeof child !== "string" && child.slot === name);
1412
- }
1413
1474
 
1414
- class OneCard extends Component9 {
1475
+ class OneTabs extends Component9 {
1476
+ idPrefix = normalizeId(this.props.id);
1415
1477
  initState() {
1416
- return {};
1478
+ return { internalValue: this.props.defaultValue };
1417
1479
  }
1418
1480
  initStyles() {
1419
- ONE_CARD_STYLES.forEach(({ name, ...style }) => {
1481
+ ONE_TABS_STYLES.forEach(({ name, ...style }) => {
1420
1482
  this.styleManager.addStyle(name, style);
1421
1483
  });
1422
1484
  }
1423
1485
  render() {
1424
- const children = this.props.children ?? [];
1425
- const hasHeaderSlot = hasNamedSlot(children, "header");
1426
- const hasFooterSlot = hasNamedSlot(children, "footer");
1427
- const headerChildren = hasHeaderSlot ? [slot4("header")] : this.props.title ? [this.props.title] : [];
1486
+ const items = this.normalizedItems();
1487
+ const value = this.effectiveValue(items);
1428
1488
  return {
1429
1489
  tag: "section",
1430
- props: { className: "one-card" },
1490
+ props: { className: "one-tabs" },
1431
1491
  children: [
1432
- ...headerChildren.length > 0 ? [
1433
- {
1434
- tag: "header",
1435
- props: { className: "one-card__header" },
1436
- children: headerChildren
1437
- }
1438
- ] : [],
1439
1492
  {
1440
1493
  tag: "div",
1441
- props: { className: "one-card__body" },
1442
- children: [slot4("default")]
1494
+ props: {
1495
+ className: "one-tabs__list",
1496
+ role: "tablist",
1497
+ "aria-label": this.props.ariaLabel,
1498
+ "aria-orientation": "horizontal"
1499
+ },
1500
+ children: items.map((item, index) => {
1501
+ const selected = item.value === value;
1502
+ return {
1503
+ tag: "button",
1504
+ props: {
1505
+ className: "one-tabs__tab",
1506
+ type: "button",
1507
+ id: `${this.idPrefix}-tab-${index}`,
1508
+ role: "tab",
1509
+ disabled: item.disabled === true,
1510
+ tabindex: selected ? 0 : -1,
1511
+ "aria-selected": selected ? "true" : "false",
1512
+ "aria-controls": `${this.idPrefix}-panel-${index}`
1513
+ },
1514
+ listeners: {
1515
+ click: (event) => this.activate(item, index, event),
1516
+ keydown: (event) => this.handleKeydown(event, index)
1517
+ },
1518
+ children: [item.label]
1519
+ };
1520
+ })
1443
1521
  },
1444
- ...hasFooterSlot ? [
1445
- {
1446
- tag: "footer",
1447
- props: { className: "one-card__footer" },
1448
- children: [slot4("footer")]
1449
- }
1450
- ] : []
1522
+ ...items.map((item, index) => ({
1523
+ tag: "div",
1524
+ props: {
1525
+ className: "one-tabs__panel",
1526
+ id: `${this.idPrefix}-panel-${index}`,
1527
+ role: "tabpanel",
1528
+ hidden: item.value === value ? undefined : true,
1529
+ tabindex: 0,
1530
+ "aria-labelledby": `${this.idPrefix}-tab-${index}`
1531
+ },
1532
+ children: [slot4(item.value)]
1533
+ }))
1534
+ ]
1535
+ };
1536
+ }
1537
+ normalizedItems() {
1538
+ const items = Array.isArray(this.props.items) ? this.props.items : [];
1539
+ const values = new Set;
1540
+ return items.flatMap((item) => {
1541
+ if (!item || typeof item.value !== "string" || typeof item.label !== "string" || values.has(item.value)) {
1542
+ return [];
1543
+ }
1544
+ values.add(item.value);
1545
+ return [{ ...item, disabled: item.disabled === true }];
1546
+ });
1547
+ }
1548
+ effectiveValue(items) {
1549
+ const candidate = this.props.value ?? this.state.internalValue;
1550
+ const selected = items.find((item) => item.value === candidate && !item.disabled);
1551
+ return selected?.value ?? items.find((item) => !item.disabled)?.value;
1552
+ }
1553
+ activate(item, index, event) {
1554
+ if (item.disabled) {
1555
+ return;
1556
+ }
1557
+ this.focusTab(index);
1558
+ if (item.value === this.effectiveValue(this.normalizedItems())) {
1559
+ return;
1560
+ }
1561
+ if (this.props.value === undefined) {
1562
+ this.state.internalValue = item.value;
1563
+ }
1564
+ this.emit("change", {
1565
+ value: item.value,
1566
+ originalEvent: event
1567
+ });
1568
+ }
1569
+ handleKeydown(event, currentIndex) {
1570
+ if (!(event instanceof KeyboardEvent)) {
1571
+ return;
1572
+ }
1573
+ if (!["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) {
1574
+ return;
1575
+ }
1576
+ const items = this.normalizedItems();
1577
+ const enabled = this.enabledIndices(items);
1578
+ if (enabled.length === 0) {
1579
+ return;
1580
+ }
1581
+ event.preventDefault();
1582
+ const currentPosition = Math.max(0, enabled.indexOf(currentIndex));
1583
+ const nextPosition = event.key === "Home" ? 0 : event.key === "End" ? enabled.length - 1 : event.key === "ArrowRight" ? (currentPosition + 1) % enabled.length : (currentPosition - 1 + enabled.length) % enabled.length;
1584
+ const nextIndex = enabled[nextPosition];
1585
+ this.focusTab(nextIndex);
1586
+ this.activate(items[nextIndex], nextIndex, event);
1587
+ }
1588
+ enabledIndices(items) {
1589
+ return items.flatMap((item, index) => item.disabled ? [] : [index]);
1590
+ }
1591
+ focusTab(index) {
1592
+ const element = this.getElement();
1593
+ if (!(element instanceof HTMLElement)) {
1594
+ return;
1595
+ }
1596
+ const tab = element.querySelectorAll('[role="tab"]')[index];
1597
+ tab?.focus();
1598
+ }
1599
+ }
1600
+ // lib/breadcrumb/OneBreadcrumb.ts
1601
+ import { Component as Component10, slot as slot5 } from "@geektech/tsone";
1602
+
1603
+ // lib/navigation/normalize.ts
1604
+ function normalizeNonNegativeInteger(value, fallback) {
1605
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : Math.max(0, Math.floor(fallback));
1606
+ }
1607
+ function normalizePositiveInteger(value, fallback) {
1608
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : Math.max(1, Math.floor(fallback));
1609
+ }
1610
+ function normalizePositiveIntegerList(values, fallback) {
1611
+ const source = Array.isArray(values) ? values : fallback;
1612
+ return [
1613
+ ...new Set(source.filter((value) => typeof value === "number" && Number.isFinite(value) && value > 0).map(Math.floor))
1614
+ ];
1615
+ }
1616
+ // lib/breadcrumb/OneBreadcrumb.ts
1617
+ var ONE_BREADCRUMB_STYLES = [
1618
+ {
1619
+ name: "one-breadcrumb-base",
1620
+ selector: ".one-breadcrumb",
1621
+ properties: {
1622
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
1623
+ color: `var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText})`
1624
+ }
1625
+ },
1626
+ {
1627
+ name: "one-breadcrumb-list",
1628
+ selector: ".one-breadcrumb__list",
1629
+ properties: {
1630
+ display: "flex",
1631
+ flexWrap: "wrap",
1632
+ gap: ONE_THEME_DEFAULTS.spaceXs,
1633
+ alignItems: "center",
1634
+ margin: "0",
1635
+ padding: "0",
1636
+ listStyle: "none"
1637
+ }
1638
+ },
1639
+ {
1640
+ name: "one-breadcrumb-token",
1641
+ selector: ".one-breadcrumb__item, .one-breadcrumb__collapse",
1642
+ properties: {
1643
+ display: "inline-flex",
1644
+ gap: ONE_THEME_DEFAULTS.spaceXs,
1645
+ alignItems: "center"
1646
+ }
1647
+ },
1648
+ {
1649
+ name: "one-breadcrumb-link",
1650
+ selector: ".one-breadcrumb__link",
1651
+ properties: {
1652
+ color: `var(--one-color-muted, ${ONE_THEME_DEFAULTS.colorMuted})`,
1653
+ textDecoration: "none"
1654
+ },
1655
+ hover: {
1656
+ color: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`
1657
+ }
1658
+ },
1659
+ {
1660
+ name: "one-breadcrumb-link-focus-visible",
1661
+ selector: ".one-breadcrumb__link:focus-visible",
1662
+ properties: {
1663
+ outline: `2px solid var(--one-color-focus, ${ONE_THEME_DEFAULTS.colorFocus})`,
1664
+ outlineOffset: "2px"
1665
+ }
1666
+ },
1667
+ {
1668
+ name: "one-breadcrumb-current",
1669
+ selector: ".one-breadcrumb__current",
1670
+ properties: { fontWeight: "600" }
1671
+ },
1672
+ {
1673
+ name: "one-breadcrumb-separator",
1674
+ selector: ".one-breadcrumb__separator",
1675
+ properties: {
1676
+ color: `var(--one-color-muted, ${ONE_THEME_DEFAULTS.colorMuted})`,
1677
+ userSelect: "none"
1678
+ }
1679
+ },
1680
+ {
1681
+ name: "one-breadcrumb-ellipsis",
1682
+ selector: ".one-breadcrumb__ellipsis",
1683
+ properties: {
1684
+ padding: `0 ${ONE_THEME_DEFAULTS.spaceXs}`,
1685
+ color: `var(--one-color-muted, ${ONE_THEME_DEFAULTS.colorMuted})`,
1686
+ backgroundColor: "transparent",
1687
+ border: "0",
1688
+ cursor: "pointer",
1689
+ font: "inherit"
1690
+ }
1691
+ },
1692
+ {
1693
+ name: "one-breadcrumb-ellipsis-focus-visible",
1694
+ selector: ".one-breadcrumb__ellipsis:focus-visible",
1695
+ properties: {
1696
+ outline: `2px solid var(--one-color-focus, ${ONE_THEME_DEFAULTS.colorFocus})`,
1697
+ outlineOffset: "2px"
1698
+ }
1699
+ }
1700
+ ];
1701
+
1702
+ class OneBreadcrumb extends Component10 {
1703
+ initState() {
1704
+ return { expanded: false };
1705
+ }
1706
+ initStyles() {
1707
+ ONE_BREADCRUMB_STYLES.forEach(({ name, ...style }) => {
1708
+ this.styleManager.addStyle(name, style);
1709
+ });
1710
+ }
1711
+ render() {
1712
+ const items = this.normalizedItems();
1713
+ const currentIndex = this.currentIndex(items);
1714
+ const tokens = this.tokens(items, currentIndex);
1715
+ return {
1716
+ tag: "nav",
1717
+ props: {
1718
+ className: "one-breadcrumb",
1719
+ "aria-label": this.props.ariaLabel ?? "面包屑"
1720
+ },
1721
+ children: [
1722
+ {
1723
+ tag: "ol",
1724
+ props: { className: "one-breadcrumb__list" },
1725
+ children: tokens.map((token, tokenIndex) => this.renderToken(token, tokenIndex < tokens.length - 1, currentIndex))
1726
+ }
1727
+ ]
1728
+ };
1729
+ }
1730
+ normalizedItems() {
1731
+ const items = Array.isArray(this.props.items) ? this.props.items : [];
1732
+ return items.flatMap((item) => item && typeof item.label === "string" ? [{ ...item }] : []);
1733
+ }
1734
+ currentIndex(items) {
1735
+ const explicit = items.findIndex((item) => item.current === true);
1736
+ return explicit >= 0 ? explicit : items.length - 1;
1737
+ }
1738
+ tokens(items, currentIndex) {
1739
+ const limit = Math.max(3, normalizePositiveInteger(this.props.maxItems, items.length || 3));
1740
+ if (this.state.expanded || items.length <= limit) {
1741
+ return items.map((item, index) => ({ type: "item", item, index }));
1742
+ }
1743
+ const visible = new Set([0, currentIndex, items.length - 1]);
1744
+ const candidates = items.map((_, index) => index).filter((index) => !visible.has(index)).sort((left, right) => Math.abs(left - currentIndex) - Math.abs(right - currentIndex) || left - right);
1745
+ candidates.slice(0, Math.max(0, limit - visible.size)).forEach((index) => {
1746
+ visible.add(index);
1747
+ });
1748
+ const result = [];
1749
+ let hiddenStart = -1;
1750
+ items.forEach((item, index) => {
1751
+ if (!visible.has(index)) {
1752
+ if (hiddenStart < 0)
1753
+ hiddenStart = index;
1754
+ return;
1755
+ }
1756
+ if (hiddenStart >= 0) {
1757
+ result.push({ type: "collapse", key: `${hiddenStart}-${index - 1}` });
1758
+ hiddenStart = -1;
1759
+ }
1760
+ result.push({ type: "item", item, index });
1761
+ });
1762
+ if (hiddenStart >= 0) {
1763
+ result.push({
1764
+ type: "collapse",
1765
+ key: `${hiddenStart}-${items.length - 1}`
1766
+ });
1767
+ }
1768
+ return result;
1769
+ }
1770
+ renderToken(token, hasSeparator, currentIndex) {
1771
+ const content = token.type === "collapse" ? this.renderCollapse() : this.renderItem(token.item, token.index, token.index === currentIndex);
1772
+ return {
1773
+ tag: "li",
1774
+ props: {
1775
+ className: token.type === "item" ? "one-breadcrumb__item" : "one-breadcrumb__collapse"
1776
+ },
1777
+ children: [content, ...hasSeparator ? [this.renderSeparator()] : []]
1778
+ };
1779
+ }
1780
+ renderItem(item, index, current) {
1781
+ if (current || !item.href) {
1782
+ return {
1783
+ tag: "span",
1784
+ props: {
1785
+ className: current ? "one-breadcrumb__current" : "one-breadcrumb__label",
1786
+ "aria-current": current ? "page" : undefined
1787
+ },
1788
+ children: [item.label]
1789
+ };
1790
+ }
1791
+ return {
1792
+ tag: "a",
1793
+ props: { className: "one-breadcrumb__link", href: item.href },
1794
+ listeners: { click: (event) => this.handleItemClick(event, item, index) },
1795
+ children: [item.label]
1796
+ };
1797
+ }
1798
+ renderCollapse() {
1799
+ return {
1800
+ tag: "button",
1801
+ props: {
1802
+ className: "one-breadcrumb__ellipsis",
1803
+ type: "button",
1804
+ "aria-label": "展开面包屑",
1805
+ "aria-expanded": "false"
1806
+ },
1807
+ listeners: { click: () => this.state.expanded = true },
1808
+ children: ["…"]
1809
+ };
1810
+ }
1811
+ renderSeparator() {
1812
+ return {
1813
+ tag: "span",
1814
+ props: { className: "one-breadcrumb__separator", "aria-hidden": "true" },
1815
+ children: [
1816
+ this.hasSlot("separator") ? slot5("separator") : this.props.separator ?? "/"
1451
1817
  ]
1452
1818
  };
1453
1819
  }
1820
+ handleItemClick(event, item, index) {
1821
+ if (!(event instanceof MouseEvent))
1822
+ return;
1823
+ this.emit("itemClick", {
1824
+ item,
1825
+ index,
1826
+ originalEvent: event
1827
+ });
1828
+ }
1829
+ hasSlot(name) {
1830
+ return this.props.children?.some((child) => typeof child !== "string" && child.slot === name) ?? false;
1831
+ }
1832
+ }
1833
+ // lib/pagination/OnePagination.ts
1834
+ import { Component as Component11 } from "@geektech/tsone";
1835
+
1836
+ // lib/pagination/tokens.ts
1837
+ function createOnePaginationTokens(pageCount, page, siblingCount) {
1838
+ const normalizedCount = normalizePositiveInteger(pageCount, 1);
1839
+ const normalizedPage = Math.min(normalizedCount, normalizePositiveInteger(page, 1));
1840
+ const normalizedSiblings = normalizeNonNegativeInteger(siblingCount, 1);
1841
+ const pages = new Set([1, normalizedCount]);
1842
+ for (let candidate = Math.max(1, normalizedPage - normalizedSiblings);candidate <= Math.min(normalizedCount, normalizedPage + normalizedSiblings); candidate += 1) {
1843
+ pages.add(candidate);
1844
+ }
1845
+ const sorted = [...pages].sort((left, right) => left - right);
1846
+ return sorted.flatMap((value, index) => {
1847
+ if (index === 0)
1848
+ return [value];
1849
+ const previous = sorted[index - 1];
1850
+ const gap = value - previous;
1851
+ if (gap === 2)
1852
+ return [previous + 1, value];
1853
+ if (gap > 2) {
1854
+ return [previous === 1 ? "ellipsis-start" : "ellipsis-end", value];
1855
+ }
1856
+ return [value];
1857
+ });
1858
+ }
1859
+
1860
+ // lib/pagination/OnePagination.ts
1861
+ var DEFAULT_PAGE_SIZE_OPTIONS = [10, 20, 50, 100];
1862
+ var ONE_PAGINATION_STYLES = [
1863
+ {
1864
+ name: "one-pagination-base",
1865
+ selector: ".one-pagination",
1866
+ properties: {
1867
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
1868
+ display: "flex",
1869
+ flexWrap: "wrap",
1870
+ gap: ONE_THEME_DEFAULTS.spaceSm,
1871
+ alignItems: "center",
1872
+ color: `var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText})`
1873
+ }
1874
+ },
1875
+ {
1876
+ name: "one-pagination-pages",
1877
+ selector: ".one-pagination__pages",
1878
+ properties: {
1879
+ display: "flex",
1880
+ flexWrap: "wrap",
1881
+ gap: ONE_THEME_DEFAULTS.spaceXs,
1882
+ alignItems: "center"
1883
+ }
1884
+ },
1885
+ {
1886
+ name: "one-pagination-button",
1887
+ selector: ".one-pagination__button",
1888
+ properties: {
1889
+ minWidth: "32px",
1890
+ height: "32px",
1891
+ padding: `0 ${ONE_THEME_DEFAULTS.spaceSm}`,
1892
+ color: "inherit",
1893
+ backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
1894
+ border: oneThemeBorder(),
1895
+ borderRadius: `var(--one-radius-sm, ${ONE_THEME_DEFAULTS.radiusSm})`,
1896
+ cursor: "pointer",
1897
+ font: "inherit"
1898
+ },
1899
+ hover: {
1900
+ color: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`,
1901
+ borderColor: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`
1902
+ }
1903
+ },
1904
+ {
1905
+ name: "one-pagination-button-current",
1906
+ selector: '.one-pagination__button[aria-current="page"]',
1907
+ properties: {
1908
+ color: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
1909
+ backgroundColor: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`,
1910
+ borderColor: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`
1911
+ }
1912
+ },
1913
+ {
1914
+ name: "one-pagination-button-disabled",
1915
+ selector: ".one-pagination__button:disabled",
1916
+ properties: {
1917
+ color: `var(--one-color-muted, ${ONE_THEME_DEFAULTS.colorMuted})`,
1918
+ cursor: "not-allowed",
1919
+ opacity: "0.55"
1920
+ }
1921
+ },
1922
+ {
1923
+ name: "one-pagination-button-focus-visible",
1924
+ selector: ".one-pagination__button:focus-visible",
1925
+ properties: {
1926
+ outline: `2px solid var(--one-color-focus, ${ONE_THEME_DEFAULTS.colorFocus})`,
1927
+ outlineOffset: "2px"
1928
+ }
1929
+ },
1930
+ {
1931
+ name: "one-pagination-ellipsis",
1932
+ selector: ".one-pagination__ellipsis",
1933
+ properties: {
1934
+ minWidth: "24px",
1935
+ color: `var(--one-color-muted, ${ONE_THEME_DEFAULTS.colorMuted})`,
1936
+ textAlign: "center"
1937
+ }
1938
+ },
1939
+ {
1940
+ name: "one-pagination-control",
1941
+ selector: ".one-pagination__size, .one-pagination__jumper",
1942
+ properties: {
1943
+ height: "32px",
1944
+ padding: `0 ${ONE_THEME_DEFAULTS.spaceSm}`,
1945
+ color: "inherit",
1946
+ backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
1947
+ border: oneThemeBorder(),
1948
+ borderRadius: `var(--one-radius-sm, ${ONE_THEME_DEFAULTS.radiusSm})`,
1949
+ font: "inherit"
1950
+ }
1951
+ },
1952
+ {
1953
+ name: "one-pagination-control-focus-visible",
1954
+ selector: ".one-pagination__size:focus-visible, .one-pagination__jumper:focus-visible",
1955
+ properties: {
1956
+ outline: `2px solid var(--one-color-focus, ${ONE_THEME_DEFAULTS.colorFocus})`,
1957
+ outlineOffset: "2px"
1958
+ }
1959
+ },
1960
+ {
1961
+ name: "one-pagination-jumper",
1962
+ selector: ".one-pagination__jumper",
1963
+ properties: { width: "80px" }
1964
+ }
1965
+ ];
1966
+
1967
+ class OnePagination extends Component11 {
1968
+ initState() {
1969
+ return {
1970
+ internalPage: normalizePositiveInteger(this.props.defaultPage, 1),
1971
+ internalPageSize: normalizePositiveInteger(this.props.defaultPageSize, 10),
1972
+ jumpValue: ""
1973
+ };
1974
+ }
1975
+ initStyles() {
1976
+ ONE_PAGINATION_STYLES.forEach(({ name, ...style }) => {
1977
+ this.styleManager.addStyle(name, style);
1978
+ });
1979
+ }
1980
+ render() {
1981
+ const pageSize = this.effectivePageSize();
1982
+ const pageCount = this.pageCount(pageSize);
1983
+ const page = this.effectivePage(pageSize);
1984
+ const disabled = this.props.disabled === true;
1985
+ const siblingCount = normalizeNonNegativeInteger(this.props.siblingCount, 1);
1986
+ return {
1987
+ tag: "nav",
1988
+ props: {
1989
+ className: "one-pagination",
1990
+ "aria-label": this.props.ariaLabel ?? "分页"
1991
+ },
1992
+ children: [
1993
+ {
1994
+ tag: "div",
1995
+ props: { className: "one-pagination__pages" },
1996
+ children: [
1997
+ this.renderPageButton("上一页", "‹", page - 1, page <= 1),
1998
+ ...createOnePaginationTokens(pageCount, page, siblingCount).map((token) => typeof token === "number" ? this.renderPageButton(`第 ${token} 页`, String(token), token, false, token === page) : this.renderEllipsis(token)),
1999
+ this.renderPageButton("下一页", "›", page + 1, page >= pageCount)
2000
+ ]
2001
+ },
2002
+ {
2003
+ tag: "select",
2004
+ props: {
2005
+ className: "one-pagination__size",
2006
+ value: String(pageSize),
2007
+ disabled,
2008
+ "aria-label": "每页条数"
2009
+ },
2010
+ listeners: { change: (event) => this.handleSizeChange(event) },
2011
+ children: this.sizeOptions().map((option) => ({
2012
+ tag: "option",
2013
+ props: {
2014
+ value: String(option),
2015
+ selected: option === pageSize
2016
+ },
2017
+ children: [`${option} 条/页`]
2018
+ }))
2019
+ },
2020
+ ...this.props.showQuickJumper ? [
2021
+ {
2022
+ tag: "input",
2023
+ props: {
2024
+ className: "one-pagination__jumper",
2025
+ type: "text",
2026
+ inputmode: "numeric",
2027
+ value: this.state.jumpValue,
2028
+ disabled,
2029
+ "aria-label": "快速跳转页码",
2030
+ placeholder: "跳至页码"
2031
+ },
2032
+ listeners: {
2033
+ input: (event) => this.handleJumpInput(event),
2034
+ keydown: (event) => this.handleJumpKeydown(event),
2035
+ blur: (event) => this.submitJump(event)
2036
+ }
2037
+ }
2038
+ ] : []
2039
+ ]
2040
+ };
2041
+ }
2042
+ effectivePageSize() {
2043
+ return normalizePositiveInteger(this.props.pageSize ?? this.state.internalPageSize, 10);
2044
+ }
2045
+ pageCount(pageSize = this.effectivePageSize()) {
2046
+ const total = normalizeNonNegativeInteger(this.props.total, 0);
2047
+ return Math.max(1, Math.ceil(total / pageSize));
2048
+ }
2049
+ effectivePage(pageSize = this.effectivePageSize()) {
2050
+ const candidate = normalizePositiveInteger(this.props.page ?? this.state.internalPage, 1);
2051
+ return Math.min(this.pageCount(pageSize), candidate);
2052
+ }
2053
+ sizeOptions() {
2054
+ const active = this.effectivePageSize();
2055
+ const options = normalizePositiveIntegerList(this.props.pageSizeOptions, DEFAULT_PAGE_SIZE_OPTIONS);
2056
+ if (!options.includes(active))
2057
+ options.push(active);
2058
+ return options;
2059
+ }
2060
+ renderPageButton(ariaLabel, label, targetPage, boundaryDisabled, current = false) {
2061
+ const disabled = this.props.disabled === true || boundaryDisabled;
2062
+ return {
2063
+ tag: "button",
2064
+ props: {
2065
+ className: "one-pagination__button",
2066
+ type: "button",
2067
+ disabled,
2068
+ "aria-label": ariaLabel,
2069
+ "aria-current": current ? "page" : undefined
2070
+ },
2071
+ listeners: {
2072
+ click: (event) => this.requestChange(targetPage, this.effectivePageSize(), event)
2073
+ },
2074
+ children: [label]
2075
+ };
2076
+ }
2077
+ renderEllipsis(token) {
2078
+ return {
2079
+ tag: "span",
2080
+ props: {
2081
+ className: "one-pagination__ellipsis",
2082
+ "aria-hidden": "true",
2083
+ "data-token": token
2084
+ },
2085
+ children: ["…"]
2086
+ };
2087
+ }
2088
+ handleSizeChange(event) {
2089
+ const select = event.currentTarget;
2090
+ if (!(select instanceof HTMLSelectElement) || this.props.disabled)
2091
+ return;
2092
+ const pageSize = normalizePositiveInteger(Number(select.value), 10);
2093
+ this.requestChange(this.effectivePage(), pageSize, event);
2094
+ }
2095
+ handleJumpInput(event) {
2096
+ const input = event.currentTarget;
2097
+ if (!(input instanceof HTMLInputElement) || this.props.disabled)
2098
+ return;
2099
+ this.state.jumpValue = input.value;
2100
+ }
2101
+ handleJumpKeydown(event) {
2102
+ if (!(event instanceof KeyboardEvent) || event.key !== "Enter")
2103
+ return;
2104
+ event.preventDefault();
2105
+ this.submitJump(event);
2106
+ }
2107
+ requestChange(page, pageSize, event) {
2108
+ if (this.props.disabled)
2109
+ return;
2110
+ const nextPageSize = normalizePositiveInteger(pageSize, 10);
2111
+ const nextPage = Math.min(this.pageCount(nextPageSize), normalizePositiveInteger(page, 1));
2112
+ const currentPage = this.effectivePage();
2113
+ const currentPageSize = this.effectivePageSize();
2114
+ if (nextPage === currentPage && nextPageSize === currentPageSize)
2115
+ return;
2116
+ if (this.props.pageSize === undefined) {
2117
+ this.state.internalPageSize = nextPageSize;
2118
+ }
2119
+ if (this.props.page === undefined) {
2120
+ this.state.internalPage = nextPage;
2121
+ }
2122
+ this.emit("change", {
2123
+ page: nextPage,
2124
+ pageSize: nextPageSize,
2125
+ originalEvent: event
2126
+ });
2127
+ }
2128
+ submitJump(event) {
2129
+ if (this.props.disabled)
2130
+ return;
2131
+ const value = this.state.jumpValue.trim();
2132
+ if (!value)
2133
+ return;
2134
+ const page = Number(value);
2135
+ this.state.jumpValue = "";
2136
+ if (event.currentTarget instanceof HTMLInputElement) {
2137
+ event.currentTarget.value = "";
2138
+ }
2139
+ if (!Number.isFinite(page))
2140
+ return;
2141
+ this.requestChange(page, this.effectivePageSize(), event);
2142
+ }
2143
+ }
2144
+ // lib/categories.ts
2145
+ var ONE_COMPONENT_CATEGORIES = [
2146
+ { id: "basic", label: "基础", components: ["OneButton", "OneInput"] },
2147
+ {
2148
+ id: "form",
2149
+ label: "表单",
2150
+ components: [
2151
+ "OneForm",
2152
+ "OneFormItem",
2153
+ "OneSelect",
2154
+ "OneCheckbox",
2155
+ "OneCheckboxGroup",
2156
+ "OneSwitch"
2157
+ ]
2158
+ },
2159
+ {
2160
+ id: "navigation",
2161
+ label: "导航",
2162
+ components: ["OneTabs", "OneBreadcrumb", "OnePagination"]
2163
+ },
2164
+ {
2165
+ id: "data-display",
2166
+ label: "数据展示",
2167
+ components: ["OneCard", "OneTag", "OneBadge", "OneEmpty"]
2168
+ },
2169
+ {
2170
+ id: "feedback",
2171
+ label: "反馈与浮层",
2172
+ components: ["OneAlert", "OneMessage", "OneDialog", "OneTooltip"]
2173
+ }
2174
+ ];
2175
+ // lib/card/OneCard.ts
2176
+ import { Component as Component12, slot as slot6 } from "@geektech/tsone";
2177
+ var ONE_CARD_STYLES = [
2178
+ {
2179
+ name: "one-card-base",
2180
+ selector: ".one-card",
2181
+ properties: {
2182
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
2183
+ overflow: "hidden",
2184
+ color: `var(--one-card-color, var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText}))`,
2185
+ backgroundColor: `var(--one-card-background, var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface}))`,
2186
+ border: oneThemeBorder(`var(--one-card-border-color, var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder}))`),
2187
+ borderRadius: `var(--one-card-radius, var(--one-radius-lg, ${ONE_THEME_DEFAULTS.radiusMd}))`,
2188
+ boxShadow: `var(--one-card-shadow, var(--one-shadow-card, ${ONE_THEME_DEFAULTS.shadowCard}))`
2189
+ }
2190
+ },
2191
+ {
2192
+ name: "one-card-header",
2193
+ selector: ".one-card__header",
2194
+ properties: {
2195
+ padding: `var(--one-card-header-padding, var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg}))`,
2196
+ borderBottom: oneThemeBorder(`var(--one-card-border-color, var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder}))`),
2197
+ fontWeight: "500"
2198
+ }
2199
+ },
2200
+ {
2201
+ name: "one-card-body",
2202
+ selector: ".one-card__body",
2203
+ properties: {
2204
+ padding: `var(--one-card-body-padding, var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg}))`
2205
+ }
2206
+ },
2207
+ {
2208
+ name: "one-card-footer",
2209
+ selector: ".one-card__footer",
2210
+ properties: {
2211
+ padding: `var(--one-card-footer-padding, var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg}))`,
2212
+ borderTop: oneThemeBorder(`var(--one-card-border-color, var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder}))`)
2213
+ }
2214
+ }
2215
+ ];
2216
+ function hasNamedSlot(children, name) {
2217
+ return children.some((child) => typeof child !== "string" && child.slot === name);
2218
+ }
2219
+
2220
+ class OneCard extends Component12 {
2221
+ initState() {
2222
+ return {};
2223
+ }
2224
+ initStyles() {
2225
+ ONE_CARD_STYLES.forEach(({ name, ...style }) => {
2226
+ this.styleManager.addStyle(name, style);
2227
+ });
2228
+ }
2229
+ render() {
2230
+ const children = this.props.children ?? [];
2231
+ const hasHeaderSlot = hasNamedSlot(children, "header");
2232
+ const hasFooterSlot = hasNamedSlot(children, "footer");
2233
+ const headerChildren = hasHeaderSlot ? [slot6("header")] : this.props.title ? [this.props.title] : [];
2234
+ return {
2235
+ tag: "section",
2236
+ props: { className: "one-card" },
2237
+ children: [
2238
+ ...headerChildren.length > 0 ? [
2239
+ {
2240
+ tag: "header",
2241
+ props: { className: "one-card__header" },
2242
+ children: headerChildren
2243
+ }
2244
+ ] : [],
2245
+ {
2246
+ tag: "div",
2247
+ props: { className: "one-card__body" },
2248
+ children: [slot6("default")]
2249
+ },
2250
+ ...hasFooterSlot ? [
2251
+ {
2252
+ tag: "footer",
2253
+ props: { className: "one-card__footer" },
2254
+ children: [slot6("footer")]
2255
+ }
2256
+ ] : []
2257
+ ]
2258
+ };
2259
+ }
2260
+ }
2261
+ // lib/tag/OneTag.ts
2262
+ import { Component as Component13 } from "@geektech/tsone";
2263
+
2264
+ // lib/data-display/types.ts
2265
+ var VARIANTS = [
2266
+ "neutral",
2267
+ "primary",
2268
+ "success",
2269
+ "warning",
2270
+ "error"
2271
+ ];
2272
+ function normalizeOneDataDisplayVariant(value, fallback = "neutral") {
2273
+ return VARIANTS.includes(value) ? value : fallback;
2274
+ }
2275
+ // lib/tag/OneTag.ts
2276
+ var ONE_TAG_STYLES = [
2277
+ {
2278
+ name: "one-tag-base",
2279
+ selector: ".one-tag",
2280
+ properties: {
2281
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
2282
+ display: "inline-flex",
2283
+ alignItems: "center",
2284
+ gap: ONE_THEME_DEFAULTS.spaceXs,
2285
+ border: oneThemeBorder(),
2286
+ borderRadius: `var(--one-radius-sm, ${ONE_THEME_DEFAULTS.radiusSm})`
2287
+ }
2288
+ },
2289
+ {
2290
+ name: "one-tag-neutral",
2291
+ selector: ".one-tag--neutral",
2292
+ properties: {
2293
+ color: `var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText})`,
2294
+ backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
2295
+ borderColor: `var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder})`
2296
+ }
2297
+ },
2298
+ {
2299
+ name: "one-tag-primary",
2300
+ selector: ".one-tag--primary",
2301
+ properties: {
2302
+ color: `var(--one-color-primary-contrast, ${ONE_THEME_DEFAULTS.colorText})`,
2303
+ backgroundColor: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`,
2304
+ borderColor: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`
2305
+ }
2306
+ },
2307
+ {
2308
+ name: "one-tag-success",
2309
+ selector: ".one-tag--success",
2310
+ properties: {
2311
+ color: `var(--one-color-success, ${ONE_THEME_DEFAULTS.colorSuccess})`,
2312
+ backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
2313
+ borderColor: `var(--one-color-success, ${ONE_THEME_DEFAULTS.colorSuccess})`
2314
+ }
2315
+ },
2316
+ {
2317
+ name: "one-tag-warning",
2318
+ selector: ".one-tag--warning",
2319
+ properties: {
2320
+ color: `var(--one-color-warning, ${ONE_THEME_DEFAULTS.colorWarning})`,
2321
+ backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
2322
+ borderColor: `var(--one-color-warning, ${ONE_THEME_DEFAULTS.colorWarning})`
2323
+ }
2324
+ },
2325
+ {
2326
+ name: "one-tag-error",
2327
+ selector: ".one-tag--error",
2328
+ properties: {
2329
+ color: `var(--one-color-danger, ${ONE_THEME_DEFAULTS.colorDanger})`,
2330
+ backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
2331
+ borderColor: `var(--one-color-danger, ${ONE_THEME_DEFAULTS.colorDanger})`
2332
+ }
2333
+ },
2334
+ {
2335
+ name: "one-tag-sm",
2336
+ selector: ".one-tag--sm",
2337
+ properties: {
2338
+ padding: "2px 6px",
2339
+ fontSize: `var(--one-font-size-sm, ${ONE_THEME_DEFAULTS.fontSizeSm})`
2340
+ }
2341
+ },
2342
+ {
2343
+ name: "one-tag-md",
2344
+ selector: ".one-tag--md",
2345
+ properties: {
2346
+ padding: "4px 8px",
2347
+ fontSize: `var(--one-font-size-md, ${ONE_THEME_DEFAULTS.fontSizeMd})`
2348
+ }
2349
+ },
2350
+ {
2351
+ name: "one-tag-lg",
2352
+ selector: ".one-tag--lg",
2353
+ properties: {
2354
+ padding: "6px 10px",
2355
+ fontSize: `var(--one-font-size-lg, ${ONE_THEME_DEFAULTS.fontSizeLg})`
2356
+ }
2357
+ },
2358
+ {
2359
+ name: "one-tag-close",
2360
+ selector: ".one-tag__close",
2361
+ properties: {
2362
+ display: "inline-grid",
2363
+ placeItems: "center",
2364
+ padding: "0",
2365
+ color: "inherit",
2366
+ backgroundColor: "transparent",
2367
+ border: "0",
2368
+ cursor: "pointer",
2369
+ font: "inherit",
2370
+ lineHeight: "1"
2371
+ }
2372
+ },
2373
+ {
2374
+ name: "one-tag-close-focus-visible",
2375
+ selector: ".one-tag__close:focus-visible",
2376
+ properties: {
2377
+ outline: `2px solid var(--one-color-focus, ${ONE_THEME_DEFAULTS.colorFocus})`,
2378
+ outlineOffset: "2px"
2379
+ }
2380
+ }
2381
+ ];
2382
+
2383
+ class OneTag extends Component13 {
2384
+ initState() {
2385
+ return { visible: true };
2386
+ }
2387
+ initStyles() {
2388
+ ONE_TAG_STYLES.forEach(({ name, ...style }) => {
2389
+ this.styleManager.addStyle(name, style);
2390
+ });
2391
+ }
2392
+ render() {
2393
+ if (!this.state.visible) {
2394
+ return {
2395
+ tag: "span",
2396
+ props: { hidden: true, "data-one-tag-anchor": "" }
2397
+ };
2398
+ }
2399
+ const variant = normalizeOneDataDisplayVariant(this.props.variant);
2400
+ const size = normalizeOneSize(this.props.size);
2401
+ return {
2402
+ tag: "span",
2403
+ props: {
2404
+ className: `one-tag one-tag--${variant} one-tag--${size}`
2405
+ },
2406
+ children: [
2407
+ ...this.props.children ?? [],
2408
+ ...this.props.closable ? [
2409
+ {
2410
+ tag: "button",
2411
+ props: {
2412
+ className: "one-tag__close",
2413
+ type: "button",
2414
+ "aria-label": "关闭标签"
2415
+ },
2416
+ listeners: { click: () => this.close() },
2417
+ children: ["×"]
2418
+ }
2419
+ ] : []
2420
+ ]
2421
+ };
2422
+ }
2423
+ close() {
2424
+ if (!this.state.visible) {
2425
+ return;
2426
+ }
2427
+ this.emit("close");
2428
+ this.state.visible = false;
2429
+ }
2430
+ }
2431
+ // lib/badge/OneBadge.ts
2432
+ import { Component as Component14 } from "@geektech/tsone";
2433
+ var ONE_BADGE_STYLES = [
2434
+ {
2435
+ name: "one-badge-base",
2436
+ selector: ".one-badge",
2437
+ properties: {
2438
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
2439
+ position: "relative",
2440
+ display: "inline-flex",
2441
+ verticalAlign: "middle"
2442
+ }
2443
+ },
2444
+ {
2445
+ name: "one-badge-content",
2446
+ selector: ".one-badge__content",
2447
+ properties: {
2448
+ position: "absolute",
2449
+ top: "0",
2450
+ right: "0",
2451
+ display: "inline-flex",
2452
+ alignItems: "center",
2453
+ justifyContent: "center",
2454
+ boxSizing: "border-box",
2455
+ minWidth: "18px",
2456
+ height: "18px",
2457
+ padding: "0 5px",
2458
+ borderRadius: "999px",
2459
+ fontFamily: `var(--one-font-family, ${ONE_THEME_DEFAULTS.fontFamily})`,
2460
+ fontSize: `var(--one-font-size-sm, ${ONE_THEME_DEFAULTS.fontSizeSm})`,
2461
+ lineHeight: "1",
2462
+ transform: "translate(50%, -50%)"
2463
+ }
2464
+ },
2465
+ {
2466
+ name: "one-badge-standalone-content",
2467
+ selector: ".one-badge--standalone .one-badge__content",
2468
+ properties: {
2469
+ position: "static",
2470
+ transform: "none"
2471
+ }
2472
+ },
2473
+ {
2474
+ name: "one-badge-dot",
2475
+ selector: ".one-badge__content--dot",
2476
+ properties: {
2477
+ width: "8px",
2478
+ minWidth: "8px",
2479
+ height: "8px",
2480
+ padding: "0"
2481
+ }
2482
+ },
2483
+ {
2484
+ name: "one-badge-neutral",
2485
+ selector: ".one-badge--neutral .one-badge__content",
2486
+ properties: {
2487
+ color: `var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText})`,
2488
+ backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
2489
+ border: oneThemeBorder()
2490
+ }
2491
+ },
2492
+ {
2493
+ name: "one-badge-primary",
2494
+ selector: ".one-badge--primary .one-badge__content",
2495
+ properties: {
2496
+ color: `var(--one-color-primary-contrast, ${ONE_THEME_DEFAULTS.colorText})`,
2497
+ backgroundColor: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`
2498
+ }
2499
+ },
2500
+ {
2501
+ name: "one-badge-success",
2502
+ selector: ".one-badge--success .one-badge__content",
2503
+ properties: {
2504
+ color: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
2505
+ backgroundColor: `var(--one-color-success, ${ONE_THEME_DEFAULTS.colorSuccess})`
2506
+ }
2507
+ },
2508
+ {
2509
+ name: "one-badge-warning",
2510
+ selector: ".one-badge--warning .one-badge__content",
2511
+ properties: {
2512
+ color: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
2513
+ backgroundColor: `var(--one-color-warning, ${ONE_THEME_DEFAULTS.colorWarning})`
2514
+ }
2515
+ },
2516
+ {
2517
+ name: "one-badge-error",
2518
+ selector: ".one-badge--error .one-badge__content",
2519
+ properties: {
2520
+ color: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
2521
+ backgroundColor: `var(--one-color-danger, ${ONE_THEME_DEFAULTS.colorDanger})`
2522
+ }
2523
+ }
2524
+ ];
2525
+ function normalizeMax(value) {
2526
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : 99;
2527
+ }
2528
+ function displayValue(props) {
2529
+ if (props.dot) {
2530
+ return "";
2531
+ }
2532
+ if (props.value === undefined || props.value === "") {
2533
+ return;
2534
+ }
2535
+ if (props.value === 0 && props.showZero !== true) {
2536
+ return;
2537
+ }
2538
+ if (typeof props.value === "number" && !Number.isFinite(props.value)) {
2539
+ return;
2540
+ }
2541
+ if (typeof props.value === "number") {
2542
+ const max = normalizeMax(props.max);
2543
+ return props.value > max ? `${max}+` : String(props.value);
2544
+ }
2545
+ return props.value;
2546
+ }
2547
+
2548
+ class OneBadge extends Component14 {
2549
+ initState() {
2550
+ return {};
2551
+ }
2552
+ initStyles() {
2553
+ ONE_BADGE_STYLES.forEach(({ name, ...style }) => {
2554
+ this.styleManager.addStyle(name, style);
2555
+ });
2556
+ }
2557
+ render() {
2558
+ const children = this.props.children ?? [];
2559
+ const standalone = children.length === 0;
2560
+ const variant = normalizeOneDataDisplayVariant(this.props.variant, "primary");
2561
+ const value = displayValue(this.props);
2562
+ const showContent = this.props.dot === true || value !== undefined;
2563
+ return {
2564
+ tag: "span",
2565
+ props: {
2566
+ className: [
2567
+ "one-badge",
2568
+ `one-badge--${variant}`,
2569
+ ...standalone ? ["one-badge--standalone"] : []
2570
+ ].join(" ")
2571
+ },
2572
+ children: [
2573
+ ...children,
2574
+ ...showContent ? [
2575
+ {
2576
+ tag: "span",
2577
+ props: {
2578
+ className: [
2579
+ "one-badge__content",
2580
+ ...this.props.dot ? ["one-badge__content--dot"] : []
2581
+ ].join(" "),
2582
+ "aria-label": this.props.ariaLabel,
2583
+ "aria-hidden": this.props.dot && !this.props.ariaLabel ? "true" : undefined
2584
+ },
2585
+ children: value ? [value] : []
2586
+ }
2587
+ ] : []
2588
+ ]
2589
+ };
2590
+ }
2591
+ }
2592
+ // lib/empty/OneEmpty.ts
2593
+ import { Component as Component15, slot as slot7 } from "@geektech/tsone";
2594
+ var ONE_EMPTY_STYLES = [
2595
+ {
2596
+ name: "one-empty-base",
2597
+ selector: ".one-empty",
2598
+ properties: {
2599
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
2600
+ display: "grid",
2601
+ justifyItems: "center",
2602
+ gap: ONE_THEME_DEFAULTS.spaceMd,
2603
+ padding: "24px",
2604
+ color: `var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText})`,
2605
+ textAlign: "center"
2606
+ }
2607
+ },
2608
+ {
2609
+ name: "one-empty-image",
2610
+ selector: ".one-empty__image",
2611
+ properties: {
2612
+ display: "grid",
2613
+ placeItems: "center",
2614
+ minHeight: "56px"
2615
+ }
2616
+ },
2617
+ {
2618
+ name: "one-empty-illustration",
2619
+ selector: ".one-empty__illustration",
2620
+ properties: {
2621
+ display: "block",
2622
+ width: "48px",
2623
+ height: "36px",
2624
+ backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
2625
+ border: `2px solid var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder})`,
2626
+ borderRadius: `var(--one-radius-md, ${ONE_THEME_DEFAULTS.radiusMd})`
2627
+ }
2628
+ },
2629
+ {
2630
+ name: "one-empty-description",
2631
+ selector: ".one-empty__description",
2632
+ properties: {
2633
+ color: `var(--one-color-muted, ${ONE_THEME_DEFAULTS.colorMuted})`,
2634
+ fontSize: `var(--one-font-size-md, ${ONE_THEME_DEFAULTS.fontSizeMd})`
2635
+ }
2636
+ },
2637
+ {
2638
+ name: "one-empty-actions",
2639
+ selector: ".one-empty__actions",
2640
+ properties: {
2641
+ display: "flex",
2642
+ flexWrap: "wrap",
2643
+ justifyContent: "center",
2644
+ gap: ONE_THEME_DEFAULTS.spaceSm
2645
+ }
2646
+ }
2647
+ ];
2648
+ function hasNamedSlot2(children, name) {
2649
+ return children.some((child) => typeof child !== "string" && child.slot === name);
2650
+ }
2651
+ function hasDefaultSlot(children) {
2652
+ return children.some((child) => typeof child === "string" || child.slot === undefined);
2653
+ }
2654
+
2655
+ class OneEmpty extends Component15 {
2656
+ initState() {
2657
+ return {};
2658
+ }
2659
+ initStyles() {
2660
+ ONE_EMPTY_STYLES.forEach(({ name, ...style }) => {
2661
+ this.styleManager.addStyle(name, style);
2662
+ });
2663
+ }
2664
+ render() {
2665
+ const children = this.props.children ?? [];
2666
+ const customImage = hasNamedSlot2(children, "image");
2667
+ const customDescription = hasDefaultSlot(children);
2668
+ const customActions = hasNamedSlot2(children, "actions");
2669
+ return {
2670
+ tag: "section",
2671
+ props: { className: "one-empty" },
2672
+ children: [
2673
+ {
2674
+ tag: "div",
2675
+ props: {
2676
+ className: "one-empty__image",
2677
+ "aria-hidden": customImage ? undefined : "true"
2678
+ },
2679
+ children: customImage ? [slot7("image")] : [
2680
+ {
2681
+ tag: "span",
2682
+ props: { className: "one-empty__illustration" }
2683
+ }
2684
+ ]
2685
+ },
2686
+ {
2687
+ tag: "div",
2688
+ props: { className: "one-empty__description" },
2689
+ children: customDescription ? [slot7("default")] : [this.props.description ?? "暂无数据"]
2690
+ },
2691
+ ...customActions ? [
2692
+ {
2693
+ tag: "div",
2694
+ props: { className: "one-empty__actions" },
2695
+ children: [slot7("actions")]
2696
+ }
2697
+ ] : []
2698
+ ]
2699
+ };
2700
+ }
2701
+ }
2702
+ // lib/theme/default-theme.ts
2703
+ var ONE_DEFAULT_THEME = Object.freeze({
2704
+ colors: Object.freeze({
2705
+ primary: ONE_THEME_DEFAULTS.colorPrimary,
2706
+ primaryHover: ONE_THEME_DEFAULTS.colorPrimaryHover,
2707
+ primaryContrast: ONE_THEME_DEFAULTS.colorText,
2708
+ secondary: ONE_THEME_DEFAULTS.colorSurface,
2709
+ secondaryHover: ONE_THEME_DEFAULTS.colorBorder,
2710
+ secondaryContrast: ONE_THEME_DEFAULTS.colorText,
2711
+ danger: ONE_THEME_DEFAULTS.colorDanger,
2712
+ dangerHover: ONE_THEME_DEFAULTS.colorDangerHover,
2713
+ dangerContrast: ONE_THEME_DEFAULTS.colorSurface,
2714
+ info: ONE_THEME_DEFAULTS.colorInfo,
2715
+ success: ONE_THEME_DEFAULTS.colorSuccess,
2716
+ warning: ONE_THEME_DEFAULTS.colorWarning,
2717
+ overlay: ONE_THEME_DEFAULTS.colorOverlay,
2718
+ surface: ONE_THEME_DEFAULTS.colorSurface,
2719
+ text: ONE_THEME_DEFAULTS.colorText,
2720
+ muted: ONE_THEME_DEFAULTS.colorMuted,
2721
+ focus: ONE_THEME_DEFAULTS.colorFocus
2722
+ }),
2723
+ typography: Object.freeze({
2724
+ fontFamily: ONE_THEME_DEFAULTS.fontFamily,
2725
+ fontSizeSm: ONE_THEME_DEFAULTS.fontSizeSm,
2726
+ fontSizeMd: ONE_THEME_DEFAULTS.fontSizeMd,
2727
+ fontSizeLg: ONE_THEME_DEFAULTS.fontSizeLg,
2728
+ lineHeight: "1.5"
2729
+ }),
2730
+ border: Object.freeze({
2731
+ color: ONE_THEME_DEFAULTS.colorBorder,
2732
+ width: "1px",
2733
+ style: "solid"
2734
+ }),
2735
+ radius: Object.freeze({
2736
+ sm: ONE_THEME_DEFAULTS.radiusSm,
2737
+ md: ONE_THEME_DEFAULTS.radiusMd,
2738
+ lg: ONE_THEME_DEFAULTS.radiusMd
2739
+ })
2740
+ });
2741
+ // lib/theme/errors.ts
2742
+ class OneThemeConfigError extends Error {
2743
+ constructor(message) {
2744
+ super(message);
2745
+ this.name = "OneThemeConfigError";
2746
+ }
2747
+ }
2748
+
2749
+ class OneThemeNotFoundError extends Error {
2750
+ constructor(themeName) {
2751
+ super(`One UI theme "${themeName}" is not registered.`);
2752
+ this.name = "OneThemeNotFoundError";
2753
+ }
2754
+ }
2755
+
2756
+ class OneThemeEnvironmentError extends Error {
2757
+ constructor() {
2758
+ super("One UI themes require a browser document root.");
2759
+ this.name = "OneThemeEnvironmentError";
2760
+ }
2761
+ }
2762
+ // lib/theme/normalize.ts
2763
+ var OPTION_KEYS = ["themes", "defaultTheme"];
2764
+ var DEFINITION_KEYS = ["colors", "typography", "border", "radius"];
2765
+ var COLOR_KEYS = [
2766
+ "primary",
2767
+ "primaryHover",
2768
+ "primaryContrast",
2769
+ "secondary",
2770
+ "secondaryHover",
2771
+ "secondaryContrast",
2772
+ "danger",
2773
+ "dangerHover",
2774
+ "dangerContrast",
2775
+ "info",
2776
+ "success",
2777
+ "warning",
2778
+ "overlay",
2779
+ "surface",
2780
+ "text",
2781
+ "muted",
2782
+ "focus"
2783
+ ];
2784
+ var TYPOGRAPHY_KEYS = [
2785
+ "fontFamily",
2786
+ "fontSizeSm",
2787
+ "fontSizeMd",
2788
+ "fontSizeLg",
2789
+ "lineHeight"
2790
+ ];
2791
+ var BORDER_KEYS = ["color", "width", "style"];
2792
+ var RADIUS_KEYS = ["sm", "md", "lg"];
2793
+ function isRecord(value) {
2794
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2795
+ }
2796
+ function assertRecord(value, path) {
2797
+ if (!isRecord(value)) {
2798
+ throw new OneThemeConfigError(`${path} must be an object.`);
2799
+ }
2800
+ }
2801
+ function assertKnownKeys(value, allowedKeys, path) {
2802
+ const unknownKey = Object.keys(value).find((key) => !allowedKeys.includes(key));
2803
+ if (unknownKey) {
2804
+ throw new OneThemeConfigError(`${path}.${unknownKey} is not supported.`);
2805
+ }
2806
+ }
2807
+ function normalizeStringGroup(value, fallback, allowedKeys, path) {
2808
+ if (value === undefined) {
2809
+ return fallback;
2810
+ }
2811
+ assertRecord(value, path);
2812
+ assertKnownKeys(value, allowedKeys, path);
2813
+ const resolved = { ...fallback };
2814
+ for (const key of allowedKeys) {
2815
+ const candidate = value[key];
2816
+ if (candidate === undefined) {
2817
+ continue;
2818
+ }
2819
+ if (typeof candidate !== "string" || candidate.trim().length === 0) {
2820
+ throw new OneThemeConfigError(`${path}.${key} must be a non-empty string.`);
2821
+ }
2822
+ resolved[key] = candidate;
2823
+ }
2824
+ return Object.freeze(resolved);
2825
+ }
2826
+ function normalizeTheme(value, path) {
2827
+ assertRecord(value, path);
2828
+ assertKnownKeys(value, DEFINITION_KEYS, path);
2829
+ const definition = value;
2830
+ return Object.freeze({
2831
+ colors: normalizeStringGroup(definition.colors, ONE_DEFAULT_THEME.colors, COLOR_KEYS, `${path}.colors`),
2832
+ typography: normalizeStringGroup(definition.typography, ONE_DEFAULT_THEME.typography, TYPOGRAPHY_KEYS, `${path}.typography`),
2833
+ border: normalizeStringGroup(definition.border, ONE_DEFAULT_THEME.border, BORDER_KEYS, `${path}.border`),
2834
+ radius: normalizeStringGroup(definition.radius, ONE_DEFAULT_THEME.radius, RADIUS_KEYS, `${path}.radius`)
2835
+ });
2836
+ }
2837
+ function assertThemeName(name, path) {
2838
+ if (name.length === 0 || name.trim() !== name || /\s/.test(name)) {
2839
+ throw new OneThemeConfigError(`${path} must be a non-empty name without whitespace.`);
2840
+ }
2841
+ }
2842
+ function normalizeOneThemeOptions(options = {}) {
2843
+ assertRecord(options, "options");
2844
+ assertKnownKeys(options, OPTION_KEYS, "options");
2845
+ const themes = Object.create(null);
2846
+ themes.default = ONE_DEFAULT_THEME;
2847
+ if (options.themes !== undefined) {
2848
+ assertRecord(options.themes, "options.themes");
2849
+ for (const [name, definition] of Object.entries(options.themes)) {
2850
+ assertThemeName(name, `options.themes.${name || "<empty>"}`);
2851
+ if (name === "default") {
2852
+ throw new OneThemeConfigError("options.themes.default is reserved by One UI.");
2853
+ }
2854
+ themes[name] = normalizeTheme(definition, `options.themes.${name}`);
2855
+ }
2856
+ }
2857
+ const defaultTheme = options.defaultTheme ?? "default";
2858
+ if (typeof defaultTheme !== "string") {
2859
+ throw new OneThemeConfigError("options.defaultTheme must be a string.");
2860
+ }
2861
+ assertThemeName(defaultTheme, "options.defaultTheme");
2862
+ if (!(defaultTheme in themes)) {
2863
+ throw new OneThemeConfigError(`options.defaultTheme references unknown theme "${defaultTheme}".`);
2864
+ }
2865
+ return Object.freeze({
2866
+ themes: Object.freeze(themes),
2867
+ defaultTheme
2868
+ });
2869
+ }
2870
+
2871
+ // lib/theme/variables.ts
2872
+ var THEME_VARIABLES = [
2873
+ ["--one-color-primary", (theme) => theme.colors.primary],
2874
+ ["--one-color-primary-hover", (theme) => theme.colors.primaryHover],
2875
+ ["--one-color-primary-contrast", (theme) => theme.colors.primaryContrast],
2876
+ ["--one-color-secondary", (theme) => theme.colors.secondary],
2877
+ ["--one-color-secondary-hover", (theme) => theme.colors.secondaryHover],
2878
+ ["--one-color-secondary-contrast", (theme) => theme.colors.secondaryContrast],
2879
+ ["--one-color-danger", (theme) => theme.colors.danger],
2880
+ ["--one-color-danger-hover", (theme) => theme.colors.dangerHover],
2881
+ ["--one-color-danger-contrast", (theme) => theme.colors.dangerContrast],
2882
+ ["--one-color-info", (theme) => theme.colors.info],
2883
+ ["--one-color-success", (theme) => theme.colors.success],
2884
+ ["--one-color-warning", (theme) => theme.colors.warning],
2885
+ ["--one-color-overlay", (theme) => theme.colors.overlay],
2886
+ ["--one-color-surface", (theme) => theme.colors.surface],
2887
+ ["--one-color-text", (theme) => theme.colors.text],
2888
+ ["--one-color-muted", (theme) => theme.colors.muted],
2889
+ ["--one-color-focus", (theme) => theme.colors.focus],
2890
+ ["--one-color-border", (theme) => theme.border.color],
2891
+ ["--one-font-family", (theme) => theme.typography.fontFamily],
2892
+ ["--one-font-size-sm", (theme) => theme.typography.fontSizeSm],
2893
+ ["--one-font-size-md", (theme) => theme.typography.fontSizeMd],
2894
+ ["--one-font-size-lg", (theme) => theme.typography.fontSizeLg],
2895
+ ["--one-line-height", (theme) => theme.typography.lineHeight],
2896
+ ["--one-border-width", (theme) => theme.border.width],
2897
+ ["--one-border-style", (theme) => theme.border.style],
2898
+ ["--one-radius-sm", (theme) => theme.radius.sm],
2899
+ ["--one-radius-md", (theme) => theme.radius.md],
2900
+ ["--one-radius-lg", (theme) => theme.radius.lg]
2901
+ ];
2902
+ var ONE_THEME_VARIABLES = Object.freeze(THEME_VARIABLES);
2903
+ function oneThemeToVariables(theme) {
2904
+ return ONE_THEME_VARIABLES.map(([name, readValue]) => [
2905
+ name,
2906
+ readValue(theme)
2907
+ ]);
2908
+ }
2909
+
2910
+ // lib/theme/OneThemeService.ts
2911
+ var DEFAULT_REGISTRY = Object.freeze({ default: ONE_DEFAULT_THEME });
2912
+ function assertSwitchName(name) {
2913
+ if (typeof name !== "string" || name.length === 0 || name.trim() !== name || /\s/.test(name)) {
2914
+ throw new OneThemeConfigError("Theme name must be a non-empty string without whitespace.");
2915
+ }
2916
+ }
2917
+ function snapshotRoot(root) {
2918
+ return {
2919
+ styles: ONE_THEME_VARIABLES.map(([name]) => ({
2920
+ name,
2921
+ value: root.style.getPropertyValue(name),
2922
+ priority: root.style.getPropertyPriority(name)
2923
+ })),
2924
+ dataTheme: root.getAttribute("data-one-theme")
2925
+ };
2926
+ }
2927
+ function restoreRoot(root, snapshot) {
2928
+ snapshot.styles.forEach(({ name, value, priority }) => {
2929
+ if (value.length === 0) {
2930
+ root.style.removeProperty(name);
2931
+ return;
2932
+ }
2933
+ root.style.setProperty(name, value, priority);
2934
+ });
2935
+ if (snapshot.dataTheme === null) {
2936
+ root.removeAttribute("data-one-theme");
2937
+ } else {
2938
+ root.setAttribute("data-one-theme", snapshot.dataTheme);
2939
+ }
2940
+ }
2941
+ function applyTheme(root, name, theme) {
2942
+ const snapshot = snapshotRoot(root);
2943
+ try {
2944
+ oneThemeToVariables(theme).forEach(([property, value]) => {
2945
+ root.style.setProperty(property, value);
2946
+ });
2947
+ root.setAttribute("data-one-theme", name);
2948
+ } catch (error) {
2949
+ restoreRoot(root, snapshot);
2950
+ throw error;
2951
+ }
2952
+ }
2953
+
2954
+ class DomOneThemeService {
2955
+ resolveRoot;
2956
+ themes = DEFAULT_REGISTRY;
2957
+ activeTheme = "default";
2958
+ constructor(resolveRoot) {
2959
+ this.resolveRoot = resolveRoot;
2960
+ }
2961
+ get currentTheme() {
2962
+ return this.activeTheme;
2963
+ }
2964
+ init(options) {
2965
+ const normalized = normalizeOneThemeOptions(options);
2966
+ const root = this.requireRoot();
2967
+ const theme = normalized.themes[normalized.defaultTheme];
2968
+ applyTheme(root, normalized.defaultTheme, theme);
2969
+ this.themes = normalized.themes;
2970
+ this.activeTheme = normalized.defaultTheme;
2971
+ }
2972
+ switch(name) {
2973
+ assertSwitchName(name);
2974
+ if (!Object.prototype.hasOwnProperty.call(this.themes, name)) {
2975
+ throw new OneThemeNotFoundError(name);
2976
+ }
2977
+ const root = this.requireRoot();
2978
+ applyTheme(root, name, this.themes[name]);
2979
+ this.activeTheme = name;
2980
+ }
2981
+ requireRoot() {
2982
+ const root = this.resolveRoot();
2983
+ if (!root) {
2984
+ throw new OneThemeEnvironmentError;
2985
+ }
2986
+ return root;
2987
+ }
2988
+ }
2989
+ function resolveDocumentRoot() {
2990
+ return typeof document === "undefined" ? undefined : document.documentElement;
2991
+ }
2992
+ var oneTheme = new DomOneThemeService(resolveDocumentRoot);
2993
+ // lib/overlay/errors.ts
2994
+ class OneOverlayEnvironmentError extends Error {
2995
+ constructor(message = "One overlay requires a browser document") {
2996
+ super(message);
2997
+ this.name = "OneOverlayEnvironmentError";
2998
+ }
2999
+ }
3000
+
3001
+ class OneOverlayContainerError extends Error {
3002
+ constructor(message) {
3003
+ super(message);
3004
+ this.name = "OneOverlayContainerError";
3005
+ }
3006
+ }
3007
+
3008
+ class OneTooltipTriggerError extends Error {
3009
+ constructor(message = "OneTooltip requires one HTMLElement trigger child") {
3010
+ super(message);
3011
+ this.name = "OneTooltipTriggerError";
3012
+ }
3013
+ }
3014
+
3015
+ // lib/overlay/container.ts
3016
+ function globalDocument() {
3017
+ return typeof document === "undefined" ? null : document;
3018
+ }
3019
+ function resolveOneOverlayContainer(container, targetDocument = globalDocument()) {
3020
+ if (!targetDocument) {
3021
+ throw new OneOverlayEnvironmentError;
3022
+ }
3023
+ const resolved = typeof container === "function" ? container() : container ?? targetDocument.body;
3024
+ if (!resolved) {
3025
+ throw new OneOverlayContainerError("One overlay container was not found");
3026
+ }
3027
+ if (resolved.ownerDocument !== targetDocument) {
3028
+ throw new OneOverlayContainerError("One overlay container must belong to the current document");
3029
+ }
3030
+ if (!resolved.isConnected) {
3031
+ throw new OneOverlayContainerError("One overlay container must be connected");
3032
+ }
3033
+ if (resolved !== targetDocument.body) {
3034
+ const bounds = resolved.getBoundingClientRect();
3035
+ if (bounds.width <= 0 || bounds.height <= 0) {
3036
+ throw new OneOverlayContainerError("One overlay container must have measurable layout");
3037
+ }
3038
+ }
3039
+ return resolved;
3040
+ }
3041
+ // lib/overlay/host.ts
3042
+ class DomOneOverlayHost {
3043
+ targetDocument;
3044
+ entries = new Map;
3045
+ records = new Map;
3046
+ sequence = 0;
3047
+ constructor(targetDocument) {
3048
+ this.targetDocument = targetDocument;
3049
+ }
3050
+ open(request) {
3051
+ const container = resolveOneOverlayContainer(request.container, this.targetDocument);
3052
+ const entry = this.getOrCreateEntry(container);
3053
+ const groupKey = request.group ? `${request.kind}:${request.group}` : undefined;
3054
+ const parent = groupKey ? this.getOrCreateGroup(entry, groupKey, request.kind, request.group) : entry.element;
3055
+ const id = `one-${request.kind}-${++this.sequence}`;
3056
+ const slot8 = this.targetDocument.createElement("div");
3057
+ slot8.dataset.oneOverlayId = id;
3058
+ slot8.dataset.oneOverlayKind = request.kind;
3059
+ parent.appendChild(slot8);
3060
+ const record = {
3061
+ id,
3062
+ kind: request.kind,
3063
+ container,
3064
+ groupKey,
3065
+ slot: slot8,
3066
+ closed: false
3067
+ };
3068
+ this.records.set(id, record);
3069
+ try {
3070
+ record.managed = request.factory({
3071
+ id,
3072
+ slot: slot8,
3073
+ requestClose: () => this.close(id),
3074
+ isTop: () => this.isTop(id)
3075
+ });
3076
+ } catch (error) {
3077
+ this.removeRecord(record, false);
3078
+ throw error;
3079
+ }
3080
+ return {
3081
+ id,
3082
+ update: (options) => {
3083
+ const current = this.records.get(id);
3084
+ if (!current || current.closed) {
3085
+ return;
3086
+ }
3087
+ current.managed?.update(options);
3088
+ },
3089
+ close: () => this.close(id)
3090
+ };
3091
+ }
3092
+ close(id) {
3093
+ const record = this.records.get(id);
3094
+ if (!record || record.closed) {
3095
+ return;
3096
+ }
3097
+ this.removeRecord(record, true);
3098
+ }
3099
+ closeAll(kind) {
3100
+ [...this.records.values()].forEach((record) => {
3101
+ if (!kind || record.kind === kind) {
3102
+ this.close(record.id);
3103
+ }
3104
+ });
3105
+ }
3106
+ isTop(id) {
3107
+ const record = this.records.get(id);
3108
+ if (!record || record.closed) {
3109
+ return false;
3110
+ }
3111
+ const matching = [...this.records.values()].filter((candidate) => !candidate.closed && candidate.kind === record.kind && candidate.container === record.container);
3112
+ return matching[matching.length - 1]?.id === id;
3113
+ }
3114
+ getOrCreateEntry(container) {
3115
+ const existing = this.entries.get(container);
3116
+ if (existing) {
3117
+ return existing;
3118
+ }
3119
+ const element = this.targetDocument.createElement("div");
3120
+ element.dataset.oneOverlayHost = "";
3121
+ container.appendChild(element);
3122
+ const entry = { element, groups: new Map };
3123
+ this.entries.set(container, entry);
3124
+ return entry;
3125
+ }
3126
+ getOrCreateGroup(entry, key, kind, group) {
3127
+ const existing = entry.groups.get(key);
3128
+ if (existing) {
3129
+ return existing;
3130
+ }
3131
+ const element = this.targetDocument.createElement("div");
3132
+ element.dataset.oneOverlayGroup = group;
3133
+ element.dataset.oneOverlayKind = kind;
3134
+ entry.element.appendChild(element);
3135
+ entry.groups.set(key, element);
3136
+ return element;
3137
+ }
3138
+ removeRecord(record, destroy) {
3139
+ record.closed = true;
3140
+ this.records.delete(record.id);
3141
+ if (destroy) {
3142
+ record.managed?.destroy();
3143
+ }
3144
+ record.slot.remove();
3145
+ const entry = this.entries.get(record.container);
3146
+ if (!entry) {
3147
+ return;
3148
+ }
3149
+ if (record.groupKey) {
3150
+ const group = entry.groups.get(record.groupKey);
3151
+ if (group && group.childElementCount === 0) {
3152
+ group.remove();
3153
+ entry.groups.delete(record.groupKey);
3154
+ }
3155
+ }
3156
+ if (entry.element.childElementCount === 0) {
3157
+ entry.element.remove();
3158
+ this.entries.delete(record.container);
3159
+ }
3160
+ }
3161
+ }
3162
+ var defaultHosts = new WeakMap;
3163
+ function getDefaultOneOverlayHost(targetDocument) {
3164
+ const resolved = targetDocument ?? (typeof document === "undefined" ? null : document);
3165
+ if (!resolved) {
3166
+ throw new OneOverlayEnvironmentError;
3167
+ }
3168
+ const existing = defaultHosts.get(resolved);
3169
+ if (existing) {
3170
+ return existing;
3171
+ }
3172
+ const host = new DomOneOverlayHost(resolved);
3173
+ defaultHosts.set(resolved, host);
3174
+ return host;
3175
+ }
3176
+ // lib/overlay/mount-controller.ts
3177
+ class OneOverlayMountController {
3178
+ host;
3179
+ kind;
3180
+ factory;
3181
+ group;
3182
+ handle;
3183
+ constructor(host, kind, factory, group) {
3184
+ this.host = host;
3185
+ this.kind = kind;
3186
+ this.factory = factory;
3187
+ this.group = group;
3188
+ }
3189
+ open(container) {
3190
+ if (this.handle) {
3191
+ return;
3192
+ }
3193
+ this.handle = this.host.open({
3194
+ kind: this.kind,
3195
+ group: this.group,
3196
+ container,
3197
+ factory: this.factory
3198
+ });
3199
+ }
3200
+ update(options) {
3201
+ this.handle?.update(options);
3202
+ }
3203
+ close() {
3204
+ this.handle?.close();
3205
+ this.handle = undefined;
3206
+ }
3207
+ isOpen() {
3208
+ return this.handle !== undefined;
3209
+ }
3210
+ }
3211
+ // lib/overlay/positioner.ts
3212
+ var OPPOSITE = {
3213
+ top: "bottom",
3214
+ right: "left",
3215
+ bottom: "top",
3216
+ left: "right"
3217
+ };
3218
+ var CLOCKWISE = {
3219
+ top: "right",
3220
+ right: "bottom",
3221
+ bottom: "left",
3222
+ left: "top"
3223
+ };
3224
+ var COUNTER_CLOCKWISE = {
3225
+ top: "left",
3226
+ right: "top",
3227
+ bottom: "right",
3228
+ left: "bottom"
3229
+ };
3230
+ function parsePlacement(placement) {
3231
+ const [side, alignment = "center"] = placement.split("-");
3232
+ return { side, alignment };
3233
+ }
3234
+ function formatPlacement(side, alignment) {
3235
+ return alignment === "center" ? side : `${side}-${alignment}`;
3236
+ }
3237
+ function clamp(value, minimum, maximum) {
3238
+ if (maximum < minimum) {
3239
+ return minimum;
3240
+ }
3241
+ return Math.min(Math.max(value, minimum), maximum);
3242
+ }
3243
+ function coordinates(reference, floating, side, alignment, offset) {
3244
+ let x = reference.left + (reference.width - floating.width) / 2;
3245
+ let y = reference.top + (reference.height - floating.height) / 2;
3246
+ if (side === "top") {
3247
+ y = reference.top - floating.height - offset;
3248
+ } else if (side === "bottom") {
3249
+ y = reference.bottom + offset;
3250
+ } else if (side === "left") {
3251
+ x = reference.left - floating.width - offset;
3252
+ } else {
3253
+ x = reference.right + offset;
3254
+ }
3255
+ if (side === "top" || side === "bottom") {
3256
+ if (alignment === "start") {
3257
+ x = reference.left;
3258
+ } else if (alignment === "end") {
3259
+ x = reference.right - floating.width;
3260
+ }
3261
+ } else if (alignment === "start") {
3262
+ y = reference.top;
3263
+ } else if (alignment === "end") {
3264
+ y = reference.bottom - floating.height;
3265
+ }
3266
+ return { x, y };
3267
+ }
3268
+ function fits(point, floating, boundary, padding) {
3269
+ return point.x >= boundary.left + padding && point.y >= boundary.top + padding && point.x + floating.width <= boundary.right - padding && point.y + floating.height <= boundary.bottom - padding;
3270
+ }
3271
+ function visibleArea(point, floating, boundary, padding) {
3272
+ const left = Math.max(point.x, boundary.left + padding);
3273
+ const top = Math.max(point.y, boundary.top + padding);
3274
+ const right = Math.min(point.x + floating.width, boundary.right - padding);
3275
+ const bottom = Math.min(point.y + floating.height, boundary.bottom - padding);
3276
+ return Math.max(0, right - left) * Math.max(0, bottom - top);
3277
+ }
3278
+ function scrollAncestors(element) {
3279
+ const targets = new Set;
3280
+ const view = element.ownerDocument.defaultView;
3281
+ let current = element.parentElement;
3282
+ while (current) {
3283
+ const style = view?.getComputedStyle(current);
3284
+ if (style && /(auto|scroll|overlay)/.test(style.overflow + style.overflowX + style.overflowY)) {
3285
+ targets.add(current);
3286
+ }
3287
+ current = current.parentElement;
3288
+ }
3289
+ if (view) {
3290
+ targets.add(view);
3291
+ }
3292
+ return [...targets];
3293
+ }
3294
+
3295
+ class OneFloatingPositioner {
3296
+ compute(request) {
3297
+ const preferred = parsePlacement(request.placement);
3298
+ const sides = [
3299
+ preferred.side,
3300
+ OPPOSITE[preferred.side],
3301
+ CLOCKWISE[preferred.side],
3302
+ COUNTER_CLOCKWISE[preferred.side]
3303
+ ];
3304
+ const candidates = sides.map((side) => ({
3305
+ placement: formatPlacement(side, preferred.alignment),
3306
+ side,
3307
+ point: coordinates(request.reference, request.floating, side, preferred.alignment, request.offset)
3308
+ }));
3309
+ const selected = candidates.find((candidate) => fits(candidate.point, request.floating, request.boundary, request.padding)) ?? candidates.reduce((best, candidate) => visibleArea(candidate.point, request.floating, request.boundary, request.padding) > visibleArea(best.point, request.floating, request.boundary, request.padding) ? candidate : best);
3310
+ const x = clamp(selected.point.x, request.boundary.left + request.padding, request.boundary.right - request.padding - request.floating.width);
3311
+ const y = clamp(selected.point.y, request.boundary.top + request.padding, request.boundary.bottom - request.padding - request.floating.height);
3312
+ const centerX = request.reference.left + request.reference.width / 2;
3313
+ const centerY = request.reference.top + request.reference.height / 2;
3314
+ const arrow = selected.side === "top" || selected.side === "bottom" ? {
3315
+ x: clamp(centerX - x, 8, Math.max(8, request.floating.width - 8))
3316
+ } : {
3317
+ y: clamp(centerY - y, 8, Math.max(8, request.floating.height - 8))
3318
+ };
3319
+ return { x, y, placement: selected.placement, arrow };
3320
+ }
3321
+ autoUpdate(reference, floating, update) {
3322
+ const view = reference.ownerDocument.defaultView;
3323
+ if (!view) {
3324
+ return () => {};
3325
+ }
3326
+ let disposed = false;
3327
+ let frame;
3328
+ const schedule = () => {
3329
+ if (disposed || frame !== undefined) {
3330
+ return;
3331
+ }
3332
+ frame = view.requestAnimationFrame(() => {
3333
+ frame = undefined;
3334
+ if (!disposed) {
3335
+ update();
3336
+ }
3337
+ });
3338
+ };
3339
+ const targets = new Set([
3340
+ ...scrollAncestors(reference),
3341
+ ...scrollAncestors(floating)
3342
+ ]);
3343
+ targets.forEach((target) => target.addEventListener("scroll", schedule));
3344
+ view.addEventListener("resize", schedule);
3345
+ const observer = view.ResizeObserver ? new view.ResizeObserver(schedule) : undefined;
3346
+ observer?.observe(reference);
3347
+ observer?.observe(floating);
3348
+ return () => {
3349
+ if (disposed) {
3350
+ return;
3351
+ }
3352
+ disposed = true;
3353
+ if (frame !== undefined) {
3354
+ view.cancelAnimationFrame(frame);
3355
+ frame = undefined;
3356
+ }
3357
+ observer?.disconnect();
3358
+ targets.forEach((target) => target.removeEventListener("scroll", schedule));
3359
+ view.removeEventListener("resize", schedule);
3360
+ };
3361
+ }
3362
+ }
3363
+ // lib/alert/OneAlert.ts
3364
+ import { Component as Component16, slot as slot8 } from "@geektech/tsone";
3365
+ var VARIANTS2 = [
3366
+ "info",
3367
+ "success",
3368
+ "warning",
3369
+ "error"
3370
+ ];
3371
+ var DEFAULT_ICONS = {
3372
+ info: "i",
3373
+ success: "✓",
3374
+ warning: "!",
3375
+ error: "×"
3376
+ };
3377
+ var ONE_ALERT_STYLES = [
3378
+ {
3379
+ name: "one-alert-base",
3380
+ selector: ".one-alert",
3381
+ properties: {
3382
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
3383
+ display: "grid",
3384
+ gridTemplateColumns: "auto minmax(0, 1fr) auto",
3385
+ gap: `var(--one-alert-gap, var(--one-space-sm, ${ONE_THEME_DEFAULTS.spaceSm}))`,
3386
+ alignItems: "start",
3387
+ padding: `var(--one-alert-padding, var(--one-space-md, ${ONE_THEME_DEFAULTS.spaceMd}))`,
3388
+ color: `var(--one-alert-color, var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText}))`,
3389
+ backgroundColor: `var(--one-alert-background, var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface}))`,
3390
+ border: oneThemeBorder(`var(--one-alert-border-color, var(--one-color-border, ${ONE_THEME_DEFAULTS.colorBorder}))`),
3391
+ borderRadius: `var(--one-alert-radius, var(--one-radius-md, ${ONE_THEME_DEFAULTS.radiusMd}))`
3392
+ }
3393
+ },
3394
+ {
3395
+ name: "one-alert-info",
3396
+ selector: ".one-alert--info",
3397
+ properties: {
3398
+ borderColor: `var(--one-color-info, ${ONE_THEME_DEFAULTS.colorInfo})`
3399
+ }
3400
+ },
3401
+ {
3402
+ name: "one-alert-success",
3403
+ selector: ".one-alert--success",
3404
+ properties: {
3405
+ borderColor: `var(--one-color-success, ${ONE_THEME_DEFAULTS.colorSuccess})`
3406
+ }
3407
+ },
3408
+ {
3409
+ name: "one-alert-warning",
3410
+ selector: ".one-alert--warning",
3411
+ properties: {
3412
+ borderColor: `var(--one-color-warning, ${ONE_THEME_DEFAULTS.colorWarning})`
3413
+ }
3414
+ },
3415
+ {
3416
+ name: "one-alert-error",
3417
+ selector: ".one-alert--error",
3418
+ properties: {
3419
+ borderColor: `var(--one-color-danger, ${ONE_THEME_DEFAULTS.colorDanger})`
3420
+ }
3421
+ },
3422
+ {
3423
+ name: "one-alert-icon",
3424
+ selector: ".one-alert__icon",
3425
+ properties: {
3426
+ display: "inline-flex",
3427
+ alignItems: "center",
3428
+ justifyContent: "center",
3429
+ minWidth: "20px",
3430
+ fontWeight: "700"
3431
+ }
3432
+ },
3433
+ {
3434
+ name: "one-alert-title",
3435
+ selector: ".one-alert__title",
3436
+ properties: { fontWeight: "600" }
3437
+ },
3438
+ {
3439
+ name: "one-alert-description",
3440
+ selector: ".one-alert__description",
3441
+ properties: {
3442
+ marginTop: `var(--one-space-xs, ${ONE_THEME_DEFAULTS.spaceXs})`,
3443
+ color: `var(--one-color-muted, ${ONE_THEME_DEFAULTS.colorMuted})`
3444
+ }
3445
+ },
3446
+ {
3447
+ name: "one-alert-actions",
3448
+ selector: ".one-alert__actions",
3449
+ properties: { alignSelf: "center" }
3450
+ },
3451
+ {
3452
+ name: "one-alert-controls",
3453
+ selector: ".one-alert__controls",
3454
+ properties: {
3455
+ display: "inline-flex",
3456
+ gap: `var(--one-space-sm, ${ONE_THEME_DEFAULTS.spaceSm})`,
3457
+ alignItems: "center"
3458
+ }
3459
+ },
3460
+ {
3461
+ name: "one-alert-close",
3462
+ selector: ".one-alert__close",
3463
+ properties: {
3464
+ padding: "2px",
3465
+ color: "inherit",
3466
+ backgroundColor: "transparent",
3467
+ border: "0",
3468
+ cursor: "pointer"
3469
+ }
3470
+ }
3471
+ ];
3472
+ function normalizeVariant(value) {
3473
+ return VARIANTS2.includes(value) ? value : "info";
3474
+ }
3475
+ function hasNamedSlot3(children, name) {
3476
+ return children.some((child) => typeof child !== "string" && child.slot === name);
3477
+ }
3478
+ function hasDefaultSlot2(children) {
3479
+ return children.some((child) => typeof child === "string" || child.slot === undefined);
3480
+ }
3481
+
3482
+ class OneAlert extends Component16 {
3483
+ initState() {
3484
+ return { visible: true };
3485
+ }
3486
+ initStyles() {
3487
+ ONE_ALERT_STYLES.forEach(({ name, ...style }) => {
3488
+ this.styleManager.addStyle(name, style);
3489
+ });
3490
+ }
3491
+ render() {
3492
+ if (!this.state.visible) {
3493
+ return {
3494
+ tag: "span",
3495
+ props: { hidden: true, "data-one-alert-anchor": "" }
3496
+ };
3497
+ }
3498
+ const variant = normalizeVariant(this.props.variant);
3499
+ const children = this.props.children ?? [];
3500
+ const customIcon = hasNamedSlot3(children, "icon");
3501
+ const customActions = hasNamedSlot3(children, "actions");
3502
+ const customDescription = hasDefaultSlot2(children);
3503
+ return {
3504
+ tag: "section",
3505
+ props: {
3506
+ className: `one-alert one-alert--${variant}`,
3507
+ role: variant === "warning" || variant === "error" ? "alert" : "status"
3508
+ },
3509
+ children: [
3510
+ {
3511
+ tag: "div",
3512
+ props: { className: "one-alert__icon", "aria-hidden": "true" },
3513
+ children: customIcon ? [slot8("icon")] : [DEFAULT_ICONS[variant]]
3514
+ },
3515
+ {
3516
+ tag: "div",
3517
+ props: { className: "one-alert__content" },
3518
+ children: [
3519
+ ...this.props.title ? [
3520
+ {
3521
+ tag: "div",
3522
+ props: { className: "one-alert__title" },
3523
+ children: [this.props.title]
3524
+ }
3525
+ ] : [],
3526
+ ...customDescription || this.props.description ? [
3527
+ {
3528
+ tag: "div",
3529
+ props: { className: "one-alert__description" },
3530
+ children: customDescription ? [slot8("default")] : [this.props.description ?? ""]
3531
+ }
3532
+ ] : []
3533
+ ]
3534
+ },
3535
+ ...customActions || this.props.closable ? [
3536
+ {
3537
+ tag: "div",
3538
+ props: { className: "one-alert__controls" },
3539
+ children: [
3540
+ ...customActions ? [
3541
+ {
3542
+ tag: "div",
3543
+ props: { className: "one-alert__actions" },
3544
+ children: [slot8("actions")]
3545
+ }
3546
+ ] : [],
3547
+ ...this.props.closable ? [
3548
+ {
3549
+ tag: "button",
3550
+ props: {
3551
+ type: "button",
3552
+ className: "one-alert__close",
3553
+ "aria-label": "关闭提示"
3554
+ },
3555
+ children: ["×"],
3556
+ listeners: { click: () => this.close() }
3557
+ }
3558
+ ] : []
3559
+ ]
3560
+ }
3561
+ ] : []
3562
+ ]
3563
+ };
3564
+ }
3565
+ close() {
3566
+ if (!this.state.visible) {
3567
+ return;
3568
+ }
3569
+ this.emit("close");
3570
+ this.state.visible = false;
3571
+ }
3572
+ }
3573
+ // lib/message/MessageOverlay.ts
3574
+ import { Component as Component17 } from "@geektech/tsone";
3575
+
3576
+ // lib/message/timer.ts
3577
+ var DEFAULT_SCHEDULER = {
3578
+ now: () => typeof performance === "undefined" ? Date.now() : performance.now(),
3579
+ set: (callback, delay) => globalThis.setTimeout(callback, delay),
3580
+ clear: (handle) => globalThis.clearTimeout(handle)
3581
+ };
3582
+
3583
+ class OneMessageTimer {
3584
+ scheduler;
3585
+ onElapsed;
3586
+ handle;
3587
+ remaining = 0;
3588
+ startedAt = 0;
3589
+ paused = false;
3590
+ disposed = false;
3591
+ constructor(duration, scheduler = DEFAULT_SCHEDULER, onElapsed) {
3592
+ this.scheduler = scheduler;
3593
+ this.onElapsed = onElapsed;
3594
+ this.reset(duration);
3595
+ }
3596
+ pause() {
3597
+ if (this.disposed || this.paused || this.handle === undefined) {
3598
+ return;
3599
+ }
3600
+ this.remaining = Math.max(0, this.remaining - (this.scheduler.now() - this.startedAt));
3601
+ this.clear();
3602
+ this.paused = true;
3603
+ }
3604
+ resume() {
3605
+ if (this.disposed || !this.paused) {
3606
+ return;
3607
+ }
3608
+ this.paused = false;
3609
+ this.schedule();
3610
+ }
3611
+ reset(duration) {
3612
+ if (this.disposed) {
3613
+ return;
3614
+ }
3615
+ this.clear();
3616
+ this.remaining = normalizeDuration(duration);
3617
+ this.paused = false;
3618
+ this.schedule();
3619
+ }
3620
+ dispose() {
3621
+ if (this.disposed) {
3622
+ return;
3623
+ }
3624
+ this.disposed = true;
3625
+ this.clear();
3626
+ }
3627
+ schedule() {
3628
+ if (this.remaining <= 0) {
3629
+ return;
3630
+ }
3631
+ this.startedAt = this.scheduler.now();
3632
+ this.handle = this.scheduler.set(() => {
3633
+ this.handle = undefined;
3634
+ this.remaining = 0;
3635
+ if (!this.disposed) {
3636
+ this.onElapsed();
3637
+ }
3638
+ }, this.remaining);
3639
+ }
3640
+ clear() {
3641
+ if (this.handle === undefined) {
3642
+ return;
3643
+ }
3644
+ this.scheduler.clear(this.handle);
3645
+ this.handle = undefined;
3646
+ }
3647
+ }
3648
+ function normalizeDuration(duration) {
3649
+ return Number.isFinite(duration) && duration > 0 ? duration : 0;
3650
+ }
3651
+
3652
+ // lib/message/MessageOverlay.ts
3653
+ var ONE_MESSAGE_STYLES = [
3654
+ {
3655
+ name: "one-message-group",
3656
+ selector: ".one-overlay-group--message",
3657
+ properties: {
3658
+ position: "fixed",
3659
+ zIndex: `var(--one-z-index-message, ${ONE_THEME_DEFAULTS.zIndexMessage})`,
3660
+ display: "flex",
3661
+ flexDirection: "column",
3662
+ gap: `var(--one-space-sm, ${ONE_THEME_DEFAULTS.spaceSm})`,
3663
+ width: "min(420px, calc(100vw - 32px))",
3664
+ pointerEvents: "none"
3665
+ }
3666
+ },
3667
+ {
3668
+ name: "one-message-group-top",
3669
+ selector: '.one-overlay-group--message[data-one-message-placement^="top"]',
3670
+ properties: { top: "16px" }
3671
+ },
3672
+ {
3673
+ name: "one-message-group-bottom",
3674
+ selector: '.one-overlay-group--message[data-one-message-placement^="bottom"]',
3675
+ properties: { bottom: "16px", flexDirection: "column-reverse" }
3676
+ },
3677
+ {
3678
+ name: "one-message-group-center",
3679
+ selector: '.one-overlay-group--message[data-one-message-placement="top"], .one-overlay-group--message[data-one-message-placement="bottom"]',
3680
+ properties: { left: "50%", transform: "translateX(-50%)" }
3681
+ },
3682
+ {
3683
+ name: "one-message-group-start",
3684
+ selector: '.one-overlay-group--message[data-one-message-placement$="start"]',
3685
+ properties: { left: "16px" }
3686
+ },
3687
+ {
3688
+ name: "one-message-group-end",
3689
+ selector: '.one-overlay-group--message[data-one-message-placement$="end"]',
3690
+ properties: { right: "16px" }
3691
+ },
3692
+ {
3693
+ name: "one-message-base",
3694
+ selector: ".one-message",
3695
+ properties: {
3696
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
3697
+ display: "grid",
3698
+ gridTemplateColumns: "minmax(0, 1fr) auto",
3699
+ alignItems: "center",
3700
+ gap: `var(--one-space-sm, ${ONE_THEME_DEFAULTS.spaceSm})`,
3701
+ boxSizing: "border-box",
3702
+ padding: `var(--one-space-md, ${ONE_THEME_DEFAULTS.spaceMd}) var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg})`,
3703
+ color: `var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText})`,
3704
+ backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
3705
+ border: oneThemeBorder(),
3706
+ borderRadius: `var(--one-radius-md, ${ONE_THEME_DEFAULTS.radiusMd})`,
3707
+ boxShadow: `var(--one-shadow-overlay, ${ONE_THEME_DEFAULTS.shadowOverlay})`,
3708
+ pointerEvents: "auto"
3709
+ }
3710
+ },
3711
+ {
3712
+ name: "one-message-info",
3713
+ selector: ".one-message--info",
3714
+ properties: {
3715
+ borderColor: `var(--one-color-info, ${ONE_THEME_DEFAULTS.colorInfo})`
3716
+ }
3717
+ },
3718
+ {
3719
+ name: "one-message-success",
3720
+ selector: ".one-message--success",
3721
+ properties: {
3722
+ borderColor: `var(--one-color-success, ${ONE_THEME_DEFAULTS.colorSuccess})`
3723
+ }
3724
+ },
3725
+ {
3726
+ name: "one-message-warning",
3727
+ selector: ".one-message--warning",
3728
+ properties: {
3729
+ borderColor: `var(--one-color-warning, ${ONE_THEME_DEFAULTS.colorWarning})`
3730
+ }
3731
+ },
3732
+ {
3733
+ name: "one-message-error",
3734
+ selector: ".one-message--error",
3735
+ properties: {
3736
+ borderColor: `var(--one-color-danger, ${ONE_THEME_DEFAULTS.colorDanger})`
3737
+ }
3738
+ },
3739
+ {
3740
+ name: "one-message-close",
3741
+ selector: ".one-message__close",
3742
+ properties: {
3743
+ padding: "2px",
3744
+ color: "inherit",
3745
+ backgroundColor: "transparent",
3746
+ border: "0",
3747
+ cursor: "pointer"
3748
+ }
3749
+ }
3750
+ ];
3751
+
3752
+ class MessageOverlay extends Component17 {
3753
+ timer;
3754
+ mount(container) {
3755
+ super.mount(container);
3756
+ this.decorateGroup();
3757
+ }
3758
+ initState() {
3759
+ return {};
3760
+ }
3761
+ initStyles() {
3762
+ ONE_MESSAGE_STYLES.forEach(({ name, ...style }) => {
3763
+ this.styleManager.addStyle(name, style);
3764
+ });
3765
+ }
3766
+ onMounted() {
3767
+ this.timer = new OneMessageTimer(this.props.duration, undefined, () => {
3768
+ this.props.requestClose();
3769
+ });
3770
+ }
3771
+ onUnmounted() {
3772
+ this.timer?.dispose();
3773
+ this.timer = undefined;
3774
+ }
3775
+ setProps(props) {
3776
+ const durationChanged = props.duration !== undefined && props.duration !== this.props.duration;
3777
+ super.setProps(props);
3778
+ if (durationChanged) {
3779
+ this.timer?.reset(this.props.duration);
3780
+ }
3781
+ }
3782
+ render() {
3783
+ const urgent = this.props.variant === "warning" || this.props.variant === "error";
3784
+ return {
3785
+ tag: "div",
3786
+ props: {
3787
+ className: `one-message one-message--${this.props.variant}`,
3788
+ role: urgent ? "alert" : "status",
3789
+ "data-one-message-placement": this.props.placement
3790
+ },
3791
+ children: [
3792
+ {
3793
+ tag: "div",
3794
+ props: { className: "one-message__content" },
3795
+ children: [this.props.content]
3796
+ },
3797
+ ...this.props.closable ? [
3798
+ {
3799
+ tag: "button",
3800
+ props: {
3801
+ type: "button",
3802
+ className: "one-message__close",
3803
+ "aria-label": "关闭消息"
3804
+ },
3805
+ children: ["×"],
3806
+ listeners: { click: () => this.props.requestClose() }
3807
+ }
3808
+ ] : []
3809
+ ],
3810
+ listeners: {
3811
+ mouseenter: () => this.timer?.pause(),
3812
+ mouseleave: () => this.timer?.resume()
3813
+ }
3814
+ };
3815
+ }
3816
+ decorateGroup() {
3817
+ const element = this.getElement();
3818
+ if (!(element instanceof HTMLElement)) {
3819
+ return;
3820
+ }
3821
+ const group = element.parentElement?.parentElement;
3822
+ if (group?.dataset.oneOverlayKind !== "message") {
3823
+ return;
3824
+ }
3825
+ group.classList.add("one-overlay-group", "one-overlay-group--message");
3826
+ group.dataset.oneMessagePlacement = this.props.placement;
3827
+ }
3828
+ }
3829
+ // lib/message/OneMessage.ts
3830
+ import { Component as Component18 } from "@geektech/tsone";
3831
+
3832
+ // lib/message/normalize.ts
3833
+ var VARIANTS3 = [
3834
+ "info",
3835
+ "success",
3836
+ "warning",
3837
+ "error"
3838
+ ];
3839
+ var PLACEMENTS = [
3840
+ "top-start",
3841
+ "top",
3842
+ "top-end",
3843
+ "bottom-start",
3844
+ "bottom",
3845
+ "bottom-end"
3846
+ ];
3847
+ function normalizeOneMessageOptions(options) {
3848
+ return {
3849
+ ...options,
3850
+ variant: VARIANTS3.includes(options.variant) ? options.variant : "info",
3851
+ duration: typeof options.duration === "number" && Number.isFinite(options.duration) && options.duration >= 0 ? options.duration : 3000,
3852
+ placement: PLACEMENTS.includes(options.placement) ? options.placement : "top"
3853
+ };
3854
+ }
3855
+
3856
+ // lib/message/OneMessage.ts
3857
+ class OneMessage extends Component18 {
3858
+ controller;
3859
+ viewMounted = false;
3860
+ initState() {
3861
+ return { internalOpen: this.props.defaultOpen === true };
3862
+ }
3863
+ initStyles() {}
3864
+ onMounted() {
3865
+ const options = normalizeOneMessageOptions(this.props);
3866
+ this.controller = new OneOverlayMountController(getDefaultOneOverlayHost(), "message", (context) => this.createOverlay(context), options.placement);
3867
+ this.synchronizeOverlay();
3868
+ }
3869
+ beforeUpdate() {
3870
+ this.synchronizeOverlay();
3871
+ }
3872
+ beforeUnmount() {
3873
+ this.controller?.close();
3874
+ this.controller = undefined;
3875
+ }
3876
+ render() {
3877
+ return {
3878
+ tag: "span",
3879
+ props: { hidden: true, "data-one-message-anchor": "" }
3880
+ };
3881
+ }
3882
+ createOverlay(context) {
3883
+ const options = normalizeOneMessageOptions(this.props);
3884
+ const overlay = new MessageOverlay({
3885
+ ...options,
3886
+ requestClose: () => this.requestClose()
3887
+ });
3888
+ overlay.mount(context.slot);
3889
+ this.viewMounted = true;
3890
+ return {
3891
+ update: (next) => {
3892
+ const normalized = normalizeOneMessageOptions({
3893
+ ...options,
3894
+ ...next
3895
+ });
3896
+ overlay.setProps({ ...normalized });
3897
+ },
3898
+ destroy: () => {
3899
+ overlay.unmount();
3900
+ if (this.viewMounted) {
3901
+ this.viewMounted = false;
3902
+ this.emit("afterClose");
3903
+ }
3904
+ }
3905
+ };
3906
+ }
3907
+ synchronizeOverlay() {
3908
+ if (!this.controller) {
3909
+ return;
3910
+ }
3911
+ const open = this.props.open === undefined ? this.state.internalOpen : this.props.open === true;
3912
+ if (!open) {
3913
+ this.controller.close();
3914
+ return;
3915
+ }
3916
+ const options = normalizeOneMessageOptions(this.props);
3917
+ this.controller.open(options.container);
3918
+ this.controller.update(options);
3919
+ }
3920
+ requestClose() {
3921
+ this.emit("openChange", false);
3922
+ this.emit("close");
3923
+ if (this.props.open !== undefined) {
3924
+ return;
3925
+ }
3926
+ this.state.internalOpen = false;
3927
+ this.controller?.close();
3928
+ }
3929
+ }
3930
+ // lib/message/service.ts
3931
+ class OneMessageService {
3932
+ suppliedHost;
3933
+ constructor(suppliedHost) {
3934
+ this.suppliedHost = suppliedHost;
3935
+ }
3936
+ open(options) {
3937
+ const host = this.suppliedHost ?? getDefaultOneOverlayHost();
3938
+ let current = normalizeOneMessageOptions(options);
3939
+ const hostHandle = host.open({
3940
+ kind: "message",
3941
+ group: current.placement,
3942
+ container: current.container,
3943
+ factory: ({ slot: slot9, requestClose }) => {
3944
+ const overlay = new MessageOverlay({
3945
+ ...current,
3946
+ requestClose
3947
+ });
3948
+ overlay.mount(slot9);
3949
+ return {
3950
+ update: (next) => {
3951
+ current = normalizeOneMessageOptions({ ...current, ...next });
3952
+ overlay.setProps({ ...current });
3953
+ },
3954
+ destroy: () => overlay.unmount()
3955
+ };
3956
+ }
3957
+ });
3958
+ return {
3959
+ id: hostHandle.id,
3960
+ update: (next) => hostHandle.update(next),
3961
+ close: () => hostHandle.close()
3962
+ };
3963
+ }
3964
+ info(content, options = {}) {
3965
+ return this.open({ ...options, content, variant: "info" });
3966
+ }
3967
+ success(content, options = {}) {
3968
+ return this.open({ ...options, content, variant: "success" });
3969
+ }
3970
+ warning(content, options = {}) {
3971
+ return this.open({ ...options, content, variant: "warning" });
3972
+ }
3973
+ error(content, options = {}) {
3974
+ return this.open({ ...options, content, variant: "error" });
3975
+ }
3976
+ close(id) {
3977
+ (this.suppliedHost ?? getDefaultOneOverlayHost()).close(id);
3978
+ }
3979
+ closeAll() {
3980
+ (this.suppliedHost ?? getDefaultOneOverlayHost()).closeAll("message");
3981
+ }
3982
+ }
3983
+ function createOneMessageService(host) {
3984
+ return new OneMessageService(host);
3985
+ }
3986
+ var oneMessage = createOneMessageService();
3987
+ // lib/dialog/DialogOverlay.ts
3988
+ import { Component as Component19, slot as slot9 } from "@geektech/tsone";
3989
+
3990
+ // lib/dialog/focus-manager.ts
3991
+ var FOCUSABLE_SELECTOR = [
3992
+ "button:not([disabled])",
3993
+ "input:not([disabled])",
3994
+ "select:not([disabled])",
3995
+ "textarea:not([disabled])",
3996
+ "a[href]",
3997
+ '[tabindex]:not([tabindex="-1"])'
3998
+ ].join(",");
3999
+
4000
+ class OneDialogFocusManager {
4001
+ dialog;
4002
+ previousFocus;
4003
+ isTop = () => true;
4004
+ targetDocument;
4005
+ activate(dialog, isTop = () => true) {
4006
+ this.deactivate(false);
4007
+ this.dialog = dialog;
4008
+ this.targetDocument = dialog.ownerDocument;
4009
+ this.isTop = isTop;
4010
+ const active = this.targetDocument.activeElement;
4011
+ this.previousFocus = active instanceof HTMLElement ? active : undefined;
4012
+ this.targetDocument.addEventListener("keydown", this.handleKeydown);
4013
+ (this.focusableElements()[0] ?? dialog).focus();
4014
+ }
4015
+ deactivate(restoreFocus = true) {
4016
+ this.targetDocument?.removeEventListener("keydown", this.handleKeydown);
4017
+ if (restoreFocus && this.previousFocus?.isConnected) {
4018
+ this.previousFocus.focus();
4019
+ }
4020
+ this.dialog = undefined;
4021
+ this.previousFocus = undefined;
4022
+ this.targetDocument = undefined;
4023
+ this.isTop = () => true;
4024
+ }
4025
+ handleKeydown = (event) => {
4026
+ if (event.key !== "Tab" || !this.dialog || !this.isTop()) {
4027
+ return;
4028
+ }
4029
+ const focusable = this.focusableElements();
4030
+ if (focusable.length === 0) {
4031
+ event.preventDefault();
4032
+ this.dialog.focus();
4033
+ return;
4034
+ }
4035
+ const first = focusable[0];
4036
+ const last = focusable[focusable.length - 1];
4037
+ const active = this.targetDocument?.activeElement ?? null;
4038
+ if (event.shiftKey && (active === first || !this.dialog.contains(active))) {
4039
+ event.preventDefault();
4040
+ last.focus();
4041
+ } else if (!event.shiftKey && active === last) {
4042
+ event.preventDefault();
4043
+ first.focus();
4044
+ }
4045
+ };
4046
+ focusableElements() {
4047
+ if (!this.dialog) {
4048
+ return [];
4049
+ }
4050
+ return [
4051
+ ...this.dialog.querySelectorAll(FOCUSABLE_SELECTOR)
4052
+ ].filter((element) => element.getAttribute("aria-hidden") !== "true" && !element.hasAttribute("hidden"));
4053
+ }
4054
+ }
4055
+
4056
+ // lib/dialog/scroll-lock.ts
4057
+ var scrollLocks = new WeakMap;
4058
+ function lockOneDialogBody(targetDocument) {
4059
+ const existing = scrollLocks.get(targetDocument);
4060
+ if (existing) {
4061
+ existing.count += 1;
4062
+ } else {
4063
+ scrollLocks.set(targetDocument, {
4064
+ count: 1,
4065
+ previousOverflow: targetDocument.body.style.overflow
4066
+ });
4067
+ targetDocument.body.style.overflow = "hidden";
4068
+ }
4069
+ let released = false;
4070
+ return () => {
4071
+ if (released) {
4072
+ return;
4073
+ }
4074
+ released = true;
4075
+ unlockOneDialogBody(targetDocument);
4076
+ };
4077
+ }
4078
+ function unlockOneDialogBody(targetDocument) {
4079
+ const record = scrollLocks.get(targetDocument);
4080
+ if (!record) {
4081
+ return;
4082
+ }
4083
+ record.count -= 1;
4084
+ if (record.count > 0) {
4085
+ return;
4086
+ }
4087
+ targetDocument.body.style.overflow = record.previousOverflow;
4088
+ scrollLocks.delete(targetDocument);
4089
+ }
4090
+
4091
+ // lib/dialog/DialogOverlay.ts
4092
+ var ONE_DIALOG_STYLES = [
4093
+ {
4094
+ name: "one-dialog-backdrop",
4095
+ selector: ".one-dialog__backdrop",
4096
+ properties: {
4097
+ position: "fixed",
4098
+ inset: "0",
4099
+ zIndex: `var(--one-z-index-dialog, ${ONE_THEME_DEFAULTS.zIndexDialog})`,
4100
+ display: "grid",
4101
+ placeItems: "center",
4102
+ boxSizing: "border-box",
4103
+ padding: `var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg})`,
4104
+ backgroundColor: `var(--one-color-overlay, ${ONE_THEME_DEFAULTS.colorOverlay})`
4105
+ }
4106
+ },
4107
+ {
4108
+ name: "one-dialog-backdrop-contained",
4109
+ selector: ".one-dialog__backdrop--contained",
4110
+ properties: { position: "absolute" }
4111
+ },
4112
+ {
4113
+ name: "one-dialog-panel",
4114
+ selector: ".one-dialog",
4115
+ properties: {
4116
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
4117
+ width: "min(520px, 100%)",
4118
+ maxHeight: "calc(100vh - 32px)",
4119
+ overflow: "auto",
4120
+ color: `var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText})`,
4121
+ backgroundColor: `var(--one-color-surface, ${ONE_THEME_DEFAULTS.colorSurface})`,
4122
+ border: oneThemeBorder(),
4123
+ borderRadius: `var(--one-radius-lg, ${ONE_THEME_DEFAULTS.radiusMd})`,
4124
+ boxShadow: `var(--one-shadow-overlay, ${ONE_THEME_DEFAULTS.shadowOverlay})`
4125
+ }
4126
+ },
4127
+ {
4128
+ name: "one-dialog-header",
4129
+ selector: ".one-dialog__header",
4130
+ properties: {
4131
+ padding: `var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg})`,
4132
+ fontSize: "18px",
4133
+ fontWeight: "600",
4134
+ borderBottom: oneThemeBorder()
4135
+ }
4136
+ },
4137
+ {
4138
+ name: "one-dialog-body",
4139
+ selector: ".one-dialog__body",
4140
+ properties: {
4141
+ padding: `var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg})`,
4142
+ color: `var(--one-color-muted, ${ONE_THEME_DEFAULTS.colorMuted})`
4143
+ }
4144
+ },
4145
+ {
4146
+ name: "one-dialog-footer",
4147
+ selector: ".one-dialog__footer",
4148
+ properties: {
4149
+ display: "flex",
4150
+ justifyContent: "flex-end",
4151
+ gap: `var(--one-space-sm, ${ONE_THEME_DEFAULTS.spaceSm})`,
4152
+ padding: `var(--one-space-md, ${ONE_THEME_DEFAULTS.spaceMd}) var(--one-space-lg, ${ONE_THEME_DEFAULTS.spaceLg})`,
4153
+ borderTop: oneThemeBorder()
4154
+ }
4155
+ },
4156
+ {
4157
+ name: "one-dialog-button",
4158
+ selector: ".one-dialog__cancel, .one-dialog__confirm",
4159
+ properties: {
4160
+ minHeight: "36px",
4161
+ padding: "0 14px",
4162
+ border: oneThemeBorder(),
4163
+ borderRadius: `var(--one-radius-md, ${ONE_THEME_DEFAULTS.radiusMd})`,
4164
+ cursor: "pointer"
4165
+ }
4166
+ },
4167
+ {
4168
+ name: "one-dialog-confirm",
4169
+ selector: ".one-dialog__confirm",
4170
+ properties: {
4171
+ color: "#ffffff",
4172
+ backgroundColor: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`,
4173
+ borderColor: `var(--one-color-primary, ${ONE_THEME_DEFAULTS.colorPrimary})`
4174
+ }
4175
+ }
4176
+ ];
4177
+ function hasSlot(children, name) {
4178
+ return children.some((child) => {
4179
+ if (typeof child === "string") {
4180
+ return name === "default";
4181
+ }
4182
+ return (child.slot ?? "default") === name;
4183
+ });
4184
+ }
4185
+
4186
+ class DialogOverlay extends Component19 {
4187
+ focusManager = new OneDialogFocusManager;
4188
+ releaseScrollLock;
4189
+ targetDocument;
4190
+ mount(container) {
4191
+ super.mount(container);
4192
+ const panel = this.getPanel();
4193
+ if (panel) {
4194
+ this.focusManager.activate(panel, this.props.isTop);
4195
+ }
4196
+ }
4197
+ initState() {
4198
+ return {};
4199
+ }
4200
+ initStyles() {
4201
+ ONE_DIALOG_STYLES.forEach(({ name, ...style }) => {
4202
+ this.styleManager.addStyle(name, style);
4203
+ });
4204
+ }
4205
+ onMounted() {
4206
+ const panel = this.getPanel();
4207
+ const targetDocument = panel?.ownerDocument;
4208
+ if (!panel || !targetDocument) {
4209
+ return;
4210
+ }
4211
+ this.targetDocument = targetDocument;
4212
+ if (this.props.lockBody) {
4213
+ this.releaseScrollLock = lockOneDialogBody(targetDocument);
4214
+ }
4215
+ targetDocument.addEventListener("keydown", this.handleEscape);
4216
+ }
4217
+ onUnmounted() {
4218
+ this.targetDocument?.removeEventListener("keydown", this.handleEscape);
4219
+ this.focusManager.deactivate();
4220
+ this.releaseScrollLock?.();
4221
+ this.releaseScrollLock = undefined;
4222
+ this.targetDocument = undefined;
4223
+ }
4224
+ render() {
4225
+ const children = this.props.children ?? [];
4226
+ const customHeader = hasSlot(children, "header");
4227
+ const customBody = hasSlot(children, "default");
4228
+ const customFooter = hasSlot(children, "footer");
4229
+ const titleId = `${this.props.id}-title`;
4230
+ const descriptionId = `${this.props.id}-description`;
4231
+ const hasHeader = customHeader || Boolean(this.props.title);
4232
+ const hasBody = customBody || this.props.content !== undefined || Boolean(this.props.description);
4233
+ return {
4234
+ tag: "div",
4235
+ props: {
4236
+ className: [
4237
+ "one-dialog__backdrop",
4238
+ ...!this.props.lockBody ? ["one-dialog__backdrop--contained"] : []
4239
+ ].join(" ")
4240
+ },
4241
+ children: [
4242
+ {
4243
+ tag: "section",
4244
+ props: {
4245
+ className: "one-dialog",
4246
+ role: "dialog",
4247
+ tabindex: "-1",
4248
+ "aria-modal": "true",
4249
+ "aria-labelledby": hasHeader ? titleId : undefined,
4250
+ "aria-describedby": hasBody ? descriptionId : undefined
4251
+ },
4252
+ children: [
4253
+ ...hasHeader ? [
4254
+ {
4255
+ tag: "header",
4256
+ props: { className: "one-dialog__header", id: titleId },
4257
+ children: customHeader ? [slot9("header")] : [this.props.title ?? ""]
4258
+ }
4259
+ ] : [],
4260
+ ...hasBody ? [
4261
+ {
4262
+ tag: "div",
4263
+ props: { className: "one-dialog__body", id: descriptionId },
4264
+ children: customBody ? [slot9("default")] : [this.props.content ?? this.props.description ?? ""]
4265
+ }
4266
+ ] : [],
4267
+ {
4268
+ tag: "footer",
4269
+ props: { className: "one-dialog__footer" },
4270
+ children: customFooter ? [slot9("footer")] : [
4271
+ {
4272
+ tag: "button",
4273
+ props: {
4274
+ type: "button",
4275
+ className: "one-dialog__cancel",
4276
+ disabled: this.props.confirmLoading === true
4277
+ },
4278
+ children: [this.props.cancelText ?? "取消"],
4279
+ listeners: {
4280
+ click: () => this.requestClose("cancel")
4281
+ }
4282
+ },
4283
+ {
4284
+ tag: "button",
4285
+ props: {
4286
+ type: "button",
4287
+ className: "one-dialog__confirm",
4288
+ disabled: this.props.confirmLoading === true,
4289
+ "aria-busy": this.props.confirmLoading ? "true" : undefined
4290
+ },
4291
+ children: [
4292
+ this.props.confirmLoading ? "处理中…" : this.props.confirmText ?? "确认"
4293
+ ],
4294
+ listeners: {
4295
+ click: () => this.requestClose("confirm")
4296
+ }
4297
+ }
4298
+ ]
4299
+ }
4300
+ ]
4301
+ }
4302
+ ],
4303
+ listeners: {
4304
+ click: (event) => {
4305
+ if (event.target === event.currentTarget) {
4306
+ this.requestClose("overlay");
4307
+ }
4308
+ }
4309
+ }
4310
+ };
4311
+ }
4312
+ handleEscape = (event) => {
4313
+ if (event.key === "Escape") {
4314
+ this.requestClose("escape");
4315
+ }
4316
+ };
4317
+ requestClose(reason) {
4318
+ if (!this.props.isTop() || this.props.confirmLoading) {
4319
+ return;
4320
+ }
4321
+ if (reason === "overlay" && this.props.closeOnOverlay === false) {
4322
+ return;
4323
+ }
4324
+ if (reason === "escape" && this.props.closeOnEscape === false) {
4325
+ return;
4326
+ }
4327
+ this.props.requestClose(reason);
4328
+ }
4329
+ getPanel() {
4330
+ const element = this.getElement();
4331
+ return element instanceof HTMLElement ? element.querySelector(".one-dialog") : null;
4332
+ }
4333
+ }
4334
+ // lib/dialog/OneDialog.ts
4335
+ import { Component as Component20 } from "@geektech/tsone";
4336
+ class OneDialog extends Component20 {
4337
+ controller;
4338
+ lockBody = true;
4339
+ viewMounted = false;
4340
+ initState() {
4341
+ return { internalOpen: this.props.defaultOpen === true };
4342
+ }
4343
+ initStyles() {}
4344
+ onMounted() {
4345
+ this.controller = new OneOverlayMountController(getDefaultOneOverlayHost(), "dialog", (context) => this.createOverlay(context));
4346
+ this.synchronizeOverlay();
4347
+ }
4348
+ beforeUpdate() {
4349
+ this.synchronizeOverlay();
4350
+ }
4351
+ beforeUnmount() {
4352
+ this.controller?.close();
4353
+ this.controller = undefined;
4354
+ }
4355
+ render() {
4356
+ return {
4357
+ tag: "span",
4358
+ props: { hidden: true, "data-one-dialog-anchor": "" }
4359
+ };
4360
+ }
4361
+ createOverlay(context) {
4362
+ const overlay = new DialogOverlay({
4363
+ ...this.props,
4364
+ id: context.id,
4365
+ lockBody: this.lockBody,
4366
+ isTop: context.isTop,
4367
+ requestClose: (reason) => this.requestClose(reason)
4368
+ });
4369
+ overlay.mount(context.slot);
4370
+ this.viewMounted = true;
4371
+ return {
4372
+ update: (next) => overlay.setProps(next),
4373
+ destroy: () => {
4374
+ overlay.unmount();
4375
+ if (this.viewMounted) {
4376
+ this.viewMounted = false;
4377
+ this.emit("afterClose");
4378
+ }
4379
+ }
4380
+ };
4381
+ }
4382
+ synchronizeOverlay() {
4383
+ if (!this.controller) {
4384
+ return;
4385
+ }
4386
+ const open = this.props.open === undefined ? this.state.internalOpen : this.props.open === true;
4387
+ if (!open) {
4388
+ this.controller.close();
4389
+ return;
4390
+ }
4391
+ const resolved = resolveOneOverlayContainer(this.props.container);
4392
+ this.lockBody = resolved === resolved.ownerDocument.body;
4393
+ this.controller.open(resolved);
4394
+ this.controller.update(this.props);
4395
+ }
4396
+ requestClose(reason) {
4397
+ if (reason === "confirm") {
4398
+ this.emit("confirm");
4399
+ } else {
4400
+ this.emit("cancel", reason);
4401
+ }
4402
+ this.emit("openChange", false);
4403
+ if (this.props.open !== undefined) {
4404
+ return;
4405
+ }
4406
+ this.state.internalOpen = false;
4407
+ this.controller?.close();
4408
+ }
4409
+ }
4410
+ // lib/dialog/service.ts
4411
+ class OneDialogService {
4412
+ suppliedHost;
4413
+ constructor(suppliedHost) {
4414
+ this.suppliedHost = suppliedHost;
4415
+ }
4416
+ open(options) {
4417
+ return this.openInternal(options);
4418
+ }
4419
+ confirm(options) {
4420
+ return new Promise((resolve) => {
4421
+ this.openInternal(options, resolve);
4422
+ });
4423
+ }
4424
+ close(id) {
4425
+ (this.suppliedHost ?? getDefaultOneOverlayHost()).close(id);
4426
+ }
4427
+ closeAll() {
4428
+ (this.suppliedHost ?? getDefaultOneOverlayHost()).closeAll("dialog");
4429
+ }
4430
+ openInternal(options, settle) {
4431
+ const host = this.suppliedHost ?? getDefaultOneOverlayHost();
4432
+ let current = { ...options };
4433
+ let pending = false;
4434
+ let settled = false;
4435
+ const hostHandle = host.open({
4436
+ kind: "dialog",
4437
+ container: current.container,
4438
+ factory: ({ id, slot: slot10, requestClose, isTop }) => {
4439
+ const hostContainer = slot10.parentElement?.parentElement;
4440
+ const overlay = new DialogOverlay({
4441
+ ...current,
4442
+ id,
4443
+ lockBody: hostContainer === slot10.ownerDocument.body,
4444
+ isTop,
4445
+ requestClose: (reason) => {
4446
+ handleClose(reason);
4447
+ }
4448
+ });
4449
+ const updateOverlay = () => {
4450
+ overlay.setProps({
4451
+ ...current,
4452
+ confirmLoading: pending || current.confirmLoading === true
4453
+ });
4454
+ };
4455
+ const finish = (result) => {
4456
+ if (settled) {
4457
+ return;
4458
+ }
4459
+ settled = true;
4460
+ requestClose();
4461
+ settle?.(result);
4462
+ };
4463
+ const handleClose = async (reason) => {
4464
+ if (settled || pending) {
4465
+ return;
4466
+ }
4467
+ if (reason !== "confirm") {
4468
+ try {
4469
+ current.onCancel?.();
4470
+ } catch (error) {
4471
+ current.onError?.(error);
4472
+ }
4473
+ if (settle) {
4474
+ finish(false);
4475
+ } else {
4476
+ requestClose();
4477
+ }
4478
+ return;
4479
+ }
4480
+ pending = true;
4481
+ updateOverlay();
4482
+ try {
4483
+ const result = await current.onConfirm?.();
4484
+ if (result === false) {
4485
+ pending = false;
4486
+ updateOverlay();
4487
+ return;
4488
+ }
4489
+ if (settle) {
4490
+ finish(true);
4491
+ } else {
4492
+ requestClose();
4493
+ }
4494
+ } catch (error) {
4495
+ pending = false;
4496
+ updateOverlay();
4497
+ current.onError?.(error);
4498
+ }
4499
+ };
4500
+ overlay.mount(slot10);
4501
+ return {
4502
+ update: (next) => {
4503
+ current = { ...current, ...next };
4504
+ updateOverlay();
4505
+ },
4506
+ destroy: () => {
4507
+ overlay.unmount();
4508
+ if (settle && !settled) {
4509
+ settled = true;
4510
+ settle(false);
4511
+ }
4512
+ }
4513
+ };
4514
+ }
4515
+ });
4516
+ return {
4517
+ id: hostHandle.id,
4518
+ update: (next) => hostHandle.update(next),
4519
+ close: () => hostHandle.close()
4520
+ };
4521
+ }
4522
+ }
4523
+ function createOneDialogService(host) {
4524
+ return new OneDialogService(host);
4525
+ }
4526
+ var oneDialog = createOneDialogService();
4527
+ // lib/tooltip/OneTooltip.ts
4528
+ import { Component as Component22 } from "@geektech/tsone";
4529
+
4530
+ // lib/tooltip/TooltipBubble.ts
4531
+ import { Component as Component21 } from "@geektech/tsone";
4532
+ var ONE_TOOLTIP_STYLES = [
4533
+ {
4534
+ name: "one-tooltip-bubble",
4535
+ selector: ".one-tooltip__bubble",
4536
+ properties: {
4537
+ ...ONE_THEME_TYPOGRAPHY_PROPERTIES,
4538
+ position: "fixed",
4539
+ zIndex: `var(--one-z-index-tooltip, ${ONE_THEME_DEFAULTS.zIndexTooltip})`,
4540
+ boxSizing: "border-box",
4541
+ maxWidth: "280px",
4542
+ padding: `var(--one-space-sm, ${ONE_THEME_DEFAULTS.spaceSm}) var(--one-space-md, ${ONE_THEME_DEFAULTS.spaceMd})`,
4543
+ color: "#ffffff",
4544
+ fontSize: `var(--one-font-size-sm, ${ONE_THEME_DEFAULTS.fontSizeSm})`,
4545
+ backgroundColor: `var(--one-tooltip-background, var(--one-color-text, ${ONE_THEME_DEFAULTS.colorText}))`,
4546
+ borderRadius: `var(--one-radius-sm, ${ONE_THEME_DEFAULTS.radiusSm})`,
4547
+ boxShadow: `var(--one-shadow-overlay, ${ONE_THEME_DEFAULTS.shadowOverlay})`,
4548
+ pointerEvents: "none"
4549
+ }
4550
+ },
4551
+ {
4552
+ name: "one-tooltip-bubble-contained",
4553
+ selector: ".one-tooltip__bubble--contained",
4554
+ properties: { position: "absolute" }
4555
+ },
4556
+ {
4557
+ name: "one-tooltip-arrow",
4558
+ selector: ".one-tooltip__arrow",
4559
+ properties: {
4560
+ position: "absolute",
4561
+ width: "8px",
4562
+ height: "8px",
4563
+ backgroundColor: "inherit",
4564
+ transform: "rotate(45deg)"
4565
+ }
4566
+ },
4567
+ {
4568
+ name: "one-tooltip-arrow-vertical",
4569
+ selector: '.one-tooltip__bubble[data-placement^="top"] .one-tooltip__arrow, .one-tooltip__bubble[data-placement^="bottom"] .one-tooltip__arrow',
4570
+ properties: {
4571
+ left: "var(--one-tooltip-arrow-x, 50%)",
4572
+ marginLeft: "-4px"
4573
+ }
4574
+ },
4575
+ {
4576
+ name: "one-tooltip-arrow-horizontal",
4577
+ selector: '.one-tooltip__bubble[data-placement^="left"] .one-tooltip__arrow, .one-tooltip__bubble[data-placement^="right"] .one-tooltip__arrow',
4578
+ properties: {
4579
+ top: "var(--one-tooltip-arrow-y, 50%)",
4580
+ marginTop: "-4px"
4581
+ }
4582
+ },
4583
+ {
4584
+ name: "one-tooltip-arrow-top",
4585
+ selector: '.one-tooltip__bubble[data-placement^="top"] .one-tooltip__arrow',
4586
+ properties: { bottom: "-4px" }
4587
+ },
4588
+ {
4589
+ name: "one-tooltip-arrow-bottom",
4590
+ selector: '.one-tooltip__bubble[data-placement^="bottom"] .one-tooltip__arrow',
4591
+ properties: { top: "-4px" }
4592
+ },
4593
+ {
4594
+ name: "one-tooltip-arrow-left",
4595
+ selector: '.one-tooltip__bubble[data-placement^="left"] .one-tooltip__arrow',
4596
+ properties: { right: "-4px" }
4597
+ },
4598
+ {
4599
+ name: "one-tooltip-arrow-right",
4600
+ selector: '.one-tooltip__bubble[data-placement^="right"] .one-tooltip__arrow',
4601
+ properties: { left: "-4px" }
4602
+ }
4603
+ ];
4604
+
4605
+ class TooltipBubble extends Component21 {
4606
+ stopAutoUpdate;
4607
+ mount(container) {
4608
+ super.mount(container);
4609
+ this.updatePosition();
4610
+ const element = this.getElement();
4611
+ if (element instanceof HTMLElement) {
4612
+ this.stopAutoUpdate = this.props.positioner.autoUpdate(this.props.reference, element, () => this.updatePosition());
4613
+ }
4614
+ }
4615
+ setProps(props) {
4616
+ super.setProps(props);
4617
+ this.updatePosition();
4618
+ }
4619
+ initState() {
4620
+ return {};
4621
+ }
4622
+ initStyles() {
4623
+ ONE_TOOLTIP_STYLES.forEach(({ name, ...style }) => {
4624
+ this.styleManager.addStyle(name, style);
4625
+ });
4626
+ }
4627
+ onUnmounted() {
4628
+ this.stopAutoUpdate?.();
4629
+ this.stopAutoUpdate = undefined;
4630
+ }
4631
+ render() {
4632
+ const contained = this.props.container !== this.props.container.ownerDocument.body;
4633
+ return {
4634
+ tag: "div",
4635
+ props: {
4636
+ id: this.props.id,
4637
+ className: [
4638
+ "one-tooltip__bubble",
4639
+ ...contained ? ["one-tooltip__bubble--contained"] : []
4640
+ ].join(" "),
4641
+ role: "tooltip",
4642
+ "data-placement": this.props.placement
4643
+ },
4644
+ children: [
4645
+ this.props.content,
4646
+ ...this.props.arrow ? [
4647
+ {
4648
+ tag: "span",
4649
+ props: {
4650
+ className: "one-tooltip__arrow",
4651
+ "aria-hidden": "true"
4652
+ }
4653
+ }
4654
+ ] : []
4655
+ ]
4656
+ };
4657
+ }
4658
+ updatePosition() {
4659
+ const element = this.getElement();
4660
+ if (!(element instanceof HTMLElement) || !element.isConnected) {
4661
+ return;
4662
+ }
4663
+ const boundary = this.boundaryRect();
4664
+ const result = this.props.positioner.compute({
4665
+ reference: toOverlayRect(this.props.reference.getBoundingClientRect()),
4666
+ floating: toOverlayRect(element.getBoundingClientRect()),
4667
+ boundary,
4668
+ placement: this.props.placement,
4669
+ offset: this.props.offset,
4670
+ padding: this.props.boundaryPadding
4671
+ });
4672
+ const contained = this.props.container !== this.props.container.ownerDocument.body;
4673
+ element.style.left = `${result.x - (contained ? boundary.left : 0)}px`;
4674
+ element.style.top = `${result.y - (contained ? boundary.top : 0)}px`;
4675
+ element.dataset.placement = result.placement;
4676
+ element.style.removeProperty("--one-tooltip-arrow-x");
4677
+ element.style.removeProperty("--one-tooltip-arrow-y");
4678
+ if (result.arrow.x !== undefined) {
4679
+ element.style.setProperty("--one-tooltip-arrow-x", `${result.arrow.x}px`);
4680
+ }
4681
+ if (result.arrow.y !== undefined) {
4682
+ element.style.setProperty("--one-tooltip-arrow-y", `${result.arrow.y}px`);
4683
+ }
4684
+ }
4685
+ boundaryRect() {
4686
+ const targetDocument = this.props.container.ownerDocument;
4687
+ if (this.props.container !== targetDocument.body) {
4688
+ return toOverlayRect(this.props.container.getBoundingClientRect());
4689
+ }
4690
+ const view = targetDocument.defaultView;
4691
+ const width = view?.innerWidth ?? targetDocument.documentElement.clientWidth;
4692
+ const height = view?.innerHeight ?? targetDocument.documentElement.clientHeight;
4693
+ return {
4694
+ x: 0,
4695
+ y: 0,
4696
+ top: 0,
4697
+ left: 0,
4698
+ width,
4699
+ height,
4700
+ right: width,
4701
+ bottom: height
4702
+ };
4703
+ }
4704
+ }
4705
+ function toOverlayRect(rect) {
4706
+ return {
4707
+ x: rect.x,
4708
+ y: rect.y,
4709
+ width: rect.width,
4710
+ height: rect.height,
4711
+ top: rect.top,
4712
+ right: rect.right,
4713
+ bottom: rect.bottom,
4714
+ left: rect.left
4715
+ };
4716
+ }
4717
+
4718
+ // lib/tooltip/OneTooltip.ts
4719
+ var PLACEMENTS2 = [
4720
+ "top-start",
4721
+ "top",
4722
+ "top-end",
4723
+ "right-start",
4724
+ "right",
4725
+ "right-end",
4726
+ "bottom-start",
4727
+ "bottom",
4728
+ "bottom-end",
4729
+ "left-start",
4730
+ "left",
4731
+ "left-end"
4732
+ ];
4733
+ var TRIGGERS = [
4734
+ "hover-focus",
4735
+ "click",
4736
+ "manual"
4737
+ ];
4738
+
4739
+ class OneTooltip extends Component22 {
4740
+ positioner = new OneFloatingPositioner;
4741
+ controller;
4742
+ triggerElement;
4743
+ targetDocument;
4744
+ previousDescribedBy = null;
4745
+ describedBySaved = false;
4746
+ tooltipId;
4747
+ hovered = false;
4748
+ focused = false;
4749
+ openTimer;
4750
+ closeTimer;
4751
+ initState() {
4752
+ return { internalOpen: this.props.defaultOpen === true };
4753
+ }
4754
+ initStyles() {}
4755
+ onMounted() {
4756
+ const wrapper = this.getElement();
4757
+ const trigger = wrapper instanceof HTMLElement ? wrapper.firstElementChild : null;
4758
+ if (!(trigger instanceof HTMLElement)) {
4759
+ throw new OneTooltipTriggerError;
4760
+ }
4761
+ this.triggerElement = trigger;
4762
+ this.targetDocument = trigger.ownerDocument;
4763
+ this.targetDocument.addEventListener("click", this.handleDocumentClick);
4764
+ this.targetDocument.addEventListener("keydown", this.handleDocumentKeydown);
4765
+ this.controller = new OneOverlayMountController(getDefaultOneOverlayHost(this.targetDocument), "tooltip", (context) => this.createBubble(context));
4766
+ this.synchronizeOverlay();
4767
+ }
4768
+ beforeUpdate() {
4769
+ this.synchronizeOverlay();
4770
+ }
4771
+ beforeUnmount() {
4772
+ this.clearTimers();
4773
+ this.targetDocument?.removeEventListener("click", this.handleDocumentClick);
4774
+ this.targetDocument?.removeEventListener("keydown", this.handleDocumentKeydown);
4775
+ this.controller?.close();
4776
+ this.restoreDescribedBy();
4777
+ this.controller = undefined;
4778
+ this.triggerElement = undefined;
4779
+ this.targetDocument = undefined;
4780
+ }
4781
+ render() {
4782
+ return {
4783
+ tag: "span",
4784
+ props: { className: "one-tooltip__trigger" },
4785
+ children: defaultChildren(this.props.children ?? []),
4786
+ listeners: {
4787
+ mouseenter: () => this.handleMouseEnter(),
4788
+ mouseleave: () => this.handleMouseLeave(),
4789
+ focusin: () => this.handleFocusIn(),
4790
+ focusout: (event) => this.handleFocusOut(event),
4791
+ click: () => this.handleTriggerClick()
4792
+ }
4793
+ };
4794
+ }
4795
+ createBubble(context) {
4796
+ this.tooltipId = context.id;
4797
+ const options = this.bubbleOptions(context.id);
4798
+ this.applyDescribedBy(context.id);
4799
+ const bubble = new TooltipBubble(options);
4800
+ bubble.mount(context.slot);
4801
+ return {
4802
+ update: (next) => bubble.setProps(next),
4803
+ destroy: () => {
4804
+ bubble.unmount();
4805
+ this.restoreDescribedBy();
4806
+ this.tooltipId = undefined;
4807
+ }
4808
+ };
4809
+ }
4810
+ synchronizeOverlay() {
4811
+ if (!this.controller || !this.triggerElement || !this.targetDocument) {
4812
+ return;
4813
+ }
4814
+ const shouldOpen = !this.props.disabled && this.requestedOpen();
4815
+ if (!shouldOpen) {
4816
+ this.controller.close();
4817
+ return;
4818
+ }
4819
+ const container = resolveOneOverlayContainer(this.props.container, this.targetDocument);
4820
+ this.controller.open(container);
4821
+ this.controller.update(this.bubbleOptions());
4822
+ }
4823
+ bubbleOptions(id = this.tooltipId ?? "") {
4824
+ const targetDocument = this.targetDocument;
4825
+ if (!this.triggerElement || !targetDocument) {
4826
+ throw new OneTooltipTriggerError;
4827
+ }
4828
+ return {
4829
+ id,
4830
+ content: this.props.content,
4831
+ reference: this.triggerElement,
4832
+ placement: normalizePlacement(this.props.placement),
4833
+ offset: normalizeDelay(this.props.offset, 8),
4834
+ boundaryPadding: 8,
4835
+ arrow: this.props.arrow !== false,
4836
+ container: resolveOneOverlayContainer(this.props.container, targetDocument),
4837
+ positioner: this.positioner
4838
+ };
4839
+ }
4840
+ requestedOpen() {
4841
+ return this.props.open === undefined ? this.state.internalOpen : this.props.open === true;
4842
+ }
4843
+ requestOpen(open) {
4844
+ if (this.props.disabled || open === this.requestedOpen()) {
4845
+ return;
4846
+ }
4847
+ this.emit("openChange", open);
4848
+ if (this.props.open !== undefined) {
4849
+ return;
4850
+ }
4851
+ this.state.internalOpen = open;
4852
+ this.synchronizeOverlay();
4853
+ }
4854
+ handleMouseEnter() {
4855
+ if (this.normalizedTrigger() !== "hover-focus") {
4856
+ return;
4857
+ }
4858
+ this.hovered = true;
4859
+ this.cancelCloseTimer();
4860
+ this.scheduleOpen();
4861
+ }
4862
+ handleMouseLeave() {
4863
+ if (this.normalizedTrigger() !== "hover-focus") {
4864
+ return;
4865
+ }
4866
+ this.hovered = false;
4867
+ if (!this.focused) {
4868
+ this.scheduleClose();
4869
+ }
4870
+ }
4871
+ handleFocusIn() {
4872
+ if (this.normalizedTrigger() !== "hover-focus") {
4873
+ return;
4874
+ }
4875
+ this.focused = true;
4876
+ this.cancelCloseTimer();
4877
+ this.scheduleOpen();
4878
+ }
4879
+ handleFocusOut(event) {
4880
+ if (this.normalizedTrigger() !== "hover-focus") {
4881
+ return;
4882
+ }
4883
+ const wrapper = this.getElement();
4884
+ const next = event.relatedTarget;
4885
+ if (wrapper instanceof HTMLElement && next instanceof Node) {
4886
+ if (wrapper.contains(next)) {
4887
+ return;
4888
+ }
4889
+ }
4890
+ this.focused = false;
4891
+ if (!this.hovered) {
4892
+ this.scheduleClose();
4893
+ }
4894
+ }
4895
+ handleTriggerClick() {
4896
+ if (this.normalizedTrigger() === "click") {
4897
+ this.requestOpen(!this.requestedOpen());
4898
+ }
4899
+ }
4900
+ handleDocumentClick = (event) => {
4901
+ if (this.normalizedTrigger() !== "click" || !this.requestedOpen() || event.target instanceof Node && this.getElement()?.contains(event.target)) {
4902
+ return;
4903
+ }
4904
+ this.requestOpen(false);
4905
+ };
4906
+ handleDocumentKeydown = (event) => {
4907
+ if (event.key === "Escape" && this.requestedOpen()) {
4908
+ this.requestOpen(false);
4909
+ }
4910
+ };
4911
+ scheduleOpen() {
4912
+ this.cancelCloseTimer();
4913
+ if (this.openTimer !== undefined || this.requestedOpen()) {
4914
+ return;
4915
+ }
4916
+ const delay = normalizeDelay(this.props.openDelay, 100);
4917
+ if (delay === 0) {
4918
+ this.requestOpen(true);
4919
+ return;
4920
+ }
4921
+ this.openTimer = this.targetDocument?.defaultView?.setTimeout(() => {
4922
+ this.openTimer = undefined;
4923
+ if (this.hovered || this.focused) {
4924
+ this.requestOpen(true);
4925
+ }
4926
+ }, delay);
4927
+ }
4928
+ scheduleClose() {
4929
+ this.cancelOpenTimer();
4930
+ if (this.closeTimer !== undefined || !this.requestedOpen()) {
4931
+ return;
4932
+ }
4933
+ const delay = normalizeDelay(this.props.closeDelay, 100);
4934
+ if (delay === 0) {
4935
+ this.requestOpen(false);
4936
+ return;
4937
+ }
4938
+ this.closeTimer = this.targetDocument?.defaultView?.setTimeout(() => {
4939
+ this.closeTimer = undefined;
4940
+ if (!this.hovered && !this.focused) {
4941
+ this.requestOpen(false);
4942
+ }
4943
+ }, delay);
4944
+ }
4945
+ clearTimers() {
4946
+ this.cancelOpenTimer();
4947
+ this.cancelCloseTimer();
4948
+ }
4949
+ cancelOpenTimer() {
4950
+ if (this.openTimer !== undefined) {
4951
+ this.targetDocument?.defaultView?.clearTimeout(this.openTimer);
4952
+ this.openTimer = undefined;
4953
+ }
4954
+ }
4955
+ cancelCloseTimer() {
4956
+ if (this.closeTimer !== undefined) {
4957
+ this.targetDocument?.defaultView?.clearTimeout(this.closeTimer);
4958
+ this.closeTimer = undefined;
4959
+ }
4960
+ }
4961
+ applyDescribedBy(id) {
4962
+ if (!this.triggerElement) {
4963
+ return;
4964
+ }
4965
+ if (!this.describedBySaved) {
4966
+ this.previousDescribedBy = this.triggerElement.getAttribute("aria-describedby");
4967
+ this.describedBySaved = true;
4968
+ }
4969
+ const tokens = (this.previousDescribedBy ?? "").split(/\s+/).filter(Boolean);
4970
+ if (!tokens.includes(id)) {
4971
+ tokens.push(id);
4972
+ }
4973
+ this.triggerElement.setAttribute("aria-describedby", tokens.join(" "));
4974
+ }
4975
+ restoreDescribedBy() {
4976
+ if (!this.triggerElement || !this.describedBySaved) {
4977
+ return;
4978
+ }
4979
+ if (this.previousDescribedBy === null) {
4980
+ this.triggerElement.removeAttribute("aria-describedby");
4981
+ } else {
4982
+ this.triggerElement.setAttribute("aria-describedby", this.previousDescribedBy);
4983
+ }
4984
+ this.previousDescribedBy = null;
4985
+ this.describedBySaved = false;
4986
+ }
4987
+ normalizedTrigger() {
4988
+ return TRIGGERS.includes(this.props.trigger) ? this.props.trigger : "hover-focus";
4989
+ }
4990
+ }
4991
+ function normalizePlacement(value) {
4992
+ return PLACEMENTS2.includes(value) ? value : "top";
4993
+ }
4994
+ function defaultChildren(children) {
4995
+ const result = [];
4996
+ children.forEach((child) => {
4997
+ if (typeof child === "string") {
4998
+ result.push(child);
4999
+ return;
5000
+ }
5001
+ if (child.slot !== undefined && child.slot !== "default") {
5002
+ return;
5003
+ }
5004
+ const normalized = { ...child };
5005
+ delete normalized.slot;
5006
+ result.push(normalized);
5007
+ });
5008
+ return result;
5009
+ }
5010
+ function normalizeDelay(value, fallback) {
5011
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : fallback;
1454
5012
  }
1455
5013
  // lib/index.ts
1456
5014
  var ONE_NAME = "@geektech/one";
1457
5015
  var ONE_VERSION = "0.0.1";
1458
5016
  export {
5017
+ oneTheme,
5018
+ oneMessage,
5019
+ oneDialog,
5020
+ createOnePaginationTokens,
5021
+ createOneMessageService,
5022
+ createOneDialogService,
5023
+ OneTooltipTriggerError,
5024
+ OneTooltip,
5025
+ OneThemeNotFoundError,
5026
+ OneThemeEnvironmentError,
5027
+ OneThemeConfigError,
5028
+ OneTag,
5029
+ OneTabs,
1459
5030
  OneSwitch,
1460
5031
  OneSelect,
5032
+ OnePagination,
5033
+ OneOverlayEnvironmentError,
5034
+ OneOverlayContainerError,
5035
+ OneMessageService,
5036
+ OneMessage,
1461
5037
  OneInput,
1462
5038
  OneFormModel,
1463
5039
  OneFormItem,
1464
5040
  OneForm,
5041
+ OneFloatingPositioner,
5042
+ OneEmpty,
5043
+ OneDialogService,
5044
+ OneDialog,
1465
5045
  OneCheckboxGroup,
1466
5046
  OneCheckbox,
1467
5047
  OneCard,
1468
5048
  OneButton,
5049
+ OneBreadcrumb,
5050
+ OneBadge,
5051
+ OneAlert,
1469
5052
  ONE_VERSION,
1470
5053
  ONE_THEME_DEFAULTS,
1471
5054
  ONE_NAME,
1472
- ONE_COMPONENT_CATEGORIES
5055
+ ONE_DEFAULT_THEME,
5056
+ ONE_COMPONENT_CATEGORIES,
5057
+ DomOneOverlayHost
1473
5058
  };
1474
5059
 
1475
- //# debugId=789C7C07D840D57764756E2164756E21
5060
+ //# debugId=8EB578A618FDC3A064756E2164756E21
1476
5061
  //# sourceMappingURL=index.js.map