@wc-toolkit/svelte-types 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 WC Toolkit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,440 @@
1
+ <div align="center">
2
+
3
+ ![workbench with tools, html, css, javascript, and svelte logos](https://raw.githubusercontent.com/wc-toolkit/jsx-types/refs/heads/main/assets/wc-toolkit_svelte.png)
4
+
5
+ </div>
6
+
7
+ # WC Toolkit Custom Element Svelte Types Generator
8
+
9
+ This package generates TypeScript declarations for custom elements used in [Svelte](https://svelte.dev/) projects. The generated declarations provide type-safe validation for component attributes, component properties, custom events, and CSS custom properties.
10
+
11
+ Types are generated for all custom elements defined in a [Custom Elements Manifest](https://custom-elements-manifest.open-wc.org/).
12
+
13
+ Generated declarations include:
14
+
15
+ - Custom element names and component descriptions
16
+ - Attributes and their manifest types
17
+ - Component properties passed through Svelte attributes
18
+ - Custom event handlers using Svelte's `on:` syntax
19
+ - Global element properties and optional DOM event handlers
20
+ - CSS custom properties
21
+ - Documentation for methods, slots, CSS parts, and CSS states
22
+
23
+ ## Usage
24
+
25
+ This package supports two generation workflows:
26
+
27
+ 1. Calling a function in your build pipeline
28
+ 2. Using a plugin for the [Custom Element Manifest Analyzer](https://custom-elements-manifest.open-wc.org/)
29
+
30
+ ### Install
31
+
32
+ ```bash
33
+ npm install --save-dev @wc-toolkit/svelte-types
34
+ ```
35
+
36
+ ### Build Pipeline
37
+
38
+ ```ts
39
+ import {
40
+ generateSvelteTypes,
41
+ type SvelteTypesOptions,
42
+ } from "@wc-toolkit/svelte-types";
43
+ import manifest from "./custom-elements.json";
44
+
45
+ const options: SvelteTypesOptions = {
46
+ outdir: "./src",
47
+ fileName: "custom-elements-svelte.d.ts",
48
+ };
49
+
50
+ generateSvelteTypes(manifest, options);
51
+ ```
52
+
53
+ ### CEM Analyzer
54
+
55
+ #### Setup
56
+
57
+ Ensure the following steps have been completed before using the plugin:
58
+
59
+ - Install and configure the [Custom Elements Manifest Analyzer](https://custom-elements-manifest.open-wc.org/analyzer/getting-started/)
60
+ - Create a [manifest configuration file](https://custom-elements-manifest.open-wc.org/analyzer/config/#config-file)
61
+
62
+ #### Import
63
+
64
+ ```js
65
+ // custom-elements-manifest.config.js
66
+ import { customElementSveltePlugin } from "@wc-toolkit/svelte-types";
67
+
68
+ export default {
69
+ plugins: [
70
+ customElementSveltePlugin({
71
+ outdir: "./src",
72
+ fileName: "custom-elements-svelte.d.ts",
73
+ }),
74
+ ],
75
+ };
76
+ ```
77
+
78
+ ## Implementation
79
+
80
+ The generated file declares `svelteHTML.IntrinsicElements`, so Svelte projects only need to include the file in their TypeScript project.
81
+
82
+ ### Option 1: Include the Generated File
83
+
84
+ Write the generated file somewhere covered by your `tsconfig.json`:
85
+
86
+ ```json
87
+ {
88
+ "include": [
89
+ "src/**/*.ts",
90
+ "src/**/*.svelte",
91
+ "src/custom-elements-svelte.d.ts"
92
+ ]
93
+ }
94
+ ```
95
+
96
+ ### Option 2: Configure TypeScript Types
97
+
98
+ If the generated declaration is published by a package, add its path to `tsconfig.json`:
99
+
100
+ ```json
101
+ {
102
+ "compilerOptions": {
103
+ "types": ["my-library/custom-elements-svelte"]
104
+ }
105
+ }
106
+ ```
107
+
108
+ The generated declarations can then be used directly in Svelte markup:
109
+
110
+ ```svelte
111
+ <x-button
112
+ label="Save"
113
+ value={value}
114
+ on:change={handleChange}
115
+ />
116
+ ```
117
+
118
+ ## Configuration Options
119
+
120
+ The `SvelteTypesOptions` type provides configuration options for the generator.
121
+
122
+ ### Output Options
123
+
124
+ #### `fileName`
125
+
126
+ - **Type:** `string`
127
+ - **Default:** `"custom-elements-svelte.d.ts"`
128
+ - **Description:** Name of the generated declaration file. If omitted or set to `undefined`, the generator returns the declaration text without writing a file.
129
+
130
+ ```ts
131
+ {
132
+ fileName: "my-components.d.ts";
133
+ }
134
+ ```
135
+
136
+ #### `outdir`
137
+
138
+ - **Type:** `string`
139
+ - **Default:** `"./"`
140
+ - **Description:** Directory where the generated declaration file is written.
141
+
142
+ ```ts
143
+ {
144
+ outdir: "./src/types";
145
+ }
146
+ ```
147
+
148
+ #### `exclude`
149
+
150
+ - **Type:** `string[]`
151
+ - **Default:** `[]`
152
+ - **Description:** Component class names to exclude from generation.
153
+
154
+ ```ts
155
+ {
156
+ exclude: ["InternalComponent", "DeprecatedComponent"];
157
+ }
158
+ ```
159
+
160
+ ### Import Options
161
+
162
+ #### `componentTypePath`
163
+
164
+ - **Type:** `(name: string, tag?: string, modulePath?: string) => string`
165
+ - **Description:** Returns the module path used to import each component class. The third argument is the component's source module path from the manifest. When configured, generated attributes reference the imported component class properties.
166
+
167
+ ```ts
168
+ {
169
+ componentTypePath: (name, tagName) =>
170
+ `my-library/components/${tagName}/${tagName}.js`;
171
+ }
172
+ ```
173
+
174
+ The generated declaration expects named component exports:
175
+
176
+ ```ts
177
+ import type { XButton } from "my-library/components/x-button/x-button.js";
178
+ ```
179
+
180
+ #### `globalTypePath`
181
+
182
+ - **Type:** `string`
183
+ - **Description:** Imports all component classes and named event detail types from one module instead of generating per-component import paths.
184
+
185
+ ```ts
186
+ {
187
+ globalTypePath: "my-library/types";
188
+ }
189
+ ```
190
+
191
+ When `globalTypePath` or `componentTypePath` is not configured, types are read directly from the manifest.
192
+
193
+ ### Event Options
194
+
195
+ #### `globalEvents`
196
+
197
+ - **Type:** `string`
198
+ - **Description:** Adds custom event declarations to every generated component type.
199
+
200
+ ```ts
201
+ {
202
+ globalEvents: `
203
+ /** Fired when application telemetry is recorded. */
204
+ "on:telemetry"?: (event: CustomEvent<TelemetryDetail>) => void;
205
+ `;
206
+ }
207
+ ```
208
+
209
+ #### `includeDefaultDOMEvents`
210
+
211
+ - **Type:** `boolean`
212
+ - **Default:** `false`
213
+ - **Description:** Adds common DOM event handlers such as `on:click`, `onclick`, `on:focus`, and `onfocus` to every component. Enable this only when those handlers are useful for your component API.
214
+
215
+ ```ts
216
+ {
217
+ includeDefaultDOMEvents: true;
218
+ }
219
+ ```
220
+
221
+ #### `includeModernEventHandlers`
222
+
223
+ - **Type:** `boolean`
224
+ - **Default:** `true`
225
+ - **Description:** Includes Svelte 5 event attributes such as `onclick` alongside legacy `on:` handlers. Set to `false` when supporting only the legacy event directive syntax.
226
+
227
+ ```ts
228
+ {
229
+ includeModernEventHandlers: true;
230
+ }
231
+ ```
232
+
233
+ Custom events from the manifest are generated using Svelte's legacy event directive syntax and, by default, Svelte 5 event attributes:
234
+
235
+ ```svelte
236
+ <x-button on:change={handleChange} />
237
+ <x-button onchange={handleChange} />
238
+ ```
239
+
240
+ For a manifest event typed as `CustomEvent<ChangeDetail>`, the generated handlers are:
241
+
242
+ ```ts
243
+ "on:change"?: (e: CustomEvent<ChangeDetail>) => void;
244
+ "onchange"?: (e: CustomEvent<ChangeDetail>) => void;
245
+ ```
246
+
247
+ Non-custom event types from the manifest are preserved. For example, an event typed as `MouseEvent` generates a `MouseEvent` handler rather than wrapping it in `CustomEvent`.
248
+
249
+ ### Manifest Type Options
250
+
251
+ #### `typesSrc`
252
+
253
+ - **Type:** `string`
254
+ - **Description:** Reads types from an alternate property on CEM attributes or properties, such as `parsedType`. If not provided, the standard `type` field is used.
255
+
256
+ ```ts
257
+ {
258
+ typesSrc: "parsedType";
259
+ }
260
+ ```
261
+
262
+ This is useful when another CEM plugin adds parsed or transformed type information:
263
+
264
+ ```json
265
+ {
266
+ "name": "variant",
267
+ "type": { "text": "ButtonVariant" },
268
+ "parsedType": { "text": "\"primary\" | \"secondary\"" }
269
+ }
270
+ ```
271
+
272
+ ### Tag Formatting
273
+
274
+ #### `tagFormatter`
275
+
276
+ - **Type:** `(tagName: string) => string`
277
+ - **Description:** Formats tag names before they are added to `CustomElements`.
278
+
279
+ ```ts
280
+ {
281
+ tagFormatter: (tagName) => tagName.replace("my-", "custom-");
282
+ }
283
+ ```
284
+
285
+ ### Utility Options
286
+
287
+ #### `skip`
288
+
289
+ - **Type:** `boolean`
290
+ - **Default:** `false`
291
+ - **Description:** Prevents generation when `true`.
292
+
293
+ ```ts
294
+ {
295
+ skip: process.env.SKIP_TYPES === "true";
296
+ }
297
+ ```
298
+
299
+ #### `debug`
300
+
301
+ - **Type:** `boolean`
302
+ - **Default:** `false`
303
+ - **Description:** Enables generator logs.
304
+
305
+ ```ts
306
+ {
307
+ debug: true;
308
+ }
309
+ ```
310
+
311
+ #### `componentDescriptionOptions`
312
+
313
+ - **Type:** `ComponentDescriptionOptions`
314
+ - **Description:** Configures the component documentation rendered into the generated declaration file, including description source and API order.
315
+
316
+ ```ts
317
+ {
318
+ componentDescriptionOptions: {
319
+ descriptionSrc: "summary",
320
+ order: ["attrsAndProps", "events", "slots", "methods", "cssProps"]
321
+ }
322
+ }
323
+ ```
324
+
325
+ ## Svelte Features
326
+
327
+ ### Component Properties
328
+
329
+ Public component properties are generated as typed component attributes. This is the valid way to pass values to lowercase custom elements in Svelte:
330
+
331
+ ```svelte
332
+ <x-slider value={value} />
333
+ ```
334
+
335
+ Read-only and static properties are excluded. When a CEM property is associated with an attribute, it is emitted once using the attribute name.
336
+
337
+ ### Custom Events
338
+
339
+ Manifest events are available through `on:` handlers:
340
+
341
+ ```svelte
342
+ <x-input
343
+ on:change={(event) => {
344
+ console.log(event.detail);
345
+ }}
346
+ />
347
+ ```
348
+
349
+ Named event detail types are imported automatically when the component type path is configured.
350
+
351
+ ### CSS Custom Properties
352
+
353
+ CEM CSS custom properties are generated as Svelte style directives and accept `string | number` values:
354
+
355
+ ```svelte
356
+ <x-slider style:--track-color={trackColor} />
357
+ ```
358
+
359
+ Svelte applies these values through its CSS custom-property wrapper. The generated declaration includes the property as:
360
+
361
+ ```ts
362
+ "style:--track-color"?: string | number;
363
+ ```
364
+
365
+ ### Slots
366
+
367
+ Slot metadata is included in the generated component documentation. Web component slots are used with Svelte's standard `slot` attribute:
368
+
369
+ ```svelte
370
+ <x-card>
371
+ <span slot="title">Card title</span>
372
+ Card content
373
+ </x-card>
374
+ ```
375
+
376
+ ### Refs and Methods
377
+
378
+ The generator exports a `*Element` type for each component. When component type imports are configured, this aliases the imported class. Otherwise, it includes method signatures found in the manifest. Use it with Svelte's `bind:this`:
379
+
380
+ ```svelte
381
+ <script lang="ts">
382
+ import type { DialogElement } from "./types/custom-elements-svelte";
383
+
384
+ let dialog: DialogElement;
385
+
386
+ function openDialog() {
387
+ dialog.showModal();
388
+ }
389
+ </script>
390
+
391
+ <x-dialog bind:this={dialog} />
392
+ <button onclick={openDialog}>Open</button>
393
+ ```
394
+
395
+ Named CEM slots also produce a slot-name union for application code:
396
+
397
+ ```ts
398
+ import type { CardSlots } from "./types/custom-elements-svelte";
399
+
400
+ const slotName: CardSlots = "header";
401
+ ```
402
+
403
+ ## Complete Configuration Example
404
+
405
+ ```ts
406
+ import { generateSvelteTypes } from "@wc-toolkit/svelte-types";
407
+ import manifest from "./custom-elements.json";
408
+
409
+ generateSvelteTypes(manifest, {
410
+ // Output
411
+ fileName: "custom-elements-svelte.d.ts",
412
+ outdir: "./src/types",
413
+
414
+ // Component filtering
415
+ exclude: ["InternalComponent"],
416
+
417
+ // Type imports
418
+ componentTypePath: (name, tagName) =>
419
+ `my-library/components/${tagName}/${tagName}.js`,
420
+
421
+ // Events
422
+ includeDefaultDOMEvents: true,
423
+ globalEvents: `
424
+ "on:telemetry"?: (event: CustomEvent<TelemetryDetail>) => void;
425
+ `,
426
+
427
+ // Manifest types and tag names
428
+ typesSrc: "parsedType",
429
+ tagFormatter: (tagName) => tagName.toLowerCase(),
430
+
431
+ // Component documentation and development
432
+ componentDescriptionOptions: {
433
+ descriptionSrc: "summary",
434
+ },
435
+ debug: process.env.DEBUG === "true",
436
+ skip: false,
437
+ });
438
+ ```
439
+
440
+ For more information about this package and other Web Component tools, visit the [WC Toolkit website](https://wc-toolkit.com).