@memelabui/ui 0.3.0 → 0.5.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 +18 -3
- package/dist/index.cjs +584 -3
- package/dist/index.d.cts +151 -1
- package/dist/index.d.ts +151 -1
- package/dist/index.js +575 -4
- package/dist/styles/index.css +170 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -124,6 +124,82 @@ function useDebounce(value, delayMs = 300) {
|
|
|
124
124
|
}, [value, delayMs]);
|
|
125
125
|
return debouncedValue;
|
|
126
126
|
}
|
|
127
|
+
function matchModifiers(e, mods) {
|
|
128
|
+
const ctrl = mods?.ctrl ?? false;
|
|
129
|
+
const shift = mods?.shift ?? false;
|
|
130
|
+
const alt = mods?.alt ?? false;
|
|
131
|
+
const meta = mods?.meta ?? false;
|
|
132
|
+
return e.ctrlKey === ctrl && e.shiftKey === shift && e.altKey === alt && e.metaKey === meta;
|
|
133
|
+
}
|
|
134
|
+
function useHotkeys(bindings, options = {}) {
|
|
135
|
+
const { enabled = true } = options;
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
if (!enabled) return;
|
|
138
|
+
const onKeyDown = (e) => {
|
|
139
|
+
for (const binding of bindings) {
|
|
140
|
+
if (e.key === binding.key && matchModifiers(e, binding.modifiers)) {
|
|
141
|
+
binding.handler(e);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
document.addEventListener("keydown", onKeyDown);
|
|
146
|
+
return () => document.removeEventListener("keydown", onKeyDown);
|
|
147
|
+
}, [enabled, ...bindings]);
|
|
148
|
+
}
|
|
149
|
+
function useIntersectionObserver(options = {}) {
|
|
150
|
+
const { root = null, rootMargin = "0px", threshold = 0, enabled = true } = options;
|
|
151
|
+
const [entry, setEntry] = useState(null);
|
|
152
|
+
const nodeRef = useRef(null);
|
|
153
|
+
const observerRef = useRef(null);
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
if (!enabled) {
|
|
156
|
+
setEntry(null);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
observerRef.current = new IntersectionObserver(
|
|
160
|
+
([e]) => setEntry(e),
|
|
161
|
+
{ root, rootMargin, threshold }
|
|
162
|
+
);
|
|
163
|
+
if (nodeRef.current) {
|
|
164
|
+
observerRef.current.observe(nodeRef.current);
|
|
165
|
+
}
|
|
166
|
+
return () => {
|
|
167
|
+
observerRef.current?.disconnect();
|
|
168
|
+
observerRef.current = null;
|
|
169
|
+
};
|
|
170
|
+
}, [enabled, root, rootMargin, JSON.stringify(threshold)]);
|
|
171
|
+
const ref = (node) => {
|
|
172
|
+
if (nodeRef.current) {
|
|
173
|
+
observerRef.current?.unobserve(nodeRef.current);
|
|
174
|
+
}
|
|
175
|
+
nodeRef.current = node;
|
|
176
|
+
if (node) {
|
|
177
|
+
observerRef.current?.observe(node);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
return {
|
|
181
|
+
ref,
|
|
182
|
+
entry,
|
|
183
|
+
isIntersecting: entry?.isIntersecting ?? false
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function useSharedNow(options = {}) {
|
|
187
|
+
const { interval = 1e3, untilMs, enabled = true } = options;
|
|
188
|
+
const [now, setNow] = useState(Date.now);
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
if (!enabled) return;
|
|
191
|
+
if (untilMs !== void 0 && Date.now() >= untilMs) return;
|
|
192
|
+
const id = setInterval(() => {
|
|
193
|
+
const current = Date.now();
|
|
194
|
+
setNow(current);
|
|
195
|
+
if (untilMs !== void 0 && current >= untilMs) {
|
|
196
|
+
clearInterval(id);
|
|
197
|
+
}
|
|
198
|
+
}, interval);
|
|
199
|
+
return () => clearInterval(id);
|
|
200
|
+
}, [interval, untilMs, enabled]);
|
|
201
|
+
return now;
|
|
202
|
+
}
|
|
127
203
|
|
|
128
204
|
// src/tokens/colors.ts
|
|
129
205
|
var colors = {
|
|
@@ -552,7 +628,7 @@ var thumbSize = {
|
|
|
552
628
|
sm: { base: "w-4 h-4", translate: "translate-x-4" },
|
|
553
629
|
md: { base: "w-5 h-5", translate: "translate-x-5" }
|
|
554
630
|
};
|
|
555
|
-
var Toggle = forwardRef(function Toggle2({ checked, onChange, disabled, label, size = "md", id: externalId, "aria-label": ariaLabel }, ref) {
|
|
631
|
+
var Toggle = forwardRef(function Toggle2({ checked, onChange, disabled, busy, label, size = "md", id: externalId, "aria-label": ariaLabel }, ref) {
|
|
556
632
|
const generatedId = useId();
|
|
557
633
|
const toggleId = externalId || generatedId;
|
|
558
634
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
@@ -565,7 +641,8 @@ var Toggle = forwardRef(function Toggle2({ checked, onChange, disabled, label, s
|
|
|
565
641
|
role: "switch",
|
|
566
642
|
"aria-checked": checked,
|
|
567
643
|
"aria-label": ariaLabel || label,
|
|
568
|
-
disabled,
|
|
644
|
+
disabled: disabled || busy,
|
|
645
|
+
"aria-busy": busy || void 0,
|
|
569
646
|
onClick: () => onChange(!checked),
|
|
570
647
|
className: cn(
|
|
571
648
|
"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",
|
|
@@ -577,9 +654,18 @@ var Toggle = forwardRef(function Toggle2({ checked, onChange, disabled, label, s
|
|
|
577
654
|
"span",
|
|
578
655
|
{
|
|
579
656
|
className: cn(
|
|
580
|
-
"absolute top-0.5 left-0.5 rounded-full bg-white transition-transform duration-200",
|
|
657
|
+
"absolute top-0.5 left-0.5 rounded-full bg-white transition-transform duration-200 flex items-center justify-center",
|
|
581
658
|
thumbSize[size].base,
|
|
582
659
|
checked ? thumbSize[size].translate : "translate-x-0"
|
|
660
|
+
),
|
|
661
|
+
children: busy && /* @__PURE__ */ jsx(
|
|
662
|
+
"span",
|
|
663
|
+
{
|
|
664
|
+
className: cn(
|
|
665
|
+
"border-2 border-primary/30 border-t-primary rounded-full animate-spin",
|
|
666
|
+
size === "sm" ? "w-2.5 h-2.5" : "w-3 h-3"
|
|
667
|
+
)
|
|
668
|
+
}
|
|
583
669
|
)
|
|
584
670
|
}
|
|
585
671
|
)
|
|
@@ -2251,6 +2337,309 @@ function ProgressBar({
|
|
|
2251
2337
|
)
|
|
2252
2338
|
] });
|
|
2253
2339
|
}
|
|
2340
|
+
var sizeMap = {
|
|
2341
|
+
sm: "w-8 h-8 text-xs",
|
|
2342
|
+
md: "w-12 h-12 text-sm",
|
|
2343
|
+
lg: "w-16 h-16 text-base"
|
|
2344
|
+
};
|
|
2345
|
+
var strokeWidthMap = {
|
|
2346
|
+
sm: 3,
|
|
2347
|
+
md: 3.5,
|
|
2348
|
+
lg: 4
|
|
2349
|
+
};
|
|
2350
|
+
var RADIUS = 15.9155;
|
|
2351
|
+
var CIRCUMFERENCE = 2 * Math.PI * RADIUS;
|
|
2352
|
+
function CooldownRing({
|
|
2353
|
+
duration,
|
|
2354
|
+
remaining,
|
|
2355
|
+
size = "md",
|
|
2356
|
+
className
|
|
2357
|
+
}) {
|
|
2358
|
+
const fraction = duration > 0 ? Math.max(0, Math.min(1, remaining / duration)) : 0;
|
|
2359
|
+
const offset = CIRCUMFERENCE * (1 - fraction);
|
|
2360
|
+
const color = fraction > 0.5 ? "text-primary" : fraction > 0.25 ? "text-amber-500" : "text-rose-500";
|
|
2361
|
+
const pulse = remaining <= 10 && remaining > 0;
|
|
2362
|
+
const strokeWidth = strokeWidthMap[size];
|
|
2363
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex items-center justify-center", sizeMap[size], className), children: [
|
|
2364
|
+
/* @__PURE__ */ jsxs(
|
|
2365
|
+
"svg",
|
|
2366
|
+
{
|
|
2367
|
+
viewBox: "0 0 36 36",
|
|
2368
|
+
className: cn("w-full h-full -rotate-90", color, pulse && "animate-pulse"),
|
|
2369
|
+
"aria-label": `Cooldown: ${remaining} seconds remaining`,
|
|
2370
|
+
role: "img",
|
|
2371
|
+
children: [
|
|
2372
|
+
/* @__PURE__ */ jsx(
|
|
2373
|
+
"circle",
|
|
2374
|
+
{
|
|
2375
|
+
cx: "18",
|
|
2376
|
+
cy: "18",
|
|
2377
|
+
r: RADIUS,
|
|
2378
|
+
fill: "none",
|
|
2379
|
+
stroke: "currentColor",
|
|
2380
|
+
strokeWidth,
|
|
2381
|
+
className: "text-white/10"
|
|
2382
|
+
}
|
|
2383
|
+
),
|
|
2384
|
+
/* @__PURE__ */ jsx(
|
|
2385
|
+
"circle",
|
|
2386
|
+
{
|
|
2387
|
+
cx: "18",
|
|
2388
|
+
cy: "18",
|
|
2389
|
+
r: RADIUS,
|
|
2390
|
+
fill: "none",
|
|
2391
|
+
stroke: "currentColor",
|
|
2392
|
+
strokeWidth,
|
|
2393
|
+
strokeDasharray: `${CIRCUMFERENCE} ${CIRCUMFERENCE}`,
|
|
2394
|
+
strokeDashoffset: offset,
|
|
2395
|
+
strokeLinecap: "round",
|
|
2396
|
+
style: { transition: "stroke-dashoffset 0.6s ease" }
|
|
2397
|
+
}
|
|
2398
|
+
)
|
|
2399
|
+
]
|
|
2400
|
+
}
|
|
2401
|
+
),
|
|
2402
|
+
/* @__PURE__ */ jsx(
|
|
2403
|
+
"span",
|
|
2404
|
+
{
|
|
2405
|
+
className: "absolute font-semibold tabular-nums text-white select-none",
|
|
2406
|
+
style: { lineHeight: 1 },
|
|
2407
|
+
children: Math.max(0, Math.ceil(remaining))
|
|
2408
|
+
}
|
|
2409
|
+
)
|
|
2410
|
+
] });
|
|
2411
|
+
}
|
|
2412
|
+
function StageProgress({ stages, activeStage, className }) {
|
|
2413
|
+
const clampedActive = Math.max(0, Math.min(activeStage, stages.length - 1));
|
|
2414
|
+
const fillPercent = stages.length <= 1 ? 100 : clampedActive / (stages.length - 1) * 100;
|
|
2415
|
+
const isComplete = clampedActive >= stages.length - 1;
|
|
2416
|
+
const isAnimating = !isComplete;
|
|
2417
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("w-full", className), children: [
|
|
2418
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-between", children: stages.map((stage, index) => {
|
|
2419
|
+
const isCompleted = index < clampedActive;
|
|
2420
|
+
const isActive = index === clampedActive;
|
|
2421
|
+
return /* @__PURE__ */ jsxs(
|
|
2422
|
+
"div",
|
|
2423
|
+
{
|
|
2424
|
+
className: cn(
|
|
2425
|
+
"flex items-center gap-1.5 text-xs font-medium transition-colors duration-300",
|
|
2426
|
+
isCompleted && "text-emerald-400",
|
|
2427
|
+
isActive && "text-white",
|
|
2428
|
+
!isCompleted && !isActive && "text-white/40"
|
|
2429
|
+
),
|
|
2430
|
+
children: [
|
|
2431
|
+
isCompleted ? (
|
|
2432
|
+
// Completed: emerald check circle
|
|
2433
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-3.5 w-3.5 items-center justify-center rounded-full bg-emerald-400/20", children: /* @__PURE__ */ jsx(
|
|
2434
|
+
"svg",
|
|
2435
|
+
{
|
|
2436
|
+
className: "h-2.5 w-2.5 text-emerald-400",
|
|
2437
|
+
viewBox: "0 0 10 10",
|
|
2438
|
+
fill: "none",
|
|
2439
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2440
|
+
"aria-hidden": "true",
|
|
2441
|
+
children: /* @__PURE__ */ jsx(
|
|
2442
|
+
"path",
|
|
2443
|
+
{
|
|
2444
|
+
d: "M2 5.5L4 7.5L8 3",
|
|
2445
|
+
stroke: "currentColor",
|
|
2446
|
+
strokeWidth: "1.5",
|
|
2447
|
+
strokeLinecap: "round",
|
|
2448
|
+
strokeLinejoin: "round"
|
|
2449
|
+
}
|
|
2450
|
+
)
|
|
2451
|
+
}
|
|
2452
|
+
) })
|
|
2453
|
+
) : isActive ? (
|
|
2454
|
+
// Active: primary dot with ring
|
|
2455
|
+
/* @__PURE__ */ 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__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-[var(--ml-primary)]" }) })
|
|
2456
|
+
) : (
|
|
2457
|
+
// Upcoming: hollow dim dot
|
|
2458
|
+
/* @__PURE__ */ jsx("span", { className: "h-3.5 w-3.5 rounded-full border border-white/20 bg-transparent" })
|
|
2459
|
+
),
|
|
2460
|
+
stage
|
|
2461
|
+
]
|
|
2462
|
+
},
|
|
2463
|
+
stage
|
|
2464
|
+
);
|
|
2465
|
+
}) }),
|
|
2466
|
+
/* @__PURE__ */ jsx(
|
|
2467
|
+
"div",
|
|
2468
|
+
{
|
|
2469
|
+
className: "relative mt-3 h-1.5 w-full overflow-hidden rounded-full bg-white/10",
|
|
2470
|
+
role: "progressbar",
|
|
2471
|
+
"aria-valuenow": clampedActive,
|
|
2472
|
+
"aria-valuemin": 0,
|
|
2473
|
+
"aria-valuemax": stages.length - 1,
|
|
2474
|
+
"aria-label": `Stage ${clampedActive + 1} of ${stages.length}: ${stages[clampedActive]}`,
|
|
2475
|
+
children: /* @__PURE__ */ jsx(
|
|
2476
|
+
"div",
|
|
2477
|
+
{
|
|
2478
|
+
className: "h-full rounded-full bg-gradient-to-r from-[var(--ml-accent)] to-[var(--ml-primary)] transition-[width] duration-500 ease-in-out",
|
|
2479
|
+
style: { width: `${fillPercent}%` },
|
|
2480
|
+
children: isAnimating && /* @__PURE__ */ jsx(
|
|
2481
|
+
"span",
|
|
2482
|
+
{
|
|
2483
|
+
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",
|
|
2484
|
+
"aria-hidden": "true"
|
|
2485
|
+
}
|
|
2486
|
+
)
|
|
2487
|
+
}
|
|
2488
|
+
)
|
|
2489
|
+
}
|
|
2490
|
+
)
|
|
2491
|
+
] });
|
|
2492
|
+
}
|
|
2493
|
+
function getUrgencyClasses(remaining, max) {
|
|
2494
|
+
const ratio = max > 0 ? remaining / max : 0;
|
|
2495
|
+
if (ratio > 0.5) {
|
|
2496
|
+
return {
|
|
2497
|
+
filled: "bg-emerald-400",
|
|
2498
|
+
empty: "bg-emerald-400/30",
|
|
2499
|
+
label: "text-emerald-400"
|
|
2500
|
+
};
|
|
2501
|
+
}
|
|
2502
|
+
if (ratio > 0.25) {
|
|
2503
|
+
return {
|
|
2504
|
+
filled: "bg-amber-400",
|
|
2505
|
+
empty: "bg-amber-400/30",
|
|
2506
|
+
label: "text-amber-400"
|
|
2507
|
+
};
|
|
2508
|
+
}
|
|
2509
|
+
return {
|
|
2510
|
+
filled: "bg-rose-400",
|
|
2511
|
+
empty: "bg-rose-400/30",
|
|
2512
|
+
label: "text-rose-400"
|
|
2513
|
+
};
|
|
2514
|
+
}
|
|
2515
|
+
function DotIndicator({
|
|
2516
|
+
remaining,
|
|
2517
|
+
max,
|
|
2518
|
+
showLabel = false,
|
|
2519
|
+
labelFormat,
|
|
2520
|
+
className
|
|
2521
|
+
}) {
|
|
2522
|
+
const clampedRemaining = Math.max(0, Math.min(remaining, max));
|
|
2523
|
+
const used = max - clampedRemaining;
|
|
2524
|
+
const urgency = getUrgencyClasses(clampedRemaining, max);
|
|
2525
|
+
const defaultLabel = `${clampedRemaining}/${max}`;
|
|
2526
|
+
const label = labelFormat ? labelFormat(clampedRemaining, max) : defaultLabel;
|
|
2527
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("inline-flex items-center gap-2", className), children: [
|
|
2528
|
+
/* @__PURE__ */ jsx(
|
|
2529
|
+
"div",
|
|
2530
|
+
{
|
|
2531
|
+
className: "flex items-center gap-1",
|
|
2532
|
+
role: "meter",
|
|
2533
|
+
"aria-valuenow": clampedRemaining,
|
|
2534
|
+
"aria-valuemin": 0,
|
|
2535
|
+
"aria-valuemax": max,
|
|
2536
|
+
"aria-label": label,
|
|
2537
|
+
children: Array.from({ length: max }, (_, index) => {
|
|
2538
|
+
const isFilled = index < used;
|
|
2539
|
+
return /* @__PURE__ */ jsx(
|
|
2540
|
+
"span",
|
|
2541
|
+
{
|
|
2542
|
+
className: cn(
|
|
2543
|
+
"h-2 w-2 rounded-full transition-colors duration-300",
|
|
2544
|
+
isFilled ? urgency.filled : urgency.empty
|
|
2545
|
+
),
|
|
2546
|
+
"aria-hidden": "true"
|
|
2547
|
+
},
|
|
2548
|
+
index
|
|
2549
|
+
);
|
|
2550
|
+
})
|
|
2551
|
+
}
|
|
2552
|
+
),
|
|
2553
|
+
showLabel && /* @__PURE__ */ jsx("span", { className: cn("text-xs font-medium tabular-nums", urgency.label), children: label })
|
|
2554
|
+
] });
|
|
2555
|
+
}
|
|
2556
|
+
function ActiveFilterPills({
|
|
2557
|
+
filters,
|
|
2558
|
+
onRemove,
|
|
2559
|
+
onClearAll,
|
|
2560
|
+
clearAllLabel = "Clear all",
|
|
2561
|
+
className
|
|
2562
|
+
}) {
|
|
2563
|
+
if (filters.length === 0) return null;
|
|
2564
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-wrap items-center gap-1.5", className), children: [
|
|
2565
|
+
filters.map((filter) => /* @__PURE__ */ jsxs(
|
|
2566
|
+
"span",
|
|
2567
|
+
{
|
|
2568
|
+
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",
|
|
2569
|
+
children: [
|
|
2570
|
+
filter.label,
|
|
2571
|
+
/* @__PURE__ */ jsx(
|
|
2572
|
+
"button",
|
|
2573
|
+
{
|
|
2574
|
+
type: "button",
|
|
2575
|
+
onClick: () => onRemove(filter.key),
|
|
2576
|
+
className: "ml-0.5 text-white/50 transition-colors duration-150 hover:text-white focus:outline-none focus-visible:text-white",
|
|
2577
|
+
"aria-label": `Remove filter: ${filter.label}`,
|
|
2578
|
+
children: /* @__PURE__ */ jsx(
|
|
2579
|
+
"svg",
|
|
2580
|
+
{
|
|
2581
|
+
className: "h-3 w-3",
|
|
2582
|
+
viewBox: "0 0 12 12",
|
|
2583
|
+
fill: "none",
|
|
2584
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2585
|
+
"aria-hidden": "true",
|
|
2586
|
+
children: /* @__PURE__ */ jsx(
|
|
2587
|
+
"path",
|
|
2588
|
+
{
|
|
2589
|
+
d: "M9 3L3 9M3 3L9 9",
|
|
2590
|
+
stroke: "currentColor",
|
|
2591
|
+
strokeWidth: "1.5",
|
|
2592
|
+
strokeLinecap: "round"
|
|
2593
|
+
}
|
|
2594
|
+
)
|
|
2595
|
+
}
|
|
2596
|
+
)
|
|
2597
|
+
}
|
|
2598
|
+
)
|
|
2599
|
+
]
|
|
2600
|
+
},
|
|
2601
|
+
filter.key
|
|
2602
|
+
)),
|
|
2603
|
+
filters.length > 1 && onClearAll && /* @__PURE__ */ jsx(
|
|
2604
|
+
"button",
|
|
2605
|
+
{
|
|
2606
|
+
type: "button",
|
|
2607
|
+
onClick: onClearAll,
|
|
2608
|
+
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",
|
|
2609
|
+
children: clearAllLabel
|
|
2610
|
+
}
|
|
2611
|
+
)
|
|
2612
|
+
] });
|
|
2613
|
+
}
|
|
2614
|
+
function SectionCard({
|
|
2615
|
+
title,
|
|
2616
|
+
description,
|
|
2617
|
+
right,
|
|
2618
|
+
overlay,
|
|
2619
|
+
children,
|
|
2620
|
+
className
|
|
2621
|
+
}) {
|
|
2622
|
+
return /* @__PURE__ */ jsxs(
|
|
2623
|
+
"div",
|
|
2624
|
+
{
|
|
2625
|
+
className: cn(
|
|
2626
|
+
"relative bg-white/5 ring-1 ring-white/10 rounded-xl overflow-hidden",
|
|
2627
|
+
className
|
|
2628
|
+
),
|
|
2629
|
+
children: [
|
|
2630
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 px-5 py-4 border-b border-white/[0.06]", children: [
|
|
2631
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
2632
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-white", children: title }),
|
|
2633
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-xs text-white/40 mt-0.5", children: description })
|
|
2634
|
+
] }),
|
|
2635
|
+
right && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: right })
|
|
2636
|
+
] }),
|
|
2637
|
+
/* @__PURE__ */ jsx("div", { className: "px-5 py-4", children }),
|
|
2638
|
+
overlay
|
|
2639
|
+
]
|
|
2640
|
+
}
|
|
2641
|
+
);
|
|
2642
|
+
}
|
|
2254
2643
|
var maxWidthClass = {
|
|
2255
2644
|
sm: "max-w-2xl",
|
|
2256
2645
|
md: "max-w-4xl",
|
|
@@ -2899,5 +3288,187 @@ function useToast() {
|
|
|
2899
3288
|
}
|
|
2900
3289
|
return ctx;
|
|
2901
3290
|
}
|
|
3291
|
+
function SavingIcon() {
|
|
3292
|
+
return /* @__PURE__ */ jsxs(
|
|
3293
|
+
"svg",
|
|
3294
|
+
{
|
|
3295
|
+
className: "h-5 w-5 animate-spin text-white/70",
|
|
3296
|
+
viewBox: "0 0 24 24",
|
|
3297
|
+
fill: "none",
|
|
3298
|
+
"aria-hidden": "true",
|
|
3299
|
+
children: [
|
|
3300
|
+
/* @__PURE__ */ jsx(
|
|
3301
|
+
"circle",
|
|
3302
|
+
{
|
|
3303
|
+
className: "opacity-25",
|
|
3304
|
+
cx: "12",
|
|
3305
|
+
cy: "12",
|
|
3306
|
+
r: "10",
|
|
3307
|
+
stroke: "currentColor",
|
|
3308
|
+
strokeWidth: "4"
|
|
3309
|
+
}
|
|
3310
|
+
),
|
|
3311
|
+
/* @__PURE__ */ jsx(
|
|
3312
|
+
"path",
|
|
3313
|
+
{
|
|
3314
|
+
className: "opacity-75",
|
|
3315
|
+
fill: "currentColor",
|
|
3316
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
|
|
3317
|
+
}
|
|
3318
|
+
)
|
|
3319
|
+
]
|
|
3320
|
+
}
|
|
3321
|
+
);
|
|
3322
|
+
}
|
|
3323
|
+
function SavedIcon() {
|
|
3324
|
+
return /* @__PURE__ */ jsxs(
|
|
3325
|
+
"svg",
|
|
3326
|
+
{
|
|
3327
|
+
className: "h-5 w-5 text-green-400",
|
|
3328
|
+
viewBox: "0 0 24 24",
|
|
3329
|
+
fill: "none",
|
|
3330
|
+
stroke: "currentColor",
|
|
3331
|
+
strokeWidth: 2,
|
|
3332
|
+
"aria-hidden": "true",
|
|
3333
|
+
children: [
|
|
3334
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", strokeOpacity: 0.4 }),
|
|
3335
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 12l2 2 4-4" })
|
|
3336
|
+
]
|
|
3337
|
+
}
|
|
3338
|
+
);
|
|
3339
|
+
}
|
|
3340
|
+
function ErrorIcon2() {
|
|
3341
|
+
return /* @__PURE__ */ jsxs(
|
|
3342
|
+
"svg",
|
|
3343
|
+
{
|
|
3344
|
+
className: "h-5 w-5 text-red-400",
|
|
3345
|
+
viewBox: "0 0 24 24",
|
|
3346
|
+
fill: "none",
|
|
3347
|
+
stroke: "currentColor",
|
|
3348
|
+
strokeWidth: 2,
|
|
3349
|
+
"aria-hidden": "true",
|
|
3350
|
+
children: [
|
|
3351
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", strokeOpacity: 0.4 }),
|
|
3352
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 9l-6 6M9 9l6 6" })
|
|
3353
|
+
]
|
|
3354
|
+
}
|
|
3355
|
+
);
|
|
3356
|
+
}
|
|
3357
|
+
var statusConfig = {
|
|
3358
|
+
saving: {
|
|
3359
|
+
icon: SavingIcon,
|
|
3360
|
+
defaultText: "Saving...",
|
|
3361
|
+
textClass: "text-white/70"
|
|
3362
|
+
},
|
|
3363
|
+
saved: {
|
|
3364
|
+
icon: SavedIcon,
|
|
3365
|
+
defaultText: "Saved",
|
|
3366
|
+
textClass: "text-green-400"
|
|
3367
|
+
},
|
|
3368
|
+
error: {
|
|
3369
|
+
icon: ErrorIcon2,
|
|
3370
|
+
defaultText: "Error",
|
|
3371
|
+
textClass: "text-red-400"
|
|
3372
|
+
}
|
|
3373
|
+
};
|
|
3374
|
+
function MutationOverlay({
|
|
3375
|
+
status,
|
|
3376
|
+
savingText,
|
|
3377
|
+
savedText,
|
|
3378
|
+
errorText,
|
|
3379
|
+
className
|
|
3380
|
+
}) {
|
|
3381
|
+
if (status === "idle") return null;
|
|
3382
|
+
const config = statusConfig[status];
|
|
3383
|
+
const Icon = config.icon;
|
|
3384
|
+
const text = status === "saving" ? savingText ?? config.defaultText : status === "saved" ? savedText ?? config.defaultText : errorText ?? config.defaultText;
|
|
3385
|
+
return /* @__PURE__ */ jsx(
|
|
3386
|
+
"div",
|
|
3387
|
+
{
|
|
3388
|
+
className: cn(
|
|
3389
|
+
"absolute inset-0 z-10 flex items-center justify-center",
|
|
3390
|
+
"bg-surface-50/80 backdrop-blur-sm",
|
|
3391
|
+
"transition-opacity duration-200",
|
|
3392
|
+
className
|
|
3393
|
+
),
|
|
3394
|
+
role: "status",
|
|
3395
|
+
"aria-live": "polite",
|
|
3396
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3397
|
+
/* @__PURE__ */ jsx(Icon, {}),
|
|
3398
|
+
/* @__PURE__ */ jsx("span", { className: cn("text-sm font-medium", config.textClass), children: text })
|
|
3399
|
+
] })
|
|
3400
|
+
}
|
|
3401
|
+
);
|
|
3402
|
+
}
|
|
3403
|
+
var sizeClass6 = {
|
|
3404
|
+
sm: "w-8 h-8",
|
|
3405
|
+
md: "w-10 h-10",
|
|
3406
|
+
lg: "w-12 h-12"
|
|
3407
|
+
};
|
|
3408
|
+
var iconSizeClass = {
|
|
3409
|
+
sm: "w-4 h-4",
|
|
3410
|
+
md: "w-5 h-5",
|
|
3411
|
+
lg: "w-6 h-6"
|
|
3412
|
+
};
|
|
3413
|
+
var badgeSizeClass = {
|
|
3414
|
+
sm: "min-w-[16px] h-4 text-[10px] px-1",
|
|
3415
|
+
md: "min-w-[18px] h-[18px] text-[11px] px-1",
|
|
3416
|
+
lg: "min-w-[20px] h-5 text-xs px-1.5"
|
|
3417
|
+
};
|
|
3418
|
+
var DefaultBellIcon = ({ className }) => /* @__PURE__ */ jsxs(
|
|
3419
|
+
"svg",
|
|
3420
|
+
{
|
|
3421
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3422
|
+
viewBox: "0 0 24 24",
|
|
3423
|
+
fill: "none",
|
|
3424
|
+
stroke: "currentColor",
|
|
3425
|
+
strokeWidth: 2,
|
|
3426
|
+
strokeLinecap: "round",
|
|
3427
|
+
strokeLinejoin: "round",
|
|
3428
|
+
className,
|
|
3429
|
+
"aria-hidden": "true",
|
|
3430
|
+
children: [
|
|
3431
|
+
/* @__PURE__ */ jsx("path", { d: "M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9" }),
|
|
3432
|
+
/* @__PURE__ */ jsx("path", { d: "M10.3 21a1.94 1.94 0 0 0 3.4 0" })
|
|
3433
|
+
]
|
|
3434
|
+
}
|
|
3435
|
+
);
|
|
3436
|
+
var NotificationBell = forwardRef(
|
|
3437
|
+
function NotificationBell2({ icon, count, maxCount = 99, size = "md", ping, className, disabled, ...props }, ref) {
|
|
3438
|
+
const displayCount = count && count > maxCount ? `${maxCount}+` : count;
|
|
3439
|
+
const hasCount = count !== void 0 && count > 0;
|
|
3440
|
+
return /* @__PURE__ */ jsxs(
|
|
3441
|
+
"button",
|
|
3442
|
+
{
|
|
3443
|
+
ref,
|
|
3444
|
+
type: "button",
|
|
3445
|
+
...props,
|
|
3446
|
+
disabled,
|
|
3447
|
+
"aria-label": props["aria-label"] || `Notifications${hasCount ? ` (${count})` : ""}`,
|
|
3448
|
+
className: cn(
|
|
3449
|
+
"relative inline-flex items-center justify-center rounded-xl text-white/70 transition-colors hover:text-white hover:bg-white/10 focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-transparent disabled:opacity-60 disabled:pointer-events-none",
|
|
3450
|
+
sizeClass6[size],
|
|
3451
|
+
className
|
|
3452
|
+
),
|
|
3453
|
+
children: [
|
|
3454
|
+
icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: icon }) : /* @__PURE__ */ jsx(DefaultBellIcon, { className: iconSizeClass[size] }),
|
|
3455
|
+
hasCount && /* @__PURE__ */ jsxs(
|
|
3456
|
+
"span",
|
|
3457
|
+
{
|
|
3458
|
+
className: cn(
|
|
3459
|
+
"absolute top-0 right-0 flex items-center justify-center rounded-full bg-rose-500 text-white font-semibold leading-none",
|
|
3460
|
+
badgeSizeClass[size]
|
|
3461
|
+
),
|
|
3462
|
+
children: [
|
|
3463
|
+
ping && /* @__PURE__ */ jsx("span", { className: "absolute inset-0 rounded-full bg-rose-500 animate-ping opacity-75" }),
|
|
3464
|
+
/* @__PURE__ */ jsx("span", { className: "relative", children: displayCount })
|
|
3465
|
+
]
|
|
3466
|
+
}
|
|
3467
|
+
)
|
|
3468
|
+
]
|
|
3469
|
+
}
|
|
3470
|
+
);
|
|
3471
|
+
}
|
|
3472
|
+
);
|
|
2902
3473
|
|
|
2903
|
-
export { Alert, Avatar, Badge, Button, Card, Checkbox, CollapsibleSection, ColorInput, ConfirmDialog, CopyField, DashboardLayout, Divider, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, FormField, IconButton, Input, Modal, Navbar, PageShell, Pagination, Pill, ProgressBar, ProgressButton, RadioGroup, RadioItem, SearchInput, Select, Sidebar, Skeleton, Slider, Spinner, StatCard, Stepper, Tab, TabList, TabPanel, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TagInput, Textarea, ToastProvider, Toggle, Tooltip, cn, colors, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useMediaQuery, useToast };
|
|
3474
|
+
export { ActiveFilterPills, Alert, Avatar, Badge, Button, Card, Checkbox, CollapsibleSection, ColorInput, ConfirmDialog, CooldownRing, CopyField, DashboardLayout, Divider, DotIndicator, DropZone, Dropdown, DropdownItem, DropdownMenu, DropdownSeparator, DropdownTrigger, EmptyState, FormField, IconButton, Input, Modal, MutationOverlay, Navbar, NotificationBell, PageShell, Pagination, Pill, ProgressBar, ProgressButton, RadioGroup, RadioItem, SearchInput, SectionCard, Select, Sidebar, Skeleton, Slider, Spinner, StageProgress, StatCard, Stepper, Tab, TabList, TabPanel, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tabs, TagInput, Textarea, ToastProvider, Toggle, Tooltip, cn, colors, focusSafely, getFocusableElements, useClipboard, useDebounce, useDisclosure, useHotkeys, useIntersectionObserver, useMediaQuery, useSharedNow, useToast };
|