@lessly/ui 0.12.0 → 0.14.1
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 +11 -6
- package/dist/index.d.ts +270 -1
- package/dist/index.js +1316 -275
- package/dist/styles.css +25 -6
- package/package.json +11 -4
package/dist/index.js
CHANGED
|
@@ -2444,15 +2444,185 @@ var EmptyState = React42.forwardRef(
|
|
|
2444
2444
|
);
|
|
2445
2445
|
EmptyState.displayName = "EmptyState";
|
|
2446
2446
|
|
|
2447
|
-
// src/components/
|
|
2447
|
+
// src/components/sign-in-screen.tsx
|
|
2448
2448
|
import * as React43 from "react";
|
|
2449
|
+
import { Fragment, jsx as jsx49, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2450
|
+
var GLOW_BG = "radial-gradient(560px 320px at 28% 16%, var(--auth-glow-a), transparent 68%),radial-gradient(520px 340px at 78% 90%, var(--auth-glow-b), transparent 66%),var(--bg-sunken)";
|
|
2451
|
+
var DEFAULT_TITLE = {
|
|
2452
|
+
login: "Sign in",
|
|
2453
|
+
forbidden: "Access restricted",
|
|
2454
|
+
error: "Couldn't load"
|
|
2455
|
+
};
|
|
2456
|
+
var DEFAULT_DESCRIPTION = {
|
|
2457
|
+
forbidden: "This app is limited to one Workspace group.",
|
|
2458
|
+
error: "Something interrupted sign-in. Try again in a moment."
|
|
2459
|
+
};
|
|
2460
|
+
function Spinner({ className }) {
|
|
2461
|
+
return /* @__PURE__ */ jsx49(
|
|
2462
|
+
"span",
|
|
2463
|
+
{
|
|
2464
|
+
"aria-hidden": "true",
|
|
2465
|
+
className: cn(
|
|
2466
|
+
"inline-block animate-spin rounded-full border-2 border-current border-t-transparent",
|
|
2467
|
+
className
|
|
2468
|
+
)
|
|
2469
|
+
}
|
|
2470
|
+
);
|
|
2471
|
+
}
|
|
2472
|
+
function GoogleGlyph() {
|
|
2473
|
+
return /* @__PURE__ */ jsx49("span", { className: "inline-flex size-[26px] flex-none items-center justify-center rounded-md bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.05)_inset]", children: /* @__PURE__ */ jsxs23("svg", { width: "17", height: "17", viewBox: "0 0 18 18", "aria-hidden": "true", children: [
|
|
2474
|
+
/* @__PURE__ */ jsx49("path", { fill: "#4285F4", d: "M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.92c1.7-1.57 2.68-3.88 2.68-6.62z" }),
|
|
2475
|
+
/* @__PURE__ */ jsx49("path", { fill: "#34A853", d: "M9 18c2.43 0 4.47-.8 5.96-2.18l-2.92-2.26c-.8.54-1.84.86-3.04.86-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18z" }),
|
|
2476
|
+
/* @__PURE__ */ jsx49("path", { fill: "#FBBC05", d: "M3.97 10.72a5.4 5.4 0 0 1 0-3.44V4.95H.96a9 9 0 0 0 0 8.1l3.01-2.33z" }),
|
|
2477
|
+
/* @__PURE__ */ jsx49("path", { fill: "#EA4335", d: "M9 3.58c1.32 0 2.5.46 3.44 1.35l2.58-2.58C13.46.9 11.43 0 9 0A9 9 0 0 0 .96 4.95l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58z" })
|
|
2478
|
+
] }) });
|
|
2479
|
+
}
|
|
2480
|
+
var LockIcon = (props) => /* @__PURE__ */ jsxs23("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props, children: [
|
|
2481
|
+
/* @__PURE__ */ jsx49("rect", { x: "3", y: "11", width: "18", height: "11", rx: "2" }),
|
|
2482
|
+
/* @__PURE__ */ jsx49("path", { d: "M7 11V7a5 5 0 0 1 10 0v4" })
|
|
2483
|
+
] });
|
|
2484
|
+
var WarningIcon = (props) => /* @__PURE__ */ jsxs23("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props, children: [
|
|
2485
|
+
/* @__PURE__ */ jsx49("path", { d: "M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" }),
|
|
2486
|
+
/* @__PURE__ */ jsx49("line", { x1: "12", y1: "9", x2: "12", y2: "13" }),
|
|
2487
|
+
/* @__PURE__ */ jsx49("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
|
|
2488
|
+
] });
|
|
2489
|
+
var ErrorIcon = (props) => /* @__PURE__ */ jsxs23("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props, children: [
|
|
2490
|
+
/* @__PURE__ */ jsx49("circle", { cx: "12", cy: "12", r: "10" }),
|
|
2491
|
+
/* @__PURE__ */ jsx49("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
2492
|
+
/* @__PURE__ */ jsx49("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
|
|
2493
|
+
] });
|
|
2494
|
+
var RetryIcon = (props) => /* @__PURE__ */ jsxs23("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", ...props, children: [
|
|
2495
|
+
/* @__PURE__ */ jsx49("path", { d: "M23 4v6h-6" }),
|
|
2496
|
+
/* @__PURE__ */ jsx49("path", { d: "M20.49 15a9 9 0 1 1-2.12-9.36L23 10" })
|
|
2497
|
+
] });
|
|
2498
|
+
var filledBtn = "flex h-[46px] w-full items-center justify-center gap-[11px] rounded-[10px] border border-transparent bg-text-primary px-[14px] text-[14.5px] font-semibold tracking-[-0.005em] text-bg-sunken transition-opacity hover:opacity-[0.92] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-text-brand active:translate-y-px disabled:cursor-not-allowed disabled:opacity-[0.55]";
|
|
2499
|
+
var calloutBase = "mb-[22px] flex gap-[10px] rounded-[10px] border px-[13px] py-[12px] text-left text-[13px] leading-[1.5] text-text-secondary [&_code]:font-mono [&_code]:text-[12px] [&_code]:text-text-primary [&_strong]:font-semibold [&_strong]:text-text-primary";
|
|
2500
|
+
function LockNote({ children }) {
|
|
2501
|
+
return /* @__PURE__ */ jsxs23("div", { className: "mx-auto mt-[20px] flex flex-wrap items-center justify-center gap-[7px] text-[12px] leading-[1.4] text-text-secondary [&_code]:rounded-[5px] [&_code]:bg-bg-secondary [&_code]:px-[6px] [&_code]:py-[2px] [&_code]:font-mono [&_code]:text-[11.5px] [&_code]:text-text-secondary", children: [
|
|
2502
|
+
/* @__PURE__ */ jsx49(LockIcon, { className: "flex-none text-text-tertiary" }),
|
|
2503
|
+
children
|
|
2504
|
+
] });
|
|
2505
|
+
}
|
|
2506
|
+
var SignInScreen = React43.forwardRef(
|
|
2507
|
+
({
|
|
2508
|
+
state: state2 = "login",
|
|
2509
|
+
brand,
|
|
2510
|
+
eyebrow,
|
|
2511
|
+
title,
|
|
2512
|
+
description,
|
|
2513
|
+
googleLabel = "Continue with Google",
|
|
2514
|
+
onGoogle,
|
|
2515
|
+
signingIn = false,
|
|
2516
|
+
signingInLabel = "Signing you in\u2026",
|
|
2517
|
+
restriction,
|
|
2518
|
+
forbidden,
|
|
2519
|
+
error,
|
|
2520
|
+
onRetry,
|
|
2521
|
+
retryLabel = "Try again",
|
|
2522
|
+
loadingLabel = "Loading\u2026",
|
|
2523
|
+
footer = "Supercharged by Lessly",
|
|
2524
|
+
className,
|
|
2525
|
+
...props
|
|
2526
|
+
}, ref) => {
|
|
2527
|
+
const shell = (children) => /* @__PURE__ */ jsx49(
|
|
2528
|
+
"div",
|
|
2529
|
+
{
|
|
2530
|
+
ref,
|
|
2531
|
+
className: cn(
|
|
2532
|
+
"relative flex min-h-screen w-full items-center justify-center overflow-hidden px-6 py-12 text-text-primary",
|
|
2533
|
+
className
|
|
2534
|
+
),
|
|
2535
|
+
style: { background: GLOW_BG },
|
|
2536
|
+
...props,
|
|
2537
|
+
children
|
|
2538
|
+
}
|
|
2539
|
+
);
|
|
2540
|
+
const brandMark = /* @__PURE__ */ jsx49("div", { className: "text-[24px] font-bold leading-none tracking-[-0.02em] text-text-primary", children: brand });
|
|
2541
|
+
if (state2 === "loading") {
|
|
2542
|
+
return shell(
|
|
2543
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex flex-col items-center gap-[16px] text-text-secondary", children: [
|
|
2544
|
+
brandMark,
|
|
2545
|
+
/* @__PURE__ */ jsx49(Spinner, { className: "size-[22px] text-text-tertiary opacity-90" }),
|
|
2546
|
+
/* @__PURE__ */ jsx49("span", { role: "status", className: "text-[13.5px] tracking-[-0.005em]", children: loadingLabel })
|
|
2547
|
+
] })
|
|
2548
|
+
);
|
|
2549
|
+
}
|
|
2550
|
+
const heading = title ?? DEFAULT_TITLE[state2];
|
|
2551
|
+
const sub = description ?? DEFAULT_DESCRIPTION[state2];
|
|
2552
|
+
return shell(
|
|
2553
|
+
/* @__PURE__ */ jsxs23(
|
|
2554
|
+
"div",
|
|
2555
|
+
{
|
|
2556
|
+
className: "relative w-full max-w-[360px] rounded-2xl bg-bg-surface px-[34px] pb-[30px] pt-[38px] text-center",
|
|
2557
|
+
style: {
|
|
2558
|
+
border: "1px solid var(--auth-card-border)",
|
|
2559
|
+
boxShadow: "var(--auth-card-shadow)"
|
|
2560
|
+
},
|
|
2561
|
+
children: [
|
|
2562
|
+
/* @__PURE__ */ jsx49("div", { className: "mb-[22px]", children: brandMark }),
|
|
2563
|
+
eyebrow && state2 === "login" && /* @__PURE__ */ jsx49("p", { className: "mb-[12px] text-[11px] font-semibold uppercase tracking-[0.11em] text-text-tertiary", children: eyebrow }),
|
|
2564
|
+
/* @__PURE__ */ jsx49("h1", { className: "mb-[8px] text-[20px] font-semibold leading-[1.25] tracking-[-0.015em] text-text-primary", children: heading }),
|
|
2565
|
+
sub && /* @__PURE__ */ jsx49("p", { className: "mx-auto mb-[24px] max-w-[280px] text-[13.5px] leading-[1.5] text-text-secondary", children: sub }),
|
|
2566
|
+
state2 === "login" && /* @__PURE__ */ jsx49(
|
|
2567
|
+
"button",
|
|
2568
|
+
{
|
|
2569
|
+
type: "button",
|
|
2570
|
+
onClick: onGoogle,
|
|
2571
|
+
disabled: signingIn,
|
|
2572
|
+
"aria-busy": signingIn || void 0,
|
|
2573
|
+
className: filledBtn,
|
|
2574
|
+
style: { boxShadow: "var(--auth-btn-shadow)" },
|
|
2575
|
+
children: signingIn ? /* @__PURE__ */ jsxs23(Fragment, { children: [
|
|
2576
|
+
/* @__PURE__ */ jsx49(Spinner, { className: "size-[17px] opacity-50" }),
|
|
2577
|
+
/* @__PURE__ */ jsx49("span", { children: signingInLabel })
|
|
2578
|
+
] }) : /* @__PURE__ */ jsxs23(Fragment, { children: [
|
|
2579
|
+
/* @__PURE__ */ jsx49(GoogleGlyph, {}),
|
|
2580
|
+
/* @__PURE__ */ jsx49("span", { children: googleLabel })
|
|
2581
|
+
] })
|
|
2582
|
+
}
|
|
2583
|
+
),
|
|
2584
|
+
state2 === "forbidden" && forbidden && /* @__PURE__ */ jsxs23("div", { role: "status", className: cn(calloutBase, "border-border-warning bg-bg-warning-subtle"), children: [
|
|
2585
|
+
/* @__PURE__ */ jsx49(WarningIcon, { className: "mt-px flex-none text-border-warning" }),
|
|
2586
|
+
/* @__PURE__ */ jsx49("span", { children: forbidden })
|
|
2587
|
+
] }),
|
|
2588
|
+
state2 === "error" && /* @__PURE__ */ jsxs23(Fragment, { children: [
|
|
2589
|
+
/* @__PURE__ */ jsxs23("div", { role: "alert", className: cn(calloutBase, "border-border-danger bg-bg-danger-subtle"), children: [
|
|
2590
|
+
/* @__PURE__ */ jsx49(ErrorIcon, { className: "mt-px flex-none text-border-danger" }),
|
|
2591
|
+
/* @__PURE__ */ jsx49("span", { children: error ?? "The identity provider didn\u2019t respond. Retry in a moment." })
|
|
2592
|
+
] }),
|
|
2593
|
+
onRetry && /* @__PURE__ */ jsxs23(
|
|
2594
|
+
"button",
|
|
2595
|
+
{
|
|
2596
|
+
type: "button",
|
|
2597
|
+
onClick: onRetry,
|
|
2598
|
+
className: filledBtn,
|
|
2599
|
+
style: { boxShadow: "var(--auth-btn-shadow)" },
|
|
2600
|
+
children: [
|
|
2601
|
+
/* @__PURE__ */ jsx49(RetryIcon, {}),
|
|
2602
|
+
/* @__PURE__ */ jsx49("span", { children: retryLabel })
|
|
2603
|
+
]
|
|
2604
|
+
}
|
|
2605
|
+
)
|
|
2606
|
+
] }),
|
|
2607
|
+
restriction && (state2 === "login" || state2 === "forbidden") && /* @__PURE__ */ jsx49(LockNote, { children: restriction }),
|
|
2608
|
+
footer != null && /* @__PURE__ */ jsx49("div", { className: "mt-[24px] text-[11px] tracking-[0.005em] text-text-tertiary", children: footer })
|
|
2609
|
+
]
|
|
2610
|
+
}
|
|
2611
|
+
)
|
|
2612
|
+
);
|
|
2613
|
+
}
|
|
2614
|
+
);
|
|
2615
|
+
SignInScreen.displayName = "SignInScreen";
|
|
2616
|
+
|
|
2617
|
+
// src/components/copy-button.tsx
|
|
2618
|
+
import * as React44 from "react";
|
|
2449
2619
|
import { Check as Check5, Copy } from "lucide-react";
|
|
2450
|
-
import { jsx as
|
|
2451
|
-
var CopyButton =
|
|
2620
|
+
import { jsx as jsx50 } from "react/jsx-runtime";
|
|
2621
|
+
var CopyButton = React44.forwardRef(
|
|
2452
2622
|
({ value, label = "Copy", className, variant = "ghost", size = "icon", onClick, ...props }, ref) => {
|
|
2453
|
-
const [copied, setCopied] =
|
|
2454
|
-
const timer =
|
|
2455
|
-
|
|
2623
|
+
const [copied, setCopied] = React44.useState(false);
|
|
2624
|
+
const timer = React44.useRef(void 0);
|
|
2625
|
+
React44.useEffect(() => () => clearTimeout(timer.current), []);
|
|
2456
2626
|
const handleClick = async (e) => {
|
|
2457
2627
|
onClick?.(e);
|
|
2458
2628
|
if (!navigator.clipboard?.writeText) return;
|
|
@@ -2464,7 +2634,7 @@ var CopyButton = React43.forwardRef(
|
|
|
2464
2634
|
} catch {
|
|
2465
2635
|
}
|
|
2466
2636
|
};
|
|
2467
|
-
return /* @__PURE__ */
|
|
2637
|
+
return /* @__PURE__ */ jsx50(
|
|
2468
2638
|
Button,
|
|
2469
2639
|
{
|
|
2470
2640
|
ref,
|
|
@@ -2475,7 +2645,7 @@ var CopyButton = React43.forwardRef(
|
|
|
2475
2645
|
className: cn(className),
|
|
2476
2646
|
...props,
|
|
2477
2647
|
"aria-label": copied ? "Copied" : label,
|
|
2478
|
-
children: copied ? /* @__PURE__ */
|
|
2648
|
+
children: copied ? /* @__PURE__ */ jsx50(Check5, { className: "size-4 text-text-success" }) : /* @__PURE__ */ jsx50(Copy, { className: "size-4" })
|
|
2479
2649
|
}
|
|
2480
2650
|
);
|
|
2481
2651
|
}
|
|
@@ -2483,9 +2653,9 @@ var CopyButton = React43.forwardRef(
|
|
|
2483
2653
|
CopyButton.displayName = "CopyButton";
|
|
2484
2654
|
|
|
2485
2655
|
// src/components/stat-card.tsx
|
|
2486
|
-
import * as
|
|
2656
|
+
import * as React45 from "react";
|
|
2487
2657
|
import { ArrowDown, ArrowUp, Info as Info2, Minus as Minus2 } from "lucide-react";
|
|
2488
|
-
import { jsx as
|
|
2658
|
+
import { jsx as jsx51, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2489
2659
|
var directionIcons = {
|
|
2490
2660
|
up: ArrowUp,
|
|
2491
2661
|
down: ArrowDown,
|
|
@@ -2501,36 +2671,36 @@ var toneFromDirection = {
|
|
|
2501
2671
|
down: "negative",
|
|
2502
2672
|
neutral: "neutral"
|
|
2503
2673
|
};
|
|
2504
|
-
var StatCard =
|
|
2674
|
+
var StatCard = React45.forwardRef(
|
|
2505
2675
|
({ label, value, delta, hint, sub, icon: Icon, className, ...props }, ref) => {
|
|
2506
2676
|
const direction = delta?.direction ?? "neutral";
|
|
2507
2677
|
const tone = delta?.tone ?? toneFromDirection[direction];
|
|
2508
2678
|
const DeltaIcon = directionIcons[direction];
|
|
2509
2679
|
const deltaClass = toneClasses[tone];
|
|
2510
|
-
return /* @__PURE__ */
|
|
2680
|
+
return /* @__PURE__ */ jsxs24(
|
|
2511
2681
|
"div",
|
|
2512
2682
|
{
|
|
2513
2683
|
ref,
|
|
2514
2684
|
className: cn("rounded-xl border border-border-subtle bg-bg-surface p-5", className),
|
|
2515
2685
|
...props,
|
|
2516
2686
|
children: [
|
|
2517
|
-
/* @__PURE__ */
|
|
2518
|
-
/* @__PURE__ */
|
|
2519
|
-
/* @__PURE__ */
|
|
2520
|
-
hint && /* @__PURE__ */
|
|
2521
|
-
/* @__PURE__ */
|
|
2522
|
-
/* @__PURE__ */
|
|
2687
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2688
|
+
/* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-1.5", children: [
|
|
2689
|
+
/* @__PURE__ */ jsx51("span", { className: "text-xs font-medium uppercase tracking-wide text-text-tertiary", children: label }),
|
|
2690
|
+
hint && /* @__PURE__ */ jsx51(TooltipProvider, { children: /* @__PURE__ */ jsxs24(Tooltip, { children: [
|
|
2691
|
+
/* @__PURE__ */ jsx51(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx51("button", { type: "button", "aria-label": "More info", className: "inline-flex cursor-help text-icon-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus rounded-sm", children: /* @__PURE__ */ jsx51(Info2, { className: "size-3.5", "aria-hidden": "true" }) }) }),
|
|
2692
|
+
/* @__PURE__ */ jsx51(TooltipContent, { children: hint })
|
|
2523
2693
|
] }) })
|
|
2524
2694
|
] }),
|
|
2525
|
-
Icon && /* @__PURE__ */
|
|
2695
|
+
Icon && /* @__PURE__ */ jsx51(Icon, { className: "size-4 text-icon-secondary", "aria-hidden": "true" })
|
|
2526
2696
|
] }),
|
|
2527
|
-
/* @__PURE__ */
|
|
2528
|
-
(delta || sub) && /* @__PURE__ */
|
|
2529
|
-
delta && /* @__PURE__ */
|
|
2530
|
-
/* @__PURE__ */
|
|
2697
|
+
/* @__PURE__ */ jsx51("div", { className: "mt-2 text-3xl font-semibold text-text-primary", children: value }),
|
|
2698
|
+
(delta || sub) && /* @__PURE__ */ jsxs24("div", { className: "mt-2 flex items-center gap-2 text-sm", children: [
|
|
2699
|
+
delta && /* @__PURE__ */ jsxs24("span", { className: cn("inline-flex items-center gap-0.5 font-medium", deltaClass), children: [
|
|
2700
|
+
/* @__PURE__ */ jsx51(DeltaIcon, { className: "size-3.5", "aria-hidden": "true" }),
|
|
2531
2701
|
delta.value
|
|
2532
2702
|
] }),
|
|
2533
|
-
sub && /* @__PURE__ */
|
|
2703
|
+
sub && /* @__PURE__ */ jsx51("span", { className: "text-text-tertiary", children: sub })
|
|
2534
2704
|
] })
|
|
2535
2705
|
]
|
|
2536
2706
|
}
|
|
@@ -2540,11 +2710,11 @@ var StatCard = React44.forwardRef(
|
|
|
2540
2710
|
StatCard.displayName = "StatCard";
|
|
2541
2711
|
|
|
2542
2712
|
// src/components/confirm-dialog.tsx
|
|
2543
|
-
import * as
|
|
2713
|
+
import * as React46 from "react";
|
|
2544
2714
|
import { Loader2 } from "lucide-react";
|
|
2545
|
-
import { jsx as
|
|
2546
|
-
var InlineError =
|
|
2547
|
-
({ children, className, ...props }, ref) => /* @__PURE__ */
|
|
2715
|
+
import { jsx as jsx52, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2716
|
+
var InlineError = React46.forwardRef(
|
|
2717
|
+
({ children, className, ...props }, ref) => /* @__PURE__ */ jsx52(
|
|
2548
2718
|
"div",
|
|
2549
2719
|
{
|
|
2550
2720
|
ref,
|
|
@@ -2570,12 +2740,12 @@ function ConfirmDialog({
|
|
|
2570
2740
|
destructive = false,
|
|
2571
2741
|
onConfirm
|
|
2572
2742
|
}) {
|
|
2573
|
-
const [internalOpen, setInternalOpen] =
|
|
2743
|
+
const [internalOpen, setInternalOpen] = React46.useState(false);
|
|
2574
2744
|
const isControlled = open !== void 0;
|
|
2575
2745
|
const actualOpen = isControlled ? open : internalOpen;
|
|
2576
|
-
const [busy, setBusy] =
|
|
2577
|
-
const [error, setError] =
|
|
2578
|
-
|
|
2746
|
+
const [busy, setBusy] = React46.useState(false);
|
|
2747
|
+
const [error, setError] = React46.useState(null);
|
|
2748
|
+
React46.useEffect(() => {
|
|
2579
2749
|
if (!actualOpen) setError(null);
|
|
2580
2750
|
}, [actualOpen]);
|
|
2581
2751
|
const setOpen = (next) => {
|
|
@@ -2595,20 +2765,20 @@ function ConfirmDialog({
|
|
|
2595
2765
|
setBusy(false);
|
|
2596
2766
|
}
|
|
2597
2767
|
};
|
|
2598
|
-
return /* @__PURE__ */
|
|
2768
|
+
return /* @__PURE__ */ jsxs25(Dialog, { open: actualOpen, onOpenChange: (next) => {
|
|
2599
2769
|
if (!busy) setOpen(next);
|
|
2600
2770
|
}, children: [
|
|
2601
|
-
trigger && /* @__PURE__ */
|
|
2602
|
-
/* @__PURE__ */
|
|
2603
|
-
/* @__PURE__ */
|
|
2604
|
-
/* @__PURE__ */
|
|
2605
|
-
description && /* @__PURE__ */
|
|
2771
|
+
trigger && /* @__PURE__ */ jsx52(DialogTrigger, { asChild: true, children: trigger }),
|
|
2772
|
+
/* @__PURE__ */ jsxs25(DialogContent, { children: [
|
|
2773
|
+
/* @__PURE__ */ jsxs25(DialogHeader, { children: [
|
|
2774
|
+
/* @__PURE__ */ jsx52(DialogTitle, { children: title }),
|
|
2775
|
+
description && /* @__PURE__ */ jsx52(DialogDescription, { children: description })
|
|
2606
2776
|
] }),
|
|
2607
|
-
error && /* @__PURE__ */
|
|
2608
|
-
/* @__PURE__ */
|
|
2609
|
-
/* @__PURE__ */
|
|
2610
|
-
/* @__PURE__ */
|
|
2611
|
-
busy && /* @__PURE__ */
|
|
2777
|
+
error && /* @__PURE__ */ jsx52(InlineError, { children: error }),
|
|
2778
|
+
/* @__PURE__ */ jsxs25(DialogFooter, { children: [
|
|
2779
|
+
/* @__PURE__ */ jsx52(Button, { variant: "outline", disabled: busy, onClick: () => setOpen(false), children: cancelLabel }),
|
|
2780
|
+
/* @__PURE__ */ jsxs25(Button, { variant: destructive ? "destructive" : "default", disabled: busy, onClick: handleConfirm, children: [
|
|
2781
|
+
busy && /* @__PURE__ */ jsx52(Loader2, { className: "size-4 animate-spin", "aria-hidden": "true" }),
|
|
2612
2782
|
confirmLabel
|
|
2613
2783
|
] })
|
|
2614
2784
|
] })
|
|
@@ -2618,7 +2788,7 @@ function ConfirmDialog({
|
|
|
2618
2788
|
|
|
2619
2789
|
// src/components/user-menu.tsx
|
|
2620
2790
|
import { ChevronsUpDown } from "lucide-react";
|
|
2621
|
-
import { Fragment, jsx as
|
|
2791
|
+
import { Fragment as Fragment2, jsx as jsx53, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2622
2792
|
function initialsOf(name) {
|
|
2623
2793
|
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
2624
2794
|
if (parts.length === 0) return "?";
|
|
@@ -2627,11 +2797,11 @@ function initialsOf(name) {
|
|
|
2627
2797
|
}
|
|
2628
2798
|
function UserMenu({ user, items, collapsed = false, align = "start" }) {
|
|
2629
2799
|
const secondLine = user.subtitle ?? user.email;
|
|
2630
|
-
const avatar = /* @__PURE__ */
|
|
2631
|
-
user.avatarUrl && /* @__PURE__ */
|
|
2632
|
-
/* @__PURE__ */
|
|
2800
|
+
const avatar = /* @__PURE__ */ jsxs26(Avatar, { className: collapsed ? "size-9" : "size-7", children: [
|
|
2801
|
+
user.avatarUrl && /* @__PURE__ */ jsx53(AvatarImage, { src: user.avatarUrl, alt: user.name }),
|
|
2802
|
+
/* @__PURE__ */ jsx53(AvatarFallback, { className: "text-xs", children: initialsOf(user.name) })
|
|
2633
2803
|
] });
|
|
2634
|
-
const trigger = collapsed ? /* @__PURE__ */
|
|
2804
|
+
const trigger = collapsed ? /* @__PURE__ */ jsx53(
|
|
2635
2805
|
"button",
|
|
2636
2806
|
{
|
|
2637
2807
|
type: "button",
|
|
@@ -2639,46 +2809,46 @@ function UserMenu({ user, items, collapsed = false, align = "start" }) {
|
|
|
2639
2809
|
className: "rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
2640
2810
|
children: avatar
|
|
2641
2811
|
}
|
|
2642
|
-
) : /* @__PURE__ */
|
|
2812
|
+
) : /* @__PURE__ */ jsxs26(
|
|
2643
2813
|
"button",
|
|
2644
2814
|
{
|
|
2645
2815
|
type: "button",
|
|
2646
2816
|
className: "flex w-full items-center gap-2.5 rounded-xl px-1.5 py-[5px] text-left transition-colors hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
2647
2817
|
children: [
|
|
2648
2818
|
avatar,
|
|
2649
|
-
/* @__PURE__ */
|
|
2650
|
-
/* @__PURE__ */
|
|
2651
|
-
secondLine && /* @__PURE__ */
|
|
2819
|
+
/* @__PURE__ */ jsxs26("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
2820
|
+
/* @__PURE__ */ jsx53("span", { className: "truncate text-sm leading-[normal] font-medium text-text-primary", children: user.name }),
|
|
2821
|
+
secondLine && /* @__PURE__ */ jsx53("span", { className: "truncate text-xs leading-[normal] text-text-tertiary", children: secondLine })
|
|
2652
2822
|
] }),
|
|
2653
|
-
/* @__PURE__ */
|
|
2823
|
+
/* @__PURE__ */ jsx53(ChevronsUpDown, { size: 14, "aria-hidden": "true", className: "shrink-0 text-text-tertiary" })
|
|
2654
2824
|
]
|
|
2655
2825
|
}
|
|
2656
2826
|
);
|
|
2657
|
-
const menuTrigger = /* @__PURE__ */
|
|
2658
|
-
const menu = /* @__PURE__ */
|
|
2659
|
-
collapsed ? /* @__PURE__ */
|
|
2660
|
-
/* @__PURE__ */
|
|
2661
|
-
/* @__PURE__ */
|
|
2827
|
+
const menuTrigger = /* @__PURE__ */ jsx53(DropdownMenuTrigger, { asChild: true, children: trigger });
|
|
2828
|
+
const menu = /* @__PURE__ */ jsxs26(DropdownMenu, { children: [
|
|
2829
|
+
collapsed ? /* @__PURE__ */ jsx53(TooltipProvider, { children: /* @__PURE__ */ jsxs26(Tooltip, { children: [
|
|
2830
|
+
/* @__PURE__ */ jsx53(TooltipTrigger, { asChild: true, children: menuTrigger }),
|
|
2831
|
+
/* @__PURE__ */ jsx53(TooltipContent, { side: "right", children: user.name })
|
|
2662
2832
|
] }) }) : menuTrigger,
|
|
2663
|
-
/* @__PURE__ */
|
|
2833
|
+
/* @__PURE__ */ jsxs26(
|
|
2664
2834
|
DropdownMenuContent,
|
|
2665
2835
|
{
|
|
2666
2836
|
align,
|
|
2667
2837
|
sideOffset: 6,
|
|
2668
2838
|
className: "flex w-56 flex-col gap-px rounded-xl border-border-subtle bg-[var(--menu-bg)] p-1 shadow-(--menu-shadow)",
|
|
2669
2839
|
children: [
|
|
2670
|
-
/* @__PURE__ */
|
|
2671
|
-
/* @__PURE__ */
|
|
2672
|
-
secondLine && /* @__PURE__ */
|
|
2840
|
+
/* @__PURE__ */ jsxs26(DropdownMenuLabel, { className: "px-2 pt-1.5 pb-1 text-xs font-medium text-text-tertiary", children: [
|
|
2841
|
+
/* @__PURE__ */ jsx53("span", { className: "block truncate text-sm font-medium text-text-primary", children: user.name }),
|
|
2842
|
+
secondLine && /* @__PURE__ */ jsx53("span", { className: "block truncate text-xs font-normal text-text-tertiary", children: secondLine })
|
|
2673
2843
|
] }),
|
|
2674
|
-
/* @__PURE__ */
|
|
2844
|
+
/* @__PURE__ */ jsx53(DropdownMenuSeparator, { className: "mx-0 shrink-0 bg-border-subtle" }),
|
|
2675
2845
|
items.map((item, i) => {
|
|
2676
2846
|
const Icon = item.icon;
|
|
2677
|
-
const content = /* @__PURE__ */
|
|
2678
|
-
Icon && /* @__PURE__ */
|
|
2847
|
+
const content = /* @__PURE__ */ jsxs26(Fragment2, { children: [
|
|
2848
|
+
Icon && /* @__PURE__ */ jsx53(Icon, { className: "size-4", "aria-hidden": "true" }),
|
|
2679
2849
|
item.label
|
|
2680
2850
|
] });
|
|
2681
|
-
return /* @__PURE__ */
|
|
2851
|
+
return /* @__PURE__ */ jsx53(
|
|
2682
2852
|
DropdownMenuItem,
|
|
2683
2853
|
{
|
|
2684
2854
|
onSelect: item.onSelect,
|
|
@@ -2687,7 +2857,7 @@ function UserMenu({ user, items, collapsed = false, align = "start" }) {
|
|
|
2687
2857
|
item.destructive && "text-text-danger focus:text-text-danger"
|
|
2688
2858
|
),
|
|
2689
2859
|
asChild: Boolean(item.href),
|
|
2690
|
-
children: item.href ? /* @__PURE__ */
|
|
2860
|
+
children: item.href ? /* @__PURE__ */ jsx53("a", { href: item.href, children: content }) : content
|
|
2691
2861
|
},
|
|
2692
2862
|
`${item.label}-${i}`
|
|
2693
2863
|
);
|
|
@@ -2701,20 +2871,20 @@ function UserMenu({ user, items, collapsed = false, align = "start" }) {
|
|
|
2701
2871
|
|
|
2702
2872
|
// src/components/extension-link.tsx
|
|
2703
2873
|
import { Link as Link2 } from "react-router";
|
|
2704
|
-
import { jsx as
|
|
2874
|
+
import { jsx as jsx54 } from "react/jsx-runtime";
|
|
2705
2875
|
function ExtensionLink({ uiMode, to, className, children, ...anchorProps }) {
|
|
2706
2876
|
if (uiMode === "federation") {
|
|
2707
|
-
return /* @__PURE__ */
|
|
2877
|
+
return /* @__PURE__ */ jsx54(Link2, { to, className, ...anchorProps, children });
|
|
2708
2878
|
}
|
|
2709
|
-
return /* @__PURE__ */
|
|
2879
|
+
return /* @__PURE__ */ jsx54("a", { href: to, className, ...anchorProps, children });
|
|
2710
2880
|
}
|
|
2711
2881
|
ExtensionLink.displayName = "ExtensionLink";
|
|
2712
2882
|
|
|
2713
2883
|
// src/components/extension-icon.tsx
|
|
2714
|
-
import * as
|
|
2884
|
+
import * as React47 from "react";
|
|
2715
2885
|
import * as LucideIcons from "lucide-react";
|
|
2716
2886
|
import { Puzzle } from "lucide-react";
|
|
2717
|
-
import { jsx as
|
|
2887
|
+
import { jsx as jsx55 } from "react/jsx-runtime";
|
|
2718
2888
|
var FORWARD_REF = /* @__PURE__ */ Symbol.for("react.forward_ref");
|
|
2719
2889
|
var catalog = LucideIcons;
|
|
2720
2890
|
function toPascalCase(name) {
|
|
@@ -2739,14 +2909,14 @@ function warnUnknownIconOnce(name) {
|
|
|
2739
2909
|
warnedUnknownIcons.add(name);
|
|
2740
2910
|
console.warn(`[@lessly/ui] ExtensionIcon: unknown icon "${name}" \u2014 falling back to Puzzle.`);
|
|
2741
2911
|
}
|
|
2742
|
-
var ExtensionIcon =
|
|
2912
|
+
var ExtensionIcon = React47.forwardRef(
|
|
2743
2913
|
({ name, ...props }, ref) => {
|
|
2744
2914
|
const Icon = resolveIcon(name);
|
|
2745
2915
|
if (!Icon) {
|
|
2746
2916
|
warnUnknownIconOnce(name);
|
|
2747
|
-
return /* @__PURE__ */
|
|
2917
|
+
return /* @__PURE__ */ jsx55(Puzzle, { ref, ...props });
|
|
2748
2918
|
}
|
|
2749
|
-
return /* @__PURE__ */
|
|
2919
|
+
return /* @__PURE__ */ jsx55(Icon, { ref, ...props });
|
|
2750
2920
|
}
|
|
2751
2921
|
);
|
|
2752
2922
|
ExtensionIcon.displayName = "ExtensionIcon";
|
|
@@ -2793,9 +2963,9 @@ function useSidebar(options = {}) {
|
|
|
2793
2963
|
}
|
|
2794
2964
|
|
|
2795
2965
|
// src/components/nav-row.tsx
|
|
2796
|
-
import * as
|
|
2966
|
+
import * as React48 from "react";
|
|
2797
2967
|
import { Slot as Slot4 } from "@radix-ui/react-slot";
|
|
2798
|
-
import { Fragment as
|
|
2968
|
+
import { Fragment as Fragment3, jsx as jsx56, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2799
2969
|
var base = "flex w-full items-center text-left text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus";
|
|
2800
2970
|
var shape = {
|
|
2801
2971
|
rail: "gap-[14px] rounded-xl px-2.5 py-2",
|
|
@@ -2811,9 +2981,9 @@ var state = {
|
|
|
2811
2981
|
active: "font-semibold text-text-brand hover:bg-[var(--menu-hov)]"
|
|
2812
2982
|
}
|
|
2813
2983
|
};
|
|
2814
|
-
var NavRow =
|
|
2815
|
-
const content = /* @__PURE__ */
|
|
2816
|
-
icon && /* @__PURE__ */
|
|
2984
|
+
var NavRow = React48.forwardRef(function NavRow2({ icon, label, active = false, variant, trailing, hideLabel = false, asChild = false, className, children, ...props }, ref) {
|
|
2985
|
+
const content = /* @__PURE__ */ jsxs27(Fragment3, { children: [
|
|
2986
|
+
icon && /* @__PURE__ */ jsx56(
|
|
2817
2987
|
"span",
|
|
2818
2988
|
{
|
|
2819
2989
|
className: "flex size-5 shrink-0 items-center justify-center [&_svg]:size-[18px]",
|
|
@@ -2821,24 +2991,24 @@ var NavRow = React47.forwardRef(function NavRow2({ icon, label, active = false,
|
|
|
2821
2991
|
children: icon
|
|
2822
2992
|
}
|
|
2823
2993
|
),
|
|
2824
|
-
!hideLabel && /* @__PURE__ */
|
|
2825
|
-
trailing && /* @__PURE__ */
|
|
2994
|
+
!hideLabel && /* @__PURE__ */ jsx56("span", { className: "min-w-0 flex-1 truncate", children: label }),
|
|
2995
|
+
trailing && /* @__PURE__ */ jsx56("span", { className: "flex shrink-0 items-center", children: trailing })
|
|
2826
2996
|
] });
|
|
2827
2997
|
const classes = cn(base, shape[variant], state[variant][active ? "active" : "idle"], className);
|
|
2828
2998
|
if (asChild) {
|
|
2829
|
-
const child =
|
|
2830
|
-
return /* @__PURE__ */
|
|
2999
|
+
const child = React48.Children.only(children);
|
|
3000
|
+
return /* @__PURE__ */ jsx56(Slot4, { ref, className: classes, "aria-label": hideLabel ? label : void 0, ...props, children: React48.cloneElement(child, void 0, content) });
|
|
2831
3001
|
}
|
|
2832
|
-
return /* @__PURE__ */
|
|
3002
|
+
return /* @__PURE__ */ jsx56("button", { ref, type: "button", className: classes, "aria-label": hideLabel ? label : void 0, ...props, children: content });
|
|
2833
3003
|
});
|
|
2834
3004
|
NavRow.displayName = "NavRow";
|
|
2835
3005
|
|
|
2836
3006
|
// src/components/nav-section-label.tsx
|
|
2837
|
-
import * as
|
|
2838
|
-
import { jsx as
|
|
2839
|
-
var NavSectionLabel =
|
|
3007
|
+
import * as React49 from "react";
|
|
3008
|
+
import { jsx as jsx57 } from "react/jsx-runtime";
|
|
3009
|
+
var NavSectionLabel = React49.forwardRef(
|
|
2840
3010
|
function NavSectionLabel2({ className, ...props }, ref) {
|
|
2841
|
-
return /* @__PURE__ */
|
|
3011
|
+
return /* @__PURE__ */ jsx57(
|
|
2842
3012
|
"div",
|
|
2843
3013
|
{
|
|
2844
3014
|
ref,
|
|
@@ -2851,8 +3021,8 @@ var NavSectionLabel = React48.forwardRef(
|
|
|
2851
3021
|
NavSectionLabel.displayName = "NavSectionLabel";
|
|
2852
3022
|
|
|
2853
3023
|
// src/components/menu-popup.tsx
|
|
2854
|
-
import * as
|
|
2855
|
-
import { jsx as
|
|
3024
|
+
import * as React50 from "react";
|
|
3025
|
+
import { jsx as jsx58, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2856
3026
|
function MenuPopup({
|
|
2857
3027
|
trigger,
|
|
2858
3028
|
children,
|
|
@@ -2864,9 +3034,9 @@ function MenuPopup({
|
|
|
2864
3034
|
sideOffset = 6,
|
|
2865
3035
|
className
|
|
2866
3036
|
}) {
|
|
2867
|
-
return /* @__PURE__ */
|
|
2868
|
-
/* @__PURE__ */
|
|
2869
|
-
/* @__PURE__ */
|
|
3037
|
+
return /* @__PURE__ */ jsxs28(Popover, { open, defaultOpen, onOpenChange, children: [
|
|
3038
|
+
/* @__PURE__ */ jsx58(PopoverTrigger, { asChild: true, children: trigger }),
|
|
3039
|
+
/* @__PURE__ */ jsx58(
|
|
2870
3040
|
PopoverContent,
|
|
2871
3041
|
{
|
|
2872
3042
|
side: direction === "up" ? "top" : "bottom",
|
|
@@ -2881,9 +3051,9 @@ function MenuPopup({
|
|
|
2881
3051
|
)
|
|
2882
3052
|
] });
|
|
2883
3053
|
}
|
|
2884
|
-
var MenuDivider =
|
|
3054
|
+
var MenuDivider = React50.forwardRef(
|
|
2885
3055
|
function MenuDivider2({ className, ...props }, ref) {
|
|
2886
|
-
return /* @__PURE__ */
|
|
3056
|
+
return /* @__PURE__ */ jsx58(
|
|
2887
3057
|
"div",
|
|
2888
3058
|
{
|
|
2889
3059
|
ref,
|
|
@@ -2898,7 +3068,7 @@ MenuDivider.displayName = "MenuDivider";
|
|
|
2898
3068
|
|
|
2899
3069
|
// src/components/sidebar-nav.tsx
|
|
2900
3070
|
import { Link as Link3, useLocation } from "react-router";
|
|
2901
|
-
import { jsx as
|
|
3071
|
+
import { jsx as jsx59, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2902
3072
|
function isActivePath(pathname, full, exact) {
|
|
2903
3073
|
if (exact) return pathname === full;
|
|
2904
3074
|
return pathname === full || pathname.startsWith(`${full}/`);
|
|
@@ -2914,23 +3084,23 @@ function SidebarNavLink({
|
|
|
2914
3084
|
const Comp = LinkComponent ?? Link3;
|
|
2915
3085
|
const to = `${basePath}${item.href}`;
|
|
2916
3086
|
const Icon = item.icon;
|
|
2917
|
-
const link = /* @__PURE__ */
|
|
3087
|
+
const link = /* @__PURE__ */ jsx59(
|
|
2918
3088
|
NavRow,
|
|
2919
3089
|
{
|
|
2920
3090
|
variant: "rail",
|
|
2921
3091
|
active,
|
|
2922
3092
|
label: item.label,
|
|
2923
3093
|
hideLabel: collapsed,
|
|
2924
|
-
icon: Icon ? /* @__PURE__ */
|
|
3094
|
+
icon: Icon ? /* @__PURE__ */ jsx59(Icon, { "aria-hidden": "true" }) : void 0,
|
|
2925
3095
|
className: cn(collapsed && "size-9 justify-center px-0 py-0", className),
|
|
2926
3096
|
asChild: true,
|
|
2927
|
-
children: /* @__PURE__ */
|
|
3097
|
+
children: /* @__PURE__ */ jsx59(Comp, { to, "aria-current": active ? "page" : void 0 })
|
|
2928
3098
|
}
|
|
2929
3099
|
);
|
|
2930
3100
|
if (!collapsed) return link;
|
|
2931
|
-
return /* @__PURE__ */
|
|
2932
|
-
/* @__PURE__ */
|
|
2933
|
-
/* @__PURE__ */
|
|
3101
|
+
return /* @__PURE__ */ jsxs29(Tooltip, { children: [
|
|
3102
|
+
/* @__PURE__ */ jsx59(TooltipTrigger, { asChild: true, children: link }),
|
|
3103
|
+
/* @__PURE__ */ jsx59(TooltipContent, { side: "right", children: item.label })
|
|
2934
3104
|
] });
|
|
2935
3105
|
}
|
|
2936
3106
|
function SidebarNav({
|
|
@@ -2942,7 +3112,7 @@ function SidebarNav({
|
|
|
2942
3112
|
className
|
|
2943
3113
|
}) {
|
|
2944
3114
|
const { pathname } = useLocation();
|
|
2945
|
-
const nav = /* @__PURE__ */
|
|
3115
|
+
const nav = /* @__PURE__ */ jsx59(
|
|
2946
3116
|
"nav",
|
|
2947
3117
|
{
|
|
2948
3118
|
className: cn(
|
|
@@ -2953,7 +3123,7 @@ function SidebarNav({
|
|
|
2953
3123
|
children: items.map((item) => {
|
|
2954
3124
|
const full = `${basePath}${item.href}`;
|
|
2955
3125
|
const active = isItemActive ? isItemActive(item, pathname) : isActivePath(pathname, full, item.exact);
|
|
2956
|
-
return /* @__PURE__ */
|
|
3126
|
+
return /* @__PURE__ */ jsx59(
|
|
2957
3127
|
SidebarNavLink,
|
|
2958
3128
|
{
|
|
2959
3129
|
item,
|
|
@@ -2967,14 +3137,14 @@ function SidebarNav({
|
|
|
2967
3137
|
})
|
|
2968
3138
|
}
|
|
2969
3139
|
);
|
|
2970
|
-
return collapsed ? /* @__PURE__ */
|
|
3140
|
+
return collapsed ? /* @__PURE__ */ jsx59(TooltipProvider, { children: nav }) : nav;
|
|
2971
3141
|
}
|
|
2972
3142
|
|
|
2973
3143
|
// src/components/app-sidebar.tsx
|
|
2974
3144
|
import { PanelLeft } from "lucide-react";
|
|
2975
|
-
import { Fragment as
|
|
3145
|
+
import { Fragment as Fragment4, jsx as jsx60, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2976
3146
|
function Divider({ collapsed, testId, className }) {
|
|
2977
|
-
return /* @__PURE__ */
|
|
3147
|
+
return /* @__PURE__ */ jsx60(
|
|
2978
3148
|
"div",
|
|
2979
3149
|
{
|
|
2980
3150
|
"data-testid": testId,
|
|
@@ -3006,7 +3176,7 @@ function AppSidebar({
|
|
|
3006
3176
|
defaultCollapsed,
|
|
3007
3177
|
onCollapsedChange
|
|
3008
3178
|
});
|
|
3009
|
-
const pin = collapsible ? /* @__PURE__ */
|
|
3179
|
+
const pin = collapsible ? /* @__PURE__ */ jsx60(
|
|
3010
3180
|
"button",
|
|
3011
3181
|
{
|
|
3012
3182
|
type: "button",
|
|
@@ -3014,10 +3184,10 @@ function AppSidebar({
|
|
|
3014
3184
|
"aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
3015
3185
|
"aria-expanded": !collapsed,
|
|
3016
3186
|
className: "flex size-6 shrink-0 items-center justify-center rounded-md text-text-secondary transition-colors hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
3017
|
-
children: /* @__PURE__ */
|
|
3187
|
+
children: /* @__PURE__ */ jsx60(PanelLeft, { className: "size-4", "aria-hidden": "true" })
|
|
3018
3188
|
}
|
|
3019
3189
|
) : null;
|
|
3020
|
-
return /* @__PURE__ */
|
|
3190
|
+
return /* @__PURE__ */ jsxs30(
|
|
3021
3191
|
"aside",
|
|
3022
3192
|
{
|
|
3023
3193
|
"data-collapsed": collapsed,
|
|
@@ -3027,12 +3197,12 @@ function AppSidebar({
|
|
|
3027
3197
|
className
|
|
3028
3198
|
),
|
|
3029
3199
|
children: [
|
|
3030
|
-
/* @__PURE__ */
|
|
3200
|
+
/* @__PURE__ */ jsx60("div", { className: cn("flex items-center gap-2", collapsed ? "justify-center px-1 pt-2" : "px-3 pt-[13px]"), children: collapsed ? collapsible ? logoCollapsed ?? logo ? (
|
|
3031
3201
|
/* The collapsed rail (52px) can't fit the logo mark beside the pin side by side —
|
|
3032
3202
|
so the pin overlays the mark instead, revealed on hover/focus, same as pre-flat-rail. */
|
|
3033
|
-
/* @__PURE__ */
|
|
3034
|
-
/* @__PURE__ */
|
|
3035
|
-
/* @__PURE__ */
|
|
3203
|
+
/* @__PURE__ */ jsxs30("div", { className: "group relative flex size-8 items-center justify-center", children: [
|
|
3204
|
+
/* @__PURE__ */ jsx60("span", { className: "pointer-events-none transition-opacity group-hover:opacity-0 group-focus-within:opacity-0", children: logoCollapsed ?? logo }),
|
|
3205
|
+
/* @__PURE__ */ jsx60(
|
|
3036
3206
|
"button",
|
|
3037
3207
|
{
|
|
3038
3208
|
type: "button",
|
|
@@ -3040,7 +3210,7 @@ function AppSidebar({
|
|
|
3040
3210
|
"aria-label": "Expand sidebar",
|
|
3041
3211
|
"aria-expanded": false,
|
|
3042
3212
|
className: "absolute inset-0 flex items-center justify-center rounded-md text-text-secondary opacity-0 transition-opacity hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-border-focus group-hover:opacity-100 group-focus-within:opacity-100",
|
|
3043
|
-
children: /* @__PURE__ */
|
|
3213
|
+
children: /* @__PURE__ */ jsx60(PanelLeft, { className: "size-4", "aria-hidden": "true" })
|
|
3044
3214
|
}
|
|
3045
3215
|
)
|
|
3046
3216
|
] })
|
|
@@ -3049,7 +3219,7 @@ function AppSidebar({
|
|
|
3049
3219
|
count, it's expanded-only). Hover-revealing the pin over nothing would leave
|
|
3050
3220
|
an invisible 32px box as the only way back to expanded, so render it plain
|
|
3051
3221
|
and fully visible instead. */
|
|
3052
|
-
/* @__PURE__ */
|
|
3222
|
+
/* @__PURE__ */ jsx60(
|
|
3053
3223
|
"button",
|
|
3054
3224
|
{
|
|
3055
3225
|
type: "button",
|
|
@@ -3057,15 +3227,15 @@ function AppSidebar({
|
|
|
3057
3227
|
"aria-label": "Expand sidebar",
|
|
3058
3228
|
"aria-expanded": false,
|
|
3059
3229
|
className: "flex size-8 shrink-0 items-center justify-center rounded-md text-text-secondary transition-colors hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
|
|
3060
|
-
children: /* @__PURE__ */
|
|
3230
|
+
children: /* @__PURE__ */ jsx60(PanelLeft, { className: "size-4", "aria-hidden": "true" })
|
|
3061
3231
|
}
|
|
3062
3232
|
)
|
|
3063
|
-
) : logoCollapsed ?? logo : /* @__PURE__ */
|
|
3233
|
+
) : logoCollapsed ?? logo : /* @__PURE__ */ jsxs30(Fragment4, { children: [
|
|
3064
3234
|
header ?? logo,
|
|
3065
3235
|
pin
|
|
3066
3236
|
] }) }),
|
|
3067
|
-
/* @__PURE__ */
|
|
3068
|
-
/* @__PURE__ */
|
|
3237
|
+
/* @__PURE__ */ jsx60(Divider, { collapsed, testId: "sidebar-divider-header", className: "mt-3" }),
|
|
3238
|
+
/* @__PURE__ */ jsx60(
|
|
3069
3239
|
"div",
|
|
3070
3240
|
{
|
|
3071
3241
|
"data-testid": "sidebar-scroll",
|
|
@@ -3073,12 +3243,12 @@ function AppSidebar({
|
|
|
3073
3243
|
"min-h-0 flex-1 overflow-y-auto overflow-x-hidden pt-3 pb-2",
|
|
3074
3244
|
collapsed ? "px-1" : "px-3"
|
|
3075
3245
|
),
|
|
3076
|
-
children: /* @__PURE__ */
|
|
3246
|
+
children: /* @__PURE__ */ jsx60(SidebarNav, { items, collapsed, basePath, LinkComponent, isItemActive })
|
|
3077
3247
|
}
|
|
3078
3248
|
),
|
|
3079
|
-
footer && /* @__PURE__ */
|
|
3080
|
-
/* @__PURE__ */
|
|
3081
|
-
/* @__PURE__ */
|
|
3249
|
+
footer && /* @__PURE__ */ jsxs30(Fragment4, { children: [
|
|
3250
|
+
/* @__PURE__ */ jsx60(Divider, { collapsed, testId: "sidebar-divider-account" }),
|
|
3251
|
+
/* @__PURE__ */ jsx60("div", { className: cn("py-2", collapsed ? "px-1" : "px-3"), children: footer })
|
|
3082
3252
|
] })
|
|
3083
3253
|
]
|
|
3084
3254
|
}
|
|
@@ -3086,36 +3256,123 @@ function AppSidebar({
|
|
|
3086
3256
|
}
|
|
3087
3257
|
|
|
3088
3258
|
// src/components/sidebar-product-header.tsx
|
|
3089
|
-
import * as
|
|
3259
|
+
import * as React51 from "react";
|
|
3090
3260
|
import { Slot as Slot5 } from "@radix-ui/react-slot";
|
|
3091
3261
|
import { ChevronsUpDown as ChevronsUpDown2 } from "lucide-react";
|
|
3092
|
-
import { Fragment as
|
|
3093
|
-
var SidebarProductHeader =
|
|
3262
|
+
import { Fragment as Fragment5, jsx as jsx61, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
3263
|
+
var SidebarProductHeader = React51.forwardRef(
|
|
3094
3264
|
function SidebarProductHeader2({ name, icon, trailing, asChild = false, className, children, ...props }, ref) {
|
|
3095
|
-
const adornment = trailing === void 0 ? /* @__PURE__ */
|
|
3096
|
-
const content = /* @__PURE__ */
|
|
3097
|
-
icon && /* @__PURE__ */
|
|
3098
|
-
/* @__PURE__ */
|
|
3099
|
-
adornment && /* @__PURE__ */
|
|
3265
|
+
const adornment = trailing === void 0 ? /* @__PURE__ */ jsx61(ChevronsUpDown2, { size: 14, "aria-hidden": "true", className: "shrink-0 text-text-tertiary" }) : trailing;
|
|
3266
|
+
const content = /* @__PURE__ */ jsxs31(Fragment5, { children: [
|
|
3267
|
+
icon && /* @__PURE__ */ jsx61("span", { className: "flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-md", "aria-hidden": "true", children: icon }),
|
|
3268
|
+
/* @__PURE__ */ jsx61("span", { className: "min-w-0 flex-1 truncate text-sm font-semibold text-text-primary", children: name }),
|
|
3269
|
+
adornment && /* @__PURE__ */ jsx61("span", { className: "flex shrink-0 items-center", children: adornment })
|
|
3100
3270
|
] });
|
|
3101
3271
|
const classes = cn("flex w-full items-center gap-2.5 rounded-xl px-1.5 py-0 text-left", className);
|
|
3102
3272
|
if (asChild) {
|
|
3103
|
-
const child =
|
|
3104
|
-
return /* @__PURE__ */
|
|
3273
|
+
const child = React51.Children.only(children);
|
|
3274
|
+
return /* @__PURE__ */ jsx61(Slot5, { ref, className: classes, ...props, children: React51.cloneElement(child, void 0, content) });
|
|
3105
3275
|
}
|
|
3106
|
-
return /* @__PURE__ */
|
|
3276
|
+
return /* @__PURE__ */ jsx61("button", { ref, type: "button", className: classes, ...props, children: content });
|
|
3107
3277
|
}
|
|
3108
3278
|
);
|
|
3109
3279
|
SidebarProductHeader.displayName = "SidebarProductHeader";
|
|
3110
3280
|
|
|
3281
|
+
// src/components/org-product-switcher.tsx
|
|
3282
|
+
import { ChevronsUpDown as ChevronsUpDown3, Check as Check6 } from "lucide-react";
|
|
3283
|
+
import { Fragment as Fragment6, jsx as jsx62, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
3284
|
+
var triggerBox = "flex w-full items-center gap-2.5 rounded-xl px-1.5 py-1 text-left transition-colors hover:bg-[var(--hov-bg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus";
|
|
3285
|
+
var menuItem = "gap-2 rounded-md px-2 py-1.5 text-sm font-medium text-text-secondary focus:bg-[var(--menu-hov)] focus:text-text-primary";
|
|
3286
|
+
var sectionLabel = "px-2 pt-1.5 pb-1 text-xs font-medium text-text-tertiary";
|
|
3287
|
+
function Mark({ item, size }) {
|
|
3288
|
+
const box = size === "md" ? "size-7" : "size-5";
|
|
3289
|
+
if (item.icon) {
|
|
3290
|
+
return /* @__PURE__ */ jsx62("span", { className: cn("flex shrink-0 items-center justify-center overflow-hidden rounded-md", box), "aria-hidden": "true", children: item.icon });
|
|
3291
|
+
}
|
|
3292
|
+
return /* @__PURE__ */ jsx62(
|
|
3293
|
+
"span",
|
|
3294
|
+
{
|
|
3295
|
+
"aria-hidden": "true",
|
|
3296
|
+
className: cn(
|
|
3297
|
+
"flex shrink-0 items-center justify-center rounded-md bg-[var(--menu-hov)] font-semibold text-text-secondary",
|
|
3298
|
+
box,
|
|
3299
|
+
size === "md" ? "text-sm" : "text-xs"
|
|
3300
|
+
),
|
|
3301
|
+
children: item.name.charAt(0).toUpperCase()
|
|
3302
|
+
}
|
|
3303
|
+
);
|
|
3304
|
+
}
|
|
3305
|
+
function OrgProductSwitcher({
|
|
3306
|
+
organizations,
|
|
3307
|
+
activeOrgId,
|
|
3308
|
+
onOrgSelect,
|
|
3309
|
+
products,
|
|
3310
|
+
activeProductId,
|
|
3311
|
+
onProductSelect,
|
|
3312
|
+
actions,
|
|
3313
|
+
className,
|
|
3314
|
+
...props
|
|
3315
|
+
}) {
|
|
3316
|
+
const activeOrg = organizations.find((o) => o.id === activeOrgId);
|
|
3317
|
+
const activeProduct = products.find((p) => p.id === activeProductId);
|
|
3318
|
+
const ariaLabel = props["aria-label"] ?? `${activeOrg?.name ?? ""} / ${activeProduct?.name ?? ""}`;
|
|
3319
|
+
return /* @__PURE__ */ jsxs32(DropdownMenu, { children: [
|
|
3320
|
+
/* @__PURE__ */ jsxs32(DropdownMenuTrigger, { "aria-label": ariaLabel, className: cn(triggerBox, className), children: [
|
|
3321
|
+
activeProduct && /* @__PURE__ */ jsx62(Mark, { item: activeProduct, size: "md" }),
|
|
3322
|
+
/* @__PURE__ */ jsxs32("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
3323
|
+
/* @__PURE__ */ jsx62("span", { className: "truncate text-xs leading-[normal] text-text-tertiary", children: activeOrg?.name }),
|
|
3324
|
+
/* @__PURE__ */ jsx62("span", { className: "truncate text-sm leading-[normal] font-semibold text-text-primary", children: activeProduct?.name })
|
|
3325
|
+
] }),
|
|
3326
|
+
/* @__PURE__ */ jsx62(ChevronsUpDown3, { size: 14, "aria-hidden": "true", className: "shrink-0 text-text-tertiary" })
|
|
3327
|
+
] }),
|
|
3328
|
+
/* @__PURE__ */ jsxs32(
|
|
3329
|
+
DropdownMenuContent,
|
|
3330
|
+
{
|
|
3331
|
+
align: "start",
|
|
3332
|
+
sideOffset: 6,
|
|
3333
|
+
className: "flex w-60 flex-col gap-px rounded-xl border-border-subtle bg-[var(--menu-bg)] p-1 shadow-(--menu-shadow)",
|
|
3334
|
+
children: [
|
|
3335
|
+
/* @__PURE__ */ jsx62(DropdownMenuLabel, { className: sectionLabel, children: "Organizations" }),
|
|
3336
|
+
organizations.map((o) => /* @__PURE__ */ jsxs32(DropdownMenuItem, { className: menuItem, onSelect: () => onOrgSelect(o.id), children: [
|
|
3337
|
+
/* @__PURE__ */ jsx62(Mark, { item: o, size: "sm" }),
|
|
3338
|
+
/* @__PURE__ */ jsx62("span", { className: "min-w-0 flex-1 truncate", children: o.name }),
|
|
3339
|
+
o.id === activeOrgId && /* @__PURE__ */ jsx62(Check6, { className: "size-4 shrink-0 text-text-secondary", "aria-hidden": "true" })
|
|
3340
|
+
] }, o.id)),
|
|
3341
|
+
/* @__PURE__ */ jsx62(DropdownMenuSeparator, { className: "mx-0 shrink-0 bg-border-subtle" }),
|
|
3342
|
+
/* @__PURE__ */ jsxs32(DropdownMenuLabel, { className: sectionLabel, children: [
|
|
3343
|
+
activeOrg?.name,
|
|
3344
|
+
" \xB7 Products"
|
|
3345
|
+
] }),
|
|
3346
|
+
products.map((p) => /* @__PURE__ */ jsxs32(DropdownMenuItem, { className: menuItem, onSelect: () => onProductSelect(p.id), children: [
|
|
3347
|
+
/* @__PURE__ */ jsx62(Mark, { item: p, size: "sm" }),
|
|
3348
|
+
/* @__PURE__ */ jsx62("span", { className: "min-w-0 flex-1 truncate", children: p.name }),
|
|
3349
|
+
p.id === activeProductId && /* @__PURE__ */ jsx62(Check6, { className: "size-4 shrink-0 text-text-secondary", "aria-hidden": "true" })
|
|
3350
|
+
] }, p.id)),
|
|
3351
|
+
actions && actions.length > 0 && /* @__PURE__ */ jsxs32(Fragment6, { children: [
|
|
3352
|
+
/* @__PURE__ */ jsx62(DropdownMenuSeparator, { className: "mx-0 shrink-0 bg-border-subtle" }),
|
|
3353
|
+
actions.map((a) => /* @__PURE__ */ jsx62(DropdownMenuItem, { className: menuItem, onSelect: a.onSelect, asChild: Boolean(a.href), children: a.href ? /* @__PURE__ */ jsxs32("a", { href: a.href, children: [
|
|
3354
|
+
a.icon,
|
|
3355
|
+
a.label
|
|
3356
|
+
] }) : /* @__PURE__ */ jsxs32(Fragment6, { children: [
|
|
3357
|
+
a.icon,
|
|
3358
|
+
a.label
|
|
3359
|
+
] }) }, a.id))
|
|
3360
|
+
] })
|
|
3361
|
+
]
|
|
3362
|
+
}
|
|
3363
|
+
)
|
|
3364
|
+
] });
|
|
3365
|
+
}
|
|
3366
|
+
OrgProductSwitcher.displayName = "OrgProductSwitcher";
|
|
3367
|
+
|
|
3111
3368
|
// src/components/sidebar-back-header.tsx
|
|
3112
3369
|
import { ArrowLeft as ArrowLeft2 } from "lucide-react";
|
|
3113
|
-
import { jsx as
|
|
3370
|
+
import { jsx as jsx63, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3114
3371
|
var focusRing = "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus";
|
|
3115
3372
|
var arrowPlate = "flex size-5 items-center justify-center rounded-md transition-colors hover:bg-[color-mix(in_srgb,var(--text-primary)_12%,transparent)] hover:text-text-primary";
|
|
3116
3373
|
var arrowBox = "flex shrink-0 cursor-pointer items-center rounded-xl py-2 pr-0 pl-2.5 text-text-secondary";
|
|
3117
3374
|
var titleBox = "min-w-0 flex-1 cursor-pointer truncate rounded-xl py-2 pr-2.5 pl-[14px] text-left text-sm font-semibold text-text-primary";
|
|
3118
|
-
var Arrow = () => /* @__PURE__ */
|
|
3375
|
+
var Arrow = () => /* @__PURE__ */ jsx63(ArrowLeft2, { size: 16, "aria-hidden": "true" });
|
|
3119
3376
|
function SidebarBackHeader({
|
|
3120
3377
|
title,
|
|
3121
3378
|
onBack,
|
|
@@ -3129,7 +3386,7 @@ function SidebarBackHeader({
|
|
|
3129
3386
|
const { className: arrowClassName, ...arrowRest } = arrowProps ?? {};
|
|
3130
3387
|
const { className: titleClassName, ...titleRest } = titleProps ?? {};
|
|
3131
3388
|
if (!onTitleClick) {
|
|
3132
|
-
return /* @__PURE__ */
|
|
3389
|
+
return /* @__PURE__ */ jsxs33(
|
|
3133
3390
|
"button",
|
|
3134
3391
|
{
|
|
3135
3392
|
type: "button",
|
|
@@ -3137,14 +3394,14 @@ function SidebarBackHeader({
|
|
|
3137
3394
|
className: cn("flex items-center rounded-xl", focusRing, className),
|
|
3138
3395
|
...rowProps,
|
|
3139
3396
|
children: [
|
|
3140
|
-
/* @__PURE__ */
|
|
3141
|
-
/* @__PURE__ */
|
|
3397
|
+
/* @__PURE__ */ jsx63("span", { className: arrowBox, children: /* @__PURE__ */ jsx63("span", { className: cn(arrowPlate, arrowClassName), ...arrowRest, children: /* @__PURE__ */ jsx63(Arrow, {}) }) }),
|
|
3398
|
+
/* @__PURE__ */ jsx63("span", { className: cn(titleBox, titleClassName), ...titleRest, children: title })
|
|
3142
3399
|
]
|
|
3143
3400
|
}
|
|
3144
3401
|
);
|
|
3145
3402
|
}
|
|
3146
|
-
return /* @__PURE__ */
|
|
3147
|
-
/* @__PURE__ */
|
|
3403
|
+
return /* @__PURE__ */ jsxs33("div", { className: cn("flex items-center", className), ...rowProps, children: [
|
|
3404
|
+
/* @__PURE__ */ jsx63(
|
|
3148
3405
|
"button",
|
|
3149
3406
|
{
|
|
3150
3407
|
type: "button",
|
|
@@ -3152,10 +3409,10 @@ function SidebarBackHeader({
|
|
|
3152
3409
|
onClick: onBack,
|
|
3153
3410
|
className: cn(arrowBox, focusRing, arrowClassName),
|
|
3154
3411
|
...arrowRest,
|
|
3155
|
-
children: /* @__PURE__ */
|
|
3412
|
+
children: /* @__PURE__ */ jsx63("span", { className: arrowPlate, children: /* @__PURE__ */ jsx63(Arrow, {}) })
|
|
3156
3413
|
}
|
|
3157
3414
|
),
|
|
3158
|
-
/* @__PURE__ */
|
|
3415
|
+
/* @__PURE__ */ jsx63(
|
|
3159
3416
|
"button",
|
|
3160
3417
|
{
|
|
3161
3418
|
type: "button",
|
|
@@ -3170,54 +3427,54 @@ function SidebarBackHeader({
|
|
|
3170
3427
|
SidebarBackHeader.displayName = "SidebarBackHeader";
|
|
3171
3428
|
|
|
3172
3429
|
// src/components/app-shell.tsx
|
|
3173
|
-
import * as
|
|
3430
|
+
import * as React52 from "react";
|
|
3174
3431
|
import { Menu as Menu2 } from "lucide-react";
|
|
3175
3432
|
import { useLocation as useLocation2 } from "react-router";
|
|
3176
|
-
import { jsx as
|
|
3433
|
+
import { jsx as jsx64, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
3177
3434
|
function expandedSidebar(sidebar) {
|
|
3178
|
-
return
|
|
3435
|
+
return React52.isValidElement(sidebar) ? React52.cloneElement(sidebar, { collapsed: false }) : sidebar;
|
|
3179
3436
|
}
|
|
3180
3437
|
function AppShell({ sidebar, topBar, children, className }) {
|
|
3181
3438
|
const { pathname } = useLocation2();
|
|
3182
|
-
const [mobileOpen, setMobileOpen] =
|
|
3183
|
-
|
|
3439
|
+
const [mobileOpen, setMobileOpen] = React52.useState(false);
|
|
3440
|
+
React52.useEffect(() => {
|
|
3184
3441
|
setMobileOpen(false);
|
|
3185
3442
|
}, [pathname]);
|
|
3186
3443
|
const isMobile = useIsMobile();
|
|
3187
3444
|
if (isMobile) {
|
|
3188
|
-
return /* @__PURE__ */
|
|
3189
|
-
/* @__PURE__ */
|
|
3190
|
-
/* @__PURE__ */
|
|
3191
|
-
/* @__PURE__ */
|
|
3192
|
-
/* @__PURE__ */
|
|
3193
|
-
/* @__PURE__ */
|
|
3194
|
-
/* @__PURE__ */
|
|
3445
|
+
return /* @__PURE__ */ jsx64(TooltipProvider, { children: /* @__PURE__ */ jsxs34("div", { className: cn("flex min-h-screen flex-col bg-bg-surface", className), children: [
|
|
3446
|
+
/* @__PURE__ */ jsxs34("header", { className: "flex shrink-0 items-center justify-between border-b border-border-subtle bg-bg-surface px-4 py-3", children: [
|
|
3447
|
+
/* @__PURE__ */ jsxs34(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: [
|
|
3448
|
+
/* @__PURE__ */ jsx64(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsx64(Button, { variant: "ghost", size: "icon", className: "size-8 text-text-secondary", "aria-label": "Open navigation", children: /* @__PURE__ */ jsx64(Menu2, { className: "size-5" }) }) }),
|
|
3449
|
+
/* @__PURE__ */ jsxs34(SheetContent, { side: "left", className: "w-[248px] bg-bg-surface p-0", children: [
|
|
3450
|
+
/* @__PURE__ */ jsx64(SheetTitle, { className: "sr-only", children: "Navigation" }),
|
|
3451
|
+
/* @__PURE__ */ jsx64(SheetDescription, { className: "sr-only", children: "Application navigation menu" }),
|
|
3195
3452
|
expandedSidebar(sidebar)
|
|
3196
3453
|
] })
|
|
3197
3454
|
] }),
|
|
3198
|
-
/* @__PURE__ */
|
|
3455
|
+
/* @__PURE__ */ jsx64("div", { className: "flex items-center gap-2", children: topBar })
|
|
3199
3456
|
] }),
|
|
3200
|
-
/* @__PURE__ */
|
|
3457
|
+
/* @__PURE__ */ jsx64("main", { className: "flex-1 overflow-auto", children })
|
|
3201
3458
|
] }) });
|
|
3202
3459
|
}
|
|
3203
|
-
return /* @__PURE__ */
|
|
3204
|
-
/* @__PURE__ */
|
|
3205
|
-
/* @__PURE__ */
|
|
3206
|
-
topBar && /* @__PURE__ */
|
|
3207
|
-
/* @__PURE__ */
|
|
3460
|
+
return /* @__PURE__ */ jsx64(TooltipProvider, { children: /* @__PURE__ */ jsxs34("div", { className: cn("flex min-h-screen gap-3 bg-bg-surface p-4", className), children: [
|
|
3461
|
+
/* @__PURE__ */ jsx64("div", { className: "sticky top-4 h-[calc(100vh-32px)] shrink-0", children: sidebar }),
|
|
3462
|
+
/* @__PURE__ */ jsxs34("div", { className: "flex min-w-0 flex-1 flex-col overflow-hidden", children: [
|
|
3463
|
+
topBar && /* @__PURE__ */ jsx64("div", { className: "flex shrink-0 items-center justify-end gap-2", children: topBar }),
|
|
3464
|
+
/* @__PURE__ */ jsx64("main", { className: "flex-1 overflow-y-auto", children })
|
|
3208
3465
|
] })
|
|
3209
3466
|
] }) });
|
|
3210
3467
|
}
|
|
3211
3468
|
var AuthenticatedLayout = AppShell;
|
|
3212
3469
|
|
|
3213
3470
|
// src/components/grid.tsx
|
|
3214
|
-
import * as
|
|
3471
|
+
import * as React53 from "react";
|
|
3215
3472
|
import { Slot as Slot6 } from "@radix-ui/react-slot";
|
|
3216
|
-
import { jsx as
|
|
3217
|
-
var Grid =
|
|
3473
|
+
import { jsx as jsx65 } from "react/jsx-runtime";
|
|
3474
|
+
var Grid = React53.forwardRef(
|
|
3218
3475
|
({ fluid = false, asChild = false, className, ...props }, ref) => {
|
|
3219
3476
|
const Comp = asChild ? Slot6 : "div";
|
|
3220
|
-
return /* @__PURE__ */
|
|
3477
|
+
return /* @__PURE__ */ jsx65(
|
|
3221
3478
|
Comp,
|
|
3222
3479
|
{
|
|
3223
3480
|
ref,
|
|
@@ -3235,9 +3492,9 @@ var Grid = React52.forwardRef(
|
|
|
3235
3492
|
Grid.displayName = "Grid";
|
|
3236
3493
|
|
|
3237
3494
|
// src/components/col.tsx
|
|
3238
|
-
import * as
|
|
3495
|
+
import * as React54 from "react";
|
|
3239
3496
|
import { Slot as Slot7 } from "@radix-ui/react-slot";
|
|
3240
|
-
import { jsx as
|
|
3497
|
+
import { jsx as jsx66 } from "react/jsx-runtime";
|
|
3241
3498
|
var TIER_MAX = { base: 4, md: 8, xl: 12 };
|
|
3242
3499
|
var SPAN = {
|
|
3243
3500
|
base: { 1: "col-span-1", 2: "col-span-2", 3: "col-span-3", 4: "col-span-4" },
|
|
@@ -3357,22 +3614,194 @@ function responsiveClasses(span, offset) {
|
|
|
3357
3614
|
}
|
|
3358
3615
|
return cn(...spanClasses, ...startClasses);
|
|
3359
3616
|
}
|
|
3360
|
-
var Col =
|
|
3617
|
+
var Col = React54.forwardRef(
|
|
3361
3618
|
({ span, offset, asChild = false, className, ...props }, ref) => {
|
|
3362
3619
|
const Comp = asChild ? Slot7 : "div";
|
|
3363
|
-
return /* @__PURE__ */
|
|
3620
|
+
return /* @__PURE__ */ jsx66(Comp, { ref, className: cn(responsiveClasses(span, offset), className), ...props });
|
|
3364
3621
|
}
|
|
3365
3622
|
);
|
|
3366
3623
|
Col.displayName = "Col";
|
|
3367
3624
|
|
|
3625
|
+
// src/components/code-block.tsx
|
|
3626
|
+
import * as React55 from "react";
|
|
3627
|
+
import { jsx as jsx67, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3628
|
+
var TOKEN_CLASS = {
|
|
3629
|
+
comment: "text-text-tertiary italic",
|
|
3630
|
+
string: "text-text-success",
|
|
3631
|
+
keyword: "text-text-link",
|
|
3632
|
+
other: "text-text-secondary"
|
|
3633
|
+
};
|
|
3634
|
+
var TS_KEYWORDS = [
|
|
3635
|
+
"import",
|
|
3636
|
+
"from",
|
|
3637
|
+
"export",
|
|
3638
|
+
"default",
|
|
3639
|
+
"const",
|
|
3640
|
+
"let",
|
|
3641
|
+
"var",
|
|
3642
|
+
"function",
|
|
3643
|
+
"return",
|
|
3644
|
+
"new",
|
|
3645
|
+
"type",
|
|
3646
|
+
"interface",
|
|
3647
|
+
"enum",
|
|
3648
|
+
"extends",
|
|
3649
|
+
"implements",
|
|
3650
|
+
"class",
|
|
3651
|
+
"async",
|
|
3652
|
+
"await",
|
|
3653
|
+
"if",
|
|
3654
|
+
"else",
|
|
3655
|
+
"for",
|
|
3656
|
+
"while",
|
|
3657
|
+
"switch",
|
|
3658
|
+
"case",
|
|
3659
|
+
"break",
|
|
3660
|
+
"continue",
|
|
3661
|
+
"true",
|
|
3662
|
+
"false",
|
|
3663
|
+
"null",
|
|
3664
|
+
"undefined",
|
|
3665
|
+
"void",
|
|
3666
|
+
"as",
|
|
3667
|
+
"satisfies",
|
|
3668
|
+
"typeof",
|
|
3669
|
+
"keyof",
|
|
3670
|
+
"in",
|
|
3671
|
+
"of"
|
|
3672
|
+
];
|
|
3673
|
+
var LANGS = {
|
|
3674
|
+
ts: { lineComment: "//", blockComment: true, keywords: TS_KEYWORDS },
|
|
3675
|
+
tsx: { lineComment: "//", blockComment: true, keywords: TS_KEYWORDS },
|
|
3676
|
+
bash: {
|
|
3677
|
+
lineComment: "#",
|
|
3678
|
+
blockComment: false,
|
|
3679
|
+
keywords: [
|
|
3680
|
+
"pnpm",
|
|
3681
|
+
"npm",
|
|
3682
|
+
"npx",
|
|
3683
|
+
"yarn",
|
|
3684
|
+
"node",
|
|
3685
|
+
"cd",
|
|
3686
|
+
"export",
|
|
3687
|
+
"echo",
|
|
3688
|
+
"sudo",
|
|
3689
|
+
"git",
|
|
3690
|
+
"rm",
|
|
3691
|
+
"mkdir",
|
|
3692
|
+
"cp",
|
|
3693
|
+
"mv",
|
|
3694
|
+
"ls",
|
|
3695
|
+
"cat",
|
|
3696
|
+
"set",
|
|
3697
|
+
"source"
|
|
3698
|
+
]
|
|
3699
|
+
},
|
|
3700
|
+
json: { blockComment: false, keywords: ["true", "false", "null"] },
|
|
3701
|
+
css: {
|
|
3702
|
+
blockComment: true,
|
|
3703
|
+
keywords: [
|
|
3704
|
+
"important",
|
|
3705
|
+
"inherit",
|
|
3706
|
+
"initial",
|
|
3707
|
+
"unset",
|
|
3708
|
+
"none",
|
|
3709
|
+
"auto",
|
|
3710
|
+
"@media",
|
|
3711
|
+
"@import",
|
|
3712
|
+
"@keyframes",
|
|
3713
|
+
"@font-face",
|
|
3714
|
+
"@supports"
|
|
3715
|
+
]
|
|
3716
|
+
}
|
|
3717
|
+
};
|
|
3718
|
+
function escapeRe(s) {
|
|
3719
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3720
|
+
}
|
|
3721
|
+
function buildRegex(cfg) {
|
|
3722
|
+
const commentAlts = [];
|
|
3723
|
+
if (cfg.blockComment) commentAlts.push("/\\*[\\s\\S]*?\\*/");
|
|
3724
|
+
if (cfg.lineComment) commentAlts.push(escapeRe(cfg.lineComment) + "[^\\n]*");
|
|
3725
|
+
const comment = commentAlts.length ? `(?<comment>${commentAlts.join("|")})` : "";
|
|
3726
|
+
const string = `(?<string>'(?:[^'\\\\]|\\\\.)*'|"(?:[^"\\\\]|\\\\.)*"|\`(?:[^\`\\\\]|\\\\.)*\`)`;
|
|
3727
|
+
const kw = cfg.keywords.map(escapeRe).join("|");
|
|
3728
|
+
const keyword = kw ? `(?<keyword>(?<![\\w$])(?:${kw})(?![\\w$]))` : "";
|
|
3729
|
+
const other = "(?<other>[\\s\\S])";
|
|
3730
|
+
const src = [comment, string, keyword, other].filter(Boolean).join("|");
|
|
3731
|
+
return new RegExp(src, "g");
|
|
3732
|
+
}
|
|
3733
|
+
var LANG_RE = {
|
|
3734
|
+
ts: buildRegex(LANGS.ts),
|
|
3735
|
+
tsx: buildRegex(LANGS.tsx),
|
|
3736
|
+
bash: buildRegex(LANGS.bash),
|
|
3737
|
+
json: buildRegex(LANGS.json),
|
|
3738
|
+
css: buildRegex(LANGS.css)
|
|
3739
|
+
};
|
|
3740
|
+
function tokenize(code, lang) {
|
|
3741
|
+
const tokens = [];
|
|
3742
|
+
for (const match of code.matchAll(LANG_RE[lang])) {
|
|
3743
|
+
const g = match.groups ?? {};
|
|
3744
|
+
const kind = g.comment != null ? "comment" : g.string != null ? "string" : g.keyword != null ? "keyword" : "other";
|
|
3745
|
+
const text = match[0];
|
|
3746
|
+
const prev = tokens[tokens.length - 1];
|
|
3747
|
+
if (prev && prev.kind === kind && kind === "other") {
|
|
3748
|
+
prev.text += text;
|
|
3749
|
+
} else {
|
|
3750
|
+
tokens.push({ kind, text });
|
|
3751
|
+
}
|
|
3752
|
+
}
|
|
3753
|
+
return tokens;
|
|
3754
|
+
}
|
|
3755
|
+
var CodeBlock = React55.forwardRef(
|
|
3756
|
+
({ code, lang = "tsx", copy = false, filename, scroll = false, className, ...props }, ref) => {
|
|
3757
|
+
const tokens = React55.useMemo(() => tokenize(code, lang), [code, lang]);
|
|
3758
|
+
const framed = Boolean(filename) || copy;
|
|
3759
|
+
const pre = /* @__PURE__ */ jsx67(
|
|
3760
|
+
"pre",
|
|
3761
|
+
{
|
|
3762
|
+
ref,
|
|
3763
|
+
className: cn(
|
|
3764
|
+
"p-4 font-mono text-xs leading-6 text-text-secondary",
|
|
3765
|
+
scroll ? "overflow-x-auto" : "whitespace-pre-wrap break-words",
|
|
3766
|
+
!framed && "rounded-lg border border-border-subtle bg-bg-primary",
|
|
3767
|
+
className
|
|
3768
|
+
),
|
|
3769
|
+
...props,
|
|
3770
|
+
children: /* @__PURE__ */ jsx67("code", { children: tokens.map((token, index) => /* @__PURE__ */ jsx67("span", { className: TOKEN_CLASS[token.kind], children: token.text }, index)) })
|
|
3771
|
+
}
|
|
3772
|
+
);
|
|
3773
|
+
if (!framed) return pre;
|
|
3774
|
+
return /* @__PURE__ */ jsxs35("div", { className: "overflow-hidden rounded-lg border border-border-subtle bg-bg-primary", children: [
|
|
3775
|
+
/* @__PURE__ */ jsxs35("div", { className: "flex items-center justify-between gap-3 border-b border-border-subtle px-4 py-2", children: [
|
|
3776
|
+
filename ? /* @__PURE__ */ jsx67("span", { className: "font-mono text-xs text-text-tertiary", children: filename }) : /* @__PURE__ */ jsx67("span", {}),
|
|
3777
|
+
copy ? /* @__PURE__ */ jsx67(CopyButton, { value: code, label: "Copy code" }) : null
|
|
3778
|
+
] }),
|
|
3779
|
+
pre
|
|
3780
|
+
] });
|
|
3781
|
+
}
|
|
3782
|
+
);
|
|
3783
|
+
CodeBlock.displayName = "CodeBlock";
|
|
3784
|
+
var Code = React55.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx67(
|
|
3785
|
+
"code",
|
|
3786
|
+
{
|
|
3787
|
+
ref,
|
|
3788
|
+
className: cn(
|
|
3789
|
+
"rounded border border-border-subtle bg-bg-secondary px-1.5 py-0.5 font-mono text-[0.85em] text-text-primary",
|
|
3790
|
+
className
|
|
3791
|
+
),
|
|
3792
|
+
...props
|
|
3793
|
+
}
|
|
3794
|
+
));
|
|
3795
|
+
Code.displayName = "Code";
|
|
3796
|
+
|
|
3368
3797
|
// src/components/grid-overlay.tsx
|
|
3369
|
-
import * as
|
|
3370
|
-
import { jsx as
|
|
3798
|
+
import * as React56 from "react";
|
|
3799
|
+
import { jsx as jsx68 } from "react/jsx-runtime";
|
|
3371
3800
|
var BASELINE = "var(--grid-gutter) / 2";
|
|
3372
|
-
var GridOverlay =
|
|
3801
|
+
var GridOverlay = React56.forwardRef(
|
|
3373
3802
|
({ columns, baseline = false, className, style, ...props }, ref) => {
|
|
3374
3803
|
const count = Number.isFinite(columns) ? Math.max(1, Math.floor(columns)) : 1;
|
|
3375
|
-
return /* @__PURE__ */
|
|
3804
|
+
return /* @__PURE__ */ jsx68(
|
|
3376
3805
|
"div",
|
|
3377
3806
|
{
|
|
3378
3807
|
ref,
|
|
@@ -3389,7 +3818,7 @@ var GridOverlay = React54.forwardRef(
|
|
|
3389
3818
|
...style
|
|
3390
3819
|
},
|
|
3391
3820
|
...props,
|
|
3392
|
-
children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */
|
|
3821
|
+
children: Array.from({ length: count }).map((_, i) => /* @__PURE__ */ jsx68("span", { style: { backgroundColor: "var(--bg-brand)", opacity: 0.1 } }, i))
|
|
3393
3822
|
}
|
|
3394
3823
|
);
|
|
3395
3824
|
}
|
|
@@ -3397,10 +3826,10 @@ var GridOverlay = React54.forwardRef(
|
|
|
3397
3826
|
GridOverlay.displayName = "GridOverlay";
|
|
3398
3827
|
|
|
3399
3828
|
// src/components/segment-chip.tsx
|
|
3400
|
-
import * as
|
|
3829
|
+
import * as React57 from "react";
|
|
3401
3830
|
import { cva as cva9 } from "class-variance-authority";
|
|
3402
3831
|
import { Link2 as Link22, KeyRound, Clock, Plus } from "lucide-react";
|
|
3403
|
-
import { jsx as
|
|
3832
|
+
import { jsx as jsx69, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
3404
3833
|
var segmentChipVariants = cva9(
|
|
3405
3834
|
"inline-flex items-center gap-1.5 rounded-lg border px-2.5 py-1 text-sm font-medium leading-tight",
|
|
3406
3835
|
{
|
|
@@ -3421,11 +3850,11 @@ var kindIcons = {
|
|
|
3421
3850
|
pending: Clock,
|
|
3422
3851
|
available: Plus
|
|
3423
3852
|
};
|
|
3424
|
-
var SegmentChip =
|
|
3853
|
+
var SegmentChip = React57.forwardRef(
|
|
3425
3854
|
({ kind, resource, icon, hideIcon = false, className, ...props }, ref) => {
|
|
3426
3855
|
const Icon = icon ?? kindIcons[kind ?? "granted"];
|
|
3427
|
-
return /* @__PURE__ */
|
|
3428
|
-
!hideIcon && /* @__PURE__ */
|
|
3856
|
+
return /* @__PURE__ */ jsxs36("span", { ref, className: cn(segmentChipVariants({ kind }), className), ...props, children: [
|
|
3857
|
+
!hideIcon && /* @__PURE__ */ jsx69(Icon, { className: "size-3.5 shrink-0 opacity-90", "aria-hidden": "true" }),
|
|
3429
3858
|
resource
|
|
3430
3859
|
] });
|
|
3431
3860
|
}
|
|
@@ -3433,9 +3862,9 @@ var SegmentChip = React55.forwardRef(
|
|
|
3433
3862
|
SegmentChip.displayName = "SegmentChip";
|
|
3434
3863
|
|
|
3435
3864
|
// src/components/connection-card.tsx
|
|
3436
|
-
import * as
|
|
3865
|
+
import * as React58 from "react";
|
|
3437
3866
|
import { AlertTriangle, ChevronDown as ChevronDown4 } from "lucide-react";
|
|
3438
|
-
import { Fragment as
|
|
3867
|
+
import { Fragment as Fragment7, jsx as jsx70, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
3439
3868
|
var authLabels = { app: "App", oauth: "OAuth", token: "token" };
|
|
3440
3869
|
var statusMeta = {
|
|
3441
3870
|
connected: { label: "Connected", badge: "success", dot: "success" },
|
|
@@ -3445,7 +3874,7 @@ var statusMeta = {
|
|
|
3445
3874
|
function monogram(name) {
|
|
3446
3875
|
return name.replace(/[^a-zA-Z0-9 ]/g, " ").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
3447
3876
|
}
|
|
3448
|
-
var ConnectionCard =
|
|
3877
|
+
var ConnectionCard = React58.forwardRef(
|
|
3449
3878
|
({
|
|
3450
3879
|
name,
|
|
3451
3880
|
scope,
|
|
@@ -3466,7 +3895,7 @@ var ConnectionCard = React56.forwardRef(
|
|
|
3466
3895
|
}, ref) => {
|
|
3467
3896
|
const meta = statusMeta[status];
|
|
3468
3897
|
const connected = status !== "disconnected";
|
|
3469
|
-
const glyphBox = /* @__PURE__ */
|
|
3898
|
+
const glyphBox = /* @__PURE__ */ jsx70(
|
|
3470
3899
|
"div",
|
|
3471
3900
|
{
|
|
3472
3901
|
"aria-hidden": "true",
|
|
@@ -3474,51 +3903,51 @@ var ConnectionCard = React56.forwardRef(
|
|
|
3474
3903
|
children: glyph ?? monogram(name)
|
|
3475
3904
|
}
|
|
3476
3905
|
);
|
|
3477
|
-
const identity = /* @__PURE__ */
|
|
3478
|
-
/* @__PURE__ */
|
|
3479
|
-
/* @__PURE__ */
|
|
3480
|
-
/* @__PURE__ */
|
|
3481
|
-
/* @__PURE__ */
|
|
3906
|
+
const identity = /* @__PURE__ */ jsxs37("div", { className: "min-w-0", children: [
|
|
3907
|
+
/* @__PURE__ */ jsx70("p", { className: "truncate text-sm font-semibold text-text-primary", children: name }),
|
|
3908
|
+
/* @__PURE__ */ jsxs37("div", { className: "mt-0.5 flex flex-wrap gap-1", children: [
|
|
3909
|
+
/* @__PURE__ */ jsx70(Badge, { variant: "secondary", children: scope }),
|
|
3910
|
+
/* @__PURE__ */ jsx70(Badge, { variant: "secondary", children: authLabels[auth] })
|
|
3482
3911
|
] })
|
|
3483
3912
|
] });
|
|
3484
|
-
const statusBadge = /* @__PURE__ */
|
|
3485
|
-
/* @__PURE__ */
|
|
3913
|
+
const statusBadge = /* @__PURE__ */ jsxs37(Badge, { variant: meta.badge, className: "gap-1.5", children: [
|
|
3914
|
+
/* @__PURE__ */ jsx70(StatusDot, { status: meta.dot, size: "sm" }),
|
|
3486
3915
|
statusLabel ?? meta.label
|
|
3487
3916
|
] });
|
|
3488
|
-
const accessNote = access ? /* @__PURE__ */
|
|
3917
|
+
const accessNote = access ? /* @__PURE__ */ jsxs37(
|
|
3489
3918
|
"div",
|
|
3490
3919
|
{
|
|
3491
3920
|
role: "note",
|
|
3492
3921
|
className: "flex items-start gap-2 border-t border-border-subtle bg-bg-warning-subtle px-4 py-2.5 text-xs font-medium text-text-warning",
|
|
3493
3922
|
children: [
|
|
3494
|
-
/* @__PURE__ */
|
|
3495
|
-
/* @__PURE__ */
|
|
3923
|
+
/* @__PURE__ */ jsx70(AlertTriangle, { className: "mt-0.5 size-3.5 shrink-0", "aria-hidden": "true" }),
|
|
3924
|
+
/* @__PURE__ */ jsx70("span", { children: access })
|
|
3496
3925
|
]
|
|
3497
3926
|
}
|
|
3498
3927
|
) : null;
|
|
3499
3928
|
const footerAction = collapsible ? action : connected && action;
|
|
3500
|
-
const footer = grantedCount !== void 0 || footerAction ? /* @__PURE__ */
|
|
3501
|
-
/* @__PURE__ */
|
|
3929
|
+
const footer = grantedCount !== void 0 || footerAction ? /* @__PURE__ */ jsxs37("div", { className: "flex items-center justify-between border-t border-border-subtle px-4 py-3", children: [
|
|
3930
|
+
/* @__PURE__ */ jsx70("span", { className: "text-sm text-text-secondary", children: grantedCount !== void 0 ? /* @__PURE__ */ jsxs37(Fragment7, { children: [
|
|
3502
3931
|
"Granted to ",
|
|
3503
|
-
/* @__PURE__ */
|
|
3932
|
+
/* @__PURE__ */ jsx70("span", { className: "font-semibold text-text-primary", children: grantedCount }),
|
|
3504
3933
|
" ",
|
|
3505
3934
|
grantedCount === 1 ? "product" : "products"
|
|
3506
|
-
] }) : /* @__PURE__ */
|
|
3935
|
+
] }) : /* @__PURE__ */ jsx70("span", { className: "text-text-tertiary", children: "Not granted to any product yet" }) }),
|
|
3507
3936
|
footerAction
|
|
3508
3937
|
] }) : null;
|
|
3509
|
-
const drawer = children ? /* @__PURE__ */
|
|
3938
|
+
const drawer = children ? /* @__PURE__ */ jsx70("div", { "data-slot": "drawer", className: "border-t border-border-subtle", children }) : null;
|
|
3510
3939
|
if (!collapsible) {
|
|
3511
|
-
return /* @__PURE__ */
|
|
3940
|
+
return /* @__PURE__ */ jsxs37(
|
|
3512
3941
|
Card,
|
|
3513
3942
|
{
|
|
3514
3943
|
ref,
|
|
3515
3944
|
className: cn(status === "disconnected" && "border-dashed border-border-default", className),
|
|
3516
3945
|
...props,
|
|
3517
3946
|
children: [
|
|
3518
|
-
/* @__PURE__ */
|
|
3947
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex items-center gap-3 p-4", children: [
|
|
3519
3948
|
glyphBox,
|
|
3520
3949
|
identity,
|
|
3521
|
-
/* @__PURE__ */
|
|
3950
|
+
/* @__PURE__ */ jsx70("div", { className: "ml-auto shrink-0", children: connected ? statusBadge : action })
|
|
3522
3951
|
] }),
|
|
3523
3952
|
accessNote,
|
|
3524
3953
|
footer,
|
|
@@ -3527,7 +3956,7 @@ var ConnectionCard = React56.forwardRef(
|
|
|
3527
3956
|
}
|
|
3528
3957
|
);
|
|
3529
3958
|
}
|
|
3530
|
-
return /* @__PURE__ */
|
|
3959
|
+
return /* @__PURE__ */ jsx70(Collapsible, { defaultOpen, open, onOpenChange, children: /* @__PURE__ */ jsxs37(
|
|
3531
3960
|
Card,
|
|
3532
3961
|
{
|
|
3533
3962
|
ref,
|
|
@@ -3538,7 +3967,7 @@ var ConnectionCard = React56.forwardRef(
|
|
|
3538
3967
|
),
|
|
3539
3968
|
...props,
|
|
3540
3969
|
children: [
|
|
3541
|
-
/* @__PURE__ */
|
|
3970
|
+
/* @__PURE__ */ jsx70(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs37(
|
|
3542
3971
|
"button",
|
|
3543
3972
|
{
|
|
3544
3973
|
type: "button",
|
|
@@ -3546,9 +3975,9 @@ var ConnectionCard = React56.forwardRef(
|
|
|
3546
3975
|
children: [
|
|
3547
3976
|
glyphBox,
|
|
3548
3977
|
identity,
|
|
3549
|
-
/* @__PURE__ */
|
|
3978
|
+
/* @__PURE__ */ jsxs37("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
|
|
3550
3979
|
statusBadge,
|
|
3551
|
-
/* @__PURE__ */
|
|
3980
|
+
/* @__PURE__ */ jsx70(
|
|
3552
3981
|
ChevronDown4,
|
|
3553
3982
|
{
|
|
3554
3983
|
"aria-hidden": "true",
|
|
@@ -3559,7 +3988,7 @@ var ConnectionCard = React56.forwardRef(
|
|
|
3559
3988
|
]
|
|
3560
3989
|
}
|
|
3561
3990
|
) }),
|
|
3562
|
-
/* @__PURE__ */
|
|
3991
|
+
/* @__PURE__ */ jsxs37(CollapsibleContent2, { children: [
|
|
3563
3992
|
accessNote,
|
|
3564
3993
|
footer,
|
|
3565
3994
|
drawer
|
|
@@ -3572,32 +4001,32 @@ var ConnectionCard = React56.forwardRef(
|
|
|
3572
4001
|
ConnectionCard.displayName = "ConnectionCard";
|
|
3573
4002
|
|
|
3574
4003
|
// src/components/request-row.tsx
|
|
3575
|
-
import * as
|
|
3576
|
-
import { Fragment as
|
|
4004
|
+
import * as React59 from "react";
|
|
4005
|
+
import { Fragment as Fragment8, jsx as jsx71, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
3577
4006
|
function monogram2(name) {
|
|
3578
4007
|
return name.replace(/[^a-zA-Z0-9 ]/g, " ").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
|
|
3579
4008
|
}
|
|
3580
|
-
var RequestRow =
|
|
4009
|
+
var RequestRow = React59.forwardRef(
|
|
3581
4010
|
({ surface, name, state: state2, glyph, subtitle, grantedResource, onApprove, onDeny, onRequest, action, className, ...props }, ref) => {
|
|
3582
4011
|
let controls = action;
|
|
3583
4012
|
if (controls === void 0) {
|
|
3584
4013
|
if (surface === "org" && state2 === "pending") {
|
|
3585
|
-
controls = /* @__PURE__ */
|
|
3586
|
-
/* @__PURE__ */
|
|
3587
|
-
/* @__PURE__ */
|
|
4014
|
+
controls = /* @__PURE__ */ jsxs38(Fragment8, { children: [
|
|
4015
|
+
/* @__PURE__ */ jsx71(Button, { variant: "outline", size: "sm", onClick: onDeny, children: "Deny" }),
|
|
4016
|
+
/* @__PURE__ */ jsx71(Button, { size: "sm", onClick: onApprove, children: "Approve" })
|
|
3588
4017
|
] });
|
|
3589
4018
|
} else if (state2 === "available") {
|
|
3590
|
-
controls = /* @__PURE__ */
|
|
4019
|
+
controls = /* @__PURE__ */ jsx71(Button, { size: "sm", onClick: onRequest, children: "Request" });
|
|
3591
4020
|
} else if (state2 === "pending") {
|
|
3592
|
-
controls = /* @__PURE__ */
|
|
3593
|
-
/* @__PURE__ */
|
|
4021
|
+
controls = /* @__PURE__ */ jsxs38(Badge, { variant: "secondary", className: "gap-1.5", children: [
|
|
4022
|
+
/* @__PURE__ */ jsx71(StatusDot, { status: "neutral", size: "sm" }),
|
|
3594
4023
|
"Pending"
|
|
3595
4024
|
] });
|
|
3596
4025
|
} else if (state2 === "granted") {
|
|
3597
|
-
controls = /* @__PURE__ */
|
|
4026
|
+
controls = /* @__PURE__ */ jsx71(SegmentChip, { kind: "granted", resource: grantedResource ?? "a segment" });
|
|
3598
4027
|
}
|
|
3599
4028
|
}
|
|
3600
|
-
return /* @__PURE__ */
|
|
4029
|
+
return /* @__PURE__ */ jsxs38(
|
|
3601
4030
|
"div",
|
|
3602
4031
|
{
|
|
3603
4032
|
ref,
|
|
@@ -3607,7 +4036,7 @@ var RequestRow = React57.forwardRef(
|
|
|
3607
4036
|
),
|
|
3608
4037
|
...props,
|
|
3609
4038
|
children: [
|
|
3610
|
-
/* @__PURE__ */
|
|
4039
|
+
/* @__PURE__ */ jsx71(
|
|
3611
4040
|
"div",
|
|
3612
4041
|
{
|
|
3613
4042
|
"aria-hidden": "true",
|
|
@@ -3615,11 +4044,11 @@ var RequestRow = React57.forwardRef(
|
|
|
3615
4044
|
children: glyph ?? monogram2(name)
|
|
3616
4045
|
}
|
|
3617
4046
|
),
|
|
3618
|
-
/* @__PURE__ */
|
|
3619
|
-
/* @__PURE__ */
|
|
3620
|
-
subtitle && /* @__PURE__ */
|
|
4047
|
+
/* @__PURE__ */ jsxs38("div", { className: "min-w-0", children: [
|
|
4048
|
+
/* @__PURE__ */ jsx71("p", { className: "truncate text-sm font-semibold text-text-primary", children: name }),
|
|
4049
|
+
subtitle && /* @__PURE__ */ jsx71("p", { className: "truncate text-xs text-text-tertiary", children: subtitle })
|
|
3621
4050
|
] }),
|
|
3622
|
-
/* @__PURE__ */
|
|
4051
|
+
/* @__PURE__ */ jsx71("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: controls })
|
|
3623
4052
|
]
|
|
3624
4053
|
}
|
|
3625
4054
|
);
|
|
@@ -3628,9 +4057,9 @@ var RequestRow = React57.forwardRef(
|
|
|
3628
4057
|
RequestRow.displayName = "RequestRow";
|
|
3629
4058
|
|
|
3630
4059
|
// src/components/feedback-button.tsx
|
|
3631
|
-
import * as
|
|
4060
|
+
import * as React60 from "react";
|
|
3632
4061
|
import { MessageSquare, Loader2 as Loader22, CheckCircle2 } from "lucide-react";
|
|
3633
|
-
import { jsx as
|
|
4062
|
+
import { jsx as jsx72, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
3634
4063
|
var TITLE_MAX = 256;
|
|
3635
4064
|
var DETAILS_MAX = 65536;
|
|
3636
4065
|
var DEFAULT_LABELS = {
|
|
@@ -3644,15 +4073,15 @@ var DEFAULT_LABELS = {
|
|
|
3644
4073
|
};
|
|
3645
4074
|
function FeedbackButton({ onSubmit, labels, className }) {
|
|
3646
4075
|
const l = { ...DEFAULT_LABELS, ...labels };
|
|
3647
|
-
const uid =
|
|
4076
|
+
const uid = React60.useId();
|
|
3648
4077
|
const titleId = `${uid}-title`;
|
|
3649
4078
|
const detailsId = `${uid}-details`;
|
|
3650
4079
|
const titleErrId = `${uid}-title-error`;
|
|
3651
4080
|
const detailsErrId = `${uid}-details-error`;
|
|
3652
|
-
const [open, setOpen] =
|
|
3653
|
-
const [status, setStatus] =
|
|
3654
|
-
const [title, setTitle] =
|
|
3655
|
-
const [details, setDetails] =
|
|
4081
|
+
const [open, setOpen] = React60.useState(false);
|
|
4082
|
+
const [status, setStatus] = React60.useState("idle");
|
|
4083
|
+
const [title, setTitle] = React60.useState("");
|
|
4084
|
+
const [details, setDetails] = React60.useState("");
|
|
3656
4085
|
const titleTooLong = title.length > TITLE_MAX;
|
|
3657
4086
|
const detailsTooLong = details.length > DETAILS_MAX;
|
|
3658
4087
|
const titleEmpty = title.trim().length === 0;
|
|
@@ -3677,20 +4106,20 @@ function FeedbackButton({ onSubmit, labels, className }) {
|
|
|
3677
4106
|
setStatus("error");
|
|
3678
4107
|
}
|
|
3679
4108
|
};
|
|
3680
|
-
return /* @__PURE__ */
|
|
3681
|
-
/* @__PURE__ */
|
|
3682
|
-
/* @__PURE__ */
|
|
4109
|
+
return /* @__PURE__ */ jsxs39(Popover, { open, onOpenChange: changeOpen, children: [
|
|
4110
|
+
/* @__PURE__ */ jsx72(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs39(Button, { variant: "ghost", size: "sm", "aria-label": l.trigger, className, children: [
|
|
4111
|
+
/* @__PURE__ */ jsx72(MessageSquare, { className: "size-4", "aria-hidden": "true" }),
|
|
3683
4112
|
l.trigger
|
|
3684
4113
|
] }) }),
|
|
3685
|
-
/* @__PURE__ */
|
|
3686
|
-
/* @__PURE__ */
|
|
3687
|
-
/* @__PURE__ */
|
|
3688
|
-
/* @__PURE__ */
|
|
3689
|
-
] }) : /* @__PURE__ */
|
|
3690
|
-
/* @__PURE__ */
|
|
3691
|
-
/* @__PURE__ */
|
|
3692
|
-
/* @__PURE__ */
|
|
3693
|
-
/* @__PURE__ */
|
|
4114
|
+
/* @__PURE__ */ jsx72(PopoverContent, { align: "end", side: "bottom", className: "w-80", children: status === "success" ? /* @__PURE__ */ jsxs39("div", { className: "flex flex-col items-center gap-3 py-2 text-center", children: [
|
|
4115
|
+
/* @__PURE__ */ jsx72(CheckCircle2, { className: "size-8 text-text-success", "aria-hidden": "true" }),
|
|
4116
|
+
/* @__PURE__ */ jsx72("p", { role: "status", className: "text-sm text-text-primary", children: l.success }),
|
|
4117
|
+
/* @__PURE__ */ jsx72(Button, { variant: "outline", size: "sm", onClick: () => changeOpen(false), children: "Close" })
|
|
4118
|
+
] }) : /* @__PURE__ */ jsxs39("form", { onSubmit: handleSubmit, className: "flex flex-col gap-3", children: [
|
|
4119
|
+
/* @__PURE__ */ jsx72("p", { className: "text-sm font-medium text-text-primary", children: l.title }),
|
|
4120
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex flex-col gap-1.5", children: [
|
|
4121
|
+
/* @__PURE__ */ jsx72(Label2, { htmlFor: titleId, children: l.titleField }),
|
|
4122
|
+
/* @__PURE__ */ jsx72(
|
|
3694
4123
|
Input,
|
|
3695
4124
|
{
|
|
3696
4125
|
id: titleId,
|
|
@@ -3701,16 +4130,16 @@ function FeedbackButton({ onSubmit, labels, className }) {
|
|
|
3701
4130
|
"aria-describedby": titleTooLong ? titleErrId : void 0
|
|
3702
4131
|
}
|
|
3703
4132
|
),
|
|
3704
|
-
titleTooLong && /* @__PURE__ */
|
|
4133
|
+
titleTooLong && /* @__PURE__ */ jsxs39("p", { id: titleErrId, className: "text-xs text-text-danger", children: [
|
|
3705
4134
|
l.titleField,
|
|
3706
4135
|
" must be ",
|
|
3707
4136
|
TITLE_MAX,
|
|
3708
4137
|
" characters or fewer."
|
|
3709
4138
|
] })
|
|
3710
4139
|
] }),
|
|
3711
|
-
/* @__PURE__ */
|
|
3712
|
-
/* @__PURE__ */
|
|
3713
|
-
/* @__PURE__ */
|
|
4140
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex flex-col gap-1.5", children: [
|
|
4141
|
+
/* @__PURE__ */ jsx72(Label2, { htmlFor: detailsId, children: l.detailsField }),
|
|
4142
|
+
/* @__PURE__ */ jsx72(
|
|
3714
4143
|
Textarea,
|
|
3715
4144
|
{
|
|
3716
4145
|
id: detailsId,
|
|
@@ -3721,16 +4150,16 @@ function FeedbackButton({ onSubmit, labels, className }) {
|
|
|
3721
4150
|
"aria-describedby": detailsTooLong ? detailsErrId : void 0
|
|
3722
4151
|
}
|
|
3723
4152
|
),
|
|
3724
|
-
detailsTooLong && /* @__PURE__ */
|
|
4153
|
+
detailsTooLong && /* @__PURE__ */ jsxs39("p", { id: detailsErrId, className: "text-xs text-text-danger", children: [
|
|
3725
4154
|
l.detailsField,
|
|
3726
4155
|
" must be ",
|
|
3727
4156
|
DETAILS_MAX,
|
|
3728
4157
|
" characters or fewer."
|
|
3729
4158
|
] })
|
|
3730
4159
|
] }),
|
|
3731
|
-
status === "error" && /* @__PURE__ */
|
|
3732
|
-
/* @__PURE__ */
|
|
3733
|
-
submitting && /* @__PURE__ */
|
|
4160
|
+
status === "error" && /* @__PURE__ */ jsx72(InlineError, { children: l.error }),
|
|
4161
|
+
/* @__PURE__ */ jsxs39(Button, { type: "submit", disabled: !valid || submitting, children: [
|
|
4162
|
+
submitting && /* @__PURE__ */ jsx72(Loader22, { className: "size-4 animate-spin", "aria-hidden": "true" }),
|
|
3734
4163
|
l.submit
|
|
3735
4164
|
] })
|
|
3736
4165
|
] }) })
|
|
@@ -3739,7 +4168,7 @@ function FeedbackButton({ onSubmit, labels, className }) {
|
|
|
3739
4168
|
|
|
3740
4169
|
// src/components/create-product-window.tsx
|
|
3741
4170
|
import { useForm } from "react-hook-form";
|
|
3742
|
-
import { jsx as
|
|
4171
|
+
import { jsx as jsx73, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
3743
4172
|
var CREATE_ORG_VALUE = "__create_new_org__";
|
|
3744
4173
|
function CreateProductWindow({
|
|
3745
4174
|
organizations,
|
|
@@ -3772,10 +4201,10 @@ function CreateProductWindow({
|
|
|
3772
4201
|
}
|
|
3773
4202
|
});
|
|
3774
4203
|
const showSelect = organizations.length > 0;
|
|
3775
|
-
return /* @__PURE__ */
|
|
3776
|
-
showSelect && /* @__PURE__ */
|
|
3777
|
-
/* @__PURE__ */
|
|
3778
|
-
/* @__PURE__ */
|
|
4204
|
+
return /* @__PURE__ */ jsxs40("div", { className: "flex w-full max-w-md flex-col gap-6", children: [
|
|
4205
|
+
showSelect && /* @__PURE__ */ jsxs40("div", { className: "space-y-2", children: [
|
|
4206
|
+
/* @__PURE__ */ jsx73("span", { className: "text-sm font-medium leading-none text-text-primary", children: "Organization" }),
|
|
4207
|
+
/* @__PURE__ */ jsx73(
|
|
3779
4208
|
Select,
|
|
3780
4209
|
{
|
|
3781
4210
|
"data-testid": "create-product-org-select",
|
|
@@ -3788,9 +4217,9 @@ function CreateProductWindow({
|
|
|
3788
4217
|
}
|
|
3789
4218
|
)
|
|
3790
4219
|
] }),
|
|
3791
|
-
!createOrgMode && /* @__PURE__ */
|
|
3792
|
-
/* @__PURE__ */
|
|
3793
|
-
productsLoading ? /* @__PURE__ */
|
|
4220
|
+
!createOrgMode && /* @__PURE__ */ jsxs40("div", { className: "space-y-2", children: [
|
|
4221
|
+
/* @__PURE__ */ jsx73("span", { className: "text-sm font-medium leading-none text-text-primary", children: "Products" }),
|
|
4222
|
+
productsLoading ? /* @__PURE__ */ jsx73("p", { className: "text-sm text-text-tertiary", children: "Loading products\u2026" }) : products.length === 0 ? /* @__PURE__ */ jsx73("p", { className: "text-sm text-text-tertiary", children: "No products yet." }) : /* @__PURE__ */ jsx73("ul", { className: "flex flex-col gap-1", children: products.map((product) => /* @__PURE__ */ jsx73("li", { children: /* @__PURE__ */ jsxs40(
|
|
3794
4223
|
"button",
|
|
3795
4224
|
{
|
|
3796
4225
|
type: "button",
|
|
@@ -3799,14 +4228,14 @@ function CreateProductWindow({
|
|
|
3799
4228
|
"flex w-full items-center justify-between rounded-md border border-border-default bg-bg-primary px-3 py-2 text-left text-sm text-text-primary hover:bg-bg-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus"
|
|
3800
4229
|
),
|
|
3801
4230
|
children: [
|
|
3802
|
-
/* @__PURE__ */
|
|
3803
|
-
/* @__PURE__ */
|
|
4231
|
+
/* @__PURE__ */ jsx73("span", { className: "truncate", children: product.name }),
|
|
4232
|
+
/* @__PURE__ */ jsx73("span", { className: "ml-2 truncate text-text-tertiary", children: product.slug })
|
|
3804
4233
|
]
|
|
3805
4234
|
}
|
|
3806
4235
|
) }, product.id)) })
|
|
3807
4236
|
] }),
|
|
3808
|
-
/* @__PURE__ */
|
|
3809
|
-
createOrgMode && /* @__PURE__ */
|
|
4237
|
+
/* @__PURE__ */ jsx73(Form, { ...form, children: /* @__PURE__ */ jsxs40("form", { onSubmit: handleSubmit, className: "flex flex-col gap-4", noValidate: true, children: [
|
|
4238
|
+
createOrgMode && /* @__PURE__ */ jsx73(
|
|
3810
4239
|
FormField,
|
|
3811
4240
|
{
|
|
3812
4241
|
control: form.control,
|
|
@@ -3814,14 +4243,14 @@ function CreateProductWindow({
|
|
|
3814
4243
|
rules: {
|
|
3815
4244
|
validate: (value) => value.trim().length > 0 || "Organization name is required"
|
|
3816
4245
|
},
|
|
3817
|
-
render: ({ field }) => /* @__PURE__ */
|
|
3818
|
-
/* @__PURE__ */
|
|
3819
|
-
/* @__PURE__ */
|
|
3820
|
-
/* @__PURE__ */
|
|
4246
|
+
render: ({ field }) => /* @__PURE__ */ jsxs40(FormItem, { children: [
|
|
4247
|
+
/* @__PURE__ */ jsx73(FormLabel, { children: "Organization name" }),
|
|
4248
|
+
/* @__PURE__ */ jsx73(FormControl, { children: /* @__PURE__ */ jsx73(Input, { placeholder: "Acme Inc.", ...field }) }),
|
|
4249
|
+
/* @__PURE__ */ jsx73(FormMessage, {})
|
|
3821
4250
|
] })
|
|
3822
4251
|
}
|
|
3823
4252
|
),
|
|
3824
|
-
/* @__PURE__ */
|
|
4253
|
+
/* @__PURE__ */ jsx73(
|
|
3825
4254
|
FormField,
|
|
3826
4255
|
{
|
|
3827
4256
|
control: form.control,
|
|
@@ -3829,18 +4258,619 @@ function CreateProductWindow({
|
|
|
3829
4258
|
rules: {
|
|
3830
4259
|
validate: (value) => value.trim().length > 0 || "Product name is required"
|
|
3831
4260
|
},
|
|
3832
|
-
render: ({ field }) => /* @__PURE__ */
|
|
3833
|
-
/* @__PURE__ */
|
|
3834
|
-
/* @__PURE__ */
|
|
3835
|
-
/* @__PURE__ */
|
|
4261
|
+
render: ({ field }) => /* @__PURE__ */ jsxs40(FormItem, { children: [
|
|
4262
|
+
/* @__PURE__ */ jsx73(FormLabel, { children: "Product name" }),
|
|
4263
|
+
/* @__PURE__ */ jsx73(FormControl, { children: /* @__PURE__ */ jsx73(Input, { placeholder: "My product", ...field }) }),
|
|
4264
|
+
/* @__PURE__ */ jsx73(FormMessage, {})
|
|
3836
4265
|
] })
|
|
3837
4266
|
}
|
|
3838
4267
|
),
|
|
3839
|
-
error && /* @__PURE__ */
|
|
3840
|
-
/* @__PURE__ */
|
|
4268
|
+
error && /* @__PURE__ */ jsx73(InlineError, { children: error }),
|
|
4269
|
+
/* @__PURE__ */ jsx73(Button, { type: "submit", disabled: submitting, children: "Create product" })
|
|
3841
4270
|
] }) })
|
|
3842
4271
|
] });
|
|
3843
4272
|
}
|
|
4273
|
+
|
|
4274
|
+
// src/components/notification-types.ts
|
|
4275
|
+
var severityLabels = {
|
|
4276
|
+
critical: "Critical",
|
|
4277
|
+
important: "Important",
|
|
4278
|
+
fyi: "FYI"
|
|
4279
|
+
};
|
|
4280
|
+
var severityBadgeVariants = {
|
|
4281
|
+
critical: "destructive",
|
|
4282
|
+
important: "warning",
|
|
4283
|
+
fyi: "secondary"
|
|
4284
|
+
};
|
|
4285
|
+
function severityBadgeVariant(severity) {
|
|
4286
|
+
return severityBadgeVariants[severity];
|
|
4287
|
+
}
|
|
4288
|
+
function formatRelativeAge(createdAt, now = /* @__PURE__ */ new Date()) {
|
|
4289
|
+
const then = createdAt instanceof Date ? createdAt : new Date(createdAt);
|
|
4290
|
+
const seconds = Math.max(0, Math.floor((now.getTime() - then.getTime()) / 1e3));
|
|
4291
|
+
if (seconds < 5) return "now";
|
|
4292
|
+
if (seconds < 60) return `${seconds}s ago`;
|
|
4293
|
+
const minutes = Math.floor(seconds / 60);
|
|
4294
|
+
if (minutes < 60) return `${minutes}m ago`;
|
|
4295
|
+
return `${Math.floor(minutes / 60)}h ago`;
|
|
4296
|
+
}
|
|
4297
|
+
function isNotificationSettled(item) {
|
|
4298
|
+
if (item.cls === "ephemeral") return false;
|
|
4299
|
+
return Boolean(item.receipt) || item.read === true;
|
|
4300
|
+
}
|
|
4301
|
+
|
|
4302
|
+
// src/components/notification-bell.tsx
|
|
4303
|
+
import * as React61 from "react";
|
|
4304
|
+
import { BellRing, Settings } from "lucide-react";
|
|
4305
|
+
import { jsx as jsx74, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
4306
|
+
function BellRow({
|
|
4307
|
+
item,
|
|
4308
|
+
onItemClick,
|
|
4309
|
+
onActionClick,
|
|
4310
|
+
formatAge
|
|
4311
|
+
}) {
|
|
4312
|
+
const settled = isNotificationSettled(item);
|
|
4313
|
+
const unread = !settled && !item.read;
|
|
4314
|
+
const actions = settled ? [] : item.actions ?? [];
|
|
4315
|
+
const age = item.createdAt ? formatAge(item.createdAt instanceof Date ? item.createdAt : new Date(item.createdAt)) : null;
|
|
4316
|
+
return /* @__PURE__ */ jsxs41("div", { className: cn("rounded-lg bg-bg-surface px-3 py-2.5", settled && "opacity-45"), children: [
|
|
4317
|
+
/* @__PURE__ */ jsxs41("div", { className: "flex items-start gap-2.5", children: [
|
|
4318
|
+
/* @__PURE__ */ jsxs41("div", { className: "min-w-0 flex-1", children: [
|
|
4319
|
+
/* @__PURE__ */ jsx74(
|
|
4320
|
+
"button",
|
|
4321
|
+
{
|
|
4322
|
+
type: "button",
|
|
4323
|
+
onClick: () => onItemClick?.(item),
|
|
4324
|
+
className: cn(
|
|
4325
|
+
"block text-left text-sm leading-tight underline-offset-2 hover:underline",
|
|
4326
|
+
unread ? "font-semibold text-text-primary" : "text-text-secondary"
|
|
4327
|
+
),
|
|
4328
|
+
children: item.title
|
|
4329
|
+
}
|
|
4330
|
+
),
|
|
4331
|
+
/* @__PURE__ */ jsxs41("p", { className: "mt-1 truncate text-xs text-text-tertiary", children: [
|
|
4332
|
+
/* @__PURE__ */ jsx74("span", { className: "font-semibold uppercase tracking-wide text-text-secondary", children: item.source }),
|
|
4333
|
+
item.receipt ? `, ${item.receipt}` : ""
|
|
4334
|
+
] })
|
|
4335
|
+
] }),
|
|
4336
|
+
age && /* @__PURE__ */ jsx74("span", { className: "mt-px shrink-0 text-xs text-text-tertiary", children: age })
|
|
4337
|
+
] }),
|
|
4338
|
+
(actions.length > 0 || item.deepLink) && /* @__PURE__ */ jsxs41("div", { className: "mt-2 flex flex-wrap items-center gap-x-4 gap-y-2", children: [
|
|
4339
|
+
actions.map((action) => {
|
|
4340
|
+
const chip = action.variant === "primary" || action.variant === "destructive";
|
|
4341
|
+
return /* @__PURE__ */ jsx74(
|
|
4342
|
+
"button",
|
|
4343
|
+
{
|
|
4344
|
+
type: "button",
|
|
4345
|
+
onClick: () => onActionClick?.(item, action),
|
|
4346
|
+
className: cn(
|
|
4347
|
+
chip ? "rounded-md px-2.5 py-1 text-xs font-medium transition-colors" : "text-xs font-semibold text-text-secondary transition-opacity hover:opacity-80",
|
|
4348
|
+
action.variant === "primary" && "bg-bg-brand text-text-on-brand hover:bg-bg-brand-hover",
|
|
4349
|
+
action.variant === "destructive" && "bg-bg-elevated text-text-danger hover:bg-bg-sunken"
|
|
4350
|
+
),
|
|
4351
|
+
children: action.label
|
|
4352
|
+
},
|
|
4353
|
+
action.id
|
|
4354
|
+
);
|
|
4355
|
+
}),
|
|
4356
|
+
item.deepLink && /* @__PURE__ */ jsx74(
|
|
4357
|
+
"button",
|
|
4358
|
+
{
|
|
4359
|
+
type: "button",
|
|
4360
|
+
onClick: () => onItemClick?.(item),
|
|
4361
|
+
className: "text-xs font-semibold text-text-brand transition-opacity hover:opacity-80",
|
|
4362
|
+
children: item.deepLink.label
|
|
4363
|
+
}
|
|
4364
|
+
)
|
|
4365
|
+
] })
|
|
4366
|
+
] });
|
|
4367
|
+
}
|
|
4368
|
+
var NotificationBell = React61.forwardRef(
|
|
4369
|
+
({
|
|
4370
|
+
items,
|
|
4371
|
+
unreadCount,
|
|
4372
|
+
maxItems = 5,
|
|
4373
|
+
onMarkAllRead,
|
|
4374
|
+
onItemClick,
|
|
4375
|
+
onActionClick,
|
|
4376
|
+
onOpenSettings,
|
|
4377
|
+
onOpenArchive,
|
|
4378
|
+
open,
|
|
4379
|
+
onOpenChange,
|
|
4380
|
+
formatAge,
|
|
4381
|
+
className
|
|
4382
|
+
}, ref) => {
|
|
4383
|
+
const unread = unreadCount ?? items.filter((n) => !n.read && n.cls !== "ephemeral").length;
|
|
4384
|
+
const age = React61.useCallback(
|
|
4385
|
+
(createdAt) => formatAge ? formatAge(createdAt) : formatRelativeAge(createdAt),
|
|
4386
|
+
[formatAge]
|
|
4387
|
+
);
|
|
4388
|
+
const rows = items.slice(0, maxItems);
|
|
4389
|
+
return /* @__PURE__ */ jsxs41(Popover, { open, onOpenChange, children: [
|
|
4390
|
+
/* @__PURE__ */ jsx74(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs41(
|
|
4391
|
+
"button",
|
|
4392
|
+
{
|
|
4393
|
+
ref,
|
|
4394
|
+
type: "button",
|
|
4395
|
+
"aria-label": "Notifications",
|
|
4396
|
+
className: cn(
|
|
4397
|
+
"relative flex size-8 items-center justify-center rounded-lg text-text-secondary transition-colors hover:bg-bg-elevated hover:text-text-primary data-[state=open]:bg-bg-brand-subtle data-[state=open]:text-text-brand",
|
|
4398
|
+
className
|
|
4399
|
+
),
|
|
4400
|
+
children: [
|
|
4401
|
+
/* @__PURE__ */ jsx74(BellRing, { className: "size-[18px]", "aria-hidden": "true" }),
|
|
4402
|
+
unread > 0 && /* @__PURE__ */ jsx74("span", { className: "absolute -right-1.5 -top-1.5 flex size-[17px] items-center justify-center rounded-full bg-bg-brand text-xs font-bold leading-none text-text-on-brand ring-2 ring-bg-surface", children: unread })
|
|
4403
|
+
]
|
|
4404
|
+
}
|
|
4405
|
+
) }),
|
|
4406
|
+
/* @__PURE__ */ jsxs41(PopoverContent, { align: "end", className: "w-[380px] overflow-hidden p-0", children: [
|
|
4407
|
+
/* @__PURE__ */ jsxs41("div", { className: "flex items-center justify-between px-5 py-3", children: [
|
|
4408
|
+
/* @__PURE__ */ jsx74("span", { className: "text-sm font-bold text-text-primary", children: "Notification center" }),
|
|
4409
|
+
/* @__PURE__ */ jsxs41("div", { className: "flex items-center gap-3", children: [
|
|
4410
|
+
/* @__PURE__ */ jsx74(
|
|
4411
|
+
"button",
|
|
4412
|
+
{
|
|
4413
|
+
type: "button",
|
|
4414
|
+
disabled: unread === 0,
|
|
4415
|
+
onClick: () => onMarkAllRead?.(),
|
|
4416
|
+
className: cn(
|
|
4417
|
+
"text-sm font-medium transition-colors",
|
|
4418
|
+
unread === 0 ? "cursor-default text-text-disabled" : "text-text-tertiary hover:text-text-primary"
|
|
4419
|
+
),
|
|
4420
|
+
children: "Mark all read"
|
|
4421
|
+
}
|
|
4422
|
+
),
|
|
4423
|
+
onOpenSettings && /* @__PURE__ */ jsx74(
|
|
4424
|
+
"button",
|
|
4425
|
+
{
|
|
4426
|
+
type: "button",
|
|
4427
|
+
"aria-label": "Notification settings",
|
|
4428
|
+
onClick: () => onOpenSettings(),
|
|
4429
|
+
className: "flex size-6 items-center justify-center rounded-md text-text-tertiary transition-colors hover:bg-bg-surface hover:text-text-primary",
|
|
4430
|
+
children: /* @__PURE__ */ jsx74(Settings, { className: "size-[15px]", "aria-hidden": "true" })
|
|
4431
|
+
}
|
|
4432
|
+
)
|
|
4433
|
+
] })
|
|
4434
|
+
] }),
|
|
4435
|
+
/* @__PURE__ */ jsx74("div", { className: "space-y-1.5 px-2 pb-2", children: rows.length === 0 ? /* @__PURE__ */ jsx74("p", { className: "px-3 py-12 text-center text-xs leading-relaxed text-text-disabled", children: "Nothing yet. Everything addressed to you lands here." }) : rows.map((item) => /* @__PURE__ */ jsx74(
|
|
4436
|
+
BellRow,
|
|
4437
|
+
{
|
|
4438
|
+
item,
|
|
4439
|
+
onItemClick,
|
|
4440
|
+
onActionClick,
|
|
4441
|
+
formatAge: age
|
|
4442
|
+
},
|
|
4443
|
+
item.id
|
|
4444
|
+
)) }),
|
|
4445
|
+
items.length > 0 && onOpenArchive && /* @__PURE__ */ jsx74(
|
|
4446
|
+
"button",
|
|
4447
|
+
{
|
|
4448
|
+
type: "button",
|
|
4449
|
+
onClick: () => onOpenArchive(),
|
|
4450
|
+
className: "flex w-full items-center justify-center px-5 py-2.5 text-sm font-medium text-text-brand transition-colors hover:bg-bg-surface",
|
|
4451
|
+
children: "Open notifications archive"
|
|
4452
|
+
}
|
|
4453
|
+
)
|
|
4454
|
+
] })
|
|
4455
|
+
] });
|
|
4456
|
+
}
|
|
4457
|
+
);
|
|
4458
|
+
NotificationBell.displayName = "NotificationBell";
|
|
4459
|
+
|
|
4460
|
+
// src/components/notification-center.tsx
|
|
4461
|
+
import * as React62 from "react";
|
|
4462
|
+
import { ArrowUpRight, Check as Check7, Search as Search2 } from "lucide-react";
|
|
4463
|
+
import { jsx as jsx75, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
4464
|
+
var chipBase = "rounded-lg px-3 py-1.5 text-sm font-medium transition-colors";
|
|
4465
|
+
var chipOn = "bg-bg-brand-subtle text-text-brand";
|
|
4466
|
+
var chipOff = "bg-bg-elevated text-text-secondary hover:text-text-primary";
|
|
4467
|
+
function CenterRow({
|
|
4468
|
+
item,
|
|
4469
|
+
onItemClick,
|
|
4470
|
+
onDeepLinkClick,
|
|
4471
|
+
formatAge
|
|
4472
|
+
}) {
|
|
4473
|
+
const unread = !item.read;
|
|
4474
|
+
const age = item.createdAt ? formatAge(item.createdAt instanceof Date ? item.createdAt : new Date(item.createdAt)) : null;
|
|
4475
|
+
return /* @__PURE__ */ jsxs42("article", { className: "rounded-lg bg-bg-elevated px-4 py-3", children: [
|
|
4476
|
+
/* @__PURE__ */ jsxs42("div", { className: "flex items-center gap-2", children: [
|
|
4477
|
+
/* @__PURE__ */ jsx75("span", { className: "text-xs font-semibold uppercase tracking-[0.09em] text-text-secondary", children: item.source }),
|
|
4478
|
+
/* @__PURE__ */ jsx75(Badge, { variant: severityBadgeVariant(item.severity), children: severityLabels[item.severity] }),
|
|
4479
|
+
age && /* @__PURE__ */ jsx75("span", { className: "ml-auto shrink-0 text-xs tabular-nums text-text-tertiary", children: age })
|
|
4480
|
+
] }),
|
|
4481
|
+
/* @__PURE__ */ jsx75(
|
|
4482
|
+
"button",
|
|
4483
|
+
{
|
|
4484
|
+
type: "button",
|
|
4485
|
+
onClick: () => onItemClick?.(item),
|
|
4486
|
+
className: cn(
|
|
4487
|
+
"mt-1 block text-left text-sm leading-snug underline-offset-2 hover:underline",
|
|
4488
|
+
unread ? "font-semibold text-text-primary" : "font-medium text-text-secondary"
|
|
4489
|
+
),
|
|
4490
|
+
children: item.title
|
|
4491
|
+
}
|
|
4492
|
+
),
|
|
4493
|
+
item.body && /* @__PURE__ */ jsx75("p", { className: "mt-0.5 text-sm leading-snug text-text-secondary", children: item.body }),
|
|
4494
|
+
(item.receipt || item.deepLink) && /* @__PURE__ */ jsxs42("div", { className: "mt-2 flex flex-wrap items-center gap-x-4 gap-y-1.5", children: [
|
|
4495
|
+
item.receipt && /* @__PURE__ */ jsxs42("span", { className: "inline-flex items-center gap-1.5 text-sm text-text-tertiary", children: [
|
|
4496
|
+
/* @__PURE__ */ jsx75(Check7, { className: "size-3 shrink-0 text-text-success", "aria-hidden": "true" }),
|
|
4497
|
+
item.receipt
|
|
4498
|
+
] }),
|
|
4499
|
+
item.deepLink && /* @__PURE__ */ jsxs42(
|
|
4500
|
+
"button",
|
|
4501
|
+
{
|
|
4502
|
+
type: "button",
|
|
4503
|
+
onClick: () => onDeepLinkClick?.(item),
|
|
4504
|
+
className: "inline-flex items-center gap-1 text-sm font-medium text-text-brand transition-colors hover:text-text-primary",
|
|
4505
|
+
children: [
|
|
4506
|
+
item.deepLink.label,
|
|
4507
|
+
/* @__PURE__ */ jsx75(ArrowUpRight, { className: "size-3", "aria-hidden": "true" })
|
|
4508
|
+
]
|
|
4509
|
+
}
|
|
4510
|
+
)
|
|
4511
|
+
] })
|
|
4512
|
+
] });
|
|
4513
|
+
}
|
|
4514
|
+
var NotificationCenter = React62.forwardRef(
|
|
4515
|
+
({
|
|
4516
|
+
items,
|
|
4517
|
+
title = "Notifications",
|
|
4518
|
+
description,
|
|
4519
|
+
sources,
|
|
4520
|
+
products,
|
|
4521
|
+
searchable = true,
|
|
4522
|
+
pageSize = 20,
|
|
4523
|
+
onItemClick,
|
|
4524
|
+
onDeepLinkClick,
|
|
4525
|
+
onMarkAllRead,
|
|
4526
|
+
formatAge,
|
|
4527
|
+
className
|
|
4528
|
+
}, ref) => {
|
|
4529
|
+
const [status, setStatus] = React62.useState("all");
|
|
4530
|
+
const [source, setSource] = React62.useState("all");
|
|
4531
|
+
const [product, setProduct] = React62.useState("all");
|
|
4532
|
+
const [query, setQuery] = React62.useState("");
|
|
4533
|
+
const [limit, setLimit] = React62.useState(pageSize);
|
|
4534
|
+
const age = React62.useCallback(
|
|
4535
|
+
(createdAt) => formatAge ? formatAge(createdAt) : formatRelativeAge(createdAt),
|
|
4536
|
+
[formatAge]
|
|
4537
|
+
);
|
|
4538
|
+
const sourceChips = React62.useMemo(
|
|
4539
|
+
() => sources ?? Array.from(new Set(items.map((n) => n.source))),
|
|
4540
|
+
[sources, items]
|
|
4541
|
+
);
|
|
4542
|
+
const q = query.trim().toLowerCase();
|
|
4543
|
+
const matched = items.filter((n) => status === "all" || !n.read).filter((n) => source === "all" || n.source === source).filter((n) => product === "all" || n.product === product).filter(
|
|
4544
|
+
(n) => q === "" || n.title.toLowerCase().includes(q) || (n.body ?? "").toLowerCase().includes(q) || n.source.toLowerCase().includes(q)
|
|
4545
|
+
);
|
|
4546
|
+
const shown = matched.slice(0, limit);
|
|
4547
|
+
const remaining = matched.length - shown.length;
|
|
4548
|
+
const filtering = q !== "" || status !== "all" || source !== "all" || product !== "all";
|
|
4549
|
+
return /* @__PURE__ */ jsxs42("div", { ref, className: cn("mx-auto max-w-[560px]", className), children: [
|
|
4550
|
+
/* @__PURE__ */ jsxs42("div", { className: "mb-4 flex items-start gap-4", children: [
|
|
4551
|
+
/* @__PURE__ */ jsxs42("div", { className: "min-w-0 flex-1", children: [
|
|
4552
|
+
/* @__PURE__ */ jsx75("h1", { className: "mb-1.5 text-2xl font-semibold tracking-tight text-text-primary", children: title }),
|
|
4553
|
+
description && /* @__PURE__ */ jsx75("p", { className: "text-sm text-text-tertiary", children: description })
|
|
4554
|
+
] }),
|
|
4555
|
+
onMarkAllRead && /* @__PURE__ */ jsx75(
|
|
4556
|
+
"button",
|
|
4557
|
+
{
|
|
4558
|
+
type: "button",
|
|
4559
|
+
onClick: () => onMarkAllRead(),
|
|
4560
|
+
className: "shrink-0 rounded-md px-2.5 py-1 text-sm font-medium text-text-tertiary transition-colors hover:text-text-primary",
|
|
4561
|
+
children: "Read all"
|
|
4562
|
+
}
|
|
4563
|
+
)
|
|
4564
|
+
] }),
|
|
4565
|
+
searchable && /* @__PURE__ */ jsxs42("div", { className: "mb-3 flex items-center gap-2 rounded-lg bg-bg-elevated px-3 py-2", children: [
|
|
4566
|
+
/* @__PURE__ */ jsx75(Search2, { className: "size-4 shrink-0 text-text-tertiary", "aria-hidden": "true" }),
|
|
4567
|
+
/* @__PURE__ */ jsx75(
|
|
4568
|
+
"input",
|
|
4569
|
+
{
|
|
4570
|
+
type: "text",
|
|
4571
|
+
value: query,
|
|
4572
|
+
onChange: (e) => setQuery(e.target.value),
|
|
4573
|
+
placeholder: "Search notifications",
|
|
4574
|
+
className: "w-full bg-transparent text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none"
|
|
4575
|
+
}
|
|
4576
|
+
)
|
|
4577
|
+
] }),
|
|
4578
|
+
/* @__PURE__ */ jsxs42("div", { className: "mb-2 flex flex-wrap gap-1.5", children: [
|
|
4579
|
+
/* @__PURE__ */ jsx75(
|
|
4580
|
+
"button",
|
|
4581
|
+
{
|
|
4582
|
+
type: "button",
|
|
4583
|
+
onClick: () => setStatus("all"),
|
|
4584
|
+
className: cn(chipBase, status === "all" ? chipOn : chipOff),
|
|
4585
|
+
children: "All"
|
|
4586
|
+
}
|
|
4587
|
+
),
|
|
4588
|
+
/* @__PURE__ */ jsx75(
|
|
4589
|
+
"button",
|
|
4590
|
+
{
|
|
4591
|
+
type: "button",
|
|
4592
|
+
onClick: () => setStatus("unread"),
|
|
4593
|
+
className: cn(chipBase, status === "unread" ? chipOn : chipOff),
|
|
4594
|
+
children: "Unread"
|
|
4595
|
+
}
|
|
4596
|
+
)
|
|
4597
|
+
] }),
|
|
4598
|
+
/* @__PURE__ */ jsxs42("div", { className: "mb-2 flex flex-wrap gap-1.5", children: [
|
|
4599
|
+
/* @__PURE__ */ jsx75(
|
|
4600
|
+
"button",
|
|
4601
|
+
{
|
|
4602
|
+
type: "button",
|
|
4603
|
+
onClick: () => setSource("all"),
|
|
4604
|
+
className: cn(chipBase, source === "all" ? chipOn : chipOff),
|
|
4605
|
+
children: "All sources"
|
|
4606
|
+
}
|
|
4607
|
+
),
|
|
4608
|
+
sourceChips.map((s) => /* @__PURE__ */ jsx75(
|
|
4609
|
+
"button",
|
|
4610
|
+
{
|
|
4611
|
+
type: "button",
|
|
4612
|
+
onClick: () => setSource(s),
|
|
4613
|
+
className: cn(chipBase, source === s ? chipOn : chipOff),
|
|
4614
|
+
children: s
|
|
4615
|
+
},
|
|
4616
|
+
s
|
|
4617
|
+
))
|
|
4618
|
+
] }),
|
|
4619
|
+
products && products.length > 0 && /* @__PURE__ */ jsxs42("div", { className: "mb-4 flex flex-wrap gap-1.5", children: [
|
|
4620
|
+
/* @__PURE__ */ jsx75(
|
|
4621
|
+
"button",
|
|
4622
|
+
{
|
|
4623
|
+
type: "button",
|
|
4624
|
+
onClick: () => setProduct("all"),
|
|
4625
|
+
className: cn(chipBase, product === "all" ? chipOn : chipOff),
|
|
4626
|
+
children: "All products"
|
|
4627
|
+
}
|
|
4628
|
+
),
|
|
4629
|
+
products.map((p) => /* @__PURE__ */ jsx75(
|
|
4630
|
+
"button",
|
|
4631
|
+
{
|
|
4632
|
+
type: "button",
|
|
4633
|
+
onClick: () => setProduct(p.id),
|
|
4634
|
+
className: cn(chipBase, product === p.id ? chipOn : chipOff),
|
|
4635
|
+
children: p.label
|
|
4636
|
+
},
|
|
4637
|
+
p.id
|
|
4638
|
+
))
|
|
4639
|
+
] }),
|
|
4640
|
+
shown.length === 0 ? /* @__PURE__ */ jsx75("p", { className: "rounded-xl bg-bg-elevated px-4 py-10 text-center text-sm leading-relaxed text-text-disabled", children: filtering ? "Nothing matches." : "Nothing here yet. Everything addressed to you lands here." }) : /* @__PURE__ */ jsxs42("div", { className: "flex flex-col gap-1.5", children: [
|
|
4641
|
+
shown.map((item) => /* @__PURE__ */ jsx75(
|
|
4642
|
+
CenterRow,
|
|
4643
|
+
{
|
|
4644
|
+
item,
|
|
4645
|
+
onItemClick,
|
|
4646
|
+
onDeepLinkClick,
|
|
4647
|
+
formatAge: age
|
|
4648
|
+
},
|
|
4649
|
+
item.id
|
|
4650
|
+
)),
|
|
4651
|
+
remaining > 0 && /* @__PURE__ */ jsxs42(
|
|
4652
|
+
"button",
|
|
4653
|
+
{
|
|
4654
|
+
type: "button",
|
|
4655
|
+
onClick: () => setLimit((l) => l + pageSize),
|
|
4656
|
+
className: "mt-1 rounded-lg bg-bg-elevated px-4 py-2.5 text-sm font-medium text-text-secondary transition-colors hover:bg-bg-surface hover:text-text-primary",
|
|
4657
|
+
children: [
|
|
4658
|
+
"Load ",
|
|
4659
|
+
remaining,
|
|
4660
|
+
" more"
|
|
4661
|
+
]
|
|
4662
|
+
}
|
|
4663
|
+
)
|
|
4664
|
+
] })
|
|
4665
|
+
] });
|
|
4666
|
+
}
|
|
4667
|
+
);
|
|
4668
|
+
NotificationCenter.displayName = "NotificationCenter";
|
|
4669
|
+
|
|
4670
|
+
// src/components/notification-settings.tsx
|
|
4671
|
+
import * as React63 from "react";
|
|
4672
|
+
import { Moon as Moon2, Plus as Plus2, Volume2 } from "lucide-react";
|
|
4673
|
+
import { Fragment as Fragment9, jsx as jsx76, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
4674
|
+
var THRESHOLDS = [
|
|
4675
|
+
["everything", "Everything"],
|
|
4676
|
+
["important", "Important"],
|
|
4677
|
+
["critical only", "Critical only"]
|
|
4678
|
+
];
|
|
4679
|
+
var DEFAULT_KEY = "default";
|
|
4680
|
+
function ThresholdControl({
|
|
4681
|
+
label,
|
|
4682
|
+
value,
|
|
4683
|
+
onChange
|
|
4684
|
+
}) {
|
|
4685
|
+
return /* @__PURE__ */ jsx76(
|
|
4686
|
+
"span",
|
|
4687
|
+
{
|
|
4688
|
+
role: "group",
|
|
4689
|
+
"aria-label": `Interrupt me for ${label}`,
|
|
4690
|
+
className: "inline-flex shrink-0 overflow-hidden rounded-md bg-bg-primary",
|
|
4691
|
+
children: THRESHOLDS.map(([threshold, text]) => /* @__PURE__ */ jsx76(
|
|
4692
|
+
"button",
|
|
4693
|
+
{
|
|
4694
|
+
type: "button",
|
|
4695
|
+
"aria-pressed": value === threshold,
|
|
4696
|
+
onClick: () => onChange(threshold),
|
|
4697
|
+
className: cn(
|
|
4698
|
+
"px-3 py-1.5 text-sm font-semibold transition-colors",
|
|
4699
|
+
value === threshold ? "bg-bg-brand-subtle text-text-brand" : "text-text-tertiary hover:text-text-primary"
|
|
4700
|
+
),
|
|
4701
|
+
children: text
|
|
4702
|
+
},
|
|
4703
|
+
threshold
|
|
4704
|
+
))
|
|
4705
|
+
}
|
|
4706
|
+
);
|
|
4707
|
+
}
|
|
4708
|
+
var NotificationSettings = React63.forwardRef(
|
|
4709
|
+
({
|
|
4710
|
+
subscriptions,
|
|
4711
|
+
value,
|
|
4712
|
+
onChange,
|
|
4713
|
+
products,
|
|
4714
|
+
soundEnabled,
|
|
4715
|
+
onSoundEnabledChange,
|
|
4716
|
+
mutes = [],
|
|
4717
|
+
onUnmute,
|
|
4718
|
+
pushSlot,
|
|
4719
|
+
className
|
|
4720
|
+
}, ref) => {
|
|
4721
|
+
const [tab, setTab] = React63.useState(DEFAULT_KEY);
|
|
4722
|
+
const isDefault = tab === DEFAULT_KEY;
|
|
4723
|
+
const defaults = value[DEFAULT_KEY] ?? { thresholds: {} };
|
|
4724
|
+
const customized = !isDefault && Object.prototype.hasOwnProperty.call(value, tab);
|
|
4725
|
+
const active = customized ? value[tab] : defaults;
|
|
4726
|
+
const productLabel = products?.find((p) => p.id === tab)?.label ?? tab;
|
|
4727
|
+
const setThreshold = (id, threshold) => {
|
|
4728
|
+
const key = isDefault ? DEFAULT_KEY : tab;
|
|
4729
|
+
const base2 = value[key] ?? defaults;
|
|
4730
|
+
onChange({ ...value, [key]: { thresholds: { ...base2.thresholds, [id]: threshold } } });
|
|
4731
|
+
};
|
|
4732
|
+
const customize = () => onChange({ ...value, [tab]: { thresholds: { ...defaults.thresholds } } });
|
|
4733
|
+
const resetToDefault = () => {
|
|
4734
|
+
const next = { ...value };
|
|
4735
|
+
delete next[tab];
|
|
4736
|
+
onChange(next);
|
|
4737
|
+
};
|
|
4738
|
+
const scopeGroup = (scope) => {
|
|
4739
|
+
const rows = subscriptions.filter((s) => s.scope === scope);
|
|
4740
|
+
if (rows.length === 0) return null;
|
|
4741
|
+
return /* @__PURE__ */ jsxs43("div", { children: [
|
|
4742
|
+
/* @__PURE__ */ jsx76("p", { className: "mb-1.5 px-0.5 text-xs font-bold uppercase tracking-wider text-text-tertiary", children: scope === "product" ? "This product" : "Organization" }),
|
|
4743
|
+
/* @__PURE__ */ jsx76("div", { className: "space-y-2", children: rows.map((sub) => /* @__PURE__ */ jsxs43(
|
|
4744
|
+
"div",
|
|
4745
|
+
{
|
|
4746
|
+
className: "flex items-center gap-4 rounded-xl bg-bg-elevated px-4 py-3",
|
|
4747
|
+
children: [
|
|
4748
|
+
/* @__PURE__ */ jsx76("p", { className: "min-w-0 flex-1 text-sm font-semibold text-text-primary", children: sub.name }),
|
|
4749
|
+
/* @__PURE__ */ jsx76(
|
|
4750
|
+
ThresholdControl,
|
|
4751
|
+
{
|
|
4752
|
+
label: sub.name,
|
|
4753
|
+
value: active.thresholds[sub.id] ?? "important",
|
|
4754
|
+
onChange: (t) => setThreshold(sub.id, t)
|
|
4755
|
+
}
|
|
4756
|
+
)
|
|
4757
|
+
]
|
|
4758
|
+
},
|
|
4759
|
+
sub.id
|
|
4760
|
+
)) })
|
|
4761
|
+
] }, scope);
|
|
4762
|
+
};
|
|
4763
|
+
return /* @__PURE__ */ jsxs43("div", { ref, className: cn("space-y-5", className), children: [
|
|
4764
|
+
products && products.length > 0 && /* @__PURE__ */ jsxs43("div", { children: [
|
|
4765
|
+
/* @__PURE__ */ jsx76("p", { className: "mb-2 px-0.5 text-xs font-bold uppercase tracking-wider text-text-tertiary", children: "Preferences for" }),
|
|
4766
|
+
/* @__PURE__ */ jsx76("div", { className: "flex flex-wrap gap-2", children: [{ id: DEFAULT_KEY, label: "Default" }, ...products].map((t) => /* @__PURE__ */ jsxs43(
|
|
4767
|
+
"button",
|
|
4768
|
+
{
|
|
4769
|
+
type: "button",
|
|
4770
|
+
onClick: () => setTab(t.id),
|
|
4771
|
+
className: cn(
|
|
4772
|
+
"flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-semibold transition-colors",
|
|
4773
|
+
tab === t.id ? "bg-bg-brand-subtle text-text-brand" : "bg-bg-elevated text-text-tertiary hover:text-text-primary"
|
|
4774
|
+
),
|
|
4775
|
+
children: [
|
|
4776
|
+
t.label,
|
|
4777
|
+
t.id !== DEFAULT_KEY && Object.prototype.hasOwnProperty.call(value, t.id) && /* @__PURE__ */ jsx76("span", { className: "size-1.5 rounded-full bg-bg-brand", "aria-label": "customized" })
|
|
4778
|
+
]
|
|
4779
|
+
},
|
|
4780
|
+
t.id
|
|
4781
|
+
)) })
|
|
4782
|
+
] }),
|
|
4783
|
+
isDefault ? /* @__PURE__ */ jsxs43(Fragment9, { children: [
|
|
4784
|
+
/* @__PURE__ */ jsx76("p", { className: "text-sm leading-relaxed text-text-secondary", children: "Your defaults, applied to every product unless you customize one. Everything addressed to you always lands in the in-app record; that cannot be turned off." }),
|
|
4785
|
+
/* @__PURE__ */ jsxs43(Card, { className: "border-none bg-bg-elevated p-5", children: [
|
|
4786
|
+
/* @__PURE__ */ jsx76("p", { className: "mb-1.5 text-xs font-bold uppercase tracking-wide text-text-tertiary", children: "Push to" }),
|
|
4787
|
+
/* @__PURE__ */ jsx76("p", { className: "mb-3 text-sm leading-relaxed text-text-secondary", children: "Forward notifications beyond the in-app record to a connected integration." }),
|
|
4788
|
+
pushSlot ?? /* @__PURE__ */ jsx76("div", { className: "rounded-lg bg-bg-surface px-4 py-6 text-center", children: /* @__PURE__ */ jsx76("p", { className: "text-sm text-text-tertiary", children: "No integrations connected." }) })
|
|
4789
|
+
] }),
|
|
4790
|
+
mutes.length > 0 && /* @__PURE__ */ jsxs43("div", { children: [
|
|
4791
|
+
/* @__PURE__ */ jsx76("p", { className: "mb-1.5 px-0.5 text-xs font-bold uppercase tracking-wider text-text-tertiary", children: "Muted" }),
|
|
4792
|
+
/* @__PURE__ */ jsx76(Card, { className: "border-none bg-bg-elevated p-2", children: mutes.map((m) => /* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-3 rounded-lg px-3 py-2.5", children: [
|
|
4793
|
+
/* @__PURE__ */ jsx76(Moon2, { className: "size-4 shrink-0 text-text-tertiary", "aria-hidden": "true" }),
|
|
4794
|
+
/* @__PURE__ */ jsxs43("div", { className: "min-w-0 flex-1", children: [
|
|
4795
|
+
/* @__PURE__ */ jsx76("p", { className: "text-sm font-medium text-text-primary", children: m.source }),
|
|
4796
|
+
/* @__PURE__ */ jsxs43("p", { className: "text-sm text-text-tertiary", children: [
|
|
4797
|
+
"Muted \u2014 ",
|
|
4798
|
+
m.label,
|
|
4799
|
+
". Critical still comes through."
|
|
4800
|
+
] })
|
|
4801
|
+
] }),
|
|
4802
|
+
/* @__PURE__ */ jsx76(
|
|
4803
|
+
"button",
|
|
4804
|
+
{
|
|
4805
|
+
type: "button",
|
|
4806
|
+
onClick: () => onUnmute?.(m.source),
|
|
4807
|
+
className: "rounded-md px-2.5 py-1 text-sm font-medium text-text-brand transition-colors hover:bg-bg-surface",
|
|
4808
|
+
children: "Unmute"
|
|
4809
|
+
}
|
|
4810
|
+
)
|
|
4811
|
+
] }, m.source)) })
|
|
4812
|
+
] }),
|
|
4813
|
+
scopeGroup("product"),
|
|
4814
|
+
scopeGroup("org"),
|
|
4815
|
+
onSoundEnabledChange && /* @__PURE__ */ jsx76(Card, { className: "border-none bg-bg-elevated p-4", children: /* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-3", children: [
|
|
4816
|
+
/* @__PURE__ */ jsx76(Volume2, { className: "size-4 text-text-tertiary", "aria-hidden": "true" }),
|
|
4817
|
+
/* @__PURE__ */ jsxs43("div", { className: "flex-1", children: [
|
|
4818
|
+
/* @__PURE__ */ jsx76("p", { className: "text-sm font-medium text-text-primary", children: "Notification sound" }),
|
|
4819
|
+
/* @__PURE__ */ jsx76("p", { className: "text-sm text-text-tertiary", children: "Play a tone when a notification arrives. Critical always chimes." })
|
|
4820
|
+
] }),
|
|
4821
|
+
/* @__PURE__ */ jsx76(
|
|
4822
|
+
Switch,
|
|
4823
|
+
{
|
|
4824
|
+
checked: soundEnabled ?? false,
|
|
4825
|
+
onCheckedChange: onSoundEnabledChange,
|
|
4826
|
+
"aria-label": "Notification sound"
|
|
4827
|
+
}
|
|
4828
|
+
)
|
|
4829
|
+
] }) })
|
|
4830
|
+
] }) : !customized ? /* @__PURE__ */ jsxs43(Card, { className: "border-none bg-bg-elevated p-8 text-center", children: [
|
|
4831
|
+
/* @__PURE__ */ jsxs43("p", { className: "text-sm font-semibold text-text-primary", children: [
|
|
4832
|
+
productLabel,
|
|
4833
|
+
" follows your Default preferences."
|
|
4834
|
+
] }),
|
|
4835
|
+
/* @__PURE__ */ jsx76("p", { className: "mx-auto mt-1.5 max-w-[360px] text-sm leading-relaxed text-text-tertiary", children: "Interrupt thresholds, sound and forwarding all come from Default. Opt in to give this product its own interrupt thresholds." }),
|
|
4836
|
+
/* @__PURE__ */ jsxs43(
|
|
4837
|
+
"button",
|
|
4838
|
+
{
|
|
4839
|
+
type: "button",
|
|
4840
|
+
onClick: customize,
|
|
4841
|
+
className: "mt-5 inline-flex items-center gap-1.5 rounded-lg bg-bg-brand px-3.5 py-2 text-sm font-semibold text-text-on-brand transition-colors hover:bg-bg-brand-hover",
|
|
4842
|
+
children: [
|
|
4843
|
+
/* @__PURE__ */ jsx76(Plus2, { className: "size-4", "aria-hidden": "true" }),
|
|
4844
|
+
" Customize for ",
|
|
4845
|
+
productLabel
|
|
4846
|
+
]
|
|
4847
|
+
}
|
|
4848
|
+
)
|
|
4849
|
+
] }) : /* @__PURE__ */ jsxs43(Fragment9, { children: [
|
|
4850
|
+
/* @__PURE__ */ jsx76(Card, { className: "border-none bg-bg-brand-subtle p-3.5", children: /* @__PURE__ */ jsxs43("div", { className: "flex items-center gap-3", children: [
|
|
4851
|
+
/* @__PURE__ */ jsxs43("div", { className: "min-w-0 flex-1", children: [
|
|
4852
|
+
/* @__PURE__ */ jsxs43("p", { className: "text-sm font-semibold text-text-brand", children: [
|
|
4853
|
+
"Custom preferences for ",
|
|
4854
|
+
productLabel
|
|
4855
|
+
] }),
|
|
4856
|
+
/* @__PURE__ */ jsx76("p", { className: "text-sm leading-relaxed text-text-secondary", children: "Only the interrupt thresholds below differ. Sound and forwarding follow Default." })
|
|
4857
|
+
] }),
|
|
4858
|
+
/* @__PURE__ */ jsx76(
|
|
4859
|
+
"button",
|
|
4860
|
+
{
|
|
4861
|
+
type: "button",
|
|
4862
|
+
onClick: resetToDefault,
|
|
4863
|
+
className: "shrink-0 rounded-md px-2.5 py-1 text-sm font-medium text-text-tertiary transition-colors hover:text-text-danger",
|
|
4864
|
+
children: "Reset to Default"
|
|
4865
|
+
}
|
|
4866
|
+
)
|
|
4867
|
+
] }) }),
|
|
4868
|
+
scopeGroup("product")
|
|
4869
|
+
] })
|
|
4870
|
+
] });
|
|
4871
|
+
}
|
|
4872
|
+
);
|
|
4873
|
+
NotificationSettings.displayName = "NotificationSettings";
|
|
3844
4874
|
export {
|
|
3845
4875
|
Accordion,
|
|
3846
4876
|
AccordionContent,
|
|
@@ -3889,6 +4919,8 @@ export {
|
|
|
3889
4919
|
CarouselNext,
|
|
3890
4920
|
CarouselPrevious,
|
|
3891
4921
|
Checkbox,
|
|
4922
|
+
Code,
|
|
4923
|
+
CodeBlock,
|
|
3892
4924
|
Col,
|
|
3893
4925
|
Collapsible,
|
|
3894
4926
|
CollapsibleContent2 as CollapsibleContent,
|
|
@@ -4009,6 +5041,10 @@ export {
|
|
|
4009
5041
|
NavigationMenuList,
|
|
4010
5042
|
NavigationMenuTrigger,
|
|
4011
5043
|
NavigationMenuViewport,
|
|
5044
|
+
NotificationBell,
|
|
5045
|
+
NotificationCenter,
|
|
5046
|
+
NotificationSettings,
|
|
5047
|
+
OrgProductSwitcher,
|
|
4012
5048
|
Pagination,
|
|
4013
5049
|
PaginationContent,
|
|
4014
5050
|
PaginationEllipsis,
|
|
@@ -4044,6 +5080,7 @@ export {
|
|
|
4044
5080
|
SidebarNav,
|
|
4045
5081
|
SidebarNavLink,
|
|
4046
5082
|
SidebarProductHeader,
|
|
5083
|
+
SignInScreen,
|
|
4047
5084
|
Skeleton,
|
|
4048
5085
|
Slider,
|
|
4049
5086
|
StatCard,
|
|
@@ -4076,9 +5113,13 @@ export {
|
|
|
4076
5113
|
badgeVariants,
|
|
4077
5114
|
buttonVariants,
|
|
4078
5115
|
cn,
|
|
5116
|
+
formatRelativeAge,
|
|
4079
5117
|
isKnownExtensionIcon,
|
|
5118
|
+
isNotificationSettled,
|
|
4080
5119
|
navigationMenuTriggerStyle,
|
|
4081
5120
|
segmentChipVariants,
|
|
5121
|
+
severityBadgeVariant,
|
|
5122
|
+
severityLabels,
|
|
4082
5123
|
statusDotVariants,
|
|
4083
5124
|
toast,
|
|
4084
5125
|
toggleVariants,
|