@vllnt/ui 0.2.1-canary.61cce77 → 0.2.1-canary.63297c5

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.
Files changed (83) hide show
  1. package/README.md +38 -24
  2. package/dist/components/activity-log/activity-log.js +1 -1
  3. package/dist/components/ai-chat-input/ai-chat-input.js +1 -1
  4. package/dist/components/ai-message-bubble/ai-message-bubble.js +1 -1
  5. package/dist/components/ai-tool-call-display/ai-tool-call-display.js +1 -1
  6. package/dist/components/animated-text/animated-text.js +6 -3
  7. package/dist/components/annotation/annotation.js +1 -1
  8. package/dist/components/avatar-group/avatar-group.js +1 -1
  9. package/dist/components/blog-card/blog-card.js +1 -1
  10. package/dist/components/border-beam/border-beam.js +2 -2
  11. package/dist/components/candlestick-chart/candlestick-chart.js +3 -3
  12. package/dist/components/canvas-shell/canvas-foundation-demo.js +6 -6
  13. package/dist/components/canvas-shell/canvas-shell.js +2 -2
  14. package/dist/components/category-filter/category-filter.js +1 -1
  15. package/dist/components/chat-dock-section/chat-dock-section.js +2 -2
  16. package/dist/components/chronological-timeline/chronological-timeline.js +36 -31
  17. package/dist/components/code-block/code-block.js +31 -10
  18. package/dist/components/code-playground/code-playground.js +2 -1
  19. package/dist/components/combobox/combobox.js +1 -6
  20. package/dist/components/completion-dialog/completion-dialog.js +1 -1
  21. package/dist/components/connector-edge/connector-edge.js +1 -1
  22. package/dist/components/content-intro/content-intro.js +1 -1
  23. package/dist/components/conversation-thread/conversation-thread.js +1 -1
  24. package/dist/components/countdown-timer/countdown-timer.js +1 -1
  25. package/dist/components/data-table/data-table.js +1 -1
  26. package/dist/components/date-picker/date-picker.js +1 -6
  27. package/dist/components/exercise/exercise.js +1 -1
  28. package/dist/components/file-upload/file-upload.js +1 -6
  29. package/dist/components/filter-bar/filter-bar.js +1 -1
  30. package/dist/components/flashcard/flashcard.js +1 -1
  31. package/dist/components/form/form.js +1 -1
  32. package/dist/components/glass-panel/glass-panel.js +1 -1
  33. package/dist/components/index.js +6 -0
  34. package/dist/components/infinite-plane/infinite-plane.js +2 -2
  35. package/dist/components/inline-input/inline-input.js +1 -1
  36. package/dist/components/kbd/kbd.js +1 -1
  37. package/dist/components/lang-provider/lang-provider.js +3 -3
  38. package/dist/components/live-feed/live-feed.js +1 -1
  39. package/dist/components/mdx-content/mdx-content.js +2 -1
  40. package/dist/components/metric-gauge/metric-gauge.js +1 -1
  41. package/dist/components/model-selector/model-selector.js +1 -1
  42. package/dist/components/multi-select/multi-select.js +1 -1
  43. package/dist/components/navbar-saas/navbar-saas.js +5 -6
  44. package/dist/components/number-input/number-input.js +1 -1
  45. package/dist/components/object-card/object-card.js +3 -3
  46. package/dist/components/overview-board/overview-board.js +2 -2
  47. package/dist/components/progress-card/progress-card.js +1 -1
  48. package/dist/components/progress-tracker/progress-tracker.js +5 -3
  49. package/dist/components/scope-selector/scope-selector.js +1 -1
  50. package/dist/components/search-dialog/search-dialog.js +1 -1
  51. package/dist/components/sidebar/sidebar.js +11 -7
  52. package/dist/components/sidebar-toggle/sidebar-toggle.js +3 -1
  53. package/dist/components/slideshow/slideshow.js +1 -1
  54. package/dist/components/spinner/unicode-spinner.js +4 -2
  55. package/dist/components/stat-card/stat-card.js +1 -1
  56. package/dist/components/static-code/index.js +4 -0
  57. package/dist/components/static-code/static-code-copy.js +29 -0
  58. package/dist/components/static-code/static-code.js +41 -0
  59. package/dist/components/status-board/status-board.js +1 -1
  60. package/dist/components/terminal/terminal.js +3 -1
  61. package/dist/components/theme-preset-provider/index.js +4 -0
  62. package/dist/components/theme-preset-provider/theme-preset-provider.js +55 -0
  63. package/dist/components/theme-switcher/index.js +4 -0
  64. package/dist/components/theme-switcher/theme-switcher.js +43 -0
  65. package/dist/components/ticker-tape/ticker-tape.js +1 -1
  66. package/dist/components/tour/tour.js +1 -1
  67. package/dist/components/tutorial-card/tutorial-card.js +1 -1
  68. package/dist/components/tutorial-complete/tutorial-complete.js +1 -1
  69. package/dist/components/tutorial-filters/tutorial-filters.js +1 -1
  70. package/dist/components/tutorial-mdx/tutorial-mdx.js +1 -1
  71. package/dist/components/usage-breakdown/usage-breakdown.js +1 -1
  72. package/dist/components/viewport-bookmarks/viewport-bookmarks.js +3 -1
  73. package/dist/components/world-clock-bar/world-clock-bar.js +1 -1
  74. package/dist/components/zoom-hud/zoom-hud.js +1 -1
  75. package/dist/index.d.ts +89 -1
  76. package/dist/index.js +19 -1
  77. package/dist/lib/theme-presets.js +32 -0
  78. package/dist/lib/use-theme-preset.js +94 -0
  79. package/dist/tailwind-preset.js +19 -19
  80. package/package.json +3 -2
  81. package/styles.css +38 -38
  82. package/themes/default.css +39 -39
  83. 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 `hsl(var(--name))` for theming
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 use HSL CSS variables. Override them after importing styles:
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% 100%;
95
- --foreground: 0 0% 3.9%;
96
- --primary: 222.2 47.4% 11.2%;
97
- --primary-foreground: 210 40% 98%;
98
- --secondary: 210 40% 96.1%;
99
- --secondary-foreground: 222.2 47.4% 11.2%;
100
- --muted: 210 40% 96.1%;
101
- --muted-foreground: 215.4 16.3% 46.9%;
102
- --accent: 210 40% 96.1%;
103
- --accent-foreground: 222.2 47.4% 11.2%;
104
- --destructive: 0 84.2% 60.2%;
105
- --destructive-foreground: 0 0% 98%;
106
- --border: 214.3 31.8% 91.4%;
107
- --input: 214.3 31.8% 91.4%;
108
- --ring: 222.2 84% 4.9%;
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% 100%;
111
- --card-foreground: 0 0% 3.9%;
112
- --popover: 0 0% 100%;
113
- --popover-foreground: 0 0% 3.9%;
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% 3.9%;
119
- --foreground: 0 0% 98%;
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 want the variables without Tailwind base layer styles.
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
 
@@ -3,7 +3,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { forwardRef, useMemo, useState } from "react";
4
4
  import { ArrowRight, ChevronLeft, ChevronRight } from "lucide-react";
5
5
  import { cn } from "../../lib/utils";
6
- import { Avatar, AvatarFallback } from "../avatar";
6
+ import { Avatar, AvatarFallback } from "../avatar/avatar";
7
7
  import { Badge } from "../badge";
8
8
  import { Button } from "../button";
9
9
  import {
@@ -3,7 +3,7 @@ import { forwardRef } from "react";
3
3
  import { cva } from "class-variance-authority";
4
4
  import { LoaderCircle, SendHorizontal } from "lucide-react";
5
5
  import { cn } from "../../lib/utils";
6
- import { Button } from "../button";
6
+ import { Button } from "../button/button";
7
7
  import { Textarea } from "../textarea";
8
8
  const formShellVariants = cva(
9
9
  "rounded-2xl border border-border/70 bg-background shadow-sm"
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
3
  import { cva } from "class-variance-authority";
4
4
  import { cn } from "../../lib/utils";
5
- import { Avatar, AvatarFallback } from "../avatar";
5
+ import { Avatar, AvatarFallback } from "../avatar/avatar";
6
6
  import { Badge } from "../badge";
7
7
  const bubbleVariants = cva(
8
8
  "rounded-2xl border px-4 py-3 shadow-sm transition-colors",
@@ -3,7 +3,7 @@ import { forwardRef } from "react";
3
3
  import { cva } from "class-variance-authority";
4
4
  import { AlertCircle, CheckCircle2, Clock3, Wrench } from "lucide-react";
5
5
  import { cn } from "../../lib/utils";
6
- import { Badge } from "../badge";
6
+ import { Badge } from "../badge/badge";
7
7
  const statusVariants = cva(
8
8
  "rounded-full px-2 py-0 text-[10px] uppercase tracking-wide",
9
9
  {
@@ -87,13 +87,16 @@ function buildRevealPlan(direction, length, randomness) {
87
87
  return revealPlan;
88
88
  }
89
89
  function useRevealProgress(active, length, stagger) {
90
- const [progress, setProgress] = React.useState(0);
90
+ const [progress, setProgress] = React.useState(() => active ? 0 : length);
91
+ const [revealKey, setRevealKey] = React.useState({ active, length, stagger });
92
+ if (revealKey.active !== active || revealKey.length !== length || revealKey.stagger !== stagger) {
93
+ setRevealKey({ active, length, stagger });
94
+ setProgress(active ? 0 : length);
95
+ }
91
96
  React.useEffect(() => {
92
97
  if (!active) {
93
- setProgress(length);
94
98
  return;
95
99
  }
96
- setProgress(0);
97
100
  const revealInterval = window.setInterval(
98
101
  () => {
99
102
  setProgress((current) => {
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { cn } from "../../lib/utils";
4
- import { Popover, PopoverContent, PopoverTrigger } from "../popover";
4
+ import { Popover, PopoverContent, PopoverTrigger } from "../popover/popover";
5
5
  const toneClasses = {
6
6
  amber: "bg-amber-500/20 text-amber-950 dark:text-amber-100",
7
7
  emerald: "bg-emerald-500/20 text-emerald-950 dark:text-emerald-100",
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { cva } from "class-variance-authority";
4
4
  import { cn } from "../../lib/utils";
5
- import { Avatar, AvatarFallback, AvatarImage } from "../avatar";
5
+ import { Avatar, AvatarFallback, AvatarImage } from "../avatar/avatar";
6
6
  const avatarGroupVariants = cva("flex items-center", {
7
7
  defaultVariants: {
8
8
  size: "md"
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import Link from "next/link";
3
- import { Badge } from "../badge";
3
+ import { Badge } from "../badge/badge";
4
4
  import {
5
5
  Card,
6
6
  CardContent,
@@ -5,8 +5,8 @@ const BorderBeam = React.forwardRef(
5
5
  ({
6
6
  borderWidth = 1,
7
7
  className,
8
- colorFrom = "hsl(var(--primary) / 0.85)",
9
- colorTo = "hsl(var(--ring) / 0.25)",
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: "hsl(var(--border))",
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: "hsl(var(--muted-foreground))",
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: "hsl(var(--muted-foreground))",
130
+ fill: "oklch(var(--muted-foreground))",
131
131
  fontSize: "11",
132
132
  textAnchor: "middle",
133
133
  x: centerX,
@@ -1,6 +1,6 @@
1
1
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Activity, Bot, Compass, Layers3, Sparkles } from "lucide-react";
3
- import { BottomBar } from "../bottom-bar";
3
+ import { BottomBar } from "../bottom-bar/bottom-bar";
4
4
  import { Button } from "../button";
5
5
  import { CanvasView } from "../canvas-view";
6
6
  import { ChatDockSection } from "../chat-dock-section";
@@ -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-[0_10px_35px_hsl(var(--foreground)/0.06)] backdrop-blur-xl", children: [
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,hsl(var(--primary)/0.07),transparent_38%),linear-gradient(180deg,hsl(var(--background)/0.18),hsl(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_hsl(var(--foreground)/0.05)] backdrop-blur-xl", children: [
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-[0_18px_60px_hsl(var(--foreground)/0.04)] backdrop-blur-xl", children: [
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-[0_18px_60px_hsl(var(--foreground)/0.04)] backdrop-blur-xl", children: [
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,hsl(var(--background)/0.94),hsl(var(--muted)/0.6))]",
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,hsl(var(--background)/0.94),hsl(var(--background)/0.8))]" }),
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
  {
@@ -2,7 +2,7 @@
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import Link from "next/link";
4
4
  import { usePathname } from "next/navigation";
5
- import { Badge } from "../badge";
5
+ import { Badge } from "../badge/badge";
6
6
  function slugify(text) {
7
7
  return text.toLowerCase().normalize("NFD").replaceAll(/[\u0300-\u036F]/g, "").replaceAll(/[^\s\w-]/g, "").trim().replaceAll(/\s+/g, "-").replaceAll(/-+/g, "-").replaceAll(/^-+|-+$/g, "");
8
8
  }
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
3
  import { ArrowUpRight, MessageSquareText } from "lucide-react";
4
4
  import { cn } from "../../lib/utils";
5
- import { Button } from "../button";
5
+ import { Button } from "../button/button";
6
6
  const ChatDockSection = forwardRef(
7
7
  ({
8
8
  className,
@@ -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-[0_10px_35px_hsl(var(--foreground)/0.06)] backdrop-blur-xl",
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,
@@ -171,37 +171,42 @@ const ChronoEvent = forwardRef(
171
171
  const handleFocusEvent = useCallback(() => {
172
172
  setActiveId(eventId);
173
173
  }, [eventId, setActiveId]);
174
- return /* @__PURE__ */ jsxs(
175
- "article",
176
- {
177
- "aria-labelledby": `${eventId}-title`,
178
- className: cn(
179
- "group relative grid gap-4 py-6 md:grid-cols-[1fr_auto_1fr] md:gap-8",
180
- className
181
- ),
182
- "data-event-id": eventId,
183
- "data-featured": featured ? "true" : void 0,
184
- id: eventId,
185
- onFocus: handleFocusEvent,
186
- ref: refCallback,
187
- ...rest,
188
- children: [
189
- /* @__PURE__ */ jsx(DateColumn, { date }),
190
- /* @__PURE__ */ jsx(RailColumn, { featured }),
191
- /* @__PURE__ */ jsx(
192
- EventCard,
193
- {
194
- date,
195
- eventId,
196
- featured,
197
- media,
198
- subtitle,
199
- title,
200
- children
201
- }
202
- )
203
- ]
204
- }
174
+ return (
175
+ /* Passive focus tracking: the container observes focus bubbling from
176
+ its interactive children to drive the scroll-spy active state. */
177
+ // eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
178
+ /* @__PURE__ */ jsxs(
179
+ "article",
180
+ {
181
+ "aria-labelledby": `${eventId}-title`,
182
+ className: cn(
183
+ "group relative grid gap-4 py-6 md:grid-cols-[1fr_auto_1fr] md:gap-8",
184
+ className
185
+ ),
186
+ "data-event-id": eventId,
187
+ "data-featured": featured ? "true" : void 0,
188
+ id: eventId,
189
+ onFocus: handleFocusEvent,
190
+ ref: refCallback,
191
+ ...rest,
192
+ children: [
193
+ /* @__PURE__ */ jsx(DateColumn, { date }),
194
+ /* @__PURE__ */ jsx(RailColumn, { featured }),
195
+ /* @__PURE__ */ jsx(
196
+ EventCard,
197
+ {
198
+ date,
199
+ eventId,
200
+ featured,
201
+ media,
202
+ subtitle,
203
+ title,
204
+ children
205
+ }
206
+ )
207
+ ]
208
+ }
209
+ )
205
210
  );
206
211
  }
207
212
  );
@@ -1,13 +1,12 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useEffect, useRef, useState } from "react";
3
+ import {
4
+ useEffect,
5
+ useRef,
6
+ useState
7
+ } from "react";
4
8
  import { Check, Copy } from "lucide-react";
5
9
  import { useTheme } from "next-themes";
6
- import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
7
- import {
8
- oneDark,
9
- oneLight
10
- } from "react-syntax-highlighter/dist/esm/styles/prism";
11
10
  import { cn } from "../../lib/utils";
12
11
  import { Button } from "../button/button";
13
12
  function extractTextFromChildren(children) {
@@ -37,12 +36,31 @@ function CodeBlock({
37
36
  showLanguage = false
38
37
  }) {
39
38
  const [copied, setCopied] = useState(false);
39
+ const [highlighter, setHighlighter] = useState(
40
+ null
41
+ );
40
42
  const { systemTheme, theme } = useTheme();
41
43
  const resolvedTheme = theme === "system" ? systemTheme : theme;
42
44
  const isDark = resolvedTheme !== "light";
43
- const codeStyle = isDark ? oneDark : oneLight;
44
45
  const code = extractTextFromChildren(children);
45
46
  const scrollRef = useRef(null);
47
+ useEffect(() => {
48
+ let active = true;
49
+ void Promise.all([
50
+ import("react-syntax-highlighter"),
51
+ import("react-syntax-highlighter/dist/esm/styles/prism")
52
+ ]).then(([module_, styles]) => {
53
+ if (!active) return;
54
+ setHighlighter({
55
+ oneDark: styles.oneDark,
56
+ oneLight: styles.oneLight,
57
+ SyntaxHighlighter: module_.Prism
58
+ });
59
+ });
60
+ return () => {
61
+ active = false;
62
+ };
63
+ }, []);
46
64
  useEffect(() => {
47
65
  const element = scrollRef.current;
48
66
  if (!element) return;
@@ -66,6 +84,8 @@ function CodeBlock({
66
84
  setCopied(false);
67
85
  }, 2e3);
68
86
  };
87
+ const SyntaxHighlighter = highlighter?.SyntaxHighlighter;
88
+ const codeStyle = isDark ? highlighter?.oneDark : highlighter?.oneLight;
69
89
  return /* @__PURE__ */ jsx(
70
90
  "div",
71
91
  {
@@ -79,7 +99,7 @@ function CodeBlock({
79
99
  className: "relative overflow-x-auto overflow-y-hidden touch-pan-y",
80
100
  ref: scrollRef,
81
101
  children: [
82
- /* @__PURE__ */ jsx(
102
+ SyntaxHighlighter ? /* @__PURE__ */ jsx(
83
103
  SyntaxHighlighter,
84
104
  {
85
105
  codeTagProps: {
@@ -90,7 +110,7 @@ function CodeBlock({
90
110
  }
91
111
  },
92
112
  customStyle: {
93
- background: "hsl(var(--background))",
113
+ background: "oklch(var(--background))",
94
114
  fontSize: "0.875rem",
95
115
  margin: 0,
96
116
  minWidth: "fit-content",
@@ -101,12 +121,13 @@ function CodeBlock({
101
121
  style: codeStyle,
102
122
  children: code
103
123
  }
104
- ),
124
+ ) : /* @__PURE__ */ jsx("pre", { className: "m-0 min-w-fit overflow-y-hidden p-4 font-mono text-sm", children: /* @__PURE__ */ jsx("code", { className: "block bg-transparent", children: code }) }),
105
125
  /* @__PURE__ */ jsxs("div", { className: "absolute right-2 top-2 flex items-center gap-2", children: [
106
126
  showLanguage ? /* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-muted-foreground uppercase tracking-wider", children: language }) : null,
107
127
  /* @__PURE__ */ jsx(
108
128
  Button,
109
129
  {
130
+ "aria-label": copied ? "Copied" : "Copy code",
110
131
  className: "size-8",
111
132
  onClick: handleCopy,
112
133
  size: "icon",
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { Check, Code, Copy, FileCode } from "lucide-react";
5
5
  import { cn } from "../../lib/utils";
6
- import { Button } from "../button";
6
+ import { Button } from "../button/button";
7
7
  function CodeLine({ highlightLines, line, lineNumber }) {
8
8
  const isHighlighted = highlightLines.includes(lineNumber);
9
9
  return /* @__PURE__ */ jsxs("div", { className: cn("flex", isHighlighted && "bg-primary/10 -mx-4 px-4"), children: [
@@ -49,6 +49,7 @@ function CodePlayground({
49
49
  /* @__PURE__ */ jsx(
50
50
  Button,
51
51
  {
52
+ "aria-label": copied ? "Copied" : "Copy code",
52
53
  className: "size-8",
53
54
  onClick: handleCopy,
54
55
  size: "icon",
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { Check, ChevronsUpDown } from "lucide-react";
5
5
  import { cn } from "../../lib/utils";
6
- import { Button } from "../button";
6
+ import { Button } from "../button/button";
7
7
  import {
8
8
  Command,
9
9
  CommandEmpty,
@@ -15,11 +15,6 @@ import {
15
15
  import { Popover, PopoverContent, PopoverTrigger } from "../popover";
16
16
  function useComboboxValue(value, onValueChange) {
17
17
  const [internalValue, setInternalValue] = React.useState(value ?? "");
18
- React.useEffect(() => {
19
- if (value !== void 0) {
20
- setInternalValue(value);
21
- }
22
- }, [value]);
23
18
  const resolvedValue = value ?? internalValue;
24
19
  const setResolvedValue = (nextValue) => {
25
20
  if (value === void 0) {
@@ -2,7 +2,7 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { memo, useEffect, useRef } from "react";
4
4
  import { cn } from "../../lib/utils";
5
- import { Button } from "../button";
5
+ import { Button } from "../button/button";
6
6
  function DialogContent({
7
7
  as: Heading = "h2",
8
8
  cancelLabel = "Skip",
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef } from "react";
3
3
  import { cn } from "../../lib/utils";
4
- import { EdgeLabel } from "../edge-label";
4
+ import { EdgeLabel } from "../edge-label/edge-label";
5
5
  const strokeClasses = {
6
6
  active: "stroke-sky-500",
7
7
  blocked: "stroke-amber-500",
@@ -2,7 +2,7 @@
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { memo, useEffect, useRef } from "react";
4
4
  import { cn } from "../../lib/utils";
5
- import { Button } from "../button";
5
+ import { Button } from "../button/button";
6
6
  const DEFAULT_LABELS = {
7
7
  continueLabel: "Continue Tutorial",
8
8
  startLabel: "Start Tutorial",
@@ -12,7 +12,7 @@ import {
12
12
  } from "react";
13
13
  import { ArrowDown, RefreshCw, ThumbsDown, ThumbsUp } from "lucide-react";
14
14
  import { cn } from "../../lib/utils";
15
- import { ThinkingBlock } from "../thinking-block";
15
+ import { ThinkingBlock } from "../thinking-block/thinking-block";
16
16
  const ConversationThreadContext = createContext(null);
17
17
  function useConversationThreadContext() {
18
18
  const ctx = useContext(ConversationThreadContext);
@@ -2,7 +2,7 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { cn } from "../../lib/utils";
5
- import { Badge } from "../badge";
5
+ import { Badge } from "../badge/badge";
6
6
  import {
7
7
  Card,
8
8
  CardContent,
@@ -11,7 +11,7 @@ import {
11
11
  } from "@tanstack/react-table";
12
12
  import { ArrowDown, ArrowUp, ArrowUpDown } from "lucide-react";
13
13
  import { cn } from "../../lib/utils";
14
- import { Button } from "../button";
14
+ import { Button } from "../button/button";
15
15
  import { Checkbox } from "../checkbox";
16
16
  import { Input } from "../input";
17
17
  import {
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { CalendarIcon } from "lucide-react";
5
5
  import { cn } from "../../lib/utils";
6
- import { Button } from "../button";
6
+ import { Button } from "../button/button";
7
7
  import { Calendar } from "../calendar";
8
8
  import { Popover, PopoverContent, PopoverTrigger } from "../popover";
9
9
  const defaultDateFormatter = new Intl.DateTimeFormat("en-US", {
@@ -25,11 +25,6 @@ const DatePicker = React.forwardRef(
25
25
  value
26
26
  );
27
27
  const selectedDate = value ?? internalValue;
28
- React.useEffect(() => {
29
- if (value !== void 0) {
30
- setInternalValue(value);
31
- }
32
- }, [value]);
33
28
  const handleSelect = (nextDate) => {
34
29
  if (value === void 0) {
35
30
  setInternalValue(nextDate);
@@ -3,7 +3,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useState } from "react";
4
4
  import { Check, Dumbbell, Eye, EyeOff } from "lucide-react";
5
5
  import { cn } from "../../lib/utils";
6
- import { Button } from "../button";
6
+ import { Button } from "../button/button";
7
7
  const difficultyConfig = {
8
8
  easy: { className: "text-green-600 dark:text-green-400", label: "Easy" },
9
9
  hard: { className: "text-red-600 dark:text-red-400", label: "Hard" },
@@ -3,16 +3,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { FileUp, UploadCloud, X } from "lucide-react";
5
5
  import { cn } from "../../lib/utils";
6
- import { Button } from "../button";
6
+ import { Button } from "../button/button";
7
7
  function useFileUploadState(controlledFiles, multiple, onFilesChange) {
8
8
  const [internalFiles, setInternalFiles] = React.useState(
9
9
  controlledFiles ?? []
10
10
  );
11
- React.useEffect(() => {
12
- if (controlledFiles !== void 0) {
13
- setInternalFiles(controlledFiles);
14
- }
15
- }, [controlledFiles]);
16
11
  const resolvedFiles = controlledFiles ?? internalFiles;
17
12
  const updateFiles = React.useCallback(
18
13
  (nextFiles) => {