@vllnt/ui 0.2.1-canary.bf41f62 → 0.2.1-canary.c065357
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 +38 -24
- package/dist/components/border-beam/border-beam.js +2 -2
- package/dist/components/candlestick-chart/candlestick-chart.js +3 -3
- package/dist/components/canvas-shell/canvas-foundation-demo.js +5 -5
- package/dist/components/canvas-shell/canvas-shell.js +2 -2
- package/dist/components/chat-dock-section/chat-dock-section.js +1 -1
- package/dist/components/code-block/code-block.js +2 -1
- package/dist/components/code-playground/code-playground.js +1 -0
- package/dist/components/glass-panel/glass-panel.js +1 -1
- package/dist/components/index.js +6 -0
- package/dist/components/infinite-plane/infinite-plane.js +2 -2
- package/dist/components/kbd/kbd.js +1 -1
- package/dist/components/mdx-content/mdx-content.js +2 -1
- package/dist/components/object-card/object-card.js +2 -2
- package/dist/components/overview-board/overview-board.js +1 -1
- package/dist/components/sidebar-toggle/sidebar-toggle.js +2 -0
- package/dist/components/static-code/index.js +4 -0
- package/dist/components/static-code/static-code-copy.js +29 -0
- package/dist/components/static-code/static-code.js +41 -0
- package/dist/components/terminal/terminal.js +2 -0
- package/dist/components/theme-preset-provider/index.js +4 -0
- package/dist/components/theme-preset-provider/theme-preset-provider.js +55 -0
- package/dist/components/theme-switcher/index.js +4 -0
- package/dist/components/theme-switcher/theme-switcher.js +43 -0
- package/dist/components/viewport-bookmarks/viewport-bookmarks.js +3 -1
- package/dist/index.d.ts +89 -1
- package/dist/index.js +19 -1
- package/dist/lib/theme-presets.js +32 -0
- package/dist/lib/use-theme-preset.js +94 -0
- package/dist/tailwind-preset.js +19 -19
- package/package.json +3 -2
- package/styles.css +38 -38
- package/themes/default.css +39 -39
- package/themes/presets.css +547 -0
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ export default {
|
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
The preset configures:
|
|
47
|
-
- **Colors**: `primary`, `secondary`, `muted`, `accent`, `destructive`, `background`, `foreground`, `card`, `popover`, `border`, `input`, `ring` — all as `
|
|
47
|
+
- **Colors**: `primary`, `secondary`, `muted`, `accent`, `destructive`, `background`, `foreground`, `card`, `popover`, `border`, `input`, `ring` — all as `oklch(var(--name) / <alpha-value>)` for theming
|
|
48
48
|
- **Border radius**: `lg`, `md`, `sm` via `--radius` CSS variable
|
|
49
49
|
- **Animations**: `accordion-down`, `accordion-up`, `shimmer`
|
|
50
50
|
- **Font**: `mono` family via `--font-mono` variable
|
|
@@ -83,45 +83,59 @@ export function Example() {
|
|
|
83
83
|
| `@vllnt/ui/tailwind-preset` | Tailwind CSS preset config |
|
|
84
84
|
| `@vllnt/ui/styles.css` | Full styles (Tailwind base + theme variables + utilities) |
|
|
85
85
|
| `@vllnt/ui/themes/default.css` | Theme CSS variables only (no Tailwind base) |
|
|
86
|
+
| `@vllnt/ui/themes/presets.css` | Built-in color presets (applied via `data-theme`) |
|
|
86
87
|
|
|
87
88
|
## Theming
|
|
88
89
|
|
|
89
|
-
All colors
|
|
90
|
+
All colors are **OKLCH channel** CSS variables (`L C H`), consumed as
|
|
91
|
+
`oklch(var(--name) / <alpha-value>)`. Override them after importing styles:
|
|
90
92
|
|
|
91
93
|
```css
|
|
92
94
|
/* Light theme */
|
|
93
95
|
:root {
|
|
94
|
-
--background: 0 0
|
|
95
|
-
--foreground: 0 0
|
|
96
|
-
--primary:
|
|
97
|
-
--primary-foreground:
|
|
98
|
-
--secondary:
|
|
99
|
-
--secondary-foreground:
|
|
100
|
-
--muted:
|
|
101
|
-
--muted-foreground:
|
|
102
|
-
--accent:
|
|
103
|
-
--accent-foreground:
|
|
104
|
-
--destructive: 0
|
|
105
|
-
--destructive-foreground: 0 0
|
|
106
|
-
--border:
|
|
107
|
-
--input:
|
|
108
|
-
--ring:
|
|
96
|
+
--background: 1 0 0;
|
|
97
|
+
--foreground: 0.1445 0 0;
|
|
98
|
+
--primary: 0.2044 0 0;
|
|
99
|
+
--primary-foreground: 0.9848 0 0;
|
|
100
|
+
--secondary: 0.9703 0 0;
|
|
101
|
+
--secondary-foreground: 0.2044 0 0;
|
|
102
|
+
--muted: 0.9703 0 0;
|
|
103
|
+
--muted-foreground: 0.5555 0 0;
|
|
104
|
+
--accent: 0.9703 0 0;
|
|
105
|
+
--accent-foreground: 0.2044 0 0;
|
|
106
|
+
--destructive: 0.6368 0.2078 25.326;
|
|
107
|
+
--destructive-foreground: 0.9848 0 0;
|
|
108
|
+
--border: 0.9219 0 0;
|
|
109
|
+
--input: 0.9219 0 0;
|
|
110
|
+
--ring: 0.1445 0 0;
|
|
109
111
|
--radius: 0.5rem;
|
|
110
|
-
--card: 0 0
|
|
111
|
-
--card-foreground: 0 0
|
|
112
|
-
--popover: 0 0
|
|
113
|
-
--popover-foreground: 0 0
|
|
112
|
+
--card: 1 0 0;
|
|
113
|
+
--card-foreground: 0.1445 0 0;
|
|
114
|
+
--popover: 1 0 0;
|
|
115
|
+
--popover-foreground: 0.1445 0 0;
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
/* Dark theme (applied via class="dark" on html/body) */
|
|
117
119
|
.dark {
|
|
118
|
-
--background: 0 0
|
|
119
|
-
--foreground: 0 0
|
|
120
|
+
--background: 0 0 0;
|
|
121
|
+
--foreground: 0.9848 0 0;
|
|
120
122
|
/* ... override other variables */
|
|
121
123
|
}
|
|
122
124
|
```
|
|
123
125
|
|
|
124
|
-
Use `@vllnt/ui/themes/default.css` instead of `@vllnt/ui/styles.css` if you only
|
|
126
|
+
Use `@vllnt/ui/themes/default.css` instead of `@vllnt/ui/styles.css` if you only
|
|
127
|
+
want the variables without the Tailwind base layer.
|
|
128
|
+
|
|
129
|
+
### Runtime presets & the theme editor
|
|
130
|
+
|
|
131
|
+
Import `@vllnt/ui/themes/presets.css` and switch between built-in color presets
|
|
132
|
+
at runtime with `<ThemeSwitcher />` (or `setThemePreset` / `useThemePreset`),
|
|
133
|
+
which set `data-theme` on the document root. Render `<ThemePresetProvider />`
|
|
134
|
+
once near the root to restore the saved preset before paint.
|
|
135
|
+
|
|
136
|
+
To design and export your own theme, use the visual editor at
|
|
137
|
+
[`/themes`](https://ui.vllnt.ai/themes) — it exports a CSS block, a
|
|
138
|
+
`npx shadcn add` command, or design tokens.
|
|
125
139
|
|
|
126
140
|
## Component Patterns
|
|
127
141
|
|
|
@@ -5,8 +5,8 @@ const BorderBeam = React.forwardRef(
|
|
|
5
5
|
({
|
|
6
6
|
borderWidth = 1,
|
|
7
7
|
className,
|
|
8
|
-
colorFrom = "
|
|
9
|
-
colorTo = "
|
|
8
|
+
colorFrom = "oklch(var(--primary) / 0.85)",
|
|
9
|
+
colorTo = "oklch(var(--ring) / 0.25)",
|
|
10
10
|
delay = 0,
|
|
11
11
|
duration = 6,
|
|
12
12
|
reverse = false,
|
|
@@ -59,7 +59,7 @@ function PriceGrid({
|
|
|
59
59
|
/* @__PURE__ */ jsx(
|
|
60
60
|
"line",
|
|
61
61
|
{
|
|
62
|
-
stroke: "
|
|
62
|
+
stroke: "oklch(var(--border))",
|
|
63
63
|
strokeDasharray: "4 6",
|
|
64
64
|
strokeOpacity: "0.8",
|
|
65
65
|
x1: "0",
|
|
@@ -71,7 +71,7 @@ function PriceGrid({
|
|
|
71
71
|
/* @__PURE__ */ jsx(
|
|
72
72
|
"text",
|
|
73
73
|
{
|
|
74
|
-
fill: "
|
|
74
|
+
fill: "oklch(var(--muted-foreground))",
|
|
75
75
|
fontSize: "11",
|
|
76
76
|
textAnchor: "end",
|
|
77
77
|
x: width - 6,
|
|
@@ -127,7 +127,7 @@ function CandleMarks({
|
|
|
127
127
|
/* @__PURE__ */ jsx(
|
|
128
128
|
"text",
|
|
129
129
|
{
|
|
130
|
-
fill: "
|
|
130
|
+
fill: "oklch(var(--muted-foreground))",
|
|
131
131
|
fontSize: "11",
|
|
132
132
|
textAnchor: "middle",
|
|
133
133
|
x: centerX,
|
|
@@ -85,7 +85,7 @@ function DemoRightBar() {
|
|
|
85
85
|
]
|
|
86
86
|
}
|
|
87
87
|
),
|
|
88
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border/70 bg-background/75 p-4 shadow-[
|
|
88
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border/70 bg-background/75 p-4 shadow-[0_10px_35px_oklch(var(--foreground)/0.06)] backdrop-blur-xl", children: [
|
|
89
89
|
/* @__PURE__ */ jsx("div", { className: "text-[11px] font-medium uppercase tracking-[0.24em] text-muted-foreground", children: "Selected context" }),
|
|
90
90
|
/* @__PURE__ */ jsx("div", { className: "mt-2 text-sm font-medium text-foreground", children: "Inbox triage" }),
|
|
91
91
|
/* @__PURE__ */ jsx("div", { className: "mt-2 text-sm leading-6 text-muted-foreground", children: "Landing route keeps the assistant close to the operational queue instead of taking over the center canvas." })
|
|
@@ -111,8 +111,8 @@ function DemoBottomBar() {
|
|
|
111
111
|
) });
|
|
112
112
|
}
|
|
113
113
|
function DemoCanvasObjects() {
|
|
114
|
-
return /* @__PURE__ */ jsxs("div", { className: "relative h-[1200px] w-[1600px] overflow-hidden rounded-[28px] border border-border/12 bg-[radial-gradient(circle_at_top,
|
|
115
|
-
/* @__PURE__ */ jsxs("div", { className: "absolute left-[14%] top-[22%] w-72 rounded-[2rem] border border-border/18 bg-background/18 p-5 shadow-[
|
|
114
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative h-[1200px] w-[1600px] overflow-hidden rounded-[28px] border border-border/12 bg-[radial-gradient(circle_at_top,oklch(var(--primary)/0.07),transparent_38%),linear-gradient(180deg,oklch(var(--background)/0.18),oklch(var(--background)/0.04))]", children: [
|
|
115
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute left-[14%] top-[22%] w-72 rounded-[2rem] border border-border/18 bg-background/18 p-5 shadow-[0_22px_80px_oklch(var(--foreground)/0.05)] backdrop-blur-xl", children: [
|
|
116
116
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
117
117
|
/* @__PURE__ */ jsx("div", { className: "flex size-11 items-center justify-center rounded-2xl bg-primary/10 text-primary", children: /* @__PURE__ */ jsx(Layers3, { className: "size-5" }) }),
|
|
118
118
|
/* @__PURE__ */ jsx("div", { className: "size-2 rounded-full bg-primary/50" })
|
|
@@ -126,7 +126,7 @@ function DemoCanvasObjects() {
|
|
|
126
126
|
/* @__PURE__ */ jsx("div", { className: "h-10 rounded-[1.25rem] border border-border/18 bg-background/30" })
|
|
127
127
|
] })
|
|
128
128
|
] }),
|
|
129
|
-
/* @__PURE__ */ jsxs("div", { className: "absolute right-[15%] top-[18%] w-56 rounded-[1.75rem] border border-border/18 bg-background/14 p-4 shadow-[
|
|
129
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute right-[15%] top-[18%] w-56 rounded-[1.75rem] border border-border/18 bg-background/14 p-4 shadow-[0_18px_60px_oklch(var(--foreground)/0.04)] backdrop-blur-xl", children: [
|
|
130
130
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
131
131
|
/* @__PURE__ */ jsx("div", { className: "flex size-10 items-center justify-center rounded-2xl bg-background/60 text-foreground/70", children: /* @__PURE__ */ jsx(Activity, { className: "size-4" }) }),
|
|
132
132
|
/* @__PURE__ */ jsxs("div", { className: "flex gap-1.5", children: [
|
|
@@ -144,7 +144,7 @@ function DemoCanvasObjects() {
|
|
|
144
144
|
] })
|
|
145
145
|
] })
|
|
146
146
|
] }),
|
|
147
|
-
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-[18%] left-[22%] w-64 rounded-[1.75rem] border border-border/18 bg-background/12 p-4 shadow-[
|
|
147
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-[18%] left-[22%] w-64 rounded-[1.75rem] border border-border/18 bg-background/12 p-4 shadow-[0_18px_60px_oklch(var(--foreground)/0.04)] backdrop-blur-xl", children: [
|
|
148
148
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
149
149
|
/* @__PURE__ */ jsx("div", { className: "flex size-10 items-center justify-center rounded-2xl bg-background/55 text-foreground/70", children: /* @__PURE__ */ jsx(Sparkles, { className: "size-4" }) }),
|
|
150
150
|
/* @__PURE__ */ jsx("div", { className: "h-7 w-16 rounded-full border border-border/18 bg-background/38" })
|
|
@@ -214,14 +214,14 @@ function renderFloatingCanvasShell({
|
|
|
214
214
|
"section",
|
|
215
215
|
{
|
|
216
216
|
className: cn(
|
|
217
|
-
"relative isolate flex min-h-[720px] w-full overflow-hidden bg-[radial-gradient(circle_at_top,
|
|
217
|
+
"relative isolate flex min-h-[720px] w-full overflow-hidden bg-[radial-gradient(circle_at_top,oklch(var(--background)/0.94),oklch(var(--muted)/0.6))]",
|
|
218
218
|
className
|
|
219
219
|
),
|
|
220
220
|
ref,
|
|
221
221
|
style: mergedStyle,
|
|
222
222
|
...props,
|
|
223
223
|
children: [
|
|
224
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-[linear-gradient(180deg,
|
|
224
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-[linear-gradient(180deg,oklch(var(--background)/0.94),oklch(var(--background)/0.8))]" }),
|
|
225
225
|
/* @__PURE__ */ jsx(
|
|
226
226
|
CanvasShellChromeBefore,
|
|
227
227
|
{
|
|
@@ -15,7 +15,7 @@ const ChatDockSection = forwardRef(
|
|
|
15
15
|
"section",
|
|
16
16
|
{
|
|
17
17
|
className: cn(
|
|
18
|
-
"flex flex-col gap-4 rounded-2xl border border-border/70 bg-background/75 p-4 shadow-[
|
|
18
|
+
"flex flex-col gap-4 rounded-2xl border border-border/70 bg-background/75 p-4 shadow-[0_10px_35px_oklch(var(--foreground)/0.06)] backdrop-blur-xl",
|
|
19
19
|
className
|
|
20
20
|
),
|
|
21
21
|
ref,
|
|
@@ -90,7 +90,7 @@ function CodeBlock({
|
|
|
90
90
|
}
|
|
91
91
|
},
|
|
92
92
|
customStyle: {
|
|
93
|
-
background: "
|
|
93
|
+
background: "oklch(var(--background))",
|
|
94
94
|
fontSize: "0.875rem",
|
|
95
95
|
margin: 0,
|
|
96
96
|
minWidth: "fit-content",
|
|
@@ -107,6 +107,7 @@ function CodeBlock({
|
|
|
107
107
|
/* @__PURE__ */ jsx(
|
|
108
108
|
Button,
|
|
109
109
|
{
|
|
110
|
+
"aria-label": copied ? "Copied" : "Copy code",
|
|
110
111
|
className: "size-8",
|
|
111
112
|
onClick: handleCopy,
|
|
112
113
|
size: "icon",
|
|
@@ -6,7 +6,7 @@ const GlassPanel = forwardRef(
|
|
|
6
6
|
"div",
|
|
7
7
|
{
|
|
8
8
|
className: cn(
|
|
9
|
-
"rounded-2xl border border-border/60 bg-background/70 shadow-[
|
|
9
|
+
"rounded-2xl border border-border/60 bg-background/70 shadow-[0_12px_40px_oklch(var(--foreground)/0.08)] backdrop-blur-xl",
|
|
10
10
|
className
|
|
11
11
|
),
|
|
12
12
|
ref,
|
package/dist/components/index.js
CHANGED
|
@@ -325,6 +325,7 @@ import {
|
|
|
325
325
|
useAgentStepStatus
|
|
326
326
|
} from "./agent-activity";
|
|
327
327
|
import { StatCard, statCardVariants } from "./stat-card";
|
|
328
|
+
import { StaticCode } from "./static-code";
|
|
328
329
|
import {
|
|
329
330
|
dotVariants,
|
|
330
331
|
StatusIndicator,
|
|
@@ -467,7 +468,9 @@ import {
|
|
|
467
468
|
} from "./share-section";
|
|
468
469
|
import { SearchDialog } from "./search-dialog";
|
|
469
470
|
import { LangProvider } from "./lang-provider";
|
|
471
|
+
import { ThemePresetProvider } from "./theme-preset-provider";
|
|
470
472
|
import { ThemeProvider } from "./theme-provider";
|
|
473
|
+
import { ThemeSwitcher } from "./theme-switcher";
|
|
471
474
|
import { ThemeToggle } from "./theme-toggle";
|
|
472
475
|
import {
|
|
473
476
|
CandlestickChart
|
|
@@ -1263,6 +1266,7 @@ export {
|
|
|
1263
1266
|
Spinner,
|
|
1264
1267
|
StatCard,
|
|
1265
1268
|
StateBadgeOverlay,
|
|
1269
|
+
StaticCode,
|
|
1266
1270
|
StatusBoard,
|
|
1267
1271
|
StatusIndicator,
|
|
1268
1272
|
Step,
|
|
@@ -1293,7 +1297,9 @@ export {
|
|
|
1293
1297
|
TagsInput,
|
|
1294
1298
|
Terminal,
|
|
1295
1299
|
Textarea,
|
|
1300
|
+
ThemePresetProvider,
|
|
1296
1301
|
ThemeProvider,
|
|
1302
|
+
ThemeSwitcher,
|
|
1297
1303
|
ThemeToggle,
|
|
1298
1304
|
ThinkingBlock,
|
|
1299
1305
|
ThreadBubble,
|
|
@@ -25,13 +25,13 @@ const buildBackground = (input) => {
|
|
|
25
25
|
const pos = `${input.translate.x}px ${input.translate.y}px`;
|
|
26
26
|
if (input.pattern === "grid") {
|
|
27
27
|
return {
|
|
28
|
-
backgroundImage: "linear-gradient(to right,
|
|
28
|
+
backgroundImage: "linear-gradient(to right, oklch(var(--border)) 1px, transparent 1px), linear-gradient(to bottom, oklch(var(--border)) 1px, transparent 1px)",
|
|
29
29
|
backgroundPosition: pos,
|
|
30
30
|
backgroundSize: `${size}px ${size}px`
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
return {
|
|
34
|
-
backgroundImage: "radial-gradient(circle,
|
|
34
|
+
backgroundImage: "radial-gradient(circle, oklch(var(--border)) 1px, transparent 1px)",
|
|
35
35
|
backgroundPosition: pos,
|
|
36
36
|
backgroundSize: `${size}px ${size}px`
|
|
37
37
|
};
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import { cva } from "class-variance-authority";
|
|
8
8
|
import { cn } from "../../lib/utils";
|
|
9
9
|
const kbdVariants = cva(
|
|
10
|
-
"inline-flex select-none items-center justify-center rounded border border-border bg-muted font-mono font-medium text-foreground shadow-[
|
|
10
|
+
"inline-flex select-none items-center justify-center rounded border border-border bg-muted font-mono font-medium text-foreground shadow-[0_1px_0_0_oklch(var(--border))] [&>svg]:h-3 [&>svg]:w-3",
|
|
11
11
|
{
|
|
12
12
|
defaultVariants: {
|
|
13
13
|
size: "md"
|
|
@@ -4,6 +4,7 @@ import * as runtime from "react/jsx-runtime";
|
|
|
4
4
|
import ReactMarkdown from "react-markdown";
|
|
5
5
|
import remarkGfm from "remark-gfm";
|
|
6
6
|
import { CodeBlock } from "../code-block/code-block";
|
|
7
|
+
import { StaticCode } from "../static-code/static-code";
|
|
7
8
|
const MDXComponents = {
|
|
8
9
|
a: ({ children, href, ...props }) => /* @__PURE__ */ jsx(
|
|
9
10
|
"a",
|
|
@@ -26,7 +27,7 @@ const MDXComponents = {
|
|
|
26
27
|
if (typeof className === "string" && className.startsWith("language-")) {
|
|
27
28
|
const language = className.replace(/^language-/, "");
|
|
28
29
|
const text = typeof children === "string" ? children.replace(/\n$/, "") : String(children ?? "");
|
|
29
|
-
return /* @__PURE__ */ jsx(
|
|
30
|
+
return /* @__PURE__ */ jsx(StaticCode, { code: text, language });
|
|
30
31
|
}
|
|
31
32
|
return /* @__PURE__ */ jsx(
|
|
32
33
|
"code",
|
|
@@ -94,14 +94,14 @@ const ObjectCard = forwardRef(
|
|
|
94
94
|
"article",
|
|
95
95
|
{
|
|
96
96
|
className: cn(
|
|
97
|
-
"group relative flex min-w-[320px] max-w-[420px] flex-col gap-4 rounded-[1.5rem] border border-border/70 bg-[linear-gradient(180deg,
|
|
97
|
+
"group relative flex min-w-[320px] max-w-[420px] flex-col gap-4 rounded-[1.5rem] border border-border/70 bg-[linear-gradient(180deg,oklch(var(--background)),oklch(var(--muted)/0.22))] p-5 shadow-[0_24px_80px_oklch(var(--foreground)/0.08)] transition-transform duration-200 hover:-translate-y-0.5",
|
|
98
98
|
className
|
|
99
99
|
),
|
|
100
100
|
"data-state": state,
|
|
101
101
|
ref,
|
|
102
102
|
...props,
|
|
103
103
|
children: [
|
|
104
|
-
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-5 top-0 h-px bg-[linear-gradient(90deg,transparent,
|
|
104
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-5 top-0 h-px bg-[linear-gradient(90deg,transparent,oklch(var(--foreground)/0.22),transparent)]" }),
|
|
105
105
|
/* @__PURE__ */ jsx(
|
|
106
106
|
ObjectCardHeader,
|
|
107
107
|
{
|
|
@@ -28,7 +28,7 @@ const OverviewCard = forwardRef(
|
|
|
28
28
|
"section",
|
|
29
29
|
{
|
|
30
30
|
className: cn(
|
|
31
|
-
"flex min-h-[172px] flex-col gap-4 rounded-2xl border p-5 shadow-[
|
|
31
|
+
"flex min-h-[172px] flex-col gap-4 rounded-2xl border p-5 shadow-[0_8px_30px_oklch(var(--foreground)/0.06)] backdrop-blur-xl",
|
|
32
32
|
toneClassNames[tone],
|
|
33
33
|
className
|
|
34
34
|
),
|
|
@@ -12,6 +12,7 @@ function SidebarToggle({
|
|
|
12
12
|
/* @__PURE__ */ jsx(
|
|
13
13
|
Button,
|
|
14
14
|
{
|
|
15
|
+
"aria-label": open ? "Close menu" : "Open menu",
|
|
15
16
|
className: cn("lg:hidden", className),
|
|
16
17
|
onClick: onToggle,
|
|
17
18
|
size: "icon",
|
|
@@ -22,6 +23,7 @@ function SidebarToggle({
|
|
|
22
23
|
/* @__PURE__ */ jsx(
|
|
23
24
|
Button,
|
|
24
25
|
{
|
|
26
|
+
"aria-label": "Toggle sidebar",
|
|
25
27
|
className: cn("hidden lg:flex", className),
|
|
26
28
|
onClick: onToggle,
|
|
27
29
|
size: "icon",
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Check, Copy } from "lucide-react";
|
|
5
|
+
import { Button } from "../button/button";
|
|
6
|
+
function StaticCodeCopy({ value }) {
|
|
7
|
+
const [copied, setCopied] = useState(false);
|
|
8
|
+
const handleCopy = async () => {
|
|
9
|
+
await navigator.clipboard.writeText(value);
|
|
10
|
+
setCopied(true);
|
|
11
|
+
setTimeout(() => {
|
|
12
|
+
setCopied(false);
|
|
13
|
+
}, 2e3);
|
|
14
|
+
};
|
|
15
|
+
return /* @__PURE__ */ jsx(
|
|
16
|
+
Button,
|
|
17
|
+
{
|
|
18
|
+
"aria-label": copied ? "Copied" : "Copy code",
|
|
19
|
+
className: "absolute right-2 top-2 size-8",
|
|
20
|
+
onClick: handleCopy,
|
|
21
|
+
size: "icon",
|
|
22
|
+
variant: "ghost",
|
|
23
|
+
children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-3" }) : /* @__PURE__ */ jsx(Copy, { className: "size-3" })
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
StaticCodeCopy
|
|
29
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
|
3
|
+
import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism";
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
import { StaticCodeCopy } from "./static-code-copy";
|
|
6
|
+
function StaticCode({
|
|
7
|
+
className,
|
|
8
|
+
code,
|
|
9
|
+
language = "tsx"
|
|
10
|
+
}) {
|
|
11
|
+
return /* @__PURE__ */ jsxs(
|
|
12
|
+
"div",
|
|
13
|
+
{
|
|
14
|
+
className: cn(
|
|
15
|
+
"group relative overflow-x-auto rounded-lg border border-border bg-[#282c34]",
|
|
16
|
+
className
|
|
17
|
+
),
|
|
18
|
+
children: [
|
|
19
|
+
/* @__PURE__ */ jsx(
|
|
20
|
+
SyntaxHighlighter,
|
|
21
|
+
{
|
|
22
|
+
customStyle: {
|
|
23
|
+
background: "transparent",
|
|
24
|
+
fontSize: "0.875rem",
|
|
25
|
+
margin: 0,
|
|
26
|
+
padding: "1rem"
|
|
27
|
+
},
|
|
28
|
+
language,
|
|
29
|
+
PreTag: "div",
|
|
30
|
+
style: oneDark,
|
|
31
|
+
children: code
|
|
32
|
+
}
|
|
33
|
+
),
|
|
34
|
+
/* @__PURE__ */ jsx(StaticCodeCopy, { value: code })
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
StaticCode
|
|
41
|
+
};
|
|
@@ -59,6 +59,7 @@ function Terminal({
|
|
|
59
59
|
copyable && commands.length > 0 ? /* @__PURE__ */ jsx(
|
|
60
60
|
Button,
|
|
61
61
|
{
|
|
62
|
+
"aria-label": copied ? "Copied" : "Copy commands",
|
|
62
63
|
className: "absolute top-2 right-2 size-8 bg-zinc-800 hover:bg-zinc-700 text-zinc-300",
|
|
63
64
|
onClick: handleCopy,
|
|
64
65
|
size: "icon",
|
|
@@ -125,6 +126,7 @@ function SimpleTerminal({
|
|
|
125
126
|
commands.length > 0 && /* @__PURE__ */ jsx(
|
|
126
127
|
Button,
|
|
127
128
|
{
|
|
129
|
+
"aria-label": copied ? "Copied" : "Copy commands",
|
|
128
130
|
className: "absolute top-2 right-2 size-8 bg-zinc-800 hover:bg-zinc-700 text-zinc-300",
|
|
129
131
|
onClick: handleCopy,
|
|
130
132
|
size: "icon",
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect } from "react";
|
|
4
|
+
import {
|
|
5
|
+
CUSTOM_THEME_NAME,
|
|
6
|
+
DEFAULT_THEME_PRESET,
|
|
7
|
+
isThemePresetName,
|
|
8
|
+
THEME_CUSTOM_CSS_STORAGE_KEY,
|
|
9
|
+
THEME_CUSTOM_STYLE_ID,
|
|
10
|
+
THEME_PRESET_STORAGE_KEY
|
|
11
|
+
} from "../../lib/theme-presets";
|
|
12
|
+
import { setThemePreset } from "../../lib/use-theme-preset";
|
|
13
|
+
const FOUC_SCRIPT = `(function(){try{var v=localStorage.getItem(${JSON.stringify(
|
|
14
|
+
THEME_PRESET_STORAGE_KEY
|
|
15
|
+
)});if(!v||v===${JSON.stringify(
|
|
16
|
+
DEFAULT_THEME_PRESET
|
|
17
|
+
)})return;document.documentElement.setAttribute("data-theme",v);if(v===${JSON.stringify(
|
|
18
|
+
CUSTOM_THEME_NAME
|
|
19
|
+
)}){var c=localStorage.getItem(${JSON.stringify(
|
|
20
|
+
THEME_CUSTOM_CSS_STORAGE_KEY
|
|
21
|
+
)});if(c){var s=document.createElement("style");s.id=${JSON.stringify(
|
|
22
|
+
THEME_CUSTOM_STYLE_ID
|
|
23
|
+
)};s.textContent=c;document.head.appendChild(s);}}}catch(e){}})();`;
|
|
24
|
+
function ThemePresetProvider({
|
|
25
|
+
children,
|
|
26
|
+
defaultPreset
|
|
27
|
+
}) {
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!defaultPreset || defaultPreset === DEFAULT_THEME_PRESET) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
let stored = null;
|
|
33
|
+
try {
|
|
34
|
+
stored = window.localStorage.getItem(THEME_PRESET_STORAGE_KEY);
|
|
35
|
+
} catch {
|
|
36
|
+
stored = null;
|
|
37
|
+
}
|
|
38
|
+
if (!stored && isThemePresetName(defaultPreset)) {
|
|
39
|
+
setThemePreset(defaultPreset);
|
|
40
|
+
}
|
|
41
|
+
}, [defaultPreset]);
|
|
42
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
43
|
+
/* @__PURE__ */ jsx(
|
|
44
|
+
"script",
|
|
45
|
+
{
|
|
46
|
+
dangerouslySetInnerHTML: { __html: FOUC_SCRIPT },
|
|
47
|
+
suppressHydrationWarning: true
|
|
48
|
+
}
|
|
49
|
+
),
|
|
50
|
+
children
|
|
51
|
+
] });
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
ThemePresetProvider
|
|
55
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useMounted } from "../../lib/use-mounted";
|
|
4
|
+
import { useThemePreset } from "../../lib/use-theme-preset";
|
|
5
|
+
import { cn } from "../../lib/utils";
|
|
6
|
+
function ThemeSwitcher({ className }) {
|
|
7
|
+
const mounted = useMounted();
|
|
8
|
+
const { preset, presets, setPreset } = useThemePreset();
|
|
9
|
+
return /* @__PURE__ */ jsx(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
"aria-label": "Theme preset",
|
|
13
|
+
className: cn("flex items-center gap-1.5", className),
|
|
14
|
+
role: "radiogroup",
|
|
15
|
+
children: presets.map((item) => {
|
|
16
|
+
const active = mounted && preset === item.name;
|
|
17
|
+
return /* @__PURE__ */ jsx(
|
|
18
|
+
"button",
|
|
19
|
+
{
|
|
20
|
+
"aria-checked": active,
|
|
21
|
+
"aria-label": item.label,
|
|
22
|
+
className: cn(
|
|
23
|
+
"size-6 rounded-full border transition-transform hover:scale-110",
|
|
24
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
25
|
+
active ? "border-foreground ring-2 ring-ring ring-offset-2 ring-offset-background" : "border-border"
|
|
26
|
+
),
|
|
27
|
+
onClick: () => {
|
|
28
|
+
setPreset(item.name);
|
|
29
|
+
},
|
|
30
|
+
role: "radio",
|
|
31
|
+
style: { backgroundColor: item.swatch },
|
|
32
|
+
title: item.label,
|
|
33
|
+
type: "button"
|
|
34
|
+
},
|
|
35
|
+
item.name
|
|
36
|
+
);
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
ThemeSwitcher
|
|
43
|
+
};
|
|
@@ -51,7 +51,9 @@ const RowBody = (props) => {
|
|
|
51
51
|
{
|
|
52
52
|
"aria-hidden": "true",
|
|
53
53
|
className: "size-1.5 rounded-full",
|
|
54
|
-
style: {
|
|
54
|
+
style: {
|
|
55
|
+
backgroundColor: bookmark.color ?? "oklch(var(--foreground))"
|
|
56
|
+
}
|
|
55
57
|
}
|
|
56
58
|
),
|
|
57
59
|
/* @__PURE__ */ jsxs("span", { className: "flex flex-1 flex-col text-left", children: [
|