sellmate-design-system-react 0.5.0 → 0.6.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 (38) hide show
  1. package/README.md +20 -0
  2. package/dist/components/SDateRangePicker/SDateRangePicker.cjs +180 -37
  3. package/dist/components/SDateRangePicker/SDateRangePicker.cjs.map +1 -1
  4. package/dist/components/SDateRangePicker/SDateRangePicker.d.ts +6 -1
  5. package/dist/components/SDateRangePicker/SDateRangePicker.js +180 -37
  6. package/dist/components/SDateRangePicker/SDateRangePicker.js.map +1 -1
  7. package/dist/components/SGnb/SGnb.cjs +145 -57
  8. package/dist/components/SGnb/SGnb.cjs.map +1 -1
  9. package/dist/components/SGnb/SGnb.d.ts +7 -1
  10. package/dist/components/SGnb/SGnb.js +146 -58
  11. package/dist/components/SGnb/SGnb.js.map +1 -1
  12. package/dist/components/SKeyValueTable/SKeyValueTable.cjs +180 -37
  13. package/dist/components/SKeyValueTable/SKeyValueTable.cjs.map +1 -1
  14. package/dist/components/SKeyValueTable/SKeyValueTable.js +180 -37
  15. package/dist/components/SKeyValueTable/SKeyValueTable.js.map +1 -1
  16. package/dist/components/SLayout/SLayout.cjs +21 -6
  17. package/dist/components/SLayout/SLayout.cjs.map +1 -1
  18. package/dist/components/SLayout/SLayout.d.ts +17 -2
  19. package/dist/components/SLayout/SLayout.js +21 -6
  20. package/dist/components/SLayout/SLayout.js.map +1 -1
  21. package/dist/components/SPage/SPage.cjs +21 -6
  22. package/dist/components/SPage/SPage.cjs.map +1 -1
  23. package/dist/components/SPage/SPage.js +21 -6
  24. package/dist/components/SPage/SPage.js.map +1 -1
  25. package/dist/components/SStepper/SStepper.cjs +3019 -0
  26. package/dist/components/SStepper/SStepper.cjs.map +1 -0
  27. package/dist/components/SStepper/SStepper.d.ts +16 -0
  28. package/dist/components/SStepper/SStepper.js +3017 -0
  29. package/dist/components/SStepper/SStepper.js.map +1 -0
  30. package/dist/components/SStepper/index.d.ts +2 -0
  31. package/dist/components/SStepper/stepper.config.d.ts +42 -0
  32. package/dist/index.cjs +500 -104
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.ts +1 -0
  35. package/dist/index.js +499 -105
  36. package/dist/index.js.map +1 -1
  37. package/dist/styles.css +61 -0
  38. package/package.json +3 -1
package/README.md CHANGED
@@ -135,6 +135,26 @@ export function Example() {
135
135
  - **단일 라이트 테마** — 다크모드는 지원하지 않습니다.
136
136
  - **타입 포함** — 모든 컴포넌트에 TypeScript 타입 정의(`.d.ts`)가 함께 제공됩니다.
137
137
 
138
+ ## 버전 업 / 릴리스
139
+
140
+ Stencil 쪽 `lerna version` 과 동일하게 **Conventional Commits 기반**으로 버전을 올리고 `CHANGELOG.md` 를 누적합니다. 이 패키지는 lerna 관리 대상이 아니라 전용 스크립트를 씁니다.
141
+
142
+ ```bash
143
+ # 마지막 릴리스 이후 커밋으로 상승 폭을 자동 추론 → package.json/CHANGELOG 갱신 + 릴리스 커밋
144
+ npm run version
145
+
146
+ # 실제로 바꾸지 않고 결과만 미리보기
147
+ npm run version:dry
148
+
149
+ # 루트에서도 실행 가능
150
+ npm run version:rn # (design-system 루트)
151
+ ```
152
+
153
+ - 마지막 `chore(release): react-native <ver>` 커밋 이후 `react-native/` 를 건드린 커밋을 모읍니다.
154
+ - `BREAKING CHANGE → major`, `feat → minor`, 그 외(`fix` 등) `→ patch` 로 버전을 올립니다.
155
+ - 주요 옵션: `--bump <major|minor|patch>` · `--release-as <x.y.z>` · `--pre-major`(0.x 유지) · `--tag` · `--no-commit` · `--dry-run` · `--force` (`node scripts/version.mjs --help`).
156
+ - push 는 하지 않습니다. 커밋/태그 확인 후 직접 push 하세요.
157
+
138
158
  ## 라이선스
139
159
 
140
160
  UNLICENSED — Sellmate 내부용 독점 패키지입니다. 무단 사용·복제·재배포를 금합니다.
@@ -3448,25 +3448,45 @@ function monthCells(year, month) {
3448
3448
  return cells;
3449
3449
  }
3450
3450
  var WEEK_LABELS = ["\uC77C", "\uC6D4", "\uD654", "\uC218", "\uBAA9", "\uAE08", "\uD1A0"];
3451
+ function splitDateTime(v) {
3452
+ if (!v) return { date: null, hour: "00", minute: "00" };
3453
+ const [date = "", time = ""] = v.split(" ");
3454
+ const [hour = "00", minute = "00"] = time.split(":");
3455
+ return { date: date || null, hour, minute };
3456
+ }
3451
3457
  function RangeCalendar({
3452
3458
  value,
3453
3459
  selectable,
3454
3460
  maxRange,
3461
+ useTimePicker = false,
3455
3462
  onSelect,
3456
3463
  onPendingStartChange,
3457
3464
  onViewChange
3458
3465
  }) {
3459
3466
  const today = todayStr();
3460
- const base = value?.[0] || today;
3467
+ const initial = splitDateTime(value?.[0]);
3468
+ const base = initial.date || today;
3461
3469
  const [y, setY] = react.useState(Number(base.split("-")[0]));
3462
3470
  const [m, setM] = react.useState(Number(base.split("-")[1]));
3463
- const [start, setStart] = react.useState(value?.[0] ?? null);
3464
- const [end, setEnd] = react.useState(value?.[1] ?? null);
3471
+ const [start, setStart] = react.useState(initial.date);
3472
+ const [end, setEnd] = react.useState(splitDateTime(value?.[1]).date);
3465
3473
  const [hover, setHover] = react.useState(null);
3474
+ const [sH, setSH] = react.useState(initial.hour);
3475
+ const [sM, setSM] = react.useState(initial.minute);
3476
+ const [eH, setEH] = react.useState(splitDateTime(value?.[1]).hour);
3477
+ const [eM, setEM] = react.useState(splitDateTime(value?.[1]).minute);
3478
+ const lastEmitted = react.useRef("");
3466
3479
  react.useEffect(() => {
3467
- setStart(value?.[0] ?? null);
3468
- setEnd(value?.[1] ?? null);
3469
- }, [value]);
3480
+ if (useTimePicker && JSON.stringify(value) === lastEmitted.current) return;
3481
+ const s = splitDateTime(value?.[0]);
3482
+ const e = splitDateTime(value?.[1]);
3483
+ setStart(s.date);
3484
+ setEnd(e.date);
3485
+ setSH(s.hour);
3486
+ setSM(s.minute);
3487
+ setEH(e.hour);
3488
+ setEM(e.minute);
3489
+ }, [value, useTimePicker]);
3470
3490
  const setBase = (ny, nm) => {
3471
3491
  setY(ny);
3472
3492
  setM(nm);
@@ -3510,18 +3530,53 @@ function RangeCalendar({
3510
3530
  const hasRange = !!(rStart && rEnd && rStart !== rEnd);
3511
3531
  const inRange = (d) => !!(rStart && rEnd && d > rStart && d < rEnd);
3512
3532
  const RANGE_BG = "var(--cmp-datepicker-calendar-range-bg)";
3533
+ const pad = (v) => String(Number(v) || 0).padStart(2, "0");
3534
+ const emit = (dateStart, dateEnd, time) => {
3535
+ const t = time ?? { sH, sM, eH, eM };
3536
+ const range = useTimePicker ? [`${dateStart} ${pad(t.sH)}:${pad(t.sM)}`, `${dateEnd} ${pad(t.eH)}:${pad(t.eM)}`] : [dateStart, dateEnd];
3537
+ lastEmitted.current = JSON.stringify(range);
3538
+ onSelect(range);
3539
+ };
3513
3540
  const click = (d) => {
3514
3541
  if (isDisabled(d)) return;
3515
3542
  if (!start || complete || d < start) {
3516
3543
  setStart(d);
3517
3544
  setEnd(null);
3518
3545
  setHover(null);
3546
+ if (useTimePicker) {
3547
+ setSH("00");
3548
+ setSM("00");
3549
+ setEH("23");
3550
+ setEM("59");
3551
+ }
3519
3552
  onPendingStartChange?.(d);
3520
3553
  return;
3521
3554
  }
3522
3555
  setEnd(d);
3523
3556
  onPendingStartChange?.(null);
3524
- onSelect([start, d]);
3557
+ emit(start, d, useTimePicker ? { sH, sM, eH: "23", eM: "59" } : void 0);
3558
+ };
3559
+ const changeTime = (which, part, raw) => {
3560
+ const digits = raw.replace(/\D/g, "").slice(0, 2);
3561
+ const max = part === "h" ? 23 : 59;
3562
+ const next = digits !== "" && Number(digits) > max ? String(max) : digits;
3563
+ const nextTime = { sH, sM, eH, eM };
3564
+ if (which === "start") nextTime[part === "h" ? "sH" : "sM"] = next;
3565
+ else nextTime[part === "h" ? "eH" : "eM"] = next;
3566
+ setSH(nextTime.sH);
3567
+ setSM(nextTime.sM);
3568
+ setEH(nextTime.eH);
3569
+ setEM(nextTime.eM);
3570
+ if (start && end) emit(start, end, nextTime);
3571
+ };
3572
+ const blurTime = (which, part) => {
3573
+ if (which === "start") {
3574
+ if (part === "h") setSH(pad(sH));
3575
+ else setSM(pad(sM));
3576
+ } else {
3577
+ if (part === "h") setEH(pad(eH));
3578
+ else setEM(pad(eM));
3579
+ }
3525
3580
  };
3526
3581
  const GRID_COLS = "grid grid-cols-[repeat(7,var(--cmp-datepicker-calendar-day-width))]";
3527
3582
  const renderPanel = (gy, gm, isLeft) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-[var(--cmp-datepicker-calendar-gap)]", children: [
@@ -3596,35 +3651,120 @@ function RangeCalendar({
3596
3651
  );
3597
3652
  }) })
3598
3653
  ] });
3599
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex h-[364px] flex-col gap-[var(--cmp-datepicker-calendar-gap)] rounded-[var(--cmp-datepicker-calendar-radius)] bg-[var(--cmp-datepicker-calendar-bg)] p-[var(--cmp-datepicker-calendar-paddingXY)] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.2)] select-none", children: [
3600
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
3601
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-[var(--cmp-datepicker-calendar-gap)] text-[14px] font-medium leading-[24px]", children: [
3602
- /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "chevronLeft", size: "xxs", ariaLabel: "prevYear", onClick: goPrevYear }),
3603
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-[40px] items-center justify-center text-center", children: y }),
3604
- /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "chevronRight", size: "xxs", ariaLabel: "nextYear", onClick: goNextYear })
3605
- ] }),
3606
- /* @__PURE__ */ jsxRuntime.jsx(
3607
- "button",
3608
- {
3609
- type: "button",
3610
- onClick: goToday,
3611
- className: "absolute right-0 h-[24px] min-w-[37px] cursor-pointer bg-transparent text-center text-[12px] font-medium leading-[24px] text-[color:var(--cmp-datepicker-calendar-day-default-text)] hover:underline",
3612
- children: "\uC624\uB298"
3613
- }
3614
- )
3615
- ] }),
3616
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-[var(--cmp-datepicker-calendar-range-panelGap)]", children: [
3617
- renderPanel(y, m, true),
3618
- /* @__PURE__ */ jsxRuntime.jsx(
3619
- "span",
3620
- {
3621
- className: "w-px shrink-0 self-stretch bg-[var(--cmp-datepicker-calendar-range-divider)]",
3622
- "aria-hidden": true
3623
- }
3654
+ const renderTimeSection = (which, date, suffix) => {
3655
+ const active = !!date;
3656
+ const [yy = "", mm = "", dd = ""] = date ? date.split("-") : [];
3657
+ const hour = which === "start" ? sH : eH;
3658
+ const minute = which === "start" ? sM : eM;
3659
+ const num = (n, strip) => active && n !== "" ? strip ? String(Number(n)) : n : "-";
3660
+ const INPUT_CLS = "h-[var(--cmp-datepicker-sm-height)] w-[40px] rounded-[var(--cmp-datepicker-sm-radius)] border border-solid border-[color:var(--cmp-datepicker-border-default)] bg-[var(--cmp-datepicker-bg-default)] text-center text-[12px] font-medium leading-[20px] text-[color:var(--cmp-datepicker-text-default)] outline-none placeholder:text-[color:var(--cmp-datepicker-text-disabled)] focus:border-[color:var(--cmp-datepicker-border-focus)] disabled:cursor-not-allowed";
3661
+ const LABEL = "text-[color:var(--cmp-datepicker-calendar-time-date-label)]";
3662
+ const UNIT = "text-[color:var(--cmp-datepicker-calendar-time-date-unit)]";
3663
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3664
+ "div",
3665
+ {
3666
+ className: cn(
3667
+ "flex flex-1 items-center justify-center gap-[var(--cmp-datepicker-calendar-time-section-gap)] rounded-[var(--cmp-datepicker-calendar-time-radius)] px-[var(--cmp-datepicker-calendar-time-paddingX)] py-[var(--cmp-datepicker-calendar-time-paddingY)] text-[12px] font-medium leading-[20px]",
3668
+ active ? "bg-[var(--cmp-datepicker-calendar-time-bg-selected)]" : "bg-[var(--cmp-datepicker-calendar-time-bg-default)]"
3669
+ ),
3670
+ children: [
3671
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-[var(--cmp-datepicker-calendar-time-date-gap)]", children: [
3672
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: LABEL, children: num(yy, false) }),
3673
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: UNIT, children: "\uB144" }),
3674
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: LABEL, children: num(mm, true) }),
3675
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: UNIT, children: "\uC6D4" }),
3676
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: LABEL, children: num(dd, true) }),
3677
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: UNIT, children: "\uC77C" })
3678
+ ] }),
3679
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-[var(--cmp-datepicker-calendar-time-unit-gap)]", children: [
3680
+ /* @__PURE__ */ jsxRuntime.jsx(
3681
+ "input",
3682
+ {
3683
+ type: "text",
3684
+ inputMode: "numeric",
3685
+ maxLength: 2,
3686
+ "aria-label": `${suffix} \uC2DC`,
3687
+ disabled: !active,
3688
+ value: active ? hour : "",
3689
+ placeholder: "--",
3690
+ onChange: (e) => changeTime(which, "h", e.target.value),
3691
+ onBlur: () => blurTime(which, "h"),
3692
+ className: INPUT_CLS
3693
+ }
3694
+ ),
3695
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: LABEL, children: ":" }),
3696
+ /* @__PURE__ */ jsxRuntime.jsx(
3697
+ "input",
3698
+ {
3699
+ type: "text",
3700
+ inputMode: "numeric",
3701
+ maxLength: 2,
3702
+ "aria-label": `${suffix} \uBD84`,
3703
+ disabled: !active,
3704
+ value: active ? minute : "",
3705
+ placeholder: "--",
3706
+ onChange: (e) => changeTime(which, "m", e.target.value),
3707
+ onBlur: () => blurTime(which, "m"),
3708
+ className: INPUT_CLS
3709
+ }
3710
+ )
3711
+ ] }),
3712
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: UNIT, children: suffix })
3713
+ ]
3714
+ }
3715
+ );
3716
+ };
3717
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3718
+ "div",
3719
+ {
3720
+ className: cn(
3721
+ "inline-flex flex-col gap-[var(--cmp-datepicker-calendar-gap)] rounded-[var(--cmp-datepicker-calendar-radius)] bg-[var(--cmp-datepicker-calendar-bg)] p-[var(--cmp-datepicker-calendar-paddingXY)] shadow-[2px_2px_12px_2px_rgba(0,0,0,0.2)] select-none",
3722
+ useTimePicker ? "h-auto" : "h-[364px]"
3624
3723
  ),
3625
- renderPanel(nextMonthYM.year, nextMonthYM.month, false)
3626
- ] })
3627
- ] });
3724
+ children: [
3725
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center justify-center", children: [
3726
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-[var(--cmp-datepicker-calendar-gap)] text-[14px] font-medium leading-[24px]", children: [
3727
+ /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "chevronLeft", size: "xxs", ariaLabel: "prevYear", onClick: goPrevYear }),
3728
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex min-w-[40px] items-center justify-center text-center", children: y }),
3729
+ /* @__PURE__ */ jsxRuntime.jsx(SGhostButton, { icon: "chevronRight", size: "xxs", ariaLabel: "nextYear", onClick: goNextYear })
3730
+ ] }),
3731
+ /* @__PURE__ */ jsxRuntime.jsx(
3732
+ "button",
3733
+ {
3734
+ type: "button",
3735
+ onClick: goToday,
3736
+ className: "absolute right-0 h-[24px] min-w-[37px] cursor-pointer bg-transparent text-center text-[12px] font-medium leading-[24px] text-[color:var(--cmp-datepicker-calendar-day-default-text)] hover:underline",
3737
+ children: "\uC624\uB298"
3738
+ }
3739
+ )
3740
+ ] }),
3741
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-[var(--cmp-datepicker-calendar-range-panelGap)]", children: [
3742
+ renderPanel(y, m, true),
3743
+ /* @__PURE__ */ jsxRuntime.jsx(
3744
+ "span",
3745
+ {
3746
+ className: "w-px shrink-0 self-stretch bg-[var(--cmp-datepicker-calendar-range-divider)]",
3747
+ "aria-hidden": true
3748
+ }
3749
+ ),
3750
+ renderPanel(nextMonthYM.year, nextMonthYM.month, false)
3751
+ ] }),
3752
+ useTimePicker && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3753
+ /* @__PURE__ */ jsxRuntime.jsx(
3754
+ "span",
3755
+ {
3756
+ className: "h-px w-full bg-[var(--cmp-datepicker-calendar-range-divider)]",
3757
+ "aria-hidden": true
3758
+ }
3759
+ ),
3760
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-[var(--cmp-datepicker-calendar-time-gap)]", children: [
3761
+ renderTimeSection("start", start, "\uBD80\uD130"),
3762
+ renderTimeSection("end", end, "\uAE4C\uC9C0")
3763
+ ] })
3764
+ ] })
3765
+ ]
3766
+ }
3767
+ );
3628
3768
  }
3629
3769
  function SDateRangePicker({
3630
3770
  value,
@@ -3634,6 +3774,7 @@ function SDateRangePicker({
3634
3774
  placeholder = "YYYY-MM-DD ~ YYYY-MM-DD",
3635
3775
  selectable,
3636
3776
  maxRange,
3777
+ useTimePicker = false,
3637
3778
  disabled = false,
3638
3779
  width,
3639
3780
  name,
@@ -3677,8 +3818,9 @@ function SDateRangePicker({
3677
3818
  setPendingStart(null);
3678
3819
  onValueChange?.(r);
3679
3820
  if (rules && rules.length > 0) setRuleError(runRules(r, rules));
3680
- setOpen(false);
3821
+ if (!useTimePicker) setOpen(false);
3681
3822
  };
3823
+ const resolvedPlaceholder = useTimePicker && placeholder === "YYYY-MM-DD ~ YYYY-MM-DD" ? "YYYY-MM-DD HH:mm ~ YYYY-MM-DD HH:mm" : placeholder;
3682
3824
  return /* @__PURE__ */ jsxRuntime.jsx(
3683
3825
  SField,
3684
3826
  {
@@ -3745,7 +3887,7 @@ function SDateRangePicker({
3745
3887
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-right", children: startText }),
3746
3888
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-[4px]", children: "~" }),
3747
3889
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate text-left", children: endText })
3748
- ] }) : placeholder
3890
+ ] }) : resolvedPlaceholder
3749
3891
  }
3750
3892
  )
3751
3893
  ]
@@ -3764,6 +3906,7 @@ function SDateRangePicker({
3764
3906
  value: value ?? null,
3765
3907
  selectable,
3766
3908
  maxRange,
3909
+ useTimePicker,
3767
3910
  onSelect: select,
3768
3911
  onPendingStartChange: setPendingStart,
3769
3912
  onViewChange