sveld 0.27.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 CHANGED
@@ -3,13 +3,22 @@
3
3
  [![NPM][npm]][npm-url]
4
4
  ![npm downloads to date](https://img.shields.io/npm/dt/sveld?color=262626&style=for-the-badge)
5
5
 
6
- `sveld` is a TypeScript definition generator 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/). The tool can also generate component documentation in Markdown and JSON formats.
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 (IDE) like VSCode.
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
- **Note:** `sveld` supports Svelte 3, 4, and 5, but does not support Svelte 5-specific syntax or runes-only usage. Components must use traditional Svelte syntax (e.g., `export let` for props, not `$props()`).
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 definition extends the official `SvelteComponentTyped` interface exported from Svelte.
40
+ The following generated `.d.ts` extends `SvelteComponentTyped`:
32
41
 
33
42
  **Button.svelte.d.ts**
34
43
 
@@ -119,6 +128,7 @@ export default class Button extends SvelteComponentTyped<
119
128
  - [API Reference](#api-reference)
120
129
  - [@type](#type)
121
130
  - [@typedef](#typedef)
131
+ - [@callback](#callback)
122
132
  - [@slot](#slot)
123
133
  - [Svelte 5 Snippet Compatibility](#svelte-5-snippet-compatibility)
124
134
  - [@event](#event)
@@ -309,6 +319,23 @@ sveld({
309
319
 
310
320
  ## API Reference
311
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
+
312
339
  ### `@type`
313
340
 
314
341
  Without a `@type` annotation, `sveld` will infer the primitive type for a prop:
@@ -327,7 +354,7 @@ export let id = `ccs-${Math.random().toString(36)}`;
327
354
 
328
355
  Use the `@type` tag to explicitly document the type. In the following example, the `kind` property has an enumerated (enum) type.
329
356
 
330
- Signature:
357
+ **Signature:**
331
358
 
332
359
  ```js
333
360
  /**
@@ -336,27 +363,47 @@ Signature:
336
363
  */
337
364
  ```
338
365
 
339
- Example:
366
+ **Example:**
340
367
 
341
- ```js
342
- /**
343
- * Specify the kind of button
344
- * @type {"primary" | "secondary" | "tertiary"}
345
- */
346
- export let kind = "primary";
368
+ **Svelte 5 Runes:**
347
369
 
348
- /**
349
- * Specify the Carbon icon to render
350
- * @type {typeof import("carbon-icons-svelte").CarbonIcon}
351
- */
352
- export let renderIcon = Close20;
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>
353
400
  ```
354
401
 
355
402
  ### `@typedef`
356
403
 
357
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.
358
405
 
359
- Signature:
406
+ **Signature:**
360
407
 
361
408
  ```js
362
409
  /**
@@ -364,26 +411,48 @@ Signature:
364
411
  */
365
412
  ```
366
413
 
367
- Example:
414
+ **Example:**
368
415
 
369
- ```js
370
- /**
371
- * @typedef {string} AuthorName
372
- * @typedef {{ name?: AuthorName; dob?: string; }} Author
373
- */
416
+ **Svelte 5 Runes:**
417
+
418
+ ```svelte
419
+ <script>
420
+ /**
421
+ * @typedef {string} AuthorName
422
+ * @typedef {{ name?: AuthorName; dob?: string; }} Author
423
+ */
424
+
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
+ */
374
442
 
375
- /** @type {Author} */
376
- export let author = {};
443
+ /** @type {Author} */
444
+ export let author = {};
377
445
 
378
- /** @type {Author[]} */
379
- export let authors = [];
446
+ /** @type {Author[]} */
447
+ export let authors = [];
448
+ </script>
380
449
  ```
381
450
 
382
451
  #### Using `@property` for complex typedefs
383
452
 
384
453
  For complex object types, use the `@property` tag to document individual properties. This provides better documentation and IDE support with per-property tooltips.
385
454
 
386
- Signature:
455
+ **Signature:**
387
456
 
388
457
  ```js
389
458
  /**
@@ -393,19 +462,40 @@ Signature:
393
462
  */
394
463
  ```
395
464
 
396
- Example:
465
+ **Example:**
397
466
 
398
- ```js
399
- /**
400
- * Represents a user in the system
401
- * @typedef {object} User
402
- * @property {string} name - The user's full name
403
- * @property {string} email - The user's email address
404
- * @property {number} age - The user's age in years
405
- */
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):**
485
+
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
+ */
406
495
 
407
- /** @type {User} */
408
- export let user = { name: "John", email: "john@example.com", age: 30 };
496
+ /** @type {User} */
497
+ export let user = { name: "John", email: "john@example.com", age: 30 };
498
+ </script>
409
499
  ```
410
500
 
411
501
  Output:
@@ -433,7 +523,7 @@ export type ComponentProps = {
433
523
 
434
524
  Following JSDoc standards, use square brackets to mark properties as optional. You can also specify default values using the `[propertyName=defaultValue]` syntax.
435
525
 
436
- Signature:
526
+ **Signature:**
437
527
 
438
528
  ```js
439
529
  /**
@@ -443,20 +533,42 @@ Signature:
443
533
  */
444
534
  ```
445
535
 
446
- Example:
536
+ **Example:**
447
537
 
448
- ```js
449
- /**
450
- * Configuration options for the component
451
- * @typedef {object} ComponentConfig
452
- * @property {boolean} enabled - Whether the component is enabled
453
- * @property {string} theme - The component theme
454
- * @property {number} [timeout=5000] - Optional timeout in milliseconds
455
- * @property {boolean} [debug] - Optional debug mode flag
456
- */
538
+ **Svelte 5 Runes:**
539
+
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
+ */
457
550
 
458
- /** @type {ComponentConfig} */
459
- export let config = { enabled: true, theme: "dark" };
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>
460
572
  ```
461
573
 
462
574
  Output:
@@ -484,13 +596,97 @@ export type ComponentProps = {
484
596
 
485
597
  > **Note:** The inline syntax `@typedef {{ name: string }} User` continues to work for backwards compatibility.
486
598
 
599
+ ### `@callback`
600
+
601
+ The `@callback` tag defines a function type using `@param` and `@returns` tags, following the [TypeScript JSDoc `@callback` specification](https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html#callback). Like `@typedef`, callbacks are exported from the generated TypeScript definition file.
602
+
603
+ This is useful for typing callback props without using inline function type syntax.
604
+
605
+ **Signature:**
606
+
607
+ ```js
608
+ /**
609
+ * Optional description
610
+ * @callback CallbackName
611
+ * @param {Type} paramName - Parameter description
612
+ * @returns {ReturnType}
613
+ */
614
+ ```
615
+
616
+ **Example:**
617
+
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
+ */
646
+
647
+ /** @type {OnChange} */
648
+ export let onChange = (value, index) => {};
649
+ </script>
650
+ ```
651
+
652
+ Output:
653
+
654
+ ```ts
655
+ /**
656
+ * Callback fired when the value changes
657
+ */
658
+ export type OnChange = (value: string, index: number) => void;
659
+
660
+ export type ComponentProps = {
661
+ /**
662
+ * Callback fired when the value changes
663
+ */
664
+ onChange?: OnChange;
665
+ };
666
+ ```
667
+
668
+ Callbacks can be combined with `@typedef` in the same comment block:
669
+
670
+ ```js
671
+ /**
672
+ * @typedef {"asc" | "desc"} SortDirection
673
+ * @callback SortFn
674
+ * @param {any} a
675
+ * @param {any} b
676
+ * @param {SortDirection} direction
677
+ * @returns {number}
678
+ */
679
+ ```
680
+
681
+ 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.
682
+
487
683
  ### `@slot`
488
684
 
489
685
  Use the `@slot` tag for typing component slots. Note that `@slot` is a non-standard JSDoc tag.
490
686
 
491
687
  Descriptions are optional for named slots. Currently, the default slot cannot have a description.
492
688
 
493
- Signature:
689
+ **Signature:**
494
690
 
495
691
  ```js
496
692
  /**
@@ -504,7 +700,32 @@ Omit the `slot-name` to type the default slot.
504
700
  */
505
701
  ```
506
702
 
507
- 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):**
508
729
 
509
730
  ```svelte
510
731
  <script>
@@ -531,6 +752,8 @@ Example:
531
752
 
532
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.
533
754
 
755
+ When parsing runes components, `sveld` also maps `{@render ...}` calls back into the same slot metadata used for traditional `<slot>` declarations.
756
+
534
757
  For slots with props (e.g., `let:prop`), the generated type uses a Snippet-compatible signature:
535
758
 
536
759
  ```ts
@@ -633,9 +856,11 @@ export default class DataTable<Row> extends SvelteComponentTyped<
633
856
 
634
857
  Use the `@event` tag to type dispatched events. An event name is required and a description optional.
635
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
+
636
861
  Use `null` as the value if no event detail is provided.
637
862
 
638
- Signature:
863
+ **Signature:**
639
864
 
640
865
  ```js
641
866
  /**
@@ -644,22 +869,48 @@ Signature:
644
869
  */
645
870
  ```
646
871
 
647
- Example:
872
+ **Example:**
648
873
 
649
- ```js
650
- /**
651
- * @event {{ key: string }} button:key
652
- * @event {null} key – Fired when `key` changes.
653
- */
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();
654
888
 
655
- export let key = "";
889
+ $effect(() => {
890
+ dispatch("button:key", { key });
891
+ if (key) dispatch("key");
892
+ });
893
+ </script>
894
+ ```
656
895
 
657
- import { createEventDispatcher } from "svelte";
896
+ **Svelte 3, 4, 5 (non-Runes):**
658
897
 
659
- const dispatch = createEventDispatcher();
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";
660
908
 
661
- $: dispatch("button:key", { key });
662
- $: if (key) dispatch("key");
909
+ const dispatch = createEventDispatcher();
910
+
911
+ $: dispatch("button:key", { key });
912
+ $: if (key) dispatch("key");
913
+ </script>
663
914
  ```
664
915
 
665
916
  Output:
@@ -679,7 +930,7 @@ export default class Component extends SvelteComponentTyped<
679
930
 
680
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.
681
932
 
682
- Signature:
933
+ **Signature:**
683
934
 
684
935
  ```js
685
936
  /**
@@ -690,30 +941,64 @@ Signature:
690
941
  */
691
942
  ```
692
943
 
693
- Example:
944
+ **Example:**
694
945
 
695
- ```js
696
- /**
697
- * Fired when the user submits the form
698
- *
699
- * @event submit
700
- * @type {object}
701
- * @property {string} name - The user's name
702
- * @property {string} email - The user's email address
703
- * @property {boolean} newsletter - Whether the user opted into the newsletter
704
- */
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
+ */
705
959
 
706
- import { createEventDispatcher } from "svelte";
960
+ let { name = "Jane Doe", email = "jane@example.com", newsletter = true } = $props();
707
961
 
708
- const dispatch = createEventDispatcher();
962
+ import { createEventDispatcher } from "svelte";
709
963
 
710
- function handleSubmit() {
711
- dispatch("submit", {
712
- name: "Jane Doe",
713
- email: "jane@example.com",
714
- newsletter: true,
715
- });
716
- }
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>
717
1002
  ```
718
1003
 
719
1004
  Output:
@@ -740,30 +1025,70 @@ export default class Component extends SvelteComponentTyped<
740
1025
 
741
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.
742
1027
 
743
- Example:
1028
+ **Example:**
744
1029
 
745
- ```js
746
- /**
747
- * Snowball event fired when throwing a snowball
748
- *
749
- * @event snowball
750
- * @type {object}
751
- * @property {boolean} isPacked - Indicates whether the snowball is tightly packed
752
- * @property {number} speed - The speed of the snowball in mph
753
- * @property {string} [color] - Optional color of the snowball
754
- * @property {number} [density=0.9] - Optional density with default value
755
- */
1030
+ **Svelte 5 Runes:**
756
1031
 
757
- import { createEventDispatcher } from "svelte";
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
+ */
758
1044
 
759
- const dispatch = createEventDispatcher();
1045
+ let { speed = 50 } = $props();
760
1046
 
761
- function throwSnowball() {
762
- dispatch("snowball", {
763
- isPacked: true,
764
- speed: 50,
765
- });
766
- }
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>
767
1092
  ```
768
1093
 
769
1094
  Output:
@@ -805,9 +1130,11 @@ When you use `setContext` in a component, `sveld` will:
805
1130
 
806
1131
  **Modal.svelte**
807
1132
 
1133
+ **Svelte 5 Runes:**
1134
+
808
1135
  ```svelte
809
1136
  <script>
810
- import { setContext } from 'svelte';
1137
+ import { setContext } from "svelte";
811
1138
 
812
1139
  /**
813
1140
  * Close the modal
@@ -825,7 +1152,39 @@ When you use `setContext` in a component, `sveld` will:
825
1152
  // Open logic
826
1153
  };
827
1154
 
828
- setContext('simple-modal', { open, close });
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";
1170
+
1171
+ /**
1172
+ * Close the modal
1173
+ * @type {() => void}
1174
+ */
1175
+ const close = () => {
1176
+ // Close logic
1177
+ };
1178
+
1179
+ /**
1180
+ * Open the modal with content
1181
+ * @type {(component: any, props?: any) => void}
1182
+ */
1183
+ const open = (component, props) => {
1184
+ // Open logic
1185
+ };
1186
+
1187
+ setContext("simple-modal", { open, close });
829
1188
  </script>
830
1189
 
831
1190
  <div class="modal">
@@ -963,7 +1322,7 @@ There are several ways to provide type information for contexts:
963
1322
 
964
1323
  You can use the `@restProps` tag to specify the element tags that `$$restProps` is forwarded to.
965
1324
 
966
- Signature:
1325
+ **Signature:**
967
1326
 
968
1327
  ```js
969
1328
  /**
@@ -975,14 +1334,35 @@ Signature:
975
1334
  */
976
1335
  ```
977
1336
 
978
- 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):**
979
1359
 
980
1360
  ```svelte
981
1361
  <script>
982
1362
  /** @restProps {h1 | button} */
983
1363
  export let edit = false;
984
1364
 
985
- import Button from "../";
1365
+ import Button from "./Button.svelte";
986
1366
  </script>
987
1367
 
988
1368
  {#if edit}
@@ -998,7 +1378,7 @@ In some cases, a component may be based on another component. The `@extendProps`
998
1378
 
999
1379
  > **Note:** `@extends` is supported as an alias but `@extendProps` is preferred to avoid conflicts with standard JSDoc `@extends` (used for class inheritance).
1000
1380
 
1001
- Signature:
1381
+ **Signature:**
1002
1382
 
1003
1383
  ```js
1004
1384
  /**
@@ -1006,7 +1386,7 @@ Signature:
1006
1386
  */
1007
1387
  ```
1008
1388
 
1009
- Example:
1389
+ **Example:**
1010
1390
 
1011
1391
  ```js
1012
1392
  /** @extendProps {"./Button.svelte"} ButtonProps */
@@ -1029,7 +1409,7 @@ However, the `generics` attribute only works if using `lang="ts"`; the language
1029
1409
 
1030
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`.
1031
1411
 
1032
- Signature:
1412
+ **Signature:**
1033
1413
 
1034
1414
  ```js
1035
1415
  /**
@@ -1037,7 +1417,7 @@ Signature:
1037
1417
  */
1038
1418
  ```
1039
1419
 
1040
- Example
1420
+ **Example:**
1041
1421
 
1042
1422
  ```js
1043
1423
  /**
@@ -1045,6 +1425,49 @@ Example
1045
1425
  */
1046
1426
  ```
1047
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
+
1048
1471
  The generated TypeScript definition will resemble the following:
1049
1472
 
1050
1473
  ```ts
@@ -1086,7 +1509,27 @@ The Svelte Language Server supports component-level comments through the followi
1086
1509
 
1087
1510
  `sveld` will copy these over to the exported default component in the TypeScript definition.
1088
1511
 
1089
- 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):**
1090
1533
 
1091
1534
  ```svelte
1092
1535
  <!-- @component
@@ -1122,7 +1565,7 @@ Exported functions and consts become accessor props in generated TypeScript defi
1122
1565
 
1123
1566
  Note that `@type` tag annotations take precedence over `@param`/`@returns` tags.
1124
1567
 
1125
- Signature:
1568
+ **Signature:**
1126
1569
 
1127
1570
  ```js
1128
1571
  /**
@@ -1133,7 +1576,54 @@ Signature:
1133
1576
  */
1134
1577
  ```
1135
1578
 
1136
- 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):**
1137
1627
 
1138
1628
  ```svelte
1139
1629
  <script>