@motion-proto/live-tokens 0.20.1 → 0.21.1
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 +33 -4
- package/bin/cli.mjs +22 -1
- package/bin/create.mjs +89 -0
- package/package.json +4 -2
- package/template/README.md +38 -0
- package/template/_gitignore +15 -0
- package/template/index.html +12 -0
- package/template/package.json +24 -0
- package/template/src/App.svelte +18 -0
- package/template/src/main.ts +12 -0
- package/template/src/pages/Home.svelte +84 -0
- package/template/src/vite-env.d.ts +2 -0
- package/template/svelte.config.js +6 -0
- package/template/tsconfig.json +17 -0
- package/template/vite.config.ts +12 -0
package/README.md
CHANGED
|
@@ -216,18 +216,47 @@ export default defineConfig({
|
|
|
216
216
|
|
|
217
217
|
No `css: 'injected'` workaround, no `optimizeDeps` excludes — `vite build` works as-is. (You'll want the full `themeFileApi` plugin and `bootLiveTokens` / `<LiveTokensRouter>` from the Quick install section above when you're ready to persist edits to disk and ship a real app.)
|
|
218
218
|
|
|
219
|
-
## Greenfield?
|
|
219
|
+
## Greenfield? Scaffold a new app
|
|
220
220
|
|
|
221
|
-
If you're starting from scratch, skip the manual wiring
|
|
221
|
+
If you're starting from scratch, skip the manual wiring:
|
|
222
222
|
|
|
223
223
|
```bash
|
|
224
|
-
npx
|
|
224
|
+
npx @motion-proto/live-tokens create my-app
|
|
225
225
|
cd my-app
|
|
226
226
|
npm install
|
|
227
227
|
npm run dev
|
|
228
228
|
```
|
|
229
229
|
|
|
230
|
-
|
|
230
|
+
This generates a Svelte + Vite app that **depends on** the package — `vite.config.ts`, `main.ts`, `App.svelte`, the `themeFileApi` plugin, and a placeholder `src/pages/Home.svelte` are all pre-wired. The token CSS is seeded from the version you scaffolded against, so it never drifts. Open http://localhost:5173 and replace `Home.svelte` with your content; upgrade the package later with `npm update`.
|
|
231
|
+
|
|
232
|
+
(The older `npx degit motionproto/live-tokens` route cloned this whole repo as your app — the package's source, tests, and all. `create` gives you a thin consumer app instead.)
|
|
233
|
+
|
|
234
|
+
## Recommended project layout
|
|
235
|
+
|
|
236
|
+
`create` scaffolds the preferred integration surface. Whether you scaffolded or wired up by hand, conforming to this layout keeps upgrades non-destructive and consistent across projects.
|
|
237
|
+
|
|
238
|
+
```
|
|
239
|
+
src/
|
|
240
|
+
main.ts # token CSS chain → bootLiveTokens(App, '#app')
|
|
241
|
+
App.svelte # routes (e.g. <LiveTokensRouter {pages} />)
|
|
242
|
+
pages/ # your pages
|
|
243
|
+
styles/site.css # your themed page typography (yours to edit)
|
|
244
|
+
system/styles/tokens.css # vendored Layer-1 tokens — committed
|
|
245
|
+
live-tokens/data/ # editor state — committed
|
|
246
|
+
tokens.generated.css # editor output
|
|
247
|
+
themes/ manifests/ component-configs/
|
|
248
|
+
**/_backups/ # gitignored (local-only snapshots)
|
|
249
|
+
vite.config.ts # svelte({ preprocess: vitePreprocess() }) + themeFileApi
|
|
250
|
+
svelte.config.js # vitePreprocess()
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Conventions that make this work:
|
|
254
|
+
|
|
255
|
+
- **Vendor `tokens.css` into `src/` and commit it.** Point `themeFileApi({ tokensCssPath })` at that file, not at one inside `node_modules`. The dev server writes your edits there; a copy under `node_modules` is wiped on every `npm install`.
|
|
256
|
+
- **All editable state lives under `src/` and is committed** — `tokens.css`, `tokens.generated.css`, and everything in `live-tokens/data/`. This is the invariant that makes upgrades safe: `npm install` only ever touches `node_modules` + `package.json` + the lockfile, never your `src/`.
|
|
257
|
+
- **`_backups/` is gitignored.** The dev server snapshots a file before overwriting it; those snapshots are local working state, not source.
|
|
258
|
+
- **Preprocess with `vitePreprocess()`** (bundled in `@sveltejs/vite-plugin-svelte`), keeping `sass` installed for the components' `scss`. No `svelte-preprocess`, no `legacy-peer-deps` `.npmrc` — the dependency tree resolves cleanly on its own (since 0.19.1).
|
|
259
|
+
- **Import only from the public surface** — `@motion-proto/live-tokens`, `/components/*`, `/vite-plugin`, `/app/*`.
|
|
231
260
|
|
|
232
261
|
## Consumer-authored components
|
|
233
262
|
|
package/bin/cli.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// CLI for @motion-proto/live-tokens.
|
|
3
3
|
// Subcommands:
|
|
4
|
+
// create <dir> Scaffold a new app that depends on this package.
|
|
4
5
|
// setup-claude [--force] Copy bundled Claude Code skills into ./.claude/skills/.
|
|
5
6
|
// check-component <id> Validate a component against the add-component skill contract.
|
|
6
7
|
|
|
@@ -10,10 +11,13 @@ import { fileURLToPath } from 'node:url';
|
|
|
10
11
|
import process from 'node:process';
|
|
11
12
|
import { checkComponent, formatReport } from './check-component.mjs';
|
|
12
13
|
import { runMigrate, formatMigrateResult } from './migrate.mjs';
|
|
14
|
+
import { runCreate, formatCreateResult } from './create.mjs';
|
|
13
15
|
|
|
14
16
|
const USAGE = `Usage: npx @motion-proto/live-tokens <command> [options]
|
|
15
17
|
|
|
16
18
|
Commands:
|
|
19
|
+
create <dir> [--force] Scaffold a new Svelte + Vite app wired up with
|
|
20
|
+
live-tokens (editor, components, theme tokens)
|
|
17
21
|
setup-claude [--force] Install bundled Claude Code skills into ./.claude/skills/
|
|
18
22
|
check-component <id> Validate <id>'s runtime, editor, and registration
|
|
19
23
|
against the live-tokens-create-component contract
|
|
@@ -35,6 +39,24 @@ if (!command || command === '--help' || command === '-h') {
|
|
|
35
39
|
process.exit(0);
|
|
36
40
|
}
|
|
37
41
|
|
|
42
|
+
const pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
43
|
+
|
|
44
|
+
if (command === 'create' || command === 'init') {
|
|
45
|
+
const targetArg = rest.find((a) => !a.startsWith('-'));
|
|
46
|
+
if (!targetArg) {
|
|
47
|
+
fail(`Usage: npx @motion-proto/live-tokens create <project-directory>`);
|
|
48
|
+
}
|
|
49
|
+
const force = rest.includes('--force');
|
|
50
|
+
const targetDir = resolve(process.cwd(), targetArg);
|
|
51
|
+
try {
|
|
52
|
+
const result = runCreate({ targetDir, pkgRoot, force });
|
|
53
|
+
console.log(formatCreateResult(result, targetArg));
|
|
54
|
+
process.exit(0);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
fail(err instanceof Error ? err.message : String(err));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
38
60
|
if (command === 'check-component') {
|
|
39
61
|
const id = rest[0];
|
|
40
62
|
if (!id) fail(`Usage: npx @motion-proto/live-tokens check-component <id>`);
|
|
@@ -70,7 +92,6 @@ if (process.platform === 'win32') {
|
|
|
70
92
|
|
|
71
93
|
const force = rest.includes('--force');
|
|
72
94
|
|
|
73
|
-
const pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
74
95
|
const srcSkills = join(pkgRoot, '.claude', 'skills');
|
|
75
96
|
|
|
76
97
|
if (!existsSync(srcSkills)) {
|
package/bin/create.mjs
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// `create` subcommand: scaffold a new Svelte + Vite app that depends on the
|
|
2
|
+
// published package. Extracted from cli.mjs so it can be unit-tested.
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
cpSync,
|
|
6
|
+
existsSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
readFileSync,
|
|
9
|
+
readdirSync,
|
|
10
|
+
renameSync,
|
|
11
|
+
writeFileSync,
|
|
12
|
+
} from 'node:fs';
|
|
13
|
+
import { dirname, join, resolve } from 'node:path';
|
|
14
|
+
|
|
15
|
+
// npm strips dotfiles from published tarballs, so the template ships them
|
|
16
|
+
// renamed; `create` restores the leading dot on scaffold.
|
|
17
|
+
const DOTFILES = [['_gitignore', '.gitignore']];
|
|
18
|
+
|
|
19
|
+
// Seeded from THIS installed package (src → scaffold) so the generated app's
|
|
20
|
+
// token/theme CSS never drifts from the version it was created against.
|
|
21
|
+
const SEEDS = [
|
|
22
|
+
['src/system/styles/tokens.css', 'src/system/styles/tokens.css'],
|
|
23
|
+
['src/live-tokens/data/tokens.generated.css', 'src/live-tokens/data/tokens.generated.css'],
|
|
24
|
+
['src/app/site.css', 'src/styles/site.css'],
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const PLACEHOLDER_FILES = ['package.json', 'index.html', 'README.md'];
|
|
28
|
+
|
|
29
|
+
export function appNameFrom(targetDir) {
|
|
30
|
+
return (
|
|
31
|
+
(targetDir.split(/[/\\]/).filter(Boolean).pop() || '')
|
|
32
|
+
.replace(/[^a-z0-9._-]+/gi, '-')
|
|
33
|
+
.replace(/^[-.]+|[-.]+$/g, '')
|
|
34
|
+
.toLowerCase() || 'live-tokens-app'
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function runCreate({ targetDir, pkgRoot, force = false }) {
|
|
39
|
+
const templateDir = join(pkgRoot, 'template');
|
|
40
|
+
if (!existsSync(templateDir)) {
|
|
41
|
+
throw new Error(`Template not found at ${templateDir}. Is the package installed correctly?`);
|
|
42
|
+
}
|
|
43
|
+
if (existsSync(targetDir) && readdirSync(targetDir).length > 0 && !force) {
|
|
44
|
+
throw new Error(`${targetDir} is not empty. Pass --force to scaffold into it anyway.`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const appName = appNameFrom(targetDir);
|
|
48
|
+
const ltVersion = JSON.parse(readFileSync(join(pkgRoot, 'package.json'), 'utf8')).version;
|
|
49
|
+
|
|
50
|
+
cpSync(templateDir, targetDir, { recursive: true });
|
|
51
|
+
|
|
52
|
+
for (const [from, to] of DOTFILES) {
|
|
53
|
+
const src = join(targetDir, from);
|
|
54
|
+
if (existsSync(src)) renameSync(src, join(targetDir, to));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
for (const [srcRel, destRel] of SEEDS) {
|
|
58
|
+
const src = join(pkgRoot, srcRel);
|
|
59
|
+
const dest = join(targetDir, destRel);
|
|
60
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
61
|
+
if (existsSync(src)) cpSync(src, dest);
|
|
62
|
+
else writeFileSync(dest, '');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
for (const rel of PLACEHOLDER_FILES) {
|
|
66
|
+
const p = join(targetDir, rel);
|
|
67
|
+
if (!existsSync(p)) continue;
|
|
68
|
+
const filled = readFileSync(p, 'utf8')
|
|
69
|
+
.replaceAll('__APP_NAME__', appName)
|
|
70
|
+
.replaceAll('__LT_VERSION__', `^${ltVersion}`);
|
|
71
|
+
writeFileSync(p, filled);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return { appName, targetDir: resolve(targetDir), ltVersion };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function formatCreateResult({ appName, targetDir }, targetArg) {
|
|
78
|
+
return [
|
|
79
|
+
``,
|
|
80
|
+
`Scaffolded ${appName} → ${targetDir}`,
|
|
81
|
+
``,
|
|
82
|
+
`Next steps:`,
|
|
83
|
+
` cd ${targetArg}`,
|
|
84
|
+
` npm install`,
|
|
85
|
+
` npm run dev`,
|
|
86
|
+
``,
|
|
87
|
+
`Then open http://localhost:5173 and edit src/pages/Home.svelte.`,
|
|
88
|
+
].join('\n');
|
|
89
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@motion-proto/live-tokens",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Design token editor with live CSS variable editing. Svelte 5 + Vite 8.",
|
|
6
6
|
"keywords": [
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"dist-plugin",
|
|
27
27
|
".claude/skills",
|
|
28
28
|
"bin",
|
|
29
|
+
"template",
|
|
29
30
|
"!**/*.test.ts",
|
|
30
31
|
"!**/*.spec.ts",
|
|
31
32
|
"!**/__tests__/**",
|
|
@@ -89,7 +90,8 @@
|
|
|
89
90
|
"check:no-style-imports": "node scripts/check-no-style-imports.mjs",
|
|
90
91
|
"check:editor-font-isolation": "node scripts/check-editor-font-isolation.mjs",
|
|
91
92
|
"check:smoke-install": "bash scripts/smoke-install.sh",
|
|
92
|
-
"
|
|
93
|
+
"check:smoke-create": "bash scripts/smoke-create.sh",
|
|
94
|
+
"prepublishOnly": "npm run check:no-style-imports && npm run check:editor-font-isolation && npm run build:lib && npm run check:smoke-install && npm run check:smoke-create"
|
|
93
95
|
},
|
|
94
96
|
"peerDependencies": {
|
|
95
97
|
"@sveltejs/vite-plugin-svelte": "^7.0",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# __APP_NAME__
|
|
2
|
+
|
|
3
|
+
Scaffolded with [`@motion-proto/live-tokens`](https://github.com/motionproto/live-tokens).
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install
|
|
7
|
+
npm run dev
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Open http://localhost:5173.
|
|
11
|
+
|
|
12
|
+
## What you have
|
|
13
|
+
|
|
14
|
+
This project follows the package's [recommended layout](https://github.com/motionproto/live-tokens#recommended-project-layout): all editable state lives under `src/` and is committed, so `npm install` and upgrades never touch your styles.
|
|
15
|
+
|
|
16
|
+
- `src/pages/Home.svelte` — the starter page. Replace it with your own content.
|
|
17
|
+
- `src/App.svelte` — your routes. `<LiveTokensRouter>` adds the dev-only
|
|
18
|
+
`/editor` (theme tokens) and `/components` (per-component aliases) routes.
|
|
19
|
+
- `src/system/styles/tokens.css` — your theme token vocabulary. The dev server
|
|
20
|
+
writes edits here when you use the in-browser editor.
|
|
21
|
+
- `src/styles/site.css` — themed page typography. Yours to edit.
|
|
22
|
+
|
|
23
|
+
## Editing live
|
|
24
|
+
|
|
25
|
+
Run `npm run dev`, then click **Open Token Editor** on the home page (or visit
|
|
26
|
+
`/editor`). Changes persist to `src/system/styles/tokens.css` and the JSON under
|
|
27
|
+
`src/live-tokens/data/`. The editor is dev-only — `npm run build` ships plain
|
|
28
|
+
CSS variables and the components you used, nothing else.
|
|
29
|
+
|
|
30
|
+
## Adding components
|
|
31
|
+
|
|
32
|
+
The package ships ~25 editable components (Button, Card, Table, Dialog, …).
|
|
33
|
+
Import them from `@motion-proto/live-tokens/components/<Name>.svelte`. To author
|
|
34
|
+
your own editable component, install the Claude Code skills:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx @motion-proto/live-tokens setup-claude
|
|
38
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
node_modules
|
|
2
|
+
dist
|
|
3
|
+
dist-ssr
|
|
4
|
+
*.local
|
|
5
|
+
*.log
|
|
6
|
+
|
|
7
|
+
# Editor-written backups stay local to each machine; the live JSON/CSS commit.
|
|
8
|
+
src/live-tokens/data/themes/_backups/
|
|
9
|
+
src/live-tokens/data/manifests/_backups/
|
|
10
|
+
src/live-tokens/data/component-configs/*/_backups/
|
|
11
|
+
src/system/styles/_backups/
|
|
12
|
+
|
|
13
|
+
.DS_Store
|
|
14
|
+
.vscode/*
|
|
15
|
+
!.vscode/extensions.json
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>__APP_NAME__</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body style="margin: 0;">
|
|
9
|
+
<div id="app"></div>
|
|
10
|
+
<script type="module" src="/src/main.ts"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__APP_NAME__",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"preview": "vite preview",
|
|
10
|
+
"check": "svelte-check --tsconfig ./tsconfig.json"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@motion-proto/live-tokens": "__LT_VERSION__"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
|
17
|
+
"@types/node": "^25.9.1",
|
|
18
|
+
"sass": "^1.98.0",
|
|
19
|
+
"svelte": "^5.55.5",
|
|
20
|
+
"svelte-check": "^4.4.8",
|
|
21
|
+
"typescript": "~6.0.3",
|
|
22
|
+
"vite": "^8.0.14"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { LiveTokensRouter } from '@motion-proto/live-tokens';
|
|
3
|
+
|
|
4
|
+
// <LiveTokensRouter> owns the dev-only /editor and /components routes.
|
|
5
|
+
// Declare your own pages here. Lazy imports keep each page's CSS
|
|
6
|
+
// side-effects out of the editor routes; omit `label` to keep a route
|
|
7
|
+
// reachable by URL but hidden from the overlay nav rail.
|
|
8
|
+
const pages = {
|
|
9
|
+
'/': {
|
|
10
|
+
lazy: () => import('./pages/Home.svelte'),
|
|
11
|
+
label: 'Home',
|
|
12
|
+
icon: 'fa-home',
|
|
13
|
+
source: 'src/pages/Home.svelte',
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<LiveTokensRouter {pages} />
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Token CSS order matters: defaults → editor overrides → fonts. The first two
|
|
2
|
+
// are project-local (the dev plugin writes to them); fonts ship with the package.
|
|
3
|
+
import './system/styles/tokens.css';
|
|
4
|
+
import './live-tokens/data/tokens.generated.css';
|
|
5
|
+
import '@motion-proto/live-tokens/app/fonts.css';
|
|
6
|
+
|
|
7
|
+
import { bootLiveTokens, configureEditor } from '@motion-proto/live-tokens';
|
|
8
|
+
import App from './App.svelte';
|
|
9
|
+
|
|
10
|
+
configureEditor({ storagePrefix: 'app-' });
|
|
11
|
+
|
|
12
|
+
bootLiveTokens(App, '#app');
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
// site.css carries themed page typography (bare h1/p/a rules that consume
|
|
3
|
+
// theme tokens). Imported per-page, not globally, so the editor routes stay
|
|
4
|
+
// theme-immune. It's yours to edit — see src/styles/site.css.
|
|
5
|
+
import '../styles/site.css';
|
|
6
|
+
import Card from '@motion-proto/live-tokens/components/Card.svelte';
|
|
7
|
+
import Button from '@motion-proto/live-tokens/components/Button.svelte';
|
|
8
|
+
import { navigate } from '@motion-proto/live-tokens';
|
|
9
|
+
|
|
10
|
+
const isDev = import.meta.env.DEV;
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<div class="home">
|
|
14
|
+
<section class="stub">
|
|
15
|
+
<Card>
|
|
16
|
+
<span class="eyebrow">Your app lives here</span>
|
|
17
|
+
<h1>Home</h1>
|
|
18
|
+
<p>
|
|
19
|
+
Replace this with your own content. Edit <code>src/pages/Home.svelte</code>
|
|
20
|
+
to get started, or add routes in <code>src/App.svelte</code>. Components
|
|
21
|
+
and theme tokens are editable live while <code>npm run dev</code> is running.
|
|
22
|
+
</p>
|
|
23
|
+
{#if isDev}
|
|
24
|
+
<div class="actions">
|
|
25
|
+
<Button on:click={() => navigate('/editor')}>Open Token Editor</Button>
|
|
26
|
+
<Button variant="secondary" on:click={() => navigate('/components')}>Components</Button>
|
|
27
|
+
</div>
|
|
28
|
+
{/if}
|
|
29
|
+
</Card>
|
|
30
|
+
</section>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
.home {
|
|
35
|
+
display: grid;
|
|
36
|
+
grid-template-columns: repeat(var(--columns-count), 1fr);
|
|
37
|
+
column-gap: var(--columns-gutter);
|
|
38
|
+
max-width: var(--columns-max-width);
|
|
39
|
+
margin: 0 auto;
|
|
40
|
+
padding: var(--space-48) var(--space-32);
|
|
41
|
+
min-height: 100vh;
|
|
42
|
+
align-content: center;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.stub {
|
|
46
|
+
grid-column: 4 / span 6;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.eyebrow {
|
|
50
|
+
display: block;
|
|
51
|
+
font-size: var(--font-size-sm);
|
|
52
|
+
font-weight: var(--font-weight-normal);
|
|
53
|
+
text-transform: uppercase;
|
|
54
|
+
color: var(--text-tertiary);
|
|
55
|
+
margin-bottom: var(--space-8);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
h1 {
|
|
59
|
+
font-family: var(--font-display);
|
|
60
|
+
font-size: var(--font-size-4xl);
|
|
61
|
+
color: var(--text-primary);
|
|
62
|
+
margin: 0 0 var(--space-12);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
p {
|
|
66
|
+
color: var(--text-secondary);
|
|
67
|
+
line-height: 1.6;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
code {
|
|
71
|
+
background: var(--surface-neutral-high);
|
|
72
|
+
padding: 2px 6px;
|
|
73
|
+
border-radius: var(--radius-sm);
|
|
74
|
+
font-family: var(--font-mono, monospace);
|
|
75
|
+
font-size: 0.9em;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.actions {
|
|
79
|
+
display: flex;
|
|
80
|
+
gap: var(--space-12);
|
|
81
|
+
flex-wrap: wrap;
|
|
82
|
+
margin-top: var(--space-20);
|
|
83
|
+
}
|
|
84
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ES2022",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"isolatedModules": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"types": ["vite/client"]
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*.ts", "src/**/*.svelte"]
|
|
17
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import { svelte, vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
|
3
|
+
import { themeFileApi } from '@motion-proto/live-tokens/vite-plugin';
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [
|
|
7
|
+
svelte({ preprocess: vitePreprocess() }),
|
|
8
|
+
// Dev-only: persists editor changes to src/system/styles/tokens.css and
|
|
9
|
+
// the JSON under src/live-tokens/data/. No effect on `vite build`.
|
|
10
|
+
themeFileApi({ tokensCssPath: 'src/system/styles/tokens.css' }),
|
|
11
|
+
],
|
|
12
|
+
});
|