@ramme-io/ui 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +158 -7
- package/dist/blocks/ai/Actions.js +2 -2
- package/dist/blocks/ai/PromptInput.js +6 -6
- package/dist/component-registry.js +386 -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/auth/AuthLayout.js +4 -4
- 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/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/Textarea.js +9 -9
- package/dist/components/forms/ToggleSwitch.js +9 -9
- package/dist/components/layout/AboutRamme.d.ts +8 -0
- package/dist/components/layout/Accordion.js +13 -13
- package/dist/components/layout/AppShell.js +7 -7
- package/dist/components/layout/DetailDrawer.js +2 -2
- 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 +20 -18
- 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.js +1 -1
- package/dist/components/navigation/Pagination.js +46 -41
- package/dist/components/navigation/Stepper.js +17 -17
- package/dist/components/navigation/Tabs.js +12 -12
- package/dist/components/theme/ThemeLab.d.ts +7 -1
- package/dist/components/theme/ThemeLab.js +175 -154
- 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 +8 -0
- package/dist/index.js +203 -185
- package/dist/lib/hooks/useBodyScrollLock.d.ts +27 -0
- package/dist/lib/hooks/useBodyScrollLock.js +18 -0
- package/dist/lib/theme/themeUtils.d.ts +21 -0
- package/dist/lib/theme/themeUtils.js +31 -17
- package/dist/wizardManifest.js +234 -9
- package/package.json +14 -15
- package/src/wizardManifest.ts +234 -9
- package/tailwind.preset.js +98 -10
- package/src/index.css +0 -335
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import { jsx as e, jsxs as
|
|
1
|
+
import { jsx as e, jsxs as t } from "react/jsx-runtime";
|
|
2
2
|
import { useState as n } from "react";
|
|
3
3
|
import { Button as m } from "../ui/Button.js";
|
|
4
4
|
import { Input as c } from "../forms/Input.js";
|
|
5
5
|
import { Card as u } from "../layout/Card.js";
|
|
6
6
|
import { Icon as f } from "../ui/Icon.js";
|
|
7
|
-
function I({ status: i, setSessionKey:
|
|
8
|
-
const [s,
|
|
9
|
-
return i !== "BYOK_REQUIRED" && i !== "KEY_EXPIRED" ? null : /* @__PURE__ */ e("div", { className: "fixed inset-0 z-
|
|
10
|
-
|
|
7
|
+
function I({ status: i, setSessionKey: a }) {
|
|
8
|
+
const [s, o] = n(""), [l, d] = n(!0);
|
|
9
|
+
return i !== "BYOK_REQUIRED" && i !== "KEY_EXPIRED" ? null : /* @__PURE__ */ e("div", { className: "fixed inset-0 z-drawer flex items-center justify-center bg-background/80 backdrop-blur-sm", children: /* @__PURE__ */ e(u, { className: "w-[450px] p-6 shadow-xl border-destructive/20 border", children: /* @__PURE__ */ t("form", { onSubmit: (r) => {
|
|
10
|
+
r.preventDefault(), s.trim() && a(s.trim());
|
|
11
11
|
}, className: "space-y-4", children: [
|
|
12
|
-
/* @__PURE__ */
|
|
13
|
-
/* @__PURE__ */
|
|
12
|
+
/* @__PURE__ */ t("div", { className: "space-y-2", children: [
|
|
13
|
+
/* @__PURE__ */ t("div", { className: "flex items-center gap-2 text-destructive", children: [
|
|
14
14
|
/* @__PURE__ */ e(f, { name: "alert-triangle", size: 20 }),
|
|
15
15
|
/* @__PURE__ */ e("h3", { className: "font-semibold text-lg", children: "AI Key Required" })
|
|
16
16
|
] }),
|
|
17
17
|
/* @__PURE__ */ e("p", { className: "text-sm text-muted-foreground", children: i === "KEY_EXPIRED" ? "Your AI API key has expired or is invalid. Please provide a new key." : "This terminal requires an AI API key to function. We do not bundle keys in the client for security." })
|
|
18
18
|
] }),
|
|
19
|
-
/* @__PURE__ */
|
|
19
|
+
/* @__PURE__ */ t("div", { className: "space-y-2", children: [
|
|
20
20
|
/* @__PURE__ */ e("label", { className: "text-sm font-medium text-foreground", children: "API Key" }),
|
|
21
21
|
/* @__PURE__ */ e(
|
|
22
22
|
c,
|
|
@@ -24,20 +24,20 @@ function I({ status: i, setSessionKey: o }) {
|
|
|
24
24
|
type: "password",
|
|
25
25
|
placeholder: "Paste your AI provider key here...",
|
|
26
26
|
value: s,
|
|
27
|
-
onChange: (
|
|
27
|
+
onChange: (r) => o(r.target.value),
|
|
28
28
|
className: "font-mono w-full font-medium",
|
|
29
29
|
autoComplete: "off"
|
|
30
30
|
}
|
|
31
31
|
)
|
|
32
32
|
] }),
|
|
33
|
-
/* @__PURE__ */
|
|
33
|
+
/* @__PURE__ */ t("div", { className: "flex items-center gap-2", children: [
|
|
34
34
|
/* @__PURE__ */ e(
|
|
35
35
|
"input",
|
|
36
36
|
{
|
|
37
37
|
type: "checkbox",
|
|
38
38
|
id: "session-only",
|
|
39
39
|
checked: l,
|
|
40
|
-
onChange: (
|
|
40
|
+
onChange: (r) => d(r.target.checked),
|
|
41
41
|
className: "rounded border-input text-primary focus:ring-primary"
|
|
42
42
|
}
|
|
43
43
|
),
|
|
@@ -3,7 +3,7 @@ import { Outlet as c } from "react-router-dom";
|
|
|
3
3
|
import { useTheme as d } from "../../contexts/ThemeContext.js";
|
|
4
4
|
import { Button as t } from "../ui/Button.js";
|
|
5
5
|
const m = () => {
|
|
6
|
-
const { setTheme:
|
|
6
|
+
const { setTheme: a, customTheme: n, setCustomTheme: i } = d(), s = {
|
|
7
7
|
name: "Cyberpunk",
|
|
8
8
|
colors: {
|
|
9
9
|
primary: "255 238 88",
|
|
@@ -26,19 +26,19 @@ const m = () => {
|
|
|
26
26
|
},
|
|
27
27
|
borderRadius: "0px"
|
|
28
28
|
};
|
|
29
|
-
return /* @__PURE__ */ o("div", { className: "absolute top-4 right-4 flex gap-2 z-
|
|
29
|
+
return /* @__PURE__ */ o("div", { className: "absolute top-4 right-4 flex gap-2 z-drawer", children: [
|
|
30
30
|
["light", "dark", "system"].map((r) => /* @__PURE__ */ e(
|
|
31
31
|
t,
|
|
32
32
|
{
|
|
33
33
|
size: "sm",
|
|
34
34
|
variant: "ghost",
|
|
35
|
-
onClick: () =>
|
|
35
|
+
onClick: () => a(r),
|
|
36
36
|
className: "opacity-50 hover:opacity-100 capitalize",
|
|
37
37
|
children: r
|
|
38
38
|
},
|
|
39
39
|
r
|
|
40
40
|
)),
|
|
41
|
-
/* @__PURE__ */ e(t, { size: "sm", variant: "ghost", onClick: () => i(
|
|
41
|
+
/* @__PURE__ */ e(t, { size: "sm", variant: "ghost", onClick: () => i(n ? null : s), className: "opacity-50 hover:opacity-100", children: "AI" })
|
|
42
42
|
] });
|
|
43
43
|
}, g = () => /* @__PURE__ */ o("div", { className: "min-h-dvh w-full flex items-center justify-center bg-background text-foreground relative transition-colors duration-300", children: [
|
|
44
44
|
/* @__PURE__ */ e("div", { className: "absolute inset-0 z-0 opacity-[0.03] pointer-events-none bg-[radial-gradient(#888_1px,transparent_1px)] [background-size:16px_16px]" }),
|
|
@@ -1,23 +1,49 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
interface CodeBlockProps {
|
|
2
|
+
export interface CodeBlockProps {
|
|
3
|
+
/** The snippet. Leading/trailing blank lines are trimmed. */
|
|
3
4
|
code: string;
|
|
4
|
-
language
|
|
5
|
+
/** Prism language id — `tsx`, `bash`, `css`, `json`, … Defaults to `tsx`. */
|
|
6
|
+
language?: string;
|
|
7
|
+
/** Shown in the header. Prefer a real path (`src/App.tsx`); falls back to the language. */
|
|
8
|
+
filename?: string;
|
|
9
|
+
/** Gutter line numbers. Worth it when prose refers to "line 12". */
|
|
10
|
+
showLineNumbers?: boolean;
|
|
11
|
+
/** 1-based lines to emphasise — the "change this line" case in a tutorial. */
|
|
12
|
+
highlightLines?: number[];
|
|
13
|
+
/** Wrap long lines instead of scrolling. Off by default: wrapping a shell command misrepresents it. */
|
|
14
|
+
wrap?: boolean;
|
|
15
|
+
/** Hide the copy button. Only for snippets that are not meant to be run. */
|
|
16
|
+
hideCopy?: boolean;
|
|
5
17
|
className?: string;
|
|
6
18
|
}
|
|
7
19
|
/**
|
|
8
20
|
* @wizard
|
|
9
21
|
* @name CodeBlock
|
|
10
|
-
* @description
|
|
11
|
-
* @tags ui, data-display, code
|
|
22
|
+
* @description The one way to show code. Syntax-highlighted, theme-aware, with a copy button that works on touch and outside secure contexts. Use for every snippet in docs and tutorials — do not hand-roll a <pre>. Long lines scroll inside the block so the page never scrolls sideways on a phone.
|
|
23
|
+
* @tags ui, data-display, code, docs, tutorial
|
|
12
24
|
* @props
|
|
13
25
|
* - name: code
|
|
14
26
|
* type: string
|
|
15
|
-
* description: The
|
|
27
|
+
* description: The snippet to display. Outer blank lines are trimmed.
|
|
16
28
|
* - name: language
|
|
17
29
|
* type: string
|
|
18
|
-
* description:
|
|
30
|
+
* description: Prism language id — 'tsx', 'bash', 'css', 'json'. Defaults to 'tsx'.
|
|
31
|
+
* - name: filename
|
|
32
|
+
* type: string
|
|
33
|
+
* description: Header label. Prefer a real path like 'src/App.tsx'; falls back to the language.
|
|
34
|
+
* - name: showLineNumbers
|
|
35
|
+
* type: boolean
|
|
36
|
+
* description: Show gutter line numbers. Use when the surrounding prose cites line numbers.
|
|
37
|
+
* - name: highlightLines
|
|
38
|
+
* type: number[]
|
|
39
|
+
* description: 1-based lines to emphasise, for "change this line" steps.
|
|
40
|
+
* - name: wrap
|
|
41
|
+
* type: boolean
|
|
42
|
+
* description: Wrap long lines instead of scrolling them. Off by default.
|
|
43
|
+
* - name: hideCopy
|
|
44
|
+
* type: boolean
|
|
45
|
+
* description: Hide the copy button, for snippets that are not meant to be run.
|
|
19
46
|
* @category ui
|
|
20
47
|
* @id code-block
|
|
21
48
|
*/
|
|
22
49
|
export declare const CodeBlock: React.FC<CodeBlockProps>;
|
|
23
|
-
export {};
|
|
@@ -1,45 +1,138 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import
|
|
3
|
-
import { Prism as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
import { jsxs as f, jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import t from "react";
|
|
3
|
+
import { Prism as x } from "react-syntax-highlighter";
|
|
4
|
+
import { oneDark as k, oneLight as w } from "react-syntax-highlighter/dist/esm/styles/prism";
|
|
5
|
+
import { cn as C } from "../../utils/cn.js";
|
|
6
|
+
import { Icon as S } from "../ui/Icon.js";
|
|
7
|
+
function T() {
|
|
8
|
+
const [r, e] = t.useState(
|
|
9
|
+
() => typeof document < "u" && document.documentElement.classList.contains("dark")
|
|
10
|
+
);
|
|
11
|
+
return t.useEffect(() => {
|
|
12
|
+
const o = document.documentElement, s = () => e(o.classList.contains("dark"));
|
|
13
|
+
s();
|
|
14
|
+
const i = new MutationObserver(s);
|
|
15
|
+
return i.observe(o, { attributes: !0, attributeFilter: ["class"] }), () => i.disconnect();
|
|
16
|
+
}, []), r;
|
|
17
|
+
}
|
|
18
|
+
async function N(r) {
|
|
19
|
+
var o;
|
|
20
|
+
if ((o = navigator.clipboard) != null && o.writeText) {
|
|
21
|
+
await navigator.clipboard.writeText(r);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const e = document.createElement("textarea");
|
|
25
|
+
e.value = r, e.setAttribute("readonly", ""), e.style.position = "fixed", e.style.opacity = "0", document.body.appendChild(e), e.select(), document.execCommand("copy"), document.body.removeChild(e);
|
|
26
|
+
}
|
|
27
|
+
const B = ({
|
|
28
|
+
code: r,
|
|
29
|
+
language: e = "tsx",
|
|
30
|
+
filename: o,
|
|
31
|
+
showLineNumbers: s = !1,
|
|
32
|
+
highlightLines: i,
|
|
33
|
+
wrap: b = !1,
|
|
34
|
+
hideCopy: v = !1,
|
|
35
|
+
className: g
|
|
36
|
+
}) => {
|
|
37
|
+
const y = T(), [a, m] = t.useState(!1), d = t.useRef(), p = t.useMemo(() => r.replace(/^\n+|\s+$/g, ""), [r]), u = o || e;
|
|
38
|
+
t.useEffect(() => () => clearTimeout(d.current), []);
|
|
39
|
+
const h = async () => {
|
|
40
|
+
try {
|
|
41
|
+
await N(p), m(!0), clearTimeout(d.current), d.current = setTimeout(() => m(!1), 2e3);
|
|
42
|
+
} catch (l) {
|
|
43
|
+
console.warn("[CodeBlock] Copy failed", l);
|
|
44
|
+
}
|
|
45
|
+
}, c = t.useMemo(
|
|
46
|
+
() => new Set(i ?? []),
|
|
47
|
+
[i]
|
|
48
|
+
);
|
|
49
|
+
return /* @__PURE__ */ f(
|
|
50
|
+
"div",
|
|
51
|
+
{
|
|
52
|
+
className: C(
|
|
53
|
+
"group relative overflow-hidden rounded-lg border border-border bg-card",
|
|
54
|
+
g
|
|
55
|
+
),
|
|
56
|
+
children: [
|
|
57
|
+
/* @__PURE__ */ f("div", { className: "flex items-center justify-between gap-2 border-b border-border bg-surface-muted pl-4 pr-1.5", children: [
|
|
58
|
+
/* @__PURE__ */ n("span", { className: "truncate py-2 font-mono text-2xs font-medium uppercase tracking-wider text-muted-foreground", children: u }),
|
|
59
|
+
!v && /* @__PURE__ */ n(
|
|
60
|
+
"button",
|
|
61
|
+
{
|
|
62
|
+
type: "button",
|
|
63
|
+
onClick: h,
|
|
64
|
+
className: "inline-flex min-h-11 min-w-11 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-surface-hover hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
65
|
+
"aria-label": a ? "Copied" : `Copy ${u} snippet to clipboard`,
|
|
66
|
+
children: /* @__PURE__ */ n(
|
|
67
|
+
S,
|
|
68
|
+
{
|
|
69
|
+
name: a ? "check" : "copy",
|
|
70
|
+
size: 16,
|
|
71
|
+
className: a ? "text-success" : void 0
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
] }),
|
|
77
|
+
/* @__PURE__ */ n(
|
|
78
|
+
"div",
|
|
79
|
+
{
|
|
80
|
+
className: "overflow-x-auto overscroll-x-contain focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset",
|
|
81
|
+
tabIndex: 0,
|
|
82
|
+
role: "region",
|
|
83
|
+
"aria-label": `${u} code`,
|
|
84
|
+
children: /* @__PURE__ */ n(
|
|
85
|
+
x,
|
|
86
|
+
{
|
|
87
|
+
language: e,
|
|
88
|
+
style: y ? k : w,
|
|
89
|
+
showLineNumbers: s,
|
|
90
|
+
wrapLines: c.size > 0,
|
|
91
|
+
lineProps: c.size > 0 ? (l) => ({
|
|
92
|
+
style: {
|
|
93
|
+
display: "block",
|
|
94
|
+
// Semantic tokens, so the emphasis survives all five themes.
|
|
95
|
+
backgroundColor: c.has(l) ? "rgb(var(--app-primary-color) / 0.12)" : void 0,
|
|
96
|
+
boxShadow: c.has(l) ? "inset 2px 0 0 0 rgb(var(--app-primary-color))" : void 0
|
|
97
|
+
}
|
|
98
|
+
}) : void 0,
|
|
99
|
+
lineNumberStyle: {
|
|
100
|
+
minWidth: "2.5em",
|
|
101
|
+
paddingRight: "1em",
|
|
102
|
+
color: "rgb(var(--app-fg-muted) / 0.6)",
|
|
103
|
+
userSelect: "none"
|
|
104
|
+
},
|
|
105
|
+
customStyle: {
|
|
106
|
+
margin: 0,
|
|
107
|
+
padding: "1rem 1.25rem",
|
|
108
|
+
background: "transparent",
|
|
109
|
+
// Sizes come from the fluid scale, never a hardcoded rem — the three
|
|
110
|
+
// implementations this replaces used 0.875rem, 0.85rem and text-sm.
|
|
111
|
+
fontSize: "var(--app-step--1)",
|
|
112
|
+
lineHeight: "var(--app-leading-relaxed)",
|
|
113
|
+
tabSize: 2,
|
|
114
|
+
...b ? { whiteSpace: "pre-wrap", wordBreak: "break-word" } : {}
|
|
115
|
+
},
|
|
116
|
+
codeTagProps: {
|
|
117
|
+
style: {
|
|
118
|
+
// The single place the code typeface is decided. Swapping the
|
|
119
|
+
// token in index.css re-fonts every snippet in every product.
|
|
120
|
+
fontFamily: "var(--app-font-mono)",
|
|
121
|
+
// Ligatures off: a tutorial shows the characters you must type,
|
|
122
|
+
// and a font that draws `=>` as one arrow misleads a beginner.
|
|
123
|
+
fontVariantLigatures: "none"
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
children: p
|
|
127
|
+
}
|
|
128
|
+
)
|
|
36
129
|
}
|
|
37
|
-
|
|
38
|
-
children:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
130
|
+
),
|
|
131
|
+
/* @__PURE__ */ n("span", { "aria-live": "polite", className: "sr-only", children: a ? "Copied to clipboard" : "" })
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
);
|
|
42
135
|
};
|
|
43
136
|
export {
|
|
44
|
-
|
|
137
|
+
B as CodeBlock
|
|
45
138
|
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { jsx as e, jsxs as
|
|
1
|
+
import { jsx as e, jsxs as c } from "react/jsx-runtime";
|
|
2
2
|
import { EmptyState as d } from "../feedback/EmptyState.js";
|
|
3
|
-
const b = ({ headers:
|
|
4
|
-
i && /* @__PURE__ */ e("caption", { className: "p-4 text-lg font-semibold text-
|
|
5
|
-
/* @__PURE__ */ e("thead", { className: "bg-card-alt", children: /* @__PURE__ */ e("tr", { children:
|
|
6
|
-
/* @__PURE__ */ e("tbody", { className: "divide-y divide-border", children: a.length > 0 ? a.map((t,
|
|
7
|
-
const
|
|
8
|
-
return /* @__PURE__ */ e("td", { className: "p-4 text-sm text-
|
|
9
|
-
}) },
|
|
3
|
+
const b = ({ headers: l, data: a, caption: i, className: n }) => /* @__PURE__ */ e("div", { className: `overflow-x-auto rounded-lg border border-border ${n || ""}`, children: /* @__PURE__ */ c("table", { className: "w-full text-left", children: [
|
|
4
|
+
i && /* @__PURE__ */ e("caption", { className: "p-4 text-lg font-semibold text-foreground bg-card-alt", children: i }),
|
|
5
|
+
/* @__PURE__ */ e("thead", { className: "bg-card-alt", children: /* @__PURE__ */ e("tr", { children: l.map((t) => /* @__PURE__ */ e("th", { scope: "col", className: "p-4 text-sm font-semibold text-foreground whitespace-nowrap", children: t.label }, t.key)) }) }),
|
|
6
|
+
/* @__PURE__ */ e("tbody", { className: "divide-y divide-border", children: a.length > 0 ? a.map((t, s) => /* @__PURE__ */ e("tr", { className: "hover:bg-primary/5 transition-colors", children: l.map((r) => {
|
|
7
|
+
const o = t[r.key];
|
|
8
|
+
return /* @__PURE__ */ e("td", { className: "p-4 text-sm text-muted-foreground whitespace-nowrap", children: r.render ? r.render(o, t) : String(o) }, r.key);
|
|
9
|
+
}) }, s)) : /* @__PURE__ */ e("tr", { children: /* @__PURE__ */ e("td", { colSpan: l.length, children: /* @__PURE__ */ e("div", { className: "p-8 flex justify-center items-center", children: /* @__PURE__ */ e(
|
|
10
10
|
d,
|
|
11
11
|
{
|
|
12
12
|
title: "No Data Available",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import { Card as
|
|
3
|
-
import { Icon as
|
|
4
|
-
const
|
|
5
|
-
t && /* @__PURE__ */ e("div", { className: "text-
|
|
6
|
-
/* @__PURE__ */ e("h3", { className: "text-2xl font-semibold text-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { jsxs as l, jsx as e } from "react/jsx-runtime";
|
|
2
|
+
import { Card as o } from "../layout/Card.js";
|
|
3
|
+
import { Icon as a } from "../ui/Icon.js";
|
|
4
|
+
const i = ({ icon: t, title: s, description: r, actionButton: m, className: d }) => /* @__PURE__ */ l(o, { className: `p-8 text-center flex flex-col items-center justify-center space-y-4 ${d || ""}`, children: [
|
|
5
|
+
t && /* @__PURE__ */ e("div", { className: "text-muted-foreground/50 mb-4", children: /* @__PURE__ */ e(a, { name: t, size: 64, strokeWidth: 1.5 }) }),
|
|
6
|
+
/* @__PURE__ */ e("h3", { className: "text-2xl font-semibold text-foreground", children: s }),
|
|
7
|
+
r && /* @__PURE__ */ e("p", { className: "text-muted-foreground max-w-md", children: r }),
|
|
8
|
+
m && /* @__PURE__ */ e("div", { className: "mt-4", children: m })
|
|
9
9
|
] });
|
|
10
10
|
export {
|
|
11
|
-
|
|
11
|
+
i as EmptyState
|
|
12
12
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs as f, jsx as
|
|
1
|
+
import { jsxs as f, jsx as n } from "react/jsx-runtime";
|
|
2
2
|
import p, { useState as T, useCallback as d, createContext as v, useContext as g } from "react";
|
|
3
3
|
import { createPortal as h } from "react-dom";
|
|
4
4
|
import { Toast as w } from "./Toast.js";
|
|
@@ -8,17 +8,17 @@ const c = v(void 0), S = () => {
|
|
|
8
8
|
throw new Error("useToast must be used within a ToastProvider");
|
|
9
9
|
return o;
|
|
10
10
|
}, j = ({ children: o }) => {
|
|
11
|
-
const [m, i] = T([]),
|
|
11
|
+
const [m, i] = T([]), a = d((t, s = "info", r = 3e3) => {
|
|
12
12
|
const l = Date.now().toString() + Math.random().toString(36).substring(2, 9);
|
|
13
13
|
i((x) => [...x, { id: l, message: t, type: s, duration: r }]);
|
|
14
14
|
}, []), e = d((t) => {
|
|
15
15
|
i((s) => s.filter((r) => r.id !== t));
|
|
16
|
-
}, []), u = p.useMemo(() => ({ addToast:
|
|
16
|
+
}, []), u = p.useMemo(() => ({ addToast: a, dismissToast: e }), [a, e]);
|
|
17
17
|
return /* @__PURE__ */ f(c.Provider, { value: u, children: [
|
|
18
18
|
o,
|
|
19
19
|
h(
|
|
20
20
|
// This container holds all the toasts and positions them on the screen
|
|
21
|
-
/* @__PURE__ */
|
|
21
|
+
/* @__PURE__ */ n("div", { className: "fixed bottom-4 right-4 z-toast w-80 max-w-full space-y-2", children: m.map((t) => /* @__PURE__ */ n(
|
|
22
22
|
w,
|
|
23
23
|
{
|
|
24
24
|
id: t.id,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { jsxs as i, jsx as
|
|
1
|
+
import { jsxs as i, jsx as r } from "react/jsx-runtime";
|
|
2
2
|
import { useState as a } from "react";
|
|
3
|
-
const u = ({ label: e, id:
|
|
4
|
-
const [t] = a(() =>
|
|
3
|
+
const u = ({ label: e, id: s, className: o, ...c }) => {
|
|
4
|
+
const [t] = a(() => s || `checkbox-${Math.random().toString(36).substr(2, 9)}`);
|
|
5
5
|
return /* @__PURE__ */ i("div", { className: "flex items-center", children: [
|
|
6
|
-
/* @__PURE__ */
|
|
6
|
+
/* @__PURE__ */ r(
|
|
7
7
|
"input",
|
|
8
8
|
{
|
|
9
9
|
id: t,
|
|
@@ -12,7 +12,7 @@ const u = ({ label: e, id: r, className: o, ...c }) => {
|
|
|
12
12
|
...c
|
|
13
13
|
}
|
|
14
14
|
),
|
|
15
|
-
e && /* @__PURE__ */
|
|
15
|
+
e && /* @__PURE__ */ r("label", { htmlFor: t, className: "ml-2 text-sm text-foreground cursor-pointer", children: e })
|
|
16
16
|
] });
|
|
17
17
|
};
|
|
18
18
|
export {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { jsxs as a, jsx as
|
|
2
|
-
const m = ({ label:
|
|
3
|
-
const
|
|
1
|
+
import { jsxs as a, jsx as t } from "react/jsx-runtime";
|
|
2
|
+
const m = ({ label: e, id: s, className: o, ...i }) => {
|
|
3
|
+
const r = s || `radio-${Math.random().toString(36).substr(2, 9)}`;
|
|
4
4
|
return /* @__PURE__ */ a("div", { className: "flex items-center", children: [
|
|
5
|
-
/* @__PURE__ */
|
|
5
|
+
/* @__PURE__ */ t(
|
|
6
6
|
"input",
|
|
7
7
|
{
|
|
8
|
-
id:
|
|
8
|
+
id: r,
|
|
9
9
|
type: "radio",
|
|
10
10
|
className: `form-radio h-4 w-4 transition-colors duration-200 ease-in-out cursor-pointer text-primary border-border bg-card focus:ring-primary disabled:opacity-50 disabled:cursor-not-allowed ${o || ""}`,
|
|
11
11
|
...i
|
|
12
12
|
}
|
|
13
13
|
),
|
|
14
|
-
|
|
14
|
+
e && /* @__PURE__ */ t("label", { htmlFor: r, className: "ml-2 text-sm text-foreground cursor-pointer", children: e })
|
|
15
15
|
] });
|
|
16
16
|
};
|
|
17
17
|
export {
|
|
@@ -19,7 +19,7 @@ export interface SegmentedControlProps {
|
|
|
19
19
|
/**
|
|
20
20
|
* @wizard
|
|
21
21
|
* @name SegmentedControl
|
|
22
|
-
* @description A theme-aware linear toggle component. Ideal for switching between discrete modes (e.g., "Map / List").
|
|
22
|
+
* @description A theme-aware linear toggle component. Ideal for switching between discrete modes (e.g., "Map / List"). Every size clears the 24px WCAG 2.5.8 (AA) target-size minimum — xs 24px, sm ~25px, md ~36px. None reaches the 44px 2.5.5 (AAA) figure, so for a primary control on a touch screen prefer md or give the control its own 44px row; xs and sm are density sizes for pointer-driven toolbars.
|
|
23
23
|
* @tags input, toggle, switch, radio, control
|
|
24
24
|
* @category form
|
|
25
25
|
* @id segmented-control
|
|
@@ -1,29 +1,46 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { cn as
|
|
1
|
+
import { jsx as t } from "react/jsx-runtime";
|
|
2
|
+
import { cn as d } from "../../utils/cn.js";
|
|
3
3
|
const m = ({
|
|
4
4
|
options: n,
|
|
5
|
-
value:
|
|
5
|
+
value: i,
|
|
6
6
|
onChange: l,
|
|
7
7
|
size: r = "md",
|
|
8
|
-
className:
|
|
9
|
-
}) => /* @__PURE__ */
|
|
8
|
+
className: o
|
|
9
|
+
}) => /* @__PURE__ */ t("div", { className: d(
|
|
10
10
|
// Container: Use 'muted' background for the track (works in all themes)
|
|
11
11
|
"inline-flex bg-muted border border-border",
|
|
12
12
|
r === "xs" ? "rounded-md p-0.5" : "rounded-lg p-1",
|
|
13
|
-
|
|
13
|
+
o
|
|
14
14
|
), children: n.map((e) => {
|
|
15
|
-
const
|
|
16
|
-
return /* @__PURE__ */
|
|
15
|
+
const s = e.value === i;
|
|
16
|
+
return /* @__PURE__ */ t(
|
|
17
17
|
"button",
|
|
18
18
|
{
|
|
19
19
|
onClick: () => !e.disabled && l(e.value),
|
|
20
20
|
disabled: e.disabled,
|
|
21
|
-
className:
|
|
21
|
+
className: d(
|
|
22
22
|
"relative rounded-md font-medium transition-all duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-primary",
|
|
23
23
|
// Size Variants
|
|
24
|
-
|
|
24
|
+
//
|
|
25
|
+
// `xs` carries a stated 24px floor rather than a padding value
|
|
26
|
+
// tuned to reach one. WCAG 2.5.8 Target Size (Minimum, level AA)
|
|
27
|
+
// is 24x24; this variant measured 19px, so it was the only size
|
|
28
|
+
// in the set that failed. min-h-6 cannot drift when the fluid
|
|
29
|
+
// scale interpolates or when a theme changes the base font size,
|
|
30
|
+
// where padding arithmetic silently can.
|
|
31
|
+
//
|
|
32
|
+
// It also drops `text-[10px]`: an arbitrary type size is banned
|
|
33
|
+
// outright by AGENTS.md, and being outside the scale made this
|
|
34
|
+
// the one size that ignored both the viewport and
|
|
35
|
+
// useTheme().setFontSize — it measured 19px at 360px and 19px at
|
|
36
|
+
// 1280px while every other size moved.
|
|
37
|
+
//
|
|
38
|
+
// inline-flex is scoped to `xs` on purpose. Applying it to all
|
|
39
|
+
// three would re-resolve the line box for `sm` and `md`, and
|
|
40
|
+
// those two already clear AA and must not move.
|
|
41
|
+
r === "xs" ? "inline-flex items-center justify-center min-h-6 text-2xs px-2 py-0.5" : r === "sm" ? "text-xs px-3 py-1" : "text-sm px-4 py-1.5",
|
|
25
42
|
// State Styles (Theme Aware)
|
|
26
|
-
|
|
43
|
+
s ? "bg-card text-foreground shadow-sm ring-1 ring-black/5 dark:ring-white/10" : "text-muted-foreground hover:text-foreground hover:bg-background/50",
|
|
27
44
|
e.disabled && "opacity-50 cursor-not-allowed"
|
|
28
45
|
),
|
|
29
46
|
type: "button",
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import
|
|
3
|
-
const
|
|
4
|
-
({ label: r, className:
|
|
5
|
-
r && /* @__PURE__ */
|
|
6
|
-
/* @__PURE__ */
|
|
1
|
+
import { jsxs as n, jsx as o } from "react/jsx-runtime";
|
|
2
|
+
import d from "react";
|
|
3
|
+
const m = d.forwardRef(
|
|
4
|
+
({ label: r, className: t, containerClassName: a, ...e }, s) => /* @__PURE__ */ n("div", { className: `w-full ${a || ""}`, children: [
|
|
5
|
+
r && /* @__PURE__ */ o("label", { htmlFor: e.id || e.name, className: "block text-sm font-medium text-muted-foreground mb-1", children: r }),
|
|
6
|
+
/* @__PURE__ */ o(
|
|
7
7
|
"textarea",
|
|
8
8
|
{
|
|
9
9
|
ref: s,
|
|
10
|
-
className: `w-full px-3 py-2 rounded-md bg-card border border-border transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary ${
|
|
10
|
+
className: `w-full px-3 py-2 rounded-md bg-card border border-border transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary ${t || ""}`,
|
|
11
11
|
...e
|
|
12
12
|
}
|
|
13
13
|
)
|
|
14
14
|
] })
|
|
15
15
|
);
|
|
16
|
-
|
|
16
|
+
m.displayName = "Textarea";
|
|
17
17
|
export {
|
|
18
|
-
|
|
18
|
+
m as Textarea
|
|
19
19
|
};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { jsxs as s, jsx as e } from "react/jsx-runtime";
|
|
2
2
|
import m from "react";
|
|
3
3
|
const d = ({
|
|
4
|
-
checked:
|
|
4
|
+
checked: o,
|
|
5
5
|
onChange: n,
|
|
6
6
|
label: a,
|
|
7
7
|
className: l,
|
|
8
|
-
disabled:
|
|
8
|
+
disabled: t = !1
|
|
9
9
|
}) => {
|
|
10
10
|
const i = () => {
|
|
11
|
-
|
|
11
|
+
t || n(!o);
|
|
12
12
|
}, r = m.useId();
|
|
13
|
-
return /* @__PURE__ */ s("label", { htmlFor: r, className: `flex items-center cursor-pointer ${l || ""} ${
|
|
13
|
+
return /* @__PURE__ */ s("label", { htmlFor: r, className: `flex items-center cursor-pointer ${l || ""} ${t ? "opacity-50 cursor-not-allowed" : ""}`, children: [
|
|
14
14
|
/* @__PURE__ */ s("div", { className: "relative", children: [
|
|
15
15
|
/* @__PURE__ */ e(
|
|
16
16
|
"input",
|
|
@@ -18,20 +18,20 @@ const d = ({
|
|
|
18
18
|
id: r,
|
|
19
19
|
type: "checkbox",
|
|
20
20
|
className: "sr-only",
|
|
21
|
-
checked:
|
|
21
|
+
checked: o,
|
|
22
22
|
onChange: i,
|
|
23
|
-
disabled:
|
|
23
|
+
disabled: t
|
|
24
24
|
}
|
|
25
25
|
),
|
|
26
|
-
/* @__PURE__ */ e("div", { className: `block w-12 h-6 rounded-full transition-colors duration-200 ease-in-out ${
|
|
26
|
+
/* @__PURE__ */ e("div", { className: `block w-12 h-6 rounded-full transition-colors duration-200 ease-in-out ${o ? "bg-primary" : "bg-border"}` }),
|
|
27
27
|
/* @__PURE__ */ e(
|
|
28
28
|
"div",
|
|
29
29
|
{
|
|
30
|
-
className: `dot absolute left-1 top-1 bg-white w-4 h-4 rounded-full shadow-sm transition-transform duration-200 ease-in-out ${
|
|
30
|
+
className: `dot absolute left-1 top-1 bg-white w-4 h-4 rounded-full shadow-sm transition-transform duration-200 ease-in-out ${o ? "translate-x-6" : ""}`
|
|
31
31
|
}
|
|
32
32
|
)
|
|
33
33
|
] }),
|
|
34
|
-
/* @__PURE__ */ e("div", { className: "ml-3 text-
|
|
34
|
+
/* @__PURE__ */ e("div", { className: "ml-3 text-foreground font-medium select-none", children: a })
|
|
35
35
|
] });
|
|
36
36
|
};
|
|
37
37
|
export {
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* @wizard
|
|
4
|
+
* @name AboutRamme
|
|
5
|
+
* @description The "About" panel for a Settings Console — what the framework is, which packages make it up, and why it is built this way. Strategic purpose: ships the explanation with the framework so every product's about screen stays accurate as the architecture moves, instead of each one carrying a copy that goes stale. Takes no props; drop it into a settings tab.
|
|
6
|
+
* @tags layout, settings, about, documentation, panel
|
|
7
|
+
* @category layout
|
|
8
|
+
* @id about-ramme
|
|
9
|
+
*/
|
|
2
10
|
/**
|
|
3
11
|
* AboutRamme — static informational panel for the Settings Console's "About" tab.
|
|
4
12
|
* Describes the framework architecture, core packages, and business rationale.
|