sveld 0.28.0 → 0.29.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/README.md +587 -135
- package/lib/ComponentParser.d.ts +56 -7
- package/lib/index.js +146 -146
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -3,13 +3,22 @@
|
|
|
3
3
|
[![NPM][npm]][npm-url]
|
|
4
4
|

|
|
5
5
|
|
|
6
|
-
`sveld`
|
|
6
|
+
`sveld` generates TypeScript definitions and component documentation (Markdown/JSON) for Svelte components. It analyzes props, events, slots, and other component features through static analysis. Types and signatures can be defined using [JSDoc notation](https://jsdoc.app/).
|
|
7
7
|
|
|
8
|
-
The purpose of this project is to make third party Svelte component libraries compatible with the Svelte Language Server and TypeScript with minimal effort required by the author. For example, TypeScript definitions may be used during development via intelligent code completion in Integrated Development Environments (
|
|
8
|
+
The purpose of this project is to make third party Svelte component libraries compatible with the Svelte Language Server and TypeScript with minimal effort required by the author. For example, TypeScript definitions may be used during development via intelligent code completion in Integrated Development Environments (IDEs) like VSCode.
|
|
9
9
|
|
|
10
10
|
[Carbon Components Svelte](https://github.com/carbon-design-system/carbon-components-svelte) uses this library to auto-generate component types and API metadata.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
`sveld` uses the Svelte 5 compiler to parse `.svelte` files. That single parse path powers docgen and TypeScript output for Svelte 3, Svelte 4, Svelte 5 without runes (`export let`, `<slot>`, `$$restProps`, …), and Svelte 5 Runes (`$props()`, `$bindable()`, `{@render ...}`, callback props such as `onclick`, …).
|
|
13
|
+
|
|
14
|
+
| Syntax mode | Supported |
|
|
15
|
+
| :------------------- | :-------: |
|
|
16
|
+
| Svelte 3 | ✓ |
|
|
17
|
+
| Svelte 4 | ✓ |
|
|
18
|
+
| Svelte 5 (non-Runes) | ✓ |
|
|
19
|
+
| Svelte 5 Runes | ✓ |
|
|
20
|
+
|
|
21
|
+
**Note** that generated `.d.ts` files extend `SvelteComponentTyped` from `svelte`, so TypeScript and the Svelte Language Server work whether consumers use Svelte 3, Svelte 4, or Svelte 5.
|
|
13
22
|
|
|
14
23
|
---
|
|
15
24
|
|
|
@@ -28,7 +37,7 @@ Given a Svelte component, `sveld` can infer basic prop types to generate TypeScr
|
|
|
28
37
|
</button>
|
|
29
38
|
```
|
|
30
39
|
|
|
31
|
-
The generated
|
|
40
|
+
The following generated `.d.ts` extends `SvelteComponentTyped`:
|
|
32
41
|
|
|
33
42
|
**Button.svelte.d.ts**
|
|
34
43
|
|
|
@@ -120,7 +129,7 @@ export default class Button extends SvelteComponentTyped<
|
|
|
120
129
|
- [@type](#type)
|
|
121
130
|
- [@typedef](#typedef)
|
|
122
131
|
- [@callback](#callback)
|
|
123
|
-
- [@slot](#slot)
|
|
132
|
+
- [@slot / @snippet](#slot--snippet)
|
|
124
133
|
- [Svelte 5 Snippet Compatibility](#svelte-5-snippet-compatibility)
|
|
125
134
|
- [@event](#event)
|
|
126
135
|
- [Context API](#context-api)
|
|
@@ -310,6 +319,23 @@ sveld({
|
|
|
310
319
|
|
|
311
320
|
## API Reference
|
|
312
321
|
|
|
322
|
+
### `reactive`
|
|
323
|
+
|
|
324
|
+
The `reactive` field in generated JSON is heuristic metadata. It is not a complete statement of whether a parent may use `bind:prop` in Svelte.
|
|
325
|
+
|
|
326
|
+
`sveld` marks `reactive: true` when it finds internal evidence that a prop is writable, including:
|
|
327
|
+
|
|
328
|
+
- the prop is assigned or mutated inside the component
|
|
329
|
+
- the prop is marked bindable in runes mode with `$bindable(...)`
|
|
330
|
+
- the prop is used as the target of `bind:*` on an element or child component
|
|
331
|
+
- wrapper-forwarded bindings such as `bind:value`, `bind:selected`, and `bind:ref`
|
|
332
|
+
|
|
333
|
+
Local variables or parameters that shadow a prop name do not count as writes to the exported prop.
|
|
334
|
+
|
|
335
|
+
`reactive: false` means `sveld` found no such evidence. It does not imply that parent-side `bind:` usage is impossible.
|
|
336
|
+
|
|
337
|
+
For stable output, generated `events` arrays are emitted in deterministic sorted order.
|
|
338
|
+
|
|
313
339
|
### `@type`
|
|
314
340
|
|
|
315
341
|
Without a `@type` annotation, `sveld` will infer the primitive type for a prop:
|
|
@@ -328,7 +354,7 @@ export let id = `ccs-${Math.random().toString(36)}`;
|
|
|
328
354
|
|
|
329
355
|
Use the `@type` tag to explicitly document the type. In the following example, the `kind` property has an enumerated (enum) type.
|
|
330
356
|
|
|
331
|
-
Signature
|
|
357
|
+
**Signature:**
|
|
332
358
|
|
|
333
359
|
```js
|
|
334
360
|
/**
|
|
@@ -337,27 +363,52 @@ Signature:
|
|
|
337
363
|
*/
|
|
338
364
|
```
|
|
339
365
|
|
|
340
|
-
Example
|
|
366
|
+
**Example:**
|
|
341
367
|
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Specify the kind of button
|
|
345
|
-
* @type {"primary" | "secondary" | "tertiary"}
|
|
346
|
-
*/
|
|
347
|
-
export let kind = "primary";
|
|
368
|
+
**Svelte 5 Runes:**
|
|
348
369
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
370
|
+
```svelte
|
|
371
|
+
<script>
|
|
372
|
+
let {
|
|
373
|
+
/**
|
|
374
|
+
* Specify the kind of button
|
|
375
|
+
* @type {"primary" | "secondary" | "tertiary"}
|
|
376
|
+
*/
|
|
377
|
+
kind = "primary",
|
|
378
|
+
/**
|
|
379
|
+
* Specify the Carbon icon to render
|
|
380
|
+
* @type {typeof import("carbon-icons-svelte").CarbonIcon}
|
|
381
|
+
*/
|
|
382
|
+
renderIcon = Close20,
|
|
383
|
+
} = $props();
|
|
384
|
+
</script>
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
For runes components with multiple destructured props, place JSDoc on the individual property you want to document. A declaration-level JSDoc block is only used as a fallback when the destructure exposes a single public prop.
|
|
388
|
+
|
|
389
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
390
|
+
|
|
391
|
+
```svelte
|
|
392
|
+
<script>
|
|
393
|
+
/**
|
|
394
|
+
* Specify the kind of button
|
|
395
|
+
* @type {"primary" | "secondary" | "tertiary"}
|
|
396
|
+
*/
|
|
397
|
+
export let kind = "primary";
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Specify the Carbon icon to render
|
|
401
|
+
* @type {typeof import("carbon-icons-svelte").CarbonIcon}
|
|
402
|
+
*/
|
|
403
|
+
export let renderIcon = Close20;
|
|
404
|
+
</script>
|
|
354
405
|
```
|
|
355
406
|
|
|
356
407
|
### `@typedef`
|
|
357
408
|
|
|
358
409
|
The `@typedef` tag can be used to define a common type that is used multiple times within a component. All typedefs defined in a component will be exported from the generated TypeScript definition file.
|
|
359
410
|
|
|
360
|
-
Signature
|
|
411
|
+
**Signature:**
|
|
361
412
|
|
|
362
413
|
```js
|
|
363
414
|
/**
|
|
@@ -365,26 +416,48 @@ Signature:
|
|
|
365
416
|
*/
|
|
366
417
|
```
|
|
367
418
|
|
|
368
|
-
Example
|
|
419
|
+
**Example:**
|
|
369
420
|
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* @typedef {string} AuthorName
|
|
373
|
-
* @typedef {{ name?: AuthorName; dob?: string; }} Author
|
|
374
|
-
*/
|
|
421
|
+
**Svelte 5 Runes:**
|
|
375
422
|
|
|
376
|
-
|
|
377
|
-
|
|
423
|
+
```svelte
|
|
424
|
+
<script>
|
|
425
|
+
/**
|
|
426
|
+
* @typedef {string} AuthorName
|
|
427
|
+
* @typedef {{ name?: AuthorName; dob?: string; }} Author
|
|
428
|
+
*/
|
|
378
429
|
|
|
379
|
-
|
|
380
|
-
|
|
430
|
+
let {
|
|
431
|
+
/** @type {Author} */
|
|
432
|
+
author = {},
|
|
433
|
+
/** @type {Author[]} */
|
|
434
|
+
authors = [],
|
|
435
|
+
} = $props();
|
|
436
|
+
</script>
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
440
|
+
|
|
441
|
+
```svelte
|
|
442
|
+
<script>
|
|
443
|
+
/**
|
|
444
|
+
* @typedef {string} AuthorName
|
|
445
|
+
* @typedef {{ name?: AuthorName; dob?: string; }} Author
|
|
446
|
+
*/
|
|
447
|
+
|
|
448
|
+
/** @type {Author} */
|
|
449
|
+
export let author = {};
|
|
450
|
+
|
|
451
|
+
/** @type {Author[]} */
|
|
452
|
+
export let authors = [];
|
|
453
|
+
</script>
|
|
381
454
|
```
|
|
382
455
|
|
|
383
456
|
#### Using `@property` for complex typedefs
|
|
384
457
|
|
|
385
458
|
For complex object types, use the `@property` tag to document individual properties. This provides better documentation and IDE support with per-property tooltips.
|
|
386
459
|
|
|
387
|
-
Signature
|
|
460
|
+
**Signature:**
|
|
388
461
|
|
|
389
462
|
```js
|
|
390
463
|
/**
|
|
@@ -394,19 +467,40 @@ Signature:
|
|
|
394
467
|
*/
|
|
395
468
|
```
|
|
396
469
|
|
|
397
|
-
Example
|
|
470
|
+
**Example:**
|
|
398
471
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
472
|
+
**Svelte 5 Runes:**
|
|
473
|
+
|
|
474
|
+
```svelte
|
|
475
|
+
<script>
|
|
476
|
+
/**
|
|
477
|
+
* Represents a user in the system
|
|
478
|
+
* @typedef {object} User
|
|
479
|
+
* @property {string} name - The user's full name
|
|
480
|
+
* @property {string} email - The user's email address
|
|
481
|
+
* @property {number} age - The user's age in years
|
|
482
|
+
*/
|
|
483
|
+
|
|
484
|
+
/** @type {User} */
|
|
485
|
+
let { user = { name: "John", email: "john@example.com", age: 30 } } = $props();
|
|
486
|
+
</script>
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
490
|
+
|
|
491
|
+
```svelte
|
|
492
|
+
<script>
|
|
493
|
+
/**
|
|
494
|
+
* Represents a user in the system
|
|
495
|
+
* @typedef {object} User
|
|
496
|
+
* @property {string} name - The user's full name
|
|
497
|
+
* @property {string} email - The user's email address
|
|
498
|
+
* @property {number} age - The user's age in years
|
|
499
|
+
*/
|
|
407
500
|
|
|
408
|
-
/** @type {User} */
|
|
409
|
-
export let user = { name: "John", email: "john@example.com", age: 30 };
|
|
501
|
+
/** @type {User} */
|
|
502
|
+
export let user = { name: "John", email: "john@example.com", age: 30 };
|
|
503
|
+
</script>
|
|
410
504
|
```
|
|
411
505
|
|
|
412
506
|
Output:
|
|
@@ -434,7 +528,7 @@ export type ComponentProps = {
|
|
|
434
528
|
|
|
435
529
|
Following JSDoc standards, use square brackets to mark properties as optional. You can also specify default values using the `[propertyName=defaultValue]` syntax.
|
|
436
530
|
|
|
437
|
-
Signature
|
|
531
|
+
**Signature:**
|
|
438
532
|
|
|
439
533
|
```js
|
|
440
534
|
/**
|
|
@@ -444,20 +538,42 @@ Signature:
|
|
|
444
538
|
*/
|
|
445
539
|
```
|
|
446
540
|
|
|
447
|
-
Example
|
|
541
|
+
**Example:**
|
|
448
542
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
543
|
+
**Svelte 5 Runes:**
|
|
544
|
+
|
|
545
|
+
```svelte
|
|
546
|
+
<script>
|
|
547
|
+
/**
|
|
548
|
+
* Configuration options for the component
|
|
549
|
+
* @typedef {object} ComponentConfig
|
|
550
|
+
* @property {boolean} enabled - Whether the component is enabled
|
|
551
|
+
* @property {string} theme - The component theme
|
|
552
|
+
* @property {number} [timeout=5000] - Optional timeout in milliseconds
|
|
553
|
+
* @property {boolean} [debug] - Optional debug mode flag
|
|
554
|
+
*/
|
|
555
|
+
|
|
556
|
+
/** @type {ComponentConfig} */
|
|
557
|
+
let { config = { enabled: true, theme: "dark" } } = $props();
|
|
558
|
+
</script>
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
562
|
+
|
|
563
|
+
```svelte
|
|
564
|
+
<script>
|
|
565
|
+
/**
|
|
566
|
+
* Configuration options for the component
|
|
567
|
+
* @typedef {object} ComponentConfig
|
|
568
|
+
* @property {boolean} enabled - Whether the component is enabled
|
|
569
|
+
* @property {string} theme - The component theme
|
|
570
|
+
* @property {number} [timeout=5000] - Optional timeout in milliseconds
|
|
571
|
+
* @property {boolean} [debug] - Optional debug mode flag
|
|
572
|
+
*/
|
|
458
573
|
|
|
459
|
-
/** @type {ComponentConfig} */
|
|
460
|
-
export let config = { enabled: true, theme: "dark" };
|
|
574
|
+
/** @type {ComponentConfig} */
|
|
575
|
+
export let config = { enabled: true, theme: "dark" };
|
|
576
|
+
</script>
|
|
461
577
|
```
|
|
462
578
|
|
|
463
579
|
Output:
|
|
@@ -491,7 +607,7 @@ The `@callback` tag defines a function type using `@param` and `@returns` tags,
|
|
|
491
607
|
|
|
492
608
|
This is useful for typing callback props without using inline function type syntax.
|
|
493
609
|
|
|
494
|
-
Signature
|
|
610
|
+
**Signature:**
|
|
495
611
|
|
|
496
612
|
```js
|
|
497
613
|
/**
|
|
@@ -502,19 +618,40 @@ Signature:
|
|
|
502
618
|
*/
|
|
503
619
|
```
|
|
504
620
|
|
|
505
|
-
Example
|
|
621
|
+
**Example:**
|
|
506
622
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
623
|
+
**Svelte 5 Runes:**
|
|
624
|
+
|
|
625
|
+
```svelte
|
|
626
|
+
<script>
|
|
627
|
+
/**
|
|
628
|
+
* Callback fired when the value changes
|
|
629
|
+
* @callback OnChange
|
|
630
|
+
* @param {string} value - The new value
|
|
631
|
+
* @param {number} index - The index of the changed item
|
|
632
|
+
* @returns {void}
|
|
633
|
+
*/
|
|
515
634
|
|
|
516
|
-
/** @type {OnChange} */
|
|
517
|
-
|
|
635
|
+
/** @type {OnChange} */
|
|
636
|
+
let { onChange = (value, index) => {} } = $props();
|
|
637
|
+
</script>
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
641
|
+
|
|
642
|
+
```svelte
|
|
643
|
+
<script>
|
|
644
|
+
/**
|
|
645
|
+
* Callback fired when the value changes
|
|
646
|
+
* @callback OnChange
|
|
647
|
+
* @param {string} value - The new value
|
|
648
|
+
* @param {number} index - The index of the changed item
|
|
649
|
+
* @returns {void}
|
|
650
|
+
*/
|
|
651
|
+
|
|
652
|
+
/** @type {OnChange} */
|
|
653
|
+
export let onChange = (value, index) => {};
|
|
654
|
+
</script>
|
|
518
655
|
```
|
|
519
656
|
|
|
520
657
|
Output:
|
|
@@ -548,27 +685,54 @@ Callbacks can be combined with `@typedef` in the same comment block:
|
|
|
548
685
|
|
|
549
686
|
When `@returns` is omitted, the return type defaults to `void`. When no `@param` tags are present, the callback is typed as a no-argument function.
|
|
550
687
|
|
|
551
|
-
### `@slot`
|
|
688
|
+
### `@slot` / `@snippet`
|
|
552
689
|
|
|
553
|
-
Use the `@slot` tag for typing component slots.
|
|
690
|
+
Use the `@slot` tag for typing component slots. For Svelte 5 runes components, `@snippet` is also supported as an alias. Both are non-standard JSDoc tags.
|
|
554
691
|
|
|
555
692
|
Descriptions are optional for named slots. Currently, the default slot cannot have a description.
|
|
556
693
|
|
|
557
|
-
Signature
|
|
694
|
+
**Signature:**
|
|
558
695
|
|
|
559
696
|
```js
|
|
560
697
|
/**
|
|
561
698
|
* @slot {Type} slot-name [slot description]
|
|
699
|
+
* @snippet {Type} snippet-name [snippet description]
|
|
562
700
|
*/
|
|
563
701
|
|
|
564
702
|
Omit the `slot-name` to type the default slot.
|
|
565
703
|
|
|
566
704
|
/**
|
|
567
705
|
* @slot {Type}
|
|
706
|
+
* @snippet {Type}
|
|
568
707
|
*/
|
|
569
708
|
```
|
|
570
709
|
|
|
571
|
-
Example
|
|
710
|
+
**Example:**
|
|
711
|
+
|
|
712
|
+
**Svelte 5 Runes:**
|
|
713
|
+
|
|
714
|
+
```svelte
|
|
715
|
+
<script>
|
|
716
|
+
/**
|
|
717
|
+
* @snippet {{ prop: number; doubled: number; }}
|
|
718
|
+
* @snippet {{}} title
|
|
719
|
+
* @snippet {{ prop: number }} body - Customize the paragraph text.
|
|
720
|
+
*/
|
|
721
|
+
|
|
722
|
+
let { prop = 0, children, title, body } = $props();
|
|
723
|
+
</script>
|
|
724
|
+
|
|
725
|
+
<h1>
|
|
726
|
+
{@render children?.({ prop, doubled: prop * 2 })}
|
|
727
|
+
{@render title?.()}
|
|
728
|
+
</h1>
|
|
729
|
+
|
|
730
|
+
<p>
|
|
731
|
+
{@render body?.({ prop })}
|
|
732
|
+
</p>
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
572
736
|
|
|
573
737
|
```svelte
|
|
574
738
|
<script>
|
|
@@ -595,6 +759,8 @@ Example:
|
|
|
595
759
|
|
|
596
760
|
For Svelte 5 compatibility, `sveld` automatically generates optional snippet props for all slots. This allows consumers to use either the traditional slot syntax or Svelte 5's `{#snippet}` syntax.
|
|
597
761
|
|
|
762
|
+
When parsing runes components, `sveld` maps `{@render ...}` calls back into the same slot metadata used for traditional `<slot>` declarations. Reserved snippet props such as `children`, along with named snippet props discovered from `{@render ...}`, are represented through `slots` metadata and generated snippet prop types rather than duplicated in the `props` output.
|
|
763
|
+
|
|
598
764
|
For slots with props (e.g., `let:prop`), the generated type uses a Snippet-compatible signature:
|
|
599
765
|
|
|
600
766
|
```ts
|
|
@@ -697,9 +863,11 @@ export default class DataTable<Row> extends SvelteComponentTyped<
|
|
|
697
863
|
|
|
698
864
|
Use the `@event` tag to type dispatched events. An event name is required and a description optional.
|
|
699
865
|
|
|
866
|
+
In Svelte 5 runes components, callback props such as `onclick` are treated as component props, not events. The `events` output remains reserved for real dispatched events and legacy forwarded events. If a runes component documents `@event foo` and exposes a matching callback prop like `onfoo` without actually dispatching or forwarding `foo`, `sveld` aliases that documentation onto the callback prop instead of synthesizing an emitted event.
|
|
867
|
+
|
|
700
868
|
Use `null` as the value if no event detail is provided.
|
|
701
869
|
|
|
702
|
-
Signature
|
|
870
|
+
**Signature:**
|
|
703
871
|
|
|
704
872
|
```js
|
|
705
873
|
/**
|
|
@@ -708,22 +876,62 @@ Signature:
|
|
|
708
876
|
*/
|
|
709
877
|
```
|
|
710
878
|
|
|
711
|
-
Example
|
|
879
|
+
**Example:**
|
|
712
880
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
881
|
+
**Svelte 5 Runes:**
|
|
882
|
+
|
|
883
|
+
```svelte
|
|
884
|
+
<script>
|
|
885
|
+
/**
|
|
886
|
+
* Fired when a value is saved.
|
|
887
|
+
* @event {{ id: string }} save
|
|
888
|
+
*/
|
|
889
|
+
let { onsave } = $props();
|
|
890
|
+
</script>
|
|
891
|
+
|
|
892
|
+
<button onclick={() => onsave?.({ id: "1" })}>Save</button>
|
|
893
|
+
```
|
|
894
|
+
|
|
895
|
+
**Svelte 5 Runes with dispatched events:**
|
|
896
|
+
|
|
897
|
+
```svelte
|
|
898
|
+
<script>
|
|
899
|
+
/**
|
|
900
|
+
* @event {{ key: string }} button:key
|
|
901
|
+
* @event {null} key - Fired when `key` changes.
|
|
902
|
+
*/
|
|
903
|
+
|
|
904
|
+
let { key = "" } = $props();
|
|
905
|
+
|
|
906
|
+
import { createEventDispatcher } from "svelte";
|
|
907
|
+
|
|
908
|
+
const dispatch = createEventDispatcher();
|
|
909
|
+
|
|
910
|
+
$effect(() => {
|
|
911
|
+
dispatch("button:key", { key });
|
|
912
|
+
if (key) dispatch("key");
|
|
913
|
+
});
|
|
914
|
+
</script>
|
|
915
|
+
```
|
|
718
916
|
|
|
719
|
-
|
|
917
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
720
918
|
|
|
721
|
-
|
|
919
|
+
```svelte
|
|
920
|
+
<script>
|
|
921
|
+
/**
|
|
922
|
+
* @event {{ key: string }} button:key
|
|
923
|
+
* @event {null} key - Fired when `key` changes.
|
|
924
|
+
*/
|
|
722
925
|
|
|
723
|
-
|
|
926
|
+
export let key = "";
|
|
724
927
|
|
|
725
|
-
|
|
726
|
-
|
|
928
|
+
import { createEventDispatcher } from "svelte";
|
|
929
|
+
|
|
930
|
+
const dispatch = createEventDispatcher();
|
|
931
|
+
|
|
932
|
+
$: dispatch("button:key", { key });
|
|
933
|
+
$: if (key) dispatch("key");
|
|
934
|
+
</script>
|
|
727
935
|
```
|
|
728
936
|
|
|
729
937
|
Output:
|
|
@@ -743,7 +951,7 @@ export default class Component extends SvelteComponentTyped<
|
|
|
743
951
|
|
|
744
952
|
For events with complex object payloads, use the `@property` tag to document individual properties. The main comment description will be used as the event description.
|
|
745
953
|
|
|
746
|
-
Signature
|
|
954
|
+
**Signature:**
|
|
747
955
|
|
|
748
956
|
```js
|
|
749
957
|
/**
|
|
@@ -754,30 +962,64 @@ Signature:
|
|
|
754
962
|
*/
|
|
755
963
|
```
|
|
756
964
|
|
|
757
|
-
Example
|
|
965
|
+
**Example:**
|
|
758
966
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
967
|
+
**Svelte 5 Runes:**
|
|
968
|
+
|
|
969
|
+
```svelte
|
|
970
|
+
<script>
|
|
971
|
+
/**
|
|
972
|
+
* Fired when the user submits the form
|
|
973
|
+
*
|
|
974
|
+
* @event submit
|
|
975
|
+
* @type {object}
|
|
976
|
+
* @property {string} name - The user's name
|
|
977
|
+
* @property {string} email - The user's email address
|
|
978
|
+
* @property {boolean} newsletter - Whether the user opted into the newsletter
|
|
979
|
+
*/
|
|
769
980
|
|
|
770
|
-
|
|
981
|
+
let { name = "Jane Doe", email = "jane@example.com", newsletter = true } = $props();
|
|
771
982
|
|
|
772
|
-
|
|
983
|
+
import { createEventDispatcher } from "svelte";
|
|
773
984
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
985
|
+
const dispatch = createEventDispatcher();
|
|
986
|
+
|
|
987
|
+
function handleSubmit() {
|
|
988
|
+
dispatch("submit", { name, email, newsletter });
|
|
989
|
+
}
|
|
990
|
+
</script>
|
|
991
|
+
|
|
992
|
+
<button type="button" onclick={handleSubmit}>Submit</button>
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
996
|
+
|
|
997
|
+
```svelte
|
|
998
|
+
<script>
|
|
999
|
+
/**
|
|
1000
|
+
* Fired when the user submits the form
|
|
1001
|
+
*
|
|
1002
|
+
* @event submit
|
|
1003
|
+
* @type {object}
|
|
1004
|
+
* @property {string} name - The user's name
|
|
1005
|
+
* @property {string} email - The user's email address
|
|
1006
|
+
* @property {boolean} newsletter - Whether the user opted into the newsletter
|
|
1007
|
+
*/
|
|
1008
|
+
|
|
1009
|
+
export let name = "Jane Doe";
|
|
1010
|
+
export let email = "jane@example.com";
|
|
1011
|
+
export let newsletter = true;
|
|
1012
|
+
|
|
1013
|
+
import { createEventDispatcher } from "svelte";
|
|
1014
|
+
|
|
1015
|
+
const dispatch = createEventDispatcher();
|
|
1016
|
+
|
|
1017
|
+
function handleSubmit() {
|
|
1018
|
+
dispatch("submit", { name, email, newsletter });
|
|
1019
|
+
}
|
|
1020
|
+
</script>
|
|
1021
|
+
|
|
1022
|
+
<button type="button" on:click={handleSubmit}>Submit</button>
|
|
781
1023
|
```
|
|
782
1024
|
|
|
783
1025
|
Output:
|
|
@@ -804,30 +1046,70 @@ export default class Component extends SvelteComponentTyped<
|
|
|
804
1046
|
|
|
805
1047
|
Just like with typedefs, you can mark event detail properties as optional using square brackets. This is useful when some properties may not always be included in the event payload.
|
|
806
1048
|
|
|
807
|
-
Example
|
|
1049
|
+
**Example:**
|
|
808
1050
|
|
|
809
|
-
|
|
810
|
-
/**
|
|
811
|
-
* Snowball event fired when throwing a snowball
|
|
812
|
-
*
|
|
813
|
-
* @event snowball
|
|
814
|
-
* @type {object}
|
|
815
|
-
* @property {boolean} isPacked - Indicates whether the snowball is tightly packed
|
|
816
|
-
* @property {number} speed - The speed of the snowball in mph
|
|
817
|
-
* @property {string} [color] - Optional color of the snowball
|
|
818
|
-
* @property {number} [density=0.9] - Optional density with default value
|
|
819
|
-
*/
|
|
1051
|
+
**Svelte 5 Runes:**
|
|
820
1052
|
|
|
821
|
-
|
|
1053
|
+
```svelte
|
|
1054
|
+
<script>
|
|
1055
|
+
/**
|
|
1056
|
+
* Snowball event fired when throwing a snowball
|
|
1057
|
+
*
|
|
1058
|
+
* @event snowball
|
|
1059
|
+
* @type {object}
|
|
1060
|
+
* @property {boolean} isPacked - Indicates whether the snowball is tightly packed
|
|
1061
|
+
* @property {number} speed - The speed of the snowball in mph
|
|
1062
|
+
* @property {string} [color] - Optional color of the snowball
|
|
1063
|
+
* @property {number} [density=0.9] - Optional density with default value
|
|
1064
|
+
*/
|
|
822
1065
|
|
|
823
|
-
|
|
1066
|
+
let { speed = 50 } = $props();
|
|
824
1067
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
1068
|
+
import { createEventDispatcher } from "svelte";
|
|
1069
|
+
|
|
1070
|
+
const dispatch = createEventDispatcher();
|
|
1071
|
+
|
|
1072
|
+
function throwSnowball() {
|
|
1073
|
+
dispatch("snowball", {
|
|
1074
|
+
isPacked: true,
|
|
1075
|
+
speed,
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
</script>
|
|
1079
|
+
|
|
1080
|
+
<button type="button" onclick={throwSnowball}>Throw</button>
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1084
|
+
|
|
1085
|
+
```svelte
|
|
1086
|
+
<script>
|
|
1087
|
+
/**
|
|
1088
|
+
* Snowball event fired when throwing a snowball
|
|
1089
|
+
*
|
|
1090
|
+
* @event snowball
|
|
1091
|
+
* @type {object}
|
|
1092
|
+
* @property {boolean} isPacked - Indicates whether the snowball is tightly packed
|
|
1093
|
+
* @property {number} speed - The speed of the snowball in mph
|
|
1094
|
+
* @property {string} [color] - Optional color of the snowball
|
|
1095
|
+
* @property {number} [density=0.9] - Optional density with default value
|
|
1096
|
+
*/
|
|
1097
|
+
|
|
1098
|
+
export let speed = 50;
|
|
1099
|
+
|
|
1100
|
+
import { createEventDispatcher } from "svelte";
|
|
1101
|
+
|
|
1102
|
+
const dispatch = createEventDispatcher();
|
|
1103
|
+
|
|
1104
|
+
function throwSnowball() {
|
|
1105
|
+
dispatch("snowball", {
|
|
1106
|
+
isPacked: true,
|
|
1107
|
+
speed,
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
</script>
|
|
1111
|
+
|
|
1112
|
+
<button type="button" on:click={throwSnowball}>Throw</button>
|
|
831
1113
|
```
|
|
832
1114
|
|
|
833
1115
|
Output:
|
|
@@ -869,9 +1151,43 @@ When you use `setContext` in a component, `sveld` will:
|
|
|
869
1151
|
|
|
870
1152
|
**Modal.svelte**
|
|
871
1153
|
|
|
1154
|
+
**Svelte 5 Runes:**
|
|
1155
|
+
|
|
872
1156
|
```svelte
|
|
873
1157
|
<script>
|
|
874
|
-
import { setContext } from
|
|
1158
|
+
import { setContext } from "svelte";
|
|
1159
|
+
|
|
1160
|
+
/**
|
|
1161
|
+
* Close the modal
|
|
1162
|
+
* @type {() => void}
|
|
1163
|
+
*/
|
|
1164
|
+
const close = () => {
|
|
1165
|
+
// Close logic
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
/**
|
|
1169
|
+
* Open the modal with content
|
|
1170
|
+
* @type {(component: any, props?: any) => void}
|
|
1171
|
+
*/
|
|
1172
|
+
const open = (component, props) => {
|
|
1173
|
+
// Open logic
|
|
1174
|
+
};
|
|
1175
|
+
|
|
1176
|
+
setContext("simple-modal", { open, close });
|
|
1177
|
+
|
|
1178
|
+
let { children } = $props();
|
|
1179
|
+
</script>
|
|
1180
|
+
|
|
1181
|
+
<div class="modal">
|
|
1182
|
+
{@render children?.()}
|
|
1183
|
+
</div>
|
|
1184
|
+
```
|
|
1185
|
+
|
|
1186
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1187
|
+
|
|
1188
|
+
```svelte
|
|
1189
|
+
<script>
|
|
1190
|
+
import { setContext } from "svelte";
|
|
875
1191
|
|
|
876
1192
|
/**
|
|
877
1193
|
* Close the modal
|
|
@@ -889,7 +1205,7 @@ When you use `setContext` in a component, `sveld` will:
|
|
|
889
1205
|
// Open logic
|
|
890
1206
|
};
|
|
891
1207
|
|
|
892
|
-
setContext(
|
|
1208
|
+
setContext("simple-modal", { open, close });
|
|
893
1209
|
</script>
|
|
894
1210
|
|
|
895
1211
|
<div class="modal">
|
|
@@ -1027,7 +1343,7 @@ There are several ways to provide type information for contexts:
|
|
|
1027
1343
|
|
|
1028
1344
|
You can use the `@restProps` tag to specify the element tags that `$$restProps` is forwarded to.
|
|
1029
1345
|
|
|
1030
|
-
Signature
|
|
1346
|
+
**Signature:**
|
|
1031
1347
|
|
|
1032
1348
|
```js
|
|
1033
1349
|
/**
|
|
@@ -1039,14 +1355,35 @@ Signature:
|
|
|
1039
1355
|
*/
|
|
1040
1356
|
```
|
|
1041
1357
|
|
|
1042
|
-
Example
|
|
1358
|
+
**Example:**
|
|
1359
|
+
|
|
1360
|
+
**Svelte 5 Runes:**
|
|
1361
|
+
|
|
1362
|
+
```svelte
|
|
1363
|
+
<script>
|
|
1364
|
+
import Button from "./Button.svelte";
|
|
1365
|
+
|
|
1366
|
+
/** @restProps {h1 | button} */
|
|
1367
|
+
let { edit = false, children, ...restProps } = $props();
|
|
1368
|
+
</script>
|
|
1369
|
+
|
|
1370
|
+
{#if edit}
|
|
1371
|
+
<Button {...restProps} />
|
|
1372
|
+
{:else}
|
|
1373
|
+
<h1 {...restProps}>
|
|
1374
|
+
{@render children?.()}
|
|
1375
|
+
</h1>
|
|
1376
|
+
{/if}
|
|
1377
|
+
```
|
|
1378
|
+
|
|
1379
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1043
1380
|
|
|
1044
1381
|
```svelte
|
|
1045
1382
|
<script>
|
|
1046
1383
|
/** @restProps {h1 | button} */
|
|
1047
1384
|
export let edit = false;
|
|
1048
1385
|
|
|
1049
|
-
import Button from "
|
|
1386
|
+
import Button from "./Button.svelte";
|
|
1050
1387
|
</script>
|
|
1051
1388
|
|
|
1052
1389
|
{#if edit}
|
|
@@ -1062,7 +1399,7 @@ In some cases, a component may be based on another component. The `@extendProps`
|
|
|
1062
1399
|
|
|
1063
1400
|
> **Note:** `@extends` is supported as an alias but `@extendProps` is preferred to avoid conflicts with standard JSDoc `@extends` (used for class inheritance).
|
|
1064
1401
|
|
|
1065
|
-
Signature
|
|
1402
|
+
**Signature:**
|
|
1066
1403
|
|
|
1067
1404
|
```js
|
|
1068
1405
|
/**
|
|
@@ -1070,7 +1407,7 @@ Signature:
|
|
|
1070
1407
|
*/
|
|
1071
1408
|
```
|
|
1072
1409
|
|
|
1073
|
-
Example
|
|
1410
|
+
**Example:**
|
|
1074
1411
|
|
|
1075
1412
|
```js
|
|
1076
1413
|
/** @extendProps {"./Button.svelte"} ButtonProps */
|
|
@@ -1093,7 +1430,7 @@ However, the `generics` attribute only works if using `lang="ts"`; the language
|
|
|
1093
1430
|
|
|
1094
1431
|
Because `sveld` is designed to support JavaScript-only usage as a baseline, the API design to specify generics uses a custom JSDoc tag `@generics`.
|
|
1095
1432
|
|
|
1096
|
-
Signature
|
|
1433
|
+
**Signature:**
|
|
1097
1434
|
|
|
1098
1435
|
```js
|
|
1099
1436
|
/**
|
|
@@ -1101,7 +1438,7 @@ Signature:
|
|
|
1101
1438
|
*/
|
|
1102
1439
|
```
|
|
1103
1440
|
|
|
1104
|
-
Example
|
|
1441
|
+
**Example:**
|
|
1105
1442
|
|
|
1106
1443
|
```js
|
|
1107
1444
|
/**
|
|
@@ -1109,6 +1446,54 @@ Example
|
|
|
1109
1446
|
*/
|
|
1110
1447
|
```
|
|
1111
1448
|
|
|
1449
|
+
**Component example:**
|
|
1450
|
+
|
|
1451
|
+
**Svelte 5 Runes:**
|
|
1452
|
+
|
|
1453
|
+
```svelte
|
|
1454
|
+
<script>
|
|
1455
|
+
/**
|
|
1456
|
+
* @typedef {{ id: string | number; [key: string]: any; }} DataTableRow
|
|
1457
|
+
* @typedef {Exclude<keyof Row, "id">} DataTableKey<Row>
|
|
1458
|
+
* @typedef {{ key: DataTableKey<Row>; value: string; }} DataTableHeader<Row=DataTableRow>
|
|
1459
|
+
* @template {DataTableRow} <Row extends DataTableRow = DataTableRow>
|
|
1460
|
+
* @generics {Row extends DataTableRow = DataTableRow} Row
|
|
1461
|
+
*/
|
|
1462
|
+
|
|
1463
|
+
let {
|
|
1464
|
+
/** @type {ReadonlyArray<DataTableHeader<Row>>} */
|
|
1465
|
+
headers = [],
|
|
1466
|
+
/** @type {ReadonlyArray<Row>} */
|
|
1467
|
+
rows = [],
|
|
1468
|
+
children,
|
|
1469
|
+
} = $props();
|
|
1470
|
+
</script>
|
|
1471
|
+
|
|
1472
|
+
{@render children?.({ headers, rows })}
|
|
1473
|
+
```
|
|
1474
|
+
|
|
1475
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1476
|
+
|
|
1477
|
+
```svelte
|
|
1478
|
+
<script>
|
|
1479
|
+
/**
|
|
1480
|
+
* @typedef {{ id: string | number; [key: string]: any; }} DataTableRow
|
|
1481
|
+
* @typedef {Exclude<keyof Row, "id">} DataTableKey<Row>
|
|
1482
|
+
* @typedef {{ key: DataTableKey<Row>; value: string; }} DataTableHeader<Row=DataTableRow>
|
|
1483
|
+
* @template {DataTableRow} <Row extends DataTableRow = DataTableRow>
|
|
1484
|
+
* @generics {Row extends DataTableRow = DataTableRow} Row
|
|
1485
|
+
*/
|
|
1486
|
+
|
|
1487
|
+
/** @type {ReadonlyArray<DataTableHeader<Row>>} */
|
|
1488
|
+
export let headers = [];
|
|
1489
|
+
|
|
1490
|
+
/** @type {ReadonlyArray<Row>} */
|
|
1491
|
+
export let rows = [];
|
|
1492
|
+
</script>
|
|
1493
|
+
|
|
1494
|
+
<slot {headers} {rows} />
|
|
1495
|
+
```
|
|
1496
|
+
|
|
1112
1497
|
The generated TypeScript definition will resemble the following:
|
|
1113
1498
|
|
|
1114
1499
|
```ts
|
|
@@ -1150,7 +1535,27 @@ The Svelte Language Server supports component-level comments through the followi
|
|
|
1150
1535
|
|
|
1151
1536
|
`sveld` will copy these over to the exported default component in the TypeScript definition.
|
|
1152
1537
|
|
|
1153
|
-
Example
|
|
1538
|
+
**Example:**
|
|
1539
|
+
|
|
1540
|
+
**Svelte 5 Runes:**
|
|
1541
|
+
|
|
1542
|
+
```svelte
|
|
1543
|
+
<!-- @component
|
|
1544
|
+
@example
|
|
1545
|
+
<Button>
|
|
1546
|
+
Text
|
|
1547
|
+
</Button>
|
|
1548
|
+
-->
|
|
1549
|
+
<script>
|
|
1550
|
+
let { children } = $props();
|
|
1551
|
+
</script>
|
|
1552
|
+
|
|
1553
|
+
<button>
|
|
1554
|
+
{@render children?.()}
|
|
1555
|
+
</button>
|
|
1556
|
+
```
|
|
1557
|
+
|
|
1558
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1154
1559
|
|
|
1155
1560
|
```svelte
|
|
1156
1561
|
<!-- @component
|
|
@@ -1186,7 +1591,7 @@ Exported functions and consts become accessor props in generated TypeScript defi
|
|
|
1186
1591
|
|
|
1187
1592
|
Note that `@type` tag annotations take precedence over `@param`/`@returns` tags.
|
|
1188
1593
|
|
|
1189
|
-
Signature
|
|
1594
|
+
**Signature:**
|
|
1190
1595
|
|
|
1191
1596
|
```js
|
|
1192
1597
|
/**
|
|
@@ -1197,7 +1602,54 @@ Signature:
|
|
|
1197
1602
|
*/
|
|
1198
1603
|
```
|
|
1199
1604
|
|
|
1200
|
-
Example
|
|
1605
|
+
**Example:**
|
|
1606
|
+
|
|
1607
|
+
**Svelte 5 Runes:**
|
|
1608
|
+
|
|
1609
|
+
```svelte
|
|
1610
|
+
<script>
|
|
1611
|
+
/**
|
|
1612
|
+
* @typedef {object} NotificationData
|
|
1613
|
+
* @property {string} [id] - Optional id for deduplication
|
|
1614
|
+
* @property {"error" | "info" | "success"} [kind]
|
|
1615
|
+
*/
|
|
1616
|
+
|
|
1617
|
+
let { children } = $props();
|
|
1618
|
+
|
|
1619
|
+
/**
|
|
1620
|
+
* Add a notification to the queue.
|
|
1621
|
+
* @param {NotificationData} notification
|
|
1622
|
+
* @returns {string} The notification id
|
|
1623
|
+
*/
|
|
1624
|
+
export function add(notification) {
|
|
1625
|
+
const id = notification.id ?? "id";
|
|
1626
|
+
return id;
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
/**
|
|
1630
|
+
* Remove a notification by id.
|
|
1631
|
+
* @param {string} id
|
|
1632
|
+
* @returns {boolean} True if the notification was found and removed
|
|
1633
|
+
*/
|
|
1634
|
+
export function remove(id) {
|
|
1635
|
+
return true;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
/**
|
|
1639
|
+
* Get notification count.
|
|
1640
|
+
* @returns {number} The number of notifications
|
|
1641
|
+
*/
|
|
1642
|
+
export function getCount() {
|
|
1643
|
+
return 0;
|
|
1644
|
+
}
|
|
1645
|
+
</script>
|
|
1646
|
+
|
|
1647
|
+
<div>
|
|
1648
|
+
{@render children?.()}
|
|
1649
|
+
</div>
|
|
1650
|
+
```
|
|
1651
|
+
|
|
1652
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1201
1653
|
|
|
1202
1654
|
```svelte
|
|
1203
1655
|
<script>
|