@symbo.ls/mcp 1.0.13 → 1.0.17
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 +86 -32
- package/bin/symbols-mcp.js +846 -9
- package/package.json +2 -2
- package/symbols_mcp/skills/AUDIT.md +2 -0
- package/symbols_mcp/skills/CLI.md +374 -0
- package/symbols_mcp/skills/COMMON_MISTAKES.md +225 -0
- package/symbols_mcp/skills/DEFAULT_COMPONENTS.md +6 -22
- package/symbols_mcp/skills/LEARNINGS.md +1 -1
- package/symbols_mcp/skills/PATTERNS.md +14 -12
- package/symbols_mcp/skills/PROJECT_STRUCTURE.md +148 -37
- package/symbols_mcp/skills/RULES.md +685 -31
- package/symbols_mcp/skills/SDK.md +440 -0
- package/symbols_mcp/skills/SYNTAX.md +22 -19
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbo.ls/mcp",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "MCP server for Symbols.app — documentation search
|
|
3
|
+
"version": "1.0.17",
|
|
4
|
+
"description": "MCP server for Symbols.app — documentation search, code generation, project management, publishing, CLI/SDK reference",
|
|
5
5
|
"mcpName": "io.github.symbo-ls/symbols-mcp",
|
|
6
6
|
"files": [
|
|
7
7
|
"bin/",
|
|
@@ -259,3 +259,5 @@ Produce the following deliverables:
|
|
|
259
259
|
- Project issues (implementation-level) in project-feedback.md
|
|
260
260
|
|
|
261
261
|
Enforce full DOMQL v3 purity across the entire codebase. No exceptions.
|
|
262
|
+
|
|
263
|
+
**CRITICAL: There is NO concept of "known debt", "accepted violations", or "technical debt exceptions" in Symbols audits. Every violation MUST be fixed. Never label a violation as "known debt" or suggest it can be deferred. If the audit finds a Rule 30 violation (direct DOM manipulation), it must be rewritten using DOMQL declarative syntax — not acknowledged and kept. The same applies to ALL rules (27-33). Zero tolerance.**
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
# Symbols CLI Reference (`@symbo.ls/cli`)
|
|
2
|
+
|
|
3
|
+
The `smbls` command-line interface for the Symbols design platform.
|
|
4
|
+
|
|
5
|
+
**Install:** `npm install -g @symbo.ls/cli`
|
|
6
|
+
**Version:** 3.7.5
|
|
7
|
+
**Global command:** `smbls`
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Project Setup
|
|
12
|
+
|
|
13
|
+
### `smbls init [dest]`
|
|
14
|
+
Initialize or add Symbols to a project.
|
|
15
|
+
- `--non-interactive` — disable prompts (requires flags)
|
|
16
|
+
- `--name <name>` — project name
|
|
17
|
+
- `--location <location>` — where to init: root or subfolder
|
|
18
|
+
- `--v2-action <action>` — v2 project action: migrate, root, or subfolder
|
|
19
|
+
- `-y, --yes` — skip confirmation prompts
|
|
20
|
+
|
|
21
|
+
Auto-detects v2 projects and offers migration path.
|
|
22
|
+
|
|
23
|
+
### `smbls create [dir]`
|
|
24
|
+
Create and scaffold a new project.
|
|
25
|
+
- `--workspace` — scaffold only symbols source files (no full repo, dir: ".")
|
|
26
|
+
- `--create-new` — force create new platform project
|
|
27
|
+
- `--link-existing` — force link to existing platform project
|
|
28
|
+
- `--local-only` — local-only (no platform)
|
|
29
|
+
- `--non-interactive` — disable prompts (requires flags)
|
|
30
|
+
- `--project-name <name>` — platform project name
|
|
31
|
+
- `--type <projectType>` — platform projectType
|
|
32
|
+
- `--key <projectKey>` — platform project key
|
|
33
|
+
- `--id <projectId>` — platform project id (for link mode)
|
|
34
|
+
- `--visibility <visibility>` — platform visibility (default: private)
|
|
35
|
+
- `--language <language>` — platform language (default: javascript)
|
|
36
|
+
- `--branch <branch>` — local branch (default: main)
|
|
37
|
+
- `--template <gitUrl>` — override template git repo URL
|
|
38
|
+
- `--package-manager <manager>` — npm or yarn (default: npm)
|
|
39
|
+
- `--no-dependencies` — skip installing dependencies
|
|
40
|
+
- `--no-clone` — create folder instead of cloning from git
|
|
41
|
+
- `--blank-shared-libraries` — create project with blank shared libraries
|
|
42
|
+
- `--domql` — use DOMQL template (default: true)
|
|
43
|
+
- `--remote` — clone feature/remote branch (default: true)
|
|
44
|
+
- `--clean-from-git` — remove starter-kit git repository (default: true)
|
|
45
|
+
- `-v, --verbose` — verbose output
|
|
46
|
+
|
|
47
|
+
### `smbls install`
|
|
48
|
+
Install Symbols into an existing project.
|
|
49
|
+
- `-d, --dev` — run against local server
|
|
50
|
+
- `-f, --fetch` — fetch config after install (default: true)
|
|
51
|
+
- `--framework <framework>` — framework: domql or react
|
|
52
|
+
- `-v, --verbose` — verbose output
|
|
53
|
+
|
|
54
|
+
### `smbls eject`
|
|
55
|
+
Eject from `@symbo.ls/runner` to explicit bundler dependencies.
|
|
56
|
+
- `--no-install` — skip npm install after ejecting
|
|
57
|
+
|
|
58
|
+
Updates package.json, removes @symbo.ls/runner, adds bundler deps, expands .parcelrc for parcel.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Development
|
|
63
|
+
|
|
64
|
+
### `smbls start [entry]`
|
|
65
|
+
Start development server.
|
|
66
|
+
- `-p, --port <port>` — port to use (default from symbols.json or 1234)
|
|
67
|
+
- `--no-cache` — disable build cache
|
|
68
|
+
- `--open` — open browser on start
|
|
69
|
+
- `--bundler <bundler>` — force bundler: parcel, vite, or browser
|
|
70
|
+
|
|
71
|
+
Supports pass-through args to underlying bundler. Auto-selects free port if specified port is busy. Browser mode injects importmap and globals script.
|
|
72
|
+
|
|
73
|
+
### `smbls build [entry]`
|
|
74
|
+
Build project for production.
|
|
75
|
+
- `--no-cache` — disable build cache
|
|
76
|
+
- `--no-optimize` — disable optimization
|
|
77
|
+
- `--no-brender` — skip brender pre-rendering
|
|
78
|
+
- `--out-dir <dir>` — output directory (default from symbols.json or dist)
|
|
79
|
+
- `--bundler <bundler>` — force bundler: parcel, vite, or browser
|
|
80
|
+
|
|
81
|
+
### `smbls brender [entry]`
|
|
82
|
+
Pre-render static pages to HTML using server-side rendering.
|
|
83
|
+
- `--out-dir <dir>` — output directory (default: brenderDistDir from symbols.json, or dist-brender)
|
|
84
|
+
- `--no-isr` — disable ISR (skip client SPA bundle)
|
|
85
|
+
- `--no-prefetch` — disable SSR data prefetching
|
|
86
|
+
- `-w, --watch` — watch for changes and re-render
|
|
87
|
+
|
|
88
|
+
Output: `dist-brender/` with static HTML, metadata, CSS, optional client bundle.
|
|
89
|
+
|
|
90
|
+
### `smbls deploy`
|
|
91
|
+
Deploy project to hosting providers.
|
|
92
|
+
- `--provider <provider>` — deploy target: symbols, cloudflare, vercel, netlify, github-pages
|
|
93
|
+
- `--init` — initialize deployment config without deploying
|
|
94
|
+
- `--out-dir <dir>` — output directory for build
|
|
95
|
+
- `--bundler <bundler>` — force bundler: parcel, vite, or browser
|
|
96
|
+
|
|
97
|
+
Creates provider-specific config files (wrangler.jsonc, vercel.json, netlify.toml, GitHub Actions workflow).
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Sync & Configuration
|
|
102
|
+
|
|
103
|
+
### `smbls fetch`
|
|
104
|
+
Pull design system and project config from the Symbols platform.
|
|
105
|
+
- `-d, --dev` — run against local server
|
|
106
|
+
- `-v, --verbose` — verbose output
|
|
107
|
+
- `--convert` — convert fetched config (default: true)
|
|
108
|
+
- `--schema` — include schema (default: false)
|
|
109
|
+
- `--force` — force override local changes
|
|
110
|
+
- `--update` — override local changes from platform
|
|
111
|
+
- `-y, --yes` — skip confirmation prompts
|
|
112
|
+
- `--dist-dir <dir>` — directory to import files to
|
|
113
|
+
- `--skip-confirm` — skip confirmation for local changes
|
|
114
|
+
- `--non-interactive` — disable interactive prompts
|
|
115
|
+
|
|
116
|
+
Includes git-based or mtime heuristic detection of local changes.
|
|
117
|
+
|
|
118
|
+
### `smbls sync`
|
|
119
|
+
Bidirectional sync with remote server (two-way merge with conflict resolution).
|
|
120
|
+
- `-b, --branch <branch>` — branch to sync
|
|
121
|
+
- `-m, --message <message>` — commit message
|
|
122
|
+
- `-d, --dev` — run against local server
|
|
123
|
+
- `-v, --verbose` — verbose output
|
|
124
|
+
- `--mode <mode>` — sync mode: merge, remote, local, cancel
|
|
125
|
+
- `--conflict-resolution <mode>` — conflict resolution: local or remote
|
|
126
|
+
- `--non-interactive` — disable interactive prompts
|
|
127
|
+
- `-y, --yes` — skip confirmation prompts
|
|
128
|
+
|
|
129
|
+
Uses 3-way merge: local, remote, and base comparison.
|
|
130
|
+
|
|
131
|
+
### `smbls push`
|
|
132
|
+
Push local changes to the Symbols platform.
|
|
133
|
+
- `-m, --message <message>` — commit message
|
|
134
|
+
- `-v, --verbose` — verbose output
|
|
135
|
+
- `-d, --dev` — run against local server
|
|
136
|
+
- `--non-interactive` — disable interactive prompts
|
|
137
|
+
- `-y, --yes` — skip confirmation prompts
|
|
138
|
+
|
|
139
|
+
Shows diffs before confirmation.
|
|
140
|
+
|
|
141
|
+
### `smbls publish`
|
|
142
|
+
Build and publish project to preview environments.
|
|
143
|
+
- `--env <envs...>` — environments to publish to (development, staging, production)
|
|
144
|
+
- `--all` — publish to all environments
|
|
145
|
+
- `--non-interactive` — disable prompts (requires --env or --all)
|
|
146
|
+
- `-v, --verbose` — verbose output
|
|
147
|
+
|
|
148
|
+
Preview URLs are auto-generated for each environment.
|
|
149
|
+
|
|
150
|
+
### `smbls config`
|
|
151
|
+
Interactively configure Symbols project settings.
|
|
152
|
+
- `--non-interactive` — disable prompts
|
|
153
|
+
- `--dist-dir <dir>` — set distribution directory
|
|
154
|
+
- `--owner <owner>` — Symbols username
|
|
155
|
+
- `--key <key>` — project key
|
|
156
|
+
- `--branch <branch>` — default branch
|
|
157
|
+
- `--version <version>` — version
|
|
158
|
+
- `--dir <dir>` — Symbols source directory
|
|
159
|
+
- `--runtime <runtime>` — environment: node, bun, deno, browser
|
|
160
|
+
- `--bundler <bundler>` — build tool: parcel, vite, turbopack, webpack, rollup
|
|
161
|
+
- `--package-manager <pm>` — npm, yarn, pnpm, bun
|
|
162
|
+
- `--api-base-url <url>` — API base URL
|
|
163
|
+
- `--deploy <target>` — deploy target: symbols, cloudflare, vercel, netlify, github-pages
|
|
164
|
+
|
|
165
|
+
Updates `symbols.json` and `.symbols_local/config.json`.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Collaboration & Authentication
|
|
170
|
+
|
|
171
|
+
### `smbls login`
|
|
172
|
+
Sign in to Symbols. Opens browser for OAuth/auth flow, stores credentials in `~/.smblsrc`.
|
|
173
|
+
|
|
174
|
+
### `smbls signup`
|
|
175
|
+
Create a new Symbols account.
|
|
176
|
+
|
|
177
|
+
### `smbls logout`
|
|
178
|
+
Sign out of Symbols (clears local credentials).
|
|
179
|
+
|
|
180
|
+
### `smbls collab`
|
|
181
|
+
Connect to real-time collaboration socket and live-sync changes.
|
|
182
|
+
- `-b, --branch <branch>` — branch to collaborate on
|
|
183
|
+
- `--no-sync-first` — skip initial sync (not recommended)
|
|
184
|
+
- `-l, --live` — enable live collaboration mode (default: false)
|
|
185
|
+
- `-d, --debounce-ms <ms>` — local changes debounce (default: 200ms)
|
|
186
|
+
- `-v, --verbose` — verbose output
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Project Management
|
|
191
|
+
|
|
192
|
+
### `smbls project <subcommand>`
|
|
193
|
+
Project lifecycle management with subcommands:
|
|
194
|
+
|
|
195
|
+
| Subcommand | Description |
|
|
196
|
+
|---|---|
|
|
197
|
+
| `create` | Create a new project |
|
|
198
|
+
| `link` | Link local project to platform |
|
|
199
|
+
| `delete` | Delete a project |
|
|
200
|
+
| `update` | Update project metadata |
|
|
201
|
+
| `list` | List projects |
|
|
202
|
+
| `duplicate` | Duplicate a project |
|
|
203
|
+
| `restore` | Restore a project |
|
|
204
|
+
| `libs` | Library management (add, remove, list, available) |
|
|
205
|
+
| `members` | Members management (add, remove, list, invite, role, acceptInvite, inviteLink) |
|
|
206
|
+
| `versions` | Versions management (create, get, list, latest, publish, snapshot, update) |
|
|
207
|
+
| `environments` | Environments management (list, activate, publish, upsert, update, delete) |
|
|
208
|
+
| `pipeline` | Pipeline management (promote) |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## File Management
|
|
213
|
+
|
|
214
|
+
### `smbls files <subcommand>`
|
|
215
|
+
Upload, download, and manage project files.
|
|
216
|
+
|
|
217
|
+
| Subcommand | Description | Key Options |
|
|
218
|
+
|---|---|---|
|
|
219
|
+
| `list` | List project-linked files | `--remote`, `--uploads`, `--limit <n>`, `--search <q>` |
|
|
220
|
+
| `upload <paths...>` | Upload files to project | `--key`, `--visibility`, `--tags`, `--metadata`, `--mime`, `--overwrite` |
|
|
221
|
+
| `download` | Download a file | `--key`, `--out <path>`, `--remote` |
|
|
222
|
+
| `rm` | Remove file from project | `--key`, `--local-only`, `--force-remote` |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## AI Assistant
|
|
227
|
+
|
|
228
|
+
### `smbls ask [question...]`
|
|
229
|
+
Chat with AI about your Symbols project.
|
|
230
|
+
- `--provider <provider>` — AI provider: claude, openai, gemini, ollama, symbols
|
|
231
|
+
- `--model <model>` — model name
|
|
232
|
+
- `--init` — configure AI settings and MCP
|
|
233
|
+
|
|
234
|
+
**Supported providers and models:**
|
|
235
|
+
| Provider | Models |
|
|
236
|
+
|---|---|
|
|
237
|
+
| Claude | claude-sonnet-4-6, claude-opus-4-6, claude-haiku-4-5-20251001 |
|
|
238
|
+
| OpenAI | gpt-4o, gpt-4o-mini, o3-mini |
|
|
239
|
+
| Gemini | gemini-2.5-pro, gemini-2.5-flash |
|
|
240
|
+
| Ollama | llama3.3, codellama, mistral, deepseek-coder-v2 (local) |
|
|
241
|
+
|
|
242
|
+
Config stored in `~/.smblsrc`. Environment variables: `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## Utilities
|
|
247
|
+
|
|
248
|
+
### `smbls convert [src] [dest]`
|
|
249
|
+
Convert DOMQL components to other frameworks.
|
|
250
|
+
- `--react` — convert to React
|
|
251
|
+
- `--angular` — convert to Angular
|
|
252
|
+
- `--vue2` — convert to Vue 2
|
|
253
|
+
- `--vue3` — convert to Vue 3
|
|
254
|
+
- `-o, --only <components>` — only convert specific components (comma-separated)
|
|
255
|
+
- `-m, --merge <dir>` — recursive merge files into dest
|
|
256
|
+
- `-v, --verbose` — verbose mode
|
|
257
|
+
|
|
258
|
+
### `smbls migrate`
|
|
259
|
+
Migrate a v2 Symbols project to v3.
|
|
260
|
+
- `--yes` — skip confirmation
|
|
261
|
+
- `--non-interactive` — disable all prompts
|
|
262
|
+
|
|
263
|
+
Renames `.symbols/` to `.symbols_local/`, `smbls/` to `symbols/`, creates missing `symbols/app.js`, rewrites `symbols/index.js` to v3 format.
|
|
264
|
+
|
|
265
|
+
### `smbls validate [target]`
|
|
266
|
+
Validate DOMQL syntax in source files.
|
|
267
|
+
- Uses esbuild to check JS/TS/JSX/TSX syntax
|
|
268
|
+
- Reports violations, warnings, and compliance scores
|
|
269
|
+
|
|
270
|
+
### `smbls clean`
|
|
271
|
+
Clean Symbols temporary files.
|
|
272
|
+
|
|
273
|
+
### `smbls sdk [method] [args...]`
|
|
274
|
+
Proxy SDK service methods from the terminal.
|
|
275
|
+
- `-l, --list` — list all available SDK methods
|
|
276
|
+
- `-s, --service <name>` — filter methods by service name
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
smbls sdk --list # List all methods
|
|
280
|
+
smbls sdk --list --service auth # Filter by service
|
|
281
|
+
smbls sdk getProjects # Call method
|
|
282
|
+
smbls sdk getProjectByKey '{"key":"myapp"}' # Call with arguments
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### `smbls link-packages`
|
|
286
|
+
Link all smbls packages into the project.
|
|
287
|
+
- `-c, --capture` — capture and write all package names
|
|
288
|
+
- `-j, --join` — join all links into one command (default: true)
|
|
289
|
+
|
|
290
|
+
### `smbls servers`
|
|
291
|
+
List and switch CLI servers (API base URLs).
|
|
292
|
+
- `-s, --select` — interactively select active server
|
|
293
|
+
|
|
294
|
+
### `smbls completion [shell]`
|
|
295
|
+
Generate shell completion script.
|
|
296
|
+
- `--install` — print install instructions
|
|
297
|
+
|
|
298
|
+
### `smbls github <subcommand>`
|
|
299
|
+
GitHub integration helpers.
|
|
300
|
+
- `connect` — connect GitHub repository
|
|
301
|
+
- `initActions` — initialize GitHub Actions workflow
|
|
302
|
+
- `sync` — sync with GitHub
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Configuration Files
|
|
307
|
+
|
|
308
|
+
### `symbols.json` (project root)
|
|
309
|
+
Main project configuration:
|
|
310
|
+
- `owner` — Symbols username
|
|
311
|
+
- `key` — project identifier
|
|
312
|
+
- `dir` — symbols source directory
|
|
313
|
+
- `branch` — git branch (default: main)
|
|
314
|
+
- `entry` — bundler entry point
|
|
315
|
+
- `port` — dev server port
|
|
316
|
+
- `distDir` — build output directory
|
|
317
|
+
- `brenderDistDir` — brender output directory
|
|
318
|
+
- `brender` — enable pre-rendering
|
|
319
|
+
- `runtime` — node, bun, deno, or browser
|
|
320
|
+
- `bundler` — parcel, vite, etc.
|
|
321
|
+
- `packageManager` — npm, yarn, pnpm, bun
|
|
322
|
+
- `libraries` / `librariesDir` — shared library config
|
|
323
|
+
- `designSystem` — design system with buckets
|
|
324
|
+
|
|
325
|
+
### `.symbols_local/config.json` (local)
|
|
326
|
+
Local machine configuration:
|
|
327
|
+
- `owner` — local username
|
|
328
|
+
- `branch` — active branch
|
|
329
|
+
- `projectKey` — linked project key
|
|
330
|
+
- `projectId` — platform project ID
|
|
331
|
+
- `apiBaseUrl` — API endpoint
|
|
332
|
+
|
|
333
|
+
### `~/.smblsrc` (global)
|
|
334
|
+
Global credentials and AI configuration.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## Common Workflows
|
|
339
|
+
|
|
340
|
+
### New project from scratch
|
|
341
|
+
```bash
|
|
342
|
+
smbls create my-app
|
|
343
|
+
cd my-app
|
|
344
|
+
smbls start
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Add Symbols to existing project
|
|
348
|
+
```bash
|
|
349
|
+
cd existing-project
|
|
350
|
+
smbls init
|
|
351
|
+
smbls install
|
|
352
|
+
smbls start
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### Fetch, edit, push cycle
|
|
356
|
+
```bash
|
|
357
|
+
smbls fetch # pull latest from platform
|
|
358
|
+
# ... edit components ...
|
|
359
|
+
smbls push -m "updated header"
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### Deploy to production
|
|
363
|
+
```bash
|
|
364
|
+
smbls build
|
|
365
|
+
smbls deploy --provider cloudflare
|
|
366
|
+
# or
|
|
367
|
+
smbls publish --env production
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Migrate v2 to v3
|
|
371
|
+
```bash
|
|
372
|
+
smbls migrate --yes
|
|
373
|
+
smbls start
|
|
374
|
+
```
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Common Mistakes — Wrong vs Correct DOMQL v3 Patterns
|
|
2
|
+
|
|
3
|
+
This is a zero-tolerance reference. Every pattern in the "Wrong" column is FORBIDDEN. The audit tool catches all of them. There is no concept of "known debt" — every violation must be fixed to 100%.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Colors — use design system tokens, never hex/rgb
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
// ❌ WRONG — raw hex values
|
|
11
|
+
color: '#202124', background: '#f1f3f4', borderColor: '#dadce0'
|
|
12
|
+
|
|
13
|
+
// ✅ CORRECT — named tokens from designSystem.color
|
|
14
|
+
color: 'text', background: 'headerBg', borderColor: 'border'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 2. CSS — flatten at root level, never use `style: {}` wrapper
|
|
20
|
+
|
|
21
|
+
```js
|
|
22
|
+
// ❌ WRONG — CSS inside style: {} block
|
|
23
|
+
FileName: {
|
|
24
|
+
tag: 'input',
|
|
25
|
+
style: { fontSize: '16px', border: 'none', color: '#202124' }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ✅ CORRECT — CSS flat as props
|
|
29
|
+
FileName: {
|
|
30
|
+
tag: 'input',
|
|
31
|
+
fontSize: 'A', border: 'none', color: 'text'
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 3. Spacing — use design system tokens, never raw px
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
// ❌ WRONG — raw pixel values
|
|
41
|
+
padding: '4px 10px', height: '30px', width: '1px', gap: '4px'
|
|
42
|
+
|
|
43
|
+
// ✅ CORRECT — spacing tokens
|
|
44
|
+
padding: 'X Y', height: 'B', borderLeft: '1px solid border', gap: 'X'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 4. Icons — use Icon component + `designSystem/icons`, never inline HTML
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
// ❌ WRONG — inline HTML strings
|
|
53
|
+
BtnBold: { extends: 'ToolbarBtn', html: '<b>B</b>' }
|
|
54
|
+
BtnColorRed: { html: '<span style="color:#d93025;font-weight:bold">A</span>' }
|
|
55
|
+
|
|
56
|
+
// ✅ CORRECT — Icon component with designSystem/icons
|
|
57
|
+
BtnBold: { extends: 'ToolbarBtn', Icon: { extends: 'Icon', icon: 'bold', width: 'A', height: 'A' } }
|
|
58
|
+
BtnColorRed: { extends: 'ToolbarBtn', color: 'danger', Icon: { extends: 'Icon', icon: 'colorA', width: 'A', height: 'A' } }
|
|
59
|
+
|
|
60
|
+
// designSystem/icons.js:
|
|
61
|
+
// bold: '<svg width="24" height="24" viewBox="0 0 24 24"><path d="..."/></svg>'
|
|
62
|
+
// colorA: '<svg width="24" height="24" viewBox="0 0 24 24"><path d="..."/></svg>'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 5. Select options — use children + childExtends, never raw HTML
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
// ❌ WRONG — raw html string of option tags
|
|
71
|
+
FontSizeSelect: {
|
|
72
|
+
html: '<option value="12">12</option><option value="13" selected>13</option>...'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ✅ CORRECT — declarative children with state
|
|
76
|
+
FontSizeSelect: {
|
|
77
|
+
children: [10, 11, 12, 13, 14, 16, 18, 20, 24, 28, 32].map(sz => ({
|
|
78
|
+
label: String(sz), value: String(sz)
|
|
79
|
+
})),
|
|
80
|
+
childrenAs: 'state',
|
|
81
|
+
childExtends: 'FontSizeOption',
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 6. Grids/tables — declarative DOMQL, never `document.createElement`
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
// ❌ WRONG — imperative DOM building
|
|
91
|
+
GridWrapper: {
|
|
92
|
+
onRender: (el) => {
|
|
93
|
+
const table = document.createElement('table')
|
|
94
|
+
const th = document.createElement('th')
|
|
95
|
+
th.textContent = colLabel(c)
|
|
96
|
+
headRow.appendChild(th)
|
|
97
|
+
// ... hundreds of lines of imperative DOM
|
|
98
|
+
document.getElementById(`cell-${r}-${c}`)?.querySelector('input')?.focus()
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ✅ CORRECT — fully declarative DOMQL
|
|
103
|
+
BodyRows: {
|
|
104
|
+
children: (el) => {
|
|
105
|
+
const rs = el.getRootState()
|
|
106
|
+
return rs.grid.map((row, r) => ({ cells: row.map((v, c) => ({ v, r, c })) }))
|
|
107
|
+
},
|
|
108
|
+
childrenAs: 'state',
|
|
109
|
+
childExtends: 'SpreadsheetRow',
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
SpreadsheetCell: {
|
|
113
|
+
CellInput: {
|
|
114
|
+
value: (el, s) => s.v,
|
|
115
|
+
onFocus: (e, el, s) => el.call('selectCell', { r: s.r, c: s.c }),
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 7. Dynamic text — reactive `text:` prop, never polling with `el.node.textContent`
|
|
123
|
+
|
|
124
|
+
```js
|
|
125
|
+
// ❌ WRONG — setInterval polling with el.node.textContent
|
|
126
|
+
CellLabel: {
|
|
127
|
+
onRender: (el) => {
|
|
128
|
+
setInterval(() => {
|
|
129
|
+
el.node.textContent = colLabel(rs.sel.c) + (rs.sel.r + 1)
|
|
130
|
+
}, 50)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ✅ CORRECT — reactive text prop
|
|
135
|
+
CellLabel: {
|
|
136
|
+
text: (el) => {
|
|
137
|
+
const rs = el.getRootState()
|
|
138
|
+
return rs ? el.call('colLabel', rs.sel.c) + (rs.sel.r + 1) : 'A1'
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## 8. Input value — reactive `value:` prop, never polling with `el.node.value`
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
// ❌ WRONG — setInterval writing el.node.value
|
|
149
|
+
FormulaInput: {
|
|
150
|
+
onRender: (el) => {
|
|
151
|
+
setInterval(() => {
|
|
152
|
+
if (document.activeElement !== el.node) return
|
|
153
|
+
el.node.value = rs.formulaBarValue
|
|
154
|
+
}, 60)
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ✅ CORRECT — reactive value prop
|
|
159
|
+
FormulaInput: {
|
|
160
|
+
value: (el) => el.getRootState()?.formulaBarValue || '',
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 9. State — use `s` directly with `childrenAs: 'state'`, never `el.parent.state`
|
|
167
|
+
|
|
168
|
+
```js
|
|
169
|
+
// ❌ WRONG — parent state traversal
|
|
170
|
+
value: (el) => el.parent.state.v,
|
|
171
|
+
onFocus: (e, el) => el.call('selectCell', { r: el.parent.state.r, c: el.parent.state.c })
|
|
172
|
+
|
|
173
|
+
// ✅ CORRECT — s inherited automatically via childrenAs: 'state'
|
|
174
|
+
value: (el, s) => s.v,
|
|
175
|
+
onFocus: (e, el, s) => el.call('selectCell', { r: s.r, c: s.c })
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## 10. Event handlers — correct signature for root vs local state
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
// ❌ WRONG — s is local state, not root — breaks for global updates
|
|
184
|
+
onInput: (e, el, s) => s.update({ filename: e.target.value })
|
|
185
|
+
|
|
186
|
+
// ✅ CORRECT — el.getRootState() for global state, s for local inherited state
|
|
187
|
+
onInput: (e, el) => el.getRootState().update({ filename: e.target.value })
|
|
188
|
+
onBlur: (e, el, s) => el.call('commitEdit', { r: s.r, c: s.c, val: e.target.value })
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 11. Rich text — DOMQL children with tokens, never inline `style=`
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
// ❌ WRONG — html string with inline style
|
|
197
|
+
PoweredBy: { html: 'Built with <strong style="color:#1a73e8">Symbols</strong>' }
|
|
198
|
+
|
|
199
|
+
// ✅ CORRECT — DOMQL children with token colors
|
|
200
|
+
PoweredBy: {
|
|
201
|
+
flow: 'x',
|
|
202
|
+
gap: 'X',
|
|
203
|
+
Prefix: { text: 'Built with' },
|
|
204
|
+
Sym: { tag: 'strong', color: 'accent', text: 'Symbols' },
|
|
205
|
+
Ver: { tag: 'span', text: ' · smbls@latest' },
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## 12. Token alignment — aligned elements must share `fontSize`
|
|
212
|
+
|
|
213
|
+
Spacing tokens are em-based. Mixed `fontSize` on siblings causes the same token to resolve to different px values.
|
|
214
|
+
|
|
215
|
+
```js
|
|
216
|
+
// ❌ WRONG — mixed fontSize, E resolves differently
|
|
217
|
+
ColHeaderCell: { fontSize: 'Z1', width: 'E', ... }
|
|
218
|
+
SpreadsheetCell: { fontSize: 'Z2', width: 'E', ... } // wider than header!
|
|
219
|
+
|
|
220
|
+
// ✅ CORRECT — all grid elements share the same fontSize
|
|
221
|
+
ColHeaderCell: { fontSize: 'Z1', width: 'E', ... }
|
|
222
|
+
SpreadsheetCell: { fontSize: 'Z1', width: 'E', ... }
|
|
223
|
+
RowNumberCell: { fontSize: 'Z1', width: 'C', ... }
|
|
224
|
+
CornerCell: { fontSize: 'Z1', width: 'C', ... }
|
|
225
|
+
```
|
|
@@ -1341,17 +1341,9 @@ export const CircleButton = {
|
|
|
1341
1341
|
```js
|
|
1342
1342
|
export const CircleProgress = {
|
|
1343
1343
|
tag: 'progress',
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
}) => props.max,
|
|
1348
|
-
progress: ({
|
|
1349
|
-
props
|
|
1350
|
-
}) => props.progress,
|
|
1351
|
-
value: ({
|
|
1352
|
-
props
|
|
1353
|
-
}) => props.value,
|
|
1354
|
-
},
|
|
1344
|
+
max: ({ props }) => props.max,
|
|
1345
|
+
progress: ({ props }) => props.progress,
|
|
1346
|
+
value: ({ props }) => props.value,
|
|
1355
1347
|
boxSize: 'D D',
|
|
1356
1348
|
value: 0.73,
|
|
1357
1349
|
round: '100%',
|
|
@@ -2655,17 +2647,9 @@ export const Pills = {
|
|
|
2655
2647
|
```js
|
|
2656
2648
|
export const Progress = {
|
|
2657
2649
|
tag: 'progress',
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
}) => props.max,
|
|
2662
|
-
progress: ({
|
|
2663
|
-
props
|
|
2664
|
-
}) => props.progress,
|
|
2665
|
-
value: ({
|
|
2666
|
-
props
|
|
2667
|
-
}) => props.value,
|
|
2668
|
-
},
|
|
2650
|
+
max: ({ props }) => props.max,
|
|
2651
|
+
progress: ({ props }) => props.progress,
|
|
2652
|
+
value: ({ props }) => props.value,
|
|
2669
2653
|
height: 'X',
|
|
2670
2654
|
minWidth: 'F3',
|
|
2671
2655
|
round: 'Y',
|
|
@@ -176,7 +176,7 @@ onClick: (e, el, s) => {
|
|
|
176
176
|
|
|
177
177
|
## SPA Navigation — preventDefault Required
|
|
178
178
|
|
|
179
|
-
When using `tag: 'a'` with `
|
|
179
|
+
When using `tag: 'a'` with `href: '/'` AND an `onClick` handler, both the handler and the browser's default navigation fire. Always call `e.preventDefault()`.
|
|
180
180
|
|
|
181
181
|
```js
|
|
182
182
|
export const NavLink = {
|