sveld 0.29.0 → 0.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -129,7 +129,7 @@ export default class Button extends SvelteComponentTyped<
129
129
  - [@type](#type)
130
130
  - [@typedef](#typedef)
131
131
  - [@callback](#callback)
132
- - [@slot](#slot)
132
+ - [@slot / @snippet](#slot--snippet)
133
133
  - [Svelte 5 Snippet Compatibility](#svelte-5-snippet-compatibility)
134
134
  - [@event](#event)
135
135
  - [Context API](#context-api)
@@ -369,18 +369,23 @@ Use the `@type` tag to explicitly document the type. In the following example, t
369
369
 
370
370
  ```svelte
371
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();
372
+ let {
373
+ /**
374
+ * Specify the kind of button
375
+ * @type {"primary" | "secondary" | "tertiary"}
376
+ */
377
+ kind = "primary",
378
+ /**
379
+ * Specify the Carbon icon to render
380
+ * @type {typeof import("carbon-icons-svelte").CarbonIcon}
381
+ */
382
+ renderIcon = Close20,
383
+ } = $props();
381
384
  </script>
382
385
  ```
383
386
 
387
+ For runes components with multiple destructured props, place JSDoc on the individual property you want to document. A declaration-level JSDoc block is only used as a fallback when the destructure exposes a single public prop.
388
+
384
389
  **Svelte 3, 4, 5 (non-Runes):**
385
390
 
386
391
  ```svelte
@@ -680,9 +685,9 @@ Callbacks can be combined with `@typedef` in the same comment block:
680
685
 
681
686
  When `@returns` is omitted, the return type defaults to `void`. When no `@param` tags are present, the callback is typed as a no-argument function.
682
687
 
683
- ### `@slot`
688
+ ### `@slot` / `@snippet`
684
689
 
685
- Use the `@slot` tag for typing component slots. Note that `@slot` is a non-standard JSDoc tag.
690
+ Use the `@slot` tag for typing component slots. For Svelte 5 runes components, `@snippet` is also supported as an alias. Both are non-standard JSDoc tags.
686
691
 
687
692
  Descriptions are optional for named slots. Currently, the default slot cannot have a description.
688
693
 
@@ -691,12 +696,14 @@ Descriptions are optional for named slots. Currently, the default slot cannot ha
691
696
  ```js
692
697
  /**
693
698
  * @slot {Type} slot-name [slot description]
699
+ * @snippet {Type} snippet-name [snippet description]
694
700
  */
695
701
 
696
702
  Omit the `slot-name` to type the default slot.
697
703
 
698
704
  /**
699
705
  * @slot {Type}
706
+ * @snippet {Type}
700
707
  */
701
708
  ```
702
709
 
@@ -707,9 +714,9 @@ Omit the `slot-name` to type the default slot.
707
714
  ```svelte
708
715
  <script>
709
716
  /**
710
- * @slot {{ prop: number; doubled: number; }}
711
- * @slot {{}} title
712
- * @slot {{ prop: number }} body - Customize the paragraph text.
717
+ * @snippet {{ prop: number; doubled: number; }}
718
+ * @snippet {{}} title
719
+ * @snippet {{ prop: number }} body - Customize the paragraph text.
713
720
  */
714
721
 
715
722
  let { prop = 0, children, title, body } = $props();
@@ -752,7 +759,7 @@ Omit the `slot-name` to type the default slot.
752
759
 
753
760
  For Svelte 5 compatibility, `sveld` automatically generates optional snippet props for all slots. This allows consumers to use either the traditional slot syntax or Svelte 5's `{#snippet}` syntax.
754
761
 
755
- When parsing runes components, `sveld` also maps `{@render ...}` calls back into the same slot metadata used for traditional `<slot>` declarations.
762
+ When parsing runes components, `sveld` maps `{@render ...}` calls back into the same slot metadata used for traditional `<slot>` declarations. Reserved snippet props such as `children`, along with named snippet props discovered from `{@render ...}`, are represented through `slots` metadata and generated snippet prop types rather than duplicated in the `props` output.
756
763
 
757
764
  For slots with props (e.g., `let:prop`), the generated type uses a Snippet-compatible signature:
758
765
 
@@ -856,7 +863,7 @@ export default class DataTable<Row> extends SvelteComponentTyped<
856
863
 
857
864
  Use the `@event` tag to type dispatched events. An event name is required and a description optional.
858
865
 
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.
866
+ In Svelte 5 runes components, callback props such as `onclick` are treated as component props, not events. The `events` output remains reserved for real dispatched events and legacy forwarded events. If a runes component documents `@event foo` and exposes a matching callback prop like `onfoo` without actually dispatching or forwarding `foo`, `sveld` aliases that documentation onto the callback prop instead of synthesizing an emitted event.
860
867
 
861
868
  Use `null` as the value if no event detail is provided.
862
869
 
@@ -873,6 +880,20 @@ Use `null` as the value if no event detail is provided.
873
880
 
874
881
  **Svelte 5 Runes:**
875
882
 
883
+ ```svelte
884
+ <script>
885
+ /**
886
+ * Fired when a value is saved.
887
+ * @event {{ id: string }} save
888
+ */
889
+ let { onsave } = $props();
890
+ </script>
891
+
892
+ <button onclick={() => onsave?.({ id: "1" })}>Save</button>
893
+ ```
894
+
895
+ **Svelte 5 Runes with dispatched events:**
896
+
876
897
  ```svelte
877
898
  <script>
878
899
  /**
@@ -1439,8 +1460,13 @@ Because `sveld` is designed to support JavaScript-only usage as a baseline, the
1439
1460
  * @generics {Row extends DataTableRow = DataTableRow} Row
1440
1461
  */
1441
1462
 
1442
- /** @type {ReadonlyArray<DataTableHeader<Row>>} */
1443
- let { headers = [], rows = [], children } = $props();
1463
+ let {
1464
+ /** @type {ReadonlyArray<DataTableHeader<Row>>} */
1465
+ headers = [],
1466
+ /** @type {ReadonlyArray<Row>} */
1467
+ rows = [],
1468
+ children,
1469
+ } = $props();
1444
1470
  </script>
1445
1471
 
1446
1472
  {@render children?.({ headers, rows })}
@@ -80,7 +80,7 @@ interface ComponentSlot {
80
80
  fallback?: string;
81
81
  /** TypeScript type definition for slot props (e.g., "{ title: string }") */
82
82
  slot_props?: string;
83
- /** Description extracted from JSDoc `@slot` tags */
83
+ /** Description extracted from JSDoc `@slot` or `@snippet` tags */
84
84
  description?: string;
85
85
  }
86
86
  /**
@@ -308,6 +308,8 @@ export default class ComponentParser {
308
308
  private readonly restPropLocals;
309
309
  /** Tracks prop locals that are used as snippet/render props */
310
310
  private readonly snippetPropLocals;
311
+ /** Per-declarator type metadata extracted from modern AST `$props()` annotations */
312
+ private readonly runesPropTypeMetadataByDeclaratorStart;
311
313
  /** Component-level lexical scope shared by instance script and template */
312
314
  private readonly componentScope;
313
315
  /** Precomputed lexical scopes for nested AST nodes */
@@ -323,6 +325,7 @@ export default class ComponentParser {
323
325
  private trackPropLocalName;
324
326
  private getPropByLocalOrPublic;
325
327
  private getPropTypeByLocalOrPublic;
328
+ private getRunesPropTypeMetadata;
326
329
  private declareScopeBinding;
327
330
  private resolveIdentifierToReactiveProp;
328
331
  private collectPatternIdentifiers;
@@ -347,7 +350,7 @@ export default class ComponentParser {
347
350
  * Extracts and categorizes JSDoc tags from a parsed comment.
348
351
  *
349
352
  * Separates tags into type, param, returns, and additional categories while
350
- * excluding tags that are handled separately (extends, restProps, slot, event, typedef).
353
+ * excluding tags that are handled separately (extends, restProps, slot/snippet, event, typedef).
351
354
  *
352
355
  * @param parsed - The parsed comment result from comment-parser
353
356
  * @returns An object containing categorized tags and the comment description
@@ -390,6 +393,7 @@ export default class ComponentParser {
390
393
  private static findJSDocComment;
391
394
  private findAdjacentJSDocComment;
392
395
  private processNodeJSDoc;
396
+ private processLeadingCommentsJSDoc;
393
397
  /**
394
398
  * Processes JSDoc comments from leadingComments and extracts structured information.
395
399
  *
@@ -423,6 +427,7 @@ export default class ComponentParser {
423
427
  * ```
424
428
  */
425
429
  private processJSDocComment;
430
+ private buildRunesPropTypeMetadata;
426
431
  /**
427
432
  * Checks if a MemberExpression represents a well-known numeric constant.
428
433
  *
@@ -640,6 +645,7 @@ export default class ComponentParser {
640
645
  * ```
641
646
  */
642
647
  private addDispatchedEvent;
648
+ private normalizeRunesCallbackProps;
643
649
  /**
644
650
  * Parses custom types, events, slots, and other JSDoc annotations from component comments.
645
651
  *