slexkit 0.2.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/AGENTS.slexkit.md +29 -0
- package/CHANGELOG.md +90 -0
- package/LICENSE +21 -0
- package/README.md +165 -0
- package/README.zh-CN.md +165 -0
- package/dist/ai/llms-authoring.txt +44 -0
- package/dist/ai/llms-components.txt +669 -0
- package/dist/ai/llms-full.txt +6586 -0
- package/dist/ai/llms-runtime.txt +1475 -0
- package/dist/ai/llms-toolhost.txt +295 -0
- package/dist/ai/llms.txt +69 -0
- package/dist/ai/slexkit-ai-manifest.json +2922 -0
- package/dist/base.css +621 -0
- package/dist/chunks/accordion-5f0nvjjm.js +376 -0
- package/dist/chunks/accordion-830dw78f.js +221 -0
- package/dist/chunks/accordion-cfjyxw93.js +630 -0
- package/dist/chunks/accordion-cw5r75jm.js +424 -0
- package/dist/chunks/accordion-ehnhpeca.js +492 -0
- package/dist/chunks/accordion-hzyrngd6.js +2377 -0
- package/dist/chunks/accordion-nw12ytps.js +6823 -0
- package/dist/components/accordion.js +163 -0
- package/dist/components/badge.js +80 -0
- package/dist/components/button.css +114 -0
- package/dist/components/button.js +16 -0
- package/dist/components/callout.js +154 -0
- package/dist/components/card.js +95 -0
- package/dist/components/checkbox.js +114 -0
- package/dist/components/choice.css +165 -0
- package/dist/components/code-block.js +264 -0
- package/dist/components/collapsible.js +111 -0
- package/dist/components/column.js +49 -0
- package/dist/components/content.css +474 -0
- package/dist/components/disclosure.css +162 -0
- package/dist/components/display.css +259 -0
- package/dist/components/divider.js +98 -0
- package/dist/components/feedback.css +219 -0
- package/dist/components/grid.js +67 -0
- package/dist/components/index.js +13364 -0
- package/dist/components/input.css +1247 -0
- package/dist/components/input.js +384 -0
- package/dist/components/link.js +77 -0
- package/dist/components/progress.js +111 -0
- package/dist/components/radio-group.js +189 -0
- package/dist/components/row.js +200 -0
- package/dist/components/section.js +161 -0
- package/dist/components/select.css +260 -0
- package/dist/components/select.js +16 -0
- package/dist/components/slider.css +125 -0
- package/dist/components/slider.js +175 -0
- package/dist/components/specs.js +1090 -0
- package/dist/components/stat.js +178 -0
- package/dist/components/submit.css +9 -0
- package/dist/components/submit.js +77 -0
- package/dist/components/switch.css +114 -0
- package/dist/components/switch.js +114 -0
- package/dist/components/table.js +157 -0
- package/dist/components/tabs.css +192 -0
- package/dist/components/tabs.js +17 -0
- package/dist/components/text-input.css +245 -0
- package/dist/components/text.js +50 -0
- package/dist/components/toast.js +240 -0
- package/dist/components/tooling.css +1009 -0
- package/dist/components/tooling.js +48951 -0
- package/dist/runtime.cjs +3728 -0
- package/dist/runtime.js +3686 -0
- package/dist/slexkit.cjs +18539 -0
- package/dist/slexkit.css +4776 -0
- package/dist/slexkit.js +18497 -0
- package/dist/tooling.js +59141 -0
- package/dist/types/components/accordion.d.ts +2 -0
- package/dist/types/components/badge.d.ts +2 -0
- package/dist/types/components/button.d.ts +2 -0
- package/dist/types/components/callout.d.ts +2 -0
- package/dist/types/components/card.d.ts +2 -0
- package/dist/types/components/checkbox.d.ts +2 -0
- package/dist/types/components/code-block.d.ts +2 -0
- package/dist/types/components/collapsible.d.ts +2 -0
- package/dist/types/components/column.d.ts +2 -0
- package/dist/types/components/divider.d.ts +2 -0
- package/dist/types/components/entries/accordion.d.ts +3 -0
- package/dist/types/components/entries/badge.d.ts +3 -0
- package/dist/types/components/entries/button.d.ts +3 -0
- package/dist/types/components/entries/callout.d.ts +3 -0
- package/dist/types/components/entries/card.d.ts +3 -0
- package/dist/types/components/entries/checkbox.d.ts +3 -0
- package/dist/types/components/entries/code-block.d.ts +3 -0
- package/dist/types/components/entries/collapsible.d.ts +3 -0
- package/dist/types/components/entries/column.d.ts +3 -0
- package/dist/types/components/entries/divider.d.ts +3 -0
- package/dist/types/components/entries/grid.d.ts +3 -0
- package/dist/types/components/entries/input.d.ts +3 -0
- package/dist/types/components/entries/link.d.ts +3 -0
- package/dist/types/components/entries/progress.d.ts +3 -0
- package/dist/types/components/entries/radio-group.d.ts +3 -0
- package/dist/types/components/entries/row.d.ts +3 -0
- package/dist/types/components/entries/section.d.ts +3 -0
- package/dist/types/components/entries/select.d.ts +3 -0
- package/dist/types/components/entries/slider.d.ts +3 -0
- package/dist/types/components/entries/specs.d.ts +1 -0
- package/dist/types/components/entries/stat.d.ts +3 -0
- package/dist/types/components/entries/submit.d.ts +3 -0
- package/dist/types/components/entries/switch.d.ts +3 -0
- package/dist/types/components/entries/table.d.ts +3 -0
- package/dist/types/components/entries/tabs.d.ts +3 -0
- package/dist/types/components/entries/text.d.ts +3 -0
- package/dist/types/components/entries/toast.d.ts +3 -0
- package/dist/types/components/entries/tooling.d.ts +1 -0
- package/dist/types/components/grid.d.ts +2 -0
- package/dist/types/components/index.d.ts +6 -0
- package/dist/types/components/input.d.ts +2 -0
- package/dist/types/components/link.d.ts +2 -0
- package/dist/types/components/progress.d.ts +2 -0
- package/dist/types/components/radio-group.d.ts +2 -0
- package/dist/types/components/row.d.ts +2 -0
- package/dist/types/components/section.d.ts +2 -0
- package/dist/types/components/select.d.ts +2 -0
- package/dist/types/components/slider.d.ts +2 -0
- package/dist/types/components/spec-helpers.d.ts +23 -0
- package/dist/types/components/spec-registry.d.ts +12 -0
- package/dist/types/components/spec-schema.d.ts +74 -0
- package/dist/types/components/specs.d.ts +2 -0
- package/dist/types/components/stat.d.ts +2 -0
- package/dist/types/components/submit.d.ts +2 -0
- package/dist/types/components/svelte/adapter.d.ts +3 -0
- package/dist/types/components/svelte/bindProps.d.ts +2 -0
- package/dist/types/components/svelte/helpers.d.ts +33 -0
- package/dist/types/components/svelte/layout/balancedTiles.d.ts +14 -0
- package/dist/types/components/svelte/types.d.ts +12 -0
- package/dist/types/components/switch.d.ts +2 -0
- package/dist/types/components/table.d.ts +2 -0
- package/dist/types/components/tabs.d.ts +2 -0
- package/dist/types/components/text.d.ts +2 -0
- package/dist/types/components/toast.d.ts +2 -0
- package/dist/types/components/tooling.d.ts +2 -0
- package/dist/types/components-svelte.d.ts +5 -0
- package/dist/types/engine/component-scope.d.ts +14 -0
- package/dist/types/engine/component-state.d.ts +9 -0
- package/dist/types/engine/diagnostics.d.ts +24 -0
- package/dist/types/engine/engineering.d.ts +11 -0
- package/dist/types/engine/eval.d.ts +5 -0
- package/dist/types/engine/index.d.ts +26 -0
- package/dist/types/engine/markdown-runtime.d.ts +33 -0
- package/dist/types/engine/merge.d.ts +1 -0
- package/dist/types/engine/reactive.d.ts +11 -0
- package/dist/types/engine/registry.d.ts +4 -0
- package/dist/types/engine/renderer.d.ts +6 -0
- package/dist/types/engine/sandbox-runner.d.ts +2 -0
- package/dist/types/engine/secure-runtime.d.ts +214 -0
- package/dist/types/engine/store.d.ts +12 -0
- package/dist/types/engine/types.d.ts +58 -0
- package/dist/types/icons/manager.d.ts +17 -0
- package/dist/types/icons/phosphor.d.ts +45 -0
- package/dist/types/index.d.ts +61 -0
- package/dist/types/runtime.d.ts +32 -0
- package/dist/types/toolhost/index.d.ts +78 -0
- package/dist/types/tooling-umd.d.ts +47 -0
- package/dist/types/version.d.ts +8 -0
- package/dist/umd/slexkit.tooling.umd.js +66553 -0
- package/dist/umd/slexkit.umd.js +18552 -0
- package/package.json +136 -0
- package/scripts/cli.mjs +47 -0
- package/skills/slexkit/SKILL.md +27 -0
- package/skills/slexkit-author/SKILL.md +50 -0
- package/skills/slexkit-host-integration/SKILL.md +33 -0
- package/skills/slexkit-secure-runtime/SKILL.md +31 -0
- package/skills/slexkit-toolhost/SKILL.md +38 -0
- package/skills/slexkit-update/SKILL.md +23 -0
- package/src/components/svelte/InlineIcon.svelte +66 -0
- package/src/components/svelte/adapter.ts +76 -0
- package/src/components/svelte/bindProps.ts +9 -0
- package/src/components/svelte/content/Badge.svelte +19 -0
- package/src/components/svelte/content/Callout.svelte +57 -0
- package/src/components/svelte/content/CodeBlock.svelte +130 -0
- package/src/components/svelte/content/Divider.svelte +21 -0
- package/src/components/svelte/content/Link.svelte +21 -0
- package/src/components/svelte/content/Section.svelte +24 -0
- package/src/components/svelte/content/Table.svelte +44 -0
- package/src/components/svelte/disclosure/Accordion.svelte +100 -0
- package/src/components/svelte/disclosure/Collapsible.svelte +45 -0
- package/src/components/svelte/display/Stat.svelte +102 -0
- package/src/components/svelte/display/Text.svelte +11 -0
- package/src/components/svelte/feedback/Progress.svelte +34 -0
- package/src/components/svelte/feedback/Toast.svelte +105 -0
- package/src/components/svelte/helpers.ts +148 -0
- package/src/components/svelte/input/Button.svelte +78 -0
- package/src/components/svelte/input/Checkbox.svelte +52 -0
- package/src/components/svelte/input/Input.svelte +202 -0
- package/src/components/svelte/input/RadioGroup.svelte +71 -0
- package/src/components/svelte/input/Select.svelte +220 -0
- package/src/components/svelte/input/Slider.svelte +96 -0
- package/src/components/svelte/input/Submit.svelte +32 -0
- package/src/components/svelte/input/Switch.svelte +53 -0
- package/src/components/svelte/input/Tabs.svelte +188 -0
- package/src/components/svelte/layout/Card.svelte +17 -0
- package/src/components/svelte/layout/Column.svelte +15 -0
- package/src/components/svelte/layout/Grid.svelte +26 -0
- package/src/components/svelte/layout/Row.svelte +105 -0
- package/src/components/svelte/layout/balancedTiles.ts +85 -0
- package/src/components/svelte/tooling/CodeMirror.svelte +91 -0
- package/src/components/svelte/tooling/Playground.svelte +765 -0
- package/src/components/svelte/tooling/PlaygroundMarkdown.svelte +26 -0
- package/src/components/svelte/tooling/PlaygroundSlexCode.svelte +76 -0
- package/src/components/svelte/types.ts +17 -0
- package/src/styles/animation.css +98 -0
- package/src/styles/components/button.css +114 -0
- package/src/styles/components/choice.css +165 -0
- package/src/styles/components/select.css +260 -0
- package/src/styles/components/slider.css +125 -0
- package/src/styles/components/submit.css +9 -0
- package/src/styles/components/switch.css +114 -0
- package/src/styles/components/tabs.css +192 -0
- package/src/styles/components/text-input.css +245 -0
- package/src/styles/content.css +474 -0
- package/src/styles/disclosure.css +162 -0
- package/src/styles/display.css +259 -0
- package/src/styles/entry.css +34 -0
- package/src/styles/feedback.css +219 -0
- package/src/styles/input.css +8 -0
- package/src/styles/layout.css +365 -0
- package/src/styles/theme.css +31 -0
- package/src/styles/tooling.css +1009 -0
|
@@ -0,0 +1,2922 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "slexkit-ai-docs",
|
|
3
|
+
"packageName": "slexkit",
|
|
4
|
+
"version": "0.2.0",
|
|
5
|
+
"generatedAt": "2026-05-29T16:08:38.010Z",
|
|
6
|
+
"docs": {
|
|
7
|
+
"llms.txt": {
|
|
8
|
+
"path": "/llms.txt",
|
|
9
|
+
"title": "llms.txt",
|
|
10
|
+
"summary": "- [Full documentation](/llms-full.txt): all canonical English docs pages in one text file.",
|
|
11
|
+
"hash": "d1a1d567"
|
|
12
|
+
},
|
|
13
|
+
"llms-full.txt": {
|
|
14
|
+
"path": "/llms-full.txt",
|
|
15
|
+
"title": "llms-full.txt",
|
|
16
|
+
"summary": "Version: 0.2.0",
|
|
17
|
+
"hash": "578d915f"
|
|
18
|
+
},
|
|
19
|
+
"llms-components.txt": {
|
|
20
|
+
"path": "/llms-components.txt",
|
|
21
|
+
"title": "llms-components.txt",
|
|
22
|
+
"summary": "Use these components inside Markdown `slex` fences. Raw component docs are ordinary `.md` pages that preserve `slex` examples.",
|
|
23
|
+
"hash": "7322df08"
|
|
24
|
+
},
|
|
25
|
+
"llms-runtime.txt": {
|
|
26
|
+
"path": "/llms-runtime.txt",
|
|
27
|
+
"title": "llms-runtime.txt",
|
|
28
|
+
"summary": "Raw Markdown: /docs/reference/spec.md",
|
|
29
|
+
"hash": "97f74329"
|
|
30
|
+
},
|
|
31
|
+
"llms-toolhost.txt": {
|
|
32
|
+
"path": "/llms-toolhost.txt",
|
|
33
|
+
"title": "llms-toolhost.txt",
|
|
34
|
+
"summary": "ToolHost is the structured-input path for confirmations, choices, and forms. Do not use it for ordinary display-only UI.",
|
|
35
|
+
"hash": "6fe87511"
|
|
36
|
+
},
|
|
37
|
+
"llms-authoring.txt": {
|
|
38
|
+
"path": "/llms-authoring.txt",
|
|
39
|
+
"title": "llms-authoring.txt",
|
|
40
|
+
"summary": "SlexKit's agent-readable source is Markdown with explicit `slex` fences. Do not use `.mdx`; `slex` fences are the interactive layer.",
|
|
41
|
+
"hash": "1d27a35f"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"pages": [
|
|
45
|
+
{
|
|
46
|
+
"id": "README",
|
|
47
|
+
"group": "Guides",
|
|
48
|
+
"title": "README",
|
|
49
|
+
"summary": "Root package overview and installation matrix.",
|
|
50
|
+
"href": "/",
|
|
51
|
+
"rawHref": "/README.md",
|
|
52
|
+
"sourcePath": "README.md",
|
|
53
|
+
"body": "<div align=\"center\">\n <p>\n <img src=\"site/assets/logo.svg\" alt=\"SlexKit\" width=\"84\" height=\"84\" />\n </p>\n <h1>SlexKit</h1>\n <p><strong>Streaming Live EXpressions Kit</strong></p>\n <p>\n \"Docs as tools, tools as docs.\" Give Markdown interactive power and make every AI output come alive.\n </p>\n <p>\n <a href=\"site/content/guides/intro/en-US.md\">Documentation</a> ·\n <a href=\"site/content/components/accordion/en-US.md\">Components</a> ·\n <a href=\"site/content/reference/spec/en-US.md\">Specification</a> ·\n <a href=\"site/content/guides/ai-agents/en-US.md\">AI / Agents</a> ·\n <a href=\"README.zh-CN.md\">简体中文</a>\n </p>\n <p>\n <img alt=\"version\" src=\"https://img.shields.io/badge/version-0.2.0-18181b\">\n <img alt=\"script\" src=\"https://img.shields.io/badge/Slex-v0.1-18181b\">\n <img alt=\"TypeScript\" src=\"https://img.shields.io/badge/runtime-TypeScript-3178c6\">\n <img alt=\"Svelte 5\" src=\"https://img.shields.io/badge/components-Svelte_5-ff3e00\">\n <img alt=\"license\" src=\"https://img.shields.io/badge/license-MIT-16a34a\">\n </p>\n</div>\n\n## Live interface blocks inside Markdown\n\n**SlexKit** turns explicit `slex` Markdown fences into live, stateful UI blocks. A Slex source is just a JavaScript object literal: `g` holds state and logic, `layout` describes the component tree, and the browser runtime renders the result in place.\n\nIt is built for chat messages, documents, agent panels, tool results, and AI-authored dashboards. It is not a full application framework.\n\n## Installation\n\n```sh\nnpm install slexkit\n```\n\n```ts\nimport { mount } from \"slexkit\";\nimport \"slexkit/style.css\";\n```\n\n## Usage\n\n```html\n<div id=\"app\"></div>\n\n<script type=\"module\">\n import { mount } from \"slexkit\";\n import \"slexkit/style.css\";\n\n mount(\n {\n slex: \"0.1\",\n namespace: \"hello\",\n g: { name: \"World\", count: 0 },\n layout: {\n \"card:greeting\": {\n title: \"Greeting\",\n \"text:message\": {\n \"$text\": \"'Hello, ' + g.name + '! Count: ' + g.count\"\n },\n \"button:add\": {\n label: \"+1\",\n onclick: \"g.count++\"\n }\n }\n }\n },\n document.getElementById(\"app\")\n );\n</script>\n```\n\n## Markdown Native\n\nSlexKit-capable hosts process explicit `slex` fences only. Plain `js`, `json`, and unlabeled code blocks stay inert.\n\n````md\n```slex\n{\n slex: \"0.1\",\n namespace: \"status\",\n g: { done: 3, total: 4 },\n layout: {\n \"badge:state\": { label: \"Ready\", tone: \"success\" },\n \"text:summary\": { \"$text\": \"g.done + '/' + g.total + ' complete'\" }\n }\n}\n```\n\n**Status:** Ready. 3/4 complete.\n````\n\nMarkdown platforms without SlexKit support show the fallback text. Hosts with SlexKit render the interactive UI.\n\n## What You Get\n\n- **Zero-build Slex source**: object literals with no imports, scaffolding, or component bundling in the generated output.\n- **Reactive `g` / `layout` model**: centralized state and logic with declarative component trees.\n- **Expression pipes**: `$` read expressions for dynamic props and `on*` write expressions for events.\n- **Directives**: `$if` and `$for` for conditional rendering and keyed list reconciliation.\n- **Official Svelte components**: 40+ layout, input, content, display, disclosure, feedback, and tooling components.\n- **Extensible registry**: custom component types, Svelte renderers, and component state modes.\n- **Trusted and secure runtimes**: host-realm rendering for trusted content, sandbox iframe rendering for untrusted source.\n- **ToolHost**: confirm, choose, and fill-form templates for structured AI tool-call UX.\n- **AI-friendly docs surface**: `llms.txt`, skills, and the `@slexkit/mcp` read-only MCP server.\n\n## Packages\n\n| Package | Install | Contents |\n| --- | --- | --- |\n| `slexkit` | `npm install slexkit` | Runtime, Svelte components, ToolHost, styles |\n| `@slexkit/runtime` | `npm install slexkit @slexkit/runtime` | Component-free runtime wrapper |\n| `@slexkit/components-svelte` | `npm install slexkit @slexkit/runtime @slexkit/components-svelte` | Svelte component registration |\n| `@slexkit/theme-shadcn` | `npm install @slexkit/theme-shadcn` | CSS theme tokens |\n| `@slexkit/streamdown` | `npm install slexkit @slexkit/theme-shadcn @slexkit/streamdown streamdown react react-dom` | React / Streamdown Markdown renderer |\n| `@slexkit/obsidian` | `npm install slexkit @slexkit/obsidian` | Obsidian plugin adapter |\n| `@slexkit/mcp` | `npx -y @slexkit/mcp` | Read-only MCP server for docs, examples, and source validation |\n\nSee [Package Boundaries](site/content/reference/packages/en-US.md) for details.\n\n## Integrations\n\n| Host | Path |\n| --- | --- |\n| Browser DOM | `mount()`, `ingest()`, `boot()`, `disposeNamespace()` |\n| Markdown renderers | `createSlexKitMarkdownRuntimeHost()` |\n| React / Streamdown | `@slexkit/streamdown` |\n| Obsidian | `@slexkit/obsidian` |\n| AI agents | `@slexkit/mcp`, `llms.txt`, SlexKit skill docs |\n| Custom components | `register()`, `registerSvelteComponent()`, `registerSubset()` |\n\n## Security Runtime\n\nTrusted mode runs inside the host realm and is intended for application-authored or reviewed source. Secure mode isolates untrusted Slex source in a sandbox iframe with an opaque origin, nonce-based CSP, locked-down globals, host-mediated network access, and a heartbeat watchdog.\n\nRead the [Security Runtime](site/content/reference/security/en-US.md) docs before rendering unreviewed user or model output.\n\n## Documentation\n\n| Document | Topic |\n| --- | --- |\n| [Getting Started](site/content/guides/quick-start/en-US.md) | Install and render a first Markdown-friendly Slex source |\n| [Integration](site/content/guides/integration/en-US.md) | Streamdown, Obsidian, and custom host paths |\n| [Runtime model](site/content/reference/runtime/en-US.md) | Mounting, updates, namespace store, lifecycle |\n| [Slex usage reference](site/content/reference/usage/en-US.md) | Source structure, directives, expressions, events, custom components |\n| [Security runtime](site/content/reference/security/en-US.md) | Threat model, sandbox iframe, policy, postMessage bridge |\n| [Slex Specification](site/content/reference/spec/en-US.md) | Protocol v0.1, types, merge rules, lifecycle hooks |\n| [ToolHost](site/content/reference/toolhost/en-US.md) | Tool-call rendering and custom templates |\n| [Icon system](site/content/reference/icons/en-US.md) | Phosphor icons, custom registration, Iconify fallback |\n| [AI / Agents](site/content/guides/ai-agents/en-US.md) | `llms.txt`, MCP server, skills, and authoring rules |\n| [Changelog](CHANGELOG.md) | Release notes and notable changes |\n\n## Version Information\n\n```ts\nimport { SLEXKIT_VERSION, SLEX_PROTOCOL_VERSION, getSlexKitInfo } from \"slexkit\";\n```\n\nThe npm package version, component implementation version, and Slex protocol version are exposed separately. The current public protocol is `v0.1`.\n\n## License\n\nMIT",
|
|
54
|
+
"hash": "e1cb682c"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "guides/intro",
|
|
58
|
+
"group": "Guides",
|
|
59
|
+
"title": "SlexKit Introduction",
|
|
60
|
+
"summary": "What SlexKit is and where it fits.",
|
|
61
|
+
"href": "/docs/guides/intro",
|
|
62
|
+
"rawHref": "/docs/guides/intro.md",
|
|
63
|
+
"sourcePath": "site/content/guides/intro/en-US.md",
|
|
64
|
+
"body": "---\ntitle: SlexKit Introduction\ncategory: Guides\nstatus: ready\norder: 10\nsummary: \"Markdown-friendly reactive UI runtime for explicit slex fences.\"\nslexkitRenderMode: component\n---\n\n# SlexKit Introduction\n\nSlexKit is a Markdown-friendly reactive UI runtime for explicit `slex` fences. Hosts can render small interactive fragments inside AI conversations, documents, agent panels, and dashboards without adding a build step to the generated content.\n\nSlexKit is currently v0/beta. The public surface is usable, but long-term compatibility is not yet guaranteed.\n\n## Use Cases\n\nWhen Markdown needs a small amount of interaction:\n\n- Status cards, counters, calculators, parameter panels, lightweight dashboards\n- AI-generated UI fragments that should degrade to plain Markdown\n- React, Svelte, Obsidian, or vanilla HTML hosts rendering the same fenced source\n\nSlexKit is not a full application framework. It does not provide routing, server-side rendering, a data fetching layer, or a cross-platform pure JSON UI standard.\n\n## Source Format\n\nA Slex source is a JavaScript object literal with state in `g` and the component tree in `layout`:\n\n```slex\n{\n namespace: \"intro_counter\",\n g: {\n count: 0\n },\n layout: {\n \"card:counter\": {\n title: \"Counter\",\n \"text:value\": {\n \"$text\": \"'Count: ' + g.count\"\n },\n \"button:add\": {\n label: \"+1\",\n onclick: \"g.count++\"\n }\n }\n }\n}\n```\n\n- `namespace` identifies the state domain\n- `g` contains reactive state, functions, and small calculations\n- `layout` contains component nodes keyed as `type:name`\n- `$`-prefixed props are read expressions, such as `\"$text\": \"'Count: ' + g.count\"`\n- `on*` props are write expressions, such as `onclick: \"g.count++\"`\n\nThe runtime also accepts a bare component tree as shorthand, but the full envelope is preferred for documentation and shared examples.\n\n## Fence Convention\n\nHosts must process only fences explicitly marked as `slex`:\n\n````md\n```slex\n{\n namespace: \"status\",\n layout: {\n \"badge:state\": { label: \"Ready\", tone: \"success\" }\n }\n}\n```\n\n**Status:** Ready\n````\n\nThe Markdown after the fence is the fallback. Plain Markdown readers show the fallback text; SlexKit-capable hosts replace the fence with interactive UI.\n\nPlain JavaScript, JSON, or untagged code blocks must not be scanned or executed.\n\n## Runtime Modes\n\n**Trusted mode** executes Slex source in the host page. Use it for application-generated content, local documents, and repository-maintained examples.\n\n**Secure mode** executes untrusted or agent-generated source in a sandbox iframe. Sensitive capabilities such as network, timers, animation, and canvas are exposed only through host policy and `api.*`.\n\nUse secure mode when rendering third-party or unreviewed content. See [Secure Runtime Setup](security-runtime).\n\n## Boundary Separation\n\n**Display UI** renders via `slex` fences or `mount()`. These fragments show information and local interaction but are not function calls.\n\n**ToolHost** is a separate boundary. It renders confirmations, option pickers, and forms that must return structured input to the host. The `submit` component is the explicit completion boundary for tool templates.\n\nThis separation prevents ordinary display UI from being mispackaged as tool invocations.\n\n## Core APIs\n\n| API | Use |\n|---|---|\n| `mount(input, container, options?)` | Render trusted Slex source into a container |\n| `ingest(input)` | Merge state-only source without rendering UI |\n| `boot(options?)` | Enhance static page `slex` fences |\n| `createSlexKitMarkdownRuntimeHost(options?)` | Recommended API for Markdown hosts |\n| `mountSecureArtifact(input, container, options)` | Render source in the secure sandbox runtime |\n| `renderToolCall(call, container)` | Render a ToolHost template and collect a result |\n\nFor exact types and beta compatibility notes, use the [Slex Specification](../../reference/spec/en-US.md) as the technical reference.\n\n## Next Steps\n\n- [Getting Started](quick-start): developer integration path\n- [Integration](integration): Streamdown and Obsidian host plugins\n- [Design Guidelines](design): authoring public examples and component usage\n- [Secure Runtime Setup](security-runtime): untrusted content boundary\n- [Component Reference](../components/card): built-in component catalog\n- [AI / Agents](ai-agents): SlexKit context for models and agents",
|
|
65
|
+
"hash": "bff82366"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"id": "guides/quick-start",
|
|
69
|
+
"group": "Guides",
|
|
70
|
+
"title": "Quick Start",
|
|
71
|
+
"summary": "Install SlexKit and render a first Markdown-friendly Slex source.",
|
|
72
|
+
"href": "/docs/guides/quick-start",
|
|
73
|
+
"rawHref": "/docs/guides/quick-start.md",
|
|
74
|
+
"sourcePath": "site/content/guides/quick-start/en-US.md",
|
|
75
|
+
"body": "---\ntitle: Getting Started\ncategory: Guides\nstatus: ready\norder: 20\nsummary: \"Developer-first SlexKit integration: install the runtime, mount trusted fragments, wire Markdown hosts, and choose the next integration path.\"\nslexkitRenderMode: component\n---\n\n# Getting Started\n\nInstall `slexkit`, mount a trusted fragment, and you're off. Hand off Markdown / React / Obsidian details to dedicated guides — this page keeps the core integration path focused.\n\n## Installation Entry\n\nFor most apps, start by installing the root package:\n\n```sh\nnpm install slexkit\n```\n\n```ts\nimport { mount } from \"slexkit\";\nimport \"slexkit/style.css\";\n```\n\nFor clearer package boundaries, choose scoped packages by host:\n\n| Use case | Install |\n|---|---|\n| Custom components or component-free runtime | `npm install slexkit @slexkit/runtime` |\n| Official Svelte component registration | `npm install slexkit @slexkit/runtime @slexkit/components-svelte` |\n| Standalone shadcn-token theme CSS | `npm install @slexkit/theme-shadcn` |\n| React + Streamdown Markdown host | `npm install slexkit @slexkit/theme-shadcn @slexkit/streamdown streamdown react react-dom` |\n| Obsidian vault rendering | `npm install slexkit @slexkit/obsidian` |\n\n`@slexkit/runtime` and `@slexkit/components-svelte` are thin wrappers around the root package, not independent implementations.\n\n## Trusted Fragment\n\nTrusted mode is the minimal integration path. Use it for application-authored source, local examples, repository-maintained content, and reviewed snippets.\n\n```ts\nimport { mount } from \"slexkit\";\nimport \"slexkit/style.css\";\n\nconst source = {\n namespace: \"getting_started_counter\",\n g: {\n count: 0\n },\n layout: {\n \"card:demo\": {\n title: \"Counter\",\n \"text:value\": {\n \"$text\": \"'Count: ' + g.count\"\n },\n \"button:add\": {\n label: \"+1\",\n onclick: \"g.count++\"\n }\n }\n }\n};\n\nconst cleanup = mount(source, document.getElementById(\"app\")!);\n```\n\nCall `cleanup()` when removing containers, replacing messages, or unloading pages. If the namespace won't be reused, call `disposeNamespace(namespace)`.\n\n## Markdown Fallback\n\nWhen source appears in Markdown, handle only explicit `slex` fences and keep readable fallback text after the fence:\n\n````md\n```slex\n{\n namespace: \"release_status\",\n layout: {\n \"badge:status\": { label: \"Ready\", tone: \"success\" },\n \"text:summary\": { text: \"3 of 3 checks passed.\" }\n }\n}\n```\n\n**Release status:** Ready. 3 of 3 checks passed.\n````\n\nSlexKit-capable hosts render the fence. Plain Markdown hosts show the fallback. Do not infer executable SlexKit source from `js`, `json`, or unlabeled code blocks.\n\n## Markdown Host\n\nFor products rendering chat messages, docs pages, or long Markdown artifacts, use `createSlexKitMarkdownRuntimeHost`. It manages artifact scoping, block lifecycle, state-only fences, and trusted/secure mode selection.\n\n```ts\nimport { createSlexKitMarkdownRuntimeHost } from \"slexkit\";\nimport \"slexkit/style.css\";\n\nconst runtime = createSlexKitMarkdownRuntimeHost({\n mode: \"trusted\",\n theme: \"host-shadcn\"\n});\n\nexport function mountSlexFence(source: string, container: HTMLElement) {\n return runtime.mountBlock({\n artifactId: \"message-42\",\n source,\n container\n });\n}\n```\n\nWhen the whole document or message thread is destroyed, call `runtime.disposeArtifact(artifactId)` or `runtime.disposeAll()`.\n\n## Trust Boundary\n\n| Content source | Recommended mode |\n|---|---|\n| App-generated source, repository examples, local vault content | trusted |\n| Unreviewed user input, third-party Markdown, direct agent output | secure |\n\nSecure mode requires a sandbox iframe, a publicly served `slexkit.runtime.js`, and a host policy. See [Secure Runtime Setup](security-runtime).\n\n## Next Steps\n\n- [Integration](integration): React/Streamdown and Obsidian plugins\n- [Secure Runtime Setup](security-runtime): untrusted or agent-generated content\n- [Component Reference](../components/card): built-in component catalog\n- [AI / Agents](ai-agents): SlexKit authoring context for models and agents",
|
|
76
|
+
"hash": "ab0489b2"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": "guides/integration",
|
|
80
|
+
"group": "Guides",
|
|
81
|
+
"title": "Integration",
|
|
82
|
+
"summary": "React/Streamdown and Obsidian host plugins for explicit Slex fences.",
|
|
83
|
+
"href": "/docs/guides/integration",
|
|
84
|
+
"rawHref": "/docs/guides/integration.md",
|
|
85
|
+
"sourcePath": "site/content/guides/integration/en-US.md",
|
|
86
|
+
"body": "---\ntitle: Integration\ncategory: Guides\nstatus: ready\norder: 25\nsummary: \"Plugin setup guide for Streamdown and Obsidian hosts that render explicit Slex fences.\"\nslexkitRenderMode: component\n---\n\n# Integration\n\nSlexKit ships two official plugins: Streamdown and Obsidian. Both process only explicit `slex` fences — they don't scan ordinary JavaScript, JSON, or unlabeled code blocks. For the full API and host contract, see the [Host Integration reference](/docs/reference/integration).\n\n## Plugin Selection\n\n| Host | Package | Use case | Runtime boundary |\n|---|---|---|---|\n| React / Streamdown | `@slexkit/streamdown` | Chat messages, AI output, React Markdown pages | trusted or secure |\n| Obsidian | `@slexkit/obsidian` | Slex fences in local vault reading mode | trusted readonly |\n| Custom Markdown host | `slexkit` | Product-specific Markdown renderer or document viewer | trusted or secure |\n\nUse the packaged plugin when the host is Streamdown or Obsidian. Use `createSlexKitMarkdownRuntimeHost` directly for custom Markdown renderers.\n\nPackage installation details and release boundaries are tracked in [Package Boundaries](/docs/reference/packages).\n\n## Streamdown\n\nInstall the runtime, theme, plugin, and React peer dependencies:\n\n```sh\nnpm install slexkit @slexkit/theme-shadcn @slexkit/streamdown streamdown react react-dom\n```\n\nImport styles once in the app entry:\n\n```ts\nimport \"@slexkit/theme-shadcn/style.css\";\nimport \"@slexkit/streamdown/style.css\";\n```\n\nRegister the renderer with Streamdown:\n\n```tsx\nimport { Streamdown } from \"streamdown\";\nimport { slexkitRenderer } from \"@slexkit/streamdown\";\n\nexport function Message({ markdown }: { markdown: string }) {\n return (\n <Streamdown plugins={{ renderers: [slexkitRenderer] }}>\n {markdown}\n </Streamdown>\n );\n}\n```\n\nThe default renderer handles only `slex` fences. Ordinary code blocks pass through to Streamdown.\n\n## Streamdown Options\n\nUse `createSlexKitRenderer` when the host needs explicit domain scoping, source controls, playground mode, or secure mode:\n\n```tsx\nimport { createSlexKitRenderer } from \"@slexkit/streamdown\";\n\nconst renderer = createSlexKitRenderer({\n domain: \"chat-thread-42\",\n showChrome: false,\n showSource: false,\n runtime: \"trusted\"\n});\n```\n\nState-only fences in the same `domain` can seed later layout fences:\n\n````md\n```slex\n{\n namespace: \"calc\",\n g: { value: 21 }\n}\n```\n\n```slex\n{\n namespace: \"calc\",\n layout: {\n \"text:answer\": { \"$text\": \"'answer: ' + (g.value * 2)\" }\n }\n}\n```\n````\n\nFor unreviewed user input, third-party Markdown, or direct agent output, switch to secure mode and configure a host policy:\n\n```tsx\nconst renderer = createSlexKitRenderer({\n runtime: \"secure\",\n secureFrame: {\n runtimeUrl: \"/slexkit.runtime.js\"\n },\n securePolicy: {\n execution: {\n maxUnresponsiveMs: 30000\n }\n }\n});\n```\n\nThe secure runtime deployment checklist lives in [Secure Runtime Setup](security-runtime). Exact policy fields live in the [Security Runtime Contract](/docs/reference/security).\n\n## Obsidian\n\nThe Obsidian plugin targets local vault content. It registers a `slex` code block processor in reading mode, renders the fence as a readonly interactive fragment, and does not write output back to notes.\n\nBuild the plugin:\n\n```sh\nbun run --filter @slexkit/obsidian build\n```\n\nCopy release assets into the vault:\n\n```text\n.obsidian/plugins/slexkit/\n main.js\n manifest.json\n styles.css\n```\n\nEnable **SlexKit** in Obsidian's community plugin settings.\n\n## Obsidian Example\n\nWrite an explicit `slex` fence in a note:\n\n````md\n```slex\n{\n namespace: \"vault_status\",\n layout: {\n \"card:status\": {\n title: \"Vault status\",\n \"badge:ready\": { label: \"Ready\", tone: \"success\" },\n \"text:note\": { text: \"Rendered by SlexKit in reading mode.\" }\n }\n }\n}\n```\n\nVault status: Ready.\n````\n\nBlocks in the same note share one Markdown artifact runtime, so a state-only fence can affect a later renderable fence.\n\n## Obsidian Boundary\n\n`@slexkit/obsidian` v0 is a trusted readonly adapter. Content comes from the user's local vault; the plugin is not a sandbox for third-party Markdown or agent output.\n\nFor untrusted content, use secure mode in a web host with an explicit sandbox frame and host policy.\n\n## Integration Checklist\n\n- Process only fences whose language is exactly `slex`\n- Keep Markdown fallback for environments without SlexKit\n- Use a stable artifact/domain for each document, message, or note\n- Call cleanup when a container unmounts; dispose the artifact when the document is destroyed\n- Use secure mode for untrusted content instead of trusted mode\n- Link API, lifecycle, package, and security details to the reference pages instead of duplicating them in host guides",
|
|
87
|
+
"hash": "f3b8bc00"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "guides/design",
|
|
91
|
+
"group": "Guides",
|
|
92
|
+
"title": "Design Guidelines",
|
|
93
|
+
"summary": "Design and authoring guidelines for SlexKit components and docs.",
|
|
94
|
+
"href": "/docs/guides/design",
|
|
95
|
+
"rawHref": "/docs/guides/design.md",
|
|
96
|
+
"sourcePath": "site/content/guides/design/en-US.md",
|
|
97
|
+
"body": "---\ntitle: Design Philosophy\ncategory: Guides\nstatus: ready\norder: 30\nsummary: \"Design principles for live Markdown, components, and agent-friendly UI output.\"\nincludeTitleInToc: true\nslexkitRenderMode: component\n---\n\n# SlexKit Design Philosophy\n\n**Docs as tools, tools as docs.**\n\nMake static documents come alive. Give AI agents the power to output interactive experiences.\n\n```slex\n{\n namespace: \"design_philosophy\",\n layout: {\n \"diagram:philosophy\": {},\n \"grid:philosophy\": {\n columns: 1,\n lgColumns: 3,\n \"card:task\": {\n \"heading:title\": { level: 4, title: \"Task-First\" },\n \"text:bodyA\": { text: \"Start from the task the user needs to complete.\" },\n \"text:bodyB\": { text: \"Every design decision serves the core task.\" }\n },\n \"card:intuitive\": {\n \"heading:title\": { level: 4, title: \"Intuitive\" },\n \"text:bodyA\": { text: \"Docs include live examples that update instantly.\" },\n \"text:bodyB\": { text: \"Data flows across components through scoped binding.\" }\n },\n \"card:breath\": {\n \"heading:title\": { level: 4, title: \"Visual Breath\" },\n \"text:bodyA\": { text: \"Whitespace and spacing create visual rhythm.\" },\n \"text:bodyB\": { text: \"Typography and color build clear hierarchy.\" }\n }\n }\n }\n}\n```\n\n## Color Semantics\n\nColor expresses role, not personal preference.\n\n```slex\n{\n namespace: \"design_color\",\n layout: {\n \"grid:colors\": {\n columns: 1,\n mdColumns: 2,\n lgColumns: 3,\n \"card:primary\": {\n \"swatch:primary\": { tone: \"primary\" },\n \"heading:title\": { level: 4, title: \"Primary\" },\n \"text:body\": { text: \"Main actions, current selection, high-priority emphasis. Do not use as decoration.\" }\n },\n \"card:info\": {\n \"swatch:info\": { tone: \"info\" },\n \"heading:title\": { level: 4, title: \"Info\" },\n \"text:body\": { text: \"Guidance, hints, informational states. Do not replace Primary.\" }\n },\n \"card:success\": {\n \"swatch:success\": { tone: \"success\" },\n \"heading:title\": { level: 4, title: \"Success\" },\n \"text:body\": { text: \"Completed, passed, safe to continue. Use only when the result is confirmed.\" }\n },\n \"card:warning\": {\n \"swatch:warning\": { tone: \"warning\" },\n \"heading:title\": { level: 4, title: \"Warning\" },\n \"text:body\": { text: \"Risk, threshold, needs attention but not failed. Do not use to brighten pages.\" }\n },\n \"card:destructive\": {\n \"swatch:destructive\": { tone: \"destructive\" },\n \"heading:title\": { level: 4, title: \"Destructive\" },\n \"text:body\": { text: \"Errors, deletions, irreversible actions. Must include consequence description.\" }\n },\n \"card:neutral\": {\n \"swatch:neutral\": { tone: \"neutral\" },\n \"heading:title\": { level: 4, title: \"Neutral\" },\n \"text:body\": { text: \"Backgrounds, dividers, secondary information, default containers. Provides structure, not emphasis.\" }\n }\n }\n }\n}\n```\n\n## Card Arrangement\n\nSmall cards are for comparison and judgment. Run metrics side-by-side; the system handles equal width, spacing, and wrapping. Wrap in a parent card when items share context; stack vertically when order matters.\n\n```slex\n{\n namespace: \"design_arrangement\",\n layout: {\n \"column:arrange\": {\n \"row:metrics\": {\n \"stat:requests\": {\n label: \"Requests\",\n value: \"1.2k\",\n unit: \"/min\",\n tone: \"info\"\n },\n \"stat:success\": {\n label: \"Success\",\n value: \"98.4\",\n unit: \"%\",\n tone: \"success\"\n },\n \"stat:latency\": {\n label: \"Latency\",\n value: \"42\",\n unit: \"ms\"\n },\n \"stat:errors\": {\n label: \"Errors\",\n value: \"3\",\n tone: \"warning\"\n },\n \"stat:queued\": {\n label: \"Queued\",\n value: \"8\"\n }\n },\n \"grid:examples\": {\n columns: 1,\n mdColumns: 2,\n \"card:summary\": {\n title: \"Same Object\",\n \"row:service\": {\n \"stat:idle\": {\n label: \"Pending\",\n value: \"12\"\n },\n \"stat:active\": {\n label: \"Running\",\n value: \"5\",\n tone: \"info\"\n },\n \"stat:done\": {\n label: \"Done\",\n value: \"47\",\n tone: \"success\"\n },\n \"stat:failed\": {\n label: \"Failed\",\n value: \"2\",\n tone: \"danger\"\n }\n }\n },\n \"card:flow\": {\n title: \"Sequential\",\n \"column:steps\": {\n \"stat:input\": {\n label: \"Input\",\n value: \"1\"\n },\n \"stat:compute\": {\n label: \"Compute\",\n value: \"2\",\n tone: \"info\"\n },\n \"stat:output\": {\n label: \"Output\",\n value: \"3\",\n tone: \"success\"\n }\n }\n }\n }\n }\n }\n}\n```\n\n## Typography & Icons\n\nSlexKit's typography is calm, clear, and technical. Icons are light, rounded, and restrained — serving as punctuation marks in the interface, not illustrations.\n\n```slex\n{\n namespace: \"design_type_icon\",\n layout: {\n \"grid:type\": {\n columns: 1,\n lgColumns: 2,\n \"card:type\": {\n \"heading:title\": { level: 4, title: \"Type Voice\", meta: \"GEIST / NOTO SANS SC\" },\n \"diagram:font\": { kind: \"font-sample\" },\n \"text:body\": { text: \"English uses Geist, Chinese uses Noto Sans SC. Letterforms stay open and clean, serving readability rather than volume.\" }\n },\n \"card:icon\": {\n \"heading:title\": { level: 4, title: \"Icon Voice\", meta: \"PHOSPHOR ICONS\" },\n \"row:icons\": {\n \"button:sparkle\": { icon: \"sparkle\", iconOnly: true, label: \"Assist\" },\n \"button:book\": { icon: \"book-open-text\", iconOnly: true, label: \"Manual\" },\n \"button:terminal\": { icon: \"terminal-window\", iconOnly: true, label: \"Terminal\" },\n \"button:cursor\": { icon: \"cursor-click\", iconOnly: true, label: \"Click\" },\n \"button:nut\": { icon: \"nut\", iconOnly: true, label: \"Nut\" },\n \"button:gear\": { icon: \"gear-six\", iconOnly: true, label: \"Gear\" }\n },\n \"text:body\": { text: \"Phosphor's character comes from geometric outlines, rounded corners, and consistent stroke width. When choosing icons, first check tone consistency, then semantic accuracy.\" }\n }\n }\n }\n}\n```\n\n## Markdown Authoring\n\nDesign specs and component pages use Markdown for prose, with `slex` fenced blocks for runnable examples, achieving docs-as-examples authoring.\n\n```slex\n{\n namespace: \"design_markdown\",\n layout: {\n \"grid:doc\": {\n columns: 1,\n lgColumns: 3,\n \"card:write\": {\n \"diagram:markdown\": {},\n \"heading:title\": { level: 4, title: \"Prose in Markdown\" },\n \"text:body\": { text: \"Explain context, boundaries, and rules. Do not write explanations inside UI components.\" }\n },\n \"card:run\": {\n \"diagram:fence\": {},\n \"heading:title\": { level: 4, title: \"Examples in slex\" },\n \"text:body\": { text: \"Every key example should render and preview live, not be a screenshot.\" }\n },\n \"card:compare\": {\n \"diagram:cards\": {},\n \"heading:title\": { level: 4, title: \"Rules as Small Cards\" },\n \"text:body\": { text: \"Put comparable principles into cards so readers can judge at a glance.\" }\n }\n }\n }\n}\n```\n\n## Product Shape\n\nSlexKit targets interactive fragments inside Markdown, not full applications. Typical scenarios include:\n\n- A card explaining a result\n- A row of metrics\n- A form-like control area\n- A status or confirmation block\n\nThe framework focuses on embedded document interactions, not routing, global app state, SSR, data fetching frameworks, or general UI standardization.\n\n```slex\n{\n namespace: \"design_shape\",\n layout: {\n \"card:status\": {\n title: \"Build summary\",\n tone: \"info\",\n \"row:metrics\": {\n \"stat:passed\": { label: \"Passed\", value: 28, tone: \"success\" },\n \"stat:failed\": { label: \"Failed\", value: 1, tone: \"danger\" },\n \"stat:queued\": { label: \"Queued\", value: 3, tone: \"muted\" }\n },\n \"text:note\": {\n text: \"Keep the surface focused on one document or message task.\"\n }\n }\n }\n}\n```\n\n## Tone Rules\n\nComponents support semantic tone values for expressing state roles.\n\n```slex\n{\n namespace: \"design_tones\",\n layout: {\n \"grid:tones\": {\n columns: 1,\n mdColumns: 2,\n lgColumns: 3,\n \"card:info\": {\n \"badge:tone\": { label: \"info\", tone: \"info\" },\n \"text:body\": { text: \"Neutral guidance, current process, or informational state.\" }\n },\n \"card:success\": {\n \"badge:tone\": { label: \"success\", tone: \"success\" },\n \"text:body\": { text: \"Completed, accepted, or safe-to-continue state.\" }\n },\n \"card:warning\": {\n \"badge:tone\": { label: \"warning\", tone: \"warning\" },\n \"text:body\": { text: \"Risk, threshold, or review-needed state.\" }\n },\n \"card:danger\": {\n \"badge:tone\": { label: \"danger\", tone: \"danger\" },\n \"text:body\": { text: \"Error, destructive action, or blocked state.\" }\n },\n \"card:muted\": {\n \"badge:tone\": { label: \"muted\", tone: \"muted\" },\n \"text:body\": { text: \"Secondary or background information.\" }\n }\n }\n }\n}\n```\n\n## Display UI Versus ToolHost\n\nDisplay UI is for information presentation and local interaction. ToolHost mode is used when the host needs structured results from the user.\n\n```slex\n{\n namespace: \"design_boundary\",\n layout: {\n \"grid:boundary\": {\n columns: 1,\n mdColumns: 2,\n \"card:display\": {\n title: \"Display UI\",\n \"text:body\": { text: \"Use slex fences for status, metrics, previews, and local controls.\" },\n \"badge:kind\": { label: \"No host result\", tone: \"muted\" }\n },\n \"card:toolhost\": {\n title: \"ToolHost\",\n \"text:body\": { text: \"Use tool templates when confirmation or form data must return to the host.\" },\n \"badge:kind\": { label: \"Returns ToolResult\", tone: \"info\" }\n }\n }\n }\n}\n```",
|
|
98
|
+
"hash": "8a3b35fd"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"id": "guides/security-runtime",
|
|
102
|
+
"group": "Guides",
|
|
103
|
+
"title": "Secure Runtime Setup",
|
|
104
|
+
"summary": "Decision and setup guide for rendering untrusted or agent-generated Slex source.",
|
|
105
|
+
"href": "/docs/guides/security-runtime",
|
|
106
|
+
"rawHref": "/docs/guides/security-runtime.md",
|
|
107
|
+
"sourcePath": "site/content/guides/security-runtime/en-US.md",
|
|
108
|
+
"body": "---\ntitle: Secure Runtime Setup\ncategory: Guides\nstatus: ready\norder: 40\nsummary: \"Decision and setup guide for rendering untrusted or agent-generated Slex source.\"\nslexkitRenderMode: component\n---\n\n# Secure Runtime Setup\n\nUse secure mode when the host does not fully control the Slex source: unreviewed user input, third-party Markdown, direct agent output, or shared documents where authorship is unclear.\n\nSecure mode is a deployment and policy choice. The complete threat model, `HostRuntimePolicy`, sandbox attributes, bridge messages, and fail-closed behavior are specified in the [Security Runtime Contract](/docs/reference/security).\n\n## Mode Decision\n\n| Source | Recommended mode | Notes |\n|---|---|---|\n| Application-generated source | trusted | Lowest overhead; source is part of your app boundary. |\n| Repository examples or reviewed snippets | trusted | Keep examples explicit and versioned. |\n| Local Obsidian vault notes | trusted readonly | The Obsidian adapter is not a sandbox boundary. |\n| User-submitted Markdown | secure | Treat source as untrusted even when the Markdown looks harmless. |\n| Direct agent output | secure | Do not grant network, timer, animation, or canvas access by default. |\n\nIf the answer is unclear, start with secure mode and enable capabilities only after the host has a concrete product need.\n\n## Minimal Host Setup\n\nFor Markdown hosts, prefer `createSlexKitMarkdownRuntimeHost`. It keeps artifact scoping, state-only fences, block cleanup, and secure-frame mounting in one place.\n\n```ts\nimport { createSlexKitMarkdownRuntimeHost } from \"slexkit\";\nimport \"slexkit/style.css\";\n\nconst runtime = createSlexKitMarkdownRuntimeHost({\n mode: \"secure\",\n theme: \"host-shadcn\",\n secureFrame: {\n runtimeUrl: \"/slexkit.runtime.js\"\n },\n policy: {\n execution: {\n heartbeatIntervalMs: 1000,\n maxUnresponsiveMs: 30000\n }\n }\n});\n\nexport function mountSlexFence(source: string, container: HTMLElement) {\n return runtime.mountBlock({\n artifactId: \"message-42\",\n source,\n container\n });\n}\n```\n\nCall `disposeBlock(container)` when a fence disappears, and call `disposeArtifact(artifactId)` when the full message, document, or note is destroyed.\n\nOmitted capability policies deny access by default. Add `network`, `timer`, `animation`, or `canvas` policy objects only when the host intentionally enables those capabilities.\n\n## Runtime Module\n\nThe secure iframe imports the runtime from `secureFrame.runtimeUrl`. Serve that file as a public ES module:\n\n```http\nAccess-Control-Allow-Origin: *\nContent-Type: text/javascript\n```\n\nThis is server or deployment configuration. It cannot be repaired from frontend JavaScript after the request has already failed.\n\n## Policy Checklist\n\n- Keep network disabled unless a specific product feature needs it.\n- If network is enabled, allow only required methods, origins, headers, body sizes, response sizes, and content types.\n- Keep timers, animation, and canvas disabled unless the Slex source needs them.\n- Never treat `capabilities`, `permissions`, `api`, or similar fields inside Slex source as authorization.\n- Do not add `allow-same-origin` to solve CORS or debugging issues.\n- Keep unresponsive runtime failures visible to users through the built-in fail-closed diagnostic.\n\nFor exact policy fields and allowed adapter hooks, use the [Security Runtime Contract](/docs/reference/security).\n\n## Host Boundaries\n\n`@slexkit/streamdown` can run trusted or secure. Use secure mode for chat messages and agent output unless the message source is already trusted by the host.\n\n`@slexkit/obsidian` v0 is a trusted readonly adapter for local vault content. It should not be used as the isolation boundary for third-party Markdown or direct agent output.\n\nCustom Markdown hosts should still process only fences whose language is exactly `slex` and should preserve readable Markdown fallback for non-SlexKit environments.\n\n## Production Checklist\n\n- Stable `artifactId` per message, document, or note\n- Explicit `slex` fence detection only\n- Public `slexkit.runtime.js` module with CORS and JavaScript content type\n- Deny-by-default host policy\n- Cleanup on block removal and artifact destruction\n- Visible fallback text after each interactive fence\n- Link to the reference contract for policy, bridge, CSP, and sandbox details",
|
|
109
|
+
"hash": "bbf1d81f"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "guides/ai-agents",
|
|
113
|
+
"group": "Guides",
|
|
114
|
+
"title": "AI / Agents",
|
|
115
|
+
"summary": "LLM docs, MCP server, skills, and authoring rules for SlexKit agents.",
|
|
116
|
+
"href": "/docs/guides/ai-agents",
|
|
117
|
+
"rawHref": "/docs/guides/ai-agents.md",
|
|
118
|
+
"sourcePath": "site/content/guides/ai-agents/en-US.md",
|
|
119
|
+
"body": "---\ntitle: AI / Agents\ncategory: Guides\nstatus: ready\norder: 50\nsummary: \"LLM docs, MCP server, skills, and authoring rules for SlexKit agents.\"\nslexkitRenderMode: component\n---\n\n# AI / Agents\n\n## AI Accessible Documentation\n\nSlexKit follows the assistant-ui information architecture: a clear index, a full-context file, task-oriented skills, and a minimal MCP surface. Raw docs stay as `.md` pages, and interactive examples use explicit `slex` fences.\n\n```slex\n{\n namespace: \"ai_docs_links\",\n layout: {\n \"column:links\": {\n gap: \"sm\",\n \"link:index\": { href: \"/llms.txt\", text: \"/llms.txt - docs index\", icon: \"list-magnifying-glass\" },\n \"link:full\": { href: \"/llms-full.txt\", text: \"/llms-full.txt - full English context\", icon: \"book-open-text\" },\n \"link:components\": { href: \"/llms-components.txt\", text: \"/llms-components.txt - components and API\", icon: \"puzzle-piece\" },\n \"link:runtime\": { href: \"/llms-runtime.txt\", text: \"/llms-runtime.txt - runtime and host integration\", icon: \"cpu\" },\n \"link:toolhost\": { href: \"/llms-toolhost.txt\", text: \"/llms-toolhost.txt - structured input\", icon: \"cursor-click\" },\n \"link:authoring\": { href: \"/llms-authoring.txt\", text: \"/llms-authoring.txt - slex fence authoring rules\", icon: \"pencil-simple\" },\n \"link:manifest\": { href: \"/slexkit-ai-manifest.json\", text: \"/slexkit-ai-manifest.json - machine-readable index\", icon: \"brackets-curly\" },\n \"text:note\": { text: \"Raw docs use .md routes such as /docs/components/card.md. Do not add .mdx routes.\" }\n }\n }\n}\n```\n\nMinimal reading path:\n\n1. Start with [`/llms.txt`](/llms.txt) for the grouped index.\n2. Use [`/llms-full.txt`](/llms-full.txt) when the agent needs broad context.\n3. Use [`/llms-components.txt`](/llms-components.txt) and raw component `.md` pages when authoring UI.\n4. Use [`/llms-runtime.txt`](/llms-runtime.txt) for host and secure runtime integration.\n5. Use [`/llms-toolhost.txt`](/llms-toolhost.txt) only when user input must return structured data to the host.\n\nSlexKit raw docs are ordinary `.md` pages with explicit `slex` fences. There is no `.mdx` route — `slex` fences are the interactive layer.\n\n## Context Files\n\nAdd SlexKit context to `AGENTS.md`, `CLAUDE.md`, or `.cursorrules`:\n\n````md\n## SlexKit\n\nThis project uses SlexKit for Markdown-native interactive AI output.\n\nDocumentation: https://slexkit.dev/llms-full.txt\n\nKey patterns:\n- Display UI uses explicit `slex` fenced blocks plus Markdown fallback.\n- Slex source uses `{ slex, namespace, g, layout }`; use `slex: \"0.1\"` for the current public protocol.\n- ToolHost is only for structured user input flows.\n- Untrusted or agent-generated source should use the secure runtime.\n- Raw docs are `.md` files with `slex` fences, not `.mdx`.\n````\n\n## Skills\n\nThe `skills/` directory provides these task entry points:\n\n- `/slexkit`: overview, architecture boundaries, and positioning\n- `/author`: write display-oriented `slex` fences with Markdown fallback\n- `/host`: integrate Markdown, Streamdown, Obsidian, or custom hosts\n- `/toolhost`: build confirmations, choices, and structured forms\n- `/secure`: configure sandbox runtime and host policy\n- `/update`: regenerate AI docs after API, docs, or component changes\n\nUse `/author` for display UI. Use `/toolhost` when the host must receive a submitted result.\n\n## MCP\n\n`@slexkit/mcp` provides read-only access to SlexKit documentation, examples, and Slex source validation. Keep the public surface small and natural: docs, examples, validate.\n\n```slex\n{\n namespace: \"ai_mcp_tools\",\n layout: {\n \"grid:tools\": {\n columns: 1,\n mdColumns: 3,\n \"card:docs\": {\n title: \"slexkitDocs\",\n icon: \"book-open-text\",\n \"text:body\": { text: \"Search or fetch Markdown docs by query, group, slug, or raw .md URL.\" }\n },\n \"card:examples\": {\n title: \"slexkitExamples\",\n icon: \"code\",\n \"text:body\": { text: \"Browse component examples, ToolHost templates, and host integration snippets.\" }\n },\n \"card:validate\": {\n title: \"slexkitValidate\",\n icon: \"check-circle\",\n \"text:body\": { text: \"Parse Slex source and return diagnostics plus component usage.\" }\n }\n }\n }\n}\n```\n\n### Quick Install\n\n```sh\nnpx add-mcp @slexkit/mcp\n```\n\nOr specify an app:\n\n```sh\nnpx add-mcp @slexkit/mcp -a claude-code\nnpx add-mcp @slexkit/mcp -a codex\nnpx add-mcp @slexkit/mcp -a cursor\nnpx add-mcp @slexkit/mcp -a vscode\nnpx add-mcp @slexkit/mcp -a zed\n```\n\n### Manual Installation\n\n```slex\n{\n namespace: \"ai_manual_configs\",\n layout: {\n \"tabs:manualConfigs\": {\n value: \"cursor\",\n tabs: [\n {\n value: \"cursor\",\n label: \"Cursor\",\n content: {\n \"code-block:cursor\": {\n title: \".cursor/mcp.json\",\n language: \"json\",\n code: \"{\\n \\\"mcpServers\\\": {\\n \\\"slexkit\\\": {\\n \\\"command\\\": \\\"npx\\\",\\n \\\"args\\\": [\\\"-y\\\", \\\"@slexkit/mcp\\\"]\\n }\\n }\\n}\"\n }\n }\n },\n {\n value: \"codex\",\n label: \"Codex\",\n content: {\n \"code-block:codex\": {\n title: \"config.toml\",\n language: \"toml\",\n code: \"[mcp_servers.slexkit]\\ncommand = \\\"npx\\\"\\nargs = [\\\"-y\\\", \\\"@slexkit/mcp\\\"]\"\n }\n }\n },\n {\n value: \"vscode\",\n label: \"VS Code\",\n content: {\n \"code-block:vscode\": {\n title: \".vscode/mcp.json\",\n language: \"json\",\n code: \"{\\n \\\"servers\\\": {\\n \\\"slexkit\\\": {\\n \\\"command\\\": \\\"npx\\\",\\n \\\"args\\\": [\\\"-y\\\", \\\"@slexkit/mcp\\\"],\\n \\\"type\\\": \\\"stdio\\\"\\n }\\n }\\n}\"\n }\n }\n }\n ]\n }\n }\n}\n```\n\n## Troubleshooting\n\n- MCP server does not start: verify `npx` and MCP config JSON, then restart the IDE.\n- Tool calls fail: restart the MCP server and confirm `tools/list` exposes only `slexkitDocs`, `slexkitExamples`, and `slexkitValidate`.\n- Docs are stale: run `bun run ai:docs` or `bun run build:core`.\n- Wrong raw source route: use `.md` routes with `slex` fences. Do not request `.mdx`.",
|
|
120
|
+
"hash": "eab33b74"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"id": "components/accordion",
|
|
124
|
+
"group": "Components",
|
|
125
|
+
"title": "Accordion",
|
|
126
|
+
"summary": "Expandable grouped panels.",
|
|
127
|
+
"href": "/docs/components/accordion",
|
|
128
|
+
"rawHref": "/docs/components/accordion.md",
|
|
129
|
+
"sourcePath": "site/content/components/accordion/en-US.md",
|
|
130
|
+
"body": "---\ntitle: \"Accordion\"\ncategory: Disclosure\nstatus: ready\nsummary: \"Multi-panel collapse for FAQs or grouped details.\"\n---\n# Accordion\n\nManages multiple collapsible panels, with one or more open at a time.\n\n<!-- slex:spec-example:start component=\"accordion\" id=\"basic\" sourceHash=\"0a070e32\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_accordion_typical\",\n \"layout\": {\n \"accordion:faq\": {\n \"multiple\": true,\n \"value\": [\n \"install\"\n ],\n \"items\": [\n {\n \"value\": \"install\",\n \"label\": \"Install\",\n \"icon\": \"download-simple\",\n \"content\": \"Prepare dependencies.\"\n },\n {\n \"value\": \"review\",\n \"label\": \"Review\",\n \"icon\": \"check-circle\",\n \"content\": \"Check the result.\"\n },\n {\n \"value\": \"ship\",\n \"label\": \"Ship\",\n \"icon\": \"rocket-launch\",\n \"content\": \"Publish the change.\"\n }\n ]\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for FAQs, grouped details, and collapsible setting lists.\n- Not suitable for a single expandable area (use `collapsible`).\n- Related components: `collapsible` for single expandable regions.\n- Use `$value` and `onchange` for controlled expansion.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"accordion\" sourceHash=\"e838d3e9\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `value` | string \\| string[] | No | Yes | | Current expanded item value; use an array when multiple is true. |\n| `multiple` | boolean | No | No | `false` | Allow multiple items to be expanded at the same time. |\n| `items` | array | No | No | | Panel definitions with value, label, content, and optional icon. |\n| `items[].icon` | string | No | No | | Icon name shown before an item trigger label. |\n| `onchange` | write-expression | No | No | | Write expression invoked when expanded items change. |\n<!-- slex:spec-api:end -->",
|
|
131
|
+
"hash": "9e90867f"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"id": "components/badge",
|
|
135
|
+
"group": "Components",
|
|
136
|
+
"title": "Badge",
|
|
137
|
+
"summary": "Compact label for status or classification.",
|
|
138
|
+
"href": "/docs/components/badge",
|
|
139
|
+
"rawHref": "/docs/components/badge.md",
|
|
140
|
+
"sourcePath": "site/content/components/badge/en-US.md",
|
|
141
|
+
"body": "---\ntitle: \"Badge\"\ncategory: Content\nstatus: ready\nsummary: \"Compact label for status or classification.\"\n---\n# Badge\n\nCompact status label component with semantic tone colors.\n\n<!-- slex:spec-example:start component=\"badge\" id=\"basic\" sourceHash=\"0f5f8aba\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_badge_typical\",\n \"layout\": {\n \"row:badges\": {\n \"badge:ready\": {\n \"label\": \"ready\",\n \"icon\": \"check-circle\",\n \"tone\": \"success\"\n },\n \"badge:pending\": {\n \"label\": \"pending\",\n \"tone\": \"warning\"\n },\n \"badge:info\": {\n \"label\": \"info\",\n \"tone\": \"info\"\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for status indicators (success / warning / error), classification labels, and count markers.\n- Not suitable for long text labels (use `callout`) or interactive triggers (use `button`).\n- Related components: `callout` for titled message blocks, `stat` for numeric metrics.\n- Multiple badges are typically placed inside a `row`.\n- Use `tone` only for semantic state, not as an arbitrary style picker.\n\n### Tone variants\n\n```slex\n{\n namespace: \"doc_badge_tone_diff\",\n layout: {\n \"row:tones\": {\n \"badge:info\": {\n label: \"info\",\n tone: \"info\"\n },\n \"badge:success\": {\n label: \"success\",\n tone: \"success\"\n },\n \"badge:warning\": {\n label: \"warning\",\n tone: \"warning\"\n },\n \"badge:danger\": {\n label: \"danger\",\n tone: \"danger\"\n },\n \"badge:muted\": {\n label: \"muted\",\n tone: \"muted\"\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"badge\" sourceHash=\"5621b8b3\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `label` | string | No | Yes | | Badge text. |\n| `text` | string | No | Yes | | Alias for label. |\n| `content` | string | No | Yes | | Alias for label. |\n| `icon` | string | No | No | | Icon name shown before the badge label. |\n| `tone` | string: info, success, warning, danger, muted | No | No | `\"info\"` | Semantic tone applied to the badge. |\n| `variant` | string: info, success, warning, danger, muted | No | No | | Alias for tone. |\n<!-- slex:spec-api:end -->",
|
|
142
|
+
"hash": "fb8275e7"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"id": "components/button",
|
|
146
|
+
"group": "Components",
|
|
147
|
+
"title": "Button",
|
|
148
|
+
"summary": "Action trigger.",
|
|
149
|
+
"href": "/docs/components/button",
|
|
150
|
+
"rawHref": "/docs/components/button.md",
|
|
151
|
+
"sourcePath": "site/content/components/button/en-US.md",
|
|
152
|
+
"body": "---\ntitle: \"Button\"\ncategory: Action\nstatus: ready\nsummary: \"Action trigger button.\"\n---\n# Button\n\nTriggers actions in interactive SlexKit layouts.\n\n<!-- slex:spec-example:start component=\"button\" id=\"basic\" sourceHash=\"267bd8d1\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_button_typical\",\n \"layout\": {\n \"row:actions\": {\n \"button:save\": {\n \"label\": \"Save\",\n \"icon\": \"floppy-disk\",\n \"variant\": \"primary\"\n },\n \"button:cancel\": {\n \"label\": \"Cancel\",\n \"variant\": \"secondary\"\n },\n \"button:delete\": {\n \"label\": \"Delete\",\n \"variant\": \"danger\"\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for form submission, confirmation actions, and command triggers.\n- When `href` is present, the button renders as a button-styled link action; use `link` for ordinary inline navigation.\n- `selected`, `active`, and `pressed` describe the visual state of the button icon and pressed metadata.\n- Related components: `link` for navigation instead of actions, `submit` for ToolHost submission flows.\n- Multiple buttons are typically placed inside a `row`.\n- Use `variant` only for semantic action types, not as a general style picker.\n\n### Variants\n\n```slex\n{\n namespace: \"doc_button_variant_diff\",\n layout: {\n \"row:variants\": {\n \"button:primary\": {\n label: \"Primary\",\n variant: \"primary\"\n },\n \"button:secondary\": {\n label: \"Secondary\",\n variant: \"secondary\"\n },\n \"button:danger\": {\n label: \"Danger\",\n variant: \"danger\"\n },\n \"button:ghost\": {\n label: \"Ghost\",\n variant: \"ghost\"\n }\n }\n }\n}\n```\n\n### Disabled state\n\n```slex\n{\n namespace: \"doc_button_disabled_diff\",\n layout: {\n \"row:disabled\": {\n \"button:enabled\": {\n label: \"Enabled\"\n },\n \"button:disabled\": {\n label: \"Disabled\",\n disabled: true\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"button\" sourceHash=\"11a5a574\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `label` | string | No | Yes | | Visible button text and accessible name. |\n| `icon` | string | No | No | | Icon name shown before the label. |\n| `iconOnly` | boolean | No | No | `false` | Show only the icon while retaining label as the accessible name. |\n| `variant` | string: primary, secondary, danger, ghost | No | No | `\"primary\"` | Semantic action variant. |\n| `disabled` | boolean | No | Yes | `false` | Disable the action. |\n| `href` | string | No | Yes | | Render the button surface as a link to this URL. |\n| `target` | string | No | No | | Link target used when href is present. |\n| `title` | string | No | Yes | | Tooltip and accessible-label fallback. |\n| `selected` | boolean | No | Yes | | Render the icon in its selected visual state. |\n| `active` | boolean | No | Yes | | Render the icon in its active visual state. |\n| `pressed` | boolean | No | Yes | | Expose pressed state and render the selected icon style. |\n| `onclick` | write-expression | No | No | | Write expression invoked when the button is clicked. |\n<!-- slex:spec-api:end -->",
|
|
153
|
+
"hash": "30463322"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"id": "components/callout",
|
|
157
|
+
"group": "Components",
|
|
158
|
+
"title": "Callout",
|
|
159
|
+
"summary": "Highlighted contextual message.",
|
|
160
|
+
"href": "/docs/components/callout",
|
|
161
|
+
"rawHref": "/docs/components/callout.md",
|
|
162
|
+
"sourcePath": "site/content/components/callout/en-US.md",
|
|
163
|
+
"body": "---\ntitle: \"Callout\"\ncategory: Content\nstatus: ready\nsummary: \"Highlighted contextual message for notes, warnings, and tips.\"\n---\n# Callout\n\nProminent notice block with title, body text, and semantic tone.\n\n<!-- slex:spec-example:start component=\"callout\" id=\"basic\" sourceHash=\"e07c6bdd\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_callout_typical\",\n \"layout\": {\n \"callout:notice\": {\n \"tone\": \"info\",\n \"title\": \"Notice\",\n \"icon\": \"info\",\n \"text\": \"Use callout for information that should stand out.\"\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for operation instructions, caution warnings, success prompts, and informational messages.\n- Not suitable for pure status labels (use `badge`) or interactive content that needs its own flow.\n- Related components: `badge` for compact labels, `toast` for transient feedback.\n- Child components can be nested inside a callout to extend the body area.\n- Use `tone` only for semantic state, not as an arbitrary style picker.\n\n### Tone variants\n\n```slex\n{\n namespace: \"doc_callout_tone_diff\",\n layout: {\n \"column:tones\": {\n \"callout:info\": {\n tone: \"info\",\n title: \"Info\",\n text: \"This is an informational message.\"\n },\n \"callout:success\": {\n tone: \"success\",\n title: \"Success\",\n text: \"Operation completed successfully.\"\n },\n \"callout:warning\": {\n tone: \"warning\",\n title: \"Warning\",\n text: \"Please review before proceeding.\"\n },\n \"callout:danger\": {\n tone: \"danger\",\n title: \"Danger\",\n text: \"This action cannot be undone.\"\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"callout\" sourceHash=\"aed6ad17\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `title` | string | No | Yes | | Callout title. |\n| `heading` | string | No | Yes | | Alias for title. |\n| `label` | string | No | Yes | | Alias for title. |\n| `icon` | string | No | No | | Icon name shown before the title. |\n| `text` | string | No | Yes | | Callout body text. |\n| `message` | string | No | Yes | | Alias for text. |\n| `content` | string | No | Yes | | Alias for text. |\n| `tone` | string: info, success, warning, danger | No | No | `\"info\"` | Semantic tone for the callout. |\n| child components | object | No | No | | Nested component fields are rendered as child content in field order. |\n<!-- slex:spec-api:end -->",
|
|
164
|
+
"hash": "d16f713d"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"id": "components/card",
|
|
168
|
+
"group": "Components",
|
|
169
|
+
"title": "Card",
|
|
170
|
+
"summary": "Bordered grouping container.",
|
|
171
|
+
"href": "/docs/components/card",
|
|
172
|
+
"rawHref": "/docs/components/card.md",
|
|
173
|
+
"sourcePath": "site/content/components/card/en-US.md",
|
|
174
|
+
"body": "---\ntitle: \"Card\"\ncategory: Layout\nstatus: ready\nsummary: \"Bordered grouping container for related content.\"\n---\n# Card\n\nBordered container with optional title and semantic tone.\n\n<!-- slex:spec-example:start component=\"card\" id=\"basic\" sourceHash=\"74b8c7a0\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_card_typical\",\n \"layout\": {\n \"card:metrics\": {\n \"title\": \"Metrics\",\n \"icon\": \"chart-bar\",\n \"grid:items\": {\n \"columns\": 2,\n \"stat:requests\": {\n \"label\": \"Requests\",\n \"value\": \"1.2k\",\n \"unit\": \"/min\"\n },\n \"stat:latency\": {\n \"label\": \"Latency\",\n \"value\": \"42\",\n \"unit\": \"ms\"\n }\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for grouped metrics, settings blocks, and information summaries.\n- Not suitable for page-level section headers (use `section`) or pure layout containers (use `column` or `grid`).\n- Related components: `section` provides a complete page block structure (title + subtitle + action), while `card` is more lightweight.\n- Child components arrange naturally inside a card; nest `row`, `column`, or `grid`.\n- Use `tone` only for semantic state, not as an arbitrary style picker.\n\n### Tone variants\n\n```slex\n{\n namespace: \"doc_card_tone_diff\",\n layout: {\n \"row:tones\": {\n \"card:info\": {\n title: \"Info\",\n tone: \"info\",\n \"text:body\": {\n text: \"Information card.\"\n }\n },\n \"card:success\": {\n title: \"Success\",\n tone: \"success\",\n \"text:body\": {\n text: \"Success card.\"\n }\n },\n \"card:warning\": {\n title: \"Warning\",\n tone: \"warning\",\n \"text:body\": {\n text: \"Warning card.\"\n }\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"card\" sourceHash=\"add47956\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `title` | string | No | Yes | | Card title. |\n| `icon` | string | No | No | | Icon name shown before the title. |\n| `tone` | string: info, success, warning, danger, muted | No | No | | Optional semantic tone for the card surface. |\n| child components | object | No | No | | Nested component fields are rendered as child content in field order. |\n<!-- slex:spec-api:end -->",
|
|
175
|
+
"hash": "99f4bf99"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"id": "components/checkbox",
|
|
179
|
+
"group": "Components",
|
|
180
|
+
"title": "Checkbox",
|
|
181
|
+
"summary": "Boolean checkbox input.",
|
|
182
|
+
"href": "/docs/components/checkbox",
|
|
183
|
+
"rawHref": "/docs/components/checkbox.md",
|
|
184
|
+
"sourcePath": "site/content/components/checkbox/en-US.md",
|
|
185
|
+
"body": "---\ntitle: \"Checkbox\"\ncategory: Input\nstatus: ready\nsummary: \"Boolean checkbox for confirmations and multi-select.\"\n---\n# Checkbox\n\nBoolean toggle for confirmation or multi-select scenarios.\n\n<!-- slex:spec-example:start component=\"checkbox\" id=\"basic\" sourceHash=\"060e0c05\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_checkbox_typical\",\n \"layout\": {\n \"checkbox:agree\": {\n \"checked\": true,\n \"label\": \"I agree\",\n \"icon\": \"handshake\"\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for terms agreement, multi-select settings, and per-item enable/disable.\n- Not suitable for instant-activation toggles (use `switch`) or mutually exclusive options (use `radio-group`).\n- Related components: `switch` for instant effect toggles, `radio-group` for exclusive options.\n- Multiple options are typically arranged vertically inside a `column`.\n- Use `$checked` and `onchange` for state binding.\n\n### Checked / disabled states\n\n```slex\n{\n namespace: \"doc_checkbox_state_diff\",\n layout: {\n \"column:diff\": {\n \"checkbox:checked\": {\n label: \"Checked\",\n checked: true\n },\n \"checkbox:unchecked\": {\n label: \"Unchecked\"\n },\n \"checkbox:disabled-checked\": {\n label: \"Disabled checked\",\n checked: true,\n disabled: true\n },\n \"checkbox:disabled\": {\n label: \"Disabled\",\n disabled: true\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"checkbox\" sourceHash=\"a507c04a\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `checked` | boolean | No | Yes | `false` | Checked state. |\n| `label` | string | No | Yes | | Checkbox label. |\n| `icon` | string | No | No | | Icon name shown before the visible label. |\n| `disabled` | boolean | No | Yes | `false` | Disable the checkbox. |\n| `haptic` | boolean | No | No | `true` | Enable vibration feedback on supported devices. |\n| `haptics` | boolean | No | No | `true` | Alias for haptic. |\n| `onchange` | write-expression | No | No | | Write expression invoked when checked state changes. |\n<!-- slex:spec-api:end -->",
|
|
186
|
+
"hash": "6d83ab0c"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"id": "components/code-block",
|
|
190
|
+
"group": "Components",
|
|
191
|
+
"title": "Code Block",
|
|
192
|
+
"summary": "Formatted code or log block.",
|
|
193
|
+
"href": "/docs/components/code-block",
|
|
194
|
+
"rawHref": "/docs/components/code-block.md",
|
|
195
|
+
"sourcePath": "site/content/components/code-block/en-US.md",
|
|
196
|
+
"body": "---\ntitle: \"Code Block\"\ncategory: Content\nstatus: ready\nsummary: \"Code or configuration snippet display.\"\n---\n# Code Block\n\nDisplay code, configuration, or source snippets with a language label and optional title.\n\n<!-- slex:spec-example:start component=\"code-block\" id=\"basic\" sourceHash=\"9c3453f7\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_code_block_typical\",\n \"layout\": {\n \"code-block:config\": {\n \"title\": \"Config\",\n \"icon\": \"code\",\n \"language\": \"js\",\n \"code\": \"export const enabled = true;\"\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for code samples, JSON config, CLI snippets, and log output.\n- Not suitable for runnable SlexKit examples (use `slex` fence or `playground`).\n- Related components: `playground` for editable interactive previews.\n- Code content is display-only; editing is not supported.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"code-block\" sourceHash=\"0cc54fab\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `code` | string | No | Yes | | Code text content. |\n| `source` | string | No | Yes | | Alias for code. |\n| `content` | string | No | Yes | | Alias for code. |\n| `language` | string | No | No | | Language label. |\n| `title` | string | No | No | | Code block title. |\n| `icon` | string | No | No | | Icon name shown before the title. |\n| `lineNumbers` | boolean | No | No | `true` | Show line numbers. |\n<!-- slex:spec-api:end -->",
|
|
197
|
+
"hash": "171d1695"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"id": "components/collapsible",
|
|
201
|
+
"group": "Components",
|
|
202
|
+
"title": "Collapsible",
|
|
203
|
+
"summary": "Single expandable region.",
|
|
204
|
+
"href": "/docs/components/collapsible",
|
|
205
|
+
"rawHref": "/docs/components/collapsible.md",
|
|
206
|
+
"sourcePath": "site/content/components/collapsible/en-US.md",
|
|
207
|
+
"body": "---\ntitle: \"Collapsible\"\ncategory: Disclosure\nstatus: ready\nsummary: \"Single expandable content area.\"\n---\n# Collapsible\n\nManages a single expand/collapse region for supplementary details or secondary information.\n\n<!-- slex:spec-example:start component=\"collapsible\" id=\"basic\" sourceHash=\"d074a138\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_collapsible_typical\",\n \"layout\": {\n \"collapsible:more\": {\n \"open\": true,\n \"trigger\": \"Details\",\n \"icon\": \"caret-circle-down\",\n \"content\": \"This secondary content can be collapsed.\"\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for expandable details, supplementary notes, and collapsible secondary info.\n- Not suitable for multi-panel lists (use `accordion`).\n- Related components: `accordion` for multi-panel collapse.\n- Child components extend the default body content area.\n- Use `$value` and `onchange` for controlled expansion.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"collapsible\" sourceHash=\"7580b7c4\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `open` | boolean | No | Yes | `false` | Expanded state. |\n| `trigger` | string | No | Yes | | Trigger button text. |\n| `icon` | string | No | No | | Icon name shown before trigger text. |\n| `content` | string | No | Yes | | Static body content. |\n| `onchange` | write-expression | No | No | | Write expression invoked when open state changes. |\n| child components | object | No | No | | Nested component fields are rendered as child content in field order. |\n<!-- slex:spec-api:end -->",
|
|
208
|
+
"hash": "003307a3"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"id": "components/column",
|
|
212
|
+
"group": "Components",
|
|
213
|
+
"title": "Column",
|
|
214
|
+
"summary": "Vertical layout container.",
|
|
215
|
+
"href": "/docs/components/column",
|
|
216
|
+
"rawHref": "/docs/components/column.md",
|
|
217
|
+
"sourcePath": "site/content/components/column/en-US.md",
|
|
218
|
+
"body": "---\ntitle: \"Column\"\ncategory: Layout\nstatus: ready\nsummary: \"Vertical layout container for forms, text, and control groups.\"\n---\n# Column\n\nBasic vertical layout container.\n\n<!-- slex:spec-example:start component=\"column\" id=\"basic\" sourceHash=\"b28bf5e9\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_column_typical\",\n \"layout\": {\n \"column:form\": {\n \"input:name\": {\n \"placeholder\": \"Name\"\n },\n \"input:email\": {\n \"placeholder\": \"Email\"\n },\n \"button:save\": {\n \"label\": \"Save\"\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for form field groups, settings panels, description text, and sequences of actions.\n- Not suitable for horizontal layouts (use `row`) or equal-width card grids (use `grid`).\n- Related components: `row` for horizontal layout, `grid` for two-dimensional equal-width layout.\n- Place child components as fields, stacked top-to-bottom.\n- Default width fills the parent container; height is content-driven.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"column\" sourceHash=\"5a83045d\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| child components | object | No | No | | Nested component fields are rendered as child content in field order. |\n<!-- slex:spec-api:end -->",
|
|
219
|
+
"hash": "718a5b54"
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"id": "components/divider",
|
|
223
|
+
"group": "Components",
|
|
224
|
+
"title": "Divider",
|
|
225
|
+
"summary": "Visual separator.",
|
|
226
|
+
"href": "/docs/components/divider",
|
|
227
|
+
"rawHref": "/docs/components/divider.md",
|
|
228
|
+
"sourcePath": "site/content/components/divider/en-US.md",
|
|
229
|
+
"body": "---\ntitle: \"Divider\"\ncategory: Content\nstatus: ready\nsummary: \"Separator line, optionally with label.\"\n---\n# Divider\n\nHorizontal separator, optionally with a centered text label.\n\n<!-- slex:spec-example:start component=\"divider\" id=\"basic\" sourceHash=\"888b7416\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_divider_typical\",\n \"layout\": {\n \"column:content\": {\n \"text:top\": {\n \"text\": \"Above\"\n },\n \"divider:line\": {\n \"label\": \"Divider\",\n \"icon\": \"flag\"\n },\n \"text:bottom\": {\n \"text\": \"Below\"\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for form sections, settings groups, and visual separation between content paragraphs.\n- Not suitable as a spacing mechanism (use layout container `gap`).\n- Related components: `section` for more structured block separation.\n- Place inside a `column` to separate upper and lower content areas.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"divider\" sourceHash=\"92dc5387\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `label` | string | No | Yes | | Text shown in the divider. |\n| `icon` | string | No | No | | Icon name shown before the label. |\n<!-- slex:spec-api:end -->",
|
|
230
|
+
"hash": "cc7df031"
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"id": "components/grid",
|
|
234
|
+
"group": "Components",
|
|
235
|
+
"title": "Grid",
|
|
236
|
+
"summary": "Responsive grid container.",
|
|
237
|
+
"href": "/docs/components/grid",
|
|
238
|
+
"rawHref": "/docs/components/grid.md",
|
|
239
|
+
"sourcePath": "site/content/components/grid/en-US.md",
|
|
240
|
+
"body": "---\ntitle: \"Grid\"\ncategory: Layout\nstatus: ready\nsummary: \"Responsive equal-width grid for sibling cards, metrics, and field groups.\"\n---\n# Grid\n\nResponsive equal-width column layout with breakpoint-prefixed column count.\n\n<!-- slex:spec-example:start component=\"grid\" id=\"basic\" sourceHash=\"fc9c72e9\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_grid_typical\",\n \"layout\": {\n \"grid:stats\": {\n \"columns\": 1,\n \"mdColumns\": 3,\n \"stat:a\": {\n \"label\": \"Requests\",\n \"value\": \"1.2k\"\n },\n \"stat:b\": {\n \"label\": \"Success\",\n \"value\": \"98%\"\n },\n \"stat:c\": {\n \"label\": \"Errors\",\n \"value\": \"3\"\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for metric dashboards, card lists, and horizontal equal-width groups of form fields.\n- Not suitable for mixed-width layouts (use `row` + `column` combinations) or single-column arrangements (use `column`).\n- Related components: `row` for horizontal layout without equal-width guarantees, `column` for vertical layout.\n- Child components are automatically equal-width — best for same-level content.\n- Use `gap` to override the spacing; when omitted, the grid keeps its theme CSS default.\n\n### Column variants\n\n```slex\n{\n namespace: \"doc_grid_columns_diff\",\n layout: {\n \"column:demo\": {\n \"text:cols2\": {\n text: \"columns: 2\"\n },\n \"grid:cols2\": {\n columns: 2,\n \"stat:a\": {\n label: \"A\",\n value: \"1\"\n },\n \"stat:b\": {\n label: \"B\",\n value: \"2\"\n },\n \"stat:c\": {\n label: \"C\",\n value: \"3\"\n }\n },\n \"text:cols3\": {\n text: \"columns: 3\"\n },\n \"grid:cols3\": {\n columns: 3,\n \"stat:a\": {\n label: \"A\",\n value: \"1\"\n },\n \"stat:b\": {\n label: \"B\",\n value: \"2\"\n },\n \"stat:c\": {\n label: \"C\",\n value: \"3\"\n }\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"grid\" sourceHash=\"e8ab3ffb\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `columns` | number | No | Yes | `1` | Base column count. |\n| `smColumns` | number | No | Yes | | Column count at the small breakpoint. |\n| `mdColumns` | number | No | Yes | | Column count at the medium breakpoint. |\n| `lgColumns` | number | No | Yes | | Column count at the large breakpoint. |\n| `xlColumns` | number | No | Yes | | Column count at the extra-large breakpoint. |\n| `gap` | string | No | Yes | | Spacing between grid items. |\n| child components | object | No | No | | Nested component fields are rendered as child content in field order. |\n<!-- slex:spec-api:end -->",
|
|
241
|
+
"hash": "07d773b2"
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"id": "components/icon",
|
|
245
|
+
"group": "Components",
|
|
246
|
+
"title": "Icon",
|
|
247
|
+
"summary": "Shared icon field capability.",
|
|
248
|
+
"href": "/docs/components/icon",
|
|
249
|
+
"rawHref": "/docs/components/icon.md",
|
|
250
|
+
"sourcePath": "site/content/components/icon/en-US.md",
|
|
251
|
+
"body": "---\ntitle: \"Icon\"\ncategory: Component\nstatus: ready\nsummary: \"Shared icon field capability used by all icon-supporting components.\"\n---\n# Icon\n\nIcon is not a standalone layout component — it is a component field capability. Components that support the `icon` field resolve icon names through the global icon manager and place the resulting SVG in their own visual position.\n\n<!-- slex:spec-example:start component=\"icon\" id=\"basic\" sourceHash=\"5fce5080\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"spec_button_basic\",\n \"layout\": {\n \"button:demo\": {\n \"label\": \"Settings\",\n \"icon\": \"gear-six\",\n \"iconOnly\": true,\n \"variant\": \"ghost\"\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Supported components\n\n| Component | Field | Description |\n| --- | --- | --- |\n| accordion | `items[].icon` | Icon before each accordion item trigger label. |\n| badge | `icon` | Icon before the badge text. |\n| button | `icon`, `iconOnly` | Icon before the button label; `iconOnly: true` shows only the icon while still requiring `label`. |\n| callout | `icon` | Icon before the callout title. |\n| card | `icon` | Icon before the card title. |\n| checkbox | `icon` | Icon before the visible checkbox label. |\n| code-block | `icon` | Icon before the code block title. |\n| collapsible | `icon` | Icon before the collapsible trigger text. |\n| divider | `icon` | Icon before the divider label text. |\n| link | `icon` | Icon before the link text. |\n| progress | `icon` | Icon before the progress label. |\n| radio-group | `icon`, `options[].icon` | Icon before the group label and each option label. |\n| section | `icon` | Icon before the section title. |\n| select | `icon`, `options[].icon` | `icon` decorates the top label; `options[].icon` decorates menu options and the selected value. |\n| slider | `icon` | Icon before the slider label. |\n| stat | `icon` | Icon before the metric label. |\n| switch | `icon` | Icon before the visible switch label. |\n| table | `columns[].icon` | Icon before each table column header label. |\n| tabs | `tabs[].icon`, `tabs[].iconOnly` | Icon in each tab trigger; selected tab may request an active variant. |\n| toast | `icon` | Replaces the default left semantic marker with an icon while retaining tone color. |\n\n`playground` internally reuses button for its toolbar actions, so it benefits from the same icon manager, but it does not expose a public `icon` field. `select`'s dropdown arrow is a fixed control indicator; `select.icon` only decorates the top label, not the dropdown arrow.\n\n## Name resolution\n\nUnprefixed icon names default to Iconify's `ph` collection (Phosphor icons).\n\n```slex\n{\n namespace: \"doc_icon_names\",\n layout: {\n \"row:icons\": {\n \"button:chart\": {\n label: \"Chart\",\n icon: \"ChartBar\"\n },\n \"button:copy\": {\n label: \"Copy\",\n icon: \"lucide:copy\",\n variant: \"secondary\"\n },\n \"button:settings\": {\n label: \"Settings\",\n icon: \"gear-six\",\n iconOnly: true,\n variant: \"ghost\"\n }\n }\n }\n}\n```\n\nCommon syntax:\n\n| Syntax | Resolves to |\n| ----------------- | ---------------------------------------- |\n| `ChartBar` | `ph:chart-bar` |\n| `chart-bar` | `ph:chart-bar` |\n| `ph:chart-bar` | Phosphor / Iconify `ph` collection |\n| `lucide:copy` | Iconify `lucide` collection |\n| `brand:logo-mark` | Custom icon registered by the host via `registerIcon` |\n\n## Tabs with icons\n\n```slex\n{\n namespace: \"doc_icon_tabs\",\n layout: {\n \"tabs:main\": {\n value: \"overview\",\n tabs: [\n {\n value: \"overview\",\n label: \"Overview\",\n icon: \"ChartBar\"\n },\n {\n value: \"activity\",\n label: \"Activity\",\n icon: \"pulse\"\n },\n {\n value: \"settings\",\n label: \"Settings\",\n icon: \"Gear\",\n iconOnly: true\n }\n ]\n }\n }\n}\n```\n\n## Label and title icons\n\n```slex\n{\n namespace: \"doc_icon_labels\",\n layout: {\n \"column:demo\": {\n \"callout:notice\": {\n title: \"Notice\",\n icon: \"info\",\n text: \"Title-bearing components can use the same icon field.\"\n },\n \"accordion:faq\": {\n value: \"install\",\n items: [\n {\n value: \"install\",\n label: \"Install\",\n icon: \"download-simple\",\n content: \"Prepare dependencies.\"\n },\n {\n value: \"review\",\n label: \"Review\",\n icon: \"check-circle\",\n content: \"Verify the result.\"\n }\n ]\n },\n \"select:env\": {\n label: \"Environment\",\n icon: \"server\",\n value: \"prod\",\n options: [\n { label: \"Development\", value: \"dev\", icon: \"code\" },\n { label: \"Production\", value: \"prod\", icon: \"rocket-launch\" }\n ]\n },\n \"radio-group:mode\": {\n label: \"Mode\",\n icon: \"sliders-horizontal\",\n value: \"auto\",\n options: [\n { label: \"Auto\", value: \"auto\", icon: \"sparkle\" },\n { label: \"Manual\", value: \"manual\", icon: \"wrench\" }\n ]\n }\n }\n }\n}\n```\n\n## Custom icons\n\nHosts can register their own SVG icons before mounting content. Once registered, all components that support the `icon` field can use them by name.\n\n```js\nimport { registerIcon, registerIcons } from \"slexkit\";\n\nregisterIcon(\n \"brand:logo-mark\",\n '<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><path d=\"M8 1 15 15H1L8 1Z\"/></svg>',\n { aliases: [\"logo-mark\"] },\n);\n\nregisterIcons({\n \"status:healthy\":\n '<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><circle cx=\"8\" cy=\"8\" r=\"6\"/></svg>',\n});\n```\n\n## Usage rules\n\n- `iconOnly` is supported on `button` and `tabs` only; titles, labels, and column headers never hide text.\n- `iconOnly` must be paired with `label`, `title`, or `aria-label` — assistive technology needs a readable name.\n- Without a prefix, prefer Phosphor semantic names; use an explicit prefix such as `lucide:copy` for cross-icon-set usage.\n- The runtime does not accept arbitrary URLs as icon sources. Remote icons are fetched via the Iconify API and the returned SVG passes through basic filtering.\n- Bundled icons display synchronously on first paint; unbundled icons load asynchronously. When the network is unavailable, components retain their text content.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"icon\" sourceHash=\"cf2e09a0\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `icon` | string | No | No | | Icon name resolved through the global icon manager. |\n| `iconOnly` | boolean | No | No | | Render only the icon while retaining an accessible label where supported. |\n| `items[].icon` | string | No | No | | Accordion item trigger icon. |\n| `options[].icon` | string | No | No | | Select or radio option icon. |\n| `columns[].icon` | string | No | No | | Table column header icon. |\n| `tabs[].icon` | string | No | No | | Tab trigger icon. |\n| `tabs[].iconOnly` | boolean | No | No | | Tab trigger icon-only mode. |\n<!-- slex:spec-api:end -->",
|
|
252
|
+
"hash": "a8497d85"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"id": "components/input",
|
|
256
|
+
"group": "Components",
|
|
257
|
+
"title": "Input",
|
|
258
|
+
"summary": "Text or engineering-value input.",
|
|
259
|
+
"href": "/docs/components/input",
|
|
260
|
+
"rawHref": "/docs/components/input.md",
|
|
261
|
+
"sourcePath": "site/content/components/input/en-US.md",
|
|
262
|
+
"body": "---\ntitle: \"Input\"\ncategory: Input\nstatus: ready\nsummary: \"Single-line text or engineering value input.\"\n---\n# Input\n\nSingle-line text input with controlled value, placeholder, label, description, native types, engineering input, and disabled state.\n\n<!-- slex:spec-example:start component=\"input\" id=\"basic\" sourceHash=\"4215f98a\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_input_typical\",\n \"layout\": {\n \"input:name\": {\n \"label\": \"Project\",\n \"value\": \"SlexKit\",\n \"placeholder\": \"Enter name\",\n \"description\": \"Visible labels keep form fields scannable.\"\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for name input, search boxes, email/password, and other single-line text.\n- Use `type: \"engineering\"` for values such as `4.7k`, `2.2uF`, or `1e-3`.\n- Not suitable for numeric range selection (use `slider`).\n- Related components: `select` for option selection, `slider` for numeric ranges.\n- Typically placed inside a `column` to compose forms.\n- Use `$value` and `onchange` for state binding.\n- Numeric inputs show decrement and increment buttons by default. Use `step`, `min`, and `max` to define quick-adjust behavior, or set `controls: false` to hide them.\n- `onchange` fires when the user edits the value or clicks a step control.\n- `type: \"number\"` still emits a string value. Convert with `Number($event)` or use `type: \"engineering\"` to read parsed results.\n- Use `invalid` plus `error` for validation feedback. Error text is linked through `aria-describedby`.\n\n### Label and unit\n\n`label` renders as a clickable native label; `unit` renders as trailing text, suitable for voltage, resistance, frequency, etc.\n\n```slex\n{\n namespace: \"doc_input_label_unit\",\n layout: {\n \"input:voltage\": {\n label: \"Voltage\",\n value: \"3.3\",\n unit: \"V\",\n description: \"Supply rail\"\n }\n }\n}\n```\n\n### Disabled state\n\n```slex\n{\n namespace: \"doc_input_disabled_diff\",\n layout: {\n \"row:diff\": {\n \"input:enabled\": {\n value: \"Editable\",\n placeholder: \"Type here\"\n },\n \"input:disabled\": {\n value: \"Disabled\",\n disabled: true\n }\n }\n }\n}\n```\n\n### Engineering input\n\n`type: \"engineering\"` uses a text input (not the native number type). Component state retains the raw string and additionally exposes parsed results:\n\n```slex\n{\n namespace: \"doc_input_engineering\",\n layout: {\n \"input:resistance\": {\n type: \"engineering\",\n value: \"4.7kΩ\"\n },\n \"stat:parsed\": {\n label: \"Parsed value\",\n $value: \"resistance.valid ? resistance.number : 'Invalid'\",\n $unit: \"resistance.unit\"\n }\n }\n}\n```\n\nSupports scientific notation and SI prefixes: `p`, `n`, `u`, `µ`, `m`, `k`, `K`, `M`, `meg`, `G`, `T`. Units are captured but not converted across physical dimensions.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"input\" sourceHash=\"08bdd046\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `value` | string | No | Yes | | Current input value. |\n| `label` | string | No | Yes | | Input label. |\n| `unit` | string | No | Yes | | Trailing unit text. |\n| `description` | string | No | Yes | | Assistive description below the input. |\n| `help` | string | No | Yes | | Alias for description. |\n| `hint` | string | No | Yes | | Alias for description. |\n| `error` | string | No | Yes | | Error text shown below the input and linked with aria-describedby. |\n| `errorMessage` | string | No | Yes | | Alias for error. |\n| `invalid` | boolean | No | Yes | `false` | Mark the input as invalid with aria-invalid and error styling. |\n| `placeholder` | string | No | No | | Placeholder text for empty values. |\n| `type` | string | No | No | `\"text\"` | Input value kind; use engineering for parsed engineering values. |\n| `disabled` | boolean | No | Yes | `false` | Disable editing. |\n| `readonly` | boolean | No | Yes | `false` | Make the input read-only. |\n| `readOnly` | boolean | No | Yes | `false` | Alias for readonly. |\n| `required` | boolean | No | Yes | `false` | Mark the input as required. |\n| `id` | string | No | No | | Native input id; defaults to a stable id derived from the component name. |\n| `name` | string | No | No | | Native input name attribute. |\n| `min` | string \\| number | No | Yes | | Minimum value used by numeric input controls. |\n| `max` | string \\| number | No | Yes | | Maximum value used by numeric input controls. |\n| `step` | string \\| number | No | Yes | | Step size used by numeric input controls. |\n| `controls` | boolean | No | Yes | `true` | Show decrement and increment buttons for numeric inputs. |\n| `onchange` | write-expression | No | No | | Write expression invoked when the value changes. |\n<!-- slex:spec-api:end -->",
|
|
263
|
+
"hash": "558a0288"
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
"id": "components/link",
|
|
267
|
+
"group": "Components",
|
|
268
|
+
"title": "Link",
|
|
269
|
+
"summary": "Inline navigation link.",
|
|
270
|
+
"href": "/docs/components/link",
|
|
271
|
+
"rawHref": "/docs/components/link.md",
|
|
272
|
+
"sourcePath": "site/content/components/link/en-US.md",
|
|
273
|
+
"body": "---\ntitle: \"Link\"\ncategory: Content\nstatus: ready\nsummary: \"Navigation or lightweight jump action.\"\n---\n# Link\n\nText link navigation.\n\n<!-- slex:spec-example:start component=\"link\" id=\"basic\" sourceHash=\"cf9f6896\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_link_typical\",\n \"layout\": {\n \"column:links\": {\n \"link:docs\": {\n \"href\": \"/components\",\n \"icon\": \"arrow-square-out\",\n \"text\": \"View components\"\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for page navigation, external links, and inline text links.\n- Not suitable for primary action buttons (use `button`).\n- Related components: `button` for explicit action triggers.\n- Keep link text short.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"link\" sourceHash=\"7404dc9d\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `href` | string | No | No | | Target URL. |\n| `text` | string | No | Yes | | Visible link text. |\n| `label` | string | No | Yes | | Alias for text. |\n| `content` | string | No | Yes | | Alias for text. |\n| `icon` | string | No | No | | Icon name shown before link text. |\n| `target` | string | No | No | | Native link target attribute. |\n| `variant` | string: default, muted | No | No | `\"default\"` | Link visual variant. |\n<!-- slex:spec-api:end -->",
|
|
274
|
+
"hash": "8eeb87ad"
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"id": "components/playground",
|
|
278
|
+
"group": "Components",
|
|
279
|
+
"title": "Playground",
|
|
280
|
+
"summary": "Interactive source preview.",
|
|
281
|
+
"href": "/docs/components/playground",
|
|
282
|
+
"rawHref": "/docs/components/playground.md",
|
|
283
|
+
"sourcePath": "site/content/components/playground/en-US.md",
|
|
284
|
+
"body": "---\ntitle: \"Playground\"\ncategory: Tooling\nstatus: ready\nsummary: \"Interactive preview and editor for SlexKit / Markdown source.\"\n---\n# Playground\n\nInteractive preview component that embeds editable, runnable SlexKit or Markdown source previews inside a page.\n\n<!-- slex:spec-example:start component=\"playground\" id=\"basic\" sourceHash=\"bccf9e4b\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_playground_typical\",\n \"layout\": {\n \"playground:demo\": {\n \"title\": \"Stat Playground\",\n \"previewMinHeight\": \"180px\",\n \"source\": {\n \"namespace\": \"inner_stat_demo\",\n \"layout\": {\n \"stat:value\": {\n \"label\": \"Requests\",\n \"value\": \"1.2k\",\n \"unit\": \"/min\"\n }\n }\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for runnable examples in documentation, interactive demos, and source code teaching.\n- Not suitable for ordinary component rendering (use layout components directly).\n- Related components: `code-block` for read-only code display.\n- Nested source is rendered in an isolated scope — it does not conflict with the parent namespace.\n- Playground is a documentation and teaching surface, not part of the product UI.\n- Public fields cover source parsing, preview placement, theme toggle controls, labels, and open/copy URLs.\n- `domain`, `pluginVersion`, and `version` are host integration metadata and are not part of the public component API.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"playground\" sourceHash=\"beb5402a\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `source` | object \\| string | No | No | | SlexKit or Markdown source to preview. |\n| `sourceType` | string: slex, markdown, auto-markdown | No | No | `\"slex\"` | Source parser mode. |\n| `title` | string | No | No | | Playground title. |\n| `previewAlign` | string: center, start | No | No | `\"center\"` | Vertical preview alignment in render mode. |\n| `alignPreview` | string: center, start | No | No | | Alias for previewAlign. |\n| `previewPlacement` | string: center, start | No | No | | Alias for previewAlign. |\n| `previewMinHeight` | string | No | No | | Minimum preview area height. |\n| `previewMaxWidth` | string | No | No | | Maximum preview content width. |\n| `themeToggle` | boolean | No | No | `false` | Show the theme toggle action. |\n| `showThemeToggle` | boolean | No | No | `false` | Alias for themeToggle. |\n| `enableThemeToggle` | boolean | No | No | `false` | Alias for themeToggle. |\n| `themeLabel` | string | No | No | | Accessible label for the theme toggle action. |\n| `themeToggleLabel` | string | No | No | | Alias for themeLabel. |\n| `sourceTypeLabel` | string | No | No | | Accessible label for the source type selector. |\n| `copyLabel` | string | No | No | | Accessible label for the copy source action. |\n| `openWebLabel` | string | No | No | | Accessible label for opening the source in the standalone playground. |\n| `webUrl` | string | No | No | | Standalone playground URL used by the open action. |\n| `playgroundUrl` | string | No | No | | Alias for webUrl. |\n<!-- slex:spec-api:end -->",
|
|
285
|
+
"hash": "7313ccc4"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"id": "components/progress",
|
|
289
|
+
"group": "Components",
|
|
290
|
+
"title": "Progress",
|
|
291
|
+
"summary": "Progress bar.",
|
|
292
|
+
"href": "/docs/components/progress",
|
|
293
|
+
"rawHref": "/docs/components/progress.md",
|
|
294
|
+
"sourcePath": "site/content/components/progress/en-US.md",
|
|
295
|
+
"body": "---\ntitle: \"Progress\"\ncategory: Feedback\nstatus: ready\nsummary: \"Progress bar.\"\n---\n# Progress\n\nDisplay task completion progress controlled by value.\n\n<!-- slex:spec-example:start component=\"progress\" id=\"basic\" sourceHash=\"d5fe2c3c\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_progress_typical\",\n \"layout\": {\n \"progress:build\": {\n \"label\": \"Build progress\",\n \"icon\": \"gear-six\",\n \"value\": 64\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for build progress, upload progress, and task completion.\n- Not suitable for indeterminate waiting states.\n- Related components: `stat` for numeric metric display.\n- Value range is 0-100.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"progress\" sourceHash=\"a6111bbf\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `value` | number | No | Yes | `0` | Progress percentage from 0 to 100. |\n| `label` | string | No | Yes | | Progress label. |\n| `icon` | string | No | No | | Icon name shown before the label. |\n| `indeterminate` | boolean | No | Yes | `false` | Render an indeterminate progress state without aria-valuenow. |\n<!-- slex:spec-api:end -->",
|
|
296
|
+
"hash": "7d008e59"
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
"id": "components/radio-group",
|
|
300
|
+
"group": "Components",
|
|
301
|
+
"title": "Radio Group",
|
|
302
|
+
"summary": "Single-choice option group.",
|
|
303
|
+
"href": "/docs/components/radio-group",
|
|
304
|
+
"rawHref": "/docs/components/radio-group.md",
|
|
305
|
+
"sourcePath": "site/content/components/radio-group/en-US.md",
|
|
306
|
+
"body": "---\ntitle: \"Radio Group\"\ncategory: Input\nstatus: ready\nsummary: \"Mutually exclusive radio selection.\"\n---\n# Radio Group\n\nMutually exclusive option selection for small choice sets.\n\n<!-- slex:spec-example:start component=\"radio-group\" id=\"basic\" sourceHash=\"4ad4aa38\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_radio_group_typical\",\n \"layout\": {\n \"radio-group:mode\": {\n \"label\": \"Mode\",\n \"icon\": \"sliders-horizontal\",\n \"value\": \"auto\",\n \"options\": [\n {\n \"label\": \"Auto\",\n \"value\": \"auto\",\n \"icon\": \"sparkle\"\n },\n {\n \"label\": \"Manual\",\n \"value\": \"manual\",\n \"icon\": \"wrench\"\n }\n ]\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for mode selection, small enum choices, and mutually exclusive config items.\n- Not suitable for many options (use `select`).\n- Related components: `select` for dropdown single selection with more options.\n- Keep options between 2-5 items.\n- Use `$value` and `onchange` for state binding.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"radio-group\" sourceHash=\"9770be28\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `value` | string | No | Yes | | Current selected value. |\n| `label` | string | No | Yes | | Group label. |\n| `icon` | string | No | No | | Icon name shown before the group label. |\n| `options` | array | No | No | | Options with label, value, and optional icon. |\n| `options[].icon` | string | No | No | | Icon name shown before a single option label. |\n| `disabled` | boolean | No | Yes | `false` | Disable every radio option in the group. |\n| `orientation` | string: vertical, horizontal | No | No | `\"vertical\"` | Radio option layout direction. |\n| `haptic` | boolean | No | No | `true` | Enable vibration feedback on supported devices. |\n| `haptics` | boolean | No | No | `true` | Alias for haptic. |\n| `name` | string | No | No | | Native radio group name shared by options. |\n| `onchange` | write-expression | No | No | | Write expression invoked when selection changes. |\n<!-- slex:spec-api:end -->",
|
|
307
|
+
"hash": "c3190775"
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
"id": "components/row",
|
|
311
|
+
"group": "Components",
|
|
312
|
+
"title": "Row",
|
|
313
|
+
"summary": "Horizontal layout container.",
|
|
314
|
+
"href": "/docs/components/row",
|
|
315
|
+
"rawHref": "/docs/components/row.md",
|
|
316
|
+
"sourcePath": "site/content/components/row/en-US.md",
|
|
317
|
+
"body": "---\ntitle: \"Row\"\ncategory: Layout\nstatus: ready\nsummary: \"Horizontal layout container for toolbars, status lines, and button groups.\"\n---\n# Row\n\nBasic horizontal layout container.\n\n<!-- slex:spec-example:start component=\"row\" id=\"basic\" sourceHash=\"6d23c539\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_row_typical\",\n \"layout\": {\n \"row:toolbar\": {\n \"justify\": \"space-between\",\n \"text:title\": {\n \"text\": \"Runtime status\"\n },\n \"button:refresh\": {\n \"label\": \"Refresh\"\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for button groups, toolbars, status indicator lines, and table header actions.\n- Not suitable for vertical form fields (use `column`) or equal-width card grids (use `grid`).\n- Related components: `column` for vertical layout, `grid` for two-dimensional equal-width layout.\n- Children arrange at natural width; use `justify` to control distribution.\n- Use `gap` to override the spacing between children; when omitted, the row keeps its theme CSS default.\n\n### Justify variants\n\n```slex\n{\n namespace: \"doc_row_justify_diff\",\n layout: {\n \"column:demo\": {\n \"text:start\": {\n text: \"justify: start\"\n },\n \"row:justify-start\": {\n justify: \"start\",\n \"badge:a\": {\n label: \"A\"\n },\n \"badge:b\": {\n label: \"B\"\n }\n },\n \"text:center\": {\n text: \"justify: center\"\n },\n \"row:justify-center\": {\n justify: \"center\",\n \"badge:a\": {\n label: \"A\"\n },\n \"badge:b\": {\n label: \"B\"\n }\n },\n \"text:end\": {\n text: \"justify: end\"\n },\n \"row:justify-end\": {\n justify: \"end\",\n \"badge:a\": {\n label: \"A\"\n },\n \"badge:b\": {\n label: \"B\"\n }\n },\n \"text:space-between\": {\n text: \"justify: space-between\"\n },\n \"row:justify-between\": {\n justify: \"space-between\",\n \"badge:a\": {\n label: \"A\"\n },\n \"badge:b\": {\n label: \"B\"\n }\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"row\" sourceHash=\"70f941d7\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `justify` | string: start, center, end, space-between, space-around | No | No | `\"start\"` | Main-axis distribution. |\n| `align` | string: start, center, end, baseline, stretch | No | No | `\"center\"` | Cross-axis alignment. |\n| `gap` | string | No | Yes | | Spacing between children. |\n| child components | object | No | No | | Nested component fields are rendered as child content in field order. |\n<!-- slex:spec-api:end -->",
|
|
318
|
+
"hash": "026953f5"
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
"id": "components/section",
|
|
322
|
+
"group": "Components",
|
|
323
|
+
"title": "Section",
|
|
324
|
+
"summary": "Page section with optional heading chrome.",
|
|
325
|
+
"href": "/docs/components/section",
|
|
326
|
+
"rawHref": "/docs/components/section.md",
|
|
327
|
+
"sourcePath": "site/content/components/section/en-US.md",
|
|
328
|
+
"body": "---\ntitle: \"Section\"\ncategory: Layout\nstatus: ready\nsummary: \"Page section with title, subtitle, optional action, and content area.\"\n---\n# Section\n\nPage-level block container with title, subtitle, optional action link, and content area.\n\n<!-- slex:spec-example:start component=\"section\" id=\"basic\" sourceHash=\"094666a8\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_section_typical\",\n \"layout\": {\n \"section:overview\": {\n \"eyebrow\": \"Dashboard\",\n \"title\": \"Runtime overview\",\n \"icon\": \"chart-bar\",\n \"subtitle\": \"This section groups the most important state.\",\n \"stat:latency\": {\n \"label\": \"Latency\",\n \"value\": \"42\",\n \"unit\": \"ms\"\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for dashboard blocks, settings groups, and categorized content areas.\n- Not suitable for purely visual cards (use `card`) or untitled containers (use `column`).\n- Related components: `card` is a lighter grouping container, while `section` provides a more complete heading structure.\n- The heading area and content area are distinct; nest any layout component inside the content area.\n\n### Eyebrow / subtitle variants\n\n```slex\n{\n namespace: \"doc_section_eyebrow_diff\",\n layout: {\n \"column:demo\": {\n \"section:with-eyebrow\": {\n eyebrow: \"Overview\",\n title: \"With eyebrow\",\n \"text:body\": {\n text: \"Eyebrow appears above the title.\"\n }\n },\n \"section:with-subtitle\": {\n title: \"With subtitle\",\n subtitle: \"Additional context below the title.\",\n \"text:body\": {\n text: \"Subtitle provides extra context.\"\n }\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"section\" sourceHash=\"03916011\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `title` | string | No | Yes | | Section title. |\n| `icon` | string | No | No | | Icon name shown before the title. |\n| `eyebrow` | string | No | Yes | | Small label above the title. |\n| `subtitle` | string | No | Yes | | Subtitle text below the title. |\n| `actionLabel` | string | No | Yes | | Optional action link label. |\n| `actionHref` | string | No | No | | Optional action link target. |\n| child components | object | No | No | | Nested component fields are rendered as child content in field order. |\n<!-- slex:spec-api:end -->",
|
|
329
|
+
"hash": "f6df61a4"
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
"id": "components/select",
|
|
333
|
+
"group": "Components",
|
|
334
|
+
"title": "Select",
|
|
335
|
+
"summary": "Dropdown selection input.",
|
|
336
|
+
"href": "/docs/components/select",
|
|
337
|
+
"rawHref": "/docs/components/select.md",
|
|
338
|
+
"sourcePath": "site/content/components/select/en-US.md",
|
|
339
|
+
"body": "---\ntitle: \"Select\"\ncategory: Input\nstatus: ready\nsummary: \"Single-select dropdown.\"\n---\n# Select\n\nSingle-select dropdown with options defined as an array and the current value controlled via value.\n\n<!-- slex:spec-example:start component=\"select\" id=\"basic\" sourceHash=\"b5675bcc\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_select_typical\",\n \"layout\": {\n \"select:env\": {\n \"label\": \"Environment\",\n \"icon\": \"server\",\n \"value\": \"prod\",\n \"options\": [\n {\n \"label\": \"Development\",\n \"value\": \"dev\",\n \"icon\": \"code\"\n },\n {\n \"label\": \"Production\",\n \"value\": \"prod\",\n \"icon\": \"rocket-launch\"\n }\n ]\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for enum selection, config items, and environment choice.\n- Not suitable for small mutually exclusive groups (use `radio-group`).\n- Related components: `radio-group` for smaller option sets.\n- Combine with `column` to compose forms.\n- Use `$value` and `onchange` for state binding.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"select\" sourceHash=\"44dbc082\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `label` | string | No | Yes | | Select label. |\n| `icon` | string | No | No | | Icon name shown before the top label. |\n| `value` | string | No | Yes | | Current selected value. |\n| `options` | array | No | No | | Options with label, value, and optional icon. |\n| `options[].icon` | string | No | No | | Icon name shown before an option label. |\n| `placeholder` | string | No | No | | Placeholder shown when no value is selected. |\n| `disabled` | boolean | No | Yes | `false` | Disable the select trigger and native select. |\n| `required` | boolean | No | Yes | `false` | Require a non-placeholder value in the native select. |\n| `variant` | string: default, toolbar | No | No | `\"default\"` | Select surface variant. |\n| `onchange` | write-expression | No | No | | Write expression invoked when selection changes. |\n<!-- slex:spec-api:end -->",
|
|
340
|
+
"hash": "43c6a193"
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"id": "components/slider",
|
|
344
|
+
"group": "Components",
|
|
345
|
+
"title": "Slider",
|
|
346
|
+
"summary": "Numeric range input.",
|
|
347
|
+
"href": "/docs/components/slider",
|
|
348
|
+
"rawHref": "/docs/components/slider.md",
|
|
349
|
+
"sourcePath": "site/content/components/slider/en-US.md",
|
|
350
|
+
"body": "---\ntitle: \"Slider\"\ncategory: Input\nstatus: ready\nsummary: \"Numeric range input.\"\n---\n# Slider\n\nNumeric range selection with min, max, step control and unit display.\n\n<!-- slex:spec-example:start component=\"slider\" id=\"basic\" sourceHash=\"a0525d92\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_slider_typical\",\n \"layout\": {\n \"slider:volume\": {\n \"label\": \"Volume\",\n \"icon\": \"speaker-high\",\n \"value\": 42,\n \"min\": 0,\n \"max\": 100,\n \"step\": 1,\n \"unit\": \"%\"\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for volume, brightness, threshold, and percentage adjustments.\n- Not suitable for precise text entry (use `input`).\n- Related components: `input` for text input.\n- Use `$value` and `onchange` for state binding.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"slider\" sourceHash=\"0939dc16\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `label` | string | No | Yes | | Slider label. |\n| `icon` | string | No | No | | Icon name shown before the label. |\n| `value` | number | No | Yes | `0` | Current numeric value. |\n| `min` | number | No | Yes | `0` | Minimum value. |\n| `max` | number | No | Yes | `100` | Maximum value. |\n| `step` | number | No | Yes | `1` | Step interval. |\n| `unit` | string | No | Yes | | Unit shown after the value. |\n| `disabled` | boolean | No | Yes | `false` | Disable the range input. |\n| `orientation` | string: horizontal, vertical | No | No | `\"horizontal\"` | Slider orientation metadata used for styling. |\n| `haptic` | boolean | No | No | `true` | Enable vibration feedback on supported devices. |\n| `haptics` | boolean | No | No | `true` | Alias for haptic. |\n| `onchange` | write-expression | No | No | | Write expression invoked when the value changes. |\n<!-- slex:spec-api:end -->",
|
|
351
|
+
"hash": "b34cc3f8"
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
"id": "components/stat",
|
|
355
|
+
"group": "Components",
|
|
356
|
+
"title": "Stat",
|
|
357
|
+
"summary": "Metric display.",
|
|
358
|
+
"href": "/docs/components/stat",
|
|
359
|
+
"rawHref": "/docs/components/stat.md",
|
|
360
|
+
"sourcePath": "site/content/components/stat/en-US.md",
|
|
361
|
+
"body": "---\ntitle: \"Stat\"\ncategory: Display\nstatus: ready\nsummary: \"Metric display with label, value, unit, and semantic tone.\"\n---\n# Stat\n\nPresent a labeled metric value with optional unit and semantic tone.\n\n<!-- slex:spec-example:start component=\"stat\" id=\"basic\" sourceHash=\"9fa58aeb\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_stat_typical\",\n \"layout\": {\n \"grid:stats\": {\n \"columns\": 2,\n \"stat:requests\": {\n \"label\": \"Requests\",\n \"icon\": \"activity\",\n \"value\": \"1.2k\",\n \"unit\": \"/min\"\n },\n \"stat:success\": {\n \"label\": \"Success\",\n \"icon\": \"check-circle\",\n \"value\": \"98.4\",\n \"unit\": \"%\",\n \"tone\": \"success\"\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for data dashboards, metric overviews, and key indicator displays.\n- Not suitable for long text (use `text`) or interactive input (use `input`).\n- Related components: `text` for text output, `badge` for label status.\n- Stats are typically used inside a `grid` or `row`.\n- Use `tone` only for semantic state, not as an arbitrary style picker.\n\n### Tone variants\n\n```slex\n{\n namespace: \"doc_stat_tone_diff\",\n layout: {\n \"row:tones\": {\n \"stat:info\": {\n label: \"Info\",\n value: \"42\",\n tone: \"info\"\n },\n \"stat:success\": {\n label: \"Success\",\n value: \"98%\",\n tone: \"success\"\n },\n \"stat:warning\": {\n label: \"Warning\",\n value: \"73\",\n tone: \"warning\"\n },\n \"stat:danger\": {\n label: \"Danger\",\n value: \"5\",\n tone: \"danger\"\n },\n \"stat:muted\": {\n label: \"Muted\",\n value: \"0\",\n tone: \"muted\"\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"stat\" sourceHash=\"389443e6\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `label` | string | No | Yes | | Metric label. |\n| `icon` | string | No | No | | Icon name shown before the label. |\n| `value` | string \\| number | No | Yes | | Metric value. |\n| `unit` | string | No | Yes | | Unit shown after the value. |\n| `tone` | string: info, success, warning, danger, muted | No | No | | Optional semantic tone. |\n| `animateInitial` | boolean | No | No | `false` | Animate the initial rendered value. |\n<!-- slex:spec-api:end -->",
|
|
362
|
+
"hash": "e352f69e"
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
"id": "components/submit",
|
|
366
|
+
"group": "Components",
|
|
367
|
+
"title": "Submit",
|
|
368
|
+
"summary": "ToolHost submit and ignore controls.",
|
|
369
|
+
"href": "/docs/components/submit",
|
|
370
|
+
"rawHref": "/docs/components/submit.md",
|
|
371
|
+
"sourcePath": "site/content/components/submit/en-US.md",
|
|
372
|
+
"body": "---\ntitle: \"Submit\"\ncategory: Action\nstatus: ready\nsummary: \"ToolHost submission boundary that returns current selection or form values to the host.\"\n---\n# Submit\n\nToolHost submission boundary component providing submit and ignore actions.\n\n<!-- slex:spec-example:start component=\"submit\" id=\"basic\" sourceHash=\"b5d89128\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_submit_typical\",\n \"layout\": {\n \"column:tool\": {\n \"input:title\": {\n \"value\": \"Release note\",\n \"placeholder\": \"Title\"\n },\n \"submit:done\": {\n \"submitLabel\": \"Submit\",\n \"ignoreLabel\": \"Ignore\",\n \"returnKeys\": [\n \"title\"\n ]\n }\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for AI toolchain confirmation forms, parameter panels, and selection confirmation flows.\n- Not suitable for ordinary action buttons (use `button`).\n- Related components: `button` for local action triggers.\n- Combine with input components such as `input` and `select` to read user choices.\n- Paths in `returnKeys` are read from the global state `g`.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"submit\" sourceHash=\"1c7c766f\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `submitLabel` | string | No | No | `\"Submit\"` | Submit button text. |\n| `ignoreLabel` | string | No | No | `\"Ignore\"` | Ignore button text. |\n| `returnKeys` | string[] | No | No | | State field paths returned to ToolHost. |\n| `disabled` | boolean | No | Yes | `false` | Disable submit action. |\n<!-- slex:spec-api:end -->",
|
|
373
|
+
"hash": "ab4cdd10"
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"id": "components/switch",
|
|
377
|
+
"group": "Components",
|
|
378
|
+
"title": "Switch",
|
|
379
|
+
"summary": "Boolean switch input.",
|
|
380
|
+
"href": "/docs/components/switch",
|
|
381
|
+
"rawHref": "/docs/components/switch.md",
|
|
382
|
+
"sourcePath": "site/content/components/switch/en-US.md",
|
|
383
|
+
"body": "---\ntitle: \"Switch\"\ncategory: Input\nstatus: ready\nsummary: \"Boolean toggle input for instant settings.\"\n---\n# Switch\n\nBoolean toggle for instant-activation settings.\n\n<!-- slex:spec-example:start component=\"switch\" id=\"basic\" sourceHash=\"9c7b3bda\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_switch_typical\",\n \"layout\": {\n \"switch:feature\": {\n \"enabled\": true,\n \"label\": \"Enable sync\",\n \"icon\": \"arrows-clockwise\"\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for feature toggles, preference enable/disable, and instant-effect settings.\n- Not suitable for confirmation-style toggles (use `checkbox`).\n- Related components: `checkbox` for confirmations or multi-select.\n- Typically placed inside a `row` or `column`.\n- Use `$enabled` and `onchange` for state binding.\n\n### Enabled / disabled variants\n\n```slex\n{\n namespace: \"doc_switch_state_diff\",\n layout: {\n \"row:diff\": {\n \"switch:enabled\": {\n label: \"Enabled\",\n enabled: true\n },\n \"switch:disabled\": {\n label: \"Disabled\"\n },\n \"switch:enabled-not-available\": {\n label: \"Enabled (not available)\",\n enabled: true,\n disabled: true\n },\n \"switch:disabled-not-available\": {\n label: \"Disabled (not available)\",\n disabled: true\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"switch\" sourceHash=\"27367ad0\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `enabled` | boolean | No | Yes | `false` | Enabled state. |\n| `label` | string | No | Yes | | Switch label. |\n| `icon` | string | No | No | | Icon name shown before the visible label. |\n| `disabled` | boolean | No | Yes | `false` | Disable the switch. |\n| `haptic` | boolean | No | No | `true` | Enable vibration feedback on supported devices. |\n| `haptics` | boolean | No | No | `true` | Alias for haptic. |\n| `onchange` | write-expression | No | No | | Write expression invoked when enabled state changes. |\n<!-- slex:spec-api:end -->",
|
|
384
|
+
"hash": "d72058e4"
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
"id": "components/table",
|
|
388
|
+
"group": "Components",
|
|
389
|
+
"title": "Table",
|
|
390
|
+
"summary": "Simple data table.",
|
|
391
|
+
"href": "/docs/components/table",
|
|
392
|
+
"rawHref": "/docs/components/table.md",
|
|
393
|
+
"sourcePath": "site/content/components/table/en-US.md",
|
|
394
|
+
"body": "---\ntitle: \"Table\"\ncategory: Data\nstatus: ready\nsummary: \"Structured table with columns and rows.\"\n---\n# Table\n\nStructured row-column data display with column headers and data rows.\n\n<!-- slex:spec-example:start component=\"table\" id=\"basic\" sourceHash=\"8491bf94\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_table_typical\",\n \"layout\": {\n \"table:routes\": {\n \"columns\": [\n {\n \"key\": \"name\",\n \"label\": \"Name\",\n \"icon\": \"text-t\"\n },\n {\n \"key\": \"status\",\n \"label\": \"Status\",\n \"icon\": \"check-circle\"\n }\n ],\n \"rows\": [\n {\n \"name\": \"Parse\",\n \"status\": \"ready\"\n },\n {\n \"name\": \"Publish\",\n \"status\": \"pending\"\n }\n ]\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for data lists, configuration tables, and structured information display.\n- Not suitable for card-style layouts (use `grid`).\n- Related components: `grid` for equal-width card layouts.\n- Column `key` values correspond to field names in each row.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"table\" sourceHash=\"9a408c2a\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `columns` | array | No | No | | Column definitions with key, label, and optional icon. |\n| `columns[].icon` | string | No | No | | Icon name shown before a column label. |\n| `rows` | array | No | No | | Row data objects keyed by column key. |\n| `items` | array | No | No | | Alias for rows. |\n<!-- slex:spec-api:end -->",
|
|
395
|
+
"hash": "be8190d7"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"id": "components/tabs",
|
|
399
|
+
"group": "Components",
|
|
400
|
+
"title": "Tabs",
|
|
401
|
+
"summary": "Tabbed view switcher.",
|
|
402
|
+
"href": "/docs/components/tabs",
|
|
403
|
+
"rawHref": "/docs/components/tabs.md",
|
|
404
|
+
"sourcePath": "site/content/components/tabs/en-US.md",
|
|
405
|
+
"body": "---\ntitle: \"Tabs\"\ncategory: Navigation\nstatus: ready\nsummary: \"Tabbed view switcher.\"\n---\n# Tabs\n\nSwitch between named content panels.\n\n<!-- slex:spec-example:start component=\"tabs\" id=\"basic\" sourceHash=\"df3a28e8\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_tabs_typical\",\n \"layout\": {\n \"tabs:main\": {\n \"value\": \"overview\",\n \"tabs\": [\n {\n \"value\": \"overview\",\n \"label\": \"Overview\"\n },\n {\n \"value\": \"settings\",\n \"label\": \"Settings\"\n }\n ]\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for settings panel sections, content category switching, and configuration groups.\n- Not suitable for multi-page wizards — use explicit page state and navigation.\n- Related components: `button` for submit actions, `link` for cross-page navigation.\n- Use `$value` and `onchange` for controlled switching.\n\n### Orientation variants\n\n```slex\n{\n namespace: \"doc_tabs_orientation_diff\",\n layout: {\n \"row:orientations\": {\n \"column:h\": {\n \"text:horiz\": {\n text: \"horizontal (default)\"\n },\n \"tabs:horizontal\": {\n value: \"a\",\n orientation: \"horizontal\",\n tabs: [\n {\n value: \"a\",\n label: \"Tab A\"\n },\n {\n value: \"b\",\n label: \"Tab B\"\n }\n ]\n }\n },\n \"column:v\": {\n \"text:vert\": {\n text: \"vertical\"\n },\n \"tabs:vertical\": {\n value: \"a\",\n orientation: \"vertical\",\n tabs: [\n {\n value: \"a\",\n label: \"Tab A\"\n },\n {\n value: \"b\",\n label: \"Tab B\"\n }\n ]\n }\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"tabs\" sourceHash=\"a8288681\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `value` | string | No | Yes | | Current active tab value. |\n| `tabs` | array | No | No | | Tab definitions with value, label, content, icon, and iconOnly. |\n| `tabs[].icon` | string | No | No | | Icon name shown before a tab trigger label. |\n| `tabs[].iconOnly` | boolean | No | No | | Show only the tab icon while retaining label as accessible text. |\n| `orientation` | string: horizontal, vertical | No | No | `\"horizontal\"` | Tab list orientation. |\n| `onchange` | write-expression | No | No | | Write expression invoked when the active tab changes. |\n<!-- slex:spec-api:end -->",
|
|
406
|
+
"hash": "a0029940"
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
"id": "components/text",
|
|
410
|
+
"group": "Components",
|
|
411
|
+
"title": "Text",
|
|
412
|
+
"summary": "Plain text display.",
|
|
413
|
+
"href": "/docs/components/text",
|
|
414
|
+
"rawHref": "/docs/components/text.md",
|
|
415
|
+
"sourcePath": "site/content/components/text/en-US.md",
|
|
416
|
+
"body": "---\ntitle: \"Text\"\ncategory: Display\nstatus: ready\nsummary: \"Short text output for status, description, and results.\"\n---\n# Text\n\nOutput text content for status messages, descriptions, and result display.\n\n<!-- slex:spec-example:start component=\"text\" id=\"basic\" sourceHash=\"bd63ce36\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_text_typical\",\n \"layout\": {\n \"text:status\": {\n \"text\": \"System is healthy\"\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for status text, short descriptions, label values, and lightweight output.\n- Not suitable for long paragraphs or structured data (use `table`).\n- Related components: `stat` for numeric metrics, `badge` for status labels.\n- Keep text short; use multiple `text` nodes for longer content.\n- Typically placed inside `row`, `column`, or `card`.\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"text\" sourceHash=\"32589fbc\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `text` | string | No | Yes | | Displayed text. |\n| `content` | string | No | Yes | | Alias for text. |\n| `label` | string | No | Yes | | Alias for text. |\n| `variant` | string: default, muted | No | No | `\"default\"` | Text visual variant. |\n| `class` | string | No | No | | Additional host-controlled CSS class. |\n<!-- slex:spec-api:end -->",
|
|
417
|
+
"hash": "075cd122"
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
"id": "components/toast",
|
|
421
|
+
"group": "Components",
|
|
422
|
+
"title": "Toast",
|
|
423
|
+
"summary": "Transient notification.",
|
|
424
|
+
"href": "/docs/components/toast",
|
|
425
|
+
"rawHref": "/docs/components/toast.md",
|
|
426
|
+
"sourcePath": "site/content/components/toast/en-US.md",
|
|
427
|
+
"body": "---\ntitle: \"Toast\"\ncategory: Feedback\nstatus: ready\nsummary: \"Transient notification with semantic type.\"\n---\n# Toast\n\nInline notification with semantic type and optional icon.\n\n<!-- slex:spec-example:start component=\"toast\" id=\"basic\" sourceHash=\"1cab367e\" -->\n```slex\n{\n \"slex\": \"0.1\",\n \"namespace\": \"doc_toast_typical\",\n \"layout\": {\n \"toast:saved\": {\n \"type\": \"success\",\n \"title\": \"Saved\",\n \"icon\": \"check-circle\",\n \"description\": \"Changes have been written.\"\n }\n }\n}\n```\n<!-- slex:spec-example:end -->\n\n## Usage Notes\n\n- Use for save confirmations, operation errors, and status change notifications.\n- Not suitable for messages that require user response or long-term visibility — use an inline form or `callout` instead.\n- Related components: `callout` for in-page prompt blocks, `badge` for compact status.\n- Set `duration` for auto-hide behavior; without it, the toast renders as an inline notification card.\n- Use `type` only for semantic message purpose.\n\n### Type variants\n\n```slex\n{\n namespace: \"doc_toast_type_diff\",\n layout: {\n \"column:types\": {\n \"toast:info\": {\n type: \"info\",\n title: \"Info\",\n description: \"A new update is available.\"\n },\n \"toast:success\": {\n type: \"success\",\n title: \"Success\",\n description: \"Operation completed.\"\n },\n \"toast:warning\": {\n type: \"warning\",\n title: \"Warning\",\n description: \"Review before proceeding.\"\n },\n \"toast:danger\": {\n type: \"danger\",\n title: \"Error\",\n description: \"Something went wrong.\"\n }\n }\n }\n}\n```\n\n## API Reference {#api}\n\n<!-- slex:spec-api:start component=\"toast\" sourceHash=\"854ea3a2\" -->\n| Field | Type | Required | Dynamic | Default | Description |\n|---|---|---|---|---|---|\n| `title` | string | No | Yes | | Toast title. |\n| `heading` | string | No | Yes | | Alias for title. |\n| `label` | string | No | Yes | | Alias for title. |\n| `icon` | string | No | No | | Icon name shown at the left of the toast. |\n| `description` | string | No | Yes | | Toast body text. |\n| `text` | string | No | Yes | | Alias for description. |\n| `message` | string | No | Yes | | Alias for description. |\n| `content` | string | No | Yes | | Alias for description. |\n| `type` | string: info, success, warning, danger | No | No | `\"info\"` | Semantic notification type. |\n| `tone` | string: info, success, warning, danger | No | No | `\"info\"` | Alias for type. |\n| `duration` | number | No | No | | Auto-hide delay in milliseconds. |\n| `dismissable` | boolean | No | No | `true` | Show a close button. |\n| `dismissible` | boolean | No | No | `true` | Alias for dismissable. |\n| `closeLabel` | string | No | No | `\"Close notification\"` | Accessible close button label. |\n| `closeAriaLabel` | string | No | No | | Alias for closeLabel. |\n<!-- slex:spec-api:end -->",
|
|
428
|
+
"hash": "960011bc"
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
"id": "reference/spec",
|
|
432
|
+
"group": "Reference",
|
|
433
|
+
"title": "Slex Specification",
|
|
434
|
+
"summary": "Public Slex expression envelope, component keys, props, directives, and lifecycle.",
|
|
435
|
+
"href": "/docs/reference/spec",
|
|
436
|
+
"rawHref": "/docs/reference/spec.md",
|
|
437
|
+
"sourcePath": "site/content/reference/spec/en-US.md",
|
|
438
|
+
"body": "---\ntitle: Slex Specification v0.1\ncategory: Reference\nstatus: ready\norder: 10\nsummary: \"Public Slex expression envelope, component keys, props, directives, lifecycle, and runtime API contract.\"\nslexkitRenderMode: component\n---\n\n# Slex Specification v0.1\n\nSlex expression envelope, component keys, props, directives, lifecycle, and runtime API contract — SlexKit v0's entire public protocol in one place. Source of truth for implementors, test authors, and host adapter authors.\n\n**v0/beta.** The current implementation may evolve, but the protocol version (v0.1) is independent of the SlexKit package version. The same protocol may remain stable across multiple package releases.\n\n## 1. Slex expression envelope\n\nThe canonical Slex expression is an object. Slex source is the JavaScript object literal string form of that expression:\n\n```ts\ntype SlexExpression = {\n slex?: \"0.1\";\n namespace: string;\n g: Record<string, unknown>;\n layout: Record<string, unknown>;\n};\n```\n\n`slex`, `namespace`, `g`, and `layout` are the standard envelope fields. `slex: \"0.1\"` is an optional protocol marker for humans, agents, and validators; it does not affect namespace identity or state merging. The runtime also accepts a bare component tree as shorthand: if the input has component keys at the top level and does not define `namespace`, `g`, or `layout`, it is normalized to:\n\n```js\n{ namespace: \"default\", g: {}, layout: <input> }\n```\n\n## 2. Layout key\n\nComponent keys use the format:\n\n```\nComponentKey = ComponentType \":\" Identifier\n```\n\n- `ComponentType` maps to a type in the component registry.\n- `Identifier` may be empty (e.g. `\"box:\"`).\n- Named components use `Identifier` for instance state and lifecycle hooks.\n- Keys without `:` are not rendered as component nodes.\n\nReserved context names: `g`, `api`, `$event`, `$item`, `$index`, `$key`.\n\n## 3. Props classification\n\n### Static props\n\nPassed to the component unchanged:\n\n```js\n\"text:title\": { text: \"Hello\" }\n```\n\n### `$` read-pipes\n\nA string value on a `$`-prefixed key (excluding `$if`, `$for`, `$key`) is evaluated as a JavaScript expression. The result is passed under the key with the `$` prefix removed:\n\n```js\n\"text:value\": { \"$content\": \"'Count: ' + g.count\" }\n// Resolves to: content = \"Count: <value of g.count>\"\n```\n\n### `on*` write-pipes\n\nA string value on an `on*`-prefixed key is executed as a JavaScript statement:\n\n```js\n\"button:add\": { onclick: \"g.count++\" }\n\"input:name\": { onchange: \"g.name = String($event || '')\" }\n```\n\nThe handler receives `$event` as the event data.\n\n### Structural directives\n\n`$if`, `$for`, `$key` are structural directives and are never passed to the component as props. Children of `$if` and `$for` components are treated as the conditional/iterated subtree.\n\n## 4. `g` merge\n\nWhen the same namespace is mounted or ingested again, the new `g` is merged into the existing store:\n\n| Value type | Merge behavior |\n| ------------------- | ------------------------ |\n| Function | Overwrites the old value |\n| Array | Replaces entirely |\n| Plain object | Recursively deep-merges |\n| Other scalar | Overwrites the old value |\n| Keys not in new `g` | Preserved from old `g` |\n\nThe new `layout` always replaces the current layout. Layout is never deep-merged.\n\n## 5. Expression context\n\nExpressions can access these variables:\n\n| Variable | Type | Scope |\n| ------------------ | ----------------------------- | ------------------------ |\n| `g` | Reactive state proxy | Always |\n| Component state | e.g. `slider.value` | Named components |\n| `api` | Host-injected object | If `api` option provided |\n| `$event` | Event data | `on*` handlers only |\n| `$item` | Current array item | `$for` context only |\n| `$index` | Current array index | `$for` context only |\n| `$key` | Current item key | `$for` context only |\n| Named `$for` alias | e.g. `user` for `\"card:user\"` | `$for` context only |\n\nExpression evaluation errors are caught and produce a warning with namespace and path information. The last known value is returned as a fallback.\n\n## 6. Component instance state\n\nComponent registration declares a state mode:\n\n```ts\nregister(type, renderer, { state: \"value\" | \"checked\" | \"enabled\" | \"readable\" | \"none\" });\n```\n\n| Mode | Writable | Behavior |\n| ---------- | ------------------ | ------------------------------------------------------------- |\n| `value` | `value` | Input component; `value` writable from expressions and events |\n| `checked` | `checked`, `value` | Checkbox-like boolean component; both synced and writable |\n| `enabled` | `enabled` | Switch-like boolean component; enabled state is writable |\n| `readable` | (none) | Readable from expressions; write emits console warning |\n| `none` | (none) | No instance state exposed |\n\nInput components (`value`/`checked`/`enabled` modes) sync `change` events to instance state automatically. Duplicate-named components share one namespace-level state instance.\n\n`input` with `type: \"engineering\"` is a value-mode component with additional parsed fields. `value` remains the raw input string, while `number`, `valid`, `prefix`, `unit`, `normalized`, and optional `error` expose the parsed engineering number. Supported v1 notation includes scientific notation plus SI prefixes (`p`, `n`, `u`, `µ`, `m`, `k`, `K`, `M`, `meg`, `G`, `T`) with an optional unit suffix. Units are captured but not dimension-converted.\n\n## 7. `$if`\n\n`$if` controls component existence:\n\n```js\n\"card:panel\": {\n \"$if\": \"g.visible\",\n \"text:body\": { text: \"Visible\" }\n}\n```\n\n- **Truthy** -mounts the component and its subtree with enter animation if `$enter` is defined.\n- **Falsy** -unmounts the component and subtree with leave animation if `$leave` is defined, then fires lifecycle hooks, disposers, and subtree cleanup.\n\n## 8. `$for`\n\n`$for` renders a component for each array element:\n\n```js\n\"text:item\": {\n \"$for\": \"g.items\",\n \"$key\": \"id\",\n \"$content\": \"$item.label\"\n}\n```\n\nContext variables: `$item`, `$index`, `$key`. Named components inject the current item as a same-name variable.\n\n### `$key` strategy\n\n| `$key` value | Behavior |\n| ------------------------ | ------------------------------------------------------------------------------- |\n| `\"$value\"` | Use the primitive item itself |\n| `\"id\"` or other property | Read that property from object items |\n| Omitted | Use `item.id` if available; otherwise fall back to index with a console warning |\n\nPrimitive arrays should always specify `$key: \"$value\"`.\n\n### $for phases\n\n1. **Delete** -Remove items whose keys are absent from the new array (with leave animation).\n2. **Add/update/reorder** -Create new items for new keys; update retained items' `forCtx` (item reference, index); reorder DOM nodes to match array order. Updated items fire `onUpdate_<name>`.\n3. **Trim** -Defensively remove excess children.\n\n## 9. Lifecycle and cleanup\n\nConvention hooks on `g`:\n\n```\ng.onMount_<name>() -after component is appended to DOM\ng.onUnmount_<name>() -before component is removed from DOM\ng.onUpdate_<name>() -after $for item changes (index or item reference)\n```\n\nComponent implementations can register resource cleanup:\n\n```ts\nattachComponentDisposer(el, dispose);\n```\n\nComponent disposal is triggered by normal unmount, `$if` toggle-off, `$for` item removal, root cleanup, and `disposeNamespace()`.\n\n## 10. Public runtime API\n\n| Function | Signature | Description |\n| ----------------------------------- | ------------------------------------------- | -------------------------------------------------------------------- |\n| `mount` | `(input, container, options?) => Cleanup` | Parse, merge state, render component tree |\n| `ingest` | `(input) => boolean` | Ingest state-only Slex, no rendering |\n| `boot` | `(options?) => void` | Enhance static page code blocks |\n| `disposeNamespace` | `(namespace) => void` | Release namespace roots, store, and cache |\n| `register` | `(type, renderer, options?) => void` | Register component type |\n| `getRenderer` | `(type) => ComponentRenderer \\| undefined` | Look up a registered renderer |\n| `getIcon` | `(name, state?) => string` | Resolve a registered or bundled icon synchronously |\n| `loadIcon` | `(name, state?) => Promise<string>` | Resolve an icon, using Iconify fallback when not bundled |\n| `registerIcon` | `(name, svg, options?) => void` | Register one global SVG icon for all components with an `icon` field |\n| `registerIcons` | `(icons, options?) => void` | Register multiple global SVG icons |\n| `clearRegisteredIcons` | `() => void` | Clear all custom registered icons |\n| `getRegisteredIcon` | `(name, state?) => string` | Look up only registered icons (no Phosphor fallback) |\n| `normalizeIconName` | `(name) => string` | Normalize icon name to kebab-case with set prefix |\n| `resolveIconWeight` | `(state?) => IconWeight` | Resolve icon weight from component state |\n| `resolveIconifyIcon` | `(name, state?) => {prefix, name}` | Resolve to Iconify-compatible name pair |\n| `iconifySvgUrl` | `(name, state?) => string` | Build full Iconify API SVG URL |\n| `configureComponentScope` | `(options) => void` | Configure framework adapter flush |\n| `attachComponentDisposer` | `(el, dispose) => void` | Bind cleanup to element lifecycle |\n| `createSecureRuntime` | `(policy, adapter?) => SecureRuntimeHandle` | Create gated runtime instance |\n| `mountSecureArtifact` | `(input, container, options) => Cleanup` | Mount in secure sandbox |\n| `createSlexKitMarkdownRuntimeHost` | `(options?) => MarkdownRuntimeHost` | Create Markdown host instance |\n| `getSlexKitMarkdownRuntimeHost` | `() => MarkdownRuntimeHost` | Get or create global Markdown host |\n| `installSlexKitMarkdownRuntimeHost` | `(options?) => MarkdownRuntimeHost` | Install and return global Markdown host |\n| `getSlexKitRuntimeUrl` | `() => string \\| undefined` | Get default sandbox runtime URL |\n| `setSlexKitRuntimeUrl` | `(url) => void` | Set default sandbox runtime URL |\n| `diagnoseSlexKitSource` | `(source, error) => Diagnostic` | Locate syntax error in source |\n| `parseSlexSource` | `(source) => ParseResult` | Parse Slex source to object |\n| `formatSlexKitDiagnostic` | `(diagnostic) => string` | Format diagnostic to readable string |\n\n## 11. Error types\n\n### SlexKitSyntaxError\n\nThrown when Slex source parsing fails. Includes a `diagnostic` property with `message`, `line`, `column`, `detail`, and `excerpt`.\n\n### SlexKitRuntimeError\n\nThrown when a runtime operation violates policy or encounters a runtime failure. Has properties: `kind` (`\"policy\"` | `\"network\"` | `\"timeout\"`), `code` (specific error code string), `message`, `elapsedMs`.\n\n## 12. Markdown language handling\n\nSlexKit hosts must only process explicit fence language tags:\n\n- `slex`\n\nPlain JavaScript, JSON, or untagged code blocks must not be scanned or executed.\n\n## 13. Secure runtime types\n\n```ts\ntype SecureRuntimeHandle = {\n api: SlexKitRuntimeApi;\n dispose: () => void;\n};\n```\n\nFor full secure runtime types (`HostRuntimePolicy`, `HostRuntimeAdapter`, `SlexKitRuntimeApi`, `SecureFrameOptions`, `SecureMountOptions`, sandbox message types), see the [security runtime contract](/docs/reference/security).\n\n## 14. ToolHost\n\nToolHost bridges AI tool calls to interactive UI that returns structured user input. It is separate from display-oriented `slex` fences.\n\n**Public API:**\n\n| Function | Signature | Description |\n|----------|-----------|-------------|\n| `renderToolCall` | `(call, container) => ToolRenderHandle` | Compile and mount tool UI, return promise |\n| `registerToolTemplate` | `(name, compiler) => void` | Register a custom tool template compiler |\n\n**Result type:**\n\n```ts\ntype ToolResult =\n | { toolCallId?: string; toolName: string; status: \"submitted\"; value: Record<string, unknown> }\n | { toolCallId?: string; toolName: string; status: \"ignored\"; value: null };\n```\n\n**Built-in templates:** `confirm-action`, `choose-options`, `option-list`, `fill-form`. Templates compile to standard Slex expressions using `card:tool` and `submit:actions` components. The `submit:actions` component serves as the completion boundary — it is only used by tool templates, not general display fences.\n\nFor full template reference, arguments, type definitions, and custom template development, see [ToolHost documentation](/docs/reference/toolhost).\n\n## 15. Icon system\n\nSlexKit includes a built-in icon system with Phosphor Icons, a custom registration API, and Iconify fallback support.\n\n**Public API (10 functions):** `registerIcon`, `registerIcons`, `clearRegisteredIcons`, `getIcon`, `getRegisteredIcon`, `loadIcon`, `normalizeIconName`, `resolveIconWeight`, `resolveIconifyIcon`, `iconifySvgUrl`.\n\nIcons are resolved through a three-tier chain: registered icons → bundled Phosphor (24 icons, 2 weights) → Iconify API fetch (async, `loadIcon` only). Components that accept an `icon` prop automatically display the resolved SVG.\n\nFor the full API reference, icon list, naming conventions, and custom icon registration, see [Icon system documentation](/docs/reference/icons).\n\n## 16. Non-goals\n\n- No public stable compatibility commitment (v0/beta).\n- Not a pure JSON cross-platform protocol.\n- No automatic security hardening of arbitrary browser APIs.\n- No heuristic scanning of code blocks to guess whether to render.\n- No implicit wrapping of display UI as function calls.",
|
|
439
|
+
"hash": "8a8391af"
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
"id": "reference/usage",
|
|
443
|
+
"group": "Reference",
|
|
444
|
+
"title": "Slex Usage Reference",
|
|
445
|
+
"summary": "Slex source structure, props, directives, events, theming, custom components, and ToolHost boundaries.",
|
|
446
|
+
"href": "/docs/reference/usage",
|
|
447
|
+
"rawHref": "/docs/reference/usage.md",
|
|
448
|
+
"sourcePath": "site/content/reference/usage/en-US.md",
|
|
449
|
+
"body": "---\ntitle: Slex Usage Reference\ncategory: Reference\nstatus: ready\norder: 20\nsummary: \"Reference for Slex source structure, props, directives, events, theming, custom components, and ToolHost boundaries.\"\nslexkitRenderMode: component\n---\n\n# Slex Usage Reference\n\nSlex source shape and runtime-facing authoring rules: props, directives, events, theming, custom components, and ToolHost boundaries. For first-time setup, start with [Getting Started](/docs/guides/quick-start). For exact protocol compatibility, use the [Slex Specification](/docs/reference/spec).\n\n## Installation\n\nMost hosts install the root package:\n\n```sh\nnpm install slexkit\n```\n\n```js\nimport { mount } from \"slexkit\";\nimport \"slexkit/style.css\";\n```\n\nComponent-free bare runtime:\n\n```sh\nnpm install slexkit @slexkit/runtime\n```\n\n```js\nimport { mount, register } from \"@slexkit/runtime\";\nimport \"@slexkit/components-svelte\";\nimport \"@slexkit/theme-shadcn/style.css\";\n```\n\nFor package boundaries and host-specific install commands, see [Package Boundaries](/docs/reference/packages).\n\n## Slex source structure\n\nA Slex source is a JavaScript object literal:\n\n```js\n{\n slex: \"0.1\",\n namespace: \"demo\",\n g: { count: 0 },\n layout: {\n \"button:add\": { text: \"Add\", onclick: \"g.count++\" },\n \"text:value\": { \"$content\": \"'Count: ' + g.count\" }\n }\n}\n```\n\n- `slex` -optional Slex protocol marker; use `\"0.1\"` for the current public protocol.\n- `namespace` -state domain identifier (defaults to `\"default\"`).\n- `g` -reactive state and logic (functions, data).\n- `layout` -component tree.\n\nAs a convenience, a bare component tree (keys containing `:`) is normalized to `{ namespace: \"default\", g: {}, layout: <tree> }`. If the bare tree includes `slex: \"0.1\"`, that marker is preserved while component keys move under `layout`.\n\n## Props\n\n### Static props\n\nPassed to the component as-is:\n\n```js\n\"text:title\": { text: \"Hello World\" }\n```\n\n### Dynamic read-pipes (`$`)\n\nA string value on a `$`-prefixed key is evaluated as a JavaScript expression. The result replaces the key stripped of the `$` prefix:\n\n```js\n\"text:value\": { \"$content\": \"'Count: ' + g.count\" }\n```\n\nThe `$` prefix is removed. The prop passed to the component is `content`. Re-evaluation is triggered automatically when any reactive dependency changes.\n\n### Write-pipes (`on*`)\n\nA string value on an `on*`-prefixed key is executed as a JavaScript statement:\n\n```js\n\"button:add\": { onclick: \"g.count++\" }\n\"input:name\": { onchange: \"g.name = String($event || '')\" }\n```\n\nThe handler receives `$event` as the event data.\n\n### Structural directives\n\n`$if`, `$for`, and `$key` are structural directives -they are not passed to the component as props.\n\n## `$if` -conditional rendering\n\nControls whether the component and its subtree are mounted:\n\n```js\n\"card:panel\": {\n \"$if\": \"g.visible\",\n \"text:body\": { text: \"I am visible\" }\n}\n```\n\nWhen the expression is truthy, the component mounts (with enter animation if `$enter` is defined). When falsy, it unmounts (with leave animation if `$leave` is defined, then cleanup).\n\n## `$for` -array iteration\n\nRenders a component for each item in an array:\n\n```js\n\"text:item\": {\n \"$for\": \"g.items\",\n \"$key\": \"id\",\n \"$content\": \"$item.label\"\n}\n```\n\nContext variables available inside `$for`: `$item` (current item), `$index` (current index), `$key` (item key). Named components also inject the current item as a same-name variable (e.g. `\"card:user\"` makes `user` available).\n\n### Key strategy\n\n`$key` supports:\n- `\"$value\"` -use the primitive item itself as key.\n- `\"id\"` (or any property name) -read that property from object items.\n- Omitted -uses `item.id` if available, otherwise falls back to index with a console warning.\n\nPrimitive array items should always specify `$key: \"$value\"`.\n\n### $for update algorithm\n\n1. **Delete phase** -remove items whose keys are no longer in the array (with leave animation).\n2. **Add/update/reorder phase** -create new items, update retained items' context (index, item reference), and reorder DOM nodes to match the array.\n3. **Trim phase** -defensively remove any excess children.\n\nWhen an item's index or item reference changes, `onUpdate_<name>` is called.\n\n## Events\n\nEvent handlers are defined as `on*` write-pipes. The component's native change/input events are automatically wired to component instance state for writable components:\n\n```js\n\"input:name\": { onchange: \"g.name = String($event || '')\" }\n```\n\nThe `$event` variable contains the event data. For change events on writable components (`value`, `checked`, or `enabled` mode), the component state is automatically synced before the handler runs.\n\n## Trusted vs secure mode\n\n### Trusted mode (default)\n\nSlex source executes in the host page realm. Use for application-generated content, repository-maintained Slex source, or already-reviewed snippets.\n\n```js\nimport { mount } from \"slexkit\";\n\nmount(script, container, { theme: \"host-shadcn\" });\n```\n\n### Secure mode\n\nUntrusted or agent-generated Slex source runs in a sandbox iframe with opaque origin. Sensitive capabilities are gated behind host policy:\n\n```js\nimport { mountSecureArtifact } from \"slexkit\";\n\nmountSecureArtifact(script, container, {\n policy: {},\n frame: { runtimeUrl: \"/slexkit.runtime.js\" },\n});\n```\n\nUse [Secure Runtime Setup](/docs/guides/security-runtime) for the deployment checklist. Use the [Security Runtime Contract](/docs/reference/security) for the full policy model, sandbox behavior, bridge protocol, and fail-closed requirements.\n\n## Theming\n\nTheme mode is resolved from the `theme` option:\n\n| Value | Behavior |\n|-------|----------|\n| `\"auto\"` | Checks container for known theme classes; falls back to `\"uno\"` |\n| `\"host-shadcn\"` | shadcn/ui compatible |\n| `\"uno\"` | Uno/Flowbite compatible |\n| `\"flowbite\"` | Flowbite compatible |\n\nDirection (`ltr`, `rtl`, `auto`) is resolved from the inherited `dir` attribute or the document element.\n\n```js\nmount(script, container, { theme: \"host-shadcn\", dir: \"auto\" });\n```\n\n## Custom components\n\nRegister a component type with a render function:\n\n```ts\nimport { register } from \"slexkit\";\n\nregister(\"custom\", (props, name, ctx) => {\n const el = ctx.document.createElement(\"div\");\n el.textContent = String(props.label ?? name);\n return el;\n}, { state: \"value\" });\n```\n\nThe `RenderContext` provides:\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `g` | reactive proxy | Global state |\n| `api` | `Record<string, unknown>` | Host-injected capabilities |\n| `dir` | `\"ltr\"` or `\"rtl\"` | Resolved direction |\n| `labels` | `Partial<Record<string, string>>` | Runtime labels |\n| `id` | `string \\| null` | Component name |\n| `emit` | `(event, data?) => void` | Event emitter |\n| `children` | `Record<string, unknown>` | Nested component tree |\n| `document` | `Document` | Owner document |\n| `renderTree` | function | Recursive render helper |\n\nUse `attachComponentDisposer(el, fn)` to bind cleanup to the component's DOM lifecycle.\n\n## ToolHost\n\nToolHost handles UI that must return structured user input (confirmations, selections, forms). It is separate from display-oriented `slex` fences.\n\nBuilt-in templates:\n- `confirm-action` -yes/no confirmation\n- `choose-options` -single or multi-select\n- `option-list` -scrollable option list\n- `fill-form` -structured form with submit\n\nTemplates compile to standard Slex source. The `submit` component serves as the completion boundary -only tool templates use it, not display fences.",
|
|
450
|
+
"hash": "aaac995d"
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"id": "reference/runtime",
|
|
454
|
+
"group": "Reference",
|
|
455
|
+
"title": "Runtime Model",
|
|
456
|
+
"summary": "Mounting, ingestion, boot, namespace store, lifecycle, and runtime APIs.",
|
|
457
|
+
"href": "/docs/reference/runtime",
|
|
458
|
+
"rawHref": "/docs/reference/runtime.md",
|
|
459
|
+
"sourcePath": "site/content/reference/runtime/en-US.md",
|
|
460
|
+
"body": "---\ntitle: Runtime Model\ncategory: Reference\nstatus: ready\norder: 30\nsummary: \"Mounting, ingestion, boot, namespace store, lifecycle hooks, component state, and runtime APIs.\"\nslexkitRenderMode: component\n---\n\n# Runtime Model\n\nThe core SlexKit runtime: entry points, namespace store, component state, lifecycle hooks, and expression evaluation.\n\nSlex source syntax is covered in the [protocol specification](/docs/reference/spec). Secure mode isolation is covered in the [security runtime contract](/docs/reference/security).\n\n## Entry points\n\n### `mount(input, container, options)`\n\nParses Slex source object or source string, merges state into the namespace store, renders the component tree into `container`, returns a root cleanup function.\n\n```ts\nfunction mount(\n input: SlexExpression | string,\n container: HTMLElement,\n options?: MountOptions\n): () => void;\n\ntype MountOptions = {\n theme?: \"auto\" | \"host-shadcn\" | \"uno\" | \"flowbite\";\n dir?: \"ltr\" | \"rtl\" | \"auto\";\n labels?: Partial<Record<string, string>>;\n api?: Record<string, unknown>;\n};\n```\n\nCalling `mount()` again on the same `container` clears the old root first, then appends a new root. The returned cleanup only unmounts the current root; it does not delete the namespace store.\n\n### `ingest(input)`\n\nIngests state-only Slex: updates `g` without rendering UI. Used by the Markdown runtime host for state-only fences. Returns `true` if parsing succeeded.\n\n```ts\nfunction ingest(input: SlexExpression | string): boolean;\n```\n\n### `disposeNamespace(namespace)`\n\nPermanently releases all roots, cleanups, store entries, and expression caches for a namespace. Call this when a document, message domain, or page section is permanently removed. Root cleanup is not equivalent to namespace disposal.\n\n```ts\nfunction disposeNamespace(namespace: string): void;\n```\n\n### `boot(options)`\n\nEnhances static pages by auto-discovering explicitly marked Slex blocks (`<pre><code class=\"language-slex\">`) and mounting live previews.\n\n```ts\nfunction boot(options?: BootOptions): void;\n\ntype BootOptions = {\n selector?: string;\n sourceControls?: boolean;\n theme?: ThemeMode;\n dir?: MountOptions[\"dir\"];\n labels?: MountOptions[\"labels\"];\n};\n```\n\nDefault selector covers: `language-slex`.\n\nHosts like React/Streamdown or Obsidian should typically use the Markdown runtime host directly rather than `boot()`.\n\n### `register(type, renderer, options)`\n\nRegisters a component type with a render function and state mode.\n\n```ts\nfunction register(\n type: string,\n renderer: ComponentRenderer,\n options?: ComponentRegistrationOptions\n): void;\n\ntype ComponentRenderer = (\n props: Record<string, unknown>,\n name: string,\n ctx: RenderContext\n) => HTMLElement | void;\n\ntype ComponentRegistrationOptions = {\n state?: \"value\" | \"checked\" | \"enabled\" | \"readable\" | \"none\";\n};\n```\n\n### `configureComponentScope(options)`\n\nConfigures a flush function for component scope -used by framework adapters to synchronize DOM after reactive updates.\n\n```ts\nfunction configureComponentScope(options: { flush?: () => void }): void;\n```\n\n## Namespace store\n\n`namespace` is the state domain. Multiple mounts with the same namespace share one store:\n\n- New `g` is deep-merged into the old `g` (functions overwrite, objects recursively merge, arrays replace, scalars overwrite).\n- New `layout` replaces the current layout (no deep merge for layout).\n- Component instance state is persisted within the namespace.\n- Expression caches are managed per namespace.\n\nThis allows a document, message domain, or tool panel to update its UI incrementally while preserving state.\n\n## Component instance state\n\nNamed components can expose instance state. Which prop is writable depends on the component's registered state mode:\n\n| Mode | Writable prop | Behavior |\n|------|---------------|----------|\n| `value` | `value` | Writable from expressions and events |\n| `checked` | `checked`, `value` | Both synced, writable |\n| `enabled` | `enabled` | Switch enabled state, writable |\n| `readable` | (none) | Readable from expressions, write emits a console warning |\n| `none` | (none) | No state exposed |\n\n```js\n{\n layout: {\n \"slider:threshold\": { value: 42 },\n \"text:preview\": { \"$content\": \"'Threshold: ' + threshold.value\" }\n }\n}\n```\n\nRepeatedly named components share namespace-level state. `$for` items with the same component name also share one state instance.\n\n## Lifecycle hooks\n\nThe runtime calls convention-based hooks on the `g` object:\n\n```\ng.onMount_<name>() -after component is appended to DOM\ng.onUnmount_<name>() -before component is removed from DOM\ng.onUpdate_<name>() -after $for item index or item reference changes\n```\n\nThese hooks fire for normal components, `$if` branches, and `$for` slots. Root cleanup and `disposeNamespace()` trigger `onUnmount`.\n\n## Component disposer\n\nFramework components, event listeners, subscriptions, and external resources should bind their cleanup to the component DOM element:\n\n```ts\nimport { register, attachComponentDisposer } from \"slexkit/runtime\";\n\nregister(\"custom\", (props, name, ctx) => {\n const el = ctx.document.createElement(\"div\");\n const stop = subscribeSomething();\n attachComponentDisposer(el, stop);\n return el;\n});\n```\n\nThe runtime calls the disposer when the element is unmounted. The official Svelte adapter uses this mechanism to destroy Svelte component instances.\n\n## Expression evaluation context\n\nExpressions in `$` read-pipes and statements in `on*` write-pipes can access these variables:\n\n| Variable | Type | Availability |\n|----------|------|--------------|\n| `g` | reactive state proxy | always |\n| `api` | host-injected capabilities | if `api` option passed to `mount()` |\n| `$event` | event data | `on*` handlers only |\n| `$item` | current array item | `$for` context only |\n| `$index` | current array index | `$for` context only |\n| `$key` | current item key | `$for` context only |\n| named component state | e.g. `threshold.value` | named components |\n\nExpression evaluation uses `new Function()` in trusted mode. Evaluation errors are caught and produce a console warning with namespace and path information; the last known value is used as a fallback.",
|
|
461
|
+
"hash": "559e05c2"
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"id": "reference/integration",
|
|
465
|
+
"group": "Reference",
|
|
466
|
+
"title": "Host Integration",
|
|
467
|
+
"summary": "Markdown renderers, Streamdown, Obsidian, custom hosts, and artifact lifecycle.",
|
|
468
|
+
"href": "/docs/reference/integration",
|
|
469
|
+
"rawHref": "/docs/reference/integration.md",
|
|
470
|
+
"sourcePath": "site/content/reference/integration/en-US.md",
|
|
471
|
+
"body": "---\ntitle: Host Integration\ncategory: Reference\nstatus: ready\norder: 40\nsummary: \"MarkdownRuntimeHost, trusted and secure host integrations, Streamdown, Obsidian, and custom adapters.\"\nslexkitRenderMode: component\n---\n\n# Host Integration\n\nHow to integrate SlexKit into Markdown renderers, chat hosts, document viewers, and custom platforms.\n\n## Core concepts\n\n### Artifact\n\nAn artifact is a group of Slex blocks belonging to the same document, message, or note. Hosts identify an artifact by an `artifactId` and group related blocks into one runtime domain.\n\nIn **trusted mode**, the runtime prefixes each block's namespace with the artifact ID to prevent cross-document state pollution. `disposeArtifact()` releases all namespace stores for that artifact.\n\nIn **secure mode**, all fences in one artifact are combined into a single sandbox iframe. The runtime maintains artifact slots, syncing rendered heights back to the original Markdown placeholder containers.\n\n### Block\n\nA block is a single Slex block: one renderable unit. It has:\n- A source (Slex expression object or source string).\n- A container element (where the rendered output goes).\n- An optional `artifactId` (for grouping into an artifact).\n\n### Cleanup\n\nEvery block mount returns a cleanup function. The host must call it when the block is removed. For artifact-level cleanup, call `disposeArtifact(artifactId)`. For global cleanup, call `disposeAll()`.\n\n## MarkdownRuntimeHost\n\nThe `SlexKitMarkdownRuntimeHost` is the recommended API for Markdown-based hosts. It handles mode selection, artifact management, and block lifecycle.\n\n```ts\nimport {\n createSlexKitMarkdownRuntimeHost,\n getSlexKitMarkdownRuntimeHost,\n installSlexKitMarkdownRuntimeHost\n} from \"slexkit\";\n```\n\n### Interface\n\n```ts\ntype SlexKitMarkdownRuntimeHost = {\n configure(options: Partial<SlexKitMarkdownRuntimeOptions>): void;\n getMode(): \"trusted\" | \"secure\";\n mountBlock(block: SlexKitMarkdownBlock): () => void;\n disposeBlock(container: HTMLElement): void;\n disposeArtifact(artifactId: string): void;\n disposeAll(): void;\n};\n\ntype SlexKitMarkdownBlock = {\n artifactId?: string;\n blockId?: string;\n source: SlexExpression | string;\n container: HTMLElement;\n stateOnly?: boolean;\n theme?: ThemeMode;\n dir?: MountOptions[\"dir\"];\n labels?: MountOptions[\"labels\"];\n};\n\ntype SlexKitMarkdownRuntimeOptions = {\n mode?: \"trusted\" | \"secure\";\n policy?: HostRuntimePolicy;\n hostAdapter?: HostRuntimeAdapter;\n secureFrame?: boolean | SecureFrameOptions;\n theme?: ThemeMode;\n dir?: MountOptions[\"dir\"];\n labels?: MountOptions[\"labels\"];\n};\n```\n\n### Global singleton\n\nThe module provides a global singleton for convenience:\n\n```ts\n// Install explicitly\nconst runtime = installSlexKitMarkdownRuntimeHost({\n mode: \"secure\",\n policy: { execution: { maxUnresponsiveMs: 30000 } },\n secureFrame: { runtimeUrl: \"/slexkit.runtime.js\" }\n});\n\n// Or use lazy global (auto-creates with defaults on first call)\nconst runtime = getSlexKitMarkdownRuntimeHost();\n```\n\nUse the singleton when the entire application shares one runtime configuration. Avoid it when different host contexts need different policies.\n\n## Trusted mode integration\n\nTrusted mode runs Slex source in the host page realm. Use for local documents, application-generated content, or reviewed Slex source.\n\n```ts\nconst runtime = createSlexKitMarkdownRuntimeHost({\n mode: \"trusted\",\n theme: \"host-shadcn\"\n});\n\n// Detect a slex fence at position <container>\nconst cleanup = runtime.mountBlock({\n artifactId: \"doc-1\",\n source: fenceSource,\n container: fenceContainer\n});\n\n// When the fence container is removed\nruntime.disposeBlock(fenceContainer);\n\n// When the document is closed\nruntime.disposeArtifact(\"doc-1\");\n\n// When the plugin or page unloads\nruntime.disposeAll();\n```\n\nIn trusted mode, the runtime automatically scopes namespaces by artifact ID (`<artifactId>::<namespace>`) to prevent different documents from polluting each other's state.\n\nState-only blocks (no `layout`, only `g` updates) are detected automatically and ingested via `ingest()`. Subsequent renderable blocks in the same artifact can read that state.\n\n## Secure mode integration\n\nSecure mode runs Slex source in a sandbox iframe. Use for untrusted or agent-generated Markdown.\n\n```ts\nconst runtime = createSlexKitMarkdownRuntimeHost({\n mode: \"secure\",\n policy: {\n execution: { maxUnresponsiveMs: 30000 }\n },\n secureFrame: {\n runtimeUrl: \"/slexkit.runtime.js\"\n },\n theme: \"host-shadcn\"\n});\n\nconst cleanup = runtime.mountBlock({\n artifactId: \"agent-msg-1\",\n source: agentGeneratedDsl,\n container: fenceContainer\n});\n```\n\nOmitted capability policies deny access by default. Add `network`, `timer`, `animation`, or `canvas` policy objects only when the host intentionally enables those capabilities.\n\n### Artifact slot bridge\n\nWhen multiple secure blocks belong to the same artifact, they share one sandbox iframe. The first block (in document order) becomes the iframe anchor. Other blocks act as slots -their containers receive position and height updates from the sandbox via the postMessage bridge.\n\n```html\n<!-- In Markdown, the first fence becomes the anchor -->\n<div id=\"fence-1\"><!-- anchor: iframe rendered here --></div>\n<div id=\"fence-2\"><!-- slot: height synced from iframe --></div>\n<div id=\"fence-3\"><!-- slot: height synced from iframe --></div>\n```\n\nThis allows state sharing across fences within one artifact while keeping all execution confined to one sandbox.\n\n### `runtimeUrl` requirements\n\nThe `runtimeUrl` must serve the SlexKit runtime as an ES module with:\n\n```\nAccess-Control-Allow-Origin: *\nContent-Type: text/javascript\n```\n\nThe build output includes `dist/runtime.js` for this purpose. The `slex copy-runtime` command copies that module to `public/slexkit.runtime.js` by default so existing secure-frame URLs can stay stable. Configure your CDN or static file server to serve it with the correct headers.\n\n## Streamdown / React integration\n\nThe `@slexkit/streamdown` package provides a React/Streamdown custom renderer:\n\n```tsx\nimport { Streamdown } from \"streamdown\";\nimport { slexkitRenderer } from \"@slexkit/streamdown\";\nimport \"@slexkit/theme-shadcn/style.css\";\nimport \"@slexkit/streamdown/style.css\";\n\nexport function Message({ markdown }: { markdown: string }) {\n return (\n <Streamdown plugins={{ renderers: [slexkitRenderer] }}>\n {markdown}\n </Streamdown>\n );\n}\n```\n\nThe renderer handles `slex` fences. It supports both trusted and secure runtime modes and can delegate to a shared Markdown runtime host instance.\n\n## Obsidian integration\n\nThe `@slexkit/obsidian` package registers the `slex` fenced code block processor in Obsidian:\n\n```ts\n// In the Obsidian plugin:\nregisterMarkdownCodeBlockProcessor(\"slex\", (source, el, ctx) => { ... });\n```\n\nThe adapter renders blocks in **reading mode only** and does not write back to the vault. Blocks within the same note share a trusted artifact runtime.\n\n**Important**: The Obsidian adapter uses trusted mode because it renders content from the user's login vault. It is not designed as a security boundary for untrusted or agent-generated Markdown.\n\n## Writing a custom host adapter\n\nTo integrate SlexKit into a custom Markdown renderer or chat host:\n\n### 1. Detect fence language\n\nOnly process fences tagged with `slex`. Never scan plain JavaScript, JSON, or untagged code blocks.\n\n### 2. Create a runtime host\n\n```ts\nimport { createSlexKitMarkdownRuntimeHost } from \"slexkit\";\n\nconst runtime = createSlexKitMarkdownRuntimeHost({\n mode: \"trusted\", // or \"secure\"\n theme: \"host-shadcn\"\n});\n```\n\n### 3. Mount blocks\n\nFor each detected fence, create a container element and mount:\n\n```ts\nfunction processFence(source: string, fenceIndex: number) {\n const container = document.createElement(\"div\");\n // Insert container at the fence position in the document\n\n const cleanup = runtime.mountBlock({\n artifactId: \"message-42\",\n source,\n container\n });\n\n return cleanup;\n}\n```\n\n### 4. Manage lifecycle\n\n```ts\n// When a single block is removed\nruntime.disposeBlock(container);\n\n// When the entire artifact (message/document) is removed\nruntime.disposeArtifact(\"message-42\");\n\n// When the plugin/page unloads\nruntime.disposeAll();\n```\n\n### 5. Handle secure mode\n\nIf using secure mode, serve `slexkit.runtime.js` as a public ES module with the correct CORS headers, and configure `secureFrame.runtimeUrl`.\n\n## Fallback rendering\n\nSlexKit-capable hosts should still include the raw fence content or a plain text fallback in the DOM for environments that don't support SlexKit. The runtime replaces the container children, so fallback text is only visible before mount or after disposal.",
|
|
472
|
+
"hash": "ac782b49"
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
"id": "reference/security",
|
|
476
|
+
"group": "Reference",
|
|
477
|
+
"title": "Security Runtime",
|
|
478
|
+
"summary": "Threat model, sandbox iframe, postMessage bridge, policy, and fail-closed behavior.",
|
|
479
|
+
"href": "/docs/reference/security",
|
|
480
|
+
"rawHref": "/docs/reference/security.md",
|
|
481
|
+
"sourcePath": "site/content/reference/security/en-US.md",
|
|
482
|
+
"body": "---\ntitle: Security Runtime Contract\ncategory: Reference\nstatus: ready\norder: 50\nsummary: \"Threat model, sandbox iframe deployment, host policy, postMessage bridge, and fail-closed behavior.\"\nslexkitRenderMode: component\n---\n\n# Security Runtime Contract\n\nThe secure runtime defines what untrusted Slex source can and cannot do, how the host authorizes capabilities, and how sandbox isolation works.\n\n## Threat model\n\n- The host page and host application are trusted.\n- Slex source may be untrusted.\n- Secure artifacts run inside a sandbox iframe.\n- The iframe uses an opaque origin by default (no `allow-same-origin`).\n- Slex source must not access the host DOM, cookies, `localStorage`, `IndexedDB`, or host global objects.\n\nSecure mode confines expression execution to an isolated environment and consolidates sensitive capabilities under the host `policy` and `api.*`.\n\n## Authorization source\n\nThe sole authorization source is the `HostRuntimePolicy` provided by the host. Slex source fields such as `capabilities`, `permissions`, `api`, or other top-level declarations cannot grant themselves authority.\n\nAll capabilities are accessed through `api.*`:\n\n```\napi.get(url, options)\napi.post(url, body, options)\napi.fetch(url, options)\n\napi.setTimeout(fn, ms)\napi.clearTimeout(id)\napi.setInterval(fn, ms)\napi.clearInterval(id)\n\napi.raf(fn)\napi.cancelRaf(id)\n\napi.createCanvas(width, height)\napi.getCanvasContext(canvas, contextId, options)\n\napi.onDispose(fn)\napi.now()\n\napi.isTimeoutError(error)\napi.isNetworkError(error)\napi.isPolicyError(error)\napi.errorMessage(error)\n```\n\nCapabilities not exposed through `api.*` are unsupported.\n\n## HostRuntimePolicy\n\n```ts\ntype HostRuntimePolicy = {\n network?: {\n enabled: boolean;\n methods: (\"GET\" | \"POST\")[];\n allowOrigins: string[];\n allowHeaders?: string[];\n allowContentTypes?: string[];\n credentials: \"omit\" | \"same-origin\" | \"include\";\n timeoutMs: number;\n maxBodyBytes: number;\n maxResponseBytes?: number;\n };\n timer?: {\n enabled: boolean;\n maxTimers: number;\n minIntervalMs: number;\n };\n animation?: {\n enabled: boolean;\n };\n canvas?: {\n enabled: boolean;\n maxCanvases?: number;\n maxPixels?: number;\n allowedContexts?: (\"2d\" | \"webgl\" | \"webgl2\" | \"bitmaprenderer\")[];\n };\n execution?: {\n heartbeatIntervalMs?: number;\n maxUnresponsiveMs?: number;\n };\n};\n```\n\n### Network policy\n\nNetwork is denied by default unless `policy.network.enabled` is `true`. The policy constrains:\n- HTTP method (only listed methods allowed)\n- Origin (supports `*`, exact match, `protocol://*` protocol wildcard, and `protocol://*.domain` subdomain wildcard)\n- Request headers (only listed headers pass; `Authorization`, `Cookie`, `Proxy-Authorization`, `Set-Cookie`, and Sec-Fetch headers are always blocked)\n- Credentials mode\n- Request body size\n- Request timeout\n- Response body size\n- Response content-type\n\n`hostAdapter.fetch` can replace the actual request implementation. `hostAdapter.onNetworkLog` is observational only -it must not alter runtime behavior.\n\n### Timer, animation, and canvas\n\n- **Timer**: denied by default. When enabled, subject to `maxTimers` (total concurrent) and `minIntervalMs` (minimum delay). All timers and intervals are cleaned up on dispose.\n- **Animation**: denied by default. Controlled via `animation.enabled`; `api.raf` is the only animation primitive.\n- **Canvas**: denied by default. When enabled, subject to `maxCanvases`, `maxPixels`, and `allowedContexts`.\n\n### Execution monitoring\n\n`execution.heartbeatIntervalMs` controls how often the sandbox sends a heartbeat to the host. `execution.maxUnresponsiveMs` defines the maximum silence before the sandbox is terminated as unresponsive.\n\n## HostRuntimeAdapter\n\nThe adapter allows the host to override or observe runtime behavior:\n\n```ts\ntype HostRuntimeAdapter = {\n fetch?: (request: HostFetchRequest) => Promise<NetworkResult>;\n onNetworkLog?: (event: RuntimeNetworkLogEvent) => void;\n onRuntimeError?: (event: RuntimeErrorEvent) => void;\n now?: () => number;\n setTimeout?: (fn: () => void, ms: number) => TimerId;\n clearTimeout?: (id: TimerId) => void;\n setInterval?: (fn: () => void, ms: number) => TimerId;\n clearInterval?: (id: TimerId) => void;\n requestAnimationFrame?: (fn: (time: number) => void) => RafId;\n cancelAnimationFrame?: (id: RafId) => void;\n};\n```\n\n`onNetworkLog` and `onRuntimeError` are audit hooks -they must not change runtime behavior. Errors thrown within them are silently caught.\n\n## Sandbox iframe deployment\n\nThe secure frame imports the main runtime module from a `runtimeUrl`:\n\n```ts\nmountSecureArtifact(script, container, {\n frame: {\n runtimeUrl: \"/slexkit.runtime.js\"\n }\n});\n```\n\nThis URL must serve as a public ES module and return:\n\n```\nAccess-Control-Allow-Origin: *\nContent-Type: text/javascript\n```\n\nThis is server or deployment layer configuration -it cannot be set from frontend JavaScript.\n\n### CSP\n\nThe sandbox iframe is served via `srcdoc` with a strict Content-Security-Policy:\n\n```\ndefault-src 'none'\nscript-src 'nonce-{random}' 'unsafe-eval' {runtimeOrigin}\nconnect-src 'none'\nimg-src data: blob:\nstyle-src 'unsafe-inline'\nfont-src data:\nform-action 'none'\nbase-uri 'none'\n```\n\nA random nonce is generated for each frame instance. `unsafe-eval` is required because Slex source expression evaluation uses `eval()` inside the sandbox.\n\n### Sandbox attribute\n\nThe iframe requires `allow-scripts`. `allow-same-origin` is **blocked by default** -it would weaken the opaque origin isolation. Only set `unsafeAllowSameOrigin: true` explicitly if the host accepts the risk:\n\n```ts\nframe: {\n unsafeAllowSameOrigin: true, // only with explicit host acceptance\n sandbox: \"allow-scripts allow-same-origin\"\n}\n```\n\nDo not add `allow-same-origin` to fix CORS or debugging issues.\n\n## postMessage bridge protocol\n\nThe host and sandbox communicate via `window.postMessage`. All messages are tagged with `channel: \"slexkit-secure\"`.\n\n### Host -Sandbox messages\n\n| Type | Purpose |\n|------|---------|\n| `mount` | Sends Slex source, policy, theme to render |\n| `dispose` | Tells sandbox to tear down |\n| `fetch-result` | Returns fetch response or error |\n| `slots` | Synchronizes artifact slot positions |\n\n### Sandbox -Host messages\n\n| Type | Purpose |\n|------|---------|\n| `ready` | Runner module loaded and listening |\n| `mounted` | Artifact render confirmed |\n| `disposed` | Sandbox teardown acknowledged |\n| `heartbeat` | Periodic liveness signal |\n| `error` | Mount or runtime error |\n| `fetch` | Proxied network request |\n| `slot-size` | Artifact slot height report |\n\nEvery host→sandbox message includes an `id` and `token`. The token is opaque, cryptographically random, and scoped to a single mount instance. Messages with mismatched tokens are rejected.\n\nMessages are verified: the sandbox checks `event.source === window.parent`; the host checks `event.source === iframe.contentWindow`.\n\n## Artifact slot bridge\n\nMultiple Markdown fences belonging to one artifact share a single sandbox iframe. The host sends slot rectangles to the sandbox, which renders each fence's output inside the corresponding slot container. The sandbox reports each slot's rendered height back via `slot-size` messages.\n\nA `ResizeObserver` on the host side and inside the sandbox keeps positions and heights synchronized. This allows visual continuity across fence boundaries while keeping all execution confined to one isolation context.\n\n## Heartbeat watchdog\n\nWhen `execution.maxUnresponsiveMs` is set, the host monitors the sandbox heartbeat interval. If no heartbeat arrives within the threshold, the iframe is terminated, a diagnostic alert (`role=\"alert\"`) is rendered, and a `console.error` is emitted.\n\n## Fail-closed behavior\n\nIf the iframe cannot load the runtime, does not send a ready/mounted message, or the heartbeat times out, SlexKit:\n\n1. Removes the unresponsive iframe.\n2. Renders a `role=\"alert\"` diagnostic element with a description of the failure.\n3. Emits the same information via `console.error`.\n\nLoad timeout is configurable via `frame.loadTimeoutMs` (default: 8000ms).\n\n## Escape hatches\n\n### `unsafeInlineExecution`\n\nAllows a secure artifact to execute inline in the host page with an injected secure runtime API. **Intended for testing or host-trusted content only.** Not recommended for untrusted paths.\n\n```ts\nmountSecureArtifact(script, container, {\n policy,\n hostAdapter,\n unsafeInlineExecution: true\n});\n```\n\n### `unsafeAllowSameOrigin`\n\nAllows `allow-same-origin` in the sandbox attribute. **Reduces isolation strength** -only use when the host explicitly accepts the risk.\n\n```ts\nframe: {\n sandbox: \"allow-scripts allow-same-origin\",\n unsafeAllowSameOrigin: true\n}\n```\n\n## Sandbox hardening\n\nWhen the sandbox runner starts, it hardens the global scope:\n\n**Blocked network globals** -`fetch`, `XMLHttpRequest`, `WebSocket`, `EventSource`, `Worker`, `SharedWorker`, and `navigator.sendBeacon` are replaced with functions that throw, ensuring all network traffic must go through the bridge.\n\n**Blocked scheduling globals** -`setTimeout`, `setInterval`, `requestAnimationFrame` are replaced with functions that throw, directing code to `api.setTimeout()`, `api.setInterval()`, and `api.raf()`.\n\n**Canvas prototype wrapping** -`HTMLCanvasElement.prototype.getContext` is wrapped to enforce canvas policy on context creation. `OffscreenCanvas` is replaced with a subclass that validates dimensions on construction.\n\n## Maintenance principles\n\n- New capabilities must define a policy field first, then an `api.*` method, then the bridge.\n- Slex source declarations are never an authorization source.\n- Default to opaque origin.\n- Always fail closed.\n- Log and error hooks are observational -they must not alter runtime behavior.",
|
|
483
|
+
"hash": "4cfe36f1"
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
"id": "reference/packages",
|
|
487
|
+
"group": "Reference",
|
|
488
|
+
"title": "Package Boundaries",
|
|
489
|
+
"summary": "Package relationships, installation matrix, and packaging strategy.",
|
|
490
|
+
"href": "/docs/reference/packages",
|
|
491
|
+
"rawHref": "/docs/reference/packages.md",
|
|
492
|
+
"sourcePath": "site/content/reference/packages/en-US.md",
|
|
493
|
+
"body": "---\ntitle: Package Boundaries\ncategory: Reference\nstatus: ready\norder: 60\nsummary: \"Package relationships, installation matrix, publish contents, and release quality gates.\"\nslexkitRenderMode: component\n---\n\n# Package Boundaries\n\nSlexKit v0/beta npm packages, their relationships, and installation.\n\n## Package relationship\n\n```\nslexkit (root - real code)\n ├── runtime entry\n ├── Svelte component registrations\n ├── ToolHost\n ├── default styles\n └── secure iframe runner\n\n @slexkit/runtime (thin wrapper) ─── re-exports slexkit/runtime\n @slexkit/components-svelte (thin wrapper) ─── re-exports slexkit/components-svelte\n @slexkit/theme-shadcn ─── CSS only\n @slexkit/streamdown ─── React/Streamdown renderer\n @slexkit/obsidian ─── Obsidian plugin\n @slexkit/mcp ─── read-only MCP server for AI agents\n```\n\n`@slexkit/runtime` and `@slexkit/components-svelte` are thin wrappers that re-export from the root `slexkit` package. They are not standalone physical packages; installing them still requires installing `slexkit`. `@slexkit/theme-shadcn` is CSS-only and contains no runtime implementation.\n\n## slexkit (root)\n\nThe actual implementation package. Contains the runtime engine, official Svelte components, ToolHost, and styles.\n\n```sh\nnpm install slexkit\n```\n\n```js\nimport { mount, disposeNamespace, boot } from \"slexkit\";\nimport \"slexkit/style.css\"; // default styles (includes all component CSS)\nimport \"slexkit/dist/style.css\"; // same distributed CSS bundle via dist alias\n```\n\nVersion helpers are exported from both the root and runtime entries:\n\n```js\nimport { SLEXKIT_VERSION, SLEX_PROTOCOL_VERSION, getSlexKitInfo } from \"slexkit\";\n```\n\n## @slexkit/runtime\n\nComponent-free runtime entry point. Does not auto-register any official Svelte components.\n\n```sh\nnpm install slexkit @slexkit/runtime\n```\n\n```js\nimport { mount, register, createSecureRuntime } from \"@slexkit/runtime\";\n```\n\nUse this when you want to register your own component set instead of the bundled Svelte components.\n\n## @slexkit/components-svelte\n\nSide-effect import that registers all official Svelte components into the runtime registry.\n\n```sh\nnpm install slexkit @slexkit/runtime @slexkit/components-svelte\n```\n\n```js\nimport { mount } from \"@slexkit/runtime\";\nimport \"@slexkit/components-svelte\";\n```\n\nPublic component specs: action (2), component capability (1), content (6), data (1), disclosure (2), display (2), feedback (2), input (6), layout (4), navigation (1), tooling (1).\n\n## @slexkit/theme-shadcn\n\nCSS theme bundle (shadcn/ui compatible).\n\n```sh\nnpm install @slexkit/theme-shadcn\n```\n\n```js\nimport \"@slexkit/theme-shadcn/style.css\";\n```\n\n## @slexkit/streamdown\n\nReact/Streamdown custom renderer for Markdown-hosted SlexKit fences.\n\n```sh\nnpm install slexkit @slexkit/theme-shadcn @slexkit/streamdown streamdown react react-dom\n```\n\n```tsx\nimport { Streamdown } from \"streamdown\";\nimport { slexkitRenderer } from \"@slexkit/streamdown\";\nimport \"@slexkit/theme-shadcn/style.css\";\nimport \"@slexkit/streamdown/style.css\";\n\nexport function Message({ markdown }: { markdown: string }) {\n return (\n <Streamdown plugins={{ renderers: [slexkitRenderer] }}>\n {markdown}\n </Streamdown>\n );\n}\n```\n\nProcesses `slex` fences. Supports both trusted and secure runtime modes.\n\n## @slexkit/obsidian\n\nObsidian plugin adapter. Registers SlexKit fenced code block processors and renders local vault content in reading mode.\n\n```sh\nnpm install slexkit @slexkit/obsidian\n```\n\nThe adapter uses trusted runtime mode -it renders content from the user's local vault and is not designed as a sandbox for third-party or agent-generated Markdown. Obsidian secure sandbox support is not part of the v0 adapter.\n\n## @slexkit/mcp\n\nRead-only MCP server for AI agents. It serves generated LLM docs, component metadata, examples, runtime docs, ToolHost docs, and Slex source validation.\n\n```sh\nnpx -y @slexkit/mcp\n```\n\nThe server does not modify project files. Use it when an agent needs current SlexKit component or runtime context.\n\n## Installation matrix\n\n| Use case | Install command |\n|----------|----------------|\n| Quick start, everything included | `npm install slexkit` |\n| Component-free, custom components | `npm install slexkit @slexkit/runtime` |\n| With Svelte components | `npm install slexkit @slexkit/runtime @slexkit/components-svelte` |\n| Add shadcn theme | `npm install @slexkit/theme-shadcn` |\n| React/Streamdown host | `npm install slexkit @slexkit/theme-shadcn @slexkit/streamdown streamdown react react-dom` |\n| Obsidian plugin | `npm install slexkit @slexkit/obsidian` |\n| AI agent MCP server | `npx -y @slexkit/mcp` |\n\n## v0 packaging strategy\n\nThe current approach keeps the root `slexkit` package as the real code carrier. Scoped `@slexkit/*` wrappers exist to define future package boundaries. If physical package splitting happens in the future, it will involve splitting source code, build output, and publishing workflows.\n\n## Release quality gate\n\nAll scoped packages are release-checked together:\n\n```sh\nbun run build\nbun run test\nbun run smoke:release\n```\n\nThe release smoke packs and installs every scoped package, verifies public entry points, verifies CSS subpath exports, loads the Obsidian CJS bundle with an Obsidian module mock, and starts the MCP stdio binary to check `initialize`, `tools/list`, and `slexkitValidate`.",
|
|
494
|
+
"hash": "79d87cbd"
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"id": "reference/toolhost",
|
|
498
|
+
"group": "Reference",
|
|
499
|
+
"title": "ToolHost",
|
|
500
|
+
"summary": "Tool call rendering, built-in templates, custom templates, and submit boundaries.",
|
|
501
|
+
"href": "/docs/reference/toolhost",
|
|
502
|
+
"rawHref": "/docs/reference/toolhost.md",
|
|
503
|
+
"sourcePath": "site/content/reference/toolhost/en-US.md",
|
|
504
|
+
"body": "---\ntitle: ToolHost\ncategory: Reference\nstatus: ready\norder: 70\nsummary: \"Structured user-input UI for confirmations, choices, forms, templates, and submit boundaries.\"\nslexkitRenderMode: component\n---\n\n# ToolHost\n\nToolHost bridges AI tool calls to interactive UI. Instead of the AI executing tools server-side, ToolHost renders a structured input form in the browser and returns the user's response as a `ToolResult`.\n\n## Concepts\n\nWhen an AI model emits a tool call (e.g., `confirm-action`, `fill-form`), ToolHost compiles it into a standard `SlexExpression` and mounts it using the core runtime. The mounted UI has a **submit boundary** (`submit:actions` component) that settles a Promise with the user's input.\n\nToolHost is **separate from display-oriented `slex` fences**. Display components render information; ToolHost components collect structured user input and return it programmatically.\n\n## Public API\n\n### `renderToolCall(call, container) → ToolRenderHandle`\n\nCompiles a tool call into a SlexExpression, mounts it, and returns a handle.\n\n```ts\nfunction renderToolCall(call: ToolCall, container: HTMLElement): ToolRenderHandle;\n```\n\n```ts\ntype ToolRenderHandle = {\n promise: Promise<ToolResult>; // Resolves when user submits or ignores\n dispose: () => void; // Clean up the rendered UI\n};\n\ntype ToolResult =\n | { toolCallId?: string; toolName: string; status: \"submitted\"; value: Record<string, unknown> }\n | { toolCallId?: string; toolName: string; status: \"ignored\"; value: null };\n```\n\n**Usage:**\n\n```js\nimport { renderToolCall } from \"slexkit\";\n\nconst handle = renderToolCall(\n {\n id: \"call_001\",\n name: \"confirm-action\",\n arguments: {\n title: \"Delete file?\",\n description: \"This action cannot be undone.\",\n confirmLabel: \"Delete\",\n requireReason: true,\n },\n },\n document.getElementById(\"tool-container\"),\n);\n\nhandle.promise.then((result) => {\n console.log(result.status); // \"submitted\" or \"ignored\"\n console.log(result.value); // { confirmed: true, reason: \"Obsolete file\" }\n handle.dispose();\n});\n```\n\n### `registerToolTemplate(name, compiler)`\n\nRegister a custom tool template. The compiler function receives the tool arguments and returns a `SlexExpression`.\n\n```ts\nfunction registerToolTemplate(name: string, compiler: ToolTemplateCompiler): void;\n\ntype ToolTemplateCompiler<TArgs = Record<string, unknown>> = (\n args: TArgs,\n runtime: ToolRuntime,\n call: ToolCall,\n) => SlexExpression;\n\ntype ToolRuntime = {\n submit: (value: Record<string, unknown>) => void;\n ignore: () => void;\n};\n```\n\n## Built-in templates\n\n### `confirm-action`\n\nYes/no confirmation dialog. Supports an optional reason field.\n\n**Arguments (`ConfirmActionArguments`):**\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `title` | `string` | `\"Confirm action\"` | Dialog title |\n| `description` | `string` | — | Optional explanation text |\n| `confirmLabel` | `string` | `\"Confirm\"` | Submit button label |\n| `ignoreLabel` | `string` | `\"Ignore\"` | Cancel button label |\n| `requireReason` | `boolean` | `false` | Show a reason text input |\n| `reasonLabel` | `string` | `\"Reason\"` | Label for the reason input |\n| `reasonPlaceholder` | `string` | `\"Add a reason\"` | Placeholder for the reason input |\n\n**Result value:**\n\n| Key | Type | Description |\n|-----|------|-------------|\n| `confirmed` | `boolean` | Always `true` when submitted |\n| `reason` | `string` | User's reason text (only if `requireReason: true`) |\n\n**Example:**\n\n```js\nrenderToolCall({\n name: \"confirm-action\",\n arguments: {\n title: \"Delete project?\",\n description: \"This will permanently delete all files.\",\n confirmLabel: \"Delete\",\n requireReason: true,\n },\n}, container);\n```\n\n### `choose-options` / `option-list`\n\nSingle or multi-select option list. `option-list` is an alias for `choose-options` — behavior is identical.\n\n**Arguments (`ChooseOptionsArguments` / `OptionListArguments`):**\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `title` | `string` | `\"Choose options\"` | Dialog title |\n| `description` | `string` | — | Optional explanation text |\n| `options` / `items` | `OptionListItem[]` | `[]` | List of selectable items |\n| `multiple` | `boolean` | `true` | Allow multiple selection |\n| `selected` | `string[]` | auto | Pre-selected item IDs |\n| `minSelected` | `number` | `0` | Minimum required selections |\n| `maxSelected` | `number` | `Infinity` | Maximum allowed selections |\n| `submitLabel` | `string` | `\"Submit\"` | Submit button label |\n| `ignoreLabel` | `string` | `\"Ignore\"` | Cancel button label |\n\n**OptionListItem:**\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `label` | `string` | Display text (required) |\n| `id` | `string` | Unique identifier (defaults to `value` or index) |\n| `value` | `string` | Submitted value (defaults to `id`) |\n| `description` | `string` | Secondary text shown after label |\n| `selected` | `boolean` | Pre-selected state |\n| `disabled` | `boolean` | Disabled state |\n\n**Rendering:**\n- When `multiple: true` (default): renders **checkboxes**\n- When `multiple: false`: renders a **radio group**\n\n**Result value:**\n\n| Key | Type | Description |\n|-----|------|-------------|\n| `selected` | `string[]` | IDs of selected items |\n\n**Example:**\n\n```js\nrenderToolCall({\n name: \"choose-options\",\n arguments: {\n title: \"Select dependencies\",\n options: [\n { id: \"react\", label: \"React\", description: \"UI library\" },\n { id: \"vue\", label: \"Vue\", description: \"Progressive framework\" },\n { id: \"svelte\", label: \"Svelte\", description: \"Compiled framework\", selected: true },\n ],\n multiple: true,\n minSelected: 1,\n maxSelected: 2,\n },\n}, container);\n```\n\n### `fill-form`\n\nMulti-field form with various field types.\n\n**Arguments (`FillFormArguments`):**\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `title` | `string` | `\"Fill form\"` | Form title |\n| `description` | `string` | — | Optional explanation text |\n| `fields` | `FormField[]` | `[]` | Form field definitions |\n| `values` | `Record<string, unknown>` | — | Initial field values |\n| `submitLabel` | `string` | `\"Submit\"` | Submit button label |\n| `ignoreLabel` | `string` | `\"Ignore\"` | Cancel button label |\n\n**FormField:**\n\n| Field | Type | Default | Description |\n|-------|------|---------|-------------|\n| `name` | `string` | (required) | Field name (used as key in result value) |\n| `type` | `FormFieldType` | `\"text\"` | Field type |\n| `label` | `string` | `name` | Display label |\n| `description` | `string` | — | Help text below the field |\n| `placeholder` | `string` | — | Input placeholder |\n| `required` | `boolean` | `false` | Require non-empty value to submit |\n| `disabled` | `boolean` | `false` | Disable the field |\n| `value` | `unknown` | — | Initial value |\n| `options` | `Array<{label, value}>` | — | Options for `select` type |\n\n**FormFieldType:**\n\n| Type | Renders | Description |\n|------|---------|-------------|\n| `text` | `<input>` | Free-form text |\n| `number` | `<input type=\"number\">` | Numeric input, value is `number \\| null` |\n| `engineering` | `<input>` with SI prefix parsing | Accepts values like `\"10kΩ\"`, `\"100nF\"`, `\"1.5MegHz\"`. Parsed with `parseEngineeringNumber()`. State includes `raw`, `number`, `valid`, `prefix`, `unit`, `normalized` |\n| `select` | `<select>` | Dropdown from `options` array |\n| `checkbox` | Checkbox | Boolean toggle |\n| `switch` | Switch toggle | Boolean toggle (switch style) |\n\n**Result value:**\n\nAn object with a key for each field name, containing the submitted value. For `engineering` fields, the raw input string is submitted. For `checkbox`/`switch` fields, a boolean is submitted. For `number` fields, a number or `null` is submitted.\n\n**Example:**\n\n```js\nrenderToolCall({\n name: \"fill-form\",\n arguments: {\n title: \"New project\",\n fields: [\n { name: \"name\", type: \"text\", label: \"Project name\", required: true },\n { name: \"framework\", type: \"select\", label: \"Framework\", options: [\n { label: \"React\", value: \"react\" },\n { label: \"Svelte\", value: \"svelte\" },\n ]},\n { name: \"resistance\", type: \"engineering\", label: \"Target resistance\", placeholder: \"e.g. 10kΩ\" },\n { name: \"typescript\", type: \"checkbox\", label: \"Use TypeScript\", value: true },\n ],\n },\n}, container);\n```\n\n## Writing a custom template\n\nImplement the `ToolTemplateCompiler` function and register it:\n\n```js\nimport { registerToolTemplate, renderToolCall } from \"slexkit\";\n\nregisterToolTemplate(\"greet-user\", (args, runtime, call) => ({\n namespace: `tool_greet_${Date.now()}`,\n g: {\n __slexkitTool: runtime,\n name: args.name || \"World\",\n },\n layout: {\n \"card:tool\": {\n title: \"Greeting\",\n \"text:message\": { \"$content\": \"'Hello, ' + g.name + '!'\" },\n \"submit:actions\": {\n returnKeys: [\"name\"],\n submitLabel: args.submitLabel || \"OK\",\n ignoreLabel: args.ignoreLabel || \"Cancel\",\n },\n },\n },\n}));\n\nrenderToolCall(\n { name: \"greet-user\", arguments: { name: \"Alice\" } },\n container,\n);\n```\n\n### Key patterns\n\n1. **`__slexkitTool`** — Set `g.__slexkitTool = runtime` to give expressions access to `submit()` and `ignore()`\n2. **`submit:actions`** — Always include a `submit:actions` component as the completion boundary. Set `returnKeys` to the property names that should be included in the result value\n3. **`canSubmit`** — Add a `g.canSubmit()` method to control the submit button's disabled state\n4. **Unique namespace** — Use a timestamp-based namespace to avoid collisions with other tool calls\n5. **Validation** — Implement validation logic in `g` methods and wire `$disabled` on the submit button",
|
|
505
|
+
"hash": "f62ba8aa"
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
"id": "reference/icons",
|
|
509
|
+
"group": "Reference",
|
|
510
|
+
"title": "Icon System",
|
|
511
|
+
"summary": "Phosphor icons, custom icon registration, Iconify fallback, and API reference.",
|
|
512
|
+
"href": "/docs/reference/icons",
|
|
513
|
+
"rawHref": "/docs/reference/icons.md",
|
|
514
|
+
"sourcePath": "site/content/reference/icons/en-US.md",
|
|
515
|
+
"body": "---\ntitle: Icon System\ncategory: Reference\nstatus: ready\norder: 90\nsummary: \"Phosphor icons, custom icon registration, Iconify fallback, and component icon usage.\"\nslexkitRenderMode: component\n---\n\n# Icon System\n\nSlexKit includes a built-in icon system powered by Phosphor Icons with a custom registration API for extended icon sets.\n\n## Resolution chain\n\nWhen a component requests an icon by name, the system resolves it through this chain:\n\n1. **Registered icons** — custom icons registered via `registerIcon()` or `registerIcons()`\n2. **Phosphor Icons** — 24 bundled Phosphor icons available synchronously\n3. **Iconify fallback** — `loadIcon()` fetches from the Iconify API if neither source has the icon\n\n## Public API\n\n### Registration\n\n#### `registerIcon(name, svg, options?)`\n\nRegister a single SVG icon globally. All components with an `icon` field can reference it by name.\n\n```ts\nfunction registerIcon(name: string, svg: string, options?: RegisterIconOptions): void;\n```\n\n```ts\ntype RegisterIconOptions = {\n aliases?: string[]; // Alternative names for the same icon\n weight?: IconWeight; // \"regular\" | \"duotone\" — defaults to \"regular\"\n};\n```\n\n**Example:**\n\n```js\nimport { registerIcon } from \"slexkit\";\n\nregisterIcon(\n \"my-custom-icon\",\n `<svg viewBox=\"0 0 24 24\" fill=\"none\" ...>...</svg>`,\n { aliases: [\"custom\", \"my-icon\"] }\n);\n```\n\n#### `registerIcons(icons, options?)`\n\nRegister multiple icons at once.\n\n```ts\nfunction registerIcons(icons: Record<string, string>, options?: RegisterIconOptions): void;\n```\n\n**Example:**\n\n```js\nimport { registerIcons } from \"slexkit\";\n\nregisterIcons(\n {\n \"cpu\": `<svg>...</svg>`,\n \"memory\": `<svg>...</svg>`,\n \"database\": `<svg>...</svg>`,\n },\n { weight: \"regular\" }\n);\n```\n\n#### `clearRegisteredIcons()`\n\nRemove all custom registered icons from the global registry.\n\n```ts\nfunction clearRegisteredIcons(): void;\n```\n\n### Retrieval\n\n#### `getIcon(name, state?)`\n\nResolve an icon synchronously. Returns the SVG string or an empty string if not found.\n\n```ts\nfunction getIcon(name: string, state?: IconWeight | IconState): string;\n```\n\nLooks up registered icons first, then falls back to bundled Phosphor icons. Does **not** fetch from Iconify.\n\n#### `getRegisteredIcon(name, state?)`\n\nLook up only from the registered icon registry. Returns the SVG string or an empty string. Does not check Phosphor or Iconify.\n\n```ts\nfunction getRegisteredIcon(name: string, state?: IconWeight | IconState): string;\n```\n\nUseful for checking if a custom icon exists without triggering Phosphor or Iconify lookups.\n\n#### `loadIcon(name, state?)`\n\nResolve an icon asynchronously. Returns a Promise that resolves to the SVG string.\n\n```ts\nfunction loadIcon(name: string, state?: IconWeight | IconState): Promise<string>;\n```\n\nSearches registered icons → Phosphor → fetches from Iconify API as a last resort. Use this when the icon set is not known at build time.\n\n### Name and weight utilities\n\n#### `normalizeIconName(name)`\n\nNormalize an icon name to standard kebab-case format. Handles set prefixes.\n\n```ts\nfunction normalizeIconName(name: string): string;\n```\n\n**Examples:**\n- `\"ArrowCircleUp\"` → `\"arrow-circle-up\"`\n- `\"ph:arrow-circle-up\"` → `\"ph:arrow-circle-up\"`\n- `\"my_set:MyIcon\"` → `\"my-set:my-icon\"`\n- `\"phosphor:ArrowCircleUp\"` → `\"ph:arrow-circle-up\"`\n\nSet prefixes are normalized: `\"phosphor\"` / `\"phosphor-icons\"` become `\"ph\"`.\n\n#### `resolveIconWeight(state?)`\n\nResolve the icon weight from component state. Auto-selects `\"duotone\"` for `selected`/`active`/`pressed`/`current` states.\n\n```ts\nfunction resolveIconWeight(state?: IconWeight | IconState): IconWeight;\n```\n\n```ts\ntype IconWeight = \"regular\" | \"duotone\";\ntype IconState = {\n selected?: boolean;\n active?: boolean;\n pressed?: boolean;\n current?: boolean;\n};\n```\n\n#### `resolveIconifyIcon(name, state?)`\n\nResolve to an Iconify-compatible `{ prefix, name }` pair.\n\n```ts\nfunction resolveIconifyIcon(name: string, state?: IconWeight | IconState): { prefix: string; name: string };\n```\n\n#### `iconifySvgUrl(name, state?)`\n\nBuild the full Iconify API SVG URL for fetching a remote icon.\n\n```ts\nfunction iconifySvgUrl(name: string, state?: IconWeight | IconState): string;\n```\n\n#### `iconCacheKey(name, state?)`\n\nReturn the lookup key used internally for icon caching.\n\n```ts\nfunction iconCacheKey(name: string, state?: IconWeight | IconState): string;\n```\n\n## Built-in Phosphor icons\n\nSlexKit bundles 23 Phosphor Icons in both regular and duotone weights (46 total SVG files):\n\n| Icon | Name |\n|------|------|\n| CaretDown | `caret-down` |\n| Check | `check` |\n| CircleHalf | `circle-half` |\n| List | `list` |\n| Moon | `moon` |\n| Sun | `sun` |\n| Code | `code` |\n| BookOpenText | `book-open-text` |\n| CursorClick | `cursor-click` |\n| GearSix | `gear-six` |\n| Nut | `nut` |\n| Screwdriver | `screwdriver` |\n| Sparkle | `sparkle` |\n| TerminalWindow | `terminal-window` |\n| Wrench | `wrench` |\n| Copy | `copy` |\n| Eye | `eye` |\n| ArrowSquareOut | `arrow-square-out` |\n| SplitHorizontal | `split-horizontal` |\n| SquareHalf | `square-half` |\n| SquareSplitHorizontal | `square-split-horizontal` |\n| File | `file` |\n| X | `x` |\n\n## Icon naming convention\n\nIcons are referenced in Slex expressions using kebab-case names:\n\n```js\n\"button:add\": { text: \"Add\", icon: \"plus\" }\n\"link:docs\": { text: \"Docs\", icon: \"book-open-text\" }\n```\n\nTo use a custom icon set prefix:\n\n```js\n\"card:info\": { title: \"Info\", icon: \"ph:info\" }\n\"callout:tip\": { title: \"Tip\", icon: \"my-set:custom-bulb\" }\n```\n\nThe name resolution chain handles: `custom-icon` → registered first → bundled Phosphor → Iconify fetch (async only).\n\n## Iconify fallback\n\nWhen `loadIcon()` cannot find an icon in the registered or Phosphor sets, it fetches from the Iconify API:\n\n```\nhttps://api.iconify.design/<prefix>/<name>.svg\n```\n\nThis enables access to thousands of icons beyond the built-in set. Fetched SVGs are sanitized before use.\n\n## Usage in components\n\nComponents that accept an `icon` prop:\n\n| Component | Icon location |\n|-----------|--------------|\n| Button | Before text |\n| Badge | Before text |\n| Card | Title area |\n| Callout | Title area |\n| Section | Eyebrow/title area |\n| Link | Before text |\n| Divider | Before/around label |\n| Tabs | Tab header (icon or iconOnly mode) |\n| Toast | Title area |\n| Stat | Next to value |\n| Accordion | Trigger area |\n| Collapsible | Trigger area |\n| Submit | Button icon area |\n\nIcons automatically use duotone weight when the component or icon is in a selected/active/pressed state.",
|
|
516
|
+
"hash": "3d32cbbf"
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
"id": "reference/rationale",
|
|
520
|
+
"group": "Reference",
|
|
521
|
+
"title": "Design Rationale",
|
|
522
|
+
"summary": "Why SlexKit uses object literals, expressions, explicit fences, and secure/trusted modes.",
|
|
523
|
+
"href": "/docs/reference/rationale",
|
|
524
|
+
"rawHref": "/docs/reference/rationale.md",
|
|
525
|
+
"sourcePath": "site/content/reference/rationale/en-US.md",
|
|
526
|
+
"body": "---\ntitle: Design Rationale\ncategory: Reference\nstatus: ready\norder: 80\nsummary: \"Why SlexKit uses object literals, expressions, explicit fences, and a trusted/secure runtime split.\"\nslexkitRenderMode: component\n---\n\n# Design Rationale\n\nWhy JavaScript object literals? Why expressions? Why explicit fences? Why a trusted and secure dual runtime?\n\n## Problem space\n\nSlexKit targets small interactive UI inside chat messages, documents, agent output panels, and tool dashboards. It does not attempt to provide routing, data layers, build systems, or a full application framework.\n\nAn input format for AI-generated UI must be:\n- Short enough to stream token-by-token.\n- Embeddable in Markdown.\n- Runnable without a build step.\n- Host-agnostic (works in React, Svelte, Obsidian, vanilla HTML).\n\n## Why JavaScript object literals\n\nA Slex source is a single object literal:\n\n```js\n{\n namespace: \"demo\",\n g: { count: 0 },\n layout: {\n \"button:add\": { text: \"Add\", onclick: \"g.count++\" },\n \"text:value\": { \"$content\": \"'Count: ' + g.count\" }\n }\n}\n```\n\nA model can emit this in one shot. No project structure, no module imports, no build config, no framework boilerplate. The same content works inside a Markdown fence, a Streamdown renderer, an Obsidian adapter, or a custom runtime host.\n\n## Why `g` and `layout` are separate\n\n`g` holds state and logic. `layout` holds the component tree. Expressions read from `g`, component states, and `$for` context. Event handlers write back to `g`.\n\nThis separation makes model output easier to audit: state and algorithms are centralized in one object; UI structure is centralized in a tree. It also lets the host manage state lifecycle by namespace -same-namespace mounts share and merge state.\n\n## Why expressions (not pure JSON)\n\nSlexKit v0 is not a pure JSON protocol. `$` read-pipes and `on*` write-pipes allow JavaScript expressions and statements:\n\n```js\n\"$content\": \"'Count: ' + g.count\"\nonclick: \"g.count++\"\n```\n\nThis makes simple interactions shorter and more natural for AI generation. A pure-JSON format would require a separate expression language or declarative wiring syntax that adds complexity to both the emitter and the runtime.\n\nThe cost is an explicit trust boundary. Trusted content can execute in the host realm with low integration overhead. Untrusted content must go through the secure runtime (sandbox iframe, opaque origin, policy-gated capabilities).\n\nSlexKit's security choice is not about disabling expressions -it is about requiring the host to choose which trust boundary expressions run in.\n\n## Why only explicit fences\n\nSlexKit hosts must only process explicitly-marked fences (`slex`). Plain JavaScript, JSON, or untagged code blocks could be examples, logs, or user content -they must not be automatically executed or rendered.\n\nA generation should include a plain Markdown fallback so the output degrades gracefully:\n\n~~~~md\n```slex\n{ namespace: \"status\", ... }\n```\n\n**Status:** 3/4 complete\n~~~~\n\nOn SlexKit-capable hosts, the fence renders as interactive UI. On plain Markdown hosts, the fallback text still reads correctly.\n\n## Display UI vs ToolHost\n\nMost AI output is display-oriented -status cards, progress indicators, metrics, dashboards. These go through `slex` fences or `mount().`\n\nToolHost exists only for UI that must return structured user input to the host: confirmations, selections, forms. It compiles templates to standard Slex source, but the `submit` component serves as an explicit completion boundary.\n\nThis boundary prevents every display UI from being inadvertently wrapped as a function call.\n\n## Trusted + secure dual runtime\n\n### Trusted runtime\n\nFor application-generated content, repository-maintained Slex source, or already-reviewed snippets. Lowest integration cost -Slex source executes directly in the host page.\n\n### Secure runtime\n\nFor untrusted or agent-generated Slex source. Uses a sandbox iframe with opaque origin, CSP, and locked-down globals. Sensitive capabilities (network, timers, canvas) are gated behind a host policy.\n\nThe host chooses the trust boundary for each mount. The same Slex source syntax works in both modes.\n\n## Why a custom reactivity system\n\nSlexKit ships a minimal reactive engine (~280 lines) rather than depending on a framework:\n\n- **Zero framework dependency for the runtime core** -the `@slexkit/runtime` entry has no external dependencies.\n- **Deep tracking** -arbitrary `g` shapes require Proxy-based property access tracking that maps well to the tree-shaped Slex source model.\n- **Sufficient scope** -signal, effect, batch, memo, root/scope are the only primitives needed for this scale of UI.\n\nThe component layer (Svelte) adds `svelte` as a dependency only when using `@slexkit/components-svelte`.\n\n## How it differs from alternatives\n\n### vs A2UI\n\nA2UI is a cross-platform declarative message protocol with a component catalog approach. SlexKit v0 is browser-focused, Markdown-friendly, and uses executable JavaScript expressions for interactivity rather than declarative wiring. SlexKit does not claim to be a cross-platform UI standard.\n\n### vs application frameworks\n\nSlexKit is not a React/Vue/Svelte alternative. It renders small interactive fragments, not full applications. No router, no data fetching layer, no SSR.\n\n### vs pure JSON UI protocols\n\nSlexKit trades JSON purity for expressive short-form interactivity. The cost is the explicit trust boundary, which is addressed by the sandbox runtime rather than by restricting the expression language.",
|
|
527
|
+
"hash": "808b34ec"
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
"id": "releases/changelog",
|
|
531
|
+
"group": "Releases",
|
|
532
|
+
"title": "Changelog",
|
|
533
|
+
"summary": "Release notes and notable changes for SlexKit.",
|
|
534
|
+
"href": "/docs/releases/changelog",
|
|
535
|
+
"rawHref": "/docs/releases/changelog.md",
|
|
536
|
+
"sourcePath": "site/content/releases/changelog/en-US.md",
|
|
537
|
+
"body": "---\ntitle: Changelog\ncategory: Releases\nstatus: ready\norder: 10\nsummary: \"Release notes and notable changes for SlexKit.\"\nslexkitRenderMode: component\n---\n\n# Changelog\n\nAll notable changes to SlexKit.\n\n## v0.2.0 - First public release\n\n### Added\n- `@slexkit/mcp`: AI Agent Model Context Protocol server with `slexkitDocs`, `slexkitExamples`, `slexkitValidate` tools\n- Protocol marker: `\"slex\": \"0.1\"` required on all Slex expressions and ToolHost templates\n- SPEC contract validation: component specs are now validated against the runtime contract\n- Version sync automation (`scripts/sync-version.ts`) and changelog sync (`scripts/sync-changelog.ts`)\n- AI documentation generation pipeline with structured LLM-friendly output\n- Static site export with SEO metadata engine (`site/data/seo.js`, `site/scripts/export-static.ts`)\n- Chinese documentation for all reference and guide pages\n- Enhanced component state management with lifecycle hooks (`onMount`, `onUnmount`, `onUpdate`)\n\n### Changed\n- Switch component migrated from `checked` to `enabled` state mode\n- Documentation: restructured site content, synced en-US with zh-CN, added reference section\n- Theme: refined select styling, dropdown shadows, footer and info tone polish\n- AI docs generation enhanced with Chinese/English locale awareness\n\n### Fixed\n- Component spec alignment with documentation across all 28 components\n- Site routing and code block highlighting\n- Introduction and quick-start guide wording for clarity\n- Broken links and factual errors in component and reference documentation\n\n## v0.1.9\n\n### Added\n- Icon manager with Phosphor icon system (`registerIcon`, `registerIcons`, `getIcon`, `loadIcon`)\n- Expanded icon support across labeled components (badge, button, callout, etc.)\n- Icon docs page with registration API reference\n\n### Fixed\n- Refined component interactions in static site export\n- Tabs indicator animation restored\n- Callout and toast icon placement in titles\n- Numeric value display formatting\n\n### Changed\n- Site docs shell refactored for static export\n- Site navigation and theme controls alignment\n- Slex naming standardized across codebase\n\n## v0.1.8\n\n### Added\n- CSP-hardened secure runtime sandbox with heartbeat watchdog\n- `mountSecureArtifact()` for isolated iframe rendering\n- `createSlexKitMarkdownRuntimeHost()` for Markdown-hosted SlexKit blocks\n- Streamdown React renderer (`@slexkit/streamdown`)\n- Obsidian plugin adapter (`@slexkit/obsidian`)\n- Shadcn-compatible CSS theme (`@slexkit/theme-shadcn`)\n- Package boundary wrappers (`@slexkit/runtime`, `@slexkit/components-svelte`)\n- ToolHost with built-in templates: `confirm-action`, `choose-options`, `fill-form`\n\n### Changed\n- Component registration model: side-effect import registers all components\n- Styles reorganized into per-component CSS files\n- Build system: Bun.build with Svelte plugin, split ESM entries\n\n## v0.1.7\n\n### Added\n- `$for` list rendering with keyed reconciliation (delete / add-update-reorder / trim phases)\n- `$if` conditional rendering with enter/leave animation support\n- `$key` strategy: `$value`, property-based, or fallback to index\n- Component instance state modes: `value`, `checked`, `enabled`, `readable`, `none`\n- Lifecycle hooks: `g.onMount_<name>()`, `g.onUnmount_<name>()`, `g.onUpdate_<name>()`\n- Engineering number input with SI prefix parsing\n- Rich error diagnostics with line/column/excerpt display\n\n### Changed\n- Expression evaluation: `new Function()` compilation with reactive dependency tracking\n- Layout tree renderer now supports three rendering paths (normal, `$if`, `$for`)\n- `g` deep-merge preserves keys not present in the new state\n\n## v0.1.6 and earlier\n\n### Added\n- Reactive `g`/`layout` split with expression pipes (`$` read-pipes, `on*` write-pipes)\n- Custom fine-grained reactivity system (~280 lines, no external dependency)\n- Component registry with extensible renderer interface\n- Svelte 5 component adapter (creates stores from props, flushSync DOM)\n- `mount()`, `ingest()`, `boot()` entry points\n- 28 built-in Svelte components across 8 categories\n- `parseSlexSource()` DSL parser with `diagnoseSlexKitSource()` error reporting\n- Documentation site with interactive playground",
|
|
538
|
+
"hash": "c1cbfe8c"
|
|
539
|
+
}
|
|
540
|
+
],
|
|
541
|
+
"components": [
|
|
542
|
+
{
|
|
543
|
+
"type": "accordion",
|
|
544
|
+
"title": "Accordion",
|
|
545
|
+
"category": "Disclosure",
|
|
546
|
+
"status": "ready",
|
|
547
|
+
"state": "none",
|
|
548
|
+
"since": "0.1.0",
|
|
549
|
+
"summary": "Expandable grouped panels.",
|
|
550
|
+
"docsHref": "/docs/components/accordion",
|
|
551
|
+
"rawHref": "/docs/components/accordion.md",
|
|
552
|
+
"propCount": 5,
|
|
553
|
+
"exampleCount": 1,
|
|
554
|
+
"props": {
|
|
555
|
+
"value": {
|
|
556
|
+
"type": "string | string[]",
|
|
557
|
+
"dynamic": true,
|
|
558
|
+
"description": "Current expanded item value; use an array when multiple is true."
|
|
559
|
+
},
|
|
560
|
+
"multiple": {
|
|
561
|
+
"type": "boolean",
|
|
562
|
+
"default": false,
|
|
563
|
+
"description": "Allow multiple items to be expanded at the same time."
|
|
564
|
+
},
|
|
565
|
+
"items": {
|
|
566
|
+
"type": "array",
|
|
567
|
+
"description": "Panel definitions with value, label, content, and optional icon."
|
|
568
|
+
},
|
|
569
|
+
"items[].icon": {
|
|
570
|
+
"type": "string",
|
|
571
|
+
"description": "Icon name shown before an item trigger label."
|
|
572
|
+
},
|
|
573
|
+
"onchange": {
|
|
574
|
+
"type": "write-expression",
|
|
575
|
+
"description": "Write expression invoked when expanded items change."
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
"children": {
|
|
579
|
+
"allowed": false,
|
|
580
|
+
"description": "This component does not render nested child components."
|
|
581
|
+
},
|
|
582
|
+
"examples": [
|
|
583
|
+
{
|
|
584
|
+
"id": "basic",
|
|
585
|
+
"title": "Basic usage",
|
|
586
|
+
"source": {
|
|
587
|
+
"slex": "0.1",
|
|
588
|
+
"namespace": "doc_accordion_typical",
|
|
589
|
+
"layout": {
|
|
590
|
+
"accordion:faq": {
|
|
591
|
+
"multiple": true,
|
|
592
|
+
"value": [
|
|
593
|
+
"install"
|
|
594
|
+
],
|
|
595
|
+
"items": [
|
|
596
|
+
{
|
|
597
|
+
"value": "install",
|
|
598
|
+
"label": "Install",
|
|
599
|
+
"icon": "download-simple",
|
|
600
|
+
"content": "Prepare dependencies."
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
"value": "review",
|
|
604
|
+
"label": "Review",
|
|
605
|
+
"icon": "check-circle",
|
|
606
|
+
"content": "Check the result."
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
"value": "ship",
|
|
610
|
+
"label": "Ship",
|
|
611
|
+
"icon": "rocket-launch",
|
|
612
|
+
"content": "Publish the change."
|
|
613
|
+
}
|
|
614
|
+
]
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
],
|
|
620
|
+
"hash": "ff1be273"
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
"type": "badge",
|
|
624
|
+
"title": "Badge",
|
|
625
|
+
"category": "Content",
|
|
626
|
+
"status": "ready",
|
|
627
|
+
"state": "readable",
|
|
628
|
+
"since": "0.1.0",
|
|
629
|
+
"summary": "Compact label for status or classification.",
|
|
630
|
+
"docsHref": "/docs/components/badge",
|
|
631
|
+
"rawHref": "/docs/components/badge.md",
|
|
632
|
+
"propCount": 6,
|
|
633
|
+
"exampleCount": 1,
|
|
634
|
+
"props": {
|
|
635
|
+
"label": {
|
|
636
|
+
"type": "string",
|
|
637
|
+
"dynamic": true,
|
|
638
|
+
"description": "Badge text."
|
|
639
|
+
},
|
|
640
|
+
"text": {
|
|
641
|
+
"type": "string",
|
|
642
|
+
"dynamic": true,
|
|
643
|
+
"description": "Alias for label."
|
|
644
|
+
},
|
|
645
|
+
"content": {
|
|
646
|
+
"type": "string",
|
|
647
|
+
"dynamic": true,
|
|
648
|
+
"description": "Alias for label."
|
|
649
|
+
},
|
|
650
|
+
"icon": {
|
|
651
|
+
"type": "string",
|
|
652
|
+
"description": "Icon name shown before the badge label."
|
|
653
|
+
},
|
|
654
|
+
"tone": {
|
|
655
|
+
"type": "string",
|
|
656
|
+
"values": [
|
|
657
|
+
"info",
|
|
658
|
+
"success",
|
|
659
|
+
"warning",
|
|
660
|
+
"danger",
|
|
661
|
+
"muted"
|
|
662
|
+
],
|
|
663
|
+
"default": "info",
|
|
664
|
+
"description": "Semantic tone applied to the badge."
|
|
665
|
+
},
|
|
666
|
+
"variant": {
|
|
667
|
+
"type": "string",
|
|
668
|
+
"values": [
|
|
669
|
+
"info",
|
|
670
|
+
"success",
|
|
671
|
+
"warning",
|
|
672
|
+
"danger",
|
|
673
|
+
"muted"
|
|
674
|
+
],
|
|
675
|
+
"description": "Alias for tone."
|
|
676
|
+
}
|
|
677
|
+
},
|
|
678
|
+
"children": {
|
|
679
|
+
"allowed": false,
|
|
680
|
+
"description": "This component does not render nested child components."
|
|
681
|
+
},
|
|
682
|
+
"examples": [
|
|
683
|
+
{
|
|
684
|
+
"id": "basic",
|
|
685
|
+
"title": "Basic usage",
|
|
686
|
+
"source": {
|
|
687
|
+
"slex": "0.1",
|
|
688
|
+
"namespace": "doc_badge_typical",
|
|
689
|
+
"layout": {
|
|
690
|
+
"row:badges": {
|
|
691
|
+
"badge:ready": {
|
|
692
|
+
"label": "ready",
|
|
693
|
+
"icon": "check-circle",
|
|
694
|
+
"tone": "success"
|
|
695
|
+
},
|
|
696
|
+
"badge:pending": {
|
|
697
|
+
"label": "pending",
|
|
698
|
+
"tone": "warning"
|
|
699
|
+
},
|
|
700
|
+
"badge:info": {
|
|
701
|
+
"label": "info",
|
|
702
|
+
"tone": "info"
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
],
|
|
709
|
+
"hash": "eece8f49"
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
"type": "button",
|
|
713
|
+
"title": "Button",
|
|
714
|
+
"category": "Action",
|
|
715
|
+
"status": "ready",
|
|
716
|
+
"state": "none",
|
|
717
|
+
"since": "0.1.0",
|
|
718
|
+
"summary": "Action trigger.",
|
|
719
|
+
"docsHref": "/docs/components/button",
|
|
720
|
+
"rawHref": "/docs/components/button.md",
|
|
721
|
+
"propCount": 12,
|
|
722
|
+
"exampleCount": 1,
|
|
723
|
+
"props": {
|
|
724
|
+
"label": {
|
|
725
|
+
"type": "string",
|
|
726
|
+
"dynamic": true,
|
|
727
|
+
"description": "Visible button text and accessible name."
|
|
728
|
+
},
|
|
729
|
+
"icon": {
|
|
730
|
+
"type": "string",
|
|
731
|
+
"description": "Icon name shown before the label."
|
|
732
|
+
},
|
|
733
|
+
"iconOnly": {
|
|
734
|
+
"type": "boolean",
|
|
735
|
+
"default": false,
|
|
736
|
+
"description": "Show only the icon while retaining label as the accessible name."
|
|
737
|
+
},
|
|
738
|
+
"variant": {
|
|
739
|
+
"type": "string",
|
|
740
|
+
"values": [
|
|
741
|
+
"primary",
|
|
742
|
+
"secondary",
|
|
743
|
+
"danger",
|
|
744
|
+
"ghost"
|
|
745
|
+
],
|
|
746
|
+
"default": "primary",
|
|
747
|
+
"description": "Semantic action variant."
|
|
748
|
+
},
|
|
749
|
+
"disabled": {
|
|
750
|
+
"type": "boolean",
|
|
751
|
+
"default": false,
|
|
752
|
+
"dynamic": true,
|
|
753
|
+
"description": "Disable the action."
|
|
754
|
+
},
|
|
755
|
+
"href": {
|
|
756
|
+
"type": "string",
|
|
757
|
+
"dynamic": true,
|
|
758
|
+
"description": "Render the button surface as a link to this URL."
|
|
759
|
+
},
|
|
760
|
+
"target": {
|
|
761
|
+
"type": "string",
|
|
762
|
+
"description": "Link target used when href is present."
|
|
763
|
+
},
|
|
764
|
+
"title": {
|
|
765
|
+
"type": "string",
|
|
766
|
+
"dynamic": true,
|
|
767
|
+
"description": "Tooltip and accessible-label fallback."
|
|
768
|
+
},
|
|
769
|
+
"selected": {
|
|
770
|
+
"type": "boolean",
|
|
771
|
+
"dynamic": true,
|
|
772
|
+
"description": "Render the icon in its selected visual state."
|
|
773
|
+
},
|
|
774
|
+
"active": {
|
|
775
|
+
"type": "boolean",
|
|
776
|
+
"dynamic": true,
|
|
777
|
+
"description": "Render the icon in its active visual state."
|
|
778
|
+
},
|
|
779
|
+
"pressed": {
|
|
780
|
+
"type": "boolean",
|
|
781
|
+
"dynamic": true,
|
|
782
|
+
"description": "Expose pressed state and render the selected icon style."
|
|
783
|
+
},
|
|
784
|
+
"onclick": {
|
|
785
|
+
"type": "write-expression",
|
|
786
|
+
"description": "Write expression invoked when the button is clicked."
|
|
787
|
+
}
|
|
788
|
+
},
|
|
789
|
+
"children": {
|
|
790
|
+
"allowed": false,
|
|
791
|
+
"description": "This component does not render nested child components."
|
|
792
|
+
},
|
|
793
|
+
"examples": [
|
|
794
|
+
{
|
|
795
|
+
"id": "basic",
|
|
796
|
+
"title": "Basic usage",
|
|
797
|
+
"source": {
|
|
798
|
+
"slex": "0.1",
|
|
799
|
+
"namespace": "doc_button_typical",
|
|
800
|
+
"layout": {
|
|
801
|
+
"row:actions": {
|
|
802
|
+
"button:save": {
|
|
803
|
+
"label": "Save",
|
|
804
|
+
"icon": "floppy-disk",
|
|
805
|
+
"variant": "primary"
|
|
806
|
+
},
|
|
807
|
+
"button:cancel": {
|
|
808
|
+
"label": "Cancel",
|
|
809
|
+
"variant": "secondary"
|
|
810
|
+
},
|
|
811
|
+
"button:delete": {
|
|
812
|
+
"label": "Delete",
|
|
813
|
+
"variant": "danger"
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
],
|
|
820
|
+
"hash": "3bd71fe1"
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
"type": "callout",
|
|
824
|
+
"title": "Callout",
|
|
825
|
+
"category": "Content",
|
|
826
|
+
"status": "ready",
|
|
827
|
+
"state": "readable",
|
|
828
|
+
"since": "0.1.0",
|
|
829
|
+
"summary": "Highlighted contextual message.",
|
|
830
|
+
"docsHref": "/docs/components/callout",
|
|
831
|
+
"rawHref": "/docs/components/callout.md",
|
|
832
|
+
"propCount": 8,
|
|
833
|
+
"exampleCount": 1,
|
|
834
|
+
"props": {
|
|
835
|
+
"title": {
|
|
836
|
+
"type": "string",
|
|
837
|
+
"dynamic": true,
|
|
838
|
+
"description": "Callout title."
|
|
839
|
+
},
|
|
840
|
+
"heading": {
|
|
841
|
+
"type": "string",
|
|
842
|
+
"dynamic": true,
|
|
843
|
+
"description": "Alias for title."
|
|
844
|
+
},
|
|
845
|
+
"label": {
|
|
846
|
+
"type": "string",
|
|
847
|
+
"dynamic": true,
|
|
848
|
+
"description": "Alias for title."
|
|
849
|
+
},
|
|
850
|
+
"icon": {
|
|
851
|
+
"type": "string",
|
|
852
|
+
"description": "Icon name shown before the title."
|
|
853
|
+
},
|
|
854
|
+
"text": {
|
|
855
|
+
"type": "string",
|
|
856
|
+
"dynamic": true,
|
|
857
|
+
"description": "Callout body text."
|
|
858
|
+
},
|
|
859
|
+
"message": {
|
|
860
|
+
"type": "string",
|
|
861
|
+
"dynamic": true,
|
|
862
|
+
"description": "Alias for text."
|
|
863
|
+
},
|
|
864
|
+
"content": {
|
|
865
|
+
"type": "string",
|
|
866
|
+
"dynamic": true,
|
|
867
|
+
"description": "Alias for text."
|
|
868
|
+
},
|
|
869
|
+
"tone": {
|
|
870
|
+
"type": "string",
|
|
871
|
+
"values": [
|
|
872
|
+
"info",
|
|
873
|
+
"success",
|
|
874
|
+
"warning",
|
|
875
|
+
"danger"
|
|
876
|
+
],
|
|
877
|
+
"default": "info",
|
|
878
|
+
"description": "Semantic tone for the callout."
|
|
879
|
+
}
|
|
880
|
+
},
|
|
881
|
+
"children": {
|
|
882
|
+
"allowed": true,
|
|
883
|
+
"description": "Nested component fields are rendered as child content in field order."
|
|
884
|
+
},
|
|
885
|
+
"examples": [
|
|
886
|
+
{
|
|
887
|
+
"id": "basic",
|
|
888
|
+
"title": "Basic usage",
|
|
889
|
+
"source": {
|
|
890
|
+
"slex": "0.1",
|
|
891
|
+
"namespace": "doc_callout_typical",
|
|
892
|
+
"layout": {
|
|
893
|
+
"callout:notice": {
|
|
894
|
+
"tone": "info",
|
|
895
|
+
"title": "Notice",
|
|
896
|
+
"icon": "info",
|
|
897
|
+
"text": "Use callout for information that should stand out."
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
],
|
|
903
|
+
"hash": "0fee87ac"
|
|
904
|
+
},
|
|
905
|
+
{
|
|
906
|
+
"type": "card",
|
|
907
|
+
"title": "Card",
|
|
908
|
+
"category": "Layout",
|
|
909
|
+
"status": "ready",
|
|
910
|
+
"state": "none",
|
|
911
|
+
"since": "0.1.0",
|
|
912
|
+
"summary": "Bordered grouping container.",
|
|
913
|
+
"docsHref": "/docs/components/card",
|
|
914
|
+
"rawHref": "/docs/components/card.md",
|
|
915
|
+
"propCount": 3,
|
|
916
|
+
"exampleCount": 1,
|
|
917
|
+
"props": {
|
|
918
|
+
"title": {
|
|
919
|
+
"type": "string",
|
|
920
|
+
"dynamic": true,
|
|
921
|
+
"description": "Card title."
|
|
922
|
+
},
|
|
923
|
+
"icon": {
|
|
924
|
+
"type": "string",
|
|
925
|
+
"description": "Icon name shown before the title."
|
|
926
|
+
},
|
|
927
|
+
"tone": {
|
|
928
|
+
"type": "string",
|
|
929
|
+
"values": [
|
|
930
|
+
"info",
|
|
931
|
+
"success",
|
|
932
|
+
"warning",
|
|
933
|
+
"danger",
|
|
934
|
+
"muted"
|
|
935
|
+
],
|
|
936
|
+
"description": "Optional semantic tone for the card surface."
|
|
937
|
+
}
|
|
938
|
+
},
|
|
939
|
+
"children": {
|
|
940
|
+
"allowed": true,
|
|
941
|
+
"description": "Nested component fields are rendered as child content in field order."
|
|
942
|
+
},
|
|
943
|
+
"examples": [
|
|
944
|
+
{
|
|
945
|
+
"id": "basic",
|
|
946
|
+
"title": "Basic usage",
|
|
947
|
+
"source": {
|
|
948
|
+
"slex": "0.1",
|
|
949
|
+
"namespace": "doc_card_typical",
|
|
950
|
+
"layout": {
|
|
951
|
+
"card:metrics": {
|
|
952
|
+
"title": "Metrics",
|
|
953
|
+
"icon": "chart-bar",
|
|
954
|
+
"grid:items": {
|
|
955
|
+
"columns": 2,
|
|
956
|
+
"stat:requests": {
|
|
957
|
+
"label": "Requests",
|
|
958
|
+
"value": "1.2k",
|
|
959
|
+
"unit": "/min"
|
|
960
|
+
},
|
|
961
|
+
"stat:latency": {
|
|
962
|
+
"label": "Latency",
|
|
963
|
+
"value": "42",
|
|
964
|
+
"unit": "ms"
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
],
|
|
972
|
+
"hash": "d5c9d358"
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
"type": "checkbox",
|
|
976
|
+
"title": "Checkbox",
|
|
977
|
+
"category": "Input",
|
|
978
|
+
"status": "ready",
|
|
979
|
+
"state": "checked",
|
|
980
|
+
"since": "0.1.0",
|
|
981
|
+
"summary": "Boolean checkbox input.",
|
|
982
|
+
"docsHref": "/docs/components/checkbox",
|
|
983
|
+
"rawHref": "/docs/components/checkbox.md",
|
|
984
|
+
"propCount": 7,
|
|
985
|
+
"exampleCount": 1,
|
|
986
|
+
"props": {
|
|
987
|
+
"checked": {
|
|
988
|
+
"type": "boolean",
|
|
989
|
+
"default": false,
|
|
990
|
+
"dynamic": true,
|
|
991
|
+
"description": "Checked state."
|
|
992
|
+
},
|
|
993
|
+
"label": {
|
|
994
|
+
"type": "string",
|
|
995
|
+
"dynamic": true,
|
|
996
|
+
"description": "Checkbox label."
|
|
997
|
+
},
|
|
998
|
+
"icon": {
|
|
999
|
+
"type": "string",
|
|
1000
|
+
"description": "Icon name shown before the visible label."
|
|
1001
|
+
},
|
|
1002
|
+
"disabled": {
|
|
1003
|
+
"type": "boolean",
|
|
1004
|
+
"default": false,
|
|
1005
|
+
"dynamic": true,
|
|
1006
|
+
"description": "Disable the checkbox."
|
|
1007
|
+
},
|
|
1008
|
+
"haptic": {
|
|
1009
|
+
"type": "boolean",
|
|
1010
|
+
"default": true,
|
|
1011
|
+
"description": "Enable vibration feedback on supported devices."
|
|
1012
|
+
},
|
|
1013
|
+
"haptics": {
|
|
1014
|
+
"type": "boolean",
|
|
1015
|
+
"default": true,
|
|
1016
|
+
"description": "Alias for haptic."
|
|
1017
|
+
},
|
|
1018
|
+
"onchange": {
|
|
1019
|
+
"type": "write-expression",
|
|
1020
|
+
"description": "Write expression invoked when checked state changes."
|
|
1021
|
+
}
|
|
1022
|
+
},
|
|
1023
|
+
"children": {
|
|
1024
|
+
"allowed": false,
|
|
1025
|
+
"description": "This component does not render nested child components."
|
|
1026
|
+
},
|
|
1027
|
+
"examples": [
|
|
1028
|
+
{
|
|
1029
|
+
"id": "basic",
|
|
1030
|
+
"title": "Basic usage",
|
|
1031
|
+
"source": {
|
|
1032
|
+
"slex": "0.1",
|
|
1033
|
+
"namespace": "doc_checkbox_typical",
|
|
1034
|
+
"layout": {
|
|
1035
|
+
"checkbox:agree": {
|
|
1036
|
+
"checked": true,
|
|
1037
|
+
"label": "I agree",
|
|
1038
|
+
"icon": "handshake"
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
],
|
|
1044
|
+
"hash": "f02a8e1f"
|
|
1045
|
+
},
|
|
1046
|
+
{
|
|
1047
|
+
"type": "code-block",
|
|
1048
|
+
"title": "Code Block",
|
|
1049
|
+
"category": "Content",
|
|
1050
|
+
"status": "ready",
|
|
1051
|
+
"state": "readable",
|
|
1052
|
+
"since": "0.1.0",
|
|
1053
|
+
"summary": "Formatted code or log block.",
|
|
1054
|
+
"docsHref": "/docs/components/code-block",
|
|
1055
|
+
"rawHref": "/docs/components/code-block.md",
|
|
1056
|
+
"propCount": 7,
|
|
1057
|
+
"exampleCount": 1,
|
|
1058
|
+
"props": {
|
|
1059
|
+
"code": {
|
|
1060
|
+
"type": "string",
|
|
1061
|
+
"dynamic": true,
|
|
1062
|
+
"description": "Code text content."
|
|
1063
|
+
},
|
|
1064
|
+
"source": {
|
|
1065
|
+
"type": "string",
|
|
1066
|
+
"dynamic": true,
|
|
1067
|
+
"description": "Alias for code."
|
|
1068
|
+
},
|
|
1069
|
+
"content": {
|
|
1070
|
+
"type": "string",
|
|
1071
|
+
"dynamic": true,
|
|
1072
|
+
"description": "Alias for code."
|
|
1073
|
+
},
|
|
1074
|
+
"language": {
|
|
1075
|
+
"type": "string",
|
|
1076
|
+
"description": "Language label."
|
|
1077
|
+
},
|
|
1078
|
+
"title": {
|
|
1079
|
+
"type": "string",
|
|
1080
|
+
"description": "Code block title."
|
|
1081
|
+
},
|
|
1082
|
+
"icon": {
|
|
1083
|
+
"type": "string",
|
|
1084
|
+
"description": "Icon name shown before the title."
|
|
1085
|
+
},
|
|
1086
|
+
"lineNumbers": {
|
|
1087
|
+
"type": "boolean",
|
|
1088
|
+
"default": true,
|
|
1089
|
+
"description": "Show line numbers."
|
|
1090
|
+
}
|
|
1091
|
+
},
|
|
1092
|
+
"children": {
|
|
1093
|
+
"allowed": false,
|
|
1094
|
+
"description": "This component does not render nested child components."
|
|
1095
|
+
},
|
|
1096
|
+
"examples": [
|
|
1097
|
+
{
|
|
1098
|
+
"id": "basic",
|
|
1099
|
+
"title": "Basic usage",
|
|
1100
|
+
"source": {
|
|
1101
|
+
"slex": "0.1",
|
|
1102
|
+
"namespace": "doc_code_block_typical",
|
|
1103
|
+
"layout": {
|
|
1104
|
+
"code-block:config": {
|
|
1105
|
+
"title": "Config",
|
|
1106
|
+
"icon": "code",
|
|
1107
|
+
"language": "js",
|
|
1108
|
+
"code": "export const enabled = true;"
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
],
|
|
1114
|
+
"hash": "70ce858c"
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
"type": "collapsible",
|
|
1118
|
+
"title": "Collapsible",
|
|
1119
|
+
"category": "Disclosure",
|
|
1120
|
+
"status": "ready",
|
|
1121
|
+
"state": "none",
|
|
1122
|
+
"since": "0.1.0",
|
|
1123
|
+
"summary": "Single expandable region.",
|
|
1124
|
+
"docsHref": "/docs/components/collapsible",
|
|
1125
|
+
"rawHref": "/docs/components/collapsible.md",
|
|
1126
|
+
"propCount": 5,
|
|
1127
|
+
"exampleCount": 1,
|
|
1128
|
+
"props": {
|
|
1129
|
+
"open": {
|
|
1130
|
+
"type": "boolean",
|
|
1131
|
+
"default": false,
|
|
1132
|
+
"dynamic": true,
|
|
1133
|
+
"description": "Expanded state."
|
|
1134
|
+
},
|
|
1135
|
+
"trigger": {
|
|
1136
|
+
"type": "string",
|
|
1137
|
+
"dynamic": true,
|
|
1138
|
+
"description": "Trigger button text."
|
|
1139
|
+
},
|
|
1140
|
+
"icon": {
|
|
1141
|
+
"type": "string",
|
|
1142
|
+
"description": "Icon name shown before trigger text."
|
|
1143
|
+
},
|
|
1144
|
+
"content": {
|
|
1145
|
+
"type": "string",
|
|
1146
|
+
"dynamic": true,
|
|
1147
|
+
"description": "Static body content."
|
|
1148
|
+
},
|
|
1149
|
+
"onchange": {
|
|
1150
|
+
"type": "write-expression",
|
|
1151
|
+
"description": "Write expression invoked when open state changes."
|
|
1152
|
+
}
|
|
1153
|
+
},
|
|
1154
|
+
"children": {
|
|
1155
|
+
"allowed": true,
|
|
1156
|
+
"description": "Nested component fields are rendered as child content in field order."
|
|
1157
|
+
},
|
|
1158
|
+
"examples": [
|
|
1159
|
+
{
|
|
1160
|
+
"id": "basic",
|
|
1161
|
+
"title": "Basic usage",
|
|
1162
|
+
"source": {
|
|
1163
|
+
"slex": "0.1",
|
|
1164
|
+
"namespace": "doc_collapsible_typical",
|
|
1165
|
+
"layout": {
|
|
1166
|
+
"collapsible:more": {
|
|
1167
|
+
"open": true,
|
|
1168
|
+
"trigger": "Details",
|
|
1169
|
+
"icon": "caret-circle-down",
|
|
1170
|
+
"content": "This secondary content can be collapsed."
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
],
|
|
1176
|
+
"hash": "fbb14382"
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
"type": "column",
|
|
1180
|
+
"title": "Column",
|
|
1181
|
+
"category": "Layout",
|
|
1182
|
+
"status": "ready",
|
|
1183
|
+
"state": "none",
|
|
1184
|
+
"since": "0.1.0",
|
|
1185
|
+
"summary": "Vertical layout container.",
|
|
1186
|
+
"docsHref": "/docs/components/column",
|
|
1187
|
+
"rawHref": "/docs/components/column.md",
|
|
1188
|
+
"propCount": 0,
|
|
1189
|
+
"exampleCount": 1,
|
|
1190
|
+
"props": {},
|
|
1191
|
+
"children": {
|
|
1192
|
+
"allowed": true,
|
|
1193
|
+
"description": "Nested component fields are rendered as child content in field order."
|
|
1194
|
+
},
|
|
1195
|
+
"examples": [
|
|
1196
|
+
{
|
|
1197
|
+
"id": "basic",
|
|
1198
|
+
"title": "Basic usage",
|
|
1199
|
+
"source": {
|
|
1200
|
+
"slex": "0.1",
|
|
1201
|
+
"namespace": "doc_column_typical",
|
|
1202
|
+
"layout": {
|
|
1203
|
+
"column:form": {
|
|
1204
|
+
"input:name": {
|
|
1205
|
+
"placeholder": "Name"
|
|
1206
|
+
},
|
|
1207
|
+
"input:email": {
|
|
1208
|
+
"placeholder": "Email"
|
|
1209
|
+
},
|
|
1210
|
+
"button:save": {
|
|
1211
|
+
"label": "Save"
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
],
|
|
1218
|
+
"hash": "764d30da"
|
|
1219
|
+
},
|
|
1220
|
+
{
|
|
1221
|
+
"type": "divider",
|
|
1222
|
+
"title": "Divider",
|
|
1223
|
+
"category": "Content",
|
|
1224
|
+
"status": "ready",
|
|
1225
|
+
"state": "readable",
|
|
1226
|
+
"since": "0.1.0",
|
|
1227
|
+
"summary": "Visual separator.",
|
|
1228
|
+
"docsHref": "/docs/components/divider",
|
|
1229
|
+
"rawHref": "/docs/components/divider.md",
|
|
1230
|
+
"propCount": 2,
|
|
1231
|
+
"exampleCount": 1,
|
|
1232
|
+
"props": {
|
|
1233
|
+
"label": {
|
|
1234
|
+
"type": "string",
|
|
1235
|
+
"dynamic": true,
|
|
1236
|
+
"description": "Text shown in the divider."
|
|
1237
|
+
},
|
|
1238
|
+
"icon": {
|
|
1239
|
+
"type": "string",
|
|
1240
|
+
"description": "Icon name shown before the label."
|
|
1241
|
+
}
|
|
1242
|
+
},
|
|
1243
|
+
"children": {
|
|
1244
|
+
"allowed": false,
|
|
1245
|
+
"description": "This component does not render nested child components."
|
|
1246
|
+
},
|
|
1247
|
+
"examples": [
|
|
1248
|
+
{
|
|
1249
|
+
"id": "basic",
|
|
1250
|
+
"title": "Basic usage",
|
|
1251
|
+
"source": {
|
|
1252
|
+
"slex": "0.1",
|
|
1253
|
+
"namespace": "doc_divider_typical",
|
|
1254
|
+
"layout": {
|
|
1255
|
+
"column:content": {
|
|
1256
|
+
"text:top": {
|
|
1257
|
+
"text": "Above"
|
|
1258
|
+
},
|
|
1259
|
+
"divider:line": {
|
|
1260
|
+
"label": "Divider",
|
|
1261
|
+
"icon": "flag"
|
|
1262
|
+
},
|
|
1263
|
+
"text:bottom": {
|
|
1264
|
+
"text": "Below"
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
],
|
|
1271
|
+
"hash": "447bf44a"
|
|
1272
|
+
},
|
|
1273
|
+
{
|
|
1274
|
+
"type": "grid",
|
|
1275
|
+
"title": "Grid",
|
|
1276
|
+
"category": "Layout",
|
|
1277
|
+
"status": "ready",
|
|
1278
|
+
"state": "none",
|
|
1279
|
+
"since": "0.1.0",
|
|
1280
|
+
"summary": "Responsive grid container.",
|
|
1281
|
+
"docsHref": "/docs/components/grid",
|
|
1282
|
+
"rawHref": "/docs/components/grid.md",
|
|
1283
|
+
"propCount": 6,
|
|
1284
|
+
"exampleCount": 1,
|
|
1285
|
+
"props": {
|
|
1286
|
+
"columns": {
|
|
1287
|
+
"type": "number",
|
|
1288
|
+
"default": 1,
|
|
1289
|
+
"dynamic": true,
|
|
1290
|
+
"description": "Base column count."
|
|
1291
|
+
},
|
|
1292
|
+
"smColumns": {
|
|
1293
|
+
"type": "number",
|
|
1294
|
+
"dynamic": true,
|
|
1295
|
+
"description": "Column count at the small breakpoint."
|
|
1296
|
+
},
|
|
1297
|
+
"mdColumns": {
|
|
1298
|
+
"type": "number",
|
|
1299
|
+
"dynamic": true,
|
|
1300
|
+
"description": "Column count at the medium breakpoint."
|
|
1301
|
+
},
|
|
1302
|
+
"lgColumns": {
|
|
1303
|
+
"type": "number",
|
|
1304
|
+
"dynamic": true,
|
|
1305
|
+
"description": "Column count at the large breakpoint."
|
|
1306
|
+
},
|
|
1307
|
+
"xlColumns": {
|
|
1308
|
+
"type": "number",
|
|
1309
|
+
"dynamic": true,
|
|
1310
|
+
"description": "Column count at the extra-large breakpoint."
|
|
1311
|
+
},
|
|
1312
|
+
"gap": {
|
|
1313
|
+
"type": "string",
|
|
1314
|
+
"dynamic": true,
|
|
1315
|
+
"description": "Spacing between grid items."
|
|
1316
|
+
}
|
|
1317
|
+
},
|
|
1318
|
+
"children": {
|
|
1319
|
+
"allowed": true,
|
|
1320
|
+
"description": "Nested component fields are rendered as child content in field order."
|
|
1321
|
+
},
|
|
1322
|
+
"examples": [
|
|
1323
|
+
{
|
|
1324
|
+
"id": "basic",
|
|
1325
|
+
"title": "Basic usage",
|
|
1326
|
+
"source": {
|
|
1327
|
+
"slex": "0.1",
|
|
1328
|
+
"namespace": "doc_grid_typical",
|
|
1329
|
+
"layout": {
|
|
1330
|
+
"grid:stats": {
|
|
1331
|
+
"columns": 1,
|
|
1332
|
+
"mdColumns": 3,
|
|
1333
|
+
"stat:a": {
|
|
1334
|
+
"label": "Requests",
|
|
1335
|
+
"value": "1.2k"
|
|
1336
|
+
},
|
|
1337
|
+
"stat:b": {
|
|
1338
|
+
"label": "Success",
|
|
1339
|
+
"value": "98%"
|
|
1340
|
+
},
|
|
1341
|
+
"stat:c": {
|
|
1342
|
+
"label": "Errors",
|
|
1343
|
+
"value": "3"
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
],
|
|
1350
|
+
"hash": "912458b7"
|
|
1351
|
+
},
|
|
1352
|
+
{
|
|
1353
|
+
"type": "icon",
|
|
1354
|
+
"title": "Icon",
|
|
1355
|
+
"category": "Component",
|
|
1356
|
+
"status": "ready",
|
|
1357
|
+
"state": "none",
|
|
1358
|
+
"since": "0.1.0",
|
|
1359
|
+
"summary": "Shared icon field capability.",
|
|
1360
|
+
"docsHref": "/docs/components/icon",
|
|
1361
|
+
"rawHref": "/docs/components/icon.md",
|
|
1362
|
+
"propCount": 7,
|
|
1363
|
+
"exampleCount": 1,
|
|
1364
|
+
"props": {
|
|
1365
|
+
"icon": {
|
|
1366
|
+
"type": "string",
|
|
1367
|
+
"description": "Icon name resolved through the global icon manager."
|
|
1368
|
+
},
|
|
1369
|
+
"iconOnly": {
|
|
1370
|
+
"type": "boolean",
|
|
1371
|
+
"description": "Render only the icon while retaining an accessible label where supported."
|
|
1372
|
+
},
|
|
1373
|
+
"items[].icon": {
|
|
1374
|
+
"type": "string",
|
|
1375
|
+
"description": "Accordion item trigger icon."
|
|
1376
|
+
},
|
|
1377
|
+
"options[].icon": {
|
|
1378
|
+
"type": "string",
|
|
1379
|
+
"description": "Select or radio option icon."
|
|
1380
|
+
},
|
|
1381
|
+
"columns[].icon": {
|
|
1382
|
+
"type": "string",
|
|
1383
|
+
"description": "Table column header icon."
|
|
1384
|
+
},
|
|
1385
|
+
"tabs[].icon": {
|
|
1386
|
+
"type": "string",
|
|
1387
|
+
"description": "Tab trigger icon."
|
|
1388
|
+
},
|
|
1389
|
+
"tabs[].iconOnly": {
|
|
1390
|
+
"type": "boolean",
|
|
1391
|
+
"description": "Tab trigger icon-only mode."
|
|
1392
|
+
}
|
|
1393
|
+
},
|
|
1394
|
+
"children": {
|
|
1395
|
+
"allowed": false,
|
|
1396
|
+
"description": "This component does not render nested child components."
|
|
1397
|
+
},
|
|
1398
|
+
"examples": [
|
|
1399
|
+
{
|
|
1400
|
+
"id": "basic",
|
|
1401
|
+
"title": "Icon field usage",
|
|
1402
|
+
"source": {
|
|
1403
|
+
"slex": "0.1",
|
|
1404
|
+
"namespace": "spec_button_basic",
|
|
1405
|
+
"layout": {
|
|
1406
|
+
"button:demo": {
|
|
1407
|
+
"label": "Settings",
|
|
1408
|
+
"icon": "gear-six",
|
|
1409
|
+
"iconOnly": true,
|
|
1410
|
+
"variant": "ghost"
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
],
|
|
1416
|
+
"hash": "0b7a18c9"
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
"type": "input",
|
|
1420
|
+
"title": "Input",
|
|
1421
|
+
"category": "Input",
|
|
1422
|
+
"status": "ready",
|
|
1423
|
+
"state": "value",
|
|
1424
|
+
"since": "0.1.0",
|
|
1425
|
+
"summary": "Text or engineering-value input.",
|
|
1426
|
+
"docsHref": "/docs/components/input",
|
|
1427
|
+
"rawHref": "/docs/components/input.md",
|
|
1428
|
+
"propCount": 22,
|
|
1429
|
+
"exampleCount": 1,
|
|
1430
|
+
"props": {
|
|
1431
|
+
"value": {
|
|
1432
|
+
"type": "string",
|
|
1433
|
+
"dynamic": true,
|
|
1434
|
+
"description": "Current input value."
|
|
1435
|
+
},
|
|
1436
|
+
"label": {
|
|
1437
|
+
"type": "string",
|
|
1438
|
+
"dynamic": true,
|
|
1439
|
+
"description": "Input label."
|
|
1440
|
+
},
|
|
1441
|
+
"unit": {
|
|
1442
|
+
"type": "string",
|
|
1443
|
+
"dynamic": true,
|
|
1444
|
+
"description": "Trailing unit text."
|
|
1445
|
+
},
|
|
1446
|
+
"description": {
|
|
1447
|
+
"type": "string",
|
|
1448
|
+
"dynamic": true,
|
|
1449
|
+
"description": "Assistive description below the input."
|
|
1450
|
+
},
|
|
1451
|
+
"help": {
|
|
1452
|
+
"type": "string",
|
|
1453
|
+
"dynamic": true,
|
|
1454
|
+
"description": "Alias for description."
|
|
1455
|
+
},
|
|
1456
|
+
"hint": {
|
|
1457
|
+
"type": "string",
|
|
1458
|
+
"dynamic": true,
|
|
1459
|
+
"description": "Alias for description."
|
|
1460
|
+
},
|
|
1461
|
+
"error": {
|
|
1462
|
+
"type": "string",
|
|
1463
|
+
"dynamic": true,
|
|
1464
|
+
"description": "Error text shown below the input and linked with aria-describedby."
|
|
1465
|
+
},
|
|
1466
|
+
"errorMessage": {
|
|
1467
|
+
"type": "string",
|
|
1468
|
+
"dynamic": true,
|
|
1469
|
+
"description": "Alias for error."
|
|
1470
|
+
},
|
|
1471
|
+
"invalid": {
|
|
1472
|
+
"type": "boolean",
|
|
1473
|
+
"default": false,
|
|
1474
|
+
"dynamic": true,
|
|
1475
|
+
"description": "Mark the input as invalid with aria-invalid and error styling."
|
|
1476
|
+
},
|
|
1477
|
+
"placeholder": {
|
|
1478
|
+
"type": "string",
|
|
1479
|
+
"description": "Placeholder text for empty values."
|
|
1480
|
+
},
|
|
1481
|
+
"type": {
|
|
1482
|
+
"type": "string",
|
|
1483
|
+
"default": "text",
|
|
1484
|
+
"description": "Input value kind; use engineering for parsed engineering values."
|
|
1485
|
+
},
|
|
1486
|
+
"disabled": {
|
|
1487
|
+
"type": "boolean",
|
|
1488
|
+
"default": false,
|
|
1489
|
+
"dynamic": true,
|
|
1490
|
+
"description": "Disable editing."
|
|
1491
|
+
},
|
|
1492
|
+
"readonly": {
|
|
1493
|
+
"type": "boolean",
|
|
1494
|
+
"default": false,
|
|
1495
|
+
"dynamic": true,
|
|
1496
|
+
"description": "Make the input read-only."
|
|
1497
|
+
},
|
|
1498
|
+
"readOnly": {
|
|
1499
|
+
"type": "boolean",
|
|
1500
|
+
"default": false,
|
|
1501
|
+
"dynamic": true,
|
|
1502
|
+
"description": "Alias for readonly."
|
|
1503
|
+
},
|
|
1504
|
+
"required": {
|
|
1505
|
+
"type": "boolean",
|
|
1506
|
+
"default": false,
|
|
1507
|
+
"dynamic": true,
|
|
1508
|
+
"description": "Mark the input as required."
|
|
1509
|
+
},
|
|
1510
|
+
"id": {
|
|
1511
|
+
"type": "string",
|
|
1512
|
+
"description": "Native input id; defaults to a stable id derived from the component name."
|
|
1513
|
+
},
|
|
1514
|
+
"name": {
|
|
1515
|
+
"type": "string",
|
|
1516
|
+
"description": "Native input name attribute."
|
|
1517
|
+
},
|
|
1518
|
+
"min": {
|
|
1519
|
+
"type": "string | number",
|
|
1520
|
+
"dynamic": true,
|
|
1521
|
+
"description": "Minimum value used by numeric input controls."
|
|
1522
|
+
},
|
|
1523
|
+
"max": {
|
|
1524
|
+
"type": "string | number",
|
|
1525
|
+
"dynamic": true,
|
|
1526
|
+
"description": "Maximum value used by numeric input controls."
|
|
1527
|
+
},
|
|
1528
|
+
"step": {
|
|
1529
|
+
"type": "string | number",
|
|
1530
|
+
"dynamic": true,
|
|
1531
|
+
"description": "Step size used by numeric input controls."
|
|
1532
|
+
},
|
|
1533
|
+
"controls": {
|
|
1534
|
+
"type": "boolean",
|
|
1535
|
+
"default": true,
|
|
1536
|
+
"dynamic": true,
|
|
1537
|
+
"description": "Show decrement and increment buttons for numeric inputs."
|
|
1538
|
+
},
|
|
1539
|
+
"onchange": {
|
|
1540
|
+
"type": "write-expression",
|
|
1541
|
+
"description": "Write expression invoked when the value changes."
|
|
1542
|
+
}
|
|
1543
|
+
},
|
|
1544
|
+
"children": {
|
|
1545
|
+
"allowed": false,
|
|
1546
|
+
"description": "This component does not render nested child components."
|
|
1547
|
+
},
|
|
1548
|
+
"examples": [
|
|
1549
|
+
{
|
|
1550
|
+
"id": "basic",
|
|
1551
|
+
"title": "Basic usage",
|
|
1552
|
+
"source": {
|
|
1553
|
+
"slex": "0.1",
|
|
1554
|
+
"namespace": "doc_input_typical",
|
|
1555
|
+
"layout": {
|
|
1556
|
+
"input:name": {
|
|
1557
|
+
"label": "Project",
|
|
1558
|
+
"value": "SlexKit",
|
|
1559
|
+
"placeholder": "Enter name",
|
|
1560
|
+
"description": "Visible labels keep form fields scannable."
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
],
|
|
1566
|
+
"hash": "66f5dbc5"
|
|
1567
|
+
},
|
|
1568
|
+
{
|
|
1569
|
+
"type": "link",
|
|
1570
|
+
"title": "Link",
|
|
1571
|
+
"category": "Content",
|
|
1572
|
+
"status": "ready",
|
|
1573
|
+
"state": "readable",
|
|
1574
|
+
"since": "0.1.0",
|
|
1575
|
+
"summary": "Inline navigation link.",
|
|
1576
|
+
"docsHref": "/docs/components/link",
|
|
1577
|
+
"rawHref": "/docs/components/link.md",
|
|
1578
|
+
"propCount": 7,
|
|
1579
|
+
"exampleCount": 1,
|
|
1580
|
+
"props": {
|
|
1581
|
+
"href": {
|
|
1582
|
+
"type": "string",
|
|
1583
|
+
"description": "Target URL."
|
|
1584
|
+
},
|
|
1585
|
+
"text": {
|
|
1586
|
+
"type": "string",
|
|
1587
|
+
"dynamic": true,
|
|
1588
|
+
"description": "Visible link text."
|
|
1589
|
+
},
|
|
1590
|
+
"label": {
|
|
1591
|
+
"type": "string",
|
|
1592
|
+
"dynamic": true,
|
|
1593
|
+
"description": "Alias for text."
|
|
1594
|
+
},
|
|
1595
|
+
"content": {
|
|
1596
|
+
"type": "string",
|
|
1597
|
+
"dynamic": true,
|
|
1598
|
+
"description": "Alias for text."
|
|
1599
|
+
},
|
|
1600
|
+
"icon": {
|
|
1601
|
+
"type": "string",
|
|
1602
|
+
"description": "Icon name shown before link text."
|
|
1603
|
+
},
|
|
1604
|
+
"target": {
|
|
1605
|
+
"type": "string",
|
|
1606
|
+
"description": "Native link target attribute."
|
|
1607
|
+
},
|
|
1608
|
+
"variant": {
|
|
1609
|
+
"type": "string",
|
|
1610
|
+
"values": [
|
|
1611
|
+
"default",
|
|
1612
|
+
"muted"
|
|
1613
|
+
],
|
|
1614
|
+
"default": "default",
|
|
1615
|
+
"description": "Link visual variant."
|
|
1616
|
+
}
|
|
1617
|
+
},
|
|
1618
|
+
"children": {
|
|
1619
|
+
"allowed": false,
|
|
1620
|
+
"description": "This component does not render nested child components."
|
|
1621
|
+
},
|
|
1622
|
+
"examples": [
|
|
1623
|
+
{
|
|
1624
|
+
"id": "basic",
|
|
1625
|
+
"title": "Basic usage",
|
|
1626
|
+
"source": {
|
|
1627
|
+
"slex": "0.1",
|
|
1628
|
+
"namespace": "doc_link_typical",
|
|
1629
|
+
"layout": {
|
|
1630
|
+
"column:links": {
|
|
1631
|
+
"link:docs": {
|
|
1632
|
+
"href": "/components",
|
|
1633
|
+
"icon": "arrow-square-out",
|
|
1634
|
+
"text": "View components"
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
],
|
|
1641
|
+
"hash": "1404518b"
|
|
1642
|
+
},
|
|
1643
|
+
{
|
|
1644
|
+
"type": "playground",
|
|
1645
|
+
"title": "Playground",
|
|
1646
|
+
"category": "Tooling",
|
|
1647
|
+
"status": "ready",
|
|
1648
|
+
"state": "none",
|
|
1649
|
+
"since": "0.1.0",
|
|
1650
|
+
"summary": "Interactive source preview.",
|
|
1651
|
+
"docsHref": "/docs/components/playground",
|
|
1652
|
+
"rawHref": "/docs/components/playground.md",
|
|
1653
|
+
"propCount": 18,
|
|
1654
|
+
"exampleCount": 1,
|
|
1655
|
+
"props": {
|
|
1656
|
+
"source": {
|
|
1657
|
+
"type": "object | string",
|
|
1658
|
+
"description": "SlexKit or Markdown source to preview."
|
|
1659
|
+
},
|
|
1660
|
+
"sourceType": {
|
|
1661
|
+
"type": "string",
|
|
1662
|
+
"values": [
|
|
1663
|
+
"slex",
|
|
1664
|
+
"markdown",
|
|
1665
|
+
"auto-markdown"
|
|
1666
|
+
],
|
|
1667
|
+
"default": "slex",
|
|
1668
|
+
"description": "Source parser mode."
|
|
1669
|
+
},
|
|
1670
|
+
"title": {
|
|
1671
|
+
"type": "string",
|
|
1672
|
+
"description": "Playground title."
|
|
1673
|
+
},
|
|
1674
|
+
"previewAlign": {
|
|
1675
|
+
"type": "string",
|
|
1676
|
+
"values": [
|
|
1677
|
+
"center",
|
|
1678
|
+
"start"
|
|
1679
|
+
],
|
|
1680
|
+
"default": "center",
|
|
1681
|
+
"description": "Vertical preview alignment in render mode."
|
|
1682
|
+
},
|
|
1683
|
+
"alignPreview": {
|
|
1684
|
+
"type": "string",
|
|
1685
|
+
"values": [
|
|
1686
|
+
"center",
|
|
1687
|
+
"start"
|
|
1688
|
+
],
|
|
1689
|
+
"description": "Alias for previewAlign."
|
|
1690
|
+
},
|
|
1691
|
+
"previewPlacement": {
|
|
1692
|
+
"type": "string",
|
|
1693
|
+
"values": [
|
|
1694
|
+
"center",
|
|
1695
|
+
"start"
|
|
1696
|
+
],
|
|
1697
|
+
"description": "Alias for previewAlign."
|
|
1698
|
+
},
|
|
1699
|
+
"previewMinHeight": {
|
|
1700
|
+
"type": "string",
|
|
1701
|
+
"description": "Minimum preview area height."
|
|
1702
|
+
},
|
|
1703
|
+
"previewMaxWidth": {
|
|
1704
|
+
"type": "string",
|
|
1705
|
+
"description": "Maximum preview content width."
|
|
1706
|
+
},
|
|
1707
|
+
"themeToggle": {
|
|
1708
|
+
"type": "boolean",
|
|
1709
|
+
"default": false,
|
|
1710
|
+
"description": "Show the theme toggle action."
|
|
1711
|
+
},
|
|
1712
|
+
"showThemeToggle": {
|
|
1713
|
+
"type": "boolean",
|
|
1714
|
+
"default": false,
|
|
1715
|
+
"description": "Alias for themeToggle."
|
|
1716
|
+
},
|
|
1717
|
+
"enableThemeToggle": {
|
|
1718
|
+
"type": "boolean",
|
|
1719
|
+
"default": false,
|
|
1720
|
+
"description": "Alias for themeToggle."
|
|
1721
|
+
},
|
|
1722
|
+
"themeLabel": {
|
|
1723
|
+
"type": "string",
|
|
1724
|
+
"description": "Accessible label for the theme toggle action."
|
|
1725
|
+
},
|
|
1726
|
+
"themeToggleLabel": {
|
|
1727
|
+
"type": "string",
|
|
1728
|
+
"description": "Alias for themeLabel."
|
|
1729
|
+
},
|
|
1730
|
+
"sourceTypeLabel": {
|
|
1731
|
+
"type": "string",
|
|
1732
|
+
"description": "Accessible label for the source type selector."
|
|
1733
|
+
},
|
|
1734
|
+
"copyLabel": {
|
|
1735
|
+
"type": "string",
|
|
1736
|
+
"description": "Accessible label for the copy source action."
|
|
1737
|
+
},
|
|
1738
|
+
"openWebLabel": {
|
|
1739
|
+
"type": "string",
|
|
1740
|
+
"description": "Accessible label for opening the source in the standalone playground."
|
|
1741
|
+
},
|
|
1742
|
+
"webUrl": {
|
|
1743
|
+
"type": "string",
|
|
1744
|
+
"description": "Standalone playground URL used by the open action."
|
|
1745
|
+
},
|
|
1746
|
+
"playgroundUrl": {
|
|
1747
|
+
"type": "string",
|
|
1748
|
+
"description": "Alias for webUrl."
|
|
1749
|
+
}
|
|
1750
|
+
},
|
|
1751
|
+
"children": {
|
|
1752
|
+
"allowed": false,
|
|
1753
|
+
"description": "This component does not render nested child components."
|
|
1754
|
+
},
|
|
1755
|
+
"examples": [
|
|
1756
|
+
{
|
|
1757
|
+
"id": "basic",
|
|
1758
|
+
"title": "Basic usage",
|
|
1759
|
+
"source": {
|
|
1760
|
+
"slex": "0.1",
|
|
1761
|
+
"namespace": "doc_playground_typical",
|
|
1762
|
+
"layout": {
|
|
1763
|
+
"playground:demo": {
|
|
1764
|
+
"title": "Stat Playground",
|
|
1765
|
+
"previewMinHeight": "180px",
|
|
1766
|
+
"source": {
|
|
1767
|
+
"namespace": "inner_stat_demo",
|
|
1768
|
+
"layout": {
|
|
1769
|
+
"stat:value": {
|
|
1770
|
+
"label": "Requests",
|
|
1771
|
+
"value": "1.2k",
|
|
1772
|
+
"unit": "/min"
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
],
|
|
1781
|
+
"hash": "7d8e1d36"
|
|
1782
|
+
},
|
|
1783
|
+
{
|
|
1784
|
+
"type": "progress",
|
|
1785
|
+
"title": "Progress",
|
|
1786
|
+
"category": "Feedback",
|
|
1787
|
+
"status": "ready",
|
|
1788
|
+
"state": "readable",
|
|
1789
|
+
"since": "0.1.0",
|
|
1790
|
+
"summary": "Progress bar.",
|
|
1791
|
+
"docsHref": "/docs/components/progress",
|
|
1792
|
+
"rawHref": "/docs/components/progress.md",
|
|
1793
|
+
"propCount": 4,
|
|
1794
|
+
"exampleCount": 1,
|
|
1795
|
+
"props": {
|
|
1796
|
+
"value": {
|
|
1797
|
+
"type": "number",
|
|
1798
|
+
"default": 0,
|
|
1799
|
+
"dynamic": true,
|
|
1800
|
+
"description": "Progress percentage from 0 to 100."
|
|
1801
|
+
},
|
|
1802
|
+
"label": {
|
|
1803
|
+
"type": "string",
|
|
1804
|
+
"dynamic": true,
|
|
1805
|
+
"description": "Progress label."
|
|
1806
|
+
},
|
|
1807
|
+
"icon": {
|
|
1808
|
+
"type": "string",
|
|
1809
|
+
"description": "Icon name shown before the label."
|
|
1810
|
+
},
|
|
1811
|
+
"indeterminate": {
|
|
1812
|
+
"type": "boolean",
|
|
1813
|
+
"default": false,
|
|
1814
|
+
"dynamic": true,
|
|
1815
|
+
"description": "Render an indeterminate progress state without aria-valuenow."
|
|
1816
|
+
}
|
|
1817
|
+
},
|
|
1818
|
+
"children": {
|
|
1819
|
+
"allowed": false,
|
|
1820
|
+
"description": "This component does not render nested child components."
|
|
1821
|
+
},
|
|
1822
|
+
"examples": [
|
|
1823
|
+
{
|
|
1824
|
+
"id": "basic",
|
|
1825
|
+
"title": "Basic usage",
|
|
1826
|
+
"source": {
|
|
1827
|
+
"slex": "0.1",
|
|
1828
|
+
"namespace": "doc_progress_typical",
|
|
1829
|
+
"layout": {
|
|
1830
|
+
"progress:build": {
|
|
1831
|
+
"label": "Build progress",
|
|
1832
|
+
"icon": "gear-six",
|
|
1833
|
+
"value": 64
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
],
|
|
1839
|
+
"hash": "706fde5e"
|
|
1840
|
+
},
|
|
1841
|
+
{
|
|
1842
|
+
"type": "radio-group",
|
|
1843
|
+
"title": "Radio Group",
|
|
1844
|
+
"category": "Input",
|
|
1845
|
+
"status": "ready",
|
|
1846
|
+
"state": "value",
|
|
1847
|
+
"since": "0.1.0",
|
|
1848
|
+
"summary": "Single-choice option group.",
|
|
1849
|
+
"docsHref": "/docs/components/radio-group",
|
|
1850
|
+
"rawHref": "/docs/components/radio-group.md",
|
|
1851
|
+
"propCount": 11,
|
|
1852
|
+
"exampleCount": 1,
|
|
1853
|
+
"props": {
|
|
1854
|
+
"value": {
|
|
1855
|
+
"type": "string",
|
|
1856
|
+
"dynamic": true,
|
|
1857
|
+
"description": "Current selected value."
|
|
1858
|
+
},
|
|
1859
|
+
"label": {
|
|
1860
|
+
"type": "string",
|
|
1861
|
+
"dynamic": true,
|
|
1862
|
+
"description": "Group label."
|
|
1863
|
+
},
|
|
1864
|
+
"icon": {
|
|
1865
|
+
"type": "string",
|
|
1866
|
+
"description": "Icon name shown before the group label."
|
|
1867
|
+
},
|
|
1868
|
+
"options": {
|
|
1869
|
+
"type": "array",
|
|
1870
|
+
"description": "Options with label, value, and optional icon."
|
|
1871
|
+
},
|
|
1872
|
+
"options[].icon": {
|
|
1873
|
+
"type": "string",
|
|
1874
|
+
"description": "Icon name shown before a single option label."
|
|
1875
|
+
},
|
|
1876
|
+
"disabled": {
|
|
1877
|
+
"type": "boolean",
|
|
1878
|
+
"default": false,
|
|
1879
|
+
"dynamic": true,
|
|
1880
|
+
"description": "Disable every radio option in the group."
|
|
1881
|
+
},
|
|
1882
|
+
"orientation": {
|
|
1883
|
+
"type": "string",
|
|
1884
|
+
"values": [
|
|
1885
|
+
"vertical",
|
|
1886
|
+
"horizontal"
|
|
1887
|
+
],
|
|
1888
|
+
"default": "vertical",
|
|
1889
|
+
"description": "Radio option layout direction."
|
|
1890
|
+
},
|
|
1891
|
+
"haptic": {
|
|
1892
|
+
"type": "boolean",
|
|
1893
|
+
"default": true,
|
|
1894
|
+
"description": "Enable vibration feedback on supported devices."
|
|
1895
|
+
},
|
|
1896
|
+
"haptics": {
|
|
1897
|
+
"type": "boolean",
|
|
1898
|
+
"default": true,
|
|
1899
|
+
"description": "Alias for haptic."
|
|
1900
|
+
},
|
|
1901
|
+
"name": {
|
|
1902
|
+
"type": "string",
|
|
1903
|
+
"description": "Native radio group name shared by options."
|
|
1904
|
+
},
|
|
1905
|
+
"onchange": {
|
|
1906
|
+
"type": "write-expression",
|
|
1907
|
+
"description": "Write expression invoked when selection changes."
|
|
1908
|
+
}
|
|
1909
|
+
},
|
|
1910
|
+
"children": {
|
|
1911
|
+
"allowed": false,
|
|
1912
|
+
"description": "This component does not render nested child components."
|
|
1913
|
+
},
|
|
1914
|
+
"examples": [
|
|
1915
|
+
{
|
|
1916
|
+
"id": "basic",
|
|
1917
|
+
"title": "Basic usage",
|
|
1918
|
+
"source": {
|
|
1919
|
+
"slex": "0.1",
|
|
1920
|
+
"namespace": "doc_radio_group_typical",
|
|
1921
|
+
"layout": {
|
|
1922
|
+
"radio-group:mode": {
|
|
1923
|
+
"label": "Mode",
|
|
1924
|
+
"icon": "sliders-horizontal",
|
|
1925
|
+
"value": "auto",
|
|
1926
|
+
"options": [
|
|
1927
|
+
{
|
|
1928
|
+
"label": "Auto",
|
|
1929
|
+
"value": "auto",
|
|
1930
|
+
"icon": "sparkle"
|
|
1931
|
+
},
|
|
1932
|
+
{
|
|
1933
|
+
"label": "Manual",
|
|
1934
|
+
"value": "manual",
|
|
1935
|
+
"icon": "wrench"
|
|
1936
|
+
}
|
|
1937
|
+
]
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
],
|
|
1943
|
+
"hash": "66c04b44"
|
|
1944
|
+
},
|
|
1945
|
+
{
|
|
1946
|
+
"type": "row",
|
|
1947
|
+
"title": "Row",
|
|
1948
|
+
"category": "Layout",
|
|
1949
|
+
"status": "ready",
|
|
1950
|
+
"state": "none",
|
|
1951
|
+
"since": "0.1.0",
|
|
1952
|
+
"summary": "Horizontal layout container.",
|
|
1953
|
+
"docsHref": "/docs/components/row",
|
|
1954
|
+
"rawHref": "/docs/components/row.md",
|
|
1955
|
+
"propCount": 3,
|
|
1956
|
+
"exampleCount": 1,
|
|
1957
|
+
"props": {
|
|
1958
|
+
"justify": {
|
|
1959
|
+
"type": "string",
|
|
1960
|
+
"values": [
|
|
1961
|
+
"start",
|
|
1962
|
+
"center",
|
|
1963
|
+
"end",
|
|
1964
|
+
"space-between",
|
|
1965
|
+
"space-around"
|
|
1966
|
+
],
|
|
1967
|
+
"default": "start",
|
|
1968
|
+
"description": "Main-axis distribution."
|
|
1969
|
+
},
|
|
1970
|
+
"align": {
|
|
1971
|
+
"type": "string",
|
|
1972
|
+
"values": [
|
|
1973
|
+
"start",
|
|
1974
|
+
"center",
|
|
1975
|
+
"end",
|
|
1976
|
+
"baseline",
|
|
1977
|
+
"stretch"
|
|
1978
|
+
],
|
|
1979
|
+
"default": "center",
|
|
1980
|
+
"description": "Cross-axis alignment."
|
|
1981
|
+
},
|
|
1982
|
+
"gap": {
|
|
1983
|
+
"type": "string",
|
|
1984
|
+
"dynamic": true,
|
|
1985
|
+
"description": "Spacing between children."
|
|
1986
|
+
}
|
|
1987
|
+
},
|
|
1988
|
+
"children": {
|
|
1989
|
+
"allowed": true,
|
|
1990
|
+
"description": "Nested component fields are rendered as child content in field order."
|
|
1991
|
+
},
|
|
1992
|
+
"examples": [
|
|
1993
|
+
{
|
|
1994
|
+
"id": "basic",
|
|
1995
|
+
"title": "Basic usage",
|
|
1996
|
+
"source": {
|
|
1997
|
+
"slex": "0.1",
|
|
1998
|
+
"namespace": "doc_row_typical",
|
|
1999
|
+
"layout": {
|
|
2000
|
+
"row:toolbar": {
|
|
2001
|
+
"justify": "space-between",
|
|
2002
|
+
"text:title": {
|
|
2003
|
+
"text": "Runtime status"
|
|
2004
|
+
},
|
|
2005
|
+
"button:refresh": {
|
|
2006
|
+
"label": "Refresh"
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
],
|
|
2013
|
+
"hash": "6c9327b6"
|
|
2014
|
+
},
|
|
2015
|
+
{
|
|
2016
|
+
"type": "section",
|
|
2017
|
+
"title": "Section",
|
|
2018
|
+
"category": "Content",
|
|
2019
|
+
"status": "ready",
|
|
2020
|
+
"state": "readable",
|
|
2021
|
+
"since": "0.1.0",
|
|
2022
|
+
"summary": "Page section with optional heading chrome.",
|
|
2023
|
+
"docsHref": "/docs/components/section",
|
|
2024
|
+
"rawHref": "/docs/components/section.md",
|
|
2025
|
+
"propCount": 6,
|
|
2026
|
+
"exampleCount": 1,
|
|
2027
|
+
"props": {
|
|
2028
|
+
"title": {
|
|
2029
|
+
"type": "string",
|
|
2030
|
+
"dynamic": true,
|
|
2031
|
+
"description": "Section title."
|
|
2032
|
+
},
|
|
2033
|
+
"icon": {
|
|
2034
|
+
"type": "string",
|
|
2035
|
+
"description": "Icon name shown before the title."
|
|
2036
|
+
},
|
|
2037
|
+
"eyebrow": {
|
|
2038
|
+
"type": "string",
|
|
2039
|
+
"dynamic": true,
|
|
2040
|
+
"description": "Small label above the title."
|
|
2041
|
+
},
|
|
2042
|
+
"subtitle": {
|
|
2043
|
+
"type": "string",
|
|
2044
|
+
"dynamic": true,
|
|
2045
|
+
"description": "Subtitle text below the title."
|
|
2046
|
+
},
|
|
2047
|
+
"actionLabel": {
|
|
2048
|
+
"type": "string",
|
|
2049
|
+
"dynamic": true,
|
|
2050
|
+
"description": "Optional action link label."
|
|
2051
|
+
},
|
|
2052
|
+
"actionHref": {
|
|
2053
|
+
"type": "string",
|
|
2054
|
+
"description": "Optional action link target."
|
|
2055
|
+
}
|
|
2056
|
+
},
|
|
2057
|
+
"children": {
|
|
2058
|
+
"allowed": true,
|
|
2059
|
+
"description": "Nested component fields are rendered as child content in field order."
|
|
2060
|
+
},
|
|
2061
|
+
"examples": [
|
|
2062
|
+
{
|
|
2063
|
+
"id": "basic",
|
|
2064
|
+
"title": "Basic usage",
|
|
2065
|
+
"source": {
|
|
2066
|
+
"slex": "0.1",
|
|
2067
|
+
"namespace": "doc_section_typical",
|
|
2068
|
+
"layout": {
|
|
2069
|
+
"section:overview": {
|
|
2070
|
+
"eyebrow": "Dashboard",
|
|
2071
|
+
"title": "Runtime overview",
|
|
2072
|
+
"icon": "chart-bar",
|
|
2073
|
+
"subtitle": "This section groups the most important state.",
|
|
2074
|
+
"stat:latency": {
|
|
2075
|
+
"label": "Latency",
|
|
2076
|
+
"value": "42",
|
|
2077
|
+
"unit": "ms"
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
],
|
|
2084
|
+
"hash": "d2fe0297"
|
|
2085
|
+
},
|
|
2086
|
+
{
|
|
2087
|
+
"type": "select",
|
|
2088
|
+
"title": "Select",
|
|
2089
|
+
"category": "Input",
|
|
2090
|
+
"status": "ready",
|
|
2091
|
+
"state": "value",
|
|
2092
|
+
"since": "0.1.0",
|
|
2093
|
+
"summary": "Dropdown selection input.",
|
|
2094
|
+
"docsHref": "/docs/components/select",
|
|
2095
|
+
"rawHref": "/docs/components/select.md",
|
|
2096
|
+
"propCount": 10,
|
|
2097
|
+
"exampleCount": 1,
|
|
2098
|
+
"props": {
|
|
2099
|
+
"label": {
|
|
2100
|
+
"type": "string",
|
|
2101
|
+
"dynamic": true,
|
|
2102
|
+
"description": "Select label."
|
|
2103
|
+
},
|
|
2104
|
+
"icon": {
|
|
2105
|
+
"type": "string",
|
|
2106
|
+
"description": "Icon name shown before the top label."
|
|
2107
|
+
},
|
|
2108
|
+
"value": {
|
|
2109
|
+
"type": "string",
|
|
2110
|
+
"dynamic": true,
|
|
2111
|
+
"description": "Current selected value."
|
|
2112
|
+
},
|
|
2113
|
+
"options": {
|
|
2114
|
+
"type": "array",
|
|
2115
|
+
"description": "Options with label, value, and optional icon."
|
|
2116
|
+
},
|
|
2117
|
+
"options[].icon": {
|
|
2118
|
+
"type": "string",
|
|
2119
|
+
"description": "Icon name shown before an option label."
|
|
2120
|
+
},
|
|
2121
|
+
"placeholder": {
|
|
2122
|
+
"type": "string",
|
|
2123
|
+
"description": "Placeholder shown when no value is selected."
|
|
2124
|
+
},
|
|
2125
|
+
"disabled": {
|
|
2126
|
+
"type": "boolean",
|
|
2127
|
+
"default": false,
|
|
2128
|
+
"dynamic": true,
|
|
2129
|
+
"description": "Disable the select trigger and native select."
|
|
2130
|
+
},
|
|
2131
|
+
"required": {
|
|
2132
|
+
"type": "boolean",
|
|
2133
|
+
"default": false,
|
|
2134
|
+
"dynamic": true,
|
|
2135
|
+
"description": "Require a non-placeholder value in the native select."
|
|
2136
|
+
},
|
|
2137
|
+
"variant": {
|
|
2138
|
+
"type": "string",
|
|
2139
|
+
"values": [
|
|
2140
|
+
"default",
|
|
2141
|
+
"toolbar"
|
|
2142
|
+
],
|
|
2143
|
+
"default": "default",
|
|
2144
|
+
"description": "Select surface variant."
|
|
2145
|
+
},
|
|
2146
|
+
"onchange": {
|
|
2147
|
+
"type": "write-expression",
|
|
2148
|
+
"description": "Write expression invoked when selection changes."
|
|
2149
|
+
}
|
|
2150
|
+
},
|
|
2151
|
+
"children": {
|
|
2152
|
+
"allowed": false,
|
|
2153
|
+
"description": "This component does not render nested child components."
|
|
2154
|
+
},
|
|
2155
|
+
"examples": [
|
|
2156
|
+
{
|
|
2157
|
+
"id": "basic",
|
|
2158
|
+
"title": "Basic usage",
|
|
2159
|
+
"source": {
|
|
2160
|
+
"slex": "0.1",
|
|
2161
|
+
"namespace": "doc_select_typical",
|
|
2162
|
+
"layout": {
|
|
2163
|
+
"select:env": {
|
|
2164
|
+
"label": "Environment",
|
|
2165
|
+
"icon": "server",
|
|
2166
|
+
"value": "prod",
|
|
2167
|
+
"options": [
|
|
2168
|
+
{
|
|
2169
|
+
"label": "Development",
|
|
2170
|
+
"value": "dev",
|
|
2171
|
+
"icon": "code"
|
|
2172
|
+
},
|
|
2173
|
+
{
|
|
2174
|
+
"label": "Production",
|
|
2175
|
+
"value": "prod",
|
|
2176
|
+
"icon": "rocket-launch"
|
|
2177
|
+
}
|
|
2178
|
+
]
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
],
|
|
2184
|
+
"hash": "0636d6dd"
|
|
2185
|
+
},
|
|
2186
|
+
{
|
|
2187
|
+
"type": "slider",
|
|
2188
|
+
"title": "Slider",
|
|
2189
|
+
"category": "Input",
|
|
2190
|
+
"status": "ready",
|
|
2191
|
+
"state": "value",
|
|
2192
|
+
"since": "0.1.0",
|
|
2193
|
+
"summary": "Numeric range input.",
|
|
2194
|
+
"docsHref": "/docs/components/slider",
|
|
2195
|
+
"rawHref": "/docs/components/slider.md",
|
|
2196
|
+
"propCount": 12,
|
|
2197
|
+
"exampleCount": 1,
|
|
2198
|
+
"props": {
|
|
2199
|
+
"label": {
|
|
2200
|
+
"type": "string",
|
|
2201
|
+
"dynamic": true,
|
|
2202
|
+
"description": "Slider label."
|
|
2203
|
+
},
|
|
2204
|
+
"icon": {
|
|
2205
|
+
"type": "string",
|
|
2206
|
+
"description": "Icon name shown before the label."
|
|
2207
|
+
},
|
|
2208
|
+
"value": {
|
|
2209
|
+
"type": "number",
|
|
2210
|
+
"default": 0,
|
|
2211
|
+
"dynamic": true,
|
|
2212
|
+
"description": "Current numeric value."
|
|
2213
|
+
},
|
|
2214
|
+
"min": {
|
|
2215
|
+
"type": "number",
|
|
2216
|
+
"default": 0,
|
|
2217
|
+
"dynamic": true,
|
|
2218
|
+
"description": "Minimum value."
|
|
2219
|
+
},
|
|
2220
|
+
"max": {
|
|
2221
|
+
"type": "number",
|
|
2222
|
+
"default": 100,
|
|
2223
|
+
"dynamic": true,
|
|
2224
|
+
"description": "Maximum value."
|
|
2225
|
+
},
|
|
2226
|
+
"step": {
|
|
2227
|
+
"type": "number",
|
|
2228
|
+
"default": 1,
|
|
2229
|
+
"dynamic": true,
|
|
2230
|
+
"description": "Step interval."
|
|
2231
|
+
},
|
|
2232
|
+
"unit": {
|
|
2233
|
+
"type": "string",
|
|
2234
|
+
"dynamic": true,
|
|
2235
|
+
"description": "Unit shown after the value."
|
|
2236
|
+
},
|
|
2237
|
+
"disabled": {
|
|
2238
|
+
"type": "boolean",
|
|
2239
|
+
"default": false,
|
|
2240
|
+
"dynamic": true,
|
|
2241
|
+
"description": "Disable the range input."
|
|
2242
|
+
},
|
|
2243
|
+
"orientation": {
|
|
2244
|
+
"type": "string",
|
|
2245
|
+
"values": [
|
|
2246
|
+
"horizontal",
|
|
2247
|
+
"vertical"
|
|
2248
|
+
],
|
|
2249
|
+
"default": "horizontal",
|
|
2250
|
+
"description": "Slider orientation metadata used for styling."
|
|
2251
|
+
},
|
|
2252
|
+
"haptic": {
|
|
2253
|
+
"type": "boolean",
|
|
2254
|
+
"default": true,
|
|
2255
|
+
"description": "Enable vibration feedback on supported devices."
|
|
2256
|
+
},
|
|
2257
|
+
"haptics": {
|
|
2258
|
+
"type": "boolean",
|
|
2259
|
+
"default": true,
|
|
2260
|
+
"description": "Alias for haptic."
|
|
2261
|
+
},
|
|
2262
|
+
"onchange": {
|
|
2263
|
+
"type": "write-expression",
|
|
2264
|
+
"description": "Write expression invoked when the value changes."
|
|
2265
|
+
}
|
|
2266
|
+
},
|
|
2267
|
+
"children": {
|
|
2268
|
+
"allowed": false,
|
|
2269
|
+
"description": "This component does not render nested child components."
|
|
2270
|
+
},
|
|
2271
|
+
"examples": [
|
|
2272
|
+
{
|
|
2273
|
+
"id": "basic",
|
|
2274
|
+
"title": "Basic usage",
|
|
2275
|
+
"source": {
|
|
2276
|
+
"slex": "0.1",
|
|
2277
|
+
"namespace": "doc_slider_typical",
|
|
2278
|
+
"layout": {
|
|
2279
|
+
"slider:volume": {
|
|
2280
|
+
"label": "Volume",
|
|
2281
|
+
"icon": "speaker-high",
|
|
2282
|
+
"value": 42,
|
|
2283
|
+
"min": 0,
|
|
2284
|
+
"max": 100,
|
|
2285
|
+
"step": 1,
|
|
2286
|
+
"unit": "%"
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
],
|
|
2292
|
+
"hash": "490f7f36"
|
|
2293
|
+
},
|
|
2294
|
+
{
|
|
2295
|
+
"type": "stat",
|
|
2296
|
+
"title": "Stat",
|
|
2297
|
+
"category": "Display",
|
|
2298
|
+
"status": "ready",
|
|
2299
|
+
"state": "readable",
|
|
2300
|
+
"since": "0.1.0",
|
|
2301
|
+
"summary": "Metric display.",
|
|
2302
|
+
"docsHref": "/docs/components/stat",
|
|
2303
|
+
"rawHref": "/docs/components/stat.md",
|
|
2304
|
+
"propCount": 6,
|
|
2305
|
+
"exampleCount": 1,
|
|
2306
|
+
"props": {
|
|
2307
|
+
"label": {
|
|
2308
|
+
"type": "string",
|
|
2309
|
+
"dynamic": true,
|
|
2310
|
+
"description": "Metric label."
|
|
2311
|
+
},
|
|
2312
|
+
"icon": {
|
|
2313
|
+
"type": "string",
|
|
2314
|
+
"description": "Icon name shown before the label."
|
|
2315
|
+
},
|
|
2316
|
+
"value": {
|
|
2317
|
+
"type": "string | number",
|
|
2318
|
+
"dynamic": true,
|
|
2319
|
+
"description": "Metric value."
|
|
2320
|
+
},
|
|
2321
|
+
"unit": {
|
|
2322
|
+
"type": "string",
|
|
2323
|
+
"dynamic": true,
|
|
2324
|
+
"description": "Unit shown after the value."
|
|
2325
|
+
},
|
|
2326
|
+
"tone": {
|
|
2327
|
+
"type": "string",
|
|
2328
|
+
"values": [
|
|
2329
|
+
"info",
|
|
2330
|
+
"success",
|
|
2331
|
+
"warning",
|
|
2332
|
+
"danger",
|
|
2333
|
+
"muted"
|
|
2334
|
+
],
|
|
2335
|
+
"description": "Optional semantic tone."
|
|
2336
|
+
},
|
|
2337
|
+
"animateInitial": {
|
|
2338
|
+
"type": "boolean",
|
|
2339
|
+
"default": false,
|
|
2340
|
+
"description": "Animate the initial rendered value."
|
|
2341
|
+
}
|
|
2342
|
+
},
|
|
2343
|
+
"children": {
|
|
2344
|
+
"allowed": false,
|
|
2345
|
+
"description": "This component does not render nested child components."
|
|
2346
|
+
},
|
|
2347
|
+
"examples": [
|
|
2348
|
+
{
|
|
2349
|
+
"id": "basic",
|
|
2350
|
+
"title": "Basic usage",
|
|
2351
|
+
"source": {
|
|
2352
|
+
"slex": "0.1",
|
|
2353
|
+
"namespace": "doc_stat_typical",
|
|
2354
|
+
"layout": {
|
|
2355
|
+
"grid:stats": {
|
|
2356
|
+
"columns": 2,
|
|
2357
|
+
"stat:requests": {
|
|
2358
|
+
"label": "Requests",
|
|
2359
|
+
"icon": "activity",
|
|
2360
|
+
"value": "1.2k",
|
|
2361
|
+
"unit": "/min"
|
|
2362
|
+
},
|
|
2363
|
+
"stat:success": {
|
|
2364
|
+
"label": "Success",
|
|
2365
|
+
"icon": "check-circle",
|
|
2366
|
+
"value": "98.4",
|
|
2367
|
+
"unit": "%",
|
|
2368
|
+
"tone": "success"
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
],
|
|
2375
|
+
"hash": "cd525fc5"
|
|
2376
|
+
},
|
|
2377
|
+
{
|
|
2378
|
+
"type": "submit",
|
|
2379
|
+
"title": "Submit",
|
|
2380
|
+
"category": "Action",
|
|
2381
|
+
"status": "ready",
|
|
2382
|
+
"state": "none",
|
|
2383
|
+
"since": "0.1.0",
|
|
2384
|
+
"summary": "ToolHost submit and ignore controls.",
|
|
2385
|
+
"docsHref": "/docs/components/submit",
|
|
2386
|
+
"rawHref": "/docs/components/submit.md",
|
|
2387
|
+
"propCount": 4,
|
|
2388
|
+
"exampleCount": 1,
|
|
2389
|
+
"props": {
|
|
2390
|
+
"submitLabel": {
|
|
2391
|
+
"type": "string",
|
|
2392
|
+
"default": "Submit",
|
|
2393
|
+
"description": "Submit button text."
|
|
2394
|
+
},
|
|
2395
|
+
"ignoreLabel": {
|
|
2396
|
+
"type": "string",
|
|
2397
|
+
"default": "Ignore",
|
|
2398
|
+
"description": "Ignore button text."
|
|
2399
|
+
},
|
|
2400
|
+
"returnKeys": {
|
|
2401
|
+
"type": "string[]",
|
|
2402
|
+
"description": "State field paths returned to ToolHost."
|
|
2403
|
+
},
|
|
2404
|
+
"disabled": {
|
|
2405
|
+
"type": "boolean",
|
|
2406
|
+
"default": false,
|
|
2407
|
+
"dynamic": true,
|
|
2408
|
+
"description": "Disable submit action."
|
|
2409
|
+
}
|
|
2410
|
+
},
|
|
2411
|
+
"children": {
|
|
2412
|
+
"allowed": false,
|
|
2413
|
+
"description": "This component does not render nested child components."
|
|
2414
|
+
},
|
|
2415
|
+
"examples": [
|
|
2416
|
+
{
|
|
2417
|
+
"id": "basic",
|
|
2418
|
+
"title": "Basic usage",
|
|
2419
|
+
"source": {
|
|
2420
|
+
"slex": "0.1",
|
|
2421
|
+
"namespace": "doc_submit_typical",
|
|
2422
|
+
"layout": {
|
|
2423
|
+
"column:tool": {
|
|
2424
|
+
"input:title": {
|
|
2425
|
+
"value": "Release note",
|
|
2426
|
+
"placeholder": "Title"
|
|
2427
|
+
},
|
|
2428
|
+
"submit:done": {
|
|
2429
|
+
"submitLabel": "Submit",
|
|
2430
|
+
"ignoreLabel": "Ignore",
|
|
2431
|
+
"returnKeys": [
|
|
2432
|
+
"title"
|
|
2433
|
+
]
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
],
|
|
2440
|
+
"hash": "b3753761"
|
|
2441
|
+
},
|
|
2442
|
+
{
|
|
2443
|
+
"type": "switch",
|
|
2444
|
+
"title": "Switch",
|
|
2445
|
+
"category": "Input",
|
|
2446
|
+
"status": "ready",
|
|
2447
|
+
"state": "enabled",
|
|
2448
|
+
"since": "0.1.0",
|
|
2449
|
+
"summary": "Boolean switch input.",
|
|
2450
|
+
"docsHref": "/docs/components/switch",
|
|
2451
|
+
"rawHref": "/docs/components/switch.md",
|
|
2452
|
+
"propCount": 7,
|
|
2453
|
+
"exampleCount": 1,
|
|
2454
|
+
"props": {
|
|
2455
|
+
"enabled": {
|
|
2456
|
+
"type": "boolean",
|
|
2457
|
+
"default": false,
|
|
2458
|
+
"dynamic": true,
|
|
2459
|
+
"description": "Enabled state."
|
|
2460
|
+
},
|
|
2461
|
+
"label": {
|
|
2462
|
+
"type": "string",
|
|
2463
|
+
"dynamic": true,
|
|
2464
|
+
"description": "Switch label."
|
|
2465
|
+
},
|
|
2466
|
+
"icon": {
|
|
2467
|
+
"type": "string",
|
|
2468
|
+
"description": "Icon name shown before the visible label."
|
|
2469
|
+
},
|
|
2470
|
+
"disabled": {
|
|
2471
|
+
"type": "boolean",
|
|
2472
|
+
"default": false,
|
|
2473
|
+
"dynamic": true,
|
|
2474
|
+
"description": "Disable the switch."
|
|
2475
|
+
},
|
|
2476
|
+
"haptic": {
|
|
2477
|
+
"type": "boolean",
|
|
2478
|
+
"default": true,
|
|
2479
|
+
"description": "Enable vibration feedback on supported devices."
|
|
2480
|
+
},
|
|
2481
|
+
"haptics": {
|
|
2482
|
+
"type": "boolean",
|
|
2483
|
+
"default": true,
|
|
2484
|
+
"description": "Alias for haptic."
|
|
2485
|
+
},
|
|
2486
|
+
"onchange": {
|
|
2487
|
+
"type": "write-expression",
|
|
2488
|
+
"description": "Write expression invoked when enabled state changes."
|
|
2489
|
+
}
|
|
2490
|
+
},
|
|
2491
|
+
"children": {
|
|
2492
|
+
"allowed": false,
|
|
2493
|
+
"description": "This component does not render nested child components."
|
|
2494
|
+
},
|
|
2495
|
+
"examples": [
|
|
2496
|
+
{
|
|
2497
|
+
"id": "basic",
|
|
2498
|
+
"title": "Basic usage",
|
|
2499
|
+
"source": {
|
|
2500
|
+
"slex": "0.1",
|
|
2501
|
+
"namespace": "doc_switch_typical",
|
|
2502
|
+
"layout": {
|
|
2503
|
+
"switch:feature": {
|
|
2504
|
+
"enabled": true,
|
|
2505
|
+
"label": "Enable sync",
|
|
2506
|
+
"icon": "arrows-clockwise"
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
],
|
|
2512
|
+
"hash": "c5fd6169"
|
|
2513
|
+
},
|
|
2514
|
+
{
|
|
2515
|
+
"type": "table",
|
|
2516
|
+
"title": "Table",
|
|
2517
|
+
"category": "Data",
|
|
2518
|
+
"status": "ready",
|
|
2519
|
+
"state": "readable",
|
|
2520
|
+
"since": "0.1.0",
|
|
2521
|
+
"summary": "Simple data table.",
|
|
2522
|
+
"docsHref": "/docs/components/table",
|
|
2523
|
+
"rawHref": "/docs/components/table.md",
|
|
2524
|
+
"propCount": 4,
|
|
2525
|
+
"exampleCount": 1,
|
|
2526
|
+
"props": {
|
|
2527
|
+
"columns": {
|
|
2528
|
+
"type": "array",
|
|
2529
|
+
"description": "Column definitions with key, label, and optional icon."
|
|
2530
|
+
},
|
|
2531
|
+
"columns[].icon": {
|
|
2532
|
+
"type": "string",
|
|
2533
|
+
"description": "Icon name shown before a column label."
|
|
2534
|
+
},
|
|
2535
|
+
"rows": {
|
|
2536
|
+
"type": "array",
|
|
2537
|
+
"description": "Row data objects keyed by column key."
|
|
2538
|
+
},
|
|
2539
|
+
"items": {
|
|
2540
|
+
"type": "array",
|
|
2541
|
+
"description": "Alias for rows."
|
|
2542
|
+
}
|
|
2543
|
+
},
|
|
2544
|
+
"children": {
|
|
2545
|
+
"allowed": false,
|
|
2546
|
+
"description": "This component does not render nested child components."
|
|
2547
|
+
},
|
|
2548
|
+
"examples": [
|
|
2549
|
+
{
|
|
2550
|
+
"id": "basic",
|
|
2551
|
+
"title": "Basic usage",
|
|
2552
|
+
"source": {
|
|
2553
|
+
"slex": "0.1",
|
|
2554
|
+
"namespace": "doc_table_typical",
|
|
2555
|
+
"layout": {
|
|
2556
|
+
"table:routes": {
|
|
2557
|
+
"columns": [
|
|
2558
|
+
{
|
|
2559
|
+
"key": "name",
|
|
2560
|
+
"label": "Name",
|
|
2561
|
+
"icon": "text-t"
|
|
2562
|
+
},
|
|
2563
|
+
{
|
|
2564
|
+
"key": "status",
|
|
2565
|
+
"label": "Status",
|
|
2566
|
+
"icon": "check-circle"
|
|
2567
|
+
}
|
|
2568
|
+
],
|
|
2569
|
+
"rows": [
|
|
2570
|
+
{
|
|
2571
|
+
"name": "Parse",
|
|
2572
|
+
"status": "ready"
|
|
2573
|
+
},
|
|
2574
|
+
{
|
|
2575
|
+
"name": "Publish",
|
|
2576
|
+
"status": "pending"
|
|
2577
|
+
}
|
|
2578
|
+
]
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
],
|
|
2584
|
+
"hash": "546ee458"
|
|
2585
|
+
},
|
|
2586
|
+
{
|
|
2587
|
+
"type": "tabs",
|
|
2588
|
+
"title": "Tabs",
|
|
2589
|
+
"category": "Navigation",
|
|
2590
|
+
"status": "ready",
|
|
2591
|
+
"state": "value",
|
|
2592
|
+
"since": "0.1.0",
|
|
2593
|
+
"summary": "Tabbed view switcher.",
|
|
2594
|
+
"docsHref": "/docs/components/tabs",
|
|
2595
|
+
"rawHref": "/docs/components/tabs.md",
|
|
2596
|
+
"propCount": 6,
|
|
2597
|
+
"exampleCount": 1,
|
|
2598
|
+
"props": {
|
|
2599
|
+
"value": {
|
|
2600
|
+
"type": "string",
|
|
2601
|
+
"dynamic": true,
|
|
2602
|
+
"description": "Current active tab value."
|
|
2603
|
+
},
|
|
2604
|
+
"tabs": {
|
|
2605
|
+
"type": "array",
|
|
2606
|
+
"description": "Tab definitions with value, label, content, icon, and iconOnly."
|
|
2607
|
+
},
|
|
2608
|
+
"tabs[].icon": {
|
|
2609
|
+
"type": "string",
|
|
2610
|
+
"description": "Icon name shown before a tab trigger label."
|
|
2611
|
+
},
|
|
2612
|
+
"tabs[].iconOnly": {
|
|
2613
|
+
"type": "boolean",
|
|
2614
|
+
"description": "Show only the tab icon while retaining label as accessible text."
|
|
2615
|
+
},
|
|
2616
|
+
"orientation": {
|
|
2617
|
+
"type": "string",
|
|
2618
|
+
"values": [
|
|
2619
|
+
"horizontal",
|
|
2620
|
+
"vertical"
|
|
2621
|
+
],
|
|
2622
|
+
"default": "horizontal",
|
|
2623
|
+
"description": "Tab list orientation."
|
|
2624
|
+
},
|
|
2625
|
+
"onchange": {
|
|
2626
|
+
"type": "write-expression",
|
|
2627
|
+
"description": "Write expression invoked when the active tab changes."
|
|
2628
|
+
}
|
|
2629
|
+
},
|
|
2630
|
+
"children": {
|
|
2631
|
+
"allowed": false,
|
|
2632
|
+
"description": "This component does not render nested child components."
|
|
2633
|
+
},
|
|
2634
|
+
"examples": [
|
|
2635
|
+
{
|
|
2636
|
+
"id": "basic",
|
|
2637
|
+
"title": "Basic usage",
|
|
2638
|
+
"source": {
|
|
2639
|
+
"slex": "0.1",
|
|
2640
|
+
"namespace": "doc_tabs_typical",
|
|
2641
|
+
"layout": {
|
|
2642
|
+
"tabs:main": {
|
|
2643
|
+
"value": "overview",
|
|
2644
|
+
"tabs": [
|
|
2645
|
+
{
|
|
2646
|
+
"value": "overview",
|
|
2647
|
+
"label": "Overview"
|
|
2648
|
+
},
|
|
2649
|
+
{
|
|
2650
|
+
"value": "settings",
|
|
2651
|
+
"label": "Settings"
|
|
2652
|
+
}
|
|
2653
|
+
]
|
|
2654
|
+
}
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
],
|
|
2659
|
+
"hash": "e5cff5dc"
|
|
2660
|
+
},
|
|
2661
|
+
{
|
|
2662
|
+
"type": "text",
|
|
2663
|
+
"title": "Text",
|
|
2664
|
+
"category": "Display",
|
|
2665
|
+
"status": "ready",
|
|
2666
|
+
"state": "readable",
|
|
2667
|
+
"since": "0.1.0",
|
|
2668
|
+
"summary": "Plain text display.",
|
|
2669
|
+
"docsHref": "/docs/components/text",
|
|
2670
|
+
"rawHref": "/docs/components/text.md",
|
|
2671
|
+
"propCount": 5,
|
|
2672
|
+
"exampleCount": 1,
|
|
2673
|
+
"props": {
|
|
2674
|
+
"text": {
|
|
2675
|
+
"type": "string",
|
|
2676
|
+
"dynamic": true,
|
|
2677
|
+
"description": "Displayed text."
|
|
2678
|
+
},
|
|
2679
|
+
"content": {
|
|
2680
|
+
"type": "string",
|
|
2681
|
+
"dynamic": true,
|
|
2682
|
+
"description": "Alias for text."
|
|
2683
|
+
},
|
|
2684
|
+
"label": {
|
|
2685
|
+
"type": "string",
|
|
2686
|
+
"dynamic": true,
|
|
2687
|
+
"description": "Alias for text."
|
|
2688
|
+
},
|
|
2689
|
+
"variant": {
|
|
2690
|
+
"type": "string",
|
|
2691
|
+
"values": [
|
|
2692
|
+
"default",
|
|
2693
|
+
"muted"
|
|
2694
|
+
],
|
|
2695
|
+
"default": "default",
|
|
2696
|
+
"description": "Text visual variant."
|
|
2697
|
+
},
|
|
2698
|
+
"class": {
|
|
2699
|
+
"type": "string",
|
|
2700
|
+
"description": "Additional host-controlled CSS class."
|
|
2701
|
+
}
|
|
2702
|
+
},
|
|
2703
|
+
"children": {
|
|
2704
|
+
"allowed": false,
|
|
2705
|
+
"description": "This component does not render nested child components."
|
|
2706
|
+
},
|
|
2707
|
+
"examples": [
|
|
2708
|
+
{
|
|
2709
|
+
"id": "basic",
|
|
2710
|
+
"title": "Basic usage",
|
|
2711
|
+
"source": {
|
|
2712
|
+
"slex": "0.1",
|
|
2713
|
+
"namespace": "doc_text_typical",
|
|
2714
|
+
"layout": {
|
|
2715
|
+
"text:status": {
|
|
2716
|
+
"text": "System is healthy"
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
],
|
|
2722
|
+
"hash": "d498fd82"
|
|
2723
|
+
},
|
|
2724
|
+
{
|
|
2725
|
+
"type": "toast",
|
|
2726
|
+
"title": "Toast",
|
|
2727
|
+
"category": "Feedback",
|
|
2728
|
+
"status": "ready",
|
|
2729
|
+
"state": "none",
|
|
2730
|
+
"since": "0.1.0",
|
|
2731
|
+
"summary": "Transient notification.",
|
|
2732
|
+
"docsHref": "/docs/components/toast",
|
|
2733
|
+
"rawHref": "/docs/components/toast.md",
|
|
2734
|
+
"propCount": 15,
|
|
2735
|
+
"exampleCount": 1,
|
|
2736
|
+
"props": {
|
|
2737
|
+
"title": {
|
|
2738
|
+
"type": "string",
|
|
2739
|
+
"dynamic": true,
|
|
2740
|
+
"description": "Toast title."
|
|
2741
|
+
},
|
|
2742
|
+
"heading": {
|
|
2743
|
+
"type": "string",
|
|
2744
|
+
"dynamic": true,
|
|
2745
|
+
"description": "Alias for title."
|
|
2746
|
+
},
|
|
2747
|
+
"label": {
|
|
2748
|
+
"type": "string",
|
|
2749
|
+
"dynamic": true,
|
|
2750
|
+
"description": "Alias for title."
|
|
2751
|
+
},
|
|
2752
|
+
"icon": {
|
|
2753
|
+
"type": "string",
|
|
2754
|
+
"description": "Icon name shown at the left of the toast."
|
|
2755
|
+
},
|
|
2756
|
+
"description": {
|
|
2757
|
+
"type": "string",
|
|
2758
|
+
"dynamic": true,
|
|
2759
|
+
"description": "Toast body text."
|
|
2760
|
+
},
|
|
2761
|
+
"text": {
|
|
2762
|
+
"type": "string",
|
|
2763
|
+
"dynamic": true,
|
|
2764
|
+
"description": "Alias for description."
|
|
2765
|
+
},
|
|
2766
|
+
"message": {
|
|
2767
|
+
"type": "string",
|
|
2768
|
+
"dynamic": true,
|
|
2769
|
+
"description": "Alias for description."
|
|
2770
|
+
},
|
|
2771
|
+
"content": {
|
|
2772
|
+
"type": "string",
|
|
2773
|
+
"dynamic": true,
|
|
2774
|
+
"description": "Alias for description."
|
|
2775
|
+
},
|
|
2776
|
+
"type": {
|
|
2777
|
+
"type": "string",
|
|
2778
|
+
"values": [
|
|
2779
|
+
"info",
|
|
2780
|
+
"success",
|
|
2781
|
+
"warning",
|
|
2782
|
+
"danger"
|
|
2783
|
+
],
|
|
2784
|
+
"default": "info",
|
|
2785
|
+
"description": "Semantic notification type."
|
|
2786
|
+
},
|
|
2787
|
+
"tone": {
|
|
2788
|
+
"type": "string",
|
|
2789
|
+
"values": [
|
|
2790
|
+
"info",
|
|
2791
|
+
"success",
|
|
2792
|
+
"warning",
|
|
2793
|
+
"danger"
|
|
2794
|
+
],
|
|
2795
|
+
"default": "info",
|
|
2796
|
+
"description": "Alias for type."
|
|
2797
|
+
},
|
|
2798
|
+
"duration": {
|
|
2799
|
+
"type": "number",
|
|
2800
|
+
"description": "Auto-hide delay in milliseconds."
|
|
2801
|
+
},
|
|
2802
|
+
"dismissable": {
|
|
2803
|
+
"type": "boolean",
|
|
2804
|
+
"default": true,
|
|
2805
|
+
"description": "Show a close button."
|
|
2806
|
+
},
|
|
2807
|
+
"dismissible": {
|
|
2808
|
+
"type": "boolean",
|
|
2809
|
+
"default": true,
|
|
2810
|
+
"description": "Alias for dismissable."
|
|
2811
|
+
},
|
|
2812
|
+
"closeLabel": {
|
|
2813
|
+
"type": "string",
|
|
2814
|
+
"default": "Close notification",
|
|
2815
|
+
"description": "Accessible close button label."
|
|
2816
|
+
},
|
|
2817
|
+
"closeAriaLabel": {
|
|
2818
|
+
"type": "string",
|
|
2819
|
+
"description": "Alias for closeLabel."
|
|
2820
|
+
}
|
|
2821
|
+
},
|
|
2822
|
+
"children": {
|
|
2823
|
+
"allowed": false,
|
|
2824
|
+
"description": "This component does not render nested child components."
|
|
2825
|
+
},
|
|
2826
|
+
"examples": [
|
|
2827
|
+
{
|
|
2828
|
+
"id": "basic",
|
|
2829
|
+
"title": "Basic usage",
|
|
2830
|
+
"source": {
|
|
2831
|
+
"slex": "0.1",
|
|
2832
|
+
"namespace": "doc_toast_typical",
|
|
2833
|
+
"layout": {
|
|
2834
|
+
"toast:saved": {
|
|
2835
|
+
"type": "success",
|
|
2836
|
+
"title": "Saved",
|
|
2837
|
+
"icon": "check-circle",
|
|
2838
|
+
"description": "Changes have been written."
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
],
|
|
2844
|
+
"hash": "cc0c6b05"
|
|
2845
|
+
}
|
|
2846
|
+
],
|
|
2847
|
+
"sourceHashes": {
|
|
2848
|
+
"README.md": "e1cb682c",
|
|
2849
|
+
"site/content/guides/intro/en-US.md": "bff82366",
|
|
2850
|
+
"site/content/guides/quick-start/en-US.md": "ab0489b2",
|
|
2851
|
+
"site/content/guides/integration/en-US.md": "f3b8bc00",
|
|
2852
|
+
"site/content/guides/design/en-US.md": "8a3b35fd",
|
|
2853
|
+
"site/content/guides/security-runtime/en-US.md": "bbf1d81f",
|
|
2854
|
+
"site/content/guides/ai-agents/en-US.md": "eab33b74",
|
|
2855
|
+
"site/content/reference/spec/en-US.md": "8a8391af",
|
|
2856
|
+
"site/content/reference/usage/en-US.md": "aaac995d",
|
|
2857
|
+
"site/content/reference/runtime/en-US.md": "559e05c2",
|
|
2858
|
+
"site/content/reference/integration/en-US.md": "ac782b49",
|
|
2859
|
+
"site/content/reference/security/en-US.md": "4cfe36f1",
|
|
2860
|
+
"site/content/reference/packages/en-US.md": "79d87cbd",
|
|
2861
|
+
"site/content/reference/toolhost/en-US.md": "f62ba8aa",
|
|
2862
|
+
"site/content/reference/icons/en-US.md": "3d32cbbf",
|
|
2863
|
+
"site/content/reference/rationale/en-US.md": "808b34ec",
|
|
2864
|
+
"site/content/releases/changelog/en-US.md": "c1cbfe8c",
|
|
2865
|
+
"site/content/components/accordion/en-US.md": "9e90867f",
|
|
2866
|
+
"site/content/components/badge/en-US.md": "fb8275e7",
|
|
2867
|
+
"site/content/components/button/en-US.md": "30463322",
|
|
2868
|
+
"site/content/components/callout/en-US.md": "d16f713d",
|
|
2869
|
+
"site/content/components/card/en-US.md": "99f4bf99",
|
|
2870
|
+
"site/content/components/checkbox/en-US.md": "6d83ab0c",
|
|
2871
|
+
"site/content/components/code-block/en-US.md": "171d1695",
|
|
2872
|
+
"site/content/components/collapsible/en-US.md": "003307a3",
|
|
2873
|
+
"site/content/components/column/en-US.md": "718a5b54",
|
|
2874
|
+
"site/content/components/divider/en-US.md": "cc7df031",
|
|
2875
|
+
"site/content/components/grid/en-US.md": "07d773b2",
|
|
2876
|
+
"site/content/components/icon/en-US.md": "a8497d85",
|
|
2877
|
+
"site/content/components/input/en-US.md": "558a0288",
|
|
2878
|
+
"site/content/components/link/en-US.md": "8eeb87ad",
|
|
2879
|
+
"site/content/components/playground/en-US.md": "7313ccc4",
|
|
2880
|
+
"site/content/components/progress/en-US.md": "7d008e59",
|
|
2881
|
+
"site/content/components/radio-group/en-US.md": "c3190775",
|
|
2882
|
+
"site/content/components/row/en-US.md": "026953f5",
|
|
2883
|
+
"site/content/components/section/en-US.md": "f6df61a4",
|
|
2884
|
+
"site/content/components/select/en-US.md": "43c6a193",
|
|
2885
|
+
"site/content/components/slider/en-US.md": "b34cc3f8",
|
|
2886
|
+
"site/content/components/stat/en-US.md": "e352f69e",
|
|
2887
|
+
"site/content/components/submit/en-US.md": "ab4cdd10",
|
|
2888
|
+
"site/content/components/switch/en-US.md": "d72058e4",
|
|
2889
|
+
"site/content/components/table/en-US.md": "be8190d7",
|
|
2890
|
+
"site/content/components/tabs/en-US.md": "a0029940",
|
|
2891
|
+
"site/content/components/text/en-US.md": "075cd122",
|
|
2892
|
+
"site/content/components/toast/en-US.md": "960011bc",
|
|
2893
|
+
"component:accordion": "ff1be273",
|
|
2894
|
+
"component:badge": "eece8f49",
|
|
2895
|
+
"component:button": "3bd71fe1",
|
|
2896
|
+
"component:callout": "0fee87ac",
|
|
2897
|
+
"component:card": "d5c9d358",
|
|
2898
|
+
"component:checkbox": "f02a8e1f",
|
|
2899
|
+
"component:code-block": "70ce858c",
|
|
2900
|
+
"component:collapsible": "fbb14382",
|
|
2901
|
+
"component:column": "764d30da",
|
|
2902
|
+
"component:divider": "447bf44a",
|
|
2903
|
+
"component:grid": "912458b7",
|
|
2904
|
+
"component:icon": "0b7a18c9",
|
|
2905
|
+
"component:input": "66f5dbc5",
|
|
2906
|
+
"component:link": "1404518b",
|
|
2907
|
+
"component:playground": "7d8e1d36",
|
|
2908
|
+
"component:progress": "706fde5e",
|
|
2909
|
+
"component:radio-group": "66c04b44",
|
|
2910
|
+
"component:row": "6c9327b6",
|
|
2911
|
+
"component:section": "d2fe0297",
|
|
2912
|
+
"component:select": "0636d6dd",
|
|
2913
|
+
"component:slider": "490f7f36",
|
|
2914
|
+
"component:stat": "cd525fc5",
|
|
2915
|
+
"component:submit": "b3753761",
|
|
2916
|
+
"component:switch": "c5fd6169",
|
|
2917
|
+
"component:table": "546ee458",
|
|
2918
|
+
"component:tabs": "e5cff5dc",
|
|
2919
|
+
"component:text": "d498fd82",
|
|
2920
|
+
"component:toast": "cc0c6b05"
|
|
2921
|
+
}
|
|
2922
|
+
}
|