@memelabui/ui 0.3.0 → 0.4.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/README.md CHANGED
@@ -51,7 +51,7 @@ function App() {
51
51
  }
52
52
  ```
53
53
 
54
- ## Components (43 exports)
54
+ ## Components (50+ exports)
55
55
 
56
56
  ### Form
57
57
 
@@ -63,7 +63,7 @@ function App() {
63
63
  | `Textarea` | Multiline text input with label/error |
64
64
  | `Checkbox` | Custom checkbox with indeterminate support |
65
65
  | `RadioGroup` / `RadioItem` | Compound radio button group |
66
- | `Toggle` | Switch toggle (sm/md sizes) |
66
+ | `Toggle` | Switch toggle (sm/md sizes) with `busy` spinner state |
67
67
  | `Slider` | Range input with custom track/thumb and value display |
68
68
  | `TagInput` | Tag input with Enter/comma/paste, dedup, maxTags |
69
69
  | `ColorInput` | Hex color picker with swatch + text input |
@@ -82,6 +82,7 @@ function App() {
82
82
  | Component | Description |
83
83
  |-----------|-------------|
84
84
  | `Card` | Surface or glass card container |
85
+ | `SectionCard` | Settings section card with title, description, right slot, overlay slot |
85
86
  | `Badge` / `Pill` | Status badges (neutral, primary, success, danger, warning, accent) |
86
87
  | `StatCard` | Dashboard stat card with value, label, icon, trend indicator |
87
88
  | `Table` / `TableHeader` / `TableBody` / `TableRow` / `TableHead` / `TableCell` | Styled table primitives |
@@ -93,6 +94,16 @@ function App() {
93
94
  | `DropZone` | Drag & drop file upload area with accept filter |
94
95
  | `Avatar` | Circular avatar with image + initials fallback |
95
96
  | `Divider` | Horizontal/vertical divider with optional label |
97
+ | `ActiveFilterPills` | Dismissible filter pill row with "Clear all" action |
98
+ | `DotIndicator` | Dot-based remaining count with urgency colors |
99
+
100
+ ### Progress & Status
101
+
102
+ | Component | Description |
103
+ |-----------|-------------|
104
+ | `ProgressBar` | Horizontal progress bar with variants and sizes |
105
+ | `CooldownRing` | SVG circular countdown timer with color changes and pulse |
106
+ | `StageProgress` | Multi-stage process indicator with shimmer animation |
96
107
 
97
108
  ### Navigation
98
109
 
@@ -109,6 +120,7 @@ function App() {
109
120
  | `ConfirmDialog` | Confirmation modal with cancel/confirm actions |
110
121
  | `Tooltip` | Hover/focus tooltip with portal positioning |
111
122
  | `Dropdown` | Compound menu (Trigger, Menu, Item, Separator) |
123
+ | `MutationOverlay` | Saving/saved/error status overlay for cards |
112
124
 
113
125
  ### Layout
114
126
 
@@ -126,7 +138,6 @@ function App() {
126
138
  | `ToastProvider` / `useToast` | Toast notification system with variants |
127
139
  | `Alert` | Inline notification banner (info, success, warning, error) |
128
140
  | `CopyField` | Read-only field with copy button and optional masking |
129
- | `ProgressBar` | Horizontal progress bar with variants and sizes |
130
141
 
131
142
  ### Hooks
132
143
 
package/dist/index.cjs CHANGED
@@ -558,7 +558,7 @@ var thumbSize = {
558
558
  sm: { base: "w-4 h-4", translate: "translate-x-4" },
559
559
  md: { base: "w-5 h-5", translate: "translate-x-5" }
560
560
  };
561
- var Toggle = React.forwardRef(function Toggle2({ checked, onChange, disabled, label, size = "md", id: externalId, "aria-label": ariaLabel }, ref) {
561
+ var Toggle = React.forwardRef(function Toggle2({ checked, onChange, disabled, busy, label, size = "md", id: externalId, "aria-label": ariaLabel }, ref) {
562
562
  const generatedId = React.useId();
563
563
  const toggleId = externalId || generatedId;
564
564
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
@@ -571,7 +571,8 @@ var Toggle = React.forwardRef(function Toggle2({ checked, onChange, disabled, la
571
571
  role: "switch",
572
572
  "aria-checked": checked,
573
573
  "aria-label": ariaLabel || label,
574
- disabled,
574
+ disabled: disabled || busy,
575
+ "aria-busy": busy || void 0,
575
576
  onClick: () => onChange(!checked),
576
577
  className: cn(
577
578
  "relative rounded-full transition-colors duration-200 focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-surface",
@@ -583,9 +584,18 @@ var Toggle = React.forwardRef(function Toggle2({ checked, onChange, disabled, la
583
584
  "span",
584
585
  {
585
586
  className: cn(
586
- "absolute top-0.5 left-0.5 rounded-full bg-white transition-transform duration-200",
587
+ "absolute top-0.5 left-0.5 rounded-full bg-white transition-transform duration-200 flex items-center justify-center",
587
588
  thumbSize[size].base,
588
589
  checked ? thumbSize[size].translate : "translate-x-0"
590
+ ),
591
+ children: busy && /* @__PURE__ */ jsxRuntime.jsx(
592
+ "span",
593
+ {
594
+ className: cn(
595
+ "border-2 border-primary/30 border-t-primary rounded-full animate-spin",
596
+ size === "sm" ? "w-2.5 h-2.5" : "w-3 h-3"
597
+ )
598
+ }
589
599
  )
590
600
  }
591
601
  )
@@ -2257,6 +2267,309 @@ function ProgressBar({
2257
2267
  )
2258
2268
  ] });
2259
2269
  }
2270
+ var sizeMap = {
2271
+ sm: "w-8 h-8 text-xs",
2272
+ md: "w-12 h-12 text-sm",
2273
+ lg: "w-16 h-16 text-base"
2274
+ };
2275
+ var strokeWidthMap = {
2276
+ sm: 3,
2277
+ md: 3.5,
2278
+ lg: 4
2279
+ };
2280
+ var RADIUS = 15.9155;
2281
+ var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
2282
+ function CooldownRing({
2283
+ duration,
2284
+ remaining,
2285
+ size = "md",
2286
+ className
2287
+ }) {
2288
+ const fraction = duration > 0 ? Math.max(0, Math.min(1, remaining / duration)) : 0;
2289
+ const offset = CIRCUMFERENCE * (1 - fraction);
2290
+ const color = fraction > 0.5 ? "text-primary" : fraction > 0.25 ? "text-amber-500" : "text-rose-500";
2291
+ const pulse = remaining <= 10 && remaining > 0;
2292
+ const strokeWidth = strokeWidthMap[size];
2293
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative inline-flex items-center justify-center", sizeMap[size], className), children: [
2294
+ /* @__PURE__ */ jsxRuntime.jsxs(
2295
+ "svg",
2296
+ {
2297
+ viewBox: "0 0 36 36",
2298
+ className: cn("w-full h-full -rotate-90", color, pulse && "animate-pulse"),
2299
+ "aria-label": `Cooldown: ${remaining} seconds remaining`,
2300
+ role: "img",
2301
+ children: [
2302
+ /* @__PURE__ */ jsxRuntime.jsx(
2303
+ "circle",
2304
+ {
2305
+ cx: "18",
2306
+ cy: "18",
2307
+ r: RADIUS,
2308
+ fill: "none",
2309
+ stroke: "currentColor",
2310
+ strokeWidth,
2311
+ className: "text-white/10"
2312
+ }
2313
+ ),
2314
+ /* @__PURE__ */ jsxRuntime.jsx(
2315
+ "circle",
2316
+ {
2317
+ cx: "18",
2318
+ cy: "18",
2319
+ r: RADIUS,
2320
+ fill: "none",
2321
+ stroke: "currentColor",
2322
+ strokeWidth,
2323
+ strokeDasharray: `${CIRCUMFERENCE} ${CIRCUMFERENCE}`,
2324
+ strokeDashoffset: offset,
2325
+ strokeLinecap: "round",
2326
+ style: { transition: "stroke-dashoffset 0.6s ease" }
2327
+ }
2328
+ )
2329
+ ]
2330
+ }
2331
+ ),
2332
+ /* @__PURE__ */ jsxRuntime.jsx(
2333
+ "span",
2334
+ {
2335
+ className: "absolute font-semibold tabular-nums text-white select-none",
2336
+ style: { lineHeight: 1 },
2337
+ children: Math.max(0, Math.ceil(remaining))
2338
+ }
2339
+ )
2340
+ ] });
2341
+ }
2342
+ function StageProgress({ stages, activeStage, className }) {
2343
+ const clampedActive = Math.max(0, Math.min(activeStage, stages.length - 1));
2344
+ const fillPercent = stages.length <= 1 ? 100 : clampedActive / (stages.length - 1) * 100;
2345
+ const isComplete = clampedActive >= stages.length - 1;
2346
+ const isAnimating = !isComplete;
2347
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full", className), children: [
2348
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-between", children: stages.map((stage, index) => {
2349
+ const isCompleted = index < clampedActive;
2350
+ const isActive = index === clampedActive;
2351
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2352
+ "div",
2353
+ {
2354
+ className: cn(
2355
+ "flex items-center gap-1.5 text-xs font-medium transition-colors duration-300",
2356
+ isCompleted && "text-emerald-400",
2357
+ isActive && "text-white",
2358
+ !isCompleted && !isActive && "text-white/40"
2359
+ ),
2360
+ children: [
2361
+ isCompleted ? (
2362
+ // Completed: emerald check circle
2363
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-3.5 w-3.5 items-center justify-center rounded-full bg-emerald-400/20", children: /* @__PURE__ */ jsxRuntime.jsx(
2364
+ "svg",
2365
+ {
2366
+ className: "h-2.5 w-2.5 text-emerald-400",
2367
+ viewBox: "0 0 10 10",
2368
+ fill: "none",
2369
+ xmlns: "http://www.w3.org/2000/svg",
2370
+ "aria-hidden": "true",
2371
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2372
+ "path",
2373
+ {
2374
+ d: "M2 5.5L4 7.5L8 3",
2375
+ stroke: "currentColor",
2376
+ strokeWidth: "1.5",
2377
+ strokeLinecap: "round",
2378
+ strokeLinejoin: "round"
2379
+ }
2380
+ )
2381
+ }
2382
+ ) })
2383
+ ) : isActive ? (
2384
+ // Active: primary dot with ring
2385
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-3.5 w-3.5 items-center justify-center rounded-full ring-2 ring-[var(--ml-primary)] ring-offset-1 ring-offset-black/50", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-[var(--ml-primary)]" }) })
2386
+ ) : (
2387
+ // Upcoming: hollow dim dot
2388
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-3.5 w-3.5 rounded-full border border-white/20 bg-transparent" })
2389
+ ),
2390
+ stage
2391
+ ]
2392
+ },
2393
+ stage
2394
+ );
2395
+ }) }),
2396
+ /* @__PURE__ */ jsxRuntime.jsx(
2397
+ "div",
2398
+ {
2399
+ className: "relative mt-3 h-1.5 w-full overflow-hidden rounded-full bg-white/10",
2400
+ role: "progressbar",
2401
+ "aria-valuenow": clampedActive,
2402
+ "aria-valuemin": 0,
2403
+ "aria-valuemax": stages.length - 1,
2404
+ "aria-label": `Stage ${clampedActive + 1} of ${stages.length}: ${stages[clampedActive]}`,
2405
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2406
+ "div",
2407
+ {
2408
+ className: "h-full rounded-full bg-gradient-to-r from-[var(--ml-accent)] to-[var(--ml-primary)] transition-[width] duration-500 ease-in-out",
2409
+ style: { width: `${fillPercent}%` },
2410
+ children: isAnimating && /* @__PURE__ */ jsxRuntime.jsx(
2411
+ "span",
2412
+ {
2413
+ className: "pointer-events-none absolute inset-0 -translate-x-full animate-[ml-shimmer_2s_ease-in-out_infinite] bg-gradient-to-r from-transparent via-white/30 to-transparent",
2414
+ "aria-hidden": "true"
2415
+ }
2416
+ )
2417
+ }
2418
+ )
2419
+ }
2420
+ )
2421
+ ] });
2422
+ }
2423
+ function getUrgencyClasses(remaining, max) {
2424
+ const ratio = max > 0 ? remaining / max : 0;
2425
+ if (ratio > 0.5) {
2426
+ return {
2427
+ filled: "bg-emerald-400",
2428
+ empty: "bg-emerald-400/30",
2429
+ label: "text-emerald-400"
2430
+ };
2431
+ }
2432
+ if (ratio > 0.25) {
2433
+ return {
2434
+ filled: "bg-amber-400",
2435
+ empty: "bg-amber-400/30",
2436
+ label: "text-amber-400"
2437
+ };
2438
+ }
2439
+ return {
2440
+ filled: "bg-rose-400",
2441
+ empty: "bg-rose-400/30",
2442
+ label: "text-rose-400"
2443
+ };
2444
+ }
2445
+ function DotIndicator({
2446
+ remaining,
2447
+ max,
2448
+ showLabel = false,
2449
+ labelFormat,
2450
+ className
2451
+ }) {
2452
+ const clampedRemaining = Math.max(0, Math.min(remaining, max));
2453
+ const used = max - clampedRemaining;
2454
+ const urgency = getUrgencyClasses(clampedRemaining, max);
2455
+ const defaultLabel = `${clampedRemaining}/${max}`;
2456
+ const label = labelFormat ? labelFormat(clampedRemaining, max) : defaultLabel;
2457
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("inline-flex items-center gap-2", className), children: [
2458
+ /* @__PURE__ */ jsxRuntime.jsx(
2459
+ "div",
2460
+ {
2461
+ className: "flex items-center gap-1",
2462
+ role: "meter",
2463
+ "aria-valuenow": clampedRemaining,
2464
+ "aria-valuemin": 0,
2465
+ "aria-valuemax": max,
2466
+ "aria-label": label,
2467
+ children: Array.from({ length: max }, (_, index) => {
2468
+ const isFilled = index < used;
2469
+ return /* @__PURE__ */ jsxRuntime.jsx(
2470
+ "span",
2471
+ {
2472
+ className: cn(
2473
+ "h-2 w-2 rounded-full transition-colors duration-300",
2474
+ isFilled ? urgency.filled : urgency.empty
2475
+ ),
2476
+ "aria-hidden": "true"
2477
+ },
2478
+ index
2479
+ );
2480
+ })
2481
+ }
2482
+ ),
2483
+ showLabel && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-xs font-medium tabular-nums", urgency.label), children: label })
2484
+ ] });
2485
+ }
2486
+ function ActiveFilterPills({
2487
+ filters,
2488
+ onRemove,
2489
+ onClearAll,
2490
+ clearAllLabel = "Clear all",
2491
+ className
2492
+ }) {
2493
+ if (filters.length === 0) return null;
2494
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-wrap items-center gap-1.5", className), children: [
2495
+ filters.map((filter) => /* @__PURE__ */ jsxRuntime.jsxs(
2496
+ "span",
2497
+ {
2498
+ className: "inline-flex items-center gap-1 rounded-full bg-white/10 px-2.5 py-1 text-xs text-white/80 ring-1 ring-white/10",
2499
+ children: [
2500
+ filter.label,
2501
+ /* @__PURE__ */ jsxRuntime.jsx(
2502
+ "button",
2503
+ {
2504
+ type: "button",
2505
+ onClick: () => onRemove(filter.key),
2506
+ className: "ml-0.5 text-white/50 transition-colors duration-150 hover:text-white focus:outline-none focus-visible:text-white",
2507
+ "aria-label": `Remove filter: ${filter.label}`,
2508
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2509
+ "svg",
2510
+ {
2511
+ className: "h-3 w-3",
2512
+ viewBox: "0 0 12 12",
2513
+ fill: "none",
2514
+ xmlns: "http://www.w3.org/2000/svg",
2515
+ "aria-hidden": "true",
2516
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2517
+ "path",
2518
+ {
2519
+ d: "M9 3L3 9M3 3L9 9",
2520
+ stroke: "currentColor",
2521
+ strokeWidth: "1.5",
2522
+ strokeLinecap: "round"
2523
+ }
2524
+ )
2525
+ }
2526
+ )
2527
+ }
2528
+ )
2529
+ ]
2530
+ },
2531
+ filter.key
2532
+ )),
2533
+ filters.length > 1 && onClearAll && /* @__PURE__ */ jsxRuntime.jsx(
2534
+ "button",
2535
+ {
2536
+ type: "button",
2537
+ onClick: onClearAll,
2538
+ className: "text-xs text-white/40 underline-offset-2 transition-colors duration-150 hover:text-white/70 focus:outline-none focus-visible:text-white/70",
2539
+ children: clearAllLabel
2540
+ }
2541
+ )
2542
+ ] });
2543
+ }
2544
+ function SectionCard({
2545
+ title,
2546
+ description,
2547
+ right,
2548
+ overlay,
2549
+ children,
2550
+ className
2551
+ }) {
2552
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2553
+ "div",
2554
+ {
2555
+ className: cn(
2556
+ "relative bg-white/5 ring-1 ring-white/10 rounded-xl overflow-hidden",
2557
+ className
2558
+ ),
2559
+ children: [
2560
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3 px-5 py-4 border-b border-white/[0.06]", children: [
2561
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
2562
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-white", children: title }),
2563
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-white/40 mt-0.5", children: description })
2564
+ ] }),
2565
+ right && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0", children: right })
2566
+ ] }),
2567
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-4", children }),
2568
+ overlay
2569
+ ]
2570
+ }
2571
+ );
2572
+ }
2260
2573
  var maxWidthClass = {
2261
2574
  sm: "max-w-2xl",
2262
2575
  md: "max-w-4xl",
@@ -2905,7 +3218,120 @@ function useToast() {
2905
3218
  }
2906
3219
  return ctx;
2907
3220
  }
3221
+ function SavingIcon() {
3222
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3223
+ "svg",
3224
+ {
3225
+ className: "h-5 w-5 animate-spin text-white/70",
3226
+ viewBox: "0 0 24 24",
3227
+ fill: "none",
3228
+ "aria-hidden": "true",
3229
+ children: [
3230
+ /* @__PURE__ */ jsxRuntime.jsx(
3231
+ "circle",
3232
+ {
3233
+ className: "opacity-25",
3234
+ cx: "12",
3235
+ cy: "12",
3236
+ r: "10",
3237
+ stroke: "currentColor",
3238
+ strokeWidth: "4"
3239
+ }
3240
+ ),
3241
+ /* @__PURE__ */ jsxRuntime.jsx(
3242
+ "path",
3243
+ {
3244
+ className: "opacity-75",
3245
+ fill: "currentColor",
3246
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
3247
+ }
3248
+ )
3249
+ ]
3250
+ }
3251
+ );
3252
+ }
3253
+ function SavedIcon() {
3254
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3255
+ "svg",
3256
+ {
3257
+ className: "h-5 w-5 text-green-400",
3258
+ viewBox: "0 0 24 24",
3259
+ fill: "none",
3260
+ stroke: "currentColor",
3261
+ strokeWidth: 2,
3262
+ "aria-hidden": "true",
3263
+ children: [
3264
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeOpacity: 0.4 }),
3265
+ /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 12l2 2 4-4" })
3266
+ ]
3267
+ }
3268
+ );
3269
+ }
3270
+ function ErrorIcon2() {
3271
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3272
+ "svg",
3273
+ {
3274
+ className: "h-5 w-5 text-red-400",
3275
+ viewBox: "0 0 24 24",
3276
+ fill: "none",
3277
+ stroke: "currentColor",
3278
+ strokeWidth: 2,
3279
+ "aria-hidden": "true",
3280
+ children: [
3281
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeOpacity: 0.4 }),
3282
+ /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 9l-6 6M9 9l6 6" })
3283
+ ]
3284
+ }
3285
+ );
3286
+ }
3287
+ var statusConfig = {
3288
+ saving: {
3289
+ icon: SavingIcon,
3290
+ defaultText: "Saving...",
3291
+ textClass: "text-white/70"
3292
+ },
3293
+ saved: {
3294
+ icon: SavedIcon,
3295
+ defaultText: "Saved",
3296
+ textClass: "text-green-400"
3297
+ },
3298
+ error: {
3299
+ icon: ErrorIcon2,
3300
+ defaultText: "Error",
3301
+ textClass: "text-red-400"
3302
+ }
3303
+ };
3304
+ function MutationOverlay({
3305
+ status,
3306
+ savingText,
3307
+ savedText,
3308
+ errorText,
3309
+ className
3310
+ }) {
3311
+ if (status === "idle") return null;
3312
+ const config = statusConfig[status];
3313
+ const Icon = config.icon;
3314
+ const text = status === "saving" ? savingText ?? config.defaultText : status === "saved" ? savedText ?? config.defaultText : errorText ?? config.defaultText;
3315
+ return /* @__PURE__ */ jsxRuntime.jsx(
3316
+ "div",
3317
+ {
3318
+ className: cn(
3319
+ "absolute inset-0 z-10 flex items-center justify-center",
3320
+ "bg-surface-50/80 backdrop-blur-sm",
3321
+ "transition-opacity duration-200",
3322
+ className
3323
+ ),
3324
+ role: "status",
3325
+ "aria-live": "polite",
3326
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3327
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, {}),
3328
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm font-medium", config.textClass), children: text })
3329
+ ] })
3330
+ }
3331
+ );
3332
+ }
2908
3333
 
3334
+ exports.ActiveFilterPills = ActiveFilterPills;
2909
3335
  exports.Alert = Alert;
2910
3336
  exports.Avatar = Avatar;
2911
3337
  exports.Badge = Badge;
@@ -2915,9 +3341,11 @@ exports.Checkbox = Checkbox;
2915
3341
  exports.CollapsibleSection = CollapsibleSection;
2916
3342
  exports.ColorInput = ColorInput;
2917
3343
  exports.ConfirmDialog = ConfirmDialog;
3344
+ exports.CooldownRing = CooldownRing;
2918
3345
  exports.CopyField = CopyField;
2919
3346
  exports.DashboardLayout = DashboardLayout;
2920
3347
  exports.Divider = Divider;
3348
+ exports.DotIndicator = DotIndicator;
2921
3349
  exports.DropZone = DropZone;
2922
3350
  exports.Dropdown = Dropdown;
2923
3351
  exports.DropdownItem = DropdownItem;
@@ -2929,6 +3357,7 @@ exports.FormField = FormField;
2929
3357
  exports.IconButton = IconButton;
2930
3358
  exports.Input = Input;
2931
3359
  exports.Modal = Modal;
3360
+ exports.MutationOverlay = MutationOverlay;
2932
3361
  exports.Navbar = Navbar;
2933
3362
  exports.PageShell = PageShell;
2934
3363
  exports.Pagination = Pagination;
@@ -2938,11 +3367,13 @@ exports.ProgressButton = ProgressButton;
2938
3367
  exports.RadioGroup = RadioGroup;
2939
3368
  exports.RadioItem = RadioItem;
2940
3369
  exports.SearchInput = SearchInput;
3370
+ exports.SectionCard = SectionCard;
2941
3371
  exports.Select = Select;
2942
3372
  exports.Sidebar = Sidebar;
2943
3373
  exports.Skeleton = Skeleton;
2944
3374
  exports.Slider = Slider;
2945
3375
  exports.Spinner = Spinner;
3376
+ exports.StageProgress = StageProgress;
2946
3377
  exports.StatCard = StatCard;
2947
3378
  exports.Stepper = Stepper;
2948
3379
  exports.Tab = Tab;
package/dist/index.d.cts CHANGED
@@ -158,6 +158,7 @@ type ToggleProps = {
158
158
  checked: boolean;
159
159
  onChange: (checked: boolean) => void;
160
160
  disabled?: boolean;
161
+ busy?: boolean;
161
162
  label?: string;
162
163
  size?: ToggleSize;
163
164
  id?: string;
@@ -473,6 +474,56 @@ type ProgressBarProps = {
473
474
  };
474
475
  declare function ProgressBar({ value, max, variant, label, showValue, size, className, }: ProgressBarProps): react_jsx_runtime.JSX.Element;
475
476
 
477
+ type CooldownRingSize = 'sm' | 'md' | 'lg';
478
+ type CooldownRingProps = {
479
+ duration: number;
480
+ remaining: number;
481
+ onTick?: () => void;
482
+ onComplete?: () => void;
483
+ size?: CooldownRingSize;
484
+ className?: string;
485
+ };
486
+ declare function CooldownRing({ duration, remaining, size, className, }: CooldownRingProps): react_jsx_runtime.JSX.Element;
487
+
488
+ type StageProgressProps = {
489
+ stages: string[];
490
+ activeStage: number;
491
+ className?: string;
492
+ };
493
+ declare function StageProgress({ stages, activeStage, className }: StageProgressProps): react_jsx_runtime.JSX.Element;
494
+
495
+ type DotIndicatorProps = {
496
+ remaining: number;
497
+ max: number;
498
+ showLabel?: boolean;
499
+ labelFormat?: (remaining: number, max: number) => string;
500
+ className?: string;
501
+ };
502
+ declare function DotIndicator({ remaining, max, showLabel, labelFormat, className, }: DotIndicatorProps): react_jsx_runtime.JSX.Element;
503
+
504
+ type FilterPill = {
505
+ key: string;
506
+ label: string;
507
+ };
508
+ type ActiveFilterPillsProps = {
509
+ filters: FilterPill[];
510
+ onRemove: (key: string) => void;
511
+ onClearAll?: () => void;
512
+ clearAllLabel?: string;
513
+ className?: string;
514
+ };
515
+ declare function ActiveFilterPills({ filters, onRemove, onClearAll, clearAllLabel, className, }: ActiveFilterPillsProps): react_jsx_runtime.JSX.Element | null;
516
+
517
+ type SectionCardProps = {
518
+ title: string;
519
+ description?: string;
520
+ right?: ReactNode;
521
+ overlay?: ReactNode;
522
+ children: ReactNode;
523
+ className?: string;
524
+ };
525
+ declare function SectionCard({ title, description, right, overlay, children, className, }: SectionCardProps): react_jsx_runtime.JSX.Element;
526
+
476
527
  type PageShellVariant = 'plain' | 'glass' | 'minimal';
477
528
  type PageShellProps = {
478
529
  header?: ReactNode;
@@ -569,4 +620,14 @@ type ToastContextValue = {
569
620
  declare function ToastProvider({ children, position, maxToasts }: ToastProviderProps): react_jsx_runtime.JSX.Element;
570
621
  declare function useToast(): ToastContextValue;
571
622
 
572
- export { Alert, type AlertProps, type AlertVariant, Avatar, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, type CardProps, type CardVariant, Checkbox, type CheckboxProps, CollapsibleSection, type CollapsibleSectionProps, ColorInput, type ColorInputProps, ConfirmDialog, type ConfirmDialogProps, type ConfirmDialogVariant, CopyField, type CopyFieldProps, DashboardLayout, type DashboardLayoutProps, Divider, type DividerProps, DropZone, type DropZoneProps, Dropdown, DropdownItem, type DropdownItemProps, DropdownMenu, type DropdownMenuProps, type DropdownProps, DropdownSeparator, type DropdownSeparatorProps, DropdownTrigger, type DropdownTriggerProps, EmptyState, type EmptyStateProps, FormField, type FormFieldProps, IconButton, type IconButtonProps, Input, type InputProps, Modal, type ModalProps, Navbar, type NavbarProps, PageShell, type PageShellProps, type PageShellVariant, Pagination, type PaginationProps, Pill, ProgressBar, type ProgressBarProps, type ProgressBarVariant, ProgressButton, type ProgressButtonProps, RadioGroup, type RadioGroupProps, RadioItem, type RadioItemProps, SearchInput, type SearchInputProps, Select, type SelectProps, Sidebar, type SidebarProps, type Size, Skeleton, type SkeletonProps, Slider, type SliderProps, Spinner, type SpinnerProps, type SpinnerSize, StatCard, type StatCardProps, type StatCardTrend, type Step, Stepper, type StepperProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, TableBody, type TableBodyProps, TableCell, type TableCellProps, TableHead, type TableHeadProps, TableHeader, type TableHeaderProps, type TableProps, TableRow, type TableRowProps, Tabs, type TabsProps, type TabsVariant, TagInput, type TagInputProps, Textarea, type TextareaProps, type ToastData, type ToastPosition, ToastProvider, type ToastProviderProps, type ToastVariant, Toggle, type ToggleProps, type ToggleSize, Tooltip, type TooltipPlacement, type TooltipProps, type UseClipboardReturn, type UseDisclosureReturn, cn, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useMediaQuery, useToast };
623
+ type MutationOverlayStatus = 'idle' | 'saving' | 'saved' | 'error';
624
+ type MutationOverlayProps = {
625
+ status: MutationOverlayStatus;
626
+ savingText?: string;
627
+ savedText?: string;
628
+ errorText?: string;
629
+ className?: string;
630
+ };
631
+ declare function MutationOverlay({ status, savingText, savedText, errorText, className, }: MutationOverlayProps): react_jsx_runtime.JSX.Element | null;
632
+
633
+ export { ActiveFilterPills, type ActiveFilterPillsProps, Alert, type AlertProps, type AlertVariant, Avatar, type AvatarProps, type AvatarSize, Badge, type BadgeProps, type BadgeSize, type BadgeVariant, Button, type ButtonProps, type ButtonSize, type ButtonVariant, Card, type CardProps, type CardVariant, Checkbox, type CheckboxProps, CollapsibleSection, type CollapsibleSectionProps, ColorInput, type ColorInputProps, ConfirmDialog, type ConfirmDialogProps, type ConfirmDialogVariant, CooldownRing, type CooldownRingProps, type CooldownRingSize, CopyField, type CopyFieldProps, DashboardLayout, type DashboardLayoutProps, Divider, type DividerProps, DotIndicator, type DotIndicatorProps, DropZone, type DropZoneProps, Dropdown, DropdownItem, type DropdownItemProps, DropdownMenu, type DropdownMenuProps, type DropdownProps, DropdownSeparator, type DropdownSeparatorProps, DropdownTrigger, type DropdownTriggerProps, EmptyState, type EmptyStateProps, type FilterPill, FormField, type FormFieldProps, IconButton, type IconButtonProps, Input, type InputProps, Modal, type ModalProps, MutationOverlay, type MutationOverlayProps, type MutationOverlayStatus, Navbar, type NavbarProps, PageShell, type PageShellProps, type PageShellVariant, Pagination, type PaginationProps, Pill, ProgressBar, type ProgressBarProps, type ProgressBarVariant, ProgressButton, type ProgressButtonProps, RadioGroup, type RadioGroupProps, RadioItem, type RadioItemProps, SearchInput, type SearchInputProps, SectionCard, type SectionCardProps, Select, type SelectProps, Sidebar, type SidebarProps, type Size, Skeleton, type SkeletonProps, Slider, type SliderProps, Spinner, type SpinnerProps, type SpinnerSize, StageProgress, type StageProgressProps, StatCard, type StatCardProps, type StatCardTrend, type Step, Stepper, type StepperProps, Tab, TabList, type TabListProps, TabPanel, type TabPanelProps, type TabProps, Table, TableBody, type TableBodyProps, TableCell, type TableCellProps, TableHead, type TableHeadProps, TableHeader, type TableHeaderProps, type TableProps, TableRow, type TableRowProps, Tabs, type TabsProps, type TabsVariant, TagInput, type TagInputProps, Textarea, type TextareaProps, type ToastData, type ToastPosition, ToastProvider, type ToastProviderProps, type ToastVariant, Toggle, type ToggleProps, type ToggleSize, Tooltip, type TooltipPlacement, type TooltipProps, type UseClipboardReturn, type UseDisclosureReturn, cn, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useMediaQuery, useToast };