@ekkolyth/ui 0.1.17 → 0.1.18

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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +153 -97
  3. package/dist/base.css +263 -0
  4. package/dist/blocks.d.ts +4 -0
  5. package/dist/blocks.js +4 -0
  6. package/dist/container-BBg21poC.js +10 -0
  7. package/dist/convex.d.ts +2 -0
  8. package/dist/convex.js +2 -0
  9. package/dist/hooks.d.ts +2 -0
  10. package/dist/hooks.js +2 -0
  11. package/dist/icon-picker-ByfHyJ7i.js +4078 -0
  12. package/dist/index-Bwp0YMmG.d.ts +5 -0
  13. package/dist/index-BxcqwZNT.d.ts +30 -0
  14. package/dist/index-DHF8OR1R.d.ts +60 -0
  15. package/dist/index-DsLGf2HX.d.ts +9 -0
  16. package/dist/index-qji4ohJZ.d.ts +24 -0
  17. package/dist/index.d.ts +793 -533
  18. package/dist/index.js +3236 -5578
  19. package/dist/layout.d.ts +2 -0
  20. package/dist/layout.js +2 -0
  21. package/dist/loading-screen-DB3youyT.js +63 -0
  22. package/dist/shiki-code-Bg__Vnt1.js +29 -0
  23. package/dist/text.d.ts +17 -0
  24. package/dist/text.js +177 -0
  25. package/dist/themes/catpuccin/frappe.css +33 -33
  26. package/dist/themes/catpuccin/latte.css +33 -33
  27. package/dist/themes/catpuccin/macchiato.css +33 -33
  28. package/dist/themes/catpuccin/mocha.css +33 -33
  29. package/dist/themes/ekko-os.css +92 -37
  30. package/dist/themes/ekkolyth.css +2 -2
  31. package/dist/themes/index.css +7 -66
  32. package/dist/themes/provider.d.ts +62 -0
  33. package/dist/themes/provider.js +271 -0
  34. package/dist/themes/tokyo-night.css +33 -33
  35. package/dist/themes.css +7 -66
  36. package/dist/toggle-B2PFPImC.js +182 -0
  37. package/dist/use-mobile-BVGje-2e.d.ts +4 -0
  38. package/dist/use-mobile-CqHXB_Nc.js +18 -0
  39. package/dist/utils-C_uf36nf.js +8 -0
  40. package/dist/widget-C2vjxQms.js +94 -0
  41. package/dist/widget.d.ts +6 -0
  42. package/dist/widget.js +19 -0
  43. package/package.json +125 -170
  44. package/dist/catpuccin/frappe.css +0 -35
  45. package/dist/catpuccin/latte.css +0 -35
  46. package/dist/catpuccin/macchiato.css +0 -35
  47. package/dist/catpuccin/mocha.css +0 -35
  48. package/dist/ekko-os.css +0 -71
  49. package/dist/ekko-playlist.css +0 -71
  50. package/dist/ekkolyth.css +0 -70
  51. package/dist/index-C3ceanPz.d.ts +0 -18
  52. package/dist/index-C7t_lwpi.d.ts +0 -13
  53. package/dist/next.d.ts +0 -13
  54. package/dist/next.js +0 -271
  55. package/dist/providers/next.d.ts +0 -25
  56. package/dist/providers/next.js +0 -216
  57. package/dist/providers/tanstack.d.ts +0 -24
  58. package/dist/providers/tanstack.js +0 -120
  59. package/dist/tanstack.d.ts +0 -12
  60. package/dist/tanstack.js +0 -203
  61. package/dist/themes/ekko-playlist.css +0 -71
  62. package/dist/themes/theme-select.d.ts +0 -12
  63. package/dist/themes/theme-select.js +0 -357
  64. package/dist/themes/theme-toggle.d.ts +0 -15
  65. package/dist/themes/theme-toggle.js +0 -179
  66. package/dist/tokyo-night.css +0 -35
  67. package/dist/types-fUfvw1Mz.d.ts +0 -8
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ekkolyth
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,111 +1,164 @@
1
- # Ekko UI
1
+ # @ekkolyth/ui
2
2
 
3
- Shared UI component library.
3
+ Shared UI component library, published as `@ekkolyth/ui`.
4
4
 
5
5
  ## Installation
6
6
 
7
- ```bash
8
- npm install @ekkolyth/ui
7
+ ```sh
8
+ bun add @ekkolyth/ui
9
9
  ```
10
10
 
11
11
  ## Peer Dependencies
12
12
 
13
- - `react` ^19.2.3
14
- - `react-dom` ^19.2.3
15
- - `next-themes` ^0.4.6 (optional, for Next.js theme support)
16
- - `@tanstack/react-router` ^1.150.0 (optional, for TanStack Router theme support)
13
+ - `react` ^19.2.0
14
+ - `react-dom` ^19.2.0
15
+
16
+ `next` is only reachable through the `/widget` compatibility entry
17
+ (`Widget`). It ships as an ordinary workspace dependency here; the
18
+ published package declares it as an **optional** peer so an app that never
19
+ imports `/widget` never installs it.
17
20
 
18
21
  ## Exports
19
22
 
20
- ### Main Export (`@ekkolyth/ui`)
23
+ | Subpath | What it is |
24
+ |---|---|
25
+ | `.` | All UI components, hooks, and utilities. Theme runtime is not here — see `/themes/provider`. |
26
+ | `./text` | `RichText` — renders Tiptap `JSONContent` through a node registry. |
27
+ | `./layout` | `Container`. |
28
+ | `./blocks` | `ColorPicker`, `Field`, `IconPicker`, `LoadingScreen`, `Widget`. |
29
+ | `./hooks` | `useIsMobile`. |
30
+ | `./themes/provider` | The framework-neutral theme runtime — see below. |
31
+ | `./themes` | Stylesheet: all seven palettes, `@import`ed. |
32
+ | `./themes/catpuccin/latte`, `./themes/catpuccin/frappe`, `./themes/catpuccin/macchiato`, `./themes/catpuccin/mocha`, `./themes/tokyo-night`, `./themes/ekko-os`, `./themes/ekkolyth` | Individual palette stylesheets — seven subpaths, one per palette. |
33
+ | `./base.css` | The base theme layer — see "Base CSS" below. |
34
+
35
+ `./widget` and `./convex` are **compatibility entries, not documented API.**
36
+ They exist because specific `apps/web` call sites import from them and sit
37
+ outside this package's edit surface; don't build new code against them.
21
38
 
22
- All UI components, hooks, and utilities.
39
+ **Components:**
40
+ Built on top of shadcn@latest.
23
41
 
24
42
  ```tsx
25
43
  import { Button, Card, Dialog, useIsMobile, cn } from '@ekkolyth/ui'
26
44
  ```
27
45
 
28
- **Components:**
29
- Built on top of shadcn@latest.
30
-
31
- ### Next.js Theme Provider (`@ekkolyth/ui/next`)
46
+ ## Theme Provider
32
47
 
33
- Theme provider for Next.js applications using `next-themes`.
48
+ One framework-neutral provider, at `@ekkolyth/ui/themes/provider`. No
49
+ `next-themes` — a vitest guard (`src/index.test.ts`) fails the build if
50
+ anything reachable from the root barrel imports it. The subpath exports:
34
51
 
35
52
  ```tsx
36
- import { ThemeProvider, useTheme, Toaster } from '@ekkolyth/ui/next'
37
- import type { ThemeProviderProps, SystemTheme, ThemeName } from '@ekkolyth/ui/next'
53
+ import {
54
+ ThemeProvider,
55
+ ThemeScript,
56
+ ThemeSelect,
57
+ ThemeToggle,
58
+ Toaster,
59
+ useTheme,
60
+ } from '@ekkolyth/ui/themes/provider'
61
+ import type {
62
+ Appearance,
63
+ DarkThemes,
64
+ LightThemes,
65
+ ThemeContextState,
66
+ ThemeName,
67
+ ThemeProviderProps,
68
+ ThemeScriptProps,
69
+ } from '@ekkolyth/ui/themes/provider'
38
70
  ```
39
71
 
40
- **ThemeProvider Props:**
41
- - `defaultTheme?: SystemTheme` - Default system theme (`"light" | "dark" | "system" | "normal"`)
42
- - `lightTheme?: ThemeName | ThemeName[]` - Light theme(s) to make available.
43
- - `darkTheme?: ThemeName | ThemeName[]` - Dark theme(s) to make available.
44
- - `storageKey?: string` - localStorage key prefix (default: `"ekko-ui"`) - most people won't need this, but if you're running something like "Micro-Frontends", it might be useful to customize per-frontend, despite running on the same domain.
45
-
46
- **useTheme Hook:**
47
- Returns:
48
- - `systemTheme: SystemTheme` - Current system theme mode
49
- - `resolvedTheme: ThemeName` - Currently applied theme name
50
- - `availableThemes: { light: ThemeName[], dark: ThemeName[] }` - Available themes
51
- - `setSystemTheme: (theme: SystemTheme) => void` - Set system theme mode
52
- - `setSpecificTheme: (mode: "light" | "dark", theme: ThemeName) => void` - Set specific theme
72
+ **`ThemeProviderProps`:**
73
+ - `defaultAppearance?: Appearance` — `"light" | "dark" | "system" | "normal"`, default `"system"`. `"normal"` is a legacy alias for `"light"`.
74
+ - `lightTheme?: LightThemes | LightThemes[]` — light palette(s) to make available, default `"ekkolyth-light"`.
75
+ - `darkTheme?: DarkThemes | DarkThemes[]` — dark palette(s) to make available, default `"ekkolyth-dark"`.
76
+ - `storageKey?: string` — localStorage key prefix, default `"ekko-ui"`. Most apps won't need this; it matters if several frontends share a domain and need independent theme state.
77
+
78
+ **`useTheme()` returns `ThemeContextState`:**
79
+ - `appearance: Appearance` — the mode the user picked, before resolving `"system"`.
80
+ - `resolvedMode: 'light' | 'dark'` — `appearance` resolved against `matchMedia` when it's `"system"`.
81
+ - `resolvedTheme: ThemeName` — the palette currently applied for `resolvedMode`.
82
+ - `availableThemes: { light: LightThemes[], dark: DarkThemes[] }`
83
+ - `setAppearance: (appearance: Appearance) => void`
84
+ - `setSpecificTheme: (mode: 'light' | 'dark', theme: LightThemes | DarkThemes) => void`
85
+
86
+ `ThemeName` is the union of every palette (`LightThemes | DarkThemes`) —
87
+ which palette is showing. `Appearance` is a separate concept — light/dark/system
88
+ preference — deliberately a different word so the two don't get conflated at a
89
+ call site.
90
+
91
+ **`ThemeName` values:**
92
+ - `"latte" | "ekkoos-light" | "ekkolyth-light"` — light palettes
93
+ - `"mocha" | "frappe" | "macchiato" | "tokyo-night" | "ekkoos-dark" | "ekkolyth-dark"` — dark palettes
94
+
95
+ ### `ThemeScript`
96
+
97
+ Renders a `<script>` that reads the stored appearance/palette from
98
+ `localStorage` and sets `data-theme` + the `.dark` class on `<html>` before
99
+ React hydrates. Put it in `<head>` — `app/layout.tsx` on Next.js,
100
+ `__root.tsx` on TanStack Start — with the same `defaultAppearance`,
101
+ `lightTheme`, `darkTheme`, and `storageKey` as the `<ThemeProvider>` it pairs
102
+ with. Skipping it doesn't break anything, it just costs one painted frame of
103
+ the wrong palette before the provider's own mount effect catches up.
53
104
 
54
- **ThemeName Types:**
55
- - `"mocha" | "frappe" | "macchiato" | "latte"` - Catppuccin themes
56
- - `"tokyo-night"` - Tokyo Night theme
57
- - `"ekkoos-light" | "ekkoos-dark"` - Ekko OS themes
58
- - `"ekkolyth-light" | "ekkolyth-dark"` - Ekkolyth themes
59
- - `"ekko-playlist-light" | "ekko-playlist-dark"` - Ekko Playlist themes
105
+ ```tsx
106
+ import { ThemeScript } from '@ekkolyth/ui/themes/provider'
60
107
 
61
- ### TanStack Router Theme Provider (`@ekkolyth/ui/tanstack`)
108
+ <head>
109
+ <ThemeScript defaultAppearance='system' />
110
+ </head>
111
+ ```
62
112
 
63
- Theme provider for TanStack Router applications.
113
+ ### Theme Toggle / Theme Select
64
114
 
65
115
  ```tsx
66
- import { ThemeProvider, useTheme, Toaster } from '@ekkolyth/ui/tanstack'
67
- import type { SystemTheme, ThemeName } from '@ekkolyth/ui/tanstack'
116
+ import { ThemeToggle, ThemeSelect } from '@ekkolyth/ui/themes/provider'
68
117
  ```
69
118
 
70
- API matches Next.js provider 1:1
71
-
72
- **Note:** The `Toaster` component is exported from the theme provider entries (`/next` and `/tanstack`) and is automatically theme-aware. If you import `Toaster` from the main entry point (`@ekkolyth/ui`), it will be theme-agnostic and you'll need to pass a `theme` prop manually.
119
+ ## Base CSS
73
120
 
74
- ### Theme Components
121
+ `@ekkolyth/ui/base.css` is the base theme layer — 34 color tokens with
122
+ colourless (grayscale) defaults, the `@theme inline` mapping from those
123
+ tokens into Tailwind utilities, `@custom-variant dark`, and an `@layer base`
124
+ reset (`* { border-border outline-ring/50 }`, `body { bg-background
125
+ text-foreground }`). Import it after the consuming app's own
126
+ `@import 'tailwindcss'` and before its palette overrides:
75
127
 
76
- **Theme Toggle** (`@ekkolyth/ui/themes/theme-toggle`)
77
-
78
- ```tsx
79
- import { ThemeToggle } from '@ekkolyth/ui/themes/theme-toggle'
80
- import type { ThemeToggleProps } from '@ekkolyth/ui/themes/theme-toggle'
128
+ ```css
129
+ @import 'tailwindcss';
130
+ @import '@ekkolyth/ui/base.css';
131
+ /* app-specific palette overrides go here */
81
132
  ```
82
133
 
83
- **Theme Select** (`@ekkolyth/ui/themes/theme-select`)
134
+ The export resolves to `./src/base.css`, not `./dist/base.css`, deliberately:
135
+ `dist/` is gitignored, so a `dist` path would leave fresh clones and git
136
+ worktrees unstyled until someone ran the UI package's build.
84
137
 
85
- ```tsx
86
- import { ThemeSelect } from '@ekkolyth/ui/themes/theme-select'
87
- import type { ThemeSelectProps } from '@ekkolyth/ui/themes/theme-select'
88
- ```
138
+ ## Theme Styles
89
139
 
90
- ### Theme Styles
140
+ `@ekkolyth/ui/themes` is a **stylesheet entry** (a CSS `@import`, not a JS
141
+ module) that pulls in all seven palettes. It stands in for the app's own
142
+ Tailwind preamble, not the other way around — a theme picker that lets the
143
+ user switch palettes needs every palette present, so import it alongside the
144
+ three lines every consumer already writes:
91
145
 
92
- Import theme CSS files:
146
+ ```css
147
+ @import 'tailwindcss';
148
+ @import 'tw-animate-css';
149
+ @import '@ekkolyth/ui/base.css';
150
+ @import '@ekkolyth/ui/themes';
151
+ ```
93
152
 
94
- ```tsx
95
- // All themes
96
- import '@ekkolyth/ui/themes'
153
+ Each palette is scoped to `html[data-theme='<name>']`; the provider and
154
+ `ThemeScript` switch palettes by setting that attribute, so nothing here is a
155
+ runtime import. Pull a single palette instead of the aggregate when an app
156
+ only ever shows one:
97
157
 
98
- // Catppuccin themes
99
- import '@ekkolyth/ui/catpuccin/latte'
100
- import '@ekkolyth/ui/catpuccin/frappe'
101
- import '@ekkolyth/ui/catpuccin/macchiato'
102
- import '@ekkolyth/ui/catpuccin/mocha'
103
-
104
- // Other themes
105
- import '@ekkolyth/ui/tokyo-night'
106
- import '@ekkolyth/ui/ekko-os'
107
- import '@ekkolyth/ui/ekkolyth'
108
- import '@ekkolyth/ui/ekko-playlist'
158
+ ```css
159
+ @import '@ekkolyth/ui/themes/catpuccin/latte';
160
+ @import '@ekkolyth/ui/themes/tokyo-night';
161
+ @import '@ekkolyth/ui/themes/ekkolyth';
109
162
  ```
110
163
 
111
164
  ## Usage Example
@@ -114,17 +167,20 @@ import '@ekkolyth/ui/ekko-playlist'
114
167
 
115
168
  ```tsx
116
169
  // app/layout.tsx
117
- import { ThemeProvider, Toaster } from '@ekkolyth/ui/next'
170
+ import { ThemeProvider, ThemeScript, Toaster } from '@ekkolyth/ui/themes/provider'
118
171
  import '@ekkolyth/ui/themes'
119
172
 
120
173
  export default function RootLayout({ children }) {
121
174
  return (
122
175
  <html>
176
+ <head>
177
+ <ThemeScript defaultAppearance='system' />
178
+ </head>
123
179
  <body>
124
180
  <ThemeProvider
125
- defaultTheme="system"
126
- lightTheme={["latte", "ekkolyth-light"]}
127
- darkTheme={["mocha", "ekkolyth-dark"]}
181
+ defaultAppearance='system'
182
+ lightTheme={['latte', 'ekkolyth-light']}
183
+ darkTheme={['mocha', 'ekkolyth-dark']}
128
184
  >
129
185
  {children}
130
186
  <Toaster />
@@ -137,16 +193,15 @@ export default function RootLayout({ children }) {
137
193
  // app/page.tsx
138
194
  'use client'
139
195
  import { Button } from '@ekkolyth/ui'
140
- import { ThemeToggle } from '@ekkolyth/ui/themes/theme-toggle'
141
- import { useTheme } from '@ekkolyth/ui/next'
196
+ import { ThemeToggle, useTheme } from '@ekkolyth/ui/themes/provider'
142
197
 
143
198
  export default function Page() {
144
- const { systemTheme, setSystemTheme } = useTheme()
145
-
199
+ const { appearance, setAppearance } = useTheme()
200
+
146
201
  return (
147
202
  <div>
148
203
  <ThemeToggle />
149
- <Button onClick={() => setSystemTheme('dark')}>
204
+ <Button onClick={() => setAppearance('dark')}>
150
205
  Set Dark Mode
151
206
  </Button>
152
207
  </div>
@@ -154,23 +209,24 @@ export default function Page() {
154
209
  }
155
210
  ```
156
211
 
157
- ### TanStack Router Setup
212
+ ## Release
158
213
 
159
- ```tsx
160
- // __root.tsx
161
- import { ThemeProvider, Toaster } from '@ekkolyth/ui/tanstack'
162
- import '@ekkolyth/ui/themes'
214
+ 1. On the feature branch, describe the change: `bun run changeset`.
215
+ 2. Merge to `main`. `.github/workflows/release-packages.yml` consumes the
216
+ Changesets plan, bumps the manifest and changelog, builds the package, and
217
+ runs `scripts/stage-public.ts` to produce the `@ekkolyth/ui` artifact with its
218
+ curated `dist/` exports.
219
+ 3. `scripts/validate-package.ts` checks the staged tarball before anything
220
+ ships.
221
+ 4. The workflow publishes the validated tarball, commits the release state,
222
+ and tags the release `ui-v<version>`.
163
223
 
164
- function App() {
165
- return (
166
- <ThemeProvider
167
- defaultTheme="system"
168
- lightTheme={["latte"]}
169
- darkTheme={["mocha"]}
170
- >
171
- <Outlet />
172
- <Toaster />
173
- </ThemeProvider>
174
- )
175
- }
176
- ```
224
+ A push to `main` with no pending changeset is a no-op — `changeset version`
225
+ has nothing to consume, and the commit/publish steps detect the unchanged
226
+ manifest and stop.
227
+
228
+ ### Storybook + vitest
229
+
230
+ The package's storybook (`.storybook/main.ts`) and vitest (`vitest.config.ts`)
231
+ configs include `@ekkolyth/ui` in their alias maps so stories and unit tests resolve
232
+ internal imports the same way the dev/prod bundler does.
package/dist/base.css ADDED
@@ -0,0 +1,263 @@
1
+ /* Base theme layer for every app consuming this package.
2
+ *
3
+ * Deliberately colourless: an app that forgets to override a token renders
4
+ * unthemed rather than plausibly designed. An undefined CSS variable resolves
5
+ * to nothing silently, which is the failure this file exists to remove.
6
+ *
7
+ * Does not import tailwindcss — the consuming app owns that import and must
8
+ * place it before this one, so the @apply rules below resolve. */
9
+
10
+ @plugin '@tailwindcss/typography';
11
+
12
+ @custom-variant dark (&:is(.dark *));
13
+
14
+ :root {
15
+ --radius: 0.625rem;
16
+
17
+ --background: oklch(1 0 0);
18
+ --foreground: oklch(0.145 0 0);
19
+ --card: oklch(1 0 0);
20
+ --card-foreground: oklch(0.145 0 0);
21
+ --popover: oklch(1 0 0);
22
+ --popover-foreground: oklch(0.145 0 0);
23
+ --primary: oklch(0.205 0 0);
24
+ --primary-foreground: oklch(0.985 0 0);
25
+ --secondary: oklch(0.97 0 0);
26
+ --secondary-foreground: oklch(0.205 0 0);
27
+ --muted: oklch(0.97 0 0);
28
+ --muted-foreground: oklch(0.556 0 0);
29
+ --accent: oklch(0.97 0 0);
30
+ --accent-foreground: oklch(0.205 0 0);
31
+ --destructive: oklch(0.45 0 0);
32
+ --destructive-foreground: oklch(0.985 0 0);
33
+ --success: oklch(0.55 0 0);
34
+ --warning: oklch(0.65 0 0);
35
+ --info: oklch(0.6 0 0);
36
+ --border: oklch(0.922 0 0);
37
+ --input: oklch(0.922 0 0);
38
+ --ring: oklch(0.708 0 0);
39
+ --chart-1: oklch(0.35 0 0);
40
+ --chart-2: oklch(0.45 0 0);
41
+ --chart-3: oklch(0.55 0 0);
42
+ --chart-4: oklch(0.65 0 0);
43
+ --chart-5: oklch(0.75 0 0);
44
+ --sidebar: oklch(0.985 0 0);
45
+ --sidebar-foreground: oklch(0.145 0 0);
46
+ --sidebar-primary: oklch(0.205 0 0);
47
+ --sidebar-primary-foreground: oklch(0.985 0 0);
48
+ --sidebar-accent: oklch(0.97 0 0);
49
+ --sidebar-accent-foreground: oklch(0.205 0 0);
50
+ --sidebar-border: oklch(0.922 0 0);
51
+ --sidebar-ring: oklch(0.708 0 0);
52
+ }
53
+
54
+ .dark {
55
+ --background: oklch(0.145 0 0);
56
+ --foreground: oklch(0.985 0 0);
57
+ --card: oklch(0.205 0 0);
58
+ --card-foreground: oklch(0.985 0 0);
59
+ --popover: oklch(0.205 0 0);
60
+ --popover-foreground: oklch(0.985 0 0);
61
+ --primary: oklch(0.922 0 0);
62
+ --primary-foreground: oklch(0.205 0 0);
63
+ --secondary: oklch(0.269 0 0);
64
+ --secondary-foreground: oklch(0.985 0 0);
65
+ --muted: oklch(0.269 0 0);
66
+ --muted-foreground: oklch(0.708 0 0);
67
+ --accent: oklch(0.269 0 0);
68
+ --accent-foreground: oklch(0.985 0 0);
69
+ --destructive: oklch(0.6 0 0);
70
+ --destructive-foreground: oklch(0.985 0 0);
71
+ --success: oklch(0.65 0 0);
72
+ --warning: oklch(0.75 0 0);
73
+ --info: oklch(0.7 0 0);
74
+ --border: oklch(0.269 0 0);
75
+ --input: oklch(0.269 0 0);
76
+ --ring: oklch(0.556 0 0);
77
+ --chart-1: oklch(0.45 0 0);
78
+ --chart-2: oklch(0.55 0 0);
79
+ --chart-3: oklch(0.65 0 0);
80
+ --chart-4: oklch(0.75 0 0);
81
+ --chart-5: oklch(0.85 0 0);
82
+ --sidebar: oklch(0.205 0 0);
83
+ --sidebar-foreground: oklch(0.985 0 0);
84
+ --sidebar-primary: oklch(0.922 0 0);
85
+ --sidebar-primary-foreground: oklch(0.205 0 0);
86
+ --sidebar-accent: oklch(0.269 0 0);
87
+ --sidebar-accent-foreground: oklch(0.985 0 0);
88
+ --sidebar-border: oklch(0.269 0 0);
89
+ --sidebar-ring: oklch(0.556 0 0);
90
+ color-scheme: dark;
91
+ }
92
+
93
+ @theme inline {
94
+ --color-background: var(--background);
95
+ --color-foreground: var(--foreground);
96
+ --color-card: var(--card);
97
+ --color-card-foreground: var(--card-foreground);
98
+ --color-popover: var(--popover);
99
+ --color-popover-foreground: var(--popover-foreground);
100
+ --color-primary: var(--primary);
101
+ --color-primary-foreground: var(--primary-foreground);
102
+ --color-secondary: var(--secondary);
103
+ --color-secondary-foreground: var(--secondary-foreground);
104
+ --color-muted: var(--muted);
105
+ --color-muted-foreground: var(--muted-foreground);
106
+ --color-accent: var(--accent);
107
+ --color-accent-foreground: var(--accent-foreground);
108
+ --color-destructive: var(--destructive);
109
+ --color-destructive-foreground: var(--destructive-foreground);
110
+ --color-success: var(--success);
111
+ --color-warning: var(--warning);
112
+ --color-info: var(--info);
113
+ --color-border: var(--border);
114
+ --color-input: var(--input);
115
+ --color-ring: var(--ring);
116
+ --color-chart-1: var(--chart-1);
117
+ --color-chart-2: var(--chart-2);
118
+ --color-chart-3: var(--chart-3);
119
+ --color-chart-4: var(--chart-4);
120
+ --color-chart-5: var(--chart-5);
121
+ --color-sidebar: var(--sidebar);
122
+ --color-sidebar-foreground: var(--sidebar-foreground);
123
+ --color-sidebar-primary: var(--sidebar-primary);
124
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
125
+ --color-sidebar-accent: var(--sidebar-accent);
126
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
127
+ --color-sidebar-border: var(--sidebar-border);
128
+ --color-sidebar-ring: var(--sidebar-ring);
129
+ --radius-sm: calc(var(--radius) - 4px);
130
+ --radius-md: calc(var(--radius) - 2px);
131
+ --radius-lg: var(--radius);
132
+ --radius-xl: calc(var(--radius) + 4px);
133
+ --radius-2xl: calc(var(--radius) + 8px);
134
+ --radius-3xl: calc(var(--radius) + 12px);
135
+ --radius-4xl: calc(var(--radius) + 16px);
136
+ }
137
+
138
+ /* Plain @theme, not @theme inline: `inline` bakes the value straight into
139
+ * .font-sans, which makes a per-palette override impossible. Emitting the
140
+ * variable to :root is what lets html[data-theme='…'] swap the face.
141
+ *
142
+ * Atkinson Hyperlegible Next and its Mono sibling are the package's default
143
+ * pair — designed together, and picked for legibility. The chain degrades to
144
+ * a real system font for a consumer who hasn't loaded the webfont. */
145
+ @theme {
146
+ --font-sans:
147
+ 'Atkinson Hyperlegible Next Variable', ui-sans-serif, system-ui,
148
+ sans-serif;
149
+ --font-mono:
150
+ 'Atkinson Hyperlegible Mono Variable', ui-monospace, SFMono-Regular,
151
+ Menlo, monospace;
152
+ }
153
+
154
+ /* The sidebar is a dark panel inside a light theme, so a child reading the
155
+ * page-level tokens disappears: --muted-foreground is a mid grey tuned for
156
+ * white, --border a pale hairline that reads as a white outline. Rebinding
157
+ * them here means an ordinary component — and text-muted-foreground in
158
+ * particular — works in a sidebar without knowing it is in one. */
159
+ [data-slot='sidebar'][data-slot],
160
+ [data-slot='sidebar-container'][data-slot] {
161
+ --foreground: var(--sidebar-foreground);
162
+ --muted-foreground: color-mix(
163
+ in oklab,
164
+ var(--sidebar-foreground) 65%,
165
+ var(--sidebar)
166
+ );
167
+ --border: var(--sidebar-border);
168
+ --accent: var(--sidebar-accent);
169
+ --accent-foreground: var(--sidebar-accent-foreground);
170
+ --ring: var(--sidebar-ring);
171
+ }
172
+
173
+ @layer base {
174
+ * {
175
+ @apply border-border outline-ring/50;
176
+ }
177
+ body {
178
+ @apply bg-background text-foreground;
179
+ }
180
+ }
181
+
182
+ .prose h1,
183
+ .prose h2,
184
+ .prose h3 {
185
+ margin-top: 2.5rem;
186
+ margin-bottom: 0.5rem;
187
+ }
188
+ .prose h1 {
189
+ font-size: 1.5em;
190
+ font-weight: 600;
191
+ }
192
+ .prose h2 {
193
+ font-size: 1.25em;
194
+ font-weight: 600;
195
+ }
196
+ .prose h3 {
197
+ font-size: 1.125em;
198
+ font-weight: 600;
199
+ }
200
+ .prose h1:first-child,
201
+ .prose h2:first-child,
202
+ .prose h3:first-child {
203
+ margin-top: 0;
204
+ }
205
+ .prose h1 + * {
206
+ margin-top: 1.5rem;
207
+ }
208
+ .prose h2 + * {
209
+ margin-top: 1rem;
210
+ }
211
+ .prose h3 + * {
212
+ margin-top: 0.75rem;
213
+ }
214
+ /* @tailwindcss/typography wraps inline <code> in literal backticks via
215
+ * ::before/::after pseudo-content and leaves it otherwise unstyled. Strip
216
+ * the backticks and render inline code as a rounded muted pill. */
217
+ .prose :not(pre) > code::before,
218
+ .prose :not(pre) > code::after {
219
+ content: none;
220
+ }
221
+ .prose :not(pre) > code {
222
+ padding: 0.125rem 0.375rem;
223
+ font-family: var(--font-mono);
224
+ font-size: 0.875em;
225
+ font-weight: 500;
226
+ color: var(--foreground);
227
+ background-color: var(--muted);
228
+ border: 1px solid var(--border);
229
+ border-radius: 0.25rem;
230
+ }
231
+ .prose thead th,
232
+ .prose tbody td,
233
+ .prose tfoot td {
234
+ padding-top: 0.375rem !important;
235
+ padding-bottom: 0.375rem !important;
236
+ border-right: 1px solid color-mix(in oklab, var(--border) 40%, transparent);
237
+ }
238
+ .prose thead th:last-child,
239
+ .prose tbody td:last-child,
240
+ .prose tfoot td:last-child {
241
+ border-right: 0;
242
+ }
243
+
244
+ /* Shiki renders with `defaultColor: false`, so every token carries its colours
245
+ as --shiki-light / --shiki-dark variables and nothing else. These rules pick
246
+ the pair for the active theme. Without them the block has no colour at all,
247
+ and with shiki's default the light theme wins in dark mode — the variables
248
+ would be inert either way, because inline styles can only be beaten by
249
+ !important, which the biome config rejects. */
250
+ .shiki {
251
+ background-color: var(--shiki-light-bg);
252
+ }
253
+ .shiki,
254
+ .shiki span {
255
+ color: var(--shiki-light);
256
+ }
257
+ .dark .shiki {
258
+ background-color: var(--shiki-dark-bg);
259
+ }
260
+ .dark .shiki,
261
+ .dark .shiki span {
262
+ color: var(--shiki-dark);
263
+ }
@@ -0,0 +1,4 @@
1
+ import { i as ColorPicker, n as Field, r as validate, t as IconPicker } from "./index-DHF8OR1R.js";
2
+ import { n as LoadingScreenProps, t as LoadingScreen } from "./index-DsLGf2HX.js";
3
+ import { n as WidgetLinkProps, r as WidgetProps, t as Widget } from "./index-qji4ohJZ.js";
4
+ export { ColorPicker, Field, IconPicker, LoadingScreen, type LoadingScreenProps, Widget, type WidgetLinkProps, type WidgetProps, validate };
package/dist/blocks.js ADDED
@@ -0,0 +1,4 @@
1
+ import { R as validate, d as Field, t as IconPicker, z as ColorPicker } from "./icon-picker-ByfHyJ7i.js";
2
+ import { t as LoadingScreen } from "./loading-screen-DB3youyT.js";
3
+ import { t as Widget } from "./widget-C2vjxQms.js";
4
+ export { ColorPicker, Field, IconPicker, LoadingScreen, Widget, validate };
@@ -0,0 +1,10 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ //#region src/components/layout/container/index.tsx
3
+ function Container({ className, ...props }) {
4
+ return /* @__PURE__ */ jsx("div", {
5
+ className: ["mx-auto flex w-full max-w-7xl flex-1 flex-col p-3 md:p-6", className].filter(Boolean).join(" "),
6
+ ...props
7
+ });
8
+ }
9
+ //#endregion
10
+ export { Container as t };
@@ -0,0 +1,2 @@
1
+ import { n as LoadingScreenProps, t as LoadingScreen } from "./index-DsLGf2HX.js";
2
+ export { LoadingScreen, type LoadingScreenProps };
package/dist/convex.js ADDED
@@ -0,0 +1,2 @@
1
+ import { t as LoadingScreen } from "./loading-screen-DB3youyT.js";
2
+ export { LoadingScreen };
@@ -0,0 +1,2 @@
1
+ import { t as useIsMobile } from "./use-mobile-BVGje-2e.js";
2
+ export { useIsMobile };
package/dist/hooks.js ADDED
@@ -0,0 +1,2 @@
1
+ import { t as useIsMobile } from "./use-mobile-CqHXB_Nc.js";
2
+ export { useIsMobile };