@ramme-io/ui 4.0.1 → 4.1.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 +159 -7
- package/dist/blocks/ai/Actions.js +2 -2
- package/dist/blocks/ai/PromptInput.js +6 -6
- package/dist/component-registry.js +389 -359
- package/dist/components/ai/AIChatThread/AIChatThread.js +81 -73
- package/dist/components/ai/ArchitectureReferenceCard/ArchitectureReferenceCard.d.ts +28 -0
- package/dist/components/ai/ArchitectureReferenceCard/ArchitectureReferenceCard.js +70 -0
- package/dist/components/ai/ArchitectureReferenceCard/index.d.ts +2 -0
- package/dist/components/ai/CounterpartyGraphCard/CounterpartyGraphCard.d.ts +30 -0
- package/dist/components/ai/CounterpartyGraphCard/CounterpartyGraphCard.js +82 -0
- package/dist/components/ai/CounterpartyGraphCard/index.d.ts +2 -0
- package/dist/components/ai/DivergenceMetricsCard/DivergenceMetricsCard.d.ts +29 -0
- package/dist/components/ai/DivergenceMetricsCard/DivergenceMetricsCard.js +69 -0
- package/dist/components/ai/DivergenceMetricsCard/index.d.ts +2 -0
- package/dist/components/ai/KeyInjectionOverlay.d.ts +10 -0
- package/dist/components/ai/KeyInjectionOverlay.js +11 -11
- package/dist/components/ai/NewsSummaryCard/NewsSummaryCard.js +17 -17
- package/dist/components/ai/StockChart/StockChart.js +4 -4
- package/dist/components/auth/AuthLayout.js +4 -4
- package/dist/components/auth/LoginPage.d.ts +22 -0
- package/dist/components/auth/LoginPage.js +50 -42
- package/dist/components/data-display/CodeBlock.d.ts +33 -7
- package/dist/components/data-display/CodeBlock.js +134 -41
- package/dist/components/data-display/Table.js +8 -8
- package/dist/components/feedback/EmptyState.js +9 -9
- package/dist/components/feedback/ToastProvider.js +4 -4
- package/dist/components/forms/Checkbox.js +5 -5
- package/dist/components/forms/ComboBox.js +2 -2
- package/dist/components/forms/DatePicker.js +37 -32
- package/dist/components/forms/FileUpload.js +39 -37
- package/dist/components/forms/Input.js +19 -18
- package/dist/components/forms/MultiSelect.js +9 -8
- package/dist/components/forms/Radio.js +6 -6
- package/dist/components/forms/SegmentedControl.d.ts +1 -1
- package/dist/components/forms/SegmentedControl.js +28 -11
- package/dist/components/forms/Select.js +9 -8
- package/dist/components/forms/Textarea.d.ts +13 -11
- package/dist/components/forms/Textarea.js +36 -16
- package/dist/components/forms/ToggleSwitch.js +9 -9
- package/dist/components/layout/AboutRamme.d.ts +8 -0
- package/dist/components/layout/Accordion.js +25 -32
- package/dist/components/layout/AppShell.js +7 -7
- package/dist/components/layout/Card.js +38 -21
- package/dist/components/layout/DetailDrawer.js +37 -38
- package/dist/components/layout/Drawer.js +50 -51
- package/dist/components/layout/List.js +9 -9
- package/dist/components/layout/Modal.js +5 -5
- package/dist/components/layout/PageHeader.js +7 -7
- package/dist/components/layout/SectionHeader.js +4 -4
- package/dist/components/layout/SettingsContainer.d.ts +12 -0
- package/dist/components/layout/SettingsContainer.js +30 -18
- package/dist/components/layout/Sheet.d.ts +58 -0
- package/dist/components/layout/Sheet.js +144 -0
- package/dist/components/layout/Sidebar.js +1 -1
- package/dist/components/layout/UserNav.d.ts +13 -0
- package/dist/components/layout/UserNav.js +17 -17
- package/dist/components/molecular/ConnectorOverlay.d.ts +12 -0
- package/dist/components/navigation/Breadcrumbs.js +8 -8
- package/dist/components/navigation/Menu.js +6 -6
- package/dist/components/navigation/MobileNav.d.ts +44 -1
- package/dist/components/navigation/MobileNav.js +97 -71
- package/dist/components/navigation/Pagination.js +46 -41
- package/dist/components/navigation/Stepper.js +17 -17
- package/dist/components/navigation/Tabs.js +18 -11
- package/dist/components/theme/ThemeLab.d.ts +7 -1
- package/dist/components/theme/ThemeLab.js +175 -154
- package/dist/components/ui/icon-loader.d.ts +1 -1
- package/dist/contexts/ThemeContext.js +111 -82
- package/dist/data/mockData.d.ts +0 -3
- package/dist/index.css +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +222 -197
- package/dist/lib/hooks/useBodyScrollLock.d.ts +27 -0
- package/dist/lib/hooks/useBodyScrollLock.js +18 -0
- package/dist/lib/hooks/useSheetGesture.d.ts +81 -0
- package/dist/lib/hooks/useSheetGesture.js +70 -0
- package/dist/lib/theme/themeUtils.d.ts +21 -0
- package/dist/lib/theme/themeUtils.js +31 -17
- package/dist/setupTests.d.ts +1 -0
- package/dist/wizardManifest.js +364 -19
- package/package.json +10 -4
- package/src/wizardManifest.ts +364 -19
- package/tailwind.preset.js +98 -10
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { jsx as n } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
3
|
-
const y = ({ children:
|
|
4
|
-
const
|
|
5
|
-
return
|
|
6
|
-
|
|
7
|
-
{ className: `${
|
|
8
|
-
|
|
2
|
+
import c from "react";
|
|
3
|
+
const y = ({ children: e, className: t, ...s }) => /* @__PURE__ */ n("li", { className: `mb-1 last:mb-0 text-foreground ${t || ""}`, ...s, children: e }), b = ({ type: e = "ul", children: t, className: s, ...o }) => {
|
|
4
|
+
const l = "space-y-1", r = "text-foreground", a = e === "ol" ? "ol" : "ul";
|
|
5
|
+
return c.createElement(
|
|
6
|
+
a,
|
|
7
|
+
{ className: `${l} ${r} ${s || ""}`, ...o },
|
|
8
|
+
t
|
|
9
9
|
);
|
|
10
|
-
}, S = ({ children:
|
|
10
|
+
}, S = ({ children: e, className: t, ...s }) => /* @__PURE__ */ n("dt", { className: `font-semibold text-foreground ${t || ""}`, ...s, children: e }), $ = ({ children: e, className: t, ...s }) => /* @__PURE__ */ n("dd", { className: `ml-4 text-foreground ${t || ""}`, ...s, children: e }), u = ({ children: e, className: t, ...s }) => /* @__PURE__ */ n("dl", { className: `space-y-2 ${t || ""}`, ...s, children: e });
|
|
11
11
|
export {
|
|
12
12
|
$ as DefinitionDescription,
|
|
13
|
-
|
|
13
|
+
u as DefinitionList,
|
|
14
14
|
S as DefinitionTerm,
|
|
15
15
|
b as List,
|
|
16
16
|
y as ListItem
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { jsx as e, jsxs as
|
|
1
|
+
import { jsx as e, jsxs as t } from "react/jsx-runtime";
|
|
2
2
|
import { useRef as m, useCallback as f, useEffect as u } from "react";
|
|
3
3
|
import { createPortal as b } from "react-dom";
|
|
4
4
|
import { Icon as x } from "../ui/Icon.js";
|
|
5
5
|
import { cn as v } from "../../utils/cn.js";
|
|
6
|
-
const N = ({ isOpen: r, onClose: o, children: n, title: d, footer:
|
|
6
|
+
const N = ({ isOpen: r, onClose: o, children: n, title: d, footer: a, className: i }) => {
|
|
7
7
|
const s = m(null), l = f((c) => {
|
|
8
8
|
c.key === "Escape" && r && o();
|
|
9
9
|
}, [r, o]);
|
|
10
10
|
return u(() => (document.addEventListener("keydown", l, !1), () => {
|
|
11
11
|
document.removeEventListener("keydown", l, !1);
|
|
12
12
|
}), [l]), r ? b(
|
|
13
|
-
/* @__PURE__ */ e("div", { className: "fixed inset-0 z-
|
|
13
|
+
/* @__PURE__ */ e("div", { className: "fixed inset-0 z-drawer flex items-center justify-center p-4 bg-black/50", children: /* @__PURE__ */ t(
|
|
14
14
|
"div",
|
|
15
15
|
{
|
|
16
16
|
ref: s,
|
|
@@ -23,7 +23,7 @@ const N = ({ isOpen: r, onClose: o, children: n, title: d, footer: t, className:
|
|
|
23
23
|
"aria-modal": "true",
|
|
24
24
|
"aria-labelledby": d ? "modal-title" : void 0,
|
|
25
25
|
children: [
|
|
26
|
-
/* @__PURE__ */
|
|
26
|
+
/* @__PURE__ */ t("div", { className: "flex justify-between items-center p-4 border-b border-border", children: [
|
|
27
27
|
d && /* @__PURE__ */ e("h3", { id: "modal-title", className: "text-xl font-semibold", children: d }),
|
|
28
28
|
/* @__PURE__ */ e(
|
|
29
29
|
"button",
|
|
@@ -36,7 +36,7 @@ const N = ({ isOpen: r, onClose: o, children: n, title: d, footer: t, className:
|
|
|
36
36
|
)
|
|
37
37
|
] }),
|
|
38
38
|
/* @__PURE__ */ e("div", { className: "p-4", children: n }),
|
|
39
|
-
|
|
39
|
+
a && /* @__PURE__ */ e("div", { className: "p-4 border-t border-border flex justify-end space-x-2", children: a })
|
|
40
40
|
]
|
|
41
41
|
}
|
|
42
42
|
) }),
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
const
|
|
3
|
-
/* @__PURE__ */
|
|
4
|
-
/* @__PURE__ */ e("h1", { className: "text-3xl font-bold text-
|
|
5
|
-
r && /* @__PURE__ */ e("p", { className: "mt-1 text-
|
|
1
|
+
import { jsxs as l, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
const m = ({ title: s, description: r, actions: d, className: t }) => /* @__PURE__ */ l("div", { className: `flex flex-col @md:flex-row @md:items-center @md:justify-between gap-4 py-4 border-b border-border ${t || ""}`, children: [
|
|
3
|
+
/* @__PURE__ */ l("div", { className: "flex-grow", children: [
|
|
4
|
+
/* @__PURE__ */ e("h1", { className: "text-3xl font-bold text-foreground", children: s }),
|
|
5
|
+
r && /* @__PURE__ */ e("p", { className: "mt-1 text-muted-foreground", children: r })
|
|
6
6
|
] }),
|
|
7
|
-
|
|
7
|
+
d && /* @__PURE__ */ e("div", { className: "flex-shrink-0", children: d })
|
|
8
8
|
] });
|
|
9
9
|
export {
|
|
10
|
-
|
|
10
|
+
m as PageHeader
|
|
11
11
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
const m = ({ title:
|
|
3
|
-
/* @__PURE__ */
|
|
4
|
-
e && /* @__PURE__ */
|
|
1
|
+
import { jsxs as d, jsx as r } from "react/jsx-runtime";
|
|
2
|
+
const m = ({ title: t, description: e, className: o }) => /* @__PURE__ */ d("div", { className: `pb-2 border-b border-border mb-6 ${o || ""}`, children: [
|
|
3
|
+
/* @__PURE__ */ r("h2", { className: "text-xl font-semibold text-foreground", children: t }),
|
|
4
|
+
e && /* @__PURE__ */ r("p", { className: "mt-1 text-sm text-muted-foreground opacity-70", children: e })
|
|
5
5
|
] });
|
|
6
6
|
export {
|
|
7
7
|
m as SectionHeader
|
|
@@ -33,6 +33,18 @@ export interface SettingsContainerProps {
|
|
|
33
33
|
* Override to inject custom about content.
|
|
34
34
|
*/
|
|
35
35
|
aboutSlot?: React.ReactNode;
|
|
36
|
+
/**
|
|
37
|
+
* Which tab opens first. Defaults to 'general' so existing callers are
|
|
38
|
+
* unchanged; a theme-focused surface passes 'theme-lab' so the editor is not
|
|
39
|
+
* one click behind an app-name form.
|
|
40
|
+
*/
|
|
41
|
+
defaultTab?: 'general' | 'ai-gateway' | 'theme-lab' | 'about';
|
|
42
|
+
/**
|
|
43
|
+
* Heading above the tabs. Pass `null` when the container that holds this
|
|
44
|
+
* already has a title — a drawer labelled "Theme Studio" does not need a
|
|
45
|
+
* second heading reading "Settings".
|
|
46
|
+
*/
|
|
47
|
+
title?: React.ReactNode;
|
|
36
48
|
/** Additional CSS classes for the outermost container. */
|
|
37
49
|
className?: string;
|
|
38
50
|
}
|
|
@@ -1,22 +1,34 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { Tabs as
|
|
3
|
-
import { cn as
|
|
4
|
-
import { AboutRamme as
|
|
5
|
-
const
|
|
6
|
-
generalSlot:
|
|
1
|
+
import { jsxs as t, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { Tabs as b, TabPanel as l } from "../navigation/Tabs.js";
|
|
3
|
+
import { cn as c } from "../../utils/cn.js";
|
|
4
|
+
import { AboutRamme as s } from "./AboutRamme.js";
|
|
5
|
+
const p = ({
|
|
6
|
+
generalSlot: i,
|
|
7
7
|
aiGatewaySlot: r,
|
|
8
|
-
themeLabSlot:
|
|
9
|
-
aboutSlot:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
themeLabSlot: n,
|
|
9
|
+
aboutSlot: d = /* @__PURE__ */ e(s, {}),
|
|
10
|
+
defaultTab: o = "general",
|
|
11
|
+
title: a = "Settings",
|
|
12
|
+
className: m
|
|
13
|
+
}) => (
|
|
14
|
+
/* @container so the padding answers to the space this panel was GIVEN,
|
|
15
|
+
not the size of the screen it happens to be on.
|
|
16
|
+
|
|
17
|
+
No horizontal padding when narrow. Nested in a Sheet or a drawer, the
|
|
18
|
+
host already supplies the gutter, and adding a second one is how the
|
|
19
|
+
Theme Studio lost 21% of a 390px screen to three stacked insets before a
|
|
20
|
+
single label was drawn. Vertical padding is kept: it separates, it does
|
|
21
|
+
not compete. */
|
|
22
|
+
/* @__PURE__ */ t("div", { className: c("@container w-full py-fluid-md px-0 @md:p-fluid-lg", m), children: [
|
|
23
|
+
a !== null && /* @__PURE__ */ e("h2", { className: "text-2xl font-bold tracking-tight text-foreground mb-4", children: a }),
|
|
24
|
+
/* @__PURE__ */ t(b, { defaultActiveTab: o, size: "sm", children: [
|
|
25
|
+
/* @__PURE__ */ e(l, { id: "general", label: "General", children: i }),
|
|
26
|
+
/* @__PURE__ */ e(l, { id: "ai-gateway", label: "AI Gateway", children: r }),
|
|
27
|
+
/* @__PURE__ */ e(l, { id: "theme-lab", label: "Theme Lab", children: n }),
|
|
28
|
+
/* @__PURE__ */ e(l, { id: "about", label: "About", children: d })
|
|
29
|
+
] })
|
|
18
30
|
] })
|
|
19
|
-
|
|
31
|
+
);
|
|
20
32
|
export {
|
|
21
|
-
|
|
33
|
+
p as SettingsContainer
|
|
22
34
|
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* @wizard
|
|
4
|
+
* @name Sheet
|
|
5
|
+
* @description A bottom sheet that opens at a partial height and grows to full screen as you drag or scroll it up. Strategic purpose: the native-feeling surface for mobile navigation, settings and pickers — reachable by thumb, dismissed by flicking down. Use instead of Drawer when the surface is primarily touched.
|
|
6
|
+
* @tags layout, overlay, sheet, mobile, touch, drawer, ui
|
|
7
|
+
* @category layout
|
|
8
|
+
* @id sheet
|
|
9
|
+
* @param {boolean} isOpen - Controls the open/closed state. Required.
|
|
10
|
+
* @param {function} onClose - Fired when the sheet requests dismissal (flick down, drag below the smallest detent, Escape, overlay tap, or the close button). Required.
|
|
11
|
+
* @param {number[]} detents - Resting heights as fractions of the viewport, ascending. Defaults to [0.6, 1] — opens at 60%, expands to full.
|
|
12
|
+
* @param {number} initialDetent - Index into detents to open at. Defaults to 0.
|
|
13
|
+
* @param {string} title - Optional title in the sticky header, beside the close button.
|
|
14
|
+
* @param {ReactNode} footer - Optional sticky footer, kept clear of the home indicator.
|
|
15
|
+
* @param {boolean} overlayDismiss - Tap the dimmed backdrop to close. Defaults to true.
|
|
16
|
+
* @param {string} className - Extra classes for the sheet panel.
|
|
17
|
+
*/
|
|
18
|
+
export interface SheetProps {
|
|
19
|
+
isOpen: boolean;
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
detents?: number[];
|
|
23
|
+
initialDetent?: number;
|
|
24
|
+
title?: string;
|
|
25
|
+
footer?: React.ReactNode;
|
|
26
|
+
overlayDismiss?: boolean;
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* WHY THIS EXISTS ALONGSIDE Drawer
|
|
31
|
+
*
|
|
32
|
+
* `Drawer` already slides in from any edge, including the bottom, and it is
|
|
33
|
+
* used in 18 places across five products. It is a *static* panel: it animates
|
|
34
|
+
* to one size and stays there. The sheet pattern is a different interaction —
|
|
35
|
+
* detents, a drag that tracks your finger, and a body whose scroll is coupled
|
|
36
|
+
* to the sheet's height — and bolting that onto Drawer would put a gesture
|
|
37
|
+
* state machine into a component whose other three positions can never use it,
|
|
38
|
+
* destabilising every existing call site for a behaviour only `bottom` has.
|
|
39
|
+
*
|
|
40
|
+
* So Drawer stays as it is. Reach for Sheet when the surface is primarily
|
|
41
|
+
* touched; reach for Drawer when it is a desktop side panel.
|
|
42
|
+
*
|
|
43
|
+
* ZERO JANK
|
|
44
|
+
*
|
|
45
|
+
* - Height is driven by `transform: translateY`, never by animating `height`,
|
|
46
|
+
* so no frame triggers layout (rule 3). The panel is laid out at full
|
|
47
|
+
* viewport height once and slid down to reveal only the part in use.
|
|
48
|
+
* - `100dvh`, never `vh` (rule 5) — a sheet measured against `vh` is wrong by
|
|
49
|
+
* the height of the toolbar on every mobile browser that retracts one.
|
|
50
|
+
* - The transition is dropped entirely while a finger is down, so the sheet
|
|
51
|
+
* tracks the pointer exactly instead of lagging behind it by the duration.
|
|
52
|
+
* - `prefers-reduced-motion` disables the drag and the animation; the sheet
|
|
53
|
+
* opens at its largest detent and closes, which is the same functionality
|
|
54
|
+
* without the movement (rule 4).
|
|
55
|
+
* - Safe-area insets are honoured so the footer clears the home indicator.
|
|
56
|
+
*/
|
|
57
|
+
export declare const Sheet: React.FC<SheetProps>;
|
|
58
|
+
export default Sheet;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { jsxs as u, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { useState as m, useRef as E, useEffect as w, useCallback as S } from "react";
|
|
3
|
+
import { createPortal as j } from "react-dom";
|
|
4
|
+
import { Icon as A } from "../ui/Icon.js";
|
|
5
|
+
import { cn as x } from "../../utils/cn.js";
|
|
6
|
+
import { useBodyScrollLock as R } from "../../lib/hooks/useBodyScrollLock.js";
|
|
7
|
+
import { useSheetGesture as B } from "../../lib/hooks/useSheetGesture.js";
|
|
8
|
+
const G = ({
|
|
9
|
+
isOpen: o,
|
|
10
|
+
onClose: r,
|
|
11
|
+
children: y,
|
|
12
|
+
detents: v = [0.6, 1],
|
|
13
|
+
initialDetent: f = 0,
|
|
14
|
+
title: s,
|
|
15
|
+
footer: h,
|
|
16
|
+
overlayDismiss: k = !0,
|
|
17
|
+
className: N
|
|
18
|
+
}) => {
|
|
19
|
+
const [d, b] = m(!1), [g, p] = m(!1), D = E(null), [l] = m(
|
|
20
|
+
() => typeof window < "u" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
|
21
|
+
), i = [...v].sort((n, a) => n - a), t = B({
|
|
22
|
+
detents: i,
|
|
23
|
+
// Under reduced motion there is no drag, so a partial height would be a
|
|
24
|
+
// height the reader can never change. Open fully instead.
|
|
25
|
+
initialDetent: l ? i.length - 1 : f,
|
|
26
|
+
onDismiss: r,
|
|
27
|
+
reducedMotion: l
|
|
28
|
+
});
|
|
29
|
+
R(o), w(() => {
|
|
30
|
+
let n, a;
|
|
31
|
+
return o ? (b(!0), t.setHeight(i[l ? i.length - 1 : f] ?? i[0]), n = requestAnimationFrame(() => {
|
|
32
|
+
a = window.setTimeout(() => p(!0), 10);
|
|
33
|
+
})) : (p(!1), a = window.setTimeout(() => b(!1), 320)), () => {
|
|
34
|
+
cancelAnimationFrame(n), clearTimeout(a);
|
|
35
|
+
};
|
|
36
|
+
}, [o]);
|
|
37
|
+
const c = S(
|
|
38
|
+
(n) => {
|
|
39
|
+
n.key === "Escape" && o && r();
|
|
40
|
+
},
|
|
41
|
+
[o, r]
|
|
42
|
+
);
|
|
43
|
+
if (w(() => {
|
|
44
|
+
if (d)
|
|
45
|
+
return document.addEventListener("keydown", c), () => document.removeEventListener("keydown", c);
|
|
46
|
+
}, [d, c]), !d) return null;
|
|
47
|
+
const P = g ? 1 - t.height : 1;
|
|
48
|
+
return j(
|
|
49
|
+
/* @__PURE__ */ u(
|
|
50
|
+
"div",
|
|
51
|
+
{
|
|
52
|
+
className: x(
|
|
53
|
+
"fixed inset-0 z-drawer",
|
|
54
|
+
"transition-opacity duration-300 ease-out",
|
|
55
|
+
g ? "opacity-100" : "opacity-0"
|
|
56
|
+
),
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ e(
|
|
59
|
+
"div",
|
|
60
|
+
{
|
|
61
|
+
className: "absolute inset-0 bg-black/50",
|
|
62
|
+
onClick: k ? r : void 0,
|
|
63
|
+
"aria-hidden": "true"
|
|
64
|
+
}
|
|
65
|
+
),
|
|
66
|
+
/* @__PURE__ */ u(
|
|
67
|
+
"div",
|
|
68
|
+
{
|
|
69
|
+
ref: D,
|
|
70
|
+
role: "dialog",
|
|
71
|
+
"aria-modal": "true",
|
|
72
|
+
"aria-label": s ?? "Sheet",
|
|
73
|
+
style: {
|
|
74
|
+
transform: `translateY(${P * 100}%)`,
|
|
75
|
+
// Laid out at full height and slid down; only transform animates.
|
|
76
|
+
height: "100dvh",
|
|
77
|
+
paddingBottom: "env(safe-area-inset-bottom)"
|
|
78
|
+
},
|
|
79
|
+
className: x(
|
|
80
|
+
"absolute inset-x-0 bottom-0 flex flex-col",
|
|
81
|
+
"bg-card text-foreground border-t border-border shadow-xl",
|
|
82
|
+
// The corners round while the sheet is partial and square off once it
|
|
83
|
+
// owns the whole screen — the cue that tells you it is fully open.
|
|
84
|
+
t.expanded ? "rounded-t-none" : "rounded-t-2xl",
|
|
85
|
+
// No transition while dragging: the sheet must sit exactly under the
|
|
86
|
+
// finger, not chase it.
|
|
87
|
+
t.dragging ? "transition-none" : "transition-transform duration-300 ease-out",
|
|
88
|
+
"motion-reduce:transition-none",
|
|
89
|
+
N
|
|
90
|
+
),
|
|
91
|
+
children: [
|
|
92
|
+
/* @__PURE__ */ e(
|
|
93
|
+
"div",
|
|
94
|
+
{
|
|
95
|
+
onPointerDown: t.onPointerDown,
|
|
96
|
+
style: { touchAction: "none" },
|
|
97
|
+
className: "flex h-11 w-full shrink-0 cursor-grab items-center justify-center active:cursor-grabbing",
|
|
98
|
+
"aria-hidden": "true",
|
|
99
|
+
children: /* @__PURE__ */ e("div", { className: "h-1 w-10 rounded-full bg-muted-foreground/40" })
|
|
100
|
+
}
|
|
101
|
+
),
|
|
102
|
+
/* @__PURE__ */ u(
|
|
103
|
+
"div",
|
|
104
|
+
{
|
|
105
|
+
onPointerDown: t.onPointerDown,
|
|
106
|
+
style: { touchAction: "none" },
|
|
107
|
+
className: "flex shrink-0 items-center justify-between gap-3 px-4 pb-3",
|
|
108
|
+
children: [
|
|
109
|
+
s ? /* @__PURE__ */ e("h2", { className: "text-lg font-semibold leading-tight", children: s }) : /* @__PURE__ */ e("span", {}),
|
|
110
|
+
/* @__PURE__ */ e(
|
|
111
|
+
"button",
|
|
112
|
+
{
|
|
113
|
+
type: "button",
|
|
114
|
+
onClick: r,
|
|
115
|
+
"aria-label": "Close",
|
|
116
|
+
className: "-mr-2 inline-flex min-h-11 min-w-11 items-center justify-center rounded-full text-muted-foreground transition-colors hover:text-foreground",
|
|
117
|
+
children: /* @__PURE__ */ e(A, { name: "x", size: 22 })
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
),
|
|
123
|
+
/* @__PURE__ */ e(
|
|
124
|
+
"div",
|
|
125
|
+
{
|
|
126
|
+
onPointerDown: t.onBodyPointerDown,
|
|
127
|
+
className: "min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 pb-4",
|
|
128
|
+
children: y
|
|
129
|
+
}
|
|
130
|
+
),
|
|
131
|
+
h && /* @__PURE__ */ e("div", { className: "shrink-0 border-t border-border bg-card px-4 py-3", children: h })
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
),
|
|
138
|
+
document.body
|
|
139
|
+
);
|
|
140
|
+
};
|
|
141
|
+
export {
|
|
142
|
+
G as Sheet,
|
|
143
|
+
G as default
|
|
144
|
+
};
|
|
@@ -113,7 +113,7 @@ const F = z(void 0), P = ({ logo: e, collapsedLogo: t, title: n, collapsed: a })
|
|
|
113
113
|
var y;
|
|
114
114
|
(y = o.onClick) == null || y.call(o), u == null || u(o);
|
|
115
115
|
} }, o.id || `item-${I}`)) }) }),
|
|
116
|
-
/* @__PURE__ */ r("button", { onClick: g, className: m("absolute -right-3 z-
|
|
116
|
+
/* @__PURE__ */ r("button", { onClick: g, className: m("absolute -right-3 z-drawer rounded-full border border-border bg-background p-1 text-muted-foreground shadow-sm hover:text-foreground transition-all hover:scale-110", a || s ? "top-20" : "top-4"), children: /* @__PURE__ */ r(h, { name: c ? "chevron-right" : "chevron-left", className: "h-3 w-3" }) }),
|
|
117
117
|
/* @__PURE__ */ r(
|
|
118
118
|
U,
|
|
119
119
|
{
|
|
@@ -34,6 +34,19 @@ export interface UserNavProps {
|
|
|
34
34
|
showThemeToggle?: boolean;
|
|
35
35
|
children?: React.ReactNode;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* @wizard
|
|
39
|
+
* @name ButtonItem
|
|
40
|
+
* @description A single row inside a UserNav menu — icon, label, action. Strategic purpose: the sanctioned way to add an entry to the account menu, so extra actions match the built-in ones instead of arriving as a hand-styled button. Use `variant="destructive"` for anything that removes or signs out.
|
|
41
|
+
* @tags layout, navigation, menu, item, user-nav
|
|
42
|
+
* @category layout
|
|
43
|
+
* @id button-item
|
|
44
|
+
* @param {string} icon - Lucide icon name shown before the label.
|
|
45
|
+
* @param {string} label - The menu entry text.
|
|
46
|
+
* @param {function} onClick - Called when the entry is activated.
|
|
47
|
+
* @param {string} variant - 'default' | 'destructive'. Destructive tints the row for sign-out and delete.
|
|
48
|
+
* @param {string} className - Additional CSS classes.
|
|
49
|
+
*/
|
|
37
50
|
/**
|
|
38
51
|
* 🟢 Component: ButtonItem
|
|
39
52
|
* Extracted from main component for performance and clean scoping.
|
|
@@ -23,7 +23,7 @@ const R = () => {
|
|
|
23
23
|
label: l,
|
|
24
24
|
onClick: a,
|
|
25
25
|
variant: r = "default",
|
|
26
|
-
className:
|
|
26
|
+
className: m
|
|
27
27
|
}) => /* @__PURE__ */ n(
|
|
28
28
|
"button",
|
|
29
29
|
{
|
|
@@ -31,7 +31,7 @@ const R = () => {
|
|
|
31
31
|
className: o(
|
|
32
32
|
"relative flex w-full cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors",
|
|
33
33
|
r === "destructive" ? "text-destructive hover:bg-destructive/10" : "text-foreground hover:bg-accent hover:text-accent-foreground",
|
|
34
|
-
|
|
34
|
+
m
|
|
35
35
|
),
|
|
36
36
|
children: [
|
|
37
37
|
/* @__PURE__ */ e(O, { name: t, className: "mr-2 h-4 w-4" }),
|
|
@@ -43,20 +43,20 @@ const R = () => {
|
|
|
43
43
|
trigger: l,
|
|
44
44
|
align: a = "end",
|
|
45
45
|
side: r = "bottom",
|
|
46
|
-
className:
|
|
46
|
+
className: m,
|
|
47
47
|
onLogout: h,
|
|
48
|
-
onSettings:
|
|
48
|
+
onSettings: c,
|
|
49
49
|
onProfile: u,
|
|
50
|
-
showThemeToggle:
|
|
50
|
+
showThemeToggle: k = !0,
|
|
51
51
|
children: g
|
|
52
52
|
}) => {
|
|
53
53
|
var N;
|
|
54
54
|
const [d, s] = z(!1), f = E(null);
|
|
55
55
|
I(() => {
|
|
56
|
-
const
|
|
56
|
+
const w = (T) => {
|
|
57
57
|
f.current && !f.current.contains(T.target) && s(!1);
|
|
58
58
|
};
|
|
59
|
-
return d && document.addEventListener("mousedown",
|
|
59
|
+
return d && document.addEventListener("mousedown", w), () => document.removeEventListener("mousedown", w);
|
|
60
60
|
}, [d]);
|
|
61
61
|
const x = {
|
|
62
62
|
bottom: {
|
|
@@ -79,13 +79,13 @@ const R = () => {
|
|
|
79
79
|
start: "left-auto right-full top-0 mr-2",
|
|
80
80
|
center: "left-auto right-full top-1/2 -translate-y-1/2 mr-2"
|
|
81
81
|
}
|
|
82
|
-
}, y = ((N = x[r]) == null ? void 0 : N[a]) || x.bottom.end,
|
|
83
|
-
return /* @__PURE__ */ n("div", { className: o("relative",
|
|
82
|
+
}, y = ((N = x[r]) == null ? void 0 : N[a]) || x.bottom.end, i = !!(u || c), p = !!k, v = !!g, C = !!h;
|
|
83
|
+
return /* @__PURE__ */ n("div", { className: o("relative", m), ref: f, children: [
|
|
84
84
|
/* @__PURE__ */ e(
|
|
85
85
|
"button",
|
|
86
86
|
{
|
|
87
87
|
onClick: () => s(!d),
|
|
88
|
-
className: "flex
|
|
88
|
+
className: "flex min-h-11 min-w-11 w-full items-center focus:outline-none",
|
|
89
89
|
children: l || /* @__PURE__ */ e(
|
|
90
90
|
L,
|
|
91
91
|
{
|
|
@@ -101,7 +101,7 @@ const R = () => {
|
|
|
101
101
|
{
|
|
102
102
|
className: o(
|
|
103
103
|
// 🟢 FIXED: Using card background with backdrop blur for high visibility
|
|
104
|
-
"absolute z-
|
|
104
|
+
"absolute z-popover w-56 rounded-md border border-border shadow-2xl",
|
|
105
105
|
"bg-[rgb(var(--app-card-bg-color))] text-[rgb(var(--app-text-color))]",
|
|
106
106
|
"backdrop-blur-md",
|
|
107
107
|
// Ensures content behind doesn't make text unreadable
|
|
@@ -113,20 +113,20 @@ const R = () => {
|
|
|
113
113
|
/* @__PURE__ */ e("p", { className: "text-sm font-medium leading-none text-foreground", children: t.name }),
|
|
114
114
|
/* @__PURE__ */ e("p", { className: "text-xs leading-none text-muted-foreground truncate", children: t.email })
|
|
115
115
|
] }),
|
|
116
|
-
|
|
116
|
+
i && /* @__PURE__ */ n("div", { className: "p-1 space-y-0.5", children: [
|
|
117
117
|
u && /* @__PURE__ */ e(b, { icon: "user", label: "Profile", onClick: () => {
|
|
118
118
|
u(), s(!1);
|
|
119
119
|
} }),
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
c && /* @__PURE__ */ e(b, { icon: "settings", label: "Settings", onClick: () => {
|
|
121
|
+
c(), s(!1);
|
|
122
122
|
} })
|
|
123
123
|
] }),
|
|
124
|
-
p && /* @__PURE__ */ n("div", { className: o("p-2",
|
|
124
|
+
p && /* @__PURE__ */ n("div", { className: o("p-2", i && "border-t border-border/50"), children: [
|
|
125
125
|
/* @__PURE__ */ e("p", { className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground mb-1", children: "Theme" }),
|
|
126
126
|
/* @__PURE__ */ e(R, {})
|
|
127
127
|
] }),
|
|
128
|
-
v && /* @__PURE__ */ e("div", { className: o("p-1 space-y-0.5", (
|
|
129
|
-
C && /* @__PURE__ */ e("div", { className: o("p-1", (
|
|
128
|
+
v && /* @__PURE__ */ e("div", { className: o("p-1 space-y-0.5", (i || p) && "border-t border-border/50"), children: g }),
|
|
129
|
+
C && /* @__PURE__ */ e("div", { className: o("p-1", (i || p || v) && "border-t border-border/50"), children: /* @__PURE__ */ e(
|
|
130
130
|
b,
|
|
131
131
|
{
|
|
132
132
|
icon: "log-out",
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* @wizard
|
|
4
|
+
* @name ConnectorOverlay
|
|
5
|
+
* @description Covers a panel while its data source is connecting, and explains itself when the connection fails. Strategic purpose: the standard treatment for a live region that has no data yet — telemetry panels, market feeds, device dashboards — so every product says the same thing about a dead socket instead of inventing a spinner. Renders nothing once status is 'connected', so it can stay mounted.
|
|
6
|
+
* @tags feedback, overlay, connection, realtime, loading, error
|
|
7
|
+
* @category feedback
|
|
8
|
+
* @id connector-overlay
|
|
9
|
+
* @param {string} status - 'connecting' | 'connected' | 'error'. Renders null when connected.
|
|
10
|
+
* @param {ReactNode} message - Replaces the default copy for the current status.
|
|
11
|
+
* @param {function} onRetry - Shows a retry action in the error state when provided.
|
|
12
|
+
* @param {string} className - Additional CSS classes.
|
|
13
|
+
*/
|
|
2
14
|
export interface ConnectorOverlayProps {
|
|
3
15
|
status: 'connecting' | 'connected' | 'error';
|
|
4
16
|
message?: React.ReactNode;
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { jsx as e, jsxs as a, Fragment as
|
|
1
|
+
import { jsx as e, jsxs as a, Fragment as f } from "react/jsx-runtime";
|
|
2
2
|
import m from "react";
|
|
3
|
-
import { Link as
|
|
4
|
-
const b = ({ label:
|
|
5
|
-
const i = "inline-flex items-center text-sm font-medium", o = n ? "text-
|
|
3
|
+
import { Link as p } from "react-router-dom";
|
|
4
|
+
const b = ({ label: r, to: t, isCurrent: n, className: c, icon: s }) => {
|
|
5
|
+
const i = "inline-flex items-center text-sm font-medium", o = n ? "text-foreground" : "text-primary hover:text-secondary", d = "ml-2 text-muted-foreground", x = s && m.isValidElement(s) ? m.cloneElement(s, {
|
|
6
6
|
size: 14,
|
|
7
7
|
// This is equivalent to Tailwind's h-3.5/w-3.5
|
|
8
8
|
className: "mr-1.5"
|
|
9
|
-
}) : null,
|
|
9
|
+
}) : null, l = /* @__PURE__ */ a(f, { children: [
|
|
10
10
|
x,
|
|
11
|
-
|
|
11
|
+
r
|
|
12
12
|
] });
|
|
13
13
|
return /* @__PURE__ */ a("li", { className: `${i} ${o} ${c || ""}`, "aria-current": n ? "page" : void 0, children: [
|
|
14
|
-
t && !n ? /* @__PURE__ */ e(
|
|
14
|
+
t && !n ? /* @__PURE__ */ e(p, { to: t, className: "inline-flex items-center hover:underline", children: l }) : /* @__PURE__ */ e("span", { className: "inline-flex items-center", children: l }),
|
|
15
15
|
!n && /* @__PURE__ */ e("span", { className: d, children: "/" })
|
|
16
16
|
] });
|
|
17
|
-
}, y = ({ children:
|
|
17
|
+
}, y = ({ children: r, className: t }) => /* @__PURE__ */ e("nav", { className: `flex ${t || ""}`, "aria-label": "Breadcrumb", children: /* @__PURE__ */ e("ol", { className: "inline-flex items-center space-x-1 md:space-x-2", children: r }) });
|
|
18
18
|
export {
|
|
19
19
|
b as BreadcrumbItem,
|
|
20
20
|
y as Breadcrumbs
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as n, jsxs as p, Fragment as b } from "react/jsx-runtime";
|
|
2
|
-
import m, { useState as v, useRef as d, useCallback as f, useEffect as
|
|
3
|
-
import { Slot as
|
|
2
|
+
import m, { useState as v, useRef as d, useCallback as f, useEffect as w } from "react";
|
|
3
|
+
import { Slot as x } from "@radix-ui/react-slot";
|
|
4
4
|
import { cn as E } from "../../utils/cn.js";
|
|
5
5
|
const y = () => /* @__PURE__ */ n("div", { className: "my-1 h-px bg-border", role: "separator" }), R = ({
|
|
6
6
|
children: s,
|
|
@@ -11,14 +11,14 @@ const y = () => /* @__PURE__ */ n("div", { className: "my-1 h-px bg-border", rol
|
|
|
11
11
|
}) => {
|
|
12
12
|
const o = E(
|
|
13
13
|
"flex items-center w-full text-left px-3 py-1.5 text-sm cursor-pointer transition-colors duration-150 ease-in-out whitespace-nowrap rounded-md",
|
|
14
|
-
"hover:bg-accent hover:text-accent-foreground text-
|
|
14
|
+
"hover:bg-accent hover:text-accent-foreground text-foreground",
|
|
15
15
|
l && "opacity-50 cursor-not-allowed"
|
|
16
16
|
), r = e && m.isValidElement(e) ? m.cloneElement(e, {
|
|
17
17
|
size: 14,
|
|
18
18
|
className: "mr-2 text-muted-foreground"
|
|
19
19
|
}) : null;
|
|
20
20
|
return /* @__PURE__ */ n(
|
|
21
|
-
t ?
|
|
21
|
+
t ? x : "button",
|
|
22
22
|
{
|
|
23
23
|
onClick: c,
|
|
24
24
|
disabled: l,
|
|
@@ -42,7 +42,7 @@ const y = () => /* @__PURE__ */ n("div", { className: "my-1 h-px bg-border", rol
|
|
|
42
42
|
}, h = f(() => t((a) => !a), []), i = f((a) => {
|
|
43
43
|
o.current && !o.current.contains(a.target) && t(!1);
|
|
44
44
|
}, []);
|
|
45
|
-
return
|
|
45
|
+
return w(() => (e ? document.addEventListener("mousedown", i) : document.removeEventListener("mousedown", i), () => {
|
|
46
46
|
document.removeEventListener("mousedown", i);
|
|
47
47
|
}), [e, i]), /* @__PURE__ */ p(
|
|
48
48
|
"div",
|
|
@@ -57,7 +57,7 @@ const y = () => /* @__PURE__ */ n("div", { className: "my-1 h-px bg-border", rol
|
|
|
57
57
|
"div",
|
|
58
58
|
{
|
|
59
59
|
onMouseEnter: u,
|
|
60
|
-
className: `origin-top-right absolute z-
|
|
60
|
+
className: `origin-top-right absolute z-popover rounded-md shadow-lg bg-card border border-border ring-1 ring-black ring-opacity-5 focus:outline-none min-w-[12rem] w-max ${(() => {
|
|
61
61
|
switch (l) {
|
|
62
62
|
case "bottom-left":
|
|
63
63
|
return "top-full left-0 mt-1";
|