@chan.run/design 0.2.0 → 0.3.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 +195 -0
- package/dist/index.d.mts +26 -28
- package/dist/index.mjs +348 -98
- package/package.json +5 -5
package/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# @chan.run/design
|
|
2
|
+
|
|
3
|
+
Shared Chakra UI v3 theme and brand-asset library for the chan.run ecosystem. **Single source of truth** for tokens, components, product icons, wordmarks, and favicons. Every site, app, and product UI imports from this package — never inline an SVG, never copy a PNG.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
The package is published to npm and pinned by every workspace consumer:
|
|
8
|
+
|
|
9
|
+
```jsonc
|
|
10
|
+
// package.json
|
|
11
|
+
{
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@chakra-ui/react": "3.35.0",
|
|
14
|
+
"@chan.run/design": "^0.2.0",
|
|
15
|
+
"next-themes": "*",
|
|
16
|
+
"react": "19.2.4"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`@chakra-ui/react`, `next-themes`, and `react` are peer deps — keep them aligned to the versions in this package's `peerDependencies` to avoid duplicate Chakra installs (which produce structural type errors when passing `system` between packages).
|
|
22
|
+
|
|
23
|
+
## Theme + provider
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { ChakraProvider } from "@chakra-ui/react";
|
|
27
|
+
import { system } from "@chan.run/design";
|
|
28
|
+
import { ThemeProvider } from "next-themes";
|
|
29
|
+
|
|
30
|
+
<ChakraProvider value={system}>
|
|
31
|
+
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
|
32
|
+
{children}
|
|
33
|
+
</ThemeProvider>
|
|
34
|
+
</ChakraProvider>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Tokens live in the `chan.*` namespace (`chan.bg`, `chan.text`, `chan.orange`, …) — see [`src/theme.ts`](./src/theme.ts) and `docs/design-system.md` for the full taxonomy.
|
|
38
|
+
|
|
39
|
+
## Brand marks
|
|
40
|
+
|
|
41
|
+
Two flavors: the **chan.run umbrella brand** (`CHAN[•]RUN`, dot accent) and **per-product marks** (`SEA[M]`, `ENTROP[Y]`, …, last-letter accent). Rules locked per `docs/brand-marks.md`.
|
|
42
|
+
|
|
43
|
+
### React components
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import {
|
|
47
|
+
Wordmark, // CHAN[•]RUN — umbrella brand
|
|
48
|
+
SeamIcon, SeamWordmark,
|
|
49
|
+
EntropyIcon, EntropyWordmark,
|
|
50
|
+
RestunnelIcon, RestunnelWordmark,
|
|
51
|
+
EnsureIcon, EnsureWordmark,
|
|
52
|
+
SlidesIcon, SlidesWordmark,
|
|
53
|
+
PRODUCT_ICONS, // Record<name, ComponentType>
|
|
54
|
+
PRODUCT_WORDMARKS,
|
|
55
|
+
} from "@chan.run/design";
|
|
56
|
+
|
|
57
|
+
// Themed React component — switches with light/dark mode automatically
|
|
58
|
+
<HStack gap="3">
|
|
59
|
+
<SeamIcon />
|
|
60
|
+
<SeamWordmark fontSize="22px" />
|
|
61
|
+
</HStack>
|
|
62
|
+
|
|
63
|
+
// Loop products from the registry
|
|
64
|
+
{Object.entries(PRODUCT_ICONS).map(([name, Icon]) => <Icon key={name} />)}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`<Wordmark pulseDot />` opacity-cycles the dot via the `chan-pulse` keyframe — used by `Splash` for loading states.
|
|
68
|
+
|
|
69
|
+
### Raw SVG assets
|
|
70
|
+
|
|
71
|
+
When you need the SVG as an image (e.g. inside Chakra's `<Image>`):
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
import seamIconUrl from "@chan.run/design/svg/seam-icon-dark.svg?url";
|
|
75
|
+
import { Image } from "@chakra-ui/react";
|
|
76
|
+
|
|
77
|
+
<Image src={seamIconUrl} alt="" boxSize="44px" />
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Variants under `@chan.run/design/svg/`:
|
|
81
|
+
|
|
82
|
+
| Pattern | What |
|
|
83
|
+
| ------------------------------------------- | -------------------------------------------- |
|
|
84
|
+
| `chan-wordmark-{dark,light}.svg` | CHAN[•]RUN, dark or light text |
|
|
85
|
+
| `<name>-wordmark-{dark,light}.svg` | Product wordmark (text-as-paths) |
|
|
86
|
+
| `<name>-icon-{dark,light}.svg` | 176×176 squircle monogram |
|
|
87
|
+
| `<name>-favicon.svg` | 32×32 single-letter favicon source |
|
|
88
|
+
|
|
89
|
+
Where `<name>` ∈ `chan` (wordmark only) | `ensure` | `entropy` | `restunnel` | `seam` | `slides`. SVGs use **path-converted text** (no font dependency) and survive `pnpm build` (live in `assets/`, not `dist/`).
|
|
90
|
+
|
|
91
|
+
For theme-aware rendering, prefer the React component. The static `-dark`/`-light` SVGs are for surfaces where you can't use Chakra (Rust dashboards, native apps, README screenshots, etc.).
|
|
92
|
+
|
|
93
|
+
## Favicons
|
|
94
|
+
|
|
95
|
+
Each product ships a full favicon bundle (16/32/48 PNG, ICO, Apple touch, Android Chrome, Windows mstile, manifest, head snippet). Three ways to consume:
|
|
96
|
+
|
|
97
|
+
### 1. Head component (drop-in)
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { SeamFaviconHead } from "@chan.run/design";
|
|
101
|
+
|
|
102
|
+
<head>
|
|
103
|
+
<SeamFaviconHead />
|
|
104
|
+
{/* opt into PWA: <SeamFaviconHead manifest /> */}
|
|
105
|
+
</head>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Per-product components: `ChanFaviconHead`, `EnsureFaviconHead`, `EntropyFaviconHead`, `RestunnelFaviconHead`, `SeamFaviconHead`, `SlidesFaviconHead`. Each emits the full set of `<link>`/`<meta>` tags with hashed asset URLs the bundler emits at build time.
|
|
109
|
+
|
|
110
|
+
### 2. Asset URL imports (raw URLs for custom wiring)
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import faviconIco from "@chan.run/design/favicons/seam/favicon.ico?url";
|
|
114
|
+
import appleTouchIcon from "@chan.run/design/favicons/seam/apple-touch-icon.png?url";
|
|
115
|
+
import manifestUrl from "@chan.run/design/favicons/seam/manifest.webmanifest?url";
|
|
116
|
+
|
|
117
|
+
<link rel="icon" href={faviconIco} />
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### 3. Asset-URL maps (programmatic)
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { seamFaviconAssets } from "@chan.run/design";
|
|
124
|
+
seamFaviconAssets.ico; // bundler-emitted hashed URL
|
|
125
|
+
seamFaviconAssets.png16;
|
|
126
|
+
seamFaviconAssets.apple;
|
|
127
|
+
seamFaviconAssets.android192;
|
|
128
|
+
seamFaviconAssets.manifest;
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Browser extensions
|
|
132
|
+
|
|
133
|
+
Vite-style `?url` imports don't work inside `wxt.config.ts` (it's loaded by Node, not Vite). Use `createRequire` to get a filesystem path, then let `@wxt-dev/auto-icons` downscale to the manifest sizes:
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
// wxt.config.ts
|
|
137
|
+
import { createRequire } from 'node:module';
|
|
138
|
+
import { defineConfig } from 'wxt';
|
|
139
|
+
|
|
140
|
+
const require = createRequire(import.meta.url);
|
|
141
|
+
const seamIconPath = require.resolve(
|
|
142
|
+
'@chan.run/design/favicons/seam/android-chrome-512x512.png',
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
export default defineConfig({
|
|
146
|
+
modules: ['@wxt-dev/module-react', '@wxt-dev/auto-icons'],
|
|
147
|
+
autoIcons: { baseIconPath: seamIconPath },
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
See `products/seam/seam-extension/wxt.config.ts` for the working example.
|
|
152
|
+
|
|
153
|
+
## Adding a new product mark
|
|
154
|
+
|
|
155
|
+
1. Add to `src/products/<name>/<Name>Icon.tsx` and `<Name>Wordmark.tsx`. Use `ProductIcon` / `ProductWordmark` from `src/products/_internal.tsx` — they encode the locked visual rules so you only specify the letter splits.
|
|
156
|
+
2. Register in `src/products/index.ts` (`PRODUCT_ICONS`, `PRODUCT_WORDMARKS`).
|
|
157
|
+
3. Add an entry to `scripts/export-svg.ts` (`PRODUCTS` array) and `scripts/gen-favicons.ts` (`MARKS` array) so SVG/favicon variants are generated.
|
|
158
|
+
4. Run `pnpm gen-brand` to produce the `assets/` outputs.
|
|
159
|
+
5. Run `pnpm typecheck && pnpm exec biome check .` to confirm.
|
|
160
|
+
|
|
161
|
+
See `docs/brand-marks.md` for the full hard-rules reference.
|
|
162
|
+
|
|
163
|
+
## Repo layout
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
packages/design/
|
|
167
|
+
├── src/
|
|
168
|
+
│ ├── brand/ # CHAN[•]RUN umbrella wordmark
|
|
169
|
+
│ ├── components/ # Splash, Topbar, slides, ColorModeButton, …
|
|
170
|
+
│ ├── favicons/ # Per-product head components + asset URL maps
|
|
171
|
+
│ ├── products/ # Per-product Icon + Wordmark components
|
|
172
|
+
│ │ ├── _internal.tsx # Locked visual primitives (do not export)
|
|
173
|
+
│ │ ├── <name>/ # ensure | entropy | restunnel | seam | slides
|
|
174
|
+
│ │ └── index.ts # Exports + PRODUCT_ICONS / PRODUCT_WORDMARKS
|
|
175
|
+
│ ├── styled-system/ # Chakra typegen output (do not edit by hand)
|
|
176
|
+
│ ├── theme.ts # `system` — Chakra v3 theme config
|
|
177
|
+
│ ├── TokenShowcase.tsx # Visual reference for all tokens
|
|
178
|
+
│ └── index.ts
|
|
179
|
+
├── scripts/
|
|
180
|
+
│ ├── export-svg.ts # Wordmarks/icons/favicon-source SVGs → assets/svg/
|
|
181
|
+
│ └── gen-favicons.ts # Per-product favicon bundles → assets/favicons/
|
|
182
|
+
└── assets/ # Committed build outputs (subpath-exported)
|
|
183
|
+
├── svg/
|
|
184
|
+
└── favicons/<name>/
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Scripts
|
|
188
|
+
|
|
189
|
+
| Command | What |
|
|
190
|
+
| ------------------------- | --------------------------------------------------------------- |
|
|
191
|
+
| `pnpm build` | Build TS bundle into `dist/` (consumed by published package) |
|
|
192
|
+
| `pnpm typecheck` | `tsc --noEmit` for `src/` and `scripts/` |
|
|
193
|
+
| `pnpm gen-brand` | Regenerate all SVG and favicon assets into `assets/` |
|
|
194
|
+
| `pnpm export-svg` | Just the SVGs |
|
|
195
|
+
| `pnpm gen-favicons` | Just the favicon bundles (depends on SVGs being generated) |
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import * as _$_chakra_ui_react0 from "@chakra-ui/react";
|
|
2
1
|
import { FlexProps, TextProps } from "@chakra-ui/react";
|
|
3
|
-
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
2
|
import { ComponentType, ReactNode } from "react";
|
|
5
3
|
|
|
6
4
|
//#region src/brand/Wordmark.d.ts
|
|
@@ -15,10 +13,10 @@ declare function Wordmark({
|
|
|
15
13
|
color,
|
|
16
14
|
pulseDot,
|
|
17
15
|
...rest
|
|
18
|
-
}: WordmarkProps):
|
|
16
|
+
}: WordmarkProps): import("react/jsx-runtime").JSX.Element;
|
|
19
17
|
//#endregion
|
|
20
18
|
//#region src/components/ColorModeButton.d.ts
|
|
21
|
-
declare function ColorModeButton(props: FlexProps):
|
|
19
|
+
declare function ColorModeButton(props: FlexProps): import("react/jsx-runtime").JSX.Element;
|
|
22
20
|
//#endregion
|
|
23
21
|
//#region src/components/Splash.d.ts
|
|
24
22
|
interface SplashProps {
|
|
@@ -42,7 +40,7 @@ declare function Splash({
|
|
|
42
40
|
size,
|
|
43
41
|
holdMs,
|
|
44
42
|
revealMs
|
|
45
|
-
}: SplashProps):
|
|
43
|
+
}: SplashProps): import("react/jsx-runtime").JSX.Element | null;
|
|
46
44
|
//#endregion
|
|
47
45
|
//#region src/components/slides/types.d.ts
|
|
48
46
|
/** Supported slide layout templates */
|
|
@@ -112,7 +110,7 @@ declare function DeckCard({
|
|
|
112
110
|
tags,
|
|
113
111
|
slideCount,
|
|
114
112
|
onClick
|
|
115
|
-
}: DeckCardProps):
|
|
113
|
+
}: DeckCardProps): import("react/jsx-runtime").JSX.Element;
|
|
116
114
|
//#endregion
|
|
117
115
|
//#region src/components/slides/SlideComponents.d.ts
|
|
118
116
|
type ComponentMap = Record<string, React.ComponentType<Record<string, unknown>>>;
|
|
@@ -135,13 +133,13 @@ declare function SlideControls({
|
|
|
135
133
|
onSlideChange,
|
|
136
134
|
onTogglePresent,
|
|
137
135
|
isPresenting
|
|
138
|
-
}: SlideControlsProps):
|
|
136
|
+
}: SlideControlsProps): import("react/jsx-runtime").JSX.Element;
|
|
139
137
|
//#endregion
|
|
140
138
|
//#region src/components/slides/SlideLayout.d.ts
|
|
141
139
|
declare function SlideLayoutComponent({
|
|
142
140
|
layout,
|
|
143
141
|
children
|
|
144
|
-
}: SlideProps):
|
|
142
|
+
}: SlideProps): import("react/jsx-runtime").JSX.Element;
|
|
145
143
|
//#endregion
|
|
146
144
|
//#region src/components/slides/SlideViewer.d.ts
|
|
147
145
|
declare function SlideViewer({
|
|
@@ -150,7 +148,7 @@ declare function SlideViewer({
|
|
|
150
148
|
onSlideChange,
|
|
151
149
|
isPresenting,
|
|
152
150
|
onTogglePresent
|
|
153
|
-
}: SlideViewerProps):
|
|
151
|
+
}: SlideViewerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
154
152
|
//#endregion
|
|
155
153
|
//#region src/components/Topbar.d.ts
|
|
156
154
|
interface TopbarProps {
|
|
@@ -159,7 +157,7 @@ interface TopbarProps {
|
|
|
159
157
|
}
|
|
160
158
|
declare function Topbar({
|
|
161
159
|
onMenuOpen
|
|
162
|
-
}: TopbarProps):
|
|
160
|
+
}: TopbarProps): import("react/jsx-runtime").JSX.Element;
|
|
163
161
|
//#endregion
|
|
164
162
|
//#region src/favicons/index.d.ts
|
|
165
163
|
interface MarkAssets {
|
|
@@ -181,15 +179,15 @@ declare const entropyFaviconAssets: MarkAssets;
|
|
|
181
179
|
declare const restunnelFaviconAssets: MarkAssets;
|
|
182
180
|
declare const seamFaviconAssets: MarkAssets;
|
|
183
181
|
declare const slidesFaviconAssets: MarkAssets;
|
|
184
|
-
declare function ChanFaviconHead(props?: FaviconHeadProps):
|
|
185
|
-
declare function EnsureFaviconHead(props?: FaviconHeadProps):
|
|
186
|
-
declare function EntropyFaviconHead(props?: FaviconHeadProps):
|
|
187
|
-
declare function RestunnelFaviconHead(props?: FaviconHeadProps):
|
|
188
|
-
declare function SeamFaviconHead(props?: FaviconHeadProps):
|
|
189
|
-
declare function SlidesFaviconHead(props?: FaviconHeadProps):
|
|
182
|
+
declare function ChanFaviconHead(props?: FaviconHeadProps): import("react/jsx-runtime").JSX.Element;
|
|
183
|
+
declare function EnsureFaviconHead(props?: FaviconHeadProps): import("react/jsx-runtime").JSX.Element;
|
|
184
|
+
declare function EntropyFaviconHead(props?: FaviconHeadProps): import("react/jsx-runtime").JSX.Element;
|
|
185
|
+
declare function RestunnelFaviconHead(props?: FaviconHeadProps): import("react/jsx-runtime").JSX.Element;
|
|
186
|
+
declare function SeamFaviconHead(props?: FaviconHeadProps): import("react/jsx-runtime").JSX.Element;
|
|
187
|
+
declare function SlidesFaviconHead(props?: FaviconHeadProps): import("react/jsx-runtime").JSX.Element;
|
|
190
188
|
//#endregion
|
|
191
189
|
//#region src/products/ensure/EnsureIcon.d.ts
|
|
192
|
-
declare function EnsureIcon():
|
|
190
|
+
declare function EnsureIcon(): import("react/jsx-runtime").JSX.Element;
|
|
193
191
|
//#endregion
|
|
194
192
|
//#region src/products/_internal.d.ts
|
|
195
193
|
interface ProductWordmarkProps extends Omit<TextProps, "children"> {
|
|
@@ -203,44 +201,44 @@ interface ProductWordmarkProps extends Omit<TextProps, "children"> {
|
|
|
203
201
|
//#endregion
|
|
204
202
|
//#region src/products/ensure/EnsureWordmark.d.ts
|
|
205
203
|
interface EnsureWordmarkProps extends Omit<ProductWordmarkProps, "prefix" | "terminal"> {}
|
|
206
|
-
declare function EnsureWordmark(props: EnsureWordmarkProps):
|
|
204
|
+
declare function EnsureWordmark(props: EnsureWordmarkProps): import("react/jsx-runtime").JSX.Element;
|
|
207
205
|
//#endregion
|
|
208
206
|
//#region src/products/entropy/EntropyIcon.d.ts
|
|
209
|
-
declare function EntropyIcon():
|
|
207
|
+
declare function EntropyIcon(): import("react/jsx-runtime").JSX.Element;
|
|
210
208
|
//#endregion
|
|
211
209
|
//#region src/products/entropy/EntropyWordmark.d.ts
|
|
212
210
|
interface EntropyWordmarkProps extends Omit<ProductWordmarkProps, "prefix" | "terminal"> {}
|
|
213
|
-
declare function EntropyWordmark(props: EntropyWordmarkProps):
|
|
211
|
+
declare function EntropyWordmark(props: EntropyWordmarkProps): import("react/jsx-runtime").JSX.Element;
|
|
214
212
|
//#endregion
|
|
215
213
|
//#region src/products/restunnel/RestunnelIcon.d.ts
|
|
216
|
-
declare function RestunnelIcon():
|
|
214
|
+
declare function RestunnelIcon(): import("react/jsx-runtime").JSX.Element;
|
|
217
215
|
//#endregion
|
|
218
216
|
//#region src/products/restunnel/RestunnelWordmark.d.ts
|
|
219
217
|
interface RestunnelWordmarkProps extends Omit<ProductWordmarkProps, "prefix" | "terminal"> {}
|
|
220
|
-
declare function RestunnelWordmark(props: RestunnelWordmarkProps):
|
|
218
|
+
declare function RestunnelWordmark(props: RestunnelWordmarkProps): import("react/jsx-runtime").JSX.Element;
|
|
221
219
|
//#endregion
|
|
222
220
|
//#region src/products/seam/SeamIcon.d.ts
|
|
223
|
-
declare function SeamIcon():
|
|
221
|
+
declare function SeamIcon(): import("react/jsx-runtime").JSX.Element;
|
|
224
222
|
//#endregion
|
|
225
223
|
//#region src/products/seam/SeamWordmark.d.ts
|
|
226
224
|
interface SeamWordmarkProps extends Omit<ProductWordmarkProps, "prefix" | "terminal"> {}
|
|
227
|
-
declare function SeamWordmark(props: SeamWordmarkProps):
|
|
225
|
+
declare function SeamWordmark(props: SeamWordmarkProps): import("react/jsx-runtime").JSX.Element;
|
|
228
226
|
//#endregion
|
|
229
227
|
//#region src/products/slides/SlidesIcon.d.ts
|
|
230
|
-
declare function SlidesIcon():
|
|
228
|
+
declare function SlidesIcon(): import("react/jsx-runtime").JSX.Element;
|
|
231
229
|
//#endregion
|
|
232
230
|
//#region src/products/slides/SlidesWordmark.d.ts
|
|
233
231
|
interface SlidesWordmarkProps extends Omit<ProductWordmarkProps, "prefix" | "terminal"> {}
|
|
234
|
-
declare function SlidesWordmark(props: SlidesWordmarkProps):
|
|
232
|
+
declare function SlidesWordmark(props: SlidesWordmarkProps): import("react/jsx-runtime").JSX.Element;
|
|
235
233
|
//#endregion
|
|
236
234
|
//#region src/products/index.d.ts
|
|
237
235
|
declare const PRODUCT_ICONS: Record<string, ComponentType>;
|
|
238
236
|
declare const PRODUCT_WORDMARKS: Record<string, ComponentType>;
|
|
239
237
|
//#endregion
|
|
240
238
|
//#region src/TokenShowcase.d.ts
|
|
241
|
-
declare function TokenShowcase():
|
|
239
|
+
declare function TokenShowcase(): import("react/jsx-runtime").JSX.Element;
|
|
242
240
|
//#endregion
|
|
243
241
|
//#region src/theme.d.ts
|
|
244
|
-
declare const system:
|
|
242
|
+
declare const system: import("@chakra-ui/react").SystemContext;
|
|
245
243
|
//#endregion
|
|
246
244
|
export { ChanFaviconHead, ColorModeButton, DeckCard, type DeckCardProps, EnsureFaviconHead, EnsureIcon, EnsureWordmark, type EnsureWordmarkProps, EntropyFaviconHead, EntropyIcon, EntropyWordmark, type EntropyWordmarkProps, PRODUCT_ICONS, PRODUCT_WORDMARKS, RestunnelFaviconHead, RestunnelIcon, RestunnelWordmark, type RestunnelWordmarkProps, SeamFaviconHead, SeamIcon, SeamWordmark, type SeamWordmarkProps, SlideControls, type SlideControlsProps, type SlideEntry, SlideLayoutComponent as SlideLayout, type SlideLayout as SlideLayoutType, type SlideProps, SlideViewer, type SlideViewerProps, SlidesFaviconHead, SlidesIcon, SlidesWordmark, type SlidesWordmarkProps, Splash, type SplashProps, TokenShowcase, Topbar, type TopbarProps, Wordmark, type WordmarkProps, chanFaviconAssets, ensureFaviconAssets, entropyFaviconAssets, getSlideComponents, restunnelFaviconAssets, seamFaviconAssets, slidesFaviconAssets, system };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Badge, Box, Card, Center, Code, Flex, Grid, HStack, Heading, IconButton, Text, createSystem, defaultConfig, defineConfig, defineSlotRecipe, useSlotRecipe } from "@chakra-ui/react";
|
|
1
|
+
import { Badge, Box, Card, Center, Code, Flex, Grid, HStack, Heading, IconButton, Text, createSystem, defaultConfig, defineConfig, defineRecipe, defineSlotRecipe, useSlotRecipe } from "@chakra-ui/react";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useTheme } from "next-themes";
|
|
4
4
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
@@ -1985,6 +1985,322 @@ function TokenShowcase() {
|
|
|
1985
1985
|
]
|
|
1986
1986
|
});
|
|
1987
1987
|
}
|
|
1988
|
+
const adminChromeSlotRecipe = defineSlotRecipe({
|
|
1989
|
+
className: "chan-admin-chrome",
|
|
1990
|
+
slots: [
|
|
1991
|
+
"rail",
|
|
1992
|
+
"frame",
|
|
1993
|
+
"tick",
|
|
1994
|
+
"tag"
|
|
1995
|
+
],
|
|
1996
|
+
base: {
|
|
1997
|
+
rail: {
|
|
1998
|
+
position: "sticky",
|
|
1999
|
+
top: "52px",
|
|
2000
|
+
zIndex: 54,
|
|
2001
|
+
display: "flex",
|
|
2002
|
+
alignItems: "center",
|
|
2003
|
+
gap: "9px",
|
|
2004
|
+
height: "26px",
|
|
2005
|
+
px: "22px",
|
|
2006
|
+
fontFamily: "body",
|
|
2007
|
+
fontSize: "9px",
|
|
2008
|
+
letterSpacing: "0.18em",
|
|
2009
|
+
textTransform: "uppercase",
|
|
2010
|
+
color: "chan.orange",
|
|
2011
|
+
bg: "chan.bg",
|
|
2012
|
+
borderBottom: "1px solid",
|
|
2013
|
+
borderColor: "chan.orange.border",
|
|
2014
|
+
backgroundImage: "repeating-linear-gradient(135deg, transparent, transparent 9px, rgba(255,77,0,.06) 9px, rgba(255,77,0,.06) 18px)"
|
|
2015
|
+
},
|
|
2016
|
+
frame: {
|
|
2017
|
+
position: "fixed",
|
|
2018
|
+
inset: 0,
|
|
2019
|
+
zIndex: 80,
|
|
2020
|
+
pointerEvents: "none",
|
|
2021
|
+
border: "1.5px solid",
|
|
2022
|
+
borderColor: "chan.orange.border"
|
|
2023
|
+
},
|
|
2024
|
+
tick: {
|
|
2025
|
+
position: "absolute",
|
|
2026
|
+
width: "16px",
|
|
2027
|
+
height: "16px",
|
|
2028
|
+
border: "2px solid",
|
|
2029
|
+
borderColor: "chan.orange"
|
|
2030
|
+
},
|
|
2031
|
+
tag: {
|
|
2032
|
+
position: "absolute",
|
|
2033
|
+
left: "50%",
|
|
2034
|
+
bottom: 0,
|
|
2035
|
+
transform: "translateX(-50%)",
|
|
2036
|
+
fontFamily: "body",
|
|
2037
|
+
fontSize: "8px",
|
|
2038
|
+
letterSpacing: "0.2em",
|
|
2039
|
+
textTransform: "uppercase",
|
|
2040
|
+
color: "chan.orange",
|
|
2041
|
+
whiteSpace: "nowrap",
|
|
2042
|
+
bg: "chan.bg",
|
|
2043
|
+
border: "1px solid",
|
|
2044
|
+
borderColor: "chan.orange.border",
|
|
2045
|
+
borderBottom: 0,
|
|
2046
|
+
borderTopRadius: "4px",
|
|
2047
|
+
px: "12px",
|
|
2048
|
+
pt: "4px",
|
|
2049
|
+
pb: "5px"
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
2052
|
+
});
|
|
2053
|
+
//#endregion
|
|
2054
|
+
//#region src/components/dataTable.recipe.ts
|
|
2055
|
+
const dataTableSlotRecipe = defineSlotRecipe({
|
|
2056
|
+
className: "chan-data-table",
|
|
2057
|
+
slots: [
|
|
2058
|
+
"root",
|
|
2059
|
+
"header",
|
|
2060
|
+
"columnHeader",
|
|
2061
|
+
"row",
|
|
2062
|
+
"cell"
|
|
2063
|
+
],
|
|
2064
|
+
base: {
|
|
2065
|
+
root: {
|
|
2066
|
+
border: "1px solid",
|
|
2067
|
+
borderColor: "chan.border",
|
|
2068
|
+
borderRadius: "md",
|
|
2069
|
+
bg: "chan.bg",
|
|
2070
|
+
overflow: "hidden",
|
|
2071
|
+
fontFamily: "body"
|
|
2072
|
+
},
|
|
2073
|
+
header: { bg: "chan.bg.code" },
|
|
2074
|
+
columnHeader: {
|
|
2075
|
+
fontSize: "8px",
|
|
2076
|
+
letterSpacing: "0.22em",
|
|
2077
|
+
textTransform: "uppercase",
|
|
2078
|
+
color: "chan.text.faint",
|
|
2079
|
+
borderColor: "chan.border",
|
|
2080
|
+
py: "11px"
|
|
2081
|
+
},
|
|
2082
|
+
row: { cursor: "default" },
|
|
2083
|
+
cell: {
|
|
2084
|
+
fontSize: "11px",
|
|
2085
|
+
borderColor: "chan.border",
|
|
2086
|
+
borderBottomStyle: "dashed"
|
|
2087
|
+
}
|
|
2088
|
+
},
|
|
2089
|
+
variants: {
|
|
2090
|
+
archived: { true: { row: { opacity: .5 } } },
|
|
2091
|
+
clickable: { true: { row: { cursor: "pointer" } } }
|
|
2092
|
+
}
|
|
2093
|
+
});
|
|
2094
|
+
//#endregion
|
|
2095
|
+
//#region src/components/lbl.recipe.ts
|
|
2096
|
+
const toneColor = (color) => ({ color });
|
|
2097
|
+
const lblRecipe = defineRecipe({
|
|
2098
|
+
className: "chan-lbl",
|
|
2099
|
+
base: {
|
|
2100
|
+
display: "inline-flex",
|
|
2101
|
+
alignItems: "center",
|
|
2102
|
+
fontFamily: "body",
|
|
2103
|
+
fontSize: "9.5px",
|
|
2104
|
+
letterSpacing: "0.18em",
|
|
2105
|
+
textTransform: "uppercase"
|
|
2106
|
+
},
|
|
2107
|
+
variants: {
|
|
2108
|
+
tone: {
|
|
2109
|
+
orange: toneColor("chan.orange"),
|
|
2110
|
+
dim: toneColor("chan.text.dim"),
|
|
2111
|
+
faint: toneColor("chan.text.faint"),
|
|
2112
|
+
ok: toneColor("chan.green"),
|
|
2113
|
+
warn: toneColor("chan.yellow"),
|
|
2114
|
+
danger: toneColor("chan.danger"),
|
|
2115
|
+
info: toneColor("#6a9eda"),
|
|
2116
|
+
neutral: toneColor("chan.text.dim"),
|
|
2117
|
+
owner: toneColor("chan.orange"),
|
|
2118
|
+
admin: toneColor("#6a9eda"),
|
|
2119
|
+
member: toneColor("chan.text.dim"),
|
|
2120
|
+
off: toneColor("chan.text.faint")
|
|
2121
|
+
},
|
|
2122
|
+
variant: {
|
|
2123
|
+
plain: {},
|
|
2124
|
+
chip: {
|
|
2125
|
+
fontSize: "8.5px",
|
|
2126
|
+
letterSpacing: "0.14em",
|
|
2127
|
+
border: "1px solid",
|
|
2128
|
+
borderColor: "color-mix(in srgb, currentColor 38%, transparent)",
|
|
2129
|
+
bg: "color-mix(in srgb, currentColor 12%, transparent)",
|
|
2130
|
+
borderRadius: "3px",
|
|
2131
|
+
px: "7px",
|
|
2132
|
+
py: "2px"
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
},
|
|
2136
|
+
compoundVariants: [{
|
|
2137
|
+
tone: "off",
|
|
2138
|
+
variant: "chip",
|
|
2139
|
+
css: {
|
|
2140
|
+
borderStyle: "dashed",
|
|
2141
|
+
bg: "transparent"
|
|
2142
|
+
}
|
|
2143
|
+
}],
|
|
2144
|
+
defaultVariants: {
|
|
2145
|
+
tone: "neutral",
|
|
2146
|
+
variant: "plain"
|
|
2147
|
+
}
|
|
2148
|
+
});
|
|
2149
|
+
//#endregion
|
|
2150
|
+
//#region src/components/panel.recipe.ts
|
|
2151
|
+
const panelSlotRecipe = defineSlotRecipe({
|
|
2152
|
+
className: "chan-panel",
|
|
2153
|
+
slots: [
|
|
2154
|
+
"root",
|
|
2155
|
+
"head",
|
|
2156
|
+
"label",
|
|
2157
|
+
"body"
|
|
2158
|
+
],
|
|
2159
|
+
base: {
|
|
2160
|
+
root: {
|
|
2161
|
+
border: "1px solid",
|
|
2162
|
+
borderColor: "chan.border",
|
|
2163
|
+
borderRadius: "md",
|
|
2164
|
+
bg: "chan.bg",
|
|
2165
|
+
overflow: "hidden"
|
|
2166
|
+
},
|
|
2167
|
+
head: {
|
|
2168
|
+
display: "flex",
|
|
2169
|
+
alignItems: "center",
|
|
2170
|
+
gap: "8px",
|
|
2171
|
+
px: "16px",
|
|
2172
|
+
py: "11px",
|
|
2173
|
+
borderBottom: "1px solid",
|
|
2174
|
+
borderColor: "chan.border"
|
|
2175
|
+
},
|
|
2176
|
+
label: {
|
|
2177
|
+
fontFamily: "body",
|
|
2178
|
+
fontSize: "8.5px",
|
|
2179
|
+
letterSpacing: "0.18em",
|
|
2180
|
+
textTransform: "uppercase",
|
|
2181
|
+
color: "chan.text.dim"
|
|
2182
|
+
},
|
|
2183
|
+
body: {
|
|
2184
|
+
px: "16px",
|
|
2185
|
+
py: "14px"
|
|
2186
|
+
}
|
|
2187
|
+
},
|
|
2188
|
+
variants: { state: {
|
|
2189
|
+
default: {},
|
|
2190
|
+
live: { label: { color: "chan.orange" } },
|
|
2191
|
+
degraded: { root: { borderColor: "chan.danger.border" } },
|
|
2192
|
+
placeholder: { root: {
|
|
2193
|
+
borderStyle: "dashed",
|
|
2194
|
+
opacity: .6
|
|
2195
|
+
} }
|
|
2196
|
+
} },
|
|
2197
|
+
defaultVariants: { state: "default" }
|
|
2198
|
+
});
|
|
2199
|
+
//#endregion
|
|
2200
|
+
//#region src/components/splash.recipe.ts
|
|
2201
|
+
const splashSlotRecipe = defineSlotRecipe({
|
|
2202
|
+
className: "chan-splash",
|
|
2203
|
+
slots: [
|
|
2204
|
+
"root",
|
|
2205
|
+
"panelStart",
|
|
2206
|
+
"panelEnd",
|
|
2207
|
+
"hub"
|
|
2208
|
+
],
|
|
2209
|
+
base: {
|
|
2210
|
+
root: {
|
|
2211
|
+
position: "fixed",
|
|
2212
|
+
inset: 0,
|
|
2213
|
+
display: "flex",
|
|
2214
|
+
zIndex: 1e4
|
|
2215
|
+
},
|
|
2216
|
+
panelStart: {
|
|
2217
|
+
flex: 1,
|
|
2218
|
+
position: "relative",
|
|
2219
|
+
bg: "chan.bg.soft",
|
|
2220
|
+
transitionProperty: "top, left",
|
|
2221
|
+
transitionTimingFunction: "ease-in-out"
|
|
2222
|
+
},
|
|
2223
|
+
panelEnd: {
|
|
2224
|
+
flex: 1,
|
|
2225
|
+
position: "relative",
|
|
2226
|
+
bg: "chan.bg.soft",
|
|
2227
|
+
transitionProperty: "bottom, right",
|
|
2228
|
+
transitionTimingFunction: "ease-in-out"
|
|
2229
|
+
},
|
|
2230
|
+
hub: {
|
|
2231
|
+
position: "absolute",
|
|
2232
|
+
bg: "chan.bg.card",
|
|
2233
|
+
border: "1px solid",
|
|
2234
|
+
borderColor: "chan.border",
|
|
2235
|
+
borderRadius: "md",
|
|
2236
|
+
display: "flex",
|
|
2237
|
+
alignItems: "center",
|
|
2238
|
+
justifyContent: "center",
|
|
2239
|
+
zIndex: 1,
|
|
2240
|
+
width: "var(--splash-hub-w)"
|
|
2241
|
+
}
|
|
2242
|
+
},
|
|
2243
|
+
variants: {
|
|
2244
|
+
orientation: {
|
|
2245
|
+
vertical: {
|
|
2246
|
+
root: { flexDirection: "column" },
|
|
2247
|
+
panelStart: {
|
|
2248
|
+
borderBottom: "2px solid",
|
|
2249
|
+
borderColor: "chan.border"
|
|
2250
|
+
},
|
|
2251
|
+
panelEnd: {
|
|
2252
|
+
borderTop: "2px solid",
|
|
2253
|
+
borderColor: "chan.border"
|
|
2254
|
+
},
|
|
2255
|
+
hub: {
|
|
2256
|
+
bottom: 0,
|
|
2257
|
+
left: "50%",
|
|
2258
|
+
transform: "translate(-50%, 50%)"
|
|
2259
|
+
}
|
|
2260
|
+
},
|
|
2261
|
+
horizontal: {
|
|
2262
|
+
root: { flexDirection: "row" },
|
|
2263
|
+
panelStart: {
|
|
2264
|
+
borderRight: "2px solid",
|
|
2265
|
+
borderColor: "chan.border"
|
|
2266
|
+
},
|
|
2267
|
+
panelEnd: {
|
|
2268
|
+
borderLeft: "2px solid",
|
|
2269
|
+
borderColor: "chan.border"
|
|
2270
|
+
},
|
|
2271
|
+
hub: {
|
|
2272
|
+
right: 0,
|
|
2273
|
+
top: "50%",
|
|
2274
|
+
transform: "translate(50%, -50%)"
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
},
|
|
2278
|
+
size: {
|
|
2279
|
+
sm: { hub: {
|
|
2280
|
+
"--splash-hub-w": "180px",
|
|
2281
|
+
px: 4,
|
|
2282
|
+
py: 3
|
|
2283
|
+
} },
|
|
2284
|
+
md: { hub: {
|
|
2285
|
+
"--splash-hub-w": "240px",
|
|
2286
|
+
px: 5,
|
|
2287
|
+
py: 4
|
|
2288
|
+
} },
|
|
2289
|
+
lg: { hub: {
|
|
2290
|
+
"--splash-hub-w": "320px",
|
|
2291
|
+
px: 6,
|
|
2292
|
+
py: 5
|
|
2293
|
+
} }
|
|
2294
|
+
}
|
|
2295
|
+
},
|
|
2296
|
+
defaultVariants: {
|
|
2297
|
+
orientation: "vertical",
|
|
2298
|
+
size: "md"
|
|
2299
|
+
}
|
|
2300
|
+
});
|
|
2301
|
+
//#endregion
|
|
2302
|
+
//#region src/components/statusDot.recipe.ts
|
|
2303
|
+
const dot = (color) => ({ bg: color });
|
|
1988
2304
|
const system = createSystem(defaultConfig, defineConfig({
|
|
1989
2305
|
globalCss: { body: {
|
|
1990
2306
|
bg: "{colors.chan.bg}",
|
|
@@ -2028,6 +2344,9 @@ const system = createSystem(defaultConfig, defineConfig({
|
|
|
2028
2344
|
"chan.green": { value: "#3a8c5c" },
|
|
2029
2345
|
"chan.green.bg": { value: "rgba(58, 140, 92, 0.08)" },
|
|
2030
2346
|
"chan.green.border": { value: "rgba(58, 140, 92, 0.20)" },
|
|
2347
|
+
"chan.teal": { value: "#2f9c9c" },
|
|
2348
|
+
"chan.teal.bg": { value: "rgba(47, 156, 156, 0.08)" },
|
|
2349
|
+
"chan.teal.border": { value: "rgba(47, 156, 156, 0.20)" },
|
|
2031
2350
|
"chan.yellow": { value: "#a88000" },
|
|
2032
2351
|
"chan.yellow.bg": { value: "rgba(200, 160, 0, 0.07)" },
|
|
2033
2352
|
"chan.yellow.border": { value: "rgba(200, 160, 0, 0.15)" },
|
|
@@ -2123,106 +2442,37 @@ const system = createSystem(defaultConfig, defineConfig({
|
|
|
2123
2442
|
textTransform: "uppercase"
|
|
2124
2443
|
} }
|
|
2125
2444
|
},
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
"
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
position: "fixed",
|
|
2137
|
-
inset: 0,
|
|
2138
|
-
display: "flex",
|
|
2139
|
-
zIndex: 1e4
|
|
2445
|
+
recipes: {
|
|
2446
|
+
lbl: lblRecipe,
|
|
2447
|
+
statusDot: defineRecipe({
|
|
2448
|
+
className: "chan-status-dot",
|
|
2449
|
+
base: {
|
|
2450
|
+
display: "inline-block",
|
|
2451
|
+
width: "6px",
|
|
2452
|
+
height: "6px",
|
|
2453
|
+
borderRadius: "full",
|
|
2454
|
+
flexShrink: 0
|
|
2140
2455
|
},
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
flex: 1,
|
|
2150
|
-
position: "relative",
|
|
2151
|
-
bg: "chan.bg.soft",
|
|
2152
|
-
transitionProperty: "bottom, right",
|
|
2153
|
-
transitionTimingFunction: "ease-in-out"
|
|
2154
|
-
},
|
|
2155
|
-
hub: {
|
|
2156
|
-
position: "absolute",
|
|
2157
|
-
bg: "chan.bg.card",
|
|
2158
|
-
border: "1px solid",
|
|
2159
|
-
borderColor: "chan.border",
|
|
2160
|
-
borderRadius: "md",
|
|
2161
|
-
display: "flex",
|
|
2162
|
-
alignItems: "center",
|
|
2163
|
-
justifyContent: "center",
|
|
2164
|
-
zIndex: 1,
|
|
2165
|
-
width: "var(--splash-hub-w)"
|
|
2166
|
-
}
|
|
2167
|
-
},
|
|
2168
|
-
variants: {
|
|
2169
|
-
orientation: {
|
|
2170
|
-
vertical: {
|
|
2171
|
-
root: { flexDirection: "column" },
|
|
2172
|
-
panelStart: {
|
|
2173
|
-
borderBottom: "2px solid",
|
|
2174
|
-
borderColor: "chan.border"
|
|
2175
|
-
},
|
|
2176
|
-
panelEnd: {
|
|
2177
|
-
borderTop: "2px solid",
|
|
2178
|
-
borderColor: "chan.border"
|
|
2179
|
-
},
|
|
2180
|
-
hub: {
|
|
2181
|
-
bottom: 0,
|
|
2182
|
-
left: "50%",
|
|
2183
|
-
transform: "translate(-50%, 50%)"
|
|
2184
|
-
}
|
|
2456
|
+
variants: {
|
|
2457
|
+
tone: {
|
|
2458
|
+
ok: dot("chan.green"),
|
|
2459
|
+
warn: dot("chan.yellow"),
|
|
2460
|
+
danger: dot("chan.danger"),
|
|
2461
|
+
info: dot("#6a9eda"),
|
|
2462
|
+
neutral: dot("chan.text.faint"),
|
|
2463
|
+
off: dot("chan.text.faint")
|
|
2185
2464
|
},
|
|
2186
|
-
|
|
2187
|
-
root: { flexDirection: "row" },
|
|
2188
|
-
panelStart: {
|
|
2189
|
-
borderRight: "2px solid",
|
|
2190
|
-
borderColor: "chan.border"
|
|
2191
|
-
},
|
|
2192
|
-
panelEnd: {
|
|
2193
|
-
borderLeft: "2px solid",
|
|
2194
|
-
borderColor: "chan.border"
|
|
2195
|
-
},
|
|
2196
|
-
hub: {
|
|
2197
|
-
right: 0,
|
|
2198
|
-
top: "50%",
|
|
2199
|
-
transform: "translate(50%, -50%)"
|
|
2200
|
-
}
|
|
2201
|
-
}
|
|
2465
|
+
live: { true: { animation: "chan-pulse" } }
|
|
2202
2466
|
},
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
py: 4
|
|
2213
|
-
} },
|
|
2214
|
-
lg: { hub: {
|
|
2215
|
-
"--splash-hub-w": "320px",
|
|
2216
|
-
px: 6,
|
|
2217
|
-
py: 5
|
|
2218
|
-
} }
|
|
2219
|
-
}
|
|
2220
|
-
},
|
|
2221
|
-
defaultVariants: {
|
|
2222
|
-
orientation: "vertical",
|
|
2223
|
-
size: "md"
|
|
2224
|
-
}
|
|
2225
|
-
}) },
|
|
2467
|
+
defaultVariants: { tone: "neutral" }
|
|
2468
|
+
})
|
|
2469
|
+
},
|
|
2470
|
+
slotRecipes: {
|
|
2471
|
+
splash: splashSlotRecipe,
|
|
2472
|
+
panel: panelSlotRecipe,
|
|
2473
|
+
dataTable: dataTableSlotRecipe,
|
|
2474
|
+
adminChrome: adminChromeSlotRecipe
|
|
2475
|
+
},
|
|
2226
2476
|
semanticTokens: { colors: {
|
|
2227
2477
|
"chan.bg": { value: {
|
|
2228
2478
|
_light: "{colors.chan.palette.light.bg}",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chan.run/design",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Shared Chakra UI v3 theme and component library for chan.run",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"assets"
|
|
20
20
|
],
|
|
21
21
|
"peerDependencies": {
|
|
22
|
-
"@chakra-ui/react": "3.35.0",
|
|
22
|
+
"@chakra-ui/react": "^3.35.0",
|
|
23
23
|
"next-themes": "*",
|
|
24
|
-
"react": "19.
|
|
24
|
+
"react": "^19.0.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@chakra-ui/cli": "3.35.0",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"@types/react": "19.2.14",
|
|
30
30
|
"favicons": "^7.2.0",
|
|
31
31
|
"opentype.js": "^1.3.4",
|
|
32
|
-
"tsdown": "^0.
|
|
32
|
+
"tsdown": "^0.22.3",
|
|
33
33
|
"tsx": "^4.21.0",
|
|
34
|
-
"typescript": "
|
|
34
|
+
"typescript": "6.0.3"
|
|
35
35
|
},
|
|
36
36
|
"repository": {
|
|
37
37
|
"type": "git",
|