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 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
 
@@ -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
- ```js
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
- * Specify the Carbon icon to render
351
- * @type {typeof import("carbon-icons-svelte").CarbonIcon}
352
- */
353
- 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>
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
- ```js
371
- /**
372
- * @typedef {string} AuthorName
373
- * @typedef {{ name?: AuthorName; dob?: string; }} Author
374
- */
416
+ **Svelte 5 Runes:**
375
417
 
376
- /** @type {Author} */
377
- export let author = {};
418
+ ```svelte
419
+ <script>
420
+ /**
421
+ * @typedef {string} AuthorName
422
+ * @typedef {{ name?: AuthorName; dob?: string; }} Author
423
+ */
378
424
 
379
- /** @type {Author[]} */
380
- export let authors = [];
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
- ```js
400
- /**
401
- * Represents a user in the system
402
- * @typedef {object} User
403
- * @property {string} name - The user's full name
404
- * @property {string} email - The user's email address
405
- * @property {number} age - The user's age in years
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
- /** @type {User} */
409
- export let user = { name: "John", email: "john@example.com", age: 30 };
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
- ```js
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
- /** @type {ComponentConfig} */
460
- export let config = { enabled: true, theme: "dark" };
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
- ```js
508
- /**
509
- * Callback fired when the value changes
510
- * @callback OnChange
511
- * @param {string} value - The new value
512
- * @param {number} index - The index of the changed item
513
- * @returns {void}
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
- ```js
714
- /**
715
- * @event {{ key: string }} button:key
716
- * @event {null} key – Fired when `key` changes.
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
- export let key = "";
896
+ **Svelte 3, 4, 5 (non-Runes):**
720
897
 
721
- import { createEventDispatcher } from "svelte";
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
- ```js
760
- /**
761
- * Fired when the user submits the form
762
- *
763
- * @event submit
764
- * @type {object}
765
- * @property {string} name - The user's name
766
- * @property {string} email - The user's email address
767
- * @property {boolean} newsletter - Whether the user opted into the newsletter
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
- import { createEventDispatcher } from "svelte";
960
+ let { name = "Jane Doe", email = "jane@example.com", newsletter = true } = $props();
771
961
 
772
- const dispatch = createEventDispatcher();
962
+ import { createEventDispatcher } from "svelte";
773
963
 
774
- function handleSubmit() {
775
- dispatch("submit", {
776
- name: "Jane Doe",
777
- email: "jane@example.com",
778
- newsletter: true,
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
- ```js
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
- 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
+ */
822
1044
 
823
- const dispatch = createEventDispatcher();
1045
+ let { speed = 50 } = $props();
824
1046
 
825
- function throwSnowball() {
826
- dispatch("snowball", {
827
- isPacked: true,
828
- speed: 50,
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 'svelte';
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('simple-modal', { open, close });
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>