@olundot/ui 0.18.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -186,8 +186,61 @@ import * as React from "react";
186
186
  import { cva } from "class-variance-authority";
187
187
  import { Loader2 } from "lucide-react";
188
188
  import { Slot } from "radix-ui";
189
+
190
+ // src/components/ui/action-variants.ts
191
+ var actionPaint = {
192
+ // = Button `primary`
193
+ filledPrimary: "border-[var(--primary)] bg-[var(--primary)] text-[var(--primary-fg)] hover:bg-[var(--primary-hover)] hover:border-[var(--primary-hover)]",
194
+ // = IconButton `subtle`; the transparent 1px border keeps Button's box model
195
+ filledNeutral: "border-transparent bg-[var(--bg-inset)] text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground",
196
+ // = Button `danger`
197
+ filledDanger: "border-[var(--error)] bg-[var(--error)] text-[var(--error-contrast)] hover:bg-[var(--error-hover)] hover:border-[var(--error-hover)]",
198
+ // = Button `secondary`
199
+ outlineNeutral: "border-[var(--border-subtle)] bg-[var(--bg-surface)] text-foreground hover:border-[var(--border)] hover:bg-[var(--action-hover)]",
200
+ // = Button and IconButton `ghost`
201
+ ghostNeutral: "border-transparent bg-transparent text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground"
202
+ };
203
+ var actionAxisVariants = {
204
+ appearance: { filled: "", outline: "", ghost: "" },
205
+ tone: { primary: "", neutral: "", danger: "" }
206
+ };
207
+ var actionCompoundVariants = [
208
+ { appearance: "filled", tone: "primary", className: actionPaint.filledPrimary },
209
+ { appearance: "filled", tone: "neutral", className: actionPaint.filledNeutral },
210
+ { appearance: "filled", tone: "danger", className: actionPaint.filledDanger },
211
+ { appearance: "outline", tone: "neutral", className: actionPaint.outlineNeutral },
212
+ { appearance: "ghost", tone: "neutral", className: actionPaint.ghostNeutral }
213
+ ];
214
+ function resolveActionStyle(appearance, tone, fallback) {
215
+ const resolvedAppearance = appearance ?? fallback;
216
+ return {
217
+ appearance: resolvedAppearance,
218
+ tone: tone ?? (resolvedAppearance === "filled" ? "primary" : "neutral")
219
+ };
220
+ }
221
+
222
+ // src/components/ui/button.tsx
189
223
  import { jsx, jsxs } from "react/jsx-runtime";
190
- var buttonVariants = cva(
224
+ var buttonSizeMd = "h-[32px] gap-[6px] px-pad-default-x text-body-sm [&_svg]:size-[16px]";
225
+ var buttonSizes = {
226
+ // Cross-control height map: Button sm/md/lg match field controls sm/md/lg (30/32/36px).
227
+ // Height comes from h-* alone — no vertical padding (py-12 inside h-32 left a 6px content box).
228
+ // xs/sm: invisible ::before stretches the hit area to 44px tall (#69), vertically only so
229
+ // side-by-side buttons never overlap. Its inset is measured from the padding box, inside
230
+ // the 1px border every variant carries: inset = (44 - (height - 2 × 1px)) / 2.
231
+ // IconButton with text reuses these through `buttonSizeClassName`.
232
+ xs: "relative h-[28px] gap-[6px] px-pad-compact-x text-[12px] before:absolute before:inset-x-0 before:-inset-y-[9px] before:content-[''] [&_svg]:size-[14px] [&_svg]:stroke-[1.75]",
233
+ sm: "relative h-[30px] gap-[6px] px-pad-compact-x text-body-sm before:absolute before:inset-x-0 before:-inset-y-[8px] before:content-[''] [&_svg]:size-[16px]",
234
+ md: buttonSizeMd,
235
+ lg: "h-[36px] gap-[var(--space-2)] px-pad-default-x text-[15px] [&_svg]:size-[18px]",
236
+ xl: "h-[40px] gap-[var(--space-2)] px-5 text-[15px] [&_svg]:size-[18px]",
237
+ default: buttonSizeMd,
238
+ /** @deprecated Use IconButton `size="lg"`. */
239
+ icon: "size-[36px] p-0 [&_svg]:size-[18px]",
240
+ /** @deprecated Use IconButton `size="md"`. */
241
+ "icon-xs": "size-[32px] p-0 [&_svg]:size-[14px] [&_svg]:stroke-[1.75]"
242
+ };
243
+ var buttonCva = cva(
191
244
  [
192
245
  "inline-flex cursor-pointer items-center justify-center whitespace-nowrap rounded-[var(--radius-md)] border font-medium",
193
246
  "transition-[background-color,border-color,color,box-shadow,transform] motion-reduce:transition-none",
@@ -199,42 +252,49 @@ var buttonVariants = cva(
199
252
  ].join(" "),
200
253
  {
201
254
  variants: {
255
+ // Legacy single axis, deprecated in 0.19 for `appearance` × `tone` and removed in 0.20.
256
+ // Frozen at 0.18; button-appearance.test.tsx keeps each value equal to its new pair.
202
257
  variant: {
258
+ /** @deprecated Use `appearance="filled" tone="primary"`. */
203
259
  primary: "border-[var(--primary)] bg-[var(--primary)] text-[var(--primary-fg)] hover:bg-[var(--primary-hover)] hover:border-[var(--primary-hover)]",
204
- /** @deprecated Use `secondary` — the single supporting-action family (#58). Removed in the next breaking release. */
260
+ /** @deprecated Use `appearance="outline" tone="neutral"`. */
205
261
  outline: "border-[var(--border)] bg-transparent text-foreground hover:border-[var(--border-strong)] hover:bg-[var(--action-hover)]",
262
+ /** @deprecated Use `appearance="ghost" tone="neutral"`. */
206
263
  ghost: "border-transparent bg-transparent text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground",
264
+ /** @deprecated Use `appearance="filled" tone="danger"`. */
207
265
  danger: "border-[var(--error)] bg-[var(--error)] text-[var(--error-contrast)] hover:bg-[var(--error-hover)] hover:border-[var(--error-hover)]",
266
+ /** @deprecated Use `appearance="filled" tone="danger"`. */
208
267
  emergency: "border-[var(--error)] bg-[var(--error)] text-[var(--error-contrast)] hover:bg-[var(--error-hover)] hover:border-[var(--error-hover)]",
209
- /** @deprecated Use `secondary` (identical styling, #58). Removed in the next breaking release. */
268
+ /** @deprecated Use `appearance="outline" tone="neutral"`. */
210
269
  subtle: "border-[var(--border-subtle)] bg-[var(--bg-surface)] text-foreground hover:border-[var(--border)] hover:bg-[var(--action-hover)]",
270
+ /** @deprecated Use `appearance="filled" tone="primary"`. */
211
271
  default: "border-[var(--primary)] bg-[var(--primary)] text-[var(--primary-fg)] hover:bg-[var(--primary-hover)] hover:border-[var(--primary-hover)]",
272
+ /** @deprecated Use `appearance="filled" tone="danger"`. */
212
273
  destructive: "border-[var(--error)] bg-[var(--error)] text-[var(--error-contrast)] hover:bg-[var(--error-hover)] hover:border-[var(--error-hover)]",
274
+ /** @deprecated Use `appearance="outline" tone="neutral"`. */
213
275
  secondary: "border-[var(--border-subtle)] bg-[var(--bg-surface)] text-foreground hover:border-[var(--border)] hover:bg-[var(--action-hover)]",
276
+ /** @deprecated No replacement on Button; a link component is planned. */
214
277
  link: "border-transparent bg-transparent px-0 text-[var(--accent)] underline-offset-4 hover:underline"
215
278
  },
216
- size: {
217
- // Cross-control height map: Button sm/md/lg match field controls sm/md/lg (30/32/36px).
218
- // Height comes from h-* alone — no vertical padding (py-12 inside h-32 left a 6px content box).
219
- // xs/sm: invisible ::before stretches the hit area to 44px tall (#69), vertically only so
220
- // side-by-side buttons never overlap. Its inset is measured from the padding box, inside
221
- // the 1px border every variant carries: inset = (44 - (height - 2 × 1px)) / 2.
222
- xs: "relative h-[28px] gap-[6px] px-pad-compact-x text-[12px] before:absolute before:inset-x-0 before:-inset-y-[9px] before:content-[''] [&_svg]:size-[14px] [&_svg]:stroke-[1.75]",
223
- sm: "relative h-[30px] gap-[6px] px-pad-compact-x text-body-sm before:absolute before:inset-x-0 before:-inset-y-[8px] before:content-[''] [&_svg]:size-[16px]",
224
- md: "h-[32px] gap-[6px] px-pad-default-x text-body-sm [&_svg]:size-[16px]",
225
- lg: "h-[36px] gap-[var(--space-2)] px-pad-default-x text-[15px] [&_svg]:size-[18px]",
226
- xl: "h-[40px] gap-[var(--space-2)] px-5 text-[15px] [&_svg]:size-[18px]",
227
- default: "h-[32px] gap-[6px] px-pad-default-x text-body-sm [&_svg]:size-[16px]",
228
- icon: "size-[36px] p-0 [&_svg]:size-[18px]",
229
- "icon-xs": "size-[32px] p-0 [&_svg]:size-[14px] [&_svg]:stroke-[1.75]"
230
- }
279
+ ...actionAxisVariants,
280
+ size: buttonSizes
231
281
  },
282
+ compoundVariants: [...actionCompoundVariants],
232
283
  defaultVariants: {
233
284
  variant: "primary",
234
285
  size: "md"
235
286
  }
236
287
  }
237
288
  );
289
+ function buttonVariants(options) {
290
+ if (options?.appearance == null && options?.tone == null) return buttonCva(options);
291
+ return buttonCva({
292
+ ...options,
293
+ ...resolveActionStyle(options.appearance, options.tone, "filled"),
294
+ variant: null
295
+ });
296
+ }
297
+ var buttonSizeClassName = (size) => buttonSizes[size];
238
298
  var footerButtonHitAreaClassName = "relative before:absolute before:inset-x-0 before:-inset-y-[5px] before:content-['']";
239
299
  var Button = React.forwardRef(
240
300
  ({
@@ -247,6 +307,8 @@ var Button = React.forwardRef(
247
307
  trailingIcon: TrailingIcon,
248
308
  type = "button",
249
309
  variant,
310
+ appearance,
311
+ tone,
250
312
  size,
251
313
  style,
252
314
  ...props
@@ -281,7 +343,7 @@ var Button = React.forwardRef(
281
343
  "aria-disabled": isDisabled ? true : void 0,
282
344
  disabled: !asChild ? isDisabled : void 0,
283
345
  type: !asChild ? type : void 0,
284
- className: cn(buttonVariants({ variant, size, className })),
346
+ className: cn(buttonVariants({ variant, appearance, tone, size, className })),
285
347
  style: frozenStyle ? { ...frozenStyle, ...style } : style,
286
348
  ...props,
287
349
  children: [
@@ -947,7 +1009,7 @@ function XIcon({ size }) {
947
1009
  );
948
1010
  }
949
1011
  var Alert = React5.forwardRef(
950
- ({ variant = "info", emphasis, title, children, onDismiss, style, ...rest }, ref) => {
1012
+ ({ variant = "info", emphasis, title: title2, children, onDismiss, style, ...rest }, ref) => {
951
1013
  const weight = emphasis ?? defaultEmphasis(variant);
952
1014
  const strong = weight === "strong";
953
1015
  const fg = SEM_FG[variant];
@@ -980,7 +1042,7 @@ var Alert = React5.forwardRef(
980
1042
  "aria-hidden": "true",
981
1043
  "data-slot": "alert-dot",
982
1044
  style: {
983
- marginTop: title ? 5 : 4,
1045
+ marginTop: title2 ? 5 : 4,
984
1046
  width: 7,
985
1047
  height: 7,
986
1048
  flexShrink: 0,
@@ -990,7 +1052,7 @@ var Alert = React5.forwardRef(
990
1052
  }
991
1053
  ),
992
1054
  /* @__PURE__ */ jsxs5("div", { "data-slot": "alert-content", style: { flex: 1, minWidth: 0 }, children: [
993
- title ? /* @__PURE__ */ jsx5(
1055
+ title2 ? /* @__PURE__ */ jsx5(
994
1056
  "div",
995
1057
  {
996
1058
  "data-slot": "alert-title",
@@ -1001,7 +1063,7 @@ var Alert = React5.forwardRef(
1001
1063
  lineHeight: 1.35,
1002
1064
  color: strong ? fg : "var(--text-primary)"
1003
1065
  },
1004
- children: title
1066
+ children: title2
1005
1067
  }
1006
1068
  ) : null,
1007
1069
  /* @__PURE__ */ jsx5(
@@ -1009,7 +1071,7 @@ var Alert = React5.forwardRef(
1009
1071
  {
1010
1072
  "data-slot": "alert-body",
1011
1073
  style: {
1012
- marginTop: title ? 2 : 0,
1074
+ marginTop: title2 ? 2 : 0,
1013
1075
  fontFamily: "var(--font-sans)",
1014
1076
  fontSize: 12.5,
1015
1077
  lineHeight: 1.45,
@@ -2337,7 +2399,7 @@ var PageHeader = React13.forwardRef(
2337
2399
  className,
2338
2400
  breadcrumb,
2339
2401
  back,
2340
- title,
2402
+ title: title2,
2341
2403
  headingLevel = 1,
2342
2404
  subtitle,
2343
2405
  meta,
@@ -2381,7 +2443,7 @@ var PageHeader = React13.forwardRef(
2381
2443
  {
2382
2444
  "data-slot": "page-header-title",
2383
2445
  className: "max-w-full break-words font-[family-name:var(--font-display)] text-[28px] font-semibold leading-tight text-foreground",
2384
- children: title
2446
+ children: title2
2385
2447
  }
2386
2448
  ),
2387
2449
  subtitle ? /* @__PURE__ */ jsx14(
@@ -2963,7 +3025,7 @@ var tabsListVariants = cva8(
2963
3025
  {
2964
3026
  variant: "line",
2965
3027
  orientation: "vertical",
2966
- className: "border-r border-[var(--border-subtle)] gap-[var(--space-2)] pr-[var(--space-4)]"
3028
+ className: "border-r border-[var(--border-subtle)] gap-[var(--space-2)] pr-[var(--space-4)] max-sm:flex-row max-sm:gap-[var(--space-6)] max-sm:overflow-x-auto max-sm:overflow-y-hidden max-sm:border-r-0 max-sm:border-b max-sm:pr-0"
2967
3029
  },
2968
3030
  {
2969
3031
  variant: "contained",
@@ -3006,9 +3068,24 @@ var tabsTriggerVariants = cva8(
3006
3068
  },
3007
3069
  orientation: {
3008
3070
  horizontal: "",
3009
- vertical: "w-full justify-start data-[state=active]:after:bottom-0 data-[state=active]:after:left-auto data-[state=active]:after:right-[-1px] data-[state=active]:after:top-0 data-[state=active]:after:h-auto data-[state=active]:after:w-[2px]"
3071
+ vertical: "sm:w-full sm:justify-start sm:data-[state=active]:after:bottom-0 sm:data-[state=active]:after:left-auto sm:data-[state=active]:after:right-[calc(-1*(var(--space-4)+1px))] sm:data-[state=active]:after:top-0 sm:data-[state=active]:after:h-auto sm:data-[state=active]:after:w-[2px]"
3010
3072
  }
3011
3073
  },
3074
+ compoundVariants: [
3075
+ // 가로 line 목록은 overflow-y-hidden이라 바깥 ring이 잘린다. 2px 안쪽 여백을 두고 inset-ring으로 안쪽에 그린다.
3076
+ // ring-inset은 쓰지 않는다: 토큰 테마의 --color-inset(bg-inset) 때문에 ring 색이 배경색으로 덮인다.
3077
+ // 트리거 사이는 -mx로 보정해 텍스트 간격은 그대로 두고, 양 끝 트리거는 안쪽 여백을 유지해 ring이 목록 안에 남는다.
3078
+ {
3079
+ variant: "line",
3080
+ orientation: "horizontal",
3081
+ className: "mx-[-2px] px-[2px] first:ml-0 last:mr-0 focus-visible:ring-0 focus-visible:inset-ring-2 focus-visible:inset-ring-[var(--focus-ring)]"
3082
+ },
3083
+ {
3084
+ variant: "line",
3085
+ orientation: "vertical",
3086
+ className: "max-sm:mx-[-2px] max-sm:px-[2px] max-sm:first:ml-0 max-sm:last:mr-0 max-sm:focus-visible:ring-0 max-sm:focus-visible:inset-ring-2 max-sm:focus-visible:inset-ring-[var(--focus-ring)]"
3087
+ }
3088
+ ],
3012
3089
  defaultVariants: {
3013
3090
  variant: "line",
3014
3091
  orientation: "horizontal"
@@ -3435,38 +3512,311 @@ var FormLayout = React19.forwardRef(
3435
3512
  );
3436
3513
  FormLayout.displayName = "FormLayout";
3437
3514
 
3438
- // src/components/ui/form-modal.tsx
3439
- import * as React22 from "react";
3440
-
3441
3515
  // src/components/ui/dialog.tsx
3442
- import * as React21 from "react";
3443
- import { Dialog as DialogPrimitive } from "radix-ui";
3444
- import { X } from "lucide-react";
3445
-
3446
- // src/components/ui/sheet.tsx
3447
- import { XIcon as XIcon2 } from "lucide-react";
3448
- import { Dialog as SheetPrimitive } from "radix-ui";
3516
+ import * as React22 from "react";
3517
+ import { Dialog as DialogPrimitive2 } from "radix-ui";
3449
3518
 
3450
3519
  // src/lib/use-return-focus.ts
3451
3520
  import * as React20 from "react";
3452
3521
  function useReturnFocus() {
3453
3522
  const returnTo = React20.useRef(null);
3454
- const onOpenAutoFocus = React20.useCallback(() => {
3523
+ const onOpenAutoFocus = React20.useCallback((event) => {
3455
3524
  const active = document.activeElement;
3456
- returnTo.current = active instanceof HTMLElement && active !== document.body ? active : null;
3525
+ const content = event?.target instanceof HTMLElement ? event.target : null;
3526
+ const hasTrigger = !!content?.id && Array.from(document.querySelectorAll("[aria-controls]")).some(
3527
+ (element) => element.getAttribute("aria-controls") === content.id
3528
+ );
3529
+ returnTo.current = !hasTrigger && active instanceof HTMLElement && active !== document.body ? active : null;
3457
3530
  }, []);
3458
3531
  const onCloseAutoFocus = React20.useCallback((event) => {
3459
3532
  const target = returnTo.current;
3460
3533
  returnTo.current = null;
3461
3534
  if (!target?.isConnected) return;
3535
+ const active = document.activeElement;
3536
+ if (active instanceof HTMLElement && active !== document.body && active !== target) return;
3462
3537
  event.preventDefault();
3463
3538
  target.focus();
3464
3539
  }, []);
3465
3540
  return { onOpenAutoFocus, onCloseAutoFocus };
3466
3541
  }
3467
3542
 
3468
- // src/components/ui/sheet.tsx
3543
+ // src/components/ui/overlay-close-button.tsx
3544
+ import { X } from "lucide-react";
3545
+ import { Dialog as DialogPrimitive } from "radix-ui";
3546
+
3547
+ // src/components/ui/icon-button.tsx
3548
+ import * as React21 from "react";
3549
+ import { cva as cva9 } from "class-variance-authority";
3469
3550
  import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
3551
+ var iconButtonCva = cva9(
3552
+ [
3553
+ "olun-icon-button relative inline-flex cursor-pointer shrink-0 items-center justify-center before:absolute before:content-['']",
3554
+ "rounded-[var(--radius-md)] border font-medium",
3555
+ "transition-colors motion-reduce:transition-none",
3556
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]",
3557
+ "disabled:cursor-not-allowed disabled:bg-[var(--action-disabled-bg)] disabled:text-text-disabled",
3558
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0"
3559
+ ].join(" "),
3560
+ {
3561
+ variants: {
3562
+ // Legacy single axis, deprecated in 0.19 for `appearance` × `tone` and removed in 0.20.
3563
+ // Frozen at 0.18; button-appearance.test.tsx keeps ghost and subtle equal to their new
3564
+ // pair. `outline` and `danger` differ from the pair they migrate to (outline + neutral =
3565
+ // Button secondary, filled + danger = solid red).
3566
+ variant: {
3567
+ /** @deprecated Use `appearance="ghost" tone="neutral"` (the default). */
3568
+ ghost: "border-transparent bg-transparent text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground",
3569
+ /** @deprecated Use `appearance="outline" tone="neutral"`. */
3570
+ outline: "border-[var(--border-subtle)] bg-[var(--bg-surface)] text-text-secondary hover:border-[var(--border-strong)] hover:bg-[var(--action-hover)] hover:text-foreground",
3571
+ /** @deprecated Use `appearance="filled" tone="neutral"`. */
3572
+ subtle: "border-transparent bg-[var(--bg-inset)] text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground",
3573
+ /** @deprecated Use `appearance="filled" tone="danger"` (solid red, like Button). */
3574
+ danger: "border-transparent bg-[var(--error-bg)] text-[var(--error)] hover:bg-[var(--action-hover)]"
3575
+ },
3576
+ ...actionAxisVariants,
3577
+ // Hit area = 44px on every size. The ::before is absolutely positioned, so its
3578
+ // inset is measured from the padding box — inside the 1px border every variant
3579
+ // carries (transparent or not). Inset = (44 - (size - 2 × 1px border)) / 2.
3580
+ size: {
3581
+ sm: "size-[28px] before:-inset-[9px]",
3582
+ md: "size-[32px] before:-inset-[7px]",
3583
+ lg: "size-[40px] before:-inset-[3px]"
3584
+ },
3585
+ pressed: {
3586
+ true: "",
3587
+ false: ""
3588
+ }
3589
+ },
3590
+ compoundVariants: [
3591
+ ...actionCompoundVariants,
3592
+ {
3593
+ pressed: true,
3594
+ variant: ["ghost", "outline", "subtle"],
3595
+ className: "border-[var(--border-strong)] bg-[var(--action-selected)] text-foreground"
3596
+ },
3597
+ {
3598
+ pressed: true,
3599
+ variant: "danger",
3600
+ className: "border-[var(--error)] bg-[var(--error-bg)] text-[var(--error)]"
3601
+ },
3602
+ {
3603
+ pressed: true,
3604
+ tone: "neutral",
3605
+ className: "border-[var(--border-strong)] bg-[var(--action-selected)] text-foreground"
3606
+ }
3607
+ ],
3608
+ // ghost is the intended default, not a fallback: ghost is reserved for icon-only
3609
+ // actions repeated in rows or chrome (toolbars, headers, table rows), and
3610
+ // IconButton is its canonical entry point (#58). Text actions use Button.
3611
+ defaultVariants: {
3612
+ variant: "ghost",
3613
+ size: "md",
3614
+ pressed: false
3615
+ }
3616
+ }
3617
+ );
3618
+ var axisSizeClassName = {
3619
+ xs: "size-[28px] before:-inset-[9px]",
3620
+ sm: "size-[30px] before:-inset-[8px]",
3621
+ md: "size-[32px] before:-inset-[7px]",
3622
+ lg: "size-[36px] before:-inset-[5px]",
3623
+ xl: "size-[40px] before:-inset-[3px]"
3624
+ };
3625
+ var axisIcon = {
3626
+ xs: { size: 14, strokeWidth: 1.75 },
3627
+ sm: { size: 16, strokeWidth: 2 },
3628
+ md: { size: 16, strokeWidth: 2 },
3629
+ lg: { size: 18, strokeWidth: 2 },
3630
+ xl: { size: 18, strokeWidth: 2 }
3631
+ };
3632
+ function iconButtonVariants(options) {
3633
+ if (options?.appearance == null && options?.tone == null) {
3634
+ return iconButtonCva(options);
3635
+ }
3636
+ const { size, ...rest } = options;
3637
+ const paint = iconButtonCva({
3638
+ ...rest,
3639
+ ...resolveActionStyle(options.appearance, options.tone, "ghost"),
3640
+ variant: null,
3641
+ size: null
3642
+ });
3643
+ return size === null ? paint : `${paint} ${axisSizeClassName[size ?? "md"]}`;
3644
+ }
3645
+ var iconButtonBadgeVariants = cva9(
3646
+ [
3647
+ "pointer-events-none absolute right-0 top-0 inline-flex",
3648
+ "olun-icon-button__badge",
3649
+ "min-h-[var(--space-3)] min-w-[var(--space-3)] translate-x-1/3 -translate-y-1/3",
3650
+ "items-center justify-center gap-[2px] rounded-[var(--radius-full)] px-[3px]",
3651
+ "font-[family-name:var(--font-display)] text-[10px] font-semibold leading-none",
3652
+ "[&:has(svg)]:size-[var(--space-3)] [&:has(svg)]:px-0 [&_svg]:size-[10px]"
3653
+ ].join(" "),
3654
+ {
3655
+ variants: {
3656
+ tone: {
3657
+ info: "bg-[var(--accent-pop)] text-[var(--accent-on-fill)]",
3658
+ error: "bg-[var(--error)] text-[var(--error-contrast)]"
3659
+ }
3660
+ },
3661
+ defaultVariants: {
3662
+ tone: "info"
3663
+ }
3664
+ }
3665
+ );
3666
+ var iconSize2 = {
3667
+ sm: 14,
3668
+ md: 16,
3669
+ lg: 18
3670
+ };
3671
+ var textButtonSize = {
3672
+ sm: "xs",
3673
+ md: "md",
3674
+ lg: "xl"
3675
+ };
3676
+ var iconStrokeWidth = {
3677
+ sm: 2.25,
3678
+ md: 2.25,
3679
+ lg: 1.75
3680
+ };
3681
+ var IconButton = React21.forwardRef(
3682
+ ({
3683
+ className,
3684
+ variant = "ghost",
3685
+ appearance,
3686
+ tone,
3687
+ size = "md",
3688
+ pressed = void 0,
3689
+ icon: Icon,
3690
+ badge,
3691
+ badgeTone = "info",
3692
+ type,
3693
+ title: title2,
3694
+ "aria-label": ariaLabel,
3695
+ "aria-labelledby": ariaLabelledBy,
3696
+ iconPosition = "start",
3697
+ label,
3698
+ children,
3699
+ ...props
3700
+ }, ref) => {
3701
+ const resolvedSize = size ?? "md";
3702
+ const usesAxes = appearance != null || tone != null;
3703
+ const isToggle = pressed !== void 0;
3704
+ const isPressed = pressed === true;
3705
+ const hoverTitle = title2 ?? (typeof ariaLabel === "string" ? ariaLabel : void 0);
3706
+ const text = label ?? children;
3707
+ const hasText = text !== void 0 && text !== null && text !== false;
3708
+ const style = usesAxes ? resolveActionStyle(appearance, tone, "ghost") : void 0;
3709
+ const axisSize = usesAxes ? resolvedSize : void 0;
3710
+ const legacySize = resolvedSize;
3711
+ const textBoxSize = axisSize ?? textButtonSize[legacySize];
3712
+ const icon = /* @__PURE__ */ jsx21(
3713
+ Icon,
3714
+ {
3715
+ "aria-hidden": "true",
3716
+ "data-slot": "icon-button-icon",
3717
+ size: axisSize ? axisIcon[axisSize].size : iconSize2[legacySize],
3718
+ strokeWidth: axisSize ? axisIcon[axisSize].strokeWidth : hasText ? void 0 : iconStrokeWidth[legacySize]
3719
+ }
3720
+ );
3721
+ return /* @__PURE__ */ jsxs20(
3722
+ "button",
3723
+ {
3724
+ ref,
3725
+ ...props,
3726
+ "data-slot": "icon-button",
3727
+ "data-variant": usesAxes ? void 0 : variant,
3728
+ "data-appearance": style?.appearance,
3729
+ "data-tone": style?.tone,
3730
+ "data-size": resolvedSize,
3731
+ "data-icon-position": hasText ? iconPosition : void 0,
3732
+ "data-pressed": isToggle ? String(isPressed) : void 0,
3733
+ "aria-label": ariaLabel,
3734
+ "aria-labelledby": ariaLabelledBy,
3735
+ "aria-pressed": isToggle ? isPressed : void 0,
3736
+ title: hoverTitle,
3737
+ className: cn(
3738
+ iconButtonVariants({
3739
+ variant,
3740
+ appearance,
3741
+ tone,
3742
+ size: hasText ? null : size,
3743
+ pressed: isPressed
3744
+ }),
3745
+ hasText && ["whitespace-nowrap", buttonSizeClassName(textBoxSize)],
3746
+ className
3747
+ ),
3748
+ type: type ?? "button",
3749
+ children: [
3750
+ hasText && iconPosition === "end" ? null : icon,
3751
+ hasText ? text : null,
3752
+ hasText && iconPosition === "end" ? icon : null,
3753
+ badge !== void 0 ? /* @__PURE__ */ jsx21(
3754
+ "span",
3755
+ {
3756
+ "aria-hidden": "true",
3757
+ "data-slot": "icon-button-badge",
3758
+ "data-badge-tone": badgeTone,
3759
+ className: iconButtonBadgeVariants({ tone: badgeTone }),
3760
+ children: badge
3761
+ }
3762
+ ) : null
3763
+ ]
3764
+ }
3765
+ );
3766
+ }
3767
+ );
3768
+ IconButton.displayName = "IconButton";
3769
+
3770
+ // src/components/ui/overlay-close-button.tsx
3771
+ import { jsx as jsx22 } from "react/jsx-runtime";
3772
+ function OverlayCloseButton({
3773
+ label = "\uB2EB\uAE30",
3774
+ className
3775
+ }) {
3776
+ return /* @__PURE__ */ jsx22(DialogPrimitive.Close, { asChild: true, children: /* @__PURE__ */ jsx22(IconButton, { appearance: "ghost", size: "md", icon: X, "aria-label": label, className }) });
3777
+ }
3778
+
3779
+ // src/components/ui/overlay-surface.ts
3780
+ var bottomSheet = {
3781
+ /** Dialog / ConfirmDialog `mobilePresentation="sheet"` below 900px. */
3782
+ dialog: cn(
3783
+ // `!` on the box geometry so consumer width/offset classes (unprefixed or `sm:`) never keep
3784
+ // the centered card inside the < 900px band.
3785
+ "max-[899px]:inset-x-0! max-[899px]:top-auto! max-[899px]:bottom-0! max-[899px]:translate-x-0! max-[899px]:translate-y-0!",
3786
+ "max-[899px]:w-full! max-[899px]:max-w-none!",
3787
+ "max-[899px]:max-h-[85dvh] max-[899px]:overflow-y-auto",
3788
+ "max-[899px]:rounded-b-none max-[899px]:border-x-0",
3789
+ // Home-indicator clearance without touching the consumer's padding (DialogFooter's edge bleed
3790
+ // depends on it): a transparent bottom border as tall as the safe area, painted by the surface.
3791
+ "max-[899px]:border-b-[length:env(safe-area-inset-bottom)] max-[899px]:border-b-transparent",
3792
+ // motion-safe gate (not a motion-reduce override): a later-sorted variant would out-rank it.
3793
+ "max-[899px]:motion-safe:data-[state=open]:animate-[olun-sheet-in-from-bottom_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]",
3794
+ "max-[899px]:motion-safe:data-[state=closed]:animate-[olun-sheet-out-to-bottom_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3795
+ ),
3796
+ /**
3797
+ * SheetContent `mobileSide="bottom"` below 900px. `max-w-none!` overrides the side variant's
3798
+ * `sm:max-w-sm` cap so the bottom sheet spans the full viewport width across the whole
3799
+ * < 900px band (not capped to 24rem).
3800
+ */
3801
+ sheetMobile: "max-[899px]:inset-x-0 max-[899px]:bottom-0 max-[899px]:top-auto max-[899px]:h-auto max-[899px]:w-full max-[899px]:max-w-none! max-[899px]:border-t max-[899px]:border-l-0 max-[899px]:rounded-none",
3802
+ /** SheetDrawer below 900px: `base` for every width, `full` for `width="full"` / expanded. */
3803
+ detail: {
3804
+ base: cn(
3805
+ "max-[899px]:h-[min(85dvh,720px)] max-[899px]:max-h-[85dvh] max-[899px]:w-full max-[899px]:max-w-none",
3806
+ "max-[899px]:rounded-t-[var(--radius-lg)]"
3807
+ ),
3808
+ full: "max-[899px]:h-[100dvh] max-[899px]:max-h-[100dvh] max-[899px]:rounded-none"
3809
+ },
3810
+ /** ActionSheet, a SheetContent `side="bottom"` at every width. */
3811
+ action: cn(
3812
+ "gap-0 max-h-[85dvh] rounded-t-[var(--radius-lg)]",
3813
+ "pb-[env(safe-area-inset-bottom)]"
3814
+ )
3815
+ };
3816
+
3817
+ // src/components/ui/sheet.tsx
3818
+ import { Dialog as SheetPrimitive } from "radix-ui";
3819
+ import { jsx as jsx23, jsxs as jsxs21 } from "react/jsx-runtime";
3470
3820
  var defaultSheetMotionConfig = {
3471
3821
  type: "slide",
3472
3822
  duration: 300,
@@ -3503,22 +3853,22 @@ function getDefaultSheetMotionStyle(style) {
3503
3853
  return getSheetMotionStyle(defaultSheetMotionConfig, style);
3504
3854
  }
3505
3855
  function Sheet({ ...props }) {
3506
- return /* @__PURE__ */ jsx21(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
3856
+ return /* @__PURE__ */ jsx23(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
3507
3857
  }
3508
3858
  function SheetTrigger({
3509
3859
  ...props
3510
3860
  }) {
3511
- return /* @__PURE__ */ jsx21(SheetPrimitive.Trigger, { "data-slot": "sheet-trigger", ...props });
3861
+ return /* @__PURE__ */ jsx23(SheetPrimitive.Trigger, { "data-slot": "sheet-trigger", ...props });
3512
3862
  }
3513
3863
  function SheetClose({
3514
3864
  ...props
3515
3865
  }) {
3516
- return /* @__PURE__ */ jsx21(SheetPrimitive.Close, { "data-slot": "sheet-close", ...props });
3866
+ return /* @__PURE__ */ jsx23(SheetPrimitive.Close, { "data-slot": "sheet-close", ...props });
3517
3867
  }
3518
3868
  function SheetPortal({
3519
3869
  ...props
3520
3870
  }) {
3521
- return /* @__PURE__ */ jsx21(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
3871
+ return /* @__PURE__ */ jsx23(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
3522
3872
  }
3523
3873
  function SheetOverlay({
3524
3874
  className,
@@ -3527,12 +3877,12 @@ function SheetOverlay({
3527
3877
  ...props
3528
3878
  }) {
3529
3879
  const motionConfig = resolveSheetMotionConfig(motion);
3530
- return /* @__PURE__ */ jsx21(
3880
+ return /* @__PURE__ */ jsx23(
3531
3881
  SheetPrimitive.Overlay,
3532
3882
  {
3533
3883
  "data-slot": "sheet-overlay",
3534
3884
  className: cn(
3535
- "fixed inset-0 z-[var(--z-overlay)] bg-[var(--scrim)]",
3885
+ "fixed inset-0 z-[var(--z-modal)] bg-[var(--scrim)]",
3536
3886
  motionConfig && cn(
3537
3887
  "transition-opacity motion-reduce:transition-none",
3538
3888
  "duration-[var(--sheet-motion-duration)]",
@@ -3564,16 +3914,16 @@ function SheetContent({
3564
3914
  const hasSlideMotion = motionConfig && motionConfig.type === "slide";
3565
3915
  const returnFocus = useReturnFocus();
3566
3916
  const handleOpenAutoFocus = (event) => {
3567
- returnFocus.onOpenAutoFocus();
3917
+ returnFocus.onOpenAutoFocus(event);
3568
3918
  onOpenAutoFocus?.(event);
3569
3919
  };
3570
3920
  const handleCloseAutoFocus = (event) => {
3571
3921
  onCloseAutoFocus?.(event);
3572
3922
  if (!event.defaultPrevented) returnFocus.onCloseAutoFocus(event);
3573
3923
  };
3574
- return /* @__PURE__ */ jsxs20(SheetPortal, { children: [
3575
- /* @__PURE__ */ jsx21(SheetOverlay, { motion: motionConfig }),
3576
- /* @__PURE__ */ jsxs20(
3924
+ return /* @__PURE__ */ jsxs21(SheetPortal, { children: [
3925
+ /* @__PURE__ */ jsx23(SheetOverlay, { motion: motionConfig }),
3926
+ /* @__PURE__ */ jsxs21(
3577
3927
  SheetPrimitive.Content,
3578
3928
  {
3579
3929
  "data-slot": "sheet-content",
@@ -3613,9 +3963,7 @@ function SheetContent({
3613
3963
  hasSlideMotion && "max-[899px]:data-[state=open]:animate-[olun-sheet-in-from-top_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] max-[899px]:data-[state=closed]:animate-[olun-sheet-out-to-top_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3614
3964
  ),
3615
3965
  mobileSide === "bottom" && cn(
3616
- // `max-w-none!` overrides the side variant's `sm:max-w-sm` cap so the bottom sheet
3617
- // spans the full viewport width across the whole < 900px band (not capped to 24rem).
3618
- "max-[899px]:inset-x-0 max-[899px]:bottom-0 max-[899px]:top-auto max-[899px]:h-auto max-[899px]:w-full max-[899px]:max-w-none! max-[899px]:border-t max-[899px]:border-l-0 max-[899px]:rounded-none",
3966
+ bottomSheet.sheetMobile,
3619
3967
  hasSlideMotion && "max-[899px]:data-[state=open]:animate-[olun-sheet-in-from-bottom_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] max-[899px]:data-[state=closed]:animate-[olun-sheet-out-to-bottom_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3620
3968
  ),
3621
3969
  className
@@ -3626,17 +3974,14 @@ function SheetContent({
3626
3974
  ...props,
3627
3975
  children: [
3628
3976
  children,
3629
- showCloseButton && /* @__PURE__ */ jsxs20(SheetPrimitive.Close, { className: "absolute top-4 right-4 cursor-pointer rounded-[var(--radius-md)] opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none data-[state=open]:bg-secondary", children: [
3630
- /* @__PURE__ */ jsx21(XIcon2, { className: "size-[16px]" }),
3631
- /* @__PURE__ */ jsx21("span", { className: "sr-only", children: "Close" })
3632
- ] })
3977
+ showCloseButton && /* @__PURE__ */ jsx23(OverlayCloseButton, { className: "absolute top-4 right-4" })
3633
3978
  ]
3634
3979
  }
3635
3980
  )
3636
3981
  ] });
3637
3982
  }
3638
3983
  function SheetBody({ className, ...props }) {
3639
- return /* @__PURE__ */ jsx21(
3984
+ return /* @__PURE__ */ jsx23(
3640
3985
  "div",
3641
3986
  {
3642
3987
  "data-slot": "sheet-body",
@@ -3646,7 +3991,7 @@ function SheetBody({ className, ...props }) {
3646
3991
  );
3647
3992
  }
3648
3993
  function SheetHeader({ className, ...props }) {
3649
- return /* @__PURE__ */ jsx21(
3994
+ return /* @__PURE__ */ jsx23(
3650
3995
  "div",
3651
3996
  {
3652
3997
  "data-slot": "sheet-header",
@@ -3656,7 +4001,7 @@ function SheetHeader({ className, ...props }) {
3656
4001
  );
3657
4002
  }
3658
4003
  function SheetFooter({ className, ...props }) {
3659
- return /* @__PURE__ */ jsx21(
4004
+ return /* @__PURE__ */ jsx23(
3660
4005
  "div",
3661
4006
  {
3662
4007
  "data-slot": "sheet-footer",
@@ -3669,7 +4014,7 @@ function SheetTitle({
3669
4014
  className,
3670
4015
  ...props
3671
4016
  }) {
3672
- return /* @__PURE__ */ jsx21(
4017
+ return /* @__PURE__ */ jsx23(
3673
4018
  SheetPrimitive.Title,
3674
4019
  {
3675
4020
  "data-slot": "sheet-title",
@@ -3682,41 +4027,30 @@ function SheetDescription({
3682
4027
  className,
3683
4028
  ...props
3684
4029
  }) {
3685
- return /* @__PURE__ */ jsx21(
4030
+ return /* @__PURE__ */ jsx23(
3686
4031
  SheetPrimitive.Description,
3687
4032
  {
3688
4033
  "data-slot": "sheet-description",
3689
- className: cn("text-sm text-muted-foreground", className),
4034
+ className: cn("text-sm text-text-secondary", className),
3690
4035
  ...props
3691
4036
  }
3692
4037
  );
3693
4038
  }
3694
4039
 
3695
4040
  // src/components/ui/dialog.tsx
3696
- import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
3697
- var dialogMobileSheetClassName = cn(
3698
- // `!` on the box geometry so consumer width/offset classes (unprefixed or `sm:`) never keep
3699
- // the centered card inside the < 900px band.
3700
- "max-[899px]:inset-x-0! max-[899px]:top-auto! max-[899px]:bottom-0! max-[899px]:translate-x-0! max-[899px]:translate-y-0!",
3701
- "max-[899px]:w-full! max-[899px]:max-w-none!",
3702
- "max-[899px]:max-h-[85dvh] max-[899px]:overflow-y-auto",
3703
- "max-[899px]:rounded-b-none max-[899px]:border-x-0",
3704
- // Home-indicator clearance without touching the consumer's padding (DialogFooter's edge bleed
3705
- // depends on it): a transparent bottom border as tall as the safe area, painted by the surface.
3706
- "max-[899px]:border-b-[length:env(safe-area-inset-bottom)] max-[899px]:border-b-transparent",
3707
- // motion-safe gate (not a motion-reduce override): a later-sorted variant would out-rank it.
3708
- "max-[899px]:motion-safe:data-[state=open]:animate-[olun-sheet-in-from-bottom_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]",
3709
- "max-[899px]:motion-safe:data-[state=closed]:animate-[olun-sheet-out-to-bottom_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3710
- );
4041
+ import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
3711
4042
  function dialogMobileSheetStyle(style) {
3712
4043
  return getDefaultSheetMotionStyle(style);
3713
4044
  }
3714
- var Dialog = DialogPrimitive.Root;
3715
- var DialogTrigger = DialogPrimitive.Trigger;
3716
- var DialogPortal = DialogPrimitive.Portal;
3717
- var DialogClose = DialogPrimitive.Close;
3718
- var DialogOverlay = React21.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3719
- DialogPrimitive.Overlay,
4045
+ var DialogModalContext = React22.createContext(true);
4046
+ function Dialog({ modal = true, ...props }) {
4047
+ return /* @__PURE__ */ jsx24(DialogModalContext.Provider, { value: modal, children: /* @__PURE__ */ jsx24(DialogPrimitive2.Root, { modal, ...props }) });
4048
+ }
4049
+ var DialogTrigger = DialogPrimitive2.Trigger;
4050
+ var DialogPortal = DialogPrimitive2.Portal;
4051
+ var DialogClose = DialogPrimitive2.Close;
4052
+ var DialogOverlay = React22.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
4053
+ DialogPrimitive2.Overlay,
3720
4054
  {
3721
4055
  ref,
3722
4056
  className: cn(
@@ -3731,62 +4065,72 @@ var DialogOverlay = React21.forwardRef(({ className, ...props }, ref) => /* @__P
3731
4065
  ...props
3732
4066
  }
3733
4067
  ));
3734
- DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
3735
- var DialogContent = React21.forwardRef(({ className, children, showCloseButton = false, mobilePresentation = "center", ...props }, ref) => /* @__PURE__ */ jsxs21(DialogPortal, { children: [
3736
- /* @__PURE__ */ jsx22(DialogOverlay, {}),
3737
- /* @__PURE__ */ jsxs21(
3738
- DialogPrimitive.Content,
3739
- {
3740
- ref,
3741
- className: cn(
3742
- "fixed left-1/2 top-1/2 z-[var(--z-modal)]",
3743
- "-translate-x-1/2 -translate-y-1/2",
3744
- "grid w-full max-w-lg gap-4 p-[var(--space-8)]",
3745
- // modal은 dim overlay 위 — panel surface 토큰(--bg-surface)으로 깨끗하게.
3746
- // (page 배경 --bg-base가 아니라 카드/섹션과 같은 surface 층을 쓴다.)
3747
- // arbitrary var 사용: 소비 site/app이 dist를 content-scan 안 해 `bg-base` 유틸이 purge될 수 있어 안전하게 var로.
3748
- "bg-[var(--bg-surface)] text-foreground",
3749
- // 2026: generic 무거운 그림자 대신 floating shadow-8 + 또렷한 중립 grey border(--border·16%) + radius-lg.
3750
- // (border-subtle=8%는 너무 흐려 가장자리가 안 보였음 → border-border로 grey 또렷하게.)
3751
- "border border-border rounded-[var(--radius-lg)] shadow-8",
3752
- "duration-200",
3753
- "data-[state=open]:animate-in data-[state=closed]:animate-out",
3754
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
3755
- "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
3756
- "data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
3757
- "data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
3758
- "motion-reduce:animate-none",
3759
- mobilePresentation === "sheet" && dialogMobileSheetClassName,
3760
- className
3761
- ),
3762
- ...props,
3763
- ...mobilePresentation === "sheet" && { style: dialogMobileSheetStyle(props.style) },
3764
- children: [
3765
- children,
3766
- showCloseButton ? /* @__PURE__ */ jsx22(
3767
- DialogPrimitive.Close,
3768
- {
3769
- className: cn(
3770
- "absolute right-4 top-4 inline-flex size-[32px] cursor-pointer items-center justify-center",
3771
- "rounded-[var(--radius-md)] text-text-secondary",
3772
- "transition-colors motion-reduce:transition-none",
3773
- "hover:bg-accent hover:text-accent-foreground",
3774
- "focus-visible:outline-none focus-visible:shadow-focus-ring",
3775
- "disabled:pointer-events-none disabled:text-text-disabled"
3776
- ),
3777
- "aria-label": "\uB2EB\uAE30",
3778
- children: /* @__PURE__ */ jsx22(X, { className: "size-[16px]" })
3779
- }
3780
- ) : null
3781
- ]
3782
- }
3783
- )
3784
- ] }));
3785
- DialogContent.displayName = DialogPrimitive.Content.displayName;
4068
+ DialogOverlay.displayName = DialogPrimitive2.Overlay.displayName;
4069
+ var DialogContent = React22.forwardRef(
4070
+ ({
4071
+ className,
4072
+ children,
4073
+ showCloseButton = false,
4074
+ mobilePresentation = "center",
4075
+ onOpenAutoFocus,
4076
+ onCloseAutoFocus,
4077
+ ...props
4078
+ }, ref) => {
4079
+ const modal = React22.useContext(DialogModalContext);
4080
+ const returnFocus = useReturnFocus();
4081
+ const handleOpenAutoFocus = (event) => {
4082
+ if (modal) returnFocus.onOpenAutoFocus(event);
4083
+ onOpenAutoFocus?.(event);
4084
+ };
4085
+ const handleCloseAutoFocus = (event) => {
4086
+ onCloseAutoFocus?.(event);
4087
+ if (modal && !event.defaultPrevented) returnFocus.onCloseAutoFocus(event);
4088
+ };
4089
+ return /* @__PURE__ */ jsxs22(DialogPortal, { children: [
4090
+ /* @__PURE__ */ jsx24(DialogOverlay, {}),
4091
+ /* @__PURE__ */ jsxs22(
4092
+ DialogPrimitive2.Content,
4093
+ {
4094
+ ref,
4095
+ className: cn(
4096
+ "fixed left-1/2 top-1/2 z-[var(--z-modal)]",
4097
+ "-translate-x-1/2 -translate-y-1/2",
4098
+ "grid w-full max-w-lg gap-4 p-[var(--space-8)]",
4099
+ // modal은 dim overlay 위 — panel surface 토큰(--bg-surface)으로 깨끗하게.
4100
+ // (page 배경 --bg-base가 아니라 카드/섹션과 같은 surface 층을 쓴다.)
4101
+ // arbitrary var 사용: 소비 site/app이 dist를 content-scan 안 해 `bg-base` 유틸이 purge될 수 있어 안전하게 var로.
4102
+ "bg-[var(--bg-surface)] text-foreground",
4103
+ // 2026: generic 무거운 그림자 대신 floating shadow-8 + 또렷한 중립 grey border(--border·16%) + radius-lg.
4104
+ // (border-subtle=8%는 너무 흐려 가장자리가 안 보였음 → border-border로 grey 또렷하게.)
4105
+ "border border-border rounded-[var(--radius-lg)] shadow-8",
4106
+ "duration-200",
4107
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
4108
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
4109
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
4110
+ "data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
4111
+ "data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
4112
+ "motion-reduce:animate-none",
4113
+ mobilePresentation === "sheet" && bottomSheet.dialog,
4114
+ className
4115
+ ),
4116
+ ...props,
4117
+ ...mobilePresentation === "sheet" && { style: dialogMobileSheetStyle(props.style) },
4118
+ onOpenAutoFocus: handleOpenAutoFocus,
4119
+ onCloseAutoFocus: handleCloseAutoFocus,
4120
+ children: [
4121
+ children,
4122
+ showCloseButton ? /* @__PURE__ */ jsx24(OverlayCloseButton, { className: "absolute right-4 top-4" }) : null
4123
+ ]
4124
+ }
4125
+ )
4126
+ ] });
4127
+ }
4128
+ );
4129
+ DialogContent.displayName = DialogPrimitive2.Content.displayName;
3786
4130
  var DialogHeader = ({
3787
4131
  className,
3788
4132
  ...props
3789
- }) => /* @__PURE__ */ jsx22(
4133
+ }) => /* @__PURE__ */ jsx24(
3790
4134
  "div",
3791
4135
  {
3792
4136
  className: cn(
@@ -3801,7 +4145,7 @@ DialogHeader.displayName = "DialogHeader";
3801
4145
  var DialogFooter = ({
3802
4146
  className,
3803
4147
  ...props
3804
- }) => /* @__PURE__ */ jsx22(
4148
+ }) => /* @__PURE__ */ jsx24(
3805
4149
  "div",
3806
4150
  {
3807
4151
  className: cn(
@@ -3817,8 +4161,8 @@ var DialogFooter = ({
3817
4161
  }
3818
4162
  );
3819
4163
  DialogFooter.displayName = "DialogFooter";
3820
- var DialogTitle = React21.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3821
- DialogPrimitive.Title,
4164
+ var DialogTitle = React22.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
4165
+ DialogPrimitive2.Title,
3822
4166
  {
3823
4167
  ref,
3824
4168
  className: cn(
@@ -3828,17 +4172,17 @@ var DialogTitle = React21.forwardRef(({ className, ...props }, ref) => /* @__PUR
3828
4172
  ...props
3829
4173
  }
3830
4174
  ));
3831
- DialogTitle.displayName = DialogPrimitive.Title.displayName;
3832
- var DialogDescription = React21.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3833
- DialogPrimitive.Description,
4175
+ DialogTitle.displayName = DialogPrimitive2.Title.displayName;
4176
+ var DialogDescription = React22.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
4177
+ DialogPrimitive2.Description,
3834
4178
  {
3835
4179
  ref,
3836
4180
  className: cn("text-sm text-text-secondary", className),
3837
4181
  ...props
3838
4182
  }
3839
4183
  ));
3840
- DialogDescription.displayName = DialogPrimitive.Description.displayName;
3841
- var DialogEyebrow = React21.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
4184
+ DialogDescription.displayName = DialogPrimitive2.Description.displayName;
4185
+ var DialogEyebrow = React22.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx24(
3842
4186
  "p",
3843
4187
  {
3844
4188
  ref,
@@ -3850,43 +4194,130 @@ var DialogEyebrow = React21.forwardRef(({ className, ...props }, ref) => /* @__P
3850
4194
  }
3851
4195
  ));
3852
4196
  DialogEyebrow.displayName = "DialogEyebrow";
3853
- var DialogRawContent = DialogPrimitive.Content;
4197
+ var DialogRawContent = DialogPrimitive2.Content;
3854
4198
 
3855
- // src/components/ui/form-modal.tsx
3856
- import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
3857
- var formModalContentClassName = cn(
3858
- "w-[calc(100vw-2rem)]",
3859
- "max-w-[560px]",
3860
- "gap-0 p-[var(--space-6)]",
3861
- "bg-[var(--bg-surface)]",
3862
- "border-[var(--border)]",
3863
- "rounded-[var(--radius-lg)]",
3864
- "shadow-[var(--shadow-4)]",
3865
- "text-foreground"
3866
- );
3867
- var formModalWideContentClassName = "max-w-[720px]";
3868
- var formModalHeaderClassName = cn(
4199
+ // src/lib/use-overlay-action.ts
4200
+ import * as React23 from "react";
4201
+ function useOverlayAction({
4202
+ action,
4203
+ onOpenChange,
4204
+ loading = false,
4205
+ disabled = false
4206
+ }) {
4207
+ const [pending, setPending] = React23.useState(false);
4208
+ const busyRef = React23.useRef(false);
4209
+ const isBusy = loading || pending;
4210
+ const guardOpenChange = React23.useCallback(
4211
+ (nextOpen) => {
4212
+ if (!nextOpen && isBusy) {
4213
+ return;
4214
+ }
4215
+ onOpenChange(nextOpen);
4216
+ },
4217
+ [isBusy, onOpenChange]
4218
+ );
4219
+ const run = React23.useCallback(async () => {
4220
+ if (busyRef.current || loading || disabled) {
4221
+ return;
4222
+ }
4223
+ busyRef.current = true;
4224
+ setPending(true);
4225
+ try {
4226
+ await action();
4227
+ onOpenChange(false);
4228
+ } finally {
4229
+ busyRef.current = false;
4230
+ setPending(false);
4231
+ }
4232
+ }, [action, disabled, loading, onOpenChange]);
4233
+ return { isBusy, run, guardOpenChange };
4234
+ }
4235
+
4236
+ // src/components/ui/overlay-tokens.ts
4237
+ var OVERLAY_WIDTH = {
4238
+ compact: "max-w-[420px]",
4239
+ form: "max-w-[560px]",
4240
+ wide: "max-w-[720px]"
4241
+ };
4242
+ var OVERLAY_SHADOW = {
4243
+ preset: "shadow-[var(--shadow-4)]"
4244
+ };
4245
+
4246
+ // src/components/ui/preset-surface.ts
4247
+ var title = cn("text-[18px] font-bold leading-snug text-foreground");
4248
+ var modalHeader = cn(
3869
4249
  "flex flex-col gap-[var(--space-2)]",
3870
4250
  "border-b border-[var(--border-subtle)] pb-[var(--space-4)]",
3871
4251
  "pr-[40px]"
3872
4252
  );
3873
- var formModalTitleClassName = cn(
3874
- "text-[18px] font-bold leading-snug text-foreground"
3875
- );
3876
- var formModalDescriptionClassName = cn(
3877
- "break-keep text-[14px] leading-normal text-text-secondary"
3878
- );
3879
- var formModalBodyClassName = cn(
3880
- "flex flex-col gap-[var(--space-4)] py-[var(--space-6)]"
3881
- );
3882
- var formModalFooterClassName = cn(
4253
+ var modalDescription = cn("break-keep text-[14px] leading-normal text-text-secondary");
4254
+ var modalFooter = cn(
3883
4255
  "border-t border-[var(--border-subtle)] pt-[var(--space-4)]",
3884
4256
  "flex flex-col-reverse justify-end gap-[var(--space-2)] sm:flex-row"
3885
4257
  );
4258
+ var modalBody = "flex flex-col gap-[var(--space-4)] py-[var(--space-6)]";
4259
+ var presetSurface = {
4260
+ form: {
4261
+ content: cn(
4262
+ "w-[calc(100vw-2rem)]",
4263
+ OVERLAY_WIDTH.form,
4264
+ "gap-0 p-[var(--space-6)]",
4265
+ "bg-[var(--bg-surface)]",
4266
+ "border-[var(--border)]",
4267
+ "rounded-[var(--radius-lg)]",
4268
+ OVERLAY_SHADOW.preset,
4269
+ "text-foreground"
4270
+ ),
4271
+ wideContent: OVERLAY_WIDTH.wide,
4272
+ header: modalHeader,
4273
+ title,
4274
+ description: modalDescription,
4275
+ body: modalBody,
4276
+ footer: modalFooter
4277
+ },
4278
+ info: {
4279
+ content: cn(
4280
+ "w-[calc(100vw-2rem)]",
4281
+ OVERLAY_WIDTH.compact,
4282
+ "gap-0 p-[var(--space-6)]",
4283
+ "bg-[var(--bg-surface)]",
4284
+ "border border-[var(--border)]",
4285
+ "rounded-[var(--radius-lg)]",
4286
+ OVERLAY_SHADOW.preset,
4287
+ "text-foreground"
4288
+ ),
4289
+ wideContent: OVERLAY_WIDTH.wide,
4290
+ header: modalHeader,
4291
+ title,
4292
+ description: modalDescription,
4293
+ body: cn(modalBody, "text-[14px] leading-normal text-text-secondary"),
4294
+ footer: modalFooter
4295
+ },
4296
+ confirm: {
4297
+ content: cn(
4298
+ "fixed left-1/2 top-1/2 z-[var(--z-modal)]",
4299
+ "-translate-x-1/2 -translate-y-1/2",
4300
+ "w-[calc(100vw-2rem)]",
4301
+ OVERLAY_WIDTH.compact,
4302
+ "flex flex-col gap-[var(--space-6)]",
4303
+ "bg-[var(--bg-surface)] border border-[var(--border)]",
4304
+ "rounded-[var(--radius-lg)] p-[var(--space-6)]",
4305
+ OVERLAY_SHADOW.preset,
4306
+ "text-foreground"
4307
+ ),
4308
+ title,
4309
+ description: "break-keep text-[14px] leading-relaxed text-text-secondary",
4310
+ body: "min-w-0 text-[14px] leading-relaxed text-text-secondary",
4311
+ footer: "flex items-center justify-end gap-[var(--space-3)]"
4312
+ }
4313
+ };
4314
+
4315
+ // src/components/ui/form-modal.tsx
4316
+ import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
3886
4317
  function FormModal({
3887
4318
  open,
3888
4319
  onOpenChange,
3889
- title,
4320
+ title: title2,
3890
4321
  description,
3891
4322
  children,
3892
4323
  onSubmit,
@@ -3897,72 +4328,48 @@ function FormModal({
3897
4328
  status,
3898
4329
  mobilePresentation = "center"
3899
4330
  }) {
3900
- const [pending, setPending] = React22.useState(false);
3901
- const busyRef = React22.useRef(false);
3902
- const isBusy = loading || pending;
3903
- const returnFocus = useReturnFocus();
3904
- const handleOpenChange = React22.useCallback(
3905
- (nextOpen) => {
3906
- if (!nextOpen && isBusy) {
3907
- return;
3908
- }
3909
- onOpenChange(nextOpen);
3910
- },
3911
- [isBusy, onOpenChange]
3912
- );
3913
- const handleSubmit = React22.useCallback(
3914
- async (event) => {
3915
- event.preventDefault();
3916
- if (busyRef.current || loading) {
3917
- return;
3918
- }
3919
- busyRef.current = true;
3920
- setPending(true);
3921
- try {
3922
- await onSubmit();
3923
- onOpenChange(false);
3924
- } finally {
3925
- busyRef.current = false;
3926
- setPending(false);
3927
- }
3928
- },
3929
- [loading, onOpenChange, onSubmit]
3930
- );
3931
- return /* @__PURE__ */ jsx23(Dialog, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsx23(
4331
+ const { isBusy, run, guardOpenChange } = useOverlayAction({
4332
+ action: onSubmit,
4333
+ onOpenChange,
4334
+ loading
4335
+ });
4336
+ return /* @__PURE__ */ jsx25(Dialog, { open, onOpenChange: guardOpenChange, children: /* @__PURE__ */ jsx25(
3932
4337
  DialogContent,
3933
4338
  {
3934
4339
  "data-slot": "form-modal-content",
3935
4340
  mobilePresentation,
3936
- ...returnFocus,
3937
4341
  className: cn(
3938
- formModalContentClassName,
3939
- wide && formModalWideContentClassName
4342
+ presetSurface.form.content,
4343
+ wide && presetSurface.form.wideContent
3940
4344
  ),
3941
- children: /* @__PURE__ */ jsxs22("form", { "data-slot": "form-modal-form", onSubmit: handleSubmit, children: [
3942
- /* @__PURE__ */ jsxs22("div", { "data-slot": "form-modal-header", className: formModalHeaderClassName, children: [
3943
- /* @__PURE__ */ jsx23(DialogTitle, { className: formModalTitleClassName, children: title }),
3944
- description ? /* @__PURE__ */ jsx23(DialogDescription, { className: formModalDescriptionClassName, children: description }) : null,
3945
- status ? /* @__PURE__ */ jsx23("div", { "data-slot": "form-modal-status", children: status }) : null
4345
+ children: /* @__PURE__ */ jsxs23("form", { "data-slot": "form-modal-form", onSubmit: (event) => {
4346
+ event.preventDefault();
4347
+ return run();
4348
+ }, children: [
4349
+ /* @__PURE__ */ jsxs23("div", { "data-slot": "form-modal-header", className: presetSurface.form.header, children: [
4350
+ /* @__PURE__ */ jsx25(DialogTitle, { className: presetSurface.form.title, children: title2 }),
4351
+ description ? /* @__PURE__ */ jsx25(DialogDescription, { className: presetSurface.form.description, children: description }) : null,
4352
+ status ? /* @__PURE__ */ jsx25("div", { "data-slot": "form-modal-status", children: status }) : null
3946
4353
  ] }),
3947
- /* @__PURE__ */ jsx23("div", { "data-slot": "form-modal-body", className: formModalBodyClassName, children }),
3948
- /* @__PURE__ */ jsxs22(
4354
+ /* @__PURE__ */ jsx25("div", { "data-slot": "form-modal-body", className: presetSurface.form.body, children }),
4355
+ /* @__PURE__ */ jsxs23(
3949
4356
  "div",
3950
4357
  {
3951
4358
  "data-slot": "form-modal-footer",
3952
- className: formModalFooterClassName,
4359
+ className: presetSurface.form.footer,
3953
4360
  children: [
3954
- /* @__PURE__ */ jsx23(
4361
+ /* @__PURE__ */ jsx25(
3955
4362
  Button,
3956
4363
  {
3957
4364
  variant: "secondary",
3958
4365
  size: "lg",
3959
4366
  className: footerButtonHitAreaClassName,
3960
4367
  disabled: isBusy,
3961
- onClick: () => handleOpenChange(false),
4368
+ onClick: () => guardOpenChange(false),
3962
4369
  children: cancelLabel
3963
4370
  }
3964
4371
  ),
3965
- /* @__PURE__ */ jsx23(Button, { type: "submit", size: "lg", className: footerButtonHitAreaClassName, loading: isBusy, children: submitLabel })
4372
+ /* @__PURE__ */ jsx25(Button, { type: "submit", size: "lg", className: footerButtonHitAreaClassName, loading: isBusy, children: submitLabel })
3966
4373
  ]
3967
4374
  }
3968
4375
  )
@@ -3972,41 +4379,11 @@ function FormModal({
3972
4379
  }
3973
4380
 
3974
4381
  // src/components/ui/info-modal.tsx
3975
- import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
3976
- var infoModalContentClassName = cn(
3977
- "w-[calc(100vw-2rem)]",
3978
- "max-w-[420px]",
3979
- "gap-0 p-[var(--space-6)]",
3980
- "bg-[var(--bg-surface)]",
3981
- "border border-[var(--border)]",
3982
- "rounded-[var(--radius-lg)]",
3983
- "shadow-[var(--shadow-4)]",
3984
- "text-foreground"
3985
- );
3986
- var infoModalWideContentClassName = "max-w-[720px]";
3987
- var infoModalHeaderClassName = cn(
3988
- "flex flex-col gap-[var(--space-2)]",
3989
- "border-b border-[var(--border-subtle)] pb-[var(--space-4)]",
3990
- "pr-[40px]"
3991
- );
3992
- var infoModalTitleClassName = cn(
3993
- "text-[18px] font-bold leading-snug text-foreground"
3994
- );
3995
- var infoModalDescriptionClassName = cn(
3996
- "break-keep text-[14px] leading-normal text-text-secondary"
3997
- );
3998
- var infoModalBodyClassName = cn(
3999
- "flex flex-col gap-[var(--space-4)] py-[var(--space-6)]",
4000
- "text-[14px] leading-normal text-text-secondary"
4001
- );
4002
- var infoModalFooterClassName = cn(
4003
- "border-t border-[var(--border-subtle)] pt-[var(--space-4)]",
4004
- "flex flex-col-reverse justify-end gap-[var(--space-2)] sm:flex-row"
4005
- );
4382
+ import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
4006
4383
  function InfoModal({
4007
4384
  open,
4008
4385
  onOpenChange,
4009
- title,
4386
+ title: title2,
4010
4387
  description,
4011
4388
  children,
4012
4389
  closeLabel = "\uB2EB\uAE30",
@@ -4014,31 +4391,29 @@ function InfoModal({
4014
4391
  footer,
4015
4392
  mobilePresentation = "center"
4016
4393
  }) {
4017
- const returnFocus = useReturnFocus();
4018
- return /* @__PURE__ */ jsx24(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs23(
4394
+ return /* @__PURE__ */ jsx26(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs24(
4019
4395
  DialogContent,
4020
4396
  {
4021
4397
  "data-slot": "info-modal-content",
4022
4398
  mobilePresentation,
4023
- ...returnFocus,
4024
4399
  className: cn(
4025
- infoModalContentClassName,
4026
- width === "wide" && infoModalWideContentClassName
4400
+ presetSurface.info.content,
4401
+ width === "wide" && presetSurface.info.wideContent
4027
4402
  ),
4028
4403
  children: [
4029
- /* @__PURE__ */ jsxs23("div", { "data-slot": "info-modal-header", className: infoModalHeaderClassName, children: [
4030
- /* @__PURE__ */ jsx24(DialogTitle, { "data-slot": "info-modal-title", className: infoModalTitleClassName, children: title }),
4031
- description ? /* @__PURE__ */ jsx24(
4404
+ /* @__PURE__ */ jsxs24("div", { "data-slot": "info-modal-header", className: presetSurface.info.header, children: [
4405
+ /* @__PURE__ */ jsx26(DialogTitle, { "data-slot": "info-modal-title", className: presetSurface.info.title, children: title2 }),
4406
+ description ? /* @__PURE__ */ jsx26(
4032
4407
  DialogDescription,
4033
4408
  {
4034
4409
  "data-slot": "info-modal-description",
4035
- className: infoModalDescriptionClassName,
4410
+ className: presetSurface.info.description,
4036
4411
  children: description
4037
4412
  }
4038
4413
  ) : null
4039
4414
  ] }),
4040
- /* @__PURE__ */ jsx24("div", { "data-slot": "info-modal-body", className: infoModalBodyClassName, children }),
4041
- /* @__PURE__ */ jsx24("div", { "data-slot": "info-modal-footer", className: infoModalFooterClassName, children: footer ?? /* @__PURE__ */ jsx24(
4415
+ /* @__PURE__ */ jsx26("div", { "data-slot": "info-modal-body", className: presetSurface.info.body, children }),
4416
+ /* @__PURE__ */ jsx26("div", { "data-slot": "info-modal-footer", className: presetSurface.info.footer, children: footer ?? /* @__PURE__ */ jsx26(
4042
4417
  Button,
4043
4418
  {
4044
4419
  "data-slot": "info-modal-close-button",
@@ -4059,12 +4434,12 @@ import * as React26 from "react";
4059
4434
  import { SlidersHorizontal } from "lucide-react";
4060
4435
 
4061
4436
  // src/components/ui/chip.tsx
4062
- import * as React23 from "react";
4063
- import { cva as cva9 } from "class-variance-authority";
4437
+ import * as React24 from "react";
4438
+ import { cva as cva10 } from "class-variance-authority";
4064
4439
  import { X as X2 } from "lucide-react";
4065
4440
  import { Slot as Slot2 } from "radix-ui";
4066
- import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
4067
- var chipVariants = cva9(
4441
+ import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
4442
+ var chipVariants = cva10(
4068
4443
  [
4069
4444
  "inline-flex w-fit shrink-0 items-center justify-center whitespace-nowrap",
4070
4445
  "rounded-[var(--radius-full)] border leading-none",
@@ -4127,7 +4502,7 @@ var chipVariants = cva9(
4127
4502
  }
4128
4503
  }
4129
4504
  );
4130
- var chipCountVariants = cva9(
4505
+ var chipCountVariants = cva10(
4131
4506
  [
4132
4507
  "inline-flex min-w-[var(--space-4)] items-center justify-center",
4133
4508
  "rounded-[var(--radius-full)] px-[var(--space-1)]",
@@ -4155,7 +4530,7 @@ var chipCountVariants = cva9(
4155
4530
  }
4156
4531
  }
4157
4532
  );
4158
- var Chip = React23.forwardRef(
4533
+ var Chip = React24.forwardRef(
4159
4534
  ({
4160
4535
  className,
4161
4536
  variant = "filter",
@@ -4180,7 +4555,7 @@ var Chip = React23.forwardRef(
4180
4555
  value: _value,
4181
4556
  ...spanProps
4182
4557
  } = props;
4183
- return /* @__PURE__ */ jsxs24(
4558
+ return /* @__PURE__ */ jsxs25(
4184
4559
  "span",
4185
4560
  {
4186
4561
  "data-slot": "chip",
@@ -4189,8 +4564,8 @@ var Chip = React23.forwardRef(
4189
4564
  className: cn(chipVariants({ variant, tone, size, pressed, className })),
4190
4565
  ...spanProps,
4191
4566
  children: [
4192
- /* @__PURE__ */ jsx25("span", { children }),
4193
- count !== void 0 ? /* @__PURE__ */ jsx25(
4567
+ /* @__PURE__ */ jsx27("span", { children }),
4568
+ count !== void 0 ? /* @__PURE__ */ jsx27(
4194
4569
  "span",
4195
4570
  {
4196
4571
  "aria-hidden": "true",
@@ -4200,7 +4575,7 @@ var Chip = React23.forwardRef(
4200
4575
  children: count
4201
4576
  }
4202
4577
  ) : null,
4203
- /* @__PURE__ */ jsx25(
4578
+ /* @__PURE__ */ jsx27(
4204
4579
  "button",
4205
4580
  {
4206
4581
  ref,
@@ -4210,7 +4585,7 @@ var Chip = React23.forwardRef(
4210
4585
  disabled,
4211
4586
  onClick,
4212
4587
  className: "inline-flex size-[var(--space-4)] items-center justify-center rounded-[var(--radius-full)] text-text-tertiary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]",
4213
- children: /* @__PURE__ */ jsx25(X2, { "aria-hidden": "true", size: 14, strokeWidth: 2.25 })
4588
+ children: /* @__PURE__ */ jsx27(X2, { "aria-hidden": "true", size: 14, strokeWidth: 2.25 })
4214
4589
  }
4215
4590
  )
4216
4591
  ]
@@ -4218,7 +4593,7 @@ var Chip = React23.forwardRef(
4218
4593
  );
4219
4594
  }
4220
4595
  const Comp = asChild ? Slot2.Root : "button";
4221
- return /* @__PURE__ */ jsxs24(
4596
+ return /* @__PURE__ */ jsxs25(
4222
4597
  Comp,
4223
4598
  {
4224
4599
  ref,
@@ -4233,7 +4608,7 @@ var Chip = React23.forwardRef(
4233
4608
  ...props,
4234
4609
  children: [
4235
4610
  children,
4236
- count !== void 0 ? /* @__PURE__ */ jsx25(
4611
+ count !== void 0 ? /* @__PURE__ */ jsx27(
4237
4612
  "span",
4238
4613
  {
4239
4614
  "aria-hidden": "true",
@@ -4250,168 +4625,18 @@ var Chip = React23.forwardRef(
4250
4625
  );
4251
4626
  Chip.displayName = "Chip";
4252
4627
 
4253
- // src/components/ui/icon-button.tsx
4254
- import * as React24 from "react";
4255
- import { cva as cva10 } from "class-variance-authority";
4256
- import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
4257
- var iconButtonVariants = cva10(
4258
- [
4259
- "olun-icon-button relative inline-flex cursor-pointer shrink-0 items-center justify-center before:absolute before:content-['']",
4260
- "rounded-[var(--radius-md)] border font-medium",
4261
- "transition-colors motion-reduce:transition-none",
4262
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]",
4263
- "disabled:cursor-not-allowed disabled:bg-[var(--action-disabled-bg)] disabled:text-text-disabled",
4264
- "[&_svg]:pointer-events-none [&_svg]:shrink-0"
4265
- ].join(" "),
4266
- {
4267
- variants: {
4268
- variant: {
4269
- ghost: "border-transparent bg-transparent text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground",
4270
- outline: "border-[var(--border-subtle)] bg-[var(--bg-surface)] text-text-secondary hover:border-[var(--border-strong)] hover:bg-[var(--action-hover)] hover:text-foreground",
4271
- subtle: "border-transparent bg-[var(--bg-inset)] text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground",
4272
- danger: "border-transparent bg-[var(--error-bg)] text-[var(--error)] hover:bg-[var(--action-hover)]"
4273
- },
4274
- // Hit area = 44px on every size. The ::before is absolutely positioned, so its
4275
- // inset is measured from the padding box — inside the 1px border every variant
4276
- // carries (transparent or not). Inset = (44 - (size - 2 × 1px border)) / 2.
4277
- size: {
4278
- sm: "size-[28px] before:-inset-[9px]",
4279
- md: "size-[32px] before:-inset-[7px]",
4280
- lg: "size-[40px] before:-inset-[3px]"
4281
- },
4282
- pressed: {
4283
- true: "",
4284
- false: ""
4285
- }
4286
- },
4287
- compoundVariants: [
4288
- {
4289
- pressed: true,
4290
- variant: ["ghost", "outline", "subtle"],
4291
- className: "border-[var(--border-strong)] bg-[var(--action-selected)] text-foreground"
4292
- },
4293
- {
4294
- pressed: true,
4295
- variant: "danger",
4296
- className: "border-[var(--error)] bg-[var(--error-bg)] text-[var(--error)]"
4297
- }
4298
- ],
4299
- // ghost is the intended default, not a fallback: ghost is reserved for icon-only
4300
- // actions repeated in rows or chrome (toolbars, headers, table rows), and
4301
- // IconButton is its canonical entry point (#58). Text actions use Button.
4302
- defaultVariants: {
4303
- variant: "ghost",
4304
- size: "md",
4305
- pressed: false
4306
- }
4307
- }
4308
- );
4309
- var iconButtonBadgeVariants = cva10(
4310
- [
4311
- "pointer-events-none absolute right-0 top-0 inline-flex",
4312
- "olun-icon-button__badge",
4313
- "min-h-[var(--space-3)] min-w-[var(--space-3)] translate-x-1/3 -translate-y-1/3",
4314
- "items-center justify-center gap-[2px] rounded-[var(--radius-full)] px-[3px]",
4315
- "font-[family-name:var(--font-display)] text-[10px] font-semibold leading-none",
4316
- "[&:has(svg)]:size-[var(--space-3)] [&:has(svg)]:px-0 [&_svg]:size-[10px]"
4317
- ].join(" "),
4318
- {
4319
- variants: {
4320
- tone: {
4321
- info: "bg-[var(--accent-pop)] text-[var(--accent-on-fill)]",
4322
- error: "bg-[var(--error)] text-[var(--error-contrast)]"
4323
- }
4324
- },
4325
- defaultVariants: {
4326
- tone: "info"
4327
- }
4328
- }
4329
- );
4330
- var iconSize2 = {
4331
- sm: 14,
4332
- md: 16,
4333
- lg: 18
4334
- };
4335
- var iconStrokeWidth = {
4336
- sm: 2.25,
4337
- md: 2.25,
4338
- lg: 1.75
4339
- };
4340
- var IconButton = React24.forwardRef(
4341
- ({
4342
- className,
4343
- variant = "ghost",
4344
- size = "md",
4345
- pressed = void 0,
4346
- icon: Icon,
4347
- badge,
4348
- badgeTone = "info",
4349
- type,
4350
- title,
4351
- "aria-label": ariaLabel,
4352
- "aria-labelledby": ariaLabelledBy,
4353
- ...props
4354
- }, ref) => {
4355
- const resolvedSize = size ?? "md";
4356
- const isToggle = pressed !== void 0;
4357
- const isPressed = pressed === true;
4358
- const hoverTitle = title ?? (typeof ariaLabel === "string" ? ariaLabel : void 0);
4359
- return /* @__PURE__ */ jsxs25(
4360
- "button",
4361
- {
4362
- ref,
4363
- ...props,
4364
- "data-slot": "icon-button",
4365
- "data-variant": variant,
4366
- "data-size": resolvedSize,
4367
- "data-pressed": isToggle ? String(isPressed) : void 0,
4368
- "aria-label": ariaLabel,
4369
- "aria-labelledby": ariaLabelledBy,
4370
- "aria-pressed": isToggle ? isPressed : void 0,
4371
- title: hoverTitle,
4372
- className: cn(
4373
- iconButtonVariants({ variant, size, pressed: isPressed, className })
4374
- ),
4375
- type: type ?? "button",
4376
- children: [
4377
- /* @__PURE__ */ jsx26(
4378
- Icon,
4379
- {
4380
- "aria-hidden": "true",
4381
- "data-slot": "icon-button-icon",
4382
- size: iconSize2[resolvedSize],
4383
- strokeWidth: iconStrokeWidth[resolvedSize]
4384
- }
4385
- ),
4386
- badge !== void 0 ? /* @__PURE__ */ jsx26(
4387
- "span",
4388
- {
4389
- "aria-hidden": "true",
4390
- "data-slot": "icon-button-badge",
4391
- "data-badge-tone": badgeTone,
4392
- className: iconButtonBadgeVariants({ tone: badgeTone }),
4393
- children: badge
4394
- }
4395
- ) : null
4396
- ]
4397
- }
4398
- );
4399
- }
4400
- );
4401
- IconButton.displayName = "IconButton";
4402
-
4403
4628
  // src/components/ui/popover.tsx
4404
4629
  import * as React25 from "react";
4405
4630
  import { Popover as PopoverPrimitive } from "radix-ui";
4406
- import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
4631
+ import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
4407
4632
  function Popover({ modal = false, ...props }) {
4408
- return /* @__PURE__ */ jsx27(PopoverPrimitive.Root, { modal, ...props });
4633
+ return /* @__PURE__ */ jsx28(PopoverPrimitive.Root, { modal, ...props });
4409
4634
  }
4410
4635
  var popoverArrowClassName = "fill-[var(--bg-surface)] stroke-[var(--border)] [&>polygon]:[vector-effect:non-scaling-stroke]";
4411
4636
  var PopoverTrigger = PopoverPrimitive.Trigger;
4412
4637
  var PopoverAnchor = PopoverPrimitive.Anchor;
4413
4638
  var PopoverClose = PopoverPrimitive.Close;
4414
- var PopoverContent = React25.forwardRef(({ className, align = "center", sideOffset = 8, collisionPadding = 8, showArrow = false, children, ...props }, ref) => /* @__PURE__ */ jsx27(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsxs26(
4639
+ var PopoverContent = React25.forwardRef(({ className, align = "center", sideOffset = 8, collisionPadding = 8, showArrow = false, children, ...props }, ref) => /* @__PURE__ */ jsx28(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsxs26(
4415
4640
  PopoverPrimitive.Content,
4416
4641
  {
4417
4642
  ref,
@@ -4435,7 +4660,7 @@ var PopoverContent = React25.forwardRef(({ className, align = "center", sideOffs
4435
4660
  ...props,
4436
4661
  children: [
4437
4662
  children,
4438
- showArrow ? /* @__PURE__ */ jsx27(
4663
+ showArrow ? /* @__PURE__ */ jsx28(
4439
4664
  PopoverPrimitive.Arrow,
4440
4665
  {
4441
4666
  "data-slot": "popover-arrow",
@@ -4448,7 +4673,7 @@ var PopoverContent = React25.forwardRef(({ className, align = "center", sideOffs
4448
4673
  }
4449
4674
  ) }));
4450
4675
  PopoverContent.displayName = PopoverPrimitive.Content.displayName;
4451
- var PopoverArrow = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
4676
+ var PopoverArrow = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx28(
4452
4677
  PopoverPrimitive.Arrow,
4453
4678
  {
4454
4679
  ref,
@@ -4462,20 +4687,19 @@ var PopoverArrow = React25.forwardRef(({ className, ...props }, ref) => /* @__PU
4462
4687
  PopoverArrow.displayName = PopoverPrimitive.Arrow.displayName;
4463
4688
 
4464
4689
  // src/components/ui/sheet-drawer.tsx
4465
- import { Maximize2Icon, Minimize2Icon, XIcon as XIcon3 } from "lucide-react";
4466
- import { jsx as jsx28, jsxs as jsxs27 } from "react/jsx-runtime";
4690
+ import { Maximize2Icon, Minimize2Icon } from "lucide-react";
4691
+ import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
4467
4692
  var sheetDrawerContentClassName = cn(
4468
4693
  "gap-0 p-0",
4469
4694
  "bg-[var(--bg-surface)] text-foreground",
4470
4695
  "border-[var(--border)] shadow-[var(--shadow-16)]",
4471
4696
  "min-[900px]:w-[480px] min-[900px]:max-w-[480px]",
4472
- "max-[899px]:h-[min(85dvh,720px)] max-[899px]:max-h-[85dvh] max-[899px]:w-full max-[899px]:max-w-none",
4473
- "max-[899px]:rounded-t-[var(--radius-lg)]"
4697
+ bottomSheet.detail.base
4474
4698
  );
4475
4699
  var sheetDrawerWideContentClassName = "min-[900px]:w-[720px] min-[900px]:max-w-[720px]";
4476
4700
  var sheetDrawerFullContentClassName = cn(
4477
4701
  "min-[900px]:w-[calc(100vw_-_var(--space-8))] min-[900px]:max-w-[calc(100vw_-_var(--space-8))]",
4478
- "max-[899px]:h-[100dvh] max-[899px]:max-h-[100dvh] max-[899px]:rounded-none"
4702
+ bottomSheet.detail.full
4479
4703
  );
4480
4704
  var sheetDrawerHeaderClassName = cn(
4481
4705
  "flex items-start justify-between gap-[var(--space-4)]",
@@ -4485,12 +4709,6 @@ var sheetDrawerHeaderTextClassName = "flex min-w-0 flex-1 flex-col gap-[var(--sp
4485
4709
  var sheetDrawerCaptionClassName = "flex flex-wrap items-center gap-[var(--space-2)]";
4486
4710
  var sheetDrawerTitleClassName = "text-[18px] font-bold leading-snug text-foreground";
4487
4711
  var sheetDrawerDescriptionClassName = "break-keep text-[14px] leading-normal text-text-secondary";
4488
- var sheetDrawerCloseButtonClassName = cn(
4489
- "flex size-[32px] shrink-0 cursor-pointer items-center justify-center",
4490
- "rounded-[var(--radius-md)] text-text-tertiary transition-colors",
4491
- "hover:bg-[var(--action-hover)] hover:text-foreground",
4492
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2"
4493
- );
4494
4712
  var sheetDrawerHeaderActionsClassName = cn(
4495
4713
  "flex shrink-0 items-center gap-[var(--space-1)]"
4496
4714
  );
@@ -4513,7 +4731,7 @@ function SheetDrawer({
4513
4731
  open,
4514
4732
  onOpenChange,
4515
4733
  caption,
4516
- title,
4734
+ title: title2,
4517
4735
  description,
4518
4736
  children,
4519
4737
  expandHref,
@@ -4532,7 +4750,7 @@ function SheetDrawer({
4532
4750
  const resolvedWidth = expanded ? "full" : width;
4533
4751
  const resolvedExpandLabel = hasExpandedToggle && expanded ? collapseLabel : expandLabel;
4534
4752
  const ExpandActionIcon = hasExpandedToggle && expanded ? Minimize2Icon : Maximize2Icon;
4535
- return /* @__PURE__ */ jsx28(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs27(
4753
+ return /* @__PURE__ */ jsx29(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsxs27(
4536
4754
  SheetContent,
4537
4755
  {
4538
4756
  "data-slot": "sheet-drawer-content",
@@ -4548,9 +4766,9 @@ function SheetDrawer({
4548
4766
  children: [
4549
4767
  /* @__PURE__ */ jsxs27("div", { "data-slot": "sheet-drawer-header", className: sheetDrawerHeaderClassName, children: [
4550
4768
  /* @__PURE__ */ jsxs27("div", { className: sheetDrawerHeaderTextClassName, children: [
4551
- caption ? /* @__PURE__ */ jsx28("div", { "data-slot": "sheet-drawer-caption", className: sheetDrawerCaptionClassName, children: caption }) : null,
4552
- /* @__PURE__ */ jsx28(SheetTitle, { "data-slot": "sheet-drawer-title", className: sheetDrawerTitleClassName, children: title }),
4553
- description ? /* @__PURE__ */ jsx28(
4769
+ caption ? /* @__PURE__ */ jsx29("div", { "data-slot": "sheet-drawer-caption", className: sheetDrawerCaptionClassName, children: caption }) : null,
4770
+ /* @__PURE__ */ jsx29(SheetTitle, { "data-slot": "sheet-drawer-title", className: sheetDrawerTitleClassName, children: title2 }),
4771
+ description ? /* @__PURE__ */ jsx29(
4554
4772
  SheetDescription,
4555
4773
  {
4556
4774
  "data-slot": "sheet-drawer-description",
@@ -4571,8 +4789,8 @@ function SheetDrawer({
4571
4789
  className: sheetDrawerExpandButtonClassName,
4572
4790
  onClick: () => onExpandedChange(!expanded),
4573
4791
  children: [
4574
- /* @__PURE__ */ jsx28(ExpandActionIcon, { className: "size-[16px]" }),
4575
- /* @__PURE__ */ jsx28("span", { className: "hidden text-sm font-medium leading-normal md:inline", children: resolvedExpandLabel })
4792
+ /* @__PURE__ */ jsx29(ExpandActionIcon, { className: "size-[16px]" }),
4793
+ /* @__PURE__ */ jsx29("span", { className: "hidden text-sm font-medium leading-normal md:inline", children: resolvedExpandLabel })
4576
4794
  ]
4577
4795
  }
4578
4796
  ) : expandHref ? /* @__PURE__ */ jsxs27(
@@ -4583,8 +4801,8 @@ function SheetDrawer({
4583
4801
  "data-slot": "sheet-drawer-expand",
4584
4802
  className: sheetDrawerExpandButtonClassName,
4585
4803
  children: [
4586
- /* @__PURE__ */ jsx28(ExpandActionIcon, { className: "size-[16px]" }),
4587
- /* @__PURE__ */ jsx28("span", { className: "hidden text-sm font-medium leading-normal md:inline", children: expandLabel })
4804
+ /* @__PURE__ */ jsx29(ExpandActionIcon, { className: "size-[16px]" }),
4805
+ /* @__PURE__ */ jsx29("span", { className: "hidden text-sm font-medium leading-normal md:inline", children: expandLabel })
4588
4806
  ]
4589
4807
  }
4590
4808
  ) : /* @__PURE__ */ jsxs27(
@@ -4596,31 +4814,23 @@ function SheetDrawer({
4596
4814
  className: sheetDrawerExpandButtonClassName,
4597
4815
  onClick: onExpand,
4598
4816
  children: [
4599
- /* @__PURE__ */ jsx28(ExpandActionIcon, { className: "size-[16px]" }),
4600
- /* @__PURE__ */ jsx28("span", { className: "hidden text-sm font-medium leading-normal md:inline", children: expandLabel })
4817
+ /* @__PURE__ */ jsx29(ExpandActionIcon, { className: "size-[16px]" }),
4818
+ /* @__PURE__ */ jsx29("span", { className: "hidden text-sm font-medium leading-normal md:inline", children: expandLabel })
4601
4819
  ]
4602
4820
  }
4603
4821
  ) : null,
4604
- /* @__PURE__ */ jsx28(
4605
- SheetClose,
4606
- {
4607
- "aria-label": closeLabel,
4608
- "data-slot": "sheet-drawer-close",
4609
- className: sheetDrawerCloseButtonClassName,
4610
- children: /* @__PURE__ */ jsx28(XIcon3, { className: "size-[16px]" })
4611
- }
4612
- )
4822
+ /* @__PURE__ */ jsx29(OverlayCloseButton, { label: closeLabel })
4613
4823
  ] })
4614
4824
  ] }),
4615
- /* @__PURE__ */ jsx28("div", { "data-slot": "sheet-drawer-body", className: sheetDrawerBodyClassName, children }),
4616
- footer ? /* @__PURE__ */ jsx28("div", { "data-slot": "sheet-drawer-footer", className: sheetDrawerFooterClassName, children: footer }) : null
4825
+ /* @__PURE__ */ jsx29("div", { "data-slot": "sheet-drawer-body", className: sheetDrawerBodyClassName, children }),
4826
+ footer ? /* @__PURE__ */ jsx29("div", { "data-slot": "sheet-drawer-footer", className: sheetDrawerFooterClassName, children: footer }) : null
4617
4827
  ]
4618
4828
  }
4619
4829
  ) });
4620
4830
  }
4621
4831
 
4622
4832
  // src/components/ui/filter-toolbar.tsx
4623
- import { Fragment as Fragment7, jsx as jsx29, jsxs as jsxs28 } from "react/jsx-runtime";
4833
+ import { Fragment as Fragment7, jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
4624
4834
  var collapsibleClassNames = {
4625
4835
  sm: {
4626
4836
  inline: "hidden @[640px]:flex",
@@ -4691,7 +4901,7 @@ var FilterToolbar = React26.forwardRef(
4691
4901
  const usesSheet = containerWidth !== null && containerWidth < 640;
4692
4902
  const collapseClasses = collapsibleClassNames[collapseBelow];
4693
4903
  const collapseTriggerLabel = hasAppliedFilters ? `${collapsedLabel}, ${activeFilterCount}\uAC1C \uC801\uC6A9` : collapsedLabel;
4694
- const clearFiltersButton = onClearFilters ? /* @__PURE__ */ jsx29(
4904
+ const clearFiltersButton = onClearFilters ? /* @__PURE__ */ jsx30(
4695
4905
  "button",
4696
4906
  {
4697
4907
  type: "button",
@@ -4701,7 +4911,7 @@ var FilterToolbar = React26.forwardRef(
4701
4911
  children: "\uD574\uC81C"
4702
4912
  }
4703
4913
  ) : null;
4704
- const collapsedContent = collapsible ? /* @__PURE__ */ jsx29(
4914
+ const collapsedContent = collapsible ? /* @__PURE__ */ jsx30(
4705
4915
  "div",
4706
4916
  {
4707
4917
  "data-slot": "filter-toolbar-collapsed-content",
@@ -4718,7 +4928,7 @@ var FilterToolbar = React26.forwardRef(
4718
4928
  collapseClasses.trigger
4719
4929
  ),
4720
4930
  children: [
4721
- /* @__PURE__ */ jsx29(
4931
+ /* @__PURE__ */ jsx30(
4722
4932
  IconButton,
4723
4933
  {
4724
4934
  ref: triggerRef,
@@ -4729,7 +4939,7 @@ var FilterToolbar = React26.forwardRef(
4729
4939
  onClick: () => handleOverlayOpenChange(true)
4730
4940
  }
4731
4941
  ),
4732
- hasAppliedFilters ? /* @__PURE__ */ jsx29(
4942
+ hasAppliedFilters ? /* @__PURE__ */ jsx30(
4733
4943
  "span",
4734
4944
  {
4735
4945
  "aria-hidden": "true",
@@ -4761,7 +4971,7 @@ var FilterToolbar = React26.forwardRef(
4761
4971
  "data-slot": "filter-toolbar-row",
4762
4972
  className: "flex min-h-[32px] w-full flex-wrap items-center justify-start gap-x-[var(--space-2)] gap-y-[var(--space-2)]",
4763
4973
  children: [
4764
- search ? /* @__PURE__ */ jsx29(
4974
+ search ? /* @__PURE__ */ jsx30(
4765
4975
  "div",
4766
4976
  {
4767
4977
  "data-slot": "filter-toolbar-search",
@@ -4771,7 +4981,7 @@ var FilterToolbar = React26.forwardRef(
4771
4981
  ) : null,
4772
4982
  collapsible && usesSheet ? collapseTrigger : null,
4773
4983
  collapsible && !usesSheet ? /* @__PURE__ */ jsxs28(Popover, { open: overlayOpen, onOpenChange: handleOverlayOpenChange, children: [
4774
- /* @__PURE__ */ jsx29(PopoverAnchor, { asChild: true, children: collapseTrigger }),
4984
+ /* @__PURE__ */ jsx30(PopoverAnchor, { asChild: true, children: collapseTrigger }),
4775
4985
  overlayOpen ? /* @__PURE__ */ jsxs28(
4776
4986
  PopoverContent,
4777
4987
  {
@@ -4781,14 +4991,14 @@ var FilterToolbar = React26.forwardRef(
4781
4991
  align: "start",
4782
4992
  className: "w-[320px]",
4783
4993
  children: [
4784
- /* @__PURE__ */ jsx29("div", { className: "mb-[var(--space-3)] text-sm font-semibold", children: "\uD544\uD130" }),
4994
+ /* @__PURE__ */ jsx30("div", { className: "mb-[var(--space-3)] text-sm font-semibold", children: "\uD544\uD130" }),
4785
4995
  collapsedContent,
4786
- clearFiltersButton ? /* @__PURE__ */ jsx29("div", { className: "mt-[var(--space-4)] flex justify-end", children: clearFiltersButton }) : null
4996
+ clearFiltersButton ? /* @__PURE__ */ jsx30("div", { className: "mt-[var(--space-4)] flex justify-end", children: clearFiltersButton }) : null
4787
4997
  ]
4788
4998
  }
4789
4999
  ) : null
4790
5000
  ] }) : null,
4791
- filters ? /* @__PURE__ */ jsx29(
5001
+ filters ? /* @__PURE__ */ jsx30(
4792
5002
  "div",
4793
5003
  {
4794
5004
  "data-slot": "filter-toolbar-filters",
@@ -4796,7 +5006,7 @@ var FilterToolbar = React26.forwardRef(
4796
5006
  children: filters
4797
5007
  }
4798
5008
  ) : null,
4799
- collapsible && !overlayOpen ? /* @__PURE__ */ jsx29(
5009
+ collapsible && !overlayOpen ? /* @__PURE__ */ jsx30(
4800
5010
  "div",
4801
5011
  {
4802
5012
  "data-slot": "filter-toolbar-collapsible",
@@ -4810,7 +5020,7 @@ var FilterToolbar = React26.forwardRef(
4810
5020
  ]
4811
5021
  }
4812
5022
  ) : null,
4813
- collapsible && usesSheet && overlayOpen ? /* @__PURE__ */ jsx29(
5023
+ collapsible && usesSheet && overlayOpen ? /* @__PURE__ */ jsx30(
4814
5024
  SheetDrawer,
4815
5025
  {
4816
5026
  open: overlayOpen,
@@ -4832,8 +5042,8 @@ var FilterToolbar = React26.forwardRef(
4832
5042
  "\uAC1C \uC801\uC6A9"
4833
5043
  ] }),
4834
5044
  onClearFilters ? /* @__PURE__ */ jsxs28(Fragment7, { children: [
4835
- /* @__PURE__ */ jsx29("span", { "aria-hidden": "true", children: " \xB7 " }),
4836
- /* @__PURE__ */ jsx29(
5045
+ /* @__PURE__ */ jsx30("span", { "aria-hidden": "true", children: " \xB7 " }),
5046
+ /* @__PURE__ */ jsx30(
4837
5047
  "button",
4838
5048
  {
4839
5049
  type: "button",
@@ -4852,7 +5062,7 @@ var FilterToolbar = React26.forwardRef(
4852
5062
  "data-slot": "filter-toolbar-meta",
4853
5063
  className: "flex min-w-0 flex-wrap items-center justify-end gap-[var(--space-2)]",
4854
5064
  children: [
4855
- resultSummary ? /* @__PURE__ */ jsx29(
5065
+ resultSummary ? /* @__PURE__ */ jsx30(
4856
5066
  "div",
4857
5067
  {
4858
5068
  "data-slot": "filter-toolbar-summary",
@@ -4860,8 +5070,8 @@ var FilterToolbar = React26.forwardRef(
4860
5070
  children: resultSummary
4861
5071
  }
4862
5072
  ) : null,
4863
- clearAction ? /* @__PURE__ */ jsx29("div", { "data-slot": "filter-toolbar-clear", className: "shrink-0", children: clearAction }) : null,
4864
- actions ? /* @__PURE__ */ jsx29(
5073
+ clearAction ? /* @__PURE__ */ jsx30("div", { "data-slot": "filter-toolbar-clear", className: "shrink-0", children: clearAction }) : null,
5074
+ actions ? /* @__PURE__ */ jsx30(
4865
5075
  "div",
4866
5076
  {
4867
5077
  "data-slot": "filter-toolbar-actions",
@@ -4889,7 +5099,7 @@ import * as React27 from "react";
4889
5099
  import { cva as cva11 } from "class-variance-authority";
4890
5100
  import { Check as Check3, Minus } from "lucide-react";
4891
5101
  import { Checkbox as CheckboxPrimitive } from "radix-ui";
4892
- import { jsx as jsx30, jsxs as jsxs29 } from "react/jsx-runtime";
5102
+ import { jsx as jsx31, jsxs as jsxs29 } from "react/jsx-runtime";
4893
5103
  var checkboxFieldVariants = cva11(
4894
5104
  "flex flex-col gap-[var(--space-1)]",
4895
5105
  {
@@ -5057,7 +5267,7 @@ var Checkbox = React27.forwardRef(
5057
5267
  onCheckedChange: handleCheckedChange,
5058
5268
  ...props,
5059
5269
  children: [
5060
- /* @__PURE__ */ jsx30(
5270
+ /* @__PURE__ */ jsx31(
5061
5271
  "span",
5062
5272
  {
5063
5273
  "aria-hidden": "true",
@@ -5066,12 +5276,12 @@ var Checkbox = React27.forwardRef(
5066
5276
  checkboxBoxVariants({ size }),
5067
5277
  checkboxGroupBoxVariants({ appearance })
5068
5278
  ),
5069
- children: /* @__PURE__ */ jsx30(
5279
+ children: /* @__PURE__ */ jsx31(
5070
5280
  CheckboxPrimitive.Indicator,
5071
5281
  {
5072
5282
  "data-slot": "checkbox-indicator",
5073
5283
  className: "flex items-center justify-center",
5074
- children: resolvedChecked === "indeterminate" ? /* @__PURE__ */ jsx30(Minus, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 }) : /* @__PURE__ */ jsx30(Check3, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 })
5284
+ children: resolvedChecked === "indeterminate" ? /* @__PURE__ */ jsx31(Minus, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 }) : /* @__PURE__ */ jsx31(Check3, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 })
5075
5285
  }
5076
5286
  )
5077
5287
  }
@@ -5085,7 +5295,7 @@ var Checkbox = React27.forwardRef(
5085
5295
  className: "text-sm font-medium leading-snug text-foreground group-disabled:text-text-disabled",
5086
5296
  children: [
5087
5297
  labelContent,
5088
- required ? /* @__PURE__ */ jsx30(
5298
+ required ? /* @__PURE__ */ jsx31(
5089
5299
  "span",
5090
5300
  {
5091
5301
  "aria-hidden": "true",
@@ -5097,7 +5307,7 @@ var Checkbox = React27.forwardRef(
5097
5307
  ]
5098
5308
  }
5099
5309
  ),
5100
- error ? /* @__PURE__ */ jsx30(
5310
+ error ? /* @__PURE__ */ jsx31(
5101
5311
  "span",
5102
5312
  {
5103
5313
  id: errorId,
@@ -5106,7 +5316,7 @@ var Checkbox = React27.forwardRef(
5106
5316
  className: "text-xs font-medium leading-normal text-[var(--error)]",
5107
5317
  children: error
5108
5318
  }
5109
- ) : description ? /* @__PURE__ */ jsx30(
5319
+ ) : description ? /* @__PURE__ */ jsx31(
5110
5320
  "span",
5111
5321
  {
5112
5322
  id: descriptionId,
@@ -5133,7 +5343,7 @@ var Checkbox = React27.forwardRef(
5133
5343
  className: checkboxFieldVariants({ fullWidth }),
5134
5344
  children: [
5135
5345
  /* @__PURE__ */ jsxs29("div", { className: "inline-flex items-center gap-[var(--space-3)]", children: [
5136
- /* @__PURE__ */ jsx30(
5346
+ /* @__PURE__ */ jsx31(
5137
5347
  CheckboxPrimitive.Root,
5138
5348
  {
5139
5349
  ref,
@@ -5149,18 +5359,18 @@ var Checkbox = React27.forwardRef(
5149
5359
  className: cn(checkboxRootVariants(), className),
5150
5360
  onCheckedChange: handleCheckedChange,
5151
5361
  ...props,
5152
- children: /* @__PURE__ */ jsx30(
5362
+ children: /* @__PURE__ */ jsx31(
5153
5363
  "span",
5154
5364
  {
5155
5365
  "aria-hidden": "true",
5156
5366
  "data-slot": "checkbox-box",
5157
5367
  className: checkboxBoxVariants({ size }),
5158
- children: /* @__PURE__ */ jsx30(
5368
+ children: /* @__PURE__ */ jsx31(
5159
5369
  CheckboxPrimitive.Indicator,
5160
5370
  {
5161
5371
  "data-slot": "checkbox-indicator",
5162
5372
  className: "flex items-center justify-center",
5163
- children: resolvedChecked === "indeterminate" ? /* @__PURE__ */ jsx30(Minus, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 }) : /* @__PURE__ */ jsx30(Check3, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 })
5373
+ children: resolvedChecked === "indeterminate" ? /* @__PURE__ */ jsx31(Minus, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 }) : /* @__PURE__ */ jsx31(Check3, { "aria-hidden": "true", size: 14, strokeWidth: 2.5 })
5164
5374
  }
5165
5375
  )
5166
5376
  }
@@ -5176,7 +5386,7 @@ var Checkbox = React27.forwardRef(
5176
5386
  className: labelClassName,
5177
5387
  children: [
5178
5388
  labelContent,
5179
- required ? /* @__PURE__ */ jsx30(
5389
+ required ? /* @__PURE__ */ jsx31(
5180
5390
  "span",
5181
5391
  {
5182
5392
  "aria-hidden": "true",
@@ -5189,7 +5399,7 @@ var Checkbox = React27.forwardRef(
5189
5399
  }
5190
5400
  ) : null
5191
5401
  ] }),
5192
- error ? /* @__PURE__ */ jsx30(
5402
+ error ? /* @__PURE__ */ jsx31(
5193
5403
  "p",
5194
5404
  {
5195
5405
  id: errorId,
@@ -5198,7 +5408,7 @@ var Checkbox = React27.forwardRef(
5198
5408
  className: "ml-[32px] text-xs font-medium leading-normal text-[var(--error)]",
5199
5409
  children: error
5200
5410
  }
5201
- ) : description ? /* @__PURE__ */ jsx30(
5411
+ ) : description ? /* @__PURE__ */ jsx31(
5202
5412
  "p",
5203
5413
  {
5204
5414
  id: descriptionId,
@@ -5218,7 +5428,7 @@ var Checkbox = React27.forwardRef(
5218
5428
  Checkbox.displayName = "Checkbox";
5219
5429
 
5220
5430
  // src/components/ui/data-table.tsx
5221
- import { jsx as jsx31, jsxs as jsxs30 } from "react/jsx-runtime";
5431
+ import { jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
5222
5432
  var dataTableVariants = cva12(
5223
5433
  [
5224
5434
  "relative overflow-hidden rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -5321,7 +5531,7 @@ function isInteractiveTarget(target) {
5321
5531
  function SortIcon({ sort, columnKey }) {
5322
5532
  const isActive = sort?.key === columnKey;
5323
5533
  if (!isActive) {
5324
- return /* @__PURE__ */ jsx31(
5534
+ return /* @__PURE__ */ jsx32(
5325
5535
  ChevronsUpDown,
5326
5536
  {
5327
5537
  "aria-hidden": "true",
@@ -5333,7 +5543,7 @@ function SortIcon({ sort, columnKey }) {
5333
5543
  );
5334
5544
  }
5335
5545
  const Icon = sort.dir === "asc" ? ChevronUp2 : ChevronDown3;
5336
- return /* @__PURE__ */ jsx31(
5546
+ return /* @__PURE__ */ jsx32(
5337
5547
  Icon,
5338
5548
  {
5339
5549
  "aria-hidden": "true",
@@ -5367,11 +5577,11 @@ function MobileSortControls({
5367
5577
  surfaceClassNames[surface]
5368
5578
  ),
5369
5579
  children: [
5370
- /* @__PURE__ */ jsx31("span", { className: "text-[12px] font-medium text-text-tertiary", children: "\uC815\uB82C" }),
5580
+ /* @__PURE__ */ jsx32("span", { className: "text-[12px] font-medium text-text-tertiary", children: "\uC815\uB82C" }),
5371
5581
  sortableColumns.map((column) => {
5372
5582
  const active = sortBy?.key === column.key;
5373
5583
  const nextSort = getNextSort(sortBy, column.key);
5374
- return /* @__PURE__ */ jsx31(
5584
+ return /* @__PURE__ */ jsx32(
5375
5585
  Button,
5376
5586
  {
5377
5587
  type: "button",
@@ -5382,8 +5592,8 @@ function MobileSortControls({
5382
5592
  className: active ? "border-[var(--border-strong)] bg-[var(--action-selected)] hover:border-[var(--border-strong)] hover:bg-[var(--action-selected)]" : void 0,
5383
5593
  onClick: () => onSortChange?.(column.key, nextSort),
5384
5594
  children: /* @__PURE__ */ jsxs30("span", { className: "inline-flex min-w-0 items-center gap-[var(--space-1)]", children: [
5385
- /* @__PURE__ */ jsx31("span", { className: "truncate", children: column.header }),
5386
- /* @__PURE__ */ jsx31(SortIcon, { sort: sortBy, columnKey: column.key })
5595
+ /* @__PURE__ */ jsx32("span", { className: "truncate", children: column.header }),
5596
+ /* @__PURE__ */ jsx32(SortIcon, { sort: sortBy, columnKey: column.key })
5387
5597
  ] })
5388
5598
  },
5389
5599
  column.key
@@ -5404,7 +5614,7 @@ function SkeletonRows({
5404
5614
  // 로딩 알림은 그 안의 row/cell 안에 둔다 — 종전에는 컨테이너가 role="status"라
5405
5615
  // aria-required-children(Critical)이 났다.
5406
5616
  /* @__PURE__ */ jsxs30("div", { role: "rowgroup", children: [
5407
- /* @__PURE__ */ jsx31("div", { role: "row", children: /* @__PURE__ */ jsx31("div", { role: "cell", "aria-colindex": 1, "aria-label": "\uB370\uC774\uD130 \uB85C\uB4DC \uC911", children: /* @__PURE__ */ jsx31("span", { role: "status", className: "sr-only", children: "\uB370\uC774\uD130 \uB85C\uB4DC \uC911" }) }) }),
5617
+ /* @__PURE__ */ jsx32("div", { role: "row", children: /* @__PURE__ */ jsx32("div", { role: "cell", "aria-colindex": 1, "aria-label": "\uB370\uC774\uD130 \uB85C\uB4DC \uC911", children: /* @__PURE__ */ jsx32("span", { role: "status", className: "sr-only", children: "\uB370\uC774\uD130 \uB85C\uB4DC \uC911" }) }) }),
5408
5618
  Array.from({ length: count }, (_, rowIndex) => /* @__PURE__ */ jsxs30(
5409
5619
  "div",
5410
5620
  {
@@ -5412,8 +5622,8 @@ function SkeletonRows({
5412
5622
  className: "grid min-h-[48px] items-center border-t border-[var(--border-subtle)]",
5413
5623
  style: { gridTemplateColumns },
5414
5624
  children: [
5415
- selectable ? /* @__PURE__ */ jsx31("div", { "aria-hidden": "true", className: "px-[var(--space-4)]" }) : null,
5416
- columns.map((column, columnIndex) => /* @__PURE__ */ jsx31("div", { className: "px-[var(--space-4)] py-[var(--space-2)]", children: /* @__PURE__ */ jsx31(
5625
+ selectable ? /* @__PURE__ */ jsx32("div", { "aria-hidden": "true", className: "px-[var(--space-4)]" }) : null,
5626
+ columns.map((column, columnIndex) => /* @__PURE__ */ jsx32("div", { className: "px-[var(--space-4)] py-[var(--space-2)]", children: /* @__PURE__ */ jsx32(
5417
5627
  "div",
5418
5628
  {
5419
5629
  className: cn(
@@ -5430,7 +5640,7 @@ function SkeletonRows({
5430
5640
  );
5431
5641
  }
5432
5642
  function MobileSkeletonCards({ count }) {
5433
- return /* @__PURE__ */ jsx31(
5643
+ return /* @__PURE__ */ jsx32(
5434
5644
  "div",
5435
5645
  {
5436
5646
  "data-slot": "data-table-mobile-skeleton",
@@ -5443,9 +5653,9 @@ function MobileSkeletonCards({ count }) {
5443
5653
  "data-slot": "data-table-mobile-skeleton-card",
5444
5654
  className: "flex flex-col gap-[var(--space-2)] border-t border-[var(--border-subtle)] px-[var(--space-4)] py-[var(--space-4)]",
5445
5655
  children: [
5446
- /* @__PURE__ */ jsx31("div", { className: "h-[14px] w-[72%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
5447
- /* @__PURE__ */ jsx31("div", { className: "h-[12px] w-[56%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
5448
- /* @__PURE__ */ jsx31("div", { className: "h-[12px] w-[64%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" })
5656
+ /* @__PURE__ */ jsx32("div", { className: "h-[14px] w-[72%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
5657
+ /* @__PURE__ */ jsx32("div", { className: "h-[12px] w-[56%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" }),
5658
+ /* @__PURE__ */ jsx32("div", { className: "h-[12px] w-[64%] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-inset)]" })
5449
5659
  ]
5450
5660
  },
5451
5661
  rowIndex
@@ -5513,7 +5723,7 @@ function DataTableRowView({
5513
5723
  onClick: handlers.onClick,
5514
5724
  onKeyDown: handlers.onKeyDown,
5515
5725
  children: [
5516
- selectable ? /* @__PURE__ */ jsx31("div", { role: "cell", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx31(
5726
+ selectable ? /* @__PURE__ */ jsx32("div", { role: "cell", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx32(
5517
5727
  Checkbox,
5518
5728
  {
5519
5729
  "aria-label": `${String(row[columns[0]?.key] ?? rowId)} \uD589 \uC120\uD0DD`,
@@ -5528,7 +5738,7 @@ function DataTableRowView({
5528
5738
  columns.map((column, columnIndex) => {
5529
5739
  const align = column.align ?? "left";
5530
5740
  const content = getRenderedCell(row, column);
5531
- return /* @__PURE__ */ jsx31(
5741
+ return /* @__PURE__ */ jsx32(
5532
5742
  "div",
5533
5743
  {
5534
5744
  "data-slot": "data-table-cell",
@@ -5539,7 +5749,7 @@ function DataTableRowView({
5539
5749
  column.tabular ? "font-[family-name:var(--font-display)] tabular-nums" : null,
5540
5750
  align === "right" ? "text-text-tertiary" : null
5541
5751
  ),
5542
- children: /* @__PURE__ */ jsx31("span", { className: "min-w-0 truncate", children: linked && columnIndex === 0 && LinkComponent ? /* @__PURE__ */ jsx31(LinkComponent, { href, "data-slot": "data-table-row-link", className: rowLinkClass, children: content }) : content })
5752
+ children: /* @__PURE__ */ jsx32("span", { className: "min-w-0 truncate", children: linked && columnIndex === 0 && LinkComponent ? /* @__PURE__ */ jsx32(LinkComponent, { href, "data-slot": "data-table-row-link", className: rowLinkClass, children: content }) : content })
5543
5753
  },
5544
5754
  column.key
5545
5755
  );
@@ -5594,7 +5804,7 @@ function DataTableMobileCardView({
5594
5804
  onKeyDown: handlers.onKeyDown,
5595
5805
  children: [
5596
5806
  /* @__PURE__ */ jsxs30("div", { className: "flex min-w-0 items-start gap-[var(--space-3)]", children: [
5597
- selectable ? /* @__PURE__ */ jsx31("div", { "data-slot": "data-table-mobile-card-select", className: "shrink-0 pt-[2px]", children: /* @__PURE__ */ jsx31(
5807
+ selectable ? /* @__PURE__ */ jsx32("div", { "data-slot": "data-table-mobile-card-select", className: "shrink-0 pt-[2px]", children: /* @__PURE__ */ jsx32(
5598
5808
  Checkbox,
5599
5809
  {
5600
5810
  "aria-label": `${primaryText} \uBAA8\uBC14\uC77C \uCE74\uB4DC \uC120\uD0DD`,
@@ -5606,16 +5816,16 @@ function DataTableMobileCardView({
5606
5816
  ] })
5607
5817
  }
5608
5818
  ) }) : null,
5609
- /* @__PURE__ */ jsx31(
5819
+ /* @__PURE__ */ jsx32(
5610
5820
  "div",
5611
5821
  {
5612
5822
  "data-slot": "data-table-mobile-card-primary",
5613
5823
  className: "min-w-0 flex-1 font-medium text-foreground",
5614
- children: linked && LinkComponent ? /* @__PURE__ */ jsx31(LinkComponent, { href, "data-slot": "data-table-row-link", className: rowLinkClass, children: primaryContent }) : primaryContent
5824
+ children: linked && LinkComponent ? /* @__PURE__ */ jsx32(LinkComponent, { href, "data-slot": "data-table-row-link", className: rowLinkClass, children: primaryContent }) : primaryContent
5615
5825
  }
5616
5826
  )
5617
5827
  ] }),
5618
- secondaryColumns.length > 0 ? /* @__PURE__ */ jsx31("dl", { className: "grid min-w-0 gap-[var(--space-2)]", children: secondaryColumns.map((column) => {
5828
+ secondaryColumns.length > 0 ? /* @__PURE__ */ jsx32("dl", { className: "grid min-w-0 gap-[var(--space-2)]", children: secondaryColumns.map((column) => {
5619
5829
  const align = column.align ?? "left";
5620
5830
  return /* @__PURE__ */ jsxs30(
5621
5831
  "div",
@@ -5623,8 +5833,8 @@ function DataTableMobileCardView({
5623
5833
  "data-slot": "data-table-mobile-card-field",
5624
5834
  className: "grid min-w-0 grid-cols-[minmax(0,0.42fr)_minmax(0,1fr)] gap-[var(--space-2)] text-[12px] leading-snug",
5625
5835
  children: [
5626
- /* @__PURE__ */ jsx31("dt", { className: "min-w-0 text-text-tertiary", children: /* @__PURE__ */ jsx31("span", { className: "truncate", children: column.header }) }),
5627
- /* @__PURE__ */ jsx31(
5836
+ /* @__PURE__ */ jsx32("dt", { className: "min-w-0 text-text-tertiary", children: /* @__PURE__ */ jsx32("span", { className: "truncate", children: column.header }) }),
5837
+ /* @__PURE__ */ jsx32(
5628
5838
  "dd",
5629
5839
  {
5630
5840
  className: cn(
@@ -5632,7 +5842,7 @@ function DataTableMobileCardView({
5632
5842
  alignmentClass[align],
5633
5843
  column.tabular ? "font-[family-name:var(--font-display)] tabular-nums" : null
5634
5844
  ),
5635
- children: /* @__PURE__ */ jsx31("span", { className: "min-w-0 truncate", children: getRenderedCell(row, column) })
5845
+ children: /* @__PURE__ */ jsx32("span", { className: "min-w-0 truncate", children: getRenderedCell(row, column) })
5636
5846
  }
5637
5847
  )
5638
5848
  ]
@@ -5923,7 +6133,7 @@ function DataTableInner({
5923
6133
  ),
5924
6134
  ...props,
5925
6135
  children: [
5926
- selectable && announceSelection ? /* @__PURE__ */ jsx31(
6136
+ selectable && announceSelection ? /* @__PURE__ */ jsx32(
5927
6137
  "div",
5928
6138
  {
5929
6139
  "data-slot": "data-table-selection-status",
@@ -5932,16 +6142,16 @@ function DataTableInner({
5932
6142
  children: selectedCount > 0 ? `${selectedCount.toLocaleString("ko-KR")}${selectionUnit} \uC120\uD0DD\uB428` : ""
5933
6143
  }
5934
6144
  ) : null,
5935
- loading && data.length > 0 ? /* @__PURE__ */ jsx31(
6145
+ loading && data.length > 0 ? /* @__PURE__ */ jsx32(
5936
6146
  "div",
5937
6147
  {
5938
6148
  "data-slot": "data-table-progress",
5939
6149
  "aria-hidden": "true",
5940
6150
  className: "absolute left-0 right-0 top-0 z-10 h-[2px] overflow-hidden bg-[var(--action-selected)]",
5941
- children: /* @__PURE__ */ jsx31("div", { className: "h-full w-1/3 animate-pulse bg-[var(--primary)]" })
6151
+ children: /* @__PURE__ */ jsx32("div", { className: "h-full w-1/3 animate-pulse bg-[var(--primary)]" })
5942
6152
  }
5943
6153
  ) : null,
5944
- /* @__PURE__ */ jsx31("div", { ref: desktopRef, "data-slot": "data-table-desktop", className: "max-md:hidden md:block", children: /* @__PURE__ */ jsxs30(
6154
+ /* @__PURE__ */ jsx32("div", { ref: desktopRef, "data-slot": "data-table-desktop", className: "max-md:hidden md:block", children: /* @__PURE__ */ jsxs30(
5945
6155
  "div",
5946
6156
  {
5947
6157
  role: "table",
@@ -5963,20 +6173,20 @@ function DataTableInner({
5963
6173
  ),
5964
6174
  style: { gridTemplateColumns },
5965
6175
  children: [
5966
- selectable ? /* @__PURE__ */ jsx31("div", { role: "columnheader", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx31(
6176
+ selectable ? /* @__PURE__ */ jsx32("div", { role: "columnheader", className: "px-[var(--space-4)]", children: /* @__PURE__ */ jsx32(
5967
6177
  Checkbox,
5968
6178
  {
5969
6179
  "aria-label": "\uC804\uCCB4 \uD589 \uC120\uD0DD",
5970
6180
  checked: partiallySelected ? "indeterminate" : allVisibleRowsSelected,
5971
6181
  onCheckedChange: (nextChecked) => toggleAllRows(nextChecked === true),
5972
- children: /* @__PURE__ */ jsx31("span", { className: "sr-only", children: "\uC804\uCCB4 \uD589 \uC120\uD0DD" })
6182
+ children: /* @__PURE__ */ jsx32("span", { className: "sr-only", children: "\uC804\uCCB4 \uD589 \uC120\uD0DD" })
5973
6183
  }
5974
6184
  ) }) : null,
5975
6185
  columns.map((column) => {
5976
6186
  const align = column.align ?? "left";
5977
6187
  const nextSort = getNextSort(sortBy, column.key);
5978
6188
  const ariaSort = sortBy?.key === column.key ? sortBy.dir === "asc" ? "ascending" : "descending" : void 0;
5979
- return /* @__PURE__ */ jsx31(
6189
+ return /* @__PURE__ */ jsx32(
5980
6190
  "div",
5981
6191
  {
5982
6192
  role: "columnheader",
@@ -5996,11 +6206,11 @@ function DataTableInner({
5996
6206
  ),
5997
6207
  onClick: () => onSortChange?.(column.key, nextSort),
5998
6208
  children: [
5999
- /* @__PURE__ */ jsx31("span", { className: "truncate", children: column.header }),
6000
- /* @__PURE__ */ jsx31(SortIcon, { sort: sortBy, columnKey: column.key })
6209
+ /* @__PURE__ */ jsx32("span", { className: "truncate", children: column.header }),
6210
+ /* @__PURE__ */ jsx32(SortIcon, { sort: sortBy, columnKey: column.key })
6001
6211
  ]
6002
6212
  }
6003
- ) : /* @__PURE__ */ jsx31("span", { className: "truncate", children: column.header })
6213
+ ) : /* @__PURE__ */ jsx32("span", { className: "truncate", children: column.header })
6004
6214
  },
6005
6215
  column.key
6006
6216
  );
@@ -6008,7 +6218,7 @@ function DataTableInner({
6008
6218
  ]
6009
6219
  }
6010
6220
  ),
6011
- loading && data.length === 0 ? /* @__PURE__ */ jsx31(
6221
+ loading && data.length === 0 ? /* @__PURE__ */ jsx32(
6012
6222
  SkeletonRows,
6013
6223
  {
6014
6224
  columns,
@@ -6019,7 +6229,7 @@ function DataTableInner({
6019
6229
  ) : data.length === 0 ? (
6020
6230
  /* role="table" 직계 자식은 row/rowgroup이어야 한다. data-slot과 테두리는
6021
6231
  그대로 유지해 시각 계약을 깨지 않는다(빈 상태에서도 표가 테두리를 그린다). */
6022
- /* @__PURE__ */ jsx31("div", { role: "rowgroup", children: /* @__PURE__ */ jsx31("div", { role: "row", children: /* @__PURE__ */ jsx31(
6232
+ /* @__PURE__ */ jsx32("div", { role: "rowgroup", children: /* @__PURE__ */ jsx32("div", { role: "row", children: /* @__PURE__ */ jsx32(
6023
6233
  "div",
6024
6234
  {
6025
6235
  role: "cell",
@@ -6029,9 +6239,9 @@ function DataTableInner({
6029
6239
  children: emptyState
6030
6240
  }
6031
6241
  ) }) })
6032
- ) : /* @__PURE__ */ jsx31("div", { ref: desktopListRef, role: "rowgroup", style: desktopSlice.style, children: desktopSlice.rows.map((row, index) => {
6242
+ ) : /* @__PURE__ */ jsx32("div", { ref: desktopListRef, role: "rowgroup", style: desktopSlice.style, children: desktopSlice.rows.map((row, index) => {
6033
6243
  const itemProps = getItemProps(row);
6034
- return /* @__PURE__ */ jsx31(
6244
+ return /* @__PURE__ */ jsx32(
6035
6245
  RowComponent,
6036
6246
  {
6037
6247
  ...itemProps,
@@ -6044,7 +6254,7 @@ function DataTableInner({
6044
6254
  ]
6045
6255
  }
6046
6256
  ) }),
6047
- /* @__PURE__ */ jsx31(
6257
+ /* @__PURE__ */ jsx32(
6048
6258
  MobileSortControls,
6049
6259
  {
6050
6260
  columns,
@@ -6054,14 +6264,14 @@ function DataTableInner({
6054
6264
  surface
6055
6265
  }
6056
6266
  ),
6057
- loading && data.length === 0 ? /* @__PURE__ */ jsx31(MobileSkeletonCards, { count: skeletonRowCount }) : data.length === 0 ? /* @__PURE__ */ jsx31(
6267
+ loading && data.length === 0 ? /* @__PURE__ */ jsx32(MobileSkeletonCards, { count: skeletonRowCount }) : data.length === 0 ? /* @__PURE__ */ jsx32(
6058
6268
  "div",
6059
6269
  {
6060
6270
  "data-slot": "data-table-mobile-empty",
6061
6271
  className: "border-t border-[var(--border-subtle)] p-[var(--space-4)] md:hidden",
6062
6272
  children: emptyState
6063
6273
  }
6064
- ) : /* @__PURE__ */ jsx31(
6274
+ ) : /* @__PURE__ */ jsx32(
6065
6275
  "div",
6066
6276
  {
6067
6277
  ref: mobileListRef,
@@ -6072,7 +6282,7 @@ function DataTableInner({
6072
6282
  style: mobileSlice.style,
6073
6283
  children: mobileSlice.rows.map((row, index) => {
6074
6284
  const itemProps = getItemProps(row);
6075
- return /* @__PURE__ */ jsx31(
6285
+ return /* @__PURE__ */ jsx32(
6076
6286
  CardComponent,
6077
6287
  {
6078
6288
  ...itemProps,
@@ -6094,21 +6304,21 @@ DataTable.displayName = "DataTable";
6094
6304
  // src/components/ui/dropdown-menu.tsx
6095
6305
  import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
6096
6306
  import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
6097
- import { jsx as jsx32, jsxs as jsxs31 } from "react/jsx-runtime";
6307
+ import { jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
6098
6308
  function DropdownMenu({
6099
6309
  ...props
6100
6310
  }) {
6101
- return /* @__PURE__ */ jsx32(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
6311
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
6102
6312
  }
6103
6313
  function DropdownMenuPortal({
6104
6314
  ...props
6105
6315
  }) {
6106
- return /* @__PURE__ */ jsx32(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
6316
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Portal, { "data-slot": "dropdown-menu-portal", ...props });
6107
6317
  }
6108
6318
  function DropdownMenuTrigger({
6109
6319
  ...props
6110
6320
  }) {
6111
- return /* @__PURE__ */ jsx32(
6321
+ return /* @__PURE__ */ jsx33(
6112
6322
  DropdownMenuPrimitive.Trigger,
6113
6323
  {
6114
6324
  "data-slot": "dropdown-menu-trigger",
@@ -6121,7 +6331,7 @@ function DropdownMenuContent({
6121
6331
  sideOffset = 4,
6122
6332
  ...props
6123
6333
  }) {
6124
- return /* @__PURE__ */ jsx32(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx32(
6334
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx33(
6125
6335
  DropdownMenuPrimitive.Content,
6126
6336
  {
6127
6337
  "data-slot": "dropdown-menu-content",
@@ -6144,7 +6354,7 @@ function DropdownMenuContent({
6144
6354
  function DropdownMenuGroup({
6145
6355
  ...props
6146
6356
  }) {
6147
- return /* @__PURE__ */ jsx32(DropdownMenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
6357
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Group, { "data-slot": "dropdown-menu-group", ...props });
6148
6358
  }
6149
6359
  function DropdownMenuItem({
6150
6360
  className,
@@ -6152,7 +6362,7 @@ function DropdownMenuItem({
6152
6362
  variant = "default",
6153
6363
  ...props
6154
6364
  }) {
6155
- return /* @__PURE__ */ jsx32(
6365
+ return /* @__PURE__ */ jsx33(
6156
6366
  DropdownMenuPrimitive.Item,
6157
6367
  {
6158
6368
  "data-slot": "dropdown-menu-item",
@@ -6195,7 +6405,7 @@ function DropdownMenuCheckboxItem({
6195
6405
  checked,
6196
6406
  ...props,
6197
6407
  children: [
6198
- /* @__PURE__ */ jsx32("span", { className: "pointer-events-none absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx32(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx32(CheckIcon, { size: 16 }) }) }),
6408
+ /* @__PURE__ */ jsx33("span", { className: "pointer-events-none absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx33(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx33(CheckIcon, { size: 16 }) }) }),
6199
6409
  children
6200
6410
  ]
6201
6411
  }
@@ -6204,7 +6414,7 @@ function DropdownMenuCheckboxItem({
6204
6414
  function DropdownMenuRadioGroup({
6205
6415
  ...props
6206
6416
  }) {
6207
- return /* @__PURE__ */ jsx32(
6417
+ return /* @__PURE__ */ jsx33(
6208
6418
  DropdownMenuPrimitive.RadioGroup,
6209
6419
  {
6210
6420
  "data-slot": "dropdown-menu-radio-group",
@@ -6232,7 +6442,7 @@ function DropdownMenuRadioItem({
6232
6442
  ),
6233
6443
  ...props,
6234
6444
  children: [
6235
- /* @__PURE__ */ jsx32("span", { className: "pointer-events-none absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx32(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx32(CircleIcon, { size: 8, className: "fill-current" }) }) }),
6445
+ /* @__PURE__ */ jsx33("span", { className: "pointer-events-none absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx33(DropdownMenuPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx33(CircleIcon, { size: 8, className: "fill-current" }) }) }),
6236
6446
  children
6237
6447
  ]
6238
6448
  }
@@ -6243,7 +6453,7 @@ function DropdownMenuLabel({
6243
6453
  inset,
6244
6454
  ...props
6245
6455
  }) {
6246
- return /* @__PURE__ */ jsx32(
6456
+ return /* @__PURE__ */ jsx33(
6247
6457
  DropdownMenuPrimitive.Label,
6248
6458
  {
6249
6459
  "data-slot": "dropdown-menu-label",
@@ -6260,7 +6470,7 @@ function DropdownMenuSeparator({
6260
6470
  className,
6261
6471
  ...props
6262
6472
  }) {
6263
- return /* @__PURE__ */ jsx32(
6473
+ return /* @__PURE__ */ jsx33(
6264
6474
  DropdownMenuPrimitive.Separator,
6265
6475
  {
6266
6476
  "data-slot": "dropdown-menu-separator",
@@ -6273,7 +6483,7 @@ function DropdownMenuShortcut({
6273
6483
  className,
6274
6484
  ...props
6275
6485
  }) {
6276
- return /* @__PURE__ */ jsx32(
6486
+ return /* @__PURE__ */ jsx33(
6277
6487
  "span",
6278
6488
  {
6279
6489
  "data-slot": "dropdown-menu-shortcut",
@@ -6288,7 +6498,7 @@ function DropdownMenuShortcut({
6288
6498
  function DropdownMenuSub({
6289
6499
  ...props
6290
6500
  }) {
6291
- return /* @__PURE__ */ jsx32(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
6501
+ return /* @__PURE__ */ jsx33(DropdownMenuPrimitive.Sub, { "data-slot": "dropdown-menu-sub", ...props });
6292
6502
  }
6293
6503
  function DropdownMenuSubTrigger({
6294
6504
  className,
@@ -6313,7 +6523,7 @@ function DropdownMenuSubTrigger({
6313
6523
  ...props,
6314
6524
  children: [
6315
6525
  children,
6316
- /* @__PURE__ */ jsx32(ChevronRightIcon, { className: "ml-auto", size: 16 })
6526
+ /* @__PURE__ */ jsx33(ChevronRightIcon, { className: "ml-auto", size: 16 })
6317
6527
  ]
6318
6528
  }
6319
6529
  );
@@ -6322,7 +6532,7 @@ function DropdownMenuSubContent({
6322
6532
  className,
6323
6533
  ...props
6324
6534
  }) {
6325
- return /* @__PURE__ */ jsx32(
6535
+ return /* @__PURE__ */ jsx33(
6326
6536
  DropdownMenuPrimitive.SubContent,
6327
6537
  {
6328
6538
  "data-slot": "dropdown-menu-sub-content",
@@ -6342,7 +6552,7 @@ function DropdownMenuSubContent({
6342
6552
  }
6343
6553
 
6344
6554
  // src/components/ui/context-menu.tsx
6345
- import { jsx as jsx33, jsxs as jsxs32 } from "react/jsx-runtime";
6555
+ import { jsx as jsx34, jsxs as jsxs32 } from "react/jsx-runtime";
6346
6556
  function ContextMenu({
6347
6557
  open,
6348
6558
  onOpenChange,
@@ -6354,7 +6564,7 @@ function ContextMenu({
6354
6564
  return null;
6355
6565
  }
6356
6566
  return /* @__PURE__ */ jsxs32(DropdownMenu, { open, onOpenChange, modal: false, children: [
6357
- /* @__PURE__ */ jsx33(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx33(
6567
+ /* @__PURE__ */ jsx34(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(
6358
6568
  "span",
6359
6569
  {
6360
6570
  "aria-hidden": "true",
@@ -6368,14 +6578,14 @@ function ContextMenu({
6368
6578
  }
6369
6579
  }
6370
6580
  ) }),
6371
- /* @__PURE__ */ jsx33(DropdownMenuContent, { ...contentProps, children })
6581
+ /* @__PURE__ */ jsx34(DropdownMenuContent, { ...contentProps, children })
6372
6582
  ] });
6373
6583
  }
6374
6584
 
6375
6585
  // src/components/ui/bulk-action-bar.tsx
6376
6586
  import * as React29 from "react";
6377
6587
  import { X as X3 } from "lucide-react";
6378
- import { jsx as jsx34, jsxs as jsxs33 } from "react/jsx-runtime";
6588
+ import { jsx as jsx35, jsxs as jsxs33 } from "react/jsx-runtime";
6379
6589
  function ActionButton({ action }) {
6380
6590
  const danger = action.variant === "destructive";
6381
6591
  const off = action.disabled;
@@ -6407,7 +6617,7 @@ function ActionButton({ action }) {
6407
6617
  whiteSpace: "nowrap"
6408
6618
  },
6409
6619
  children: [
6410
- Icon ? /* @__PURE__ */ jsx34(
6620
+ Icon ? /* @__PURE__ */ jsx35(
6411
6621
  Icon,
6412
6622
  {
6413
6623
  "aria-hidden": "true",
@@ -6422,7 +6632,7 @@ function ActionButton({ action }) {
6422
6632
  );
6423
6633
  }
6424
6634
  function Divider() {
6425
- return /* @__PURE__ */ jsx34(
6635
+ return /* @__PURE__ */ jsx35(
6426
6636
  "span",
6427
6637
  {
6428
6638
  "aria-hidden": "true",
@@ -6437,7 +6647,7 @@ function Divider() {
6437
6647
  );
6438
6648
  }
6439
6649
  function ClearButton({ onClear }) {
6440
- return /* @__PURE__ */ jsx34(
6650
+ return /* @__PURE__ */ jsx35(
6441
6651
  "button",
6442
6652
  {
6443
6653
  type: "button",
@@ -6459,7 +6669,7 @@ function ClearButton({ onClear }) {
6459
6669
  justifyContent: "center",
6460
6670
  borderRadius: "var(--radius-md)"
6461
6671
  },
6462
- children: /* @__PURE__ */ jsx34(X3, { size: 16, strokeWidth: 1.75, "aria-hidden": "true" })
6672
+ children: /* @__PURE__ */ jsx35(X3, { size: 16, strokeWidth: 1.75, "aria-hidden": "true" })
6463
6673
  }
6464
6674
  );
6465
6675
  }
@@ -6551,7 +6761,7 @@ function BulkActionBar({
6551
6761
  ...props
6552
6762
  }) {
6553
6763
  const inline = placement === "inline";
6554
- const trailingSlot = trailing !== void 0 && trailing !== null ? /* @__PURE__ */ jsx34(
6764
+ const trailingSlot = trailing !== void 0 && trailing !== null ? /* @__PURE__ */ jsx35(
6555
6765
  "div",
6556
6766
  {
6557
6767
  "data-slot": "bulk-action-bar-trailing",
@@ -6580,7 +6790,7 @@ function BulkActionBar({
6580
6790
  style: { ...idleLineStyle, overflow: "visible", ...style },
6581
6791
  ...props,
6582
6792
  children: [
6583
- /* @__PURE__ */ jsx34(
6793
+ /* @__PURE__ */ jsx35(
6584
6794
  "div",
6585
6795
  {
6586
6796
  role: "status",
@@ -6602,7 +6812,7 @@ function BulkActionBar({
6602
6812
  );
6603
6813
  }
6604
6814
  if (count === 0 && idleContent !== void 0) {
6605
- return /* @__PURE__ */ jsx34(
6815
+ return /* @__PURE__ */ jsx35(
6606
6816
  "div",
6607
6817
  {
6608
6818
  role: "status",
@@ -6619,7 +6829,7 @@ function BulkActionBar({
6619
6829
  if (count === 0 && emptyHint === void 0) {
6620
6830
  return null;
6621
6831
  }
6622
- const countLabel = /* @__PURE__ */ jsx34(
6832
+ const countLabel = /* @__PURE__ */ jsx35(
6623
6833
  "span",
6624
6834
  {
6625
6835
  "data-slot": "bulk-action-bar-count",
@@ -6636,7 +6846,7 @@ function BulkActionBar({
6636
6846
  children: count > 0 ? `${count.toLocaleString("ko-KR")}${unit} \uC120\uD0DD\uB428` : emptyHint
6637
6847
  }
6638
6848
  );
6639
- const summarySlot = summary !== void 0 && summary !== null ? /* @__PURE__ */ jsx34(
6849
+ const summarySlot = summary !== void 0 && summary !== null ? /* @__PURE__ */ jsx35(
6640
6850
  "span",
6641
6851
  {
6642
6852
  ref: setSummaryElement,
@@ -6670,7 +6880,7 @@ function BulkActionBar({
6670
6880
  children: compact ? compactSummary : summary
6671
6881
  }
6672
6882
  ) : null;
6673
- const actionGroup = /* @__PURE__ */ jsx34(
6883
+ const actionGroup = /* @__PURE__ */ jsx35(
6674
6884
  "div",
6675
6885
  {
6676
6886
  "data-slot": "bulk-action-bar-actions",
@@ -6682,7 +6892,7 @@ function BulkActionBar({
6682
6892
  justifyContent: "flex-end",
6683
6893
  gap: 2
6684
6894
  },
6685
- children: actions.map((action) => /* @__PURE__ */ jsx34(ActionButton, { action }, action.key))
6895
+ children: actions.map((action) => /* @__PURE__ */ jsx35(ActionButton, { action }, action.key))
6686
6896
  }
6687
6897
  );
6688
6898
  if (inline) {
@@ -6726,10 +6936,10 @@ function BulkActionBar({
6726
6936
  gap: "var(--space-1)"
6727
6937
  },
6728
6938
  children: [
6729
- count > 0 && actions.length > 0 ? /* @__PURE__ */ jsx34(Divider, {}) : null,
6939
+ count > 0 && actions.length > 0 ? /* @__PURE__ */ jsx35(Divider, {}) : null,
6730
6940
  actionGroup,
6731
- /* @__PURE__ */ jsx34(Divider, {}),
6732
- /* @__PURE__ */ jsx34(ClearButton, { onClear })
6941
+ /* @__PURE__ */ jsx35(Divider, {}),
6942
+ /* @__PURE__ */ jsx35(ClearButton, { onClear })
6733
6943
  ]
6734
6944
  }
6735
6945
  ),
@@ -6770,10 +6980,10 @@ function BulkActionBar({
6770
6980
  ]
6771
6981
  }
6772
6982
  ),
6773
- count > 0 && actions.length > 0 ? /* @__PURE__ */ jsx34(Divider, {}) : null,
6983
+ count > 0 && actions.length > 0 ? /* @__PURE__ */ jsx35(Divider, {}) : null,
6774
6984
  actionGroup,
6775
- /* @__PURE__ */ jsx34(Divider, {}),
6776
- /* @__PURE__ */ jsx34(ClearButton, { onClear }),
6985
+ /* @__PURE__ */ jsx35(Divider, {}),
6986
+ /* @__PURE__ */ jsx35(ClearButton, { onClear }),
6777
6987
  trailingSlot
6778
6988
  ]
6779
6989
  }
@@ -6781,29 +6991,11 @@ function BulkActionBar({
6781
6991
  }
6782
6992
 
6783
6993
  // src/components/ui/confirm-dialog.tsx
6784
- import * as React30 from "react";
6785
- import { Fragment as Fragment8, jsx as jsx35, jsxs as jsxs34 } from "react/jsx-runtime";
6786
- var confirmDialogContentClassName = cn(
6787
- "fixed left-1/2 top-1/2 z-[var(--z-modal)]",
6788
- "-translate-x-1/2 -translate-y-1/2",
6789
- "w-[calc(100vw-2rem)] max-w-[420px]",
6790
- "flex flex-col gap-[var(--space-6)]",
6791
- "bg-[var(--bg-surface)] border border-[var(--border)]",
6792
- "rounded-[var(--radius-lg)] p-[var(--space-6)] shadow-[var(--shadow-4)]",
6793
- "text-foreground"
6794
- );
6795
- var confirmDialogTitleClassName = cn(
6796
- "text-[18px] font-bold leading-snug text-foreground"
6797
- );
6798
- var confirmDialogDescriptionClassName = cn(
6799
- "break-keep text-[14px] leading-relaxed text-text-secondary"
6800
- );
6801
- var confirmDialogBodyClassName = "min-w-0 text-[14px] leading-relaxed text-text-secondary";
6802
- var confirmDialogFooterClassName = "flex items-center justify-end gap-[var(--space-3)]";
6994
+ import { Fragment as Fragment8, jsx as jsx36, jsxs as jsxs34 } from "react/jsx-runtime";
6803
6995
  function ConfirmDialog({
6804
6996
  open,
6805
6997
  onOpenChange,
6806
- title,
6998
+ title: title2,
6807
6999
  description,
6808
7000
  tone = "default",
6809
7001
  confirmLabel,
@@ -6814,71 +7006,51 @@ function ConfirmDialog({
6814
7006
  confirmDisabled = false,
6815
7007
  mobilePresentation = "center"
6816
7008
  }) {
6817
- const [pending, setPending] = React30.useState(false);
6818
- const busyRef = React30.useRef(false);
6819
- const isBusy = loading || pending;
6820
7009
  const returnFocus = useReturnFocus();
6821
- const handleOpenChange = React30.useCallback(
6822
- (nextOpen) => {
6823
- if (!nextOpen && isBusy) {
6824
- return;
6825
- }
6826
- onOpenChange(nextOpen);
6827
- },
6828
- [isBusy, onOpenChange]
6829
- );
6830
- const handleConfirm = React30.useCallback(async () => {
6831
- if (busyRef.current || loading || confirmDisabled) {
6832
- return;
6833
- }
6834
- busyRef.current = true;
6835
- setPending(true);
6836
- try {
6837
- await onConfirm();
6838
- onOpenChange(false);
6839
- } finally {
6840
- busyRef.current = false;
6841
- setPending(false);
6842
- }
6843
- }, [confirmDisabled, loading, onConfirm, onOpenChange]);
7010
+ const { isBusy, run, guardOpenChange } = useOverlayAction({
7011
+ action: onConfirm,
7012
+ onOpenChange,
7013
+ loading,
7014
+ disabled: confirmDisabled
7015
+ });
6844
7016
  const dialogBody = /* @__PURE__ */ jsxs34(Fragment8, { children: [
6845
- /* @__PURE__ */ jsx35("div", { className: "flex items-start justify-between gap-[var(--space-4)]", children: /* @__PURE__ */ jsxs34("div", { className: "min-w-0 space-y-[var(--space-2)]", children: [
6846
- /* @__PURE__ */ jsx35(
7017
+ /* @__PURE__ */ jsx36("div", { className: "flex items-start justify-between gap-[var(--space-4)]", children: /* @__PURE__ */ jsxs34("div", { className: "min-w-0 space-y-[var(--space-2)]", children: [
7018
+ /* @__PURE__ */ jsx36(
6847
7019
  DialogTitle,
6848
7020
  {
6849
7021
  "data-slot": "dialog-title",
6850
- className: confirmDialogTitleClassName,
6851
- children: title
7022
+ className: presetSurface.confirm.title,
7023
+ children: title2
6852
7024
  }
6853
7025
  ),
6854
- description ? /* @__PURE__ */ jsx35(
7026
+ description ? /* @__PURE__ */ jsx36(
6855
7027
  DialogDescription,
6856
7028
  {
6857
7029
  "data-slot": "dialog-description",
6858
- className: confirmDialogDescriptionClassName,
7030
+ className: presetSurface.confirm.description,
6859
7031
  children: description
6860
7032
  }
6861
7033
  ) : null
6862
7034
  ] }) }),
6863
- children != null ? /* @__PURE__ */ jsx35("div", { "data-slot": "confirm-dialog-body", className: confirmDialogBodyClassName, children }) : null,
7035
+ children != null ? /* @__PURE__ */ jsx36("div", { "data-slot": "confirm-dialog-body", className: presetSurface.confirm.body, children }) : null,
6864
7036
  /* @__PURE__ */ jsxs34(
6865
7037
  "div",
6866
7038
  {
6867
7039
  "data-slot": "dialog-footer",
6868
- className: confirmDialogFooterClassName,
7040
+ className: presetSurface.confirm.footer,
6869
7041
  children: [
6870
- /* @__PURE__ */ jsx35(
7042
+ /* @__PURE__ */ jsx36(
6871
7043
  Button,
6872
7044
  {
6873
7045
  variant: "secondary",
6874
7046
  size: "lg",
6875
7047
  className: footerButtonHitAreaClassName,
6876
7048
  disabled: isBusy,
6877
- onClick: () => handleOpenChange(false),
7049
+ onClick: () => guardOpenChange(false),
6878
7050
  children: cancelLabel
6879
7051
  }
6880
7052
  ),
6881
- /* @__PURE__ */ jsx35(
7053
+ /* @__PURE__ */ jsx36(
6882
7054
  Button,
6883
7055
  {
6884
7056
  variant: tone === "destructive" ? "destructive" : "primary",
@@ -6886,7 +7058,7 @@ function ConfirmDialog({
6886
7058
  className: footerButtonHitAreaClassName,
6887
7059
  loading: isBusy,
6888
7060
  disabled: confirmDisabled,
6889
- onClick: handleConfirm,
7061
+ onClick: run,
6890
7062
  children: confirmLabel
6891
7063
  }
6892
7064
  )
@@ -6894,16 +7066,16 @@ function ConfirmDialog({
6894
7066
  }
6895
7067
  )
6896
7068
  ] });
6897
- return /* @__PURE__ */ jsx35(Dialog, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs34(DialogPortal, { children: [
6898
- /* @__PURE__ */ jsx35(DialogOverlay, {}),
6899
- /* @__PURE__ */ jsx35(
7069
+ return /* @__PURE__ */ jsx36(Dialog, { open, onOpenChange: guardOpenChange, children: /* @__PURE__ */ jsxs34(DialogPortal, { children: [
7070
+ /* @__PURE__ */ jsx36(DialogOverlay, {}),
7071
+ /* @__PURE__ */ jsx36(
6900
7072
  DialogRawContent,
6901
7073
  {
6902
7074
  role: "alertdialog",
6903
7075
  "data-slot": "dialog-content",
6904
7076
  className: cn(
6905
- confirmDialogContentClassName,
6906
- mobilePresentation === "sheet" && dialogMobileSheetClassName
7077
+ presetSurface.confirm.content,
7078
+ mobilePresentation === "sheet" && bottomSheet.dialog
6907
7079
  ),
6908
7080
  style: mobilePresentation === "sheet" ? dialogMobileSheetStyle() : void 0,
6909
7081
  ...returnFocus,
@@ -6915,14 +7087,14 @@ function ConfirmDialog({
6915
7087
 
6916
7088
  // src/components/ui/separator.tsx
6917
7089
  import { Separator as SeparatorPrimitive } from "radix-ui";
6918
- import { jsx as jsx36 } from "react/jsx-runtime";
7090
+ import { jsx as jsx37 } from "react/jsx-runtime";
6919
7091
  function Separator2({
6920
7092
  className,
6921
7093
  orientation = "horizontal",
6922
7094
  decorative = true,
6923
7095
  ...props
6924
7096
  }) {
6925
- return /* @__PURE__ */ jsx36(
7097
+ return /* @__PURE__ */ jsx37(
6926
7098
  SeparatorPrimitive.Root,
6927
7099
  {
6928
7100
  "data-slot": "separator",
@@ -6939,13 +7111,13 @@ function Separator2({
6939
7111
 
6940
7112
  // src/components/ui/avatar.tsx
6941
7113
  import { Avatar as AvatarPrimitive } from "radix-ui";
6942
- import { jsx as jsx37 } from "react/jsx-runtime";
7114
+ import { jsx as jsx38 } from "react/jsx-runtime";
6943
7115
  function Avatar({
6944
7116
  className,
6945
7117
  size = "md",
6946
7118
  ...props
6947
7119
  }) {
6948
- return /* @__PURE__ */ jsx37(
7120
+ return /* @__PURE__ */ jsx38(
6949
7121
  AvatarPrimitive.Root,
6950
7122
  {
6951
7123
  "data-slot": "avatar",
@@ -6966,7 +7138,7 @@ function AvatarImage({
6966
7138
  className,
6967
7139
  ...props
6968
7140
  }) {
6969
- return /* @__PURE__ */ jsx37(
7141
+ return /* @__PURE__ */ jsx38(
6970
7142
  AvatarPrimitive.Image,
6971
7143
  {
6972
7144
  "data-slot": "avatar-image",
@@ -6991,7 +7163,7 @@ function AvatarFallback({
6991
7163
  ...props
6992
7164
  }) {
6993
7165
  const fallbackText = children ?? (name ? getAvatarFallbackText(name) : null);
6994
- return /* @__PURE__ */ jsx37(
7166
+ return /* @__PURE__ */ jsx38(
6995
7167
  AvatarPrimitive.Fallback,
6996
7168
  {
6997
7169
  "data-slot": "avatar-fallback",
@@ -7009,13 +7181,8 @@ function AvatarFallback({
7009
7181
  }
7010
7182
 
7011
7183
  // src/components/ui/action-sheet.tsx
7012
- import * as React31 from "react";
7013
- import { X as X4 } from "lucide-react";
7014
- import { jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
7015
- var actionSheetContentClassName = cn(
7016
- "gap-0 max-h-[85dvh] rounded-t-[var(--radius-lg)]",
7017
- "pb-[env(safe-area-inset-bottom)]"
7018
- );
7184
+ import * as React30 from "react";
7185
+ import { jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
7019
7186
  var actionSheetHeaderClassName = cn(
7020
7187
  "flex items-start gap-[var(--space-3)] px-[var(--space-4)] pt-[var(--space-4)] pb-[var(--space-3)]"
7021
7188
  );
@@ -7037,12 +7204,12 @@ var actionSheetItemClassName = cn(
7037
7204
  function ActionSheet({
7038
7205
  open,
7039
7206
  onOpenChange,
7040
- title,
7207
+ title: title2,
7041
7208
  description,
7042
7209
  items,
7043
7210
  closeLabel = "\uB2EB\uAE30"
7044
7211
  }) {
7045
- const pendingRef = React31.useRef(null);
7212
+ const pendingRef = React30.useRef(null);
7046
7213
  const returnFocus = useReturnFocus();
7047
7214
  const handleOpenChange = (nextOpen) => {
7048
7215
  pendingRef.current = null;
@@ -7058,24 +7225,24 @@ function ActionSheet({
7058
7225
  pendingRef.current = null;
7059
7226
  item?.onSelect();
7060
7227
  };
7061
- return /* @__PURE__ */ jsx38(Sheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs35(
7228
+ return /* @__PURE__ */ jsx39(Sheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs35(
7062
7229
  SheetContent,
7063
7230
  {
7064
7231
  side: "bottom",
7065
7232
  "data-slot": "action-sheet-content",
7066
- className: actionSheetContentClassName,
7233
+ className: bottomSheet.action,
7067
7234
  onOpenAutoFocus: returnFocus.onOpenAutoFocus,
7068
7235
  onCloseAutoFocus: handleCloseAutoFocus,
7069
7236
  ...description ? {} : { "aria-describedby": void 0 },
7070
7237
  children: [
7071
7238
  /* @__PURE__ */ jsxs35("div", { "data-slot": "action-sheet-header", className: actionSheetHeaderClassName, children: [
7072
7239
  /* @__PURE__ */ jsxs35("div", { className: "min-w-0 flex-1", children: [
7073
- /* @__PURE__ */ jsx38(SheetTitle, { className: actionSheetTitleClassName, children: title }),
7074
- description ? /* @__PURE__ */ jsx38(SheetDescription, { className: actionSheetDescriptionClassName, children: description }) : null
7240
+ /* @__PURE__ */ jsx39(SheetTitle, { className: actionSheetTitleClassName, children: title2 }),
7241
+ description ? /* @__PURE__ */ jsx39(SheetDescription, { className: actionSheetDescriptionClassName, children: description }) : null
7075
7242
  ] }),
7076
- /* @__PURE__ */ jsx38(SheetClose, { asChild: true, children: /* @__PURE__ */ jsx38(IconButton, { size: "sm", icon: X4, "aria-label": closeLabel }) })
7243
+ /* @__PURE__ */ jsx39(OverlayCloseButton, { label: closeLabel })
7077
7244
  ] }),
7078
- /* @__PURE__ */ jsx38("div", { "data-slot": "action-sheet-list", className: actionSheetListClassName, children: items.map((item) => {
7245
+ /* @__PURE__ */ jsx39("div", { "data-slot": "action-sheet-list", className: actionSheetListClassName, children: items.map((item) => {
7079
7246
  const Icon = item.icon;
7080
7247
  return /* @__PURE__ */ jsxs35(
7081
7248
  "button",
@@ -7087,8 +7254,8 @@ function ActionSheet({
7087
7254
  disabled: item.disabled,
7088
7255
  onClick: () => handleSelect(item),
7089
7256
  children: [
7090
- Icon ? /* @__PURE__ */ jsx38(Icon, { "aria-hidden": true, size: 17, strokeWidth: 1.75, className: "shrink-0" }) : null,
7091
- /* @__PURE__ */ jsx38("span", { className: "min-w-0 flex-1 break-keep", children: item.label })
7257
+ Icon ? /* @__PURE__ */ jsx39(Icon, { "aria-hidden": true, size: 17, strokeWidth: 1.75, className: "shrink-0" }) : null,
7258
+ /* @__PURE__ */ jsx39("span", { className: "min-w-0 flex-1 break-keep", children: item.label })
7092
7259
  ]
7093
7260
  },
7094
7261
  item.id
@@ -7100,8 +7267,8 @@ function ActionSheet({
7100
7267
  }
7101
7268
 
7102
7269
  // src/components/ui/badge.tsx
7103
- import * as React32 from "react";
7104
- import { jsx as jsx39, jsxs as jsxs36 } from "react/jsx-runtime";
7270
+ import * as React31 from "react";
7271
+ import { jsx as jsx40, jsxs as jsxs36 } from "react/jsx-runtime";
7105
7272
  var DOT = {
7106
7273
  error: "var(--semantic-error-fg)",
7107
7274
  warning: "var(--semantic-warning-fg)",
@@ -7110,7 +7277,7 @@ var DOT = {
7110
7277
  neutral: "var(--text-tertiary)",
7111
7278
  brand: "var(--accent-pop)"
7112
7279
  };
7113
- var Badge = React32.forwardRef(
7280
+ var Badge = React31.forwardRef(
7114
7281
  ({ tone = "neutral", className, children, ...props }, ref) => /* @__PURE__ */ jsxs36(
7115
7282
  "span",
7116
7283
  {
@@ -7125,7 +7292,7 @@ var Badge = React32.forwardRef(
7125
7292
  ),
7126
7293
  ...props,
7127
7294
  children: [
7128
- /* @__PURE__ */ jsx39(
7295
+ /* @__PURE__ */ jsx40(
7129
7296
  "span",
7130
7297
  {
7131
7298
  "aria-hidden": "true",
@@ -7142,8 +7309,8 @@ var Badge = React32.forwardRef(
7142
7309
  Badge.displayName = "Badge";
7143
7310
 
7144
7311
  // src/components/ui/two-tier-badge.tsx
7145
- import * as React33 from "react";
7146
- import { jsx as jsx40, jsxs as jsxs37 } from "react/jsx-runtime";
7312
+ import * as React32 from "react";
7313
+ import { jsx as jsx41, jsxs as jsxs37 } from "react/jsx-runtime";
7147
7314
  var FG = {
7148
7315
  neutral: "var(--text-secondary)",
7149
7316
  info: "var(--semantic-info-fg)",
@@ -7164,7 +7331,7 @@ var SEGMENT = {
7164
7331
  md: "gap-[7px] py-[var(--space-1)] px-[var(--space-3)] text-[14px]"
7165
7332
  };
7166
7333
  var DOT2 = { xs: 5, sm: 6, md: 7 };
7167
- var TwoTierBadge = React33.forwardRef(
7334
+ var TwoTierBadge = React32.forwardRef(
7168
7335
  ({ primary, secondary, tone = "neutral", emphasis = "subtle", size = "sm", showDot = false, className, style, ...props }, ref) => {
7169
7336
  const strong = emphasis === "strong";
7170
7337
  const fg = FG[tone];
@@ -7194,7 +7361,7 @@ var TwoTierBadge = React33.forwardRef(
7194
7361
  className: cn("inline-flex items-center whitespace-nowrap font-semibold", SEGMENT[size]),
7195
7362
  style: { color: fg, background: strong ? BG[tone] : "transparent" },
7196
7363
  children: [
7197
- showDot ? /* @__PURE__ */ jsx40(
7364
+ showDot ? /* @__PURE__ */ jsx41(
7198
7365
  "span",
7199
7366
  {
7200
7367
  "aria-hidden": "true",
@@ -7209,11 +7376,11 @@ var TwoTierBadge = React33.forwardRef(
7209
7376
  }
7210
7377
  }
7211
7378
  ) : null,
7212
- /* @__PURE__ */ jsx40("span", { children: primary })
7379
+ /* @__PURE__ */ jsx41("span", { children: primary })
7213
7380
  ]
7214
7381
  }
7215
7382
  ),
7216
- secondary != null ? /* @__PURE__ */ jsx40(
7383
+ secondary != null ? /* @__PURE__ */ jsx41(
7217
7384
  "span",
7218
7385
  {
7219
7386
  "data-slot": "two-tier-badge-secondary",
@@ -7234,8 +7401,8 @@ var TwoTierBadge = React33.forwardRef(
7234
7401
  TwoTierBadge.displayName = "TwoTierBadge";
7235
7402
 
7236
7403
  // src/components/ui/status-badge.tsx
7237
- import * as React34 from "react";
7238
- import { jsx as jsx41, jsxs as jsxs38 } from "react/jsx-runtime";
7404
+ import * as React33 from "react";
7405
+ import { jsx as jsx42, jsxs as jsxs38 } from "react/jsx-runtime";
7239
7406
  var ROLE = {
7240
7407
  error: "error",
7241
7408
  warning: "warning",
@@ -7264,7 +7431,7 @@ var SIZE = {
7264
7431
  sm: { cls: "gap-[6px] py-[var(--space-1)] px-[var(--space-2)] text-[12px]", dot: 6 },
7265
7432
  md: { cls: "gap-[var(--space-2)] py-[var(--space-1)] px-[14px] text-[14px]", dot: 7 }
7266
7433
  };
7267
- var StatusBadge = React34.forwardRef(
7434
+ var StatusBadge = React33.forwardRef(
7268
7435
  ({ status = "active", emphasis = "subtle", size = "sm", showDot = true, pulse = true, className, children, style, ...props }, ref) => {
7269
7436
  const role = ROLE[status];
7270
7437
  const fg = FG2[role];
@@ -7288,7 +7455,7 @@ var StatusBadge = React34.forwardRef(
7288
7455
  },
7289
7456
  ...props,
7290
7457
  children: [
7291
- showDot ? /* @__PURE__ */ jsx41(
7458
+ showDot ? /* @__PURE__ */ jsx42(
7292
7459
  "span",
7293
7460
  {
7294
7461
  "aria-hidden": "true",
@@ -7306,7 +7473,7 @@ var StatusBadge = React34.forwardRef(
7306
7473
  }
7307
7474
  ) : null,
7308
7475
  children,
7309
- /* @__PURE__ */ jsx41("style", { children: "@keyframes olun-status-pulse{0%,100%{opacity:1}50%{opacity:.4}}@media (prefers-reduced-motion: reduce){[data-slot=status-badge-dot]{animation:none!important}}" })
7476
+ /* @__PURE__ */ jsx42("style", { children: "@keyframes olun-status-pulse{0%,100%{opacity:1}50%{opacity:.4}}@media (prefers-reduced-motion: reduce){[data-slot=status-badge-dot]{animation:none!important}}" })
7310
7477
  ]
7311
7478
  }
7312
7479
  );
@@ -7315,9 +7482,9 @@ var StatusBadge = React34.forwardRef(
7315
7482
  StatusBadge.displayName = "StatusBadge";
7316
7483
 
7317
7484
  // src/components/ui/notification-badge.tsx
7318
- import * as React35 from "react";
7485
+ import * as React34 from "react";
7319
7486
  import { cva as cva13 } from "class-variance-authority";
7320
- import { jsx as jsx42 } from "react/jsx-runtime";
7487
+ import { jsx as jsx43 } from "react/jsx-runtime";
7321
7488
  var notificationBadgeVariants = cva13(
7322
7489
  [
7323
7490
  "inline-flex shrink-0 items-center justify-center rounded-[var(--radius-full)]",
@@ -7348,7 +7515,7 @@ function formatNotificationCount(count, max) {
7348
7515
  }
7349
7516
  return String(count);
7350
7517
  }
7351
- var NotificationBadge = React35.forwardRef(
7518
+ var NotificationBadge = React34.forwardRef(
7352
7519
  ({
7353
7520
  className,
7354
7521
  count,
@@ -7363,7 +7530,7 @@ var NotificationBadge = React35.forwardRef(
7363
7530
  }
7364
7531
  const normalizedMax = Math.max(1, Math.floor(max));
7365
7532
  const label = ariaLabel ?? (count > normalizedMax ? `\uC77D\uC9C0 \uC54A\uC740 \uC54C\uB9BC ${normalizedMax}\uAC1C \uC774\uC0C1` : `\uC77D\uC9C0 \uC54A\uC740 \uC54C\uB9BC ${count}\uAC1C`);
7366
- return /* @__PURE__ */ jsx42(
7533
+ return /* @__PURE__ */ jsx43(
7367
7534
  "span",
7368
7535
  {
7369
7536
  ref,
@@ -7381,9 +7548,9 @@ var NotificationBadge = React35.forwardRef(
7381
7548
  NotificationBadge.displayName = "NotificationBadge";
7382
7549
 
7383
7550
  // src/components/ui/empty-state.tsx
7384
- import * as React36 from "react";
7551
+ import * as React35 from "react";
7385
7552
  import { cva as cva14 } from "class-variance-authority";
7386
- import { jsx as jsx43, jsxs as jsxs39 } from "react/jsx-runtime";
7553
+ import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
7387
7554
  var emptyStateBaseVariants = cva14(
7388
7555
  [
7389
7556
  "flex flex-col items-center justify-center text-center",
@@ -7455,14 +7622,14 @@ var iconSize3 = {
7455
7622
  md: 20,
7456
7623
  lg: 24
7457
7624
  };
7458
- var EmptyState = React36.forwardRef(
7625
+ var EmptyState = React35.forwardRef(
7459
7626
  ({
7460
7627
  className,
7461
7628
  size = "md",
7462
7629
  tone = "neutral",
7463
7630
  surface,
7464
7631
  icon: Icon,
7465
- title,
7632
+ title: title2,
7466
7633
  description,
7467
7634
  hint,
7468
7635
  action,
@@ -7479,25 +7646,25 @@ var EmptyState = React36.forwardRef(
7479
7646
  className: cn(emptyStateVariants({ size, tone, surface, bordered, className })),
7480
7647
  ...props,
7481
7648
  children: [
7482
- Icon ? /* @__PURE__ */ jsx43(
7649
+ Icon ? /* @__PURE__ */ jsx44(
7483
7650
  "span",
7484
7651
  {
7485
7652
  "aria-hidden": "true",
7486
7653
  "data-slot": "empty-state-icon",
7487
7654
  className: emptyStateIconVariants({ size: resolvedSize }),
7488
- children: /* @__PURE__ */ jsx43(Icon, { size: iconSize3[resolvedSize], strokeWidth: 1.75 })
7655
+ children: /* @__PURE__ */ jsx44(Icon, { size: iconSize3[resolvedSize], strokeWidth: 1.75 })
7489
7656
  }
7490
7657
  ) : null,
7491
7658
  /* @__PURE__ */ jsxs39("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
7492
- /* @__PURE__ */ jsx43(
7659
+ /* @__PURE__ */ jsx44(
7493
7660
  "h2",
7494
7661
  {
7495
7662
  "data-slot": "empty-state-title",
7496
7663
  className: "break-keep text-base font-semibold leading-snug text-foreground",
7497
- children: title
7664
+ children: title2
7498
7665
  }
7499
7666
  ),
7500
- description ? /* @__PURE__ */ jsx43(
7667
+ description ? /* @__PURE__ */ jsx44(
7501
7668
  "p",
7502
7669
  {
7503
7670
  "data-slot": "empty-state-description",
@@ -7505,7 +7672,7 @@ var EmptyState = React36.forwardRef(
7505
7672
  children: description
7506
7673
  }
7507
7674
  ) : null,
7508
- hint ? /* @__PURE__ */ jsx43(
7675
+ hint ? /* @__PURE__ */ jsx44(
7509
7676
  "p",
7510
7677
  {
7511
7678
  "data-slot": "empty-state-hint",
@@ -7514,7 +7681,7 @@ var EmptyState = React36.forwardRef(
7514
7681
  }
7515
7682
  ) : null
7516
7683
  ] }),
7517
- action ? /* @__PURE__ */ jsx43("div", { "data-slot": "empty-state-action", className: "mt-[var(--space-2)]", children: action }) : null
7684
+ action ? /* @__PURE__ */ jsx44("div", { "data-slot": "empty-state-action", className: "mt-[var(--space-2)]", children: action }) : null
7518
7685
  ]
7519
7686
  }
7520
7687
  );
@@ -7523,10 +7690,10 @@ var EmptyState = React36.forwardRef(
7523
7690
  EmptyState.displayName = "EmptyState";
7524
7691
 
7525
7692
  // src/components/ui/error-state.tsx
7526
- import * as React37 from "react";
7693
+ import * as React36 from "react";
7527
7694
  import { AlertTriangle } from "lucide-react";
7528
7695
  import { cva as cva15 } from "class-variance-authority";
7529
- import { jsx as jsx44, jsxs as jsxs40 } from "react/jsx-runtime";
7696
+ import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
7530
7697
  var errorStateVariants = cva15(
7531
7698
  [
7532
7699
  "flex flex-col items-center justify-center text-center",
@@ -7548,12 +7715,12 @@ var errorStateVariants = cva15(
7548
7715
  }
7549
7716
  }
7550
7717
  );
7551
- var ErrorState = React37.forwardRef(
7718
+ var ErrorState = React36.forwardRef(
7552
7719
  ({
7553
7720
  className,
7554
7721
  size = "md",
7555
7722
  surface = "surface",
7556
- title = "\uBD88\uB7EC\uC624\uAE30 \uC2E4\uD328",
7723
+ title: title2 = "\uBD88\uB7EC\uC624\uAE30 \uC2E4\uD328",
7557
7724
  message = "\uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.",
7558
7725
  errorCode,
7559
7726
  onRetry,
@@ -7568,25 +7735,25 @@ var ErrorState = React37.forwardRef(
7568
7735
  className: cn(errorStateVariants({ size, surface, className })),
7569
7736
  ...props,
7570
7737
  children: [
7571
- /* @__PURE__ */ jsx44(
7738
+ /* @__PURE__ */ jsx45(
7572
7739
  "span",
7573
7740
  {
7574
7741
  "aria-hidden": "true",
7575
7742
  "data-slot": "error-state-icon",
7576
7743
  className: "inline-flex size-[48px] items-center justify-center rounded-[var(--radius-full)] bg-[var(--error-bg)] text-[var(--error)]",
7577
- children: /* @__PURE__ */ jsx44(AlertTriangle, { size: 24, strokeWidth: 1.75 })
7744
+ children: /* @__PURE__ */ jsx45(AlertTriangle, { size: 24, strokeWidth: 1.75 })
7578
7745
  }
7579
7746
  ),
7580
7747
  /* @__PURE__ */ jsxs40("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
7581
- /* @__PURE__ */ jsx44(
7748
+ /* @__PURE__ */ jsx45(
7582
7749
  "h2",
7583
7750
  {
7584
7751
  "data-slot": "error-state-title",
7585
7752
  className: "break-keep text-base font-semibold leading-snug text-foreground",
7586
- children: title
7753
+ children: title2
7587
7754
  }
7588
7755
  ),
7589
- /* @__PURE__ */ jsx44(
7756
+ /* @__PURE__ */ jsx45(
7590
7757
  "p",
7591
7758
  {
7592
7759
  "data-slot": "error-state-message",
@@ -7594,7 +7761,7 @@ var ErrorState = React37.forwardRef(
7594
7761
  children: message
7595
7762
  }
7596
7763
  ),
7597
- errorCode ? /* @__PURE__ */ jsx44(
7764
+ errorCode ? /* @__PURE__ */ jsx45(
7598
7765
  "p",
7599
7766
  {
7600
7767
  "data-slot": "error-state-code",
@@ -7603,7 +7770,7 @@ var ErrorState = React37.forwardRef(
7603
7770
  }
7604
7771
  ) : null
7605
7772
  ] }),
7606
- onRetry ? /* @__PURE__ */ jsx44(Button, { size: "sm", variant: "secondary", onClick: onRetry, children: retryLabel }) : null
7773
+ onRetry ? /* @__PURE__ */ jsx45(Button, { size: "sm", variant: "secondary", onClick: onRetry, children: retryLabel }) : null
7607
7774
  ]
7608
7775
  }
7609
7776
  )
@@ -7611,9 +7778,9 @@ var ErrorState = React37.forwardRef(
7611
7778
  ErrorState.displayName = "ErrorState";
7612
7779
 
7613
7780
  // src/components/ui/skeleton.tsx
7614
- import * as React38 from "react";
7781
+ import * as React37 from "react";
7615
7782
  import { cva as cva16 } from "class-variance-authority";
7616
- import { jsx as jsx45 } from "react/jsx-runtime";
7783
+ import { jsx as jsx46 } from "react/jsx-runtime";
7617
7784
  var skeletonVariants = cva16(
7618
7785
  [
7619
7786
  // bg-inset: light #F1F2F4 reads on white surfaces (bg-raised was white = invisible);
@@ -7657,8 +7824,8 @@ var spinnerVariants = cva16(
7657
7824
  }
7658
7825
  }
7659
7826
  );
7660
- var Skeleton = React38.forwardRef(
7661
- ({ className, shape, style, ...props }, ref) => /* @__PURE__ */ jsx45(
7827
+ var Skeleton = React37.forwardRef(
7828
+ ({ className, shape, style, ...props }, ref) => /* @__PURE__ */ jsx46(
7662
7829
  "div",
7663
7830
  {
7664
7831
  ref,
@@ -7671,15 +7838,15 @@ var Skeleton = React38.forwardRef(
7671
7838
  );
7672
7839
  Skeleton.displayName = "Skeleton";
7673
7840
  var defaultTextWidths = ["92%", "84%", "68%", "76%"];
7674
- var SkeletonText = React38.forwardRef(
7675
- ({ className, lines = 3, widths = defaultTextWidths, ...props }, ref) => /* @__PURE__ */ jsx45(
7841
+ var SkeletonText = React37.forwardRef(
7842
+ ({ className, lines = 3, widths = defaultTextWidths, ...props }, ref) => /* @__PURE__ */ jsx46(
7676
7843
  "div",
7677
7844
  {
7678
7845
  ref,
7679
7846
  "data-slot": "skeleton-text",
7680
7847
  className: cn("flex flex-col gap-[var(--space-2)]", className),
7681
7848
  ...props,
7682
- children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx45(
7849
+ children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx46(
7683
7850
  Skeleton,
7684
7851
  {
7685
7852
  shape: "text",
@@ -7691,7 +7858,7 @@ var SkeletonText = React38.forwardRef(
7691
7858
  )
7692
7859
  );
7693
7860
  SkeletonText.displayName = "SkeletonText";
7694
- var SkeletonRow = React38.forwardRef(
7861
+ var SkeletonRow = React37.forwardRef(
7695
7862
  ({
7696
7863
  className,
7697
7864
  columns,
@@ -7702,7 +7869,7 @@ var SkeletonRow = React38.forwardRef(
7702
7869
  }, ref) => {
7703
7870
  const rowCount = Math.max(5, count);
7704
7871
  const gridTemplateColumns = columns.map((column) => column.width ?? "1fr").join(" ");
7705
- return /* @__PURE__ */ jsx45(
7872
+ return /* @__PURE__ */ jsx46(
7706
7873
  "div",
7707
7874
  {
7708
7875
  ref,
@@ -7716,7 +7883,7 @@ var SkeletonRow = React38.forwardRef(
7716
7883
  className
7717
7884
  ),
7718
7885
  ...props,
7719
- children: Array.from({ length: rowCount }, (_, rowIndex) => /* @__PURE__ */ jsx45(
7886
+ children: Array.from({ length: rowCount }, (_, rowIndex) => /* @__PURE__ */ jsx46(
7720
7887
  "div",
7721
7888
  {
7722
7889
  "data-slot": "skeleton-row",
@@ -7724,11 +7891,11 @@ var SkeletonRow = React38.forwardRef(
7724
7891
  "grid min-h-[48px] items-center border-t border-[var(--border-subtle)] first:border-t-0"
7725
7892
  ),
7726
7893
  style: { gridTemplateColumns },
7727
- children: columns.map((column, columnIndex) => /* @__PURE__ */ jsx45(
7894
+ children: columns.map((column, columnIndex) => /* @__PURE__ */ jsx46(
7728
7895
  "div",
7729
7896
  {
7730
7897
  className: "px-[var(--space-4)] py-[var(--space-2)]",
7731
- children: /* @__PURE__ */ jsx45(
7898
+ children: /* @__PURE__ */ jsx46(
7732
7899
  Skeleton,
7733
7900
  {
7734
7901
  shape: "text",
@@ -7748,8 +7915,8 @@ var SkeletonRow = React38.forwardRef(
7748
7915
  }
7749
7916
  );
7750
7917
  SkeletonRow.displayName = "SkeletonRow";
7751
- var Spinner = React38.forwardRef(
7752
- ({ className, size, label = "\uB85C\uB529 \uC911", ...props }, ref) => /* @__PURE__ */ jsx45(
7918
+ var Spinner = React37.forwardRef(
7919
+ ({ className, size, label = "\uB85C\uB529 \uC911", ...props }, ref) => /* @__PURE__ */ jsx46(
7753
7920
  "span",
7754
7921
  {
7755
7922
  ref,
@@ -7764,12 +7931,12 @@ var Spinner = React38.forwardRef(
7764
7931
  Spinner.displayName = "Spinner";
7765
7932
 
7766
7933
  // src/components/ui/pagination.tsx
7767
- import * as React39 from "react";
7934
+ import * as React38 from "react";
7768
7935
  import { ChevronsLeft, ChevronLeft, ChevronRight as ChevronRight2, ChevronsRight } from "lucide-react";
7769
7936
  import { cva as cva17 } from "class-variance-authority";
7770
7937
 
7771
7938
  // src/components/ui/page-size-select.tsx
7772
- import { jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
7939
+ import { jsx as jsx47, jsxs as jsxs41 } from "react/jsx-runtime";
7773
7940
  var DEFAULT_OPTIONS = [10, 20, 50, 100];
7774
7941
  function PageSizeSelect({
7775
7942
  value,
@@ -7797,8 +7964,8 @@ function PageSizeSelect({
7797
7964
  className
7798
7965
  ),
7799
7966
  children: [
7800
- label != null ? /* @__PURE__ */ jsx46("span", { children: label }) : null,
7801
- /* @__PURE__ */ jsx46(
7967
+ label != null ? /* @__PURE__ */ jsx47("span", { children: label }) : null,
7968
+ /* @__PURE__ */ jsx47(
7802
7969
  Select,
7803
7970
  {
7804
7971
  id,
@@ -7820,7 +7987,7 @@ function PageSizeSelect({
7820
7987
  }
7821
7988
 
7822
7989
  // src/components/ui/pagination.tsx
7823
- import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
7990
+ import { jsx as jsx48, jsxs as jsxs42 } from "react/jsx-runtime";
7824
7991
  var paginationVariants = cva17(
7825
7992
  [
7826
7993
  "flex w-full flex-col gap-[var(--space-3)]",
@@ -7893,7 +8060,7 @@ function NavigationButton({
7893
8060
  icon: Icon,
7894
8061
  onPageChange
7895
8062
  }) {
7896
- return /* @__PURE__ */ jsx47(
8063
+ return /* @__PURE__ */ jsx48(
7897
8064
  "button",
7898
8065
  {
7899
8066
  "aria-label": label,
@@ -7901,11 +8068,11 @@ function NavigationButton({
7901
8068
  className: paginationControlVariants({ size }),
7902
8069
  type: "button",
7903
8070
  onClick: () => onPageChange?.(page),
7904
- children: /* @__PURE__ */ jsx47(Icon, { "aria-hidden": "true", "data-slot": "pagination-icon" })
8071
+ children: /* @__PURE__ */ jsx48(Icon, { "aria-hidden": "true", "data-slot": "pagination-icon" })
7905
8072
  }
7906
8073
  );
7907
8074
  }
7908
- var Pagination = React39.forwardRef(
8075
+ var Pagination = React38.forwardRef(
7909
8076
  ({
7910
8077
  className,
7911
8078
  size = "standard",
@@ -7941,8 +8108,8 @@ var Pagination = React39.forwardRef(
7941
8108
  ...props,
7942
8109
  children: [
7943
8110
  /* @__PURE__ */ jsxs42("div", { className: "flex flex-wrap items-center gap-[var(--space-3)]", children: [
7944
- /* @__PURE__ */ jsx47("span", { "data-slot": "pagination-total", className: "font-medium text-text-secondary", children: totalLabel(total) }),
7945
- showPageSize ? /* @__PURE__ */ jsx47("div", { "data-slot": "pagination-size", children: /* @__PURE__ */ jsx47(
8111
+ /* @__PURE__ */ jsx48("span", { "data-slot": "pagination-total", className: "font-medium text-text-secondary", children: totalLabel(total) }),
8112
+ showPageSize ? /* @__PURE__ */ jsx48("div", { "data-slot": "pagination-size", children: /* @__PURE__ */ jsx48(
7946
8113
  PageSizeSelect,
7947
8114
  {
7948
8115
  label: pageSizeLabel,
@@ -7960,7 +8127,7 @@ var Pagination = React39.forwardRef(
7960
8127
  "data-slot": "pagination-list",
7961
8128
  className: "flex items-center justify-center gap-[var(--space-1)]",
7962
8129
  children: [
7963
- /* @__PURE__ */ jsx47(
8130
+ /* @__PURE__ */ jsx48(
7964
8131
  NavigationButton,
7965
8132
  {
7966
8133
  label: "\uCCAB \uD398\uC774\uC9C0",
@@ -7971,7 +8138,7 @@ var Pagination = React39.forwardRef(
7971
8138
  onPageChange
7972
8139
  }
7973
8140
  ),
7974
- /* @__PURE__ */ jsx47(
8141
+ /* @__PURE__ */ jsx48(
7975
8142
  NavigationButton,
7976
8143
  {
7977
8144
  label: "\uC774\uC804 \uD398\uC774\uC9C0",
@@ -7983,7 +8150,7 @@ var Pagination = React39.forwardRef(
7983
8150
  }
7984
8151
  ),
7985
8152
  items.map(
7986
- (item, index) => item === "ellipsis" ? /* @__PURE__ */ jsx47(
8153
+ (item, index) => item === "ellipsis" ? /* @__PURE__ */ jsx48(
7987
8154
  "span",
7988
8155
  {
7989
8156
  "data-slot": "pagination-ellipsis",
@@ -7995,7 +8162,7 @@ var Pagination = React39.forwardRef(
7995
8162
  children: "..."
7996
8163
  },
7997
8164
  `ellipsis-${index}`
7998
- ) : /* @__PURE__ */ jsx47(
8165
+ ) : /* @__PURE__ */ jsx48(
7999
8166
  "button",
8000
8167
  {
8001
8168
  "aria-label": `${item} \uD398\uC774\uC9C0`,
@@ -8009,7 +8176,7 @@ var Pagination = React39.forwardRef(
8009
8176
  item
8010
8177
  )
8011
8178
  ),
8012
- /* @__PURE__ */ jsx47(
8179
+ /* @__PURE__ */ jsx48(
8013
8180
  NavigationButton,
8014
8181
  {
8015
8182
  label: "\uB2E4\uC74C \uD398\uC774\uC9C0",
@@ -8020,7 +8187,7 @@ var Pagination = React39.forwardRef(
8020
8187
  onPageChange
8021
8188
  }
8022
8189
  ),
8023
- /* @__PURE__ */ jsx47(
8190
+ /* @__PURE__ */ jsx48(
8024
8191
  NavigationButton,
8025
8192
  {
8026
8193
  label: "\uB9C8\uC9C0\uB9C9 \uD398\uC774\uC9C0",
@@ -8043,7 +8210,7 @@ Pagination.displayName = "Pagination";
8043
8210
 
8044
8211
  // src/components/ui/mode-toggle.tsx
8045
8212
  import { cva as cva18 } from "class-variance-authority";
8046
- import { jsx as jsx48, jsxs as jsxs43 } from "react/jsx-runtime";
8213
+ import { jsx as jsx49, jsxs as jsxs43 } from "react/jsx-runtime";
8047
8214
  var modeToggleVariants = cva18(
8048
8215
  [
8049
8216
  "inline-flex items-center rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -8073,7 +8240,7 @@ function ModeToggle({
8073
8240
  onChange,
8074
8241
  ...props
8075
8242
  }) {
8076
- return /* @__PURE__ */ jsx48(
8243
+ return /* @__PURE__ */ jsx49(
8077
8244
  "div",
8078
8245
  {
8079
8246
  role: "group",
@@ -8099,8 +8266,8 @@ function ModeToggle({
8099
8266
  }
8100
8267
  },
8101
8268
  children: [
8102
- Icon ? /* @__PURE__ */ jsx48(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
8103
- /* @__PURE__ */ jsx48("span", { children: option.label })
8269
+ Icon ? /* @__PURE__ */ jsx49(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
8270
+ /* @__PURE__ */ jsx49("span", { children: option.label })
8104
8271
  ]
8105
8272
  },
8106
8273
  option.value
@@ -8111,9 +8278,9 @@ function ModeToggle({
8111
8278
  }
8112
8279
 
8113
8280
  // src/components/ui/action-footer.tsx
8114
- import * as React40 from "react";
8281
+ import * as React39 from "react";
8115
8282
  import { cva as cva19 } from "class-variance-authority";
8116
- import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
8283
+ import { jsx as jsx50, jsxs as jsxs44 } from "react/jsx-runtime";
8117
8284
  var actionFooterVariants = cva19(
8118
8285
  [
8119
8286
  "flex flex-wrap items-center gap-[var(--space-4)] border-t border-[var(--border-subtle)]",
@@ -8184,7 +8351,7 @@ function getStatusLabel(status) {
8184
8351
  }
8185
8352
  }
8186
8353
  function renderAction(action) {
8187
- return /* @__PURE__ */ jsx49(
8354
+ return /* @__PURE__ */ jsx50(
8188
8355
  Button,
8189
8356
  {
8190
8357
  variant: action.variant,
@@ -8199,7 +8366,7 @@ function renderAction(action) {
8199
8366
  action.id ?? action.label
8200
8367
  );
8201
8368
  }
8202
- var ActionFooter = React40.forwardRef(
8369
+ var ActionFooter = React39.forwardRef(
8203
8370
  ({
8204
8371
  className,
8205
8372
  status,
@@ -8225,7 +8392,7 @@ var ActionFooter = React40.forwardRef(
8225
8392
  className: cn(actionFooterVariants({ position, surface, className })),
8226
8393
  ...props,
8227
8394
  children: [
8228
- destructiveActions.length > 0 ? /* @__PURE__ */ jsx49(
8395
+ destructiveActions.length > 0 ? /* @__PURE__ */ jsx50(
8229
8396
  "div",
8230
8397
  {
8231
8398
  "data-slot": "action-footer-destructive-actions",
@@ -8241,7 +8408,7 @@ var ActionFooter = React40.forwardRef(
8241
8408
  "aria-live": "polite",
8242
8409
  className: cn(actionFooterStatusVariants({ kind: status.kind })),
8243
8410
  children: [
8244
- /* @__PURE__ */ jsx49(
8411
+ /* @__PURE__ */ jsx50(
8245
8412
  "span",
8246
8413
  {
8247
8414
  "aria-hidden": "true",
@@ -8249,11 +8416,11 @@ var ActionFooter = React40.forwardRef(
8249
8416
  className: "size-[6px] shrink-0 rounded-[var(--radius-full)]"
8250
8417
  }
8251
8418
  ),
8252
- /* @__PURE__ */ jsx49("span", { className: "truncate", children: getStatusLabel(status) })
8419
+ /* @__PURE__ */ jsx50("span", { className: "truncate", children: getStatusLabel(status) })
8253
8420
  ]
8254
8421
  }
8255
8422
  ) : null,
8256
- /* @__PURE__ */ jsx49(
8423
+ /* @__PURE__ */ jsx50(
8257
8424
  "div",
8258
8425
  {
8259
8426
  "data-slot": "action-footer-main-actions",
@@ -8269,9 +8436,9 @@ var ActionFooter = React40.forwardRef(
8269
8436
  ActionFooter.displayName = "ActionFooter";
8270
8437
 
8271
8438
  // src/components/ui/toast.tsx
8272
- import * as React41 from "react";
8439
+ import * as React40 from "react";
8273
8440
  import { cva as cva20 } from "class-variance-authority";
8274
- import { jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
8441
+ import { jsx as jsx51, jsxs as jsxs45 } from "react/jsx-runtime";
8275
8442
  var DOT3 = {
8276
8443
  default: "var(--neutral)",
8277
8444
  success: "var(--success)",
@@ -8389,7 +8556,7 @@ var toast = {
8389
8556
  }
8390
8557
  };
8391
8558
  var Toast = toast;
8392
- var ToastRoot = React41.forwardRef(
8559
+ var ToastRoot = React40.forwardRef(
8393
8560
  ({
8394
8561
  className,
8395
8562
  id,
@@ -8406,10 +8573,10 @@ var ToastRoot = React41.forwardRef(
8406
8573
  ...props
8407
8574
  }, ref) => {
8408
8575
  const durationMs = getToastDuration({ message, variant, duration });
8409
- const onCloseRef = React41.useRef(onClose);
8576
+ const onCloseRef = React40.useRef(onClose);
8410
8577
  onCloseRef.current = onClose;
8411
- const timerRef = React41.useRef(null);
8412
- React41.useEffect(() => {
8578
+ const timerRef = React40.useRef(null);
8579
+ React40.useEffect(() => {
8413
8580
  if (!onCloseRef.current) return void 0;
8414
8581
  const timer = createToastTimer(durationMs, () => onCloseRef.current?.());
8415
8582
  timerRef.current = timer;
@@ -8446,7 +8613,7 @@ var ToastRoot = React41.forwardRef(
8446
8613
  },
8447
8614
  ...props,
8448
8615
  children: [
8449
- /* @__PURE__ */ jsx50(
8616
+ /* @__PURE__ */ jsx51(
8450
8617
  "span",
8451
8618
  {
8452
8619
  "aria-hidden": "true",
@@ -8456,7 +8623,7 @@ var ToastRoot = React41.forwardRef(
8456
8623
  }
8457
8624
  ),
8458
8625
  /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
8459
- /* @__PURE__ */ jsx50(
8626
+ /* @__PURE__ */ jsx51(
8460
8627
  "div",
8461
8628
  {
8462
8629
  "data-slot": "toast-message",
@@ -8464,7 +8631,7 @@ var ToastRoot = React41.forwardRef(
8464
8631
  children: message
8465
8632
  }
8466
8633
  ),
8467
- description ? /* @__PURE__ */ jsx50(
8634
+ description ? /* @__PURE__ */ jsx51(
8468
8635
  "div",
8469
8636
  {
8470
8637
  "data-slot": "toast-description",
@@ -8474,7 +8641,7 @@ var ToastRoot = React41.forwardRef(
8474
8641
  ) : null
8475
8642
  ] }),
8476
8643
  /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
8477
- action ? /* @__PURE__ */ jsx50(
8644
+ action ? /* @__PURE__ */ jsx51(
8478
8645
  Button,
8479
8646
  {
8480
8647
  "data-slot": "toast-action",
@@ -8484,7 +8651,7 @@ var ToastRoot = React41.forwardRef(
8484
8651
  children: action.label
8485
8652
  }
8486
8653
  ) : null,
8487
- /* @__PURE__ */ jsx50(
8654
+ /* @__PURE__ */ jsx51(
8488
8655
  "button",
8489
8656
  {
8490
8657
  type: "button",
@@ -8506,7 +8673,7 @@ var ToastRoot = React41.forwardRef(
8506
8673
  }
8507
8674
  );
8508
8675
  ToastRoot.displayName = "ToastRoot";
8509
- var ToastViewport = React41.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx50(
8676
+ var ToastViewport = React40.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx51(
8510
8677
  "ol",
8511
8678
  {
8512
8679
  ref,
@@ -8517,8 +8684,8 @@ var ToastViewport = React41.forwardRef(({ className, ...props }, ref) => /* @__P
8517
8684
  ));
8518
8685
  ToastViewport.displayName = "ToastViewport";
8519
8686
  function ToastProvider({ children, maxToasts = 3, className, ...props }) {
8520
- const [items, setItems] = React41.useState([]);
8521
- React41.useEffect(
8687
+ const [items, setItems] = React40.useState([]);
8688
+ React40.useEffect(
8522
8689
  () => toast.subscribe((nextItems) => {
8523
8690
  setItems(limitToasts(nextItems, maxToasts));
8524
8691
  }),
@@ -8526,15 +8693,15 @@ function ToastProvider({ children, maxToasts = 3, className, ...props }) {
8526
8693
  );
8527
8694
  return /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-provider", className, ...props, children: [
8528
8695
  children,
8529
- /* @__PURE__ */ jsx50(ToastViewport, { children: items.map((item) => /* @__PURE__ */ jsx50("li", { children: /* @__PURE__ */ jsx50(ToastRoot, { ...item, onClose: () => toast.dismiss(item.id) }) }, item.id)) })
8696
+ /* @__PURE__ */ jsx51(ToastViewport, { children: items.map((item) => /* @__PURE__ */ jsx51("li", { children: /* @__PURE__ */ jsx51(ToastRoot, { ...item, onClose: () => toast.dismiss(item.id) }) }, item.id)) })
8530
8697
  ] });
8531
8698
  }
8532
8699
 
8533
8700
  // src/components/ui/otp-field.tsx
8534
- import * as React42 from "react";
8701
+ import * as React41 from "react";
8535
8702
  import { cva as cva21 } from "class-variance-authority";
8536
8703
  import { AlertCircle as AlertCircle4 } from "lucide-react";
8537
- import { Fragment as Fragment9, jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
8704
+ import { Fragment as Fragment9, jsx as jsx52, jsxs as jsxs46 } from "react/jsx-runtime";
8538
8705
  var otpFieldVariants = cva21("flex w-full min-w-0 flex-col gap-[var(--space-3)]", {
8539
8706
  variants: {
8540
8707
  size: {
@@ -8661,7 +8828,7 @@ function fillDigitsFromIndex(slots, index, inserted, length) {
8661
8828
  focusIndex: Math.min(cursor, length - 1)
8662
8829
  };
8663
8830
  }
8664
- var OTPField = React42.forwardRef(
8831
+ var OTPField = React41.forwardRef(
8665
8832
  ({
8666
8833
  className,
8667
8834
  defaultValue,
@@ -8683,24 +8850,24 @@ var OTPField = React42.forwardRef(
8683
8850
  required,
8684
8851
  ...props
8685
8852
  }, ref) => {
8686
- const generatedId = React42.useId();
8853
+ const generatedId = React41.useId();
8687
8854
  const fieldId = id ?? generatedId;
8688
8855
  const labelId = `${fieldId}-label`;
8689
8856
  const helperId = helperText ? `${fieldId}-helper` : void 0;
8690
8857
  const errorId = errorText ? `${fieldId}-error` : void 0;
8691
8858
  const resolvedState = invalid || errorText ? "error" : "default";
8692
8859
  const isControlled = value !== void 0;
8693
- const [uncontrolledSlots, setUncontrolledSlots] = React42.useState(
8860
+ const [uncontrolledSlots, setUncontrolledSlots] = React41.useState(
8694
8861
  () => toDigitsArray(onlyDigits(defaultValue, length), length)
8695
8862
  );
8696
- const resolvedSlots = React42.useMemo(
8863
+ const resolvedSlots = React41.useMemo(
8697
8864
  () => isControlled ? toDigitsArray(onlyDigits(value, length), length) : uncontrolledSlots,
8698
8865
  [isControlled, length, uncontrolledSlots, value]
8699
8866
  );
8700
8867
  const resolvedValue = joinDigits(resolvedSlots).slice(0, length);
8701
- const cellsRef = React42.useRef([]);
8868
+ const cellsRef = React41.useRef([]);
8702
8869
  const groupDescribedBy = [helperId, errorId].filter(Boolean).join(" ") || void 0;
8703
- const setResolvedValue = React42.useCallback(
8870
+ const setResolvedValue = React41.useCallback(
8704
8871
  (nextSlots, focusIndex) => {
8705
8872
  const normalizedSlots = nextSlots.slice(0, length);
8706
8873
  const normalizedValue = joinDigits(normalizedSlots).slice(0, length);
@@ -8740,11 +8907,11 @@ var OTPField = React42.forwardRef(
8740
8907
  className: "text-sm font-medium leading-snug text-foreground",
8741
8908
  children: [
8742
8909
  label,
8743
- required ? /* @__PURE__ */ jsx51("span", { "aria-hidden": "true", className: "ml-1 font-bold text-[var(--error)]", children: "*" }) : null
8910
+ required ? /* @__PURE__ */ jsx52("span", { "aria-hidden": "true", className: "ml-1 font-bold text-[var(--error)]", children: "*" }) : null
8744
8911
  ]
8745
8912
  }
8746
8913
  ),
8747
- /* @__PURE__ */ jsx51(
8914
+ /* @__PURE__ */ jsx52(
8748
8915
  "div",
8749
8916
  {
8750
8917
  "data-slot": "otp-field-group",
@@ -8754,7 +8921,7 @@ var OTPField = React42.forwardRef(
8754
8921
  children: Array.from({ length }, (_, index) => {
8755
8922
  const digit = resolvedSlots[index] ?? "";
8756
8923
  const inputId = `${fieldId}-cell-${index + 1}`;
8757
- return /* @__PURE__ */ jsx51(
8924
+ return /* @__PURE__ */ jsx52(
8758
8925
  "input",
8759
8926
  {
8760
8927
  ref: (node) => {
@@ -8849,7 +9016,7 @@ var OTPField = React42.forwardRef(
8849
9016
  })
8850
9017
  }
8851
9018
  ),
8852
- helperText || errorText ? /* @__PURE__ */ jsx51(
9019
+ helperText || errorText ? /* @__PURE__ */ jsx52(
8853
9020
  "p",
8854
9021
  {
8855
9022
  id: errorText ? errorId : helperId,
@@ -8857,7 +9024,7 @@ var OTPField = React42.forwardRef(
8857
9024
  "data-kind": errorText ? "error" : "helper",
8858
9025
  className: otpFieldMessageVariants({ state: resolvedState }),
8859
9026
  children: errorText ? /* @__PURE__ */ jsxs46(Fragment9, { children: [
8860
- /* @__PURE__ */ jsx51(
9027
+ /* @__PURE__ */ jsx52(
8861
9028
  AlertCircle4,
8862
9029
  {
8863
9030
  "aria-hidden": "true",
@@ -8865,11 +9032,11 @@ var OTPField = React42.forwardRef(
8865
9032
  strokeWidth: 2
8866
9033
  }
8867
9034
  ),
8868
- /* @__PURE__ */ jsx51("span", { children: errorText })
8869
- ] }) : /* @__PURE__ */ jsx51("span", { children: helperText })
9035
+ /* @__PURE__ */ jsx52("span", { children: errorText })
9036
+ ] }) : /* @__PURE__ */ jsx52("span", { children: helperText })
8870
9037
  }
8871
9038
  ) : null,
8872
- name ? /* @__PURE__ */ jsx51(
9039
+ name ? /* @__PURE__ */ jsx52(
8873
9040
  "input",
8874
9041
  {
8875
9042
  "aria-hidden": "true",
@@ -8890,10 +9057,10 @@ var OTPField = React42.forwardRef(
8890
9057
  OTPField.displayName = "OTPField";
8891
9058
 
8892
9059
  // src/components/ui/search-field.tsx
8893
- import * as React43 from "react";
8894
- import { Search, X as X5 } from "lucide-react";
9060
+ import * as React42 from "react";
9061
+ import { Search, X as X4 } from "lucide-react";
8895
9062
  import { cva as cva22 } from "class-variance-authority";
8896
- import { jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
9063
+ import { jsx as jsx53, jsxs as jsxs47 } from "react/jsx-runtime";
8897
9064
  var searchFieldVariants = cva22("relative flex w-full items-center", {
8898
9065
  variants: {
8899
9066
  size: {
@@ -8958,7 +9125,7 @@ var iconSize4 = {
8958
9125
  function hasVisibleValue(value) {
8959
9126
  return typeof value === "string" ? value.length > 0 : value !== void 0;
8960
9127
  }
8961
- var SearchField = React43.forwardRef(
9128
+ var SearchField = React42.forwardRef(
8962
9129
  ({
8963
9130
  className,
8964
9131
  inputMode = "search",
@@ -8974,12 +9141,12 @@ var SearchField = React43.forwardRef(
8974
9141
  ...props
8975
9142
  }, ref) => {
8976
9143
  const resolvedSize = size ?? "md";
8977
- const inputRef = React43.useRef(null);
8978
- const [hasText, setHasText] = React43.useState(
9144
+ const inputRef = React42.useRef(null);
9145
+ const [hasText, setHasText] = React42.useState(
8979
9146
  () => hasVisibleValue(value ?? defaultValue)
8980
9147
  );
8981
- React43.useImperativeHandle(ref, () => inputRef.current);
8982
- React43.useEffect(() => {
9148
+ React42.useImperativeHandle(ref, () => inputRef.current);
9149
+ React42.useEffect(() => {
8983
9150
  if (value !== void 0) {
8984
9151
  setHasText(hasVisibleValue(value));
8985
9152
  }
@@ -8999,7 +9166,7 @@ var SearchField = React43.forwardRef(
8999
9166
  "data-size": resolvedSize,
9000
9167
  className: cn(searchFieldVariants({ size, className })),
9001
9168
  children: [
9002
- /* @__PURE__ */ jsx52(
9169
+ /* @__PURE__ */ jsx53(
9003
9170
  Search,
9004
9171
  {
9005
9172
  "aria-hidden": "true",
@@ -9009,7 +9176,7 @@ var SearchField = React43.forwardRef(
9009
9176
  strokeWidth: resolvedSize === "sm" ? 2 : 1.75
9010
9177
  }
9011
9178
  ),
9012
- /* @__PURE__ */ jsx52(
9179
+ /* @__PURE__ */ jsx53(
9013
9180
  "input",
9014
9181
  {
9015
9182
  ref: inputRef,
@@ -9030,7 +9197,7 @@ var SearchField = React43.forwardRef(
9030
9197
  ...props
9031
9198
  }
9032
9199
  ),
9033
- showClear ? /* @__PURE__ */ jsx52(
9200
+ showClear ? /* @__PURE__ */ jsx53(
9034
9201
  "button",
9035
9202
  {
9036
9203
  type: "button",
@@ -9038,7 +9205,7 @@ var SearchField = React43.forwardRef(
9038
9205
  "data-slot": "search-field-clear",
9039
9206
  className: "absolute right-[8px] top-1/2 inline-flex size-[var(--space-4)] -translate-y-1/2 cursor-pointer items-center justify-center rounded-[var(--radius-full)] text-text-tertiary transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]",
9040
9207
  onClick: clearInput,
9041
- children: /* @__PURE__ */ jsx52(X5, { "aria-hidden": "true", size: 16, strokeWidth: 1.75 })
9208
+ children: /* @__PURE__ */ jsx53(X4, { "aria-hidden": "true", size: 16, strokeWidth: 1.75 })
9042
9209
  }
9043
9210
  ) : null
9044
9211
  ]
@@ -9049,9 +9216,9 @@ var SearchField = React43.forwardRef(
9049
9216
  SearchField.displayName = "SearchField";
9050
9217
 
9051
9218
  // src/components/ui/checkbox-group.tsx
9052
- import * as React44 from "react";
9219
+ import * as React43 from "react";
9053
9220
  import { cva as cva23 } from "class-variance-authority";
9054
- import { jsx as jsx53 } from "react/jsx-runtime";
9221
+ import { jsx as jsx54 } from "react/jsx-runtime";
9055
9222
  var checkboxGroupVariants = cva23("gap-[var(--space-2)]", {
9056
9223
  variants: {
9057
9224
  appearance: {
@@ -9077,7 +9244,7 @@ var checkboxGroupVariants = cva23("gap-[var(--space-2)]", {
9077
9244
  function toSelectionSet(value) {
9078
9245
  return new Set(value ?? []);
9079
9246
  }
9080
- var CheckboxGroup = React44.forwardRef(
9247
+ var CheckboxGroup = React43.forwardRef(
9081
9248
  ({
9082
9249
  className,
9083
9250
  children,
@@ -9093,14 +9260,14 @@ var CheckboxGroup = React44.forwardRef(
9093
9260
  ...props
9094
9261
  }, ref) => {
9095
9262
  const isControlled = value != null;
9096
- const [uncontrolledValue, setUncontrolledValue] = React44.useState(
9263
+ const [uncontrolledValue, setUncontrolledValue] = React43.useState(
9097
9264
  () => toSelectionSet(defaultValue)
9098
9265
  );
9099
- const selectedValues = React44.useMemo(
9266
+ const selectedValues = React43.useMemo(
9100
9267
  () => isControlled ? toSelectionSet(value) : uncontrolledValue,
9101
9268
  [isControlled, uncontrolledValue, value]
9102
9269
  );
9103
- const toggleValue = React44.useCallback(
9270
+ const toggleValue = React43.useCallback(
9104
9271
  (itemValue, checked) => {
9105
9272
  const nextValues = new Set(selectedValues);
9106
9273
  if (checked) {
@@ -9116,7 +9283,7 @@ var CheckboxGroup = React44.forwardRef(
9116
9283
  },
9117
9284
  [isControlled, onValueChange, selectedValues]
9118
9285
  );
9119
- const contextValue = React44.useMemo(
9286
+ const contextValue = React43.useMemo(
9120
9287
  () => ({
9121
9288
  appearance,
9122
9289
  density,
@@ -9127,7 +9294,7 @@ var CheckboxGroup = React44.forwardRef(
9127
9294
  }),
9128
9295
  [appearance, density, disabled, name, selectedValues, toggleValue]
9129
9296
  );
9130
- return /* @__PURE__ */ jsx53(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx53(
9297
+ return /* @__PURE__ */ jsx54(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx54(
9131
9298
  "div",
9132
9299
  {
9133
9300
  ref,
@@ -9151,11 +9318,11 @@ var CheckboxGroup = React44.forwardRef(
9151
9318
  CheckboxGroup.displayName = "CheckboxGroup";
9152
9319
 
9153
9320
  // src/components/ui/radio-group.tsx
9154
- import * as React45 from "react";
9321
+ import * as React44 from "react";
9155
9322
  import { cva as cva24 } from "class-variance-authority";
9156
9323
  import { Circle } from "lucide-react";
9157
9324
  import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
9158
- import { jsx as jsx54, jsxs as jsxs48 } from "react/jsx-runtime";
9325
+ import { jsx as jsx55, jsxs as jsxs48 } from "react/jsx-runtime";
9159
9326
  var radioGroupVariants = cva24("gap-[var(--space-2)]", {
9160
9327
  variants: {
9161
9328
  appearance: {
@@ -9244,11 +9411,11 @@ var radioControlVariants = cva24(
9244
9411
  }
9245
9412
  }
9246
9413
  );
9247
- var RadioGroupContext = React45.createContext({
9414
+ var RadioGroupContext = React44.createContext({
9248
9415
  appearance: "plain",
9249
9416
  density: "comfortable"
9250
9417
  });
9251
- var RadioGroup = React45.forwardRef(
9418
+ var RadioGroup = React44.forwardRef(
9252
9419
  ({
9253
9420
  className,
9254
9421
  children,
@@ -9259,11 +9426,11 @@ var RadioGroup = React45.forwardRef(
9259
9426
  required,
9260
9427
  ...props
9261
9428
  }, ref) => {
9262
- const contextValue = React45.useMemo(
9429
+ const contextValue = React44.useMemo(
9263
9430
  () => ({ appearance, density }),
9264
9431
  [appearance, density]
9265
9432
  );
9266
- return /* @__PURE__ */ jsx54(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx54(
9433
+ return /* @__PURE__ */ jsx55(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx55(
9267
9434
  RadioGroupPrimitive.Root,
9268
9435
  {
9269
9436
  ref,
@@ -9286,9 +9453,9 @@ var RadioGroup = React45.forwardRef(
9286
9453
  }
9287
9454
  );
9288
9455
  RadioGroup.displayName = "RadioGroup";
9289
- var Radio = React45.forwardRef(({ className, children, description, id, ...props }, ref) => {
9290
- const { appearance, density } = React45.useContext(RadioGroupContext);
9291
- const generatedId = React45.useId();
9456
+ var Radio = React44.forwardRef(({ className, children, description, id, ...props }, ref) => {
9457
+ const { appearance, density } = React44.useContext(RadioGroupContext);
9458
+ const generatedId = React44.useId();
9292
9459
  const radioId = id ?? generatedId;
9293
9460
  const labelId = `${radioId}-label`;
9294
9461
  const descriptionId = description ? `${radioId}-description` : void 0;
@@ -9303,24 +9470,24 @@ var Radio = React45.forwardRef(({ className, children, description, id, ...props
9303
9470
  className: cn(radioVariants({ appearance, density }), className),
9304
9471
  ...props,
9305
9472
  children: [
9306
- /* @__PURE__ */ jsx54(
9473
+ /* @__PURE__ */ jsx55(
9307
9474
  "span",
9308
9475
  {
9309
9476
  "aria-hidden": "true",
9310
9477
  "data-slot": "radio-control",
9311
9478
  className: radioControlVariants({ appearance }),
9312
- children: /* @__PURE__ */ jsx54(
9479
+ children: /* @__PURE__ */ jsx55(
9313
9480
  RadioGroupPrimitive.Indicator,
9314
9481
  {
9315
9482
  "data-slot": "radio-indicator",
9316
9483
  className: "flex items-center justify-center",
9317
- children: /* @__PURE__ */ jsx54(Circle, { "aria-hidden": "true", size: 8, fill: "currentColor" })
9484
+ children: /* @__PURE__ */ jsx55(Circle, { "aria-hidden": "true", size: 8, fill: "currentColor" })
9318
9485
  }
9319
9486
  )
9320
9487
  }
9321
9488
  ),
9322
9489
  /* @__PURE__ */ jsxs48("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
9323
- /* @__PURE__ */ jsx54(
9490
+ /* @__PURE__ */ jsx55(
9324
9491
  "span",
9325
9492
  {
9326
9493
  id: labelId,
@@ -9332,7 +9499,7 @@ var Radio = React45.forwardRef(({ className, children, description, id, ...props
9332
9499
  children
9333
9500
  }
9334
9501
  ),
9335
- description ? /* @__PURE__ */ jsx54(
9502
+ description ? /* @__PURE__ */ jsx55(
9336
9503
  "span",
9337
9504
  {
9338
9505
  id: descriptionId,
@@ -9350,7 +9517,7 @@ Radio.displayName = "Radio";
9350
9517
 
9351
9518
  // src/components/ui/scroll-area.tsx
9352
9519
  import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
9353
- import { jsx as jsx55, jsxs as jsxs49 } from "react/jsx-runtime";
9520
+ import { jsx as jsx56, jsxs as jsxs49 } from "react/jsx-runtime";
9354
9521
  function ScrollArea({
9355
9522
  className,
9356
9523
  children,
@@ -9363,7 +9530,7 @@ function ScrollArea({
9363
9530
  className: cn("relative", className),
9364
9531
  ...props,
9365
9532
  children: [
9366
- /* @__PURE__ */ jsx55(
9533
+ /* @__PURE__ */ jsx56(
9367
9534
  ScrollAreaPrimitive.Viewport,
9368
9535
  {
9369
9536
  "data-slot": "scroll-area-viewport",
@@ -9371,8 +9538,8 @@ function ScrollArea({
9371
9538
  children
9372
9539
  }
9373
9540
  ),
9374
- /* @__PURE__ */ jsx55(ScrollBar, {}),
9375
- /* @__PURE__ */ jsx55(ScrollAreaPrimitive.Corner, {})
9541
+ /* @__PURE__ */ jsx56(ScrollBar, {}),
9542
+ /* @__PURE__ */ jsx56(ScrollAreaPrimitive.Corner, {})
9376
9543
  ]
9377
9544
  }
9378
9545
  );
@@ -9382,7 +9549,7 @@ function ScrollBar({
9382
9549
  orientation = "vertical",
9383
9550
  ...props
9384
9551
  }) {
9385
- return /* @__PURE__ */ jsx55(
9552
+ return /* @__PURE__ */ jsx56(
9386
9553
  ScrollAreaPrimitive.ScrollAreaScrollbar,
9387
9554
  {
9388
9555
  "data-slot": "scroll-area-scrollbar",
@@ -9394,7 +9561,7 @@ function ScrollBar({
9394
9561
  className
9395
9562
  ),
9396
9563
  ...props,
9397
- children: /* @__PURE__ */ jsx55(
9564
+ children: /* @__PURE__ */ jsx56(
9398
9565
  ScrollAreaPrimitive.ScrollAreaThumb,
9399
9566
  {
9400
9567
  "data-slot": "scroll-area-thumb",
@@ -9406,7 +9573,7 @@ function ScrollBar({
9406
9573
  }
9407
9574
 
9408
9575
  // src/components/ui/progress.tsx
9409
- import { jsx as jsx56 } from "react/jsx-runtime";
9576
+ import { jsx as jsx57 } from "react/jsx-runtime";
9410
9577
  var progressFillByStatus = {
9411
9578
  active: "bg-[var(--primary)]",
9412
9579
  success: "bg-[var(--success)]",
@@ -9427,7 +9594,7 @@ function Progress({
9427
9594
  const clamped = Math.max(0, Math.min(safeMax, value));
9428
9595
  const percent = clamped / safeMax * 100;
9429
9596
  const w = typeof width === "number" ? `${width}px` : width;
9430
- return /* @__PURE__ */ jsx56(
9597
+ return /* @__PURE__ */ jsx57(
9431
9598
  "div",
9432
9599
  {
9433
9600
  role: "progressbar",
@@ -9441,7 +9608,7 @@ function Progress({
9441
9608
  ),
9442
9609
  style: { width: w, height: `${height}px`, ...style },
9443
9610
  ...props,
9444
- children: /* @__PURE__ */ jsx56(
9611
+ children: /* @__PURE__ */ jsx57(
9445
9612
  "div",
9446
9613
  {
9447
9614
  className: cn(
@@ -9456,10 +9623,10 @@ function Progress({
9456
9623
  }
9457
9624
 
9458
9625
  // src/components/ui/tree-view.tsx
9459
- import * as React46 from "react";
9626
+ import * as React45 from "react";
9460
9627
  import { ChevronRight as ChevronRight3 } from "lucide-react";
9461
9628
  import { cva as cva25 } from "class-variance-authority";
9462
- import { jsx as jsx57, jsxs as jsxs50 } from "react/jsx-runtime";
9629
+ import { jsx as jsx58, jsxs as jsxs50 } from "react/jsx-runtime";
9463
9630
  var treeViewVariants = cva25(
9464
9631
  "m-0 list-none p-[var(--space-1)] text-body-sm text-foreground"
9465
9632
  );
@@ -9562,27 +9729,27 @@ function TreeView({
9562
9729
  ...rest
9563
9730
  }) {
9564
9731
  const isExpandedControlled = expandedIds !== void 0;
9565
- const [internalExpanded, setInternalExpanded] = React46.useState(
9732
+ const [internalExpanded, setInternalExpanded] = React45.useState(
9566
9733
  () => defaultExpandedIds ?? []
9567
9734
  );
9568
9735
  const expandedList = isExpandedControlled ? expandedIds : internalExpanded;
9569
- const expandedSet = React46.useMemo(() => new Set(expandedList), [expandedList]);
9570
- const items = React46.useMemo(
9736
+ const expandedSet = React45.useMemo(() => new Set(expandedList), [expandedList]);
9737
+ const items = React45.useMemo(
9571
9738
  () => flattenVisibleNodes(nodes, getChildren, expandedSet),
9572
9739
  [nodes, getChildren, expandedSet]
9573
9740
  );
9574
- const [focusedId, setFocusedId] = React46.useState(null);
9741
+ const [focusedId, setFocusedId] = React45.useState(null);
9575
9742
  const visibleIds = items.map((item) => item.id);
9576
9743
  const activeId = focusedId && visibleIds.includes(focusedId) ? focusedId : selectedId && visibleIds.includes(selectedId) ? selectedId : visibleIds[0] ?? null;
9577
- const itemRefs = React46.useRef(/* @__PURE__ */ new Map());
9578
- const commitExpanded = React46.useCallback(
9744
+ const itemRefs = React45.useRef(/* @__PURE__ */ new Map());
9745
+ const commitExpanded = React45.useCallback(
9579
9746
  (next) => {
9580
9747
  if (!isExpandedControlled) setInternalExpanded(next);
9581
9748
  onExpandedChange?.(next);
9582
9749
  },
9583
9750
  [isExpandedControlled, onExpandedChange]
9584
9751
  );
9585
- const setExpanded = React46.useCallback(
9752
+ const setExpanded = React45.useCallback(
9586
9753
  (id, expand) => {
9587
9754
  const has = expandedSet.has(id);
9588
9755
  if (expand && !has) {
@@ -9593,7 +9760,7 @@ function TreeView({
9593
9760
  },
9594
9761
  [commitExpanded, expandedList, expandedSet]
9595
9762
  );
9596
- const focusItem = React46.useCallback((id) => {
9763
+ const focusItem = React45.useCallback((id) => {
9597
9764
  setFocusedId(id);
9598
9765
  itemRefs.current.get(id)?.focus();
9599
9766
  }, []);
@@ -9663,7 +9830,7 @@ function TreeView({
9663
9830
  },
9664
9831
  className: treeItemRowVariants({ selected }),
9665
9832
  children: [
9666
- hasChildren ? /* @__PURE__ */ jsx57(
9833
+ hasChildren ? /* @__PURE__ */ jsx58(
9667
9834
  "span",
9668
9835
  {
9669
9836
  "data-slot": "treeitem-toggle",
@@ -9673,7 +9840,7 @@ function TreeView({
9673
9840
  setExpanded(node.id, !expanded);
9674
9841
  },
9675
9842
  className: "flex size-[var(--space-4)] shrink-0 items-center justify-center text-text-tertiary",
9676
- children: /* @__PURE__ */ jsx57(
9843
+ children: /* @__PURE__ */ jsx58(
9677
9844
  ChevronRight3,
9678
9845
  {
9679
9846
  "aria-hidden": "true",
@@ -9686,7 +9853,7 @@ function TreeView({
9686
9853
  }
9687
9854
  )
9688
9855
  }
9689
- ) : /* @__PURE__ */ jsx57(
9856
+ ) : /* @__PURE__ */ jsx58(
9690
9857
  "span",
9691
9858
  {
9692
9859
  "data-slot": "treeitem-spacer",
@@ -9694,18 +9861,18 @@ function TreeView({
9694
9861
  className: "size-[var(--space-4)] shrink-0"
9695
9862
  }
9696
9863
  ),
9697
- /* @__PURE__ */ jsx57("span", { className: "flex min-w-0 flex-1 items-center gap-[var(--space-2)]", children: renderItem(node, itemState) })
9864
+ /* @__PURE__ */ jsx58("span", { className: "flex min-w-0 flex-1 items-center gap-[var(--space-2)]", children: renderItem(node, itemState) })
9698
9865
  ]
9699
9866
  }
9700
9867
  ),
9701
- hasChildren && expanded && children ? /* @__PURE__ */ jsx57("ul", { role: "group", "data-slot": "tree-group", className: "m-0 list-none p-0", children: renderLevel(children, depth + 1) }) : null
9868
+ hasChildren && expanded && children ? /* @__PURE__ */ jsx58("ul", { role: "group", "data-slot": "tree-group", className: "m-0 list-none p-0", children: renderLevel(children, depth + 1) }) : null
9702
9869
  ]
9703
9870
  },
9704
9871
  node.id
9705
9872
  );
9706
9873
  });
9707
9874
  }
9708
- return /* @__PURE__ */ jsx57(
9875
+ return /* @__PURE__ */ jsx58(
9709
9876
  "ul",
9710
9877
  {
9711
9878
  role: "tree",
@@ -9721,8 +9888,11 @@ function TreeView({
9721
9888
  }
9722
9889
 
9723
9890
  // src/components/branding/olun-logo.tsx
9724
- import { jsx as jsx58, jsxs as jsxs51 } from "react/jsx-runtime";
9891
+ import { jsx as jsx59, jsxs as jsxs51 } from "react/jsx-runtime";
9892
+ var SYMBOL_LARGE = { stroke: 24, dotX: 184, dotY: 180, dotR: 13 };
9893
+ var SYMBOL_SMALL = { stroke: 18, dotX: 185, dotY: 175, dotR: 22 };
9725
9894
  function OlunSymbol({ size = 28, className }) {
9895
+ const g = size > 32 ? SYMBOL_LARGE : SYMBOL_SMALL;
9726
9896
  return /* @__PURE__ */ jsxs51(
9727
9897
  "svg",
9728
9898
  {
@@ -9734,19 +9904,19 @@ function OlunSymbol({ size = 28, className }) {
9734
9904
  className,
9735
9905
  "aria-hidden": "true",
9736
9906
  children: [
9737
- /* @__PURE__ */ jsx58(
9907
+ /* @__PURE__ */ jsx59(
9738
9908
  "circle",
9739
9909
  {
9740
9910
  cx: "108",
9741
9911
  cy: "120",
9742
9912
  r: "60",
9743
9913
  stroke: "currentColor",
9744
- strokeWidth: "18",
9914
+ strokeWidth: g.stroke,
9745
9915
  fill: "none",
9746
9916
  style: { color: "var(--text-primary)" }
9747
9917
  }
9748
9918
  ),
9749
- /* @__PURE__ */ jsx58("circle", { cx: "185", cy: "175", r: "22", fill: "var(--accent-pop)" })
9919
+ /* @__PURE__ */ jsx59("circle", { cx: g.dotX, cy: g.dotY, r: g.dotR, fill: "var(--accent-pop)" })
9750
9920
  ]
9751
9921
  }
9752
9922
  );
@@ -9767,7 +9937,7 @@ function OlunLogo({
9767
9937
  gap: "var(--space-3)"
9768
9938
  },
9769
9939
  children: [
9770
- showSymbol && /* @__PURE__ */ jsx58(OlunSymbol, { size: symbolSize }),
9940
+ showSymbol && /* @__PURE__ */ jsx59(OlunSymbol, { size: symbolSize }),
9771
9941
  /* @__PURE__ */ jsxs51(
9772
9942
  "span",
9773
9943
  {
@@ -9780,7 +9950,7 @@ function OlunLogo({
9780
9950
  },
9781
9951
  children: [
9782
9952
  "OLUN",
9783
- /* @__PURE__ */ jsx58("span", { style: { color: "var(--accent)" }, children: "." })
9953
+ !showSymbol && /* @__PURE__ */ jsx59("span", { style: { color: "var(--accent)" }, children: "." })
9784
9954
  ]
9785
9955
  }
9786
9956
  )
@@ -9791,11 +9961,11 @@ function OlunLogo({
9791
9961
 
9792
9962
  // src/components/branding/theme-toggle.tsx
9793
9963
  import { Sun, Moon } from "lucide-react";
9794
- import { jsx as jsx59 } from "react/jsx-runtime";
9964
+ import { jsx as jsx60 } from "react/jsx-runtime";
9795
9965
  function ThemeToggle({ className }) {
9796
9966
  const { resolvedTheme, toggleTheme } = useOlunTheme();
9797
9967
  const Icon = resolvedTheme === "dark" ? Moon : Sun;
9798
- return /* @__PURE__ */ jsx59(
9968
+ return /* @__PURE__ */ jsx60(
9799
9969
  "button",
9800
9970
  {
9801
9971
  onClick: () => toggleTheme(),
@@ -9807,14 +9977,14 @@ function ThemeToggle({ className }) {
9807
9977
  ),
9808
9978
  "aria-label": "\uD14C\uB9C8 \uC804\uD658",
9809
9979
  title: resolvedTheme === "dark" ? "\uB77C\uC774\uD2B8 \uBAA8\uB4DC\uB85C" : "\uB2E4\uD06C \uBAA8\uB4DC\uB85C",
9810
- children: /* @__PURE__ */ jsx59(Icon, { className: "size-[18px]", strokeWidth: 1.75 })
9980
+ children: /* @__PURE__ */ jsx60(Icon, { className: "size-[18px]", strokeWidth: 1.75 })
9811
9981
  }
9812
9982
  );
9813
9983
  }
9814
9984
 
9815
9985
  // src/components/branding/theme-fab.tsx
9816
9986
  import { Sun as Sun2, Moon as Moon2 } from "lucide-react";
9817
- import { jsx as jsx60 } from "react/jsx-runtime";
9987
+ import { jsx as jsx61 } from "react/jsx-runtime";
9818
9988
  function ThemeFab({ variant = "square" } = {}) {
9819
9989
  const { mounted, resolvedTheme, toggleTheme } = useOlunTheme();
9820
9990
  if (!mounted) {
@@ -9854,7 +10024,7 @@ function ThemeFab({ variant = "square" } = {}) {
9854
10024
  WebkitBackdropFilter: "blur(16px)",
9855
10025
  zIndex: 9999
9856
10026
  };
9857
- return /* @__PURE__ */ jsx60(
10027
+ return /* @__PURE__ */ jsx61(
9858
10028
  "button",
9859
10029
  {
9860
10030
  onClick: () => toggleTheme(),
@@ -9879,7 +10049,7 @@ function ThemeFab({ variant = "square" } = {}) {
9879
10049
  e.currentTarget.style.color = "var(--text-secondary)";
9880
10050
  }
9881
10051
  },
9882
- children: /* @__PURE__ */ jsx60(
10052
+ children: /* @__PURE__ */ jsx61(
9883
10053
  Icon,
9884
10054
  {
9885
10055
  size: isCircle ? 22 : 16,
@@ -9891,7 +10061,7 @@ function ThemeFab({ variant = "square" } = {}) {
9891
10061
  }
9892
10062
 
9893
10063
  // src/components/logos/organization-logo.tsx
9894
- import { jsx as jsx61 } from "react/jsx-runtime";
10064
+ import { jsx as jsx62 } from "react/jsx-runtime";
9895
10065
  var organizationLogoRegistry = {
9896
10066
  jbnu: {
9897
10067
  label: "\uC804\uBD81\uB300\uD559\uAD50 \uC5E0\uBE14\uB7FC",
@@ -9920,7 +10090,7 @@ function OrganizationLogo({
9920
10090
  }) {
9921
10091
  const asset = organizationLogoRegistry[organization];
9922
10092
  const isDecorative = ariaHidden === true || ariaHidden === "true";
9923
- return /* @__PURE__ */ jsx61(
10093
+ return /* @__PURE__ */ jsx62(
9924
10094
  "svg",
9925
10095
  {
9926
10096
  viewBox: asset.viewBox,
@@ -9938,7 +10108,7 @@ function OrganizationLogo({
9938
10108
  ...style
9939
10109
  },
9940
10110
  ...props,
9941
- children: asset.paths.map((path) => /* @__PURE__ */ jsx61("path", { d: path }, path))
10111
+ children: asset.paths.map((path) => /* @__PURE__ */ jsx62("path", { d: path }, path))
9942
10112
  }
9943
10113
  );
9944
10114
  }