sellmate-design-system-react 9.0.0-beta.5 → 9.0.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -7,7 +7,7 @@ var react = require('react');
7
7
  var jsxRuntime = require('react/jsx-runtime');
8
8
  var reactDom = require('react-dom');
9
9
  var RCheckbox = require('@radix-ui/react-checkbox');
10
- var RPopover9 = require('@radix-ui/react-popover');
10
+ var RPopover10 = require('@radix-ui/react-popover');
11
11
  var client = require('react-dom/client');
12
12
  var RTooltip = require('@radix-ui/react-tooltip');
13
13
  var RDropdown = require('@radix-ui/react-dropdown-menu');
@@ -34,7 +34,7 @@ function _interopNamespace(e) {
34
34
  }
35
35
 
36
36
  var RCheckbox__namespace = /*#__PURE__*/_interopNamespace(RCheckbox);
37
- var RPopover9__namespace = /*#__PURE__*/_interopNamespace(RPopover9);
37
+ var RPopover10__namespace = /*#__PURE__*/_interopNamespace(RPopover10);
38
38
  var RTooltip__namespace = /*#__PURE__*/_interopNamespace(RTooltip);
39
39
  var RDropdown__namespace = /*#__PURE__*/_interopNamespace(RDropdown);
40
40
  var RSwitch__namespace = /*#__PURE__*/_interopNamespace(RSwitch);
@@ -3445,7 +3445,7 @@ var SDraggableItemView = /* @__PURE__ */ react.forwardRef(
3445
3445
  !disabled && !selected && !dragging && "hover:bg-(--cmp-listDraggableItem-bg-hover)",
3446
3446
  hasSupportingText && supportingTextPosition === "bottom" ? dense ? "min-h-[52px]" : "min-h-[60px]" : dense ? "h-[32px]" : "h-[40px]",
3447
3447
  paddingYClass,
3448
- // 항목 사이 구분선은 리스트가 그린다 — SDraggableList 의 separator (SList.tsx)
3448
+ // 항목 사이 구분선은 리스트가 그린다.
3449
3449
  bordered && cn(
3450
3450
  "rounded-(--cmp-listDraggableItem-radius-bordered) border border-(--cmp-listDraggableItem-border-default)",
3451
3451
  !disabled && !selected && !dragging && "hover:border-(--cmp-listDraggableItem-bordered-border-hover)",
@@ -3653,7 +3653,7 @@ var SDraggableItemImpl = /* @__PURE__ */ react.forwardRef(function SDraggableIte
3653
3653
  ] });
3654
3654
  });
3655
3655
  var SDraggableItem2 = /* @__PURE__ */ withDisplayName(SDraggableItemImpl, "SDraggableItem");
3656
- var SListImpl = /* @__PURE__ */ react.forwardRef(function SList({ className, children, useGap = false, usePadding = false, separator = false, ...rest }, ref) {
3656
+ var SListImpl = /* @__PURE__ */ react.forwardRef(function SList({ className, children, useGap = false, usePadding = false, ...rest }, ref) {
3657
3657
  return /* @__PURE__ */ jsxRuntime.jsx(
3658
3658
  "div",
3659
3659
  {
@@ -3661,7 +3661,7 @@ var SListImpl = /* @__PURE__ */ react.forwardRef(function SList({ className, chi
3661
3661
  className: cn(
3662
3662
  useGap && "flex flex-col gap-(--cmp-list-group-gap)",
3663
3663
  usePadding && "p-(--cmp-list-group-padding)",
3664
- separator && "[&>*]:border-b [&>*]:border-(--cmp-listItem-border-default)",
3664
+ "[&>*]:border-b [&>*]:border-(--cmp-listItem-border-default)",
3665
3665
  className
3666
3666
  ),
3667
3667
  ...rest,
@@ -4033,7 +4033,7 @@ var SExpansionItem = /* @__PURE__ */ react.forwardRef(
4033
4033
  ref,
4034
4034
  className: cn(
4035
4035
  "group/expansion-item relative overflow-hidden bg-(--cmp-listExpansionItem-title-bg-default)",
4036
- // 항목 사이 구분선은 리스트가 그린다 — SList/SExpansionList 의 separator (SList.tsx)
4036
+ // 항목 사이 구분선은 리스트가 그린다.
4037
4037
  // 보더 색은 시맨틱 토큰(border-default → hover strong → 펼침 accentLight)을 쓴다.
4038
4038
  // TODO: expansionItem/bordered/radius 토큰 생성 후 rounded 고정값도 토큰으로 교체한다.
4039
4039
  bordered && "rounded-[8px] border border-border-default hover:border-border-strong [&:has(>button:hover)]:border-border-strong",
@@ -4585,8 +4585,8 @@ function SGhostButton({
4585
4585
  }
4586
4586
  );
4587
4587
  if (!hasTooltip) return btn;
4588
- return /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open, onOpenChange: setOpen, children: [
4589
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4588
+ return /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: setOpen, children: [
4589
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
4590
4590
  "span",
4591
4591
  {
4592
4592
  className: cn("inline-flex", anchorClassName),
@@ -4598,8 +4598,8 @@ function SGhostButton({
4598
4598
  children: btn
4599
4599
  }
4600
4600
  ) }),
4601
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
4602
- RPopover9__namespace.Content,
4601
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
4602
+ RPopover10__namespace.Content,
4603
4603
  {
4604
4604
  side: "top",
4605
4605
  sideOffset: 4,
@@ -4613,6 +4613,18 @@ function SGhostButton({
4613
4613
  ) })
4614
4614
  ] });
4615
4615
  }
4616
+ var TREE_LABEL_TYPOGRAPHY = {
4617
+ sm: {
4618
+ default: "typo-body-sm-medium",
4619
+ selected: "typo-body-sm-bold",
4620
+ rowHeight: "h-[28px]"
4621
+ },
4622
+ md: {
4623
+ default: "typo-body-md-medium",
4624
+ selected: "typo-body-md-bold",
4625
+ rowHeight: "h-[32px]"
4626
+ }
4627
+ };
4616
4628
  function collectIds(nodes) {
4617
4629
  return nodes.flatMap((node) => [node.id, ...collectIds(node.children ?? [])]);
4618
4630
  }
@@ -4623,18 +4635,19 @@ function collectSelectableIds(node) {
4623
4635
  function toSelectedSet(value) {
4624
4636
  return new Set(value ?? []);
4625
4637
  }
4626
- function getSelectionState(node, selectedSet) {
4627
- if (selectedSet.has(node.id)) {
4628
- return { selected: true, indeterminate: false };
4638
+ var TREE_ALL_NODE = { id: "__all__", label: "\uC804\uCCB4" };
4639
+ function getSelectionState(node, selectedSet, cascadeSelection) {
4640
+ if (!cascadeSelection) {
4641
+ return { selected: selectedSet.has(node.id), indeterminate: false };
4629
4642
  }
4630
4643
  const selectableChildren = (node.children ?? []).filter(
4631
4644
  (child) => collectSelectableIds(child).length > 0
4632
4645
  );
4633
4646
  if (selectableChildren.length === 0) {
4634
- return { selected: false, indeterminate: false };
4647
+ return { selected: selectedSet.has(node.id), indeterminate: false };
4635
4648
  }
4636
4649
  const childStates = selectableChildren.map(
4637
- (child) => getSelectionState(child, selectedSet)
4650
+ (child) => getSelectionState(child, selectedSet, cascadeSelection)
4638
4651
  );
4639
4652
  const selectedCount = childStates.filter((state2) => state2.selected).length;
4640
4653
  return {
@@ -4644,6 +4657,7 @@ function getSelectionState(node, selectedSet) {
4644
4657
  }
4645
4658
  function TreeConnector({
4646
4659
  guideline,
4660
+ size,
4647
4661
  depth,
4648
4662
  hasChildren,
4649
4663
  isLast,
@@ -4651,6 +4665,8 @@ function TreeConnector({
4651
4665
  }) {
4652
4666
  if (depth <= 1) return null;
4653
4667
  const ancestorConnectors = ancestorLast.slice(0, -1);
4668
+ const branchTop = size === "sm" ? "top-[13px]" : "top-[15px]";
4669
+ const nodeHeight = size === "sm" ? "h-[15px]" : "h-[17px]";
4654
4670
  return /* @__PURE__ */ jsxRuntime.jsxs("span", { "aria-hidden": "true", className: "flex self-stretch", children: [
4655
4671
  ancestorConnectors.map((last, index) => /* @__PURE__ */ jsxRuntime.jsx(
4656
4672
  "span",
@@ -4664,13 +4680,22 @@ function TreeConnector({
4664
4680
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative block w-[20px] shrink-0", children: [
4665
4681
  guideline && !isLast && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute bottom-0 left-[6px] top-[-1px] w-px bg-(--cmp-tree-connector-line-color)" }),
4666
4682
  guideline && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4667
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-[6px] top-[-1px] h-[17px] w-px bg-(--cmp-tree-connector-line-color)" }),
4683
+ /* @__PURE__ */ jsxRuntime.jsx(
4684
+ "span",
4685
+ {
4686
+ className: cn(
4687
+ "absolute left-[6px] top-[-1px] w-px bg-(--cmp-tree-connector-line-color)",
4688
+ nodeHeight
4689
+ )
4690
+ }
4691
+ ),
4668
4692
  /* @__PURE__ */ jsxRuntime.jsx(
4669
4693
  "span",
4670
4694
  {
4671
4695
  "data-tree-connector-branch": hasChildren ? "parent" : "leaf",
4672
4696
  className: cn(
4673
- "absolute left-[6px] top-[15px] h-px bg-(--cmp-tree-connector-line-color)",
4697
+ "absolute left-[6px] h-px bg-(--cmp-tree-connector-line-color)",
4698
+ branchTop,
4674
4699
  hasChildren ? "w-[14px]" : "w-[calc(14px+var(--cmp-tree-item-arrow-icon))]"
4675
4700
  )
4676
4701
  }
@@ -4679,6 +4704,44 @@ function TreeConnector({
4679
4704
  ] })
4680
4705
  ] });
4681
4706
  }
4707
+ function STreeAllItem({
4708
+ selected,
4709
+ indeterminate,
4710
+ border,
4711
+ size,
4712
+ onSelect
4713
+ }) {
4714
+ const checkboxValue = indeterminate ? null : selected;
4715
+ const typography = TREE_LABEL_TYPOGRAPHY[size];
4716
+ const labelTypo = selected || indeterminate ? typography.selected : typography.default;
4717
+ return /* @__PURE__ */ jsxRuntime.jsx(
4718
+ "div",
4719
+ {
4720
+ role: "treeitem",
4721
+ "aria-level": 1,
4722
+ "aria-selected": selected,
4723
+ onClick: onSelect,
4724
+ className: cn(
4725
+ "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)",
4726
+ typography.rowHeight,
4727
+ border && "border-b border-(--cmp-tree-item-border-default)"
4728
+ ),
4729
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "box-border flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)", children: [
4730
+ /* @__PURE__ */ jsxRuntime.jsx("span", { onClick: (event) => event.stopPropagation(), className: "flex shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(SCheckbox, { value: checkboxValue, onValueChange: () => onSelect() }) }),
4731
+ /* @__PURE__ */ jsxRuntime.jsx(
4732
+ "span",
4733
+ {
4734
+ className: cn(
4735
+ "block min-w-0 flex-1 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
4736
+ labelTypo
4737
+ ),
4738
+ children: "\uC804\uCCB4"
4739
+ }
4740
+ )
4741
+ ] })
4742
+ }
4743
+ );
4744
+ }
4682
4745
  var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
4683
4746
  node,
4684
4747
  depth = 1,
@@ -4690,6 +4753,7 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
4690
4753
  border = true,
4691
4754
  indeterminate = false,
4692
4755
  selectable = true,
4756
+ size = "sm",
4693
4757
  leading,
4694
4758
  trailing,
4695
4759
  onToggle,
@@ -4701,6 +4765,7 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
4701
4765
  const renderState = {
4702
4766
  node,
4703
4767
  depth,
4768
+ size,
4704
4769
  expanded,
4705
4770
  selected,
4706
4771
  indeterminate,
@@ -4710,6 +4775,8 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
4710
4775
  const leadingNode = typeof leading === "function" ? leading(renderState) : leading;
4711
4776
  const trailingNode = typeof trailing === "function" ? trailing(renderState) : trailing;
4712
4777
  const checkboxValue = indeterminate ? null : selected;
4778
+ const typography = TREE_LABEL_TYPOGRAPHY[size];
4779
+ const labelTypo = selected || indeterminate ? typography.selected : typography.default;
4713
4780
  const handleSelect = (event) => {
4714
4781
  if (node.disabled) return;
4715
4782
  onTreeSelect?.(node, event);
@@ -4729,7 +4796,8 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
4729
4796
  "aria-disabled": node.disabled || void 0,
4730
4797
  onClick: handleRowClick,
4731
4798
  className: cn(
4732
- "group/tree-item box-border flex h-[32px] w-full items-center gap-(--cmp-tree-item-rowGap) overflow-hidden bg-(--cmp-tree-item-bg-default) px-(--cmp-tree-item-paddingX) text-left",
4799
+ "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",
4800
+ typography.rowHeight,
4733
4801
  border && "border-b border-(--cmp-tree-item-border-default)",
4734
4802
  !node.disabled && "hover:bg-(--cmp-tree-item-bg-hover)",
4735
4803
  node.disabled && "cursor-not-allowed opacity-60",
@@ -4742,13 +4810,14 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
4742
4810
  TreeConnector,
4743
4811
  {
4744
4812
  guideline,
4813
+ size,
4745
4814
  depth,
4746
4815
  hasChildren,
4747
4816
  isLast,
4748
4817
  ancestorLast
4749
4818
  }
4750
4819
  ),
4751
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "box-border flex h-full min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap) py-(--cmp-tree-item-paddingY)", children: [
4820
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "box-border flex min-w-0 flex-1 items-center gap-(--cmp-tree-item-contentGap)", children: [
4752
4821
  hasChildren ? /* @__PURE__ */ jsxRuntime.jsx(
4753
4822
  SGhostButton,
4754
4823
  {
@@ -4790,8 +4859,8 @@ var STreeItemImpl = /* @__PURE__ */ react.forwardRef(function STreeItem({
4790
4859
  if (!node.disabled && selectable) onTreeSelect?.(node, event);
4791
4860
  },
4792
4861
  className: cn(
4793
- "block min-w-0 flex-1 truncate text-[14px] leading-[24px]",
4794
- selected || indeterminate ? "font-bold text-(--cmp-tree-item-text-selected)" : "font-medium text-(--cmp-tree-item-text-default)",
4862
+ "block min-w-0 flex-1 truncate py-(--cmp-tree-item-paddingY) text-(--cmp-tree-item-text-default)",
4863
+ labelTypo,
4795
4864
  node.disabled ? "cursor-not-allowed" : selectable ? "cursor-pointer" : void 0
4796
4865
  ),
4797
4866
  children: node.label
@@ -4811,6 +4880,8 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
4811
4880
  expandedIds,
4812
4881
  defaultExpandedIds,
4813
4882
  selectable = true,
4883
+ size = "sm",
4884
+ useAll = false,
4814
4885
  cascadeSelection = true,
4815
4886
  guideline = true,
4816
4887
  border = true,
@@ -4829,6 +4900,11 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
4829
4900
  const currentExpandedIds = expandedIds ?? internalExpandedIds;
4830
4901
  const selectedSet = react.useMemo(() => toSelectedSet(currentValue), [currentValue]);
4831
4902
  const expandedSet = react.useMemo(() => new Set(currentExpandedIds), [currentExpandedIds]);
4903
+ const selectableIds = react.useMemo(() => items.flatMap(collectSelectableIds), [items]);
4904
+ const allSelected = selectableIds.length > 0 && selectableIds.every((id) => selectedSet.has(id));
4905
+ const someSelected = selectableIds.some((id) => selectedSet.has(id));
4906
+ const allIndeterminate = someSelected && !allSelected;
4907
+ const showAllItem = selectable && useAll;
4832
4908
  const updateExpanded = (node) => {
4833
4909
  const next = new Set(currentExpandedIds);
4834
4910
  if (next.has(node.id)) next.delete(node.id);
@@ -4840,7 +4916,7 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
4840
4916
  const updateSelected = (node) => {
4841
4917
  if (node.disabled) return;
4842
4918
  const targetIds = cascadeSelection ? collectSelectableIds(node) : [node.id];
4843
- const everySelected = getSelectionState(node, selectedSet).selected;
4919
+ const everySelected = getSelectionState(node, selectedSet, cascadeSelection).selected;
4844
4920
  const next = new Set(selectedSet);
4845
4921
  targetIds.forEach((id) => {
4846
4922
  if (everySelected) next.delete(id);
@@ -4850,10 +4926,22 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
4850
4926
  if (value === void 0) setInternalValue(orderedIds);
4851
4927
  onValueChange?.(orderedIds, node);
4852
4928
  };
4929
+ const updateAllSelected = (event) => {
4930
+ event?.stopPropagation();
4931
+ if (selectableIds.length === 0) return;
4932
+ const next = new Set(selectedSet);
4933
+ selectableIds.forEach((id) => {
4934
+ if (allSelected) next.delete(id);
4935
+ else next.add(id);
4936
+ });
4937
+ const orderedIds = collectIds(items).filter((id) => next.has(id));
4938
+ if (value === void 0) setInternalValue(orderedIds);
4939
+ onValueChange?.(orderedIds, TREE_ALL_NODE);
4940
+ };
4853
4941
  const renderNodes = (nodes, depth = 1, ancestorLast = []) => nodes.map((node, index) => {
4854
4942
  const isLast = index === nodes.length - 1;
4855
4943
  const isExpanded = expandedSet.has(node.id);
4856
- const { selected, indeterminate } = getSelectionState(node, selectedSet);
4944
+ const { selected, indeterminate } = getSelectionState(node, selectedSet, cascadeSelection);
4857
4945
  return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
4858
4946
  /* @__PURE__ */ jsxRuntime.jsx(
4859
4947
  STreeItem2,
@@ -4866,6 +4954,7 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
4866
4954
  selected,
4867
4955
  indeterminate,
4868
4956
  selectable,
4957
+ size,
4869
4958
  guideline,
4870
4959
  border,
4871
4960
  leading,
@@ -4887,14 +4976,26 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
4887
4976
  ) : null
4888
4977
  ] }, node.id);
4889
4978
  });
4890
- return /* @__PURE__ */ jsxRuntime.jsx(
4979
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4891
4980
  "div",
4892
4981
  {
4893
4982
  ref,
4894
4983
  role: "tree",
4895
4984
  className: cn("flex w-full flex-col items-start bg-(--cmp-tree-item-bg-default)", className),
4896
4985
  ...rest,
4897
- children: renderNodes(items)
4986
+ children: [
4987
+ showAllItem && /* @__PURE__ */ jsxRuntime.jsx(
4988
+ STreeAllItem,
4989
+ {
4990
+ selected: allSelected,
4991
+ indeterminate: allIndeterminate,
4992
+ border,
4993
+ size,
4994
+ onSelect: updateAllSelected
4995
+ }
4996
+ ),
4997
+ renderNodes(items)
4998
+ ]
4898
4999
  }
4899
5000
  );
4900
5001
  });
@@ -5074,14 +5175,14 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
5074
5175
  ...style,
5075
5176
  ...contentPropsStyle
5076
5177
  };
5077
- return /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open, onOpenChange: setOpenState, children: [
5178
+ return /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: setOpenState, children: [
5078
5179
  isNone ? (
5079
5180
  // 트리거 없음: children 을 래퍼 없이 그대로 앵커로 쓴다 (소비자 레이아웃 보존).
5080
5181
  // mouse/focus 핸들러가 없으므로 useClose 없이도 자동 닫힘이 발생하지 않는다.
5081
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Anchor, { asChild: true, children: triggerNode })
5182
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { asChild: true, children: triggerNode })
5082
5183
  ) : isHover ? (
5083
5184
  // hover: Anchor(위치 기준) + 직접 mouse 핸들러 — 클릭으로 토글되지 않도록 Trigger 미사용
5084
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
5185
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
5085
5186
  "span",
5086
5187
  {
5087
5188
  className: "inline-flex",
@@ -5092,9 +5193,9 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
5092
5193
  children: triggerNode
5093
5194
  }
5094
5195
  ) })
5095
- ) : /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Trigger, { asChild: true, children: triggerNode }),
5096
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
5097
- RPopover9__namespace.Content,
5196
+ ) : /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: triggerNode }),
5197
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
5198
+ RPopover10__namespace.Content,
5098
5199
  {
5099
5200
  side: placement,
5100
5201
  sideOffset,
@@ -5128,7 +5229,7 @@ var STooltipImpl = /* @__PURE__ */ react.forwardRef(function STooltip({
5128
5229
  }
5129
5230
  )
5130
5231
  ] }),
5131
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
5232
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
5132
5233
  ]
5133
5234
  }
5134
5235
  ) })
@@ -6415,10 +6516,10 @@ function SPopover({
6415
6516
  const descColor = type === "default" ? "var(--cmp-popover-default-description)" : "var(--cmp-popover-light-description)";
6416
6517
  const leftLinkLabelClass = type === "default" ? "text-[color:var(--cmp-popover-default-subAction)]" : "text-[color:var(--cmp-popover-light-subAction)]";
6417
6518
  const triggerNode = trigger ?? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex cursor-pointer", "aria-label": ariaLabel, children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: icon, size: iconSize, color }) });
6418
- return /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open: actualOpen, onOpenChange: setOpen, children: [
6419
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Trigger, { asChild: true, children: triggerNode }),
6420
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
6421
- RPopover9__namespace.Content,
6519
+ return /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: actualOpen, onOpenChange: setOpen, children: [
6520
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: triggerNode }),
6521
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
6522
+ RPopover10__namespace.Content,
6422
6523
  {
6423
6524
  side: placement,
6424
6525
  sideOffset: 8,
@@ -6484,7 +6585,7 @@ function SPopover({
6484
6585
  ]
6485
6586
  }
6486
6587
  ),
6487
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
6588
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Arrow, { width: 16, height: 12, style: { fill: bg } })
6488
6589
  ]
6489
6590
  }
6490
6591
  ) })
@@ -6515,7 +6616,7 @@ function SPortal({
6515
6616
  const portalContainer = usePortalContainer();
6516
6617
  const { minWidth: styleMinWidth, maxWidth: styleMaxWidth, ...restStyle } = style ?? {};
6517
6618
  return /* @__PURE__ */ jsxRuntime.jsxs(
6518
- RPopover9__namespace.Root,
6619
+ RPopover10__namespace.Root,
6519
6620
  {
6520
6621
  open,
6521
6622
  onOpenChange: (next) => {
@@ -6523,9 +6624,9 @@ function SPortal({
6523
6624
  if (!next) onClose?.();
6524
6625
  },
6525
6626
  children: [
6526
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Anchor, { virtualRef: anchorRef }),
6527
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
6528
- RPopover9__namespace.Content,
6627
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { virtualRef: anchorRef }),
6628
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
6629
+ RPopover10__namespace.Content,
6529
6630
  {
6530
6631
  side: placement,
6531
6632
  align,
@@ -6723,10 +6824,10 @@ function SGuide({
6723
6824
  );
6724
6825
  if (isNotion)
6725
6826
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className, style, children: trigger });
6726
- return /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open, onOpenChange: setOpen, children: [
6727
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Trigger, { asChild: true, children: trigger }),
6728
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
6729
- RPopover9__namespace.Content,
6827
+ return /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: setOpen, children: [
6828
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: trigger }),
6829
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
6830
+ RPopover10__namespace.Content,
6730
6831
  {
6731
6832
  side: "bottom",
6732
6833
  align: "start",
@@ -8807,10 +8908,10 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
8807
8908
  }
8808
8909
  ),
8809
8910
  header === "fix" && menuResizeHandle,
8810
- /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open: labelTip !== null, onOpenChange: (open) => !open && setLabelTip(null), children: [
8811
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Anchor, { virtualRef: labelTipAnchorRef }),
8812
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
8813
- RPopover9__namespace.Content,
8911
+ /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: labelTip !== null, onOpenChange: (open) => !open && setLabelTip(null), children: [
8912
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { virtualRef: labelTipAnchorRef }),
8913
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
8914
+ RPopover10__namespace.Content,
8814
8915
  {
8815
8916
  side: "right",
8816
8917
  sideOffset: 4,
@@ -8881,13 +8982,155 @@ var SPageHeader = /* @__PURE__ */ withDisplayName(
8881
8982
  );
8882
8983
  var MIN_CONTENT_WIDTH = `calc(var(${SLAYOUT_MIN_WIDTH_VAR}, 0px) - 100cqw + 100%)`;
8883
8984
  var BACKGROUND_CLASS = {
8884
- frame: `bg-[var(--sys-color-bg-frame)] ${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`,
8885
- neutral: `bg-[var(--sys-color-bg-neutralLight)] ${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_WHITE_CLASS}`,
8886
- screen: `bg-[var(--sys-color-bg-screen)] ${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`
8985
+ frame: "bg-[var(--sys-color-bg-frame)]",
8986
+ neutral: "bg-[var(--sys-color-bg-neutralLight)]",
8987
+ screen: "bg-[var(--sys-color-bg-screen)]"
8988
+ };
8989
+ var NATIVE_SCROLLBAR_BACKGROUND_CLASS = {
8990
+ frame: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`,
8991
+ neutral: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_WHITE_CLASS}`,
8992
+ screen: `${SCROLLBAR_TRACK_BORDER_CLASS} ${SCROLLBAR_TRACK_BG_CLASS}`
8993
+ };
8994
+ var SCROLLBAR_SIZE = 12;
8995
+ var SCROLLBAR_MIN_THUMB_SIZE = 32;
8996
+ var getMetrics = (viewportSize, contentSize, scrollOffset) => {
8997
+ if (contentSize <= viewportSize) {
8998
+ return { visible: false, thumbSize: 0, thumbOffset: 0 };
8999
+ }
9000
+ const trackSize = viewportSize;
9001
+ const maxScrollOffset = contentSize - viewportSize;
9002
+ const thumbSize = Math.min(
9003
+ trackSize,
9004
+ Math.max(SCROLLBAR_MIN_THUMB_SIZE, viewportSize / contentSize * trackSize)
9005
+ );
9006
+ const maxThumbOffset = trackSize - thumbSize;
9007
+ const thumbOffset = maxScrollOffset > 0 ? scrollOffset / maxScrollOffset * maxThumbOffset : 0;
9008
+ return { visible: true, thumbSize, thumbOffset };
9009
+ };
9010
+ var setForwardedRef = (ref, node) => {
9011
+ if (typeof ref === "function") {
9012
+ ref(node);
9013
+ return;
9014
+ }
9015
+ if (ref) ref.current = node;
8887
9016
  };
9017
+ function SPageOverlayScrollbars({ scrollRef }) {
9018
+ const [vertical, setVertical] = react.useState({
9019
+ visible: false,
9020
+ thumbSize: 0,
9021
+ thumbOffset: 0
9022
+ });
9023
+ const [horizontal, setHorizontal] = react.useState({
9024
+ visible: false,
9025
+ thumbSize: 0,
9026
+ thumbOffset: 0
9027
+ });
9028
+ const update = react.useCallback(() => {
9029
+ const el = scrollRef.current;
9030
+ if (!el) return;
9031
+ setVertical(getMetrics(el.clientHeight, el.scrollHeight, el.scrollTop));
9032
+ setHorizontal(getMetrics(el.clientWidth, el.scrollWidth, el.scrollLeft));
9033
+ }, [scrollRef]);
9034
+ react.useEffect(() => {
9035
+ const el = scrollRef.current;
9036
+ if (!el) return;
9037
+ update();
9038
+ el.addEventListener("scroll", update, { passive: true });
9039
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(update);
9040
+ observer?.observe(el);
9041
+ if (el.firstElementChild) observer?.observe(el.firstElementChild);
9042
+ return () => {
9043
+ el.removeEventListener("scroll", update);
9044
+ observer?.disconnect();
9045
+ };
9046
+ }, [scrollRef, update]);
9047
+ const dragVertical = (startEvent) => {
9048
+ const el = scrollRef.current;
9049
+ if (!el || !vertical.visible) return;
9050
+ startEvent.preventDefault();
9051
+ startEvent.currentTarget.setPointerCapture(startEvent.pointerId);
9052
+ const startPointer = startEvent.clientY;
9053
+ const startScrollTop = el.scrollTop;
9054
+ const maxThumbOffset = el.clientHeight - vertical.thumbSize;
9055
+ const maxScrollTop = el.scrollHeight - el.clientHeight;
9056
+ if (maxThumbOffset <= 0 || maxScrollTop <= 0) return;
9057
+ const onPointerMove = (moveEvent) => {
9058
+ const delta = moveEvent.clientY - startPointer;
9059
+ el.scrollTop = startScrollTop + delta / maxThumbOffset * maxScrollTop;
9060
+ };
9061
+ const onPointerUp = () => {
9062
+ window.removeEventListener("pointermove", onPointerMove);
9063
+ window.removeEventListener("pointerup", onPointerUp);
9064
+ };
9065
+ window.addEventListener("pointermove", onPointerMove);
9066
+ window.addEventListener("pointerup", onPointerUp, { once: true });
9067
+ };
9068
+ const dragHorizontal = (startEvent) => {
9069
+ const el = scrollRef.current;
9070
+ if (!el || !horizontal.visible) return;
9071
+ startEvent.preventDefault();
9072
+ startEvent.currentTarget.setPointerCapture(startEvent.pointerId);
9073
+ const startPointer = startEvent.clientX;
9074
+ const startScrollLeft = el.scrollLeft;
9075
+ const maxThumbOffset = el.clientWidth - horizontal.thumbSize;
9076
+ const maxScrollLeft = el.scrollWidth - el.clientWidth;
9077
+ if (maxThumbOffset <= 0 || maxScrollLeft <= 0) return;
9078
+ const onPointerMove = (moveEvent) => {
9079
+ const delta = moveEvent.clientX - startPointer;
9080
+ el.scrollLeft = startScrollLeft + delta / maxThumbOffset * maxScrollLeft;
9081
+ };
9082
+ const onPointerUp = () => {
9083
+ window.removeEventListener("pointermove", onPointerMove);
9084
+ window.removeEventListener("pointerup", onPointerUp);
9085
+ };
9086
+ window.addEventListener("pointermove", onPointerMove);
9087
+ window.addEventListener("pointerup", onPointerUp, { once: true });
9088
+ };
9089
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9090
+ vertical.visible && /* @__PURE__ */ jsxRuntime.jsx(
9091
+ "div",
9092
+ {
9093
+ "aria-hidden": "true",
9094
+ className: "pointer-events-none absolute bottom-0 right-0 top-0 z-[1] w-[12px]",
9095
+ style: { bottom: horizontal.visible ? SCROLLBAR_SIZE : 0 },
9096
+ children: /* @__PURE__ */ jsxRuntime.jsx(
9097
+ "div",
9098
+ {
9099
+ className: "pointer-events-auto absolute right-[2px] w-[8px] cursor-default touch-none rounded-full bg-[var(--color-grey-45)]",
9100
+ style: {
9101
+ height: vertical.thumbSize,
9102
+ transform: `translateY(${vertical.thumbOffset}px)`
9103
+ },
9104
+ onPointerDown: dragVertical
9105
+ }
9106
+ )
9107
+ }
9108
+ ),
9109
+ horizontal.visible && /* @__PURE__ */ jsxRuntime.jsx(
9110
+ "div",
9111
+ {
9112
+ "aria-hidden": "true",
9113
+ className: "pointer-events-none absolute bottom-0 left-0 right-0 z-[1] h-[12px]",
9114
+ style: { right: vertical.visible ? SCROLLBAR_SIZE : 0 },
9115
+ children: /* @__PURE__ */ jsxRuntime.jsx(
9116
+ "div",
9117
+ {
9118
+ className: "pointer-events-auto absolute bottom-[2px] h-[8px] cursor-default touch-none rounded-full bg-[var(--color-grey-45)]",
9119
+ style: {
9120
+ width: horizontal.thumbSize,
9121
+ transform: `translateX(${horizontal.thumbOffset}px)`
9122
+ },
9123
+ onPointerDown: dragHorizontal
9124
+ }
9125
+ )
9126
+ }
9127
+ )
9128
+ ] });
9129
+ }
8888
9130
  var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
8889
9131
  background = "frame",
8890
9132
  scrollEndSpacing = true,
9133
+ overlayScrollbar = false,
8891
9134
  contentHeight = "auto",
8892
9135
  header,
8893
9136
  className,
@@ -8898,6 +9141,14 @@ var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
8898
9141
  }, ref) {
8899
9142
  const layout = react.useContext(SLayoutContext);
8900
9143
  const gridStyle = layout?.header === "full" ? { gridArea: "page" } : void 0;
9144
+ const scrollRef = react.useRef(null);
9145
+ const setMainRef = react.useCallback(
9146
+ (node) => {
9147
+ scrollRef.current = node;
9148
+ setForwardedRef(ref, node);
9149
+ },
9150
+ [ref]
9151
+ );
8901
9152
  const [scrolled, setScrolled] = react.useState(false);
8902
9153
  const handleScroll = (e) => {
8903
9154
  onScroll?.(e);
@@ -8907,21 +9158,54 @@ var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
8907
9158
  const main = /* @__PURE__ */ jsxRuntime.jsx(
8908
9159
  "main",
8909
9160
  {
8910
- ref,
9161
+ ref: setMainRef,
8911
9162
  className: cn(
8912
9163
  "box-border min-h-0 min-w-0 flex-1 overflow-auto p-[var(--cmp-pageBody-padding-default)]",
9164
+ overlayScrollbar && "h-full",
8913
9165
  !fill && scrollEndSpacing && "pb-[var(--cmp-pageBody-padding-scrollEnd)]",
8914
- SCROLLBAR_CLASS,
9166
+ overlayScrollbar ? SCROLLBAR_HIDDEN_CLASS : `${SCROLLBAR_CLASS} ${NATIVE_SCROLLBAR_BACKGROUND_CLASS[background]}`,
8915
9167
  BACKGROUND_CLASS[background],
8916
9168
  className
8917
9169
  ),
8918
- style: header == null ? { ...gridStyle, ...style } : style,
9170
+ style: header == null && !overlayScrollbar ? { ...gridStyle, ...style } : style,
8919
9171
  onScroll: handleScroll,
8920
9172
  ...rest,
8921
9173
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(fill && "h-full"), style: { minWidth: MIN_CONTENT_WIDTH }, children })
8922
9174
  }
8923
9175
  );
8924
- if (header == null) return main;
9176
+ if (!overlayScrollbar) {
9177
+ if (header == null) return main;
9178
+ return (
9179
+ // fix 가 아닌 헤더는 자기 배경이 투명이라(SPageHeader.tsx) 이 배경이 그대로 비친다.
9180
+ /* @__PURE__ */ jsxRuntime.jsxs(
9181
+ "div",
9182
+ {
9183
+ className: cn("flex min-h-0 min-w-0 flex-1 flex-col", BACKGROUND_CLASS[background]),
9184
+ style: gridStyle,
9185
+ children: [
9186
+ /* @__PURE__ */ jsxRuntime.jsx(SPageHeader, { ...header, scrolled }),
9187
+ main
9188
+ ]
9189
+ }
9190
+ )
9191
+ );
9192
+ }
9193
+ if (header == null) {
9194
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9195
+ "div",
9196
+ {
9197
+ className: cn(
9198
+ "relative min-h-0 min-w-0 flex-1 overflow-hidden",
9199
+ BACKGROUND_CLASS[background]
9200
+ ),
9201
+ style: gridStyle,
9202
+ children: [
9203
+ main,
9204
+ /* @__PURE__ */ jsxRuntime.jsx(SPageOverlayScrollbars, { scrollRef })
9205
+ ]
9206
+ }
9207
+ );
9208
+ }
8925
9209
  return (
8926
9210
  // fix 가 아닌 헤더는 자기 배경이 투명이라(SPageHeader.tsx) 이 배경이 그대로 비친다 —
8927
9211
  // 그래서 SPage 의 background 를 main 뿐 아니라 여기에도 칠한다(스크롤바 관련 클래스는
@@ -8933,7 +9217,10 @@ var SPage = /* @__PURE__ */ react.forwardRef(function SPage2({
8933
9217
  style: gridStyle,
8934
9218
  children: [
8935
9219
  /* @__PURE__ */ jsxRuntime.jsx(SPageHeader, { ...header, scrolled }),
8936
- main
9220
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative min-h-0 min-w-0 flex-1 overflow-hidden", children: [
9221
+ main,
9222
+ /* @__PURE__ */ jsxRuntime.jsx(SPageOverlayScrollbars, { scrollRef })
9223
+ ] })
8937
9224
  ]
8938
9225
  }
8939
9226
  )
@@ -11240,6 +11527,67 @@ var STableBar = /* @__PURE__ */ react.forwardRef(function STableBar2({ total, se
11240
11527
 
11241
11528
  // src/lib/autofill.ts
11242
11529
  var AUTOFILL_RESET_CLASS = "autofill:[-webkit-text-fill-color:currentColor] autofill:[box-shadow:0_0_0_1000px_var(--sys-color-field-bg-default)_inset] autofill:[transition:background-color_5000s_ease-in-out_0s] [&:-webkit-autofill]:[-webkit-text-fill-color:currentColor] [&:-webkit-autofill]:[box-shadow:0_0_0_1000px_var(--sys-color-field-bg-default)_inset] [&:-webkit-autofill]:[transition:background-color_5000s_ease-in-out_0s]";
11530
+ var HIDE_DELAY_MS2 = 100;
11531
+ function mergeRefs(...refs) {
11532
+ return (node) => {
11533
+ for (const ref of refs) {
11534
+ if (!ref) continue;
11535
+ if (typeof ref === "function") ref(node);
11536
+ else ref.current = node;
11537
+ }
11538
+ };
11539
+ }
11540
+ function useTruncatedValueTooltip({
11541
+ enabled,
11542
+ text
11543
+ }) {
11544
+ const portalContainer = usePortalContainer();
11545
+ const elRef = react.useRef(null);
11546
+ const [open, setOpen] = react.useState(false);
11547
+ const hideTimer = react.useRef(void 0);
11548
+ const cancelHide = react.useCallback(() => {
11549
+ if (hideTimer.current) {
11550
+ clearTimeout(hideTimer.current);
11551
+ hideTimer.current = void 0;
11552
+ }
11553
+ }, []);
11554
+ const startHide = react.useCallback(() => {
11555
+ cancelHide();
11556
+ hideTimer.current = setTimeout(() => setOpen(false), HIDE_DELAY_MS2);
11557
+ }, [cancelHide]);
11558
+ const onMouseEnter = react.useCallback(() => {
11559
+ cancelHide();
11560
+ const el = elRef.current;
11561
+ if (!el) return;
11562
+ if (el.scrollWidth - el.clientWidth > 1) setOpen(true);
11563
+ }, [cancelHide]);
11564
+ react.useEffect(() => {
11565
+ if (!enabled || text === "") setOpen(false);
11566
+ }, [enabled, text]);
11567
+ react.useEffect(() => cancelHide, [cancelHide]);
11568
+ const active = enabled && text !== "";
11569
+ return {
11570
+ valueRef: elRef,
11571
+ onMouseEnter: active ? onMouseEnter : cancelHide,
11572
+ onMouseLeave: active ? startHide : cancelHide,
11573
+ tooltip: active ? /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: setOpen, children: [
11574
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Anchor, { virtualRef: elRef }),
11575
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
11576
+ RPopover10__namespace.Content,
11577
+ {
11578
+ side: "top",
11579
+ sideOffset: 4,
11580
+ "aria-hidden": true,
11581
+ className: cn("z-50", FLOATING_SLIDE_ANIM),
11582
+ onOpenAutoFocus: (e) => e.preventDefault(),
11583
+ onMouseEnter: cancelHide,
11584
+ onMouseLeave: startHide,
11585
+ children: /* @__PURE__ */ jsxRuntime.jsx(STag, { shape: "square", size: "xs", color: "grey", label: text })
11586
+ }
11587
+ ) })
11588
+ ] }) : null
11589
+ };
11590
+ }
11243
11591
  var FONT = {
11244
11592
  sm: { fontSize: 12, lineHeight: 20, paddingX: "var(--cmp-textinput-sm-paddingX)" },
11245
11593
  md: { fontSize: 14, lineHeight: 24, paddingX: "var(--cmp-textinput-md-paddingX)" }
@@ -11297,6 +11645,10 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
11297
11645
  const resolvedError = error || ruleError !== "";
11298
11646
  const resolvedErrorMessage = ruleError !== "" ? ruleError : errorMessage;
11299
11647
  const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
11648
+ const valueTooltip = useTruncatedValueTooltip({
11649
+ enabled: readOnly && !disabled,
11650
+ text: String(value ?? "")
11651
+ });
11300
11652
  return /* @__PURE__ */ jsxRuntime.jsx(
11301
11653
  SField,
11302
11654
  {
@@ -11337,7 +11689,7 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
11337
11689
  /* @__PURE__ */ jsxRuntime.jsx(
11338
11690
  "input",
11339
11691
  {
11340
- ref,
11692
+ ref: mergeRefs(ref, valueTooltip.valueRef),
11341
11693
  type: inputType,
11342
11694
  value: value ?? "",
11343
11695
  disabled,
@@ -11362,9 +11714,18 @@ var SInput = /* @__PURE__ */ react.forwardRef(function SInput2({
11362
11714
  color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--sys-color-field-text-default)",
11363
11715
  ...inputStyle
11364
11716
  },
11365
- ...rest
11717
+ ...rest,
11718
+ onMouseEnter: (e) => {
11719
+ rest.onMouseEnter?.(e);
11720
+ valueTooltip.onMouseEnter();
11721
+ },
11722
+ onMouseLeave: (e) => {
11723
+ rest.onMouseLeave?.(e);
11724
+ valueTooltip.onMouseLeave();
11725
+ }
11366
11726
  }
11367
11727
  ),
11728
+ valueTooltip.tooltip,
11368
11729
  suffix != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex flex-shrink-0 items-center", children: suffix }),
11369
11730
  clearable && hasValue && !disabled && !readOnly && /* @__PURE__ */ jsxRuntime.jsx(
11370
11731
  SGhostButton,
@@ -11598,8 +11959,10 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
11598
11959
  const [display, setDisplay] = react.useState(() => formatWithCommas(numValue));
11599
11960
  const [ruleError, setRuleError] = react.useState("");
11600
11961
  const innerRef = react.useRef(null);
11962
+ const valueTooltip = useTruncatedValueTooltip({ enabled: readOnly && !disabled, text: display });
11601
11963
  const setRefs2 = (el) => {
11602
11964
  innerRef.current = el;
11965
+ valueTooltip.valueRef.current = el;
11603
11966
  if (typeof ref === "function") ref(el);
11604
11967
  else if (ref) ref.current = el;
11605
11968
  };
@@ -11813,9 +12176,12 @@ var SNumberInput = /* @__PURE__ */ react.forwardRef(function SNumberInput2({
11813
12176
  textAlign: useButton ? "center" : "right",
11814
12177
  color: disabled ? "var(--cmp-numberInput-text-disabled)" : "var(--cmp-numberInput-text-default)",
11815
12178
  ...inputStyle
11816
- }
12179
+ },
12180
+ onMouseEnter: valueTooltip.onMouseEnter,
12181
+ onMouseLeave: valueTooltip.onMouseLeave
11817
12182
  }
11818
12183
  ),
12184
+ valueTooltip.tooltip,
11819
12185
  inputSuffix !== "" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", style: { color: affixColor }, children: inputSuffix }),
11820
12186
  useButton && stepper("inc")
11821
12187
  ]
@@ -12556,8 +12922,8 @@ function SDatePicker({
12556
12922
  disabled,
12557
12923
  className,
12558
12924
  style,
12559
- children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open, onOpenChange: (o) => !disabled && setOpen(o), children: [
12560
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
12925
+ children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: (o) => !disabled && setOpen(o), children: [
12926
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
12561
12927
  "button",
12562
12928
  {
12563
12929
  type: "button",
@@ -12593,8 +12959,8 @@ function SDatePicker({
12593
12959
  ]
12594
12960
  }
12595
12961
  ) }),
12596
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
12597
- RPopover9__namespace.Content,
12962
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
12963
+ RPopover10__namespace.Content,
12598
12964
  {
12599
12965
  side: "bottom",
12600
12966
  align: mode === "date" ? "start" : "center",
@@ -13060,7 +13426,7 @@ function SDateRangePicker({
13060
13426
  className,
13061
13427
  style,
13062
13428
  children: /* @__PURE__ */ jsxRuntime.jsxs(
13063
- RPopover9__namespace.Root,
13429
+ RPopover10__namespace.Root,
13064
13430
  {
13065
13431
  open,
13066
13432
  onOpenChange: (o) => {
@@ -13069,7 +13435,7 @@ function SDateRangePicker({
13069
13435
  if (!o) setPendingStart(null);
13070
13436
  },
13071
13437
  children: [
13072
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
13438
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
13073
13439
  "button",
13074
13440
  {
13075
13441
  type: "button",
@@ -13110,8 +13476,8 @@ function SDateRangePicker({
13110
13476
  ]
13111
13477
  }
13112
13478
  ) }),
13113
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
13114
- RPopover9__namespace.Content,
13479
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
13480
+ RPopover10__namespace.Content,
13115
13481
  {
13116
13482
  side: "bottom",
13117
13483
  align: "start",
@@ -14637,8 +15003,8 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
14637
15003
  })(),
14638
15004
  hasRightActions && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14639
15005
  /* @__PURE__ */ jsxRuntime.jsx(Divider, { inset: true }),
14640
- hasAddButton && /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open: addOpen, onOpenChange: setAddOpen, children: [
14641
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
15006
+ hasAddButton && /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: addOpen, onOpenChange: setAddOpen, children: [
15007
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
14642
15008
  "button",
14643
15009
  {
14644
15010
  type: "button",
@@ -14663,8 +15029,8 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
14663
15029
  ]
14664
15030
  }
14665
15031
  ) }),
14666
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
14667
- RPopover9__namespace.Content,
15032
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
15033
+ RPopover10__namespace.Content,
14668
15034
  {
14669
15035
  side: "bottom",
14670
15036
  align: "start",
@@ -14704,17 +15070,17 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
14704
15070
  )
14705
15071
  ] })
14706
15072
  ] }),
14707
- /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open: openKey != null, onOpenChange: (next) => !next && setOpenKey(null), children: [
15073
+ /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: openKey != null, onOpenChange: (next) => !next && setOpenKey(null), children: [
14708
15074
  /* @__PURE__ */ jsxRuntime.jsx(
14709
- RPopover9__namespace.Anchor,
15075
+ RPopover10__namespace.Anchor,
14710
15076
  {
14711
15077
  virtualRef: {
14712
15078
  current: openKey ? triggerRefs.current.get(openKey) : null
14713
15079
  }
14714
15080
  }
14715
15081
  ),
14716
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
14717
- RPopover9__namespace.Content,
15082
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
15083
+ RPopover10__namespace.Content,
14718
15084
  {
14719
15085
  side: "bottom",
14720
15086
  align: "start",
@@ -15254,8 +15620,8 @@ function InlineDatePresetFilter({
15254
15620
  applied && (rangeValue ? (
15255
15621
  // 뱃지 모양은 그대로 두고, 눌렀을 때 캘린더가 열려 기간을 직접 다시 고를 수 있게 한다.
15256
15622
  // 직접 고르면 프리셋 선택은 해제된다.
15257
- /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open: pickerOpen, onOpenChange: setPickerOpen, children: [
15258
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
15623
+ /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open: pickerOpen, onOpenChange: setPickerOpen, children: [
15624
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
15259
15625
  "button",
15260
15626
  {
15261
15627
  type: "button",
@@ -15264,8 +15630,8 @@ function InlineDatePresetFilter({
15264
15630
  children: badge
15265
15631
  }
15266
15632
  ) }),
15267
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
15268
- RPopover9__namespace.Content,
15633
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
15634
+ RPopover10__namespace.Content,
15269
15635
  {
15270
15636
  side: "bottom",
15271
15637
  align: "start",
@@ -16076,6 +16442,10 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
16076
16442
  });
16077
16443
  const resolvedError = error || ruleError !== "";
16078
16444
  const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
16445
+ const valueTooltip = useTruncatedValueTooltip({
16446
+ enabled: readOnly && !disabled,
16447
+ text: String(value ?? "")
16448
+ });
16079
16449
  return /* @__PURE__ */ jsxRuntime.jsx(
16080
16450
  SField,
16081
16451
  {
@@ -16112,7 +16482,7 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
16112
16482
  /* @__PURE__ */ jsxRuntime.jsx(
16113
16483
  "input",
16114
16484
  {
16115
- ref,
16485
+ ref: mergeRefs(ref, valueTooltip.valueRef),
16116
16486
  name,
16117
16487
  type: "text",
16118
16488
  value: value ?? "",
@@ -16138,9 +16508,12 @@ var SBarcodeInput = /* @__PURE__ */ react.forwardRef(
16138
16508
  fontSize: f.fontSize,
16139
16509
  color: disabled ? "var(--cmp-textinput-text-disabled)" : "var(--cmp-textinput-text-default)",
16140
16510
  ...inputStyle
16141
- }
16511
+ },
16512
+ onMouseEnter: valueTooltip.onMouseEnter,
16513
+ onMouseLeave: valueTooltip.onMouseLeave
16142
16514
  }
16143
16515
  ),
16516
+ valueTooltip.tooltip,
16144
16517
  suffix,
16145
16518
  clearable && hasValue && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
16146
16519
  SGhostButton,
@@ -16520,8 +16893,8 @@ function STimePicker({
16520
16893
  disabled,
16521
16894
  className,
16522
16895
  style,
16523
- children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open, onOpenChange: commitOpen, children: [
16524
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
16896
+ children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: commitOpen, children: [
16897
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
16525
16898
  "div",
16526
16899
  {
16527
16900
  ref: triggerRef,
@@ -16581,8 +16954,8 @@ function STimePicker({
16581
16954
  ]
16582
16955
  }
16583
16956
  ) }),
16584
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
16585
- RPopover9__namespace.Content,
16957
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
16958
+ RPopover10__namespace.Content,
16586
16959
  {
16587
16960
  side: "bottom",
16588
16961
  align: "start",
@@ -16987,8 +17360,8 @@ function STimeRangePicker({
16987
17360
  disabled,
16988
17361
  className,
16989
17362
  style,
16990
- children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover9__namespace.Root, { open, onOpenChange: commitOpen, children: [
16991
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
17363
+ children: /* @__PURE__ */ jsxRuntime.jsxs(RPopover10__namespace.Root, { open, onOpenChange: commitOpen, children: [
17364
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
16992
17365
  "div",
16993
17366
  {
16994
17367
  ref: triggerRef,
@@ -17048,8 +17421,8 @@ function STimeRangePicker({
17048
17421
  ]
17049
17422
  }
17050
17423
  ) }),
17051
- /* @__PURE__ */ jsxRuntime.jsx(RPopover9__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
17052
- RPopover9__namespace.Content,
17424
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover10__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
17425
+ RPopover10__namespace.Content,
17053
17426
  {
17054
17427
  side: "bottom",
17055
17428
  align: "start",