@olundot/ui 0.12.0 → 0.14.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
@@ -28,6 +28,14 @@ var durationMsByToken = {
28
28
  slower: 400,
29
29
  slowest: 600
30
30
  };
31
+ var transitionDurationVarByToken = {
32
+ instant: "0ms",
33
+ fast: "var(--dur-fast)",
34
+ base: "var(--dur-base)",
35
+ slow: "var(--dur-slow)",
36
+ slower: "400ms",
37
+ slowest: "600ms"
38
+ };
31
39
  var transitionCleanupTimer;
32
40
  var defaultThemeState = {
33
41
  theme: "light",
@@ -105,7 +113,7 @@ function setOlunTheme(nextTheme, options = {}) {
105
113
  root.dataset[TRANSITION_ATTR] = "true";
106
114
  root.style.setProperty(
107
115
  TRANSITION_DURATION_PROPERTY,
108
- `var(--duration-${duration})`
116
+ transitionDurationVarByToken[duration]
109
117
  );
110
118
  void root.offsetWidth;
111
119
  }
@@ -201,7 +209,7 @@ var buttonVariants = cva(
201
209
  default: "border-[var(--primary)] bg-[var(--primary)] text-[var(--primary-fg)] hover:bg-[var(--primary-hover)] hover:border-[var(--primary-hover)]",
202
210
  destructive: "border-[var(--error)] bg-[var(--error)] text-[var(--error-contrast)] hover:bg-[var(--error-hover)] hover:border-[var(--error-hover)]",
203
211
  secondary: "border-[var(--border-subtle)] bg-[var(--bg-surface)] text-foreground hover:border-[var(--border)] hover:bg-[var(--action-hover)]",
204
- link: "border-transparent bg-transparent px-0 text-[var(--accent-fg)] underline-offset-4 hover:underline"
212
+ link: "border-transparent bg-transparent px-0 text-[var(--accent)] underline-offset-4 hover:underline"
205
213
  },
206
214
  size: {
207
215
  // Cross-control height map: Button sm/md/lg match field controls sm/md/lg (30/32/36px).
@@ -2168,43 +2176,54 @@ import { cva as cva7 } from "class-variance-authority";
2168
2176
  import { jsx as jsx13 } from "react/jsx-runtime";
2169
2177
  var cardBaseVariants = cva7(
2170
2178
  [
2171
- "rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
2179
+ "rounded-[var(--radius-lg)] border border-[var(--border)]",
2172
2180
  "px-pad-roomy-x py-pad-roomy-y text-foreground"
2173
2181
  ].join(" "),
2174
2182
  {
2175
2183
  variants: {
2176
2184
  variant: {
2177
- default: "",
2178
- elevated: "shadow-[var(--elevation-2)]",
2179
- notice: "border-[var(--border-accent)]",
2180
- interactive: [
2185
+ default: "shadow-[var(--shadow-2)]",
2186
+ elevated: "shadow-[var(--shadow-4)]",
2187
+ notice: "border-[var(--border-accent)] shadow-[var(--shadow-2)]"
2188
+ },
2189
+ interactive: {
2190
+ true: [
2181
2191
  "cursor-pointer",
2182
2192
  "transition-[transform,border-color,box-shadow,background-color]",
2183
2193
  "motion-reduce:transition-none",
2184
2194
  "hover:-translate-y-[1px] motion-reduce:hover:translate-y-0",
2185
2195
  "hover:border-[var(--border-strong)]",
2186
2196
  "hover:bg-[var(--action-hover)]",
2187
- "hover:shadow-[var(--elevation-2)]",
2188
- "dark:hover:shadow-[var(--elevation-2),var(--glow-sm)]",
2189
2197
  "focus-visible:outline-none",
2190
- "focus-visible:border-[var(--border-accent)]",
2191
- "focus-visible:shadow-[var(--elevation-2),var(--glow-sm)]"
2192
- ].join(" ")
2198
+ "focus-visible:border-[var(--focus-ring)]",
2199
+ "focus-visible:shadow-[0_0_0_1px_var(--focus-ring)]"
2200
+ ].join(" "),
2201
+ false: ""
2193
2202
  }
2194
2203
  },
2195
- defaultVariants: { variant: "default" }
2204
+ // Interactive hover lifts the shadow one step above the variant's resting depth.
2205
+ compoundVariants: [
2206
+ { variant: "default", interactive: true, class: "hover:shadow-[var(--shadow-4)]" },
2207
+ { variant: "notice", interactive: true, class: "hover:shadow-[var(--shadow-4)]" },
2208
+ { variant: "elevated", interactive: true, class: "hover:shadow-[var(--shadow-8)]" }
2209
+ ],
2210
+ defaultVariants: { variant: "default", interactive: false }
2196
2211
  }
2197
2212
  );
2198
2213
  function getCardDefaultSurface(variant) {
2199
2214
  return variant === "elevated" ? "raised" : "surface";
2200
2215
  }
2201
- function cardVariants({ variant, surface, className } = {}) {
2216
+ function cardVariants({ variant, surface, interactive, className } = {}) {
2202
2217
  const resolvedVariant = variant ?? "default";
2203
2218
  const resolvedSurface = surface ?? getCardDefaultSurface(resolvedVariant);
2204
- return cn(cardBaseVariants({ variant: resolvedVariant }), surfaceClassNames[resolvedSurface], className);
2219
+ return cn(
2220
+ cardBaseVariants({ variant: resolvedVariant, interactive: interactive ?? false }),
2221
+ surfaceClassNames[resolvedSurface],
2222
+ className
2223
+ );
2205
2224
  }
2206
2225
  var Card = React12.forwardRef(
2207
- ({ className, variant, surface, selected, disabled, "aria-disabled": ariaDisabled, ...props }, ref) => /* @__PURE__ */ jsx13(
2226
+ ({ className, variant, surface, interactive, selected, disabled, "aria-disabled": ariaDisabled, ...props }, ref) => /* @__PURE__ */ jsx13(
2208
2227
  "div",
2209
2228
  {
2210
2229
  ref,
@@ -2214,8 +2233,8 @@ var Card = React12.forwardRef(
2214
2233
  "aria-disabled": disabled ? true : ariaDisabled,
2215
2234
  className: cn(
2216
2235
  "group/card",
2217
- cardVariants({ variant, surface }),
2218
- selected && "border-[var(--border-strong)] bg-[var(--bg-canvas)]",
2236
+ cardVariants({ variant, surface, interactive }),
2237
+ selected && "border-[var(--border-strong)] bg-[var(--action-selected)]",
2219
2238
  disabled && "pointer-events-none cursor-not-allowed border-[var(--border-subtle)] bg-[var(--action-disabled-bg)] text-text-disabled",
2220
2239
  className
2221
2240
  ),
@@ -2958,7 +2977,7 @@ var tabsTriggerVariants = cva8(
2958
2977
  "relative inline-flex shrink-0 cursor-pointer items-center gap-[var(--space-2)]",
2959
2978
  "px-0 py-pad-compact-y text-body-sm font-medium",
2960
2979
  "text-text-secondary transition-colors",
2961
- "duration-[var(--duration-fast)] ease-[var(--ease-standard)]",
2980
+ "duration-[var(--dur-fast)] ease-[var(--ease-standard)]",
2962
2981
  "hover:text-foreground",
2963
2982
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]",
2964
2983
  "disabled:cursor-not-allowed disabled:pointer-events-auto disabled:text-text-disabled disabled:hover:text-text-disabled",
@@ -3130,6 +3149,38 @@ function DetailLayoutBody({
3130
3149
  }
3131
3150
  );
3132
3151
  }
3152
+ function isTabsContentChild(child) {
3153
+ return React18.isValidElement(child) && child.type === TabsContent;
3154
+ }
3155
+ function containsTabsContent(children) {
3156
+ return React18.Children.toArray(children).some((child) => {
3157
+ if (isTabsContentChild(child)) return true;
3158
+ return React18.isValidElement(child) && containsTabsContent(child.props.children);
3159
+ });
3160
+ }
3161
+ function appendFooterToActiveTabsContent(children, activeTab, footer) {
3162
+ return React18.Children.map(children, (child) => {
3163
+ if (isTabsContentChild(child)) {
3164
+ if (child.props.tabKey !== activeTab || !footer) return child;
3165
+ return React18.cloneElement(
3166
+ child,
3167
+ void 0,
3168
+ /* @__PURE__ */ jsxs18(Fragment6, { children: [
3169
+ child.props.children,
3170
+ /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-footer", className: "min-w-0", children: footer })
3171
+ ] })
3172
+ );
3173
+ }
3174
+ if (React18.isValidElement(child)) {
3175
+ return React18.cloneElement(
3176
+ child,
3177
+ void 0,
3178
+ appendFooterToActiveTabsContent(child.props.children, activeTab, footer)
3179
+ );
3180
+ }
3181
+ return child;
3182
+ });
3183
+ }
3133
3184
  var DetailLayout = React18.forwardRef(
3134
3185
  ({
3135
3186
  className,
@@ -3160,6 +3211,7 @@ var DetailLayout = React18.forwardRef(
3160
3211
  children
3161
3212
  }
3162
3213
  );
3214
+ const hasExplicitTabsContent = containsTabsContent(children);
3163
3215
  return /* @__PURE__ */ jsxs18(
3164
3216
  "section",
3165
3217
  {
@@ -3169,10 +3221,31 @@ var DetailLayout = React18.forwardRef(
3169
3221
  ...props,
3170
3222
  children: [
3171
3223
  /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-header", className: "min-w-0", children: header }),
3172
- tabs ? /* @__PURE__ */ jsxs18(Tabs, { tabs, activeKey: activeTab, onChange: onTabChange, baseId, children: [
3173
- body,
3174
- footer ? /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-footer", className: "min-w-0", children: footer }) : null
3175
- ] }) : /* @__PURE__ */ jsxs18(Fragment6, { children: [
3224
+ tabs ? /* @__PURE__ */ jsx19(Tabs, { tabs, activeKey: activeTab, onChange: onTabChange, baseId, children: hasExplicitTabsContent ? /* @__PURE__ */ jsx19(
3225
+ DetailLayoutBody,
3226
+ {
3227
+ aside,
3228
+ bodyClassName,
3229
+ contentClassName,
3230
+ asideClassName,
3231
+ stickyAside,
3232
+ stickyAsideTopClassName,
3233
+ children: appendFooterToActiveTabsContent(children, activeTab, footer)
3234
+ }
3235
+ ) : tabs.map((tab) => /* @__PURE__ */ jsx19(
3236
+ TabsContent,
3237
+ {
3238
+ tabKey: tab.key,
3239
+ baseId,
3240
+ forceMount: true,
3241
+ hidden: tab.key !== activeTab,
3242
+ children: tab.key === activeTab ? /* @__PURE__ */ jsxs18(Fragment6, { children: [
3243
+ body,
3244
+ footer ? /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-footer", className: "min-w-0", children: footer }) : null
3245
+ ] }) : null
3246
+ },
3247
+ tab.key
3248
+ )) }) : /* @__PURE__ */ jsxs18(Fragment6, { children: [
3176
3249
  body,
3177
3250
  footer ? /* @__PURE__ */ jsx19("div", { "data-slot": "detail-layout-footer", className: "min-w-0", children: footer }) : null
3178
3251
  ] })
@@ -3384,9 +3457,9 @@ var DialogContent = React20.forwardRef(({ className, children, showCloseButton =
3384
3457
  // modal은 dim overlay 위 — 가장 밝은 DS surface(--bg-base #F1F3F5·여전히 tinted·순백 아님)로 깨끗하게.
3385
3458
  // arbitrary var 사용: 소비 site/app이 dist를 content-scan 안 해 `bg-base` 유틸이 purge될 수 있어 안전하게 var로.
3386
3459
  "bg-[var(--bg-base)] text-foreground",
3387
- // 2026: generic 무거운 그림자 대신 floating elevation-8 + 또렷한 중립 grey border(--border·16%) + radius-lg.
3460
+ // 2026: generic 무거운 그림자 대신 floating shadow-8 + 또렷한 중립 grey border(--border·16%) + radius-lg.
3388
3461
  // (border-subtle=8%는 너무 흐려 가장자리가 안 보였음 → border-border로 grey 또렷하게.)
3389
- "border border-border rounded-[var(--radius-lg)] shadow-elevation-8",
3462
+ "border border-border rounded-[var(--radius-lg)] shadow-8",
3390
3463
  "duration-200",
3391
3464
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
3392
3465
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
@@ -3497,7 +3570,7 @@ var formModalContentClassName = cn(
3497
3570
  "bg-[var(--bg-raised)]",
3498
3571
  "border-[var(--border-subtle)]",
3499
3572
  "rounded-[var(--radius-lg)]",
3500
- "shadow-[var(--elevation-4)]",
3573
+ "shadow-[var(--shadow-4)]",
3501
3574
  "text-foreground"
3502
3575
  );
3503
3576
  var formModalWideContentClassName = "max-w-[720px]";
@@ -3610,7 +3683,7 @@ var infoModalContentClassName = cn(
3610
3683
  "bg-[var(--bg-raised)]",
3611
3684
  "border border-[var(--border-subtle)]",
3612
3685
  "rounded-[var(--radius-lg)]",
3613
- "shadow-[var(--elevation-4)]",
3686
+ "shadow-[var(--shadow-4)]",
3614
3687
  "text-foreground"
3615
3688
  );
3616
3689
  var infoModalWideContentClassName = "max-w-[720px]";
@@ -4110,7 +4183,7 @@ var Checkbox = React23.forwardRef(
4110
4183
  Checkbox.displayName = "Checkbox";
4111
4184
 
4112
4185
  // src/components/ui/data-table.tsx
4113
- import { Fragment as Fragment7, jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
4186
+ import { jsx as jsx26, jsxs as jsxs25 } from "react/jsx-runtime";
4114
4187
  var dataTableVariants = cva10(
4115
4188
  [
4116
4189
  "relative overflow-hidden rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -4290,27 +4363,35 @@ function SkeletonRows({
4290
4363
  gridTemplateColumns,
4291
4364
  count
4292
4365
  }) {
4293
- return /* @__PURE__ */ jsx26("div", { "aria-label": "\uB370\uC774\uD130 \uB85C\uB4DC \uC911", role: "status", children: Array.from({ length: count }, (_, rowIndex) => /* @__PURE__ */ jsxs25(
4294
- "div",
4295
- {
4296
- "data-slot": "data-table-skeleton-row",
4297
- className: "grid min-h-[48px] items-center border-t border-[var(--border-subtle)]",
4298
- style: { gridTemplateColumns },
4299
- children: [
4300
- selectable ? /* @__PURE__ */ jsx26("div", { "aria-hidden": "true", className: "px-[var(--space-4)]" }) : null,
4301
- columns.map((column, columnIndex) => /* @__PURE__ */ jsx26("div", { className: "px-[var(--space-4)] py-[var(--space-2)]", children: /* @__PURE__ */ jsx26(
4302
- "div",
4303
- {
4304
- className: cn(
4305
- "h-[14px] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-raised)]",
4306
- columnIndex === 0 ? "w-[72%]" : column.align === "right" ? "ml-auto w-[54%]" : "w-[62%]"
4307
- )
4308
- }
4309
- ) }, column.key))
4310
- ]
4311
- },
4312
- rowIndex
4313
- )) });
4366
+ return (
4367
+ // role="table"의 허용 자식은 row/rowgroup뿐이라 컨테이너는 rowgroup이어야 한다.
4368
+ // 로딩 알림은 그 안의 row/cell 안에 둔다 — 종전에는 컨테이너가 role="status"라
4369
+ // aria-required-children(Critical)이 났다.
4370
+ /* @__PURE__ */ jsxs25("div", { role: "rowgroup", children: [
4371
+ /* @__PURE__ */ jsx26("div", { role: "row", children: /* @__PURE__ */ jsx26("div", { role: "cell", "aria-colindex": 1, "aria-label": "\uB370\uC774\uD130 \uB85C\uB4DC \uC911", children: /* @__PURE__ */ jsx26("span", { role: "status", className: "sr-only", children: "\uB370\uC774\uD130 \uB85C\uB4DC \uC911" }) }) }),
4372
+ Array.from({ length: count }, (_, rowIndex) => /* @__PURE__ */ jsxs25(
4373
+ "div",
4374
+ {
4375
+ "data-slot": "data-table-skeleton-row",
4376
+ className: "grid min-h-[48px] items-center border-t border-[var(--border-subtle)]",
4377
+ style: { gridTemplateColumns },
4378
+ children: [
4379
+ selectable ? /* @__PURE__ */ jsx26("div", { "aria-hidden": "true", className: "px-[var(--space-4)]" }) : null,
4380
+ columns.map((column, columnIndex) => /* @__PURE__ */ jsx26("div", { className: "px-[var(--space-4)] py-[var(--space-2)]", children: /* @__PURE__ */ jsx26(
4381
+ "div",
4382
+ {
4383
+ className: cn(
4384
+ "h-[14px] animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-raised)]",
4385
+ columnIndex === 0 ? "w-[72%]" : column.align === "right" ? "ml-auto w-[54%]" : "w-[62%]"
4386
+ )
4387
+ }
4388
+ ) }, column.key))
4389
+ ]
4390
+ },
4391
+ rowIndex
4392
+ ))
4393
+ ] })
4394
+ );
4314
4395
  }
4315
4396
  function MobileSkeletonCards({ count }) {
4316
4397
  return /* @__PURE__ */ jsx26(
@@ -4346,14 +4427,12 @@ function DataTableInner({
4346
4427
  selectable = false,
4347
4428
  selectedIds,
4348
4429
  onSelectionChange,
4349
- selectionBar = "top",
4350
4430
  activeRowId,
4351
4431
  onRowContextMenu,
4352
4432
  sortBy,
4353
4433
  onSortChange,
4354
4434
  loading = false,
4355
4435
  emptyState,
4356
- bulkActions = [],
4357
4436
  rowHref,
4358
4437
  skeletonRowCount = 8,
4359
4438
  "aria-label": ariaLabel = "\uB370\uC774\uD130 \uD14C\uC774\uBE14",
@@ -4396,44 +4475,13 @@ function DataTableInner({
4396
4475
  className: cn(dataTableVariants({ density, surface, className })),
4397
4476
  ...props,
4398
4477
  children: [
4399
- selectable && selectionBar === "top" ? /* @__PURE__ */ jsx26(
4478
+ selectable ? /* @__PURE__ */ jsx26(
4400
4479
  "div",
4401
4480
  {
4402
- "data-slot": "data-table-selection-bar",
4403
- "data-active": selectedCount > 0 ? "true" : "false",
4481
+ "data-slot": "data-table-selection-status",
4404
4482
  "aria-live": "polite",
4405
- className: cn(
4406
- "flex min-h-[48px] flex-wrap items-center justify-between gap-[var(--space-3)] border-b border-[var(--border-subtle)] px-[var(--space-4)] py-[var(--space-2)]",
4407
- "bg-[var(--bg-raised)]"
4408
- ),
4409
- children: selectedCount > 0 ? /* @__PURE__ */ jsxs25(Fragment7, { children: [
4410
- /* @__PURE__ */ jsxs25("div", { className: "text-sm font-medium text-foreground", children: [
4411
- selectedCount.toLocaleString("ko-KR"),
4412
- "\uAC1C \uC120\uD0DD\uB428"
4413
- ] }),
4414
- /* @__PURE__ */ jsxs25("div", { className: "flex flex-wrap items-center justify-end gap-[var(--space-2)]", children: [
4415
- bulkActions.map((action, index) => /* @__PURE__ */ jsx26(
4416
- Button,
4417
- {
4418
- size: "xs",
4419
- variant: action.variant === "destructive" ? "destructive" : "secondary",
4420
- onClick: () => action.onClick(new Set(resolvedSelectedIds)),
4421
- children: action.label
4422
- },
4423
- index
4424
- )),
4425
- /* @__PURE__ */ jsx26(
4426
- Button,
4427
- {
4428
- "aria-label": "\uC120\uD0DD \uCDE8\uC18C",
4429
- size: "xs",
4430
- variant: "ghost",
4431
- onClick: () => emitSelection(/* @__PURE__ */ new Set()),
4432
- children: "\uCDE8\uC18C"
4433
- }
4434
- )
4435
- ] })
4436
- ] }) : /* @__PURE__ */ jsx26("div", { className: "text-sm text-text-tertiary", children: "\uC120\uD0DD\uB41C \uD589 \uC5C6\uC74C" })
4483
+ className: "sr-only",
4484
+ children: selectedCount > 0 ? `${selectedCount.toLocaleString("ko-KR")}\uAC1C \uC120\uD0DD\uB428` : ""
4437
4485
  }
4438
4486
  ) : null,
4439
4487
  loading && data.length > 0 ? /* @__PURE__ */ jsx26(
@@ -4507,7 +4555,20 @@ function DataTableInner({
4507
4555
  gridTemplateColumns,
4508
4556
  count: skeletonRowCount
4509
4557
  }
4510
- ) : data.length === 0 ? /* @__PURE__ */ jsx26("div", { "data-slot": "data-table-empty", className: "border-t border-[var(--border-subtle)] p-[var(--space-4)]", children: emptyState }) : /* @__PURE__ */ jsx26("div", { role: "rowgroup", children: data.map((row) => {
4558
+ ) : data.length === 0 ? (
4559
+ /* role="table" 직계 자식은 row/rowgroup이어야 한다. data-slot과 테두리는
4560
+ 그대로 유지해 시각 계약을 깨지 않는다(빈 상태에서도 표가 테두리를 그린다). */
4561
+ /* @__PURE__ */ jsx26("div", { role: "rowgroup", children: /* @__PURE__ */ jsx26("div", { role: "row", children: /* @__PURE__ */ jsx26(
4562
+ "div",
4563
+ {
4564
+ role: "cell",
4565
+ "aria-colindex": 1,
4566
+ "data-slot": "data-table-empty",
4567
+ className: "border-t border-[var(--border-subtle)] p-[var(--space-4)]",
4568
+ children: emptyState
4569
+ }
4570
+ ) }) })
4571
+ ) : /* @__PURE__ */ jsx26("div", { role: "rowgroup", children: data.map((row) => {
4511
4572
  const rowId = getRowId(row, keyField);
4512
4573
  const selected = resolvedSelectedIds.has(rowId);
4513
4574
  const visuallySelected = selected || rowId === activeRowId;
@@ -4737,7 +4798,7 @@ function DropdownMenuContent({
4737
4798
  className: cn(
4738
4799
  "z-[var(--z-popover)] max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem]",
4739
4800
  "origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto",
4740
- "rounded-sm border border-[var(--border)] bg-canvas p-[var(--space-1)] text-text-primary shadow-elevation-2",
4801
+ "rounded-sm border border-[var(--border)] bg-canvas p-[var(--space-1)] text-text-primary shadow-2",
4741
4802
  "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
4742
4803
  "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4743
4804
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
@@ -4936,7 +4997,7 @@ function DropdownMenuSubContent({
4936
4997
  "data-slot": "dropdown-menu-sub-content",
4937
4998
  className: cn(
4938
4999
  "z-[var(--z-popover)] min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden",
4939
- "rounded-sm border border-[var(--border)] bg-canvas p-[var(--space-1)] text-text-primary shadow-elevation-2",
5000
+ "rounded-sm border border-[var(--border)] bg-canvas p-[var(--space-1)] text-text-primary shadow-2",
4940
5001
  "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
4941
5002
  "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4942
5003
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
@@ -5075,6 +5136,7 @@ function BulkActionBar({
5075
5136
  actions,
5076
5137
  onClear,
5077
5138
  emptyHint,
5139
+ className,
5078
5140
  style,
5079
5141
  ...props
5080
5142
  }) {
@@ -5087,9 +5149,15 @@ function BulkActionBar({
5087
5149
  role: "toolbar",
5088
5150
  "aria-label": "\uC120\uD0DD \uD56D\uBAA9 \uC77C\uAD04 \uC791\uC5C5",
5089
5151
  "data-slot": "bulk-action-bar",
5152
+ className: cn(
5153
+ // Subtle entrance when the bar appears (count>0). CSS animation runs once
5154
+ // on mount; reduced motion opts out via the global guard + this variant.
5155
+ "animate-[olun-bulk-action-bar-in_var(--dur-fast)_var(--ease-out)_both] motion-reduce:animate-none",
5156
+ className
5157
+ ),
5090
5158
  style: {
5091
5159
  position: "sticky",
5092
- bottom: "var(--space-4)",
5160
+ bottom: "calc(var(--space-4) + env(safe-area-inset-bottom))",
5093
5161
  zIndex: 1100,
5094
5162
  margin: "0 auto",
5095
5163
  display: "flex",
@@ -5149,14 +5217,14 @@ function BulkActionBar({
5149
5217
 
5150
5218
  // src/components/ui/confirm-dialog.tsx
5151
5219
  import * as React25 from "react";
5152
- import { Fragment as Fragment8, jsx as jsx30, jsxs as jsxs29 } from "react/jsx-runtime";
5220
+ import { Fragment as Fragment7, jsx as jsx30, jsxs as jsxs29 } from "react/jsx-runtime";
5153
5221
  var confirmDialogContentClassName = cn(
5154
5222
  "fixed left-1/2 top-1/2 z-[var(--z-modal)]",
5155
5223
  "-translate-x-1/2 -translate-y-1/2",
5156
5224
  "w-[calc(100vw-2rem)] max-w-[420px]",
5157
5225
  "flex flex-col gap-[var(--space-6)]",
5158
5226
  "bg-[var(--bg-raised)] border border-[var(--border-subtle)]",
5159
- "rounded-[var(--radius-lg)] p-[var(--space-6)] shadow-[var(--elevation-4)]",
5227
+ "rounded-[var(--radius-lg)] p-[var(--space-6)] shadow-[var(--shadow-4)]",
5160
5228
  "text-foreground"
5161
5229
  );
5162
5230
  var confirmDialogTitleClassName = cn(
@@ -5203,7 +5271,7 @@ function ConfirmDialog({
5203
5271
  setPending(false);
5204
5272
  }
5205
5273
  }, [loading, onConfirm, onOpenChange]);
5206
- const dialogBody = /* @__PURE__ */ jsxs29(Fragment8, { children: [
5274
+ const dialogBody = /* @__PURE__ */ jsxs29(Fragment7, { children: [
5207
5275
  /* @__PURE__ */ jsx30("div", { className: "flex items-start justify-between gap-[var(--space-4)]", children: /* @__PURE__ */ jsxs29("div", { className: "min-w-0 space-y-[var(--space-2)]", children: [
5208
5276
  /* @__PURE__ */ jsx30(
5209
5277
  DialogTitle,
@@ -5353,11 +5421,13 @@ var defaultSheetMotionConfig = {
5353
5421
  easing: "decel"
5354
5422
  };
5355
5423
  var sheetMotionEasingValue = {
5356
- standard: "var(--easing-standard)",
5424
+ standard: "var(--ease-standard)",
5425
+ // decel/sharp have no canonical --ease-* token; these compat beziers are frozen
5426
+ // specifically to back this public `easing` prop (see tokens/compat.css).
5357
5427
  decel: "var(--easing-decel)",
5358
- accel: "var(--easing-accel)",
5428
+ accel: "var(--ease-in)",
5359
5429
  sharp: "var(--easing-sharp)",
5360
- bounce: "var(--easing-bounce)"
5430
+ bounce: "var(--ease-out)"
5361
5431
  };
5362
5432
  function resolveSheetMotionConfig(motion) {
5363
5433
  if (motion === false) return false;
@@ -5560,7 +5630,7 @@ import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
5560
5630
  var sheetDrawerContentClassName = cn(
5561
5631
  "gap-0 p-0",
5562
5632
  "bg-[var(--bg-surface)] text-foreground",
5563
- "border-[var(--border)] shadow-[var(--elevation-4)]",
5633
+ "border-[var(--border)] shadow-[var(--shadow-4)]",
5564
5634
  "min-[900px]:w-[480px] min-[900px]:max-w-[480px]",
5565
5635
  "max-[899px]:h-[min(85dvh,720px)] max-[899px]:max-h-[85dvh] max-[899px]:w-full max-[899px]:max-w-none",
5566
5636
  "max-[899px]:rounded-t-[var(--radius-lg)]"
@@ -5734,7 +5804,7 @@ var PopoverContent = React26.forwardRef(({ className, align = "center", sideOffs
5734
5804
  "z-[var(--z-popover)] w-[260px] outline-none",
5735
5805
  "rounded-[var(--radius-md)] border border-[var(--border)]",
5736
5806
  "bg-[var(--bg-raised)] p-[var(--space-4)] text-foreground",
5737
- "shadow-[var(--elevation-4)]",
5807
+ "shadow-[var(--shadow-4)]",
5738
5808
  "data-[state=open]:animate-in data-[state=closed]:animate-out",
5739
5809
  "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
5740
5810
  "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
@@ -5816,100 +5886,93 @@ Badge.displayName = "Badge";
5816
5886
 
5817
5887
  // src/components/ui/two-tier-badge.tsx
5818
5888
  import * as React28 from "react";
5819
- import { cva as cva11 } from "class-variance-authority";
5820
5889
  import { jsx as jsx37, jsxs as jsxs34 } from "react/jsx-runtime";
5821
- var twoTierBadgeVariants = cva11(
5822
- "inline-flex w-fit flex-col gap-[var(--space-1)]",
5823
- {
5824
- variants: {
5825
- align: {
5826
- start: "items-start text-left",
5827
- center: "items-center text-center",
5828
- end: "items-end text-right"
5829
- }
5830
- },
5831
- defaultVariants: {
5832
- align: "start"
5833
- }
5834
- }
5835
- );
5836
- var twoTierBadgeLineVariants = cva11(
5837
- [
5838
- "inline-flex w-fit shrink-0 items-center justify-center whitespace-nowrap",
5839
- "rounded-[var(--radius-xs)] border leading-none",
5840
- "transition-colors motion-reduce:transition-none"
5841
- ].join(" "),
5842
- {
5843
- variants: {
5844
- tier: {
5845
- primary: "px-[var(--space-2)] py-[calc(var(--space-1)/2)] text-xs font-medium",
5846
- secondary: "px-[var(--space-2)] py-[calc(var(--space-1)/2)] text-xs font-normal"
5847
- },
5848
- intent: {
5849
- neutral: "border-transparent bg-[var(--bg-raised)] text-foreground",
5850
- muted: "border-[var(--border-subtle)] bg-transparent text-text-tertiary",
5851
- brand: "border-[var(--border-accent)] bg-[var(--accent-bg-strong)] text-accent-fg",
5852
- success: "border-transparent bg-[var(--success-bg)] text-[var(--success)]",
5853
- warning: "border-transparent bg-[var(--warning-bg)] text-[var(--warning)]",
5854
- danger: "border-transparent bg-[var(--error-bg)] text-[var(--error)]"
5855
- }
5856
- },
5857
- defaultVariants: {
5858
- tier: "primary",
5859
- intent: "neutral"
5860
- }
5861
- }
5862
- );
5890
+ var FG = {
5891
+ neutral: "var(--text-secondary)",
5892
+ info: "var(--semantic-info-fg)",
5893
+ success: "var(--semantic-success-fg)",
5894
+ warning: "var(--semantic-warning-fg)",
5895
+ error: "var(--semantic-error-fg)"
5896
+ };
5897
+ var BG = {
5898
+ neutral: "var(--bg-inset)",
5899
+ info: "var(--semantic-info-bg)",
5900
+ success: "var(--semantic-success-bg)",
5901
+ warning: "var(--semantic-warning-bg)",
5902
+ error: "var(--semantic-error-bg)"
5903
+ };
5904
+ var SEGMENT = {
5905
+ xs: "gap-[5px] py-[2px] px-[var(--space-2)] text-[12px]",
5906
+ sm: "gap-[6px] py-[var(--space-1)] px-[var(--space-2)] text-[12px]",
5907
+ md: "gap-[7px] py-[var(--space-1)] px-[var(--space-3)] text-[14px]"
5908
+ };
5909
+ var DOT2 = { xs: 5, sm: 6, md: 7 };
5863
5910
  var TwoTierBadge = React28.forwardRef(
5864
- ({
5865
- className,
5866
- align,
5867
- primary,
5868
- secondary,
5869
- primaryIntent = "neutral",
5870
- secondaryIntent = "muted",
5871
- primaryClassName,
5872
- secondaryClassName,
5873
- ...props
5874
- }, ref) => /* @__PURE__ */ jsxs34(
5875
- "div",
5876
- {
5877
- ref,
5878
- "data-slot": "two-tier-badge",
5879
- className: cn(twoTierBadgeVariants({ align, className })),
5880
- ...props,
5881
- children: [
5882
- /* @__PURE__ */ jsx37(
5883
- "span",
5884
- {
5885
- "data-slot": "two-tier-badge-primary",
5886
- className: cn(
5887
- twoTierBadgeLineVariants({
5888
- tier: "primary",
5889
- intent: primaryIntent
5890
- }),
5891
- primaryClassName
5892
- ),
5893
- children: primary
5894
- }
5911
+ ({ primary, secondary, tone = "neutral", emphasis = "subtle", size = "sm", showDot = false, className, style, ...props }, ref) => {
5912
+ const strong = emphasis === "strong";
5913
+ const fg = FG[tone];
5914
+ const ringDot = tone === "neutral";
5915
+ const tinted = tone === "neutral" ? "var(--border)" : `color-mix(in srgb, ${fg} 26%, transparent)`;
5916
+ const frame = strong ? tinted : "var(--border-subtle)";
5917
+ const divider = strong ? tinted : "var(--border)";
5918
+ const dotSize = DOT2[size];
5919
+ return /* @__PURE__ */ jsxs34(
5920
+ "span",
5921
+ {
5922
+ ref,
5923
+ "data-slot": "two-tier-badge",
5924
+ "data-tone": tone,
5925
+ "data-emphasis": emphasis,
5926
+ className: cn(
5927
+ "inline-flex w-fit shrink-0 items-stretch overflow-hidden rounded-full border font-medium leading-none",
5928
+ className
5895
5929
  ),
5896
- secondary ? /* @__PURE__ */ jsx37(
5897
- "span",
5898
- {
5899
- "data-slot": "two-tier-badge-secondary",
5900
- className: cn(
5901
- twoTierBadgeLineVariants({
5902
- tier: "secondary",
5903
- intent: secondaryIntent
5904
- }),
5905
- secondaryClassName
5906
- ),
5907
- children: secondary
5908
- }
5909
- ) : null
5910
- ]
5911
- }
5912
- )
5930
+ style: { fontFamily: "var(--font-sans)", borderColor: frame, background: "transparent", ...style },
5931
+ ...props,
5932
+ children: [
5933
+ /* @__PURE__ */ jsxs34(
5934
+ "span",
5935
+ {
5936
+ "data-slot": "two-tier-badge-primary",
5937
+ className: cn("inline-flex items-center whitespace-nowrap font-semibold", SEGMENT[size]),
5938
+ style: { color: fg, background: strong ? BG[tone] : "transparent" },
5939
+ children: [
5940
+ showDot ? /* @__PURE__ */ jsx37(
5941
+ "span",
5942
+ {
5943
+ "aria-hidden": "true",
5944
+ "data-slot": "two-tier-badge-dot",
5945
+ "data-ring-dot": ringDot ? "true" : "false",
5946
+ className: "box-border shrink-0 rounded-full",
5947
+ style: {
5948
+ width: dotSize,
5949
+ height: dotSize,
5950
+ background: ringDot ? "transparent" : "currentColor",
5951
+ border: ringDot ? "1.5px solid currentColor" : "none"
5952
+ }
5953
+ }
5954
+ ) : null,
5955
+ /* @__PURE__ */ jsx37("span", { children: primary })
5956
+ ]
5957
+ }
5958
+ ),
5959
+ secondary != null ? /* @__PURE__ */ jsx37(
5960
+ "span",
5961
+ {
5962
+ "data-slot": "two-tier-badge-secondary",
5963
+ className: cn("inline-flex items-center whitespace-nowrap", SEGMENT[size]),
5964
+ style: {
5965
+ borderLeft: `1px solid ${divider}`,
5966
+ color: "var(--text-tertiary)",
5967
+ background: strong ? "var(--bg-inset)" : "transparent"
5968
+ },
5969
+ children: secondary
5970
+ }
5971
+ ) : null
5972
+ ]
5973
+ }
5974
+ );
5975
+ }
5913
5976
  );
5914
5977
  TwoTierBadge.displayName = "TwoTierBadge";
5915
5978
 
@@ -5925,14 +5988,14 @@ var ROLE = {
5925
5988
  success: "success",
5926
5989
  archived: "neutral"
5927
5990
  };
5928
- var FG = {
5991
+ var FG2 = {
5929
5992
  error: "var(--semantic-error-fg)",
5930
5993
  warning: "var(--semantic-warning-fg)",
5931
5994
  info: "var(--semantic-info-fg)",
5932
5995
  success: "var(--semantic-success-fg)",
5933
5996
  neutral: "var(--semantic-neutral-fg)"
5934
5997
  };
5935
- var BG = {
5998
+ var BG2 = {
5936
5999
  error: "var(--semantic-error-bg)",
5937
6000
  warning: "var(--semantic-warning-bg)",
5938
6001
  info: "var(--semantic-info-bg)",
@@ -5947,7 +6010,7 @@ var SIZE = {
5947
6010
  var StatusBadge = React29.forwardRef(
5948
6011
  ({ status = "active", emphasis = "subtle", size = "sm", showDot = true, pulse = true, className, children, style, ...props }, ref) => {
5949
6012
  const role = ROLE[status];
5950
- const fg = FG[role];
6013
+ const fg = FG2[role];
5951
6014
  const strong = emphasis === "strong";
5952
6015
  const ringDot = role === "neutral";
5953
6016
  return /* @__PURE__ */ jsxs35(
@@ -5961,7 +6024,7 @@ var StatusBadge = React29.forwardRef(
5961
6024
  className: cn("inline-flex w-fit shrink-0 items-center whitespace-nowrap rounded-full border font-medium leading-none", SIZE[size].cls, className),
5962
6025
  style: {
5963
6026
  fontFamily: "var(--font-sans)",
5964
- background: strong ? BG[role] : "transparent",
6027
+ background: strong ? BG2[role] : "transparent",
5965
6028
  borderColor: strong ? `color-mix(in srgb, ${fg} 26%, transparent)` : "var(--border-subtle)",
5966
6029
  color: fg,
5967
6030
  ...style
@@ -5996,9 +6059,9 @@ StatusBadge.displayName = "StatusBadge";
5996
6059
 
5997
6060
  // src/components/ui/notification-badge.tsx
5998
6061
  import * as React30 from "react";
5999
- import { cva as cva12 } from "class-variance-authority";
6062
+ import { cva as cva11 } from "class-variance-authority";
6000
6063
  import { jsx as jsx39 } from "react/jsx-runtime";
6001
- var notificationBadgeVariants = cva12(
6064
+ var notificationBadgeVariants = cva11(
6002
6065
  [
6003
6066
  "inline-flex shrink-0 items-center justify-center rounded-[var(--radius-full)]",
6004
6067
  "bg-[var(--semantic-error,var(--error))] text-[var(--error-contrast)]",
@@ -6062,11 +6125,11 @@ NotificationBadge.displayName = "NotificationBadge";
6062
6125
 
6063
6126
  // src/components/ui/chip.tsx
6064
6127
  import * as React31 from "react";
6065
- import { cva as cva13 } from "class-variance-authority";
6128
+ import { cva as cva12 } from "class-variance-authority";
6066
6129
  import { X as X3 } from "lucide-react";
6067
6130
  import { Slot as Slot2 } from "radix-ui";
6068
6131
  import { jsx as jsx40, jsxs as jsxs36 } from "react/jsx-runtime";
6069
- var chipVariants = cva13(
6132
+ var chipVariants = cva12(
6070
6133
  [
6071
6134
  "inline-flex w-fit shrink-0 items-center justify-center whitespace-nowrap",
6072
6135
  "rounded-[var(--radius-full)] border leading-none",
@@ -6087,7 +6150,7 @@ var chipVariants = cva13(
6087
6150
  },
6088
6151
  tone: {
6089
6152
  neutral: "border-[var(--border-subtle)] bg-[var(--bg-surface)] text-text-secondary hover:bg-[var(--action-hover)]",
6090
- accent: "border-[var(--border-accent)] bg-transparent text-[var(--accent-fg)] hover:bg-[var(--action-accent-hover)]",
6153
+ accent: "border-[var(--border-accent)] bg-transparent text-[var(--accent)] hover:bg-[var(--action-accent-hover)]",
6091
6154
  success: "border-transparent bg-[var(--success-bg)] text-[var(--success)] hover:bg-[var(--action-hover)]",
6092
6155
  warning: "border-transparent bg-[var(--warning-bg)] text-[var(--warning)] hover:bg-[var(--action-hover)]",
6093
6156
  danger: "border-transparent bg-[var(--error-bg)] text-[var(--error)] hover:bg-[var(--action-hover)]",
@@ -6110,10 +6173,10 @@ var chipVariants = cva13(
6110
6173
  className: "border-[var(--border-strong)] bg-[var(--action-selected)] text-foreground"
6111
6174
  },
6112
6175
  {
6113
- // R10 — wash 패턴 정합 (--accent-bg-strong deep olive wash / --accent-fg olive/lime text).
6176
+ // R10 — wash 패턴 정합 (--accent-bg-strong deep olive wash / --accent olive/lime text).
6114
6177
  pressed: true,
6115
6178
  tone: "accent",
6116
- className: "border-[var(--border-accent)] bg-[var(--accent-bg-strong)] text-[var(--accent-fg)]"
6179
+ className: "border-[var(--border-accent)] bg-[var(--accent-bg-strong)] text-[var(--accent)]"
6117
6180
  },
6118
6181
  {
6119
6182
  pressed: true,
@@ -6129,7 +6192,7 @@ var chipVariants = cva13(
6129
6192
  }
6130
6193
  }
6131
6194
  );
6132
- var chipCountVariants = cva13(
6195
+ var chipCountVariants = cva12(
6133
6196
  [
6134
6197
  "inline-flex min-w-[var(--space-4)] items-center justify-center",
6135
6198
  "rounded-[var(--radius-full)] px-[var(--space-1)]",
@@ -6139,7 +6202,7 @@ var chipCountVariants = cva13(
6139
6202
  variants: {
6140
6203
  tone: {
6141
6204
  neutral: "bg-[var(--bg-raised)] text-text-tertiary",
6142
- accent: "bg-[var(--accent-solid)] text-[var(--accent-on-solid)]",
6205
+ accent: "bg-[var(--accent-pop)] text-[var(--accent-on-fill)]",
6143
6206
  success: "bg-[var(--success)] text-[var(--success-contrast)]",
6144
6207
  warning: "bg-[var(--warning)] text-[var(--warning-contrast)]",
6145
6208
  danger: "bg-[var(--error)] text-[var(--error-contrast)]",
@@ -6254,9 +6317,9 @@ Chip.displayName = "Chip";
6254
6317
 
6255
6318
  // src/components/ui/empty-state.tsx
6256
6319
  import * as React32 from "react";
6257
- import { cva as cva14 } from "class-variance-authority";
6320
+ import { cva as cva13 } from "class-variance-authority";
6258
6321
  import { jsx as jsx41, jsxs as jsxs37 } from "react/jsx-runtime";
6259
- var emptyStateBaseVariants = cva14(
6322
+ var emptyStateBaseVariants = cva13(
6260
6323
  [
6261
6324
  "flex flex-col items-center justify-center text-center",
6262
6325
  "text-foreground"
@@ -6304,7 +6367,7 @@ function emptyStateVariants({
6304
6367
  className
6305
6368
  );
6306
6369
  }
6307
- var emptyStateIconVariants = cva14(
6370
+ var emptyStateIconVariants = cva13(
6308
6371
  [
6309
6372
  "inline-flex items-center justify-center rounded-[var(--radius-full)]",
6310
6373
  "border border-[var(--border-subtle)] bg-[var(--bg-raised)] text-text-tertiary"
@@ -6397,9 +6460,9 @@ EmptyState.displayName = "EmptyState";
6397
6460
  // src/components/ui/error-state.tsx
6398
6461
  import * as React33 from "react";
6399
6462
  import { AlertTriangle } from "lucide-react";
6400
- import { cva as cva15 } from "class-variance-authority";
6463
+ import { cva as cva14 } from "class-variance-authority";
6401
6464
  import { jsx as jsx42, jsxs as jsxs38 } from "react/jsx-runtime";
6402
- var errorStateVariants = cva15(
6465
+ var errorStateVariants = cva14(
6403
6466
  [
6404
6467
  "flex flex-col items-center justify-center text-center",
6405
6468
  "rounded-[var(--radius-md)] border border-[var(--border-subtle)]",
@@ -6484,9 +6547,9 @@ ErrorState.displayName = "ErrorState";
6484
6547
 
6485
6548
  // src/components/ui/skeleton.tsx
6486
6549
  import * as React34 from "react";
6487
- import { cva as cva16 } from "class-variance-authority";
6550
+ import { cva as cva15 } from "class-variance-authority";
6488
6551
  import { jsx as jsx43 } from "react/jsx-runtime";
6489
- var skeletonVariants = cva16(
6552
+ var skeletonVariants = cva15(
6490
6553
  [
6491
6554
  "animate-pulse rounded-[var(--radius-sm)] bg-[var(--bg-raised)]",
6492
6555
  "motion-reduce:animate-none motion-reduce:opacity-80"
@@ -6504,7 +6567,7 @@ var skeletonVariants = cva16(
6504
6567
  }
6505
6568
  }
6506
6569
  );
6507
- var spinnerVariants = cva16(
6570
+ var spinnerVariants = cva15(
6508
6571
  [
6509
6572
  "inline-block shrink-0 animate-spin rounded-[var(--radius-full)] border-2",
6510
6573
  "border-[var(--border-subtle)] border-t-[var(--primary)]",
@@ -6635,9 +6698,9 @@ Spinner.displayName = "Spinner";
6635
6698
 
6636
6699
  // src/components/ui/icon-button.tsx
6637
6700
  import * as React35 from "react";
6638
- import { cva as cva17 } from "class-variance-authority";
6701
+ import { cva as cva16 } from "class-variance-authority";
6639
6702
  import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
6640
- var iconButtonVariants = cva17(
6703
+ var iconButtonVariants = cva16(
6641
6704
  [
6642
6705
  "olun-icon-button relative inline-flex cursor-pointer shrink-0 items-center justify-center",
6643
6706
  "rounded-[var(--radius-sm)] border font-medium",
@@ -6683,7 +6746,7 @@ var iconButtonVariants = cva17(
6683
6746
  }
6684
6747
  }
6685
6748
  );
6686
- var iconButtonBadgeVariants = cva17(
6749
+ var iconButtonBadgeVariants = cva16(
6687
6750
  [
6688
6751
  "pointer-events-none absolute right-0 top-0 inline-flex",
6689
6752
  "olun-icon-button__badge",
@@ -6695,7 +6758,7 @@ var iconButtonBadgeVariants = cva17(
6695
6758
  {
6696
6759
  variants: {
6697
6760
  tone: {
6698
- info: "bg-[var(--accent-solid)] text-[var(--accent-on-solid)]",
6761
+ info: "bg-[var(--accent-pop)] text-[var(--accent-on-fill)]",
6699
6762
  error: "bg-[var(--error)] text-[var(--error-contrast)]"
6700
6763
  }
6701
6764
  },
@@ -6780,7 +6843,7 @@ IconButton.displayName = "IconButton";
6780
6843
  // src/components/ui/pagination.tsx
6781
6844
  import * as React36 from "react";
6782
6845
  import { ChevronsLeft, ChevronLeft, ChevronRight as ChevronRight2, ChevronsRight } from "lucide-react";
6783
- import { cva as cva18 } from "class-variance-authority";
6846
+ import { cva as cva17 } from "class-variance-authority";
6784
6847
 
6785
6848
  // src/components/ui/page-size-select.tsx
6786
6849
  import { jsx as jsx45, jsxs as jsxs40 } from "react/jsx-runtime";
@@ -6835,7 +6898,7 @@ function PageSizeSelect({
6835
6898
 
6836
6899
  // src/components/ui/pagination.tsx
6837
6900
  import { jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
6838
- var paginationVariants = cva18(
6901
+ var paginationVariants = cva17(
6839
6902
  [
6840
6903
  "flex w-full flex-col gap-[var(--space-3)]",
6841
6904
  "text-sm text-text-secondary",
@@ -6853,7 +6916,7 @@ var paginationVariants = cva18(
6853
6916
  }
6854
6917
  }
6855
6918
  );
6856
- var paginationControlVariants = cva18(
6919
+ var paginationControlVariants = cva17(
6857
6920
  [
6858
6921
  "inline-flex shrink-0 items-center justify-center rounded-[var(--radius-sm)] border",
6859
6922
  "border-transparent bg-transparent font-medium text-text-secondary",
@@ -7056,26 +7119,26 @@ var Pagination = React36.forwardRef(
7056
7119
  Pagination.displayName = "Pagination";
7057
7120
 
7058
7121
  // src/components/ui/mode-toggle.tsx
7059
- import { cva as cva19 } from "class-variance-authority";
7122
+ import { cva as cva18 } from "class-variance-authority";
7060
7123
  import { jsx as jsx47, jsxs as jsxs42 } from "react/jsx-runtime";
7061
- var modeToggleVariants = cva19(
7124
+ var modeToggleVariants = cva18(
7062
7125
  [
7063
7126
  "inline-flex items-center rounded-[var(--radius-sm)] border border-[var(--border-subtle)]",
7064
7127
  "bg-[var(--bg-raised)] p-[2px]"
7065
7128
  ].join(" ")
7066
7129
  );
7067
- var modeToggleItemVariants = cva19(
7130
+ var modeToggleItemVariants = cva18(
7068
7131
  [
7069
7132
  "inline-flex min-h-[28px] cursor-pointer items-center justify-center gap-[var(--space-1)]",
7070
7133
  "rounded-[calc(var(--radius-sm)_-_2px)] px-[var(--space-3)] py-[var(--space-1)]",
7071
7134
  "font-[family-name:var(--font-display)] text-xs font-medium leading-none",
7072
7135
  "text-text-secondary transition-[background-color,color,box-shadow]",
7073
- "duration-[var(--duration-fast)] ease-[var(--ease-standard)]",
7136
+ "duration-[var(--dur-fast)] ease-[var(--ease-standard)]",
7074
7137
  "hover:text-foreground",
7075
7138
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)]",
7076
7139
  "disabled:cursor-not-allowed disabled:text-text-disabled disabled:hover:text-text-disabled",
7077
7140
  "data-[state=active]:bg-[var(--bg-surface)] data-[state=active]:font-semibold",
7078
- "data-[state=active]:text-foreground data-[state=active]:shadow-[var(--elevation-1)]",
7141
+ "data-[state=active]:text-foreground data-[state=active]:shadow-[var(--shadow-1)]",
7079
7142
  "[&_svg]:pointer-events-none [&_svg]:size-[14px] [&_svg]:shrink-0 [&_svg]:stroke-[1.75]"
7080
7143
  ].join(" ")
7081
7144
  );
@@ -7126,9 +7189,9 @@ function ModeToggle({
7126
7189
 
7127
7190
  // src/components/ui/action-footer.tsx
7128
7191
  import * as React37 from "react";
7129
- import { cva as cva20 } from "class-variance-authority";
7192
+ import { cva as cva19 } from "class-variance-authority";
7130
7193
  import { jsx as jsx48, jsxs as jsxs43 } from "react/jsx-runtime";
7131
- var actionFooterVariants = cva20(
7194
+ var actionFooterVariants = cva19(
7132
7195
  [
7133
7196
  "flex flex-wrap items-center gap-[var(--space-4)] border-t border-[var(--border-subtle)]",
7134
7197
  "px-[var(--space-6)] py-[var(--space-4)]",
@@ -7150,7 +7213,7 @@ var actionFooterVariants = cva20(
7150
7213
  }
7151
7214
  }
7152
7215
  );
7153
- var actionFooterStatusVariants = cva20(
7216
+ var actionFooterStatusVariants = cva19(
7154
7217
  [
7155
7218
  "flex min-w-0 flex-1 items-center gap-[var(--space-2)]",
7156
7219
  "text-sm leading-snug text-text-tertiary"
@@ -7283,21 +7346,21 @@ ActionFooter.displayName = "ActionFooter";
7283
7346
 
7284
7347
  // src/components/ui/toast.tsx
7285
7348
  import * as React38 from "react";
7286
- import { cva as cva21 } from "class-variance-authority";
7349
+ import { cva as cva20 } from "class-variance-authority";
7287
7350
  import { jsx as jsx49, jsxs as jsxs44 } from "react/jsx-runtime";
7288
- var DOT2 = {
7351
+ var DOT3 = {
7289
7352
  default: "var(--neutral)",
7290
7353
  success: "var(--success)",
7291
7354
  warning: "var(--warning)",
7292
7355
  info: "var(--info)",
7293
7356
  error: "var(--error)"
7294
7357
  };
7295
- var toastVariants = cva21(
7358
+ var toastVariants = cva20(
7296
7359
  [
7297
7360
  "flex min-w-[280px] max-w-[420px] items-center",
7298
7361
  "gap-[11px] rounded-[10px] border border-[var(--border)]",
7299
7362
  "px-[14px] py-[11px]",
7300
- "shadow-[var(--elevation-4)]",
7363
+ "shadow-[var(--shadow-4)]",
7301
7364
  "pointer-events-auto",
7302
7365
  "motion-reduce:animate-none"
7303
7366
  ].join(" "),
@@ -7314,7 +7377,7 @@ var toastVariants = cva21(
7314
7377
  defaultVariants: { variant: "default" }
7315
7378
  }
7316
7379
  );
7317
- var toastViewportVariants = cva21(
7380
+ var toastViewportVariants = cva20(
7318
7381
  [
7319
7382
  "fixed bottom-[var(--space-6)] right-[var(--space-6)] z-[var(--z-toast,50)]",
7320
7383
  "flex w-[min(420px,calc(100vw-var(--space-12)))] list-none flex-col gap-[var(--space-2)]",
@@ -7465,7 +7528,7 @@ var ToastRoot = React38.forwardRef(
7465
7528
  "aria-hidden": "true",
7466
7529
  "data-slot": "toast-dot",
7467
7530
  className: "size-[7px] shrink-0 rounded-full",
7468
- style: { background: DOT2[variant] ?? DOT2.default }
7531
+ style: { background: DOT3[variant] ?? DOT3.default }
7469
7532
  }
7470
7533
  ),
7471
7534
  /* @__PURE__ */ jsxs44("div", { "data-slot": "toast-body", className: "min-w-0 flex-1", children: [
@@ -7545,10 +7608,10 @@ function ToastProvider({ children, maxToasts = 3, className, ...props }) {
7545
7608
 
7546
7609
  // src/components/ui/otp-field.tsx
7547
7610
  import * as React39 from "react";
7548
- import { cva as cva22 } from "class-variance-authority";
7611
+ import { cva as cva21 } from "class-variance-authority";
7549
7612
  import { AlertCircle as AlertCircle4 } from "lucide-react";
7550
- import { Fragment as Fragment9, jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
7551
- var otpFieldVariants = cva22("flex w-full min-w-0 flex-col gap-[var(--space-3)]", {
7613
+ import { Fragment as Fragment8, jsx as jsx50, jsxs as jsxs45 } from "react/jsx-runtime";
7614
+ var otpFieldVariants = cva21("flex w-full min-w-0 flex-col gap-[var(--space-3)]", {
7552
7615
  variants: {
7553
7616
  size: {
7554
7617
  default: "",
@@ -7559,7 +7622,7 @@ var otpFieldVariants = cva22("flex w-full min-w-0 flex-col gap-[var(--space-3)]"
7559
7622
  size: "default"
7560
7623
  }
7561
7624
  });
7562
- var otpFieldGroupVariants = cva22("flex items-start gap-[var(--space-2)] pt-[var(--space-1)]", {
7625
+ var otpFieldGroupVariants = cva21("flex items-start gap-[var(--space-2)] pt-[var(--space-1)]", {
7563
7626
  variants: {
7564
7627
  size: {
7565
7628
  default: "",
@@ -7575,7 +7638,7 @@ var otpFieldGroupVariants = cva22("flex items-start gap-[var(--space-2)] pt-[var
7575
7638
  fluid: false
7576
7639
  }
7577
7640
  });
7578
- var otpCellVariants = cva22(
7641
+ var otpCellVariants = cva21(
7579
7642
  [
7580
7643
  "flex items-center justify-center rounded-[var(--radius-sm)] border",
7581
7644
  "border-[var(--border)] text-foreground",
@@ -7630,7 +7693,7 @@ var otpCellVariants = cva22(
7630
7693
  }
7631
7694
  }
7632
7695
  );
7633
- var otpFieldMessageVariants = cva22("flex items-start gap-[var(--space-1)] text-xs leading-snug", {
7696
+ var otpFieldMessageVariants = cva21("flex items-start gap-[var(--space-1)] text-xs leading-snug", {
7634
7697
  variants: {
7635
7698
  state: {
7636
7699
  default: "text-text-tertiary",
@@ -7869,7 +7932,7 @@ var OTPField = React39.forwardRef(
7869
7932
  "data-slot": "otp-field-message",
7870
7933
  "data-kind": errorText ? "error" : "helper",
7871
7934
  className: otpFieldMessageVariants({ state: resolvedState }),
7872
- children: errorText ? /* @__PURE__ */ jsxs45(Fragment9, { children: [
7935
+ children: errorText ? /* @__PURE__ */ jsxs45(Fragment8, { children: [
7873
7936
  /* @__PURE__ */ jsx50(
7874
7937
  AlertCircle4,
7875
7938
  {
@@ -7905,9 +7968,9 @@ OTPField.displayName = "OTPField";
7905
7968
  // src/components/ui/search-field.tsx
7906
7969
  import * as React40 from "react";
7907
7970
  import { Search, X as X4 } from "lucide-react";
7908
- import { cva as cva23 } from "class-variance-authority";
7971
+ import { cva as cva22 } from "class-variance-authority";
7909
7972
  import { jsx as jsx51, jsxs as jsxs46 } from "react/jsx-runtime";
7910
- var searchFieldVariants = cva23("relative flex w-full items-center", {
7973
+ var searchFieldVariants = cva22("relative flex w-full items-center", {
7911
7974
  variants: {
7912
7975
  size: {
7913
7976
  // Field-control scale follows Select: sm/md/lg = 30/32/36px. Pair with Button sm/md/lg.
@@ -7920,7 +7983,7 @@ var searchFieldVariants = cva23("relative flex w-full items-center", {
7920
7983
  size: "md"
7921
7984
  }
7922
7985
  });
7923
- var searchFieldInputVariants = cva23(
7986
+ var searchFieldInputVariants = cva22(
7924
7987
  [
7925
7988
  "h-full w-full rounded-[var(--radius-sm)] border",
7926
7989
  "border-[var(--border)]",
@@ -8063,9 +8126,9 @@ SearchField.displayName = "SearchField";
8063
8126
 
8064
8127
  // src/components/ui/checkbox-group.tsx
8065
8128
  import * as React41 from "react";
8066
- import { cva as cva24 } from "class-variance-authority";
8129
+ import { cva as cva23 } from "class-variance-authority";
8067
8130
  import { jsx as jsx52 } from "react/jsx-runtime";
8068
- var checkboxGroupVariants = cva24("gap-[var(--space-2)]", {
8131
+ var checkboxGroupVariants = cva23("gap-[var(--space-2)]", {
8069
8132
  variants: {
8070
8133
  appearance: {
8071
8134
  plain: "flex",
@@ -8165,11 +8228,11 @@ CheckboxGroup.displayName = "CheckboxGroup";
8165
8228
 
8166
8229
  // src/components/ui/radio-group.tsx
8167
8230
  import * as React42 from "react";
8168
- import { cva as cva25 } from "class-variance-authority";
8231
+ import { cva as cva24 } from "class-variance-authority";
8169
8232
  import { Circle } from "lucide-react";
8170
8233
  import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
8171
8234
  import { jsx as jsx53, jsxs as jsxs47 } from "react/jsx-runtime";
8172
- var radioGroupVariants = cva25("gap-[var(--space-2)]", {
8235
+ var radioGroupVariants = cva24("gap-[var(--space-2)]", {
8173
8236
  variants: {
8174
8237
  appearance: {
8175
8238
  plain: "flex",
@@ -8194,7 +8257,7 @@ var radioGroupVariants = cva25("gap-[var(--space-2)]", {
8194
8257
  columns: "one"
8195
8258
  }
8196
8259
  });
8197
- var radioVariants = cva25(
8260
+ var radioVariants = cva24(
8198
8261
  [
8199
8262
  "group w-full cursor-pointer text-left transition-colors motion-reduce:transition-none",
8200
8263
  "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--focus-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--bg-base)]",
@@ -8236,7 +8299,7 @@ var radioVariants = cva25(
8236
8299
  }
8237
8300
  }
8238
8301
  );
8239
- var radioControlVariants = cva25(
8302
+ var radioControlVariants = cva24(
8240
8303
  [
8241
8304
  "flex size-[calc(var(--space-4)+var(--space-1))] shrink-0 items-center justify-center",
8242
8305
  "rounded-[var(--radius-full)] border border-[var(--border-strong)] bg-[var(--bg-surface)] text-transparent",
@@ -8471,16 +8534,16 @@ function Progress({
8471
8534
  // src/components/ui/tree-view.tsx
8472
8535
  import * as React43 from "react";
8473
8536
  import { ChevronRight as ChevronRight3 } from "lucide-react";
8474
- import { cva as cva26 } from "class-variance-authority";
8537
+ import { cva as cva25 } from "class-variance-authority";
8475
8538
  import { jsx as jsx56, jsxs as jsxs49 } from "react/jsx-runtime";
8476
- var treeViewVariants = cva26(
8539
+ var treeViewVariants = cva25(
8477
8540
  "m-0 list-none p-[var(--space-1)] text-body-sm text-foreground"
8478
8541
  );
8479
- var treeItemRowVariants = cva26(
8542
+ var treeItemRowVariants = cva25(
8480
8543
  [
8481
8544
  "flex min-h-[32px] w-full cursor-pointer select-none items-center gap-[var(--space-2)]",
8482
8545
  "rounded-[var(--radius-sm)] py-[var(--space-2)] pr-[var(--space-3)]",
8483
- "text-text-secondary transition-colors duration-[var(--duration-fast)] ease-[var(--ease-standard)] motion-reduce:transition-none",
8546
+ "text-text-secondary transition-colors duration-[var(--dur-fast)] ease-[var(--ease-standard)] motion-reduce:transition-none",
8484
8547
  "hover:bg-[var(--action-hover)] hover:text-foreground",
8485
8548
  // Roving focus lives on the treeitem <li> (named group/treeitem); the ring is
8486
8549
  // painted on the visual row so it never wraps the nested child group.
@@ -8692,7 +8755,7 @@ function TreeView({
8692
8755
  "aria-hidden": "true",
8693
8756
  "data-slot": "treeitem-chevron",
8694
8757
  className: cn(
8695
- "size-[16px] transition-transform duration-[var(--duration-fast)] ease-[var(--ease-standard)] motion-reduce:transition-none",
8758
+ "size-[16px] transition-transform duration-[var(--dur-fast)] ease-[var(--ease-standard)] motion-reduce:transition-none",
8696
8759
  expanded && "rotate-90"
8697
8760
  ),
8698
8761
  strokeWidth: 2
@@ -8759,7 +8822,7 @@ function OlunSymbol({ size = 28, className }) {
8759
8822
  style: { color: "var(--text-primary)" }
8760
8823
  }
8761
8824
  ),
8762
- /* @__PURE__ */ jsx57("circle", { cx: "185", cy: "175", r: "22", fill: "var(--accent-solid)" })
8825
+ /* @__PURE__ */ jsx57("circle", { cx: "185", cy: "175", r: "22", fill: "var(--accent-pop)" })
8763
8826
  ]
8764
8827
  }
8765
8828
  );
@@ -8793,7 +8856,7 @@ function OlunLogo({
8793
8856
  },
8794
8857
  children: [
8795
8858
  "OLUN",
8796
- /* @__PURE__ */ jsx57("span", { style: { color: "var(--accent-fg)" }, children: "." })
8859
+ /* @__PURE__ */ jsx57("span", { style: { color: "var(--accent)" }, children: "." })
8797
8860
  ]
8798
8861
  }
8799
8862
  )
@@ -8862,7 +8925,7 @@ function ThemeFab({ variant = "square" } = {}) {
8862
8925
  border: "1px solid var(--border-accent)",
8863
8926
  background: "var(--theme-fab-bg, var(--bg-surface))",
8864
8927
  color: "var(--theme-fab-icon, var(--text-primary))",
8865
- boxShadow: "var(--elevation-4)",
8928
+ boxShadow: "var(--shadow-4)",
8866
8929
  backdropFilter: "blur(16px)",
8867
8930
  WebkitBackdropFilter: "blur(16px)",
8868
8931
  zIndex: 9999
@@ -9144,8 +9207,6 @@ export {
9144
9207
  toastViewportVariants,
9145
9208
  treeItemRowVariants,
9146
9209
  treeViewVariants,
9147
- twoTierBadgeLineVariants,
9148
- twoTierBadgeVariants,
9149
9210
  useOlunTheme,
9150
9211
  usePermission
9151
9212
  };