@olundot/ui 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -189,7 +189,7 @@ import { Slot } from "radix-ui";
189
189
  import { jsx, jsxs } from "react/jsx-runtime";
190
190
  var buttonVariants = cva(
191
191
  [
192
- "inline-flex cursor-pointer items-center justify-center whitespace-nowrap rounded-[var(--radius-sm)] border font-medium",
192
+ "inline-flex cursor-pointer items-center justify-center whitespace-nowrap rounded-[var(--radius-md)] border font-medium",
193
193
  "transition-[background-color,border-color,color,box-shadow,transform] motion-reduce:transition-none",
194
194
  "focus-visible:outline-none focus-visible:border-[var(--focus-ring)] focus-visible:shadow-[0_0_0_2px_var(--focus-ring)]",
195
195
  "active:scale-[0.98] disabled:active:scale-100 aria-disabled:active:scale-100",
@@ -201,10 +201,12 @@ var buttonVariants = cva(
201
201
  variants: {
202
202
  variant: {
203
203
  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. */
204
205
  outline: "border-[var(--border)] bg-transparent text-foreground hover:border-[var(--border-strong)] hover:bg-[var(--action-hover)]",
205
206
  ghost: "border-transparent bg-transparent text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground",
206
207
  danger: "border-[var(--error)] bg-[var(--error)] text-[var(--error-contrast)] hover:bg-[var(--error-hover)] hover:border-[var(--error-hover)]",
207
208
  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. */
208
210
  subtle: "border-[var(--border-subtle)] bg-[var(--bg-surface)] text-foreground hover:border-[var(--border)] hover:bg-[var(--action-hover)]",
209
211
  default: "border-[var(--primary)] bg-[var(--primary)] text-[var(--primary-fg)] hover:bg-[var(--primary-hover)] hover:border-[var(--primary-hover)]",
210
212
  destructive: "border-[var(--error)] bg-[var(--error)] text-[var(--error-contrast)] hover:bg-[var(--error-hover)] hover:border-[var(--error-hover)]",
@@ -214,8 +216,11 @@ var buttonVariants = cva(
214
216
  size: {
215
217
  // Cross-control height map: Button sm/md/lg match field controls sm/md/lg (30/32/36px).
216
218
  // Height comes from h-* alone — no vertical padding (py-12 inside h-32 left a 6px content box).
217
- xs: "h-[28px] gap-[6px] px-pad-compact-x text-[12px] [&_svg]:size-[14px] [&_svg]:stroke-[1.75]",
218
- sm: "h-[30px] gap-[6px] px-pad-compact-x text-body-sm [&_svg]:size-[16px]",
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]",
219
224
  md: "h-[32px] gap-[6px] px-pad-default-x text-body-sm [&_svg]:size-[16px]",
220
225
  lg: "h-[36px] gap-[var(--space-2)] px-pad-default-x text-[15px] [&_svg]:size-[18px]",
221
226
  xl: "h-[40px] gap-[var(--space-2)] px-5 text-[15px] [&_svg]:size-[18px]",
@@ -230,6 +235,7 @@ var buttonVariants = cva(
230
235
  }
231
236
  }
232
237
  );
238
+ var footerButtonHitAreaClassName = "relative before:absolute before:inset-x-0 before:-inset-y-[5px] before:content-['']";
233
239
  var Button = React.forwardRef(
234
240
  ({
235
241
  asChild = false,
@@ -325,7 +331,7 @@ var CopyButton = React2.forwardRef(
325
331
  onCopied,
326
332
  size = "sm",
327
333
  value,
328
- variant = "outline",
334
+ variant = "secondary",
329
335
  ...props
330
336
  }, ref) => {
331
337
  const [copied, setCopied] = React2.useState(false);
@@ -611,7 +617,7 @@ var fileUploadZoneVariants = cva3(
611
617
  variants: {
612
618
  size: {
613
619
  default: "gap-[var(--space-2)] rounded-[var(--radius-md)] px-[var(--space-6)] py-[var(--space-10)]",
614
- compact: "gap-[var(--space-1)] rounded-[var(--radius-sm)] px-[var(--space-4)] py-[20px]"
620
+ compact: "gap-[var(--space-1)] rounded-[var(--radius-md)] px-[var(--space-4)] py-[20px]"
615
621
  },
616
622
  surface: surfaceClassNames
617
623
  },
@@ -1046,7 +1052,7 @@ function DismissButton({
1046
1052
  marginTop: -1,
1047
1053
  alignItems: "center",
1048
1054
  justifyContent: "center",
1049
- borderRadius: "var(--radius-sm)",
1055
+ borderRadius: "var(--radius-md)",
1050
1056
  border: 0,
1051
1057
  background: hover ? "var(--action-hover)" : "transparent",
1052
1058
  color: hover ? strong ? fg : "var(--text-primary)" : strong ? "color-mix(in srgb, " + fg + " 70%, transparent)" : "var(--text-tertiary)",
@@ -1532,7 +1538,7 @@ var Select = React7.forwardRef(
1532
1538
  "data-slot": "select-content",
1533
1539
  position: "popper",
1534
1540
  sideOffset: 4,
1535
- className: "z-[var(--z-popover)] max-h-[var(--radix-select-content-available-height)] min-w-[var(--radix-select-trigger-width)] overflow-hidden rounded-[var(--radius-md)] border border-[var(--border)] bg-[var(--bg-surface)] text-foreground shadow-[var(--shadow-4)]",
1541
+ className: "z-[var(--z-popover)] max-h-[var(--radix-select-content-available-height)] min-w-[var(--radix-select-trigger-width)] overflow-hidden rounded-[var(--radius-md)] border border-[var(--border)] bg-[var(--bg-surface)] text-foreground shadow-[var(--shadow-16)]",
1536
1542
  children: [
1537
1543
  /* @__PURE__ */ jsx7(
1538
1544
  SelectPrimitive.ScrollUpButton,
@@ -2823,7 +2829,7 @@ var WizardLayout = React16.forwardRef(
2823
2829
  type: "button",
2824
2830
  "data-slot": "wizard-layout-step-button",
2825
2831
  "data-step-state": step.resolvedState,
2826
- className: "flex cursor-pointer flex-col items-center gap-[var(--space-2)] rounded-[var(--radius-sm)] focus-visible:outline-none focus-visible:ring-[1px] focus-visible:ring-[var(--focus-ring)]",
2832
+ className: "flex cursor-pointer flex-col items-center gap-[var(--space-2)] rounded-[var(--radius-md)] focus-visible:outline-none focus-visible:ring-[1px] focus-visible:ring-[var(--focus-ring)]",
2827
2833
  onClick: () => onStepChange(index),
2828
2834
  children: [
2829
2835
  /* @__PURE__ */ jsx17(
@@ -2952,7 +2958,7 @@ var tabsListVariants = cva8(
2952
2958
  {
2953
2959
  variant: "line",
2954
2960
  orientation: "horizontal",
2955
- className: "border-b border-[var(--border-subtle)] gap-[var(--space-6)] overflow-x-auto overflow-y-hidden mb-[var(--space-6)]"
2961
+ className: "border-b border-[var(--border-subtle)] gap-[var(--space-6)] overflow-x-auto overflow-y-hidden"
2956
2962
  },
2957
2963
  {
2958
2964
  variant: "line",
@@ -2962,7 +2968,7 @@ var tabsListVariants = cva8(
2962
2968
  {
2963
2969
  variant: "contained",
2964
2970
  orientation: "horizontal",
2965
- className: "gap-[var(--space-1)] overflow-x-auto overflow-y-hidden mb-[var(--space-6)]"
2971
+ className: "gap-[var(--space-1)] overflow-x-auto overflow-y-hidden"
2966
2972
  },
2967
2973
  {
2968
2974
  variant: "contained",
@@ -3225,31 +3231,41 @@ var DetailLayout = React18.forwardRef(
3225
3231
  ...props,
3226
3232
  children: [
3227
3233
  /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-header", className: "min-w-0", children: header }),
3228
- tabs ? /* @__PURE__ */ jsx19(Tabs, { tabs, activeKey: activeTab, onChange: onTabChange, baseId, children: hasExplicitTabsContent ? /* @__PURE__ */ jsx19(
3229
- DetailLayoutBody,
3234
+ tabs ? /* @__PURE__ */ jsx19(
3235
+ Tabs,
3230
3236
  {
3231
- aside,
3232
- bodyClassName,
3233
- contentClassName,
3234
- asideClassName,
3235
- stickyAside,
3236
- stickyAsideTopClassName,
3237
- children: appendFooterToActiveTabsContent(children, activeTab, footer)
3238
- }
3239
- ) : tabs.map((tab) => /* @__PURE__ */ jsx19(
3240
- TabsContent,
3241
- {
3242
- tabKey: tab.key,
3237
+ tabs,
3238
+ activeKey: activeTab,
3239
+ onChange: onTabChange,
3243
3240
  baseId,
3244
- forceMount: true,
3245
- hidden: tab.key !== activeTab,
3246
- children: tab.key === activeTab ? /* @__PURE__ */ jsxs18(Fragment6, { children: [
3247
- body,
3248
- footer ? /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-footer", className: "min-w-0", children: footer }) : null
3249
- ] }) : null
3250
- },
3251
- tab.key
3252
- )) }) : /* @__PURE__ */ jsxs18(Fragment6, { children: [
3241
+ className: "flex flex-col gap-[var(--space-6)]",
3242
+ children: hasExplicitTabsContent ? /* @__PURE__ */ jsx19(
3243
+ DetailLayoutBody,
3244
+ {
3245
+ aside,
3246
+ bodyClassName,
3247
+ contentClassName,
3248
+ asideClassName,
3249
+ stickyAside,
3250
+ stickyAsideTopClassName,
3251
+ children: appendFooterToActiveTabsContent(children, activeTab, footer)
3252
+ }
3253
+ ) : tabs.map((tab) => /* @__PURE__ */ jsx19(
3254
+ TabsContent,
3255
+ {
3256
+ tabKey: tab.key,
3257
+ baseId,
3258
+ forceMount: true,
3259
+ hidden: tab.key !== activeTab,
3260
+ children: tab.key === activeTab ? /* @__PURE__ */ jsxs18(Fragment6, { children: [
3261
+ body,
3262
+ footer ? /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-footer", className: "min-w-0", children: footer }) : null
3263
+ ] }) : null
3264
+ },
3265
+ tab.key
3266
+ ))
3267
+ }
3268
+ ) : /* @__PURE__ */ jsxs18(Fragment6, { children: [
3253
3269
  body,
3254
3270
  footer ? /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-footer", className: "min-w-0", children: footer }) : null
3255
3271
  ] })
@@ -3420,18 +3436,286 @@ var FormLayout = React19.forwardRef(
3420
3436
  FormLayout.displayName = "FormLayout";
3421
3437
 
3422
3438
  // src/components/ui/form-modal.tsx
3423
- import * as React21 from "react";
3439
+ import * as React22 from "react";
3424
3440
 
3425
3441
  // src/components/ui/dialog.tsx
3426
- import * as React20 from "react";
3442
+ import * as React21 from "react";
3427
3443
  import { Dialog as DialogPrimitive } from "radix-ui";
3428
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";
3449
+
3450
+ // src/lib/use-return-focus.ts
3451
+ import * as React20 from "react";
3452
+ function useReturnFocus() {
3453
+ const returnTo = React20.useRef(null);
3454
+ const onOpenAutoFocus = React20.useCallback(() => {
3455
+ const active = document.activeElement;
3456
+ returnTo.current = active instanceof HTMLElement && active !== document.body ? active : null;
3457
+ }, []);
3458
+ const onCloseAutoFocus = React20.useCallback((event) => {
3459
+ const target = returnTo.current;
3460
+ returnTo.current = null;
3461
+ if (!target?.isConnected) return;
3462
+ event.preventDefault();
3463
+ target.focus();
3464
+ }, []);
3465
+ return { onOpenAutoFocus, onCloseAutoFocus };
3466
+ }
3467
+
3468
+ // src/components/ui/sheet.tsx
3429
3469
  import { jsx as jsx21, jsxs as jsxs20 } from "react/jsx-runtime";
3470
+ var defaultSheetMotionConfig = {
3471
+ type: "slide",
3472
+ duration: 300,
3473
+ easing: "decel"
3474
+ };
3475
+ var sheetMotionEasingValue = {
3476
+ standard: "var(--ease-standard)",
3477
+ // decel/sharp have no canonical --ease-* token; these compat beziers are frozen
3478
+ // specifically to back this public `easing` prop (see tokens/compat.css).
3479
+ decel: "var(--easing-decel)",
3480
+ accel: "var(--ease-in)",
3481
+ sharp: "var(--easing-sharp)",
3482
+ bounce: "var(--ease-out)"
3483
+ };
3484
+ function resolveSheetMotionConfig(motion) {
3485
+ if (motion === false) return false;
3486
+ return {
3487
+ ...defaultSheetMotionConfig,
3488
+ ...motion
3489
+ };
3490
+ }
3491
+ function formatSheetMotionDuration(duration) {
3492
+ return typeof duration === "number" ? `${duration}ms` : duration;
3493
+ }
3494
+ function getSheetMotionStyle(motionConfig, style) {
3495
+ if (!motionConfig) return style;
3496
+ return {
3497
+ ...style,
3498
+ "--sheet-motion-duration": formatSheetMotionDuration(motionConfig.duration),
3499
+ "--sheet-motion-easing": sheetMotionEasingValue[motionConfig.easing]
3500
+ };
3501
+ }
3502
+ function getDefaultSheetMotionStyle(style) {
3503
+ return getSheetMotionStyle(defaultSheetMotionConfig, style);
3504
+ }
3505
+ function Sheet({ ...props }) {
3506
+ return /* @__PURE__ */ jsx21(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
3507
+ }
3508
+ function SheetTrigger({
3509
+ ...props
3510
+ }) {
3511
+ return /* @__PURE__ */ jsx21(SheetPrimitive.Trigger, { "data-slot": "sheet-trigger", ...props });
3512
+ }
3513
+ function SheetClose({
3514
+ ...props
3515
+ }) {
3516
+ return /* @__PURE__ */ jsx21(SheetPrimitive.Close, { "data-slot": "sheet-close", ...props });
3517
+ }
3518
+ function SheetPortal({
3519
+ ...props
3520
+ }) {
3521
+ return /* @__PURE__ */ jsx21(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
3522
+ }
3523
+ function SheetOverlay({
3524
+ className,
3525
+ motion,
3526
+ style,
3527
+ ...props
3528
+ }) {
3529
+ const motionConfig = resolveSheetMotionConfig(motion);
3530
+ return /* @__PURE__ */ jsx21(
3531
+ SheetPrimitive.Overlay,
3532
+ {
3533
+ "data-slot": "sheet-overlay",
3534
+ className: cn(
3535
+ "fixed inset-0 z-[var(--z-overlay)] bg-[var(--scrim)]",
3536
+ motionConfig && cn(
3537
+ "transition-opacity motion-reduce:transition-none",
3538
+ "duration-[var(--sheet-motion-duration)]",
3539
+ "data-[state=closed]:opacity-0 data-[state=open]:opacity-100",
3540
+ "data-[state=open]:animate-[olun-sheet-fade-in_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]",
3541
+ "data-[state=closed]:animate-[olun-sheet-fade-out_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]",
3542
+ "motion-reduce:animate-none"
3543
+ ),
3544
+ className
3545
+ ),
3546
+ style: getSheetMotionStyle(motionConfig, style),
3547
+ ...props
3548
+ }
3549
+ );
3550
+ }
3551
+ function SheetContent({
3552
+ className,
3553
+ children,
3554
+ side = "right",
3555
+ mobileSide,
3556
+ motion,
3557
+ showCloseButton = false,
3558
+ style,
3559
+ onOpenAutoFocus,
3560
+ onCloseAutoFocus,
3561
+ ...props
3562
+ }) {
3563
+ const motionConfig = resolveSheetMotionConfig(motion);
3564
+ const hasSlideMotion = motionConfig && motionConfig.type === "slide";
3565
+ const returnFocus = useReturnFocus();
3566
+ const handleOpenAutoFocus = (event) => {
3567
+ returnFocus.onOpenAutoFocus();
3568
+ onOpenAutoFocus?.(event);
3569
+ };
3570
+ const handleCloseAutoFocus = (event) => {
3571
+ onCloseAutoFocus?.(event);
3572
+ if (!event.defaultPrevented) returnFocus.onCloseAutoFocus(event);
3573
+ };
3574
+ return /* @__PURE__ */ jsxs20(SheetPortal, { children: [
3575
+ /* @__PURE__ */ jsx21(SheetOverlay, { motion: motionConfig }),
3576
+ /* @__PURE__ */ jsxs20(
3577
+ SheetPrimitive.Content,
3578
+ {
3579
+ "data-slot": "sheet-content",
3580
+ className: cn(
3581
+ "fixed z-[var(--z-modal)] flex flex-col gap-4 border-[var(--border)] bg-[var(--bg-surface)] shadow-[var(--shadow-16)]",
3582
+ motionConfig && cn(
3583
+ "motion-reduce:animate-none",
3584
+ motionConfig.type === "fade" && "data-[state=open]:animate-[olun-sheet-fade-in_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] data-[state=closed]:animate-[olun-sheet-fade-out_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3585
+ ),
3586
+ side === "right" && cn(
3587
+ "inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
3588
+ hasSlideMotion && "data-[state=open]:animate-[olun-sheet-in-from-right_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] data-[state=closed]:animate-[olun-sheet-out-to-right_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3589
+ ),
3590
+ side === "left" && cn(
3591
+ "inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
3592
+ hasSlideMotion && "data-[state=open]:animate-[olun-sheet-in-from-left_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] data-[state=closed]:animate-[olun-sheet-out-to-left_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3593
+ ),
3594
+ side === "top" && cn(
3595
+ "inset-x-0 top-0 h-auto border-b",
3596
+ hasSlideMotion && "data-[state=open]:animate-[olun-sheet-in-from-top_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] data-[state=closed]:animate-[olun-sheet-out-to-top_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3597
+ ),
3598
+ side === "bottom" && cn(
3599
+ "inset-x-0 bottom-0 h-auto border-t",
3600
+ hasSlideMotion && "data-[state=open]:animate-[olun-sheet-in-from-bottom_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] data-[state=closed]:animate-[olun-sheet-out-to-bottom_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3601
+ ),
3602
+ mobileSide === "right" && cn(
3603
+ "max-[899px]:inset-y-0 max-[899px]:right-0 max-[899px]:left-auto max-[899px]:h-full max-[899px]:w-3/4 max-[899px]:border-l max-[899px]:border-t-0 max-[899px]:rounded-none",
3604
+ hasSlideMotion && "max-[899px]:data-[state=open]:animate-[olun-sheet-in-from-right_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] max-[899px]:data-[state=closed]:animate-[olun-sheet-out-to-right_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3605
+ ),
3606
+ mobileSide === "left" && cn(
3607
+ "max-[899px]:inset-y-0 max-[899px]:left-0 max-[899px]:right-auto max-[899px]:h-full max-[899px]:w-3/4 max-[899px]:border-r max-[899px]:border-t-0 max-[899px]:rounded-none",
3608
+ hasSlideMotion && "max-[899px]:data-[state=open]:animate-[olun-sheet-in-from-left_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] max-[899px]:data-[state=closed]:animate-[olun-sheet-out-to-left_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
3609
+ ),
3610
+ mobileSide === "top" && cn(
3611
+ // `max-w-none!` overrides the side variant's `sm:max-w-sm` cap (see mobileSide bottom).
3612
+ "max-[899px]:inset-x-0 max-[899px]:top-0 max-[899px]:bottom-auto max-[899px]:h-auto max-[899px]:w-full max-[899px]:max-w-none! max-[899px]:border-b max-[899px]:border-l-0 max-[899px]:rounded-none",
3613
+ 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
+ ),
3615
+ 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",
3619
+ 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
+ ),
3621
+ className
3622
+ ),
3623
+ style: getSheetMotionStyle(motionConfig, style),
3624
+ onOpenAutoFocus: handleOpenAutoFocus,
3625
+ onCloseAutoFocus: handleCloseAutoFocus,
3626
+ ...props,
3627
+ children: [
3628
+ 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
+ ] })
3633
+ ]
3634
+ }
3635
+ )
3636
+ ] });
3637
+ }
3638
+ function SheetBody({ className, ...props }) {
3639
+ return /* @__PURE__ */ jsx21(
3640
+ "div",
3641
+ {
3642
+ "data-slot": "sheet-body",
3643
+ className: cn("flex-1 overflow-y-auto p-4", className),
3644
+ ...props
3645
+ }
3646
+ );
3647
+ }
3648
+ function SheetHeader({ className, ...props }) {
3649
+ return /* @__PURE__ */ jsx21(
3650
+ "div",
3651
+ {
3652
+ "data-slot": "sheet-header",
3653
+ className: cn("flex flex-col gap-1.5 p-4", className),
3654
+ ...props
3655
+ }
3656
+ );
3657
+ }
3658
+ function SheetFooter({ className, ...props }) {
3659
+ return /* @__PURE__ */ jsx21(
3660
+ "div",
3661
+ {
3662
+ "data-slot": "sheet-footer",
3663
+ className: cn("mt-auto flex flex-col gap-2 p-4", className),
3664
+ ...props
3665
+ }
3666
+ );
3667
+ }
3668
+ function SheetTitle({
3669
+ className,
3670
+ ...props
3671
+ }) {
3672
+ return /* @__PURE__ */ jsx21(
3673
+ SheetPrimitive.Title,
3674
+ {
3675
+ "data-slot": "sheet-title",
3676
+ className: cn("font-semibold text-foreground", className),
3677
+ ...props
3678
+ }
3679
+ );
3680
+ }
3681
+ function SheetDescription({
3682
+ className,
3683
+ ...props
3684
+ }) {
3685
+ return /* @__PURE__ */ jsx21(
3686
+ SheetPrimitive.Description,
3687
+ {
3688
+ "data-slot": "sheet-description",
3689
+ className: cn("text-sm text-muted-foreground", className),
3690
+ ...props
3691
+ }
3692
+ );
3693
+ }
3694
+
3695
+ // 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
+ );
3711
+ function dialogMobileSheetStyle(style) {
3712
+ return getDefaultSheetMotionStyle(style);
3713
+ }
3430
3714
  var Dialog = DialogPrimitive.Root;
3431
3715
  var DialogTrigger = DialogPrimitive.Trigger;
3432
3716
  var DialogPortal = DialogPrimitive.Portal;
3433
3717
  var DialogClose = DialogPrimitive.Close;
3434
- var DialogOverlay = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx21(
3718
+ var DialogOverlay = React21.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3435
3719
  DialogPrimitive.Overlay,
3436
3720
  {
3437
3721
  ref,
@@ -3448,9 +3732,9 @@ var DialogOverlay = React20.forwardRef(({ className, ...props }, ref) => /* @__P
3448
3732
  }
3449
3733
  ));
3450
3734
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
3451
- var DialogContent = React20.forwardRef(({ className, children, showCloseButton = false, ...props }, ref) => /* @__PURE__ */ jsxs20(DialogPortal, { children: [
3452
- /* @__PURE__ */ jsx21(DialogOverlay, {}),
3453
- /* @__PURE__ */ jsxs20(
3735
+ var DialogContent = React21.forwardRef(({ className, children, showCloseButton = false, mobilePresentation = "center", ...props }, ref) => /* @__PURE__ */ jsxs21(DialogPortal, { children: [
3736
+ /* @__PURE__ */ jsx22(DialogOverlay, {}),
3737
+ /* @__PURE__ */ jsxs21(
3454
3738
  DialogPrimitive.Content,
3455
3739
  {
3456
3740
  ref,
@@ -3472,24 +3756,26 @@ var DialogContent = React20.forwardRef(({ className, children, showCloseButton =
3472
3756
  "data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
3473
3757
  "data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
3474
3758
  "motion-reduce:animate-none",
3759
+ mobilePresentation === "sheet" && dialogMobileSheetClassName,
3475
3760
  className
3476
3761
  ),
3477
3762
  ...props,
3763
+ ...mobilePresentation === "sheet" && { style: dialogMobileSheetStyle(props.style) },
3478
3764
  children: [
3479
3765
  children,
3480
- showCloseButton ? /* @__PURE__ */ jsx21(
3766
+ showCloseButton ? /* @__PURE__ */ jsx22(
3481
3767
  DialogPrimitive.Close,
3482
3768
  {
3483
3769
  className: cn(
3484
3770
  "absolute right-4 top-4 inline-flex size-[32px] cursor-pointer items-center justify-center",
3485
- "rounded-sm text-text-secondary",
3771
+ "rounded-[var(--radius-md)] text-text-secondary",
3486
3772
  "transition-colors motion-reduce:transition-none",
3487
3773
  "hover:bg-accent hover:text-accent-foreground",
3488
3774
  "focus-visible:outline-none focus-visible:shadow-focus-ring",
3489
3775
  "disabled:pointer-events-none disabled:text-text-disabled"
3490
3776
  ),
3491
3777
  "aria-label": "\uB2EB\uAE30",
3492
- children: /* @__PURE__ */ jsx21(X, { className: "size-[16px]" })
3778
+ children: /* @__PURE__ */ jsx22(X, { className: "size-[16px]" })
3493
3779
  }
3494
3780
  ) : null
3495
3781
  ]
@@ -3500,7 +3786,7 @@ DialogContent.displayName = DialogPrimitive.Content.displayName;
3500
3786
  var DialogHeader = ({
3501
3787
  className,
3502
3788
  ...props
3503
- }) => /* @__PURE__ */ jsx21(
3789
+ }) => /* @__PURE__ */ jsx22(
3504
3790
  "div",
3505
3791
  {
3506
3792
  className: cn(
@@ -3515,7 +3801,7 @@ DialogHeader.displayName = "DialogHeader";
3515
3801
  var DialogFooter = ({
3516
3802
  className,
3517
3803
  ...props
3518
- }) => /* @__PURE__ */ jsx21(
3804
+ }) => /* @__PURE__ */ jsx22(
3519
3805
  "div",
3520
3806
  {
3521
3807
  className: cn(
@@ -3531,7 +3817,7 @@ var DialogFooter = ({
3531
3817
  }
3532
3818
  );
3533
3819
  DialogFooter.displayName = "DialogFooter";
3534
- var DialogTitle = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx21(
3820
+ var DialogTitle = React21.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3535
3821
  DialogPrimitive.Title,
3536
3822
  {
3537
3823
  ref,
@@ -3543,7 +3829,7 @@ var DialogTitle = React20.forwardRef(({ className, ...props }, ref) => /* @__PUR
3543
3829
  }
3544
3830
  ));
3545
3831
  DialogTitle.displayName = DialogPrimitive.Title.displayName;
3546
- var DialogDescription = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx21(
3832
+ var DialogDescription = React21.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3547
3833
  DialogPrimitive.Description,
3548
3834
  {
3549
3835
  ref,
@@ -3552,7 +3838,7 @@ var DialogDescription = React20.forwardRef(({ className, ...props }, ref) => /*
3552
3838
  }
3553
3839
  ));
3554
3840
  DialogDescription.displayName = DialogPrimitive.Description.displayName;
3555
- var DialogEyebrow = React20.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx21(
3841
+ var DialogEyebrow = React21.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3556
3842
  "p",
3557
3843
  {
3558
3844
  ref,
@@ -3567,7 +3853,7 @@ DialogEyebrow.displayName = "DialogEyebrow";
3567
3853
  var DialogRawContent = DialogPrimitive.Content;
3568
3854
 
3569
3855
  // src/components/ui/form-modal.tsx
3570
- import { jsx as jsx22, jsxs as jsxs21 } from "react/jsx-runtime";
3856
+ import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
3571
3857
  var formModalContentClassName = cn(
3572
3858
  "w-[calc(100vw-2rem)]",
3573
3859
  "max-w-[560px]",
@@ -3608,12 +3894,14 @@ function FormModal({
3608
3894
  cancelLabel = "\uCDE8\uC18C",
3609
3895
  wide = false,
3610
3896
  loading = false,
3611
- status
3897
+ status,
3898
+ mobilePresentation = "center"
3612
3899
  }) {
3613
- const [pending, setPending] = React21.useState(false);
3614
- const busyRef = React21.useRef(false);
3900
+ const [pending, setPending] = React22.useState(false);
3901
+ const busyRef = React22.useRef(false);
3615
3902
  const isBusy = loading || pending;
3616
- const handleOpenChange = React21.useCallback(
3903
+ const returnFocus = useReturnFocus();
3904
+ const handleOpenChange = React22.useCallback(
3617
3905
  (nextOpen) => {
3618
3906
  if (!nextOpen && isBusy) {
3619
3907
  return;
@@ -3622,7 +3910,7 @@ function FormModal({
3622
3910
  },
3623
3911
  [isBusy, onOpenChange]
3624
3912
  );
3625
- const handleSubmit = React21.useCallback(
3913
+ const handleSubmit = React22.useCallback(
3626
3914
  async (event) => {
3627
3915
  event.preventDefault();
3628
3916
  if (busyRef.current || loading) {
@@ -3640,37 +3928,41 @@ function FormModal({
3640
3928
  },
3641
3929
  [loading, onOpenChange, onSubmit]
3642
3930
  );
3643
- return /* @__PURE__ */ jsx22(Dialog, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsx22(
3931
+ return /* @__PURE__ */ jsx23(Dialog, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsx23(
3644
3932
  DialogContent,
3645
3933
  {
3646
3934
  "data-slot": "form-modal-content",
3935
+ mobilePresentation,
3936
+ ...returnFocus,
3647
3937
  className: cn(
3648
3938
  formModalContentClassName,
3649
3939
  wide && formModalWideContentClassName
3650
3940
  ),
3651
- children: /* @__PURE__ */ jsxs21("form", { "data-slot": "form-modal-form", onSubmit: handleSubmit, children: [
3652
- /* @__PURE__ */ jsxs21("div", { "data-slot": "form-modal-header", className: formModalHeaderClassName, children: [
3653
- /* @__PURE__ */ jsx22(DialogTitle, { className: formModalTitleClassName, children: title }),
3654
- description ? /* @__PURE__ */ jsx22(DialogDescription, { className: formModalDescriptionClassName, children: description }) : null,
3655
- status ? /* @__PURE__ */ jsx22("div", { "data-slot": "form-modal-status", children: status }) : null
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
3656
3946
  ] }),
3657
- /* @__PURE__ */ jsx22("div", { "data-slot": "form-modal-body", className: formModalBodyClassName, children }),
3658
- /* @__PURE__ */ jsxs21(
3947
+ /* @__PURE__ */ jsx23("div", { "data-slot": "form-modal-body", className: formModalBodyClassName, children }),
3948
+ /* @__PURE__ */ jsxs22(
3659
3949
  "div",
3660
3950
  {
3661
3951
  "data-slot": "form-modal-footer",
3662
3952
  className: formModalFooterClassName,
3663
3953
  children: [
3664
- /* @__PURE__ */ jsx22(
3954
+ /* @__PURE__ */ jsx23(
3665
3955
  Button,
3666
3956
  {
3667
3957
  variant: "secondary",
3958
+ size: "lg",
3959
+ className: footerButtonHitAreaClassName,
3668
3960
  disabled: isBusy,
3669
3961
  onClick: () => handleOpenChange(false),
3670
3962
  children: cancelLabel
3671
3963
  }
3672
3964
  ),
3673
- /* @__PURE__ */ jsx22(Button, { type: "submit", loading: isBusy, children: submitLabel })
3965
+ /* @__PURE__ */ jsx23(Button, { type: "submit", size: "lg", className: footerButtonHitAreaClassName, loading: isBusy, children: submitLabel })
3674
3966
  ]
3675
3967
  }
3676
3968
  )
@@ -3680,7 +3972,7 @@ function FormModal({
3680
3972
  }
3681
3973
 
3682
3974
  // src/components/ui/info-modal.tsx
3683
- import { jsx as jsx23, jsxs as jsxs22 } from "react/jsx-runtime";
3975
+ import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
3684
3976
  var infoModalContentClassName = cn(
3685
3977
  "w-[calc(100vw-2rem)]",
3686
3978
  "max-w-[420px]",
@@ -3719,20 +4011,24 @@ function InfoModal({
3719
4011
  children,
3720
4012
  closeLabel = "\uB2EB\uAE30",
3721
4013
  width = "default",
3722
- footer
4014
+ footer,
4015
+ mobilePresentation = "center"
3723
4016
  }) {
3724
- return /* @__PURE__ */ jsx23(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs22(
4017
+ const returnFocus = useReturnFocus();
4018
+ return /* @__PURE__ */ jsx24(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs23(
3725
4019
  DialogContent,
3726
4020
  {
3727
4021
  "data-slot": "info-modal-content",
4022
+ mobilePresentation,
4023
+ ...returnFocus,
3728
4024
  className: cn(
3729
4025
  infoModalContentClassName,
3730
4026
  width === "wide" && infoModalWideContentClassName
3731
4027
  ),
3732
4028
  children: [
3733
- /* @__PURE__ */ jsxs22("div", { "data-slot": "info-modal-header", className: infoModalHeaderClassName, children: [
3734
- /* @__PURE__ */ jsx23(DialogTitle, { "data-slot": "info-modal-title", className: infoModalTitleClassName, children: title }),
3735
- description ? /* @__PURE__ */ jsx23(
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(
3736
4032
  DialogDescription,
3737
4033
  {
3738
4034
  "data-slot": "info-modal-description",
@@ -3741,13 +4037,14 @@ function InfoModal({
3741
4037
  }
3742
4038
  ) : null
3743
4039
  ] }),
3744
- /* @__PURE__ */ jsx23("div", { "data-slot": "info-modal-body", className: infoModalBodyClassName, children }),
3745
- /* @__PURE__ */ jsx23("div", { "data-slot": "info-modal-footer", className: infoModalFooterClassName, children: footer ?? /* @__PURE__ */ jsx23(
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(
3746
4042
  Button,
3747
4043
  {
3748
4044
  "data-slot": "info-modal-close-button",
3749
4045
  variant: "secondary",
3750
- size: "sm",
4046
+ size: "lg",
4047
+ className: footerButtonHitAreaClassName,
3751
4048
  onClick: () => onOpenChange(false),
3752
4049
  children: closeLabel
3753
4050
  }
@@ -3758,15 +4055,15 @@ function InfoModal({
3758
4055
  }
3759
4056
 
3760
4057
  // src/components/ui/filter-toolbar.tsx
3761
- import * as React25 from "react";
4058
+ import * as React26 from "react";
3762
4059
  import { SlidersHorizontal } from "lucide-react";
3763
4060
 
3764
4061
  // src/components/ui/chip.tsx
3765
- import * as React22 from "react";
4062
+ import * as React23 from "react";
3766
4063
  import { cva as cva9 } from "class-variance-authority";
3767
4064
  import { X as X2 } from "lucide-react";
3768
4065
  import { Slot as Slot2 } from "radix-ui";
3769
- import { jsx as jsx24, jsxs as jsxs23 } from "react/jsx-runtime";
4066
+ import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
3770
4067
  var chipVariants = cva9(
3771
4068
  [
3772
4069
  "inline-flex w-fit shrink-0 items-center justify-center whitespace-nowrap",
@@ -3858,7 +4155,7 @@ var chipCountVariants = cva9(
3858
4155
  }
3859
4156
  }
3860
4157
  );
3861
- var Chip = React22.forwardRef(
4158
+ var Chip = React23.forwardRef(
3862
4159
  ({
3863
4160
  className,
3864
4161
  variant = "filter",
@@ -3883,7 +4180,7 @@ var Chip = React22.forwardRef(
3883
4180
  value: _value,
3884
4181
  ...spanProps
3885
4182
  } = props;
3886
- return /* @__PURE__ */ jsxs23(
4183
+ return /* @__PURE__ */ jsxs24(
3887
4184
  "span",
3888
4185
  {
3889
4186
  "data-slot": "chip",
@@ -3892,8 +4189,8 @@ var Chip = React22.forwardRef(
3892
4189
  className: cn(chipVariants({ variant, tone, size, pressed, className })),
3893
4190
  ...spanProps,
3894
4191
  children: [
3895
- /* @__PURE__ */ jsx24("span", { children }),
3896
- count !== void 0 ? /* @__PURE__ */ jsx24(
4192
+ /* @__PURE__ */ jsx25("span", { children }),
4193
+ count !== void 0 ? /* @__PURE__ */ jsx25(
3897
4194
  "span",
3898
4195
  {
3899
4196
  "aria-hidden": "true",
@@ -3903,7 +4200,7 @@ var Chip = React22.forwardRef(
3903
4200
  children: count
3904
4201
  }
3905
4202
  ) : null,
3906
- /* @__PURE__ */ jsx24(
4203
+ /* @__PURE__ */ jsx25(
3907
4204
  "button",
3908
4205
  {
3909
4206
  ref,
@@ -3913,7 +4210,7 @@ var Chip = React22.forwardRef(
3913
4210
  disabled,
3914
4211
  onClick,
3915
4212
  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)]",
3916
- children: /* @__PURE__ */ jsx24(X2, { "aria-hidden": "true", size: 14, strokeWidth: 2.25 })
4213
+ children: /* @__PURE__ */ jsx25(X2, { "aria-hidden": "true", size: 14, strokeWidth: 2.25 })
3917
4214
  }
3918
4215
  )
3919
4216
  ]
@@ -3921,7 +4218,7 @@ var Chip = React22.forwardRef(
3921
4218
  );
3922
4219
  }
3923
4220
  const Comp = asChild ? Slot2.Root : "button";
3924
- return /* @__PURE__ */ jsxs23(
4221
+ return /* @__PURE__ */ jsxs24(
3925
4222
  Comp,
3926
4223
  {
3927
4224
  ref,
@@ -3936,7 +4233,7 @@ var Chip = React22.forwardRef(
3936
4233
  ...props,
3937
4234
  children: [
3938
4235
  children,
3939
- count !== void 0 ? /* @__PURE__ */ jsx24(
4236
+ count !== void 0 ? /* @__PURE__ */ jsx25(
3940
4237
  "span",
3941
4238
  {
3942
4239
  "aria-hidden": "true",
@@ -3954,13 +4251,13 @@ var Chip = React22.forwardRef(
3954
4251
  Chip.displayName = "Chip";
3955
4252
 
3956
4253
  // src/components/ui/icon-button.tsx
3957
- import * as React23 from "react";
4254
+ import * as React24 from "react";
3958
4255
  import { cva as cva10 } from "class-variance-authority";
3959
- import { jsx as jsx25, jsxs as jsxs24 } from "react/jsx-runtime";
4256
+ import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
3960
4257
  var iconButtonVariants = cva10(
3961
4258
  [
3962
4259
  "olun-icon-button relative inline-flex cursor-pointer shrink-0 items-center justify-center before:absolute before:content-['']",
3963
- "rounded-[var(--radius-sm)] border font-medium",
4260
+ "rounded-[var(--radius-md)] border font-medium",
3964
4261
  "transition-colors motion-reduce:transition-none",
3965
4262
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]",
3966
4263
  "disabled:cursor-not-allowed disabled:bg-[var(--action-disabled-bg)] disabled:text-text-disabled",
@@ -3999,6 +4296,9 @@ var iconButtonVariants = cva10(
3999
4296
  className: "border-[var(--error)] bg-[var(--error-bg)] text-[var(--error)]"
4000
4297
  }
4001
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.
4002
4302
  defaultVariants: {
4003
4303
  variant: "ghost",
4004
4304
  size: "md",
@@ -4037,7 +4337,7 @@ var iconStrokeWidth = {
4037
4337
  md: 2.25,
4038
4338
  lg: 1.75
4039
4339
  };
4040
- var IconButton = React23.forwardRef(
4340
+ var IconButton = React24.forwardRef(
4041
4341
  ({
4042
4342
  className,
4043
4343
  variant = "ghost",
@@ -4056,7 +4356,7 @@ var IconButton = React23.forwardRef(
4056
4356
  const isToggle = pressed !== void 0;
4057
4357
  const isPressed = pressed === true;
4058
4358
  const hoverTitle = title ?? (typeof ariaLabel === "string" ? ariaLabel : void 0);
4059
- return /* @__PURE__ */ jsxs24(
4359
+ return /* @__PURE__ */ jsxs25(
4060
4360
  "button",
4061
4361
  {
4062
4362
  ref,
@@ -4074,7 +4374,7 @@ var IconButton = React23.forwardRef(
4074
4374
  ),
4075
4375
  type: type ?? "button",
4076
4376
  children: [
4077
- /* @__PURE__ */ jsx25(
4377
+ /* @__PURE__ */ jsx26(
4078
4378
  Icon,
4079
4379
  {
4080
4380
  "aria-hidden": "true",
@@ -4083,7 +4383,7 @@ var IconButton = React23.forwardRef(
4083
4383
  strokeWidth: iconStrokeWidth[resolvedSize]
4084
4384
  }
4085
4385
  ),
4086
- badge !== void 0 ? /* @__PURE__ */ jsx25(
4386
+ badge !== void 0 ? /* @__PURE__ */ jsx26(
4087
4387
  "span",
4088
4388
  {
4089
4389
  "aria-hidden": "true",
@@ -4098,291 +4398,76 @@ var IconButton = React23.forwardRef(
4098
4398
  );
4099
4399
  }
4100
4400
  );
4101
- IconButton.displayName = "IconButton";
4102
-
4103
- // src/components/ui/popover.tsx
4104
- import * as React24 from "react";
4105
- import { Popover as PopoverPrimitive } from "radix-ui";
4106
- import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
4107
- function Popover({ modal = false, ...props }) {
4108
- return /* @__PURE__ */ jsx26(PopoverPrimitive.Root, { modal, ...props });
4109
- }
4110
- var popoverArrowClassName = "fill-[var(--bg-surface)] stroke-[var(--border)] [&>polygon]:[vector-effect:non-scaling-stroke]";
4111
- var PopoverTrigger = PopoverPrimitive.Trigger;
4112
- var PopoverAnchor = PopoverPrimitive.Anchor;
4113
- var PopoverClose = PopoverPrimitive.Close;
4114
- var PopoverContent = React24.forwardRef(({ className, align = "center", sideOffset = 8, collisionPadding = 8, showArrow = false, children, ...props }, ref) => /* @__PURE__ */ jsx26(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsxs25(
4115
- PopoverPrimitive.Content,
4116
- {
4117
- ref,
4118
- align,
4119
- sideOffset,
4120
- collisionPadding,
4121
- "data-slot": "popover-content",
4122
- className: cn(
4123
- "z-[var(--z-popover)] w-[260px] outline-none",
4124
- "rounded-[var(--radius-md)] border border-[var(--border)]",
4125
- "bg-[var(--bg-surface)] p-[var(--space-4)] text-foreground",
4126
- "shadow-[var(--shadow-4)]",
4127
- "data-[state=open]:animate-in data-[state=closed]:animate-out",
4128
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
4129
- "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
4130
- "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
4131
- "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4132
- "motion-reduce:animate-none",
4133
- className
4134
- ),
4135
- ...props,
4136
- children: [
4137
- children,
4138
- showArrow ? /* @__PURE__ */ jsx26(
4139
- PopoverPrimitive.Arrow,
4140
- {
4141
- "data-slot": "popover-arrow",
4142
- className: popoverArrowClassName,
4143
- width: 11,
4144
- height: 5
4145
- }
4146
- ) : null
4147
- ]
4148
- }
4149
- ) }));
4150
- PopoverContent.displayName = PopoverPrimitive.Content.displayName;
4151
- var PopoverArrow = React24.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx26(
4152
- PopoverPrimitive.Arrow,
4153
- {
4154
- ref,
4155
- "data-slot": "popover-arrow",
4156
- className: cn(popoverArrowClassName, className),
4157
- width: 11,
4158
- height: 5,
4159
- ...props
4160
- }
4161
- ));
4162
- PopoverArrow.displayName = PopoverPrimitive.Arrow.displayName;
4163
-
4164
- // src/components/ui/sheet-drawer.tsx
4165
- import { Maximize2Icon, Minimize2Icon, XIcon as XIcon3 } from "lucide-react";
4166
-
4167
- // src/components/ui/sheet.tsx
4168
- import { XIcon as XIcon2 } from "lucide-react";
4169
- import { Dialog as SheetPrimitive } from "radix-ui";
4170
- import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
4171
- var defaultSheetMotionConfig = {
4172
- type: "slide",
4173
- duration: 300,
4174
- easing: "decel"
4175
- };
4176
- var sheetMotionEasingValue = {
4177
- standard: "var(--ease-standard)",
4178
- // decel/sharp have no canonical --ease-* token; these compat beziers are frozen
4179
- // specifically to back this public `easing` prop (see tokens/compat.css).
4180
- decel: "var(--easing-decel)",
4181
- accel: "var(--ease-in)",
4182
- sharp: "var(--easing-sharp)",
4183
- bounce: "var(--ease-out)"
4184
- };
4185
- function resolveSheetMotionConfig(motion) {
4186
- if (motion === false) return false;
4187
- return {
4188
- ...defaultSheetMotionConfig,
4189
- ...motion
4190
- };
4191
- }
4192
- function formatSheetMotionDuration(duration) {
4193
- return typeof duration === "number" ? `${duration}ms` : duration;
4194
- }
4195
- function getSheetMotionStyle(motionConfig, style) {
4196
- if (!motionConfig) return style;
4197
- return {
4198
- ...style,
4199
- "--sheet-motion-duration": formatSheetMotionDuration(motionConfig.duration),
4200
- "--sheet-motion-easing": sheetMotionEasingValue[motionConfig.easing]
4201
- };
4202
- }
4203
- function Sheet({ ...props }) {
4204
- return /* @__PURE__ */ jsx27(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
4205
- }
4206
- function SheetTrigger({
4207
- ...props
4208
- }) {
4209
- return /* @__PURE__ */ jsx27(SheetPrimitive.Trigger, { "data-slot": "sheet-trigger", ...props });
4210
- }
4211
- function SheetClose({
4212
- ...props
4213
- }) {
4214
- return /* @__PURE__ */ jsx27(SheetPrimitive.Close, { "data-slot": "sheet-close", ...props });
4215
- }
4216
- function SheetPortal({
4217
- ...props
4218
- }) {
4219
- return /* @__PURE__ */ jsx27(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
4220
- }
4221
- function SheetOverlay({
4222
- className,
4223
- motion,
4224
- style,
4225
- ...props
4226
- }) {
4227
- const motionConfig = resolveSheetMotionConfig(motion);
4228
- return /* @__PURE__ */ jsx27(
4229
- SheetPrimitive.Overlay,
4230
- {
4231
- "data-slot": "sheet-overlay",
4232
- className: cn(
4233
- "fixed inset-0 z-[var(--z-overlay)] bg-[var(--scrim)]",
4234
- motionConfig && cn(
4235
- "transition-opacity motion-reduce:transition-none",
4236
- "duration-[var(--sheet-motion-duration)]",
4237
- "data-[state=closed]:opacity-0 data-[state=open]:opacity-100",
4238
- "data-[state=open]:animate-[olun-sheet-fade-in_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]",
4239
- "data-[state=closed]:animate-[olun-sheet-fade-out_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]",
4240
- "motion-reduce:animate-none"
4241
- ),
4242
- className
4243
- ),
4244
- style: getSheetMotionStyle(motionConfig, style),
4245
- ...props
4246
- }
4247
- );
4248
- }
4249
- function SheetContent({
4250
- className,
4251
- children,
4252
- side = "right",
4253
- mobileSide,
4254
- motion,
4255
- showCloseButton = false,
4256
- style,
4257
- ...props
4258
- }) {
4259
- const motionConfig = resolveSheetMotionConfig(motion);
4260
- const hasSlideMotion = motionConfig && motionConfig.type === "slide";
4261
- return /* @__PURE__ */ jsxs26(SheetPortal, { children: [
4262
- /* @__PURE__ */ jsx27(SheetOverlay, { motion: motionConfig }),
4263
- /* @__PURE__ */ jsxs26(
4264
- SheetPrimitive.Content,
4265
- {
4266
- "data-slot": "sheet-content",
4267
- className: cn(
4268
- "fixed z-[var(--z-modal)] flex flex-col gap-4 border-[var(--border)] bg-[var(--bg-surface)] shadow-[var(--shadow-4)]",
4269
- motionConfig && cn(
4270
- "motion-reduce:animate-none",
4271
- motionConfig.type === "fade" && "data-[state=open]:animate-[olun-sheet-fade-in_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] data-[state=closed]:animate-[olun-sheet-fade-out_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
4272
- ),
4273
- side === "right" && cn(
4274
- "inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
4275
- hasSlideMotion && "data-[state=open]:animate-[olun-sheet-in-from-right_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] data-[state=closed]:animate-[olun-sheet-out-to-right_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
4276
- ),
4277
- side === "left" && cn(
4278
- "inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
4279
- hasSlideMotion && "data-[state=open]:animate-[olun-sheet-in-from-left_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] data-[state=closed]:animate-[olun-sheet-out-to-left_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
4280
- ),
4281
- side === "top" && cn(
4282
- "inset-x-0 top-0 h-auto border-b",
4283
- hasSlideMotion && "data-[state=open]:animate-[olun-sheet-in-from-top_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] data-[state=closed]:animate-[olun-sheet-out-to-top_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
4284
- ),
4285
- side === "bottom" && cn(
4286
- "inset-x-0 bottom-0 h-auto border-t",
4287
- hasSlideMotion && "data-[state=open]:animate-[olun-sheet-in-from-bottom_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] data-[state=closed]:animate-[olun-sheet-out-to-bottom_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
4288
- ),
4289
- mobileSide === "right" && cn(
4290
- "max-[899px]:inset-y-0 max-[899px]:right-0 max-[899px]:left-auto max-[899px]:h-full max-[899px]:w-3/4 max-[899px]:border-l max-[899px]:border-t-0 max-[899px]:rounded-none",
4291
- hasSlideMotion && "max-[899px]:data-[state=open]:animate-[olun-sheet-in-from-right_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] max-[899px]:data-[state=closed]:animate-[olun-sheet-out-to-right_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
4292
- ),
4293
- mobileSide === "left" && cn(
4294
- "max-[899px]:inset-y-0 max-[899px]:left-0 max-[899px]:right-auto max-[899px]:h-full max-[899px]:w-3/4 max-[899px]:border-r max-[899px]:border-t-0 max-[899px]:rounded-none",
4295
- hasSlideMotion && "max-[899px]:data-[state=open]:animate-[olun-sheet-in-from-left_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both] max-[899px]:data-[state=closed]:animate-[olun-sheet-out-to-left_var(--sheet-motion-duration)_var(--sheet-motion-easing)_both]"
4296
- ),
4297
- mobileSide === "top" && cn(
4298
- // `max-w-none!` overrides the side variant's `sm:max-w-sm` cap (see mobileSide bottom).
4299
- "max-[899px]:inset-x-0 max-[899px]:top-0 max-[899px]:bottom-auto max-[899px]:h-auto max-[899px]:w-full max-[899px]:max-w-none! max-[899px]:border-b max-[899px]:border-l-0 max-[899px]:rounded-none",
4300
- 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]"
4301
- ),
4302
- mobileSide === "bottom" && cn(
4303
- // `max-w-none!` overrides the side variant's `sm:max-w-sm` cap so the bottom sheet
4304
- // spans the full viewport width across the whole < 900px band (not capped to 24rem).
4305
- "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",
4306
- 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]"
4307
- ),
4308
- className
4309
- ),
4310
- style: getSheetMotionStyle(motionConfig, style),
4311
- ...props,
4312
- children: [
4313
- children,
4314
- showCloseButton && /* @__PURE__ */ jsxs26(SheetPrimitive.Close, { className: "absolute top-4 right-4 cursor-pointer rounded-xs 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: [
4315
- /* @__PURE__ */ jsx27(XIcon2, { className: "size-[16px]" }),
4316
- /* @__PURE__ */ jsx27("span", { className: "sr-only", children: "Close" })
4317
- ] })
4318
- ]
4319
- }
4320
- )
4321
- ] });
4322
- }
4323
- function SheetBody({ className, ...props }) {
4324
- return /* @__PURE__ */ jsx27(
4325
- "div",
4326
- {
4327
- "data-slot": "sheet-body",
4328
- className: cn("flex-1 overflow-y-auto p-4", className),
4329
- ...props
4330
- }
4331
- );
4332
- }
4333
- function SheetHeader({ className, ...props }) {
4334
- return /* @__PURE__ */ jsx27(
4335
- "div",
4336
- {
4337
- "data-slot": "sheet-header",
4338
- className: cn("flex flex-col gap-1.5 p-4", className),
4339
- ...props
4340
- }
4341
- );
4342
- }
4343
- function SheetFooter({ className, ...props }) {
4344
- return /* @__PURE__ */ jsx27(
4345
- "div",
4346
- {
4347
- "data-slot": "sheet-footer",
4348
- className: cn("mt-auto flex flex-col gap-2 p-4", className),
4349
- ...props
4350
- }
4351
- );
4352
- }
4353
- function SheetTitle({
4354
- className,
4355
- ...props
4356
- }) {
4357
- return /* @__PURE__ */ jsx27(
4358
- SheetPrimitive.Title,
4359
- {
4360
- "data-slot": "sheet-title",
4361
- className: cn("font-semibold text-foreground", className),
4362
- ...props
4363
- }
4364
- );
4365
- }
4366
- function SheetDescription({
4367
- className,
4368
- ...props
4369
- }) {
4370
- return /* @__PURE__ */ jsx27(
4371
- SheetPrimitive.Description,
4372
- {
4373
- "data-slot": "sheet-description",
4374
- className: cn("text-sm text-muted-foreground", className),
4375
- ...props
4376
- }
4377
- );
4401
+ IconButton.displayName = "IconButton";
4402
+
4403
+ // src/components/ui/popover.tsx
4404
+ import * as React25 from "react";
4405
+ import { Popover as PopoverPrimitive } from "radix-ui";
4406
+ import { jsx as jsx27, jsxs as jsxs26 } from "react/jsx-runtime";
4407
+ function Popover({ modal = false, ...props }) {
4408
+ return /* @__PURE__ */ jsx27(PopoverPrimitive.Root, { modal, ...props });
4378
4409
  }
4410
+ var popoverArrowClassName = "fill-[var(--bg-surface)] stroke-[var(--border)] [&>polygon]:[vector-effect:non-scaling-stroke]";
4411
+ var PopoverTrigger = PopoverPrimitive.Trigger;
4412
+ var PopoverAnchor = PopoverPrimitive.Anchor;
4413
+ 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(
4415
+ PopoverPrimitive.Content,
4416
+ {
4417
+ ref,
4418
+ align,
4419
+ sideOffset,
4420
+ collisionPadding,
4421
+ "data-slot": "popover-content",
4422
+ className: cn(
4423
+ "z-[var(--z-popover)] w-[260px] outline-none",
4424
+ "rounded-[var(--radius-md)] border border-[var(--border)]",
4425
+ "bg-[var(--bg-surface)] p-[var(--space-4)] text-foreground",
4426
+ "shadow-[var(--shadow-16)]",
4427
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
4428
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
4429
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
4430
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
4431
+ "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4432
+ "motion-reduce:animate-none",
4433
+ className
4434
+ ),
4435
+ ...props,
4436
+ children: [
4437
+ children,
4438
+ showArrow ? /* @__PURE__ */ jsx27(
4439
+ PopoverPrimitive.Arrow,
4440
+ {
4441
+ "data-slot": "popover-arrow",
4442
+ className: popoverArrowClassName,
4443
+ width: 11,
4444
+ height: 5
4445
+ }
4446
+ ) : null
4447
+ ]
4448
+ }
4449
+ ) }));
4450
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName;
4451
+ var PopoverArrow = React25.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx27(
4452
+ PopoverPrimitive.Arrow,
4453
+ {
4454
+ ref,
4455
+ "data-slot": "popover-arrow",
4456
+ className: cn(popoverArrowClassName, className),
4457
+ width: 11,
4458
+ height: 5,
4459
+ ...props
4460
+ }
4461
+ ));
4462
+ PopoverArrow.displayName = PopoverPrimitive.Arrow.displayName;
4379
4463
 
4380
4464
  // src/components/ui/sheet-drawer.tsx
4465
+ import { Maximize2Icon, Minimize2Icon, XIcon as XIcon3 } from "lucide-react";
4381
4466
  import { jsx as jsx28, jsxs as jsxs27 } from "react/jsx-runtime";
4382
4467
  var sheetDrawerContentClassName = cn(
4383
4468
  "gap-0 p-0",
4384
4469
  "bg-[var(--bg-surface)] text-foreground",
4385
- "border-[var(--border)] shadow-[var(--shadow-4)]",
4470
+ "border-[var(--border)] shadow-[var(--shadow-16)]",
4386
4471
  "min-[900px]:w-[480px] min-[900px]:max-w-[480px]",
4387
4472
  "max-[899px]:h-[min(85dvh,720px)] max-[899px]:max-h-[85dvh] max-[899px]:w-full max-[899px]:max-w-none",
4388
4473
  "max-[899px]:rounded-t-[var(--radius-lg)]"
@@ -4402,7 +4487,7 @@ var sheetDrawerTitleClassName = "text-[18px] font-bold leading-snug text-foregro
4402
4487
  var sheetDrawerDescriptionClassName = "break-keep text-[14px] leading-normal text-text-secondary";
4403
4488
  var sheetDrawerCloseButtonClassName = cn(
4404
4489
  "flex size-[32px] shrink-0 cursor-pointer items-center justify-center",
4405
- "rounded-[var(--radius-sm)] text-text-tertiary transition-colors",
4490
+ "rounded-[var(--radius-md)] text-text-tertiary transition-colors",
4406
4491
  "hover:bg-[var(--action-hover)] hover:text-foreground",
4407
4492
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2"
4408
4493
  );
@@ -4411,7 +4496,7 @@ var sheetDrawerHeaderActionsClassName = cn(
4411
4496
  );
4412
4497
  var sheetDrawerExpandButtonClassName = cn(
4413
4498
  "inline-flex cursor-pointer items-center justify-center gap-[var(--space-1)]",
4414
- "rounded-[var(--radius-sm)] text-text-tertiary transition-colors",
4499
+ "rounded-[var(--radius-md)] text-text-tertiary transition-colors",
4415
4500
  "hover:bg-[var(--action-hover)] hover:text-foreground",
4416
4501
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2",
4417
4502
  "h-[32px] px-[var(--space-2)]"
@@ -4554,7 +4639,7 @@ var collapsibleClassNames = {
4554
4639
  trigger: "hidden"
4555
4640
  }
4556
4641
  };
4557
- var FilterToolbar = React25.forwardRef(
4642
+ var FilterToolbar = React26.forwardRef(
4558
4643
  ({
4559
4644
  className,
4560
4645
  search,
@@ -4569,15 +4654,15 @@ var FilterToolbar = React25.forwardRef(
4569
4654
  actions,
4570
4655
  ...props
4571
4656
  }, ref) => {
4572
- const [rootElement, setRootElement] = React25.useState(
4657
+ const [rootElement, setRootElement] = React26.useState(
4573
4658
  null
4574
4659
  );
4575
- const [containerWidth, setContainerWidth] = React25.useState(
4660
+ const [containerWidth, setContainerWidth] = React26.useState(
4576
4661
  null
4577
4662
  );
4578
- const [overlayOpen, setOverlayOpen] = React25.useState(false);
4579
- const triggerRef = React25.useRef(null);
4580
- const setRootRefs = React25.useCallback(
4663
+ const [overlayOpen, setOverlayOpen] = React26.useState(false);
4664
+ const triggerRef = React26.useRef(null);
4665
+ const setRootRefs = React26.useCallback(
4581
4666
  (element) => {
4582
4667
  setRootElement(element);
4583
4668
  if (typeof ref === "function") ref(element);
@@ -4585,7 +4670,7 @@ var FilterToolbar = React25.forwardRef(
4585
4670
  },
4586
4671
  [ref]
4587
4672
  );
4588
- React25.useEffect(() => {
4673
+ React26.useEffect(() => {
4589
4674
  if (!rootElement) return;
4590
4675
  const updateWidth = () => {
4591
4676
  setContainerWidth(rootElement.getBoundingClientRect().width);
@@ -4596,7 +4681,7 @@ var FilterToolbar = React25.forwardRef(
4596
4681
  observer.observe(rootElement);
4597
4682
  return () => observer.disconnect();
4598
4683
  }, [rootElement]);
4599
- const handleOverlayOpenChange = React25.useCallback((open) => {
4684
+ const handleOverlayOpenChange = React26.useCallback((open) => {
4600
4685
  setOverlayOpen(open);
4601
4686
  if (!open) queueMicrotask(() => triggerRef.current?.focus());
4602
4687
  }, []);
@@ -4795,12 +4880,12 @@ var FilterToolbar = React25.forwardRef(
4795
4880
  FilterToolbar.displayName = "FilterToolbar";
4796
4881
 
4797
4882
  // src/components/ui/data-table.tsx
4798
- import * as React27 from "react";
4883
+ import * as React28 from "react";
4799
4884
  import { ChevronDown as ChevronDown3, ChevronUp as ChevronUp2, ChevronsUpDown } from "lucide-react";
4800
4885
  import { cva as cva12 } from "class-variance-authority";
4801
4886
 
4802
4887
  // src/components/ui/checkbox.tsx
4803
- import * as React26 from "react";
4888
+ import * as React27 from "react";
4804
4889
  import { cva as cva11 } from "class-variance-authority";
4805
4890
  import { Check as Check3, Minus } from "lucide-react";
4806
4891
  import { Checkbox as CheckboxPrimitive } from "radix-ui";
@@ -4860,7 +4945,7 @@ var checkboxGroupItemVariants = cva11(
4860
4945
  {
4861
4946
  variants: {
4862
4947
  appearance: {
4863
- plain: "inline-flex items-start gap-[var(--space-3)] rounded-[var(--radius-sm)] px-pad-compact-x py-pad-compact-y",
4948
+ plain: "inline-flex items-start gap-[var(--space-3)] rounded-[var(--radius-md)] px-pad-compact-x py-pad-compact-y",
4864
4949
  card: [
4865
4950
  "flex min-h-[calc(var(--space-12)+var(--space-2))] items-start gap-[var(--space-3)]",
4866
4951
  "rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-surface)]",
@@ -4907,11 +4992,11 @@ var checkboxGroupBoxVariants = cva11(
4907
4992
  }
4908
4993
  }
4909
4994
  );
4910
- var CheckboxGroupContext = React26.createContext(null);
4995
+ var CheckboxGroupContext = React27.createContext(null);
4911
4996
  function getLabel(children, label) {
4912
4997
  return children ?? label;
4913
4998
  }
4914
- var Checkbox = React26.forwardRef(
4999
+ var Checkbox = React27.forwardRef(
4915
5000
  ({
4916
5001
  className,
4917
5002
  size = "md",
@@ -4929,8 +5014,8 @@ var Checkbox = React26.forwardRef(
4929
5014
  onCheckedChange,
4930
5015
  ...props
4931
5016
  }, ref) => {
4932
- const group = React26.useContext(CheckboxGroupContext);
4933
- const generatedId = React26.useId();
5017
+ const group = React27.useContext(CheckboxGroupContext);
5018
+ const generatedId = React27.useId();
4934
5019
  const checkboxId = id ?? generatedId;
4935
5020
  const labelContent = getLabel(children, label);
4936
5021
  const isGrouped = Boolean(group && value != null);
@@ -5196,7 +5281,7 @@ function getRenderedCell(row, column) {
5196
5281
  if (value === null || value === void 0) {
5197
5282
  return null;
5198
5283
  }
5199
- if (React27.isValidElement(value)) {
5284
+ if (React28.isValidElement(value)) {
5200
5285
  return value;
5201
5286
  }
5202
5287
  return String(value);
@@ -5292,8 +5377,9 @@ function MobileSortControls({
5292
5377
  type: "button",
5293
5378
  "data-slot": "data-table-mobile-sort-button",
5294
5379
  size: "xs",
5295
- variant: active ? "secondary" : "outline",
5380
+ variant: "secondary",
5296
5381
  "aria-pressed": active,
5382
+ className: active ? "border-[var(--border-strong)] bg-[var(--action-selected)] hover:border-[var(--border-strong)] hover:bg-[var(--action-selected)]" : void 0,
5297
5383
  onClick: () => onSortChange?.(column.key, nextSort),
5298
5384
  children: /* @__PURE__ */ jsxs30("span", { className: "inline-flex min-w-0 items-center gap-[var(--space-1)]", children: [
5299
5385
  /* @__PURE__ */ jsx31("span", { className: "truncate", children: column.header }),
@@ -5558,28 +5644,41 @@ function DataTableMobileCardView({
5558
5644
  }
5559
5645
  );
5560
5646
  }
5561
- var MemoDataTableRow = React27.memo(DataTableRowView);
5562
- var MemoDataTableMobileCard = React27.memo(DataTableMobileCardView);
5563
- var useIsomorphicLayoutEffect = typeof window === "undefined" ? React27.useEffect : React27.useLayoutEffect;
5647
+ var MemoDataTableRow = React28.memo(DataTableRowView);
5648
+ var MemoDataTableMobileCard = React28.memo(DataTableMobileCardView);
5649
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? React28.useEffect : React28.useLayoutEffect;
5564
5650
  var VIRTUAL_DEFAULT_OVERSCAN = 8;
5565
5651
  var VIRTUAL_INITIAL_ROWS = 24;
5566
5652
  var VIRTUAL_FALLBACK_SIZE = { desktop: 48, mobile: 120 };
5653
+ function getScrollParent(node) {
5654
+ for (let el = node.parentElement; el && el !== document.body; el = el.parentElement) {
5655
+ const { overflowY } = window.getComputedStyle(el);
5656
+ if ((overflowY === "auto" || overflowY === "scroll") && el.scrollHeight > el.clientHeight) {
5657
+ return el;
5658
+ }
5659
+ }
5660
+ return null;
5661
+ }
5567
5662
  function useVirtualWindow({
5568
5663
  enabled,
5569
5664
  count,
5570
5665
  overscan,
5666
+ onRangeChange,
5571
5667
  desktopRef,
5668
+ headerRef,
5572
5669
  desktopListRef,
5573
5670
  mobileListRef
5574
5671
  }) {
5575
- const [win, setWin] = React27.useState({
5672
+ const [win, setWin] = React28.useState({
5576
5673
  layout: null,
5577
5674
  start: 0,
5578
5675
  end: VIRTUAL_INITIAL_ROWS,
5579
5676
  size: 0
5580
5677
  });
5581
- const measuredSize = React27.useRef({ desktop: 0, mobile: 0 });
5582
- const update = React27.useRef(() => void 0);
5678
+ const measuredSize = React28.useRef({ desktop: 0, mobile: 0 });
5679
+ const update = React28.useRef(() => void 0);
5680
+ const reported = React28.useRef("");
5681
+ const latest = React28.useRef({ count, layout: "desktop" });
5583
5682
  update.current = () => {
5584
5683
  if (!enabled) {
5585
5684
  return;
@@ -5593,6 +5692,7 @@ function useVirtualWindow({
5593
5692
  measuredSize.current[layout] = itemHeight;
5594
5693
  }
5595
5694
  const size = measuredSize.current[layout] || VIRTUAL_FALLBACK_SIZE[layout];
5695
+ latest.current = { count, layout };
5596
5696
  let start = 0;
5597
5697
  let end = Math.min(count, VIRTUAL_INITIAL_ROWS);
5598
5698
  if (list) {
@@ -5600,6 +5700,23 @@ function useVirtualWindow({
5600
5700
  const viewport = window.innerHeight || document.documentElement.clientHeight;
5601
5701
  start = Math.min(count, Math.max(0, Math.floor(-top / size) - overscan));
5602
5702
  end = Math.min(count, Math.max(start, Math.ceil((viewport - top) / size) + overscan));
5703
+ if (onRangeChange) {
5704
+ const container = getScrollParent(list);
5705
+ const bounds = container?.getBoundingClientRect();
5706
+ let visibleTop = Math.max(0, bounds ? bounds.top : 0);
5707
+ const visibleBottom = Math.min(viewport, bounds ? bounds.bottom : viewport);
5708
+ const header = headerRef.current;
5709
+ if (layout === "desktop" && header) {
5710
+ visibleTop = Math.max(visibleTop, header.getBoundingClientRect().bottom);
5711
+ }
5712
+ const first = Math.min(count, Math.max(0, Math.floor((visibleTop - top) / size)));
5713
+ const last = Math.min(count, Math.max(first, Math.ceil((visibleBottom - top) / size)));
5714
+ const key = `${first}:${last}:${count}`;
5715
+ if (reported.current !== key) {
5716
+ reported.current = key;
5717
+ onRangeChange({ start: first, end: last });
5718
+ }
5719
+ }
5603
5720
  }
5604
5721
  setWin(
5605
5722
  (prev) => prev.layout === layout && prev.start === start && prev.end === end && prev.size === size ? prev : { layout, start, end, size }
@@ -5608,7 +5725,7 @@ function useVirtualWindow({
5608
5725
  useIsomorphicLayoutEffect(() => {
5609
5726
  update.current();
5610
5727
  });
5611
- React27.useEffect(() => {
5728
+ React28.useEffect(() => {
5612
5729
  if (!enabled) {
5613
5730
  return;
5614
5731
  }
@@ -5630,7 +5747,34 @@ function useVirtualWindow({
5630
5747
  window.cancelAnimationFrame(frame);
5631
5748
  };
5632
5749
  }, [enabled]);
5633
- return win;
5750
+ const scrollToIndex = React28.useCallback(
5751
+ (index) => {
5752
+ const { count: rowCount, layout } = latest.current;
5753
+ const list = (layout === "desktop" ? desktopListRef : mobileListRef).current;
5754
+ if (!list || rowCount === 0) {
5755
+ return;
5756
+ }
5757
+ const row = Math.min(rowCount - 1, Math.max(0, Math.floor(index)));
5758
+ const size = measuredSize.current[layout] || VIRTUAL_FALLBACK_SIZE[layout];
5759
+ const container = getScrollParent(list);
5760
+ let target = container ? container.getBoundingClientRect().top : 0;
5761
+ const header = headerRef.current;
5762
+ if (layout === "desktop" && header) {
5763
+ const { position, top } = window.getComputedStyle(header);
5764
+ if (position === "sticky") {
5765
+ target += (Number.parseFloat(top) || 0) + header.getBoundingClientRect().height;
5766
+ }
5767
+ }
5768
+ const delta = list.getBoundingClientRect().top + row * size - target;
5769
+ if (container) {
5770
+ container.scrollTop += delta;
5771
+ } else {
5772
+ window.scrollBy(0, delta);
5773
+ }
5774
+ },
5775
+ [desktopListRef, headerRef, mobileListRef]
5776
+ );
5777
+ return { win, scrollToIndex };
5634
5778
  }
5635
5779
  function DataTableInner({
5636
5780
  className,
@@ -5642,6 +5786,8 @@ function DataTableInner({
5642
5786
  selectable = false,
5643
5787
  selectedIds,
5644
5788
  onSelectionChange,
5789
+ selectionUnit = "\uAC1C",
5790
+ announceSelection = true,
5645
5791
  activeRowId,
5646
5792
  onRowContextMenu,
5647
5793
  sortBy,
@@ -5658,17 +5804,21 @@ function DataTableInner({
5658
5804
  }, ref) {
5659
5805
  const virtualOptions = virtual ? virtual === true ? {} : virtual : null;
5660
5806
  const isVirtual = virtualOptions !== null;
5661
- const desktopRef = React27.useRef(null);
5662
- const desktopListRef = React27.useRef(null);
5663
- const mobileListRef = React27.useRef(null);
5664
- const virtualWindow = useVirtualWindow({
5807
+ const desktopRef = React28.useRef(null);
5808
+ const headerRef = React28.useRef(null);
5809
+ const desktopListRef = React28.useRef(null);
5810
+ const mobileListRef = React28.useRef(null);
5811
+ const { win: virtualWindow, scrollToIndex } = useVirtualWindow({
5665
5812
  enabled: isVirtual,
5666
5813
  count: data.length,
5667
5814
  overscan: virtualOptions?.overscan ?? VIRTUAL_DEFAULT_OVERSCAN,
5815
+ onRangeChange: virtualOptions?.onRangeChange,
5668
5816
  desktopRef,
5817
+ headerRef,
5669
5818
  desktopListRef,
5670
5819
  mobileListRef
5671
5820
  });
5821
+ React28.useImperativeHandle(virtualOptions?.handleRef, () => ({ scrollToIndex }), [scrollToIndex]);
5672
5822
  const resolvedSelectedIds = selectedIds ?? /* @__PURE__ */ new Set();
5673
5823
  const rowIds = data.map((row) => getRowId(row, keyField));
5674
5824
  const selectedCount = rowIds.filter((id) => resolvedSelectedIds.has(id)).length;
@@ -5703,19 +5853,19 @@ function DataTableInner({
5703
5853
  window.location.assign(href);
5704
5854
  }
5705
5855
  };
5706
- const latestHandlers = React27.useRef({ toggleRow, activateRow, onRowContextMenu });
5856
+ const latestHandlers = React28.useRef({ toggleRow, activateRow, onRowContextMenu });
5707
5857
  useIsomorphicLayoutEffect(() => {
5708
5858
  latestHandlers.current = { toggleRow, activateRow, onRowContextMenu };
5709
5859
  });
5710
- const stableToggleRow = React27.useCallback(
5860
+ const stableToggleRow = React28.useCallback(
5711
5861
  (id, checked) => latestHandlers.current.toggleRow(id, checked),
5712
5862
  []
5713
5863
  );
5714
- const stableActivateRow = React27.useCallback(
5864
+ const stableActivateRow = React28.useCallback(
5715
5865
  (row, href, event) => latestHandlers.current.activateRow(row, href, event),
5716
5866
  []
5717
5867
  );
5718
- const stableRowContextMenu = React27.useCallback(
5868
+ const stableRowContextMenu = React28.useCallback(
5719
5869
  (rowId, event) => latestHandlers.current.onRowContextMenu?.(rowId, event),
5720
5870
  []
5721
5871
  );
@@ -5773,13 +5923,13 @@ function DataTableInner({
5773
5923
  ),
5774
5924
  ...props,
5775
5925
  children: [
5776
- selectable ? /* @__PURE__ */ jsx31(
5926
+ selectable && announceSelection ? /* @__PURE__ */ jsx31(
5777
5927
  "div",
5778
5928
  {
5779
5929
  "data-slot": "data-table-selection-status",
5780
5930
  "aria-live": "polite",
5781
5931
  className: "sr-only",
5782
- children: selectedCount > 0 ? `${selectedCount.toLocaleString("ko-KR")}\uAC1C \uC120\uD0DD\uB428` : ""
5932
+ children: selectedCount > 0 ? `${selectedCount.toLocaleString("ko-KR")}${selectionUnit} \uC120\uD0DD\uB428` : ""
5783
5933
  }
5784
5934
  ) : null,
5785
5935
  loading && data.length > 0 ? /* @__PURE__ */ jsx31(
@@ -5801,6 +5951,7 @@ function DataTableInner({
5801
5951
  /* @__PURE__ */ jsxs30(
5802
5952
  "div",
5803
5953
  {
5954
+ ref: headerRef,
5804
5955
  "data-slot": "data-table-header",
5805
5956
  role: "row",
5806
5957
  className: cn(
@@ -5937,7 +6088,7 @@ function DataTableInner({
5937
6088
  }
5938
6089
  );
5939
6090
  }
5940
- var DataTable = React27.forwardRef(DataTableInner);
6091
+ var DataTable = React28.forwardRef(DataTableInner);
5941
6092
  DataTable.displayName = "DataTable";
5942
6093
 
5943
6094
  // src/components/ui/dropdown-menu.tsx
@@ -5978,7 +6129,7 @@ function DropdownMenuContent({
5978
6129
  className: cn(
5979
6130
  "z-[var(--z-popover)] max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem]",
5980
6131
  "origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto",
5981
- "rounded-sm border border-[var(--border)] bg-[var(--bg-surface)] p-[var(--space-1)] text-text-primary shadow-2",
6132
+ "rounded-[var(--radius-lg)] border border-[var(--border)] bg-[var(--bg-surface)] p-[var(--space-1)] text-text-primary shadow-[var(--shadow-16)]",
5982
6133
  "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
5983
6134
  "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
5984
6135
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
@@ -6177,7 +6328,7 @@ function DropdownMenuSubContent({
6177
6328
  "data-slot": "dropdown-menu-sub-content",
6178
6329
  className: cn(
6179
6330
  "z-[var(--z-popover)] min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden",
6180
- "rounded-sm border border-[var(--border)] bg-[var(--bg-surface)] p-[var(--space-1)] text-text-primary shadow-2",
6331
+ "rounded-[var(--radius-lg)] border border-[var(--border)] bg-[var(--bg-surface)] p-[var(--space-1)] text-text-primary shadow-[var(--shadow-16)]",
6181
6332
  "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
6182
6333
  "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
6183
6334
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
@@ -6222,7 +6373,7 @@ function ContextMenu({
6222
6373
  }
6223
6374
 
6224
6375
  // src/components/ui/bulk-action-bar.tsx
6225
- import * as React28 from "react";
6376
+ import * as React29 from "react";
6226
6377
  import { X as X3 } from "lucide-react";
6227
6378
  import { jsx as jsx34, jsxs as jsxs33 } from "react/jsx-runtime";
6228
6379
  function ActionButton({ action }) {
@@ -6249,7 +6400,7 @@ function ActionButton({ action }) {
6249
6400
  gap: 6,
6250
6401
  height: 30,
6251
6402
  padding: "0 10px",
6252
- borderRadius: "var(--radius-sm)",
6403
+ borderRadius: "var(--radius-md)",
6253
6404
  fontFamily: "var(--font-sans)",
6254
6405
  fontSize: 13,
6255
6406
  fontWeight: 500,
@@ -6306,13 +6457,15 @@ function ClearButton({ onClear }) {
6306
6457
  flexShrink: 0,
6307
6458
  alignItems: "center",
6308
6459
  justifyContent: "center",
6309
- borderRadius: "var(--radius-sm)"
6460
+ borderRadius: "var(--radius-md)"
6310
6461
  },
6311
6462
  children: /* @__PURE__ */ jsx34(X3, { size: 16, strokeWidth: 1.75, "aria-hidden": "true" })
6312
6463
  }
6313
6464
  );
6314
6465
  }
6315
6466
  var INLINE_HEIGHT = 40;
6467
+ var HIT_AREA = 44;
6468
+ var HIT_INSET = 8;
6316
6469
  var floatingStyle = {
6317
6470
  position: "sticky",
6318
6471
  bottom: "calc(var(--space-4) + env(safe-area-inset-bottom))",
@@ -6361,10 +6514,10 @@ var idleLineStyle = {
6361
6514
  fontVariantNumeric: "tabular-nums",
6362
6515
  color: "var(--text-secondary)"
6363
6516
  };
6364
- var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React28.useEffect : React28.useLayoutEffect;
6517
+ var useIsomorphicLayoutEffect2 = typeof window === "undefined" ? React29.useEffect : React29.useLayoutEffect;
6365
6518
  function useCompactSummary(slot, enabled) {
6366
- const [fullWidth, setFullWidth] = React28.useState(null);
6367
- const measure = React28.useCallback(() => {
6519
+ const [fullWidth, setFullWidth] = React29.useState(null);
6520
+ const measure = React29.useCallback(() => {
6368
6521
  if (!slot) return;
6369
6522
  setFullWidth((prev) => {
6370
6523
  if (prev === null) return slot.scrollWidth > slot.clientWidth ? slot.scrollWidth : null;
@@ -6374,7 +6527,7 @@ function useCompactSummary(slot, enabled) {
6374
6527
  useIsomorphicLayoutEffect2(() => {
6375
6528
  if (enabled) measure();
6376
6529
  });
6377
- React28.useEffect(() => {
6530
+ React29.useEffect(() => {
6378
6531
  if (!enabled || !slot || typeof ResizeObserver === "undefined") return;
6379
6532
  const observer = new ResizeObserver(measure);
6380
6533
  observer.observe(slot);
@@ -6392,16 +6545,62 @@ function BulkActionBar({
6392
6545
  summary,
6393
6546
  compactSummary,
6394
6547
  idleContent,
6548
+ trailing,
6395
6549
  className,
6396
6550
  style,
6397
6551
  ...props
6398
6552
  }) {
6399
6553
  const inline = placement === "inline";
6400
- const [summaryElement, setSummaryElement] = React28.useState(null);
6554
+ const trailingSlot = trailing !== void 0 && trailing !== null ? /* @__PURE__ */ jsx34(
6555
+ "div",
6556
+ {
6557
+ "data-slot": "bulk-action-bar-trailing",
6558
+ style: {
6559
+ display: "flex",
6560
+ flexShrink: 0,
6561
+ alignItems: "center",
6562
+ gap: "var(--space-2)"
6563
+ },
6564
+ children: trailing
6565
+ }
6566
+ ) : null;
6567
+ const [summaryElement, setSummaryElement] = React29.useState(null);
6401
6568
  const compact = useCompactSummary(
6402
6569
  summaryElement,
6403
6570
  inline && compactSummary !== void 0 && compactSummary !== null
6404
6571
  );
6572
+ if (count === 0 && idleContent !== void 0 && trailingSlot) {
6573
+ return /* @__PURE__ */ jsxs33(
6574
+ "div",
6575
+ {
6576
+ "data-slot": "bulk-action-bar",
6577
+ "data-placement": placement,
6578
+ "data-state": "idle",
6579
+ className,
6580
+ style: { ...idleLineStyle, overflow: "visible", ...style },
6581
+ ...props,
6582
+ children: [
6583
+ /* @__PURE__ */ jsx34(
6584
+ "div",
6585
+ {
6586
+ role: "status",
6587
+ "data-slot": "bulk-action-bar-idle",
6588
+ style: {
6589
+ display: "flex",
6590
+ flex: "1 1 auto",
6591
+ minWidth: 0,
6592
+ alignItems: "center",
6593
+ columnGap: "var(--space-3)",
6594
+ overflow: "hidden"
6595
+ },
6596
+ children: idleContent
6597
+ }
6598
+ ),
6599
+ trailingSlot
6600
+ ]
6601
+ }
6602
+ );
6603
+ }
6405
6604
  if (count === 0 && idleContent !== void 0) {
6406
6605
  return /* @__PURE__ */ jsx34(
6407
6606
  "div",
@@ -6452,12 +6651,16 @@ function BulkActionBar({
6452
6651
  color: "var(--text-secondary)",
6453
6652
  ...inline ? (
6454
6653
  // inline-size containment: the summary never widens the band's parent. The
6455
- // slot is full-height with 3px side gutters so focus rings are not clipped.
6654
+ // slot clips text, so it is as tall as an IconButton's hit area (overhanging
6655
+ // the 40px band) and has that inset as its left gutter: a compact IconButton
6656
+ // keeps its full 44px target. The right gutter stays 3px (focus ring) so
6657
+ // clipped text keeps clear of the controls.
6456
6658
  {
6457
6659
  flex: "1 1 0",
6458
- alignSelf: "stretch",
6459
- margin: "0 -3px",
6460
- padding: "0 3px",
6660
+ alignSelf: "center",
6661
+ height: HIT_AREA,
6662
+ margin: `0 -3px 0 -${HIT_INSET}px`,
6663
+ padding: `0 3px 0 ${HIT_INSET}px`,
6461
6664
  overflow: "hidden",
6462
6665
  whiteSpace: "nowrap",
6463
6666
  contain: "inline-size"
@@ -6529,7 +6732,8 @@ function BulkActionBar({
6529
6732
  /* @__PURE__ */ jsx34(ClearButton, { onClear })
6530
6733
  ]
6531
6734
  }
6532
- )
6735
+ ),
6736
+ trailingSlot
6533
6737
  ]
6534
6738
  }
6535
6739
  );
@@ -6549,19 +6753,35 @@ function BulkActionBar({
6549
6753
  style: { ...floatingStyle, ...style },
6550
6754
  ...props,
6551
6755
  children: [
6552
- countLabel,
6553
- summarySlot,
6756
+ /* @__PURE__ */ jsxs33(
6757
+ "div",
6758
+ {
6759
+ role: "status",
6760
+ "data-slot": "bulk-action-bar-state",
6761
+ style: {
6762
+ display: "flex",
6763
+ minWidth: 0,
6764
+ alignItems: "center",
6765
+ gap: "var(--space-2)"
6766
+ },
6767
+ children: [
6768
+ countLabel,
6769
+ summarySlot
6770
+ ]
6771
+ }
6772
+ ),
6554
6773
  count > 0 && actions.length > 0 ? /* @__PURE__ */ jsx34(Divider, {}) : null,
6555
6774
  actionGroup,
6556
6775
  /* @__PURE__ */ jsx34(Divider, {}),
6557
- /* @__PURE__ */ jsx34(ClearButton, { onClear })
6776
+ /* @__PURE__ */ jsx34(ClearButton, { onClear }),
6777
+ trailingSlot
6558
6778
  ]
6559
6779
  }
6560
6780
  );
6561
6781
  }
6562
6782
 
6563
6783
  // src/components/ui/confirm-dialog.tsx
6564
- import * as React29 from "react";
6784
+ import * as React30 from "react";
6565
6785
  import { Fragment as Fragment8, jsx as jsx35, jsxs as jsxs34 } from "react/jsx-runtime";
6566
6786
  var confirmDialogContentClassName = cn(
6567
6787
  "fixed left-1/2 top-1/2 z-[var(--z-modal)]",
@@ -6591,12 +6811,14 @@ function ConfirmDialog({
6591
6811
  onConfirm,
6592
6812
  loading = false,
6593
6813
  children,
6594
- confirmDisabled = false
6814
+ confirmDisabled = false,
6815
+ mobilePresentation = "center"
6595
6816
  }) {
6596
- const [pending, setPending] = React29.useState(false);
6597
- const busyRef = React29.useRef(false);
6817
+ const [pending, setPending] = React30.useState(false);
6818
+ const busyRef = React30.useRef(false);
6598
6819
  const isBusy = loading || pending;
6599
- const handleOpenChange = React29.useCallback(
6820
+ const returnFocus = useReturnFocus();
6821
+ const handleOpenChange = React30.useCallback(
6600
6822
  (nextOpen) => {
6601
6823
  if (!nextOpen && isBusy) {
6602
6824
  return;
@@ -6605,7 +6827,7 @@ function ConfirmDialog({
6605
6827
  },
6606
6828
  [isBusy, onOpenChange]
6607
6829
  );
6608
- const handleConfirm = React29.useCallback(async () => {
6830
+ const handleConfirm = React30.useCallback(async () => {
6609
6831
  if (busyRef.current || loading || confirmDisabled) {
6610
6832
  return;
6611
6833
  }
@@ -6645,11 +6867,23 @@ function ConfirmDialog({
6645
6867
  "data-slot": "dialog-footer",
6646
6868
  className: confirmDialogFooterClassName,
6647
6869
  children: [
6648
- /* @__PURE__ */ jsx35(Button, { variant: "secondary", disabled: isBusy, onClick: () => handleOpenChange(false), children: cancelLabel }),
6870
+ /* @__PURE__ */ jsx35(
6871
+ Button,
6872
+ {
6873
+ variant: "secondary",
6874
+ size: "lg",
6875
+ className: footerButtonHitAreaClassName,
6876
+ disabled: isBusy,
6877
+ onClick: () => handleOpenChange(false),
6878
+ children: cancelLabel
6879
+ }
6880
+ ),
6649
6881
  /* @__PURE__ */ jsx35(
6650
6882
  Button,
6651
6883
  {
6652
6884
  variant: tone === "destructive" ? "destructive" : "primary",
6885
+ size: "lg",
6886
+ className: footerButtonHitAreaClassName,
6653
6887
  loading: isBusy,
6654
6888
  disabled: confirmDisabled,
6655
6889
  onClick: handleConfirm,
@@ -6662,7 +6896,20 @@ function ConfirmDialog({
6662
6896
  ] });
6663
6897
  return /* @__PURE__ */ jsx35(Dialog, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs34(DialogPortal, { children: [
6664
6898
  /* @__PURE__ */ jsx35(DialogOverlay, {}),
6665
- /* @__PURE__ */ jsx35(DialogRawContent, { role: "alertdialog", "data-slot": "dialog-content", className: confirmDialogContentClassName, children: dialogBody })
6899
+ /* @__PURE__ */ jsx35(
6900
+ DialogRawContent,
6901
+ {
6902
+ role: "alertdialog",
6903
+ "data-slot": "dialog-content",
6904
+ className: cn(
6905
+ confirmDialogContentClassName,
6906
+ mobilePresentation === "sheet" && dialogMobileSheetClassName
6907
+ ),
6908
+ style: mobilePresentation === "sheet" ? dialogMobileSheetStyle() : void 0,
6909
+ ...returnFocus,
6910
+ children: dialogBody
6911
+ }
6912
+ )
6666
6913
  ] }) });
6667
6914
  }
6668
6915
 
@@ -6761,9 +7008,100 @@ function AvatarFallback({
6761
7008
  );
6762
7009
  }
6763
7010
 
6764
- // src/components/ui/badge.tsx
6765
- import * as React30 from "react";
7011
+ // src/components/ui/action-sheet.tsx
7012
+ import * as React31 from "react";
7013
+ import { X as X4 } from "lucide-react";
6766
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
+ );
7019
+ var actionSheetHeaderClassName = cn(
7020
+ "flex items-start gap-[var(--space-3)] px-[var(--space-4)] pt-[var(--space-4)] pb-[var(--space-3)]"
7021
+ );
7022
+ var actionSheetTitleClassName = cn(
7023
+ "break-keep text-[15px] font-semibold leading-snug text-foreground"
7024
+ );
7025
+ var actionSheetDescriptionClassName = cn(
7026
+ "mt-[var(--space-1)] break-keep text-[13px] leading-normal text-text-secondary"
7027
+ );
7028
+ var actionSheetListClassName = "min-h-0 overflow-y-auto";
7029
+ var actionSheetItemClassName = cn(
7030
+ "flex min-h-12 w-full cursor-pointer items-center gap-[var(--space-3)] px-[var(--space-4)] text-left",
7031
+ "border-t border-[var(--border-subtle)] text-[13px] font-medium text-text-primary",
7032
+ "transition-colors motion-reduce:transition-none hover:bg-[var(--action-hover)]",
7033
+ "focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[var(--focus-ring)]",
7034
+ "enabled:data-[destructive]:text-[var(--semantic-error-fg)]",
7035
+ "disabled:cursor-not-allowed disabled:bg-[var(--action-disabled-bg)] disabled:text-text-disabled"
7036
+ );
7037
+ function ActionSheet({
7038
+ open,
7039
+ onOpenChange,
7040
+ title,
7041
+ description,
7042
+ items,
7043
+ closeLabel = "\uB2EB\uAE30"
7044
+ }) {
7045
+ const pendingRef = React31.useRef(null);
7046
+ const returnFocus = useReturnFocus();
7047
+ const handleOpenChange = (nextOpen) => {
7048
+ pendingRef.current = null;
7049
+ onOpenChange(nextOpen);
7050
+ };
7051
+ const handleSelect = (item) => {
7052
+ onOpenChange(false);
7053
+ pendingRef.current = item;
7054
+ };
7055
+ const handleCloseAutoFocus = (event) => {
7056
+ returnFocus.onCloseAutoFocus(event);
7057
+ const item = pendingRef.current;
7058
+ pendingRef.current = null;
7059
+ item?.onSelect();
7060
+ };
7061
+ return /* @__PURE__ */ jsx38(Sheet, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs35(
7062
+ SheetContent,
7063
+ {
7064
+ side: "bottom",
7065
+ "data-slot": "action-sheet-content",
7066
+ className: actionSheetContentClassName,
7067
+ onOpenAutoFocus: returnFocus.onOpenAutoFocus,
7068
+ onCloseAutoFocus: handleCloseAutoFocus,
7069
+ ...description ? {} : { "aria-describedby": void 0 },
7070
+ children: [
7071
+ /* @__PURE__ */ jsxs35("div", { "data-slot": "action-sheet-header", className: actionSheetHeaderClassName, children: [
7072
+ /* @__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
7075
+ ] }),
7076
+ /* @__PURE__ */ jsx38(SheetClose, { asChild: true, children: /* @__PURE__ */ jsx38(IconButton, { size: "sm", icon: X4, "aria-label": closeLabel }) })
7077
+ ] }),
7078
+ /* @__PURE__ */ jsx38("div", { "data-slot": "action-sheet-list", className: actionSheetListClassName, children: items.map((item) => {
7079
+ const Icon = item.icon;
7080
+ return /* @__PURE__ */ jsxs35(
7081
+ "button",
7082
+ {
7083
+ type: "button",
7084
+ "data-slot": "action-sheet-item",
7085
+ "data-destructive": item.destructive ? "" : void 0,
7086
+ className: actionSheetItemClassName,
7087
+ disabled: item.disabled,
7088
+ onClick: () => handleSelect(item),
7089
+ 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 })
7092
+ ]
7093
+ },
7094
+ item.id
7095
+ );
7096
+ }) })
7097
+ ]
7098
+ }
7099
+ ) });
7100
+ }
7101
+
7102
+ // src/components/ui/badge.tsx
7103
+ import * as React32 from "react";
7104
+ import { jsx as jsx39, jsxs as jsxs36 } from "react/jsx-runtime";
6767
7105
  var DOT = {
6768
7106
  error: "var(--semantic-error-fg)",
6769
7107
  warning: "var(--semantic-warning-fg)",
@@ -6772,8 +7110,8 @@ var DOT = {
6772
7110
  neutral: "var(--text-tertiary)",
6773
7111
  brand: "var(--accent-pop)"
6774
7112
  };
6775
- var Badge = React30.forwardRef(
6776
- ({ tone = "neutral", className, children, ...props }, ref) => /* @__PURE__ */ jsxs35(
7113
+ var Badge = React32.forwardRef(
7114
+ ({ tone = "neutral", className, children, ...props }, ref) => /* @__PURE__ */ jsxs36(
6777
7115
  "span",
6778
7116
  {
6779
7117
  ref,
@@ -6787,7 +7125,7 @@ var Badge = React30.forwardRef(
6787
7125
  ),
6788
7126
  ...props,
6789
7127
  children: [
6790
- /* @__PURE__ */ jsx38(
7128
+ /* @__PURE__ */ jsx39(
6791
7129
  "span",
6792
7130
  {
6793
7131
  "aria-hidden": "true",
@@ -6804,8 +7142,8 @@ var Badge = React30.forwardRef(
6804
7142
  Badge.displayName = "Badge";
6805
7143
 
6806
7144
  // src/components/ui/two-tier-badge.tsx
6807
- import * as React31 from "react";
6808
- import { jsx as jsx39, jsxs as jsxs36 } from "react/jsx-runtime";
7145
+ import * as React33 from "react";
7146
+ import { jsx as jsx40, jsxs as jsxs37 } from "react/jsx-runtime";
6809
7147
  var FG = {
6810
7148
  neutral: "var(--text-secondary)",
6811
7149
  info: "var(--semantic-info-fg)",
@@ -6826,7 +7164,7 @@ var SEGMENT = {
6826
7164
  md: "gap-[7px] py-[var(--space-1)] px-[var(--space-3)] text-[14px]"
6827
7165
  };
6828
7166
  var DOT2 = { xs: 5, sm: 6, md: 7 };
6829
- var TwoTierBadge = React31.forwardRef(
7167
+ var TwoTierBadge = React33.forwardRef(
6830
7168
  ({ primary, secondary, tone = "neutral", emphasis = "subtle", size = "sm", showDot = false, className, style, ...props }, ref) => {
6831
7169
  const strong = emphasis === "strong";
6832
7170
  const fg = FG[tone];
@@ -6835,7 +7173,7 @@ var TwoTierBadge = React31.forwardRef(
6835
7173
  const frame = strong ? tinted : "var(--border-subtle)";
6836
7174
  const divider = strong ? tinted : "var(--border)";
6837
7175
  const dotSize = DOT2[size];
6838
- return /* @__PURE__ */ jsxs36(
7176
+ return /* @__PURE__ */ jsxs37(
6839
7177
  "span",
6840
7178
  {
6841
7179
  ref,
@@ -6849,14 +7187,14 @@ var TwoTierBadge = React31.forwardRef(
6849
7187
  style: { fontFamily: "var(--font-sans)", borderColor: frame, background: "transparent", ...style },
6850
7188
  ...props,
6851
7189
  children: [
6852
- /* @__PURE__ */ jsxs36(
7190
+ /* @__PURE__ */ jsxs37(
6853
7191
  "span",
6854
7192
  {
6855
7193
  "data-slot": "two-tier-badge-primary",
6856
7194
  className: cn("inline-flex items-center whitespace-nowrap font-semibold", SEGMENT[size]),
6857
7195
  style: { color: fg, background: strong ? BG[tone] : "transparent" },
6858
7196
  children: [
6859
- showDot ? /* @__PURE__ */ jsx39(
7197
+ showDot ? /* @__PURE__ */ jsx40(
6860
7198
  "span",
6861
7199
  {
6862
7200
  "aria-hidden": "true",
@@ -6871,11 +7209,11 @@ var TwoTierBadge = React31.forwardRef(
6871
7209
  }
6872
7210
  }
6873
7211
  ) : null,
6874
- /* @__PURE__ */ jsx39("span", { children: primary })
7212
+ /* @__PURE__ */ jsx40("span", { children: primary })
6875
7213
  ]
6876
7214
  }
6877
7215
  ),
6878
- secondary != null ? /* @__PURE__ */ jsx39(
7216
+ secondary != null ? /* @__PURE__ */ jsx40(
6879
7217
  "span",
6880
7218
  {
6881
7219
  "data-slot": "two-tier-badge-secondary",
@@ -6896,8 +7234,8 @@ var TwoTierBadge = React31.forwardRef(
6896
7234
  TwoTierBadge.displayName = "TwoTierBadge";
6897
7235
 
6898
7236
  // src/components/ui/status-badge.tsx
6899
- import * as React32 from "react";
6900
- import { jsx as jsx40, jsxs as jsxs37 } from "react/jsx-runtime";
7237
+ import * as React34 from "react";
7238
+ import { jsx as jsx41, jsxs as jsxs38 } from "react/jsx-runtime";
6901
7239
  var ROLE = {
6902
7240
  error: "error",
6903
7241
  warning: "warning",
@@ -6926,13 +7264,13 @@ var SIZE = {
6926
7264
  sm: { cls: "gap-[6px] py-[var(--space-1)] px-[var(--space-2)] text-[12px]", dot: 6 },
6927
7265
  md: { cls: "gap-[var(--space-2)] py-[var(--space-1)] px-[14px] text-[14px]", dot: 7 }
6928
7266
  };
6929
- var StatusBadge = React32.forwardRef(
7267
+ var StatusBadge = React34.forwardRef(
6930
7268
  ({ status = "active", emphasis = "subtle", size = "sm", showDot = true, pulse = true, className, children, style, ...props }, ref) => {
6931
7269
  const role = ROLE[status];
6932
7270
  const fg = FG2[role];
6933
7271
  const strong = emphasis === "strong";
6934
7272
  const ringDot = role === "neutral";
6935
- return /* @__PURE__ */ jsxs37(
7273
+ return /* @__PURE__ */ jsxs38(
6936
7274
  "span",
6937
7275
  {
6938
7276
  ref,
@@ -6950,7 +7288,7 @@ var StatusBadge = React32.forwardRef(
6950
7288
  },
6951
7289
  ...props,
6952
7290
  children: [
6953
- showDot ? /* @__PURE__ */ jsx40(
7291
+ showDot ? /* @__PURE__ */ jsx41(
6954
7292
  "span",
6955
7293
  {
6956
7294
  "aria-hidden": "true",
@@ -6968,7 +7306,7 @@ var StatusBadge = React32.forwardRef(
6968
7306
  }
6969
7307
  ) : null,
6970
7308
  children,
6971
- /* @__PURE__ */ jsx40("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}}" })
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}}" })
6972
7310
  ]
6973
7311
  }
6974
7312
  );
@@ -6977,9 +7315,9 @@ var StatusBadge = React32.forwardRef(
6977
7315
  StatusBadge.displayName = "StatusBadge";
6978
7316
 
6979
7317
  // src/components/ui/notification-badge.tsx
6980
- import * as React33 from "react";
7318
+ import * as React35 from "react";
6981
7319
  import { cva as cva13 } from "class-variance-authority";
6982
- import { jsx as jsx41 } from "react/jsx-runtime";
7320
+ import { jsx as jsx42 } from "react/jsx-runtime";
6983
7321
  var notificationBadgeVariants = cva13(
6984
7322
  [
6985
7323
  "inline-flex shrink-0 items-center justify-center rounded-[var(--radius-full)]",
@@ -7010,7 +7348,7 @@ function formatNotificationCount(count, max) {
7010
7348
  }
7011
7349
  return String(count);
7012
7350
  }
7013
- var NotificationBadge = React33.forwardRef(
7351
+ var NotificationBadge = React35.forwardRef(
7014
7352
  ({
7015
7353
  className,
7016
7354
  count,
@@ -7025,7 +7363,7 @@ var NotificationBadge = React33.forwardRef(
7025
7363
  }
7026
7364
  const normalizedMax = Math.max(1, Math.floor(max));
7027
7365
  const label = ariaLabel ?? (count > normalizedMax ? `\uC77D\uC9C0 \uC54A\uC740 \uC54C\uB9BC ${normalizedMax}\uAC1C \uC774\uC0C1` : `\uC77D\uC9C0 \uC54A\uC740 \uC54C\uB9BC ${count}\uAC1C`);
7028
- return /* @__PURE__ */ jsx41(
7366
+ return /* @__PURE__ */ jsx42(
7029
7367
  "span",
7030
7368
  {
7031
7369
  ref,
@@ -7043,9 +7381,9 @@ var NotificationBadge = React33.forwardRef(
7043
7381
  NotificationBadge.displayName = "NotificationBadge";
7044
7382
 
7045
7383
  // src/components/ui/empty-state.tsx
7046
- import * as React34 from "react";
7384
+ import * as React36 from "react";
7047
7385
  import { cva as cva14 } from "class-variance-authority";
7048
- import { jsx as jsx42, jsxs as jsxs38 } from "react/jsx-runtime";
7386
+ import { jsx as jsx43, jsxs as jsxs39 } from "react/jsx-runtime";
7049
7387
  var emptyStateBaseVariants = cva14(
7050
7388
  [
7051
7389
  "flex flex-col items-center justify-center text-center",
@@ -7117,7 +7455,7 @@ var iconSize3 = {
7117
7455
  md: 20,
7118
7456
  lg: 24
7119
7457
  };
7120
- var EmptyState = React34.forwardRef(
7458
+ var EmptyState = React36.forwardRef(
7121
7459
  ({
7122
7460
  className,
7123
7461
  size = "md",
@@ -7132,7 +7470,7 @@ var EmptyState = React34.forwardRef(
7132
7470
  ...props
7133
7471
  }, ref) => {
7134
7472
  const resolvedSize = size ?? "md";
7135
- return /* @__PURE__ */ jsxs38(
7473
+ return /* @__PURE__ */ jsxs39(
7136
7474
  "div",
7137
7475
  {
7138
7476
  ref,
@@ -7141,17 +7479,17 @@ var EmptyState = React34.forwardRef(
7141
7479
  className: cn(emptyStateVariants({ size, tone, surface, bordered, className })),
7142
7480
  ...props,
7143
7481
  children: [
7144
- Icon ? /* @__PURE__ */ jsx42(
7482
+ Icon ? /* @__PURE__ */ jsx43(
7145
7483
  "span",
7146
7484
  {
7147
7485
  "aria-hidden": "true",
7148
7486
  "data-slot": "empty-state-icon",
7149
7487
  className: emptyStateIconVariants({ size: resolvedSize }),
7150
- children: /* @__PURE__ */ jsx42(Icon, { size: iconSize3[resolvedSize], strokeWidth: 1.75 })
7488
+ children: /* @__PURE__ */ jsx43(Icon, { size: iconSize3[resolvedSize], strokeWidth: 1.75 })
7151
7489
  }
7152
7490
  ) : null,
7153
- /* @__PURE__ */ jsxs38("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
7154
- /* @__PURE__ */ jsx42(
7491
+ /* @__PURE__ */ jsxs39("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
7492
+ /* @__PURE__ */ jsx43(
7155
7493
  "h2",
7156
7494
  {
7157
7495
  "data-slot": "empty-state-title",
@@ -7159,7 +7497,7 @@ var EmptyState = React34.forwardRef(
7159
7497
  children: title
7160
7498
  }
7161
7499
  ),
7162
- description ? /* @__PURE__ */ jsx42(
7500
+ description ? /* @__PURE__ */ jsx43(
7163
7501
  "p",
7164
7502
  {
7165
7503
  "data-slot": "empty-state-description",
@@ -7167,7 +7505,7 @@ var EmptyState = React34.forwardRef(
7167
7505
  children: description
7168
7506
  }
7169
7507
  ) : null,
7170
- hint ? /* @__PURE__ */ jsx42(
7508
+ hint ? /* @__PURE__ */ jsx43(
7171
7509
  "p",
7172
7510
  {
7173
7511
  "data-slot": "empty-state-hint",
@@ -7176,7 +7514,7 @@ var EmptyState = React34.forwardRef(
7176
7514
  }
7177
7515
  ) : null
7178
7516
  ] }),
7179
- action ? /* @__PURE__ */ jsx42("div", { "data-slot": "empty-state-action", className: "mt-[var(--space-2)]", children: action }) : null
7517
+ action ? /* @__PURE__ */ jsx43("div", { "data-slot": "empty-state-action", className: "mt-[var(--space-2)]", children: action }) : null
7180
7518
  ]
7181
7519
  }
7182
7520
  );
@@ -7185,10 +7523,10 @@ var EmptyState = React34.forwardRef(
7185
7523
  EmptyState.displayName = "EmptyState";
7186
7524
 
7187
7525
  // src/components/ui/error-state.tsx
7188
- import * as React35 from "react";
7526
+ import * as React37 from "react";
7189
7527
  import { AlertTriangle } from "lucide-react";
7190
7528
  import { cva as cva15 } from "class-variance-authority";
7191
- import { jsx as jsx43, jsxs as jsxs39 } from "react/jsx-runtime";
7529
+ import { jsx as jsx44, jsxs as jsxs40 } from "react/jsx-runtime";
7192
7530
  var errorStateVariants = cva15(
7193
7531
  [
7194
7532
  "flex flex-col items-center justify-center text-center",
@@ -7210,7 +7548,7 @@ var errorStateVariants = cva15(
7210
7548
  }
7211
7549
  }
7212
7550
  );
7213
- var ErrorState = React35.forwardRef(
7551
+ var ErrorState = React37.forwardRef(
7214
7552
  ({
7215
7553
  className,
7216
7554
  size = "md",
@@ -7221,7 +7559,7 @@ var ErrorState = React35.forwardRef(
7221
7559
  onRetry,
7222
7560
  retryLabel = "\uB2E4\uC2DC \uC2DC\uB3C4",
7223
7561
  ...props
7224
- }, ref) => /* @__PURE__ */ jsxs39(
7562
+ }, ref) => /* @__PURE__ */ jsxs40(
7225
7563
  "div",
7226
7564
  {
7227
7565
  ref,
@@ -7230,17 +7568,17 @@ var ErrorState = React35.forwardRef(
7230
7568
  className: cn(errorStateVariants({ size, surface, className })),
7231
7569
  ...props,
7232
7570
  children: [
7233
- /* @__PURE__ */ jsx43(
7571
+ /* @__PURE__ */ jsx44(
7234
7572
  "span",
7235
7573
  {
7236
7574
  "aria-hidden": "true",
7237
7575
  "data-slot": "error-state-icon",
7238
7576
  className: "inline-flex size-[48px] items-center justify-center rounded-[var(--radius-full)] bg-[var(--error-bg)] text-[var(--error)]",
7239
- children: /* @__PURE__ */ jsx43(AlertTriangle, { size: 24, strokeWidth: 1.75 })
7577
+ children: /* @__PURE__ */ jsx44(AlertTriangle, { size: 24, strokeWidth: 1.75 })
7240
7578
  }
7241
7579
  ),
7242
- /* @__PURE__ */ jsxs39("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
7243
- /* @__PURE__ */ jsx43(
7580
+ /* @__PURE__ */ jsxs40("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
7581
+ /* @__PURE__ */ jsx44(
7244
7582
  "h2",
7245
7583
  {
7246
7584
  "data-slot": "error-state-title",
@@ -7248,7 +7586,7 @@ var ErrorState = React35.forwardRef(
7248
7586
  children: title
7249
7587
  }
7250
7588
  ),
7251
- /* @__PURE__ */ jsx43(
7589
+ /* @__PURE__ */ jsx44(
7252
7590
  "p",
7253
7591
  {
7254
7592
  "data-slot": "error-state-message",
@@ -7256,7 +7594,7 @@ var ErrorState = React35.forwardRef(
7256
7594
  children: message
7257
7595
  }
7258
7596
  ),
7259
- errorCode ? /* @__PURE__ */ jsx43(
7597
+ errorCode ? /* @__PURE__ */ jsx44(
7260
7598
  "p",
7261
7599
  {
7262
7600
  "data-slot": "error-state-code",
@@ -7265,7 +7603,7 @@ var ErrorState = React35.forwardRef(
7265
7603
  }
7266
7604
  ) : null
7267
7605
  ] }),
7268
- onRetry ? /* @__PURE__ */ jsx43(Button, { size: "sm", variant: "outline", onClick: onRetry, children: retryLabel }) : null
7606
+ onRetry ? /* @__PURE__ */ jsx44(Button, { size: "sm", variant: "secondary", onClick: onRetry, children: retryLabel }) : null
7269
7607
  ]
7270
7608
  }
7271
7609
  )
@@ -7273,9 +7611,9 @@ var ErrorState = React35.forwardRef(
7273
7611
  ErrorState.displayName = "ErrorState";
7274
7612
 
7275
7613
  // src/components/ui/skeleton.tsx
7276
- import * as React36 from "react";
7614
+ import * as React38 from "react";
7277
7615
  import { cva as cva16 } from "class-variance-authority";
7278
- import { jsx as jsx44 } from "react/jsx-runtime";
7616
+ import { jsx as jsx45 } from "react/jsx-runtime";
7279
7617
  var skeletonVariants = cva16(
7280
7618
  [
7281
7619
  // bg-inset: light #F1F2F4 reads on white surfaces (bg-raised was white = invisible);
@@ -7319,8 +7657,8 @@ var spinnerVariants = cva16(
7319
7657
  }
7320
7658
  }
7321
7659
  );
7322
- var Skeleton = React36.forwardRef(
7323
- ({ className, shape, style, ...props }, ref) => /* @__PURE__ */ jsx44(
7660
+ var Skeleton = React38.forwardRef(
7661
+ ({ className, shape, style, ...props }, ref) => /* @__PURE__ */ jsx45(
7324
7662
  "div",
7325
7663
  {
7326
7664
  ref,
@@ -7333,15 +7671,15 @@ var Skeleton = React36.forwardRef(
7333
7671
  );
7334
7672
  Skeleton.displayName = "Skeleton";
7335
7673
  var defaultTextWidths = ["92%", "84%", "68%", "76%"];
7336
- var SkeletonText = React36.forwardRef(
7337
- ({ className, lines = 3, widths = defaultTextWidths, ...props }, ref) => /* @__PURE__ */ jsx44(
7674
+ var SkeletonText = React38.forwardRef(
7675
+ ({ className, lines = 3, widths = defaultTextWidths, ...props }, ref) => /* @__PURE__ */ jsx45(
7338
7676
  "div",
7339
7677
  {
7340
7678
  ref,
7341
7679
  "data-slot": "skeleton-text",
7342
7680
  className: cn("flex flex-col gap-[var(--space-2)]", className),
7343
7681
  ...props,
7344
- children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx44(
7682
+ children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx45(
7345
7683
  Skeleton,
7346
7684
  {
7347
7685
  shape: "text",
@@ -7353,7 +7691,7 @@ var SkeletonText = React36.forwardRef(
7353
7691
  )
7354
7692
  );
7355
7693
  SkeletonText.displayName = "SkeletonText";
7356
- var SkeletonRow = React36.forwardRef(
7694
+ var SkeletonRow = React38.forwardRef(
7357
7695
  ({
7358
7696
  className,
7359
7697
  columns,
@@ -7364,7 +7702,7 @@ var SkeletonRow = React36.forwardRef(
7364
7702
  }, ref) => {
7365
7703
  const rowCount = Math.max(5, count);
7366
7704
  const gridTemplateColumns = columns.map((column) => column.width ?? "1fr").join(" ");
7367
- return /* @__PURE__ */ jsx44(
7705
+ return /* @__PURE__ */ jsx45(
7368
7706
  "div",
7369
7707
  {
7370
7708
  ref,
@@ -7378,7 +7716,7 @@ var SkeletonRow = React36.forwardRef(
7378
7716
  className
7379
7717
  ),
7380
7718
  ...props,
7381
- children: Array.from({ length: rowCount }, (_, rowIndex) => /* @__PURE__ */ jsx44(
7719
+ children: Array.from({ length: rowCount }, (_, rowIndex) => /* @__PURE__ */ jsx45(
7382
7720
  "div",
7383
7721
  {
7384
7722
  "data-slot": "skeleton-row",
@@ -7386,11 +7724,11 @@ var SkeletonRow = React36.forwardRef(
7386
7724
  "grid min-h-[48px] items-center border-t border-[var(--border-subtle)] first:border-t-0"
7387
7725
  ),
7388
7726
  style: { gridTemplateColumns },
7389
- children: columns.map((column, columnIndex) => /* @__PURE__ */ jsx44(
7727
+ children: columns.map((column, columnIndex) => /* @__PURE__ */ jsx45(
7390
7728
  "div",
7391
7729
  {
7392
7730
  className: "px-[var(--space-4)] py-[var(--space-2)]",
7393
- children: /* @__PURE__ */ jsx44(
7731
+ children: /* @__PURE__ */ jsx45(
7394
7732
  Skeleton,
7395
7733
  {
7396
7734
  shape: "text",
@@ -7410,8 +7748,8 @@ var SkeletonRow = React36.forwardRef(
7410
7748
  }
7411
7749
  );
7412
7750
  SkeletonRow.displayName = "SkeletonRow";
7413
- var Spinner = React36.forwardRef(
7414
- ({ className, size, label = "\uB85C\uB529 \uC911", ...props }, ref) => /* @__PURE__ */ jsx44(
7751
+ var Spinner = React38.forwardRef(
7752
+ ({ className, size, label = "\uB85C\uB529 \uC911", ...props }, ref) => /* @__PURE__ */ jsx45(
7415
7753
  "span",
7416
7754
  {
7417
7755
  ref,
@@ -7426,12 +7764,12 @@ var Spinner = React36.forwardRef(
7426
7764
  Spinner.displayName = "Spinner";
7427
7765
 
7428
7766
  // src/components/ui/pagination.tsx
7429
- import * as React37 from "react";
7767
+ import * as React39 from "react";
7430
7768
  import { ChevronsLeft, ChevronLeft, ChevronRight as ChevronRight2, ChevronsRight } from "lucide-react";
7431
7769
  import { cva as cva17 } from "class-variance-authority";
7432
7770
 
7433
7771
  // src/components/ui/page-size-select.tsx
7434
- import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
7772
+ import { jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
7435
7773
  var DEFAULT_OPTIONS = [10, 20, 50, 100];
7436
7774
  function PageSizeSelect({
7437
7775
  value,
@@ -7450,7 +7788,7 @@ function PageSizeSelect({
7450
7788
  label: `${opt}${unit}`
7451
7789
  }));
7452
7790
  const selectSize = size === "compact" ? "sm" : "md";
7453
- return /* @__PURE__ */ jsxs40(
7791
+ return /* @__PURE__ */ jsxs41(
7454
7792
  "div",
7455
7793
  {
7456
7794
  "data-slot": "page-size-select",
@@ -7459,8 +7797,8 @@ function PageSizeSelect({
7459
7797
  className
7460
7798
  ),
7461
7799
  children: [
7462
- label != null ? /* @__PURE__ */ jsx45("span", { children: label }) : null,
7463
- /* @__PURE__ */ jsx45(
7800
+ label != null ? /* @__PURE__ */ jsx46("span", { children: label }) : null,
7801
+ /* @__PURE__ */ jsx46(
7464
7802
  Select,
7465
7803
  {
7466
7804
  id,
@@ -7482,7 +7820,7 @@ function PageSizeSelect({
7482
7820
  }
7483
7821
 
7484
7822
  // src/components/ui/pagination.tsx
7485
- import { jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
7823
+ import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
7486
7824
  var paginationVariants = cva17(
7487
7825
  [
7488
7826
  "flex w-full flex-col gap-[var(--space-3)]",
@@ -7503,7 +7841,7 @@ var paginationVariants = cva17(
7503
7841
  );
7504
7842
  var paginationControlVariants = cva17(
7505
7843
  [
7506
- "inline-flex shrink-0 items-center justify-center rounded-[var(--radius-sm)] border",
7844
+ "inline-flex shrink-0 items-center justify-center rounded-[var(--radius-md)] border",
7507
7845
  "border-transparent bg-transparent font-medium text-text-secondary",
7508
7846
  "transition-colors motion-reduce:transition-none",
7509
7847
  "hover:border-[var(--border-strong)] hover:bg-[var(--action-hover)] hover:text-foreground",
@@ -7555,7 +7893,7 @@ function NavigationButton({
7555
7893
  icon: Icon,
7556
7894
  onPageChange
7557
7895
  }) {
7558
- return /* @__PURE__ */ jsx46(
7896
+ return /* @__PURE__ */ jsx47(
7559
7897
  "button",
7560
7898
  {
7561
7899
  "aria-label": label,
@@ -7563,11 +7901,11 @@ function NavigationButton({
7563
7901
  className: paginationControlVariants({ size }),
7564
7902
  type: "button",
7565
7903
  onClick: () => onPageChange?.(page),
7566
- children: /* @__PURE__ */ jsx46(Icon, { "aria-hidden": "true", "data-slot": "pagination-icon" })
7904
+ children: /* @__PURE__ */ jsx47(Icon, { "aria-hidden": "true", "data-slot": "pagination-icon" })
7567
7905
  }
7568
7906
  );
7569
7907
  }
7570
- var Pagination = React37.forwardRef(
7908
+ var Pagination = React39.forwardRef(
7571
7909
  ({
7572
7910
  className,
7573
7911
  size = "standard",
@@ -7592,7 +7930,7 @@ var Pagination = React37.forwardRef(
7592
7930
  const items = getPaginationItems(currentPage, pageCount);
7593
7931
  const isFirstPage = currentPage === 1;
7594
7932
  const isLastPage = currentPage === pageCount;
7595
- return /* @__PURE__ */ jsxs41(
7933
+ return /* @__PURE__ */ jsxs42(
7596
7934
  "nav",
7597
7935
  {
7598
7936
  ref,
@@ -7602,9 +7940,9 @@ var Pagination = React37.forwardRef(
7602
7940
  className: cn(paginationVariants({ size: resolvedSize, className })),
7603
7941
  ...props,
7604
7942
  children: [
7605
- /* @__PURE__ */ jsxs41("div", { className: "flex flex-wrap items-center gap-[var(--space-3)]", children: [
7606
- /* @__PURE__ */ jsx46("span", { "data-slot": "pagination-total", className: "font-medium text-text-secondary", children: totalLabel(total) }),
7607
- showPageSize ? /* @__PURE__ */ jsx46("div", { "data-slot": "pagination-size", children: /* @__PURE__ */ jsx46(
7943
+ /* @__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(
7608
7946
  PageSizeSelect,
7609
7947
  {
7610
7948
  label: pageSizeLabel,
@@ -7616,13 +7954,13 @@ var Pagination = React37.forwardRef(
7616
7954
  }
7617
7955
  ) }) : null
7618
7956
  ] }),
7619
- /* @__PURE__ */ jsxs41(
7957
+ /* @__PURE__ */ jsxs42(
7620
7958
  "div",
7621
7959
  {
7622
7960
  "data-slot": "pagination-list",
7623
7961
  className: "flex items-center justify-center gap-[var(--space-1)]",
7624
7962
  children: [
7625
- /* @__PURE__ */ jsx46(
7963
+ /* @__PURE__ */ jsx47(
7626
7964
  NavigationButton,
7627
7965
  {
7628
7966
  label: "\uCCAB \uD398\uC774\uC9C0",
@@ -7633,7 +7971,7 @@ var Pagination = React37.forwardRef(
7633
7971
  onPageChange
7634
7972
  }
7635
7973
  ),
7636
- /* @__PURE__ */ jsx46(
7974
+ /* @__PURE__ */ jsx47(
7637
7975
  NavigationButton,
7638
7976
  {
7639
7977
  label: "\uC774\uC804 \uD398\uC774\uC9C0",
@@ -7645,7 +7983,7 @@ var Pagination = React37.forwardRef(
7645
7983
  }
7646
7984
  ),
7647
7985
  items.map(
7648
- (item, index) => item === "ellipsis" ? /* @__PURE__ */ jsx46(
7986
+ (item, index) => item === "ellipsis" ? /* @__PURE__ */ jsx47(
7649
7987
  "span",
7650
7988
  {
7651
7989
  "data-slot": "pagination-ellipsis",
@@ -7657,7 +7995,7 @@ var Pagination = React37.forwardRef(
7657
7995
  children: "..."
7658
7996
  },
7659
7997
  `ellipsis-${index}`
7660
- ) : /* @__PURE__ */ jsx46(
7998
+ ) : /* @__PURE__ */ jsx47(
7661
7999
  "button",
7662
8000
  {
7663
8001
  "aria-label": `${item} \uD398\uC774\uC9C0`,
@@ -7671,7 +8009,7 @@ var Pagination = React37.forwardRef(
7671
8009
  item
7672
8010
  )
7673
8011
  ),
7674
- /* @__PURE__ */ jsx46(
8012
+ /* @__PURE__ */ jsx47(
7675
8013
  NavigationButton,
7676
8014
  {
7677
8015
  label: "\uB2E4\uC74C \uD398\uC774\uC9C0",
@@ -7682,7 +8020,7 @@ var Pagination = React37.forwardRef(
7682
8020
  onPageChange
7683
8021
  }
7684
8022
  ),
7685
- /* @__PURE__ */ jsx46(
8023
+ /* @__PURE__ */ jsx47(
7686
8024
  NavigationButton,
7687
8025
  {
7688
8026
  label: "\uB9C8\uC9C0\uB9C9 \uD398\uC774\uC9C0",
@@ -7705,17 +8043,17 @@ Pagination.displayName = "Pagination";
7705
8043
 
7706
8044
  // src/components/ui/mode-toggle.tsx
7707
8045
  import { cva as cva18 } from "class-variance-authority";
7708
- import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
8046
+ import { jsx as jsx48, jsxs as jsxs43 } from "react/jsx-runtime";
7709
8047
  var modeToggleVariants = cva18(
7710
8048
  [
7711
- "inline-flex items-center rounded-[var(--radius-sm)] border border-[var(--border-subtle)]",
8049
+ "inline-flex items-center rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
7712
8050
  "bg-[var(--bg-inset)] p-[2px]"
7713
8051
  ].join(" ")
7714
8052
  );
7715
8053
  var modeToggleItemVariants = cva18(
7716
8054
  [
7717
8055
  "inline-flex min-h-[28px] cursor-pointer items-center justify-center gap-[var(--space-1)]",
7718
- "rounded-[calc(var(--radius-sm)_-_2px)] px-[var(--space-3)] py-[var(--space-1)]",
8056
+ "rounded-[calc(var(--radius-md)_-_2px)] px-[var(--space-3)] py-[var(--space-1)]",
7719
8057
  "font-[family-name:var(--font-display)] text-xs font-medium leading-none",
7720
8058
  "text-text-secondary transition-[background-color,color,box-shadow]",
7721
8059
  "duration-[var(--dur-fast)] ease-[var(--ease-standard)]",
@@ -7735,7 +8073,7 @@ function ModeToggle({
7735
8073
  onChange,
7736
8074
  ...props
7737
8075
  }) {
7738
- return /* @__PURE__ */ jsx47(
8076
+ return /* @__PURE__ */ jsx48(
7739
8077
  "div",
7740
8078
  {
7741
8079
  role: "group",
@@ -7745,7 +8083,7 @@ function ModeToggle({
7745
8083
  children: options.map((option) => {
7746
8084
  const Icon = option.icon;
7747
8085
  const isActive = option.value === value;
7748
- return /* @__PURE__ */ jsxs42(
8086
+ return /* @__PURE__ */ jsxs43(
7749
8087
  "button",
7750
8088
  {
7751
8089
  type: "button",
@@ -7761,8 +8099,8 @@ function ModeToggle({
7761
8099
  }
7762
8100
  },
7763
8101
  children: [
7764
- Icon ? /* @__PURE__ */ jsx47(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
7765
- /* @__PURE__ */ jsx47("span", { children: option.label })
8102
+ Icon ? /* @__PURE__ */ jsx48(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
8103
+ /* @__PURE__ */ jsx48("span", { children: option.label })
7766
8104
  ]
7767
8105
  },
7768
8106
  option.value
@@ -7773,9 +8111,9 @@ function ModeToggle({
7773
8111
  }
7774
8112
 
7775
8113
  // src/components/ui/action-footer.tsx
7776
- import * as React38 from "react";
8114
+ import * as React40 from "react";
7777
8115
  import { cva as cva19 } from "class-variance-authority";
7778
- import { jsx as jsx48, jsxs as jsxs43 } from "react/jsx-runtime";
8116
+ import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
7779
8117
  var actionFooterVariants = cva19(
7780
8118
  [
7781
8119
  "flex flex-wrap items-center gap-[var(--space-4)] border-t border-[var(--border-subtle)]",
@@ -7846,11 +8184,12 @@ function getStatusLabel(status) {
7846
8184
  }
7847
8185
  }
7848
8186
  function renderAction(action) {
7849
- return /* @__PURE__ */ jsx48(
8187
+ return /* @__PURE__ */ jsx49(
7850
8188
  Button,
7851
8189
  {
7852
8190
  variant: action.variant,
7853
- size: "md",
8191
+ size: "lg",
8192
+ className: footerButtonHitAreaClassName,
7854
8193
  disabled: action.disabled,
7855
8194
  loading: action.loading,
7856
8195
  leadingIcon: action.leadingIcon,
@@ -7860,7 +8199,7 @@ function renderAction(action) {
7860
8199
  action.id ?? action.label
7861
8200
  );
7862
8201
  }
7863
- var ActionFooter = React38.forwardRef(
8202
+ var ActionFooter = React40.forwardRef(
7864
8203
  ({
7865
8204
  className,
7866
8205
  status,
@@ -7877,7 +8216,7 @@ var ActionFooter = React38.forwardRef(
7877
8216
  const mainActions = sortMainActions(
7878
8217
  visibleActions.filter((action) => !destructiveVariants.has(action.variant ?? "default"))
7879
8218
  );
7880
- return /* @__PURE__ */ jsxs43(
8219
+ return /* @__PURE__ */ jsxs44(
7881
8220
  "div",
7882
8221
  {
7883
8222
  ref,
@@ -7886,7 +8225,7 @@ var ActionFooter = React38.forwardRef(
7886
8225
  className: cn(actionFooterVariants({ position, surface, className })),
7887
8226
  ...props,
7888
8227
  children: [
7889
- destructiveActions.length > 0 ? /* @__PURE__ */ jsx48(
8228
+ destructiveActions.length > 0 ? /* @__PURE__ */ jsx49(
7890
8229
  "div",
7891
8230
  {
7892
8231
  "data-slot": "action-footer-destructive-actions",
@@ -7894,7 +8233,7 @@ var ActionFooter = React38.forwardRef(
7894
8233
  children: destructiveActions.map(renderAction)
7895
8234
  }
7896
8235
  ) : null,
7897
- status ? /* @__PURE__ */ jsxs43(
8236
+ status ? /* @__PURE__ */ jsxs44(
7898
8237
  "div",
7899
8238
  {
7900
8239
  "data-slot": "action-footer-status",
@@ -7902,7 +8241,7 @@ var ActionFooter = React38.forwardRef(
7902
8241
  "aria-live": "polite",
7903
8242
  className: cn(actionFooterStatusVariants({ kind: status.kind })),
7904
8243
  children: [
7905
- /* @__PURE__ */ jsx48(
8244
+ /* @__PURE__ */ jsx49(
7906
8245
  "span",
7907
8246
  {
7908
8247
  "aria-hidden": "true",
@@ -7910,11 +8249,11 @@ var ActionFooter = React38.forwardRef(
7910
8249
  className: "size-[6px] shrink-0 rounded-[var(--radius-full)]"
7911
8250
  }
7912
8251
  ),
7913
- /* @__PURE__ */ jsx48("span", { className: "truncate", children: getStatusLabel(status) })
8252
+ /* @__PURE__ */ jsx49("span", { className: "truncate", children: getStatusLabel(status) })
7914
8253
  ]
7915
8254
  }
7916
8255
  ) : null,
7917
- /* @__PURE__ */ jsx48(
8256
+ /* @__PURE__ */ jsx49(
7918
8257
  "div",
7919
8258
  {
7920
8259
  "data-slot": "action-footer-main-actions",
@@ -7930,9 +8269,9 @@ var ActionFooter = React38.forwardRef(
7930
8269
  ActionFooter.displayName = "ActionFooter";
7931
8270
 
7932
8271
  // src/components/ui/toast.tsx
7933
- import * as React39 from "react";
8272
+ import * as React41 from "react";
7934
8273
  import { cva as cva20 } from "class-variance-authority";
7935
- import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
8274
+ import { jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
7936
8275
  var DOT3 = {
7937
8276
  default: "var(--neutral)",
7938
8277
  success: "var(--success)",
@@ -7945,7 +8284,7 @@ var toastVariants = cva20(
7945
8284
  "flex min-w-[280px] max-w-[420px] items-center",
7946
8285
  "gap-[11px] rounded-[10px] border border-[var(--border)]",
7947
8286
  "px-[14px] py-[11px]",
7948
- "shadow-[var(--shadow-4)]",
8287
+ "shadow-[var(--shadow-8)]",
7949
8288
  "pointer-events-auto",
7950
8289
  "motion-reduce:animate-none"
7951
8290
  ].join(" "),
@@ -8050,7 +8389,7 @@ var toast = {
8050
8389
  }
8051
8390
  };
8052
8391
  var Toast = toast;
8053
- var ToastRoot = React39.forwardRef(
8392
+ var ToastRoot = React41.forwardRef(
8054
8393
  ({
8055
8394
  className,
8056
8395
  id,
@@ -8067,10 +8406,10 @@ var ToastRoot = React39.forwardRef(
8067
8406
  ...props
8068
8407
  }, ref) => {
8069
8408
  const durationMs = getToastDuration({ message, variant, duration });
8070
- const onCloseRef = React39.useRef(onClose);
8409
+ const onCloseRef = React41.useRef(onClose);
8071
8410
  onCloseRef.current = onClose;
8072
- const timerRef = React39.useRef(null);
8073
- React39.useEffect(() => {
8411
+ const timerRef = React41.useRef(null);
8412
+ React41.useEffect(() => {
8074
8413
  if (!onCloseRef.current) return void 0;
8075
8414
  const timer = createToastTimer(durationMs, () => onCloseRef.current?.());
8076
8415
  timerRef.current = timer;
@@ -8079,7 +8418,7 @@ var ToastRoot = React39.forwardRef(
8079
8418
  timerRef.current = null;
8080
8419
  };
8081
8420
  }, [durationMs]);
8082
- return /* @__PURE__ */ jsxs44(
8421
+ return /* @__PURE__ */ jsxs45(
8083
8422
  "div",
8084
8423
  {
8085
8424
  ref,
@@ -8107,7 +8446,7 @@ var ToastRoot = React39.forwardRef(
8107
8446
  },
8108
8447
  ...props,
8109
8448
  children: [
8110
- /* @__PURE__ */ jsx49(
8449
+ /* @__PURE__ */ jsx50(
8111
8450
  "span",
8112
8451
  {
8113
8452
  "aria-hidden": "true",
@@ -8116,8 +8455,8 @@ var ToastRoot = React39.forwardRef(
8116
8455
  style: { background: DOT3[variant] ?? DOT3.default }
8117
8456
  }
8118
8457
  ),
8119
- /* @__PURE__ */ jsxs44("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
8120
- /* @__PURE__ */ jsx49(
8458
+ /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
8459
+ /* @__PURE__ */ jsx50(
8121
8460
  "div",
8122
8461
  {
8123
8462
  "data-slot": "toast-message",
@@ -8125,7 +8464,7 @@ var ToastRoot = React39.forwardRef(
8125
8464
  children: message
8126
8465
  }
8127
8466
  ),
8128
- description ? /* @__PURE__ */ jsx49(
8467
+ description ? /* @__PURE__ */ jsx50(
8129
8468
  "div",
8130
8469
  {
8131
8470
  "data-slot": "toast-description",
@@ -8134,25 +8473,25 @@ var ToastRoot = React39.forwardRef(
8134
8473
  }
8135
8474
  ) : null
8136
8475
  ] }),
8137
- /* @__PURE__ */ jsxs44("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
8138
- action ? /* @__PURE__ */ jsx49(
8476
+ /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
8477
+ action ? /* @__PURE__ */ jsx50(
8139
8478
  Button,
8140
8479
  {
8141
8480
  "data-slot": "toast-action",
8142
8481
  size: "xs",
8143
- variant: "outline",
8482
+ variant: "secondary",
8144
8483
  onClick: action.onClick,
8145
8484
  children: action.label
8146
8485
  }
8147
8486
  ) : null,
8148
- /* @__PURE__ */ jsx49(
8487
+ /* @__PURE__ */ jsx50(
8149
8488
  "button",
8150
8489
  {
8151
8490
  type: "button",
8152
8491
  "aria-label": "\uC54C\uB9BC \uB2EB\uAE30",
8153
8492
  "data-slot": "toast-close",
8154
8493
  className: cn(
8155
- "inline-flex size-[28px] shrink-0 cursor-pointer items-center justify-center rounded-[var(--radius-sm)]",
8494
+ "inline-flex size-[28px] shrink-0 cursor-pointer items-center justify-center rounded-[var(--radius-md)]",
8156
8495
  "text-current opacity-70 transition-opacity hover:opacity-100",
8157
8496
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]"
8158
8497
  ),
@@ -8167,7 +8506,7 @@ var ToastRoot = React39.forwardRef(
8167
8506
  }
8168
8507
  );
8169
8508
  ToastRoot.displayName = "ToastRoot";
8170
- var ToastViewport = React39.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx49(
8509
+ var ToastViewport = React41.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx50(
8171
8510
  "ol",
8172
8511
  {
8173
8512
  ref,
@@ -8178,24 +8517,24 @@ var ToastViewport = React39.forwardRef(({ className, ...props }, ref) => /* @__P
8178
8517
  ));
8179
8518
  ToastViewport.displayName = "ToastViewport";
8180
8519
  function ToastProvider({ children, maxToasts = 3, className, ...props }) {
8181
- const [items, setItems] = React39.useState([]);
8182
- React39.useEffect(
8520
+ const [items, setItems] = React41.useState([]);
8521
+ React41.useEffect(
8183
8522
  () => toast.subscribe((nextItems) => {
8184
8523
  setItems(limitToasts(nextItems, maxToasts));
8185
8524
  }),
8186
8525
  [maxToasts]
8187
8526
  );
8188
- return /* @__PURE__ */ jsxs44("div", { "data-slot": "toast-provider", className, ...props, children: [
8527
+ return /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-provider", className, ...props, children: [
8189
8528
  children,
8190
- /* @__PURE__ */ jsx49(ToastViewport, { children: items.map((item) => /* @__PURE__ */ jsx49("li", { children: /* @__PURE__ */ jsx49(ToastRoot, { ...item, onClose: () => toast.dismiss(item.id) }) }, item.id)) })
8529
+ /* @__PURE__ */ jsx50(ToastViewport, { children: items.map((item) => /* @__PURE__ */ jsx50("li", { children: /* @__PURE__ */ jsx50(ToastRoot, { ...item, onClose: () => toast.dismiss(item.id) }) }, item.id)) })
8191
8530
  ] });
8192
8531
  }
8193
8532
 
8194
8533
  // src/components/ui/otp-field.tsx
8195
- import * as React40 from "react";
8534
+ import * as React42 from "react";
8196
8535
  import { cva as cva21 } from "class-variance-authority";
8197
8536
  import { AlertCircle as AlertCircle4 } from "lucide-react";
8198
- import { Fragment as Fragment9, jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
8537
+ import { Fragment as Fragment9, jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
8199
8538
  var otpFieldVariants = cva21("flex w-full min-w-0 flex-col gap-[var(--space-3)]", {
8200
8539
  variants: {
8201
8540
  size: {
@@ -8322,7 +8661,7 @@ function fillDigitsFromIndex(slots, index, inserted, length) {
8322
8661
  focusIndex: Math.min(cursor, length - 1)
8323
8662
  };
8324
8663
  }
8325
- var OTPField = React40.forwardRef(
8664
+ var OTPField = React42.forwardRef(
8326
8665
  ({
8327
8666
  className,
8328
8667
  defaultValue,
@@ -8344,24 +8683,24 @@ var OTPField = React40.forwardRef(
8344
8683
  required,
8345
8684
  ...props
8346
8685
  }, ref) => {
8347
- const generatedId = React40.useId();
8686
+ const generatedId = React42.useId();
8348
8687
  const fieldId = id ?? generatedId;
8349
8688
  const labelId = `${fieldId}-label`;
8350
8689
  const helperId = helperText ? `${fieldId}-helper` : void 0;
8351
8690
  const errorId = errorText ? `${fieldId}-error` : void 0;
8352
8691
  const resolvedState = invalid || errorText ? "error" : "default";
8353
8692
  const isControlled = value !== void 0;
8354
- const [uncontrolledSlots, setUncontrolledSlots] = React40.useState(
8693
+ const [uncontrolledSlots, setUncontrolledSlots] = React42.useState(
8355
8694
  () => toDigitsArray(onlyDigits(defaultValue, length), length)
8356
8695
  );
8357
- const resolvedSlots = React40.useMemo(
8696
+ const resolvedSlots = React42.useMemo(
8358
8697
  () => isControlled ? toDigitsArray(onlyDigits(value, length), length) : uncontrolledSlots,
8359
8698
  [isControlled, length, uncontrolledSlots, value]
8360
8699
  );
8361
8700
  const resolvedValue = joinDigits(resolvedSlots).slice(0, length);
8362
- const cellsRef = React40.useRef([]);
8701
+ const cellsRef = React42.useRef([]);
8363
8702
  const groupDescribedBy = [helperId, errorId].filter(Boolean).join(" ") || void 0;
8364
- const setResolvedValue = React40.useCallback(
8703
+ const setResolvedValue = React42.useCallback(
8365
8704
  (nextSlots, focusIndex) => {
8366
8705
  const normalizedSlots = nextSlots.slice(0, length);
8367
8706
  const normalizedValue = joinDigits(normalizedSlots).slice(0, length);
@@ -8380,7 +8719,7 @@ var OTPField = React40.forwardRef(
8380
8719
  },
8381
8720
  [disabled, isControlled, length, onComplete, onValueChange]
8382
8721
  );
8383
- return /* @__PURE__ */ jsxs45(
8722
+ return /* @__PURE__ */ jsxs46(
8384
8723
  "fieldset",
8385
8724
  {
8386
8725
  ref,
@@ -8393,7 +8732,7 @@ var OTPField = React40.forwardRef(
8393
8732
  className: cn(otpFieldVariants({ size, className })),
8394
8733
  ...props,
8395
8734
  children: [
8396
- /* @__PURE__ */ jsxs45(
8735
+ /* @__PURE__ */ jsxs46(
8397
8736
  "legend",
8398
8737
  {
8399
8738
  id: labelId,
@@ -8401,11 +8740,11 @@ var OTPField = React40.forwardRef(
8401
8740
  className: "text-sm font-medium leading-snug text-foreground",
8402
8741
  children: [
8403
8742
  label,
8404
- required ? /* @__PURE__ */ jsx50("span", { "aria-hidden": "true", className: "ml-1 font-bold text-[var(--error)]", children: "*" }) : null
8743
+ required ? /* @__PURE__ */ jsx51("span", { "aria-hidden": "true", className: "ml-1 font-bold text-[var(--error)]", children: "*" }) : null
8405
8744
  ]
8406
8745
  }
8407
8746
  ),
8408
- /* @__PURE__ */ jsx50(
8747
+ /* @__PURE__ */ jsx51(
8409
8748
  "div",
8410
8749
  {
8411
8750
  "data-slot": "otp-field-group",
@@ -8415,7 +8754,7 @@ var OTPField = React40.forwardRef(
8415
8754
  children: Array.from({ length }, (_, index) => {
8416
8755
  const digit = resolvedSlots[index] ?? "";
8417
8756
  const inputId = `${fieldId}-cell-${index + 1}`;
8418
- return /* @__PURE__ */ jsx50(
8757
+ return /* @__PURE__ */ jsx51(
8419
8758
  "input",
8420
8759
  {
8421
8760
  ref: (node) => {
@@ -8510,15 +8849,15 @@ var OTPField = React40.forwardRef(
8510
8849
  })
8511
8850
  }
8512
8851
  ),
8513
- helperText || errorText ? /* @__PURE__ */ jsx50(
8852
+ helperText || errorText ? /* @__PURE__ */ jsx51(
8514
8853
  "p",
8515
8854
  {
8516
8855
  id: errorText ? errorId : helperId,
8517
8856
  "data-slot": "otp-field-message",
8518
8857
  "data-kind": errorText ? "error" : "helper",
8519
8858
  className: otpFieldMessageVariants({ state: resolvedState }),
8520
- children: errorText ? /* @__PURE__ */ jsxs45(Fragment9, { children: [
8521
- /* @__PURE__ */ jsx50(
8859
+ children: errorText ? /* @__PURE__ */ jsxs46(Fragment9, { children: [
8860
+ /* @__PURE__ */ jsx51(
8522
8861
  AlertCircle4,
8523
8862
  {
8524
8863
  "aria-hidden": "true",
@@ -8526,11 +8865,11 @@ var OTPField = React40.forwardRef(
8526
8865
  strokeWidth: 2
8527
8866
  }
8528
8867
  ),
8529
- /* @__PURE__ */ jsx50("span", { children: errorText })
8530
- ] }) : /* @__PURE__ */ jsx50("span", { children: helperText })
8868
+ /* @__PURE__ */ jsx51("span", { children: errorText })
8869
+ ] }) : /* @__PURE__ */ jsx51("span", { children: helperText })
8531
8870
  }
8532
8871
  ) : null,
8533
- name ? /* @__PURE__ */ jsx50(
8872
+ name ? /* @__PURE__ */ jsx51(
8534
8873
  "input",
8535
8874
  {
8536
8875
  "aria-hidden": "true",
@@ -8551,10 +8890,10 @@ var OTPField = React40.forwardRef(
8551
8890
  OTPField.displayName = "OTPField";
8552
8891
 
8553
8892
  // src/components/ui/search-field.tsx
8554
- import * as React41 from "react";
8555
- import { Search, X as X4 } from "lucide-react";
8893
+ import * as React43 from "react";
8894
+ import { Search, X as X5 } from "lucide-react";
8556
8895
  import { cva as cva22 } from "class-variance-authority";
8557
- import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
8896
+ import { jsx as jsx52, jsxs as jsxs47 } from "react/jsx-runtime";
8558
8897
  var searchFieldVariants = cva22("relative flex w-full items-center", {
8559
8898
  variants: {
8560
8899
  size: {
@@ -8619,7 +8958,7 @@ var iconSize4 = {
8619
8958
  function hasVisibleValue(value) {
8620
8959
  return typeof value === "string" ? value.length > 0 : value !== void 0;
8621
8960
  }
8622
- var SearchField = React41.forwardRef(
8961
+ var SearchField = React43.forwardRef(
8623
8962
  ({
8624
8963
  className,
8625
8964
  inputMode = "search",
@@ -8635,12 +8974,12 @@ var SearchField = React41.forwardRef(
8635
8974
  ...props
8636
8975
  }, ref) => {
8637
8976
  const resolvedSize = size ?? "md";
8638
- const inputRef = React41.useRef(null);
8639
- const [hasText, setHasText] = React41.useState(
8977
+ const inputRef = React43.useRef(null);
8978
+ const [hasText, setHasText] = React43.useState(
8640
8979
  () => hasVisibleValue(value ?? defaultValue)
8641
8980
  );
8642
- React41.useImperativeHandle(ref, () => inputRef.current);
8643
- React41.useEffect(() => {
8981
+ React43.useImperativeHandle(ref, () => inputRef.current);
8982
+ React43.useEffect(() => {
8644
8983
  if (value !== void 0) {
8645
8984
  setHasText(hasVisibleValue(value));
8646
8985
  }
@@ -8653,14 +8992,14 @@ var SearchField = React41.forwardRef(
8653
8992
  }
8654
8993
  onClear?.();
8655
8994
  };
8656
- return /* @__PURE__ */ jsxs46(
8995
+ return /* @__PURE__ */ jsxs47(
8657
8996
  "div",
8658
8997
  {
8659
8998
  "data-slot": "search-field",
8660
8999
  "data-size": resolvedSize,
8661
9000
  className: cn(searchFieldVariants({ size, className })),
8662
9001
  children: [
8663
- /* @__PURE__ */ jsx51(
9002
+ /* @__PURE__ */ jsx52(
8664
9003
  Search,
8665
9004
  {
8666
9005
  "aria-hidden": "true",
@@ -8670,7 +9009,7 @@ var SearchField = React41.forwardRef(
8670
9009
  strokeWidth: resolvedSize === "sm" ? 2 : 1.75
8671
9010
  }
8672
9011
  ),
8673
- /* @__PURE__ */ jsx51(
9012
+ /* @__PURE__ */ jsx52(
8674
9013
  "input",
8675
9014
  {
8676
9015
  ref: inputRef,
@@ -8691,7 +9030,7 @@ var SearchField = React41.forwardRef(
8691
9030
  ...props
8692
9031
  }
8693
9032
  ),
8694
- showClear ? /* @__PURE__ */ jsx51(
9033
+ showClear ? /* @__PURE__ */ jsx52(
8695
9034
  "button",
8696
9035
  {
8697
9036
  type: "button",
@@ -8699,7 +9038,7 @@ var SearchField = React41.forwardRef(
8699
9038
  "data-slot": "search-field-clear",
8700
9039
  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)]",
8701
9040
  onClick: clearInput,
8702
- children: /* @__PURE__ */ jsx51(X4, { "aria-hidden": "true", size: 16, strokeWidth: 1.75 })
9041
+ children: /* @__PURE__ */ jsx52(X5, { "aria-hidden": "true", size: 16, strokeWidth: 1.75 })
8703
9042
  }
8704
9043
  ) : null
8705
9044
  ]
@@ -8710,9 +9049,9 @@ var SearchField = React41.forwardRef(
8710
9049
  SearchField.displayName = "SearchField";
8711
9050
 
8712
9051
  // src/components/ui/checkbox-group.tsx
8713
- import * as React42 from "react";
9052
+ import * as React44 from "react";
8714
9053
  import { cva as cva23 } from "class-variance-authority";
8715
- import { jsx as jsx52 } from "react/jsx-runtime";
9054
+ import { jsx as jsx53 } from "react/jsx-runtime";
8716
9055
  var checkboxGroupVariants = cva23("gap-[var(--space-2)]", {
8717
9056
  variants: {
8718
9057
  appearance: {
@@ -8738,7 +9077,7 @@ var checkboxGroupVariants = cva23("gap-[var(--space-2)]", {
8738
9077
  function toSelectionSet(value) {
8739
9078
  return new Set(value ?? []);
8740
9079
  }
8741
- var CheckboxGroup = React42.forwardRef(
9080
+ var CheckboxGroup = React44.forwardRef(
8742
9081
  ({
8743
9082
  className,
8744
9083
  children,
@@ -8754,14 +9093,14 @@ var CheckboxGroup = React42.forwardRef(
8754
9093
  ...props
8755
9094
  }, ref) => {
8756
9095
  const isControlled = value != null;
8757
- const [uncontrolledValue, setUncontrolledValue] = React42.useState(
9096
+ const [uncontrolledValue, setUncontrolledValue] = React44.useState(
8758
9097
  () => toSelectionSet(defaultValue)
8759
9098
  );
8760
- const selectedValues = React42.useMemo(
9099
+ const selectedValues = React44.useMemo(
8761
9100
  () => isControlled ? toSelectionSet(value) : uncontrolledValue,
8762
9101
  [isControlled, uncontrolledValue, value]
8763
9102
  );
8764
- const toggleValue = React42.useCallback(
9103
+ const toggleValue = React44.useCallback(
8765
9104
  (itemValue, checked) => {
8766
9105
  const nextValues = new Set(selectedValues);
8767
9106
  if (checked) {
@@ -8777,7 +9116,7 @@ var CheckboxGroup = React42.forwardRef(
8777
9116
  },
8778
9117
  [isControlled, onValueChange, selectedValues]
8779
9118
  );
8780
- const contextValue = React42.useMemo(
9119
+ const contextValue = React44.useMemo(
8781
9120
  () => ({
8782
9121
  appearance,
8783
9122
  density,
@@ -8788,7 +9127,7 @@ var CheckboxGroup = React42.forwardRef(
8788
9127
  }),
8789
9128
  [appearance, density, disabled, name, selectedValues, toggleValue]
8790
9129
  );
8791
- return /* @__PURE__ */ jsx52(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx52(
9130
+ return /* @__PURE__ */ jsx53(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx53(
8792
9131
  "div",
8793
9132
  {
8794
9133
  ref,
@@ -8812,11 +9151,11 @@ var CheckboxGroup = React42.forwardRef(
8812
9151
  CheckboxGroup.displayName = "CheckboxGroup";
8813
9152
 
8814
9153
  // src/components/ui/radio-group.tsx
8815
- import * as React43 from "react";
9154
+ import * as React45 from "react";
8816
9155
  import { cva as cva24 } from "class-variance-authority";
8817
9156
  import { Circle } from "lucide-react";
8818
9157
  import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
8819
- import { jsx as jsx53, jsxs as jsxs47 } from "react/jsx-runtime";
9158
+ import { jsx as jsx54, jsxs as jsxs48 } from "react/jsx-runtime";
8820
9159
  var radioGroupVariants = cva24("gap-[var(--space-2)]", {
8821
9160
  variants: {
8822
9161
  appearance: {
@@ -8851,7 +9190,7 @@ var radioVariants = cva24(
8851
9190
  {
8852
9191
  variants: {
8853
9192
  appearance: {
8854
- plain: "inline-flex items-start gap-[var(--space-3)] rounded-[var(--radius-sm)] px-pad-compact-x py-pad-compact-y",
9193
+ plain: "inline-flex items-start gap-[var(--space-3)] rounded-[var(--radius-md)] px-pad-compact-x py-pad-compact-y",
8855
9194
  card: [
8856
9195
  "flex min-h-[calc(var(--space-12)+var(--space-2))] items-start gap-[var(--space-3)]",
8857
9196
  "rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-surface)]",
@@ -8905,11 +9244,11 @@ var radioControlVariants = cva24(
8905
9244
  }
8906
9245
  }
8907
9246
  );
8908
- var RadioGroupContext = React43.createContext({
9247
+ var RadioGroupContext = React45.createContext({
8909
9248
  appearance: "plain",
8910
9249
  density: "comfortable"
8911
9250
  });
8912
- var RadioGroup = React43.forwardRef(
9251
+ var RadioGroup = React45.forwardRef(
8913
9252
  ({
8914
9253
  className,
8915
9254
  children,
@@ -8920,11 +9259,11 @@ var RadioGroup = React43.forwardRef(
8920
9259
  required,
8921
9260
  ...props
8922
9261
  }, ref) => {
8923
- const contextValue = React43.useMemo(
9262
+ const contextValue = React45.useMemo(
8924
9263
  () => ({ appearance, density }),
8925
9264
  [appearance, density]
8926
9265
  );
8927
- return /* @__PURE__ */ jsx53(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx53(
9266
+ return /* @__PURE__ */ jsx54(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx54(
8928
9267
  RadioGroupPrimitive.Root,
8929
9268
  {
8930
9269
  ref,
@@ -8947,13 +9286,13 @@ var RadioGroup = React43.forwardRef(
8947
9286
  }
8948
9287
  );
8949
9288
  RadioGroup.displayName = "RadioGroup";
8950
- var Radio = React43.forwardRef(({ className, children, description, id, ...props }, ref) => {
8951
- const { appearance, density } = React43.useContext(RadioGroupContext);
8952
- const generatedId = React43.useId();
9289
+ var Radio = React45.forwardRef(({ className, children, description, id, ...props }, ref) => {
9290
+ const { appearance, density } = React45.useContext(RadioGroupContext);
9291
+ const generatedId = React45.useId();
8953
9292
  const radioId = id ?? generatedId;
8954
9293
  const labelId = `${radioId}-label`;
8955
9294
  const descriptionId = description ? `${radioId}-description` : void 0;
8956
- return /* @__PURE__ */ jsxs47(
9295
+ return /* @__PURE__ */ jsxs48(
8957
9296
  RadioGroupPrimitive.Item,
8958
9297
  {
8959
9298
  ref,
@@ -8964,24 +9303,24 @@ var Radio = React43.forwardRef(({ className, children, description, id, ...props
8964
9303
  className: cn(radioVariants({ appearance, density }), className),
8965
9304
  ...props,
8966
9305
  children: [
8967
- /* @__PURE__ */ jsx53(
9306
+ /* @__PURE__ */ jsx54(
8968
9307
  "span",
8969
9308
  {
8970
9309
  "aria-hidden": "true",
8971
9310
  "data-slot": "radio-control",
8972
9311
  className: radioControlVariants({ appearance }),
8973
- children: /* @__PURE__ */ jsx53(
9312
+ children: /* @__PURE__ */ jsx54(
8974
9313
  RadioGroupPrimitive.Indicator,
8975
9314
  {
8976
9315
  "data-slot": "radio-indicator",
8977
9316
  className: "flex items-center justify-center",
8978
- children: /* @__PURE__ */ jsx53(Circle, { "aria-hidden": "true", size: 8, fill: "currentColor" })
9317
+ children: /* @__PURE__ */ jsx54(Circle, { "aria-hidden": "true", size: 8, fill: "currentColor" })
8979
9318
  }
8980
9319
  )
8981
9320
  }
8982
9321
  ),
8983
- /* @__PURE__ */ jsxs47("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
8984
- /* @__PURE__ */ jsx53(
9322
+ /* @__PURE__ */ jsxs48("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
9323
+ /* @__PURE__ */ jsx54(
8985
9324
  "span",
8986
9325
  {
8987
9326
  id: labelId,
@@ -8993,7 +9332,7 @@ var Radio = React43.forwardRef(({ className, children, description, id, ...props
8993
9332
  children
8994
9333
  }
8995
9334
  ),
8996
- description ? /* @__PURE__ */ jsx53(
9335
+ description ? /* @__PURE__ */ jsx54(
8997
9336
  "span",
8998
9337
  {
8999
9338
  id: descriptionId,
@@ -9011,20 +9350,20 @@ Radio.displayName = "Radio";
9011
9350
 
9012
9351
  // src/components/ui/scroll-area.tsx
9013
9352
  import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
9014
- import { jsx as jsx54, jsxs as jsxs48 } from "react/jsx-runtime";
9353
+ import { jsx as jsx55, jsxs as jsxs49 } from "react/jsx-runtime";
9015
9354
  function ScrollArea({
9016
9355
  className,
9017
9356
  children,
9018
9357
  ...props
9019
9358
  }) {
9020
- return /* @__PURE__ */ jsxs48(
9359
+ return /* @__PURE__ */ jsxs49(
9021
9360
  ScrollAreaPrimitive.Root,
9022
9361
  {
9023
9362
  "data-slot": "scroll-area",
9024
9363
  className: cn("relative", className),
9025
9364
  ...props,
9026
9365
  children: [
9027
- /* @__PURE__ */ jsx54(
9366
+ /* @__PURE__ */ jsx55(
9028
9367
  ScrollAreaPrimitive.Viewport,
9029
9368
  {
9030
9369
  "data-slot": "scroll-area-viewport",
@@ -9032,8 +9371,8 @@ function ScrollArea({
9032
9371
  children
9033
9372
  }
9034
9373
  ),
9035
- /* @__PURE__ */ jsx54(ScrollBar, {}),
9036
- /* @__PURE__ */ jsx54(ScrollAreaPrimitive.Corner, {})
9374
+ /* @__PURE__ */ jsx55(ScrollBar, {}),
9375
+ /* @__PURE__ */ jsx55(ScrollAreaPrimitive.Corner, {})
9037
9376
  ]
9038
9377
  }
9039
9378
  );
@@ -9043,7 +9382,7 @@ function ScrollBar({
9043
9382
  orientation = "vertical",
9044
9383
  ...props
9045
9384
  }) {
9046
- return /* @__PURE__ */ jsx54(
9385
+ return /* @__PURE__ */ jsx55(
9047
9386
  ScrollAreaPrimitive.ScrollAreaScrollbar,
9048
9387
  {
9049
9388
  "data-slot": "scroll-area-scrollbar",
@@ -9055,7 +9394,7 @@ function ScrollBar({
9055
9394
  className
9056
9395
  ),
9057
9396
  ...props,
9058
- children: /* @__PURE__ */ jsx54(
9397
+ children: /* @__PURE__ */ jsx55(
9059
9398
  ScrollAreaPrimitive.ScrollAreaThumb,
9060
9399
  {
9061
9400
  "data-slot": "scroll-area-thumb",
@@ -9067,7 +9406,7 @@ function ScrollBar({
9067
9406
  }
9068
9407
 
9069
9408
  // src/components/ui/progress.tsx
9070
- import { jsx as jsx55 } from "react/jsx-runtime";
9409
+ import { jsx as jsx56 } from "react/jsx-runtime";
9071
9410
  var progressFillByStatus = {
9072
9411
  active: "bg-[var(--primary)]",
9073
9412
  success: "bg-[var(--success)]",
@@ -9088,7 +9427,7 @@ function Progress({
9088
9427
  const clamped = Math.max(0, Math.min(safeMax, value));
9089
9428
  const percent = clamped / safeMax * 100;
9090
9429
  const w = typeof width === "number" ? `${width}px` : width;
9091
- return /* @__PURE__ */ jsx55(
9430
+ return /* @__PURE__ */ jsx56(
9092
9431
  "div",
9093
9432
  {
9094
9433
  role: "progressbar",
@@ -9102,7 +9441,7 @@ function Progress({
9102
9441
  ),
9103
9442
  style: { width: w, height: `${height}px`, ...style },
9104
9443
  ...props,
9105
- children: /* @__PURE__ */ jsx55(
9444
+ children: /* @__PURE__ */ jsx56(
9106
9445
  "div",
9107
9446
  {
9108
9447
  className: cn(
@@ -9117,10 +9456,10 @@ function Progress({
9117
9456
  }
9118
9457
 
9119
9458
  // src/components/ui/tree-view.tsx
9120
- import * as React44 from "react";
9459
+ import * as React46 from "react";
9121
9460
  import { ChevronRight as ChevronRight3 } from "lucide-react";
9122
9461
  import { cva as cva25 } from "class-variance-authority";
9123
- import { jsx as jsx56, jsxs as jsxs49 } from "react/jsx-runtime";
9462
+ import { jsx as jsx57, jsxs as jsxs50 } from "react/jsx-runtime";
9124
9463
  var treeViewVariants = cva25(
9125
9464
  "m-0 list-none p-[var(--space-1)] text-body-sm text-foreground"
9126
9465
  );
@@ -9223,27 +9562,27 @@ function TreeView({
9223
9562
  ...rest
9224
9563
  }) {
9225
9564
  const isExpandedControlled = expandedIds !== void 0;
9226
- const [internalExpanded, setInternalExpanded] = React44.useState(
9565
+ const [internalExpanded, setInternalExpanded] = React46.useState(
9227
9566
  () => defaultExpandedIds ?? []
9228
9567
  );
9229
9568
  const expandedList = isExpandedControlled ? expandedIds : internalExpanded;
9230
- const expandedSet = React44.useMemo(() => new Set(expandedList), [expandedList]);
9231
- const items = React44.useMemo(
9569
+ const expandedSet = React46.useMemo(() => new Set(expandedList), [expandedList]);
9570
+ const items = React46.useMemo(
9232
9571
  () => flattenVisibleNodes(nodes, getChildren, expandedSet),
9233
9572
  [nodes, getChildren, expandedSet]
9234
9573
  );
9235
- const [focusedId, setFocusedId] = React44.useState(null);
9574
+ const [focusedId, setFocusedId] = React46.useState(null);
9236
9575
  const visibleIds = items.map((item) => item.id);
9237
9576
  const activeId = focusedId && visibleIds.includes(focusedId) ? focusedId : selectedId && visibleIds.includes(selectedId) ? selectedId : visibleIds[0] ?? null;
9238
- const itemRefs = React44.useRef(/* @__PURE__ */ new Map());
9239
- const commitExpanded = React44.useCallback(
9577
+ const itemRefs = React46.useRef(/* @__PURE__ */ new Map());
9578
+ const commitExpanded = React46.useCallback(
9240
9579
  (next) => {
9241
9580
  if (!isExpandedControlled) setInternalExpanded(next);
9242
9581
  onExpandedChange?.(next);
9243
9582
  },
9244
9583
  [isExpandedControlled, onExpandedChange]
9245
9584
  );
9246
- const setExpanded = React44.useCallback(
9585
+ const setExpanded = React46.useCallback(
9247
9586
  (id, expand) => {
9248
9587
  const has = expandedSet.has(id);
9249
9588
  if (expand && !has) {
@@ -9254,7 +9593,7 @@ function TreeView({
9254
9593
  },
9255
9594
  [commitExpanded, expandedList, expandedSet]
9256
9595
  );
9257
- const focusItem = React44.useCallback((id) => {
9596
+ const focusItem = React46.useCallback((id) => {
9258
9597
  setFocusedId(id);
9259
9598
  itemRefs.current.get(id)?.focus();
9260
9599
  }, []);
@@ -9290,7 +9629,7 @@ function TreeView({
9290
9629
  const selected = node.id === selectedId;
9291
9630
  const isActive = node.id === activeId;
9292
9631
  const itemState = { expanded, selected, depth, hasChildren };
9293
- return /* @__PURE__ */ jsxs49(
9632
+ return /* @__PURE__ */ jsxs50(
9294
9633
  "li",
9295
9634
  {
9296
9635
  ref: (element) => {
@@ -9315,7 +9654,7 @@ function TreeView({
9315
9654
  onSelect?.(node.id, node);
9316
9655
  },
9317
9656
  children: [
9318
- /* @__PURE__ */ jsxs49(
9657
+ /* @__PURE__ */ jsxs50(
9319
9658
  "span",
9320
9659
  {
9321
9660
  "data-slot": "treeitem-row",
@@ -9324,7 +9663,7 @@ function TreeView({
9324
9663
  },
9325
9664
  className: treeItemRowVariants({ selected }),
9326
9665
  children: [
9327
- hasChildren ? /* @__PURE__ */ jsx56(
9666
+ hasChildren ? /* @__PURE__ */ jsx57(
9328
9667
  "span",
9329
9668
  {
9330
9669
  "data-slot": "treeitem-toggle",
@@ -9334,7 +9673,7 @@ function TreeView({
9334
9673
  setExpanded(node.id, !expanded);
9335
9674
  },
9336
9675
  className: "flex size-[var(--space-4)] shrink-0 items-center justify-center text-text-tertiary",
9337
- children: /* @__PURE__ */ jsx56(
9676
+ children: /* @__PURE__ */ jsx57(
9338
9677
  ChevronRight3,
9339
9678
  {
9340
9679
  "aria-hidden": "true",
@@ -9347,7 +9686,7 @@ function TreeView({
9347
9686
  }
9348
9687
  )
9349
9688
  }
9350
- ) : /* @__PURE__ */ jsx56(
9689
+ ) : /* @__PURE__ */ jsx57(
9351
9690
  "span",
9352
9691
  {
9353
9692
  "data-slot": "treeitem-spacer",
@@ -9355,18 +9694,18 @@ function TreeView({
9355
9694
  className: "size-[var(--space-4)] shrink-0"
9356
9695
  }
9357
9696
  ),
9358
- /* @__PURE__ */ jsx56("span", { className: "flex min-w-0 flex-1 items-center gap-[var(--space-2)]", children: renderItem(node, itemState) })
9697
+ /* @__PURE__ */ jsx57("span", { className: "flex min-w-0 flex-1 items-center gap-[var(--space-2)]", children: renderItem(node, itemState) })
9359
9698
  ]
9360
9699
  }
9361
9700
  ),
9362
- hasChildren && expanded && children ? /* @__PURE__ */ jsx56("ul", { role: "group", "data-slot": "tree-group", className: "m-0 list-none p-0", children: renderLevel(children, depth + 1) }) : null
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
9363
9702
  ]
9364
9703
  },
9365
9704
  node.id
9366
9705
  );
9367
9706
  });
9368
9707
  }
9369
- return /* @__PURE__ */ jsx56(
9708
+ return /* @__PURE__ */ jsx57(
9370
9709
  "ul",
9371
9710
  {
9372
9711
  role: "tree",
@@ -9382,9 +9721,9 @@ function TreeView({
9382
9721
  }
9383
9722
 
9384
9723
  // src/components/branding/olun-logo.tsx
9385
- import { jsx as jsx57, jsxs as jsxs50 } from "react/jsx-runtime";
9724
+ import { jsx as jsx58, jsxs as jsxs51 } from "react/jsx-runtime";
9386
9725
  function OlunSymbol({ size = 28, className }) {
9387
- return /* @__PURE__ */ jsxs50(
9726
+ return /* @__PURE__ */ jsxs51(
9388
9727
  "svg",
9389
9728
  {
9390
9729
  width: size,
@@ -9395,7 +9734,7 @@ function OlunSymbol({ size = 28, className }) {
9395
9734
  className,
9396
9735
  "aria-hidden": "true",
9397
9736
  children: [
9398
- /* @__PURE__ */ jsx57(
9737
+ /* @__PURE__ */ jsx58(
9399
9738
  "circle",
9400
9739
  {
9401
9740
  cx: "108",
@@ -9407,7 +9746,7 @@ function OlunSymbol({ size = 28, className }) {
9407
9746
  style: { color: "var(--text-primary)" }
9408
9747
  }
9409
9748
  ),
9410
- /* @__PURE__ */ jsx57("circle", { cx: "185", cy: "175", r: "22", fill: "var(--accent-pop)" })
9749
+ /* @__PURE__ */ jsx58("circle", { cx: "185", cy: "175", r: "22", fill: "var(--accent-pop)" })
9411
9750
  ]
9412
9751
  }
9413
9752
  );
@@ -9418,7 +9757,7 @@ function OlunLogo({
9418
9757
  showSymbol = true,
9419
9758
  className
9420
9759
  }) {
9421
- return /* @__PURE__ */ jsxs50(
9760
+ return /* @__PURE__ */ jsxs51(
9422
9761
  "div",
9423
9762
  {
9424
9763
  className,
@@ -9428,8 +9767,8 @@ function OlunLogo({
9428
9767
  gap: "var(--space-3)"
9429
9768
  },
9430
9769
  children: [
9431
- showSymbol && /* @__PURE__ */ jsx57(OlunSymbol, { size: symbolSize }),
9432
- /* @__PURE__ */ jsxs50(
9770
+ showSymbol && /* @__PURE__ */ jsx58(OlunSymbol, { size: symbolSize }),
9771
+ /* @__PURE__ */ jsxs51(
9433
9772
  "span",
9434
9773
  {
9435
9774
  style: {
@@ -9441,7 +9780,7 @@ function OlunLogo({
9441
9780
  },
9442
9781
  children: [
9443
9782
  "OLUN",
9444
- /* @__PURE__ */ jsx57("span", { style: { color: "var(--accent)" }, children: "." })
9783
+ /* @__PURE__ */ jsx58("span", { style: { color: "var(--accent)" }, children: "." })
9445
9784
  ]
9446
9785
  }
9447
9786
  )
@@ -9452,30 +9791,30 @@ function OlunLogo({
9452
9791
 
9453
9792
  // src/components/branding/theme-toggle.tsx
9454
9793
  import { Sun, Moon } from "lucide-react";
9455
- import { jsx as jsx58 } from "react/jsx-runtime";
9794
+ import { jsx as jsx59 } from "react/jsx-runtime";
9456
9795
  function ThemeToggle({ className }) {
9457
9796
  const { resolvedTheme, toggleTheme } = useOlunTheme();
9458
9797
  const Icon = resolvedTheme === "dark" ? Moon : Sun;
9459
- return /* @__PURE__ */ jsx58(
9798
+ return /* @__PURE__ */ jsx59(
9460
9799
  "button",
9461
9800
  {
9462
9801
  onClick: () => toggleTheme(),
9463
9802
  className: cn(
9464
- "inline-flex size-[36px] items-center justify-center rounded-sm",
9803
+ "inline-flex size-[36px] items-center justify-center rounded-[var(--radius-md)]",
9465
9804
  "text-text-secondary hover:bg-[var(--action-hover)] hover:text-foreground",
9466
9805
  "transition-colors motion-reduce:transition-none",
9467
9806
  className
9468
9807
  ),
9469
9808
  "aria-label": "\uD14C\uB9C8 \uC804\uD658",
9470
9809
  title: resolvedTheme === "dark" ? "\uB77C\uC774\uD2B8 \uBAA8\uB4DC\uB85C" : "\uB2E4\uD06C \uBAA8\uB4DC\uB85C",
9471
- children: /* @__PURE__ */ jsx58(Icon, { className: "size-[18px]", strokeWidth: 1.75 })
9810
+ children: /* @__PURE__ */ jsx59(Icon, { className: "size-[18px]", strokeWidth: 1.75 })
9472
9811
  }
9473
9812
  );
9474
9813
  }
9475
9814
 
9476
9815
  // src/components/branding/theme-fab.tsx
9477
9816
  import { Sun as Sun2, Moon as Moon2 } from "lucide-react";
9478
- import { jsx as jsx59 } from "react/jsx-runtime";
9817
+ import { jsx as jsx60 } from "react/jsx-runtime";
9479
9818
  function ThemeFab({ variant = "square" } = {}) {
9480
9819
  const { mounted, resolvedTheme, toggleTheme } = useOlunTheme();
9481
9820
  if (!mounted) {
@@ -9495,7 +9834,7 @@ function ThemeFab({ variant = "square" } = {}) {
9495
9834
  right: "12px",
9496
9835
  width: "36px",
9497
9836
  height: "36px",
9498
- borderRadius: "var(--radius-sm)",
9837
+ borderRadius: "var(--radius-md)",
9499
9838
  border: "1px solid var(--border-subtle)",
9500
9839
  background: "var(--bg-surface)",
9501
9840
  color: "var(--text-secondary)",
@@ -9515,7 +9854,7 @@ function ThemeFab({ variant = "square" } = {}) {
9515
9854
  WebkitBackdropFilter: "blur(16px)",
9516
9855
  zIndex: 9999
9517
9856
  };
9518
- return /* @__PURE__ */ jsx59(
9857
+ return /* @__PURE__ */ jsx60(
9519
9858
  "button",
9520
9859
  {
9521
9860
  onClick: () => toggleTheme(),
@@ -9540,7 +9879,7 @@ function ThemeFab({ variant = "square" } = {}) {
9540
9879
  e.currentTarget.style.color = "var(--text-secondary)";
9541
9880
  }
9542
9881
  },
9543
- children: /* @__PURE__ */ jsx59(
9882
+ children: /* @__PURE__ */ jsx60(
9544
9883
  Icon,
9545
9884
  {
9546
9885
  size: isCircle ? 22 : 16,
@@ -9552,7 +9891,7 @@ function ThemeFab({ variant = "square" } = {}) {
9552
9891
  }
9553
9892
 
9554
9893
  // src/components/logos/organization-logo.tsx
9555
- import { jsx as jsx60 } from "react/jsx-runtime";
9894
+ import { jsx as jsx61 } from "react/jsx-runtime";
9556
9895
  var organizationLogoRegistry = {
9557
9896
  jbnu: {
9558
9897
  label: "\uC804\uBD81\uB300\uD559\uAD50 \uC5E0\uBE14\uB7FC",
@@ -9581,7 +9920,7 @@ function OrganizationLogo({
9581
9920
  }) {
9582
9921
  const asset = organizationLogoRegistry[organization];
9583
9922
  const isDecorative = ariaHidden === true || ariaHidden === "true";
9584
- return /* @__PURE__ */ jsx60(
9923
+ return /* @__PURE__ */ jsx61(
9585
9924
  "svg",
9586
9925
  {
9587
9926
  viewBox: asset.viewBox,
@@ -9599,12 +9938,13 @@ function OrganizationLogo({
9599
9938
  ...style
9600
9939
  },
9601
9940
  ...props,
9602
- children: asset.paths.map((path) => /* @__PURE__ */ jsx60("path", { d: path }, path))
9941
+ children: asset.paths.map((path) => /* @__PURE__ */ jsx61("path", { d: path }, path))
9603
9942
  }
9604
9943
  );
9605
9944
  }
9606
9945
  export {
9607
9946
  ActionFooter,
9947
+ ActionSheet,
9608
9948
  Alert,
9609
9949
  Avatar,
9610
9950
  AvatarFallback,