sellmate-design-system-react 8.0.0 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3163,6 +3163,7 @@ var SDraggableItemView = /* @__PURE__ */ forwardRef(
3163
3163
  bordered,
3164
3164
  selected,
3165
3165
  dense,
3166
+ size,
3166
3167
  dragging,
3167
3168
  disabled,
3168
3169
  hovered,
@@ -3176,6 +3177,8 @@ var SDraggableItemView = /* @__PURE__ */ forwardRef(
3176
3177
  const supportingTextNode = renderSlot(supportingText, renderState);
3177
3178
  const hasSupportingText = supportingTextNode != null && supportingTextNode !== "";
3178
3179
  const trailingNode = renderSlot(trailing, renderState);
3180
+ const titleTypo = size === "sm" ? selected ? "typo-item-sm-selected" : "typo-item-sm-default" : selected ? "typo-item-md-selected" : "typo-item-md-default";
3181
+ const paddingYClass = dense ? size === "sm" ? "py-(--cmp-listDraggableItem-paddingY-sm-dense)" : "py-(--cmp-listDraggableItem-paddingY-md-dense)" : size === "sm" ? "py-(--cmp-listDraggableItem-paddingY-sm-normal)" : "py-(--cmp-listDraggableItem-paddingY-md-normal)";
3179
3182
  return /* @__PURE__ */ jsxs(
3180
3183
  "div",
3181
3184
  {
@@ -3183,10 +3186,12 @@ var SDraggableItemView = /* @__PURE__ */ forwardRef(
3183
3186
  "aria-disabled": disabled || void 0,
3184
3187
  "data-dragging": dragging || void 0,
3185
3188
  className: cn(
3186
- "relative flex w-full items-center gap-(--cmp-listDraggableItem-gap) overflow-hidden px-(--cmp-listDraggableItem-paddingX) text-[12px] leading-[20px]",
3187
- disabled ? "bg-(--cmp-listDraggableItem-bg-default) font-medium text-(--sys-color-disabled-text)" : selected ? "bg-(--cmp-listDraggableItem-bg-selected) font-bold text-(--cmp-listDraggableItem-text-selected)" : "bg-(--cmp-listDraggableItem-bg-default) font-medium text-(--cmp-listDraggableItem-text-default)",
3189
+ "relative flex w-full items-center gap-(--cmp-listDraggableItem-gap) overflow-hidden px-(--cmp-listDraggableItem-paddingX)",
3190
+ titleTypo,
3191
+ disabled ? "bg-(--cmp-listDraggableItem-bg-default) text-(--sys-color-disabled-text)" : selected ? "bg-(--cmp-listDraggableItem-bg-selected) text-(--cmp-listDraggableItem-text-selected)" : "bg-(--cmp-listDraggableItem-bg-default) text-(--cmp-listDraggableItem-text-default)",
3188
3192
  !disabled && !selected && !dragging && "hover:bg-(--cmp-listDraggableItem-bg-hover)",
3189
- hasSupportingText && supportingTextPosition === "bottom" ? dense ? "min-h-[52px] py-(--cmp-listDraggableItem-paddingY-dense)" : "min-h-[60px] py-(--cmp-listDraggableItem-paddingY-normal)" : dense ? "h-[32px] py-(--cmp-listDraggableItem-paddingY-dense)" : "h-[40px] py-(--cmp-listDraggableItem-paddingY-normal)",
3193
+ hasSupportingText && supportingTextPosition === "bottom" ? dense ? "min-h-[52px]" : "min-h-[60px]" : dense ? "h-[32px]" : "h-[40px]",
3194
+ paddingYClass,
3190
3195
  bordered ? cn(
3191
3196
  "rounded-(--cmp-listDraggableItem-radius-bordered) border border-(--cmp-listDraggableItem-border-default)",
3192
3197
  !disabled && !selected && !dragging && "hover:border-(--cmp-listDraggableItem-bordered-border-hover)",
@@ -3244,7 +3249,7 @@ var SDraggableItemView = /* @__PURE__ */ forwardRef(
3244
3249
  "span",
3245
3250
  {
3246
3251
  className: cn(
3247
- "min-w-0 truncate text-[12px] font-normal leading-[20px] text-(--sys-color-fg-secondary)",
3252
+ "typo-body-sm-default min-w-0 truncate text-(--sys-color-fg-secondary)",
3248
3253
  supportingTextPosition === "right" && "flex-1"
3249
3254
  ),
3250
3255
  children: supportingTextNode
@@ -3272,6 +3277,7 @@ var SDraggableItemImpl = /* @__PURE__ */ forwardRef(function SDraggableItem({
3272
3277
  selected = false,
3273
3278
  dragging = false,
3274
3279
  dense = false,
3280
+ size = "sm",
3275
3281
  disabled = false,
3276
3282
  dragOverlay = true,
3277
3283
  dragOverlayOpacity = 0.75,
@@ -3343,6 +3349,7 @@ var SDraggableItemImpl = /* @__PURE__ */ forwardRef(function SDraggableItem({
3343
3349
  bordered,
3344
3350
  selected,
3345
3351
  dense,
3352
+ size,
3346
3353
  dragging: dragging || overlayVisible,
3347
3354
  disabled,
3348
3355
  hovered,
@@ -3377,6 +3384,7 @@ var SDraggableItemImpl = /* @__PURE__ */ forwardRef(function SDraggableItem({
3377
3384
  bordered,
3378
3385
  selected,
3379
3386
  dense,
3387
+ size,
3380
3388
  dragging: true,
3381
3389
  disabled,
3382
3390
  hovered: true,
@@ -3728,6 +3736,7 @@ var SExpansionItem = /* @__PURE__ */ forwardRef(
3728
3736
  interaction,
3729
3737
  accentStripe = false,
3730
3738
  dense = false,
3739
+ size = "sm",
3731
3740
  disabled = false,
3732
3741
  onToggle,
3733
3742
  className,
@@ -3743,6 +3752,7 @@ var SExpansionItem = /* @__PURE__ */ forwardRef(
3743
3752
  const hasChevronInteraction = interaction === "chevron";
3744
3753
  const showInteractionChevron = hasChevronInteraction && !disabled && (isSelected || hovered);
3745
3754
  const interactionChevronColor = isSelected ? "var(--sys-color-fg-brand)" : "var(--sys-color-fg-quaternary)";
3755
+ const titleTypo = size === "sm" ? isExpanded ? "typo-item-sm-selected" : "typo-item-sm-default" : isExpanded ? "typo-item-md-selected" : "typo-item-md-default";
3746
3756
  const reportExpandedDescendant = useCallback(
3747
3757
  (delta) => {
3748
3758
  setExpandedDescendantCount((current) => Math.max(0, current + delta));
@@ -3800,7 +3810,8 @@ var SExpansionItem = /* @__PURE__ */ forwardRef(
3800
3810
  onToggle?.(next, event);
3801
3811
  },
3802
3812
  className: cn(
3803
- "group/expansion-item-button flex w-full cursor-pointer items-center justify-between border-0 text-left text-[14px] font-bold leading-[24px] text-(--cmp-listExpansionItem-title-text-default) focus-visible:outline focus-visible:outline-2 focus-visible:outline-(--sys-color-border-accent) disabled:cursor-not-allowed disabled:text-(--sys-color-disabled-text)",
3813
+ "group/expansion-item-button flex w-full cursor-pointer items-center justify-between border-0 text-left text-(--cmp-listExpansionItem-title-text-default) focus-visible:outline focus-visible:outline-2 focus-visible:outline-(--sys-color-border-accent) disabled:cursor-not-allowed disabled:text-(--sys-color-disabled-text)",
3814
+ titleTypo,
3804
3815
  isExpanded && "border-b border-(--cmp-listExpansionItem-title-border)",
3805
3816
  hasChevronInteraction ? "hover:bg-(--sys-color-bg-neutralBright)" : !isExpanded && "hover:bg-(--cmp-listExpansionItem-title-bg-hover)",
3806
3817
  hasSupportingText && supportingTextPosition === "bottom" ? dense ? "min-h-[52px] py-(--cmp-listExpansionItem-title-paddingY-dense)" : "min-h-[60px] py-(--cmp-listExpansionItem-title-paddingY-normal)" : dense ? "h-[32px] py-(--cmp-listExpansionItem-title-paddingY-dense)" : "h-[40px] py-(--cmp-listExpansionItem-title-paddingY-normal)",
@@ -3837,7 +3848,7 @@ var SExpansionItem = /* @__PURE__ */ forwardRef(
3837
3848
  "span",
3838
3849
  {
3839
3850
  className: cn(
3840
- "min-w-0 truncate text-[12px] font-normal leading-[20px] text-(--sys-color-fg-secondary)",
3851
+ "typo-body-sm-default min-w-0 truncate text-(--sys-color-fg-secondary)",
3841
3852
  supportingTextPosition === "right" && "flex-1"
3842
3853
  ),
3843
3854
  children: supportingText
@@ -3881,6 +3892,7 @@ var SListItemImpl = /* @__PURE__ */ forwardRef(function SListItem({
3881
3892
  interaction,
3882
3893
  accentStripe = false,
3883
3894
  dense = false,
3895
+ size = "sm",
3884
3896
  disabled = false,
3885
3897
  className,
3886
3898
  onMouseEnter,
@@ -3899,6 +3911,7 @@ var SListItemImpl = /* @__PURE__ */ forwardRef(function SListItem({
3899
3911
  const hasChevronInteraction = interaction === "chevron";
3900
3912
  const showInteractionChevron = hasChevronInteraction && isInteractive && (isSelected || hovered);
3901
3913
  const interactionChevronColor = isSelected ? "var(--sys-color-fg-brand)" : "var(--sys-color-fg-quaternary)";
3914
+ const titleTypo = size === "sm" ? isSelected ? "typo-item-sm-selected" : "typo-item-sm-default" : isSelected ? "typo-item-md-selected" : "typo-item-md-default";
3902
3915
  const handleMouseEnter = (event) => {
3903
3916
  if (isInteractive) setHovered(true);
3904
3917
  onMouseEnter?.(event);
@@ -3915,7 +3928,8 @@ var SListItemImpl = /* @__PURE__ */ forwardRef(function SListItem({
3915
3928
  onMouseEnter: handleMouseEnter,
3916
3929
  onMouseLeave: handleMouseLeave,
3917
3930
  className: cn(
3918
- "group/list-item relative flex w-full items-center justify-between bg-(--cmp-listItem-bg-default) text-left text-[14px] font-bold leading-[24px] text-(--cmp-listItem-text-default)",
3931
+ "group/list-item relative flex w-full items-center justify-between bg-(--cmp-listItem-bg-default) text-left text-(--cmp-listItem-text-default)",
3932
+ titleTypo,
3919
3933
  disabled ? "pointer-events-none cursor-not-allowed text-(--sys-color-disabled-text)" : isSelected ? cn(
3920
3934
  "cursor-pointer text-(--cmp-listItem-text-selected)",
3921
3935
  "bg-(--cmp-listItem-bg-selected)"
@@ -3956,7 +3970,7 @@ var SListItemImpl = /* @__PURE__ */ forwardRef(function SListItem({
3956
3970
  "span",
3957
3971
  {
3958
3972
  className: cn(
3959
- "min-w-0 truncate text-[12px] font-normal leading-[20px] text-(--sys-color-fg-secondary)",
3973
+ "typo-body-sm-default min-w-0 truncate text-(--sys-color-fg-secondary)",
3960
3974
  supportingTextPosition === "right" && "flex-1"
3961
3975
  ),
3962
3976
  children: supportingTextNode
@@ -7029,6 +7043,8 @@ function SLoadingModal({
7029
7043
  );
7030
7044
  }
7031
7045
  var CLOSE_ANIMATION_DURATION2 = 300;
7046
+ var RESIZE_KEY_STEP = { normal: 10, large: 50 };
7047
+ var RESIZE_HIT_WIDTH = "calc(var(--cmp-splitter-border-width) + var(--cmp-splitter-border-padding) * 2)";
7032
7048
  function toPx(value, percentBase) {
7033
7049
  if (typeof value === "number") return value;
7034
7050
  if (typeof value !== "string") return void 0;
@@ -7066,6 +7082,7 @@ function SDrawer({
7066
7082
  resizable = false,
7067
7083
  minWidth,
7068
7084
  maxWidth,
7085
+ onWidthChange,
7069
7086
  footerLeft,
7070
7087
  button,
7071
7088
  children,
@@ -7078,11 +7095,16 @@ function SDrawer({
7078
7095
  const [portalContainer, setPortalContainer] = useState(null);
7079
7096
  const backdropPointerDownRef = useRef(false);
7080
7097
  const contentRef = useRef(null);
7098
+ const panelRef = useRef(null);
7081
7099
  const stackRegistrationRef = useRef(null);
7082
7100
  const resizeCleanupRef = useRef(null);
7083
- const resizeStateRef = useRef(null);
7084
7101
  const [layerIndex, setLayerIndex] = useState(null);
7085
7102
  const [currentWidth, setCurrentWidth] = useState(width);
7103
+ const [resizing, setResizing] = useState(false);
7104
+ const [measuredWidth, setMeasuredWidth] = useState(null);
7105
+ const [viewportWidth, setViewportWidth] = useState(
7106
+ () => typeof window === "undefined" ? void 0 : window.innerWidth
7107
+ );
7086
7108
  useEffect(() => {
7087
7109
  setCurrentWidth(width);
7088
7110
  }, [width]);
@@ -7098,6 +7120,22 @@ function SDrawer({
7098
7120
  useEffect(() => {
7099
7121
  return () => resizeCleanupRef.current?.();
7100
7122
  }, []);
7123
+ useEffect(() => {
7124
+ if (!rendered) return;
7125
+ const sync = () => setViewportWidth(window.innerWidth);
7126
+ sync();
7127
+ window.addEventListener("resize", sync);
7128
+ return () => window.removeEventListener("resize", sync);
7129
+ }, [rendered]);
7130
+ useEffect(() => {
7131
+ const panel = panelRef.current;
7132
+ if (!resizable || !rendered || !panel || typeof ResizeObserver === "undefined") return;
7133
+ const observer = new ResizeObserver(
7134
+ () => setMeasuredWidth(Math.round(panel.getBoundingClientRect().width))
7135
+ );
7136
+ observer.observe(panel);
7137
+ return () => observer.disconnect();
7138
+ }, [resizable, rendered]);
7101
7139
  useEffect(() => {
7102
7140
  if (!open) {
7103
7141
  setEntered(false);
@@ -7139,41 +7177,80 @@ function SDrawer({
7139
7177
  }
7140
7178
  onOpenChange?.(false);
7141
7179
  };
7180
+ const resizeBounds = () => {
7181
+ const limit = viewportWidth;
7182
+ if (limit === void 0) return { min: void 0, max: void 0 };
7183
+ const min = toPx(minWidth, limit);
7184
+ const max = toPx(maxWidth, limit);
7185
+ return {
7186
+ min: min === void 0 ? void 0 : Math.min(min, limit),
7187
+ max: max === void 0 ? limit : Math.min(max, limit)
7188
+ };
7189
+ };
7190
+ const commitWidth = (next, startWidth) => {
7191
+ const { min, max } = resizeBounds();
7192
+ const clamped = Math.round(clamp3(next, min, max));
7193
+ setCurrentWidth(clamped);
7194
+ if (clamped !== Math.round(startWidth)) onWidthChange?.(clamped);
7195
+ };
7142
7196
  const handleResizeStart = (event) => {
7197
+ if (typeof document === "undefined") return;
7198
+ const panel = panelRef.current;
7199
+ if (!panel) return;
7143
7200
  event.preventDefault();
7144
7201
  event.stopPropagation();
7145
- const panel = contentRef.current?.querySelector("[data-s-drawer-panel]");
7146
- if (!panel) return;
7147
- resizeStateRef.current = {
7148
- startX: event.clientX,
7149
- startWidth: panel.getBoundingClientRect().width,
7150
- minWidth: toPx(minWidth, window.innerWidth),
7151
- maxWidth: toPx(maxWidth, window.innerWidth)
7152
- };
7202
+ event.currentTarget.focus();
7203
+ const startX = event.clientX;
7204
+ const startWidth = panel.getBoundingClientRect().width;
7205
+ const { min, max } = resizeBounds();
7206
+ let latest = startWidth;
7207
+ const { body } = document;
7208
+ const previousCursor = body.style.cursor;
7209
+ const previousUserSelect = body.style.userSelect;
7153
7210
  const onMove = (moveEvent) => {
7154
- const resizeState = resizeStateRef.current;
7155
- if (!resizeState) return;
7156
- const nextWidth = resizeState.startWidth + resizeState.startX - moveEvent.clientX;
7157
- setCurrentWidth(clamp3(nextWidth, resizeState.minWidth, resizeState.maxWidth));
7211
+ latest = Math.round(clamp3(startWidth + (startX - moveEvent.clientX), min, max));
7212
+ setCurrentWidth(latest);
7158
7213
  };
7159
- resizeCleanupRef.current?.();
7160
- const previousCursor = document.body.style.cursor;
7161
- const previousUserSelect = document.body.style.userSelect;
7162
7214
  const cleanupResize = () => {
7163
- resizeStateRef.current = null;
7164
- document.body.style.cursor = previousCursor;
7165
- document.body.style.userSelect = previousUserSelect;
7215
+ body.style.cursor = previousCursor;
7216
+ body.style.userSelect = previousUserSelect;
7166
7217
  document.removeEventListener("mousemove", onMove);
7167
7218
  document.removeEventListener("mouseup", cleanupResize);
7168
7219
  resizeCleanupRef.current = null;
7220
+ setResizing(false);
7221
+ commitWidth(latest, startWidth);
7169
7222
  };
7223
+ resizeCleanupRef.current?.();
7170
7224
  resizeCleanupRef.current = cleanupResize;
7171
- document.body.style.cursor = "col-resize";
7172
- document.body.style.userSelect = "none";
7225
+ body.style.cursor = "col-resize";
7226
+ body.style.userSelect = "none";
7173
7227
  document.addEventListener("mousemove", onMove);
7174
7228
  document.addEventListener("mouseup", cleanupResize);
7229
+ setResizing(true);
7230
+ };
7231
+ const handleResizeKeyDown = (event) => {
7232
+ const panel = panelRef.current;
7233
+ if (!panel) return;
7234
+ const startWidth = panel.getBoundingClientRect().width;
7235
+ const { min, max } = resizeBounds();
7236
+ const step = RESIZE_KEY_STEP[event.shiftKey ? "large" : "normal"];
7237
+ let next = null;
7238
+ if (event.key === "ArrowLeft") next = startWidth + step;
7239
+ else if (event.key === "ArrowRight") next = startWidth - step;
7240
+ else if (event.key === "Home" && min !== void 0) next = min;
7241
+ else if (event.key === "End" && max !== void 0) next = max;
7242
+ if (next === null) return;
7243
+ event.preventDefault();
7244
+ commitWidth(next, startWidth);
7175
7245
  };
7176
7246
  const modalHost = getModalHost();
7247
+ const resizeValueNow = measuredWidth ?? (typeof currentWidth === "number" ? Math.round(currentWidth) : void 0);
7248
+ const { min: resizeMinPx, max: resizeMaxPx } = resizeBounds();
7249
+ const resizeValueMin = resizeMinPx === void 0 ? void 0 : Math.round(resizeMinPx);
7250
+ const resizeValueMax = resizeMaxPx === void 0 ? void 0 : Math.round(resizeMaxPx);
7251
+ const appliedWidth = typeof currentWidth === "number" && viewportWidth !== void 0 ? Math.min(currentWidth, viewportWidth) : currentWidth;
7252
+ const appliedMinWidth = resizeMinPx ?? minWidth;
7253
+ const appliedMaxWidth = resizeMaxPx ?? maxWidth;
7177
7254
  return /* @__PURE__ */ jsx(RDialog.Root, { open, onOpenChange, children: /* @__PURE__ */ jsx(RDialog.Portal, { container: modalHost, forceMount: rendered ? true : void 0, children: /* @__PURE__ */ jsxs("div", { className: "pointer-events-none absolute inset-0", style: { zIndex: layerIndex ?? 0 }, children: [
7178
7255
  /* @__PURE__ */ jsx(
7179
7256
  RDialog.Overlay,
@@ -7215,6 +7292,7 @@ function SDrawer({
7215
7292
  /* @__PURE__ */ jsxs(
7216
7293
  "div",
7217
7294
  {
7295
+ ref: panelRef,
7218
7296
  className: cn(
7219
7297
  "pointer-events-auto relative flex h-full max-w-full translate-x-full flex-col overflow-hidden bg-[var(--cmp-drawer-bg)] shadow-[var(--shadow-overlay)] transition-transform duration-300 ease-out data-[state=open]:translate-x-0 data-[state=closed]:translate-x-full",
7220
7298
  shaking && "animate-drawer-shake",
@@ -7222,20 +7300,45 @@ function SDrawer({
7222
7300
  ),
7223
7301
  "data-s-drawer-panel": true,
7224
7302
  "data-state": open && entered ? "open" : "closed",
7225
- style: { width: currentWidth, minWidth, maxWidth, ...style },
7303
+ style: {
7304
+ width: appliedWidth,
7305
+ minWidth: appliedMinWidth,
7306
+ maxWidth: appliedMaxWidth,
7307
+ ...style
7308
+ },
7226
7309
  onAnimationEnd: (event) => {
7227
7310
  if (event.animationName === "drawer-shake") setShaking(false);
7228
7311
  },
7229
7312
  children: [
7230
- resizable && /* @__PURE__ */ jsx(
7231
- "button",
7313
+ resizable && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
7314
+ "div",
7232
7315
  {
7233
- type: "button",
7316
+ role: "separator",
7317
+ "aria-orientation": "vertical",
7234
7318
  "aria-label": "Drawer \uB108\uBE44 \uC870\uC808",
7235
- className: "absolute inset-y-0 left-0 z-[1] w-[8px] -translate-x-1/2 cursor-col-resize touch-none border-0 bg-transparent p-0",
7236
- onMouseDown: handleResizeStart
7319
+ "aria-valuenow": resizeValueNow,
7320
+ "aria-valuemin": resizeValueMin,
7321
+ "aria-valuemax": resizeValueMax,
7322
+ "aria-valuetext": resizeValueNow === void 0 ? void 0 : `${resizeValueNow}px`,
7323
+ tabIndex: 0,
7324
+ onMouseDown: handleResizeStart,
7325
+ onKeyDown: handleResizeKeyDown,
7326
+ className: "group absolute inset-y-0 left-0 z-[1] flex cursor-col-resize touch-none justify-start outline-none",
7327
+ style: { width: RESIZE_HIT_WIDTH },
7328
+ children: /* @__PURE__ */ jsx(
7329
+ "span",
7330
+ {
7331
+ "aria-hidden": true,
7332
+ className: cn(
7333
+ // 평상시엔 자리만 잡고 칠하지 않는다 — 색이 붙는 것 자체가 조절 가능하다는 신호다.
7334
+ "w-(--cmp-splitter-border-width) transition-colors",
7335
+ "group-hover:bg-(--cmp-splitter-border-color) group-focus-visible:bg-(--cmp-splitter-border-color)",
7336
+ resizing && "bg-(--cmp-splitter-border-color)"
7337
+ )
7338
+ }
7339
+ )
7237
7340
  }
7238
- ),
7341
+ ) }),
7239
7342
  /* @__PURE__ */ jsx(
7240
7343
  SOverlayHeader,
7241
7344
  {
@@ -7908,8 +8011,11 @@ var SGnb = /* @__PURE__ */ forwardRef(function SGnb2({
7908
8011
  onLauncherClick,
7909
8012
  logo,
7910
8013
  topContent,
8014
+ railTop,
7911
8015
  railFooter,
8016
+ menuTop,
7912
8017
  menuFooter,
8018
+ foldedTop,
7913
8019
  foldedFooter,
7914
8020
  resizable = false,
7915
8021
  menuWidth: menuWidthProp,
@@ -8418,6 +8524,7 @@ var SGnb = /* @__PURE__ */ forwardRef(function SGnb2({
8418
8524
  ] })
8419
8525
  }
8420
8526
  ),
8527
+ railFolded && foldedTop && /* @__PURE__ */ jsx("div", { className: "mt-[24px] flex shrink-0 items-center justify-center", children: foldedTop }),
8421
8528
  /* @__PURE__ */ jsxs(
8422
8529
  "div",
8423
8530
  {
@@ -8435,9 +8542,9 @@ var SGnb = /* @__PURE__ */ forwardRef(function SGnb2({
8435
8542
  transition: `transform ${GNB_FOLD_MS}ms ease-out, ${hideAfterSlide(folded)}`
8436
8543
  },
8437
8544
  children: [
8438
- useRail && // 레일 컬럼 — 스크롤되는 아이템 목록(nav) 하단 고정 footer 를 한 컬럼에 담는다.
8439
- // footer 내비게이션이 아니므로 nav(landmark) 밖에 두고, 컬럼 폭·구분선·배경은 이 래퍼가
8440
- // 전체 높이에 걸쳐 책임진다(그래야 footer 자리까지 배경·오른쪽 선이 이어진다).
8545
+ useRail && // 레일 컬럼 — 스크롤되는 아이템 목록(nav) 가운데 두고 위아래에 고정 슬롯(top/footer)을 붙인다.
8546
+ // 슬롯은 내비게이션이 아니므로 nav(landmark) 밖에 두고, 컬럼 폭·구분선·배경은 이 래퍼가
8547
+ // 전체 높이에 걸쳐 책임진다(그래야 슬롯 자리까지 배경·오른쪽 선이 이어진다).
8441
8548
  /* @__PURE__ */ jsxs(
8442
8549
  "div",
8443
8550
  {
@@ -8448,6 +8555,7 @@ var SGnb = /* @__PURE__ */ forwardRef(function SGnb2({
8448
8555
  backgroundColor: C.panelBg
8449
8556
  },
8450
8557
  children: [
8558
+ railTop && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: railTop }),
8451
8559
  /* @__PURE__ */ jsx(
8452
8560
  "nav",
8453
8561
  {
@@ -8475,6 +8583,7 @@ var SGnb = /* @__PURE__ */ forwardRef(function SGnb2({
8475
8583
  borderRight: isFull ? rightBorder : void 0
8476
8584
  },
8477
8585
  children: [
8586
+ menuTop && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: menuTop }),
8478
8587
  /* @__PURE__ */ jsx(
8479
8588
  "nav",
8480
8589
  {