sellmate-design-system-react 9.0.0-beta.30 → 9.0.0-beta.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/AGENTS.md +111 -21
  2. package/dist/components/SAccountListBox/AccountListBoxPortal.d.ts +31 -0
  3. package/dist/components/SAccountListBox/README.md +86 -0
  4. package/dist/components/SAccountListBox/SAccountListBox.d.ts +79 -0
  5. package/dist/components/SAccountListBox/SystemMenuPortal.d.ts +58 -0
  6. package/dist/components/SAccountListBox/accountListBox.config.d.ts +64 -0
  7. package/dist/components/SAccountListBox/index.d.ts +2 -0
  8. package/dist/components/SChipFilter/README.md +16 -3
  9. package/dist/components/SChipFilter/SChipFilter.d.ts +22 -4
  10. package/dist/components/SGnb/README.md +1 -1
  11. package/dist/components/SGnb/SGnb.d.ts +29 -7
  12. package/dist/components/SGnbSystem/README.md +29 -6
  13. package/dist/components/SGnbSystem/SGnbSystem.d.ts +57 -17
  14. package/dist/components/SGnbSystem/gnbSystem.config.d.ts +34 -1
  15. package/dist/components/SGnbSystem/index.d.ts +1 -1
  16. package/dist/components/SIcon/README.md +2 -0
  17. package/dist/components/SIcon/icons.gen.d.ts +2 -0
  18. package/dist/components/SPortal/README.md +2 -0
  19. package/dist/components/SSystemActionButton/README.md +96 -9
  20. package/dist/components/SSystemActionButton/SSystemActionButton.d.ts +97 -15
  21. package/dist/components/SSystemActionButton/index.d.ts +1 -1
  22. package/dist/index.cjs +1131 -398
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.js +1125 -400
  26. package/dist/index.js.map +1 -1
  27. package/dist/llms-full.txt +333 -40
  28. package/dist/llms.txt +113 -23
  29. package/dist/styles.css +66 -26
  30. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -270,6 +270,47 @@ var fieldWidthValue = (v) => {
270
270
  if (isFieldWidthGrade(v)) return `var(--cmp-field-width-${v})`;
271
271
  return typeof v === "number" ? `${v}px` : v;
272
272
  };
273
+ var Icon_account = (p) => {
274
+ const { size = 24, ...rest } = p;
275
+ return /* @__PURE__ */ jsxRuntime.jsxs(
276
+ "svg",
277
+ {
278
+ width: size,
279
+ height: size,
280
+ viewBox: "0 0 24 24",
281
+ fill: "none",
282
+ xmlns: "http://www.w3.org/2000/svg",
283
+ ...rest,
284
+ children: [
285
+ /* @__PURE__ */ jsxRuntime.jsx(
286
+ "path",
287
+ {
288
+ d: "M11.75 13.75H9.35547C7.96612 13.75 6.68824 14.3982 5.74609 15.373C4.80587 16.346 4.25975 17.5818 4.25 18.6846C4.25175 18.6862 4.25343 18.6884 4.25586 18.6904C4.28703 18.7161 4.35523 18.75 4.4541 18.75H12.5V20.25H4.4541C3.65662 20.25 2.75016 19.692 2.75 18.7148C2.75 17.144 3.50242 15.5362 4.66699 14.3311C5.83832 13.119 7.48832 12.25 9.35547 12.25H11.75V13.75Z",
289
+ fill: "currentColor"
290
+ }
291
+ ),
292
+ /* @__PURE__ */ jsxRuntime.jsx(
293
+ "path",
294
+ {
295
+ fillRule: "evenodd",
296
+ clipRule: "evenodd",
297
+ d: "M17.4854 11C17.6175 11.0001 17.7358 11.0828 17.7803 11.2061L18.0977 12.0859C18.2115 12.1143 18.3098 12.1432 18.3926 12.1729C18.483 12.2052 18.5994 12.2543 18.7432 12.3213L19.4834 11.9297C19.5436 11.8979 19.6124 11.886 19.6797 11.8965C19.7471 11.9071 19.8098 11.9394 19.8574 11.9883L20.5078 12.6611C20.5942 12.7507 20.6188 12.8818 20.5703 12.9961L20.2236 13.8096C20.2811 13.9152 20.3272 14.0055 20.3623 14.0811C20.4001 14.1633 20.4462 14.2768 20.502 14.4229L21.3105 14.7695C21.432 14.8213 21.5071 14.9432 21.499 15.0732L21.4404 16.0068C21.4363 16.0674 21.4137 16.1255 21.377 16.1738C21.3402 16.2221 21.2906 16.2592 21.2334 16.2793L20.4668 16.5508C20.4447 16.6565 20.4218 16.7477 20.3975 16.8242C20.3583 16.9421 20.3137 17.0582 20.2637 17.1719L20.6484 18.0225C20.6756 18.0822 20.6825 18.1497 20.6689 18.2139C20.6553 18.2779 20.6222 18.3364 20.5732 18.3799L19.8408 19.0332C19.7927 19.0758 19.7328 19.1026 19.6689 19.1104C19.6051 19.1181 19.5403 19.1062 19.4834 19.0762L18.7285 18.6768C18.6106 18.7392 18.4889 18.7943 18.3643 18.8418L18.0352 18.9648L17.7422 19.7744C17.7205 19.8337 17.6813 19.8852 17.6299 19.9219C17.5785 19.9585 17.5172 19.9792 17.4541 19.9805L16.5996 20C16.5348 20.0017 16.4709 19.9833 16.417 19.9473C16.3631 19.9113 16.3221 19.8593 16.2988 19.7988L15.9541 18.8867C15.8365 18.8465 15.7196 18.8026 15.6045 18.7559C15.5104 18.7151 15.4173 18.6711 15.3262 18.624L14.4717 18.9893C14.4154 19.0133 14.3533 19.0204 14.293 19.0098C14.2326 18.9991 14.1766 18.9715 14.1318 18.9297L13.499 18.3359C13.452 18.292 13.4197 18.234 13.4072 18.1709C13.3949 18.1079 13.4031 18.0428 13.4297 17.9844L13.7969 17.1826C13.7481 17.088 13.7027 16.9916 13.6611 16.8936C13.6125 16.7733 13.5677 16.6512 13.5264 16.5283L12.7207 16.2832C12.6554 16.2635 12.5985 16.2224 12.5586 16.167C12.5187 16.1114 12.4978 16.0439 12.5 15.9756L12.5312 15.1113C12.5335 15.0549 12.5519 15.0002 12.583 14.9531C12.6141 14.906 12.657 14.868 12.708 14.8438L13.5527 14.4375C13.5918 14.2943 13.6262 14.1829 13.6562 14.1016C13.6987 13.9929 13.7462 13.8859 13.7979 13.7812L13.4316 13.0068C13.4039 12.9481 13.3952 12.8821 13.4072 12.8184C13.4194 12.7545 13.4516 12.6959 13.499 12.6514L14.1309 12.0547C14.175 12.013 14.2303 11.9847 14.29 11.9736C14.3499 11.9626 14.4125 11.9699 14.4688 11.9932L15.3223 12.3457C15.4168 12.2827 15.5027 12.2314 15.5801 12.1904C15.6722 12.1415 15.7953 12.0904 15.9502 12.0352L16.248 11.207C16.27 11.1465 16.3096 11.0936 16.3623 11.0566C16.4151 11.0197 16.4785 10.9999 16.543 11H17.4854ZM17.0107 14.1582C16.2606 14.1582 15.6523 14.7594 15.6523 15.501C15.6524 16.2425 16.2607 16.8437 17.0107 16.8438C17.7604 16.8438 18.3681 16.2425 18.3682 15.501C18.3682 14.7594 17.7609 14.1582 17.0107 14.1582Z",
298
+ fill: "currentColor"
299
+ }
300
+ ),
301
+ /* @__PURE__ */ jsxRuntime.jsx(
302
+ "path",
303
+ {
304
+ fillRule: "evenodd",
305
+ clipRule: "evenodd",
306
+ d: "M10.5 3.5C12.6875 3.5 14.5 5.3125 14.5 7.5C14.5 9.71875 12.6875 11.5 10.5 11.5C8.28125 11.5 6.5 9.71875 6.5 7.5C6.5 5.3125 8.28125 3.5 10.5 3.5ZM10.5 5C9.11729 5 8 6.13329 8 7.5C8 8.89032 9.10968 10 10.5 10C11.8667 10 13 8.88271 13 7.5C13 6.14093 11.8591 5 10.5 5Z",
307
+ fill: "currentColor"
308
+ }
309
+ )
310
+ ]
311
+ }
312
+ );
313
+ };
273
314
  var Icon_add = (p) => {
274
315
  const { size = 24, ...rest } = p;
275
316
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -599,6 +640,38 @@ var Icon_bell = (p) => {
599
640
  }
600
641
  );
601
642
  };
643
+ var Icon_bellRinging = (p) => {
644
+ const { size = 24, ...rest } = p;
645
+ return /* @__PURE__ */ jsxRuntime.jsxs(
646
+ "svg",
647
+ {
648
+ width: size,
649
+ height: size,
650
+ viewBox: "0 0 24 24",
651
+ fill: "none",
652
+ xmlns: "http://www.w3.org/2000/svg",
653
+ ...rest,
654
+ children: [
655
+ /* @__PURE__ */ jsxRuntime.jsx(
656
+ "path",
657
+ {
658
+ fillRule: "evenodd",
659
+ clipRule: "evenodd",
660
+ d: "M14.7569 2.38727C15.5529 2.61577 16.0134 3.44651 15.7853 4.24262L15.6017 4.88283C18.2685 6.33275 19.6863 9.40776 18.8414 12.3553L17.8242 15.9028L17.7839 16.0822C17.615 17.0352 17.9736 18.7681 18.418 19.5394C18.8918 20.3618 17.8729 20.9656 16.9454 20.6999L12.9492 19.554C12.9484 19.5568 12.9478 19.5597 12.9468 19.5625C12.3934 21.1403 10.776 22.0516 9.24413 21.6125C7.71218 21.1732 6.82362 19.5434 7.19047 17.9119C7.19112 17.909 7.19212 17.9062 7.19289 17.9034L3.19671 16.7575L3.02761 16.6989C2.20629 16.3626 1.77717 15.4116 2.56283 14.993C3.34841 14.5742 4.57093 13.2947 4.93263 12.3972L4.99356 12.2237L6.01078 8.6762C6.85627 5.72841 9.68793 3.8709 12.7182 4.05498L12.9015 3.41571C13.13 2.61953 13.9606 2.15895 14.7569 2.38727ZM13.7922 5.75169C10.9998 4.951 8.19452 6.50346 7.45267 9.08965L6.43545 12.6371C6.2092 13.4258 5.61733 14.2164 5.11212 14.7792C4.88445 15.0328 4.62615 15.2903 4.35646 15.5296L16.6125 19.044C16.5106 18.698 16.4281 18.343 16.3694 18.0071C16.2392 17.2621 16.1562 16.2782 16.3823 15.4893L17.3995 11.9419C18.1408 9.35565 16.5842 6.55254 13.7922 5.75169Z",
661
+ fill: "currentColor"
662
+ }
663
+ ),
664
+ /* @__PURE__ */ jsxRuntime.jsx(
665
+ "path",
666
+ {
667
+ d: "M18.7143 4.09705C19.0365 3.83687 19.5097 3.88767 19.77 4.2098C20.8724 5.57421 21.6644 7.17777 22.0725 8.89915C22.1677 9.30202 21.9178 9.70642 21.515 9.80193C21.1123 9.89711 20.7087 9.64808 20.6129 9.24559C20.2569 7.74423 19.5651 6.34446 18.6025 5.15304C18.3423 4.83086 18.3922 4.35736 18.7143 4.09705Z",
668
+ fill: "currentColor"
669
+ }
670
+ )
671
+ ]
672
+ }
673
+ );
674
+ };
602
675
  var Icon_bill = (p) => {
603
676
  const { size = 24, ...rest } = p;
604
677
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -3098,6 +3171,7 @@ var Icon_youtube = (p) => {
3098
3171
  );
3099
3172
  };
3100
3173
  var ICONS = {
3174
+ account: Icon_account,
3101
3175
  add: Icon_add,
3102
3176
  alert: Icon_alert,
3103
3177
  alignKorean: Icon_alignKorean,
@@ -3110,6 +3184,7 @@ var ICONS = {
3110
3184
  attachFile: Icon_attachFile,
3111
3185
  barcode: Icon_barcode,
3112
3186
  bell: Icon_bell,
3187
+ bellRinging: Icon_bellRinging,
3113
3188
  bill: Icon_bill,
3114
3189
  board: Icon_board,
3115
3190
  box: Icon_box,
@@ -4260,7 +4335,7 @@ function moveWithDepth(items, fromIndex, target, getDepth, setDepth, maxDepth) {
4260
4335
  const nextDepth = target.intent === "inside" ? targetDepth + 1 : targetDepth;
4261
4336
  const depthDelta = clampDepth(nextDepth, maxDepth) - sourceDepth;
4262
4337
  const nextMovedItems = setDepth && depthDelta !== 0 ? movedItems.map(
4263
- (item3, index) => setDepth(item3, clampDepth(getDepth(item3, fromIndex + index) + depthDelta, maxDepth))
4338
+ (item4, index) => setDepth(item4, clampDepth(getDepth(item4, fromIndex + index) + depthDelta, maxDepth))
4264
4339
  ) : movedItems;
4265
4340
  return [
4266
4341
  ...remainingItems.slice(0, insertionIndex),
@@ -4308,7 +4383,7 @@ function SDraggableListInner({
4308
4383
  setDropTarget({ index, intent: "before" });
4309
4384
  }, []);
4310
4385
  const readDepth = react.useCallback(
4311
- (item3, index) => clampDepth(getDepth?.(item3, index) ?? 1, maxDepth),
4386
+ (item4, index) => clampDepth(getDepth?.(item4, index) ?? 1, maxDepth),
4312
4387
  [getDepth, maxDepth]
4313
4388
  );
4314
4389
  react.useEffect(() => {
@@ -4343,8 +4418,8 @@ function SDraggableListInner({
4343
4418
  nextDropTarget = ratio < 0.5 ? { index, intent: "before" } : { index, intent: "after" };
4344
4419
  break;
4345
4420
  }
4346
- const item3 = items[index];
4347
- const canHaveChildren = (getCanHaveChildren?.(item3, index) ?? true) && readDepth(item3, index) < maxDepth;
4421
+ const item4 = items[index];
4422
+ const canHaveChildren = (getCanHaveChildren?.(item4, index) ?? true) && readDepth(item4, index) < maxDepth;
4348
4423
  if (ratio < 0.25) {
4349
4424
  nextDropTarget = { index, intent: "before" };
4350
4425
  } else if (ratio > 0.75 || !canHaveChildren) {
@@ -4444,10 +4519,10 @@ function SDraggableListInner({
4444
4519
  "data-drag-active": dragActive || void 0,
4445
4520
  "data-draggable-group": dragContext ? dragGroup : void 0,
4446
4521
  "data-draggable-list-id": dragContext ? listId : void 0,
4447
- children: items.map((item3, index) => {
4448
- const itemKey = getKey(item3, index);
4449
- const disabled = (getDisabled?.(item3, index) ?? false) || isDescendant(items, index, draggedSubtreeStart, depthEnabled ? readDepth : void 0);
4450
- const depth = depthEnabled ? readDepth(item3, index) : 1;
4522
+ children: items.map((item4, index) => {
4523
+ const itemKey = getKey(item4, index);
4524
+ const disabled = (getDisabled?.(item4, index) ?? false) || isDescendant(items, index, draggedSubtreeStart, depthEnabled ? readDepth : void 0);
4525
+ const depth = depthEnabled ? readDepth(item4, index) : 1;
4451
4526
  const showBefore = isDropTarget && currentDropIndex === index && (dragContext || currentDropIntent === "before");
4452
4527
  const showInside = isDropTarget && currentDropIndex === index && !dragContext && depthEnabled && currentDropIntent === "inside";
4453
4528
  const showAfter = isDropTarget && (dragContext ? currentDropIndex === items.length && index === items.length - 1 : currentDropIndex === index && currentDropIntent === "after");
@@ -4501,7 +4576,7 @@ function SDraggableListInner({
4501
4576
  }
4502
4577
  }
4503
4578
  ),
4504
- renderItem(item3, index, {
4579
+ renderItem(item4, index, {
4505
4580
  onDragHandleMouseDown: (event) => {
4506
4581
  if (disabled) return;
4507
4582
  if (dragContext && dragGroup && listId) {
@@ -5074,7 +5149,7 @@ function SGhostButton({
5074
5149
  const contentColor = disabled ? intent === "inverse" ? "var(--cmp-ghostButton-inverse-disabled)" : "var(--cmp-ghostButton-icon-disabled)" : `var(--cmp-ghostButton-${intent}-content)`;
5075
5150
  const text = (tooltipText ?? "").trim();
5076
5151
  const hasTooltip = text !== "";
5077
- const btn = /* @__PURE__ */ jsxRuntime.jsxs(
5152
+ const btn2 = /* @__PURE__ */ jsxRuntime.jsxs(
5078
5153
  "button",
5079
5154
  {
5080
5155
  type: "button",
@@ -5116,7 +5191,7 @@ function SGhostButton({
5116
5191
  ]
5117
5192
  }
5118
5193
  );
5119
- if (!hasTooltip) return btn;
5194
+ if (!hasTooltip) return btn2;
5120
5195
  return /* @__PURE__ */ jsxRuntime.jsxs(RPopover11__namespace.Root, { open, onOpenChange: setOpen, children: [
5121
5196
  /* @__PURE__ */ jsxRuntime.jsx(RPopover11__namespace.Anchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
5122
5197
  "span",
@@ -5127,7 +5202,7 @@ function SGhostButton({
5127
5202
  onMouseLeave: startHide,
5128
5203
  onFocus: openNow,
5129
5204
  onBlur: startHide,
5130
- children: btn
5205
+ children: btn2
5131
5206
  }
5132
5207
  ) }),
5133
5208
  /* @__PURE__ */ jsxRuntime.jsx(RPopover11__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -5426,7 +5501,7 @@ var STreeImpl = /* @__PURE__ */ react.forwardRef(function STree({
5426
5501
  }, ref) {
5427
5502
  const [internalValue, setInternalValue] = react.useState(defaultValue ?? []);
5428
5503
  const [internalExpandedIds, setInternalExpandedIds] = react.useState(
5429
- defaultExpandedIds ?? items.filter((item3) => item3.children?.length).map((item3) => item3.id)
5504
+ defaultExpandedIds ?? items.filter((item4) => item4.children?.length).map((item4) => item4.id)
5430
5505
  );
5431
5506
  const currentValue = value ?? internalValue;
5432
5507
  const currentExpandedIds = expandedIds ?? internalExpandedIds;
@@ -6810,6 +6885,456 @@ function SSwitch({
6810
6885
  );
6811
6886
  }
6812
6887
 
6888
+ // src/lib/is-dev.ts
6889
+ function isDev() {
6890
+ return typeof process === "undefined" || process?.env?.NODE_ENV !== "production";
6891
+ }
6892
+ function SPortal({
6893
+ open,
6894
+ onClose,
6895
+ onOpenChange,
6896
+ anchorRef,
6897
+ placement = "bottom",
6898
+ align = "start",
6899
+ offset = 4,
6900
+ alignOffset = 0,
6901
+ fit = false,
6902
+ maxHeight,
6903
+ autoClose = false,
6904
+ persistent = false,
6905
+ viewportPadding = 0,
6906
+ onOpenAutoFocus,
6907
+ onCloseAutoFocus,
6908
+ onPointerDownOutside,
6909
+ children,
6910
+ className,
6911
+ style,
6912
+ ariaLabel
6913
+ }) {
6914
+ const portalContainer = usePortalContainer();
6915
+ const { minWidth: styleMinWidth, maxWidth: styleMaxWidth, ...restStyle } = style ?? {};
6916
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6917
+ RPopover11__namespace.Root,
6918
+ {
6919
+ open,
6920
+ onOpenChange: (next) => {
6921
+ onOpenChange?.(next);
6922
+ if (!next) onClose?.();
6923
+ },
6924
+ children: [
6925
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover11__namespace.Anchor, { virtualRef: anchorRef }),
6926
+ /* @__PURE__ */ jsxRuntime.jsx(RPopover11__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
6927
+ RPopover11__namespace.Content,
6928
+ {
6929
+ side: placement,
6930
+ align,
6931
+ sideOffset: offset,
6932
+ alignOffset,
6933
+ collisionPadding: viewportPadding,
6934
+ "aria-label": ariaLabel,
6935
+ onPointerDownOutside: (e) => {
6936
+ if (persistent || anchorRef.current?.contains(e.target)) {
6937
+ e.preventDefault();
6938
+ return;
6939
+ }
6940
+ onPointerDownOutside?.(e);
6941
+ },
6942
+ onFocusOutside: (e) => {
6943
+ if (persistent || anchorRef.current?.contains(e.target)) {
6944
+ e.preventDefault();
6945
+ }
6946
+ },
6947
+ onEscapeKeyDown: persistent ? (e) => e.preventDefault() : void 0,
6948
+ onOpenAutoFocus,
6949
+ onCloseAutoFocus,
6950
+ onClick: autoClose ? () => onClose?.() : void 0,
6951
+ className: cn(
6952
+ "z-50 overflow-hidden rounded-(--cmp-listBox-radius) bg-(--cmp-listBox-bg) shadow-normal-sm",
6953
+ maxHeight != null && "overflow-y-auto",
6954
+ // 앵커가 창보다 넓을 수 있는 자리(가로 스크롤 안의 트리거 등)에서도 하한이 상한을
6955
+ // 이기지 않도록, 앵커 너비 역시 가용 폭으로 가둔다.
6956
+ fit && "min-w-[min(var(--radix-popover-trigger-width),var(--radix-popover-content-available-width))]",
6957
+ FLOATING_SLIDE_ANIM,
6958
+ className
6959
+ ),
6960
+ style: {
6961
+ maxHeight,
6962
+ ...restStyle,
6963
+ ...styleMinWidth != null ? { minWidth: clampToAvailableWidth(styleMinWidth, POPOVER_AVAILABLE_WIDTH) } : {},
6964
+ maxWidth: clampToAvailableWidth(styleMaxWidth, POPOVER_AVAILABLE_WIDTH)
6965
+ },
6966
+ children
6967
+ }
6968
+ ) })
6969
+ ]
6970
+ }
6971
+ );
6972
+ }
6973
+
6974
+ // src/components/SAccountListBox/accountListBox.config.ts
6975
+ var box = (p) => `var(--cmp-gnb-system-accountListBox-${p})`;
6976
+ var btn = (p) => `var(--cmp-gnb-system-accountButton-${p})`;
6977
+ var item = (p) => `var(--cmp-listBoxItem-${p})`;
6978
+ var sys = (p) => `var(--sys-color-${p})`;
6979
+ var ACCOUNT_LIST_BOX_ITEM_TONES = ["default", "negative"];
6980
+ var ACCOUNT_LIST_BOX_ICONS = {
6981
+ accountSetting: "account",
6982
+ language: "global",
6983
+ logout: "logout"
6984
+ };
6985
+ var ACCOUNT_LIST_BOX_LABELS = {
6986
+ accountSetting: "\uACC4\uC815 \uC124\uC815",
6987
+ language: "\uC5B8\uC5B4 \uBCC0\uACBD",
6988
+ logout: "\uACC4\uC815 \uB85C\uADF8\uC544\uC6C3"
6989
+ };
6990
+ var ACCOUNT_LIST_BOX_TONE_CONFIG = {
6991
+ default: {
6992
+ bg: btn("bg-default"),
6993
+ bgHover: btn("bg-hover"),
6994
+ text: btn("content-default"),
6995
+ // TODO: 행 아이콘 전용 색 토큰이 없다. content.default 는 글자색(#222222)이고
6996
+ // 시안의 아이콘은 한 단계 물러난 #555555 라, 그에 맞는 시맨틱 토큰으로 둔다.
6997
+ icon: sys("fg-secondary")
6998
+ },
6999
+ negative: {
7000
+ bg: btn("bg-default"),
7001
+ bgHover: btn("bg-negativeHover"),
7002
+ // 되돌릴 수 없는 행은 글자와 아이콘이 같은 경고색으로 함께 물든다(시안).
7003
+ text: btn("content-negative"),
7004
+ icon: btn("content-negative")
7005
+ }
7006
+ };
7007
+ var ACCOUNT_LIST_BOX_LAYOUT = {
7008
+ /** 패널 고정 폭 */
7009
+ width: box("width"),
7010
+ /** 패널 배경 */
7011
+ bg: box("bg"),
7012
+ /** 패널 라운드 */
7013
+ radius: box("radius"),
7014
+ /** 사용자정보 영역 배경 */
7015
+ userdataBg: box("userdata-bg"),
7016
+ /** 사용자정보 영역 좌우 여백 */
7017
+ userdataPaddingX: box("userdata-paddingX"),
7018
+ /** 사용자정보 영역 상하 여백 */
7019
+ userdataPaddingY: box("userdata-paddingY"),
7020
+ /** 이메일 글자색 */
7021
+ emailColor: box("userdata-email-color"),
7022
+ /** 이름 글자색 */
7023
+ nameColor: box("userdata-name-color"),
7024
+ /** 권한 글자색 */
7025
+ roleColor: box("userdata-role-color"),
7026
+ /** 행 묶음의 상하 여백 */
7027
+ listPaddingY: box("list-paddingY"),
7028
+ /** 행 좌우 여백 */
7029
+ itemPaddingX: btn("paddingX"),
7030
+ /** 행 상하 여백 */
7031
+ itemPaddingY: btn("paddingY"),
7032
+ /** 행 아이콘 ↔ 라벨 간격 */
7033
+ itemGap: btn("gap"),
7034
+ /** 행 아이콘 크기 */
7035
+ itemIcon: btn("icon"),
7036
+ /** 우측 값 ↔ 화살표 간격 */
7037
+ selectDataGap: btn("selectData-gap"),
7038
+ /** 우측 화살표 크기 */
7039
+ selectDataIcon: btn("selectData-icon"),
7040
+ /** 우측 값 글자색 */
7041
+ selectDataText: btn("selectData-text"),
7042
+ /** 시스템 메뉴에서 지금 값인 칸의 글자색 — 계정 행이 아니라 목록 항목이라
7043
+ * listBoxItem 의 선택 색을 그대로 따른다(다른 목록의 선택 표시와 같은 색) */
7044
+ menuSelectedText: item("content-selected"),
7045
+ // TODO: 우측 화살표 전용 색 토큰이 없다. 시안(#888888)에 맞는 시맨틱 토큰으로 둔다.
7046
+ /** 우측 화살표색 */
7047
+ selectDataIconColor: sys("fg-tertiary")
7048
+ };
7049
+ function SystemMenuPortal({
7050
+ open,
7051
+ onOpenChange,
7052
+ anchorRef,
7053
+ placement = "bottom",
7054
+ align,
7055
+ triggerRef,
7056
+ ariaLabel,
7057
+ value,
7058
+ options,
7059
+ onSelect
7060
+ }) {
7061
+ const t = ACCOUNT_LIST_BOX_TONE_CONFIG.default;
7062
+ return /* @__PURE__ */ jsxRuntime.jsx(
7063
+ SPortal,
7064
+ {
7065
+ open,
7066
+ onClose: () => onOpenChange(false),
7067
+ anchorRef,
7068
+ placement,
7069
+ align,
7070
+ offset: 4,
7071
+ viewportPadding: 8,
7072
+ ariaLabel,
7073
+ onPointerDownOutside: (event) => {
7074
+ if (triggerRef?.current?.contains(event.target)) event.preventDefault();
7075
+ },
7076
+ onOpenAutoFocus: (event) => event.preventDefault(),
7077
+ className: "w-auto min-w-[100px] rounded-(--cmp-gnb-system-accountListBox-radius) bg-(--cmp-gnb-system-accountListBox-bg)",
7078
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { role: "menu", className: "flex flex-col", style: { paddingBlock: ACCOUNT_LIST_BOX_LAYOUT.listPaddingY }, children: options.map((option) => {
7079
+ const selected = option.value === value;
7080
+ const color = option.color ? `var(--cmp-tag-${option.color}-content)` : selected ? ACCOUNT_LIST_BOX_LAYOUT.menuSelectedText : t.text;
7081
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7082
+ "button",
7083
+ {
7084
+ type: "button",
7085
+ role: "menuitemradio",
7086
+ "aria-checked": selected,
7087
+ onClick: () => onSelect(option.value),
7088
+ className: cn(
7089
+ selected ? "typo-field-sm-bold" : "typo-field-sm-medium",
7090
+ "flex w-full cursor-pointer items-center whitespace-nowrap border-none bg-(--alb-bg) text-left transition-colors hover:bg-(--alb-bg-hover)"
7091
+ ),
7092
+ style: {
7093
+ "--alb-bg": t.bg,
7094
+ "--alb-bg-hover": t.bgHover,
7095
+ "paddingInline": ACCOUNT_LIST_BOX_LAYOUT.itemPaddingX,
7096
+ "paddingBlock": ACCOUNT_LIST_BOX_LAYOUT.itemPaddingY,
7097
+ "gap": ACCOUNT_LIST_BOX_LAYOUT.itemGap,
7098
+ color
7099
+ },
7100
+ children: [
7101
+ option.color && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex shrink-0 items-center", children: /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "dot", size: "100%", style: { width: ACCOUNT_LIST_BOX_LAYOUT.itemIcon, height: ACCOUNT_LIST_BOX_LAYOUT.itemIcon } }) }),
7102
+ option.label
7103
+ ]
7104
+ },
7105
+ option.value
7106
+ );
7107
+ }) })
7108
+ }
7109
+ );
7110
+ }
7111
+ function TokenIcon({ name, size }) {
7112
+ return /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name, size: "100%", style: { width: size, height: size } });
7113
+ }
7114
+ function Row({
7115
+ tone = "default",
7116
+ icon,
7117
+ label,
7118
+ value,
7119
+ trailingRef,
7120
+ rowRef,
7121
+ hasMenu,
7122
+ expanded,
7123
+ onClick
7124
+ }) {
7125
+ const t = ACCOUNT_LIST_BOX_TONE_CONFIG[tone];
7126
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7127
+ "button",
7128
+ {
7129
+ ref: rowRef,
7130
+ type: "button",
7131
+ "aria-haspopup": hasMenu && "menu",
7132
+ "aria-expanded": hasMenu && expanded,
7133
+ onClick,
7134
+ className: "flex w-full cursor-pointer items-center border-none bg-(--alb-bg) text-left transition-colors hover:bg-(--alb-bg-hover)",
7135
+ style: {
7136
+ "--alb-bg": t.bg,
7137
+ "--alb-bg-hover": t.bgHover,
7138
+ "paddingInline": ACCOUNT_LIST_BOX_LAYOUT.itemPaddingX,
7139
+ "paddingBlock": ACCOUNT_LIST_BOX_LAYOUT.itemPaddingY,
7140
+ "gap": ACCOUNT_LIST_BOX_LAYOUT.itemGap
7141
+ },
7142
+ children: [
7143
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex shrink-0 items-center", style: { color: t.icon }, children: /* @__PURE__ */ jsxRuntime.jsx(TokenIcon, { name: icon, size: ACCOUNT_LIST_BOX_LAYOUT.itemIcon }) }),
7144
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-field-sm-medium min-w-0 flex-1 truncate", style: { color: t.text }, children: label }),
7145
+ (value != null || hasMenu) && /* @__PURE__ */ jsxRuntime.jsxs(
7146
+ "span",
7147
+ {
7148
+ ref: trailingRef,
7149
+ className: "inline-flex shrink-0 items-center",
7150
+ style: { gap: ACCOUNT_LIST_BOX_LAYOUT.selectDataGap },
7151
+ children: [
7152
+ value != null && /* @__PURE__ */ jsxRuntime.jsx(
7153
+ "span",
7154
+ {
7155
+ className: "typo-control-xs-medium whitespace-nowrap",
7156
+ style: { color: ACCOUNT_LIST_BOX_LAYOUT.selectDataText },
7157
+ children: value
7158
+ }
7159
+ ),
7160
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex shrink-0", style: { color: ACCOUNT_LIST_BOX_LAYOUT.selectDataIconColor }, children: /* @__PURE__ */ jsxRuntime.jsx(TokenIcon, { name: "chevronRight", size: ACCOUNT_LIST_BOX_LAYOUT.selectDataIcon }) })
7161
+ ]
7162
+ }
7163
+ )
7164
+ ]
7165
+ }
7166
+ );
7167
+ }
7168
+ var SAccountListBox = /* @__PURE__ */ react.forwardRef(
7169
+ function SAccountListBox2({ email, name, authority, accountSetting, language, logout, className, style, ...rest }, ref) {
7170
+ const hasUserdata = email != null || name != null || authority != null;
7171
+ const languageOptions = language?.options ?? [];
7172
+ const hasLanguageMenu = languageOptions.length > 0;
7173
+ const [languageMenuOpen, setLanguageMenuOpen] = react.useState(false);
7174
+ const languageValueRef = react.useRef(null);
7175
+ const languageRowRef = react.useRef(null);
7176
+ const languageLabel = language?.label ?? ACCOUNT_LIST_BOX_LABELS.language;
7177
+ const languageDoesNothing = Boolean(language) && !hasLanguageMenu && !language?.onClick;
7178
+ react.useEffect(() => {
7179
+ if (isDev() && languageDoesNothing) {
7180
+ console.warn(
7181
+ "[SAccountListBox] language \uC5D0 options \uB3C4 onClick \uB3C4 \uC5C6\uC2B5\uB2C8\uB2E4. \uC571 \uC548\uC5D0\uC11C \uACE0\uB974\uAC8C \uD558\uB824\uBA74 options \uB97C, \uC5B8\uC5B4 \uD654\uBA74\uC73C\uB85C \uBCF4\uB0BC \uAC83\uC774\uBA74 onClick \uC744 \uC8FC\uC138\uC694 \u2014 \uB458 \uB2E4 \uC5C6\uC73C\uBA74 \uD654\uC0B4\uD45C\uB9CC \uC788\uACE0 \uB20C\uB7EC\uB3C4 \uC544\uBB34 \uC77C\uC774 \uC5C6\uB294 \uD589\uC774 \uB429\uB2C8\uB2E4."
7182
+ );
7183
+ }
7184
+ }, [languageDoesNothing]);
7185
+ const languageText = languageOptions.find((option) => option.value === language?.value)?.label ?? language?.value;
7186
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7187
+ "div",
7188
+ {
7189
+ ref,
7190
+ className: cn("box-border flex flex-col overflow-hidden", className),
7191
+ style: {
7192
+ width: ACCOUNT_LIST_BOX_LAYOUT.width,
7193
+ backgroundColor: ACCOUNT_LIST_BOX_LAYOUT.bg,
7194
+ borderRadius: ACCOUNT_LIST_BOX_LAYOUT.radius,
7195
+ ...style
7196
+ },
7197
+ ...rest,
7198
+ children: [
7199
+ hasUserdata && /* @__PURE__ */ jsxRuntime.jsxs(
7200
+ "div",
7201
+ {
7202
+ className: "flex flex-col",
7203
+ style: {
7204
+ backgroundColor: ACCOUNT_LIST_BOX_LAYOUT.userdataBg,
7205
+ paddingInline: ACCOUNT_LIST_BOX_LAYOUT.userdataPaddingX,
7206
+ paddingBlock: ACCOUNT_LIST_BOX_LAYOUT.userdataPaddingY
7207
+ },
7208
+ children: [
7209
+ email != null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-sm-medium truncate", style: { color: ACCOUNT_LIST_BOX_LAYOUT.emailColor }, children: email }),
7210
+ (name != null || authority != null) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", style: { gap: ACCOUNT_LIST_BOX_LAYOUT.itemGap }, children: [
7211
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-sm-bold min-w-0 truncate", style: { color: ACCOUNT_LIST_BOX_LAYOUT.nameColor }, children: name }),
7212
+ authority != null && /* @__PURE__ */ jsxRuntime.jsx(
7213
+ "span",
7214
+ {
7215
+ className: "typo-body-sm-medium shrink-0 whitespace-nowrap",
7216
+ style: { color: ACCOUNT_LIST_BOX_LAYOUT.roleColor },
7217
+ children: authority
7218
+ }
7219
+ )
7220
+ ] })
7221
+ ]
7222
+ }
7223
+ ),
7224
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", style: { paddingBlock: ACCOUNT_LIST_BOX_LAYOUT.listPaddingY }, children: [
7225
+ accountSetting && /* @__PURE__ */ jsxRuntime.jsx(
7226
+ Row,
7227
+ {
7228
+ icon: ACCOUNT_LIST_BOX_ICONS.accountSetting,
7229
+ label: accountSetting.label ?? ACCOUNT_LIST_BOX_LABELS.accountSetting,
7230
+ onClick: accountSetting.onClick
7231
+ }
7232
+ ),
7233
+ language && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7234
+ /* @__PURE__ */ jsxRuntime.jsx(
7235
+ Row,
7236
+ {
7237
+ icon: ACCOUNT_LIST_BOX_ICONS.language,
7238
+ label: languageLabel,
7239
+ value: languageText,
7240
+ trailingRef: languageValueRef,
7241
+ rowRef: languageRowRef,
7242
+ hasMenu: hasLanguageMenu,
7243
+ expanded: languageMenuOpen,
7244
+ onClick: () => {
7245
+ language.onClick?.();
7246
+ if (hasLanguageMenu) setLanguageMenuOpen((open) => !open);
7247
+ }
7248
+ }
7249
+ ),
7250
+ hasLanguageMenu && /* @__PURE__ */ jsxRuntime.jsx(
7251
+ SystemMenuPortal,
7252
+ {
7253
+ open: languageMenuOpen,
7254
+ onOpenChange: setLanguageMenuOpen,
7255
+ anchorRef: languageValueRef,
7256
+ triggerRef: languageRowRef,
7257
+ align: "end",
7258
+ ariaLabel: languageLabel,
7259
+ value: language.value,
7260
+ options: languageOptions,
7261
+ onSelect: (next) => {
7262
+ setLanguageMenuOpen(false);
7263
+ language.onChange?.(next);
7264
+ }
7265
+ }
7266
+ )
7267
+ ] }),
7268
+ /* @__PURE__ */ jsxRuntime.jsx(
7269
+ Row,
7270
+ {
7271
+ tone: "negative",
7272
+ icon: ACCOUNT_LIST_BOX_ICONS.logout,
7273
+ label: logout?.label ?? ACCOUNT_LIST_BOX_LABELS.logout,
7274
+ onClick: logout?.onClick
7275
+ }
7276
+ )
7277
+ ] })
7278
+ ]
7279
+ }
7280
+ );
7281
+ }
7282
+ );
7283
+ var AccountListBoxAnchorContext = /* @__PURE__ */ react.createContext("panel");
7284
+ var AccountListBoxAnchorProvider = AccountListBoxAnchorContext.Provider;
7285
+ var ANCHOR_PLACEMENT = {
7286
+ // 판: 계정 행 위로, 행의 왼쪽 끝에 맞춰
7287
+ panel: { placement: "top", align: "start" },
7288
+ // 상단바: 계정 이름 아래로, 이름의 오른쪽 끝에 맞춰
7289
+ top: { placement: "bottom", align: "end" }
7290
+ };
7291
+ function AccountListBoxPortal({
7292
+ open,
7293
+ onOpenChange,
7294
+ anchorRef,
7295
+ ariaLabel,
7296
+ content
7297
+ }) {
7298
+ const { placement, align } = ANCHOR_PLACEMENT[react.useContext(AccountListBoxAnchorContext)];
7299
+ const closeAfter = (item4) => item4 && {
7300
+ ...item4,
7301
+ onClick: () => {
7302
+ item4.onClick?.();
7303
+ onOpenChange(false);
7304
+ }
7305
+ };
7306
+ return /* @__PURE__ */ jsxRuntime.jsx(
7307
+ SPortal,
7308
+ {
7309
+ open,
7310
+ onClose: () => onOpenChange(false),
7311
+ anchorRef,
7312
+ placement,
7313
+ align,
7314
+ offset: 4,
7315
+ viewportPadding: 8,
7316
+ ariaLabel,
7317
+ onOpenAutoFocus: (event) => event.preventDefault(),
7318
+ className: "w-auto rounded-(--cmp-gnb-system-accountListBox-radius) bg-(--cmp-gnb-system-accountListBox-bg)",
7319
+ children: /* @__PURE__ */ jsxRuntime.jsx(
7320
+ SAccountListBox,
7321
+ {
7322
+ ...content,
7323
+ accountSetting: closeAfter(content.accountSetting),
7324
+ language: content.language && (content.language.options?.length ? {
7325
+ ...content.language,
7326
+ onChange: (next) => {
7327
+ content.language?.onChange?.(next);
7328
+ onOpenChange(false);
7329
+ }
7330
+ } : closeAfter(content.language)),
7331
+ logout: closeAfter(content.logout) ?? { onClick: () => onOpenChange(false) }
7332
+ }
7333
+ )
7334
+ }
7335
+ );
7336
+ }
7337
+
6813
7338
  // src/components/SSystemActionButton/systemActionButton.config.ts
6814
7339
  var SYSTEM_ACTION_BUTTON_COLORS = ["light", "dark", "darker"];
6815
7340
  var SYSTEM_ACTION_BUTTON_TYPES = [
@@ -6819,57 +7344,57 @@ var SYSTEM_ACTION_BUTTON_TYPES = [
6819
7344
  "subSelect",
6820
7345
  "status"
6821
7346
  ];
6822
- var item = (p) => `var(--cmp-gnb-system-item-${p})`;
7347
+ var item2 = (p) => `var(--cmp-gnb-system-item-${p})`;
6823
7348
  var action = (p) => `var(--cmp-gnb-system-actionButton-${p})`;
6824
- var sys = (p) => `var(--sys-color-${p})`;
7349
+ var sys2 = (p) => `var(--sys-color-${p})`;
6825
7350
  var SYSTEM_ACTION_BUTTON_COLOR_CONFIG = {
6826
7351
  light: {
6827
- bg: item("light-bg-default"),
6828
- bgHover: item("light-bg-hover"),
7352
+ bg: item2("light-bg-default"),
7353
+ bgHover: item2("light-bg-hover"),
6829
7354
  // light 의 아이콘 프레임 배경은 기본·hover 공통 한 값이다 (흰 면 위 흰 프레임)
6830
- iconBg: item("light-icon-bg"),
6831
- iconBgHover: item("light-icon-bg"),
6832
- iconGlyph: item("light-icon-default"),
6833
- iconGlyphHover: item("light-icon-default"),
6834
- text: item("light-text"),
7355
+ iconBg: item2("light-icon-bg"),
7356
+ iconBgHover: item2("light-icon-bg"),
7357
+ iconGlyph: item2("light-icon-default"),
7358
+ iconGlyphHover: item2("light-icon-default"),
7359
+ text: item2("light-text"),
6835
7360
  actionText: {
6836
7361
  switch: action("switch-text-light"),
6837
7362
  selectData: action("selectData-text-light")
6838
7363
  },
6839
7364
  // 트레일링 아이콘 전용 색 토큰이 없다. light 는 item.icon.default 가
6840
7365
  // "actionButton/alertButton/setting 공통 글리프색"이라고 토큰에 명시돼 있다.
6841
- actionIcon: item("light-icon-default")
7366
+ actionIcon: item2("light-icon-default")
6842
7367
  },
6843
7368
  dark: {
6844
- bg: item("dark-bg-default"),
6845
- bgHover: item("dark-bg-hover"),
6846
- iconBg: item("dark-icon-bg-default"),
6847
- iconBgHover: item("dark-icon-bg-hover"),
7369
+ bg: item2("dark-bg-default"),
7370
+ bgHover: item2("dark-bg-hover"),
7371
+ iconBg: item2("dark-icon-bg-default"),
7372
+ iconBgHover: item2("dark-icon-bg-hover"),
6848
7373
  // 어두운 면에는 글리프색 토큰이 없다. 기본은 프레임이 배경과 블렌딩되므로 라벨색(흰색),
6849
7374
  // hover 는 프레임이 흰색이 되므로 그 위에 표면색을 그대로 얹는다.
6850
- iconGlyph: item("dark-text"),
6851
- iconGlyphHover: item("dark-bg-hover"),
6852
- text: item("dark-text"),
7375
+ iconGlyph: item2("dark-text"),
7376
+ iconGlyphHover: item2("dark-bg-hover"),
7377
+ text: item2("dark-text"),
6853
7378
  actionText: {
6854
7379
  switch: action("switch-text-dark"),
6855
7380
  selectData: action("selectData-text-dark")
6856
7381
  },
6857
7382
  // TODO: 어두운 면의 트레일링 아이콘 색 토큰이 없다. 시안(#AAAAAA)에 맞는 시맨틱 토큰으로 둔다.
6858
- actionIcon: sys("fg-quaternary")
7383
+ actionIcon: sys2("fg-quaternary")
6859
7384
  },
6860
7385
  darker: {
6861
- bg: item("darker-bg-default"),
6862
- bgHover: item("darker-bg-hover"),
6863
- iconBg: item("darker-icon-bg-default"),
6864
- iconBgHover: item("darker-icon-bg-hover"),
6865
- iconGlyph: item("darker-text"),
6866
- iconGlyphHover: item("darker-bg-hover"),
6867
- text: item("darker-text"),
7386
+ bg: item2("darker-bg-default"),
7387
+ bgHover: item2("darker-bg-hover"),
7388
+ iconBg: item2("darker-icon-bg-default"),
7389
+ iconBgHover: item2("darker-icon-bg-hover"),
7390
+ iconGlyph: item2("darker-text"),
7391
+ iconGlyphHover: item2("darker-bg-hover"),
7392
+ text: item2("darker-text"),
6868
7393
  actionText: {
6869
7394
  switch: action("switch-text-dark"),
6870
7395
  selectData: action("selectData-text-dark")
6871
7396
  },
6872
- actionIcon: sys("fg-quaternary")
7397
+ actionIcon: sys2("fg-quaternary")
6873
7398
  }
6874
7399
  };
6875
7400
  var SYSTEM_ACTION_BUTTON_TYPE_CONFIG = {
@@ -6892,17 +7417,17 @@ var SYSTEM_ACTION_BUTTON_TYPE_CONFIG = {
6892
7417
  };
6893
7418
  var SYSTEM_ACTION_BUTTON_LAYOUT = {
6894
7419
  /** 행 높이 */
6895
- height: item("height"),
7420
+ height: item2("height"),
6896
7421
  /** 행 라운드 */
6897
- radius: item("radius"),
7422
+ radius: item2("radius"),
6898
7423
  /** 아이콘 프레임 한 변 */
6899
- iconFrame: item("icon-frame"),
7424
+ iconFrame: item2("icon-frame"),
6900
7425
  /** 아이콘 글리프 크기 */
6901
- iconGlyph: item("icon-glyph"),
7426
+ iconGlyph: item2("icon-glyph"),
6902
7427
  /** 아이콘 프레임 라운드 */
6903
- iconRadius: item("icon-radius"),
7428
+ iconRadius: item2("icon-radius"),
6904
7429
  /** 아이콘 프레임 ↔ 라벨 간격 */
6905
- iconLabelGap: item("iconLabelGap"),
7430
+ iconLabelGap: item2("iconLabelGap"),
6906
7431
  /** 좌측 여백 */
6907
7432
  paddingLeft: action("paddingLeft"),
6908
7433
  /** 우측 여백 */
@@ -6910,17 +7435,44 @@ var SYSTEM_ACTION_BUTTON_LAYOUT = {
6910
7435
  /** 액션 텍스트 ↔ 액션 아이콘 간격 */
6911
7436
  actionGap: action("selectData-gap")
6912
7437
  };
6913
- function TokenIcon({ name, size }) {
7438
+ function TokenIcon2({ name, size }) {
6914
7439
  return /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name, size: "100%", style: { width: size, height: size } });
6915
7440
  }
6916
7441
  var SSystemActionButton = /* @__PURE__ */ react.forwardRef(
6917
7442
  function SSystemActionButton2({ color = "light", type, label, option, disabled = false, className, style, ...rest }, ref) {
6918
7443
  const c = SYSTEM_ACTION_BUTTON_COLOR_CONFIG[color];
6919
7444
  const spec = SYSTEM_ACTION_BUTTON_TYPE_CONFIG[type];
7445
+ const listBox = type === "account" ? option ?? {} : void 0;
7446
+ const [uncontrolledOpen, setUncontrolledOpen] = react.useState(false);
7447
+ const listBoxOpen = listBox?.open ?? uncontrolledOpen;
7448
+ const commitListBoxOpen = (next) => {
7449
+ setUncontrolledOpen(next);
7450
+ listBox?.onOpenChange?.(next);
7451
+ };
7452
+ const anchorRef = react.useRef(null);
7453
+ const setRefs2 = (node) => {
7454
+ anchorRef.current = node;
7455
+ if (typeof ref === "function") ref(node);
7456
+ else if (ref) ref.current = node;
7457
+ };
6920
7458
  const hoverable = !disabled;
6921
7459
  const status = type === "status" ? option : void 0;
7460
+ const subSelect = type === "subSelect" ? option : void 0;
7461
+ const menu = subSelect ?? status;
7462
+ const menuOptions = menu?.options ?? [];
7463
+ const hasMenu = menuOptions.length > 0;
7464
+ const [menuOpen, setMenuOpen] = react.useState(false);
7465
+ const selected = menuOptions.find((item4) => item4.value === menu?.value);
6922
7466
  const resolvedIcon = spec.fixedIcon ?? option?.icon;
6923
- const actionText = spec.actionText ? option?.text : void 0;
7467
+ const actionText = spec.actionText ? subSelect ? selected?.label ?? subSelect.value : option?.text : void 0;
7468
+ const menuIsEmpty = Boolean(menu) && !hasMenu;
7469
+ react.useEffect(() => {
7470
+ if (isDev() && menuIsEmpty) {
7471
+ console.warn(
7472
+ `[SSystemActionButton] type="${type}" \uC758 option.options \uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4. \uC774 \uD589\uC740 \uACE0\uB978 \uAC12\uC744 \uBC14\uAFB8\uB294 \uBA54\uB274\uC758 \uD2B8\uB9AC\uAC70\uC774\uBBC0\uB85C \uACE0\uB97C \uBAA9\uB85D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4 \u2014 \uB20C\uB7EC\uC11C \uD654\uBA74\uC73C\uB85C \uBCF4\uB0BC \uAC83\uC774\uBA74 type="select" \uB97C, \uBCF4\uC5EC\uC8FC\uAE30\uB9CC \uD560 \uAC83\uC774\uBA74 STag \uB97C \uC4F0\uC138\uC694.`
7473
+ );
7474
+ }
7475
+ }, [menuIsEmpty, type]);
6924
7476
  const cssVars = {
6925
7477
  "--sab-bg": c.bg,
6926
7478
  "--sab-bg-hover": hoverable ? c.bgHover : c.bg,
@@ -6938,12 +7490,14 @@ var SSystemActionButton = /* @__PURE__ */ react.forwardRef(
6938
7490
  "gap": SYSTEM_ACTION_BUTTON_LAYOUT.iconLabelGap,
6939
7491
  ...style
6940
7492
  };
6941
- return /* @__PURE__ */ jsxRuntime.jsxs(
7493
+ const button = /* @__PURE__ */ jsxRuntime.jsxs(
6942
7494
  "button",
6943
7495
  {
6944
- ref,
7496
+ ref: setRefs2,
6945
7497
  type: "button",
6946
7498
  disabled,
7499
+ "aria-haspopup": listBox ? "dialog" : hasMenu ? "menu" : void 0,
7500
+ "aria-expanded": listBox ? listBoxOpen : hasMenu ? menuOpen : void 0,
6947
7501
  className: cn(
6948
7502
  "group box-border flex w-full items-center border-none bg-(--sab-bg) text-left transition-colors",
6949
7503
  "hover:bg-(--sab-bg-hover)",
@@ -6952,16 +7506,28 @@ var SSystemActionButton = /* @__PURE__ */ react.forwardRef(
6952
7506
  ),
6953
7507
  style: cssVars,
6954
7508
  ...rest,
7509
+ onClick: (event) => {
7510
+ rest.onClick?.(event);
7511
+ if (listBox) commitListBoxOpen(!listBoxOpen);
7512
+ else if (hasMenu) setMenuOpen((open) => !open);
7513
+ },
6955
7514
  children: [
6956
7515
  resolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(
6957
7516
  "span",
6958
7517
  {
6959
7518
  className: "inline-flex shrink-0 items-center justify-center bg-(--sab-icon-bg) text-(--sab-icon-glyph) transition-colors group-hover:bg-(--sab-icon-bg-hover) group-hover:text-(--sab-icon-glyph-hover)",
6960
7519
  style: { width: SYSTEM_ACTION_BUTTON_LAYOUT.iconFrame, height: SYSTEM_ACTION_BUTTON_LAYOUT.iconFrame, borderRadius: SYSTEM_ACTION_BUTTON_LAYOUT.iconRadius },
6961
- children: /* @__PURE__ */ jsxRuntime.jsx(TokenIcon, { name: resolvedIcon, size: SYSTEM_ACTION_BUTTON_LAYOUT.iconGlyph })
7520
+ children: /* @__PURE__ */ jsxRuntime.jsx(TokenIcon2, { name: resolvedIcon, size: SYSTEM_ACTION_BUTTON_LAYOUT.iconGlyph })
6962
7521
  }
6963
7522
  ),
6964
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-sm-semibold flex min-w-0 flex-1 items-center text-(--sab-text)", children: status ? /* @__PURE__ */ jsxRuntime.jsx(STag, { color: status.color ?? "blue", icon: "dot", label: status.label }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label }) }),
7523
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typo-body-sm-semibold flex min-w-0 flex-1 items-center text-(--sab-text)", children: status ? /* @__PURE__ */ jsxRuntime.jsx(
7524
+ STag,
7525
+ {
7526
+ color: selected?.color ?? "blue",
7527
+ icon: "dot",
7528
+ label: selected?.label ?? status.value
7529
+ }
7530
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label }) }),
6965
7531
  (actionText != null || spec.actionIcon) && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex shrink-0 items-center", style: { gap: SYSTEM_ACTION_BUTTON_LAYOUT.actionGap }, children: [
6966
7532
  actionText != null && spec.actionText && /* @__PURE__ */ jsxRuntime.jsx(
6967
7533
  "span",
@@ -6970,11 +7536,48 @@ var SSystemActionButton = /* @__PURE__ */ react.forwardRef(
6970
7536
  children: actionText
6971
7537
  }
6972
7538
  ),
6973
- spec.actionIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex shrink-0 items-center text-(--sab-action-icon)", children: /* @__PURE__ */ jsxRuntime.jsx(TokenIcon, { name: spec.actionIcon.name, size: spec.actionIcon.size }) })
7539
+ spec.actionIcon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex shrink-0 items-center text-(--sab-action-icon)", children: /* @__PURE__ */ jsxRuntime.jsx(TokenIcon2, { name: spec.actionIcon.name, size: spec.actionIcon.size }) })
6974
7540
  ] })
6975
7541
  ]
6976
7542
  }
6977
7543
  );
7544
+ if (!listBox) {
7545
+ if (!hasMenu) return button;
7546
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7547
+ button,
7548
+ /* @__PURE__ */ jsxRuntime.jsx(
7549
+ SystemMenuPortal,
7550
+ {
7551
+ open: menuOpen,
7552
+ onOpenChange: setMenuOpen,
7553
+ anchorRef,
7554
+ placement: "right",
7555
+ align: "start",
7556
+ ariaLabel: label ?? selected?.label ?? menu?.value,
7557
+ value: menu?.value,
7558
+ options: menuOptions,
7559
+ onSelect: (next) => {
7560
+ setMenuOpen(false);
7561
+ menu?.onChange?.(next);
7562
+ }
7563
+ }
7564
+ )
7565
+ ] });
7566
+ }
7567
+ const { open: _open, onOpenChange: _onOpenChange, ...content } = listBox;
7568
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7569
+ button,
7570
+ /* @__PURE__ */ jsxRuntime.jsx(
7571
+ AccountListBoxPortal,
7572
+ {
7573
+ open: listBoxOpen,
7574
+ onOpenChange: commitListBoxOpen,
7575
+ anchorRef,
7576
+ ariaLabel: label,
7577
+ content
7578
+ }
7579
+ )
7580
+ ] });
6978
7581
  }
6979
7582
  );
6980
7583
  var SIZE_CLASSES = {
@@ -7129,87 +7732,6 @@ function SPopover({
7129
7732
  ) })
7130
7733
  ] });
7131
7734
  }
7132
- function SPortal({
7133
- open,
7134
- onClose,
7135
- onOpenChange,
7136
- anchorRef,
7137
- placement = "bottom",
7138
- align = "start",
7139
- offset = 4,
7140
- alignOffset = 0,
7141
- fit = false,
7142
- maxHeight,
7143
- autoClose = false,
7144
- persistent = false,
7145
- viewportPadding = 0,
7146
- onOpenAutoFocus,
7147
- onCloseAutoFocus,
7148
- onPointerDownOutside,
7149
- children,
7150
- className,
7151
- style,
7152
- ariaLabel
7153
- }) {
7154
- const portalContainer = usePortalContainer();
7155
- const { minWidth: styleMinWidth, maxWidth: styleMaxWidth, ...restStyle } = style ?? {};
7156
- return /* @__PURE__ */ jsxRuntime.jsxs(
7157
- RPopover11__namespace.Root,
7158
- {
7159
- open,
7160
- onOpenChange: (next) => {
7161
- onOpenChange?.(next);
7162
- if (!next) onClose?.();
7163
- },
7164
- children: [
7165
- /* @__PURE__ */ jsxRuntime.jsx(RPopover11__namespace.Anchor, { virtualRef: anchorRef }),
7166
- /* @__PURE__ */ jsxRuntime.jsx(RPopover11__namespace.Portal, { container: portalContainer, children: /* @__PURE__ */ jsxRuntime.jsx(
7167
- RPopover11__namespace.Content,
7168
- {
7169
- side: placement,
7170
- align,
7171
- sideOffset: offset,
7172
- alignOffset,
7173
- collisionPadding: viewportPadding,
7174
- "aria-label": ariaLabel,
7175
- onPointerDownOutside: (e) => {
7176
- if (persistent || anchorRef.current?.contains(e.target)) {
7177
- e.preventDefault();
7178
- return;
7179
- }
7180
- onPointerDownOutside?.(e);
7181
- },
7182
- onFocusOutside: (e) => {
7183
- if (persistent || anchorRef.current?.contains(e.target)) {
7184
- e.preventDefault();
7185
- }
7186
- },
7187
- onEscapeKeyDown: persistent ? (e) => e.preventDefault() : void 0,
7188
- onOpenAutoFocus,
7189
- onCloseAutoFocus,
7190
- onClick: autoClose ? () => onClose?.() : void 0,
7191
- className: cn(
7192
- "z-50 overflow-hidden rounded-(--cmp-listBox-radius) bg-(--cmp-listBox-bg) shadow-normal-sm",
7193
- maxHeight != null && "overflow-y-auto",
7194
- // 앵커가 창보다 넓을 수 있는 자리(가로 스크롤 안의 트리거 등)에서도 하한이 상한을
7195
- // 이기지 않도록, 앵커 너비 역시 가용 폭으로 가둔다.
7196
- fit && "min-w-[min(var(--radix-popover-trigger-width),var(--radix-popover-content-available-width))]",
7197
- FLOATING_SLIDE_ANIM,
7198
- className
7199
- ),
7200
- style: {
7201
- maxHeight,
7202
- ...restStyle,
7203
- ...styleMinWidth != null ? { minWidth: clampToAvailableWidth(styleMinWidth, POPOVER_AVAILABLE_WIDTH) } : {},
7204
- maxWidth: clampToAvailableWidth(styleMaxWidth, POPOVER_AVAILABLE_WIDTH)
7205
- },
7206
- children
7207
- }
7208
- ) })
7209
- ]
7210
- }
7211
- );
7212
- }
7213
7735
  var SPopup = /* @__PURE__ */ react.forwardRef(function SPopup2({
7214
7736
  popupTitle = "",
7215
7737
  type = "default",
@@ -8157,11 +8679,6 @@ function SDrawer({
8157
8679
  ] }) }) });
8158
8680
  }
8159
8681
 
8160
- // src/lib/is-dev.ts
8161
- function isDev() {
8162
- return typeof process === "undefined" || process?.env?.NODE_ENV !== "production";
8163
- }
8164
-
8165
8682
  // src/lib/modal-outlet.ts
8166
8683
  var EMPTY = [];
8167
8684
  var entries2 = EMPTY;
@@ -8622,7 +9139,7 @@ var SLayout = /* @__PURE__ */ react.forwardRef(function SLayout2({
8622
9139
 
8623
9140
  // src/components/SGnb/gnb.config.ts
8624
9141
  var gnb = (p) => `var(--cmp-gnb-${p})`;
8625
- var box = (p) => `var(--cmp-gnb-box-${p})`;
9142
+ var box2 = (p) => `var(--cmp-gnb-box-${p})`;
8626
9143
  var belt = (p) => `var(--cmp-gnb-belt-${p})`;
8627
9144
  var light = (p) => `var(--cmp-gnb-light-${p})`;
8628
9145
  var dark = (p) => `var(--cmp-gnb-dark-${p})`;
@@ -8643,14 +9160,14 @@ var GNB_MENU = {
8643
9160
  itemMarginX: gnb("body-padding"),
8644
9161
  // 전방향 토큰 → 아이템 좌우 여백에도 사용
8645
9162
  itemPaddingY: gnb("item-paddingY"),
8646
- itemPaddingRight: box("item-paddingRight"),
8647
- itemGap: box("item-gap"),
8648
- itemRadius: box("item-radius"),
9163
+ itemPaddingRight: box2("item-paddingRight"),
9164
+ itemGap: box2("item-gap"),
9165
+ itemRadius: box2("item-radius"),
8649
9166
  itemArrow: gnb("item-chevron-size"),
8650
- depth1PaddingLeft: box("item-depth1-paddingLeft"),
8651
- depth2PaddingLeft: box("item-depth2-paddingLeft"),
8652
- depth3PaddingLeft: box("item-depth3-paddingLeft"),
8653
- depth1Icon: box("item-depth1-icon"),
9167
+ depth1PaddingLeft: box2("item-depth1-paddingLeft"),
9168
+ depth2PaddingLeft: box2("item-depth2-paddingLeft"),
9169
+ depth3PaddingLeft: box2("item-depth3-paddingLeft"),
9170
+ depth1Icon: box2("item-depth1-icon"),
8654
9171
  // box 는 depth1 전용 타이포 토큰이 없어 depth1 도 selected 타이포를 따른다
8655
9172
  depth1FontSize: 14,
8656
9173
  // token: gnb.box.item.typography.selected.fontSize
@@ -8763,17 +9280,17 @@ var GNB_TOP_ICON_GAP = 8;
8763
9280
  var GNB_TOP_ICON_SIZE = 24;
8764
9281
  var GNB_FULL_LOGO_WIDTH_NO_LAUNCHER = GNB_FULL_LOGO_WIDTH + GNB_TOP_ICON_SIZE + GNB_TOP_ICON_GAP;
8765
9282
  function findGnbRailValue(items, value) {
8766
- if (items.some((item3) => item3.value === value)) return value;
9283
+ if (items.some((item4) => item4.value === value)) return value;
8767
9284
  return findGnbAncestors(items, value)[0];
8768
9285
  }
8769
9286
  function findGnbSiblingValues(items, value) {
8770
9287
  const walk = (list) => {
8771
- if (list.some((item3) => item3.value === value)) {
8772
- return list.filter((item3) => item3.value !== value).map((item3) => item3.value);
9288
+ if (list.some((item4) => item4.value === value)) {
9289
+ return list.filter((item4) => item4.value !== value).map((item4) => item4.value);
8773
9290
  }
8774
- for (const item3 of list) {
8775
- if (item3.children) {
8776
- const found = walk(item3.children);
9291
+ for (const item4 of list) {
9292
+ if (item4.children) {
9293
+ const found = walk(item4.children);
8777
9294
  if (found) return found;
8778
9295
  }
8779
9296
  }
@@ -8783,10 +9300,10 @@ function findGnbSiblingValues(items, value) {
8783
9300
  }
8784
9301
  function findGnbAncestors(items, value) {
8785
9302
  const walk = (list, trail) => {
8786
- for (const item3 of list) {
8787
- if (item3.value === value) return trail;
8788
- if (item3.children) {
8789
- const found = walk(item3.children, [...trail, item3.value]);
9303
+ for (const item4 of list) {
9304
+ if (item4.value === value) return trail;
9305
+ if (item4.children) {
9306
+ const found = walk(item4.children, [...trail, item4.value]);
8790
9307
  if (found) return found;
8791
9308
  }
8792
9309
  }
@@ -8796,20 +9313,20 @@ function findGnbAncestors(items, value) {
8796
9313
  }
8797
9314
  function findGnbDescendantBranchValues(items, value) {
8798
9315
  const find = (list) => {
8799
- for (const item3 of list) {
8800
- if (item3.value === value) return item3;
8801
- if (item3.children) {
8802
- const found = find(item3.children);
9316
+ for (const item4 of list) {
9317
+ if (item4.value === value) return item4;
9318
+ if (item4.children) {
9319
+ const found = find(item4.children);
8803
9320
  if (found) return found;
8804
9321
  }
8805
9322
  }
8806
9323
  return void 0;
8807
9324
  };
8808
9325
  const collect = (list, acc) => {
8809
- for (const item3 of list) {
8810
- if (item3.children && item3.children.length > 0) {
8811
- acc.push(item3.value);
8812
- collect(item3.children, acc);
9326
+ for (const item4 of list) {
9327
+ if (item4.children && item4.children.length > 0) {
9328
+ acc.push(item4.value);
9329
+ collect(item4.children, acc);
8813
9330
  }
8814
9331
  }
8815
9332
  return acc;
@@ -8854,7 +9371,7 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
8854
9371
  const type = typeProp ?? layout?.type ?? "box";
8855
9372
  const folded = foldedProp ?? layout?.folded ?? false;
8856
9373
  const useRail = useRailProp ?? layout?.useRail ?? false;
8857
- const railHasLeaf = useRail && items.some((item3) => !item3.children || item3.children.length === 0);
9374
+ const railHasLeaf = useRail && items.some((item4) => !item4.children || item4.children.length === 0);
8858
9375
  const header = railHasLeaf ? "full" : headerProp ?? layout?.header ?? "fix";
8859
9376
  const H = GNB_HEADER[header];
8860
9377
  const M = GNB_MENU[type];
@@ -8897,13 +9414,13 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
8897
9414
  labelTipHideRef.current = setTimeout(() => setLabelTip(null), LABEL_TIP_HIDE_DELAY_MS);
8898
9415
  };
8899
9416
  react.useEffect(() => cancelLabelTipHide, []);
8900
- const rowHoverProps = (item3) => ({
9417
+ const rowHoverProps = (item4) => ({
8901
9418
  onMouseEnter: (event) => {
8902
- setHoveredKey(item3.value);
8903
- showLabelTipIfTruncated(event.currentTarget, item3.label);
9419
+ setHoveredKey(item4.value);
9420
+ showLabelTipIfTruncated(event.currentTarget, item4.label);
8904
9421
  },
8905
9422
  onMouseLeave: () => {
8906
- setHoveredKey((prev) => prev === item3.value ? null : prev);
9423
+ setHoveredKey((prev) => prev === item4.value ? null : prev);
8907
9424
  startLabelTipHide();
8908
9425
  }
8909
9426
  });
@@ -8929,7 +9446,7 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
8929
9446
  }, [items, value]);
8930
9447
  react.useEffect(() => {
8931
9448
  setActiveRail(
8932
- (prev) => prev !== void 0 && items.some((item3) => item3.value === prev) ? prev : items[0]?.value
9449
+ (prev) => prev !== void 0 && items.some((item4) => item4.value === prev) ? prev : items[0]?.value
8933
9450
  );
8934
9451
  }, [items]);
8935
9452
  const toggleExpand = (key) => {
@@ -8946,33 +9463,33 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
8946
9463
  return next;
8947
9464
  });
8948
9465
  };
8949
- const handleItemClick = (item3) => {
8950
- if (item3.disabled) return;
8951
- if (item3.children && item3.children.length > 0) {
8952
- toggleExpand(item3.value);
9466
+ const handleItemClick = (item4) => {
9467
+ if (item4.disabled) return;
9468
+ if (item4.children && item4.children.length > 0) {
9469
+ toggleExpand(item4.value);
8953
9470
  return;
8954
9471
  }
8955
- onValueChange?.(item3.value);
9472
+ onValueChange?.(item4.value);
8956
9473
  };
8957
- const handleRailClick = (item3) => {
8958
- if (item3.disabled) return;
8959
- setActiveRail(item3.value);
8960
- onRailChange?.(item3.value);
8961
- if (!item3.children || item3.children.length === 0) onValueChange?.(item3.value);
9474
+ const handleRailClick = (item4) => {
9475
+ if (item4.disabled) return;
9476
+ setActiveRail(item4.value);
9477
+ onRailChange?.(item4.value);
9478
+ if (!item4.children || item4.children.length === 0) onValueChange?.(item4.value);
8962
9479
  };
8963
9480
  const handleFoldToggle = () => {
8964
9481
  const next = !folded;
8965
9482
  onFoldChange?.(next);
8966
9483
  if (foldedProp === void 0) layout?.setFolded(next);
8967
9484
  };
8968
- const renderRailItem = (item3) => {
8969
- const isActive = item3.value === activeRail;
8970
- const isHovered = hoveredKey === item3.value && !item3.disabled;
9485
+ const renderRailItem = (item4) => {
9486
+ const isActive = item4.value === activeRail;
9487
+ const isHovered = hoveredKey === item4.value && !item4.disabled;
8971
9488
  return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
8972
9489
  "button",
8973
9490
  {
8974
9491
  type: "button",
8975
- disabled: item3.disabled,
9492
+ disabled: item4.disabled,
8976
9493
  "aria-current": isActive ? "true" : void 0,
8977
9494
  className: "box-border flex select-none flex-col items-center border-none bg-transparent transition-colors duration-150",
8978
9495
  style: {
@@ -8987,31 +9504,31 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
8987
9504
  fontSize: GNB_RAIL.itemFontSize,
8988
9505
  lineHeight: `${GNB_RAIL.itemLineHeight}px`,
8989
9506
  fontWeight: isActive ? GNB_RAIL.itemFontWeightSelected : GNB_RAIL.itemFontWeight,
8990
- opacity: item3.disabled ? 0.4 : 1,
8991
- cursor: item3.disabled ? "not-allowed" : "pointer"
9507
+ opacity: item4.disabled ? 0.4 : 1,
9508
+ cursor: item4.disabled ? "not-allowed" : "pointer"
8992
9509
  },
8993
- onClick: () => handleRailClick(item3),
8994
- ...rowHoverProps(item3),
9510
+ onClick: () => handleRailClick(item4),
9511
+ ...rowHoverProps(item4),
8995
9512
  children: [
8996
- item3.icon && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: item3.icon, size: GNB_RAIL.itemIcon, className: "shrink-0" }),
9513
+ item4.icon && /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: item4.icon, size: GNB_RAIL.itemIcon, className: "shrink-0" }),
8997
9514
  /* @__PURE__ */ jsxRuntime.jsx(
8998
9515
  "span",
8999
9516
  {
9000
9517
  "data-gnb-label": true,
9001
9518
  className: "w-full overflow-hidden text-ellipsis whitespace-nowrap text-center",
9002
- children: item3.label
9519
+ children: item4.label
9003
9520
  }
9004
9521
  )
9005
9522
  ]
9006
9523
  }
9007
- ) }, item3.value);
9524
+ ) }, item4.value);
9008
9525
  };
9009
- const renderItem = (item3, depth, branchHasIcon = false) => {
9010
- const hasChildren = !!(item3.children && item3.children.length > 0);
9011
- const isSelected = !hasChildren && item3.value === value;
9012
- const isExpanded = expandedKeys.has(item3.value);
9013
- const isHovered = hoveredKey === item3.value && !item3.disabled;
9014
- const iconBranch = depth === 1 ? !!item3.icon : branchHasIcon;
9526
+ const renderItem = (item4, depth, branchHasIcon = false) => {
9527
+ const hasChildren = !!(item4.children && item4.children.length > 0);
9528
+ const isSelected = !hasChildren && item4.value === value;
9529
+ const isExpanded = expandedKeys.has(item4.value);
9530
+ const isHovered = hoveredKey === item4.value && !item4.disabled;
9531
+ const iconBranch = depth === 1 ? !!item4.icon : branchHasIcon;
9015
9532
  const itemStyle = {
9016
9533
  gap: M.itemGap,
9017
9534
  paddingTop: M.itemPaddingY,
@@ -9028,8 +9545,8 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
9028
9545
  fontSize: depth === 1 ? M.depth1FontSize : M.itemFontSize,
9029
9546
  lineHeight: `${depth === 1 ? M.depth1LineHeight : M.itemLineHeight}px`,
9030
9547
  fontWeight: depth === 1 ? M.depth1FontWeight : isSelected ? M.itemFontWeightSelected : M.itemFontWeight,
9031
- opacity: item3.disabled ? 0.4 : 1,
9032
- cursor: item3.disabled ? "not-allowed" : "pointer"
9548
+ opacity: item4.disabled ? 0.4 : 1,
9549
+ cursor: item4.disabled ? "not-allowed" : "pointer"
9033
9550
  };
9034
9551
  return (
9035
9552
  // li 를 flex-col 로 둬야 버튼이 좌우 마진만큼 안쪽으로 들어가고,
@@ -9039,18 +9556,18 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
9039
9556
  "button",
9040
9557
  {
9041
9558
  type: "button",
9042
- disabled: item3.disabled,
9559
+ disabled: item4.disabled,
9043
9560
  "aria-expanded": hasChildren ? isExpanded : void 0,
9044
9561
  "aria-current": isSelected ? "page" : void 0,
9045
9562
  className: "box-border flex select-none items-center border-none bg-transparent text-left transition-colors duration-150",
9046
9563
  style: itemStyle,
9047
- onClick: () => handleItemClick(item3),
9048
- ...rowHoverProps(item3),
9564
+ onClick: () => handleItemClick(item4),
9565
+ ...rowHoverProps(item4),
9049
9566
  children: [
9050
- depth === 1 && item3.icon && /* @__PURE__ */ jsxRuntime.jsx(
9567
+ depth === 1 && item4.icon && /* @__PURE__ */ jsxRuntime.jsx(
9051
9568
  SIcon,
9052
9569
  {
9053
- name: item3.icon,
9570
+ name: item4.icon,
9054
9571
  size: M.depth1Icon,
9055
9572
  color: isSelected ? C.itemColorActive : C.itemIcon,
9056
9573
  className: "shrink-0"
@@ -9070,17 +9587,17 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
9070
9587
  {
9071
9588
  "data-gnb-label": true,
9072
9589
  className: "min-w-0 flex-1 overflow-hidden text-ellipsis whitespace-nowrap",
9073
- children: item3.label
9590
+ children: item4.label
9074
9591
  }
9075
9592
  )
9076
9593
  ] }),
9077
- item3.tag !== void 0 && item3.tag !== "" && /* @__PURE__ */ jsxRuntime.jsx(
9594
+ item4.tag !== void 0 && item4.tag !== "" && /* @__PURE__ */ jsxRuntime.jsx(
9078
9595
  STag,
9079
9596
  {
9080
9597
  shape: "square",
9081
9598
  size: "xs",
9082
- color: item3.tagColor ?? "blue",
9083
- label: item3.tag,
9599
+ color: item4.tagColor ?? "blue",
9600
+ label: item4.tag,
9084
9601
  className: "shrink-0"
9085
9602
  }
9086
9603
  ),
@@ -9113,16 +9630,16 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
9113
9630
  visibility: isExpanded ? "visible" : "hidden",
9114
9631
  transition: `visibility 0s linear ${isExpanded ? "0s" : `${GNB_EXPAND_MS}ms`}`
9115
9632
  },
9116
- children: item3.children.map((child) => renderItem(child, depth + 1, iconBranch))
9633
+ children: item4.children.map((child) => renderItem(child, depth + 1, iconBranch))
9117
9634
  }
9118
9635
  )
9119
9636
  }
9120
9637
  )
9121
- ] }, item3.value)
9638
+ ] }, item4.value)
9122
9639
  );
9123
9640
  };
9124
9641
  const railItems = useRail ? items : [];
9125
- const menuItems = useRail ? items.find((item3) => item3.value === activeRail)?.children ?? [] : items;
9642
+ const menuItems = useRail ? items.find((item4) => item4.value === activeRail)?.children ?? [] : items;
9126
9643
  const showMenu = !useRail || menuItems.length > 0;
9127
9644
  const [uncontrolledMenuWidth, setUncontrolledMenuWidth] = react.useState(
9128
9645
  () => defaultMenuWidth ?? GNB_MENU_WIDTH
@@ -9313,13 +9830,26 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
9313
9830
  "topContent"
9314
9831
  ) : null;
9315
9832
  const systemMenuContext = react.useMemo(
9316
- () => ({ color, folded: false }),
9317
- [color]
9833
+ () => ({ color, folded: false, placement: "panel", active: !railFolded }),
9834
+ [color, railFolded]
9318
9835
  );
9319
9836
  const systemFoldedContext = react.useMemo(
9320
- () => ({ color, folded: true }),
9837
+ () => ({ color, folded: true, placement: "panel", active: true }),
9321
9838
  [color]
9322
9839
  );
9840
+ const systemTopContext = react.useMemo(
9841
+ () => ({ color, folded: false, placement: "top", active: true }),
9842
+ [color]
9843
+ );
9844
+ const systemTopBox = header === "full" && system ? /* @__PURE__ */ jsxRuntime.jsx(
9845
+ "div",
9846
+ {
9847
+ className: "flex shrink-0 items-center",
9848
+ style: { marginLeft: topContentBox ? H.topGap : "auto" },
9849
+ children: /* @__PURE__ */ jsxRuntime.jsx(SGnbSystemContext.Provider, { value: systemTopContext, children: system })
9850
+ },
9851
+ "system"
9852
+ ) : null;
9323
9853
  return /* @__PURE__ */ jsxRuntime.jsxs(
9324
9854
  "div",
9325
9855
  {
@@ -9361,7 +9891,8 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
9361
9891
  launcherButton,
9362
9892
  foldButton,
9363
9893
  logoBox,
9364
- topContentBox
9894
+ topContentBox,
9895
+ systemTopBox
9365
9896
  ] })
9366
9897
  }
9367
9898
  ),
@@ -9437,11 +9968,11 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
9437
9968
  paddingTop: M.bodyPaddingY,
9438
9969
  paddingBottom: M.bodyPaddingY
9439
9970
  },
9440
- children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "m-0 flex list-none flex-col p-0", children: menuItems.map((item3) => renderItem(item3, 1)) })
9971
+ children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "m-0 flex list-none flex-col p-0", children: menuItems.map((item4) => renderItem(item4, 1)) })
9441
9972
  }
9442
9973
  ),
9443
9974
  menuFooter && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: menuFooter }),
9444
- system && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(SGnbSystemContext.Provider, { value: systemMenuContext, children: system }) })
9975
+ !isFull && system && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(SGnbSystemContext.Provider, { value: systemMenuContext, children: system }) })
9445
9976
  ]
9446
9977
  }
9447
9978
  )
@@ -9478,9 +10009,10 @@ var SGnb = /* @__PURE__ */ react.forwardRef(function SGnb2({
9478
10009
 
9479
10010
  // src/components/SGnbSystem/gnbSystem.config.ts
9480
10011
  var GNB_SYSTEM_COLORS = ["light", "dark"];
10012
+ var GNB_SYSTEM_PLACEMENTS = ["panel", "top"];
9481
10013
  var panel = (p) => `var(--cmp-gnb-system-panel-${p})`;
9482
10014
  var domain = (p) => `var(--cmp-gnb-system-domainTag-${p})`;
9483
- var item2 = (p) => `var(--cmp-gnb-system-item-${p})`;
10015
+ var item3 = (p) => `var(--cmp-gnb-system-item-${p})`;
9484
10016
  var alert = (p) => `var(--cmp-gnb-system-alertButton-${p})`;
9485
10017
  var GNB_SYSTEM_COLOR_CONFIG = {
9486
10018
  light: {
@@ -9508,6 +10040,27 @@ var GNB_SYSTEM_COLOR_CONFIG = {
9508
10040
  alertHoverBg: void 0
9509
10041
  }
9510
10042
  };
10043
+ var GNB_SYSTEM_TOP_COLOR_CONFIG = {
10044
+ light: {
10045
+ item: "light",
10046
+ divider: panel("divider-color-light"),
10047
+ domainBg: domain("light-bg"),
10048
+ domainText: domain("light-text"),
10049
+ alertIcon: alert("icon-color-notification-light"),
10050
+ alertCount: alert("count-color-light"),
10051
+ alertHoverBg: alert("bg-notificationHover-light")
10052
+ },
10053
+ dark: {
10054
+ item: "darker",
10055
+ divider: panel("divider-color-darker"),
10056
+ domainBg: domain("darker-bg"),
10057
+ domainText: domain("darker-text"),
10058
+ alertIcon: alert("icon-color-notification-dark"),
10059
+ alertCount: alert("count-color-dark"),
10060
+ // darker 면에는 알림 hover 배경 토큰이 없다 → 행 기본 hover 를 그대로 쓴다.
10061
+ alertHoverBg: void 0
10062
+ }
10063
+ };
9511
10064
  var GNB_SYSTEM_LAYOUT = {
9512
10065
  /** 펼친 패널의 안쪽 여백 */
9513
10066
  padding: "var(--cmp-gnb-system-project-padding)",
@@ -9519,17 +10072,17 @@ var GNB_SYSTEM_LAYOUT = {
9519
10072
  */
9520
10073
  gap: panel("gap"),
9521
10074
  /** 행 높이 */
9522
- itemHeight: item2("height"),
10075
+ itemHeight: item3("height"),
9523
10076
  /** 행 라운드 */
9524
- itemRadius: item2("radius"),
10077
+ itemRadius: item3("radius"),
9525
10078
  /** 아이콘 프레임 한 변 */
9526
- iconFrame: item2("icon-frame"),
10079
+ iconFrame: item3("icon-frame"),
9527
10080
  /** 아이콘 글리프 크기 */
9528
- iconGlyph: item2("icon-glyph"),
10081
+ iconGlyph: item3("icon-glyph"),
9529
10082
  /** 아이콘 프레임 라운드 */
9530
- iconRadius: item2("icon-radius"),
10083
+ iconRadius: item3("icon-radius"),
9531
10084
  /** 아이콘 프레임 ↔ 라벨 간격 */
9532
- iconLabelGap: item2("iconLabelGap"),
10085
+ iconLabelGap: item3("iconLabelGap"),
9533
10086
  /** 알림 버튼 좌우 여백 */
9534
10087
  alertPaddingX: alert("paddingX"),
9535
10088
  /** 설정 버튼 좌우 여백 */
@@ -9542,7 +10095,7 @@ var GNB_SYSTEM_LAYOUT = {
9542
10095
  var GNB_SYSTEM_ALERT_DOT_SIZE = 6;
9543
10096
  var GNB_SYSTEM_ALERT_LABEL = "\uC54C\uB9BC";
9544
10097
  var GNB_SYSTEM_SETTING_LABEL = "\uC124\uC815";
9545
- function TokenIcon2({ name, size }) {
10098
+ function TokenIcon3({ name, size }) {
9546
10099
  return /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name, size: "100%", style: { width: size, height: size } });
9547
10100
  }
9548
10101
  function SystemButton({
@@ -9557,14 +10110,20 @@ function SystemButton({
9557
10110
  dot,
9558
10111
  accentColor,
9559
10112
  stretch,
10113
+ buttonRef,
10114
+ hasPopup,
10115
+ expanded,
9560
10116
  onClick
9561
10117
  }) {
9562
10118
  const c = SYSTEM_ACTION_BUTTON_COLOR_CONFIG[color];
9563
10119
  return /* @__PURE__ */ jsxRuntime.jsxs(
9564
10120
  "button",
9565
10121
  {
10122
+ ref: buttonRef,
9566
10123
  type: "button",
9567
10124
  "aria-label": label ? void 0 : ariaLabel,
10125
+ "aria-haspopup": hasPopup ? "dialog" : void 0,
10126
+ "aria-expanded": hasPopup ? expanded : void 0,
9568
10127
  onClick,
9569
10128
  className: cn(
9570
10129
  "group box-border flex cursor-pointer items-center border-none bg-(--gsb-bg) text-(--gsb-text) transition-colors hover:bg-(--gsb-bg-hover)",
@@ -9593,7 +10152,7 @@ function SystemButton({
9593
10152
  className: "relative inline-flex shrink-0 items-center justify-center bg-(--gsb-icon-bg) text-(--gsb-icon) transition-colors group-hover:bg-(--gsb-icon-bg-hover) group-hover:text-(--gsb-icon-hover)",
9594
10153
  style: { width: GNB_SYSTEM_LAYOUT.iconFrame, height: GNB_SYSTEM_LAYOUT.iconFrame, borderRadius: GNB_SYSTEM_LAYOUT.iconRadius },
9595
10154
  children: [
9596
- /* @__PURE__ */ jsxRuntime.jsx(TokenIcon2, { name: icon, size: GNB_SYSTEM_LAYOUT.iconGlyph }),
10155
+ /* @__PURE__ */ jsxRuntime.jsx(TokenIcon3, { name: icon, size: GNB_SYSTEM_LAYOUT.iconGlyph }),
9597
10156
  dot && /* @__PURE__ */ jsxRuntime.jsx(
9598
10157
  "span",
9599
10158
  {
@@ -9631,11 +10190,33 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
9631
10190
  }, ref) {
9632
10191
  const gnb2 = react.useContext(SGnbSystemContext);
9633
10192
  const color = colorProp ?? gnb2?.color ?? "light";
9634
- const folded = foldedProp ?? gnb2?.folded ?? false;
10193
+ const placement = gnb2?.placement ?? "panel";
10194
+ const isTop = placement === "top";
10195
+ const folded = !isTop && (foldedProp ?? gnb2?.folded ?? false);
10196
+ const active = gnb2?.active ?? true;
9635
10197
  const c = GNB_SYSTEM_COLOR_CONFIG[color];
10198
+ const t = GNB_SYSTEM_TOP_COLOR_CONFIG[color];
10199
+ const itemColor = isTop ? t.item : color;
10200
+ const dividerColor = isTop ? t.divider : c.divider;
10201
+ const domainBg = isTop ? t.domainBg : c.domainBg;
10202
+ const domainText = isTop ? t.domainText : c.domainText;
10203
+ const alertIconColor = isTop ? t.alertIcon : c.alertIcon;
10204
+ const alertCountColor = isTop ? t.alertCount : c.alertCount;
10205
+ const alertHoverBg = isTop ? t.alertHoverBg : c.alertHoverBg;
9636
10206
  const hasActions = (actions?.length ?? 0) > 0;
9637
10207
  const hasDomain = domain2 != null;
9638
10208
  const hasUserBlock = Boolean(alert2 || setting || account);
10209
+ const foldedAccountRef = react.useRef(null);
10210
+ const [accountOpen, setAccountOpen] = react.useState(false);
10211
+ const commitAccountOpen = (next) => {
10212
+ setAccountOpen(next);
10213
+ account?.onOpenChange?.(next);
10214
+ };
10215
+ react.useEffect(() => {
10216
+ if (active || !accountOpen) return;
10217
+ setAccountOpen(false);
10218
+ account?.onOpenChange?.(false);
10219
+ }, [active, accountOpen, account]);
9639
10220
  const alertCount = alert2?.count ?? 0;
9640
10221
  const notified = alertCount > 0;
9641
10222
  const alertLabel = alert2?.label ?? GNB_SYSTEM_ALERT_LABEL;
@@ -9643,20 +10224,113 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
9643
10224
  const alertButton = alert2 && /* @__PURE__ */ jsxRuntime.jsx(
9644
10225
  SystemButton,
9645
10226
  {
9646
- color,
9647
- icon: notified ? "alert" : "bell",
9648
- label: folded ? void 0 : alertLabel,
10227
+ color: itemColor,
10228
+ icon: notified ? "bellRinging" : "bell",
10229
+ label: folded || isTop ? void 0 : alertLabel,
9649
10230
  ariaLabel: alertLabel,
9650
10231
  paddingX: GNB_SYSTEM_LAYOUT.alertPaddingX,
9651
- iconColor: notified ? c.alertIcon : void 0,
9652
- hoverBg: notified ? c.alertHoverBg : void 0,
10232
+ iconColor: notified ? alertIconColor : void 0,
10233
+ hoverBg: notified ? alertHoverBg : void 0,
9653
10234
  count: folded ? void 0 : alertCount,
9654
10235
  dot: folded && notified,
9655
- accentColor: c.alertCount,
9656
- stretch: !folded,
10236
+ accentColor: alertCountColor,
10237
+ stretch: !folded && !isTop,
9657
10238
  onClick: alert2.onClick
9658
10239
  }
9659
10240
  );
10241
+ const settingButton = setting && /* @__PURE__ */ jsxRuntime.jsx(
10242
+ SystemButton,
10243
+ {
10244
+ color: itemColor,
10245
+ icon: "setting",
10246
+ label: isTop ? void 0 : settingLabel,
10247
+ ariaLabel: settingLabel,
10248
+ paddingX: GNB_SYSTEM_LAYOUT.settingPaddingX,
10249
+ stretch: !isTop && !alert2,
10250
+ onClick: setting.onClick
10251
+ }
10252
+ );
10253
+ const accountButton = account && /* @__PURE__ */ jsxRuntime.jsx(
10254
+ SSystemActionButton,
10255
+ {
10256
+ color: itemColor,
10257
+ type: "account",
10258
+ label: account.label,
10259
+ onClick: account.onClick,
10260
+ option: { ...account.listBox, open: accountOpen, onOpenChange: commitAccountOpen },
10261
+ className: isTop ? "w-auto shrink-0" : void 0
10262
+ }
10263
+ );
10264
+ const domainTag = hasDomain && /* @__PURE__ */ jsxRuntime.jsx(
10265
+ "div",
10266
+ {
10267
+ className: cn(
10268
+ "typo-body-sm-medium box-border",
10269
+ isTop ? "shrink-0 whitespace-nowrap" : "w-full truncate text-center"
10270
+ ),
10271
+ style: {
10272
+ paddingInline: GNB_SYSTEM_LAYOUT.domainPaddingX,
10273
+ paddingBlock: GNB_SYSTEM_LAYOUT.domainPaddingY,
10274
+ borderRadius: GNB_SYSTEM_LAYOUT.domainRadius,
10275
+ backgroundColor: domainBg,
10276
+ color: domainText
10277
+ },
10278
+ children: domain2
10279
+ }
10280
+ );
10281
+ if (isTop) {
10282
+ const segments = [];
10283
+ actions?.forEach(
10284
+ ({ value, ...action2 }, index) => segments.push({
10285
+ key: `action-${value ?? index}`,
10286
+ node: /* @__PURE__ */ jsxRuntime.jsx(
10287
+ SSystemActionButton,
10288
+ {
10289
+ color: itemColor,
10290
+ ...action2,
10291
+ className: cn("w-auto shrink-0", action2.className)
10292
+ }
10293
+ )
10294
+ })
10295
+ );
10296
+ if (alertButton) segments.push({ key: "alert", node: alertButton });
10297
+ if (settingButton) segments.push({ key: "setting", node: settingButton });
10298
+ if (domainTag || accountButton) {
10299
+ segments.push({
10300
+ key: "user",
10301
+ node: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center", style: { gap: GNB_SYSTEM_LAYOUT.gap }, children: [
10302
+ domainTag,
10303
+ accountButton
10304
+ ] })
10305
+ });
10306
+ }
10307
+ if (segments.length === 0) return null;
10308
+ return (
10309
+ // 상단바 줄은 화면 맨 위에 있다 — 계정 리스트박스가 위가 아니라 아래로 펼쳐져야 한다.
10310
+ /* @__PURE__ */ jsxRuntime.jsx(AccountListBoxAnchorProvider, { value: "top", children: /* @__PURE__ */ jsxRuntime.jsx(
10311
+ "div",
10312
+ {
10313
+ ref,
10314
+ className: cn("flex items-center", className),
10315
+ style: { gap: GNB_SYSTEM_LAYOUT.gap, ...style },
10316
+ "data-color": color,
10317
+ "data-placement": "top",
10318
+ ...rest,
10319
+ children: segments.map(({ key, node }, index) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
10320
+ index > 0 && /* @__PURE__ */ jsxRuntime.jsx(
10321
+ "span",
10322
+ {
10323
+ className: "h-sd-16 w-px shrink-0",
10324
+ style: { backgroundColor: dividerColor },
10325
+ "aria-hidden": true
10326
+ }
10327
+ ),
10328
+ node
10329
+ ] }, key))
10330
+ }
10331
+ ) })
10332
+ );
10333
+ }
9660
10334
  const panelStyle = {
9661
10335
  backgroundColor: c.bg,
9662
10336
  // 색에 따라 경계선이 없을 수 있다 — 배경 차이만으로 경계가 읽히는 dark 가 그렇다.
@@ -9673,6 +10347,7 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
9673
10347
  className: cn("box-border flex w-full flex-col", className),
9674
10348
  style: panelStyle,
9675
10349
  "data-color": color,
10350
+ "data-placement": "panel",
9676
10351
  "data-folded": "",
9677
10352
  ...rest,
9678
10353
  children: [
@@ -9680,11 +10355,27 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
9680
10355
  account && /* @__PURE__ */ jsxRuntime.jsx(
9681
10356
  SystemButton,
9682
10357
  {
9683
- color,
10358
+ color: itemColor,
9684
10359
  icon: "user",
9685
10360
  ariaLabel: account.label ?? "account",
9686
10361
  paddingX: GNB_SYSTEM_LAYOUT.alertPaddingX,
9687
- onClick: account.onClick
10362
+ buttonRef: foldedAccountRef,
10363
+ hasPopup: true,
10364
+ expanded: accountOpen,
10365
+ onClick: () => {
10366
+ account.onClick?.();
10367
+ commitAccountOpen(!accountOpen);
10368
+ }
10369
+ }
10370
+ ),
10371
+ account && /* @__PURE__ */ jsxRuntime.jsx(
10372
+ AccountListBoxPortal,
10373
+ {
10374
+ open: accountOpen,
10375
+ onOpenChange: commitAccountOpen,
10376
+ anchorRef: foldedAccountRef,
10377
+ ariaLabel: account.label,
10378
+ content: account.listBox ?? {}
9688
10379
  }
9689
10380
  )
9690
10381
  ]
@@ -9699,31 +10390,19 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
9699
10390
  className: cn("box-border flex w-full flex-col", className),
9700
10391
  style: { ...panelStyle, gap: GNB_SYSTEM_LAYOUT.gap },
9701
10392
  "data-color": color,
10393
+ "data-placement": "panel",
9702
10394
  ...rest,
9703
10395
  children: [
9704
10396
  actions?.map(({ value, ...action2 }, index) => /* @__PURE__ */ jsxRuntime.jsx(
9705
10397
  SSystemActionButton,
9706
10398
  {
9707
- color,
10399
+ color: itemColor,
9708
10400
  ...action2
9709
10401
  },
9710
10402
  value ?? index
9711
10403
  )),
9712
- hasActions && (hasDomain || hasUserBlock) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px shrink-0", style: { backgroundColor: c.divider } }),
9713
- domain2 != null && /* @__PURE__ */ jsxRuntime.jsx(
9714
- "div",
9715
- {
9716
- className: "typo-body-sm-medium box-border w-full truncate text-center",
9717
- style: {
9718
- paddingInline: GNB_SYSTEM_LAYOUT.domainPaddingX,
9719
- paddingBlock: GNB_SYSTEM_LAYOUT.domainPaddingY,
9720
- borderRadius: GNB_SYSTEM_LAYOUT.domainRadius,
9721
- backgroundColor: c.domainBg,
9722
- color: c.domainText
9723
- },
9724
- children: domain2
9725
- }
9726
- ),
10404
+ hasActions && (hasDomain || hasUserBlock) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-px shrink-0", style: { backgroundColor: dividerColor } }),
10405
+ domainTag,
9727
10406
  hasUserBlock && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
9728
10407
  (alert2 || setting) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", style: { gap: GNB_SYSTEM_LAYOUT.gap }, children: [
9729
10408
  alertButton,
@@ -9731,32 +10410,13 @@ var SGnbSystem = /* @__PURE__ */ react.forwardRef(function SGnbSystem2({
9731
10410
  "span",
9732
10411
  {
9733
10412
  className: "h-sd-16 w-px shrink-0",
9734
- style: { backgroundColor: c.divider },
10413
+ style: { backgroundColor: dividerColor },
9735
10414
  "aria-hidden": true
9736
10415
  }
9737
10416
  ),
9738
- setting && /* @__PURE__ */ jsxRuntime.jsx(
9739
- SystemButton,
9740
- {
9741
- color,
9742
- icon: "setting",
9743
- label: settingLabel,
9744
- ariaLabel: settingLabel,
9745
- paddingX: GNB_SYSTEM_LAYOUT.settingPaddingX,
9746
- stretch: !alert2,
9747
- onClick: setting.onClick
9748
- }
9749
- )
10417
+ settingButton
9750
10418
  ] }),
9751
- account && /* @__PURE__ */ jsxRuntime.jsx(
9752
- SSystemActionButton,
9753
- {
9754
- color,
9755
- type: "account",
9756
- label: account.label,
9757
- onClick: account.onClick
9758
- }
9759
- )
10419
+ accountButton
9760
10420
  ] })
9761
10421
  ]
9762
10422
  }
@@ -10377,19 +11037,19 @@ var STEPPER_VERTICAL_COLORS = {
10377
11037
  errorBadge: "#FB4444"
10378
11038
  };
10379
11039
  var ERROR_TOOLTIP_MESSAGE = "\uD655\uC778\uC774 \uD544\uC694\uD55C \uD56D\uBAA9\uC774 \uC788\uC2B5\uB2C8\uB2E4.";
10380
- function getItemValue(item3, index) {
10381
- return item3.value ?? String(index + 1);
11040
+ function getItemValue(item4, index) {
11041
+ return item4.value ?? String(index + 1);
10382
11042
  }
10383
11043
  function groupAdjacentItems(items) {
10384
11044
  return items.reduce(
10385
- (groups, item3, index) => {
10386
- const currentGroup = item3.group;
11045
+ (groups, item4, index) => {
11046
+ const currentGroup = item4.group;
10387
11047
  const previous = groups[groups.length - 1];
10388
11048
  if (currentGroup && previous?.group === currentGroup) {
10389
- previous.items.push(item3);
11049
+ previous.items.push(item4);
10390
11050
  return groups;
10391
11051
  }
10392
- groups.push({ group: currentGroup, startIndex: index, items: [item3] });
11052
+ groups.push({ group: currentGroup, startIndex: index, items: [item4] });
10393
11053
  return groups;
10394
11054
  },
10395
11055
  []
@@ -10419,15 +11079,15 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10419
11079
  const verticalItemRefs = react.useRef([]);
10420
11080
  const activeIndex = Math.max(
10421
11081
  0,
10422
- items.findIndex((item3, index) => getItemValue(item3, index) === value)
11082
+ items.findIndex((item4, index) => getItemValue(item4, index) === value)
10423
11083
  );
10424
11084
  const lastCompletedIndex = items.reduce(
10425
- (lastIndex, item3, index) => item3.completed === true ? index : lastIndex,
11085
+ (lastIndex, item4, index) => item4.completed === true ? index : lastIndex,
10426
11086
  -1
10427
11087
  );
10428
11088
  const resolvedClickableIndex = lastCompletedIndex + 1;
10429
11089
  const [visitedMaxIndex, setVisitedMaxIndex] = react.useState(activeIndex);
10430
- const firstErrorIndex = items.findIndex((item3) => item3.error === true);
11090
+ const firstErrorIndex = items.findIndex((item4) => item4.error === true);
10431
11091
  react.useImperativeHandle(
10432
11092
  ref,
10433
11093
  () => ({
@@ -10455,18 +11115,18 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10455
11115
  transform: `translateY(${activeItem.offsetTop}px)`
10456
11116
  });
10457
11117
  }, [activeIndex, vertical, items]);
10458
- const getState = (item3, index) => {
11118
+ const getState = (item4, index) => {
10459
11119
  if (index === activeIndex) return "active";
10460
- if (item3.completed != null) return item3.completed ? "completed" : "default";
11120
+ if (item4.completed != null) return item4.completed ? "completed" : "default";
10461
11121
  return "default";
10462
11122
  };
10463
- const emitValueChange = (item3, index) => {
10464
- onValueChange?.(getItemValue(item3, index), item3, index);
11123
+ const emitValueChange = (item4, index) => {
11124
+ onValueChange?.(getItemValue(item4, index), item4, index);
10465
11125
  };
10466
11126
  const isWithinClickableIndex = (index) => index <= resolvedClickableIndex;
10467
- const renderStepContent = (item3, index, options = {}) => {
11127
+ const renderStepContent = (item4, index, options = {}) => {
10468
11128
  const { isVertical = false, roleListItem = true, hovered = false } = options;
10469
- const state2 = getState(item3, index);
11129
+ const state2 = getState(item4, index);
10470
11130
  const isHorizontalCompleted = !isVertical && state2 === "completed";
10471
11131
  const isVerticalCompleted = isVertical && state2 === "completed";
10472
11132
  const isVerticalLastActive = isVertical && state2 === "default" && index === visitedMaxIndex;
@@ -10541,12 +11201,12 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10541
11201
  children: showsCheckIcon ? /* @__PURE__ */ jsxRuntime.jsx(SIcon, { name: "check", size: STEPPER_LAYOUT.sequenceIcon, color: "currentColor" }) : index + 1
10542
11202
  }
10543
11203
  ),
10544
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: item3.label })
11204
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: item4.label })
10545
11205
  ]
10546
11206
  }
10547
11207
  );
10548
11208
  };
10549
- const renderClickableStepContent = (item3, index, isVertical = false) => {
11209
+ const renderClickableStepContent = (item4, index, isVertical = false) => {
10550
11210
  const isDisabled = !isWithinClickableIndex(index);
10551
11211
  return /* @__PURE__ */ jsxRuntime.jsx(
10552
11212
  "button",
@@ -10559,9 +11219,9 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10559
11219
  ),
10560
11220
  style: { font: "inherit", color: "inherit" },
10561
11221
  onClick: () => {
10562
- if (!isDisabled) emitValueChange(item3, index);
11222
+ if (!isDisabled) emitValueChange(item4, index);
10563
11223
  },
10564
- children: renderStepContent(item3, index, { isVertical, roleListItem: false })
11224
+ children: renderStepContent(item4, index, { isVertical, roleListItem: false })
10565
11225
  }
10566
11226
  );
10567
11227
  };
@@ -10620,10 +11280,10 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10620
11280
  children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap", children: group.group })
10621
11281
  }
10622
11282
  ),
10623
- group.items.map((item3, itemIndex) => {
11283
+ group.items.map((item4, itemIndex) => {
10624
11284
  const index = group.startIndex + itemIndex;
10625
- const state2 = getState(item3, index);
10626
- const itemValue = getItemValue(item3, index);
11285
+ const state2 = getState(item4, index);
11286
+ const itemValue = getItemValue(item4, index);
10627
11287
  const canClickItem = isClickable && isWithinClickableIndex(index);
10628
11288
  const isDisabled = !canClickItem;
10629
11289
  const isHovered = hoveredIndex === index && canClickItem && state2 !== "active";
@@ -10641,12 +11301,12 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10641
11301
  const handleMouseLeave = () => {
10642
11302
  setHoveredIndex((current) => current === index ? null : current);
10643
11303
  };
10644
- const stepContent = renderStepContent(item3, index, {
11304
+ const stepContent = renderStepContent(item4, index, {
10645
11305
  isVertical: true,
10646
11306
  roleListItem: false,
10647
11307
  hovered: isHovered
10648
11308
  });
10649
- const errorBadge = item3.error ? /* @__PURE__ */ jsxRuntime.jsx(
11309
+ const errorBadge = item4.error ? /* @__PURE__ */ jsxRuntime.jsx(
10650
11310
  "span",
10651
11311
  {
10652
11312
  "aria-hidden": "true",
@@ -10661,7 +11321,7 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10661
11321
  ) : null;
10662
11322
  const isTooltipHovered = tooltipHoverValue === itemValue;
10663
11323
  const isCustomTooltipOpen = customTooltipOpen && index === firstErrorIndex;
10664
- const showTooltip = item3.error === true && (isTooltipHovered || isCustomTooltipOpen);
11324
+ const showTooltip = item4.error === true && (isTooltipHovered || isCustomTooltipOpen);
10665
11325
  const handleTooltipMouseEnter = () => setTooltipHoverValue(itemValue);
10666
11326
  const handleTooltipMouseLeave = () => {
10667
11327
  setTooltipHoverValue((current) => current === itemValue ? null : current);
@@ -10685,7 +11345,7 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10685
11345
  onMouseEnter: handleTooltipMouseEnter,
10686
11346
  onMouseLeave: handleTooltipMouseLeave,
10687
11347
  onClick: isClickable ? () => {
10688
- if (!isDisabled) emitValueChange(item3, index);
11348
+ if (!isDisabled) emitValueChange(item4, index);
10689
11349
  } : void 0,
10690
11350
  children: [
10691
11351
  stepContent,
@@ -10717,13 +11377,13 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10717
11377
  {
10718
11378
  type: "button",
10719
11379
  disabled: isDisabled,
10720
- "aria-label": item3.label,
11380
+ "aria-label": item4.label,
10721
11381
  className: cn(
10722
11382
  "absolute inset-0 z-[2] m-0 border-0 bg-transparent p-0 text-left outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-(--sys-color-border-accent)",
10723
11383
  isDisabled ? "cursor-default" : "cursor-pointer"
10724
11384
  ),
10725
11385
  onClick: () => {
10726
- if (!isDisabled) emitValueChange(item3, index);
11386
+ if (!isDisabled) emitValueChange(item4, index);
10727
11387
  }
10728
11388
  }
10729
11389
  ),
@@ -10774,9 +11434,9 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10774
11434
  lineHeight: config.lineHeight,
10775
11435
  ...style
10776
11436
  },
10777
- children: items.map((item3, index) => {
10778
- const state2 = getState(item3, index);
10779
- const content = isClickable ? /* @__PURE__ */ jsxRuntime.jsx("span", { role: "listitem", "aria-current": state2 === "active" ? "step" : void 0, children: renderClickableStepContent(item3, index) }) : renderStepContent(item3, index);
11437
+ children: items.map((item4, index) => {
11438
+ const state2 = getState(item4, index);
11439
+ const content = isClickable ? /* @__PURE__ */ jsxRuntime.jsx("span", { role: "listitem", "aria-current": state2 === "active" ? "step" : void 0, children: renderClickableStepContent(item4, index) }) : renderStepContent(item4, index);
10780
11440
  return /* @__PURE__ */ jsxRuntime.jsxs(
10781
11441
  "span",
10782
11442
  {
@@ -10810,7 +11470,7 @@ var SStepper = /* @__PURE__ */ react.forwardRef(function SStepper2({
10810
11470
  )
10811
11471
  ]
10812
11472
  },
10813
- getItemValue(item3, index)
11473
+ getItemValue(item4, index)
10814
11474
  );
10815
11475
  })
10816
11476
  }
@@ -11361,7 +12021,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
11361
12021
  const selectedAnchorIndex = react.useMemo(() => {
11362
12022
  if (selected.length === 0) return -1;
11363
12023
  const selectedSet = new Set(selected);
11364
- return navigableItems.findIndex((item3) => item3.value != null && selectedSet.has(item3.value));
12024
+ return navigableItems.findIndex((item4) => item4.value != null && selectedSet.has(item4.value));
11365
12025
  }, [navigableItems, selected]);
11366
12026
  selectedAnchorRef.current = selectedAnchorIndex;
11367
12027
  const triggerText = (() => {
@@ -11655,7 +12315,7 @@ var SSelectImpl = /* @__PURE__ */ react.forwardRef(function SSelect({
11655
12315
  setFocusedIndex(-1);
11656
12316
  return;
11657
12317
  }
11658
- const index = navigableItems.findIndex((item3) => item3.key === key);
12318
+ const index = navigableItems.findIndex((item4) => item4.key === key);
11659
12319
  if (index >= 0) setFocusedIndex(index);
11660
12320
  }
11661
12321
  }
@@ -13425,7 +14085,9 @@ function SRadio({
13425
14085
  {
13426
14086
  ...labelInteractiveProps,
13427
14087
  className: cn(
13428
- "inline-flex items-center gap-[8px]",
14088
+ // align-middle: 텍스트 baseline 이 아니라 줄 중앙에 맞춘다 — SCheckbox 와 같은 규칙.
14089
+ // td 처럼 strut(셀 폰트의 줄 상자)이 라디오보다 큰 곳에서 위로 치우치지 않게 한다.
14090
+ "inline-flex items-center gap-(--cmp-radio-gap) align-middle",
13429
14091
  disabled ? "cursor-not-allowed" : "cursor-pointer",
13430
14092
  className
13431
14093
  ),
@@ -13447,17 +14109,21 @@ function SRadio({
13447
14109
  "span",
13448
14110
  {
13449
14111
  className: cn(
13450
- "flex h-[16px] w-[16px] flex-shrink-0 items-center justify-center rounded-full border border-solid border-[color:var(--rd-border)] bg-[var(--rd-bg)]",
13451
- !disabled && !checked && "hover:border-[color:var(--cmp-radio-border-hover)] hover:bg-[var(--cmp-radio-bg-hover)]"
14112
+ "relative flex h-(--cmp-radio-size) w-(--cmp-radio-size) shrink-0 items-center justify-center rounded-(--cmp-radio-radius) border-(length:--cmp-radio-borderWidth) border-solid border-(--rd-border) bg-(--rd-bg)",
14113
+ !disabled && !checked && "hover:border-(--cmp-radio-border-hover) hover:bg-(--cmp-radio-bg-hover)"
13452
14114
  ),
13453
14115
  style: {
13454
14116
  "--rd-bg": disabled ? "var(--cmp-radio-bg-disabled)" : "var(--cmp-radio-bg-default)",
13455
14117
  "--rd-border": disabled ? "var(--cmp-radio-border-disabled)" : checked ? "var(--cmp-radio-border-active)" : "var(--cmp-radio-border-default)"
13456
14118
  },
13457
- children: checked && /* @__PURE__ */ jsxRuntime.jsx(
14119
+ children: checked && // dot 은 반드시 flow 밖(absolute)에 둔다. in-flow 자식으로 넣으면 동그라미(flex 컨테이너)의
14120
+ // 합성 baseline 이 "border-box 하단"에서 "dot 하단"으로 옮겨가고, inline-flex 인 SRadio·
14121
+ // SRadioGroup 의 baseline 까지 따라 움직여 선택할 때마다 줄 상자가 3px 흔들린다
14122
+ // (SKeyValueTable 의 td 처럼 baseline 정렬되는 곳에서 눈에 띈다).
14123
+ /* @__PURE__ */ jsxRuntime.jsx(
13458
14124
  "span",
13459
14125
  {
13460
- className: "h-[10px] w-[10px] rounded-full",
14126
+ className: "absolute top-1/2 left-1/2 h-(--cmp-radio-dot-size) w-(--cmp-radio-dot-size) -translate-x-1/2 -translate-y-1/2 rounded-(--cmp-radio-radius)",
13461
14127
  style: {
13462
14128
  background: disabled ? "var(--cmp-radio-dot-disabled)" : "var(--cmp-radio-dot-default)"
13463
14129
  }
@@ -13468,13 +14134,20 @@ function SRadio({
13468
14134
  label && /* @__PURE__ */ jsxRuntime.jsxs(
13469
14135
  "span",
13470
14136
  {
13471
- className: "grid text-[12px] leading-[20px]",
14137
+ className: "grid",
13472
14138
  style: {
13473
14139
  color: disabled ? "var(--cmp-radio-label-disabled)" : "var(--cmp-radio-label-default)"
13474
14140
  },
13475
14141
  children: [
13476
- /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "invisible font-medium", style: { gridArea: "1 / 1" }, children: label }),
13477
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { gridArea: "1 / 1", fontWeight: checked ? 500 : 400 }, children: label })
14142
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "typo-body-sm-medium invisible", style: { gridArea: "1 / 1" }, children: label }),
14143
+ /* @__PURE__ */ jsxRuntime.jsx(
14144
+ "span",
14145
+ {
14146
+ className: checked ? "typo-body-sm-medium" : "typo-body-sm-default",
14147
+ style: { gridArea: "1 / 1" },
14148
+ children: label
14149
+ }
14150
+ )
13478
14151
  ]
13479
14152
  }
13480
14153
  )
@@ -13497,7 +14170,8 @@ function SRadioGroup({
13497
14170
  {
13498
14171
  role: "radiogroup",
13499
14172
  className: cn(
13500
- "inline-flex",
14173
+ // align-middle 은 SRadio 와 같은 이유 — inline 문맥(td 등)에서 줄 중앙에 맞춘다.
14174
+ "inline-flex align-middle",
13501
14175
  direction === "vertical" ? "flex-col gap-[var(--cmp-radio-group-gap-vertical)]" : "flex-row gap-[var(--cmp-radio-group-gap-horizontal)]",
13502
14176
  className
13503
14177
  ),
@@ -13733,7 +14407,7 @@ function SCalendar({
13733
14407
  }) }),
13734
14408
  legend.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
13735
14409
  /* @__PURE__ */ jsxRuntime.jsx(SDivider, {}),
13736
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center justify-center gap-x-[var(--cmp-datepicker-calendar-legend-group-gap)] gap-y-[4px] text-[11px] leading-[18px]", children: legend.map((item3) => /* @__PURE__ */ jsxRuntime.jsxs(
14410
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center justify-center gap-x-[var(--cmp-datepicker-calendar-legend-group-gap)] gap-y-[4px] text-[11px] leading-[18px]", children: legend.map((item4) => /* @__PURE__ */ jsxRuntime.jsxs(
13737
14411
  "span",
13738
14412
  {
13739
14413
  className: "inline-flex items-center gap-[var(--cmp-datepicker-calendar-legend-gap)]",
@@ -13742,14 +14416,14 @@ function SCalendar({
13742
14416
  "span",
13743
14417
  {
13744
14418
  className: "h-[var(--cmp-datepicker-calendar-day-dot-size)] w-[var(--cmp-datepicker-calendar-day-dot-size)] rounded-full",
13745
- style: { backgroundColor: resolveColor(item3.color) },
14419
+ style: { backgroundColor: resolveColor(item4.color) },
13746
14420
  "aria-hidden": true
13747
14421
  }
13748
14422
  ),
13749
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: item3.label })
14423
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: item4.label })
13750
14424
  ]
13751
14425
  },
13752
- `${item3.color}|${item3.label}`
14426
+ `${item4.color}|${item4.label}`
13753
14427
  )) })
13754
14428
  ] })
13755
14429
  ]
@@ -16871,19 +17545,19 @@ function EditorToolbarBar({
16871
17545
  closeLinkEditor();
16872
17546
  };
16873
17547
  const visible = [];
16874
- for (const item3 of items) {
16875
- if (item3 === "image" && !onImageUpload) continue;
16876
- if (item3 === "|" && (visible.length === 0 || visible[visible.length - 1] === "|")) continue;
16877
- visible.push(item3);
17548
+ for (const item4 of items) {
17549
+ if (item4 === "image" && !onImageUpload) continue;
17550
+ if (item4 === "|" && (visible.length === 0 || visible[visible.length - 1] === "|")) continue;
17551
+ visible.push(item4);
16878
17552
  }
16879
17553
  while (visible.length > 0 && visible[visible.length - 1] === "|") visible.pop();
16880
17554
  const groups = [[]];
16881
- for (const item3 of visible) {
16882
- if (item3 === "|") groups.push([]);
16883
- else groups[groups.length - 1].push(item3);
17555
+ for (const item4 of visible) {
17556
+ if (item4 === "|") groups.push([]);
17557
+ else groups[groups.length - 1].push(item4);
16884
17558
  }
16885
- const node = (item3) => {
16886
- switch (item3) {
17559
+ const node = (item4) => {
17560
+ switch (item4) {
16887
17561
  case "heading":
16888
17562
  return /* @__PURE__ */ jsxRuntime.jsxs(RDropdown2__namespace.Root, { modal: !insideModal, children: [
16889
17563
  /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxRuntime.jsxs(
@@ -16918,7 +17592,7 @@ function EditorToolbarBar({
16918
17592
  level
16919
17593
  ))
16920
17594
  ] }) })
16921
- ] }, item3);
17595
+ ] }, item4);
16922
17596
  case "fontSize":
16923
17597
  return /* @__PURE__ */ jsxRuntime.jsxs(RDropdown2__namespace.Root, { modal: !insideModal, children: [
16924
17598
  /* @__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: [
@@ -16957,7 +17631,7 @@ function EditorToolbarBar({
16957
17631
  ]
16958
17632
  }
16959
17633
  ) })
16960
- ] }, item3);
17634
+ ] }, item4);
16961
17635
  case "bold":
16962
17636
  return /* @__PURE__ */ jsxRuntime.jsx(
16963
17637
  ToolbarButton,
@@ -16969,7 +17643,7 @@ function EditorToolbarBar({
16969
17643
  onClick: () => chain()?.toggleBold().run(),
16970
17644
  children: /* @__PURE__ */ jsxRuntime.jsx(IconBold, { size: ICON_SIZE })
16971
17645
  },
16972
- item3
17646
+ item4
16973
17647
  );
16974
17648
  case "italic":
16975
17649
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -16982,7 +17656,7 @@ function EditorToolbarBar({
16982
17656
  onClick: () => chain()?.toggleItalic().run(),
16983
17657
  children: /* @__PURE__ */ jsxRuntime.jsx(IconItalic, { size: ICON_SIZE })
16984
17658
  },
16985
- item3
17659
+ item4
16986
17660
  );
16987
17661
  case "underline":
16988
17662
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -16995,7 +17669,7 @@ function EditorToolbarBar({
16995
17669
  onClick: () => chain()?.toggleUnderline().run(),
16996
17670
  children: /* @__PURE__ */ jsxRuntime.jsx(IconUnderline, { size: ICON_SIZE })
16997
17671
  },
16998
- item3
17672
+ item4
16999
17673
  );
17000
17674
  case "strike":
17001
17675
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17008,7 +17682,7 @@ function EditorToolbarBar({
17008
17682
  onClick: () => chain()?.toggleStrike().run(),
17009
17683
  children: /* @__PURE__ */ jsxRuntime.jsx(IconStrike, { size: ICON_SIZE })
17010
17684
  },
17011
- item3
17685
+ item4
17012
17686
  );
17013
17687
  case "code":
17014
17688
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17021,7 +17695,7 @@ function EditorToolbarBar({
17021
17695
  onClick: () => chain()?.toggleCode().run(),
17022
17696
  children: /* @__PURE__ */ jsxRuntime.jsx(IconCode, { size: ICON_SIZE })
17023
17697
  },
17024
- item3
17698
+ item4
17025
17699
  );
17026
17700
  case "color":
17027
17701
  if (mobile)
@@ -17033,7 +17707,7 @@ function EditorToolbarBar({
17033
17707
  onClick: () => setMobileView("color"),
17034
17708
  children: /* @__PURE__ */ jsxRuntime.jsx(ColorIndicator, { color: off ? "currentColor" : activeColor, children: /* @__PURE__ */ jsxRuntime.jsx(IconTextColor, { size: ICON_SIZE }) })
17035
17709
  },
17036
- item3
17710
+ item4
17037
17711
  );
17038
17712
  return /* @__PURE__ */ jsxRuntime.jsxs(RDropdown2__namespace.Root, { modal: !insideModal, children: [
17039
17713
  /* @__PURE__ */ jsxRuntime.jsx(RDropdown2__namespace.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { label: "\uAE00\uC790\uC0C9", disabled: off, children: /* @__PURE__ */ jsxRuntime.jsx(ColorIndicator, { color: off ? "currentColor" : activeColor, children: /* @__PURE__ */ jsxRuntime.jsx(IconTextColor, { size: ICON_SIZE }) }) }) }),
@@ -17048,7 +17722,7 @@ function EditorToolbarBar({
17048
17722
  onClear: clearColor
17049
17723
  }
17050
17724
  ) }) })
17051
- ] }, item3);
17725
+ ] }, item4);
17052
17726
  case "alignLeft":
17053
17727
  return /* @__PURE__ */ jsxRuntime.jsx(
17054
17728
  ToolbarButton,
@@ -17060,7 +17734,7 @@ function EditorToolbarBar({
17060
17734
  onClick: () => chain()?.setTextAlign("left").run(),
17061
17735
  children: /* @__PURE__ */ jsxRuntime.jsx(IconAlignLeft, { size: ICON_SIZE })
17062
17736
  },
17063
- item3
17737
+ item4
17064
17738
  );
17065
17739
  case "alignCenter":
17066
17740
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17073,7 +17747,7 @@ function EditorToolbarBar({
17073
17747
  onClick: () => chain()?.setTextAlign("center").run(),
17074
17748
  children: /* @__PURE__ */ jsxRuntime.jsx(IconAlignCenter, { size: ICON_SIZE })
17075
17749
  },
17076
- item3
17750
+ item4
17077
17751
  );
17078
17752
  case "alignRight":
17079
17753
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17086,7 +17760,7 @@ function EditorToolbarBar({
17086
17760
  onClick: () => chain()?.setTextAlign("right").run(),
17087
17761
  children: /* @__PURE__ */ jsxRuntime.jsx(IconAlignRight, { size: ICON_SIZE })
17088
17762
  },
17089
- item3
17763
+ item4
17090
17764
  );
17091
17765
  case "alignJustify":
17092
17766
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17099,7 +17773,7 @@ function EditorToolbarBar({
17099
17773
  onClick: () => chain()?.setTextAlign("justify").run(),
17100
17774
  children: /* @__PURE__ */ jsxRuntime.jsx(IconAlignJustify, { size: ICON_SIZE })
17101
17775
  },
17102
- item3
17776
+ item4
17103
17777
  );
17104
17778
  case "bulletList":
17105
17779
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17112,7 +17786,7 @@ function EditorToolbarBar({
17112
17786
  onClick: () => chain()?.toggleBulletList().run(),
17113
17787
  children: /* @__PURE__ */ jsxRuntime.jsx(IconBulletList, { size: ICON_SIZE })
17114
17788
  },
17115
- item3
17789
+ item4
17116
17790
  );
17117
17791
  case "orderedList":
17118
17792
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17125,7 +17799,7 @@ function EditorToolbarBar({
17125
17799
  onClick: () => chain()?.toggleOrderedList().run(),
17126
17800
  children: /* @__PURE__ */ jsxRuntime.jsx(IconOrderedList, { size: ICON_SIZE })
17127
17801
  },
17128
- item3
17802
+ item4
17129
17803
  );
17130
17804
  case "taskList":
17131
17805
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17138,7 +17812,7 @@ function EditorToolbarBar({
17138
17812
  onClick: () => chain()?.toggleTaskList().run(),
17139
17813
  children: /* @__PURE__ */ jsxRuntime.jsx(IconTaskList, { size: ICON_SIZE })
17140
17814
  },
17141
- item3
17815
+ item4
17142
17816
  );
17143
17817
  case "list": {
17144
17818
  const ListIcon = state2.orderedList ? IconOrderedList : state2.taskList ? IconTaskList : IconBulletList;
@@ -17183,7 +17857,7 @@ function EditorToolbarBar({
17183
17857
  }
17184
17858
  )
17185
17859
  ] }) })
17186
- ] }, item3);
17860
+ ] }, item4);
17187
17861
  }
17188
17862
  case "blockquote":
17189
17863
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17196,7 +17870,7 @@ function EditorToolbarBar({
17196
17870
  onClick: () => chain()?.toggleBlockquote().run(),
17197
17871
  children: /* @__PURE__ */ jsxRuntime.jsx(IconBlockquote, { size: ICON_SIZE })
17198
17872
  },
17199
- item3
17873
+ item4
17200
17874
  );
17201
17875
  case "codeBlock":
17202
17876
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17209,7 +17883,7 @@ function EditorToolbarBar({
17209
17883
  onClick: () => chain()?.toggleCodeBlock().run(),
17210
17884
  children: /* @__PURE__ */ jsxRuntime.jsx(IconCodeBlock, { size: ICON_SIZE })
17211
17885
  },
17212
- item3
17886
+ item4
17213
17887
  );
17214
17888
  case "horizontalRule":
17215
17889
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17220,7 +17894,7 @@ function EditorToolbarBar({
17220
17894
  onClick: () => chain()?.setHorizontalRule().run(),
17221
17895
  children: /* @__PURE__ */ jsxRuntime.jsx(IconHorizontalRule, { size: ICON_SIZE })
17222
17896
  },
17223
- item3
17897
+ item4
17224
17898
  );
17225
17899
  case "link":
17226
17900
  if (mobile)
@@ -17233,7 +17907,7 @@ function EditorToolbarBar({
17233
17907
  onClick: () => setMobileView("link"),
17234
17908
  children: /* @__PURE__ */ jsxRuntime.jsx(IconLink, { size: ICON_SIZE })
17235
17909
  },
17236
- item3
17910
+ item4
17237
17911
  );
17238
17912
  return /* @__PURE__ */ jsxRuntime.jsxs(RPopover11__namespace.Root, { open: linkOpen, onOpenChange: setLinkOpen, children: [
17239
17913
  /* @__PURE__ */ jsxRuntime.jsx(RPopover11__namespace.Trigger, { asChild: true, disabled: off, children: /* @__PURE__ */ jsxRuntime.jsx(ToolbarButton, { label: "\uB9C1\uD06C", active: state2.link, disabled: off, children: /* @__PURE__ */ jsxRuntime.jsx(IconLink, { size: ICON_SIZE }) }) }),
@@ -17258,7 +17932,7 @@ function EditorToolbarBar({
17258
17932
  )
17259
17933
  }
17260
17934
  ) })
17261
- ] }, item3);
17935
+ ] }, item4);
17262
17936
  case "image":
17263
17937
  return /* @__PURE__ */ jsxRuntime.jsxs(
17264
17938
  ToolbarButton,
@@ -17272,7 +17946,7 @@ function EditorToolbarBar({
17272
17946
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[12px] leading-[20px]", children: "\uC774\uBBF8\uC9C0" })
17273
17947
  ]
17274
17948
  },
17275
- item3
17949
+ item4
17276
17950
  );
17277
17951
  case "table":
17278
17952
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -17393,7 +18067,7 @@ function EditorToolbarBar({
17393
18067
  ] }) })
17394
18068
  ]
17395
18069
  },
17396
- item3
18070
+ item4
17397
18071
  );
17398
18072
  case "undo":
17399
18073
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17404,7 +18078,7 @@ function EditorToolbarBar({
17404
18078
  onClick: () => chain()?.undo().run(),
17405
18079
  children: /* @__PURE__ */ jsxRuntime.jsx(IconUndo, { size: ICON_SIZE })
17406
18080
  },
17407
- item3
18081
+ item4
17408
18082
  );
17409
18083
  case "redo":
17410
18084
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17415,7 +18089,7 @@ function EditorToolbarBar({
17415
18089
  onClick: () => chain()?.redo().run(),
17416
18090
  children: /* @__PURE__ */ jsxRuntime.jsx(IconRedo, { size: ICON_SIZE })
17417
18091
  },
17418
- item3
18092
+ item4
17419
18093
  );
17420
18094
  default:
17421
18095
  return null;
@@ -17996,6 +18670,13 @@ var keywordEntries = (value) => {
17996
18670
  }
17997
18671
  return [];
17998
18672
  };
18673
+ var CSV_PASTE_SEPARATOR = /[,\r\n\t]+/;
18674
+ var newKeywordEntries = (entries3, candidates) => candidates.reduce((acc, raw) => {
18675
+ const next = raw.trim();
18676
+ if (next === "" || entries3.includes(next) || acc.includes(next)) return acc;
18677
+ return [...acc, next];
18678
+ }, []);
18679
+ var withKeywordEntries = (field, current, nextEntries) => field.matchModes ? { keywords: nextEntries, mode: isKeywordValue(current) ? current.mode : "contains" } : nextEntries;
17999
18680
  var isEmptyValue = (value) => {
18000
18681
  if (value == null) return true;
18001
18682
  if (Array.isArray(value)) return value.length === 0 || value.every((v) => v == null || v === "");
@@ -18046,8 +18727,18 @@ var createPeriodValue = (unit, maxRange) => ({
18046
18727
  unit,
18047
18728
  value: getDefaultPeriodInputValue(unit, maxRange)
18048
18729
  });
18730
+ var singleOptionValue = (field) => {
18731
+ if (field.type !== "select" && field.type !== "select-multi") return void 0;
18732
+ const options = field.options ?? [];
18733
+ if (options.length !== 1 || options[0].disabled === true) return void 0;
18734
+ return options[0].value;
18735
+ };
18049
18736
  var resolveFieldDefault = (field) => {
18050
18737
  if (field.defaultValue !== void 0 && isFixedField(field)) return field.defaultValue;
18738
+ if (isFixedField(field)) {
18739
+ const only = singleOptionValue(field);
18740
+ if (only !== void 0) return field.type === "select-multi" ? [only] : only;
18741
+ }
18051
18742
  if (field.type === "datepicker-range") {
18052
18743
  if (!isInlineDateField(field) && !field.required) return void 0;
18053
18744
  const today = todayIso();
@@ -18146,7 +18837,7 @@ var displayValue = (field, value) => {
18146
18837
  if (field.type === "select-multi") {
18147
18838
  const values = toArrayValue(value);
18148
18839
  const selectableValues = (field.options ?? []).filter((option) => !option.disabled).map((option) => option.value);
18149
- if (selectableValues.length > 0 && selectableValues.every((selectableValue) => values.includes(selectableValue))) {
18840
+ if (selectableValues.length > 1 && selectableValues.every((selectableValue) => values.includes(selectableValue))) {
18150
18841
  return "\uC804\uCCB4";
18151
18842
  }
18152
18843
  return formatValueList(values.map((v) => optionLabel(field, v)));
@@ -18210,7 +18901,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
18210
18901
  const prevOpenKeyRef = react.useRef(null);
18211
18902
  const valuesRef = react.useRef(values);
18212
18903
  valuesRef.current = values;
18213
- const lastSearchedValuesRef = react.useRef(values);
18904
+ const lastSearchedValuesRef = react.useRef(null);
18214
18905
  const invalidGroups = react.useMemo(() => {
18215
18906
  const invalid = /* @__PURE__ */ new Set();
18216
18907
  groups.forEach((group, groupIndex) => {
@@ -18228,7 +18919,8 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
18228
18919
  );
18229
18920
  const runSearch = react.useCallback(
18230
18921
  (next) => {
18231
- if (valuesMapEqual(lastSearchedValuesRef.current, next)) return;
18922
+ const last = lastSearchedValuesRef.current;
18923
+ if (last != null && valuesMapEqual(last, next)) return;
18232
18924
  if (!isGroupsValid(next)) return;
18233
18925
  if (!isRequiredSatisfied(next)) return;
18234
18926
  lastSearchedValuesRef.current = next;
@@ -18236,13 +18928,36 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
18236
18928
  },
18237
18929
  [isGroupsValid, isRequiredSatisfied, onSearch]
18238
18930
  );
18931
+ const keywordDraftRef = react.useRef(null);
18932
+ const commitKeywordDraft = react.useCallback(
18933
+ (key) => {
18934
+ const draft = keywordDraftRef.current;
18935
+ keywordDraftRef.current = null;
18936
+ if (draft == null || draft.key !== key) return null;
18937
+ const field = fields.find((f) => f.key === key);
18938
+ if (field == null || field.type !== "keyword" || disabled || field.disabled) return null;
18939
+ const current = valuesRef.current[key];
18940
+ const entries3 = keywordEntries(current);
18941
+ const added = newKeywordEntries(
18942
+ entries3,
18943
+ field.input === "csv" ? draft.text.split(CSV_PASTE_SEPARATOR) : [draft.text]
18944
+ );
18945
+ if (added.length === 0) return null;
18946
+ const nextValue = withKeywordEntries(field, current, [...entries3, ...added]);
18947
+ const next = { ...valuesRef.current, [key]: nextValue };
18948
+ onValueChange?.(next);
18949
+ onFilterChange?.({ key, value: nextValue, values: next });
18950
+ return next;
18951
+ },
18952
+ [disabled, fields, onFilterChange, onValueChange]
18953
+ );
18239
18954
  react.useEffect(() => {
18240
18955
  const prevKey = prevOpenKeyRef.current;
18241
18956
  if (prevKey != null && prevKey !== openKey) {
18242
- runSearch(valuesRef.current);
18957
+ runSearch(commitKeywordDraft(prevKey) ?? valuesRef.current);
18243
18958
  }
18244
18959
  prevOpenKeyRef.current = openKey;
18245
- }, [openKey, runSearch]);
18960
+ }, [commitKeywordDraft, openKey, runSearch]);
18246
18961
  react.useEffect(() => {
18247
18962
  fields.forEach((field) => {
18248
18963
  if (isEmptyValue(values[field.key])) dismissedRef.current.delete(field.key);
@@ -18341,6 +19056,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
18341
19056
  runSearch(emitValue(key, def !== void 0 ? def : null));
18342
19057
  };
18343
19058
  const removeField = (key) => {
19059
+ keywordDraftRef.current = null;
18344
19060
  const nextValues = emitValue(key, null);
18345
19061
  dismissedRef.current.add(key);
18346
19062
  setInternalActiveKeys((current) => current.filter((activeKey) => activeKey !== key));
@@ -18353,6 +19069,7 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
18353
19069
  return acc;
18354
19070
  }, {});
18355
19071
  dismissedRef.current.clear();
19072
+ keywordDraftRef.current = null;
18356
19073
  setInternalActiveKeys(fields.filter(isFixedField).map((field) => field.key));
18357
19074
  setOpenKey(null);
18358
19075
  onValueChange?.(next);
@@ -18620,6 +19337,9 @@ var SChipFilter = /* @__PURE__ */ react.forwardRef(function SChipFilter2({
18620
19337
  disabled: disabled || currentOpenField.disabled,
18621
19338
  onValueChange: (next) => emitValue(currentOpenField.key, next),
18622
19339
  onValueCommit: (next) => emitValueAndSearch(currentOpenField.key, next),
19340
+ onDraftChange: (text) => {
19341
+ keywordDraftRef.current = text.trim() === "" ? null : { key: currentOpenField.key, text };
19342
+ },
18623
19343
  onClose: () => setOpenKey(null)
18624
19344
  }
18625
19345
  )
@@ -18771,6 +19491,7 @@ function EditorPanel({
18771
19491
  disabled,
18772
19492
  onValueChange,
18773
19493
  onValueCommit,
19494
+ onDraftChange,
18774
19495
  onClose
18775
19496
  }) {
18776
19497
  const wrapsInPaddedTop = field.type === "datepicker-day" || field.type === "datepicker-range" || field.type === "datepicker-statistics";
@@ -18792,7 +19513,8 @@ function EditorPanel({
18792
19513
  value,
18793
19514
  disabled,
18794
19515
  onValueChange,
18795
- onValueCommit
19516
+ onValueCommit,
19517
+ onDraftChange
18796
19518
  }
18797
19519
  ) }) : /* @__PURE__ */ jsxRuntime.jsx(
18798
19520
  FilterEditor,
@@ -18801,7 +19523,8 @@ function EditorPanel({
18801
19523
  value,
18802
19524
  disabled,
18803
19525
  onValueChange,
18804
- onValueCommit
19526
+ onValueCommit,
19527
+ onDraftChange
18805
19528
  }
18806
19529
  ),
18807
19530
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -18854,7 +19577,8 @@ function FilterEditor({
18854
19577
  value,
18855
19578
  disabled,
18856
19579
  onValueChange,
18857
- onValueCommit
19580
+ onValueCommit,
19581
+ onDraftChange
18858
19582
  }) {
18859
19583
  if (field.type === "datepicker-statistics") {
18860
19584
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -18900,7 +19624,8 @@ function FilterEditor({
18900
19624
  value: isKeywordValue(value) ? value : keywordEntries(value),
18901
19625
  disabled,
18902
19626
  onValueChange,
18903
- onValueCommit
19627
+ onValueCommit,
19628
+ onDraftChange
18904
19629
  }
18905
19630
  );
18906
19631
  }
@@ -19223,7 +19948,6 @@ function InlineDatePresetFilter({
19223
19948
  ) : badge)
19224
19949
  ] });
19225
19950
  }
19226
- var CSV_PASTE_SEPARATOR = /[,\r\n\t]+/;
19227
19951
  var MATCH_MODE_OPTIONS = [
19228
19952
  { value: "contains", label: "\uD3EC\uD568" },
19229
19953
  { value: "exact", label: "\uC77C\uCE58" }
@@ -19237,14 +19961,19 @@ function KeywordEditor({
19237
19961
  value,
19238
19962
  disabled,
19239
19963
  onValueChange,
19240
- onValueCommit
19964
+ onValueCommit,
19965
+ onDraftChange
19241
19966
  }) {
19242
19967
  const entries3 = keywordEntries(value);
19243
- const [draft, setDraft] = react.useState("");
19968
+ const [draftText, setDraftText] = react.useState("");
19244
19969
  const [mode, setMode] = react.useState(
19245
19970
  isKeywordValue(value) ? value.mode : "contains"
19246
19971
  );
19247
19972
  const inputRef = react.useRef(null);
19973
+ const setDraft = (next) => {
19974
+ setDraftText(next);
19975
+ onDraftChange(next);
19976
+ };
19248
19977
  react.useEffect(() => {
19249
19978
  if (disabled) return;
19250
19979
  inputRef.current?.focus();
@@ -19259,11 +19988,7 @@ function KeywordEditor({
19259
19988
  setMode(next);
19260
19989
  emit3(entries3, next);
19261
19990
  };
19262
- const newEntries = (candidates) => candidates.reduce((acc, raw) => {
19263
- const next = raw.trim();
19264
- if (next === "" || entries3.includes(next) || acc.includes(next)) return acc;
19265
- return [...acc, next];
19266
- }, []);
19991
+ const newEntries = (candidates) => newKeywordEntries(entries3, candidates);
19267
19992
  const addEntry = (raw) => {
19268
19993
  const added = newEntries([raw]);
19269
19994
  if (added.length === 0) {
@@ -19289,7 +20014,7 @@ function KeywordEditor({
19289
20014
  const text = event.clipboardData.getData("text");
19290
20015
  if (!CSV_PASTE_SEPARATOR.test(text)) return;
19291
20016
  event.preventDefault();
19292
- const added = newEntries((draft + text).split(CSV_PASTE_SEPARATOR));
20017
+ const added = newEntries((draftText + text).split(CSV_PASTE_SEPARATOR));
19293
20018
  if (added.length > 0) commit([...entries3, ...added]);
19294
20019
  setDraft("");
19295
20020
  };
@@ -19300,7 +20025,7 @@ function KeywordEditor({
19300
20025
  if (event.key === "Enter") {
19301
20026
  if (event.nativeEvent.isComposing) return;
19302
20027
  event.preventDefault();
19303
- addEntry(draft);
20028
+ addEntry(draftText);
19304
20029
  }
19305
20030
  };
19306
20031
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -19332,7 +20057,7 @@ function KeywordEditor({
19332
20057
  "input",
19333
20058
  {
19334
20059
  ref: inputRef,
19335
- value: draft,
20060
+ value: draftText,
19336
20061
  disabled,
19337
20062
  placeholder: field.placeholder ?? (field.input === "csv" ? "\uB2E4\uC911 \uD0A4\uC6CC\uB4DC\uB294 \uCF64\uB9C8(,)\uB85C \uAD6C\uBD84" : "\uC785\uB825 \uD6C4 Enter\uB85C \uCD94\uAC00"),
19338
20063
  onChange: (event) => changeDraft(event.target.value),
@@ -19935,8 +20660,8 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
19935
20660
  onMouseDown: (e) => e.preventDefault(),
19936
20661
  children: [
19937
20662
  loading2 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "s-chip-input__suggestions-empty p-sd-12 text-center text-12 leading-sd-20 text-(--color-grey-65)", children: "\uBD88\uB7EC\uC624\uB294 \uC911..." }),
19938
- !effectiveAutocomplete ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-sd-8 px-sd-12 py-sd-6", children: items.map((item3, i) => {
19939
- const selected = values.includes(item3);
20663
+ !effectiveAutocomplete ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-sd-8 px-sd-12 py-sd-6", children: items.map((item4, i) => {
20664
+ const selected = values.includes(item4);
19940
20665
  const active = i === activeIndex && !selected;
19941
20666
  return /* @__PURE__ */ jsxRuntime.jsx(
19942
20667
  "div",
@@ -19947,14 +20672,14 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
19947
20672
  style: active ? { outline: "2px solid var(--color-border-accent)", outlineOffset: 1 } : void 0,
19948
20673
  onMouseDown: (e) => {
19949
20674
  e.preventDefault();
19950
- if (!selected) addChip(item3);
20675
+ if (!selected) addChip(item4);
19951
20676
  },
19952
- children: /* @__PURE__ */ jsxRuntime.jsx(SChip2, { value: item3, disabled: selected, editable: false, showRemove: false })
20677
+ children: /* @__PURE__ */ jsxRuntime.jsx(SChip2, { value: item4, disabled: selected, editable: false, showRemove: false })
19953
20678
  },
19954
- item3
20679
+ item4
19955
20680
  );
19956
- }) }) : items.map((item3, i) => {
19957
- const selected = values.includes(item3);
20681
+ }) }) : items.map((item4, i) => {
20682
+ const selected = values.includes(item4);
19958
20683
  const active = i === activeIndex && !selected;
19959
20684
  return /* @__PURE__ */ jsxRuntime.jsxs(
19960
20685
  "div",
@@ -19967,10 +20692,10 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
19967
20692
  ),
19968
20693
  onMouseDown: (e) => {
19969
20694
  e.preventDefault();
19970
- if (!selected) addChip(item3);
20695
+ if (!selected) addChip(item4);
19971
20696
  },
19972
20697
  children: [
19973
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item3 }),
20698
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item4 }),
19974
20699
  selected && /* @__PURE__ */ jsxRuntime.jsx(
19975
20700
  SIcon,
19976
20701
  {
@@ -19981,7 +20706,7 @@ var SChipInput = /* @__PURE__ */ react.forwardRef(function SChipInput2({
19981
20706
  )
19982
20707
  ]
19983
20708
  },
19984
- item3
20709
+ item4
19985
20710
  );
19986
20711
  })
19987
20712
  ]
@@ -20365,22 +21090,22 @@ function TimeSelector({
20365
21090
  style: {
20366
21091
  padding: "var(--cmp-timepicker-selector-section-paddingY) var(--cmp-timepicker-selector-section-paddingX)"
20367
21092
  },
20368
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "isolate flex", children: ["AM", "PM"].map((item3, index) => {
20369
- const selected = item3 === meridiem;
21093
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "isolate flex", children: ["AM", "PM"].map((item4, index) => {
21094
+ const selected = item4 === meridiem;
20370
21095
  return /* @__PURE__ */ jsxRuntime.jsx(
20371
21096
  "button",
20372
21097
  {
20373
21098
  type: "button",
20374
- onClick: () => setMeridiem(item3),
21099
+ onClick: () => setMeridiem(item4),
20375
21100
  className: cn(
20376
21101
  "box-border h-[var(--cmp-textinput-sm-height)] w-[61px] cursor-pointer border border-solid bg-white text-center text-[12px] font-medium leading-[20px]",
20377
21102
  index === 0 ? "rounded-l-[var(--cmp-select-sm-radius)]" : "rounded-r-[var(--cmp-select-sm-radius)]",
20378
21103
  index === 0 ? "-mr-px" : "",
20379
21104
  selected ? "z-[1] border-[var(--cmp-timepicker-border-focus)] text-[var(--cmp-timepicker-border-focus)]" : "border-[var(--cmp-timepicker-border-default)] text-[var(--cmp-field-hint-color)]"
20380
21105
  ),
20381
- children: item3 === "AM" ? "\uC624\uC804" : "\uC624\uD6C4"
21106
+ children: item4 === "AM" ? "\uC624\uC804" : "\uC624\uD6C4"
20382
21107
  },
20383
- item3
21108
+ item4
20384
21109
  );
20385
21110
  }) })
20386
21111
  }
@@ -20601,8 +21326,8 @@ function getTimeMinutes(value) {
20601
21326
  }
20602
21327
  function normalizeTimeRangeValue(value, rangeOrder = "strict") {
20603
21328
  if (value == null) return null;
20604
- const normalized = value.map((item3) => {
20605
- const parsed = parseTimeValue(item3);
21329
+ const normalized = value.map((item4) => {
21330
+ const parsed = parseTimeValue(item4);
20606
21331
  return formatTimeValue(parsed.hour, parsed.minute);
20607
21332
  });
20608
21333
  if (rangeOrder === "strict" && getTimeMinutes(normalized[0]) > getTimeMinutes(normalized[1])) {
@@ -20812,21 +21537,21 @@ function RangeTimeSelector({
20812
21537
  style: { gap: "var(--cmp-timepicker-selector-range-heading-gap)" },
20813
21538
  children: [
20814
21539
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-nowrap text-center text-[12px] font-bold leading-[20px] text-[var(--cmp-timepicker-selector-range-heading-color)]", children: title }),
20815
- useMeridiem && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "isolate flex", children: ["AM", "PM"].map((item3, index) => {
20816
- const selected = item3 === getMeridiem(side);
21540
+ useMeridiem && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "isolate flex", children: ["AM", "PM"].map((item4, index) => {
21541
+ const selected = item4 === getMeridiem(side);
20817
21542
  return /* @__PURE__ */ jsxRuntime.jsx(
20818
21543
  "button",
20819
21544
  {
20820
21545
  type: "button",
20821
- onClick: () => setMeridiem(side, item3),
21546
+ onClick: () => setMeridiem(side, item4),
20822
21547
  className: cn(
20823
21548
  "box-border h-[var(--cmp-textinput-sm-height)] w-[61px] cursor-pointer border border-solid bg-white text-center text-[12px] font-medium leading-[20px]",
20824
21549
  index === 0 ? "rounded-l-[var(--cmp-select-sm-radius)] -mr-px" : "rounded-r-[var(--cmp-select-sm-radius)]",
20825
21550
  selected ? "z-[1] border-[var(--cmp-timepicker-border-focus)] text-[var(--cmp-timepicker-border-focus)]" : "border-[var(--cmp-timepicker-border-default)] text-[var(--cmp-field-hint-color)]"
20826
21551
  ),
20827
- children: item3 === "AM" ? "\uC624\uC804" : "\uC624\uD6C4"
21552
+ children: item4 === "AM" ? "\uC624\uC804" : "\uC624\uD6C4"
20828
21553
  },
20829
- item3
21554
+ item4
20830
21555
  );
20831
21556
  }) })
20832
21557
  ]
@@ -21062,6 +21787,11 @@ function STimeRangePicker({
21062
21787
  );
21063
21788
  }
21064
21789
 
21790
+ exports.ACCOUNT_LIST_BOX_ICONS = ACCOUNT_LIST_BOX_ICONS;
21791
+ exports.ACCOUNT_LIST_BOX_ITEM_TONES = ACCOUNT_LIST_BOX_ITEM_TONES;
21792
+ exports.ACCOUNT_LIST_BOX_LABELS = ACCOUNT_LIST_BOX_LABELS;
21793
+ exports.ACCOUNT_LIST_BOX_LAYOUT = ACCOUNT_LIST_BOX_LAYOUT;
21794
+ exports.ACCOUNT_LIST_BOX_TONE_CONFIG = ACCOUNT_LIST_BOX_TONE_CONFIG;
21065
21795
  exports.BADGE_COLORS = BADGE_COLORS;
21066
21796
  exports.BUTTON_COLORS = BUTTON_COLORS;
21067
21797
  exports.BUTTON_SIZES = BUTTON_SIZES;
@@ -21079,11 +21809,14 @@ exports.GNB_RAIL_WIDTH = GNB_RAIL_WIDTH;
21079
21809
  exports.GNB_SYSTEM_COLORS = GNB_SYSTEM_COLORS;
21080
21810
  exports.GNB_SYSTEM_COLOR_CONFIG = GNB_SYSTEM_COLOR_CONFIG;
21081
21811
  exports.GNB_SYSTEM_LAYOUT = GNB_SYSTEM_LAYOUT;
21812
+ exports.GNB_SYSTEM_PLACEMENTS = GNB_SYSTEM_PLACEMENTS;
21813
+ exports.GNB_SYSTEM_TOP_COLOR_CONFIG = GNB_SYSTEM_TOP_COLOR_CONFIG;
21082
21814
  exports.ICONS = ICONS;
21083
21815
  exports.IMAGE_FITS = IMAGE_FITS;
21084
21816
  exports.PAGE_BACKGROUNDS = PAGE_BACKGROUNDS;
21085
21817
  exports.PAGE_CONTENT_HEIGHTS = PAGE_CONTENT_HEIGHTS;
21086
21818
  exports.RangeCalendar = RangeCalendar;
21819
+ exports.SAccountListBox = SAccountListBox;
21087
21820
  exports.SActionModal = SActionModal;
21088
21821
  exports.SBadge = SBadge;
21089
21822
  exports.SBarcodeInput = SBarcodeInput;