@colletdev/docs 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.md ADDED
@@ -0,0 +1,53 @@
1
+ # Collet Documentation
2
+
3
+ 48 accessible web components built in Rust, compiled to WASM, distributed as
4
+ Custom Elements with first-class framework wrappers.
5
+
6
+ ## Packages
7
+
8
+ | Package | Description | Peer Dependencies |
9
+ |---------|-------------|-------------------|
10
+ | `@collet/core` | Custom Elements + WASM runtime + CSS tokens | — |
11
+ | `@collet/react` | React 18+ wrappers with typed refs and hooks | `react >= 18`, `@collet/core` |
12
+ | `@collet/vue` | Vue 3.3+ wrappers with Volar support | `vue >= 3.3`, `@collet/core` |
13
+ | `@collet/svelte` | Svelte 5 wrappers with runes and snippets | `svelte >= 5`, `@collet/core` |
14
+ | `@collet/angular` | Angular 16+ standalone wrappers with CVA | `@angular/core >= 16`, `@collet/core` |
15
+
16
+ ## Quick Start
17
+
18
+ ```bash
19
+ npm install @collet/core @collet/react # or vue/svelte/angular
20
+ ```
21
+
22
+ ```tsx
23
+ import { init } from '@collet/core';
24
+ import { Button } from '@collet/react';
25
+
26
+ await init();
27
+
28
+ <Button label="Click me" variant="filled" onClick={(e) => console.log(e.detail)} />
29
+ ```
30
+
31
+ ## Documentation Files
32
+
33
+ | File | Size | Contents |
34
+ |------|------|----------|
35
+ | [core.md](./core.md) | 22 KB | Initialization, theming, CSS architecture, SSR, events, slots, form integration |
36
+ | [components.md](./components.md) | 64 KB | All 48 components: multi-framework imports, props, events, methods, types |
37
+ | [react.md](./react.md) | 6 KB | React 18+ patterns: forwardRef, hooks, event callbacks, SSR |
38
+ | [vue.md](./vue.md) | 5 KB | Vue 3.3+ patterns: Composition API, Volar, expose(), slots |
39
+ | [svelte.md](./svelte.md) | 5 KB | Svelte 5 patterns: runes, callback props, snippets, migration |
40
+ | [angular.md](./angular.md) | 6 KB | Angular 16+ patterns: standalone, CVA, OnPush, template binding |
41
+
42
+ ## Generation
43
+
44
+ This documentation is auto-generated from the component manifest and kept
45
+ in sync by the build pipeline. Regenerate with:
46
+
47
+ ```bash
48
+ node scripts/generate-skill-docs.mjs
49
+ ```
50
+
51
+ ## License
52
+
53
+ MIT
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@colletdev/docs",
3
+ "version": "0.2.1",
4
+ "description": "Collet component library documentation — API reference, framework guides, and AI agent setup",
5
+ "type": "module",
6
+ "bin": {
7
+ "collet-docs": "./cli.mjs"
8
+ },
9
+ "exports": {
10
+ ".": "./index.md",
11
+ "./components": "./components.md",
12
+ "./react": "./react.md",
13
+ "./vue": "./vue.md",
14
+ "./svelte": "./svelte.md",
15
+ "./angular": "./angular.md",
16
+ "./core": "./core.md"
17
+ },
18
+ "files": [
19
+ "*.md",
20
+ "cli.mjs"
21
+ ],
22
+ "keywords": [
23
+ "collet",
24
+ "documentation",
25
+ "web-components",
26
+ "react",
27
+ "vue",
28
+ "svelte",
29
+ "angular",
30
+ "rust",
31
+ "wasm"
32
+ ],
33
+ "author": "Dan",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "https://github.com/Danrozen87/collet",
38
+ "directory": "packages/docs"
39
+ }
40
+ }
package/react.md ADDED
@@ -0,0 +1,290 @@
1
+ # Collet React Reference
2
+
3
+ React wrappers for the Collet component library. Auto-generated from
4
+ `custom-elements.json` via `scripts/generate-react.mjs`.
5
+
6
+ ---
7
+
8
+ ## Package
9
+
10
+ ```
11
+ @colletdev/react
12
+ ```
13
+
14
+ **Peer dependencies:** `react >= 18.0.0`, `@colletdev/core >= 0.1.0`
15
+
16
+ ## Architecture
17
+
18
+ React wrappers are thin `forwardRef` components that render the underlying
19
+ `<cx-*>` Custom Element. They handle:
20
+
21
+ - **Attribute serialization** — objects/arrays go through `JSON.stringify`
22
+ - **Event bridging** — `on{Event}` props attach listeners for `cx-{event}` CustomEvents
23
+ - **Slot projection** — named slots via `<div slot="name" style={{display:'contents'}}>`
24
+ - **Typed imperative refs** — `useImperativeHandle` exposes typed methods
25
+
26
+ ### Package Structure
27
+
28
+ ```
29
+ packages/react/
30
+ generated/ ← Auto-generated wrappers (DO NOT EDIT)
31
+ button.tsx
32
+ dialog.tsx
33
+ ...
34
+ index.ts ← Barrel exports
35
+ types.ts ← Shared TypeScript interfaces
36
+ elements.d.ts ← JSX IntrinsicElements augmentation
37
+ dist/ ← Compiled output (JS + .d.ts)
38
+ ```
39
+
40
+ ---
41
+
42
+ ## Patterns
43
+
44
+ ### Basic Usage
45
+
46
+ ```tsx
47
+ import { Button, Dialog, type DialogRef } from '@colletdev/react';
48
+
49
+ function App() {
50
+ const dialogRef = useRef<DialogRef>(null);
51
+
52
+ return (
53
+ <>
54
+ <Button label="Open" onClick={() => dialogRef.current?.open()} />
55
+ <Dialog
56
+ ref={dialogRef}
57
+ title="Confirm"
58
+ onClose={(e) => console.log(e.detail.reason)}
59
+ footer={<Button label="OK" variant="filled" />}
60
+ >
61
+ <p>Are you sure?</p>
62
+ </Dialog>
63
+ </>
64
+ );
65
+ }
66
+ ```
67
+
68
+ ### Event Callbacks
69
+
70
+ All events use `on{PascalEvent}` naming. The callback receives a `CustomEvent<Detail>`:
71
+
72
+ ```tsx
73
+ <TextInput
74
+ label="Email"
75
+ onInput={(e) => setValue(e.detail.value)} // InputDetail
76
+ onChange={(e) => validate(e.detail.value)} // InputDetail
77
+ onFocus={(e) => setFocused(true)} // FocusDetail
78
+ onKeydown={(e) => { // KeyboardDetail
79
+ if (e.detail.key === 'Enter') submit();
80
+ }}
81
+ />
82
+ ```
83
+
84
+ ### Overlays (Dialog, Drawer)
85
+
86
+ Overlays support both declarative and imperative control. **Always keep them
87
+ mounted** — never conditionally render with `{show && <Dialog>}`. This matches
88
+ MUI, Radix, Ant Design, and every major React UI library.
89
+
90
+ **Declarative (recommended):**
91
+
92
+ ```tsx
93
+ const [open, setOpen] = useState(false);
94
+
95
+ <Button label="Open" onClick={() => setOpen(true)} />
96
+ <Dialog
97
+ open={open}
98
+ onClose={() => setOpen(false)}
99
+ title="Confirm"
100
+ footer={<Button label="OK" variant="filled" onClick={() => setOpen(false)} />}
101
+ >
102
+ <p>Are you sure?</p>
103
+ </Dialog>
104
+ ```
105
+
106
+ **Imperative (ref-based):**
107
+
108
+ ```tsx
109
+ const ref = useRef<DialogRef>(null);
110
+
111
+ <Button label="Open" onClick={() => ref.current?.open()} />
112
+ <Dialog ref={ref} title="Confirm" onClose={() => console.log('closed')}>
113
+ <p>Are you sure?</p>
114
+ </Dialog>
115
+ ```
116
+
117
+ Both patterns work for Dialog and Drawer. The component owns its animation
118
+ lifecycle — open/close transitions play fully without being interrupted by
119
+ React state changes.
120
+
121
+ **Do NOT conditionally render overlays:**
122
+
123
+ ```tsx
124
+ // WRONG — unmounting kills exit animation, breaks accessibility
125
+ {isOpen && <Drawer open title="Settings">...</Drawer>}
126
+
127
+ // CORRECT — always mounted, visibility controlled by open prop
128
+ <Drawer open={isOpen} onClose={() => setIsOpen(false)} title="Settings">...</Drawer>
129
+ ```
130
+
131
+ ### Imperative Refs
132
+
133
+ Components with `open/close/focus` methods expose typed refs:
134
+
135
+ ```tsx
136
+ import { Select, type SelectRef } from '@colletdev/react';
137
+
138
+ const ref = useRef<SelectRef>(null);
139
+ ref.current?.open(); // Opens dropdown
140
+ ref.current?.close(); // Closes dropdown
141
+ ref.current?.focus(); // Focuses trigger
142
+ ```
143
+
144
+ ### Named Slots
145
+
146
+ Named slots use React props that accept `ReactNode`:
147
+
148
+ ```tsx
149
+ <Card
150
+ header={<h3>Title</h3>}
151
+ footer={<Button label="Action" />}
152
+ >
153
+ <p>Body content (default slot)</p>
154
+ </Card>
155
+ ```
156
+
157
+ Under the hood, these render as `<div slot="name" style={{display:'contents'}}>`.
158
+
159
+ ### Complex Props (Structured Data)
160
+
161
+ Props that accept arrays/objects are serialized to JSON attributes via `useEffect`:
162
+
163
+ ```tsx
164
+ <Table
165
+ caption="Users"
166
+ columns={[
167
+ { id: 'name', header: 'Name', sortable: true },
168
+ { id: 'email', header: 'Email' },
169
+ ]}
170
+ rows={[
171
+ { id: '1', cells: { name: 'Alice', email: 'alice@example.com' } },
172
+ ]}
173
+ sorts={[{ column_id: 'name', direction: 'asc' }]}
174
+ onSort={(e) => handleSort(e.detail)}
175
+ />
176
+ ```
177
+
178
+ ### Form Integration
179
+
180
+ Form-associated components work with uncontrolled forms via `name` prop:
181
+
182
+ ```tsx
183
+ <form onSubmit={handleSubmit}>
184
+ <TextInput name="email" label="Email" required />
185
+ <Select name="country" label="Country" items={countries} />
186
+ <Button label="Submit" kind="submit" />
187
+ </form>
188
+ ```
189
+
190
+ For controlled forms, use event callbacks:
191
+
192
+ ```tsx
193
+ const [value, setValue] = useState('');
194
+ <TextInput
195
+ label="Name"
196
+ value={value}
197
+ onInput={(e) => setValue(e.detail.value)}
198
+ />
199
+ ```
200
+
201
+ ### DOM Collision Handling
202
+
203
+ React 19 sets DOM properties directly on Custom Elements. The wrappers
204
+ automatically route these through `useEffect` + `setAttribute`:
205
+
206
+ - **HTML properties** (`title`, `width`, `loading`, `role`) — bypasses HTMLElement property setters
207
+ - **Form properties** (`name`, `value`, `type`) — on form components (TextInput, Select, Slider, etc.)
208
+ - **Numeric attributes** (`lines`, `min`, `max`, `step`, `duration`, `currentPage`, etc.) — ensures `attributeChangedCallback` fires for `_numericAttrs` coercion
209
+ - **Complex data** (`columns`, `rows`, `items`, etc.) — JSON-serialized objects/arrays
210
+
211
+ ```tsx
212
+ // All of these work correctly — routed through setAttribute automatically
213
+ <Dialog title="My Dialog" />
214
+ <Slider min={0} max={100} step={5} value={50} />
215
+ <Skeleton variant="text" lines={3} />
216
+ <Pagination currentPage={1} pageSize={10} totalItems={100} />
217
+ ```
218
+
219
+ No special handling needed from consumers.
220
+
221
+ ### Markdown Support
222
+
223
+ ```tsx
224
+ import { useMarkdown } from '@colletdev/react';
225
+ import { MessagePart, type MessagePartRef } from '@colletdev/react';
226
+
227
+ // Static markdown
228
+ const html = useMarkdown('**Hello** world');
229
+
230
+ // Streaming markdown (AI chat)
231
+ const { ref, startStream, appendTokens, endStream } = useMarkdownStream();
232
+ <MessagePart ref={ref} stream />
233
+ ```
234
+
235
+ ### Server Rendering
236
+
237
+ ```tsx
238
+ // Next.js App Router — Server Component
239
+ import { createRenderer } from '@colletdev/core/server';
240
+
241
+ export default async function Page() {
242
+ const cx = await createRenderer();
243
+ const buttonHtml = cx.renderDSD('button', { label: 'Click', id: 'btn-1' });
244
+ return <div dangerouslySetInnerHTML={{ __html: buttonHtml }} />;
245
+ }
246
+ ```
247
+
248
+ ---
249
+
250
+ ## TypeScript
251
+
252
+ All props, events, and ref types are fully typed. Import types from `@colletdev/react`:
253
+
254
+ ```tsx
255
+ import type {
256
+ // Structured data props
257
+ TableColumn, TableRow, SelectOption, MenuEntry,
258
+ // Event details
259
+ InputDetail, ClickDetail, CloseDetail,
260
+ // Ref types (from component exports)
261
+ DialogRef, SelectRef, TextInputRef,
262
+ } from '@colletdev/react';
263
+ ```
264
+
265
+ ### JSX IntrinsicElements
266
+
267
+ `@colletdev/react` augments `JSX.IntrinsicElements` with all `cx-*` elements
268
+ for direct Custom Element usage when wrappers aren't needed:
269
+
270
+ ```tsx
271
+ // Works with full type checking
272
+ <cx-button label="Raw CE" variant="filled" />
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Codegen
278
+
279
+ React wrappers are generated by `scripts/generate-react.mjs`. Configuration
280
+ lives in both the React generator (inline maps) and `scripts/component-config.mjs`
281
+ (shared across all framework generators).
282
+
283
+ **Do not edit** files in `packages/react/generated/` — they are overwritten
284
+ by `bash scripts/build-packages.sh`.
285
+
286
+ Custom files (preserved by codegen):
287
+ - `generated/message-part.tsx` — streaming markdown support
288
+ - `generated/use-markdown.ts` — `useMarkdown()` hook
289
+ - `generated/use-markdown-stream.ts` — `useMarkdownStream()` hook
290
+ - `generated/drawer.tsx` — custom drawer implementation
package/svelte.md ADDED
@@ -0,0 +1,234 @@
1
+ # Collet Svelte Reference
2
+
3
+ Svelte 5 wrappers for the Collet component library. Auto-generated from
4
+ `custom-elements.json` via `scripts/generate-svelte.mjs`.
5
+
6
+ ---
7
+
8
+ ## Package
9
+
10
+ ```
11
+ @colletdev/svelte
12
+ ```
13
+
14
+ **Peer dependencies:** `svelte >= 5.0.0`, `@colletdev/core >= 0.1.0`
15
+
16
+ Ships raw `.svelte` source files — consumers compile with their own Svelte toolchain.
17
+
18
+ ## Architecture
19
+
20
+ Svelte wrappers use Svelte 5 runes (`$props`, `$effect`) for reactive prop
21
+ syncing and event bridging. They handle:
22
+
23
+ - **Attribute serialization** — objects/arrays synced via `$effect` + `setAttribute`
24
+ - **Event bridging** — callback props (`onClick`, `onChange`) wired via `$effect` listeners
25
+ - **Slot projection** — `{@render children?.()}` for default, `{@render footer?.()}` for named
26
+ - **Imperative methods** — `export function open()` exposed to consumers
27
+
28
+ ### Package Structure
29
+
30
+ ```
31
+ packages/svelte/
32
+ src/ ← Auto-generated wrappers (DO NOT EDIT)
33
+ button.svelte
34
+ button.svelte.d.ts
35
+ dialog.svelte
36
+ dialog.svelte.d.ts
37
+ ...
38
+ index.ts ← Barrel exports + type re-exports
39
+ types.ts ← Shared TypeScript interfaces
40
+ elements.d.ts ← SvelteHTMLElements augmentation
41
+ ```
42
+
43
+ ---
44
+
45
+ ## Patterns
46
+
47
+ ### Basic Usage
48
+
49
+ ```svelte
50
+ <script lang="ts">
51
+ import Button from '@colletdev/svelte/button.svelte';
52
+ import Dialog from '@colletdev/svelte/dialog.svelte';
53
+
54
+ let dialog: { open: () => void; close: () => void };
55
+ </script>
56
+
57
+ <Button label="Open" onClick={() => dialog.open()} />
58
+ <Dialog
59
+ bind:this={dialog}
60
+ title="Confirm"
61
+ onClose={(e) => console.log(e.detail.reason)}
62
+ >
63
+ <p>Are you sure?</p>
64
+ {#snippet footer()}
65
+ <Button label="OK" variant="filled" />
66
+ {/snippet}
67
+ </Dialog>
68
+ ```
69
+
70
+ ### Event Callbacks
71
+
72
+ Svelte 5 uses callback props instead of `on:event` directives:
73
+
74
+ ```svelte
75
+ <TextInput
76
+ label="Email"
77
+ onInput={(e) => value = e.detail.value}
78
+ onChange={(e) => validate(e.detail.value)}
79
+ onFocus={(e) => focused = true}
80
+ onKeydown={(e) => {
81
+ if (e.detail.key === 'Enter') submit();
82
+ }}
83
+ />
84
+ ```
85
+
86
+ Callback props are typed: `(event: CustomEvent<InputDetail>) => void`.
87
+
88
+ ### Imperative Methods
89
+
90
+ Components expose methods via `export function`. Access through `bind:this`:
91
+
92
+ ```svelte
93
+ <script lang="ts">
94
+ import Select from '@colletdev/svelte/select.svelte';
95
+
96
+ let select: { open: () => void; close: () => void; focus: () => void };
97
+ </script>
98
+
99
+ <Select bind:this={select} label="Country" items={countries} />
100
+ <button onclick={() => select.open()}>Open dropdown</button>
101
+ ```
102
+
103
+ ### Named Slots (Snippets)
104
+
105
+ Svelte 5 uses `{#snippet}` for named slots:
106
+
107
+ ```svelte
108
+ <Card>
109
+ {#snippet header()}
110
+ <h3>Title</h3>
111
+ {/snippet}
112
+
113
+ <p>Body content (default slot via children)</p>
114
+
115
+ {#snippet footer()}
116
+ <Button label="Action" />
117
+ {/snippet}
118
+ </Card>
119
+ ```
120
+
121
+ The wrapper renders snippets inside `<div slot="name">` wrappers for
122
+ Shadow DOM slot projection.
123
+
124
+ ### Complex Props (Structured Data)
125
+
126
+ Props accepting arrays/objects are synced via `$effect` + `setAttribute(JSON.stringify())`:
127
+
128
+ ```svelte
129
+ <Table
130
+ caption="Users"
131
+ columns={[
132
+ { id: 'name', header: 'Name', sortable: true },
133
+ { id: 'email', header: 'Email' },
134
+ ]}
135
+ rows={rows}
136
+ sorts={[{ column_id: 'name', direction: 'asc' }]}
137
+ onSort={(e) => handleSort(e.detail)}
138
+ />
139
+ ```
140
+
141
+ ### Form Integration
142
+
143
+ ```svelte
144
+ <form onsubmit={handleSubmit}>
145
+ <TextInput name="email" label="Email" required />
146
+ <Select name="country" label="Country" items={countries} />
147
+ <Button label="Submit" kind="submit" />
148
+ </form>
149
+ ```
150
+
151
+ ### DOM Collision Handling
152
+
153
+ Attributes like `title`, `width`, `loading` are routed through `$effect` +
154
+ `setAttribute` to avoid Svelte setting them as DOM properties:
155
+
156
+ ```svelte
157
+ <!-- Works correctly -->
158
+ <Dialog title="My Dialog" />
159
+ <Table loading={75} />
160
+ ```
161
+
162
+ ---
163
+
164
+ ## TypeScript
165
+
166
+ ### Type Imports
167
+
168
+ ```ts
169
+ import type {
170
+ TableColumn, TableRow, SelectOption, MenuEntry,
171
+ InputDetail, ClickDetail, CloseDetail,
172
+ } from '@colletdev/svelte';
173
+ ```
174
+
175
+ ### Component Types
176
+
177
+ Each `.svelte` file has a `.svelte.d.ts` companion with full prop types:
178
+
179
+ ```ts
180
+ import type { Component } from 'svelte';
181
+
182
+ interface ButtonProps {
183
+ label?: string;
184
+ variant?: 'filled' | 'ghost' | 'outline' | 'underline' | 'side-indicator';
185
+ // ... all props typed
186
+ onClick?: (event: CustomEvent<ClickDetail>) => void;
187
+ }
188
+
189
+ declare const Button: Component<ButtonProps, { /* exports */ }>;
190
+ ```
191
+
192
+ ### SvelteHTMLElements Augmentation
193
+
194
+ `@colletdev/svelte` augments `SvelteHTMLElements` for direct Custom Element usage:
195
+
196
+ ```svelte
197
+ <!-- Type-checked cx-* elements -->
198
+ <cx-button label="Raw CE" variant="filled" />
199
+ ```
200
+
201
+ Import the augmentation in `app.d.ts`:
202
+
203
+ ```ts
204
+ /// <reference types="@colletdev/svelte/elements" />
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Svelte 5 Migration Notes
210
+
211
+ The wrappers are Svelte 5 native. Key differences from Svelte 4:
212
+
213
+ | Svelte 4 | Svelte 5 (Collet) |
214
+ |----------|-------------------|
215
+ | `export let prop` | `let { prop } = $props()` |
216
+ | `on:click` | `onclick` callback prop |
217
+ | `<slot />` | `{@render children?.()}` |
218
+ | `<slot name="x" />` | `{@render x?.()}` |
219
+ | `onMount(() => {})` | `$effect(() => { ... })` |
220
+ | `$: derived` | `let derived = $derived(...)` |
221
+ | `SvelteComponent` | `Component` type |
222
+ | `createEventDispatcher` | Callback props |
223
+
224
+ ---
225
+
226
+ ## Codegen
227
+
228
+ Svelte wrappers are generated by `scripts/generate-svelte.mjs`. Configuration
229
+ lives in `scripts/component-config.mjs` (shared across all framework generators).
230
+
231
+ **Do not edit** files in `packages/svelte/src/` — they are overwritten by
232
+ `bash scripts/build-packages.sh`.
233
+
234
+ Raw source ships to consumers (no pre-compilation needed).