sellmate-design-system-react 9.0.0-beta.21 → 9.0.0-beta.24

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
@@ -3743,7 +3743,11 @@ var SDraggableItemView = /* @__PURE__ */ react.forwardRef(
3743
3743
  const paddingYClass = dense ? size === "sm" ? "py-(--cmp-listDraggableItem-paddingY-sm-dense)" : "py-(--cmp-listDraggableItem-paddingY-md-dense)" : size === "sm" ? "py-(--cmp-listDraggableItem-paddingY-sm-normal)" : "py-(--cmp-listDraggableItem-paddingY-md-normal)";
3744
3744
  const normalizedDepth = Math.max(1, Math.floor(depth));
3745
3745
  const depthOffset = (normalizedDepth - 1) * 20;
3746
- const depthStyle = depthOffset === 0 ? style : {
3746
+ const depthStyle = depthOffset === 0 ? style : bordered ? {
3747
+ ...style,
3748
+ marginLeft: depthOffset,
3749
+ width: `calc(100% - ${depthOffset}px)`
3750
+ } : {
3747
3751
  ...style,
3748
3752
  paddingLeft: `calc(var(--cmp-listDraggableItem-paddingX) + ${depthOffset}px)`
3749
3753
  };
@@ -3972,7 +3976,8 @@ var SDraggableItemImpl = /* @__PURE__ */ react.forwardRef(function SDraggableIte
3972
3976
  ] });
3973
3977
  });
3974
3978
  var SDraggableItem2 = /* @__PURE__ */ withDisplayName(SDraggableItemImpl, "SDraggableItem");
3975
- var SDivider = /* @__PURE__ */ react.forwardRef(function SDivider2({ vertical = false, className, style, ...rest }, ref) {
3979
+ var SDivider = /* @__PURE__ */ react.forwardRef(function SDivider2({ vertical = false, height, className, style, ...rest }, ref) {
3980
+ const fixedHeight = vertical && height !== void 0;
3976
3981
  return /* @__PURE__ */ jsxRuntime.jsx(
3977
3982
  "hr",
3978
3983
  {
@@ -3980,10 +3985,14 @@ var SDivider = /* @__PURE__ */ react.forwardRef(function SDivider2({ vertical =
3980
3985
  "aria-orientation": vertical ? "vertical" : "horizontal",
3981
3986
  className: cn(
3982
3987
  "shrink-0 border-0",
3983
- vertical ? "inline-block h-auto w-px self-stretch" : "block h-px w-full",
3988
+ vertical ? cn("inline-block w-px", fixedHeight ? "self-center" : "h-auto self-stretch") : "block h-px w-full",
3984
3989
  className
3985
3990
  ),
3986
- style: { backgroundColor: "var(--sys-color-divider-default, #E1E1E1)", ...style },
3991
+ style: {
3992
+ backgroundColor: "var(--sys-color-divider-default, #E1E1E1)",
3993
+ ...fixedHeight ? { height: typeof height === "number" ? `${height}px` : height } : null,
3994
+ ...style
3995
+ },
3987
3996
  ...rest
3988
3997
  }
3989
3998
  );
@@ -4213,6 +4222,10 @@ function getSubtreeEnd(items, startIndex, getDepth) {
4213
4222
  }
4214
4223
  return endIndex;
4215
4224
  }
4225
+ function isDescendant(items, index, ancestorIndex, getDepth) {
4226
+ if (ancestorIndex == null || getDepth == null || index <= ancestorIndex) return false;
4227
+ return index < getSubtreeEnd(items, ancestorIndex, getDepth);
4228
+ }
4216
4229
  function getInsertionIndex(items, target, getDepth) {
4217
4230
  if (target.intent === "before") return target.index;
4218
4231
  if (target.intent === "inside") return target.index + 1;
@@ -4268,6 +4281,8 @@ function SDraggableListInner({
4268
4281
  const fromIndexRef = react.useRef(null);
4269
4282
  const currentSelectedKey = selectedKey ?? internalSelectedKey;
4270
4283
  const usesDepth = getDepth != null;
4284
+ const groupDragging = dragContext?.dragging;
4285
+ const draggedSubtreeStart = dragContext ? groupDragging?.listId === listId ? groupDragging?.index ?? null : null : draggingIndex;
4271
4286
  const startDrag = react.useCallback((event, index) => {
4272
4287
  event.preventDefault();
4273
4288
  fromIndexRef.current = index;
@@ -4399,7 +4414,7 @@ function SDraggableListInner({
4399
4414
  "data-draggable-list-id": dragContext ? listId : void 0,
4400
4415
  children: items.map((item, index) => {
4401
4416
  const itemKey = getKey(item, index);
4402
- const disabled = getDisabled?.(item, index) ?? false;
4417
+ const disabled = (getDisabled?.(item, index) ?? false) || isDescendant(items, index, draggedSubtreeStart, usesDepth ? readDepth : void 0);
4403
4418
  const depth = readDepth(item, index);
4404
4419
  const showBefore = isDropTarget && currentDropIndex === index && (dragContext || currentDropIntent === "before");
4405
4420
  const showInside = isDropTarget && currentDropIndex === index && !dragContext && usesDepth && currentDropIntent === "inside";
@@ -4432,6 +4447,7 @@ function SDraggableListInner({
4432
4447
  } else startDrag(event, index);
4433
4448
  },
4434
4449
  selected: currentSelectedKey === itemKey,
4450
+ disabled,
4435
4451
  depth
4436
4452
  })
4437
4453
  },
@@ -10427,7 +10443,11 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
10427
10443
  "div",
10428
10444
  {
10429
10445
  className: cn(
10430
- "relative box-border flex min-w-0 items-stretch overflow-hidden border border-solid border-(--field-bc)",
10446
+ "relative box-border flex min-w-0 items-stretch border border-solid border-(--field-bc)",
10447
+ // 둘 다 넘친 것을 잘라 내지만 clip 은 스크롤 상자를 만들지 않는다. hidden 이면
10448
+ // 이 상자가 스크롤포트가 되어 안쪽의 position:sticky 가 페이지 스크롤을 따라가지
10449
+ // 못한다 (SEditor 의 고정 툴바). 여러 줄 필드에서만 바꿔 파급을 좁힌다.
10450
+ multiline ? "overflow-clip" : "overflow-hidden",
10431
10451
  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]",
10432
10452
  disabled && "cursor-not-allowed"
10433
10453
  ),
@@ -10463,7 +10483,7 @@ var SField = /* @__PURE__ */ react.forwardRef(function SField2({
10463
10483
  ]
10464
10484
  }
10465
10485
  ),
10466
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1", children })
10486
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex min-w-0 flex-1", multiline && "bg-inherit"), children })
10467
10487
  ]
10468
10488
  }
10469
10489
  ),
@@ -11341,7 +11361,6 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
11341
11361
  onPageChange,
11342
11362
  useInternalPagination = false,
11343
11363
  useRowsPerPageSelect = false,
11344
- useDensityToggle = false,
11345
11364
  rowsPerPageOption = DEFAULT_ROWS_PER_PAGE_OPTION,
11346
11365
  onRowsPerPageChange,
11347
11366
  useVirtualScroll = false,
@@ -11357,10 +11376,18 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
11357
11376
  }, ref) {
11358
11377
  const autoId = react.useId();
11359
11378
  const resolvedTableId = tableId ?? autoId;
11379
+ const [innerDense, setInnerDense] = react.useState(dense);
11380
+ react.useEffect(() => {
11381
+ setInnerDense(dense);
11382
+ }, [dense]);
11383
+ const changeDense = (next) => {
11384
+ setInnerDense(next);
11385
+ onDenseChange?.(next);
11386
+ };
11360
11387
  const visibleCols = react.useMemo(() => columns.filter((c) => c.visible !== false), [columns]);
11361
11388
  const stickyLeft = stickyColumn?.left ?? 0;
11362
11389
  const stickyRight = stickyColumn?.right ?? 0;
11363
- const effectiveRowHeight = rowHeight ?? (dense ? DENSE_ROW_HEIGHT : DEFAULT_ROW_HEIGHT);
11390
+ const effectiveRowHeight = rowHeight ?? (innerDense ? DENSE_ROW_HEIGHT : DEFAULT_ROW_HEIGHT);
11364
11391
  const colSignature = react.useMemo(
11365
11392
  () => visibleCols.map((c) => `${c.name}:${c.width ?? ""}:${c.autoWidth ? 1 : 0}`).join("|"),
11366
11393
  [visibleCols]
@@ -11590,9 +11617,9 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
11590
11617
  else onSelectedChange?.([...selected, row]);
11591
11618
  };
11592
11619
  const radiusClass = radius === "full" ? "rounded-none" : radius === "useTop" ? "rounded-b-[var(--cmp-table-radius)] rounded-t-none" : "rounded-[var(--cmp-table-radius)]";
11593
- const cellPadY = dense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-body-paddingY-default)";
11620
+ const cellPadY = innerDense ? "var(--cmp-table-body-paddingY-dense)" : "var(--cmp-table-body-paddingY-default)";
11594
11621
  const cellPadXOf = (col) => col.contentType === "control" ? "var(--cmp-table-body-paddingX-default)" : "var(--cmp-table-body-paddingX-wide)";
11595
- const rowH = dense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-body-default-height)";
11622
+ const rowH = innerDense ? "var(--cmp-table-body-dense-height)" : "var(--cmp-table-body-default-height)";
11596
11623
  const totalColSpan = visibleCols.length + (selectable ? 1 : 0);
11597
11624
  const stickyInfo = (i) => {
11598
11625
  const isLeft = i < stickyLeft;
@@ -11944,10 +11971,11 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
11944
11971
  ]
11945
11972
  }
11946
11973
  ),
11947
- showPagination && // 원본 sd-table__pagination: 테이블 하단에 이어붙는 회색 바(높이 48px, margin-top:-1px로 테두리 겹침).
11974
+ (showPagination || dense) && // 원본 sd-table__pagination: 테이블 하단에 이어붙는 회색 바(높이 48px, margin-top:-1px로 테두리 겹침).
11948
11975
  // SPagination은 전체 폭 기준 중앙, rows-per-page SSelect는 우측에 absolute 배치해 중앙 정렬을 유지한다.
11949
11976
  // 루트 높이가 확정된 경우(테이블이 남은 영역을 채우는 배치) 페이지네이션 바가
11950
11977
  // 눌리지 않도록 shrink-0으로 48px를 보장한다.
11978
+ // 페이지네이션이 없어도 dense 면 이 바를 그린다 — 밀도 토글이 사는 곳이 여기다.
11951
11979
  /* @__PURE__ */ jsxRuntime.jsxs(
11952
11980
  "div",
11953
11981
  {
@@ -11957,22 +11985,20 @@ var STable = /* @__PURE__ */ react.forwardRef(function STable2({
11957
11985
  bordered && "-mt-px border border-solid border-[color:var(--cmp-table-border-color)]"
11958
11986
  ),
11959
11987
  children: [
11960
- /* @__PURE__ */ jsxRuntime.jsx(SPagination, { currentPage: displayPage, lastPage, onPageChange: changePage }),
11961
- (useDensityToggle || useRowsPerPageSelect) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-[10px] top-1/2 flex -translate-y-1/2 items-center gap-[12px]", children: [
11962
- useDensityToggle && // 라벨·아이콘은 현재 밀도가 아니라 **누르면 되는 상태**를 가리킨다 (dense 면 "넓게 보기").
11963
- // row·rowDense 는 세로 막대라 90도 돌려 가로 행으로 쓴다.
11964
- /* @__PURE__ */ jsxRuntime.jsx(
11988
+ showPagination && /* @__PURE__ */ jsxRuntime.jsx(SPagination, { currentPage: displayPage, lastPage, onPageChange: changePage }),
11989
+ (dense || useRowsPerPageSelect) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-[10px] top-1/2 flex -translate-y-1/2 items-center gap-[12px]", children: [
11990
+ dense && /* @__PURE__ */ jsxRuntime.jsx(
11965
11991
  STextLink,
11966
11992
  {
11967
11993
  size: "sm",
11968
- icon: dense ? "row" : "rowDense",
11994
+ icon: innerDense ? "row" : "rowDense",
11969
11995
  iconRotate: 90,
11970
11996
  iconColor: "var(--sys-color-fg-quaternary)",
11971
- label: dense ? "\uB113\uAC8C \uBCF4\uAE30" : "\uC881\uAC8C \uBCF4\uAE30",
11972
- onClick: () => onDenseChange?.(!dense)
11997
+ label: innerDense ? "\uB113\uAC8C \uBCF4\uAE30" : "\uC881\uAC8C \uBCF4\uAE30",
11998
+ onClick: () => changeDense(!innerDense)
11973
11999
  }
11974
12000
  ),
11975
- useDensityToggle && useRowsPerPageSelect && /* @__PURE__ */ jsxRuntime.jsx(SDivider, { vertical: true, className: "my-[6px]" }),
12001
+ dense && useRowsPerPageSelect && /* @__PURE__ */ jsxRuntime.jsx(SDivider, { vertical: true, className: "my-[6px]" }),
11976
12002
  useRowsPerPageSelect && /* @__PURE__ */ jsxRuntime.jsx(
11977
12003
  SSelect2,
11978
12004
  {
@@ -12035,7 +12061,7 @@ var STableBar = /* @__PURE__ */ react.forwardRef(function STableBar2({ total, se
12035
12061
  SDivider,
12036
12062
  {
12037
12063
  vertical: true,
12038
- className: "h-[var(--cmp-table-bar-divider-height)] self-center",
12064
+ height: "var(--cmp-table-bar-divider-height)",
12039
12065
  style: { backgroundColor: "var(--cmp-table-border-color)" }
12040
12066
  }
12041
12067
  ),
@@ -12960,13 +12986,7 @@ function SCalendar({
12960
12986
  }
12961
12987
  )
12962
12988
  ] }),
12963
- /* @__PURE__ */ jsxRuntime.jsx(
12964
- SDivider,
12965
- {
12966
- vertical: true,
12967
- className: "h-[var(--cmp-datepicker-calendar-header-divider-height)] self-center"
12968
- }
12969
- ),
12989
+ /* @__PURE__ */ jsxRuntime.jsx(SDivider, { vertical: true, height: "var(--cmp-datepicker-calendar-header-divider-height)" }),
12970
12990
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-[var(--cmp-datepicker-calendar-gap)]", children: [
12971
12991
  /* @__PURE__ */ jsxRuntime.jsx(
12972
12992
  SGhostButton,
@@ -15207,66 +15227,6 @@ var IconBlockquote = (p) => /* @__PURE__ */ jsxRuntime.jsxs(Frame, { ...p, child
15207
15227
  }
15208
15228
  )
15209
15229
  ] });
15210
- var IconHighlight = (p) => /* @__PURE__ */ jsxRuntime.jsx(Frame, { ...p, children: /* @__PURE__ */ jsxRuntime.jsx(
15211
- "path",
15212
- {
15213
- fillRule: "evenodd",
15214
- clipRule: "evenodd",
15215
- d: "M14.7072 4.70711C15.0977 4.31658 15.0977 3.68342 14.7072 3.29289C14.3167 2.90237 13.6835 2.90237 13.293 3.29289L8.69294 7.89286L8.68594 7.9C8.13626 8.46079 7.82837 9.21474 7.82837 10C7.82837 10.2306 7.85491 10.4584 7.90631 10.6795L2.29289 16.2929C2.10536 16.4804 2 16.7348 2 17V20C2 20.5523 2.44772 21 3 21H12C12.2652 21 12.5196 20.8946 12.7071 20.7071L15.3205 18.0937C15.5416 18.1452 15.7695 18.1717 16.0001 18.1717C16.7853 18.1717 17.5393 17.8639 18.1001 17.3142L22.7072 12.7071C23.0977 12.3166 23.0977 11.6834 22.7072 11.2929C22.3167 10.9024 21.6835 10.9024 21.293 11.2929L16.6971 15.8887C16.5105 16.0702 16.2605 16.1717 16.0001 16.1717C15.7397 16.1717 15.4897 16.0702 15.303 15.8887L10.1113 10.697C9.92992 10.5104 9.82837 10.2604 9.82837 10C9.82837 9.73963 9.92992 9.48958 10.1113 9.30297L14.7072 4.70711ZM13.5858 17L9.00004 12.4142L4 17.4142V19H11.5858L13.5858 17Z"
15216
- }
15217
- ) });
15218
- var IconSuperscript = (p) => /* @__PURE__ */ jsxRuntime.jsxs(Frame, { ...p, children: [
15219
- /* @__PURE__ */ jsxRuntime.jsx(
15220
- "path",
15221
- {
15222
- fillRule: "evenodd",
15223
- clipRule: "evenodd",
15224
- d: "M12.7071 7.29289C13.0976 7.68342 13.0976 8.31658 12.7071 8.70711L4.70711 16.7071C4.31658 17.0976 3.68342 17.0976 3.29289 16.7071C2.90237 16.3166 2.90237 15.6834 3.29289 15.2929L11.2929 7.29289C11.6834 6.90237 12.3166 6.90237 12.7071 7.29289Z"
15225
- }
15226
- ),
15227
- /* @__PURE__ */ jsxRuntime.jsx(
15228
- "path",
15229
- {
15230
- fillRule: "evenodd",
15231
- clipRule: "evenodd",
15232
- d: "M3.29289 7.29289C3.68342 6.90237 4.31658 6.90237 4.70711 7.29289L12.7071 15.2929C13.0976 15.6834 13.0976 16.3166 12.7071 16.7071C12.3166 17.0976 11.6834 17.0976 11.2929 16.7071L3.29289 8.70711C2.90237 8.31658 2.90237 7.68342 3.29289 7.29289Z"
15233
- }
15234
- ),
15235
- /* @__PURE__ */ jsxRuntime.jsx(
15236
- "path",
15237
- {
15238
- fillRule: "evenodd",
15239
- clipRule: "evenodd",
15240
- d: "M17.405 1.40657C18.0246 1.05456 18.7463 0.92634 19.4492 1.04344C20.1521 1.16054 20.7933 1.51583 21.2652 2.0497L21.2697 2.05469L21.2696 2.05471C21.7431 2.5975 22 3.28922 22 4.00203C22 5.08579 21.3952 5.84326 20.7727 6.34289C20.1966 6.80531 19.4941 7.13675 18.9941 7.37261C18.9714 7.38332 18.9491 7.39383 18.9273 7.40415C18.4487 7.63034 18.2814 7.78152 18.1927 7.91844C18.1778 7.94155 18.1625 7.96834 18.1473 8.00003H21C21.5523 8.00003 22 8.44774 22 9.00003C22 9.55231 21.5523 10 21 10H17C16.4477 10 16 9.55231 16 9.00003C16 8.17007 16.1183 7.44255 16.5138 6.83161C16.9107 6.21854 17.4934 5.86971 18.0728 5.59591C18.6281 5.33347 19.1376 5.09075 19.5208 4.78316C19.8838 4.49179 20 4.25026 20 4.00203C20 3.77192 19.9178 3.54865 19.7646 3.37182C19.5968 3.18324 19.3696 3.05774 19.1205 3.01625C18.8705 2.97459 18.6137 3.02017 18.3933 3.14533C18.1762 3.26898 18.0191 3.45826 17.9406 3.67557C17.7531 4.19504 17.18 4.46414 16.6605 4.27662C16.141 4.0891 15.8719 3.51596 16.0594 2.99649C16.303 2.3219 16.7817 1.76125 17.4045 1.40689L17.405 1.40657Z"
15241
- }
15242
- )
15243
- ] });
15244
- var IconSubscript = (p) => /* @__PURE__ */ jsxRuntime.jsxs(Frame, { ...p, children: [
15245
- /* @__PURE__ */ jsxRuntime.jsx(
15246
- "path",
15247
- {
15248
- fillRule: "evenodd",
15249
- clipRule: "evenodd",
15250
- d: "M3.29289 7.29289C3.68342 6.90237 4.31658 6.90237 4.70711 7.29289L12.7071 15.2929C13.0976 15.6834 13.0976 16.3166 12.7071 16.7071C12.3166 17.0976 11.6834 17.0976 11.2929 16.7071L3.29289 8.70711C2.90237 8.31658 2.90237 7.68342 3.29289 7.29289Z"
15251
- }
15252
- ),
15253
- /* @__PURE__ */ jsxRuntime.jsx(
15254
- "path",
15255
- {
15256
- fillRule: "evenodd",
15257
- clipRule: "evenodd",
15258
- d: "M12.7071 7.29289C13.0976 7.68342 13.0976 8.31658 12.7071 8.70711L4.70711 16.7071C4.31658 17.0976 3.68342 17.0976 3.29289 16.7071C2.90237 16.3166 2.90237 15.6834 3.29289 15.2929L11.2929 7.29289C11.6834 6.90237 12.3166 6.90237 12.7071 7.29289Z"
15259
- }
15260
- ),
15261
- /* @__PURE__ */ jsxRuntime.jsx(
15262
- "path",
15263
- {
15264
- fillRule: "evenodd",
15265
- clipRule: "evenodd",
15266
- d: "M17.4079 14.3995C18.0284 14.0487 18.7506 13.9217 19.4536 14.0397C20.1566 14.1578 20.7977 14.5138 21.2696 15.0481L21.2779 15.0574L21.2778 15.0575C21.7439 15.5988 22 16.2903 22 17C22 18.0823 21.3962 18.8401 20.7744 19.3404C20.194 19.8073 19.4858 20.141 18.9828 20.378C18.9638 20.387 18.9451 20.3958 18.9266 20.4045C18.4473 20.6306 18.2804 20.7817 18.1922 20.918C18.1773 20.9412 18.1619 20.9681 18.1467 21H21C21.5523 21 22 21.4477 22 22C22 22.5523 21.5523 23 21 23H17C16.4477 23 16 22.5523 16 22C16 21.1708 16.1176 20.4431 16.5128 19.832C16.9096 19.2184 17.4928 18.8695 18.0734 18.5956C18.6279 18.334 19.138 18.0901 19.5207 17.7821C19.8838 17.49 20 17.2477 20 17C20 16.7718 19.9176 16.5452 19.7663 16.3672C19.5983 16.1792 19.3712 16.0539 19.1224 16.0121C18.8722 15.9701 18.6152 16.015 18.3942 16.1394C18.1794 16.2628 18.0205 16.4549 17.9422 16.675C17.7572 17.1954 17.1854 17.4673 16.665 17.2822C16.1446 17.0972 15.8728 16.5254 16.0578 16.005C16.2993 15.3259 16.7797 14.7584 17.4039 14.4018L17.4079 14.3995L17.4079 14.3995Z"
15267
- }
15268
- )
15269
- ] });
15270
15230
  var IconAlignLeft = (p) => /* @__PURE__ */ jsxRuntime.jsxs(Frame, { ...p, children: [
15271
15231
  /* @__PURE__ */ jsxRuntime.jsx(
15272
15232
  "path",
@@ -15558,6 +15518,14 @@ var IconTextColor = (p) => /* @__PURE__ */ jsxRuntime.jsxs(Frame, { ...p, childr
15558
15518
  }
15559
15519
  )
15560
15520
  ] });
15521
+ var IconTable = (p) => /* @__PURE__ */ jsxRuntime.jsx(Frame, { ...p, children: /* @__PURE__ */ jsxRuntime.jsx(
15522
+ "path",
15523
+ {
15524
+ fillRule: "evenodd",
15525
+ clipRule: "evenodd",
15526
+ d: "M3 5C3 4.44772 3.44772 4 4 4H20C20.5523 4 21 4.44772 21 5V19C21 19.5523 20.5523 20 20 20H4C3.44772 20 3 19.5523 3 19V5ZM5 6V9H19V6H5ZM19 11H13V13H19V11ZM19 15H13V18H19V15ZM11 18V15H5V18H11ZM5 13H11V11H5V13Z"
15527
+ }
15528
+ ) });
15561
15529
  var IconHorizontalRule = (p) => /* @__PURE__ */ jsxRuntime.jsxs(Frame, { ...p, children: [
15562
15530
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: 3, y: 5, width: 18, height: 2, rx: 1 }),
15563
15531
  /* @__PURE__ */ jsxRuntime.jsx("rect", { x: 2, y: 11, width: 20, height: 2, rx: 1 }),
@@ -15565,39 +15533,12 @@ var IconHorizontalRule = (p) => /* @__PURE__ */ jsxRuntime.jsxs(Frame, { ...p, c
15565
15533
  ] });
15566
15534
 
15567
15535
  // src/components/SEditor/editor.config.ts
15568
- var SEDITOR_TOOLBAR_ITEMS = [
15569
- "heading",
15570
- "fontSize",
15571
- "bold",
15572
- "italic",
15573
- "underline",
15574
- "strike",
15575
- "code",
15576
- "color",
15577
- "highlight",
15578
- "superscript",
15579
- "subscript",
15580
- "alignLeft",
15581
- "alignCenter",
15582
- "alignRight",
15583
- "alignJustify",
15584
- "bulletList",
15585
- "orderedList",
15586
- "taskList",
15587
- "list",
15588
- "blockquote",
15589
- "codeBlock",
15590
- "horizontalRule",
15591
- "link",
15592
- "image",
15593
- "undo",
15594
- "redo"
15595
- ];
15596
15536
  var SEDITOR_DEFAULT_TOOLBAR = [
15597
15537
  "undo",
15598
15538
  "redo",
15599
15539
  "|",
15600
15540
  "heading",
15541
+ "fontSize",
15601
15542
  "list",
15602
15543
  "blockquote",
15603
15544
  "codeBlock",
@@ -15608,18 +15549,29 @@ var SEDITOR_DEFAULT_TOOLBAR = [
15608
15549
  "code",
15609
15550
  "underline",
15610
15551
  "color",
15611
- "highlight",
15612
15552
  "link",
15613
15553
  "|",
15614
- "superscript",
15615
- "subscript",
15616
- "|",
15617
15554
  "alignLeft",
15618
15555
  "alignCenter",
15619
15556
  "alignRight",
15620
15557
  "alignJustify",
15621
15558
  "|",
15622
- "image"
15559
+ "table",
15560
+ "image",
15561
+ "horizontalRule"
15562
+ ];
15563
+ var SEDITOR_SIMPLE_TOOLBAR = [
15564
+ "undo",
15565
+ "redo",
15566
+ "|",
15567
+ "heading",
15568
+ "fontSize",
15569
+ "|",
15570
+ "bold",
15571
+ "italic",
15572
+ "underline",
15573
+ "strike",
15574
+ "color"
15623
15575
  ];
15624
15576
  var SEDITOR_DEFAULT_BUBBLE_MENU = [
15625
15577
  "bold",
@@ -15629,9 +15581,16 @@ var SEDITOR_DEFAULT_BUBBLE_MENU = [
15629
15581
  "underline",
15630
15582
  "|",
15631
15583
  "color",
15632
- "highlight",
15633
15584
  "link"
15634
15585
  ];
15586
+ var SEDITOR_SIMPLE_BUBBLE_MENU = [
15587
+ "bold",
15588
+ "italic",
15589
+ "strike",
15590
+ "underline",
15591
+ "|",
15592
+ "color"
15593
+ ];
15635
15594
  var SEDITOR_HEADING_LEVELS = [1, 2, 3];
15636
15595
  var SEDITOR_HEADING_LABELS = {
15637
15596
  0: "\uBCF8\uBB38",
@@ -15639,7 +15598,7 @@ var SEDITOR_HEADING_LABELS = {
15639
15598
  2: "\uC81C\uBAA9 2",
15640
15599
  3: "\uC81C\uBAA9 3"
15641
15600
  };
15642
- var SEDITOR_FONT_SIZES = [11, 12, 14, 16, 18];
15601
+ var SEDITOR_FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 24, 30, 36, 48, 60, 72];
15643
15602
  var SEDITOR_DEFAULT_FONT_SIZE = 12;
15644
15603
  var SEDITOR_DEFAULT_COLORS = [
15645
15604
  { label: "\uAE30\uBCF8", color: "var(--color-fg-primary)" },
@@ -15651,17 +15610,13 @@ var SEDITOR_DEFAULT_COLORS = [
15651
15610
  { label: "\uC8FC\uC758", color: "var(--color-fg-warning)" },
15652
15611
  { label: "\uC704\uD5D8", color: "var(--color-fg-danger)" }
15653
15612
  ];
15654
- var SEDITOR_DEFAULT_HIGHLIGHTS = [
15655
- { label: "\uB178\uB791", color: "yellow_25" },
15656
- { label: "\uCD08\uB85D", color: "green_25" },
15657
- { label: "\uD30C\uB791", color: "brilliantblue_25" },
15658
- { label: "\uBE68\uAC15", color: "red_20" },
15659
- { label: "\uC8FC\uD669", color: "orange_20" },
15660
- { label: "\uD68C\uC0C9", color: "grey_20" }
15661
- ];
15662
15613
  var TASK_LIST_CLASS = "sd-editor-task-list";
15663
15614
  var TASK_ITEM_CLASS = "sd-editor-task-item";
15664
15615
  var IMAGE_CLASS = "sd-editor-image";
15616
+ var TABLE_CLASS = "sd-editor-table";
15617
+ var TABLE_ROW_CLASS = "sd-editor-table-row";
15618
+ var TABLE_HEADER_CLASS = "sd-editor-table-header";
15619
+ var TABLE_CELL_CLASS = "sd-editor-table-cell";
15665
15620
  var SEDITOR_CONTENT_CLASS = [
15666
15621
  "[&_.ProseMirror]:min-h-full [&_.ProseMirror]:outline-none [&_.ProseMirror]:whitespace-pre-wrap [&_.ProseMirror]:break-words",
15667
15622
  // placeholder — Placeholder 확장이 빈 첫 문단에 data-placeholder 와 클래스를 붙인다
@@ -15674,23 +15629,38 @@ var SEDITOR_CONTENT_CLASS = [
15674
15629
  "[&_ol]:my-[4px] [&_ol]:list-decimal [&_ol]:pl-[20px]",
15675
15630
  "[&_li]:my-0 [&_li>p]:my-0",
15676
15631
  // 체크목록 — 마커를 지우고 체크박스와 본문을 가로로 세운다
15677
- `[&_.${TASK_LIST_CLASS}]:my-[4px] [&_.${TASK_LIST_CLASS}]:list-none [&_.${TASK_LIST_CLASS}]:pl-0`,
15678
- `[&_.${TASK_ITEM_CLASS}]:flex [&_.${TASK_ITEM_CLASS}]:items-start [&_.${TASK_ITEM_CLASS}]:gap-[6px]`,
15679
- `[&_.${TASK_ITEM_CLASS}>label]:mt-[3px] [&_.${TASK_ITEM_CLASS}>label]:shrink-0 [&_.${TASK_ITEM_CLASS}>label]:leading-none`,
15680
- `[&_.${TASK_ITEM_CLASS}>div]:min-w-0 [&_.${TASK_ITEM_CLASS}>div]:flex-1`,
15681
- `[&_.${TASK_ITEM_CLASS}_input]:m-0 [&_.${TASK_ITEM_CLASS}_input]:h-[13px] [&_.${TASK_ITEM_CLASS}_input]:w-[13px] [&_.${TASK_ITEM_CLASS}_input]:cursor-pointer [&_.${TASK_ITEM_CLASS}_input]:accent-[var(--color-fg-accent)]`,
15682
- `[&_.${TASK_ITEM_CLASS}[data-checked=true]>div]:text-[color:var(--color-fg-tertiary)] [&_.${TASK_ITEM_CLASS}[data-checked=true]>div]:line-through`,
15632
+ "[&_.sd-editor-task-list]:my-[4px] [&_.sd-editor-task-list]:list-none [&_.sd-editor-task-list]:pl-0",
15633
+ "[&_.sd-editor-task-item]:flex [&_.sd-editor-task-item]:items-start [&_.sd-editor-task-item]:gap-[6px]",
15634
+ "[&_.sd-editor-task-item>label]:mt-[3px] [&_.sd-editor-task-item>label]:shrink-0 [&_.sd-editor-task-item>label]:leading-none",
15635
+ "[&_.sd-editor-task-item>div]:min-w-0 [&_.sd-editor-task-item>div]:flex-1",
15636
+ "[&_.sd-editor-task-item_input]:m-0 [&_.sd-editor-task-item_input]:h-[13px] [&_.sd-editor-task-item_input]:w-[13px] [&_.sd-editor-task-item_input]:cursor-pointer [&_.sd-editor-task-item_input]:accent-[var(--color-fg-accent)]",
15637
+ "[&_.sd-editor-task-item[data-checked=true]>div]:text-[color:var(--color-fg-tertiary)] [&_.sd-editor-task-item[data-checked=true]>div]:line-through",
15683
15638
  "[&_blockquote]:my-[8px] [&_blockquote]:border-l-[3px] [&_blockquote]:border-solid [&_blockquote]:border-l-[color:var(--color-border-default)] [&_blockquote]:pl-[12px] [&_blockquote]:text-[color:var(--color-fg-tertiary)]",
15684
15639
  "[&_a]:cursor-pointer [&_a]:text-[color:var(--color-fg-accent)] [&_a]:underline",
15685
15640
  "[&_hr]:my-[12px] [&_hr]:border-t [&_hr]:border-[color:var(--color-border-default)]",
15686
15641
  "[&_code]:rounded-[3px] [&_code]:bg-[var(--color-bg-neutralLight)] [&_code]:px-[4px] [&_code]:py-[1px]",
15687
15642
  "[&_pre]:my-[8px] [&_pre]:rounded-[4px] [&_pre]:bg-[var(--color-bg-neutralLight)] [&_pre]:p-[12px]",
15688
15643
  "[&_pre_code]:bg-transparent [&_pre_code]:p-0",
15689
- `[&_.${IMAGE_CLASS}]:my-[8px] [&_.${IMAGE_CLASS}]:h-auto [&_.${IMAGE_CLASS}]:max-w-full [&_.${IMAGE_CLASS}]:rounded-[4px]`,
15644
+ "[&_.sd-editor-image]:my-[8px] [&_.sd-editor-image]:h-auto [&_.sd-editor-image]:max-w-full [&_.sd-editor-image]:rounded-[4px]",
15645
+ /**
15646
+ * 표 — `table-layout: fixed` 로 열을 균등하게 나눈다.
15647
+ *
15648
+ * 열 너비를 저장하지 않기로 했으므로(tiptap-api.ts 의 Table 주석) 폭은 언제나 여기서
15649
+ * 정해진다. auto 로 두면 글자 많은 열이 넓어져 같은 표가 화면마다 다르게 보이고, 긴
15650
+ * 단어 하나가 상자 밖으로 표를 밀어낸다.
15651
+ */
15652
+ "[&_.sd-editor-table]:my-[8px] [&_.sd-editor-table]:w-full [&_.sd-editor-table]:table-fixed [&_.sd-editor-table]:border-collapse",
15653
+ "[&_.sd-editor-table-header]:border [&_.sd-editor-table-header]:border-solid [&_.sd-editor-table-header]:border-[color:var(--color-border-default)] [&_.sd-editor-table-header]:bg-[var(--color-bg-neutralLight)] [&_.sd-editor-table-header]:px-[8px] [&_.sd-editor-table-header]:py-[4px] [&_.sd-editor-table-header]:text-left [&_.sd-editor-table-header]:align-top [&_.sd-editor-table-header]:font-bold",
15654
+ "[&_.sd-editor-table-cell]:border [&_.sd-editor-table-cell]:border-solid [&_.sd-editor-table-cell]:border-[color:var(--color-border-default)] [&_.sd-editor-table-cell]:px-[8px] [&_.sd-editor-table-cell]:py-[4px] [&_.sd-editor-table-cell]:align-top",
15655
+ // 칸 안의 문단은 표 밖과 달리 위아래 여백을 갖지 않는다 — 한 줄짜리 칸이 대부분이다
15656
+ "[&_.sd-editor-table-header>p]:my-0 [&_.sd-editor-table-cell>p]:my-0",
15657
+ /*
15658
+ 고른 칸 표시 — ProseMirror 표 플러그인이 `.selectedCell` 을 붙인다. 배경을 직접 칠하면
15659
+ 칸이 자기 배경(헤더의 회색)을 잃으므로 덧대는 판을 하나 얹는다.
15660
+ */
15661
+ "[&_.selectedCell]:relative [&_.selectedCell]:after:pointer-events-none [&_.selectedCell]:after:absolute [&_.selectedCell]:after:inset-0 [&_.selectedCell]:after:bg-[var(--color-bg-accentFaint)]",
15690
15662
  "[&_.ProseMirror-selectednode]:outline [&_.ProseMirror-selectednode]:outline-2 [&_.ProseMirror-selectednode]:outline-[var(--color-border-accent)]",
15691
- "[&_strong]:font-bold [&_em]:italic [&_u]:underline [&_s]:line-through",
15692
- "[&_sup]:align-super [&_sup]:text-[0.75em] [&_sub]:align-sub [&_sub]:text-[0.75em]",
15693
- "[&_mark]:rounded-[2px] [&_mark]:bg-transparent [&_mark]:px-[1px]"
15663
+ "[&_strong]:font-bold [&_em]:italic [&_u]:underline [&_s]:line-through"
15694
15664
  ].join(" ");
15695
15665
  var BODY = { fontSize: 12, lineHeight: "20px", paddingX: 12, paddingY: 8 };
15696
15666
  var cssLen3 = (v) => typeof v === "number" ? `${v}px` : v;
@@ -15759,22 +15729,28 @@ var ToolbarButton = /* @__PURE__ */ react.forwardRef(function ToolbarButton2({ l
15759
15729
  }
15760
15730
  );
15761
15731
  });
15762
- var Separator = () => /* @__PURE__ */ jsxRuntime.jsx(
15732
+ var Separator2 = () => /* @__PURE__ */ jsxRuntime.jsx(
15763
15733
  "span",
15764
15734
  {
15765
15735
  "aria-hidden": true,
15766
- className: "mx-[2px] h-[16px] w-[1px] shrink-0",
15767
- style: { background: "var(--sys-color-field-border-default)" }
15736
+ className: "mx-[4px] h-[16px] w-[1px] shrink-0",
15737
+ style: { background: "var(--sys-color-border-default)" }
15768
15738
  }
15769
15739
  );
15770
15740
  var ColorIndicator = ({ color, children }) => /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex flex-col items-center gap-[1px]", children: [
15771
15741
  children,
15772
15742
  /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "h-[3px] w-[16px] rounded-[1px]", style: { background: color } })
15773
15743
  ] });
15774
- var menuClass = cn(
15775
- "z-50 overflow-hidden rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] p-[4px] shadow-normal-sm",
15776
- FLOATING_SLIDE_ANIM
15744
+ var MENU_BASE_CLASS = "z-50 rounded-[var(--cmp-listBox-radius)] bg-[var(--cmp-listBox-bg)] p-[4px] shadow-normal-sm";
15745
+ var menuClass = cn(MENU_BASE_CLASS, "overflow-hidden", FLOATING_SLIDE_ANIM);
15746
+ var scrollMenuClass = cn(
15747
+ MENU_BASE_CLASS,
15748
+ "overflow-x-hidden overflow-y-auto",
15749
+ FLOATING_SLIDE_ANIM,
15750
+ SCROLLBAR_CLASS
15777
15751
  );
15752
+ var FONT_SIZE_DEFAULT_LABEL = "\uAE30\uBCF8";
15753
+ var FONT_SIZE_MENU_MAX_HEIGHT = "min(280px, var(--radix-dropdown-menu-content-available-height))";
15778
15754
  var swatchClass = cn(
15779
15755
  "flex h-[24px] w-[24px] cursor-pointer items-center justify-center rounded-[4px] outline-none",
15780
15756
  "hover:bg-[var(--color-bg-neutralLight)] data-[highlighted]:bg-[var(--color-bg-neutralLight)]"
@@ -15789,6 +15765,9 @@ var menuItemClass = cn(
15789
15765
  "text-[color:var(--sys-color-fg-secondary)]",
15790
15766
  "data-[highlighted]:bg-[var(--sys-color-bg-accent)] data-[highlighted]:text-[color:var(--sys-color-fg-inverse)]"
15791
15767
  );
15768
+ var menuItemSelectedClass = "bg-[var(--cmp-listItem-bg-selected)] text-[color:var(--cmp-listItem-text-selected)]";
15769
+ var menuItemDisabledClass = "data-[disabled]:cursor-not-allowed data-[disabled]:bg-transparent data-[disabled]:text-[color:var(--cmp-ghostButton-icon-disabled)]";
15770
+ var menuSeparatorClass = "my-[4px] h-[1px] bg-[var(--sys-color-border-default)]";
15792
15771
  var PaletteItem = ({
15793
15772
  asMenu,
15794
15773
  label,
@@ -15830,6 +15809,111 @@ var ColorPalette = ({
15830
15809
  ),
15831
15810
  /* @__PURE__ */ jsxRuntime.jsx(PaletteItem, { asMenu, className: cn(menuItemClass, "w-full"), onSelect: onClear, children: clearLabel })
15832
15811
  ] });
15812
+ var TABLE_PICKER_ROWS = 8;
15813
+ var TABLE_PICKER_COLS = 8;
15814
+ var TABLE_PICKER_CELL = 16;
15815
+ var TABLE_PICKER_GAP = 4;
15816
+ var TableSizePicker = ({
15817
+ disabled,
15818
+ onPick
15819
+ }) => {
15820
+ const [size, setSize] = react.useState({ rows: 1, cols: 1 });
15821
+ const gridRef = react.useRef(null);
15822
+ react.useEffect(() => {
15823
+ if (disabled) return void 0;
15824
+ const id = setTimeout(() => gridRef.current?.focus(), 0);
15825
+ return () => clearTimeout(id);
15826
+ }, [disabled]);
15827
+ const clamp4 = (v, max) => Math.min(Math.max(v, 1), max);
15828
+ const move = (dRow, dCol) => setSize((p) => ({
15829
+ rows: clamp4(p.rows + dRow, TABLE_PICKER_ROWS),
15830
+ cols: clamp4(p.cols + dCol, TABLE_PICKER_COLS)
15831
+ }));
15832
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-[4px]", children: [
15833
+ /* @__PURE__ */ jsxRuntime.jsx(
15834
+ "div",
15835
+ {
15836
+ ref: gridRef,
15837
+ role: "grid",
15838
+ "aria-label": "\uD45C \uD06C\uAE30",
15839
+ "aria-disabled": disabled || void 0,
15840
+ tabIndex: disabled ? -1 : 0,
15841
+ className: cn("flex flex-col outline-none", disabled && "pointer-events-none opacity-40"),
15842
+ style: { gap: TABLE_PICKER_GAP },
15843
+ onKeyDown: (e) => {
15844
+ const step = {
15845
+ ArrowUp: [-1, 0],
15846
+ ArrowDown: [1, 0],
15847
+ ArrowLeft: [0, -1],
15848
+ ArrowRight: [0, 1]
15849
+ };
15850
+ const d = step[e.key];
15851
+ if (d) {
15852
+ e.preventDefault();
15853
+ e.stopPropagation();
15854
+ move(d[0], d[1]);
15855
+ return;
15856
+ }
15857
+ if (e.key === "Enter" || e.key === " ") {
15858
+ e.preventDefault();
15859
+ e.stopPropagation();
15860
+ onPick(size.rows, size.cols);
15861
+ }
15862
+ },
15863
+ 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) => {
15864
+ const on = r < size.rows && c < size.cols;
15865
+ return /* @__PURE__ */ jsxRuntime.jsx(
15866
+ "button",
15867
+ {
15868
+ type: "button",
15869
+ role: "gridcell",
15870
+ "aria-label": `${r + 1}\uD589 ${c + 1}\uC5F4`,
15871
+ "aria-selected": on,
15872
+ tabIndex: -1,
15873
+ className: "box-border cursor-pointer rounded-[3px] border border-solid p-0 outline-none",
15874
+ style: {
15875
+ width: TABLE_PICKER_CELL,
15876
+ height: TABLE_PICKER_CELL,
15877
+ borderColor: on ? "var(--sys-color-bg-accent)" : "var(--sys-color-border-default)",
15878
+ background: on ? "var(--color-bg-accentFaint)" : "transparent"
15879
+ },
15880
+ onMouseEnter: () => setSize({ rows: r + 1, cols: c + 1 }),
15881
+ onFocus: () => setSize({ rows: r + 1, cols: c + 1 }),
15882
+ onClick: () => onPick(r + 1, c + 1)
15883
+ },
15884
+ c
15885
+ );
15886
+ }) }, r))
15887
+ }
15888
+ ),
15889
+ /* @__PURE__ */ jsxRuntime.jsxs(
15890
+ "div",
15891
+ {
15892
+ "aria-live": "polite",
15893
+ className: "mt-[6px] text-center text-[12px] leading-[20px] text-[color:var(--sys-color-fg-secondary)]",
15894
+ children: [
15895
+ size.rows,
15896
+ "\uD589 \xD7 ",
15897
+ size.cols,
15898
+ "\uC5F4"
15899
+ ]
15900
+ }
15901
+ )
15902
+ ] });
15903
+ };
15904
+ var TableMenuItem = ({
15905
+ label,
15906
+ disabled,
15907
+ onSelect
15908
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
15909
+ RDropdown2__namespace.Item,
15910
+ {
15911
+ className: cn(menuItemClass, menuItemDisabledClass),
15912
+ disabled,
15913
+ onSelect,
15914
+ children: label
15915
+ }
15916
+ );
15833
15917
  var LinkEditor = ({
15834
15918
  href,
15835
15919
  onHrefChange,
@@ -15857,8 +15941,8 @@ var LinkEditor = ({
15857
15941
  /* @__PURE__ */ jsxRuntime.jsx(SButton, { size: "sm", label: "\uC801\uC6A9", onClick: onApply }),
15858
15942
  hasLink && /* @__PURE__ */ jsxRuntime.jsx(SButton, { size: "sm", color: "neutral", outline: true, label: "\uC81C\uAC70", onClick: onRemove })
15859
15943
  ] });
15860
- var TOOLBAR_BAR_CLASS = "flex flex-wrap items-center gap-[2px] border-b border-solid px-[8px] py-[4px]";
15861
- var TOOLBAR_BAR_STYLE = { borderBottomColor: "var(--sys-color-field-border-default)" };
15944
+ var TOOLBAR_BAR_CLASS = "sticky top-0 z-[1] flex flex-wrap items-center gap-[2px] border-b border-solid bg-inherit px-[8px] py-[4px]";
15945
+ var TOOLBAR_BAR_STYLE = { borderBottomColor: "var(--sys-color-border-default)" };
15862
15946
  var BUBBLE_BAR_CLASS = cn(
15863
15947
  "flex max-w-[calc(100vw-32px)] items-center gap-[2px] overflow-x-auto rounded-[var(--cmp-listBox-radius)]",
15864
15948
  "bg-[var(--cmp-listBox-bg)] px-[6px] py-[4px] shadow-normal-sm"
@@ -15870,8 +15954,6 @@ var readEditorState = (e) => ({
15870
15954
  underline: e.isActive("underline"),
15871
15955
  strike: e.isActive("strike"),
15872
15956
  code: e.isActive("code"),
15873
- superscript: e.isActive("superscript"),
15874
- subscript: e.isActive("subscript"),
15875
15957
  alignLeft: e.isActive({ textAlign: "left" }),
15876
15958
  alignCenter: e.isActive({ textAlign: "center" }),
15877
15959
  alignRight: e.isActive({ textAlign: "right" }),
@@ -15882,9 +15964,11 @@ var readEditorState = (e) => ({
15882
15964
  blockquote: e.isActive("blockquote"),
15883
15965
  codeBlock: e.isActive("codeBlock"),
15884
15966
  link: e.isActive("link"),
15967
+ inTable: e.isActive("table"),
15968
+ canMergeCells: e.can().mergeCells(),
15969
+ canSplitCell: e.can().splitCell(),
15885
15970
  linkHref: e.getAttributes("link").href ?? "",
15886
15971
  color: e.getAttributes("textStyle").color ?? "",
15887
- highlight: e.getAttributes("highlight").color ?? "",
15888
15972
  fontSize: e.getAttributes("textStyle").fontSize ?? "",
15889
15973
  canUndo: e.can().undo(),
15890
15974
  canRedo: e.can().redo()
@@ -15896,8 +15980,6 @@ var IDLE_TOOLBAR_STATE = {
15896
15980
  underline: false,
15897
15981
  strike: false,
15898
15982
  code: false,
15899
- superscript: false,
15900
- subscript: false,
15901
15983
  alignLeft: false,
15902
15984
  alignCenter: false,
15903
15985
  alignRight: false,
@@ -15909,8 +15991,10 @@ var IDLE_TOOLBAR_STATE = {
15909
15991
  codeBlock: false,
15910
15992
  link: false,
15911
15993
  linkHref: "",
15994
+ inTable: false,
15995
+ canMergeCells: false,
15996
+ canSplitCell: false,
15912
15997
  color: "",
15913
- highlight: "",
15914
15998
  fontSize: "",
15915
15999
  canUndo: false,
15916
16000
  canRedo: false
@@ -15919,9 +16003,6 @@ function EditorToolbarBar({
15919
16003
  state: state2,
15920
16004
  editor,
15921
16005
  items,
15922
- fontSizes,
15923
- colors,
15924
- highlights,
15925
16006
  onImageUpload,
15926
16007
  disabled,
15927
16008
  variant = "bar"
@@ -15930,6 +16011,7 @@ function EditorToolbarBar({
15930
16011
  const insideModal = useInsideModal();
15931
16012
  const isMobile = useIsMobile();
15932
16013
  const [linkOpen, setLinkOpen] = react.useState(false);
16014
+ const [tableOpen, setTableOpen] = react.useState(false);
15933
16015
  const [linkHref, setLinkHref] = react.useState("");
15934
16016
  const [uploading, setUploading] = react.useState(false);
15935
16017
  const [mobileView, setMobileView] = react.useState("main");
@@ -15944,9 +16026,8 @@ function EditorToolbarBar({
15944
16026
  const chain = () => editor?.chain()?.focus();
15945
16027
  const off = disabled;
15946
16028
  const currentFontSize = Number.parseInt(state2.fontSize, 10);
15947
- const activeFontSize = Number.isNaN(currentFontSize) ? SEDITOR_DEFAULT_FONT_SIZE : currentFontSize;
16029
+ const activeFontSize = Number.isNaN(currentFontSize) ? null : currentFontSize;
15948
16030
  const activeColor = resolveColor(state2.color) ?? "currentColor";
15949
- const activeHighlight = resolveColor(state2.highlight) ?? "currentColor";
15950
16031
  const pickImage = async (e) => {
15951
16032
  const file = e.target.files?.[0];
15952
16033
  e.target.value = "";
@@ -15963,8 +16044,6 @@ function EditorToolbarBar({
15963
16044
  };
15964
16045
  const applyColor = (color) => chain()?.setColor(resolveColor(color) ?? "inherit").run();
15965
16046
  const clearColor = () => chain()?.unsetColor().run();
15966
- const applyHighlight = (color) => chain()?.setHighlight({ color: resolveColor(color) ?? "transparent" }).run();
15967
- const clearHighlight = () => chain()?.unsetHighlight().run();
15968
16047
  const closeLinkEditor = () => {
15969
16048
  setLinkOpen(false);
15970
16049
  setMobileView("main");
@@ -16031,18 +16110,41 @@ function EditorToolbarBar({
16031
16110
  case "fontSize":
16032
16111
  return /* @__PURE__ */ jsxRuntime.jsxs(RDropdown2__namespace.Root, { modal: !insideModal, children: [
16033
16112
  /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxRuntime.jsxs(ToolbarButton, { label: "\uAE00\uC790 \uD06C\uAE30", disabled: off, className: "px-[6px]", children: [
16034
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] leading-[20px]", children: activeFontSize }),
16113
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] leading-[20px]", children: activeFontSize ?? FONT_SIZE_DEFAULT_LABEL }),
16035
16114
  /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "caretDown", size: 12 })
16036
16115
  ] }) }),
16037
- /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Content, { sideOffset: 4, align: "start", className: menuClass, children: fontSizes.map((size) => /* @__PURE__ */ jsxRuntime.jsx(
16038
- RDropdown2__namespace.Item,
16116
+ /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(
16117
+ RDropdown2__namespace.Content,
16039
16118
  {
16040
- className: menuItemClass,
16041
- onSelect: () => size === SEDITOR_DEFAULT_FONT_SIZE ? chain()?.unsetFontSize().run() : chain()?.setFontSize(`${size}px`).run(),
16042
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: size, lineHeight: "20px" }, children: size })
16043
- },
16044
- size
16045
- )) }) })
16119
+ sideOffset: 4,
16120
+ align: "start",
16121
+ className: cn(scrollMenuClass, "min-w-[72px]"),
16122
+ style: { maxHeight: FONT_SIZE_MENU_MAX_HEIGHT },
16123
+ children: [
16124
+ /* @__PURE__ */ jsxRuntime.jsx(
16125
+ RDropdown2__namespace.Item,
16126
+ {
16127
+ className: cn(menuItemClass, activeFontSize === null && menuItemSelectedClass),
16128
+ title: `${FONT_SIZE_DEFAULT_LABEL} (\uBCF8\uBB38 ${SEDITOR_DEFAULT_FONT_SIZE}px)`,
16129
+ onSelect: () => chain()?.unsetFontSize().run(),
16130
+ children: FONT_SIZE_DEFAULT_LABEL
16131
+ }
16132
+ ),
16133
+ SEDITOR_FONT_SIZES.map((size) => /* @__PURE__ */ jsxRuntime.jsx(
16134
+ RDropdown2__namespace.Item,
16135
+ {
16136
+ ref: activeFontSize === size ? (el) => {
16137
+ el?.scrollIntoView({ block: "nearest" });
16138
+ } : void 0,
16139
+ className: cn(menuItemClass, activeFontSize === size && menuItemSelectedClass),
16140
+ onSelect: () => chain()?.setFontSize(`${size}px`).run(),
16141
+ children: size
16142
+ },
16143
+ size
16144
+ ))
16145
+ ]
16146
+ }
16147
+ ) })
16046
16148
  ] }, item);
16047
16149
  case "bold":
16048
16150
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -16127,7 +16229,7 @@ function EditorToolbarBar({
16127
16229
  ColorPalette,
16128
16230
  {
16129
16231
  asMenu: true,
16130
- colors,
16232
+ colors: SEDITOR_DEFAULT_COLORS,
16131
16233
  columns: 4,
16132
16234
  clearLabel: "\uC0C9 \uC9C0\uC6B0\uAE30",
16133
16235
  onPick: applyColor,
@@ -16135,58 +16237,6 @@ function EditorToolbarBar({
16135
16237
  }
16136
16238
  ) }) })
16137
16239
  ] }, item);
16138
- case "highlight":
16139
- if (mobile)
16140
- return /* @__PURE__ */ jsxRuntime.jsx(
16141
- ToolbarButton,
16142
- {
16143
- label: "\uD615\uAD11\uD39C",
16144
- disabled: off,
16145
- onClick: () => setMobileView("highlight"),
16146
- children: /* @__PURE__ */ jsxRuntime.jsx(ColorIndicator, { color: off ? "currentColor" : activeHighlight, children: /* @__PURE__ */ jsxRuntime.jsx(IconHighlight, { size: ICON_SIZE }) })
16147
- },
16148
- item
16149
- );
16150
- return /* @__PURE__ */ jsxRuntime.jsxs(RDropdown2__namespace.Root, { modal: !insideModal, children: [
16151
- /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { label: "\uD615\uAD11\uD39C", disabled: off, children: /* @__PURE__ */ jsxRuntime.jsx(ColorIndicator, { color: off ? "currentColor" : activeHighlight, children: /* @__PURE__ */ jsxRuntime.jsx(IconHighlight, { size: ICON_SIZE }) }) }) }),
16152
- /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Content, { sideOffset: 4, align: "start", className: menuClass, children: /* @__PURE__ */ jsxRuntime.jsx(
16153
- ColorPalette,
16154
- {
16155
- asMenu: true,
16156
- colors: highlights,
16157
- columns: 3,
16158
- clearLabel: "\uD615\uAD11\uD39C \uC9C0\uC6B0\uAE30",
16159
- onPick: applyHighlight,
16160
- onClear: clearHighlight
16161
- }
16162
- ) }) })
16163
- ] }, item);
16164
- case "superscript":
16165
- return /* @__PURE__ */ jsxRuntime.jsx(
16166
- ToolbarButton,
16167
- {
16168
- label: "\uC704 \uCCA8\uC790",
16169
- active: state2.superscript,
16170
- "aria-pressed": state2.superscript,
16171
- disabled: off,
16172
- onClick: () => chain()?.toggleSuperscript().run(),
16173
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSuperscript, { size: ICON_SIZE })
16174
- },
16175
- item
16176
- );
16177
- case "subscript":
16178
- return /* @__PURE__ */ jsxRuntime.jsx(
16179
- ToolbarButton,
16180
- {
16181
- label: "\uC544\uB798 \uCCA8\uC790",
16182
- active: state2.subscript,
16183
- "aria-pressed": state2.subscript,
16184
- disabled: off,
16185
- onClick: () => chain()?.toggleSubscript().run(),
16186
- children: /* @__PURE__ */ jsxRuntime.jsx(IconSubscript, { size: ICON_SIZE })
16187
- },
16188
- item
16189
- );
16190
16240
  case "alignLeft":
16191
16241
  return /* @__PURE__ */ jsxRuntime.jsx(
16192
16242
  ToolbarButton,
@@ -16412,6 +16462,127 @@ function EditorToolbarBar({
16412
16462
  },
16413
16463
  item
16414
16464
  );
16465
+ case "table":
16466
+ return /* @__PURE__ */ jsxRuntime.jsxs(
16467
+ RDropdown2__namespace.Root,
16468
+ {
16469
+ open: tableOpen,
16470
+ onOpenChange: setTableOpen,
16471
+ modal: !insideModal,
16472
+ children: [
16473
+ /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxRuntime.jsxs(ToolbarButton, { label: "\uD45C", active: state2.inTable, disabled: off, className: "px-[6px]", children: [
16474
+ /* @__PURE__ */ jsxRuntime.jsx(IconTable, { size: ICON_SIZE }),
16475
+ /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "caretDown", size: CARET_SIZE })
16476
+ ] }) }),
16477
+ /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsxs(RDropdown2__namespace.Content, { sideOffset: 4, align: "start", className: menuClass, children: [
16478
+ !state2.inTable && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16479
+ /* @__PURE__ */ jsxRuntime.jsx(
16480
+ TableSizePicker,
16481
+ {
16482
+ disabled: state2.inTable,
16483
+ onPick: (rows, cols) => {
16484
+ chain()?.insertTable({ rows, cols, withHeaderRow: true }).run();
16485
+ setTableOpen(false);
16486
+ }
16487
+ }
16488
+ ),
16489
+ /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Separator, { className: menuSeparatorClass })
16490
+ ] }),
16491
+ /* @__PURE__ */ jsxRuntime.jsx(
16492
+ TableMenuItem,
16493
+ {
16494
+ label: "\uC704\uC5D0 \uD589 \uCD94\uAC00",
16495
+ disabled: !state2.inTable,
16496
+ onSelect: () => chain()?.addRowBefore().run()
16497
+ }
16498
+ ),
16499
+ /* @__PURE__ */ jsxRuntime.jsx(
16500
+ TableMenuItem,
16501
+ {
16502
+ label: "\uC544\uB798\uC5D0 \uD589 \uCD94\uAC00",
16503
+ disabled: !state2.inTable,
16504
+ onSelect: () => chain()?.addRowAfter().run()
16505
+ }
16506
+ ),
16507
+ /* @__PURE__ */ jsxRuntime.jsx(
16508
+ TableMenuItem,
16509
+ {
16510
+ label: "\uC67C\uCABD\uC5D0 \uC5F4 \uCD94\uAC00",
16511
+ disabled: !state2.inTable,
16512
+ onSelect: () => chain()?.addColumnBefore().run()
16513
+ }
16514
+ ),
16515
+ /* @__PURE__ */ jsxRuntime.jsx(
16516
+ TableMenuItem,
16517
+ {
16518
+ label: "\uC624\uB978\uCABD\uC5D0 \uC5F4 \uCD94\uAC00",
16519
+ disabled: !state2.inTable,
16520
+ onSelect: () => chain()?.addColumnAfter().run()
16521
+ }
16522
+ ),
16523
+ /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Separator, { className: menuSeparatorClass }),
16524
+ /* @__PURE__ */ jsxRuntime.jsx(
16525
+ TableMenuItem,
16526
+ {
16527
+ label: "\uC140 \uBCD1\uD569",
16528
+ disabled: !state2.canMergeCells,
16529
+ onSelect: () => chain()?.mergeCells().run()
16530
+ }
16531
+ ),
16532
+ /* @__PURE__ */ jsxRuntime.jsx(
16533
+ TableMenuItem,
16534
+ {
16535
+ label: "\uBCD1\uD569 \uD574\uC81C",
16536
+ disabled: !state2.canSplitCell,
16537
+ onSelect: () => chain()?.splitCell().run()
16538
+ }
16539
+ ),
16540
+ /* @__PURE__ */ jsxRuntime.jsx(
16541
+ TableMenuItem,
16542
+ {
16543
+ label: "\uD5E4\uB354 \uD589 \uD1A0\uAE00",
16544
+ disabled: !state2.inTable,
16545
+ onSelect: () => chain()?.toggleHeaderRow().run()
16546
+ }
16547
+ ),
16548
+ /* @__PURE__ */ jsxRuntime.jsx(
16549
+ TableMenuItem,
16550
+ {
16551
+ label: "\uD5E4\uB354 \uC5F4 \uD1A0\uAE00",
16552
+ disabled: !state2.inTable,
16553
+ onSelect: () => chain()?.toggleHeaderColumn().run()
16554
+ }
16555
+ ),
16556
+ /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Separator, { className: menuSeparatorClass }),
16557
+ /* @__PURE__ */ jsxRuntime.jsx(
16558
+ TableMenuItem,
16559
+ {
16560
+ label: "\uD589 \uC0AD\uC81C",
16561
+ disabled: !state2.inTable,
16562
+ onSelect: () => chain()?.deleteRow().run()
16563
+ }
16564
+ ),
16565
+ /* @__PURE__ */ jsxRuntime.jsx(
16566
+ TableMenuItem,
16567
+ {
16568
+ label: "\uC5F4 \uC0AD\uC81C",
16569
+ disabled: !state2.inTable,
16570
+ onSelect: () => chain()?.deleteColumn().run()
16571
+ }
16572
+ ),
16573
+ /* @__PURE__ */ jsxRuntime.jsx(
16574
+ TableMenuItem,
16575
+ {
16576
+ label: "\uD45C \uC0AD\uC81C",
16577
+ disabled: !state2.inTable,
16578
+ onSelect: () => chain()?.deleteTable().run()
16579
+ }
16580
+ )
16581
+ ] }) })
16582
+ ]
16583
+ },
16584
+ item
16585
+ );
16415
16586
  case "undo":
16416
16587
  return /* @__PURE__ */ jsxRuntime.jsx(
16417
16588
  ToolbarButton,
@@ -16448,7 +16619,6 @@ function EditorToolbarBar({
16448
16619
  if (mobileView !== "main") {
16449
16620
  const editing = {
16450
16621
  color: { icon: /* @__PURE__ */ jsxRuntime.jsx(IconTextColor, { size: ICON_SIZE }), label: "\uAE00\uC790\uC0C9" },
16451
- highlight: { icon: /* @__PURE__ */ jsxRuntime.jsx(IconHighlight, { size: ICON_SIZE }), label: "\uD615\uAD11\uD39C" },
16452
16622
  link: { icon: /* @__PURE__ */ jsxRuntime.jsx(IconLink, { size: ICON_SIZE }), label: "\uB9C1\uD06C" }
16453
16623
  }[mobileView];
16454
16624
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...shell, children: [
@@ -16464,7 +16634,7 @@ function EditorToolbarBar({
16464
16634
  ]
16465
16635
  }
16466
16636
  ) }),
16467
- /* @__PURE__ */ jsxRuntime.jsx(Separator, {}),
16637
+ /* @__PURE__ */ jsxRuntime.jsx(Separator2, {}),
16468
16638
  mobileView === "link" ? /* @__PURE__ */ jsxRuntime.jsx(
16469
16639
  LinkEditor,
16470
16640
  {
@@ -16477,18 +16647,18 @@ function EditorToolbarBar({
16477
16647
  ) : /* @__PURE__ */ jsxRuntime.jsx(
16478
16648
  ColorPalette,
16479
16649
  {
16480
- colors: mobileView === "color" ? colors : highlights,
16481
- columns: mobileView === "color" ? 4 : 3,
16482
- clearLabel: mobileView === "color" ? "\uC0C9 \uC9C0\uC6B0\uAE30" : "\uD615\uAD11\uD39C \uC9C0\uC6B0\uAE30",
16483
- onPick: mobileView === "color" ? applyColor : applyHighlight,
16484
- onClear: mobileView === "color" ? clearColor : clearHighlight
16650
+ colors: SEDITOR_DEFAULT_COLORS,
16651
+ columns: 4,
16652
+ clearLabel: "\uC0C9 \uC9C0\uC6B0\uAE30",
16653
+ onPick: applyColor,
16654
+ onClear: clearColor
16485
16655
  }
16486
16656
  )
16487
16657
  ] });
16488
16658
  }
16489
16659
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ...shell, children: [
16490
16660
  groups.map((group, index) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
16491
- index > 0 && /* @__PURE__ */ jsxRuntime.jsx(Separator, {}),
16661
+ index > 0 && /* @__PURE__ */ jsxRuntime.jsx(Separator2, {}),
16492
16662
  /* @__PURE__ */ jsxRuntime.jsx(
16493
16663
  "div",
16494
16664
  {
@@ -16561,16 +16731,12 @@ var EditorBody = /* @__PURE__ */ react.forwardRef(function EditorBody2({
16561
16731
  onFocusChange,
16562
16732
  onReady,
16563
16733
  placeholder,
16564
- typography,
16565
16734
  editable,
16566
16735
  disabled,
16567
16736
  minHeight,
16568
16737
  maxHeight,
16569
16738
  toolbar,
16570
16739
  bubbleMenu,
16571
- fontSizes,
16572
- colors,
16573
- highlights,
16574
16740
  onImageUpload,
16575
16741
  editorClass,
16576
16742
  editorStyle
@@ -16579,12 +16745,8 @@ var EditorBody = /* @__PURE__ */ react.forwardRef(function EditorBody2({
16579
16745
  placeholderRef.current = placeholder;
16580
16746
  const handlers = react.useRef({ onInput, onFocusChange });
16581
16747
  handlers.current = { onInput, onFocusChange };
16582
- const typographyRef = react.useRef(typography);
16583
16748
  const extensions = react.useMemo(
16584
- () => api.createExtensions({
16585
- getPlaceholder: () => placeholderRef.current,
16586
- typography: typographyRef.current
16587
- }),
16749
+ () => api.createExtensions({ getPlaceholder: () => placeholderRef.current }),
16588
16750
  [api]
16589
16751
  );
16590
16752
  const editor = api.useEditor({
@@ -16632,28 +16794,22 @@ var EditorBody = /* @__PURE__ */ react.forwardRef(function EditorBody2({
16632
16794
  [editor, htmlRef]
16633
16795
  );
16634
16796
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16635
- toolbar !== false && toolbar.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
16797
+ toolbar.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
16636
16798
  EditorToolbar,
16637
16799
  {
16638
16800
  api,
16639
16801
  editor,
16640
16802
  items: toolbar,
16641
- fontSizes,
16642
- colors,
16643
- highlights,
16644
16803
  onImageUpload,
16645
16804
  disabled: !editable
16646
16805
  }
16647
16806
  ),
16648
- bubbleMenu !== false && bubbleMenu.length > 0 && editable && /* @__PURE__ */ jsxRuntime.jsx(
16807
+ bubbleMenu.length > 0 && editable && /* @__PURE__ */ jsxRuntime.jsx(
16649
16808
  EditorBubbleMenu,
16650
16809
  {
16651
16810
  api,
16652
16811
  editor,
16653
16812
  items: bubbleMenu,
16654
- fontSizes,
16655
- colors,
16656
- highlights,
16657
16813
  onImageUpload,
16658
16814
  disabled: false
16659
16815
  }
@@ -16682,10 +16838,8 @@ var importTiptap = async () => {
16682
16838
  textAlign,
16683
16839
  textStyle,
16684
16840
  list,
16685
- highlight,
16686
16841
  image,
16687
- superscript,
16688
- subscript,
16842
+ table,
16689
16843
  typography,
16690
16844
  extensions
16691
16845
  ] = await Promise.all([
@@ -16695,17 +16849,12 @@ var importTiptap = async () => {
16695
16849
  import('@tiptap/extension-text-align'),
16696
16850
  import('@tiptap/extension-text-style'),
16697
16851
  import('@tiptap/extension-list'),
16698
- import('@tiptap/extension-highlight'),
16699
16852
  import('@tiptap/extension-image'),
16700
- import('@tiptap/extension-superscript'),
16701
- import('@tiptap/extension-subscript'),
16853
+ import('@tiptap/extension-table'),
16702
16854
  import('@tiptap/extension-typography'),
16703
16855
  import('@tiptap/extensions')
16704
16856
  ]);
16705
- const createExtensions = ({
16706
- getPlaceholder,
16707
- typography: withTypography
16708
- }) => [
16857
+ const createExtensions = ({ getPlaceholder }) => [
16709
16858
  starterKit.default.configure({
16710
16859
  heading: { levels: [...SEDITOR_HEADING_LEVELS] },
16711
16860
  link: {
@@ -16722,14 +16871,24 @@ var importTiptap = async () => {
16722
16871
  textAlign.default.configure({ types: ["heading", "paragraph"] }),
16723
16872
  list.TaskList.configure({ HTMLAttributes: { class: TASK_LIST_CLASS } }),
16724
16873
  list.TaskItem.configure({ nested: true, HTMLAttributes: { class: TASK_ITEM_CLASS } }),
16725
- highlight.default.configure({ multicolor: true }),
16726
16874
  // base64 를 막는다 — 본문 HTML 에 수 MB 짜리 data URI 가 박히면 그대로 DB·API 로 실려 간다.
16727
16875
  // 이미지는 onImageUpload 가 돌려준 URL 로만 들어온다.
16728
16876
  image.default.configure({ allowBase64: false, HTMLAttributes: { class: IMAGE_CLASS } }),
16729
- superscript.default,
16730
- subscript.default,
16877
+ /**
16878
+ * 표 — 열 너비는 **고정(균등)** 이다.
16879
+ *
16880
+ * `resizable` 을 켜면 열 경계를 끌어 폭을 정할 수 있지만 그 값이 저장 HTML 에
16881
+ * `colwidth` 로 px 단위로 박힌다. 작성한 화면보다 좁은 곳에서 다시 보여 줄 때 표가
16882
+ * 넘치고, 화면 폭이 제각각인 소비 앱에서는 되돌릴 방법이 없다. 대신 본문 스타일이
16883
+ * `table-layout: fixed` 로 열을 균등하게 나눠 어떤 폭에서도 표가 상자 안에 남는다.
16884
+ */
16885
+ table.Table.configure({ resizable: false, HTMLAttributes: { class: TABLE_CLASS } }),
16886
+ table.TableRow.configure({ HTMLAttributes: { class: TABLE_ROW_CLASS } }),
16887
+ table.TableHeader.configure({ HTMLAttributes: { class: TABLE_HEADER_CLASS } }),
16888
+ table.TableCell.configure({ HTMLAttributes: { class: TABLE_CELL_CLASS } }),
16731
16889
  extensions.Placeholder.configure({ placeholder: () => getPlaceholder() }),
16732
- ...withTypography ? [typography.default] : []
16890
+ // 따옴표·하이픈·화살표 자동 치환 (`"` → `“”`, `--` → `—`, `->` → `→`)
16891
+ typography.default
16733
16892
  ];
16734
16893
  return {
16735
16894
  useEditor: react.useEditor,
@@ -16782,13 +16941,8 @@ var SEditor = /* @__PURE__ */ react.forwardRef(function SEditor2({
16782
16941
  placeholder = "\uB0B4\uC6A9\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694.",
16783
16942
  minHeight = 200,
16784
16943
  maxHeight,
16785
- toolbar = SEDITOR_DEFAULT_TOOLBAR,
16786
- bubbleMenu = SEDITOR_DEFAULT_BUBBLE_MENU,
16787
- fontSizes = [...SEDITOR_FONT_SIZES],
16788
- colors = SEDITOR_DEFAULT_COLORS,
16789
- highlights = SEDITOR_DEFAULT_HIGHLIGHTS,
16944
+ simple = false,
16790
16945
  onImageUpload,
16791
- typography = false,
16792
16946
  rules,
16793
16947
  status,
16794
16948
  focused,
@@ -16880,7 +17034,8 @@ var SEditor = /* @__PURE__ */ react.forwardRef(function SEditor2({
16880
17034
  const resolvedError = error || ruleError !== "";
16881
17035
  const resolvedErrorMessage = ruleError !== "" ? ruleError : errorMessage;
16882
17036
  const resolvedStatus = status ?? (rules && rules.length > 0 ? ruleError !== "" ? "error" : void 0 : void 0);
16883
- const hasToolbar = toolbar !== false && toolbar.length > 0;
17037
+ const resolvedToolbar = simple ? SEDITOR_SIMPLE_TOOLBAR : SEDITOR_DEFAULT_TOOLBAR;
17038
+ const resolvedBubbleMenu = simple ? SEDITOR_SIMPLE_BUBBLE_MENU : SEDITOR_DEFAULT_BUBBLE_MENU;
16884
17039
  return /* @__PURE__ */ jsxRuntime.jsx(
16885
17040
  SField,
16886
17041
  {
@@ -16905,19 +17060,15 @@ var SEditor = /* @__PURE__ */ react.forwardRef(function SEditor2({
16905
17060
  multiline: true,
16906
17061
  className,
16907
17062
  style,
16908
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1 flex-col", children: api === null ? (
17063
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1 flex-col bg-inherit", children: api === null ? (
16909
17064
  // 엔진을 불러오는 동안의 자리 — 툴바 높이와 본문 상자를 그대로 잡아 둔다
16910
17065
  /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16911
- hasToolbar && // 진짜 툴바를 잠긴 채로 그린다 — 버튼 개수·줄바꿈이 같아야 엔진이 붙어도 안 밀린다
16912
17066
  /* @__PURE__ */ jsxRuntime.jsx(
16913
17067
  EditorToolbarBar,
16914
17068
  {
16915
17069
  state: IDLE_TOOLBAR_STATE,
16916
17070
  editor: null,
16917
- items: toolbar,
16918
- fontSizes,
16919
- colors,
16920
- highlights,
17071
+ items: resolvedToolbar,
16921
17072
  onImageUpload,
16922
17073
  disabled: true
16923
17074
  }
@@ -16944,16 +17095,12 @@ var SEditor = /* @__PURE__ */ react.forwardRef(function SEditor2({
16944
17095
  onFocusChange: handleFocusChange,
16945
17096
  onReady: handleReady,
16946
17097
  placeholder,
16947
- typography,
16948
17098
  editable,
16949
17099
  disabled,
16950
17100
  minHeight,
16951
17101
  maxHeight,
16952
- toolbar,
16953
- bubbleMenu,
16954
- fontSizes,
16955
- colors,
16956
- highlights,
17102
+ toolbar: resolvedToolbar,
17103
+ bubbleMenu: resolvedBubbleMenu,
16957
17104
  onImageUpload,
16958
17105
  editorClass,
16959
17106
  editorStyle
@@ -17035,9 +17182,9 @@ var todayIso = () => {
17035
17182
  const pad = (n) => String(n).padStart(2, "0");
17036
17183
  return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
17037
17184
  };
17038
- var isInlineDateField = (field) => field.type === "date" && field.radioButton === true && (field.presets?.length ?? 0) > 0;
17185
+ var isInlineDateField = (field) => field.type === "datepicker-range" && field.radioButton === true && (field.presets?.length ?? 0) > 0;
17039
17186
  var getFieldPresets = (field) => {
17040
- if (field.type === "period") return field.presets ?? DEFAULT_PERIOD_PRESETS;
17187
+ if (field.type === "datepicker-statistics") return field.presets ?? DEFAULT_PERIOD_PRESETS;
17041
17188
  return field.presets ?? [];
17042
17189
  };
17043
17190
  var getDefaultPeriodInputValue = (unit) => {
@@ -17054,12 +17201,16 @@ var createPeriodValue = (unit) => ({
17054
17201
  value: getDefaultPeriodInputValue(unit)
17055
17202
  });
17056
17203
  var resolveFieldDefault = (field) => {
17057
- if (field.defaultValue !== void 0) return field.defaultValue;
17058
- if (field.type === "date")
17059
- return isInlineDateField(field) || field.required ? todayIso() : void 0;
17204
+ if (field.defaultValue !== void 0 && isFixedField(field)) return field.defaultValue;
17205
+ if (field.type === "datepicker-range") {
17206
+ if (!isInlineDateField(field) && !field.required) return void 0;
17207
+ const today = todayIso();
17208
+ return [today, today];
17209
+ }
17060
17210
  if (!field.required) return void 0;
17061
- if (field.type === "single") return field.options?.[0]?.value;
17062
- if (field.type === "period") {
17211
+ if (field.type === "datepicker-day") return todayIso();
17212
+ if (field.type === "select") return field.options?.[0]?.value;
17213
+ if (field.type === "datepicker-statistics") {
17063
17214
  const unit = getFieldPresets(field).find((preset) => !preset.custom)?.value;
17064
17215
  return unit ? createPeriodValue(unit) : void 0;
17065
17216
  }
@@ -17081,9 +17232,10 @@ var valuesMapEqual = (a, b) => {
17081
17232
  }
17082
17233
  return true;
17083
17234
  };
17235
+ var fieldValuesEqual = (field, a, b) => field.type === "datepicker-range" ? sameDateValue(a, b) : valuesEqual(a, b);
17084
17236
  var isAtDefaultValue = (field, value) => {
17085
17237
  const def = resolveFieldDefault(field);
17086
- return def !== void 0 && valuesEqual(value, def);
17238
+ return def !== void 0 && fieldValuesEqual(field, value, def);
17087
17239
  };
17088
17240
  var resetTargetValue = (field) => {
17089
17241
  const def = resolveFieldDefault(field);
@@ -17092,7 +17244,7 @@ var resetTargetValue = (field) => {
17092
17244
  var isAtResetTarget = (field, value) => {
17093
17245
  const target = resetTargetValue(field);
17094
17246
  if (isEmptyValue(value) && isEmptyValue(target)) return true;
17095
- return valuesEqual(value, target);
17247
+ return fieldValuesEqual(field, value, target);
17096
17248
  };
17097
17249
  var isInlineField = (field) => isInlineDateField(field) || field.type === "custom";
17098
17250
  var isFixedField = (field) => field.fixed === true || field.required === true;
@@ -17120,17 +17272,19 @@ var defaultGroupTooltipMessage = (rule, fields) => {
17120
17272
  const label = fields.find((f) => f.key === rule.key)?.label ?? "\uD56D\uBAA9";
17121
17273
  return `${label}${koreanParticle(label, "\uC744", "\uB97C")} \uC120\uD0DD\uD574 \uC8FC\uC138\uC694.`;
17122
17274
  };
17275
+ var toDateRange = (value) => Array.isArray(value) ? [value[0], value[1]] : [value, value];
17276
+ var sameDateValue = (a, b) => {
17277
+ const [aStart, aEnd] = toDateRange(a);
17278
+ const [bStart, bEnd] = toDateRange(b);
17279
+ return aStart === bStart && aEnd === bEnd;
17280
+ };
17123
17281
  var matchPresetId = (presets, value) => {
17124
17282
  if (isEmptyValue(value)) return null;
17125
17283
  if (isPeriodValue(value)) return value.unit;
17126
17284
  for (const preset of presets) {
17127
17285
  if (preset.custom) continue;
17128
17286
  const resolved = preset.resolve ? preset.resolve() : preset.value;
17129
- if (Array.isArray(resolved) && Array.isArray(value)) {
17130
- if (resolved[0] === value[0] && resolved[1] === value[1]) return preset.value;
17131
- } else if (!Array.isArray(resolved) && !Array.isArray(value) && resolved === value) {
17132
- return preset.value;
17133
- }
17287
+ if (sameDateValue(resolved, value)) return preset.value;
17134
17288
  }
17135
17289
  return presets.find((preset) => preset.custom)?.value ?? null;
17136
17290
  };
@@ -17141,7 +17295,7 @@ var formatValueList = (labels) => {
17141
17295
  };
17142
17296
  var displayValue = (field, value) => {
17143
17297
  if (isEmptyValue(value)) return "";
17144
- if (field.type === "multi") {
17298
+ if (field.type === "select-multi") {
17145
17299
  const values = toArrayValue(value);
17146
17300
  const selectableValues = (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value);
17147
17301
  if (selectableValues.length > 0 && selectableValues.every((selectableValue) => values.includes(selectableValue))) {
@@ -17149,10 +17303,12 @@ var displayValue = (field, value) => {
17149
17303
  }
17150
17304
  return formatValueList(values.map((v) => optionLabel(field, v)));
17151
17305
  }
17152
- if (field.type === "single") return optionLabel(field, value);
17153
- if (field.type === "date")
17154
- return Array.isArray(value) ? `${value[0]} ~ ${value[1]}` : String(value);
17155
- if (field.type === "period") {
17306
+ if (field.type === "select") return optionLabel(field, value);
17307
+ if (field.type === "datepicker-day" || field.type === "datepicker-range") {
17308
+ if (!Array.isArray(value)) return String(value);
17309
+ return value[0] === value[1] ? String(value[0]) : `${value[0]} ~ ${value[1]}`;
17310
+ }
17311
+ if (field.type === "datepicker-statistics") {
17156
17312
  if (!isPeriodValue(value)) {
17157
17313
  const preset2 = getFieldPresets(field).find((p) => p.value === value);
17158
17314
  return preset2?.label ?? String(value);
@@ -17169,7 +17325,7 @@ var displayValue = (field, value) => {
17169
17325
  };
17170
17326
  var chipDisplayValue = (field, value) => {
17171
17327
  const text = displayValue(field, value);
17172
- if (field.type !== "date" || isEmptyValue(value)) return text;
17328
+ if (field.type !== "datepicker-range" || isEmptyValue(value)) return text;
17173
17329
  const presets = getFieldPresets(field);
17174
17330
  if (presets.length === 0) return text;
17175
17331
  const preset = presets.find((p) => p.value === matchPresetId(presets, value));
@@ -17260,6 +17416,14 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
17260
17416
  });
17261
17417
  if (changed) onValueChange?.({ ...values, ...patch });
17262
17418
  }, [fields, values, onValueChange]);
17419
+ if (typeof console !== "undefined") {
17420
+ const misused = fields.filter((f) => f.defaultValue !== void 0 && !isFixedField(f));
17421
+ if (misused.length > 0) {
17422
+ console.warn(
17423
+ `[SChipFilter] defaultValue \uB294 fixed\xB7required \uD544\uD130\uC5D0\uC11C\uB9CC \uC4F8 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uBB34\uC2DC\uD569\uB2C8\uB2E4. (${misused.map((f) => f.key).join(", ")})`
17424
+ );
17425
+ }
17426
+ }
17263
17427
  const fixedKeys = fields.filter(isFixedField).map((field) => field.key);
17264
17428
  const resolvedActiveKeys = Array.from(
17265
17429
  /* @__PURE__ */ new Set([...activeKeys ?? internalActiveKeys, ...fixedKeys])
@@ -17281,7 +17445,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
17281
17445
  if (currentOpenField?.type === "keyword") {
17282
17446
  return { width: CHIPFILTER_LISTBOX_WIDTH };
17283
17447
  }
17284
- if ((currentOpenField?.type === "date" || currentOpenField?.type === "period") && getFieldPresets(currentOpenField).length > 0) {
17448
+ if ((currentOpenField?.type === "datepicker-range" || currentOpenField?.type === "datepicker-statistics") && getFieldPresets(currentOpenField).length > 0) {
17285
17449
  return { width: CHIPFILTER_DATE_PRESET_LISTBOX_WIDTH };
17286
17450
  }
17287
17451
  return { width: CHIPFILTER_LISTBOX_WIDTH };
@@ -17417,7 +17581,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
17417
17581
  }
17418
17582
  clearValue(field.key);
17419
17583
  };
17420
- const node = field.type === "date" && isInlineDateField(field) ? /* @__PURE__ */ jsxRuntime.jsx(
17584
+ const node = field.type === "datepicker-range" && isInlineDateField(field) ? /* @__PURE__ */ jsxRuntime.jsx(
17421
17585
  InlineDatePresetFilter,
17422
17586
  {
17423
17587
  field,
@@ -17728,8 +17892,8 @@ function EditorPanel({
17728
17892
  onValueCommit,
17729
17893
  onClose
17730
17894
  }) {
17731
- const wrapsInPaddedTop = field.type === "date" || field.type === "period";
17732
- const isMulti = field.type === "multi";
17895
+ const wrapsInPaddedTop = field.type === "datepicker-day" || field.type === "datepicker-range" || field.type === "datepicker-statistics";
17896
+ const isMulti = field.type === "select-multi";
17733
17897
  const selectableValues = isMulti ? (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value) : [];
17734
17898
  const selectedValues = isMulti ? toArrayValue(value) : [];
17735
17899
  const allSelected = isMulti && selectableValues.length > 0 && selectableValues.every((v) => selectedValues.includes(v));
@@ -17810,7 +17974,7 @@ function FilterEditor({
17810
17974
  onValueChange,
17811
17975
  onValueCommit
17812
17976
  }) {
17813
- if (field.type === "period") {
17977
+ if (field.type === "datepicker-statistics") {
17814
17978
  return /* @__PURE__ */ jsxRuntime.jsx(
17815
17979
  PeriodPresetEditor,
17816
17980
  {
@@ -17821,7 +17985,21 @@ function FilterEditor({
17821
17985
  }
17822
17986
  );
17823
17987
  }
17824
- if (field.type === "date") {
17988
+ if (field.type === "datepicker-day") {
17989
+ return /* @__PURE__ */ jsxRuntime.jsx(
17990
+ SDatePicker,
17991
+ {
17992
+ value: typeof value === "string" ? value : null,
17993
+ onValueChange,
17994
+ selectable: field.selectable,
17995
+ disabled,
17996
+ placeholder: field.placeholder,
17997
+ width: "100%",
17998
+ maxWidth: "100%"
17999
+ }
18000
+ );
18001
+ }
18002
+ if (field.type === "datepicker-range") {
17825
18003
  return /* @__PURE__ */ jsxRuntime.jsx(
17826
18004
  DatePresetEditor,
17827
18005
  {
@@ -17848,8 +18026,8 @@ function FilterEditor({
17848
18026
  OptionList,
17849
18027
  {
17850
18028
  field,
17851
- value: field.type === "multi" ? toArrayValue(value) : value,
17852
- multiple: field.type === "multi",
18029
+ value: field.type === "select-multi" ? toArrayValue(value) : value,
18030
+ multiple: field.type === "select-multi",
17853
18031
  disabled,
17854
18032
  onValueChange
17855
18033
  }
@@ -17874,17 +18052,16 @@ function DatePresetEditor({
17874
18052
  setSelectedId(preset.value);
17875
18053
  if (!preset.custom) onValueChange(preset.resolve ? preset.resolve() : preset.value);
17876
18054
  };
17877
- if (field.type === "date" && presets.length === 0) {
18055
+ if (presets.length === 0) {
17878
18056
  return /* @__PURE__ */ jsxRuntime.jsx(
17879
- SDatePicker,
18057
+ SDateRangePicker,
17880
18058
  {
17881
- value: typeof value === "string" ? value : null,
18059
+ value: Array.isArray(value) && value.length === 2 ? value : null,
17882
18060
  onValueChange,
17883
18061
  selectable: field.selectable,
18062
+ maxRange: field.maxRange,
17884
18063
  disabled,
17885
- placeholder: field.placeholder,
17886
- width: "100%",
17887
- maxWidth: "100%"
18064
+ width: "100%"
17888
18065
  }
17889
18066
  );
17890
18067
  }
@@ -20031,15 +20208,9 @@ exports.SDraggableList = SDraggableList;
20031
20208
  exports.SDraggableProvider = SDraggableProvider;
20032
20209
  exports.SDrawer = SDrawer;
20033
20210
  exports.SDropdownButton = SDropdownButton2;
20034
- exports.SEDITOR_DEFAULT_BUBBLE_MENU = SEDITOR_DEFAULT_BUBBLE_MENU;
20035
- exports.SEDITOR_DEFAULT_COLORS = SEDITOR_DEFAULT_COLORS;
20036
20211
  exports.SEDITOR_DEFAULT_FONT_SIZE = SEDITOR_DEFAULT_FONT_SIZE;
20037
- exports.SEDITOR_DEFAULT_HIGHLIGHTS = SEDITOR_DEFAULT_HIGHLIGHTS;
20038
- exports.SEDITOR_DEFAULT_TOOLBAR = SEDITOR_DEFAULT_TOOLBAR;
20039
- exports.SEDITOR_FONT_SIZES = SEDITOR_FONT_SIZES;
20040
20212
  exports.SEDITOR_HEADING_LABELS = SEDITOR_HEADING_LABELS;
20041
20213
  exports.SEDITOR_HEADING_LEVELS = SEDITOR_HEADING_LEVELS;
20042
- exports.SEDITOR_TOOLBAR_ITEMS = SEDITOR_TOOLBAR_ITEMS;
20043
20214
  exports.SEditor = SEditor;
20044
20215
  exports.SExpansionItem = SExpansionItem;
20045
20216
  exports.SExpansionList = SExpansionList2;