pmx-canvas 0.1.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/CHANGELOG.md +38 -0
- package/LICENSE +21 -0
- package/Readme.md +865 -0
- package/dist/canvas/global.css +3173 -0
- package/dist/canvas/index.js +183 -0
- package/dist/json-render/index.css +2 -0
- package/dist/json-render/index.js +389 -0
- package/dist/types/cli/agent.d.ts +13 -0
- package/dist/types/cli/index.d.ts +2 -0
- package/dist/types/cli/watch.d.ts +5 -0
- package/dist/types/client/App.d.ts +1 -0
- package/dist/types/client/canvas/AttentionHistory.d.ts +1 -0
- package/dist/types/client/canvas/AttentionToast.d.ts +1 -0
- package/dist/types/client/canvas/CanvasNode.d.ts +8 -0
- package/dist/types/client/canvas/CanvasViewport.d.ts +8 -0
- package/dist/types/client/canvas/CommandPalette.d.ts +4 -0
- package/dist/types/client/canvas/ContextMenu.d.ts +24 -0
- package/dist/types/client/canvas/ContextPinBar.d.ts +1 -0
- package/dist/types/client/canvas/ContextPinHud.d.ts +1 -0
- package/dist/types/client/canvas/DockedNode.d.ts +4 -0
- package/dist/types/client/canvas/EdgeLayer.d.ts +8 -0
- package/dist/types/client/canvas/ExpandedNodeOverlay.d.ts +1 -0
- package/dist/types/client/canvas/FocusFieldLayer.d.ts +1 -0
- package/dist/types/client/canvas/Minimap.d.ts +23 -0
- package/dist/types/client/canvas/SelectionBar.d.ts +1 -0
- package/dist/types/client/canvas/ShortcutOverlay.d.ts +3 -0
- package/dist/types/client/canvas/SnapshotPanel.d.ts +7 -0
- package/dist/types/client/canvas/snap-guides.d.ts +23 -0
- package/dist/types/client/canvas/use-node-drag.d.ts +15 -0
- package/dist/types/client/canvas/use-node-resize.d.ts +15 -0
- package/dist/types/client/canvas/use-pan-zoom.d.ts +16 -0
- package/dist/types/client/ext-app/bridge.d.ts +161 -0
- package/dist/types/client/icons.d.ts +70 -0
- package/dist/types/client/index.d.ts +1 -0
- package/dist/types/client/nodes/ContextNode.d.ts +34 -0
- package/dist/types/client/nodes/ExtAppFrame.d.ts +18 -0
- package/dist/types/client/nodes/FileNode.d.ts +5 -0
- package/dist/types/client/nodes/GroupNode.d.ts +6 -0
- package/dist/types/client/nodes/ImageNode.d.ts +10 -0
- package/dist/types/client/nodes/InlineFormatBar.d.ts +7 -0
- package/dist/types/client/nodes/InlineMarkdownEditor.d.ts +14 -0
- package/dist/types/client/nodes/LedgerNode.d.ts +4 -0
- package/dist/types/client/nodes/MarkdownNode.d.ts +6 -0
- package/dist/types/client/nodes/McpAppNode.d.ts +4 -0
- package/dist/types/client/nodes/MdFormatBar.d.ts +8 -0
- package/dist/types/client/nodes/PromptNode.d.ts +5 -0
- package/dist/types/client/nodes/ResponseNode.d.ts +5 -0
- package/dist/types/client/nodes/StatusNode.d.ts +4 -0
- package/dist/types/client/nodes/StatusSummary.d.ts +4 -0
- package/dist/types/client/nodes/TraceNode.d.ts +4 -0
- package/dist/types/client/nodes/WebpageNode.d.ts +5 -0
- package/dist/types/client/nodes/image-warnings.d.ts +6 -0
- package/dist/types/client/nodes/inline-editor-commands.d.ts +11 -0
- package/dist/types/client/nodes/md-format.d.ts +25 -0
- package/dist/types/client/state/attention-bridge.d.ts +3 -0
- package/dist/types/client/state/attention-store.d.ts +25 -0
- package/dist/types/client/state/canvas-store.d.ts +74 -0
- package/dist/types/client/state/intent-bridge.d.ts +158 -0
- package/dist/types/client/state/sse-bridge.d.ts +5 -0
- package/dist/types/client/theme/tokens.d.ts +27 -0
- package/dist/types/client/types.d.ts +40 -0
- package/dist/types/client/utils/ext-app-tool-result.d.ts +1 -0
- package/dist/types/client/utils/placement.d.ts +1 -0
- package/dist/types/client/utils/platform.d.ts +2 -0
- package/dist/types/json-render/catalog.d.ts +815 -0
- package/dist/types/json-render/charts/components.d.ts +54 -0
- package/dist/types/json-render/charts/definitions.d.ts +103 -0
- package/dist/types/json-render/charts/extra-components.d.ts +58 -0
- package/dist/types/json-render/charts/extra-definitions.d.ts +181 -0
- package/dist/types/json-render/renderer/index.d.ts +16 -0
- package/dist/types/json-render/schema.d.ts +46 -0
- package/dist/types/json-render/server.d.ts +55 -0
- package/dist/types/mcp/server.d.ts +22 -0
- package/dist/types/server/agent-context.d.ts +21 -0
- package/dist/types/server/artifact-paths.d.ts +3 -0
- package/dist/types/server/canvas-operations.d.ts +154 -0
- package/dist/types/server/canvas-provenance.d.ts +13 -0
- package/dist/types/server/canvas-schema.d.ts +49 -0
- package/dist/types/server/canvas-serialization.d.ts +25 -0
- package/dist/types/server/canvas-state.d.ts +174 -0
- package/dist/types/server/canvas-validation.d.ts +33 -0
- package/dist/types/server/chart-template.d.ts +29 -0
- package/dist/types/server/code-graph.d.ts +67 -0
- package/dist/types/server/context-cards.d.ts +24 -0
- package/dist/types/server/diagram-presets.d.ts +28 -0
- package/dist/types/server/ext-app-call-registry.d.ts +16 -0
- package/dist/types/server/ext-app-tool-result.d.ts +1 -0
- package/dist/types/server/file-watcher.d.ts +16 -0
- package/dist/types/server/index.d.ts +243 -0
- package/dist/types/server/mcp-app-candidate.d.ts +25 -0
- package/dist/types/server/mcp-app-host.d.ts +65 -0
- package/dist/types/server/mcp-app-runtime.d.ts +47 -0
- package/dist/types/server/mutation-history.d.ts +105 -0
- package/dist/types/server/placement.d.ts +37 -0
- package/dist/types/server/server.d.ts +103 -0
- package/dist/types/server/spatial-analysis.d.ts +87 -0
- package/dist/types/server/trace-manager.d.ts +48 -0
- package/dist/types/server/web-artifacts.d.ts +50 -0
- package/dist/types/server/webpage-node.d.ts +25 -0
- package/dist/types/shared/auto-arrange.d.ts +29 -0
- package/dist/types/shared/ext-app-tool-result.d.ts +9 -0
- package/dist/types/shared/placement.d.ts +26 -0
- package/dist/types/shared/semantic-attention.d.ts +97 -0
- package/package.json +109 -0
- package/skills/data-analysis/SKILL.md +324 -0
- package/skills/doc-coauthoring/SKILL.md +375 -0
- package/skills/frontend-design/SKILL.md +45 -0
- package/skills/json-render-codegen/SKILL.md +112 -0
- package/skills/json-render-core/SKILL.md +265 -0
- package/skills/json-render-ink/SKILL.md +273 -0
- package/skills/json-render-mcp/SKILL.md +132 -0
- package/skills/json-render-react/SKILL.md +264 -0
- package/skills/json-render-shadcn/SKILL.md +159 -0
- package/skills/playwright-cli/SKILL.md +67 -0
- package/skills/pmx-canvas/SKILL.md +668 -0
- package/skills/pmx-canvas/evals/evals.json +186 -0
- package/skills/pmx-canvas-testing/SKILL.md +78 -0
- package/skills/published-consumer-e2e/SKILL.md +43 -0
- package/skills/published-consumer-e2e/scripts/run-published-consumer-e2e.sh +241 -0
- package/skills/web-artifacts-builder/SKILL.md +80 -0
- package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +167 -0
- package/skills/web-artifacts-builder/scripts/init-artifact.sh +425 -0
- package/skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/skills/web-design-guidelines/SKILL.md +39 -0
- package/src/cli/agent.ts +2144 -0
- package/src/cli/index.ts +622 -0
- package/src/cli/watch.ts +88 -0
- package/src/client/App.tsx +507 -0
- package/src/client/canvas/AttentionHistory.tsx +81 -0
- package/src/client/canvas/AttentionToast.tsx +19 -0
- package/src/client/canvas/CanvasNode.tsx +363 -0
- package/src/client/canvas/CanvasViewport.tsx +590 -0
- package/src/client/canvas/CommandPalette.tsx +302 -0
- package/src/client/canvas/ContextMenu.tsx +601 -0
- package/src/client/canvas/ContextPinBar.tsx +25 -0
- package/src/client/canvas/ContextPinHud.tsx +22 -0
- package/src/client/canvas/DockedNode.tsx +66 -0
- package/src/client/canvas/EdgeLayer.tsx +280 -0
- package/src/client/canvas/ExpandedNodeOverlay.tsx +260 -0
- package/src/client/canvas/FocusFieldLayer.tsx +107 -0
- package/src/client/canvas/Minimap.tsx +301 -0
- package/src/client/canvas/SelectionBar.tsx +69 -0
- package/src/client/canvas/ShortcutOverlay.tsx +69 -0
- package/src/client/canvas/SnapshotPanel.tsx +236 -0
- package/src/client/canvas/snap-guides.ts +170 -0
- package/src/client/canvas/use-node-drag.ts +51 -0
- package/src/client/canvas/use-node-resize.ts +59 -0
- package/src/client/canvas/use-pan-zoom.ts +191 -0
- package/src/client/ext-app/bridge.ts +542 -0
- package/src/client/icons.tsx +424 -0
- package/src/client/index.tsx +7 -0
- package/src/client/nodes/ContextNode.tsx +412 -0
- package/src/client/nodes/ExtAppFrame.tsx +509 -0
- package/src/client/nodes/FileNode.tsx +256 -0
- package/src/client/nodes/GroupNode.tsx +39 -0
- package/src/client/nodes/ImageNode.tsx +160 -0
- package/src/client/nodes/InlineFormatBar.tsx +169 -0
- package/src/client/nodes/InlineMarkdownEditor.tsx +123 -0
- package/src/client/nodes/LedgerNode.tsx +37 -0
- package/src/client/nodes/MarkdownNode.tsx +359 -0
- package/src/client/nodes/McpAppNode.tsx +85 -0
- package/src/client/nodes/MdFormatBar.tsx +109 -0
- package/src/client/nodes/PromptNode.tsx +597 -0
- package/src/client/nodes/ResponseNode.tsx +153 -0
- package/src/client/nodes/StatusNode.tsx +84 -0
- package/src/client/nodes/StatusSummary.tsx +38 -0
- package/src/client/nodes/TraceNode.tsx +120 -0
- package/src/client/nodes/WebpageNode.tsx +288 -0
- package/src/client/nodes/image-warnings.ts +95 -0
- package/src/client/nodes/inline-editor-commands.ts +37 -0
- package/src/client/nodes/md-format.ts +206 -0
- package/src/client/state/attention-bridge.ts +328 -0
- package/src/client/state/attention-store.ts +73 -0
- package/src/client/state/canvas-store.ts +631 -0
- package/src/client/state/intent-bridge.ts +315 -0
- package/src/client/state/sse-bridge.ts +965 -0
- package/src/client/theme/global.css +3173 -0
- package/src/client/theme/tokens.ts +72 -0
- package/src/client/types-shims.d.ts +5 -0
- package/src/client/types.ts +81 -0
- package/src/client/utils/ext-app-tool-result.ts +4 -0
- package/src/client/utils/placement.ts +4 -0
- package/src/client/utils/platform.ts +2 -0
- package/src/json-render/catalog.ts +256 -0
- package/src/json-render/charts/components.tsx +198 -0
- package/src/json-render/charts/definitions.ts +81 -0
- package/src/json-render/charts/extra-components.tsx +267 -0
- package/src/json-render/charts/extra-definitions.ts +145 -0
- package/src/json-render/renderer/index.css +174 -0
- package/src/json-render/renderer/index.tsx +86 -0
- package/src/json-render/schema.ts +62 -0
- package/src/json-render/server.ts +597 -0
- package/src/mcp/server.ts +1377 -0
- package/src/server/agent-context.ts +242 -0
- package/src/server/artifact-paths.ts +17 -0
- package/src/server/canvas-operations.ts +1279 -0
- package/src/server/canvas-provenance.ts +243 -0
- package/src/server/canvas-schema.ts +432 -0
- package/src/server/canvas-serialization.ts +95 -0
- package/src/server/canvas-state.ts +1134 -0
- package/src/server/canvas-validation.ts +114 -0
- package/src/server/chart-template.ts +449 -0
- package/src/server/code-graph.ts +370 -0
- package/src/server/context-cards.ts +31 -0
- package/src/server/diagram-presets.ts +71 -0
- package/src/server/ext-app-call-registry.ts +77 -0
- package/src/server/ext-app-tool-result.ts +4 -0
- package/src/server/file-watcher.ts +121 -0
- package/src/server/index.ts +647 -0
- package/src/server/mcp-app-candidate.ts +174 -0
- package/src/server/mcp-app-host.ts +814 -0
- package/src/server/mcp-app-runtime.ts +459 -0
- package/src/server/mutation-history.ts +350 -0
- package/src/server/placement.ts +125 -0
- package/src/server/server.ts +3846 -0
- package/src/server/spatial-analysis.ts +356 -0
- package/src/server/trace-manager.ts +333 -0
- package/src/server/web-artifacts/scripts/bundle-artifact.sh +167 -0
- package/src/server/web-artifacts/scripts/init-artifact.sh +426 -0
- package/src/server/web-artifacts/scripts/shadcn-components.tar.gz +0 -0
- package/src/server/web-artifacts.ts +442 -0
- package/src/server/webpage-node.ts +328 -0
- package/src/shared/auto-arrange.ts +439 -0
- package/src/shared/ext-app-tool-result.ts +76 -0
- package/src/shared/placement.ts +81 -0
- package/src/shared/semantic-attention.ts +598 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-design
|
|
3
|
+
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
|
|
4
|
+
license: Complete terms in LICENSE.txt
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
|
8
|
+
|
|
9
|
+
In `pmx-canvas`, use `canvas_build_web_artifact` when the result should be a full custom React app,
|
|
10
|
+
and use `canvas_add_json_render_node` when a schema-driven UI panel is enough.
|
|
11
|
+
|
|
12
|
+
The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
|
|
13
|
+
|
|
14
|
+
## Design Thinking
|
|
15
|
+
|
|
16
|
+
Before coding, understand the context and commit to a BOLD aesthetic direction:
|
|
17
|
+
- **Purpose**: What problem does this interface solve? Who uses it?
|
|
18
|
+
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
|
19
|
+
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
|
20
|
+
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
|
21
|
+
|
|
22
|
+
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
|
|
23
|
+
|
|
24
|
+
Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
|
|
25
|
+
- Production-grade and functional
|
|
26
|
+
- Visually striking and memorable
|
|
27
|
+
- Cohesive with a clear aesthetic point-of-view
|
|
28
|
+
- Meticulously refined in every detail
|
|
29
|
+
|
|
30
|
+
## Frontend Aesthetics Guidelines
|
|
31
|
+
|
|
32
|
+
Focus on:
|
|
33
|
+
- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
|
|
34
|
+
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
|
35
|
+
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
|
|
36
|
+
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
|
|
37
|
+
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
|
|
38
|
+
|
|
39
|
+
NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.
|
|
40
|
+
|
|
41
|
+
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
|
|
42
|
+
|
|
43
|
+
**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
|
|
44
|
+
|
|
45
|
+
Remember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: json-render-codegen
|
|
3
|
+
description: Code generation utilities for json-render. Use when generating code from UI specs, building custom code exporters, traversing specs, or serializing props for @json-render/codegen.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @json-render/codegen
|
|
7
|
+
|
|
8
|
+
Framework-agnostic utilities for generating code from json-render UI trees. Use these to build custom code exporters for Next.js, Remix, or other frameworks.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @json-render/codegen
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Tree Traversal
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import {
|
|
20
|
+
traverseSpec,
|
|
21
|
+
collectUsedComponents,
|
|
22
|
+
collectStatePaths,
|
|
23
|
+
collectActions,
|
|
24
|
+
} from "@json-render/codegen";
|
|
25
|
+
|
|
26
|
+
// Walk the spec depth-first
|
|
27
|
+
traverseSpec(spec, (element, key, depth, parent) => {
|
|
28
|
+
console.log(`${" ".repeat(depth * 2)}${key}: ${element.type}`);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Get all component types used
|
|
32
|
+
const components = collectUsedComponents(spec);
|
|
33
|
+
// Set { "Card", "Metric", "Button" }
|
|
34
|
+
|
|
35
|
+
// Get all state paths referenced
|
|
36
|
+
const statePaths = collectStatePaths(spec);
|
|
37
|
+
// Set { "analytics/revenue", "user/name" }
|
|
38
|
+
|
|
39
|
+
// Get all action names
|
|
40
|
+
const actions = collectActions(spec);
|
|
41
|
+
// Set { "submit_form", "refresh_data" }
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Serialization
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
import {
|
|
48
|
+
serializePropValue,
|
|
49
|
+
serializeProps,
|
|
50
|
+
escapeString,
|
|
51
|
+
type SerializeOptions,
|
|
52
|
+
} from "@json-render/codegen";
|
|
53
|
+
|
|
54
|
+
// Serialize a single value
|
|
55
|
+
serializePropValue("hello");
|
|
56
|
+
// { value: '"hello"', needsBraces: false }
|
|
57
|
+
|
|
58
|
+
serializePropValue({ $state: "/user/name" });
|
|
59
|
+
// { value: '{ $state: "/user/name" }', needsBraces: true }
|
|
60
|
+
|
|
61
|
+
// Serialize props for JSX
|
|
62
|
+
serializeProps({ title: "Dashboard", columns: 3, disabled: true });
|
|
63
|
+
// 'title="Dashboard" columns={3} disabled'
|
|
64
|
+
|
|
65
|
+
// Escape strings for code
|
|
66
|
+
escapeString('hello "world"');
|
|
67
|
+
// 'hello \"world\"'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### SerializeOptions
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
interface SerializeOptions {
|
|
74
|
+
quotes?: "single" | "double";
|
|
75
|
+
indent?: number;
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Types
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import type { GeneratedFile, CodeGenerator } from "@json-render/codegen";
|
|
83
|
+
|
|
84
|
+
const myGenerator: CodeGenerator = {
|
|
85
|
+
generate(spec) {
|
|
86
|
+
return [
|
|
87
|
+
{ path: "package.json", content: "..." },
|
|
88
|
+
{ path: "app/page.tsx", content: "..." },
|
|
89
|
+
];
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Building a Custom Generator
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import {
|
|
98
|
+
collectUsedComponents,
|
|
99
|
+
collectStatePaths,
|
|
100
|
+
traverseSpec,
|
|
101
|
+
serializeProps,
|
|
102
|
+
type GeneratedFile,
|
|
103
|
+
} from "@json-render/codegen";
|
|
104
|
+
import type { Spec } from "@json-render/core";
|
|
105
|
+
|
|
106
|
+
export function generateNextJSProject(spec: Spec): GeneratedFile[] {
|
|
107
|
+
const files: GeneratedFile[] = [];
|
|
108
|
+
const components = collectUsedComponents(spec);
|
|
109
|
+
// Generate package.json, component files, main page...
|
|
110
|
+
return files;
|
|
111
|
+
}
|
|
112
|
+
```
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: json-render-core
|
|
3
|
+
description: Core package for defining schemas, catalogs, and AI prompt generation for json-render. Use when working with @json-render/core, defining schemas, creating catalogs, or building JSON specs for UI/video generation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @json-render/core
|
|
7
|
+
|
|
8
|
+
Core package for schema definition, catalog creation, and spec streaming.
|
|
9
|
+
|
|
10
|
+
## Key Concepts
|
|
11
|
+
|
|
12
|
+
- **Schema**: Defines the structure of specs and catalogs (use `defineSchema`)
|
|
13
|
+
- **Catalog**: Maps component/action names to their definitions (use `defineCatalog`)
|
|
14
|
+
- **Spec**: JSON output from AI that conforms to the schema
|
|
15
|
+
- **SpecStream**: JSONL streaming format for progressive spec building
|
|
16
|
+
|
|
17
|
+
## Defining a Schema
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { defineSchema } from "@json-render/core";
|
|
21
|
+
|
|
22
|
+
export const schema = defineSchema((s) => ({
|
|
23
|
+
spec: s.object({
|
|
24
|
+
// Define spec structure
|
|
25
|
+
}),
|
|
26
|
+
catalog: s.object({
|
|
27
|
+
components: s.map({
|
|
28
|
+
props: s.zod(),
|
|
29
|
+
description: s.string(),
|
|
30
|
+
}),
|
|
31
|
+
}),
|
|
32
|
+
}), {
|
|
33
|
+
promptTemplate: myPromptTemplate, // Optional custom AI prompt
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Creating a Catalog
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { defineCatalog } from "@json-render/core";
|
|
41
|
+
import { schema } from "./schema";
|
|
42
|
+
import { z } from "zod";
|
|
43
|
+
|
|
44
|
+
export const catalog = defineCatalog(schema, {
|
|
45
|
+
components: {
|
|
46
|
+
Button: {
|
|
47
|
+
props: z.object({
|
|
48
|
+
label: z.string(),
|
|
49
|
+
variant: z.enum(["primary", "secondary"]).nullable(),
|
|
50
|
+
}),
|
|
51
|
+
description: "Clickable button component",
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Generating AI Prompts
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const systemPrompt = catalog.prompt(); // Uses schema's promptTemplate
|
|
61
|
+
const systemPrompt = catalog.prompt({ customRules: ["Rule 1", "Rule 2"] });
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## SpecStream Utilities
|
|
65
|
+
|
|
66
|
+
For streaming AI responses (JSONL patches):
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import { createSpecStreamCompiler } from "@json-render/core";
|
|
70
|
+
|
|
71
|
+
const compiler = createSpecStreamCompiler<MySpec>();
|
|
72
|
+
|
|
73
|
+
// Process streaming chunks
|
|
74
|
+
const { result, newPatches } = compiler.push(chunk);
|
|
75
|
+
|
|
76
|
+
// Get final result
|
|
77
|
+
const finalSpec = compiler.getResult();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Dynamic Prop Expressions
|
|
81
|
+
|
|
82
|
+
Any prop value can be a dynamic expression resolved at render time:
|
|
83
|
+
|
|
84
|
+
- **`{ "$state": "/state/key" }`** - reads a value from the state model (one-way read)
|
|
85
|
+
- **`{ "$bindState": "/path" }`** - two-way binding: reads from state and enables write-back. Use on the natural value prop (value, checked, pressed, etc.) of form components.
|
|
86
|
+
- **`{ "$bindItem": "field" }`** - two-way binding to a repeat item field. Use inside repeat scopes.
|
|
87
|
+
- **`{ "$cond": <condition>, "$then": <value>, "$else": <value> }`** - evaluates a visibility condition and picks a branch
|
|
88
|
+
- **`{ "$template": "Hello, ${/user/name}!" }`** - interpolates `${/path}` references with state values
|
|
89
|
+
- **`{ "$computed": "fnName", "args": { "key": <expression> } }`** - calls a registered function with resolved args
|
|
90
|
+
|
|
91
|
+
`$cond` uses the same syntax as visibility conditions (`$state`, `eq`, `neq`, `not`, arrays for AND). `$then` and `$else` can themselves be expressions (recursive).
|
|
92
|
+
|
|
93
|
+
Components do not use a `statePath` prop for two-way binding. Instead, use `{ "$bindState": "/path" }` on the natural value prop (e.g. `value`, `checked`, `pressed`).
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"color": {
|
|
98
|
+
"$cond": { "$state": "/activeTab", "eq": "home" },
|
|
99
|
+
"$then": "#007AFF",
|
|
100
|
+
"$else": "#8E8E93"
|
|
101
|
+
},
|
|
102
|
+
"label": { "$template": "Welcome, ${/user/name}!" },
|
|
103
|
+
"fullName": {
|
|
104
|
+
"$computed": "fullName",
|
|
105
|
+
"args": {
|
|
106
|
+
"first": { "$state": "/form/firstName" },
|
|
107
|
+
"last": { "$state": "/form/lastName" }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { resolvePropValue, resolveElementProps } from "@json-render/core";
|
|
115
|
+
|
|
116
|
+
const resolved = resolveElementProps(element.props, { stateModel: myState });
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## State Watchers
|
|
120
|
+
|
|
121
|
+
Elements can declare a `watch` field (top-level, sibling of type/props/children) to trigger actions when state values change:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"type": "Select",
|
|
126
|
+
"props": { "value": { "$bindState": "/form/country" }, "options": ["US", "Canada"] },
|
|
127
|
+
"watch": {
|
|
128
|
+
"/form/country": { "action": "loadCities", "params": { "country": { "$state": "/form/country" } } }
|
|
129
|
+
},
|
|
130
|
+
"children": []
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Watchers only fire on value changes, not on initial render.
|
|
135
|
+
|
|
136
|
+
## Validation
|
|
137
|
+
|
|
138
|
+
Built-in validation functions: `required`, `email`, `url`, `numeric`, `minLength`, `maxLength`, `min`, `max`, `pattern`, `matches`, `equalTo`, `lessThan`, `greaterThan`, `requiredIf`.
|
|
139
|
+
|
|
140
|
+
Cross-field validation uses `$state` expressions in args:
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
import { check } from "@json-render/core";
|
|
144
|
+
|
|
145
|
+
check.required("Field is required");
|
|
146
|
+
check.matches("/form/password", "Passwords must match");
|
|
147
|
+
check.lessThan("/form/endDate", "Must be before end date");
|
|
148
|
+
check.greaterThan("/form/startDate", "Must be after start date");
|
|
149
|
+
check.requiredIf("/form/enableNotifications", "Required when enabled");
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## User Prompt Builder
|
|
153
|
+
|
|
154
|
+
Build structured user prompts with optional spec refinement and state context:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { buildUserPrompt } from "@json-render/core";
|
|
158
|
+
|
|
159
|
+
// Fresh generation
|
|
160
|
+
buildUserPrompt({ prompt: "create a todo app" });
|
|
161
|
+
|
|
162
|
+
// Refinement with edit modes (default: patch-only)
|
|
163
|
+
buildUserPrompt({ prompt: "add a toggle", currentSpec: spec, editModes: ["patch", "merge"] });
|
|
164
|
+
|
|
165
|
+
// With runtime state
|
|
166
|
+
buildUserPrompt({ prompt: "show data", state: { todos: [] } });
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Available edit modes: `"patch"` (RFC 6902 JSON Patch), `"merge"` (RFC 7396 Merge Patch), `"diff"` (unified diff).
|
|
170
|
+
|
|
171
|
+
## Spec Validation
|
|
172
|
+
|
|
173
|
+
Validate spec structure and auto-fix common issues:
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import { validateSpec, autoFixSpec } from "@json-render/core";
|
|
177
|
+
|
|
178
|
+
const { valid, issues } = validateSpec(spec);
|
|
179
|
+
const fixed = autoFixSpec(spec);
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Visibility Conditions
|
|
183
|
+
|
|
184
|
+
Control element visibility with state-based conditions. `VisibilityContext` is `{ stateModel: StateModel }`.
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
import { visibility } from "@json-render/core";
|
|
188
|
+
|
|
189
|
+
// Syntax
|
|
190
|
+
{ "$state": "/path" } // truthiness
|
|
191
|
+
{ "$state": "/path", "not": true } // falsy
|
|
192
|
+
{ "$state": "/path", "eq": value } // equality
|
|
193
|
+
[ cond1, cond2 ] // implicit AND
|
|
194
|
+
|
|
195
|
+
// Helpers
|
|
196
|
+
visibility.when("/path") // { $state: "/path" }
|
|
197
|
+
visibility.unless("/path") // { $state: "/path", not: true }
|
|
198
|
+
visibility.eq("/path", val) // { $state: "/path", eq: val }
|
|
199
|
+
visibility.and(cond1, cond2) // { $and: [cond1, cond2] }
|
|
200
|
+
visibility.or(cond1, cond2) // { $or: [cond1, cond2] }
|
|
201
|
+
visibility.always // true
|
|
202
|
+
visibility.never // false
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Built-in Actions in Schema
|
|
206
|
+
|
|
207
|
+
Schemas can declare `builtInActions` -- actions that are always available at runtime and auto-injected into prompts:
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
const schema = defineSchema(builder, {
|
|
211
|
+
builtInActions: [
|
|
212
|
+
{ name: "setState", description: "Update a value in the state model" },
|
|
213
|
+
],
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
These appear in prompts as `[built-in]` and don't require handlers in `defineRegistry`.
|
|
218
|
+
|
|
219
|
+
## StateStore
|
|
220
|
+
|
|
221
|
+
The `StateStore` interface allows external state management libraries (Redux, Zustand, XState, etc.) to be plugged into json-render renderers. The `createStateStore` factory creates a simple in-memory implementation:
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { createStateStore, type StateStore } from "@json-render/core";
|
|
225
|
+
|
|
226
|
+
const store = createStateStore({ count: 0 });
|
|
227
|
+
|
|
228
|
+
store.get("/count"); // 0
|
|
229
|
+
store.set("/count", 1); // updates and notifies subscribers
|
|
230
|
+
store.update({ "/a": 1, "/b": 2 }); // batch update
|
|
231
|
+
|
|
232
|
+
store.subscribe(() => {
|
|
233
|
+
console.log(store.getSnapshot()); // { count: 1 }
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The `StateStore` interface: `get(path)`, `set(path, value)`, `update(updates)`, `getSnapshot()`, `subscribe(listener)`.
|
|
238
|
+
|
|
239
|
+
## Key Exports
|
|
240
|
+
|
|
241
|
+
| Export | Purpose |
|
|
242
|
+
|--------|---------|
|
|
243
|
+
| `defineSchema` | Create a new schema |
|
|
244
|
+
| `defineCatalog` | Create a catalog from schema |
|
|
245
|
+
| `createStateStore` | Create a framework-agnostic in-memory `StateStore` |
|
|
246
|
+
| `resolvePropValue` | Resolve a single prop expression against data |
|
|
247
|
+
| `resolveElementProps` | Resolve all prop expressions in an element |
|
|
248
|
+
| `buildUserPrompt` | Build user prompts with refinement and state context |
|
|
249
|
+
| `buildEditUserPrompt` | Build user prompt for editing existing specs |
|
|
250
|
+
| `buildEditInstructions` | Generate prompt section for available edit modes |
|
|
251
|
+
| `isNonEmptySpec` | Check if spec has root and at least one element |
|
|
252
|
+
| `deepMergeSpec` | RFC 7396 deep merge (null deletes, arrays replace, objects recurse) |
|
|
253
|
+
| `diffToPatches` | Generate RFC 6902 JSON Patch operations from object diff |
|
|
254
|
+
| `EditMode` | Type: `"patch" \| "merge" \| "diff"` |
|
|
255
|
+
| `validateSpec` | Validate spec structure |
|
|
256
|
+
| `autoFixSpec` | Auto-fix common spec issues |
|
|
257
|
+
| `createSpecStreamCompiler` | Stream JSONL patches into spec |
|
|
258
|
+
| `createJsonRenderTransform` | TransformStream separating text from JSONL in mixed streams |
|
|
259
|
+
| `parseSpecStreamLine` | Parse single JSONL line |
|
|
260
|
+
| `applySpecStreamPatch` | Apply patch to object |
|
|
261
|
+
| `StateStore` | Interface for plugging in external state management |
|
|
262
|
+
| `ComputedFunction` | Function signature for `$computed` expressions |
|
|
263
|
+
| `check` | TypeScript helpers for creating validation checks |
|
|
264
|
+
| `BuiltInAction` | Type for built-in action definitions (`name` + `description`) |
|
|
265
|
+
| `ActionBinding` | Action binding type (includes `preventDefault` field) |
|