@olundot/ui 0.20.0-next.0 → 0.20.0-next.2

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
@@ -3020,12 +3020,12 @@ var tabsListVariants = cva8(
3020
3020
  {
3021
3021
  variant: "line",
3022
3022
  orientation: "horizontal",
3023
- className: "border-b border-[var(--border-subtle)] gap-[var(--space-6)] overflow-x-auto overflow-y-hidden"
3023
+ className: "group/tabs-list relative border-b border-[var(--border-subtle)] gap-[var(--space-6)] overflow-x-auto overflow-y-hidden"
3024
3024
  },
3025
3025
  {
3026
3026
  variant: "line",
3027
3027
  orientation: "vertical",
3028
- className: "border-r border-[var(--border-subtle)] gap-[var(--space-2)] pr-[var(--space-4)] max-sm:flex-row max-sm:gap-[var(--space-6)] max-sm:overflow-x-auto max-sm:overflow-y-hidden max-sm:border-r-0 max-sm:border-b max-sm:pr-0"
3028
+ className: "group/tabs-list relative border-r border-[var(--border-subtle)] gap-[var(--space-2)] pr-[var(--space-4)] max-sm:flex-row max-sm:gap-[var(--space-6)] max-sm:overflow-x-auto max-sm:overflow-y-hidden max-sm:border-r-0 max-sm:border-b max-sm:pr-0"
3029
3029
  },
3030
3030
  {
3031
3031
  variant: "contained",
@@ -3080,6 +3080,12 @@ var tabsTriggerVariants = cva8(
3080
3080
  orientation: "horizontal",
3081
3081
  className: "mx-[-2px] px-[2px] first:ml-0 last:mr-0 focus-visible:ring-0 focus-visible:inset-ring-2 focus-visible:inset-ring-[var(--focus-ring)]"
3082
3082
  },
3083
+ // Once the list's indicator has measured the active trigger, it replaces the static ::after
3084
+ // underline. Before hydration (or without the indicator) the ::after stays.
3085
+ {
3086
+ variant: "line",
3087
+ className: "group-data-[indicator=ready]/tabs-list:after:hidden"
3088
+ },
3083
3089
  {
3084
3090
  variant: "line",
3085
3091
  orientation: "vertical",
@@ -3092,6 +3098,35 @@ var tabsTriggerVariants = cva8(
3092
3098
  }
3093
3099
  }
3094
3100
  );
3101
+ var tabsIndicatorVariants = cva8(
3102
+ [
3103
+ "pointer-events-none absolute invisible bg-[var(--text-primary)]",
3104
+ // transition-property stays none (duration alone would animate every property, visibility included)
3105
+ // until data-motion turns on the per-orientation transition below.
3106
+ "transition-none duration-[var(--dur-base)] ease-[var(--ease-standard)]",
3107
+ "group-data-[indicator=ready]/tabs-list:visible"
3108
+ ].join(" "),
3109
+ {
3110
+ variants: {
3111
+ orientation: {
3112
+ horizontal: "bottom-[-1px] left-0 h-[2px] w-[var(--tabs-indicator-width)] [transform:translateX(var(--tabs-indicator-left))] motion-safe:data-[motion=on]:transition-[transform,width]",
3113
+ // Below `sm` the vertical list becomes a horizontal row, so the indicator follows the horizontal rule.
3114
+ vertical: [
3115
+ "max-sm:bottom-[-1px] max-sm:left-0 max-sm:h-[2px] max-sm:w-[var(--tabs-indicator-width)] max-sm:[transform:translateX(var(--tabs-indicator-left))] max-sm:motion-safe:data-[motion=on]:transition-[transform,width]",
3116
+ "sm:top-0 sm:right-[-1px] sm:h-[var(--tabs-indicator-height)] sm:w-[2px] sm:[transform:translateY(var(--tabs-indicator-top))] sm:motion-safe:data-[motion=on]:transition-[transform,height]"
3117
+ ].join(" ")
3118
+ }
3119
+ },
3120
+ defaultVariants: {
3121
+ orientation: "horizontal"
3122
+ }
3123
+ }
3124
+ );
3125
+ var tabsLabelReserveClassName = [
3126
+ "inline-flex flex-col",
3127
+ "before:invisible before:h-0 before:overflow-hidden before:font-medium before:content-[attr(data-label)]",
3128
+ "after:invisible after:h-0 after:overflow-hidden after:font-bold after:content-[attr(data-label)]"
3129
+ ].join(" ");
3095
3130
  var tabsBadgeVariants = cva8(
3096
3131
  [
3097
3132
  "inline-flex h-[18px] min-w-[18px] items-center justify-center",
@@ -3106,6 +3141,62 @@ var tabsBadgeVariants = cva8(
3106
3141
  "group-data-[state=active]:border-[var(--border-strong)]"
3107
3142
  ].join(" ")
3108
3143
  );
3144
+ function useTabsIndicator(enabled, activeKey, tabsKey, listRef, indicatorRef) {
3145
+ const placedRef = React17.useRef(null);
3146
+ const previousKeyRef = React17.useRef(null);
3147
+ const place = React17.useCallback(
3148
+ (animate) => {
3149
+ const list = listRef.current;
3150
+ const indicator = indicatorRef.current;
3151
+ if (!list || !indicator) return;
3152
+ const trigger = list.querySelector(':scope > [data-slot="tabs-trigger"][data-state="active"]');
3153
+ if (!trigger) {
3154
+ delete list.dataset.indicator;
3155
+ placedRef.current = null;
3156
+ return;
3157
+ }
3158
+ const { offsetLeft, offsetWidth, offsetTop, offsetHeight } = trigger;
3159
+ const placed = `${offsetLeft} ${offsetWidth} ${offsetTop} ${offsetHeight}`;
3160
+ if (placed === placedRef.current) return;
3161
+ placedRef.current = placed;
3162
+ if (animate && list.dataset.indicator === "ready") indicator.dataset.motion = "on";
3163
+ else delete indicator.dataset.motion;
3164
+ indicator.style.setProperty("--tabs-indicator-left", `${offsetLeft}px`);
3165
+ indicator.style.setProperty("--tabs-indicator-width", `${offsetWidth}px`);
3166
+ indicator.style.setProperty("--tabs-indicator-top", `${offsetTop}px`);
3167
+ indicator.style.setProperty("--tabs-indicator-height", `${offsetHeight}px`);
3168
+ list.dataset.indicator = "ready";
3169
+ },
3170
+ [listRef, indicatorRef]
3171
+ );
3172
+ React17.useLayoutEffect(() => {
3173
+ if (!enabled) {
3174
+ placedRef.current = null;
3175
+ previousKeyRef.current = null;
3176
+ return;
3177
+ }
3178
+ const previousKey = previousKeyRef.current;
3179
+ previousKeyRef.current = activeKey;
3180
+ place(previousKey !== null && previousKey !== activeKey);
3181
+ }, [enabled, activeKey, tabsKey, place]);
3182
+ React17.useEffect(() => {
3183
+ const list = listRef.current;
3184
+ if (!enabled || !list) return;
3185
+ let cancelled = false;
3186
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => place(false));
3187
+ if (observer) {
3188
+ observer.observe(list);
3189
+ list.querySelectorAll(':scope > [data-slot="tabs-trigger"]').forEach((trigger) => observer.observe(trigger));
3190
+ }
3191
+ document.fonts?.ready.then(() => {
3192
+ if (!cancelled) place(false);
3193
+ });
3194
+ return () => {
3195
+ cancelled = true;
3196
+ observer?.disconnect();
3197
+ };
3198
+ }, [enabled, tabsKey, place, listRef]);
3199
+ }
3109
3200
  function formatTabBadge(value) {
3110
3201
  return value > 99 ? "99+" : String(value);
3111
3202
  }
@@ -3128,55 +3219,77 @@ var Tabs = React17.forwardRef(
3128
3219
  orientation = "horizontal",
3129
3220
  variant = "line",
3130
3221
  ...props
3131
- }, ref) => /* @__PURE__ */ jsxs17(
3132
- TabsPrimitive.Root,
3133
- {
3134
- ref,
3135
- "data-slot": "tabs",
3136
- value: activeKey,
3137
- onValueChange: onChange,
3138
- orientation,
3139
- className: cn(tabsRootVariants({ orientation }), className),
3140
- ...props,
3141
- children: [
3142
- /* @__PURE__ */ jsx18(
3143
- TabsPrimitive.List,
3144
- {
3145
- "data-slot": "tabs-list",
3146
- "data-variant": variant,
3147
- className: cn(tabsListVariants({ variant, orientation }), listClassName),
3148
- children: tabs.map((tab) => /* @__PURE__ */ jsxs17(
3149
- TabsPrimitive.Trigger,
3150
- {
3151
- id: getTabId(baseId, tab.key),
3152
- value: tab.key,
3153
- disabled: tab.disabled,
3154
- "aria-controls": getPanelId(baseId, tab.key),
3155
- "data-slot": "tabs-trigger",
3156
- "data-variant": variant,
3157
- className: cn("group", tabsTriggerVariants({ variant, orientation }), triggerClassName),
3158
- children: [
3159
- /* @__PURE__ */ jsx18("span", { children: tab.label }),
3160
- tab.badge !== void 0 && tab.badge > 0 ? /* @__PURE__ */ jsx18("span", { "aria-hidden": "true", "data-slot": "tabs-badge", className: tabsBadgeVariants(), children: formatTabBadge(tab.badge) }) : null,
3161
- tab.disabled ? /* @__PURE__ */ jsx18(
3162
- Lock,
3163
- {
3164
- "aria-hidden": "true",
3165
- "data-slot": "tabs-disabled-icon",
3166
- className: "size-[14px] shrink-0 text-text-disabled",
3167
- strokeWidth: 2
3222
+ }, ref) => {
3223
+ const listRef = React17.useRef(null);
3224
+ const indicatorRef = React17.useRef(null);
3225
+ const isLine = variant === "line";
3226
+ const tabsKey = tabs.map((tab) => tab.key).join("\0");
3227
+ useTabsIndicator(isLine, activeKey, tabsKey, listRef, indicatorRef);
3228
+ return /* @__PURE__ */ jsxs17(
3229
+ TabsPrimitive.Root,
3230
+ {
3231
+ ref,
3232
+ "data-slot": "tabs",
3233
+ value: activeKey,
3234
+ onValueChange: onChange,
3235
+ orientation,
3236
+ className: cn(tabsRootVariants({ orientation }), className),
3237
+ ...props,
3238
+ children: [
3239
+ /* @__PURE__ */ jsxs17(
3240
+ TabsPrimitive.List,
3241
+ {
3242
+ ref: listRef,
3243
+ "data-slot": "tabs-list",
3244
+ "data-variant": variant,
3245
+ className: cn(tabsListVariants({ variant, orientation }), listClassName),
3246
+ children: [
3247
+ tabs.map((tab) => /* @__PURE__ */ jsxs17(
3248
+ TabsPrimitive.Trigger,
3249
+ {
3250
+ id: getTabId(baseId, tab.key),
3251
+ value: tab.key,
3252
+ disabled: tab.disabled,
3253
+ "aria-controls": getPanelId(baseId, tab.key),
3254
+ "data-slot": "tabs-trigger",
3255
+ "data-variant": variant,
3256
+ className: cn("group", tabsTriggerVariants({ variant, orientation }), triggerClassName),
3257
+ children: [
3258
+ isLine ? /* @__PURE__ */ jsx18("span", { "data-label": tab.label, className: tabsLabelReserveClassName, children: tab.label }) : /* @__PURE__ */ jsx18("span", { children: tab.label }),
3259
+ tab.badge !== void 0 && tab.badge > 0 ? /* @__PURE__ */ jsx18("span", { "aria-hidden": "true", "data-slot": "tabs-badge", className: tabsBadgeVariants(), children: formatTabBadge(tab.badge) }) : null,
3260
+ tab.disabled ? /* @__PURE__ */ jsx18(
3261
+ Lock,
3262
+ {
3263
+ "aria-hidden": "true",
3264
+ "data-slot": "tabs-disabled-icon",
3265
+ className: "size-[14px] shrink-0 text-text-disabled",
3266
+ strokeWidth: 2
3267
+ }
3268
+ ) : null
3269
+ ]
3270
+ },
3271
+ tab.key
3272
+ )),
3273
+ isLine ? /* @__PURE__ */ jsx18(
3274
+ "span",
3275
+ {
3276
+ ref: indicatorRef,
3277
+ "aria-hidden": "true",
3278
+ "data-slot": "tabs-indicator",
3279
+ className: tabsIndicatorVariants({ orientation }),
3280
+ onTransitionEnd: (event) => {
3281
+ if (event.target === event.currentTarget) delete event.currentTarget.dataset.motion;
3168
3282
  }
3169
- ) : null
3170
- ]
3171
- },
3172
- tab.key
3173
- ))
3174
- }
3175
- ),
3176
- children
3177
- ]
3178
- }
3179
- )
3283
+ }
3284
+ ) : null
3285
+ ]
3286
+ }
3287
+ ),
3288
+ children
3289
+ ]
3290
+ }
3291
+ );
3292
+ }
3180
3293
  );
3181
3294
  Tabs.displayName = "Tabs";
3182
3295
  var TabsContent = React17.forwardRef(({ className, tabKey, baseId, ...props }, ref) => /* @__PURE__ */ jsx18(
@@ -5026,6 +5139,7 @@ var chipVariants = cva10(
5026
5139
  choice: "cursor-pointer",
5027
5140
  removable: "cursor-pointer",
5028
5141
  // status-filter — 정적 표시 chip (display only, 클릭 affordance 없음).
5142
+ /** @deprecated A read-only label is a Badge: neutral·muted → `neutral`, accent → `brand`, success → `success`, warning → `warning`, danger → `error`. */
5029
5143
  "status-filter": "cursor-default"
5030
5144
  },
5031
5145
  tone: {
@@ -7867,41 +7981,30 @@ function ActionSheet({
7867
7981
 
7868
7982
  // src/components/ui/badge.tsx
7869
7983
  import * as React34 from "react";
7870
- import { jsx as jsx44, jsxs as jsxs36 } from "react/jsx-runtime";
7871
- var DOT = {
7872
- error: "var(--semantic-error-fg)",
7873
- warning: "var(--semantic-warning-fg)",
7874
- info: "var(--semantic-info-fg)",
7875
- success: "var(--semantic-success-fg)",
7876
- neutral: "var(--text-tertiary)",
7877
- brand: "var(--accent-pop)"
7984
+ import { jsx as jsx44 } from "react/jsx-runtime";
7985
+ var TONE = {
7986
+ neutral: "bg-[var(--semantic-neutral-bg)] text-[var(--semantic-neutral-fg)]",
7987
+ info: "bg-[var(--semantic-info-bg)] text-[var(--semantic-info-fg)]",
7988
+ success: "bg-[var(--semantic-success-bg)] text-[var(--semantic-success-fg)]",
7989
+ warning: "bg-[var(--semantic-warning-bg)] text-[var(--semantic-warning-fg)]",
7990
+ error: "bg-[var(--semantic-error-bg)] text-[var(--semantic-error-fg)]",
7991
+ brand: "bg-[var(--accent-bg-strong)] text-[var(--accent)]"
7878
7992
  };
7879
7993
  var Badge = React34.forwardRef(
7880
- ({ tone = "neutral", className, children, ...props }, ref) => /* @__PURE__ */ jsxs36(
7994
+ ({ tone = "neutral", className, children, ...props }, ref) => /* @__PURE__ */ jsx44(
7881
7995
  "span",
7882
7996
  {
7883
7997
  ref,
7884
7998
  "data-slot": "badge",
7885
7999
  "data-tone": tone,
7886
8000
  className: cn(
7887
- "inline-flex h-[24px] items-center gap-[var(--space-2)] rounded-[var(--radius-sm)] px-[var(--space-3)]",
7888
- "bg-[var(--bg-surface)] border border-[var(--border-subtle)] text-[var(--text-secondary)]",
8001
+ "inline-flex h-[20px] w-fit shrink-0 items-center whitespace-nowrap rounded-[var(--radius-sm)] px-[var(--space-2)]",
7889
8002
  "text-[12px] font-medium",
8003
+ TONE[tone],
7890
8004
  className
7891
8005
  ),
7892
8006
  ...props,
7893
- children: [
7894
- /* @__PURE__ */ jsx44(
7895
- "span",
7896
- {
7897
- "aria-hidden": "true",
7898
- "data-slot": "badge-dot",
7899
- className: "size-[6px] shrink-0 rounded-full",
7900
- style: { background: DOT[tone] }
7901
- }
7902
- ),
7903
- children
7904
- ]
8007
+ children
7905
8008
  }
7906
8009
  )
7907
8010
  );
@@ -7909,7 +8012,7 @@ Badge.displayName = "Badge";
7909
8012
 
7910
8013
  // src/components/ui/two-tier-badge.tsx
7911
8014
  import * as React35 from "react";
7912
- import { jsx as jsx45, jsxs as jsxs37 } from "react/jsx-runtime";
8015
+ import { jsx as jsx45, jsxs as jsxs36 } from "react/jsx-runtime";
7913
8016
  var FG = {
7914
8017
  neutral: "var(--text-secondary)",
7915
8018
  info: "var(--semantic-info-fg)",
@@ -7929,7 +8032,7 @@ var SEGMENT = {
7929
8032
  sm: "gap-[6px] py-[var(--space-1)] px-[var(--space-2)] text-[12px]",
7930
8033
  md: "gap-[7px] py-[var(--space-1)] px-[var(--space-3)] text-[14px]"
7931
8034
  };
7932
- var DOT2 = { xs: 5, sm: 6, md: 7 };
8035
+ var DOT = { xs: 5, sm: 6, md: 7 };
7933
8036
  var TwoTierBadge = React35.forwardRef(
7934
8037
  ({ primary, secondary, tone = "neutral", emphasis = "subtle", size = "sm", showDot = false, className, style, ...props }, ref) => {
7935
8038
  const strong = emphasis === "strong";
@@ -7938,8 +8041,8 @@ var TwoTierBadge = React35.forwardRef(
7938
8041
  const tinted = tone === "neutral" ? "var(--border)" : `color-mix(in srgb, ${fg} 26%, transparent)`;
7939
8042
  const frame = strong ? tinted : "var(--border-subtle)";
7940
8043
  const divider = strong ? tinted : "var(--border)";
7941
- const dotSize = DOT2[size];
7942
- return /* @__PURE__ */ jsxs37(
8044
+ const dotSize = DOT[size];
8045
+ return /* @__PURE__ */ jsxs36(
7943
8046
  "span",
7944
8047
  {
7945
8048
  ref,
@@ -7953,7 +8056,7 @@ var TwoTierBadge = React35.forwardRef(
7953
8056
  style: { fontFamily: "var(--font-sans)", borderColor: frame, background: "transparent", ...style },
7954
8057
  ...props,
7955
8058
  children: [
7956
- /* @__PURE__ */ jsxs37(
8059
+ /* @__PURE__ */ jsxs36(
7957
8060
  "span",
7958
8061
  {
7959
8062
  "data-slot": "two-tier-badge-primary",
@@ -8001,7 +8104,7 @@ TwoTierBadge.displayName = "TwoTierBadge";
8001
8104
 
8002
8105
  // src/components/ui/status-badge.tsx
8003
8106
  import * as React36 from "react";
8004
- import { jsx as jsx46, jsxs as jsxs38 } from "react/jsx-runtime";
8107
+ import { jsx as jsx46 } from "react/jsx-runtime";
8005
8108
  var ROLE = {
8006
8109
  error: "error",
8007
8110
  warning: "warning",
@@ -8011,79 +8114,58 @@ var ROLE = {
8011
8114
  success: "success",
8012
8115
  archived: "neutral"
8013
8116
  };
8014
- var FG2 = {
8015
- error: "var(--semantic-error-fg)",
8016
- warning: "var(--semantic-warning-fg)",
8017
- info: "var(--semantic-info-fg)",
8018
- success: "var(--semantic-success-fg)",
8019
- neutral: "var(--semantic-neutral-fg)"
8020
- };
8021
- var BG2 = {
8022
- error: "var(--semantic-error-bg)",
8023
- warning: "var(--semantic-warning-bg)",
8024
- info: "var(--semantic-info-bg)",
8025
- success: "var(--semantic-success-bg)",
8026
- neutral: "var(--semantic-neutral-bg)"
8027
- };
8028
- var SIZE = {
8029
- xs: { cls: "gap-[5px] py-[2px] px-[var(--space-2)] text-[12px]", dot: 5 },
8030
- sm: { cls: "gap-[6px] py-[var(--space-1)] px-[var(--space-2)] text-[12px]", dot: 6 },
8031
- md: { cls: "gap-[var(--space-2)] py-[var(--space-1)] px-[14px] text-[14px]", dot: 7 }
8032
- };
8033
8117
  var StatusBadge = React36.forwardRef(
8034
- ({ status = "active", emphasis = "subtle", size = "sm", showDot = true, pulse = true, className, children, style, ...props }, ref) => {
8035
- const role = ROLE[status];
8036
- const fg = FG2[role];
8037
- const strong = emphasis === "strong";
8038
- const ringDot = role === "neutral";
8039
- return /* @__PURE__ */ jsxs38(
8040
- "span",
8041
- {
8042
- ref,
8043
- "data-slot": "status-badge",
8044
- "data-status": status,
8045
- "data-role": role,
8046
- "data-emphasis": emphasis,
8047
- className: cn("inline-flex w-fit shrink-0 items-center whitespace-nowrap rounded-full border font-medium leading-none", SIZE[size].cls, className),
8048
- style: {
8049
- fontFamily: "var(--font-sans)",
8050
- background: strong ? BG2[role] : "transparent",
8051
- borderColor: strong ? `color-mix(in srgb, ${fg} 26%, transparent)` : "var(--border-subtle)",
8052
- color: fg,
8053
- ...style
8054
- },
8055
- ...props,
8056
- children: [
8057
- showDot ? /* @__PURE__ */ jsx46(
8058
- "span",
8059
- {
8060
- "aria-hidden": "true",
8061
- "data-slot": "status-badge-dot",
8062
- "data-ring-dot": ringDot ? "true" : "false",
8063
- "data-pulse": pulse ? "true" : "false",
8064
- className: "shrink-0 rounded-full box-border",
8065
- style: {
8066
- width: SIZE[size].dot,
8067
- height: SIZE[size].dot,
8068
- background: ringDot ? "transparent" : "currentColor",
8069
- border: ringDot ? "1.5px solid currentColor" : "none",
8070
- animation: pulse && !ringDot ? "olun-status-pulse 1.8s var(--ease-standard) infinite" : "none"
8071
- }
8072
- }
8073
- ) : null,
8074
- children,
8075
- /* @__PURE__ */ jsx46("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}}" })
8076
- ]
8077
- }
8078
- );
8079
- }
8118
+ ({ status = "active", emphasis: _emphasis, size: _size, showDot: _showDot, pulse: _pulse, ...props }, ref) => /* @__PURE__ */ jsx46(Badge, { ref, tone: ROLE[status], ...props })
8080
8119
  );
8081
8120
  StatusBadge.displayName = "StatusBadge";
8082
8121
 
8083
- // src/components/ui/notification-badge.tsx
8122
+ // src/components/ui/status-dot.tsx
8084
8123
  import * as React37 from "react";
8124
+ import { jsx as jsx47, jsxs as jsxs37 } from "react/jsx-runtime";
8125
+ var DOT2 = {
8126
+ neutral: "bg-[var(--semantic-neutral-fg)]",
8127
+ info: "bg-[var(--semantic-info-fg)]",
8128
+ success: "bg-[var(--semantic-success-fg)]",
8129
+ warning: "bg-[var(--semantic-warning-fg)]",
8130
+ error: "bg-[var(--semantic-error-fg)]"
8131
+ };
8132
+ var StatusDot = React37.forwardRef(
8133
+ ({ tone, label, pulse = false, className, ...props }, ref) => /* @__PURE__ */ jsxs37(
8134
+ "span",
8135
+ {
8136
+ ref,
8137
+ "data-slot": "status-dot",
8138
+ "data-tone": tone,
8139
+ className: cn(
8140
+ "inline-flex items-center gap-[6px] whitespace-nowrap text-[12px] font-medium text-foreground",
8141
+ className
8142
+ ),
8143
+ ...props,
8144
+ children: [
8145
+ /* @__PURE__ */ jsx47(
8146
+ "span",
8147
+ {
8148
+ "aria-hidden": "true",
8149
+ "data-slot": "status-dot-indicator",
8150
+ "data-pulse": pulse ? "true" : void 0,
8151
+ className: cn(
8152
+ "size-[6px] shrink-0 rounded-full",
8153
+ DOT2[tone],
8154
+ pulse && "motion-safe:animate-[olun-status-dot-pulse_1.6s_var(--ease-standard)_infinite]"
8155
+ )
8156
+ }
8157
+ ),
8158
+ label
8159
+ ]
8160
+ }
8161
+ )
8162
+ );
8163
+ StatusDot.displayName = "StatusDot";
8164
+
8165
+ // src/components/ui/notification-badge.tsx
8166
+ import * as React38 from "react";
8085
8167
  import { cva as cva13 } from "class-variance-authority";
8086
- import { jsx as jsx47 } from "react/jsx-runtime";
8168
+ import { jsx as jsx48 } from "react/jsx-runtime";
8087
8169
  var notificationBadgeVariants = cva13(
8088
8170
  [
8089
8171
  "inline-flex shrink-0 items-center justify-center rounded-[var(--radius-full)]",
@@ -8114,7 +8196,7 @@ function formatNotificationCount(count, max) {
8114
8196
  }
8115
8197
  return String(count);
8116
8198
  }
8117
- var NotificationBadge = React37.forwardRef(
8199
+ var NotificationBadge = React38.forwardRef(
8118
8200
  ({
8119
8201
  className,
8120
8202
  count,
@@ -8129,7 +8211,7 @@ var NotificationBadge = React37.forwardRef(
8129
8211
  }
8130
8212
  const normalizedMax = Math.max(1, Math.floor(max));
8131
8213
  const label = ariaLabel ?? (count > normalizedMax ? `\uC77D\uC9C0 \uC54A\uC740 \uC54C\uB9BC ${normalizedMax}\uAC1C \uC774\uC0C1` : `\uC77D\uC9C0 \uC54A\uC740 \uC54C\uB9BC ${count}\uAC1C`);
8132
- return /* @__PURE__ */ jsx47(
8214
+ return /* @__PURE__ */ jsx48(
8133
8215
  "span",
8134
8216
  {
8135
8217
  ref,
@@ -8147,9 +8229,9 @@ var NotificationBadge = React37.forwardRef(
8147
8229
  NotificationBadge.displayName = "NotificationBadge";
8148
8230
 
8149
8231
  // src/components/ui/empty-state.tsx
8150
- import * as React38 from "react";
8232
+ import * as React39 from "react";
8151
8233
  import { cva as cva14 } from "class-variance-authority";
8152
- import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
8234
+ import { jsx as jsx49, jsxs as jsxs38 } from "react/jsx-runtime";
8153
8235
  var emptyStateBaseVariants = cva14(
8154
8236
  [
8155
8237
  "flex flex-col items-center justify-center text-center",
@@ -8221,7 +8303,7 @@ var iconSize3 = {
8221
8303
  md: 20,
8222
8304
  lg: 24
8223
8305
  };
8224
- var EmptyState = React38.forwardRef(
8306
+ var EmptyState = React39.forwardRef(
8225
8307
  ({
8226
8308
  className,
8227
8309
  size = "md",
@@ -8236,7 +8318,7 @@ var EmptyState = React38.forwardRef(
8236
8318
  ...props
8237
8319
  }, ref) => {
8238
8320
  const resolvedSize = size ?? "md";
8239
- return /* @__PURE__ */ jsxs39(
8321
+ return /* @__PURE__ */ jsxs38(
8240
8322
  "div",
8241
8323
  {
8242
8324
  ref,
@@ -8245,17 +8327,17 @@ var EmptyState = React38.forwardRef(
8245
8327
  className: cn(emptyStateVariants({ size, tone, surface, bordered, className })),
8246
8328
  ...props,
8247
8329
  children: [
8248
- Icon ? /* @__PURE__ */ jsx48(
8330
+ Icon ? /* @__PURE__ */ jsx49(
8249
8331
  "span",
8250
8332
  {
8251
8333
  "aria-hidden": "true",
8252
8334
  "data-slot": "empty-state-icon",
8253
8335
  className: emptyStateIconVariants({ size: resolvedSize }),
8254
- children: /* @__PURE__ */ jsx48(Icon, { size: iconSize3[resolvedSize], strokeWidth: 1.75 })
8336
+ children: /* @__PURE__ */ jsx49(Icon, { size: iconSize3[resolvedSize], strokeWidth: 1.75 })
8255
8337
  }
8256
8338
  ) : null,
8257
- /* @__PURE__ */ jsxs39("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
8258
- /* @__PURE__ */ jsx48(
8339
+ /* @__PURE__ */ jsxs38("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
8340
+ /* @__PURE__ */ jsx49(
8259
8341
  "h2",
8260
8342
  {
8261
8343
  "data-slot": "empty-state-title",
@@ -8263,7 +8345,7 @@ var EmptyState = React38.forwardRef(
8263
8345
  children: title
8264
8346
  }
8265
8347
  ),
8266
- description ? /* @__PURE__ */ jsx48(
8348
+ description ? /* @__PURE__ */ jsx49(
8267
8349
  "p",
8268
8350
  {
8269
8351
  "data-slot": "empty-state-description",
@@ -8271,7 +8353,7 @@ var EmptyState = React38.forwardRef(
8271
8353
  children: description
8272
8354
  }
8273
8355
  ) : null,
8274
- hint ? /* @__PURE__ */ jsx48(
8356
+ hint ? /* @__PURE__ */ jsx49(
8275
8357
  "p",
8276
8358
  {
8277
8359
  "data-slot": "empty-state-hint",
@@ -8280,7 +8362,7 @@ var EmptyState = React38.forwardRef(
8280
8362
  }
8281
8363
  ) : null
8282
8364
  ] }),
8283
- action ? /* @__PURE__ */ jsx48("div", { "data-slot": "empty-state-action", className: "mt-[var(--space-2)]", children: action }) : null
8365
+ action ? /* @__PURE__ */ jsx49("div", { "data-slot": "empty-state-action", className: "mt-[var(--space-2)]", children: action }) : null
8284
8366
  ]
8285
8367
  }
8286
8368
  );
@@ -8289,10 +8371,10 @@ var EmptyState = React38.forwardRef(
8289
8371
  EmptyState.displayName = "EmptyState";
8290
8372
 
8291
8373
  // src/components/ui/error-state.tsx
8292
- import * as React39 from "react";
8374
+ import * as React40 from "react";
8293
8375
  import { AlertTriangle } from "lucide-react";
8294
8376
  import { cva as cva15 } from "class-variance-authority";
8295
- import { jsx as jsx49, jsxs as jsxs40 } from "react/jsx-runtime";
8377
+ import { jsx as jsx50, jsxs as jsxs39 } from "react/jsx-runtime";
8296
8378
  var errorStateVariants = cva15(
8297
8379
  [
8298
8380
  "flex flex-col items-center justify-center text-center",
@@ -8314,7 +8396,7 @@ var errorStateVariants = cva15(
8314
8396
  }
8315
8397
  }
8316
8398
  );
8317
- var ErrorState = React39.forwardRef(
8399
+ var ErrorState = React40.forwardRef(
8318
8400
  ({
8319
8401
  className,
8320
8402
  size = "md",
@@ -8325,7 +8407,7 @@ var ErrorState = React39.forwardRef(
8325
8407
  onRetry,
8326
8408
  retryLabel = "\uB2E4\uC2DC \uC2DC\uB3C4",
8327
8409
  ...props
8328
- }, ref) => /* @__PURE__ */ jsxs40(
8410
+ }, ref) => /* @__PURE__ */ jsxs39(
8329
8411
  "div",
8330
8412
  {
8331
8413
  ref,
@@ -8334,17 +8416,17 @@ var ErrorState = React39.forwardRef(
8334
8416
  className: cn(errorStateVariants({ size, surface, className })),
8335
8417
  ...props,
8336
8418
  children: [
8337
- /* @__PURE__ */ jsx49(
8419
+ /* @__PURE__ */ jsx50(
8338
8420
  "span",
8339
8421
  {
8340
8422
  "aria-hidden": "true",
8341
8423
  "data-slot": "error-state-icon",
8342
8424
  className: "inline-flex size-[48px] items-center justify-center rounded-[var(--radius-full)] bg-[var(--error-bg)] text-[var(--error)]",
8343
- children: /* @__PURE__ */ jsx49(AlertTriangle, { size: 24, strokeWidth: 1.75 })
8425
+ children: /* @__PURE__ */ jsx50(AlertTriangle, { size: 24, strokeWidth: 1.75 })
8344
8426
  }
8345
8427
  ),
8346
- /* @__PURE__ */ jsxs40("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
8347
- /* @__PURE__ */ jsx49(
8428
+ /* @__PURE__ */ jsxs39("div", { className: "flex max-w-[420px] flex-col items-center gap-[var(--space-2)]", children: [
8429
+ /* @__PURE__ */ jsx50(
8348
8430
  "h2",
8349
8431
  {
8350
8432
  "data-slot": "error-state-title",
@@ -8352,7 +8434,7 @@ var ErrorState = React39.forwardRef(
8352
8434
  children: title
8353
8435
  }
8354
8436
  ),
8355
- /* @__PURE__ */ jsx49(
8437
+ /* @__PURE__ */ jsx50(
8356
8438
  "p",
8357
8439
  {
8358
8440
  "data-slot": "error-state-message",
@@ -8360,7 +8442,7 @@ var ErrorState = React39.forwardRef(
8360
8442
  children: message
8361
8443
  }
8362
8444
  ),
8363
- errorCode ? /* @__PURE__ */ jsx49(
8445
+ errorCode ? /* @__PURE__ */ jsx50(
8364
8446
  "p",
8365
8447
  {
8366
8448
  "data-slot": "error-state-code",
@@ -8369,7 +8451,7 @@ var ErrorState = React39.forwardRef(
8369
8451
  }
8370
8452
  ) : null
8371
8453
  ] }),
8372
- onRetry ? /* @__PURE__ */ jsx49(Button, { size: "sm", variant: "secondary", onClick: onRetry, children: retryLabel }) : null
8454
+ onRetry ? /* @__PURE__ */ jsx50(Button, { size: "sm", variant: "secondary", onClick: onRetry, children: retryLabel }) : null
8373
8455
  ]
8374
8456
  }
8375
8457
  )
@@ -8377,9 +8459,9 @@ var ErrorState = React39.forwardRef(
8377
8459
  ErrorState.displayName = "ErrorState";
8378
8460
 
8379
8461
  // src/components/ui/skeleton.tsx
8380
- import * as React40 from "react";
8462
+ import * as React41 from "react";
8381
8463
  import { cva as cva16 } from "class-variance-authority";
8382
- import { jsx as jsx50 } from "react/jsx-runtime";
8464
+ import { jsx as jsx51 } from "react/jsx-runtime";
8383
8465
  var skeletonVariants = cva16(
8384
8466
  [
8385
8467
  // bg-inset: light #F1F2F4 reads on white surfaces (bg-raised was white = invisible);
@@ -8423,8 +8505,8 @@ var spinnerVariants = cva16(
8423
8505
  }
8424
8506
  }
8425
8507
  );
8426
- var Skeleton = React40.forwardRef(
8427
- ({ className, shape, style, ...props }, ref) => /* @__PURE__ */ jsx50(
8508
+ var Skeleton = React41.forwardRef(
8509
+ ({ className, shape, style, ...props }, ref) => /* @__PURE__ */ jsx51(
8428
8510
  "div",
8429
8511
  {
8430
8512
  ref,
@@ -8437,15 +8519,15 @@ var Skeleton = React40.forwardRef(
8437
8519
  );
8438
8520
  Skeleton.displayName = "Skeleton";
8439
8521
  var defaultTextWidths = ["92%", "84%", "68%", "76%"];
8440
- var SkeletonText = React40.forwardRef(
8441
- ({ className, lines = 3, widths = defaultTextWidths, ...props }, ref) => /* @__PURE__ */ jsx50(
8522
+ var SkeletonText = React41.forwardRef(
8523
+ ({ className, lines = 3, widths = defaultTextWidths, ...props }, ref) => /* @__PURE__ */ jsx51(
8442
8524
  "div",
8443
8525
  {
8444
8526
  ref,
8445
8527
  "data-slot": "skeleton-text",
8446
8528
  className: cn("flex flex-col gap-[var(--space-2)]", className),
8447
8529
  ...props,
8448
- children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx50(
8530
+ children: Array.from({ length: lines }, (_, index) => /* @__PURE__ */ jsx51(
8449
8531
  Skeleton,
8450
8532
  {
8451
8533
  shape: "text",
@@ -8457,7 +8539,7 @@ var SkeletonText = React40.forwardRef(
8457
8539
  )
8458
8540
  );
8459
8541
  SkeletonText.displayName = "SkeletonText";
8460
- var SkeletonRow = React40.forwardRef(
8542
+ var SkeletonRow = React41.forwardRef(
8461
8543
  ({
8462
8544
  className,
8463
8545
  columns,
@@ -8468,7 +8550,7 @@ var SkeletonRow = React40.forwardRef(
8468
8550
  }, ref) => {
8469
8551
  const rowCount = Math.max(5, count);
8470
8552
  const gridTemplateColumns = columns.map((column) => column.width ?? "1fr").join(" ");
8471
- return /* @__PURE__ */ jsx50(
8553
+ return /* @__PURE__ */ jsx51(
8472
8554
  "div",
8473
8555
  {
8474
8556
  ref,
@@ -8482,7 +8564,7 @@ var SkeletonRow = React40.forwardRef(
8482
8564
  className
8483
8565
  ),
8484
8566
  ...props,
8485
- children: Array.from({ length: rowCount }, (_, rowIndex) => /* @__PURE__ */ jsx50(
8567
+ children: Array.from({ length: rowCount }, (_, rowIndex) => /* @__PURE__ */ jsx51(
8486
8568
  "div",
8487
8569
  {
8488
8570
  "data-slot": "skeleton-row",
@@ -8490,11 +8572,11 @@ var SkeletonRow = React40.forwardRef(
8490
8572
  "grid min-h-[48px] items-center border-t border-[var(--border-subtle)] first:border-t-0"
8491
8573
  ),
8492
8574
  style: { gridTemplateColumns },
8493
- children: columns.map((column, columnIndex) => /* @__PURE__ */ jsx50(
8575
+ children: columns.map((column, columnIndex) => /* @__PURE__ */ jsx51(
8494
8576
  "div",
8495
8577
  {
8496
8578
  className: "px-[var(--space-4)] py-[var(--space-2)]",
8497
- children: /* @__PURE__ */ jsx50(
8579
+ children: /* @__PURE__ */ jsx51(
8498
8580
  Skeleton,
8499
8581
  {
8500
8582
  shape: "text",
@@ -8514,8 +8596,8 @@ var SkeletonRow = React40.forwardRef(
8514
8596
  }
8515
8597
  );
8516
8598
  SkeletonRow.displayName = "SkeletonRow";
8517
- var Spinner = React40.forwardRef(
8518
- ({ className, size, label = "\uB85C\uB529 \uC911", ...props }, ref) => /* @__PURE__ */ jsx50(
8599
+ var Spinner = React41.forwardRef(
8600
+ ({ className, size, label = "\uB85C\uB529 \uC911", ...props }, ref) => /* @__PURE__ */ jsx51(
8519
8601
  "span",
8520
8602
  {
8521
8603
  ref,
@@ -8530,12 +8612,12 @@ var Spinner = React40.forwardRef(
8530
8612
  Spinner.displayName = "Spinner";
8531
8613
 
8532
8614
  // src/components/ui/pagination.tsx
8533
- import * as React41 from "react";
8615
+ import * as React42 from "react";
8534
8616
  import { ChevronsLeft, ChevronLeft, ChevronRight as ChevronRight2, ChevronsRight } from "lucide-react";
8535
8617
  import { cva as cva17 } from "class-variance-authority";
8536
8618
 
8537
8619
  // src/components/ui/page-size-select.tsx
8538
- import { jsx as jsx51, jsxs as jsxs41 } from "react/jsx-runtime";
8620
+ import { jsx as jsx52, jsxs as jsxs40 } from "react/jsx-runtime";
8539
8621
  var DEFAULT_OPTIONS = [10, 20, 50, 100];
8540
8622
  function PageSizeSelect({
8541
8623
  value,
@@ -8554,7 +8636,7 @@ function PageSizeSelect({
8554
8636
  label: `${opt}${unit}`
8555
8637
  }));
8556
8638
  const selectSize = size === "compact" ? "sm" : "md";
8557
- return /* @__PURE__ */ jsxs41(
8639
+ return /* @__PURE__ */ jsxs40(
8558
8640
  "div",
8559
8641
  {
8560
8642
  "data-slot": "page-size-select",
@@ -8563,8 +8645,8 @@ function PageSizeSelect({
8563
8645
  className
8564
8646
  ),
8565
8647
  children: [
8566
- label != null ? /* @__PURE__ */ jsx51("span", { children: label }) : null,
8567
- /* @__PURE__ */ jsx51(
8648
+ label != null ? /* @__PURE__ */ jsx52("span", { children: label }) : null,
8649
+ /* @__PURE__ */ jsx52(
8568
8650
  Select,
8569
8651
  {
8570
8652
  id,
@@ -8586,7 +8668,7 @@ function PageSizeSelect({
8586
8668
  }
8587
8669
 
8588
8670
  // src/components/ui/pagination.tsx
8589
- import { jsx as jsx52, jsxs as jsxs42 } from "react/jsx-runtime";
8671
+ import { jsx as jsx53, jsxs as jsxs41 } from "react/jsx-runtime";
8590
8672
  var paginationVariants = cva17(
8591
8673
  [
8592
8674
  "flex w-full flex-col gap-[var(--space-3)]",
@@ -8659,7 +8741,7 @@ function NavigationButton({
8659
8741
  icon: Icon,
8660
8742
  onPageChange
8661
8743
  }) {
8662
- return /* @__PURE__ */ jsx52(
8744
+ return /* @__PURE__ */ jsx53(
8663
8745
  "button",
8664
8746
  {
8665
8747
  "aria-label": label,
@@ -8667,11 +8749,11 @@ function NavigationButton({
8667
8749
  className: paginationControlVariants({ size }),
8668
8750
  type: "button",
8669
8751
  onClick: () => onPageChange?.(page),
8670
- children: /* @__PURE__ */ jsx52(Icon, { "aria-hidden": "true", "data-slot": "pagination-icon" })
8752
+ children: /* @__PURE__ */ jsx53(Icon, { "aria-hidden": "true", "data-slot": "pagination-icon" })
8671
8753
  }
8672
8754
  );
8673
8755
  }
8674
- var Pagination = React41.forwardRef(
8756
+ var Pagination = React42.forwardRef(
8675
8757
  ({
8676
8758
  className,
8677
8759
  size = "standard",
@@ -8696,7 +8778,7 @@ var Pagination = React41.forwardRef(
8696
8778
  const items = getPaginationItems(currentPage, pageCount);
8697
8779
  const isFirstPage = currentPage === 1;
8698
8780
  const isLastPage = currentPage === pageCount;
8699
- return /* @__PURE__ */ jsxs42(
8781
+ return /* @__PURE__ */ jsxs41(
8700
8782
  "nav",
8701
8783
  {
8702
8784
  ref,
@@ -8706,9 +8788,9 @@ var Pagination = React41.forwardRef(
8706
8788
  className: cn(paginationVariants({ size: resolvedSize, className })),
8707
8789
  ...props,
8708
8790
  children: [
8709
- /* @__PURE__ */ jsxs42("div", { className: "flex flex-wrap items-center gap-[var(--space-3)]", children: [
8710
- /* @__PURE__ */ jsx52("span", { "data-slot": "pagination-total", className: "font-medium text-text-secondary", children: totalLabel(total) }),
8711
- showPageSize ? /* @__PURE__ */ jsx52("div", { "data-slot": "pagination-size", children: /* @__PURE__ */ jsx52(
8791
+ /* @__PURE__ */ jsxs41("div", { className: "flex flex-wrap items-center gap-[var(--space-3)]", children: [
8792
+ /* @__PURE__ */ jsx53("span", { "data-slot": "pagination-total", className: "font-medium text-text-secondary", children: totalLabel(total) }),
8793
+ showPageSize ? /* @__PURE__ */ jsx53("div", { "data-slot": "pagination-size", children: /* @__PURE__ */ jsx53(
8712
8794
  PageSizeSelect,
8713
8795
  {
8714
8796
  label: pageSizeLabel,
@@ -8720,13 +8802,13 @@ var Pagination = React41.forwardRef(
8720
8802
  }
8721
8803
  ) }) : null
8722
8804
  ] }),
8723
- /* @__PURE__ */ jsxs42(
8805
+ /* @__PURE__ */ jsxs41(
8724
8806
  "div",
8725
8807
  {
8726
8808
  "data-slot": "pagination-list",
8727
8809
  className: "flex items-center justify-center gap-[var(--space-1)]",
8728
8810
  children: [
8729
- /* @__PURE__ */ jsx52(
8811
+ /* @__PURE__ */ jsx53(
8730
8812
  NavigationButton,
8731
8813
  {
8732
8814
  label: "\uCCAB \uD398\uC774\uC9C0",
@@ -8737,7 +8819,7 @@ var Pagination = React41.forwardRef(
8737
8819
  onPageChange
8738
8820
  }
8739
8821
  ),
8740
- /* @__PURE__ */ jsx52(
8822
+ /* @__PURE__ */ jsx53(
8741
8823
  NavigationButton,
8742
8824
  {
8743
8825
  label: "\uC774\uC804 \uD398\uC774\uC9C0",
@@ -8749,7 +8831,7 @@ var Pagination = React41.forwardRef(
8749
8831
  }
8750
8832
  ),
8751
8833
  items.map(
8752
- (item, index) => item === "ellipsis" ? /* @__PURE__ */ jsx52(
8834
+ (item, index) => item === "ellipsis" ? /* @__PURE__ */ jsx53(
8753
8835
  "span",
8754
8836
  {
8755
8837
  "data-slot": "pagination-ellipsis",
@@ -8761,7 +8843,7 @@ var Pagination = React41.forwardRef(
8761
8843
  children: "..."
8762
8844
  },
8763
8845
  `ellipsis-${index}`
8764
- ) : /* @__PURE__ */ jsx52(
8846
+ ) : /* @__PURE__ */ jsx53(
8765
8847
  "button",
8766
8848
  {
8767
8849
  "aria-label": `${item} \uD398\uC774\uC9C0`,
@@ -8775,7 +8857,7 @@ var Pagination = React41.forwardRef(
8775
8857
  item
8776
8858
  )
8777
8859
  ),
8778
- /* @__PURE__ */ jsx52(
8860
+ /* @__PURE__ */ jsx53(
8779
8861
  NavigationButton,
8780
8862
  {
8781
8863
  label: "\uB2E4\uC74C \uD398\uC774\uC9C0",
@@ -8786,7 +8868,7 @@ var Pagination = React41.forwardRef(
8786
8868
  onPageChange
8787
8869
  }
8788
8870
  ),
8789
- /* @__PURE__ */ jsx52(
8871
+ /* @__PURE__ */ jsx53(
8790
8872
  NavigationButton,
8791
8873
  {
8792
8874
  label: "\uB9C8\uC9C0\uB9C9 \uD398\uC774\uC9C0",
@@ -8809,7 +8891,7 @@ Pagination.displayName = "Pagination";
8809
8891
 
8810
8892
  // src/components/ui/mode-toggle.tsx
8811
8893
  import { cva as cva18 } from "class-variance-authority";
8812
- import { jsx as jsx53, jsxs as jsxs43 } from "react/jsx-runtime";
8894
+ import { jsx as jsx54, jsxs as jsxs42 } from "react/jsx-runtime";
8813
8895
  var modeToggleVariants = cva18(
8814
8896
  [
8815
8897
  "inline-flex items-center rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -8839,7 +8921,7 @@ function ModeToggle({
8839
8921
  onChange,
8840
8922
  ...props
8841
8923
  }) {
8842
- return /* @__PURE__ */ jsx53(
8924
+ return /* @__PURE__ */ jsx54(
8843
8925
  "div",
8844
8926
  {
8845
8927
  role: "group",
@@ -8849,7 +8931,7 @@ function ModeToggle({
8849
8931
  children: options.map((option) => {
8850
8932
  const Icon = option.icon;
8851
8933
  const isActive = option.value === value;
8852
- return /* @__PURE__ */ jsxs43(
8934
+ return /* @__PURE__ */ jsxs42(
8853
8935
  "button",
8854
8936
  {
8855
8937
  type: "button",
@@ -8865,8 +8947,8 @@ function ModeToggle({
8865
8947
  }
8866
8948
  },
8867
8949
  children: [
8868
- Icon ? /* @__PURE__ */ jsx53(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
8869
- /* @__PURE__ */ jsx53("span", { children: option.label })
8950
+ Icon ? /* @__PURE__ */ jsx54(Icon, { "aria-hidden": "true", "data-slot": "mode-toggle-icon" }) : null,
8951
+ /* @__PURE__ */ jsx54("span", { children: option.label })
8870
8952
  ]
8871
8953
  },
8872
8954
  option.value
@@ -8877,9 +8959,9 @@ function ModeToggle({
8877
8959
  }
8878
8960
 
8879
8961
  // src/components/ui/action-footer.tsx
8880
- import * as React42 from "react";
8962
+ import * as React43 from "react";
8881
8963
  import { cva as cva19 } from "class-variance-authority";
8882
- import { jsx as jsx54, jsxs as jsxs44 } from "react/jsx-runtime";
8964
+ import { jsx as jsx55, jsxs as jsxs43 } from "react/jsx-runtime";
8883
8965
  var actionFooterVariants = cva19(
8884
8966
  [
8885
8967
  "flex flex-wrap items-center gap-[var(--space-4)] border-t border-[var(--border-subtle)]",
@@ -8950,7 +9032,7 @@ function getStatusLabel(status) {
8950
9032
  }
8951
9033
  }
8952
9034
  function renderAction(action) {
8953
- return /* @__PURE__ */ jsx54(
9035
+ return /* @__PURE__ */ jsx55(
8954
9036
  Button,
8955
9037
  {
8956
9038
  variant: action.variant,
@@ -8965,7 +9047,7 @@ function renderAction(action) {
8965
9047
  action.id ?? action.label
8966
9048
  );
8967
9049
  }
8968
- var ActionFooter = React42.forwardRef(
9050
+ var ActionFooter = React43.forwardRef(
8969
9051
  ({
8970
9052
  className,
8971
9053
  status,
@@ -8982,7 +9064,7 @@ var ActionFooter = React42.forwardRef(
8982
9064
  const mainActions = sortMainActions(
8983
9065
  visibleActions.filter((action) => !destructiveVariants.has(action.variant ?? "default"))
8984
9066
  );
8985
- return /* @__PURE__ */ jsxs44(
9067
+ return /* @__PURE__ */ jsxs43(
8986
9068
  "div",
8987
9069
  {
8988
9070
  ref,
@@ -8991,7 +9073,7 @@ var ActionFooter = React42.forwardRef(
8991
9073
  className: cn(actionFooterVariants({ position, surface, className })),
8992
9074
  ...props,
8993
9075
  children: [
8994
- destructiveActions.length > 0 ? /* @__PURE__ */ jsx54(
9076
+ destructiveActions.length > 0 ? /* @__PURE__ */ jsx55(
8995
9077
  "div",
8996
9078
  {
8997
9079
  "data-slot": "action-footer-destructive-actions",
@@ -8999,7 +9081,7 @@ var ActionFooter = React42.forwardRef(
8999
9081
  children: destructiveActions.map(renderAction)
9000
9082
  }
9001
9083
  ) : null,
9002
- status ? /* @__PURE__ */ jsxs44(
9084
+ status ? /* @__PURE__ */ jsxs43(
9003
9085
  "div",
9004
9086
  {
9005
9087
  "data-slot": "action-footer-status",
@@ -9007,7 +9089,7 @@ var ActionFooter = React42.forwardRef(
9007
9089
  "aria-live": "polite",
9008
9090
  className: cn(actionFooterStatusVariants({ kind: status.kind })),
9009
9091
  children: [
9010
- /* @__PURE__ */ jsx54(
9092
+ /* @__PURE__ */ jsx55(
9011
9093
  "span",
9012
9094
  {
9013
9095
  "aria-hidden": "true",
@@ -9015,11 +9097,11 @@ var ActionFooter = React42.forwardRef(
9015
9097
  className: "size-[6px] shrink-0 rounded-[var(--radius-full)]"
9016
9098
  }
9017
9099
  ),
9018
- /* @__PURE__ */ jsx54("span", { className: "truncate", children: getStatusLabel(status) })
9100
+ /* @__PURE__ */ jsx55("span", { className: "truncate", children: getStatusLabel(status) })
9019
9101
  ]
9020
9102
  }
9021
9103
  ) : null,
9022
- /* @__PURE__ */ jsx54(
9104
+ /* @__PURE__ */ jsx55(
9023
9105
  "div",
9024
9106
  {
9025
9107
  "data-slot": "action-footer-main-actions",
@@ -9035,9 +9117,9 @@ var ActionFooter = React42.forwardRef(
9035
9117
  ActionFooter.displayName = "ActionFooter";
9036
9118
 
9037
9119
  // src/components/ui/toast.tsx
9038
- import * as React43 from "react";
9120
+ import * as React44 from "react";
9039
9121
  import { cva as cva20 } from "class-variance-authority";
9040
- import { jsx as jsx55, jsxs as jsxs45 } from "react/jsx-runtime";
9122
+ import { jsx as jsx56, jsxs as jsxs44 } from "react/jsx-runtime";
9041
9123
  var DOT3 = {
9042
9124
  default: "var(--neutral)",
9043
9125
  success: "var(--success)",
@@ -9155,7 +9237,7 @@ var toast = {
9155
9237
  }
9156
9238
  };
9157
9239
  var Toast = toast;
9158
- var ToastRoot = React43.forwardRef(
9240
+ var ToastRoot = React44.forwardRef(
9159
9241
  ({
9160
9242
  className,
9161
9243
  id,
@@ -9172,10 +9254,10 @@ var ToastRoot = React43.forwardRef(
9172
9254
  ...props
9173
9255
  }, ref) => {
9174
9256
  const durationMs = getToastDuration({ message, variant, duration });
9175
- const onCloseRef = React43.useRef(onClose);
9257
+ const onCloseRef = React44.useRef(onClose);
9176
9258
  onCloseRef.current = onClose;
9177
- const timerRef = React43.useRef(null);
9178
- React43.useEffect(() => {
9259
+ const timerRef = React44.useRef(null);
9260
+ React44.useEffect(() => {
9179
9261
  if (!onCloseRef.current) return void 0;
9180
9262
  const timer = createToastTimer(durationMs, () => onCloseRef.current?.());
9181
9263
  timerRef.current = timer;
@@ -9184,7 +9266,7 @@ var ToastRoot = React43.forwardRef(
9184
9266
  timerRef.current = null;
9185
9267
  };
9186
9268
  }, [durationMs]);
9187
- return /* @__PURE__ */ jsxs45(
9269
+ return /* @__PURE__ */ jsxs44(
9188
9270
  "div",
9189
9271
  {
9190
9272
  ref,
@@ -9212,7 +9294,7 @@ var ToastRoot = React43.forwardRef(
9212
9294
  },
9213
9295
  ...props,
9214
9296
  children: [
9215
- /* @__PURE__ */ jsx55(
9297
+ /* @__PURE__ */ jsx56(
9216
9298
  "span",
9217
9299
  {
9218
9300
  "aria-hidden": "true",
@@ -9221,8 +9303,8 @@ var ToastRoot = React43.forwardRef(
9221
9303
  style: { background: DOT3[variant] ?? DOT3.default }
9222
9304
  }
9223
9305
  ),
9224
- /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
9225
- /* @__PURE__ */ jsx55(
9306
+ /* @__PURE__ */ jsxs44("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
9307
+ /* @__PURE__ */ jsx56(
9226
9308
  "div",
9227
9309
  {
9228
9310
  "data-slot": "toast-message",
@@ -9230,7 +9312,7 @@ var ToastRoot = React43.forwardRef(
9230
9312
  children: message
9231
9313
  }
9232
9314
  ),
9233
- description ? /* @__PURE__ */ jsx55(
9315
+ description ? /* @__PURE__ */ jsx56(
9234
9316
  "div",
9235
9317
  {
9236
9318
  "data-slot": "toast-description",
@@ -9239,8 +9321,8 @@ var ToastRoot = React43.forwardRef(
9239
9321
  }
9240
9322
  ) : null
9241
9323
  ] }),
9242
- /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
9243
- action ? /* @__PURE__ */ jsx55(
9324
+ /* @__PURE__ */ jsxs44("div", { "data-slot": "toast-actions", className: "flex shrink-0 items-center gap-[2px]", children: [
9325
+ action ? /* @__PURE__ */ jsx56(
9244
9326
  Button,
9245
9327
  {
9246
9328
  "data-slot": "toast-action",
@@ -9250,7 +9332,7 @@ var ToastRoot = React43.forwardRef(
9250
9332
  children: action.label
9251
9333
  }
9252
9334
  ) : null,
9253
- /* @__PURE__ */ jsx55(
9335
+ /* @__PURE__ */ jsx56(
9254
9336
  "button",
9255
9337
  {
9256
9338
  type: "button",
@@ -9272,7 +9354,7 @@ var ToastRoot = React43.forwardRef(
9272
9354
  }
9273
9355
  );
9274
9356
  ToastRoot.displayName = "ToastRoot";
9275
- var ToastViewport = React43.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
9357
+ var ToastViewport = React44.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx56(
9276
9358
  "ol",
9277
9359
  {
9278
9360
  ref,
@@ -9283,24 +9365,24 @@ var ToastViewport = React43.forwardRef(({ className, ...props }, ref) => /* @__P
9283
9365
  ));
9284
9366
  ToastViewport.displayName = "ToastViewport";
9285
9367
  function ToastProvider({ children, maxToasts = 3, className, ...props }) {
9286
- const [items, setItems] = React43.useState([]);
9287
- React43.useEffect(
9368
+ const [items, setItems] = React44.useState([]);
9369
+ React44.useEffect(
9288
9370
  () => toast.subscribe((nextItems) => {
9289
9371
  setItems(limitToasts(nextItems, maxToasts));
9290
9372
  }),
9291
9373
  [maxToasts]
9292
9374
  );
9293
- return /* @__PURE__ */ jsxs45("div", { "data-slot": "toast-provider", className, ...props, children: [
9375
+ return /* @__PURE__ */ jsxs44("div", { "data-slot": "toast-provider", className, ...props, children: [
9294
9376
  children,
9295
- /* @__PURE__ */ jsx55(ToastViewport, { children: items.map((item) => /* @__PURE__ */ jsx55("li", { children: /* @__PURE__ */ jsx55(ToastRoot, { ...item, onClose: () => toast.dismiss(item.id) }) }, item.id)) })
9377
+ /* @__PURE__ */ jsx56(ToastViewport, { children: items.map((item) => /* @__PURE__ */ jsx56("li", { children: /* @__PURE__ */ jsx56(ToastRoot, { ...item, onClose: () => toast.dismiss(item.id) }) }, item.id)) })
9296
9378
  ] });
9297
9379
  }
9298
9380
 
9299
9381
  // src/components/ui/otp-field.tsx
9300
- import * as React44 from "react";
9382
+ import * as React45 from "react";
9301
9383
  import { cva as cva21 } from "class-variance-authority";
9302
9384
  import { AlertCircle as AlertCircle4 } from "lucide-react";
9303
- import { Fragment as Fragment12, jsx as jsx56, jsxs as jsxs46 } from "react/jsx-runtime";
9385
+ import { Fragment as Fragment12, jsx as jsx57, jsxs as jsxs45 } from "react/jsx-runtime";
9304
9386
  var otpFieldVariants = cva21("flex w-full min-w-0 flex-col gap-[var(--space-3)]", {
9305
9387
  variants: {
9306
9388
  size: {
@@ -9427,7 +9509,7 @@ function fillDigitsFromIndex(slots, index, inserted, length) {
9427
9509
  focusIndex: Math.min(cursor, length - 1)
9428
9510
  };
9429
9511
  }
9430
- var OTPField = React44.forwardRef(
9512
+ var OTPField = React45.forwardRef(
9431
9513
  ({
9432
9514
  className,
9433
9515
  defaultValue,
@@ -9449,24 +9531,24 @@ var OTPField = React44.forwardRef(
9449
9531
  required,
9450
9532
  ...props
9451
9533
  }, ref) => {
9452
- const generatedId = React44.useId();
9534
+ const generatedId = React45.useId();
9453
9535
  const fieldId = id ?? generatedId;
9454
9536
  const labelId = `${fieldId}-label`;
9455
9537
  const helperId = helperText ? `${fieldId}-helper` : void 0;
9456
9538
  const errorId = errorText ? `${fieldId}-error` : void 0;
9457
9539
  const resolvedState = invalid || errorText ? "error" : "default";
9458
9540
  const isControlled = value !== void 0;
9459
- const [uncontrolledSlots, setUncontrolledSlots] = React44.useState(
9541
+ const [uncontrolledSlots, setUncontrolledSlots] = React45.useState(
9460
9542
  () => toDigitsArray(onlyDigits(defaultValue, length), length)
9461
9543
  );
9462
- const resolvedSlots = React44.useMemo(
9544
+ const resolvedSlots = React45.useMemo(
9463
9545
  () => isControlled ? toDigitsArray(onlyDigits(value, length), length) : uncontrolledSlots,
9464
9546
  [isControlled, length, uncontrolledSlots, value]
9465
9547
  );
9466
9548
  const resolvedValue = joinDigits(resolvedSlots).slice(0, length);
9467
- const cellsRef = React44.useRef([]);
9549
+ const cellsRef = React45.useRef([]);
9468
9550
  const groupDescribedBy = [helperId, errorId].filter(Boolean).join(" ") || void 0;
9469
- const setResolvedValue = React44.useCallback(
9551
+ const setResolvedValue = React45.useCallback(
9470
9552
  (nextSlots, focusIndex) => {
9471
9553
  const normalizedSlots = nextSlots.slice(0, length);
9472
9554
  const normalizedValue = joinDigits(normalizedSlots).slice(0, length);
@@ -9485,7 +9567,7 @@ var OTPField = React44.forwardRef(
9485
9567
  },
9486
9568
  [disabled, isControlled, length, onComplete, onValueChange]
9487
9569
  );
9488
- return /* @__PURE__ */ jsxs46(
9570
+ return /* @__PURE__ */ jsxs45(
9489
9571
  "fieldset",
9490
9572
  {
9491
9573
  ref,
@@ -9498,7 +9580,7 @@ var OTPField = React44.forwardRef(
9498
9580
  className: cn(otpFieldVariants({ size, className })),
9499
9581
  ...props,
9500
9582
  children: [
9501
- /* @__PURE__ */ jsxs46(
9583
+ /* @__PURE__ */ jsxs45(
9502
9584
  "legend",
9503
9585
  {
9504
9586
  id: labelId,
@@ -9506,11 +9588,11 @@ var OTPField = React44.forwardRef(
9506
9588
  className: "text-sm font-medium leading-snug text-foreground",
9507
9589
  children: [
9508
9590
  label,
9509
- required ? /* @__PURE__ */ jsx56("span", { "aria-hidden": "true", className: "ml-1 font-bold text-[var(--error)]", children: "*" }) : null
9591
+ required ? /* @__PURE__ */ jsx57("span", { "aria-hidden": "true", className: "ml-1 font-bold text-[var(--error)]", children: "*" }) : null
9510
9592
  ]
9511
9593
  }
9512
9594
  ),
9513
- /* @__PURE__ */ jsx56(
9595
+ /* @__PURE__ */ jsx57(
9514
9596
  "div",
9515
9597
  {
9516
9598
  "data-slot": "otp-field-group",
@@ -9520,7 +9602,7 @@ var OTPField = React44.forwardRef(
9520
9602
  children: Array.from({ length }, (_, index) => {
9521
9603
  const digit = resolvedSlots[index] ?? "";
9522
9604
  const inputId = `${fieldId}-cell-${index + 1}`;
9523
- return /* @__PURE__ */ jsx56(
9605
+ return /* @__PURE__ */ jsx57(
9524
9606
  "input",
9525
9607
  {
9526
9608
  ref: (node) => {
@@ -9615,15 +9697,15 @@ var OTPField = React44.forwardRef(
9615
9697
  })
9616
9698
  }
9617
9699
  ),
9618
- helperText || errorText ? /* @__PURE__ */ jsx56(
9700
+ helperText || errorText ? /* @__PURE__ */ jsx57(
9619
9701
  "p",
9620
9702
  {
9621
9703
  id: errorText ? errorId : helperId,
9622
9704
  "data-slot": "otp-field-message",
9623
9705
  "data-kind": errorText ? "error" : "helper",
9624
9706
  className: otpFieldMessageVariants({ state: resolvedState }),
9625
- children: errorText ? /* @__PURE__ */ jsxs46(Fragment12, { children: [
9626
- /* @__PURE__ */ jsx56(
9707
+ children: errorText ? /* @__PURE__ */ jsxs45(Fragment12, { children: [
9708
+ /* @__PURE__ */ jsx57(
9627
9709
  AlertCircle4,
9628
9710
  {
9629
9711
  "aria-hidden": "true",
@@ -9631,11 +9713,11 @@ var OTPField = React44.forwardRef(
9631
9713
  strokeWidth: 2
9632
9714
  }
9633
9715
  ),
9634
- /* @__PURE__ */ jsx56("span", { children: errorText })
9635
- ] }) : /* @__PURE__ */ jsx56("span", { children: helperText })
9716
+ /* @__PURE__ */ jsx57("span", { children: errorText })
9717
+ ] }) : /* @__PURE__ */ jsx57("span", { children: helperText })
9636
9718
  }
9637
9719
  ) : null,
9638
- name ? /* @__PURE__ */ jsx56(
9720
+ name ? /* @__PURE__ */ jsx57(
9639
9721
  "input",
9640
9722
  {
9641
9723
  "aria-hidden": "true",
@@ -9656,10 +9738,10 @@ var OTPField = React44.forwardRef(
9656
9738
  OTPField.displayName = "OTPField";
9657
9739
 
9658
9740
  // src/components/ui/search-field.tsx
9659
- import * as React45 from "react";
9741
+ import * as React46 from "react";
9660
9742
  import { Search, X as X4 } from "lucide-react";
9661
9743
  import { cva as cva22 } from "class-variance-authority";
9662
- import { jsx as jsx57, jsxs as jsxs47 } from "react/jsx-runtime";
9744
+ import { jsx as jsx58, jsxs as jsxs46 } from "react/jsx-runtime";
9663
9745
  var searchFieldVariants = cva22("relative flex w-full items-center", {
9664
9746
  variants: {
9665
9747
  size: {
@@ -9724,7 +9806,7 @@ var iconSize4 = {
9724
9806
  function hasVisibleValue(value) {
9725
9807
  return typeof value === "string" ? value.length > 0 : value !== void 0;
9726
9808
  }
9727
- var SearchField = React45.forwardRef(
9809
+ var SearchField = React46.forwardRef(
9728
9810
  ({
9729
9811
  className,
9730
9812
  inputMode = "search",
@@ -9740,12 +9822,12 @@ var SearchField = React45.forwardRef(
9740
9822
  ...props
9741
9823
  }, ref) => {
9742
9824
  const resolvedSize = size ?? "md";
9743
- const inputRef = React45.useRef(null);
9744
- const [hasText, setHasText] = React45.useState(
9825
+ const inputRef = React46.useRef(null);
9826
+ const [hasText, setHasText] = React46.useState(
9745
9827
  () => hasVisibleValue(value ?? defaultValue)
9746
9828
  );
9747
- React45.useImperativeHandle(ref, () => inputRef.current);
9748
- React45.useEffect(() => {
9829
+ React46.useImperativeHandle(ref, () => inputRef.current);
9830
+ React46.useEffect(() => {
9749
9831
  if (value !== void 0) {
9750
9832
  setHasText(hasVisibleValue(value));
9751
9833
  }
@@ -9758,14 +9840,14 @@ var SearchField = React45.forwardRef(
9758
9840
  }
9759
9841
  onClear?.();
9760
9842
  };
9761
- return /* @__PURE__ */ jsxs47(
9843
+ return /* @__PURE__ */ jsxs46(
9762
9844
  "div",
9763
9845
  {
9764
9846
  "data-slot": "search-field",
9765
9847
  "data-size": resolvedSize,
9766
9848
  className: cn(searchFieldVariants({ size, className })),
9767
9849
  children: [
9768
- /* @__PURE__ */ jsx57(
9850
+ /* @__PURE__ */ jsx58(
9769
9851
  Search,
9770
9852
  {
9771
9853
  "aria-hidden": "true",
@@ -9775,7 +9857,7 @@ var SearchField = React45.forwardRef(
9775
9857
  strokeWidth: resolvedSize === "sm" ? 2 : 1.75
9776
9858
  }
9777
9859
  ),
9778
- /* @__PURE__ */ jsx57(
9860
+ /* @__PURE__ */ jsx58(
9779
9861
  "input",
9780
9862
  {
9781
9863
  ref: inputRef,
@@ -9796,7 +9878,7 @@ var SearchField = React45.forwardRef(
9796
9878
  ...props
9797
9879
  }
9798
9880
  ),
9799
- showClear ? /* @__PURE__ */ jsx57(
9881
+ showClear ? /* @__PURE__ */ jsx58(
9800
9882
  "button",
9801
9883
  {
9802
9884
  type: "button",
@@ -9804,7 +9886,7 @@ var SearchField = React45.forwardRef(
9804
9886
  "data-slot": "search-field-clear",
9805
9887
  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)]",
9806
9888
  onClick: clearInput,
9807
- children: /* @__PURE__ */ jsx57(X4, { "aria-hidden": "true", size: 16, strokeWidth: 1.75 })
9889
+ children: /* @__PURE__ */ jsx58(X4, { "aria-hidden": "true", size: 16, strokeWidth: 1.75 })
9808
9890
  }
9809
9891
  ) : null
9810
9892
  ]
@@ -9815,9 +9897,9 @@ var SearchField = React45.forwardRef(
9815
9897
  SearchField.displayName = "SearchField";
9816
9898
 
9817
9899
  // src/components/ui/checkbox-group.tsx
9818
- import * as React46 from "react";
9900
+ import * as React47 from "react";
9819
9901
  import { cva as cva23 } from "class-variance-authority";
9820
- import { jsx as jsx58 } from "react/jsx-runtime";
9902
+ import { jsx as jsx59 } from "react/jsx-runtime";
9821
9903
  var checkboxGroupVariants = cva23("gap-[var(--space-2)]", {
9822
9904
  variants: {
9823
9905
  appearance: {
@@ -9843,7 +9925,7 @@ var checkboxGroupVariants = cva23("gap-[var(--space-2)]", {
9843
9925
  function toSelectionSet(value) {
9844
9926
  return new Set(value ?? []);
9845
9927
  }
9846
- var CheckboxGroup = React46.forwardRef(
9928
+ var CheckboxGroup = React47.forwardRef(
9847
9929
  ({
9848
9930
  className,
9849
9931
  children,
@@ -9859,14 +9941,14 @@ var CheckboxGroup = React46.forwardRef(
9859
9941
  ...props
9860
9942
  }, ref) => {
9861
9943
  const isControlled = value != null;
9862
- const [uncontrolledValue, setUncontrolledValue] = React46.useState(
9944
+ const [uncontrolledValue, setUncontrolledValue] = React47.useState(
9863
9945
  () => toSelectionSet(defaultValue)
9864
9946
  );
9865
- const selectedValues = React46.useMemo(
9947
+ const selectedValues = React47.useMemo(
9866
9948
  () => isControlled ? toSelectionSet(value) : uncontrolledValue,
9867
9949
  [isControlled, uncontrolledValue, value]
9868
9950
  );
9869
- const toggleValue = React46.useCallback(
9951
+ const toggleValue = React47.useCallback(
9870
9952
  (itemValue, checked) => {
9871
9953
  const nextValues = new Set(selectedValues);
9872
9954
  if (checked) {
@@ -9882,7 +9964,7 @@ var CheckboxGroup = React46.forwardRef(
9882
9964
  },
9883
9965
  [isControlled, onValueChange, selectedValues]
9884
9966
  );
9885
- const contextValue = React46.useMemo(
9967
+ const contextValue = React47.useMemo(
9886
9968
  () => ({
9887
9969
  appearance,
9888
9970
  density,
@@ -9893,7 +9975,7 @@ var CheckboxGroup = React46.forwardRef(
9893
9975
  }),
9894
9976
  [appearance, density, disabled, name, selectedValues, toggleValue]
9895
9977
  );
9896
- return /* @__PURE__ */ jsx58(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx58(
9978
+ return /* @__PURE__ */ jsx59(CheckboxGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx59(
9897
9979
  "div",
9898
9980
  {
9899
9981
  ref,
@@ -9917,11 +9999,11 @@ var CheckboxGroup = React46.forwardRef(
9917
9999
  CheckboxGroup.displayName = "CheckboxGroup";
9918
10000
 
9919
10001
  // src/components/ui/radio-group.tsx
9920
- import * as React47 from "react";
10002
+ import * as React48 from "react";
9921
10003
  import { cva as cva24 } from "class-variance-authority";
9922
10004
  import { Circle } from "lucide-react";
9923
10005
  import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
9924
- import { jsx as jsx59, jsxs as jsxs48 } from "react/jsx-runtime";
10006
+ import { jsx as jsx60, jsxs as jsxs47 } from "react/jsx-runtime";
9925
10007
  var radioGroupVariants = cva24("gap-[var(--space-2)]", {
9926
10008
  variants: {
9927
10009
  appearance: {
@@ -10010,11 +10092,11 @@ var radioControlVariants = cva24(
10010
10092
  }
10011
10093
  }
10012
10094
  );
10013
- var RadioGroupContext = React47.createContext({
10095
+ var RadioGroupContext = React48.createContext({
10014
10096
  appearance: "plain",
10015
10097
  density: "comfortable"
10016
10098
  });
10017
- var RadioGroup = React47.forwardRef(
10099
+ var RadioGroup = React48.forwardRef(
10018
10100
  ({
10019
10101
  className,
10020
10102
  children,
@@ -10025,11 +10107,11 @@ var RadioGroup = React47.forwardRef(
10025
10107
  required,
10026
10108
  ...props
10027
10109
  }, ref) => {
10028
- const contextValue = React47.useMemo(
10110
+ const contextValue = React48.useMemo(
10029
10111
  () => ({ appearance, density }),
10030
10112
  [appearance, density]
10031
10113
  );
10032
- return /* @__PURE__ */ jsx59(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx59(
10114
+ return /* @__PURE__ */ jsx60(RadioGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx60(
10033
10115
  RadioGroupPrimitive.Root,
10034
10116
  {
10035
10117
  ref,
@@ -10052,13 +10134,13 @@ var RadioGroup = React47.forwardRef(
10052
10134
  }
10053
10135
  );
10054
10136
  RadioGroup.displayName = "RadioGroup";
10055
- var Radio = React47.forwardRef(({ className, children, description, id, ...props }, ref) => {
10056
- const { appearance, density } = React47.useContext(RadioGroupContext);
10057
- const generatedId = React47.useId();
10137
+ var Radio = React48.forwardRef(({ className, children, description, id, ...props }, ref) => {
10138
+ const { appearance, density } = React48.useContext(RadioGroupContext);
10139
+ const generatedId = React48.useId();
10058
10140
  const radioId = id ?? generatedId;
10059
10141
  const labelId = `${radioId}-label`;
10060
10142
  const descriptionId = description ? `${radioId}-description` : void 0;
10061
- return /* @__PURE__ */ jsxs48(
10143
+ return /* @__PURE__ */ jsxs47(
10062
10144
  RadioGroupPrimitive.Item,
10063
10145
  {
10064
10146
  ref,
@@ -10069,24 +10151,24 @@ var Radio = React47.forwardRef(({ className, children, description, id, ...props
10069
10151
  className: cn(radioVariants({ appearance, density }), className),
10070
10152
  ...props,
10071
10153
  children: [
10072
- /* @__PURE__ */ jsx59(
10154
+ /* @__PURE__ */ jsx60(
10073
10155
  "span",
10074
10156
  {
10075
10157
  "aria-hidden": "true",
10076
10158
  "data-slot": "radio-control",
10077
10159
  className: radioControlVariants({ appearance }),
10078
- children: /* @__PURE__ */ jsx59(
10160
+ children: /* @__PURE__ */ jsx60(
10079
10161
  RadioGroupPrimitive.Indicator,
10080
10162
  {
10081
10163
  "data-slot": "radio-indicator",
10082
10164
  className: "flex items-center justify-center",
10083
- children: /* @__PURE__ */ jsx59(Circle, { "aria-hidden": "true", size: 8, fill: "currentColor" })
10165
+ children: /* @__PURE__ */ jsx60(Circle, { "aria-hidden": "true", size: 8, fill: "currentColor" })
10084
10166
  }
10085
10167
  )
10086
10168
  }
10087
10169
  ),
10088
- /* @__PURE__ */ jsxs48("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
10089
- /* @__PURE__ */ jsx59(
10170
+ /* @__PURE__ */ jsxs47("span", { className: "flex min-w-0 flex-col gap-[var(--space-1)]", children: [
10171
+ /* @__PURE__ */ jsx60(
10090
10172
  "span",
10091
10173
  {
10092
10174
  id: labelId,
@@ -10098,7 +10180,7 @@ var Radio = React47.forwardRef(({ className, children, description, id, ...props
10098
10180
  children
10099
10181
  }
10100
10182
  ),
10101
- description ? /* @__PURE__ */ jsx59(
10183
+ description ? /* @__PURE__ */ jsx60(
10102
10184
  "span",
10103
10185
  {
10104
10186
  id: descriptionId,
@@ -10116,20 +10198,20 @@ Radio.displayName = "Radio";
10116
10198
 
10117
10199
  // src/components/ui/scroll-area.tsx
10118
10200
  import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
10119
- import { jsx as jsx60, jsxs as jsxs49 } from "react/jsx-runtime";
10201
+ import { jsx as jsx61, jsxs as jsxs48 } from "react/jsx-runtime";
10120
10202
  function ScrollArea({
10121
10203
  className,
10122
10204
  children,
10123
10205
  ...props
10124
10206
  }) {
10125
- return /* @__PURE__ */ jsxs49(
10207
+ return /* @__PURE__ */ jsxs48(
10126
10208
  ScrollAreaPrimitive.Root,
10127
10209
  {
10128
10210
  "data-slot": "scroll-area",
10129
10211
  className: cn("relative", className),
10130
10212
  ...props,
10131
10213
  children: [
10132
- /* @__PURE__ */ jsx60(
10214
+ /* @__PURE__ */ jsx61(
10133
10215
  ScrollAreaPrimitive.Viewport,
10134
10216
  {
10135
10217
  "data-slot": "scroll-area-viewport",
@@ -10137,8 +10219,8 @@ function ScrollArea({
10137
10219
  children
10138
10220
  }
10139
10221
  ),
10140
- /* @__PURE__ */ jsx60(ScrollBar, {}),
10141
- /* @__PURE__ */ jsx60(ScrollAreaPrimitive.Corner, {})
10222
+ /* @__PURE__ */ jsx61(ScrollBar, {}),
10223
+ /* @__PURE__ */ jsx61(ScrollAreaPrimitive.Corner, {})
10142
10224
  ]
10143
10225
  }
10144
10226
  );
@@ -10148,7 +10230,7 @@ function ScrollBar({
10148
10230
  orientation = "vertical",
10149
10231
  ...props
10150
10232
  }) {
10151
- return /* @__PURE__ */ jsx60(
10233
+ return /* @__PURE__ */ jsx61(
10152
10234
  ScrollAreaPrimitive.ScrollAreaScrollbar,
10153
10235
  {
10154
10236
  "data-slot": "scroll-area-scrollbar",
@@ -10160,7 +10242,7 @@ function ScrollBar({
10160
10242
  className
10161
10243
  ),
10162
10244
  ...props,
10163
- children: /* @__PURE__ */ jsx60(
10245
+ children: /* @__PURE__ */ jsx61(
10164
10246
  ScrollAreaPrimitive.ScrollAreaThumb,
10165
10247
  {
10166
10248
  "data-slot": "scroll-area-thumb",
@@ -10172,7 +10254,7 @@ function ScrollBar({
10172
10254
  }
10173
10255
 
10174
10256
  // src/components/ui/progress.tsx
10175
- import { jsx as jsx61 } from "react/jsx-runtime";
10257
+ import { jsx as jsx62 } from "react/jsx-runtime";
10176
10258
  var progressFillByStatus = {
10177
10259
  active: "bg-[var(--primary)]",
10178
10260
  success: "bg-[var(--success)]",
@@ -10193,7 +10275,7 @@ function Progress({
10193
10275
  const clamped = Math.max(0, Math.min(safeMax, value));
10194
10276
  const percent = clamped / safeMax * 100;
10195
10277
  const w = typeof width === "number" ? `${width}px` : width;
10196
- return /* @__PURE__ */ jsx61(
10278
+ return /* @__PURE__ */ jsx62(
10197
10279
  "div",
10198
10280
  {
10199
10281
  role: "progressbar",
@@ -10207,7 +10289,7 @@ function Progress({
10207
10289
  ),
10208
10290
  style: { width: w, height: `${height}px`, ...style },
10209
10291
  ...props,
10210
- children: /* @__PURE__ */ jsx61(
10292
+ children: /* @__PURE__ */ jsx62(
10211
10293
  "div",
10212
10294
  {
10213
10295
  className: cn(
@@ -10222,10 +10304,10 @@ function Progress({
10222
10304
  }
10223
10305
 
10224
10306
  // src/components/ui/tree-view.tsx
10225
- import * as React48 from "react";
10307
+ import * as React49 from "react";
10226
10308
  import { ChevronRight as ChevronRight3 } from "lucide-react";
10227
10309
  import { cva as cva25 } from "class-variance-authority";
10228
- import { jsx as jsx62, jsxs as jsxs50 } from "react/jsx-runtime";
10310
+ import { jsx as jsx63, jsxs as jsxs49 } from "react/jsx-runtime";
10229
10311
  var treeViewVariants = cva25(
10230
10312
  "m-0 list-none p-[var(--space-1)] text-body-sm text-foreground"
10231
10313
  );
@@ -10328,27 +10410,27 @@ function TreeView({
10328
10410
  ...rest
10329
10411
  }) {
10330
10412
  const isExpandedControlled = expandedIds !== void 0;
10331
- const [internalExpanded, setInternalExpanded] = React48.useState(
10413
+ const [internalExpanded, setInternalExpanded] = React49.useState(
10332
10414
  () => defaultExpandedIds ?? []
10333
10415
  );
10334
10416
  const expandedList = isExpandedControlled ? expandedIds : internalExpanded;
10335
- const expandedSet = React48.useMemo(() => new Set(expandedList), [expandedList]);
10336
- const items = React48.useMemo(
10417
+ const expandedSet = React49.useMemo(() => new Set(expandedList), [expandedList]);
10418
+ const items = React49.useMemo(
10337
10419
  () => flattenVisibleNodes(nodes, getChildren, expandedSet),
10338
10420
  [nodes, getChildren, expandedSet]
10339
10421
  );
10340
- const [focusedId, setFocusedId] = React48.useState(null);
10422
+ const [focusedId, setFocusedId] = React49.useState(null);
10341
10423
  const visibleIds = items.map((item) => item.id);
10342
10424
  const activeId = focusedId && visibleIds.includes(focusedId) ? focusedId : selectedId && visibleIds.includes(selectedId) ? selectedId : visibleIds[0] ?? null;
10343
- const itemRefs = React48.useRef(/* @__PURE__ */ new Map());
10344
- const commitExpanded = React48.useCallback(
10425
+ const itemRefs = React49.useRef(/* @__PURE__ */ new Map());
10426
+ const commitExpanded = React49.useCallback(
10345
10427
  (next) => {
10346
10428
  if (!isExpandedControlled) setInternalExpanded(next);
10347
10429
  onExpandedChange?.(next);
10348
10430
  },
10349
10431
  [isExpandedControlled, onExpandedChange]
10350
10432
  );
10351
- const setExpanded = React48.useCallback(
10433
+ const setExpanded = React49.useCallback(
10352
10434
  (id, expand) => {
10353
10435
  const has = expandedSet.has(id);
10354
10436
  if (expand && !has) {
@@ -10359,7 +10441,7 @@ function TreeView({
10359
10441
  },
10360
10442
  [commitExpanded, expandedList, expandedSet]
10361
10443
  );
10362
- const focusItem = React48.useCallback((id) => {
10444
+ const focusItem = React49.useCallback((id) => {
10363
10445
  setFocusedId(id);
10364
10446
  itemRefs.current.get(id)?.focus();
10365
10447
  }, []);
@@ -10395,7 +10477,7 @@ function TreeView({
10395
10477
  const selected = node.id === selectedId;
10396
10478
  const isActive = node.id === activeId;
10397
10479
  const itemState = { expanded, selected, depth, hasChildren };
10398
- return /* @__PURE__ */ jsxs50(
10480
+ return /* @__PURE__ */ jsxs49(
10399
10481
  "li",
10400
10482
  {
10401
10483
  ref: (element) => {
@@ -10420,7 +10502,7 @@ function TreeView({
10420
10502
  onSelect?.(node.id, node);
10421
10503
  },
10422
10504
  children: [
10423
- /* @__PURE__ */ jsxs50(
10505
+ /* @__PURE__ */ jsxs49(
10424
10506
  "span",
10425
10507
  {
10426
10508
  "data-slot": "treeitem-row",
@@ -10429,7 +10511,7 @@ function TreeView({
10429
10511
  },
10430
10512
  className: treeItemRowVariants({ selected }),
10431
10513
  children: [
10432
- hasChildren ? /* @__PURE__ */ jsx62(
10514
+ hasChildren ? /* @__PURE__ */ jsx63(
10433
10515
  "span",
10434
10516
  {
10435
10517
  "data-slot": "treeitem-toggle",
@@ -10439,7 +10521,7 @@ function TreeView({
10439
10521
  setExpanded(node.id, !expanded);
10440
10522
  },
10441
10523
  className: "flex size-[var(--space-4)] shrink-0 items-center justify-center text-text-tertiary",
10442
- children: /* @__PURE__ */ jsx62(
10524
+ children: /* @__PURE__ */ jsx63(
10443
10525
  ChevronRight3,
10444
10526
  {
10445
10527
  "aria-hidden": "true",
@@ -10452,7 +10534,7 @@ function TreeView({
10452
10534
  }
10453
10535
  )
10454
10536
  }
10455
- ) : /* @__PURE__ */ jsx62(
10537
+ ) : /* @__PURE__ */ jsx63(
10456
10538
  "span",
10457
10539
  {
10458
10540
  "data-slot": "treeitem-spacer",
@@ -10460,18 +10542,18 @@ function TreeView({
10460
10542
  className: "size-[var(--space-4)] shrink-0"
10461
10543
  }
10462
10544
  ),
10463
- /* @__PURE__ */ jsx62("span", { className: "flex min-w-0 flex-1 items-center gap-[var(--space-2)]", children: renderItem(node, itemState) })
10545
+ /* @__PURE__ */ jsx63("span", { className: "flex min-w-0 flex-1 items-center gap-[var(--space-2)]", children: renderItem(node, itemState) })
10464
10546
  ]
10465
10547
  }
10466
10548
  ),
10467
- hasChildren && expanded && children ? /* @__PURE__ */ jsx62("ul", { role: "group", "data-slot": "tree-group", className: "m-0 list-none p-0", children: renderLevel(children, depth + 1) }) : null
10549
+ hasChildren && expanded && children ? /* @__PURE__ */ jsx63("ul", { role: "group", "data-slot": "tree-group", className: "m-0 list-none p-0", children: renderLevel(children, depth + 1) }) : null
10468
10550
  ]
10469
10551
  },
10470
10552
  node.id
10471
10553
  );
10472
10554
  });
10473
10555
  }
10474
- return /* @__PURE__ */ jsx62(
10556
+ return /* @__PURE__ */ jsx63(
10475
10557
  "ul",
10476
10558
  {
10477
10559
  role: "tree",
@@ -10487,12 +10569,12 @@ function TreeView({
10487
10569
  }
10488
10570
 
10489
10571
  // src/components/branding/olun-logo.tsx
10490
- import { jsx as jsx63, jsxs as jsxs51 } from "react/jsx-runtime";
10572
+ import { jsx as jsx64, jsxs as jsxs50 } from "react/jsx-runtime";
10491
10573
  var SYMBOL_LARGE = { stroke: 24, dotX: 184, dotY: 180, dotR: 13 };
10492
10574
  var SYMBOL_SMALL = { stroke: 18, dotX: 185, dotY: 175, dotR: 22 };
10493
10575
  function OlunSymbol({ size = 28, className }) {
10494
10576
  const g = size > 32 ? SYMBOL_LARGE : SYMBOL_SMALL;
10495
- return /* @__PURE__ */ jsxs51(
10577
+ return /* @__PURE__ */ jsxs50(
10496
10578
  "svg",
10497
10579
  {
10498
10580
  width: size,
@@ -10503,7 +10585,7 @@ function OlunSymbol({ size = 28, className }) {
10503
10585
  className,
10504
10586
  "aria-hidden": "true",
10505
10587
  children: [
10506
- /* @__PURE__ */ jsx63(
10588
+ /* @__PURE__ */ jsx64(
10507
10589
  "circle",
10508
10590
  {
10509
10591
  cx: "108",
@@ -10515,7 +10597,7 @@ function OlunSymbol({ size = 28, className }) {
10515
10597
  style: { color: "var(--text-primary)" }
10516
10598
  }
10517
10599
  ),
10518
- /* @__PURE__ */ jsx63("circle", { cx: g.dotX, cy: g.dotY, r: g.dotR, fill: "var(--accent-pop)" })
10600
+ /* @__PURE__ */ jsx64("circle", { cx: g.dotX, cy: g.dotY, r: g.dotR, fill: "var(--accent-pop)" })
10519
10601
  ]
10520
10602
  }
10521
10603
  );
@@ -10526,7 +10608,7 @@ function OlunLogo({
10526
10608
  showSymbol = true,
10527
10609
  className
10528
10610
  }) {
10529
- return /* @__PURE__ */ jsxs51(
10611
+ return /* @__PURE__ */ jsxs50(
10530
10612
  "div",
10531
10613
  {
10532
10614
  className,
@@ -10536,8 +10618,8 @@ function OlunLogo({
10536
10618
  gap: "var(--space-3)"
10537
10619
  },
10538
10620
  children: [
10539
- showSymbol && /* @__PURE__ */ jsx63(OlunSymbol, { size: symbolSize }),
10540
- /* @__PURE__ */ jsxs51(
10621
+ showSymbol && /* @__PURE__ */ jsx64(OlunSymbol, { size: symbolSize }),
10622
+ /* @__PURE__ */ jsxs50(
10541
10623
  "span",
10542
10624
  {
10543
10625
  style: {
@@ -10549,7 +10631,7 @@ function OlunLogo({
10549
10631
  },
10550
10632
  children: [
10551
10633
  "OLUN",
10552
- !showSymbol && /* @__PURE__ */ jsx63("span", { style: { color: "var(--accent)" }, children: "." })
10634
+ !showSymbol && /* @__PURE__ */ jsx64("span", { style: { color: "var(--accent)" }, children: "." })
10553
10635
  ]
10554
10636
  }
10555
10637
  )
@@ -10560,11 +10642,11 @@ function OlunLogo({
10560
10642
 
10561
10643
  // src/components/branding/theme-toggle.tsx
10562
10644
  import { Sun, Moon } from "lucide-react";
10563
- import { jsx as jsx64 } from "react/jsx-runtime";
10645
+ import { jsx as jsx65 } from "react/jsx-runtime";
10564
10646
  function ThemeToggle({ className }) {
10565
10647
  const { resolvedTheme, toggleTheme } = useOlunTheme();
10566
10648
  const Icon = resolvedTheme === "dark" ? Moon : Sun;
10567
- return /* @__PURE__ */ jsx64(
10649
+ return /* @__PURE__ */ jsx65(
10568
10650
  "button",
10569
10651
  {
10570
10652
  onClick: () => toggleTheme(),
@@ -10576,14 +10658,14 @@ function ThemeToggle({ className }) {
10576
10658
  ),
10577
10659
  "aria-label": "\uD14C\uB9C8 \uC804\uD658",
10578
10660
  title: resolvedTheme === "dark" ? "\uB77C\uC774\uD2B8 \uBAA8\uB4DC\uB85C" : "\uB2E4\uD06C \uBAA8\uB4DC\uB85C",
10579
- children: /* @__PURE__ */ jsx64(Icon, { className: "size-[18px]", strokeWidth: 1.75 })
10661
+ children: /* @__PURE__ */ jsx65(Icon, { className: "size-[18px]", strokeWidth: 1.75 })
10580
10662
  }
10581
10663
  );
10582
10664
  }
10583
10665
 
10584
10666
  // src/components/branding/theme-fab.tsx
10585
10667
  import { Sun as Sun2, Moon as Moon2 } from "lucide-react";
10586
- import { jsx as jsx65 } from "react/jsx-runtime";
10668
+ import { jsx as jsx66 } from "react/jsx-runtime";
10587
10669
  function ThemeFab({ variant = "square" } = {}) {
10588
10670
  const { mounted, resolvedTheme, toggleTheme } = useOlunTheme();
10589
10671
  if (!mounted) {
@@ -10623,7 +10705,7 @@ function ThemeFab({ variant = "square" } = {}) {
10623
10705
  WebkitBackdropFilter: "blur(16px)",
10624
10706
  zIndex: 9999
10625
10707
  };
10626
- return /* @__PURE__ */ jsx65(
10708
+ return /* @__PURE__ */ jsx66(
10627
10709
  "button",
10628
10710
  {
10629
10711
  onClick: () => toggleTheme(),
@@ -10648,7 +10730,7 @@ function ThemeFab({ variant = "square" } = {}) {
10648
10730
  e.currentTarget.style.color = "var(--text-secondary)";
10649
10731
  }
10650
10732
  },
10651
- children: /* @__PURE__ */ jsx65(
10733
+ children: /* @__PURE__ */ jsx66(
10652
10734
  Icon,
10653
10735
  {
10654
10736
  size: isCircle ? 22 : 16,
@@ -10660,7 +10742,7 @@ function ThemeFab({ variant = "square" } = {}) {
10660
10742
  }
10661
10743
 
10662
10744
  // src/components/logos/organization-logo.tsx
10663
- import { jsx as jsx66 } from "react/jsx-runtime";
10745
+ import { jsx as jsx67 } from "react/jsx-runtime";
10664
10746
  var organizationLogoRegistry = {
10665
10747
  jbnu: {
10666
10748
  label: "\uC804\uBD81\uB300\uD559\uAD50 \uC5E0\uBE14\uB7FC",
@@ -10689,7 +10771,7 @@ function OrganizationLogo({
10689
10771
  }) {
10690
10772
  const asset = organizationLogoRegistry[organization];
10691
10773
  const isDecorative = ariaHidden === true || ariaHidden === "true";
10692
- return /* @__PURE__ */ jsx66(
10774
+ return /* @__PURE__ */ jsx67(
10693
10775
  "svg",
10694
10776
  {
10695
10777
  viewBox: asset.viewBox,
@@ -10707,7 +10789,7 @@ function OrganizationLogo({
10707
10789
  ...style
10708
10790
  },
10709
10791
  ...props,
10710
- children: asset.paths.map((path) => /* @__PURE__ */ jsx66("path", { d: path }, path))
10792
+ children: asset.paths.map((path) => /* @__PURE__ */ jsx67("path", { d: path }, path))
10711
10793
  }
10712
10794
  );
10713
10795
  }
@@ -10821,6 +10903,7 @@ export {
10821
10903
  SkeletonText,
10822
10904
  Spinner,
10823
10905
  StatusBadge,
10906
+ StatusDot,
10824
10907
  Switch,
10825
10908
  Tabs,
10826
10909
  TabsContent,