sellmate-design-system-react 9.0.0-beta.75 → 9.0.0-beta.76

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 (36) hide show
  1. package/AGENTS.md +35 -0
  2. package/README.md +5 -5
  3. package/bin/sellmate-ds.mjs +91 -59
  4. package/dist/components/SCircleProgress/README.md +6 -3
  5. package/dist/components/SCircleProgress/SCircleProgress.d.ts +11 -3
  6. package/dist/components/SLinearProgress/README.md +2 -2
  7. package/dist/components/SLinearProgress/SLinearProgress.d.ts +8 -2
  8. package/dist/components/SSelect/README.md +18 -2
  9. package/dist/components/SSelect/SSelect.d.ts +28 -5
  10. package/dist/components/SSelect/index.d.ts +1 -1
  11. package/dist/components/STable/README.md +29 -20
  12. package/dist/components/STable/STable.d.ts +47 -31
  13. package/dist/components/STable/index.d.ts +1 -1
  14. package/dist/index.cjs +107 -50
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.js +107 -50
  17. package/dist/index.js.map +1 -1
  18. package/dist/llms-full.txt +90 -28
  19. package/dist/llms.txt +37 -1
  20. package/dist/styles.css +16 -0
  21. package/dist/theme.css +3 -0
  22. package/eslint/index.mjs +42 -42
  23. package/eslint/lib/class-names.mjs +23 -25
  24. package/eslint/lib/table-column.mjs +11 -11
  25. package/eslint/rules/component-group-gap.mjs +32 -30
  26. package/eslint/rules/divider-vertical-height.mjs +22 -22
  27. package/eslint/rules/field-width-grade.mjs +50 -50
  28. package/eslint/rules/no-arbitrary-class.mjs +63 -20
  29. package/eslint/rules/no-off-scale-spacing.mjs +61 -41
  30. package/eslint/rules/no-raw-html-control.mjs +38 -36
  31. package/eslint/rules/prefer-typo-preset.mjs +23 -17
  32. package/eslint/rules/require-locale-number.mjs +14 -19
  33. package/eslint/rules/table-column-width.mjs +21 -17
  34. package/eslint/rules/table-numeric-align.mjs +14 -14
  35. package/eslint/scale.gen.mjs +1 -1
  36. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -3764,43 +3764,46 @@ var STROKE = 12;
3764
3764
  var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
3765
3765
  var COLOR_MAP = {
3766
3766
  primary: { arc: "var(--cmp-progress-color-active)", track: "var(--cmp-progress-color-track)" },
3767
- // inverse: 어두운 배경용 — arc 흰색, track 은 흰색 40%(회색 링)
3768
- inverse: { arc: "var(--color-white)", track: "rgba(255,255,255,0.4)" },
3769
- error: { arc: "var(--color-red-75)", track: "var(--cmp-progress-color-track)" },
3770
- complete: { arc: "#01BB4B", track: "var(--cmp-progress-color-track)" },
3767
+ // inverse: 어두운 배경용 — arc 는 반전색, track 은 반전색을 inverse-opacity 만큼만(회색 링)
3768
+ inverse: {
3769
+ arc: "var(--cmp-progress-inverse-color)",
3770
+ track: "color-mix(in srgb, var(--cmp-progress-inverse-color) var(--cmp-progress-inverse-opacity), transparent)"
3771
+ },
3772
+ warning: { arc: "var(--cmp-progress-color-warning)", track: "var(--cmp-progress-color-track)" },
3773
+ error: { arc: "var(--cmp-progress-color-error)", track: "var(--cmp-progress-color-track)" },
3774
+ complete: { arc: "var(--cmp-progress-color-success)", track: "var(--cmp-progress-color-track)" },
3771
3775
  // neutral: 콘텐츠가 아직 없는 자리를 채우는 용도 — arc 도 회색이라 진행률보다 "대기"로 읽힌다
3772
- neutral: { arc: "var(--color-grey-35)", track: "var(--cmp-progress-color-track)" }
3776
+ neutral: { arc: "var(--cmp-progress-color-neutral)", track: "var(--cmp-progress-color-track)" }
3773
3777
  };
3774
- var DEFAULT_SIZE = 80;
3775
3778
  var clamp = (v) => Number.isFinite(v) ? Math.max(0, Math.min(100, v)) : 0;
3776
3779
  var SCircleProgress = /* @__PURE__ */ forwardRef(
3777
3780
  function SCircleProgress2({
3778
3781
  value = 0,
3779
3782
  type = "primary",
3780
3783
  indeterminate = false,
3781
- size = DEFAULT_SIZE,
3784
+ size,
3782
3785
  label,
3783
3786
  innerValue = false,
3784
3787
  className,
3785
3788
  style
3786
3789
  }, ref) {
3787
3790
  const v = clamp(value);
3788
- const dimension = typeof size === "number" ? `${size}px` : size;
3791
+ const dimension = size === void 0 ? "var(--cmp-progress-circular-size)" : typeof size === "number" ? `${size}px` : size;
3789
3792
  const colors = COLOR_MAP[type];
3790
3793
  const c = VIEWBOX / 2;
3791
- const percentColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : colors.arc;
3794
+ const percentColor = v === 0 ? "var(--sys-color-fg-tertiary)" : colors.arc;
3792
3795
  const filled = v / 100 * CIRCUMFERENCE;
3793
3796
  const showPercent = !indeterminate;
3794
3797
  const percentNode = /* @__PURE__ */ jsxs(
3795
3798
  "span",
3796
3799
  {
3797
3800
  className: cn(
3798
- "text-center text-[16px] font-bold",
3801
+ "typo-heading-md text-center",
3799
3802
  innerValue ? (
3800
3803
  // leading-[normal]: 26px leading 은 폰트 content(19px) 위아래로 홀수(7px)만큼 남아
3801
3804
  // 3px/4px 로 쪼개지고 글자가 링 중심보다 위로 뜬다. (leading-normal 은 1.5 라 동일 문제)
3802
3805
  "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 leading-[normal]"
3803
- ) : "leading-[26px]"
3806
+ ) : void 0
3804
3807
  ),
3805
3808
  style: { color: percentColor },
3806
3809
  children: [
@@ -3866,7 +3869,7 @@ var SCircleProgress = /* @__PURE__ */ forwardRef(
3866
3869
  showPercent && innerValue && percentNode
3867
3870
  ] }),
3868
3871
  showPercent && !innerValue && percentNode,
3869
- label && /* @__PURE__ */ jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
3872
+ label && /* @__PURE__ */ jsx("span", { className: "typo-feedback-sm-regular text-center text-[color:var(--cmp-progress-color-label)]", children: label })
3870
3873
  ]
3871
3874
  }
3872
3875
  );
@@ -7603,6 +7606,10 @@ function TreeBranch({ expanded, children }) {
7603
7606
  }
7604
7607
  );
7605
7608
  }
7609
+ function isRowControlClick(event) {
7610
+ const control = event.target.closest("[data-tree-control]");
7611
+ return control != null && event.currentTarget.contains(control);
7612
+ }
7606
7613
  function STreeAllItem({
7607
7614
  selected,
7608
7615
  indeterminate,
@@ -7625,14 +7632,16 @@ function STreeAllItem({
7625
7632
  "data-tree-row": rowId,
7626
7633
  tabIndex,
7627
7634
  onKeyDown,
7628
- onClick: onSelect,
7635
+ onClick: (event) => {
7636
+ if (!isRowControlClick(event)) onSelect(event);
7637
+ },
7629
7638
  className: cn(
7630
7639
  "group/tree-item box-border flex w-full cursor-pointer items-center overflow-hidden bg-(--cmp-tree-item-bg-default) px-(--cmp-tree-item-paddingX) text-left hover:bg-(--cmp-tree-item-bg-hover)",
7631
7640
  typography.rowHeight,
7632
7641
  border && "border-b border-(--cmp-tree-item-border-default)"
7633
7642
  ),
7634
7643
  children: /* @__PURE__ */ jsxs("div", { className: "box-border flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)", children: [
7635
- /* @__PURE__ */ jsx("span", { onClick: (event) => event.stopPropagation(), className: "flex shrink-0", children: /* @__PURE__ */ jsx(SCheckbox, { value: checkboxValue, onValueChange: () => onSelect() }) }),
7644
+ /* @__PURE__ */ jsx("span", { "data-tree-control": true, className: "flex shrink-0", children: /* @__PURE__ */ jsx(SCheckbox, { value: checkboxValue, onValueChange: () => onSelect() }) }),
7636
7645
  /* @__PURE__ */ jsx(
7637
7646
  "span",
7638
7647
  {
@@ -7663,6 +7672,10 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
7663
7672
  trailing,
7664
7673
  onToggle,
7665
7674
  onTreeSelect,
7675
+ // treeitem 은 포커스를 받을 수 있어야 한다. tab 순서는 STree 가 한 줄에만 0 을 줘서 정한다(roving).
7676
+ tabIndex = -1,
7677
+ // 줄 단위 키보드 조작(화살표·Enter·Space)은 줄 사이를 오가야 해서 STree 가 쥐고 내려준다
7678
+ onKeyDown,
7666
7679
  className,
7667
7680
  ...rest
7668
7681
  }, ref) {
@@ -7687,6 +7700,11 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
7687
7700
  onTreeSelect?.(node, event);
7688
7701
  };
7689
7702
  const handleRowClick = (event) => {
7703
+ if (isRowControlClick(event)) return;
7704
+ if (selectable && event.target.closest("[data-tree-label]")) {
7705
+ handleSelect(event);
7706
+ return;
7707
+ }
7690
7708
  if (hasChildren) onToggle?.(node, event);
7691
7709
  };
7692
7710
  return /* @__PURE__ */ jsxs(
@@ -7698,6 +7716,8 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
7698
7716
  "aria-expanded": hasChildren ? expanded : void 0,
7699
7717
  "aria-selected": selectable ? selected : void 0,
7700
7718
  "aria-disabled": node.disabled || void 0,
7719
+ tabIndex,
7720
+ onKeyDown,
7701
7721
  onClick: handleRowClick,
7702
7722
  className: cn(
7703
7723
  "group/tree-item box-border flex w-full items-center gap-(--cmp-tree-item-rowGap) overflow-hidden bg-(--cmp-tree-item-bg-default) px-(--cmp-tree-item-paddingX) text-left",
@@ -7743,7 +7763,7 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
7743
7763
  selectable && /* @__PURE__ */ jsx(
7744
7764
  "span",
7745
7765
  {
7746
- onClick: (event) => event.stopPropagation(),
7766
+ "data-tree-control": true,
7747
7767
  className: "flex shrink-0",
7748
7768
  "aria-hidden": node.disabled ? "true" : void 0,
7749
7769
  children: /* @__PURE__ */ jsx(
@@ -7759,11 +7779,7 @@ var STreeItemImpl = /* @__PURE__ */ forwardRef(function STreeItem({
7759
7779
  /* @__PURE__ */ jsx(
7760
7780
  "span",
7761
7781
  {
7762
- onClick: (event) => {
7763
- if (!selectable) return;
7764
- event.stopPropagation();
7765
- if (!node.disabled && selectable) onTreeSelect?.(node, event);
7766
- },
7782
+ "data-tree-label": true,
7767
7783
  className: cn(
7768
7784
  "block min-w-0 flex-1 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
7769
7785
  labelTypo,
@@ -8767,6 +8783,7 @@ var SContextAlert = /* @__PURE__ */ forwardRef(function SContextAlert2({ intent
8767
8783
  });
8768
8784
  var FILL_COLOR = {
8769
8785
  primary: "var(--cmp-progress-color-active)",
8786
+ warning: "var(--cmp-progress-color-warning)",
8770
8787
  error: "var(--cmp-progress-color-error)",
8771
8788
  complete: "var(--cmp-progress-color-success)"
8772
8789
  };
@@ -8775,20 +8792,20 @@ var SLinearProgress = /* @__PURE__ */ forwardRef(
8775
8792
  function SLinearProgress2({ value = 0, type = "primary", size = "sm", indeterminate = false, label, className, style }, ref) {
8776
8793
  const v = clamp2(value);
8777
8794
  const fill = FILL_COLOR[type];
8778
- const valueColor = v === 0 ? "var(--sys-color-fg-tertiary, #888888)" : fill;
8795
+ const valueColor = v === 0 ? "var(--sys-color-fg-tertiary)" : fill;
8779
8796
  const valueText = `${Math.round(v)}%`;
8780
8797
  const showValue = !indeterminate && size !== "xs";
8781
8798
  return /* @__PURE__ */ jsxs(
8782
8799
  "div",
8783
8800
  {
8784
8801
  ref,
8785
- className: cn("flex w-full flex-col gap-[12px]", className),
8802
+ className: cn("flex w-full flex-col gap-[var(--cmp-progress-linear-gap)]", className),
8786
8803
  style,
8787
8804
  children: [
8788
8805
  /* @__PURE__ */ jsxs(
8789
8806
  "div",
8790
8807
  {
8791
- className: "relative w-full overflow-hidden rounded-full bg-[var(--cmp-progress-color-track)]",
8808
+ className: "relative w-full overflow-hidden rounded-[var(--cmp-progress-linear-radius)] bg-[var(--cmp-progress-color-track)]",
8792
8809
  style: { height: `var(--cmp-progress-linear-height-${size})` },
8793
8810
  children: [
8794
8811
  /* @__PURE__ */ jsx(
@@ -8805,7 +8822,7 @@ var SLinearProgress = /* @__PURE__ */ forwardRef(
8805
8822
  /* @__PURE__ */ jsx(
8806
8823
  "span",
8807
8824
  {
8808
- className: "pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2 select-none text-center text-[12px] font-bold leading-[20px]",
8825
+ className: "pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2 typo-feedback-sm-bold select-none text-center",
8809
8826
  style: { color: valueColor },
8810
8827
  children: valueText
8811
8828
  }
@@ -8813,7 +8830,7 @@ var SLinearProgress = /* @__PURE__ */ forwardRef(
8813
8830
  /* @__PURE__ */ jsx(
8814
8831
  "span",
8815
8832
  {
8816
- className: "pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2 select-none text-center text-[12px] font-bold leading-[20px] text-[color:var(--cmp-progress-bar-text)]",
8833
+ className: "pointer-events-none absolute inset-x-0 top-1/2 -translate-y-1/2 typo-feedback-sm-bold select-none text-center text-[color:var(--cmp-progress-bar-text)]",
8817
8834
  style: { clipPath: `inset(0 ${100 - v}% 0 0)` },
8818
8835
  children: valueText
8819
8836
  }
@@ -8822,7 +8839,7 @@ var SLinearProgress = /* @__PURE__ */ forwardRef(
8822
8839
  ]
8823
8840
  }
8824
8841
  ),
8825
- label && /* @__PURE__ */ jsx("span", { className: "text-center text-[12px] font-normal leading-[20px] text-[color:var(--cmp-progress-color-label)]", children: label })
8842
+ label && /* @__PURE__ */ jsx("span", { className: "typo-feedback-sm-regular text-center text-[color:var(--cmp-progress-color-label)]", children: label })
8826
8843
  ]
8827
8844
  }
8828
8845
  );
@@ -15700,10 +15717,12 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
15700
15717
  }
15701
15718
  commitOpen(next);
15702
15719
  };
15720
+ const commitOpenRef = useRef(commitOpen);
15721
+ commitOpenRef.current = commitOpen;
15703
15722
  useEffect(() => {
15704
15723
  if (!insideModal || portalContainer == null || !pendingOpen) return;
15705
15724
  setPendingOpen(false);
15706
- commitOpen(true);
15725
+ commitOpenRef.current(true);
15707
15726
  }, [insideModal, pendingOpen, portalContainer]);
15708
15727
  const requestOpenRef = useRef(requestOpen);
15709
15728
  requestOpenRef.current = requestOpen;
@@ -15905,6 +15924,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
15905
15924
  return labelByValue.get(selected[0]) ?? valueOptions.get(selected[0])?.label ?? selected[0];
15906
15925
  })();
15907
15926
  const isPlaceholder = selected.length === 0;
15927
+ const showTriggerSpinner = loading2 && !effectiveDisabled;
15908
15928
  const showClear = clearable && !effectiveDisabled && !isPlaceholder;
15909
15929
  const handleClear = () => {
15910
15930
  emit3([]);
@@ -16079,6 +16099,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
16079
16099
  "aria-expanded": open,
16080
16100
  "aria-controls": open ? listboxId : void 0,
16081
16101
  "aria-activedescendant": open && focusedIndex >= 0 ? activeOptionId : void 0,
16102
+ "aria-busy": showTriggerSpinner || void 0,
16082
16103
  onClick: () => requestOpen(!open),
16083
16104
  onKeyDown: handleKeyDown,
16084
16105
  className: "flex h-full w-full cursor-pointer items-center justify-between gap-[8px] bg-transparent px-[12px] text-left text-[12px] leading-[20px] outline-none disabled:cursor-not-allowed",
@@ -16130,7 +16151,7 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
16130
16151
  ]
16131
16152
  }
16132
16153
  ),
16133
- /* @__PURE__ */ jsx(
16154
+ showTriggerSpinner ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "inline-flex shrink-0", "data-select-trigger-spinner": true, children: /* @__PURE__ */ jsx(SCircleProgress, { indeterminate: true, type: "neutral", size: 12 }) }) : /* @__PURE__ */ jsx(
16134
16155
  SIcon,
16135
16156
  {
16136
16157
  name: "chevronDown",
@@ -16246,12 +16267,15 @@ var SSelectImpl = /* @__PURE__ */ forwardRef(function SSelect({
16246
16267
  // 첫 페이지를 받는 중에는 "없다"고 단정하지 않는다 — 아래 로딩 표시가 대신 나온다.
16247
16268
  /* @__PURE__ */ jsx("div", { className: "px-[12px] py-[12px] text-left text-[12px] leading-[20px] text-[color:var(--cmp-listBoxItem-content-disabled)]", children: "\uD45C\uC2DC\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4." })
16248
16269
  ),
16249
- loading2 && /* @__PURE__ */ jsx(
16270
+ loading2 && /* @__PURE__ */ jsxs(
16250
16271
  "div",
16251
16272
  {
16252
16273
  role: "status",
16253
- className: "px-[12px] py-[12px] text-center text-[12px] leading-[20px] text-[color:var(--cmp-listBoxItem-content-disabled)]",
16254
- children: "\uBD88\uB7EC\uC624\uB294 \uC911..."
16274
+ className: "flex items-center justify-center gap-[8px] px-[12px] py-[12px] text-[12px] leading-[20px] text-[color:var(--cmp-listBoxItem-content-disabled)]",
16275
+ children: [
16276
+ /* @__PURE__ */ jsx(SCircleProgress, { indeterminate: true, type: "neutral", size: 16 }),
16277
+ "\uBD88\uB7EC\uC624\uB294 \uC911..."
16278
+ ]
16255
16279
  }
16256
16280
  )
16257
16281
  ]
@@ -16521,7 +16545,7 @@ var colWidthFromDef = (c) => {
16521
16545
  const px = typeof c.width === "number" ? c.width : parseInt(c.width, 10);
16522
16546
  return Number.isFinite(px) ? px : DEFAULT_COLUMN_WIDTH;
16523
16547
  };
16524
- var STable = /* @__PURE__ */ forwardRef(function STable2({
16548
+ var STableImpl = /* @__PURE__ */ forwardRef(function STable({
16525
16549
  columns = [],
16526
16550
  headerGroups,
16527
16551
  rows = [],
@@ -17631,6 +17655,7 @@ var STable = /* @__PURE__ */ forwardRef(function STable2({
17631
17655
  }
17632
17656
  );
17633
17657
  });
17658
+ var STable2 = STableImpl;
17634
17659
  var COUNT_NULL = "var(--cmp-table-bar-count-null)";
17635
17660
  var totalColor = (n) => n > 0 ? "var(--cmp-table-bar-count-total)" : COUNT_NULL;
17636
17661
  var selectedColor = (n) => n > 0 ? "var(--color-brilliantblue-75)" : COUNT_NULL;
@@ -18437,11 +18462,13 @@ function SCalendar({
18437
18462
  const base = value || today;
18438
18463
  const [y, setY] = useState(() => Number(base.split("-")[0]));
18439
18464
  const [m, setM] = useState(() => Number(base.split("-")[1]));
18440
- useEffect(() => {
18465
+ const [syncedValue, setSyncedValue] = useState(value);
18466
+ if (syncedValue !== value) {
18467
+ setSyncedValue(value);
18441
18468
  const b = value || today;
18442
18469
  setY(Number(b.split("-")[0]));
18443
18470
  setM(Number(b.split("-")[1]));
18444
- }, [value]);
18471
+ }
18445
18472
  const cells = useMemo(() => monthCells(y, m), [y, m]);
18446
18473
  const eventMap = useMemo(() => {
18447
18474
  const map = /* @__PURE__ */ new Map();
@@ -19764,6 +19791,7 @@ var SChipImpl = /* @__PURE__ */ forwardRef(function SChip({
19764
19791
  {
19765
19792
  ref: inputRef,
19766
19793
  role: "textbox",
19794
+ tabIndex: 0,
19767
19795
  contentEditable: !disabled,
19768
19796
  suppressContentEditableWarning: true,
19769
19797
  spellCheck: false,
@@ -22188,6 +22216,7 @@ var SToastContainer = /* @__PURE__ */ forwardRef(
22188
22216
  const [mounted2, setMounted] = useState(false);
22189
22217
  const timers = useRef(/* @__PURE__ */ new Map());
22190
22218
  const elRefs = useRef(/* @__PURE__ */ new Map());
22219
+ const resizeObserverRef = useRef(null);
22191
22220
  const [heights, setHeights] = useState(/* @__PURE__ */ new Map());
22192
22221
  const onShowRef = useRef(onShow);
22193
22222
  const onDismissRef = useRef(onDismiss);
@@ -22201,6 +22230,8 @@ var SToastContainer = /* @__PURE__ */ forwardRef(
22201
22230
  if (!liveIds.current.has(id)) return;
22202
22231
  liveIds.current.delete(id);
22203
22232
  setToasts((prev) => prev.filter((t) => t.id !== id));
22233
+ const el = elRefs.current.get(id);
22234
+ if (el) resizeObserverRef.current?.unobserve(el);
22204
22235
  elRefs.current.delete(id);
22205
22236
  setHeights((prev) => {
22206
22237
  if (!prev.has(id)) return prev;
@@ -22234,21 +22265,31 @@ var SToastContainer = /* @__PURE__ */ forwardRef(
22234
22265
  });
22235
22266
  return () => cancelAnimationFrame(raf);
22236
22267
  }, [toasts]);
22237
- useLayoutEffect(() => {
22238
- let changed = false;
22239
- const next = new Map(heights);
22240
- toasts.forEach((t) => {
22241
- const el = elRefs.current.get(t.id);
22242
- if (el) {
22268
+ useEffect(() => {
22269
+ if (typeof ResizeObserver === "undefined") return;
22270
+ const observer = new ResizeObserver((entries4) => {
22271
+ const measured = [];
22272
+ for (const entry of entries4) {
22273
+ const el = entry.target;
22274
+ const id = el.dataset.toastId;
22243
22275
  const h = el.offsetHeight;
22244
- if (h > 0 && next.get(t.id) !== h) {
22245
- next.set(t.id, h);
22246
- changed = true;
22247
- }
22276
+ if (id != null && h > 0 && liveIds.current.has(id)) measured.push([id, h]);
22248
22277
  }
22278
+ if (measured.length === 0) return;
22279
+ setHeights((prev) => {
22280
+ if (measured.every(([id, h]) => prev.get(id) === h)) return prev;
22281
+ const next = new Map(prev);
22282
+ for (const [id, h] of measured) next.set(id, h);
22283
+ return next;
22284
+ });
22249
22285
  });
22250
- if (changed) setHeights(next);
22251
- });
22286
+ resizeObserverRef.current = observer;
22287
+ elRefs.current.forEach((el) => observer.observe(el));
22288
+ return () => {
22289
+ observer.disconnect();
22290
+ resizeObserverRef.current = null;
22291
+ };
22292
+ }, []);
22252
22293
  const scheduleAutoClose = useCallback(
22253
22294
  (id, duration) => {
22254
22295
  if (duration > 0)
@@ -22387,8 +22428,11 @@ var SToastContainer = /* @__PURE__ */ forwardRef(
22387
22428
  children: toasts.map((entry) => /* @__PURE__ */ jsx(
22388
22429
  "div",
22389
22430
  {
22431
+ "data-toast-id": entry.id,
22390
22432
  ref: (el) => {
22391
- if (el) elRefs.current.set(entry.id, el);
22433
+ if (el == null || elRefs.current.get(entry.id) === el) return;
22434
+ elRefs.current.set(entry.id, el);
22435
+ resizeObserverRef.current?.observe(el);
22392
22436
  },
22393
22437
  style: itemStyle(entry),
22394
22438
  children: /* @__PURE__ */ jsx(SToast, { ...entry.options, onClose: () => startDismiss(entry.id) })
@@ -26709,7 +26753,16 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
26709
26753
  const loading2 = effectiveAutocomplete ? loadingSuggestions && suggestions.length === 0 : loadingRecommendedItems && recommendedItems.length === 0;
26710
26754
  const isFieldEmpty = inputValue === "" && values.length > 0 && !focused;
26711
26755
  const isFieldFilled = inputValue !== "";
26756
+ const reopenDropdown = () => {
26757
+ setSuppressSuggestions(false);
26758
+ setSuppressRecommendations(false);
26759
+ };
26712
26760
  const onKeyDown = (e) => {
26761
+ if (e.key === "ArrowDown" && !showDropdown && (inputValue === "" ? suppressRecommendations : suppressSuggestions)) {
26762
+ e.preventDefault();
26763
+ reopenDropdown();
26764
+ return;
26765
+ }
26713
26766
  if (showDropdown && items.length > 0) {
26714
26767
  if (e.key === "ArrowDown") {
26715
26768
  e.preventDefault();
@@ -26787,10 +26840,10 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
26787
26840
  "relative box-border flex w-full flex-wrap content-center items-center gap-(--cmp-chipInput-chip-gap)",
26788
26841
  size === "md" ? "min-h-(--cmp-chipInput-md-minHeight) px-(--cmp-chipInput-md-paddingX) py-(--cmp-chipInput-md-paddingY)" : "min-h-(--cmp-chipInput-sm-minHeight) px-(--cmp-chipInput-sm-paddingX) py-(--cmp-chipInput-sm-paddingY)"
26789
26842
  ),
26843
+ role: "presentation",
26790
26844
  onClick: () => {
26791
26845
  if (!disabled) {
26792
- setSuppressSuggestions(false);
26793
- setSuppressRecommendations(false);
26846
+ reopenDropdown();
26794
26847
  inputRef.current?.focus();
26795
26848
  }
26796
26849
  },
@@ -26921,6 +26974,7 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
26921
26974
  metaPlacement === "end" && "ml-auto"
26922
26975
  ),
26923
26976
  "data-placement": metaPlacement,
26977
+ role: "presentation",
26924
26978
  onMouseDown: (e) => e.preventDefault(),
26925
26979
  children: [
26926
26980
  /* @__PURE__ */ jsx(
@@ -26977,6 +27031,7 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
26977
27031
  {
26978
27032
  id: listboxId,
26979
27033
  role: "listbox",
27034
+ tabIndex: -1,
26980
27035
  className: "s-chip-input__suggestions flex w-full flex-col outline-none",
26981
27036
  onMouseDown: (e) => e.preventDefault(),
26982
27037
  children: [
@@ -26990,6 +27045,7 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
26990
27045
  id: active ? activeOptionId : void 0,
26991
27046
  role: "option",
26992
27047
  "aria-selected": selected || active,
27048
+ tabIndex: -1,
26993
27049
  className: "rounded-full",
26994
27050
  style: active ? { outline: "2px solid var(--color-border-accent)", outlineOffset: 1 } : void 0,
26995
27051
  onMouseDown: (e) => {
@@ -27009,6 +27065,7 @@ var SChipInput = /* @__PURE__ */ forwardRef(function SChipInput2({
27009
27065
  id: active ? activeOptionId : void 0,
27010
27066
  role: "option",
27011
27067
  "aria-selected": selected || active,
27068
+ tabIndex: -1,
27012
27069
  className: cn(
27013
27070
  "s-chip-input__suggestion-item flex shrink-0 cursor-pointer items-center gap-sd-8 overflow-hidden text-ellipsis whitespace-nowrap px-sd-12 py-sd-4 text-12 leading-sd-20",
27014
27071
  selected ? "cursor-default overflow-visible font-bold text-(--cmp-listBoxItem-content-selected)" : active ? "bg-(--cmp-listBoxItem-bg-hover) font-medium text-(--cmp-listBoxItem-content-hover)" : "text-(--cmp-listBoxItem-content-default)"
@@ -28124,6 +28181,6 @@ function STimeRangePicker({
28124
28181
  );
28125
28182
  }
28126
28183
 
28127
- export { ACCOUNT_LIST_BOX_ICONS, ACCOUNT_LIST_BOX_ITEM_TONES, ACCOUNT_LIST_BOX_LABELS, ACCOUNT_LIST_BOX_LAYOUT, ACCOUNT_LIST_BOX_TONE_CONFIG, BADGE_COLORS, BAR_GAP, BAR_SIZE_MAX, BAR_SIZE_MIN, BUTTON_COLORS, BUTTON_SIZES, CALENDAR_BOARD_DAY_BG, CALENDAR_BOARD_DAY_COLORS, CALENDAR_BOARD_EVENT_COLORS, CALENDAR_BOARD_EVENT_PRESETS, CALENDAR_BOARD_MAX_VISIBLE_EVENTS, CHAT_ATTACHED_FILE_CONFIG, CHAT_FILE_CONFIG, CHAT_MESSAGE_DIRECTIONS, CHAT_MESSAGE_READ_STATUSES, CHAT_MESSAGE_VARIANTS, CHIP_COLORS, COLOR_KEYS, CONTEXT_ALERT_ICON_COLOR, CONTEXT_ALERT_INTENTS, CONTEXT_ALERT_SURFACE, FIELD_WIDTH_GRADES, GNB_COLORS, GNB_COMMON, GNB_FOLD_MS, GNB_FULL_LOGO_WIDTH, GNB_HEADER, GNB_MENU, GNB_MENU_WIDTH, GNB_RAIL, GNB_RAIL_WIDTH, GNB_SYSTEM_COLORS, GNB_SYSTEM_COLOR_CONFIG, GNB_SYSTEM_LAYOUT, GNB_SYSTEM_PLACEMENTS, GNB_SYSTEM_TOP_COLOR_CONFIG, ICONS, IMAGE_FITS, LAUNCHER_LIST_BOX_CONSOLE_HEIGHT, LAUNCHER_LIST_BOX_CONSOLE_ICON, LAUNCHER_LIST_BOX_CONSOLE_LABEL, LAUNCHER_LIST_BOX_LAYOUT, LAUNCHER_LIST_BOX_LOGO_HEIGHT, LAUNCHER_LIST_BOX_TRAILING_ICON, LAUNCHER_LIST_BOX_WIDTH, LAUNCHER_SERVICES, LAUNCHER_SERVICE_CATALOG, LOGO_DEFAULT_SIZE, LOGO_DIRECTIONS, LOGO_MODES, LOGO_NAMES, PAGE_BACKGROUNDS, PAGE_CONTENT_HEIGHTS, PAGE_CONTENT_WIDTHS, PAGE_HEADER_VARIANTS, PAGE_PADDINGS, RangeCalendar, SAccountListBox, SActionModal, SBadge, SBarChart, SBarcodeInput, SButton, SCROLL_AREA_AXES, SCalendar, SCalendarBoard, SCallout, SCard, SChatAttachedFile2 as SChatAttachedFile, SChatFile2 as SChatFile, SChatInput2 as SChatInput, SChatMessage2 as SChatMessage, SChatSystemMessage2 as SChatSystemMessage, SCheckbox, SChip2 as SChip, SChipFilter, SChipInput, SCircleProgress, SConfirmModal, SContextAlert, SDatePicker, SDatePickerMonthListbox, SDatePickerYearListbox, SDateRangePicker, SDivider, SDonutChart, SDraggableGroup, SDraggableItem2 as SDraggableItem, SDraggableList, SDraggableProvider, SDrawer, SDropdownButton2 as SDropdownButton, SEDITOR_DEFAULT_FONT_SIZE, SEDITOR_HEADING_LABELS, SEDITOR_HEADING_LEVELS, SEditor, SExpansionItem, SExpansionList2 as SExpansionList, SField, SFilePicker, SForm, SGhostButton, SGnb, SGnbSystem, SGnbSystemContext, SGuide, SIcon, SImage, SInput, SKeyValueTable, SLAYOUT_MIN_WIDTH, SLauncherListBox, SLayout, SLayoutContext, SLineChart, SLinearProgress, SList2 as SList, SListItem2 as SListItem, SLoadingContainer, SLoadingModal, SLoginCard2 as SLoginCard, SLogo, SMeatballButton2 as SMeatballButton, SModal, SModalOutlet, SNumberInput, SPage, SPageHeader, SPagination, SPieChart, SPopover, SPopup, SPortal, SRadio, SRadioButton, SRadioCard, SRadioCardGroup, SRadioGroup, SSPLITTER_UNITS, SScrollArea, SSearchInput, SSectionHeaderCard2 as SSectionHeaderCard, SSelect2 as SSelect, SSplitter2 as SSplitter, SStepper, SSwitch, SSystemActionButton, STEPPER_SIZES, STable, STableBar, STabs, STag, STextLink, STextarea, STimePicker, STimeRangePicker, SToast, SToastContainer, SToggle, STooltip2 as STooltip, STree2 as STree, STreeItem2 as STreeItem, SYSTEM_ACTION_BUTTON_COLORS, SYSTEM_ACTION_BUTTON_COLOR_CONFIG, SYSTEM_ACTION_BUTTON_LAYOUT, SYSTEM_ACTION_BUTTON_TYPES, SYSTEM_ACTION_BUTTON_TYPE_CONFIG, TAG_COLORS, TAG_SHAPES, TAG_SIZES, TIMEPICKER_SIZES, TIMEPICKER_SIZE_CONFIG, buttonPreset, cn, fieldWidthValue, fileExtension, findGnbAncestors, findGnbRailValue, formatFileSize, isColorKey, isFieldWidthGrade, loading, normalizeExtension, resolveColor, useSLayout };
28184
+ export { ACCOUNT_LIST_BOX_ICONS, ACCOUNT_LIST_BOX_ITEM_TONES, ACCOUNT_LIST_BOX_LABELS, ACCOUNT_LIST_BOX_LAYOUT, ACCOUNT_LIST_BOX_TONE_CONFIG, BADGE_COLORS, BAR_GAP, BAR_SIZE_MAX, BAR_SIZE_MIN, BUTTON_COLORS, BUTTON_SIZES, CALENDAR_BOARD_DAY_BG, CALENDAR_BOARD_DAY_COLORS, CALENDAR_BOARD_EVENT_COLORS, CALENDAR_BOARD_EVENT_PRESETS, CALENDAR_BOARD_MAX_VISIBLE_EVENTS, CHAT_ATTACHED_FILE_CONFIG, CHAT_FILE_CONFIG, CHAT_MESSAGE_DIRECTIONS, CHAT_MESSAGE_READ_STATUSES, CHAT_MESSAGE_VARIANTS, CHIP_COLORS, COLOR_KEYS, CONTEXT_ALERT_ICON_COLOR, CONTEXT_ALERT_INTENTS, CONTEXT_ALERT_SURFACE, FIELD_WIDTH_GRADES, GNB_COLORS, GNB_COMMON, GNB_FOLD_MS, GNB_FULL_LOGO_WIDTH, GNB_HEADER, GNB_MENU, GNB_MENU_WIDTH, GNB_RAIL, GNB_RAIL_WIDTH, GNB_SYSTEM_COLORS, GNB_SYSTEM_COLOR_CONFIG, GNB_SYSTEM_LAYOUT, GNB_SYSTEM_PLACEMENTS, GNB_SYSTEM_TOP_COLOR_CONFIG, ICONS, IMAGE_FITS, LAUNCHER_LIST_BOX_CONSOLE_HEIGHT, LAUNCHER_LIST_BOX_CONSOLE_ICON, LAUNCHER_LIST_BOX_CONSOLE_LABEL, LAUNCHER_LIST_BOX_LAYOUT, LAUNCHER_LIST_BOX_LOGO_HEIGHT, LAUNCHER_LIST_BOX_TRAILING_ICON, LAUNCHER_LIST_BOX_WIDTH, LAUNCHER_SERVICES, LAUNCHER_SERVICE_CATALOG, LOGO_DEFAULT_SIZE, LOGO_DIRECTIONS, LOGO_MODES, LOGO_NAMES, PAGE_BACKGROUNDS, PAGE_CONTENT_HEIGHTS, PAGE_CONTENT_WIDTHS, PAGE_HEADER_VARIANTS, PAGE_PADDINGS, RangeCalendar, SAccountListBox, SActionModal, SBadge, SBarChart, SBarcodeInput, SButton, SCROLL_AREA_AXES, SCalendar, SCalendarBoard, SCallout, SCard, SChatAttachedFile2 as SChatAttachedFile, SChatFile2 as SChatFile, SChatInput2 as SChatInput, SChatMessage2 as SChatMessage, SChatSystemMessage2 as SChatSystemMessage, SCheckbox, SChip2 as SChip, SChipFilter, SChipInput, SCircleProgress, SConfirmModal, SContextAlert, SDatePicker, SDatePickerMonthListbox, SDatePickerYearListbox, SDateRangePicker, SDivider, SDonutChart, SDraggableGroup, SDraggableItem2 as SDraggableItem, SDraggableList, SDraggableProvider, SDrawer, SDropdownButton2 as SDropdownButton, SEDITOR_DEFAULT_FONT_SIZE, SEDITOR_HEADING_LABELS, SEDITOR_HEADING_LEVELS, SEditor, SExpansionItem, SExpansionList2 as SExpansionList, SField, SFilePicker, SForm, SGhostButton, SGnb, SGnbSystem, SGnbSystemContext, SGuide, SIcon, SImage, SInput, SKeyValueTable, SLAYOUT_MIN_WIDTH, SLauncherListBox, SLayout, SLayoutContext, SLineChart, SLinearProgress, SList2 as SList, SListItem2 as SListItem, SLoadingContainer, SLoadingModal, SLoginCard2 as SLoginCard, SLogo, SMeatballButton2 as SMeatballButton, SModal, SModalOutlet, SNumberInput, SPage, SPageHeader, SPagination, SPieChart, SPopover, SPopup, SPortal, SRadio, SRadioButton, SRadioCard, SRadioCardGroup, SRadioGroup, SSPLITTER_UNITS, SScrollArea, SSearchInput, SSectionHeaderCard2 as SSectionHeaderCard, SSelect2 as SSelect, SSplitter2 as SSplitter, SStepper, SSwitch, SSystemActionButton, STEPPER_SIZES, STable2 as STable, STableBar, STabs, STag, STextLink, STextarea, STimePicker, STimeRangePicker, SToast, SToastContainer, SToggle, STooltip2 as STooltip, STree2 as STree, STreeItem2 as STreeItem, SYSTEM_ACTION_BUTTON_COLORS, SYSTEM_ACTION_BUTTON_COLOR_CONFIG, SYSTEM_ACTION_BUTTON_LAYOUT, SYSTEM_ACTION_BUTTON_TYPES, SYSTEM_ACTION_BUTTON_TYPE_CONFIG, TAG_COLORS, TAG_SHAPES, TAG_SIZES, TIMEPICKER_SIZES, TIMEPICKER_SIZE_CONFIG, buttonPreset, cn, fieldWidthValue, fileExtension, findGnbAncestors, findGnbRailValue, formatFileSize, isColorKey, isFieldWidthGrade, loading, normalizeExtension, resolveColor, useSLayout };
28128
28185
  //# sourceMappingURL=index.js.map
28129
28186
  //# sourceMappingURL=index.js.map