sellmate-design-system-react 0.7.0 → 0.8.1

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 (85) hide show
  1. package/dist/components/SBarcodeInput/SBarcodeInput.cjs +61 -49
  2. package/dist/components/SBarcodeInput/SBarcodeInput.cjs.map +1 -1
  3. package/dist/components/SBarcodeInput/SBarcodeInput.js +61 -49
  4. package/dist/components/SBarcodeInput/SBarcodeInput.js.map +1 -1
  5. package/dist/components/SChipInput/SChipInput.cjs +64 -49
  6. package/dist/components/SChipInput/SChipInput.cjs.map +1 -1
  7. package/dist/components/SChipInput/SChipInput.js +64 -49
  8. package/dist/components/SChipInput/SChipInput.js.map +1 -1
  9. package/dist/components/SDatePicker/SDatePicker.cjs +61 -49
  10. package/dist/components/SDatePicker/SDatePicker.cjs.map +1 -1
  11. package/dist/components/SDatePicker/SDatePicker.js +61 -49
  12. package/dist/components/SDatePicker/SDatePicker.js.map +1 -1
  13. package/dist/components/SDateRangePicker/SDateRangePicker.cjs +61 -49
  14. package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
  15. package/dist/components/SDateRangePicker/SDateRangePicker.js +61 -49
  16. package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
  17. package/dist/components/SField/SField.cjs +61 -49
  18. package/dist/components/SField/SField.cjs.map +1 -1
  19. package/dist/components/SField/SField.d.ts +5 -2
  20. package/dist/components/SField/SField.js +61 -49
  21. package/dist/components/SField/SField.js.map +1 -1
  22. package/dist/components/SFilePicker/SFilePicker.cjs +61 -49
  23. package/dist/components/SFilePicker/SFilePicker.cjs.map +1 -1
  24. package/dist/components/SFilePicker/SFilePicker.js +61 -49
  25. package/dist/components/SFilePicker/SFilePicker.js.map +1 -1
  26. package/dist/components/SInput/SInput.cjs +61 -49
  27. package/dist/components/SInput/SInput.cjs.map +1 -1
  28. package/dist/components/SInput/SInput.js +61 -49
  29. package/dist/components/SInput/SInput.js.map +1 -1
  30. package/dist/components/SKeyValueTable/SKeyValueTable.cjs +72 -50
  31. package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
  32. package/dist/components/SKeyValueTable/SKeyValueTable.js +72 -50
  33. package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
  34. package/dist/components/SNumberInput/SNumberInput.cjs +61 -49
  35. package/dist/components/SNumberInput/SNumberInput.cjs.map +1 -1
  36. package/dist/components/SNumberInput/SNumberInput.js +61 -49
  37. package/dist/components/SNumberInput/SNumberInput.js.map +1 -1
  38. package/dist/components/SPage/SPage.cjs +19 -2
  39. package/dist/components/SPage/SPage.cjs.map +1 -1
  40. package/dist/components/SPage/SPage.d.ts +7 -1
  41. package/dist/components/SPage/SPage.js +19 -2
  42. package/dist/components/SPage/SPage.js.map +1 -1
  43. package/dist/components/SPage/index.d.ts +1 -0
  44. package/dist/components/SPage/page.config.d.ts +8 -0
  45. package/dist/components/SPopup/SPopup.cjs.map +1 -1
  46. package/dist/components/SPopup/SPopup.js.map +1 -1
  47. package/dist/components/SPortal/SPortal.cjs +3 -0
  48. package/dist/components/SPortal/SPortal.cjs.map +1 -1
  49. package/dist/components/SPortal/SPortal.d.ts +3 -1
  50. package/dist/components/SPortal/SPortal.js +3 -0
  51. package/dist/components/SPortal/SPortal.js.map +1 -1
  52. package/dist/components/SScrollArea/SScrollArea.cjs.map +1 -1
  53. package/dist/components/SScrollArea/SScrollArea.js.map +1 -1
  54. package/dist/components/SSelect/SSelect.cjs +72 -50
  55. package/dist/components/SSelect/SSelect.cjs.map +1 -1
  56. package/dist/components/SSelect/SSelect.js +72 -50
  57. package/dist/components/SSelect/SSelect.js.map +1 -1
  58. package/dist/components/STable/STable.cjs +78 -56
  59. package/dist/components/STable/STable.cjs.map +1 -1
  60. package/dist/components/STable/STable.d.ts +2 -0
  61. package/dist/components/STable/STable.js +78 -56
  62. package/dist/components/STable/STable.js.map +1 -1
  63. package/dist/components/STextarea/STextarea.cjs +61 -49
  64. package/dist/components/STextarea/STextarea.cjs.map +1 -1
  65. package/dist/components/STextarea/STextarea.js +61 -49
  66. package/dist/components/STextarea/STextarea.js.map +1 -1
  67. package/dist/components/STimePicker/STimePicker.cjs +61 -49
  68. package/dist/components/STimePicker/STimePicker.cjs.map +1 -1
  69. package/dist/components/STimePicker/STimePicker.js +61 -49
  70. package/dist/components/STimePicker/STimePicker.js.map +1 -1
  71. package/dist/components/STimeRangePicker/STimeRangePicker.cjs +61 -49
  72. package/dist/components/STimeRangePicker/STimeRangePicker.cjs.map +1 -1
  73. package/dist/components/STimeRangePicker/STimeRangePicker.js +61 -49
  74. package/dist/components/STimeRangePicker/STimeRangePicker.js.map +1 -1
  75. package/dist/index.cjs +95 -58
  76. package/dist/index.cjs.map +1 -1
  77. package/dist/index.js +95 -59
  78. package/dist/index.js.map +1 -1
  79. package/dist/lib/scrollbar.cjs +2 -0
  80. package/dist/lib/scrollbar.cjs.map +1 -1
  81. package/dist/lib/scrollbar.d.ts +13 -1
  82. package/dist/lib/scrollbar.js +2 -1
  83. package/dist/lib/scrollbar.js.map +1 -1
  84. package/dist/styles.css +53 -3
  85. package/package.json +1 -1
@@ -23,6 +23,8 @@ export interface STableColumn {
23
23
  iconColor?: SColor;
24
24
  /** 셀 커스텀 렌더 (React 확장) */
25
25
  render?: (row: SRow, value: any) => ReactNode;
26
+ /** 헤더 셀 커스텀 렌더 (React 확장) */
27
+ renderHeader?: (column: STableColumn, index: number) => ReactNode;
26
28
  tdClass?: string;
27
29
  /** 헤더 셀 커스텀 클래스/스타일 (sd-table thClass/thStyle) */
28
30
  thClass?: string;
@@ -3635,6 +3635,7 @@ var SField = forwardRef(function SField2({
3635
3635
  const resolvedSuccess = status === "pass";
3636
3636
  const showError = resolvedError && errorMessage !== "";
3637
3637
  const interactive = !disabled && !readOnly;
3638
+ const hug = cssLen(width) !== void 0;
3638
3639
  const borderColor = borderless ? "transparent" : disabled ? "var(--color-grey-45)" : interactive && focused ? "var(--sys-color-field-border-focus)" : resolvedSuccess ? "var(--sys-color-field-border-success)" : resolvedError ? "var(--sys-color-field-border-danger)" : "var(--sys-color-field-border-default)";
3639
3640
  const bgColor = borderless ? "transparent" : disabled ? "var(--color-grey-30)" : readOnly ? "var(--sys-color-field-bg-readOnly)" : "var(--sys-color-field-bg-default)";
3640
3641
  const textColor = disabled ? "var(--color-grey-65)" : readOnly ? "var(--sys-color-field-text-readOnly)" : "var(--sys-color-field-text-default)";
@@ -3643,7 +3644,13 @@ var SField = forwardRef(function SField2({
3643
3644
  {
3644
3645
  ref: rootRef,
3645
3646
  "data-name": name || void 0,
3646
- className: cn("inline-flex h-fit w-full flex-col", className),
3647
+ className: cn(
3648
+ "h-fit flex-col",
3649
+ // hug 시 inline-flex 를 유지하면 기존에 세로로 쌓여 있던 필드들이 한 줄에 붙어버리므로
3650
+ // 블록 레벨(flex)로 두어 쌓임은 그대로 유지한다. 나란히 놓으려면 부모를 flex 로.
3651
+ hug ? "flex w-fit max-w-full" : "inline-flex w-full",
3652
+ className
3653
+ ),
3647
3654
  style,
3648
3655
  onMouseEnter,
3649
3656
  onMouseLeave,
@@ -3681,55 +3688,60 @@ var SField = forwardRef(function SField2({
3681
3688
  ]
3682
3689
  }
3683
3690
  ),
3684
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
3685
- /* @__PURE__ */ jsxs(
3686
- "div",
3687
- {
3688
- className: cn(
3689
- "relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
3690
- interactive && !borderless && "hover:border-(--sys-color-field-border-focus) hover:shadow-[0px_0px_4px_0px_#0071ff66] focus-within:border-(--sys-color-field-border-focus) focus-within:shadow-[0px_0px_4px_0px_#0071ff66]",
3691
- disabled && "cursor-not-allowed"
3691
+ /* @__PURE__ */ jsxs(
3692
+ "div",
3693
+ {
3694
+ className: cn("flex min-w-0 flex-col", !hug && "flex-1"),
3695
+ style: { width: cssLen(width), minWidth: cssLen(minWidth) },
3696
+ children: [
3697
+ /* @__PURE__ */ jsxs(
3698
+ "div",
3699
+ {
3700
+ className: cn(
3701
+ "relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
3702
+ interactive && !borderless && "hover:border-(--sys-color-field-border-focus) hover:shadow-[0px_0px_4px_0px_#0071ff66] focus-within:border-(--sys-color-field-border-focus) focus-within:shadow-[0px_0px_4px_0px_#0071ff66]",
3703
+ disabled && "cursor-not-allowed"
3704
+ ),
3705
+ style: {
3706
+ // @ts-expect-error CSS 변수
3707
+ "--field-bc": borderColor,
3708
+ // focused/hovered prop이 명시된 경우 강조를 즉시 반영
3709
+ ...interactive && !borderless && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
3710
+ ...multiline ? { minHeight: s.height } : { height: s.height },
3711
+ "borderRadius": s.radius,
3712
+ "background": bgColor,
3713
+ "color": textColor
3714
+ },
3715
+ "data-focused": focused || void 0,
3716
+ "data-hovered": hovered || void 0,
3717
+ children: [
3718
+ effectiveAddonLabel !== "" && /* @__PURE__ */ jsxs(
3719
+ "div",
3720
+ {
3721
+ className: "flex shrink-0 items-center gap-(--cmp-field-addonLabel-gap) whitespace-nowrap border-r border-solid px-(--cmp-field-addonLabel-paddingX) text-12 font-medium leading-20",
3722
+ style: {
3723
+ // 원본 sd-field: labelWidth가 addon 폭(--sd-field-addon-width)에도 적용됨
3724
+ width: cssLen(labelWidth),
3725
+ justifyContent: ALIGN[addonAlign],
3726
+ background: "var(--cmp-field-addonLabel-bg)",
3727
+ borderRightColor: disabled ? "var(--cmp-field-addonLabel-border-disabled)" : "var(--cmp-field-addonLabel-border-default)",
3728
+ borderTopLeftRadius: s.radius - 1,
3729
+ borderBottomLeftRadius: s.radius - 1
3730
+ },
3731
+ children: [
3732
+ icon && !label && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon, color: iconColor }),
3733
+ effectiveAddonLabel
3734
+ ]
3735
+ }
3736
+ ),
3737
+ /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1", children })
3738
+ ]
3739
+ }
3692
3740
  ),
3693
- style: {
3694
- // @ts-expect-error CSS 변수
3695
- "--field-bc": borderColor,
3696
- // focused/hovered prop이 명시된 경우 강조를 즉시 반영
3697
- ...interactive && !borderless && focused ? { boxShadow: "0px 0px 4px 0px #0071ff66" } : {},
3698
- ...multiline ? { minHeight: s.height } : { height: s.height },
3699
- "minWidth": cssLen(minWidth),
3700
- "width": cssLen(width),
3701
- "borderRadius": s.radius,
3702
- "background": bgColor,
3703
- "color": textColor
3704
- },
3705
- "data-focused": focused || void 0,
3706
- "data-hovered": hovered || void 0,
3707
- children: [
3708
- effectiveAddonLabel !== "" && /* @__PURE__ */ jsxs(
3709
- "div",
3710
- {
3711
- className: "flex shrink-0 items-center gap-(--cmp-field-addonLabel-gap) whitespace-nowrap border-r border-solid px-(--cmp-field-addonLabel-paddingX) text-12 font-medium leading-20",
3712
- style: {
3713
- // 원본 sd-field: labelWidth가 addon 폭(--sd-field-addon-width)에도 적용됨
3714
- width: cssLen(labelWidth),
3715
- justifyContent: ALIGN[addonAlign],
3716
- background: "var(--cmp-field-addonLabel-bg)",
3717
- borderRightColor: disabled ? "var(--cmp-field-addonLabel-border-disabled)" : "var(--cmp-field-addonLabel-border-default)",
3718
- borderTopLeftRadius: s.radius - 1,
3719
- borderBottomLeftRadius: s.radius - 1
3720
- },
3721
- children: [
3722
- icon && !label && /* @__PURE__ */ jsx(SIcon, { name: icon, size: s.icon, color: iconColor }),
3723
- effectiveAddonLabel
3724
- ]
3725
- }
3726
- ),
3727
- /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1", children })
3728
- ]
3729
- }
3730
- ),
3731
- showError ? /* @__PURE__ */ jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-errorMessage-color)", children: errorMessage }) : hint !== "" ? /* @__PURE__ */ jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-hint-color)", children: hint }) : null
3732
- ] })
3741
+ showError ? /* @__PURE__ */ jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-errorMessage-color)", children: errorMessage }) : hint !== "" ? /* @__PURE__ */ jsx("div", { className: "mt-(--cmp-field-contents-gap) text-12 font-normal leading-20 text-(--cmp-field-hint-color)", children: hint }) : null
3742
+ ]
3743
+ }
3744
+ )
3733
3745
  ] })
3734
3746
  }
3735
3747
  );
@@ -3750,6 +3762,7 @@ function SPortal({
3750
3762
  viewportPadding = 0,
3751
3763
  onOpenAutoFocus,
3752
3764
  onCloseAutoFocus,
3765
+ onPointerDownOutside,
3753
3766
  children,
3754
3767
  className,
3755
3768
  style,
@@ -3778,7 +3791,9 @@ function SPortal({
3778
3791
  onPointerDownOutside: (e) => {
3779
3792
  if (persistent || anchorRef.current?.contains(e.target)) {
3780
3793
  e.preventDefault();
3794
+ return;
3781
3795
  }
3796
+ onPointerDownOutside?.(e);
3782
3797
  },
3783
3798
  onFocusOutside: (e) => {
3784
3799
  if (persistent || anchorRef.current?.contains(e.target)) {
@@ -3883,6 +3898,7 @@ var SSelect = forwardRef(function SSelect2({
3883
3898
  const triggerRef = useRef(null);
3884
3899
  const searchInputRef = useRef(null);
3885
3900
  const listRef = useRef(null);
3901
+ const dismissedByPointerRef = useRef(false);
3886
3902
  const flat = useMemo(() => flattenOptions(options), [options]);
3887
3903
  const selectable = useMemo(() => selectableOptions(flat), [flat]);
3888
3904
  const hasLeaf = useMemo(() => flat.some((o) => !o.isGroup), [flat]);
@@ -3912,7 +3928,9 @@ var SSelect = forwardRef(function SSelect2({
3912
3928
  const commitOpen = (next) => {
3913
3929
  setOpen(next);
3914
3930
  onOpenChange?.(next);
3915
- if (!next) {
3931
+ if (next) {
3932
+ dismissedByPointerRef.current = false;
3933
+ } else {
3916
3934
  setPendingOpen(false);
3917
3935
  setSearch("");
3918
3936
  if (rules && rules.length > 0) {
@@ -4136,8 +4154,12 @@ var SSelect = forwardRef(function SSelect2({
4136
4154
  event.preventDefault();
4137
4155
  requestAnimationFrame(() => searchInputRef.current?.focus());
4138
4156
  },
4157
+ onPointerDownOutside: () => {
4158
+ dismissedByPointerRef.current = true;
4159
+ },
4139
4160
  onCloseAutoFocus: (event) => {
4140
4161
  event.preventDefault();
4162
+ if (dismissedByPointerRef.current) return;
4141
4163
  triggerRef.current?.focus();
4142
4164
  },
4143
4165
  className: "rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.1)]",
@@ -4643,7 +4665,7 @@ var STable = forwardRef(function STable2({
4643
4665
  position: "sticky",
4644
4666
  left: isLeft ? "var(--sticky-left-offset)" : void 0,
4645
4667
  right: isRight ? "var(--sticky-right-offset)" : void 0,
4646
- zIndex: 3
4668
+ zIndex: 6
4647
4669
  };
4648
4670
  };
4649
4671
  const stickyShadowClass = (i) => {
@@ -4700,7 +4722,7 @@ var STable = forwardRef(function STable2({
4700
4722
  {
4701
4723
  className: cn(
4702
4724
  // 원본 .th--selected: 48px 고정폭, 항상 left sticky, 체크박스 중앙정렬
4703
- "sticky left-0 z-[4] border-b border-solid border-[color:var(--cmp-table-border-color)] bg-[var(--cmp-table-header-bg)] text-center align-middle",
4725
+ "sticky left-0 z-[7] border-b border-solid border-[color:var(--cmp-table-border-color)] bg-[var(--cmp-table-header-bg)] text-center align-middle",
4704
4726
  stickyLeft === 0 && scrolledLeft && "shadow-[5px_0_8px_0_rgba(34,34,34,0.1)]"
4705
4727
  ),
4706
4728
  style: {
@@ -4725,13 +4747,13 @@ var STable = forwardRef(function STable2({
4725
4747
  {
4726
4748
  className: cn(
4727
4749
  "relative border-b border-solid border-[color:var(--cmp-table-border-color)] bg-[var(--cmp-table-header-bg)] px-[16px] text-[12px] font-medium leading-[20px] text-[color:var(--sys-color-fg-primary)]",
4728
- stickyInfo(i).isSticky && "z-[4]",
4750
+ stickyInfo(i).isSticky && "z-[6]",
4729
4751
  stickyShadowClass(i),
4730
4752
  col.thClass
4731
4753
  ),
4732
4754
  style: { textAlign: col.align ?? "left", ...cellStyle(i), ...col.thStyle },
4733
4755
  children: [
4734
- /* @__PURE__ */ jsxs(
4756
+ /* @__PURE__ */ jsx(
4735
4757
  "span",
4736
4758
  {
4737
4759
  className: cn(
@@ -4740,10 +4762,10 @@ var STable = forwardRef(function STable2({
4740
4762
  col.align === "center" && "justify-center",
4741
4763
  col.align === "right" && "justify-end"
4742
4764
  ),
4743
- children: [
4765
+ children: col.renderHeader ? col.renderHeader(col, i) : /* @__PURE__ */ jsxs(Fragment, { children: [
4744
4766
  col.icon && /* @__PURE__ */ jsx(SIcon, { name: col.icon, size: 16, color: col.iconColor }),
4745
4767
  /* @__PURE__ */ jsx("span", { className: "truncate", children: col.label })
4746
- ]
4768
+ ] })
4747
4769
  }
4748
4770
  ),
4749
4771
  resizable && !col.autoWidth && i < visibleCols.length - 1 && // 원본 th__resizer: 셀 우측 경계 안쪽 4px 그립(좌우 1px #CCCCCC 라인, 세로 16px).