codeforge-dev 1.4.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.
Files changed (131) hide show
  1. package/.devcontainer/.env +22 -0
  2. package/.devcontainer/CHANGELOG.md +197 -0
  3. package/.devcontainer/CLAUDE.md +117 -0
  4. package/.devcontainer/README.md +222 -0
  5. package/.devcontainer/config/main-system-prompt.md +502 -0
  6. package/.devcontainer/config/settings.json +47 -0
  7. package/.devcontainer/devcontainer.json +94 -0
  8. package/.devcontainer/features/README.md +113 -0
  9. package/.devcontainer/features/agent-browser/README.md +65 -0
  10. package/.devcontainer/features/agent-browser/devcontainer-feature.json +23 -0
  11. package/.devcontainer/features/agent-browser/install.sh +79 -0
  12. package/.devcontainer/features/ast-grep/README.md +24 -0
  13. package/.devcontainer/features/ast-grep/devcontainer-feature.json +24 -0
  14. package/.devcontainer/features/ast-grep/install.sh +51 -0
  15. package/.devcontainer/features/ccstatusline/README.md +296 -0
  16. package/.devcontainer/features/ccstatusline/devcontainer-feature.json +19 -0
  17. package/.devcontainer/features/ccstatusline/install.sh +290 -0
  18. package/.devcontainer/features/ccusage/README.md +205 -0
  19. package/.devcontainer/features/ccusage/devcontainer-feature.json +38 -0
  20. package/.devcontainer/features/ccusage/install.sh +132 -0
  21. package/.devcontainer/features/claude-code/README.md +498 -0
  22. package/.devcontainer/features/claude-code/config/settings.json +36 -0
  23. package/.devcontainer/features/claude-code/config/system-prompt.md +118 -0
  24. package/.devcontainer/features/claude-code/config/world-building-sp.md +1432 -0
  25. package/.devcontainer/features/claude-code/devcontainer-feature.json +42 -0
  26. package/.devcontainer/features/claude-code/install.sh +466 -0
  27. package/.devcontainer/features/claude-monitor/README.md +74 -0
  28. package/.devcontainer/features/claude-monitor/devcontainer-feature.json +38 -0
  29. package/.devcontainer/features/claude-monitor/install.sh +99 -0
  30. package/.devcontainer/features/lsp-servers/README.md +85 -0
  31. package/.devcontainer/features/lsp-servers/devcontainer-feature.json +40 -0
  32. package/.devcontainer/features/lsp-servers/install.sh +116 -0
  33. package/.devcontainer/features/mcp-qdrant/CHANGES.md +399 -0
  34. package/.devcontainer/features/mcp-qdrant/README.md +474 -0
  35. package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +57 -0
  36. package/.devcontainer/features/mcp-qdrant/install.sh +295 -0
  37. package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +129 -0
  38. package/.devcontainer/features/mcp-reasoner/README.md +177 -0
  39. package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +20 -0
  40. package/.devcontainer/features/mcp-reasoner/install.sh +177 -0
  41. package/.devcontainer/features/mcp-reasoner/poststart-hook.sh +67 -0
  42. package/.devcontainer/features/notify-hook/README.md +86 -0
  43. package/.devcontainer/features/notify-hook/devcontainer-feature.json +23 -0
  44. package/.devcontainer/features/notify-hook/install.sh +38 -0
  45. package/.devcontainer/features/splitrail/README.md +140 -0
  46. package/.devcontainer/features/splitrail/devcontainer-feature.json +34 -0
  47. package/.devcontainer/features/splitrail/install.sh +129 -0
  48. package/.devcontainer/features/tree-sitter/README.md +138 -0
  49. package/.devcontainer/features/tree-sitter/devcontainer-feature.json +52 -0
  50. package/.devcontainer/features/tree-sitter/install.sh +173 -0
  51. package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +106 -0
  52. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +7 -0
  53. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/hooks/hooks.json +17 -0
  54. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-file.py +101 -0
  55. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/.claude-plugin/plugin.json +7 -0
  56. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +17 -0
  57. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +137 -0
  58. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/.claude-plugin/plugin.json +8 -0
  59. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/SKILL.md +387 -0
  60. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/cli-flags-and-output.md +312 -0
  61. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/sdk-and-mcp.md +569 -0
  62. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/SKILL.md +309 -0
  63. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/compose-services.md +438 -0
  64. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/dockerfile-patterns.md +340 -0
  65. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/SKILL.md +412 -0
  66. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/container-lifecycle.md +388 -0
  67. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/resources-and-security.md +444 -0
  68. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/SKILL.md +344 -0
  69. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/middleware-and-lifespan.md +254 -0
  70. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/pydantic-models.md +245 -0
  71. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/routing-and-dependencies.md +255 -0
  72. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/sse-and-streaming.md +318 -0
  73. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/SKILL.md +345 -0
  74. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/agents-and-tools.md +271 -0
  75. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/models-and-streaming.md +422 -0
  76. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/SKILL.md +220 -0
  77. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/cross-vendor-principles.md +139 -0
  78. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/patterns-and-antipatterns.md +376 -0
  79. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/skill-authoring-patterns.md +356 -0
  80. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/SKILL.md +329 -0
  81. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/advanced-queries.md +314 -0
  82. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/javascript-patterns.md +323 -0
  83. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/python-patterns.md +354 -0
  84. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/schema-and-pragmas.md +326 -0
  85. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/SKILL.md +356 -0
  86. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/ai-sdk-svelte.md +128 -0
  87. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/component-patterns.md +332 -0
  88. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/layercake.md +203 -0
  89. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/migration-guide.md +350 -0
  90. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/runes-and-reactivity.md +328 -0
  91. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/spa-and-routing.md +262 -0
  92. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/svelte-dnd-action.md +181 -0
  93. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/SKILL.md +414 -0
  94. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/fastapi-testing.md +411 -0
  95. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/svelte-testing.md +538 -0
  96. package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/.claude-plugin/plugin.json +7 -0
  97. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/.claude-plugin/plugin.json +7 -0
  98. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/hooks/hooks.json +17 -0
  99. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +110 -0
  100. package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/.claude-plugin/plugin.json +7 -0
  101. package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/hooks/hooks.json +17 -0
  102. package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/.claude-plugin/plugin.json +7 -0
  103. package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/hooks/hooks.json +17 -0
  104. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/.claude-plugin/plugin.json +7 -0
  105. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/hooks/hooks.json +17 -0
  106. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +108 -0
  107. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272create-pr.md +337 -0
  108. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272new.md +166 -0
  109. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272review-commit.md +290 -0
  110. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272work.md +257 -0
  111. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/plugin.json +8 -0
  112. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/system-prompt.md +184 -0
  113. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/.claude-plugin/plugin.json +6 -0
  114. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/config/planning-instructions.md +14 -0
  115. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/functional-conjuring-map.md +989 -0
  116. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/hooks/hooks.json +33 -0
  117. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/__pycache__/post-enhance-task.cpython-314.pyc +0 -0
  118. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhance-planning.py +71 -0
  119. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-plan.sh +68 -0
  120. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-task.sh +120 -0
  121. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-plan.py +133 -0
  122. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-task.py +253 -0
  123. package/.devcontainer/scripts/setup-aliases.sh +80 -0
  124. package/.devcontainer/scripts/setup-config.sh +28 -0
  125. package/.devcontainer/scripts/setup-irie-claude.sh +32 -0
  126. package/.devcontainer/scripts/setup-plugins.sh +80 -0
  127. package/.devcontainer/scripts/setup.sh +58 -0
  128. package/LICENSE.txt +674 -0
  129. package/README.md +267 -0
  130. package/package.json +44 -0
  131. package/setup.js +83 -0
@@ -0,0 +1,332 @@
1
+ # Component Patterns — Deep Dive
2
+
3
+ ## 1. Props Patterns
4
+
5
+ ### Basic Destructuring with Defaults
6
+
7
+ ```svelte
8
+ <script>
9
+ let { title, subtitle = 'Default subtitle', variant = 'primary' } = $props();
10
+ </script>
11
+ ```
12
+
13
+ Missing required props produce a compile-time warning when using TypeScript.
14
+
15
+ ### Rest Props
16
+
17
+ Collect remaining props with rest syntax for forwarding to elements:
18
+
19
+ ```svelte
20
+ <script>
21
+ let { class: className = '', children, ...rest } = $props();
22
+ </script>
23
+ <div class="wrapper {className}" {...rest}>
24
+ {@render children?.()}
25
+ </div>
26
+ ```
27
+
28
+ Note: `class` is a reserved word in JavaScript — rename it during destructuring.
29
+
30
+ ### TypeScript Props
31
+
32
+ Define an interface for type safety and IDE autocompletion:
33
+
34
+ ```svelte
35
+ <script lang="ts">
36
+ import type { Snippet } from 'svelte';
37
+
38
+ interface Props {
39
+ title: string;
40
+ count?: number;
41
+ variant?: 'primary' | 'secondary' | 'danger';
42
+ children?: Snippet;
43
+ header?: Snippet<[{ title: string }]>;
44
+ onclick?: (e: MouseEvent) => void;
45
+ }
46
+
47
+ let { title, count = 0, variant = 'primary', children, header, onclick }: Props = $props();
48
+ </script>
49
+ ```
50
+
51
+ Type snippets using `Snippet` from `svelte`. Parameterized snippets use `Snippet<[ParamType]>`.
52
+
53
+ ### $bindable Props
54
+
55
+ Mark a prop as bindable to allow two-way binding from the parent:
56
+
57
+ ```svelte
58
+ <!-- Input.svelte -->
59
+ <script lang="ts">
60
+ interface Props {
61
+ value: string;
62
+ placeholder?: string;
63
+ }
64
+ let { value = $bindable(''), placeholder = '' }: Props = $props();
65
+ </script>
66
+ <input bind:value {placeholder} />
67
+ ```
68
+
69
+ ```svelte
70
+ <!-- Parent -->
71
+ <script>
72
+ import Input from './Input.svelte';
73
+ let name = $state('');
74
+ </script>
75
+ <Input bind:value={name} />
76
+ <p>Typed: {name}</p>
77
+ ```
78
+
79
+ Only mark props as `$bindable` when two-way data flow is the intended API. Prefer callback props for explicit data flow.
80
+
81
+ ## 2. Snippet Patterns
82
+
83
+ ### Basic Children
84
+
85
+ The `children` snippet is the implicit content placed between component tags:
86
+
87
+ ```svelte
88
+ <!-- Card.svelte -->
89
+ <script>
90
+ let { children } = $props();
91
+ </script>
92
+ <div class="card">
93
+ {@render children?.()}
94
+ </div>
95
+
96
+ <!-- Usage -->
97
+ <Card>
98
+ <h2>Title</h2>
99
+ <p>Content</p>
100
+ </Card>
101
+ ```
102
+
103
+ Use optional chaining (`children?.()`) when the children snippet is optional.
104
+
105
+ ### Named Snippets
106
+
107
+ Named snippets replace named slots:
108
+
109
+ ```svelte
110
+ <!-- Layout.svelte -->
111
+ <script lang="ts">
112
+ import type { Snippet } from 'svelte';
113
+ interface Props {
114
+ header: Snippet;
115
+ footer?: Snippet;
116
+ children: Snippet;
117
+ }
118
+ let { header, footer, children }: Props = $props();
119
+ </script>
120
+
121
+ <header>{@render header()}</header>
122
+ <main>{@render children()}</main>
123
+ {#if footer}
124
+ <footer>{@render footer()}</footer>
125
+ {/if}
126
+ ```
127
+
128
+ ```svelte
129
+ <!-- Usage -->
130
+ <Layout>
131
+ {#snippet header()}
132
+ <h1>Page Title</h1>
133
+ {/snippet}
134
+
135
+ <p>Main content as children</p>
136
+
137
+ {#snippet footer()}
138
+ <small>Footer text</small>
139
+ {/snippet}
140
+ </Layout>
141
+ ```
142
+
143
+ ### Parameterized Snippets
144
+
145
+ Pass data back to the parent through snippet parameters:
146
+
147
+ ```svelte
148
+ <!-- DataTable.svelte -->
149
+ <script lang="ts">
150
+ import type { Snippet } from 'svelte';
151
+
152
+ interface Props<T> {
153
+ items: T[];
154
+ row: Snippet<[T, number]>;
155
+ empty?: Snippet;
156
+ }
157
+
158
+ let { items, row, empty }: Props<any> = $props();
159
+ </script>
160
+
161
+ {#if items.length === 0}
162
+ {@render empty?.()}
163
+ {:else}
164
+ {#each items as item, index}
165
+ {@render row(item, index)}
166
+ {/each}
167
+ {/if}
168
+ ```
169
+
170
+ ```svelte
171
+ <!-- Usage -->
172
+ <DataTable {items}>
173
+ {#snippet row(item, index)}
174
+ <tr>
175
+ <td>{index + 1}</td>
176
+ <td>{item.name}</td>
177
+ </tr>
178
+ {/snippet}
179
+ {#snippet empty()}
180
+ <p>No items found</p>
181
+ {/snippet}
182
+ </DataTable>
183
+ ```
184
+
185
+ ### Local Snippets for Reuse
186
+
187
+ Define snippets locally within a component for repeated template blocks:
188
+
189
+ ```svelte
190
+ {#snippet badge(text, color)}
191
+ <span class="badge" style:background={color}>{text}</span>
192
+ {/snippet}
193
+
194
+ {@render badge('New', 'green')}
195
+ {@render badge('Sale', 'red')}
196
+ {@render badge('Featured', 'blue')}
197
+ ```
198
+
199
+ ## 3. Event Patterns
200
+
201
+ ### DOM Events
202
+
203
+ Svelte 5 uses standard HTML event attributes — no special directive syntax:
204
+
205
+ ```svelte
206
+ <button onclick={handleClick}>Click</button>
207
+ <input oninput={(e) => (query = e.currentTarget.value)} />
208
+ <form onsubmit|preventDefault={handleSubmit}>
209
+ ```
210
+
211
+ Note: Event modifiers use the pipe syntax inline. For complex modifier chains, handle in the callback instead:
212
+
213
+ ```js
214
+ function handleSubmit(e) {
215
+ e.preventDefault();
216
+ e.stopPropagation();
217
+ // handle submission
218
+ }
219
+ ```
220
+
221
+ ### Callback Props (Component Events)
222
+
223
+ Replace `createEventDispatcher` with callback props:
224
+
225
+ ```svelte
226
+ <!-- Dialog.svelte -->
227
+ <script lang="ts">
228
+ interface Props {
229
+ title: string;
230
+ onclose?: () => void;
231
+ onconfirm?: (result: string) => void;
232
+ }
233
+ let { title, onclose, onconfirm }: Props = $props();
234
+ </script>
235
+
236
+ <dialog open>
237
+ <h2>{title}</h2>
238
+ <button onclick={() => onconfirm?.('yes')}>Confirm</button>
239
+ <button onclick={() => onclose?.()}>Cancel</button>
240
+ </dialog>
241
+ ```
242
+
243
+ ```svelte
244
+ <!-- Parent -->
245
+ <Dialog
246
+ title="Confirm Action"
247
+ onclose={() => (showDialog = false)}
248
+ onconfirm={(result) => handleResult(result)}
249
+ />
250
+ ```
251
+
252
+ ### Event Forwarding
253
+
254
+ Forward DOM events from inner elements to the component's consumer by accepting and spreading handler props:
255
+
256
+ ```svelte
257
+ <!-- Button.svelte -->
258
+ <script>
259
+ let { children, ...rest } = $props();
260
+ </script>
261
+ <button {...rest}>
262
+ {@render children?.()}
263
+ </button>
264
+ ```
265
+
266
+ All `on*` attributes passed to `<Button>` forward to the underlying `<button>` element.
267
+
268
+ ## 4. Composition Patterns
269
+
270
+ ### Wrapper Components
271
+
272
+ Create components that enhance a base element while preserving its full API:
273
+
274
+ ```svelte
275
+ <!-- Tooltip.svelte -->
276
+ <script>
277
+ let { text, children, ...rest } = $props();
278
+ </script>
279
+ <div class="tooltip-wrapper" {...rest}>
280
+ {@render children?.()}
281
+ <div class="tooltip-text">{text}</div>
282
+ </div>
283
+ ```
284
+
285
+ ### Dynamic Components
286
+
287
+ Svelte 5 renders components directly from variables — `<svelte:component>` is no longer necessary:
288
+
289
+ ```svelte
290
+ <script>
291
+ import Home from './Home.svelte';
292
+ import About from './About.svelte';
293
+
294
+ const routes = { home: Home, about: About };
295
+ let current = $state('home');
296
+ </script>
297
+
298
+ {@const Page = routes[current]}
299
+ <Page />
300
+ ```
301
+
302
+ ### Generic Components with TypeScript
303
+
304
+ Use generics for type-safe reusable components:
305
+
306
+ ```svelte
307
+ <script lang="ts" generics="T">
308
+ import type { Snippet } from 'svelte';
309
+
310
+ interface Props {
311
+ items: T[];
312
+ selected?: T;
313
+ row: Snippet<[T]>;
314
+ onselect?: (item: T) => void;
315
+ }
316
+
317
+ let { items, selected, row, onselect }: Props = $props();
318
+ </script>
319
+
320
+ <ul>
321
+ {#each items as item}
322
+ <li
323
+ class:selected={item === selected}
324
+ onclick={() => onselect?.(item)}
325
+ >
326
+ {@render row(item)}
327
+ </li>
328
+ {/each}
329
+ </ul>
330
+ ```
331
+
332
+ The `generics` attribute on `<script>` declares type parameters available throughout the component.
@@ -0,0 +1,203 @@
1
+ # LayerCake — Reference
2
+
3
+ ## Mental Model
4
+
5
+ LayerCake is a headless graphics framework, not a chart library. It provides a coordinate system — reactive scales that map data values to pixel positions — and layout containers for SVG, HTML, Canvas, and WebGL. The developer authors individual layer components (axes, lines, points, labels) that read scale functions from context. This separation means LayerCake handles the math while the developer controls every visual detail.
6
+
7
+ LayerCake does not ship pre-built chart types. Instead, it provides the plumbing: scale computation, responsive dimension tracking, data transformation helpers, and a layered rendering model that composites multiple technologies in a single chart area.
8
+
9
+ > Official guide, API reference, and component gallery: <https://layercake.graphics>
10
+
11
+ ---
12
+
13
+ ## Core API
14
+
15
+ ### LayerCake Component
16
+
17
+ The `<LayerCake>` component is the root container. It computes scales from data and exposes them to all descendant layer components through Svelte context.
18
+
19
+ ```svelte
20
+ <script>
21
+ import { LayerCake, Svg } from 'layercake';
22
+ import Line from './Line.svelte';
23
+
24
+ let data = [
25
+ { x: 0, y: 10 },
26
+ { x: 1, y: 35 },
27
+ { x: 2, y: 20 }
28
+ ];
29
+ </script>
30
+
31
+ <div class="chart-container" style="width: 100%; height: 300px;">
32
+ <LayerCake
33
+ {data}
34
+ x="x"
35
+ y="y"
36
+ >
37
+ <Svg>
38
+ <Line />
39
+ </Svg>
40
+ </LayerCake>
41
+ </div>
42
+ ```
43
+
44
+ LayerCake requires a positioned container with explicit dimensions. The component measures this container and recomputes scales on resize.
45
+
46
+ ### Key Props
47
+
48
+ | Prop | Type | Description |
49
+ |------|------|-------------|
50
+ | `data` | array | The dataset. Each element is one data point |
51
+ | `x` | string / accessor | Key or function to extract the x value from each data point |
52
+ | `y` | string / accessor | Key or function to extract the y value |
53
+ | `z` | string / accessor | Optional third dimension (color, radius, category) |
54
+ | `r` | string / accessor | Optional radius/size dimension |
55
+ | `xScale` | d3 scale | Scale constructor for x axis (default: `scaleLinear`) |
56
+ | `yScale` | d3 scale | Scale constructor for y axis (default: `scaleLinear`) |
57
+ | `xDomain` | [min, max] | Override computed x domain |
58
+ | `yDomain` | [min, max] | Override computed y domain |
59
+ | `xRange` | [min, max] | Override x range (defaults to `[0, width]`) |
60
+ | `yRange` | [min, max] | Override y range (defaults to `[height, 0]` for SVG convention) |
61
+ | `padding` | object | `{ top, right, bottom, left }` in pixels |
62
+ | `xNice` | boolean | Round domain extents to nice values |
63
+ | `yNice` | boolean | Round domain extents to nice values |
64
+ | `flatData` | array | Pre-flattened data for domain calculation on nested/grouped datasets |
65
+
66
+ ---
67
+
68
+ ## Layout Components
69
+
70
+ Layout components create rendering contexts. Nest them inside `<LayerCake>` to composite multiple technologies:
71
+
72
+ | Component | Renders Into | Use Case |
73
+ |-----------|-------------|----------|
74
+ | `<Svg>` | `<svg>` element | Lines, areas, axes, annotations |
75
+ | `<Html>` | `<div>` overlay | Tooltips, labels, legends |
76
+ | `<Canvas>` | `<canvas>` element | Large point clouds, heatmaps, performance-critical rendering |
77
+ | `<WebGl>` | WebGL `<canvas>` | GPU-accelerated rendering for very large datasets |
78
+ | `<ScaledSvg>` | `<svg>` with viewBox | Resolution-independent SVG (PDF export, fixed coordinate space) |
79
+
80
+ Each layout component occupies the full chart area (respecting padding). Layers stack visually — SVG below, Canvas in the middle, HTML on top is a common arrangement.
81
+
82
+ ---
83
+
84
+ ## Context Values
85
+
86
+ Layer components (axes, lines, points) access chart context using `getContext('LayerCake')`. The context is a Svelte store containing:
87
+
88
+ ### Dimensions
89
+ - `width`, `height` — inner dimensions (after padding)
90
+ - `containerWidth`, `containerHeight` — outer dimensions
91
+
92
+ ### Scales
93
+ - `xScale`, `yScale`, `zScale`, `rScale` — configured d3 scale functions
94
+
95
+ ### Accessors
96
+ - `x`, `y`, `z`, `r` — accessor functions that extract values from data points
97
+
98
+ ### Convenience Getters
99
+ - `xGet(d)` — shorthand for `xScale(x(d))`, maps a data point to a pixel x position
100
+ - `yGet(d)` — shorthand for `yScale(y(d))`, maps to pixel y position
101
+ - `zGet(d)`, `rGet(d)` — same pattern for z and r dimensions
102
+
103
+ ### Data
104
+ - `data` — the dataset passed to LayerCake
105
+ - `flatData` — flattened version for domain calculation
106
+
107
+ ```svelte
108
+ <!-- Line.svelte (layer component) -->
109
+ <script>
110
+ import { getContext } from 'svelte';
111
+
112
+ const { data, xGet, yGet } = getContext('LayerCake');
113
+
114
+ // Build an SVG path from the data
115
+ $: path = 'M' + $data.map(d => `${$xGet(d)},${$yGet(d)}`).join('L');
116
+ </script>
117
+
118
+ <path d={path} fill="none" stroke="steelblue" stroke-width="2" />
119
+ ```
120
+
121
+ > Context values are Svelte stores. Access them with `$` prefix in layer components: `$data`, `$xGet`, `$yGet`, `$width`, etc.
122
+
123
+ ---
124
+
125
+ ## Helper Functions
126
+
127
+ | Function | Purpose |
128
+ |----------|---------|
129
+ | `calcExtents(data, keys)` | Calculate min/max extents for specified dimensions |
130
+ | `stack(data, keys)` | D3-compatible stack layout for area/bar charts |
131
+ | `groupLonger(data, keys)` | Pivot wide data to long format for multi-series charts |
132
+ | `scaleCanvas(canvas, ctx)` | Apply device pixel ratio scaling to a canvas context |
133
+ | `bin(data, accessor, options)` | Create histogram bins from continuous data |
134
+
135
+ ---
136
+
137
+ ## Runes Incompatibility
138
+
139
+ **LayerCake uses `export let` and Svelte stores internally.** This makes the library incompatible with Svelte 5's global runes mode.
140
+
141
+ ### The Problem
142
+
143
+ Enabling `runes: true` globally in `svelte.config.js` forces all components — including those inside `node_modules` — to use runes syntax. LayerCake's internal components use `export let` for props and `$:` reactive declarations, which are invalid in runes mode. The compiler will emit errors when processing LayerCake's source.
144
+
145
+ ### Workarounds
146
+
147
+ **Option A (recommended):** Do not enable global runes mode. Svelte 5 components can use runes without any config flag — runes are auto-detected per file. Global `runes: true` is unnecessary for application code and breaks libraries that have not migrated.
148
+
149
+ **Option B:** If the project requires global runes mode for other reasons, mark individual LayerCake wrapper components with per-component legacy mode:
150
+
151
+ ```svelte
152
+ <svelte:options runes={false} />
153
+ <!-- This component can use export let and $: safely -->
154
+ ```
155
+
156
+ This workaround applies only to the wrapper component that imports LayerCake. Child layer components authored by the developer can still use runes for their own logic — they access context stores with the `$` prefix as shown above.
157
+
158
+ ### Migration Status
159
+
160
+ LayerCake's runes migration is tracked in GitHub issue [#156](https://github.com/mhkeller/layercake/issues/156). Until the migration lands, treat LayerCake components as legacy-mode dependencies.
161
+
162
+ ### Layer Components and Runes
163
+
164
+ User-authored layer components (the components nested inside `<Svg>`, `<Html>`, etc.) can use runes for their own local state and derived values. The constraint applies only to LayerCake's own components (`<LayerCake>`, `<Svg>`, `<Html>`, `<Canvas>`, etc.) which live in `node_modules`.
165
+
166
+ However, context values from LayerCake are Svelte stores, not rune-based signals. Layer components must use the `$` store subscription syntax (`$data`, `$xGet`) regardless of whether they use runes for other state.
167
+
168
+ ---
169
+
170
+ ## Multi-Layer Composition
171
+
172
+ A common pattern layers SVG (for axes and lines), Canvas (for dense point rendering), and HTML (for interactive tooltips):
173
+
174
+ ```svelte
175
+ <script>
176
+ import { LayerCake, Svg, Canvas, Html } from 'layercake';
177
+ import AxisX from './AxisX.svelte';
178
+ import AxisY from './AxisY.svelte';
179
+ import Points from './Points.canvas.svelte';
180
+ import Tooltip from './Tooltip.svelte';
181
+
182
+ let data = [...];
183
+ </script>
184
+
185
+ <div class="chart-container" style="width: 100%; height: 400px;">
186
+ <LayerCake {data} x="date" y="value">
187
+ <Svg>
188
+ <AxisX />
189
+ <AxisY />
190
+ </Svg>
191
+ <Canvas>
192
+ <Points />
193
+ </Canvas>
194
+ <Html>
195
+ <Tooltip />
196
+ </Html>
197
+ </LayerCake>
198
+ </div>
199
+ ```
200
+
201
+ Each layout component creates its own rendering surface at the same dimensions. Layer components render independently — the SVG axes do not interfere with the Canvas points, and the HTML tooltip floats above both.
202
+
203
+ Canvas layer components receive the canvas context through `getContext('canvas')` and render in the `onMount` or `$effect` lifecycle. Call `scaleCanvas` to handle high-DPI displays.