sveld 0.28.0 → 0.29.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/README.md +558 -132
- package/lib/ComponentParser.d.ts +48 -5
- package/lib/index.js +145 -145
- 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
|
|
|
@@ -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,47 @@ 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
|
+
/**
|
|
373
|
+
* Specify the kind of button
|
|
374
|
+
* @type {"primary" | "secondary" | "tertiary"}
|
|
375
|
+
*/
|
|
376
|
+
/**
|
|
377
|
+
* Specify the Carbon icon to render
|
|
378
|
+
* @type {typeof import("carbon-icons-svelte").CarbonIcon}
|
|
379
|
+
*/
|
|
380
|
+
let { kind = "primary", renderIcon = Close20 } = $props();
|
|
381
|
+
</script>
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
385
|
+
|
|
386
|
+
```svelte
|
|
387
|
+
<script>
|
|
388
|
+
/**
|
|
389
|
+
* Specify the kind of button
|
|
390
|
+
* @type {"primary" | "secondary" | "tertiary"}
|
|
391
|
+
*/
|
|
392
|
+
export let kind = "primary";
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Specify the Carbon icon to render
|
|
396
|
+
* @type {typeof import("carbon-icons-svelte").CarbonIcon}
|
|
397
|
+
*/
|
|
398
|
+
export let renderIcon = Close20;
|
|
399
|
+
</script>
|
|
354
400
|
```
|
|
355
401
|
|
|
356
402
|
### `@typedef`
|
|
357
403
|
|
|
358
404
|
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
405
|
|
|
360
|
-
Signature
|
|
406
|
+
**Signature:**
|
|
361
407
|
|
|
362
408
|
```js
|
|
363
409
|
/**
|
|
@@ -365,26 +411,48 @@ Signature:
|
|
|
365
411
|
*/
|
|
366
412
|
```
|
|
367
413
|
|
|
368
|
-
Example
|
|
414
|
+
**Example:**
|
|
369
415
|
|
|
370
|
-
|
|
371
|
-
/**
|
|
372
|
-
* @typedef {string} AuthorName
|
|
373
|
-
* @typedef {{ name?: AuthorName; dob?: string; }} Author
|
|
374
|
-
*/
|
|
416
|
+
**Svelte 5 Runes:**
|
|
375
417
|
|
|
376
|
-
|
|
377
|
-
|
|
418
|
+
```svelte
|
|
419
|
+
<script>
|
|
420
|
+
/**
|
|
421
|
+
* @typedef {string} AuthorName
|
|
422
|
+
* @typedef {{ name?: AuthorName; dob?: string; }} Author
|
|
423
|
+
*/
|
|
378
424
|
|
|
379
|
-
|
|
380
|
-
|
|
425
|
+
let {
|
|
426
|
+
/** @type {Author} */
|
|
427
|
+
author = {},
|
|
428
|
+
/** @type {Author[]} */
|
|
429
|
+
authors = [],
|
|
430
|
+
} = $props();
|
|
431
|
+
</script>
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
435
|
+
|
|
436
|
+
```svelte
|
|
437
|
+
<script>
|
|
438
|
+
/**
|
|
439
|
+
* @typedef {string} AuthorName
|
|
440
|
+
* @typedef {{ name?: AuthorName; dob?: string; }} Author
|
|
441
|
+
*/
|
|
442
|
+
|
|
443
|
+
/** @type {Author} */
|
|
444
|
+
export let author = {};
|
|
445
|
+
|
|
446
|
+
/** @type {Author[]} */
|
|
447
|
+
export let authors = [];
|
|
448
|
+
</script>
|
|
381
449
|
```
|
|
382
450
|
|
|
383
451
|
#### Using `@property` for complex typedefs
|
|
384
452
|
|
|
385
453
|
For complex object types, use the `@property` tag to document individual properties. This provides better documentation and IDE support with per-property tooltips.
|
|
386
454
|
|
|
387
|
-
Signature
|
|
455
|
+
**Signature:**
|
|
388
456
|
|
|
389
457
|
```js
|
|
390
458
|
/**
|
|
@@ -394,19 +462,40 @@ Signature:
|
|
|
394
462
|
*/
|
|
395
463
|
```
|
|
396
464
|
|
|
397
|
-
Example
|
|
465
|
+
**Example:**
|
|
398
466
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
467
|
+
**Svelte 5 Runes:**
|
|
468
|
+
|
|
469
|
+
```svelte
|
|
470
|
+
<script>
|
|
471
|
+
/**
|
|
472
|
+
* Represents a user in the system
|
|
473
|
+
* @typedef {object} User
|
|
474
|
+
* @property {string} name - The user's full name
|
|
475
|
+
* @property {string} email - The user's email address
|
|
476
|
+
* @property {number} age - The user's age in years
|
|
477
|
+
*/
|
|
478
|
+
|
|
479
|
+
/** @type {User} */
|
|
480
|
+
let { user = { name: "John", email: "john@example.com", age: 30 } } = $props();
|
|
481
|
+
</script>
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
407
485
|
|
|
408
|
-
|
|
409
|
-
|
|
486
|
+
```svelte
|
|
487
|
+
<script>
|
|
488
|
+
/**
|
|
489
|
+
* Represents a user in the system
|
|
490
|
+
* @typedef {object} User
|
|
491
|
+
* @property {string} name - The user's full name
|
|
492
|
+
* @property {string} email - The user's email address
|
|
493
|
+
* @property {number} age - The user's age in years
|
|
494
|
+
*/
|
|
495
|
+
|
|
496
|
+
/** @type {User} */
|
|
497
|
+
export let user = { name: "John", email: "john@example.com", age: 30 };
|
|
498
|
+
</script>
|
|
410
499
|
```
|
|
411
500
|
|
|
412
501
|
Output:
|
|
@@ -434,7 +523,7 @@ export type ComponentProps = {
|
|
|
434
523
|
|
|
435
524
|
Following JSDoc standards, use square brackets to mark properties as optional. You can also specify default values using the `[propertyName=defaultValue]` syntax.
|
|
436
525
|
|
|
437
|
-
Signature
|
|
526
|
+
**Signature:**
|
|
438
527
|
|
|
439
528
|
```js
|
|
440
529
|
/**
|
|
@@ -444,20 +533,42 @@ Signature:
|
|
|
444
533
|
*/
|
|
445
534
|
```
|
|
446
535
|
|
|
447
|
-
Example
|
|
536
|
+
**Example:**
|
|
448
537
|
|
|
449
|
-
|
|
450
|
-
/**
|
|
451
|
-
* Configuration options for the component
|
|
452
|
-
* @typedef {object} ComponentConfig
|
|
453
|
-
* @property {boolean} enabled - Whether the component is enabled
|
|
454
|
-
* @property {string} theme - The component theme
|
|
455
|
-
* @property {number} [timeout=5000] - Optional timeout in milliseconds
|
|
456
|
-
* @property {boolean} [debug] - Optional debug mode flag
|
|
457
|
-
*/
|
|
538
|
+
**Svelte 5 Runes:**
|
|
458
539
|
|
|
459
|
-
|
|
460
|
-
|
|
540
|
+
```svelte
|
|
541
|
+
<script>
|
|
542
|
+
/**
|
|
543
|
+
* Configuration options for the component
|
|
544
|
+
* @typedef {object} ComponentConfig
|
|
545
|
+
* @property {boolean} enabled - Whether the component is enabled
|
|
546
|
+
* @property {string} theme - The component theme
|
|
547
|
+
* @property {number} [timeout=5000] - Optional timeout in milliseconds
|
|
548
|
+
* @property {boolean} [debug] - Optional debug mode flag
|
|
549
|
+
*/
|
|
550
|
+
|
|
551
|
+
/** @type {ComponentConfig} */
|
|
552
|
+
let { config = { enabled: true, theme: "dark" } } = $props();
|
|
553
|
+
</script>
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
557
|
+
|
|
558
|
+
```svelte
|
|
559
|
+
<script>
|
|
560
|
+
/**
|
|
561
|
+
* Configuration options for the component
|
|
562
|
+
* @typedef {object} ComponentConfig
|
|
563
|
+
* @property {boolean} enabled - Whether the component is enabled
|
|
564
|
+
* @property {string} theme - The component theme
|
|
565
|
+
* @property {number} [timeout=5000] - Optional timeout in milliseconds
|
|
566
|
+
* @property {boolean} [debug] - Optional debug mode flag
|
|
567
|
+
*/
|
|
568
|
+
|
|
569
|
+
/** @type {ComponentConfig} */
|
|
570
|
+
export let config = { enabled: true, theme: "dark" };
|
|
571
|
+
</script>
|
|
461
572
|
```
|
|
462
573
|
|
|
463
574
|
Output:
|
|
@@ -491,7 +602,7 @@ The `@callback` tag defines a function type using `@param` and `@returns` tags,
|
|
|
491
602
|
|
|
492
603
|
This is useful for typing callback props without using inline function type syntax.
|
|
493
604
|
|
|
494
|
-
Signature
|
|
605
|
+
**Signature:**
|
|
495
606
|
|
|
496
607
|
```js
|
|
497
608
|
/**
|
|
@@ -502,19 +613,40 @@ Signature:
|
|
|
502
613
|
*/
|
|
503
614
|
```
|
|
504
615
|
|
|
505
|
-
Example
|
|
616
|
+
**Example:**
|
|
506
617
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
618
|
+
**Svelte 5 Runes:**
|
|
619
|
+
|
|
620
|
+
```svelte
|
|
621
|
+
<script>
|
|
622
|
+
/**
|
|
623
|
+
* Callback fired when the value changes
|
|
624
|
+
* @callback OnChange
|
|
625
|
+
* @param {string} value - The new value
|
|
626
|
+
* @param {number} index - The index of the changed item
|
|
627
|
+
* @returns {void}
|
|
628
|
+
*/
|
|
629
|
+
|
|
630
|
+
/** @type {OnChange} */
|
|
631
|
+
let { onChange = (value, index) => {} } = $props();
|
|
632
|
+
</script>
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
636
|
+
|
|
637
|
+
```svelte
|
|
638
|
+
<script>
|
|
639
|
+
/**
|
|
640
|
+
* Callback fired when the value changes
|
|
641
|
+
* @callback OnChange
|
|
642
|
+
* @param {string} value - The new value
|
|
643
|
+
* @param {number} index - The index of the changed item
|
|
644
|
+
* @returns {void}
|
|
645
|
+
*/
|
|
515
646
|
|
|
516
|
-
/** @type {OnChange} */
|
|
517
|
-
export let onChange = (value, index) => {};
|
|
647
|
+
/** @type {OnChange} */
|
|
648
|
+
export let onChange = (value, index) => {};
|
|
649
|
+
</script>
|
|
518
650
|
```
|
|
519
651
|
|
|
520
652
|
Output:
|
|
@@ -554,7 +686,7 @@ Use the `@slot` tag for typing component slots. Note that `@slot` is a non-stand
|
|
|
554
686
|
|
|
555
687
|
Descriptions are optional for named slots. Currently, the default slot cannot have a description.
|
|
556
688
|
|
|
557
|
-
Signature
|
|
689
|
+
**Signature:**
|
|
558
690
|
|
|
559
691
|
```js
|
|
560
692
|
/**
|
|
@@ -568,7 +700,32 @@ Omit the `slot-name` to type the default slot.
|
|
|
568
700
|
*/
|
|
569
701
|
```
|
|
570
702
|
|
|
571
|
-
Example
|
|
703
|
+
**Example:**
|
|
704
|
+
|
|
705
|
+
**Svelte 5 Runes:**
|
|
706
|
+
|
|
707
|
+
```svelte
|
|
708
|
+
<script>
|
|
709
|
+
/**
|
|
710
|
+
* @slot {{ prop: number; doubled: number; }}
|
|
711
|
+
* @slot {{}} title
|
|
712
|
+
* @slot {{ prop: number }} body - Customize the paragraph text.
|
|
713
|
+
*/
|
|
714
|
+
|
|
715
|
+
let { prop = 0, children, title, body } = $props();
|
|
716
|
+
</script>
|
|
717
|
+
|
|
718
|
+
<h1>
|
|
719
|
+
{@render children?.({ prop, doubled: prop * 2 })}
|
|
720
|
+
{@render title?.()}
|
|
721
|
+
</h1>
|
|
722
|
+
|
|
723
|
+
<p>
|
|
724
|
+
{@render body?.({ prop })}
|
|
725
|
+
</p>
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
572
729
|
|
|
573
730
|
```svelte
|
|
574
731
|
<script>
|
|
@@ -595,6 +752,8 @@ Example:
|
|
|
595
752
|
|
|
596
753
|
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
754
|
|
|
755
|
+
When parsing runes components, `sveld` also maps `{@render ...}` calls back into the same slot metadata used for traditional `<slot>` declarations.
|
|
756
|
+
|
|
598
757
|
For slots with props (e.g., `let:prop`), the generated type uses a Snippet-compatible signature:
|
|
599
758
|
|
|
600
759
|
```ts
|
|
@@ -697,9 +856,11 @@ export default class DataTable<Row> extends SvelteComponentTyped<
|
|
|
697
856
|
|
|
698
857
|
Use the `@event` tag to type dispatched events. An event name is required and a description optional.
|
|
699
858
|
|
|
859
|
+
In Svelte 5 runes components, callback props such as `onclick` are treated as component props, not events. The `events` output remains reserved for dispatched events and legacy forwarded events.
|
|
860
|
+
|
|
700
861
|
Use `null` as the value if no event detail is provided.
|
|
701
862
|
|
|
702
|
-
Signature
|
|
863
|
+
**Signature:**
|
|
703
864
|
|
|
704
865
|
```js
|
|
705
866
|
/**
|
|
@@ -708,22 +869,48 @@ Signature:
|
|
|
708
869
|
*/
|
|
709
870
|
```
|
|
710
871
|
|
|
711
|
-
Example
|
|
872
|
+
**Example:**
|
|
712
873
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
874
|
+
**Svelte 5 Runes:**
|
|
875
|
+
|
|
876
|
+
```svelte
|
|
877
|
+
<script>
|
|
878
|
+
/**
|
|
879
|
+
* @event {{ key: string }} button:key
|
|
880
|
+
* @event {null} key - Fired when `key` changes.
|
|
881
|
+
*/
|
|
882
|
+
|
|
883
|
+
let { key = "" } = $props();
|
|
884
|
+
|
|
885
|
+
import { createEventDispatcher } from "svelte";
|
|
886
|
+
|
|
887
|
+
const dispatch = createEventDispatcher();
|
|
888
|
+
|
|
889
|
+
$effect(() => {
|
|
890
|
+
dispatch("button:key", { key });
|
|
891
|
+
if (key) dispatch("key");
|
|
892
|
+
});
|
|
893
|
+
</script>
|
|
894
|
+
```
|
|
718
895
|
|
|
719
|
-
|
|
896
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
720
897
|
|
|
721
|
-
|
|
898
|
+
```svelte
|
|
899
|
+
<script>
|
|
900
|
+
/**
|
|
901
|
+
* @event {{ key: string }} button:key
|
|
902
|
+
* @event {null} key - Fired when `key` changes.
|
|
903
|
+
*/
|
|
904
|
+
|
|
905
|
+
export let key = "";
|
|
906
|
+
|
|
907
|
+
import { createEventDispatcher } from "svelte";
|
|
722
908
|
|
|
723
|
-
const dispatch = createEventDispatcher();
|
|
909
|
+
const dispatch = createEventDispatcher();
|
|
724
910
|
|
|
725
|
-
$: dispatch("button:key", { key });
|
|
726
|
-
$: if (key) dispatch("key");
|
|
911
|
+
$: dispatch("button:key", { key });
|
|
912
|
+
$: if (key) dispatch("key");
|
|
913
|
+
</script>
|
|
727
914
|
```
|
|
728
915
|
|
|
729
916
|
Output:
|
|
@@ -743,7 +930,7 @@ export default class Component extends SvelteComponentTyped<
|
|
|
743
930
|
|
|
744
931
|
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
932
|
|
|
746
|
-
Signature
|
|
933
|
+
**Signature:**
|
|
747
934
|
|
|
748
935
|
```js
|
|
749
936
|
/**
|
|
@@ -754,30 +941,64 @@ Signature:
|
|
|
754
941
|
*/
|
|
755
942
|
```
|
|
756
943
|
|
|
757
|
-
Example
|
|
944
|
+
**Example:**
|
|
758
945
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
946
|
+
**Svelte 5 Runes:**
|
|
947
|
+
|
|
948
|
+
```svelte
|
|
949
|
+
<script>
|
|
950
|
+
/**
|
|
951
|
+
* Fired when the user submits the form
|
|
952
|
+
*
|
|
953
|
+
* @event submit
|
|
954
|
+
* @type {object}
|
|
955
|
+
* @property {string} name - The user's name
|
|
956
|
+
* @property {string} email - The user's email address
|
|
957
|
+
* @property {boolean} newsletter - Whether the user opted into the newsletter
|
|
958
|
+
*/
|
|
769
959
|
|
|
770
|
-
|
|
960
|
+
let { name = "Jane Doe", email = "jane@example.com", newsletter = true } = $props();
|
|
771
961
|
|
|
772
|
-
|
|
962
|
+
import { createEventDispatcher } from "svelte";
|
|
773
963
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
964
|
+
const dispatch = createEventDispatcher();
|
|
965
|
+
|
|
966
|
+
function handleSubmit() {
|
|
967
|
+
dispatch("submit", { name, email, newsletter });
|
|
968
|
+
}
|
|
969
|
+
</script>
|
|
970
|
+
|
|
971
|
+
<button type="button" onclick={handleSubmit}>Submit</button>
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
975
|
+
|
|
976
|
+
```svelte
|
|
977
|
+
<script>
|
|
978
|
+
/**
|
|
979
|
+
* Fired when the user submits the form
|
|
980
|
+
*
|
|
981
|
+
* @event submit
|
|
982
|
+
* @type {object}
|
|
983
|
+
* @property {string} name - The user's name
|
|
984
|
+
* @property {string} email - The user's email address
|
|
985
|
+
* @property {boolean} newsletter - Whether the user opted into the newsletter
|
|
986
|
+
*/
|
|
987
|
+
|
|
988
|
+
export let name = "Jane Doe";
|
|
989
|
+
export let email = "jane@example.com";
|
|
990
|
+
export let newsletter = true;
|
|
991
|
+
|
|
992
|
+
import { createEventDispatcher } from "svelte";
|
|
993
|
+
|
|
994
|
+
const dispatch = createEventDispatcher();
|
|
995
|
+
|
|
996
|
+
function handleSubmit() {
|
|
997
|
+
dispatch("submit", { name, email, newsletter });
|
|
998
|
+
}
|
|
999
|
+
</script>
|
|
1000
|
+
|
|
1001
|
+
<button type="button" on:click={handleSubmit}>Submit</button>
|
|
781
1002
|
```
|
|
782
1003
|
|
|
783
1004
|
Output:
|
|
@@ -804,30 +1025,70 @@ export default class Component extends SvelteComponentTyped<
|
|
|
804
1025
|
|
|
805
1026
|
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
1027
|
|
|
807
|
-
Example
|
|
1028
|
+
**Example:**
|
|
808
1029
|
|
|
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
|
-
*/
|
|
1030
|
+
**Svelte 5 Runes:**
|
|
820
1031
|
|
|
821
|
-
|
|
1032
|
+
```svelte
|
|
1033
|
+
<script>
|
|
1034
|
+
/**
|
|
1035
|
+
* Snowball event fired when throwing a snowball
|
|
1036
|
+
*
|
|
1037
|
+
* @event snowball
|
|
1038
|
+
* @type {object}
|
|
1039
|
+
* @property {boolean} isPacked - Indicates whether the snowball is tightly packed
|
|
1040
|
+
* @property {number} speed - The speed of the snowball in mph
|
|
1041
|
+
* @property {string} [color] - Optional color of the snowball
|
|
1042
|
+
* @property {number} [density=0.9] - Optional density with default value
|
|
1043
|
+
*/
|
|
822
1044
|
|
|
823
|
-
|
|
1045
|
+
let { speed = 50 } = $props();
|
|
824
1046
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
1047
|
+
import { createEventDispatcher } from "svelte";
|
|
1048
|
+
|
|
1049
|
+
const dispatch = createEventDispatcher();
|
|
1050
|
+
|
|
1051
|
+
function throwSnowball() {
|
|
1052
|
+
dispatch("snowball", {
|
|
1053
|
+
isPacked: true,
|
|
1054
|
+
speed,
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
</script>
|
|
1058
|
+
|
|
1059
|
+
<button type="button" onclick={throwSnowball}>Throw</button>
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1063
|
+
|
|
1064
|
+
```svelte
|
|
1065
|
+
<script>
|
|
1066
|
+
/**
|
|
1067
|
+
* Snowball event fired when throwing a snowball
|
|
1068
|
+
*
|
|
1069
|
+
* @event snowball
|
|
1070
|
+
* @type {object}
|
|
1071
|
+
* @property {boolean} isPacked - Indicates whether the snowball is tightly packed
|
|
1072
|
+
* @property {number} speed - The speed of the snowball in mph
|
|
1073
|
+
* @property {string} [color] - Optional color of the snowball
|
|
1074
|
+
* @property {number} [density=0.9] - Optional density with default value
|
|
1075
|
+
*/
|
|
1076
|
+
|
|
1077
|
+
export let speed = 50;
|
|
1078
|
+
|
|
1079
|
+
import { createEventDispatcher } from "svelte";
|
|
1080
|
+
|
|
1081
|
+
const dispatch = createEventDispatcher();
|
|
1082
|
+
|
|
1083
|
+
function throwSnowball() {
|
|
1084
|
+
dispatch("snowball", {
|
|
1085
|
+
isPacked: true,
|
|
1086
|
+
speed,
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
</script>
|
|
1090
|
+
|
|
1091
|
+
<button type="button" on:click={throwSnowball}>Throw</button>
|
|
831
1092
|
```
|
|
832
1093
|
|
|
833
1094
|
Output:
|
|
@@ -869,9 +1130,43 @@ When you use `setContext` in a component, `sveld` will:
|
|
|
869
1130
|
|
|
870
1131
|
**Modal.svelte**
|
|
871
1132
|
|
|
1133
|
+
**Svelte 5 Runes:**
|
|
1134
|
+
|
|
872
1135
|
```svelte
|
|
873
1136
|
<script>
|
|
874
|
-
import { setContext } from
|
|
1137
|
+
import { setContext } from "svelte";
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* Close the modal
|
|
1141
|
+
* @type {() => void}
|
|
1142
|
+
*/
|
|
1143
|
+
const close = () => {
|
|
1144
|
+
// Close logic
|
|
1145
|
+
};
|
|
1146
|
+
|
|
1147
|
+
/**
|
|
1148
|
+
* Open the modal with content
|
|
1149
|
+
* @type {(component: any, props?: any) => void}
|
|
1150
|
+
*/
|
|
1151
|
+
const open = (component, props) => {
|
|
1152
|
+
// Open logic
|
|
1153
|
+
};
|
|
1154
|
+
|
|
1155
|
+
setContext("simple-modal", { open, close });
|
|
1156
|
+
|
|
1157
|
+
let { children } = $props();
|
|
1158
|
+
</script>
|
|
1159
|
+
|
|
1160
|
+
<div class="modal">
|
|
1161
|
+
{@render children?.()}
|
|
1162
|
+
</div>
|
|
1163
|
+
```
|
|
1164
|
+
|
|
1165
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1166
|
+
|
|
1167
|
+
```svelte
|
|
1168
|
+
<script>
|
|
1169
|
+
import { setContext } from "svelte";
|
|
875
1170
|
|
|
876
1171
|
/**
|
|
877
1172
|
* Close the modal
|
|
@@ -889,7 +1184,7 @@ When you use `setContext` in a component, `sveld` will:
|
|
|
889
1184
|
// Open logic
|
|
890
1185
|
};
|
|
891
1186
|
|
|
892
|
-
setContext(
|
|
1187
|
+
setContext("simple-modal", { open, close });
|
|
893
1188
|
</script>
|
|
894
1189
|
|
|
895
1190
|
<div class="modal">
|
|
@@ -1027,7 +1322,7 @@ There are several ways to provide type information for contexts:
|
|
|
1027
1322
|
|
|
1028
1323
|
You can use the `@restProps` tag to specify the element tags that `$$restProps` is forwarded to.
|
|
1029
1324
|
|
|
1030
|
-
Signature
|
|
1325
|
+
**Signature:**
|
|
1031
1326
|
|
|
1032
1327
|
```js
|
|
1033
1328
|
/**
|
|
@@ -1039,14 +1334,35 @@ Signature:
|
|
|
1039
1334
|
*/
|
|
1040
1335
|
```
|
|
1041
1336
|
|
|
1042
|
-
Example
|
|
1337
|
+
**Example:**
|
|
1338
|
+
|
|
1339
|
+
**Svelte 5 Runes:**
|
|
1340
|
+
|
|
1341
|
+
```svelte
|
|
1342
|
+
<script>
|
|
1343
|
+
import Button from "./Button.svelte";
|
|
1344
|
+
|
|
1345
|
+
/** @restProps {h1 | button} */
|
|
1346
|
+
let { edit = false, children, ...restProps } = $props();
|
|
1347
|
+
</script>
|
|
1348
|
+
|
|
1349
|
+
{#if edit}
|
|
1350
|
+
<Button {...restProps} />
|
|
1351
|
+
{:else}
|
|
1352
|
+
<h1 {...restProps}>
|
|
1353
|
+
{@render children?.()}
|
|
1354
|
+
</h1>
|
|
1355
|
+
{/if}
|
|
1356
|
+
```
|
|
1357
|
+
|
|
1358
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1043
1359
|
|
|
1044
1360
|
```svelte
|
|
1045
1361
|
<script>
|
|
1046
1362
|
/** @restProps {h1 | button} */
|
|
1047
1363
|
export let edit = false;
|
|
1048
1364
|
|
|
1049
|
-
import Button from "
|
|
1365
|
+
import Button from "./Button.svelte";
|
|
1050
1366
|
</script>
|
|
1051
1367
|
|
|
1052
1368
|
{#if edit}
|
|
@@ -1062,7 +1378,7 @@ In some cases, a component may be based on another component. The `@extendProps`
|
|
|
1062
1378
|
|
|
1063
1379
|
> **Note:** `@extends` is supported as an alias but `@extendProps` is preferred to avoid conflicts with standard JSDoc `@extends` (used for class inheritance).
|
|
1064
1380
|
|
|
1065
|
-
Signature
|
|
1381
|
+
**Signature:**
|
|
1066
1382
|
|
|
1067
1383
|
```js
|
|
1068
1384
|
/**
|
|
@@ -1070,7 +1386,7 @@ Signature:
|
|
|
1070
1386
|
*/
|
|
1071
1387
|
```
|
|
1072
1388
|
|
|
1073
|
-
Example
|
|
1389
|
+
**Example:**
|
|
1074
1390
|
|
|
1075
1391
|
```js
|
|
1076
1392
|
/** @extendProps {"./Button.svelte"} ButtonProps */
|
|
@@ -1093,7 +1409,7 @@ However, the `generics` attribute only works if using `lang="ts"`; the language
|
|
|
1093
1409
|
|
|
1094
1410
|
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
1411
|
|
|
1096
|
-
Signature
|
|
1412
|
+
**Signature:**
|
|
1097
1413
|
|
|
1098
1414
|
```js
|
|
1099
1415
|
/**
|
|
@@ -1101,7 +1417,7 @@ Signature:
|
|
|
1101
1417
|
*/
|
|
1102
1418
|
```
|
|
1103
1419
|
|
|
1104
|
-
Example
|
|
1420
|
+
**Example:**
|
|
1105
1421
|
|
|
1106
1422
|
```js
|
|
1107
1423
|
/**
|
|
@@ -1109,6 +1425,49 @@ Example
|
|
|
1109
1425
|
*/
|
|
1110
1426
|
```
|
|
1111
1427
|
|
|
1428
|
+
**Component example:**
|
|
1429
|
+
|
|
1430
|
+
**Svelte 5 Runes:**
|
|
1431
|
+
|
|
1432
|
+
```svelte
|
|
1433
|
+
<script>
|
|
1434
|
+
/**
|
|
1435
|
+
* @typedef {{ id: string | number; [key: string]: any; }} DataTableRow
|
|
1436
|
+
* @typedef {Exclude<keyof Row, "id">} DataTableKey<Row>
|
|
1437
|
+
* @typedef {{ key: DataTableKey<Row>; value: string; }} DataTableHeader<Row=DataTableRow>
|
|
1438
|
+
* @template {DataTableRow} <Row extends DataTableRow = DataTableRow>
|
|
1439
|
+
* @generics {Row extends DataTableRow = DataTableRow} Row
|
|
1440
|
+
*/
|
|
1441
|
+
|
|
1442
|
+
/** @type {ReadonlyArray<DataTableHeader<Row>>} */
|
|
1443
|
+
let { headers = [], rows = [], children } = $props();
|
|
1444
|
+
</script>
|
|
1445
|
+
|
|
1446
|
+
{@render children?.({ headers, rows })}
|
|
1447
|
+
```
|
|
1448
|
+
|
|
1449
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1450
|
+
|
|
1451
|
+
```svelte
|
|
1452
|
+
<script>
|
|
1453
|
+
/**
|
|
1454
|
+
* @typedef {{ id: string | number; [key: string]: any; }} DataTableRow
|
|
1455
|
+
* @typedef {Exclude<keyof Row, "id">} DataTableKey<Row>
|
|
1456
|
+
* @typedef {{ key: DataTableKey<Row>; value: string; }} DataTableHeader<Row=DataTableRow>
|
|
1457
|
+
* @template {DataTableRow} <Row extends DataTableRow = DataTableRow>
|
|
1458
|
+
* @generics {Row extends DataTableRow = DataTableRow} Row
|
|
1459
|
+
*/
|
|
1460
|
+
|
|
1461
|
+
/** @type {ReadonlyArray<DataTableHeader<Row>>} */
|
|
1462
|
+
export let headers = [];
|
|
1463
|
+
|
|
1464
|
+
/** @type {ReadonlyArray<Row>} */
|
|
1465
|
+
export let rows = [];
|
|
1466
|
+
</script>
|
|
1467
|
+
|
|
1468
|
+
<slot {headers} {rows} />
|
|
1469
|
+
```
|
|
1470
|
+
|
|
1112
1471
|
The generated TypeScript definition will resemble the following:
|
|
1113
1472
|
|
|
1114
1473
|
```ts
|
|
@@ -1150,7 +1509,27 @@ The Svelte Language Server supports component-level comments through the followi
|
|
|
1150
1509
|
|
|
1151
1510
|
`sveld` will copy these over to the exported default component in the TypeScript definition.
|
|
1152
1511
|
|
|
1153
|
-
Example
|
|
1512
|
+
**Example:**
|
|
1513
|
+
|
|
1514
|
+
**Svelte 5 Runes:**
|
|
1515
|
+
|
|
1516
|
+
```svelte
|
|
1517
|
+
<!-- @component
|
|
1518
|
+
@example
|
|
1519
|
+
<Button>
|
|
1520
|
+
Text
|
|
1521
|
+
</Button>
|
|
1522
|
+
-->
|
|
1523
|
+
<script>
|
|
1524
|
+
let { children } = $props();
|
|
1525
|
+
</script>
|
|
1526
|
+
|
|
1527
|
+
<button>
|
|
1528
|
+
{@render children?.()}
|
|
1529
|
+
</button>
|
|
1530
|
+
```
|
|
1531
|
+
|
|
1532
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1154
1533
|
|
|
1155
1534
|
```svelte
|
|
1156
1535
|
<!-- @component
|
|
@@ -1186,7 +1565,7 @@ Exported functions and consts become accessor props in generated TypeScript defi
|
|
|
1186
1565
|
|
|
1187
1566
|
Note that `@type` tag annotations take precedence over `@param`/`@returns` tags.
|
|
1188
1567
|
|
|
1189
|
-
Signature
|
|
1568
|
+
**Signature:**
|
|
1190
1569
|
|
|
1191
1570
|
```js
|
|
1192
1571
|
/**
|
|
@@ -1197,7 +1576,54 @@ Signature:
|
|
|
1197
1576
|
*/
|
|
1198
1577
|
```
|
|
1199
1578
|
|
|
1200
|
-
Example
|
|
1579
|
+
**Example:**
|
|
1580
|
+
|
|
1581
|
+
**Svelte 5 Runes:**
|
|
1582
|
+
|
|
1583
|
+
```svelte
|
|
1584
|
+
<script>
|
|
1585
|
+
/**
|
|
1586
|
+
* @typedef {object} NotificationData
|
|
1587
|
+
* @property {string} [id] - Optional id for deduplication
|
|
1588
|
+
* @property {"error" | "info" | "success"} [kind]
|
|
1589
|
+
*/
|
|
1590
|
+
|
|
1591
|
+
let { children } = $props();
|
|
1592
|
+
|
|
1593
|
+
/**
|
|
1594
|
+
* Add a notification to the queue.
|
|
1595
|
+
* @param {NotificationData} notification
|
|
1596
|
+
* @returns {string} The notification id
|
|
1597
|
+
*/
|
|
1598
|
+
export function add(notification) {
|
|
1599
|
+
const id = notification.id ?? "id";
|
|
1600
|
+
return id;
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
/**
|
|
1604
|
+
* Remove a notification by id.
|
|
1605
|
+
* @param {string} id
|
|
1606
|
+
* @returns {boolean} True if the notification was found and removed
|
|
1607
|
+
*/
|
|
1608
|
+
export function remove(id) {
|
|
1609
|
+
return true;
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
/**
|
|
1613
|
+
* Get notification count.
|
|
1614
|
+
* @returns {number} The number of notifications
|
|
1615
|
+
*/
|
|
1616
|
+
export function getCount() {
|
|
1617
|
+
return 0;
|
|
1618
|
+
}
|
|
1619
|
+
</script>
|
|
1620
|
+
|
|
1621
|
+
<div>
|
|
1622
|
+
{@render children?.()}
|
|
1623
|
+
</div>
|
|
1624
|
+
```
|
|
1625
|
+
|
|
1626
|
+
**Svelte 3, 4, 5 (non-Runes):**
|
|
1201
1627
|
|
|
1202
1628
|
```svelte
|
|
1203
1629
|
<script>
|