sellmate-design-system-react 9.0.0-beta.57 → 9.0.0-beta.59

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
@@ -15564,7 +15564,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
15564
15564
  react.useEffect(() => {
15565
15565
  setColumnWidths(visibleCols.map(colWidthFromDef));
15566
15566
  }, [colSignature]);
15567
- const selectedKeys = react.useMemo(() => new Set(selected.map((r) => r[rowKey])), [selected, rowKey]);
15567
+ const selectedKeys = react.useMemo(() => new Set(selected.map((r2) => r2[rowKey])), [selected, rowKey]);
15568
15568
  const rangeAnchorRef = react.useRef(null);
15569
15569
  const shiftPressedRef = react.useRef(false);
15570
15570
  const isRowSelected = react.useCallback(
@@ -15584,7 +15584,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
15584
15584
  const targets = rws.filter(canSelectRow);
15585
15585
  const total = targets.length;
15586
15586
  if (total === 0) return false;
15587
- const cnt = targets.filter((r) => selectedKeys.has(r[rowKey])).length;
15587
+ const cnt = targets.filter((r2) => selectedKeys.has(r2[rowKey])).length;
15588
15588
  if (cnt === 0) return false;
15589
15589
  if (cnt === total) return true;
15590
15590
  return null;
@@ -15788,16 +15788,16 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
15788
15788
  updateRowSelect: (row) => {
15789
15789
  if (!canSelectRow(row)) return;
15790
15790
  if (selectedKeys.has(row[rowKey]))
15791
- onSelectedChange?.(selected.filter((r) => r[rowKey] !== row[rowKey]));
15791
+ onSelectedChange?.(selected.filter((r2) => r2[rowKey] !== row[rowKey]));
15792
15792
  else onSelectedChange?.([...selected, row]);
15793
15793
  },
15794
15794
  toggleSelectAll: (checked, rws) => {
15795
15795
  if (checked) {
15796
- const add = rws.filter((r) => canSelectRow(r) && !selectedKeys.has(r[rowKey]));
15796
+ const add = rws.filter((r2) => canSelectRow(r2) && !selectedKeys.has(r2[rowKey]));
15797
15797
  onSelectedChange?.([...selected, ...add]);
15798
15798
  } else {
15799
- const keys = new Set(rws.map((r) => r[rowKey]));
15800
- onSelectedChange?.(selected.filter((r) => !keys.has(r[rowKey])));
15799
+ const keys = new Set(rws.map((r2) => r2[rowKey]));
15800
+ onSelectedChange?.(selected.filter((r2) => !keys.has(r2[rowKey])));
15801
15801
  }
15802
15802
  }
15803
15803
  }),
@@ -15891,10 +15891,10 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
15891
15891
  const toggleAll = () => {
15892
15892
  rangeAnchorRef.current = null;
15893
15893
  if (headerCheck === true) {
15894
- const targetKeys = new Set(selectAllRows.map((r) => r[rowKey]));
15895
- onSelectedChange?.(selected.filter((r) => !targetKeys.has(r[rowKey])));
15894
+ const targetKeys = new Set(selectAllRows.map((r2) => r2[rowKey]));
15895
+ onSelectedChange?.(selected.filter((r2) => !targetKeys.has(r2[rowKey])));
15896
15896
  } else {
15897
- const add = selectAllRows.filter((r) => canSelectRow(r) && !selectedKeys.has(r[rowKey]));
15897
+ const add = selectAllRows.filter((r2) => canSelectRow(r2) && !selectedKeys.has(r2[rowKey]));
15898
15898
  onSelectedChange?.([...selected, ...add]);
15899
15899
  }
15900
15900
  };
@@ -15907,17 +15907,17 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
15907
15907
  const shouldSelect = selectedKeys.has(anchor.key);
15908
15908
  const range = rows.slice(from, to + 1).filter(canSelectRow);
15909
15909
  if (shouldSelect) {
15910
- const add = range.filter((r) => !selectedKeys.has(r[rowKey]));
15910
+ const add = range.filter((r2) => !selectedKeys.has(r2[rowKey]));
15911
15911
  onSelectedChange?.([...selected, ...add]);
15912
15912
  } else {
15913
- const keys = new Set(range.map((r) => r[rowKey]));
15914
- onSelectedChange?.(selected.filter((r) => !keys.has(r[rowKey])));
15913
+ const keys = new Set(range.map((r2) => r2[rowKey]));
15914
+ onSelectedChange?.(selected.filter((r2) => !keys.has(r2[rowKey])));
15915
15915
  }
15916
15916
  return;
15917
15917
  }
15918
15918
  rangeAnchorRef.current = { index, key: row[rowKey] };
15919
15919
  if (selectedKeys.has(row[rowKey]))
15920
- onSelectedChange?.(selected.filter((r) => r[rowKey] !== row[rowKey]));
15920
+ onSelectedChange?.(selected.filter((r2) => r2[rowKey] !== row[rowKey]));
15921
15921
  else onSelectedChange?.([...selected, row]);
15922
15922
  };
15923
15923
  const isViewSelected = (row) => row != null && (dragPreviewKeys ?? selectedKeys).has(row[rowKey]);
@@ -15925,14 +15925,14 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
15925
15925
  const [a, b] = from <= to ? [from, to] : [to, from];
15926
15926
  return rows.slice(a, b + 1).filter(canSelectRow);
15927
15927
  };
15928
- const dragPreviewOf = (base, anchor, to) => /* @__PURE__ */ new Set([...base, ...dragRangeRows(anchor, to).map((r) => r[rowKey])]);
15928
+ const dragPreviewOf = (base, anchor, to) => /* @__PURE__ */ new Set([...base, ...dragRangeRows(anchor, to).map((r2) => r2[rowKey])]);
15929
15929
  const startDragSelect = (index, event) => {
15930
15930
  if (event.button !== 0) return;
15931
15931
  const target = event.target;
15932
15932
  if (target?.closest?.(ROW_INTERACTIVE_SELECTOR)) return;
15933
15933
  event.preventDefault();
15934
15934
  const baseRows = event.ctrlKey || event.metaKey ? selected : [];
15935
- const baseKeys = new Set(baseRows.map((r) => r[rowKey]));
15935
+ const baseKeys = new Set(baseRows.map((r2) => r2[rowKey]));
15936
15936
  dragRef.current = { anchor: index, last: index, baseKeys, baseRows };
15937
15937
  setDragPreviewKeys(dragPreviewOf(baseKeys, index, index));
15938
15938
  };
@@ -15949,7 +15949,7 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
15949
15949
  if (!d) return;
15950
15950
  dragRef.current = null;
15951
15951
  setDragPreviewKeys(null);
15952
- const add = dragRangeRows(d.anchor, d.last).filter((r) => !d.baseKeys.has(r[rowKey]));
15952
+ const add = dragRangeRows(d.anchor, d.last).filter((r2) => !d.baseKeys.has(r2[rowKey]));
15953
15953
  onSelectedChange?.([...d.baseRows, ...add]);
15954
15954
  };
15955
15955
  react.useEffect(() => {
@@ -18361,6 +18361,7 @@ function SDateRangePicker({
18361
18361
  disabled = false,
18362
18362
  clearable = false,
18363
18363
  width,
18364
+ maxWidth,
18364
18365
  name,
18365
18366
  rules,
18366
18367
  status,
@@ -18421,10 +18422,10 @@ function SDateRangePicker({
18421
18422
  lineHeight: 20,
18422
18423
  radius: 4
18423
18424
  };
18424
- const select = (r) => {
18425
+ const select = (r2) => {
18425
18426
  setPendingStart(null);
18426
- onValueChange?.(r);
18427
- if (rules && rules.length > 0) setRuleError(runRules(r, rules));
18427
+ onValueChange?.(r2);
18428
+ if (rules && rules.length > 0) setRuleError(runRules(r2, rules));
18428
18429
  if (!showTimePicker) setOpen(false);
18429
18430
  };
18430
18431
  const clear = () => {
@@ -18452,7 +18453,7 @@ function SDateRangePicker({
18452
18453
  errorMessage: ruleError !== "" ? ruleError : errorMessage,
18453
18454
  width,
18454
18455
  minWidth: dims.fieldMinW,
18455
- maxWidth: dims.fieldMaxW,
18456
+ maxWidth: maxWidth ?? dims.fieldMaxW,
18456
18457
  disabled,
18457
18458
  className,
18458
18459
  style,
@@ -18942,6 +18943,7 @@ function SKeyValueTable({
18942
18943
  search = false,
18943
18944
  radius = "default",
18944
18945
  bordered = true,
18946
+ fieldWidth = "auto",
18945
18947
  onChange,
18946
18948
  onSearch,
18947
18949
  className,
@@ -18955,6 +18957,7 @@ function SKeyValueTable({
18955
18957
  });
18956
18958
  const cellHeight = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-keyValue-height)";
18957
18959
  const cellPadY = dense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-keyValue-body-paddingY)";
18960
+ const fillMaxWidth = fieldWidth === "fill" ? { maxWidth: "100%" } : void 0;
18958
18961
  const renderField = (f) => {
18959
18962
  if (f.render) return f.render;
18960
18963
  const opt = { ...f.options ?? {} };
@@ -18976,9 +18979,9 @@ function SKeyValueTable({
18976
18979
  case "switch":
18977
18980
  return /* @__PURE__ */ jsxRuntime.jsx(SSwitch, { ...opt, onValueChange: up });
18978
18981
  case "date-picker":
18979
- return /* @__PURE__ */ jsxRuntime.jsx(SDatePicker, { width: "100%", ...opt, onValueChange: up });
18982
+ return /* @__PURE__ */ jsxRuntime.jsx(SDatePicker, { width: "100%", ...fillMaxWidth, ...opt, onValueChange: up });
18980
18983
  case "date-range-picker":
18981
- return /* @__PURE__ */ jsxRuntime.jsx(SDateRangePicker, { width: "100%", ...opt, onValueChange: up });
18984
+ return /* @__PURE__ */ jsxRuntime.jsx(SDateRangePicker, { width: "100%", ...fillMaxWidth, ...opt, onValueChange: up });
18982
18985
  case "file-picker":
18983
18986
  return /* @__PURE__ */ jsxRuntime.jsx(SFilePicker, { width: "100%", ...opt, onValueChange: up });
18984
18987
  case "text":
@@ -18986,25 +18989,54 @@ function SKeyValueTable({
18986
18989
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] text-[color:var(--sys-color-fg-primary)]", children: opt.value ?? "" });
18987
18990
  }
18988
18991
  };
18989
- const skip = fields.map((row) => row.map(() => false));
18990
- fields.forEach(
18991
- (row, r) => row.forEach((f, c) => {
18992
- const span = f.thRowSpan && f.thRowSpan > 1 ? f.thRowSpan : 1;
18993
- for (let dr = 1; dr < span; dr++) {
18994
- const tr = skip[r + dr];
18995
- if (tr && c < tr.length) tr[c] = true;
18996
- }
18997
- })
18998
- );
18992
+ const grid = fields.map(() => []);
18993
+ const showThAt = fields.map((row) => row.map(() => true));
18994
+ const isLabelCol = [];
18995
+ const labelColWidth = [];
18999
18996
  let maxCols = 0;
19000
- fields.forEach((row, r) => {
19001
- let cols = 0;
19002
- row.forEach((f, c) => {
19003
- const thCols = f.hideTh ? 0 : skip[r]?.[c] ? 1 : f.thColSpan && f.thColSpan > 1 ? f.thColSpan : 1;
19004
- const tdCols = f.tdColSpan && f.tdColSpan > 1 ? f.tdColSpan : 1;
19005
- cols += thCols + tdCols;
18997
+ fields.forEach((row, r2) => {
18998
+ const occupied = grid[r2];
18999
+ let col = 0;
19000
+ const skipOccupied = () => {
19001
+ let sawThSupply = false;
19002
+ while (occupied[col] != null) {
19003
+ if (occupied[col] === "th-supply") sawThSupply = true;
19004
+ col++;
19005
+ }
19006
+ return sawThSupply;
19007
+ };
19008
+ row.forEach((f, i) => {
19009
+ const thRowSpan = f.thRowSpan && f.thRowSpan > 1 ? f.thRowSpan : 1;
19010
+ const thColSpan = f.thColSpan && f.thColSpan > 1 ? f.thColSpan : 1;
19011
+ const tdRowSpan = f.tdRowSpan && f.tdRowSpan > 1 ? f.tdRowSpan : 1;
19012
+ const tdColSpan = f.tdColSpan && f.tdColSpan > 1 ? f.tdColSpan : 1;
19013
+ const thSuppliedAbove = skipOccupied();
19014
+ const showTh = !f.hideTh && !thSuppliedAbove;
19015
+ showThAt[r2][i] = showTh;
19016
+ if (showTh) {
19017
+ isLabelCol[col] = true;
19018
+ if (thColSpan === 1 && f.thWidth != null && labelColWidth[col] == null)
19019
+ labelColWidth[col] = f.thWidth;
19020
+ for (let dr = 1; dr < thRowSpan; dr++) {
19021
+ const kind = dr >= tdRowSpan ? "th-supply" : "blocked";
19022
+ for (let dc = 0; dc < thColSpan; dc++) {
19023
+ const target = grid[r2 + dr];
19024
+ if (target) target[col + dc] = kind;
19025
+ }
19026
+ }
19027
+ col += thColSpan;
19028
+ }
19029
+ skipOccupied();
19030
+ for (let dr = 1; dr < tdRowSpan; dr++) {
19031
+ for (let dc = 0; dc < tdColSpan; dc++) {
19032
+ const target = grid[r2 + dr];
19033
+ if (target) target[col + dc] = "blocked";
19034
+ }
19035
+ }
19036
+ col += tdColSpan;
19006
19037
  });
19007
- if (cols > maxCols) maxCols = cols;
19038
+ skipOccupied();
19039
+ maxCols = Math.max(maxCols, col, occupied.length);
19008
19040
  });
19009
19041
  const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[8px] rounded-t-none" : "rounded-[8px]";
19010
19042
  const frameClass = cn(
@@ -19018,19 +19050,14 @@ function SKeyValueTable({
19018
19050
  className: "w-full border-separate border-spacing-0",
19019
19051
  style: { tableLayout: "fixed", ...style },
19020
19052
  children: [
19021
- /* @__PURE__ */ jsxRuntime.jsx("colgroup", { children: Array.from({ length: maxCols }, (_, i) => {
19022
- if (i % 2 !== 0) return /* @__PURE__ */ jsxRuntime.jsx("col", {}, `col-${i}`);
19023
- const fieldIdx = i / 2;
19024
- const fieldThWidth = fields.reduce((found, row) => {
19025
- if (found != null) return found;
19026
- return row[fieldIdx]?.thWidth;
19027
- }, void 0);
19028
- return /* @__PURE__ */ jsxRuntime.jsx("col", { style: { width: cssLen2(fieldThWidth) ?? "120px" } }, `col-${i}`);
19029
- }) }),
19030
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: fields.map((row, r) => {
19031
- const cellBorder = r === 0 ? "" : "border-t border-solid border-[color:var(--cmp-table-border-color)]";
19053
+ /* @__PURE__ */ jsxRuntime.jsx("colgroup", { children: Array.from(
19054
+ { length: maxCols },
19055
+ (_, i) => isLabelCol[i] ? /* @__PURE__ */ jsxRuntime.jsx("col", { style: { width: cssLen2(labelColWidth[i]) ?? "120px" } }, `col-${i}`) : /* @__PURE__ */ jsxRuntime.jsx("col", {}, `col-${i}`)
19056
+ ) }),
19057
+ /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: fields.map((row, r2) => {
19058
+ const cellBorder = r2 === 0 ? "" : "border-t border-solid border-[color:var(--cmp-table-border-color)]";
19032
19059
  return /* @__PURE__ */ jsxRuntime.jsx("tr", { children: row.map((f, c) => {
19033
- const showTh = !f.hideTh && !skip[r][c];
19060
+ const showTh = showThAt[r2][c];
19034
19061
  const isReadOnlyCell = f.render == null && (f.type == null || f.type === "text");
19035
19062
  return /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
19036
19063
  showTh && /* @__PURE__ */ jsxRuntime.jsx(
@@ -19066,7 +19093,7 @@ function SKeyValueTable({
19066
19093
  )
19067
19094
  ] })
19068
19095
  },
19069
- `th-${r}-${c}`
19096
+ `th-${r2}-${c}`
19070
19097
  ),
19071
19098
  /* @__PURE__ */ jsxRuntime.jsx(
19072
19099
  "td",
@@ -19083,10 +19110,10 @@ function SKeyValueTable({
19083
19110
  style: { height: cellHeight, paddingTop: cellPadY, paddingBottom: cellPadY },
19084
19111
  children: renderField(f)
19085
19112
  },
19086
- `td-${r}-${c}`
19113
+ `td-${r2}-${c}`
19087
19114
  )
19088
- ] }, `${r}-${c}`);
19089
- }) }, r);
19115
+ ] }, `${r2}-${c}`);
19116
+ }) }, r2);
19090
19117
  }) })
19091
19118
  ]
19092
19119
  }
@@ -19145,6 +19172,7 @@ function ratioOf(value, scale) {
19145
19172
  return (value - scale.min) / span;
19146
19173
  }
19147
19174
  var AXIS_LABEL_GAP = 8;
19175
+ var AXIS_EDGE_PADDING = 24;
19148
19176
  function ChartGrid({ scale, direction, width, height }) {
19149
19177
  const vertical = direction === "vertical";
19150
19178
  return /* @__PURE__ */ jsxRuntime.jsx("g", { "aria-hidden": true, children: scale.ticks.map((tick) => {
@@ -19453,7 +19481,6 @@ var BAR_SIZE_MAX = 80;
19453
19481
  var BAR_GAP = 6;
19454
19482
  var GROUP_PADDING_MIN = 8;
19455
19483
  var GROUP_PADDING_MAX = 24;
19456
- var AXIS_EDGE_PADDING = 24;
19457
19484
  var VALUE_LABEL_GAP = 6;
19458
19485
  var BAR_RADIUS = 8;
19459
19486
  var BAR_OPACITY_DEFAULT = "var(--cmp-chart-bar-opacity-default)";
@@ -19497,23 +19524,23 @@ function barOpacity(hoveredCategory, categoryIndex) {
19497
19524
  return hoveredCategory === categoryIndex ? BAR_OPACITY_HOVER : BAR_OPACITY_DIMMED;
19498
19525
  }
19499
19526
  function barPath(x, y, width, height, direction, negative) {
19500
- const r = Math.max(0, Math.min(BAR_RADIUS, width / 2, height / 2));
19501
- if (r === 0) return `M${x} ${y}h${width}v${height}h${-width}Z`;
19527
+ const r2 = Math.max(0, Math.min(BAR_RADIUS, width / 2, height / 2));
19528
+ if (r2 === 0) return `M${x} ${y}h${width}v${height}h${-width}Z`;
19502
19529
  if (direction === "vertical") {
19503
19530
  return negative ? (
19504
19531
  // 아래로 자란다 — 아래쪽 두 모서리가 둥글다
19505
- `M${x} ${y}h${width}v${height - r}a${r} ${r} 0 0 1 ${-r} ${r}h${-(width - 2 * r)}a${r} ${r} 0 0 1 ${-r} ${-r}Z`
19532
+ `M${x} ${y}h${width}v${height - r2}a${r2} ${r2} 0 0 1 ${-r2} ${r2}h${-(width - 2 * r2)}a${r2} ${r2} 0 0 1 ${-r2} ${-r2}Z`
19506
19533
  ) : (
19507
19534
  // 위로 자란다 — 위쪽 두 모서리가 둥글다
19508
- `M${x} ${y + height}v${-(height - r)}a${r} ${r} 0 0 1 ${r} ${-r}h${width - 2 * r}a${r} ${r} 0 0 1 ${r} ${r}v${height - r}Z`
19535
+ `M${x} ${y + height}v${-(height - r2)}a${r2} ${r2} 0 0 1 ${r2} ${-r2}h${width - 2 * r2}a${r2} ${r2} 0 0 1 ${r2} ${r2}v${height - r2}Z`
19509
19536
  );
19510
19537
  }
19511
19538
  return negative ? (
19512
19539
  // 왼쪽으로 자란다
19513
- `M${x + width} ${y}h${-(width - r)}a${r} ${r} 0 0 0 ${-r} ${r}v${height - 2 * r}a${r} ${r} 0 0 0 ${r} ${r}h${width - r}Z`
19540
+ `M${x + width} ${y}h${-(width - r2)}a${r2} ${r2} 0 0 0 ${-r2} ${r2}v${height - 2 * r2}a${r2} ${r2} 0 0 0 ${r2} ${r2}h${width - r2}Z`
19514
19541
  ) : (
19515
19542
  // 오른쪽으로 자란다
19516
- `M${x} ${y}h${width - r}a${r} ${r} 0 0 1 ${r} ${r}v${height - 2 * r}a${r} ${r} 0 0 1 ${-r} ${r}h${-(width - r)}Z`
19543
+ `M${x} ${y}h${width - r2}a${r2} ${r2} 0 0 1 ${r2} ${r2}v${height - 2 * r2}a${r2} ${r2} 0 0 1 ${-r2} ${r2}h${-(width - r2)}Z`
19517
19544
  );
19518
19545
  }
19519
19546
  var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
@@ -20012,6 +20039,444 @@ var SBarChart = /* @__PURE__ */ react.forwardRef(function SBarChart2({
20012
20039
  }
20013
20040
  );
20014
20041
  });
20042
+
20043
+ // src/components/SLineChart/lineChart.config.ts
20044
+ var LINE_WIDTH = 2;
20045
+ var POINT_RADIUS = 4;
20046
+ var POINT_HOVER_RADIUS = 9.5;
20047
+ var POINT_HOVER_BORDER_WIDTH = 1;
20048
+ var POINT_HOVER_INNER_RADIUS = 5;
20049
+ var POINT_HOVER_BG = "var(--cmp-chart-bg)";
20050
+ var POINT_HOVER_EXTENT = POINT_HOVER_RADIUS + POINT_HOVER_BORDER_WIDTH / 2;
20051
+ var BAND_MIN = 40;
20052
+ var VALUE_LABEL_GAP2 = 6;
20053
+ var AREA_OPACITY = "var(--opacity-040)";
20054
+ var LINE_DATA_LABEL_COLOR = "var(--cmp-chart-bar-dataLabel-color-default)";
20055
+ var LINE_DATA_LABEL_TYPO = "typo-body-sm-medium";
20056
+ var LINE_DATA_LABEL_TYPO_HOVER = "typo-body-md-bold";
20057
+ var r = (value) => Math.round(value * 100) / 100;
20058
+ function tangents(points) {
20059
+ const n = points.length;
20060
+ const slopes = [];
20061
+ for (let i = 0; i < n - 1; i += 1) {
20062
+ const dx = points[i + 1].x - points[i].x;
20063
+ slopes.push(dx === 0 ? 0 : (points[i + 1].y - points[i].y) / dx);
20064
+ }
20065
+ const m = new Array(n).fill(0);
20066
+ m[0] = slopes[0] ?? 0;
20067
+ m[n - 1] = slopes[n - 2] ?? 0;
20068
+ for (let i = 1; i < n - 1; i += 1) {
20069
+ const prev = slopes[i - 1];
20070
+ const next = slopes[i];
20071
+ m[i] = prev * next <= 0 ? 0 : (prev + next) / 2;
20072
+ }
20073
+ for (let i = 0; i < n - 1; i += 1) {
20074
+ const slope = slopes[i];
20075
+ if (slope === 0) {
20076
+ m[i] = 0;
20077
+ m[i + 1] = 0;
20078
+ continue;
20079
+ }
20080
+ const a = m[i] / slope;
20081
+ const b = m[i + 1] / slope;
20082
+ const scale = Math.hypot(a, b);
20083
+ if (scale > 3) {
20084
+ m[i] = 3 * a / scale * slope;
20085
+ m[i + 1] = 3 * b / scale * slope;
20086
+ }
20087
+ }
20088
+ return m;
20089
+ }
20090
+ function commands(points, smooth) {
20091
+ if (points.length < 2) return "";
20092
+ if (!smooth) {
20093
+ return points.slice(1).map((p) => `L${r(p.x)} ${r(p.y)}`).join("");
20094
+ }
20095
+ const m = tangents(points);
20096
+ let path = "";
20097
+ for (let i = 0; i < points.length - 1; i += 1) {
20098
+ const from = points[i];
20099
+ const to = points[i + 1];
20100
+ const dx = (to.x - from.x) / 3;
20101
+ path += `C${r(from.x + dx)} ${r(from.y + m[i] * dx)} ${r(to.x - dx)} ${r(to.y - m[i + 1] * dx)} ${r(to.x)} ${r(to.y)}`;
20102
+ }
20103
+ return path;
20104
+ }
20105
+ function linePath(points, smooth) {
20106
+ const first = points[0];
20107
+ if (!first || points.length < 2) return "";
20108
+ return `M${r(first.x)} ${r(first.y)}${commands(points, smooth)}`;
20109
+ }
20110
+ function areaPath(top, bottom, smooth) {
20111
+ const first = top[0];
20112
+ if (!first || top.length < 2 || bottom.length !== top.length) return "";
20113
+ const back = [...bottom].reverse();
20114
+ return `M${r(first.x)} ${r(first.y)}${commands(top, smooth)}L${r(back[0].x)} ${r(back[0].y)}${commands(back, smooth)}Z`;
20115
+ }
20116
+ var defaultFormat2 = (value) => value.toLocaleString();
20117
+ function runsOf(row) {
20118
+ const runs = [];
20119
+ let current = [];
20120
+ for (const point of row) {
20121
+ if (point == null) {
20122
+ if (current.length > 0) runs.push(current);
20123
+ current = [];
20124
+ continue;
20125
+ }
20126
+ current.push(point);
20127
+ }
20128
+ if (current.length > 0) runs.push(current);
20129
+ return runs;
20130
+ }
20131
+ var SLineChart = /* @__PURE__ */ react.forwardRef(function SLineChart2({
20132
+ categories,
20133
+ series,
20134
+ curve = "linear",
20135
+ area = false,
20136
+ stacked = false,
20137
+ palette = "default",
20138
+ colors: customColors,
20139
+ max,
20140
+ tickCount = 8,
20141
+ showPoint = true,
20142
+ showValueLabel = false,
20143
+ showLegend = true,
20144
+ legendPosition = "top",
20145
+ showTooltip = true,
20146
+ formatValue = defaultFormat2,
20147
+ height,
20148
+ onPointClick,
20149
+ className,
20150
+ style
20151
+ }, ref) {
20152
+ const smooth = curve === "smooth";
20153
+ const { ref: plotRef, size } = useElementSize();
20154
+ const { ref: axisTextRef, size: axisText } = useElementSize();
20155
+ const { ref: axisSampleRef, size: axisSample } = useElementSize();
20156
+ const [hoveredCategory, setHoveredCategory] = react.useState(null);
20157
+ const colorAt = react.useCallback(
20158
+ (seriesIndex) => paletteColor(palette, seriesIndex, customColors),
20159
+ [palette, customColors]
20160
+ );
20161
+ const rows = react.useMemo(() => {
20162
+ const running = categories.map(() => 0);
20163
+ return series.map(
20164
+ (s) => categories.map((_, categoryIndex) => {
20165
+ const raw = s.data[categoryIndex];
20166
+ if (raw == null || !Number.isFinite(raw)) return null;
20167
+ if (!stacked) return { value: raw, base: 0, own: raw };
20168
+ const base = running[categoryIndex];
20169
+ running[categoryIndex] = base + raw;
20170
+ return { value: base + raw, base, own: raw };
20171
+ })
20172
+ );
20173
+ }, [series, categories, stacked]);
20174
+ const scale = react.useMemo(
20175
+ () => niceScale(
20176
+ // 누적은 쌓아 올린 값까지 축에 들어와야 맨 위 선이 눈금 밖으로 나가지 않는다.
20177
+ rows.flatMap((row) => row.flatMap((point) => point == null ? [] : [point.value, point.base])),
20178
+ tickCount,
20179
+ max
20180
+ ),
20181
+ [rows, tickCount, max]
20182
+ );
20183
+ const band = categories.length > 0 ? Math.max(0, size.width - AXIS_EDGE_PADDING * 2) / categories.length : 0;
20184
+ const minPlotWidth = categories.length * BAND_MIN + AXIS_EDGE_PADDING * 2;
20185
+ const totalHeight = height ?? 320;
20186
+ const plotHeight = typeof totalHeight === "number" ? Math.max(0, totalHeight - axisText.height) : `calc(${totalHeight} - ${axisText.height}px)`;
20187
+ const plotted = react.useMemo(() => {
20188
+ if (size.width <= 0 || size.height <= 0) return [];
20189
+ const xOf = (index) => AXIS_EDGE_PADDING + (index + 0.5) * band;
20190
+ const yOf = (value) => size.height - ratioOf(value, scale) * size.height;
20191
+ return rows.map(
20192
+ (row) => row.map(
20193
+ (point, categoryIndex) => point == null ? null : { x: xOf(categoryIndex), y: yOf(point.value), baseY: yOf(point.base), own: point.own }
20194
+ )
20195
+ );
20196
+ }, [rows, size.width, size.height, band, scale]);
20197
+ const legend = showLegend ? /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { items: series.map((s, i) => ({ name: s.name, color: colorAt(i) })) }) : null;
20198
+ const handleMove = (event) => {
20199
+ if (!showTooltip || band <= 0 || series.length === 0) return;
20200
+ const rect = event.currentTarget.getBoundingClientRect();
20201
+ const along = event.clientX - rect.left - AXIS_EDGE_PADDING;
20202
+ const category = Math.floor(along / band);
20203
+ setHoveredCategory(category >= 0 && category < categories.length ? category : null);
20204
+ };
20205
+ const tooltipItems = hoveredCategory == null ? [] : rows.flatMap((row, seriesIndex) => {
20206
+ const point = row[hoveredCategory];
20207
+ if (point == null) return [];
20208
+ return [
20209
+ {
20210
+ color: colorAt(seriesIndex),
20211
+ label: series[seriesIndex]?.name ?? "",
20212
+ value: formatValue(point.own)
20213
+ }
20214
+ ];
20215
+ });
20216
+ const anchorTop = react.useMemo(() => {
20217
+ if (hoveredCategory == null || plotted.length === 0) return null;
20218
+ let top = Number.POSITIVE_INFINITY;
20219
+ for (const row of plotted) {
20220
+ const point = row[hoveredCategory];
20221
+ if (point != null) top = Math.min(top, point.y);
20222
+ }
20223
+ return Number.isFinite(top) ? top : null;
20224
+ }, [hoveredCategory, plotted]);
20225
+ const { ref: valueLabelRef, metrics: valueLabel } = useSvgTextMetrics();
20226
+ const tooltipAnchor = react.useMemo(() => {
20227
+ if (hoveredCategory == null || anchorTop == null) return null;
20228
+ const left = AXIS_EDGE_PADDING + hoveredCategory * band;
20229
+ const top = showValueLabel ? anchorTop - POINT_RADIUS - VALUE_LABEL_GAP2 + valueLabel.top : anchorTop - POINT_HOVER_EXTENT;
20230
+ return { left, right: left + band, top };
20231
+ }, [hoveredCategory, anchorTop, band, showValueLabel, valueLabel.top]);
20232
+ const categoryLabels = /* @__PURE__ */ jsxRuntime.jsxs(
20233
+ "div",
20234
+ {
20235
+ "aria-hidden": true,
20236
+ className: "relative w-full typo-body-sm-medium text-(--cmp-chart-axis-color)",
20237
+ style: { minWidth: minPlotWidth || void 0 },
20238
+ children: [
20239
+ categories.map((label, index) => /* @__PURE__ */ jsxRuntime.jsx(
20240
+ "span",
20241
+ {
20242
+ className: "absolute top-0 -translate-x-1/2 whitespace-nowrap",
20243
+ style: { left: AXIS_EDGE_PADDING + (index + 0.5) * band },
20244
+ children: label
20245
+ },
20246
+ `${label}-${index}`
20247
+ )),
20248
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "invisible block whitespace-nowrap", children: "0" })
20249
+ ]
20250
+ }
20251
+ );
20252
+ const areas = react.useMemo(() => {
20253
+ if (!area) return [];
20254
+ return plotted.flatMap(
20255
+ (row, seriesIndex) => runsOf(row).map((run, runIndex) => {
20256
+ const d = areaPath(
20257
+ run,
20258
+ run.map((p) => ({ x: p.x, y: p.baseY })),
20259
+ smooth
20260
+ );
20261
+ if (!d) return null;
20262
+ return /* @__PURE__ */ jsxRuntime.jsx(
20263
+ "path",
20264
+ {
20265
+ "aria-hidden": true,
20266
+ d,
20267
+ style: { fill: colorAt(seriesIndex), fillOpacity: AREA_OPACITY }
20268
+ },
20269
+ `area-${seriesIndex}-${runIndex}`
20270
+ );
20271
+ })
20272
+ );
20273
+ }, [area, plotted, smooth, colorAt]);
20274
+ const lines = react.useMemo(
20275
+ () => plotted.flatMap(
20276
+ (row, seriesIndex) => runsOf(row).map((run, runIndex) => {
20277
+ const d = linePath(run, smooth);
20278
+ if (!d) return null;
20279
+ return /* @__PURE__ */ jsxRuntime.jsx(
20280
+ "path",
20281
+ {
20282
+ "aria-hidden": true,
20283
+ d,
20284
+ fill: "none",
20285
+ strokeWidth: LINE_WIDTH,
20286
+ strokeLinecap: "round",
20287
+ strokeLinejoin: "round",
20288
+ style: { stroke: colorAt(seriesIndex) }
20289
+ },
20290
+ `line-${seriesIndex}-${runIndex}`
20291
+ );
20292
+ })
20293
+ ),
20294
+ [plotted, smooth, colorAt]
20295
+ );
20296
+ const { pointHalos, pointDots } = react.useMemo(() => {
20297
+ const halos = [];
20298
+ const dots = [];
20299
+ plotted.forEach((row, seriesIndex) => {
20300
+ row.forEach((point, categoryIndex) => {
20301
+ if (point == null) return;
20302
+ const hovered = hoveredCategory === categoryIndex;
20303
+ if (!showPoint && !hovered) return;
20304
+ const color = colorAt(seriesIndex);
20305
+ const key = `${seriesIndex}-${categoryIndex}`;
20306
+ if (hovered) {
20307
+ halos.push(
20308
+ /* @__PURE__ */ jsxRuntime.jsx(
20309
+ "circle",
20310
+ {
20311
+ "aria-hidden": true,
20312
+ cx: point.x,
20313
+ cy: point.y,
20314
+ r: POINT_HOVER_RADIUS,
20315
+ style: {
20316
+ fill: POINT_HOVER_BG,
20317
+ stroke: color,
20318
+ strokeWidth: POINT_HOVER_BORDER_WIDTH
20319
+ }
20320
+ },
20321
+ `halo-${key}`
20322
+ )
20323
+ );
20324
+ }
20325
+ dots.push(
20326
+ /* @__PURE__ */ jsxRuntime.jsx(
20327
+ "circle",
20328
+ {
20329
+ cx: point.x,
20330
+ cy: point.y,
20331
+ r: hovered ? POINT_HOVER_INNER_RADIUS : POINT_RADIUS,
20332
+ style: { fill: color, cursor: onPointClick ? "pointer" : void 0 },
20333
+ onClick: onPointClick ? () => onPointClick({ seriesIndex, categoryIndex, value: point.own }) : void 0,
20334
+ children: /* @__PURE__ */ jsxRuntime.jsx("title", { children: `${categories[categoryIndex]} ${series[seriesIndex]?.name ?? ""} ${formatValue(point.own)}` })
20335
+ },
20336
+ `dot-${key}`
20337
+ )
20338
+ );
20339
+ });
20340
+ });
20341
+ return { pointHalos: halos, pointDots: dots };
20342
+ }, [plotted, showPoint, hoveredCategory, colorAt, onPointClick, categories, series, formatValue]);
20343
+ const valueLabels = react.useMemo(
20344
+ () => showValueLabel ? plotted.flatMap(
20345
+ (row, seriesIndex) => row.map(
20346
+ (point, categoryIndex) => point == null ? null : /* @__PURE__ */ jsxRuntime.jsx(
20347
+ "text",
20348
+ {
20349
+ x: point.x,
20350
+ y: point.y - POINT_RADIUS - VALUE_LABEL_GAP2,
20351
+ className: hoveredCategory === categoryIndex ? LINE_DATA_LABEL_TYPO_HOVER : LINE_DATA_LABEL_TYPO,
20352
+ style: { fill: LINE_DATA_LABEL_COLOR },
20353
+ textAnchor: "middle",
20354
+ dominantBaseline: "auto",
20355
+ children: formatValue(point.own)
20356
+ },
20357
+ `label-${seriesIndex}-${categoryIndex}`
20358
+ )
20359
+ )
20360
+ ) : [],
20361
+ [showValueLabel, plotted, hoveredCategory, formatValue]
20362
+ );
20363
+ const inset = { paddingTop: axisSample.height / 2, paddingBottom: axisSample.height / 2 };
20364
+ return /* @__PURE__ */ jsxRuntime.jsx(
20365
+ ChartFrame,
20366
+ {
20367
+ ref,
20368
+ legend,
20369
+ legendPosition,
20370
+ className,
20371
+ style,
20372
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
20373
+ "div",
20374
+ {
20375
+ className: "grid",
20376
+ style: {
20377
+ columnGap: AXIS_LABEL_GAP,
20378
+ // 눈금은 왼쪽 한 줄뿐이다 — 오른쪽에도 적으면 서로 다른 단위처럼 읽힌다.
20379
+ gridTemplateColumns: "max-content 1fr"
20380
+ },
20381
+ children: [
20382
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: plotHeight, ...inset }, children: /* @__PURE__ */ jsxRuntime.jsx(
20383
+ ChartAxisLabels,
20384
+ {
20385
+ scale,
20386
+ direction: "vertical",
20387
+ format: formatValue,
20388
+ sampleRef: axisSampleRef
20389
+ }
20390
+ ) }),
20391
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 overflow-x-auto", children: [
20392
+ /* @__PURE__ */ jsxRuntime.jsx(
20393
+ "div",
20394
+ {
20395
+ className: "relative min-w-0",
20396
+ style: { height: plotHeight, minWidth: minPlotWidth || void 0, ...inset },
20397
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
20398
+ "div",
20399
+ {
20400
+ ref: plotRef,
20401
+ className: "relative h-full w-full",
20402
+ onMouseMove: handleMove,
20403
+ onMouseLeave: () => setHoveredCategory(null),
20404
+ children: [
20405
+ size.width > 0 && size.height > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
20406
+ "svg",
20407
+ {
20408
+ width: size.width,
20409
+ height: size.height,
20410
+ role: "img",
20411
+ "aria-label": `${categories.length}\uAC1C \uD56D\uBAA9, ${series.length}\uAC1C \uACC4\uC5F4 ${stacked ? "\uB204\uC801 " : ""}\uAEBE\uC740\uC120 \uADF8\uB798\uD504`,
20412
+ children: [
20413
+ /* @__PURE__ */ jsxRuntime.jsx(
20414
+ "text",
20415
+ {
20416
+ ref: valueLabelRef,
20417
+ "aria-hidden": true,
20418
+ x: 0,
20419
+ y: 0,
20420
+ className: LINE_DATA_LABEL_TYPO_HOVER,
20421
+ dominantBaseline: "auto",
20422
+ style: { visibility: "hidden" },
20423
+ children: "0"
20424
+ }
20425
+ ),
20426
+ /* @__PURE__ */ jsxRuntime.jsx(
20427
+ ChartGrid,
20428
+ {
20429
+ scale,
20430
+ direction: "vertical",
20431
+ width: size.width,
20432
+ height: size.height
20433
+ }
20434
+ ),
20435
+ hoveredCategory != null && /* @__PURE__ */ jsxRuntime.jsx(
20436
+ "rect",
20437
+ {
20438
+ "aria-hidden": true,
20439
+ x: AXIS_EDGE_PADDING + hoveredCategory * band,
20440
+ y: 0,
20441
+ width: band,
20442
+ height: size.height,
20443
+ style: {
20444
+ fill: "var(--cmp-chart-barContainer-hover-bg)",
20445
+ fillOpacity: "var(--cmp-chart-barContainer-hover-opacity)"
20446
+ }
20447
+ }
20448
+ ),
20449
+ areas,
20450
+ lines,
20451
+ pointHalos,
20452
+ pointDots,
20453
+ valueLabels
20454
+ ]
20455
+ }
20456
+ ),
20457
+ showTooltip && hoveredCategory != null && tooltipAnchor != null && tooltipItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
20458
+ ChartTooltip,
20459
+ {
20460
+ title: categories[hoveredCategory] ?? "",
20461
+ items: tooltipItems,
20462
+ anchor: tooltipAnchor,
20463
+ bounds: size,
20464
+ gapX: { after: -4, before: -4 }
20465
+ }
20466
+ )
20467
+ ]
20468
+ }
20469
+ )
20470
+ }
20471
+ ),
20472
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: axisTextRef, children: categoryLabels })
20473
+ ] })
20474
+ ]
20475
+ }
20476
+ )
20477
+ }
20478
+ );
20479
+ });
20015
20480
  var BUTTON_STYLE = {
20016
20481
  default: { color: "secondary" },
20017
20482
  danger: { color: "danger", outline: true },
@@ -21380,14 +21845,14 @@ var TableSizePicker = ({
21380
21845
  onPick(size.rows, size.cols);
21381
21846
  }
21382
21847
  },
21383
- children: Array.from({ length: TABLE_PICKER_ROWS }, (_, r) => /* @__PURE__ */ jsxRuntime.jsx("div", { role: "row", className: "flex", style: { gap: TABLE_PICKER_GAP }, children: Array.from({ length: TABLE_PICKER_COLS }, (_2, c) => {
21384
- const on = r < size.rows && c < size.cols;
21848
+ children: Array.from({ length: TABLE_PICKER_ROWS }, (_, r2) => /* @__PURE__ */ jsxRuntime.jsx("div", { role: "row", className: "flex", style: { gap: TABLE_PICKER_GAP }, children: Array.from({ length: TABLE_PICKER_COLS }, (_2, c) => {
21849
+ const on = r2 < size.rows && c < size.cols;
21385
21850
  return /* @__PURE__ */ jsxRuntime.jsx(
21386
21851
  "button",
21387
21852
  {
21388
21853
  type: "button",
21389
21854
  role: "gridcell",
21390
- "aria-label": `${r + 1}\uD589 ${c + 1}\uC5F4`,
21855
+ "aria-label": `${r2 + 1}\uD589 ${c + 1}\uC5F4`,
21391
21856
  "aria-selected": on,
21392
21857
  tabIndex: -1,
21393
21858
  className: "box-border cursor-pointer rounded-[3px] border border-solid p-0 outline-none",
@@ -21397,13 +21862,13 @@ var TableSizePicker = ({
21397
21862
  borderColor: on ? "var(--sys-color-bg-accent)" : "var(--sys-color-border-default)",
21398
21863
  background: on ? "var(--color-bg-accentFaint)" : "transparent"
21399
21864
  },
21400
- onMouseEnter: () => setSize({ rows: r + 1, cols: c + 1 }),
21401
- onFocus: () => setSize({ rows: r + 1, cols: c + 1 }),
21402
- onClick: () => onPick(r + 1, c + 1)
21865
+ onMouseEnter: () => setSize({ rows: r2 + 1, cols: c + 1 }),
21866
+ onFocus: () => setSize({ rows: r2 + 1, cols: c + 1 }),
21867
+ onClick: () => onPick(r2 + 1, c + 1)
21403
21868
  },
21404
21869
  c
21405
21870
  );
21406
- }) }, r))
21871
+ }) }, r2))
21407
21872
  }
21408
21873
  ),
21409
21874
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -25391,6 +25856,7 @@ function STimePicker({
25391
25856
  showMeridiem,
25392
25857
  minuteStep = 1,
25393
25858
  width,
25859
+ maxWidth,
25394
25860
  name,
25395
25861
  rules,
25396
25862
  status,
@@ -25464,7 +25930,7 @@ function STimePicker({
25464
25930
  errorMessage: ruleError !== "" ? ruleError : errorMessage,
25465
25931
  width,
25466
25932
  minWidth: dims.fieldMinWidth,
25467
- maxWidth: dims.fieldMaxWidth,
25933
+ maxWidth: maxWidth ?? dims.fieldMaxWidth,
25468
25934
  disabled,
25469
25935
  className,
25470
25936
  style,
@@ -25856,6 +26322,7 @@ function STimeRangePicker({
25856
26322
  minuteStep = 1,
25857
26323
  rangeOrder = "strict",
25858
26324
  width,
26325
+ maxWidth,
25859
26326
  name,
25860
26327
  rules,
25861
26328
  status,
@@ -25931,7 +26398,7 @@ function STimeRangePicker({
25931
26398
  errorMessage: ruleError !== "" ? ruleError : errorMessage,
25932
26399
  width,
25933
26400
  minWidth: effectiveShowMeridiem ? MIDDAY_FIELD_MIN_WIDTH[size] : dims.fieldMinWidth,
25934
- maxWidth: effectiveShowMeridiem ? MIDDAY_FIELD_MAX_WIDTH[size] : dims.fieldMaxWidth,
26401
+ maxWidth: maxWidth ?? (effectiveShowMeridiem ? MIDDAY_FIELD_MAX_WIDTH[size] : dims.fieldMaxWidth),
25935
26402
  disabled,
25936
26403
  className,
25937
26404
  style,
@@ -26132,6 +26599,7 @@ exports.SLAYOUT_MIN_WIDTH = SLAYOUT_MIN_WIDTH;
26132
26599
  exports.SLauncherListBox = SLauncherListBox;
26133
26600
  exports.SLayout = SLayout;
26134
26601
  exports.SLayoutContext = SLayoutContext;
26602
+ exports.SLineChart = SLineChart;
26135
26603
  exports.SLinearProgress = SLinearProgress;
26136
26604
  exports.SList = SList2;
26137
26605
  exports.SListItem = SListItem2;