sveld 0.25.5 → 0.25.7

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
@@ -14,7 +14,7 @@ The purpose of this project is to make third party Svelte component libraries co
14
14
  - [Component Index](https://github.com/IBM/carbon-components-svelte/blob/master/COMPONENT_INDEX.md): Markdown file documenting component props, slots, and events
15
15
  - [Component API](https://github.com/IBM/carbon-components-svelte/blob/master/docs/src/COMPONENT_API.json): Component API metadata in JSON format
16
16
 
17
- **Please note** that the generated TypeScript definitions require Svelte version 3.55 or greater.
17
+ **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()`).
18
18
 
19
19
  ---
20
20
 
@@ -125,6 +125,7 @@ export default class Button extends SvelteComponentTyped<
125
125
  - [@type](#type)
126
126
  - [@typedef](#typedef)
127
127
  - [@slot](#slot)
128
+ - [Svelte 5 Snippet Compatibility](#svelte-5-snippet-compatibility)
128
129
  - [@event](#event)
129
130
  - [Context API](#context-api)
130
131
  - [@restProps](#restprops)
@@ -534,6 +535,94 @@ Example:
534
535
  </p>
535
536
  ```
536
537
 
538
+ #### Svelte 5 Snippet Compatibility
539
+
540
+ 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.
541
+
542
+ For slots with props (e.g., `let:prop`), the generated type uses a Snippet-compatible signature:
543
+
544
+ ```ts
545
+ slotName?: (this: void, ...args: [{ prop: PropType }]) => void;
546
+ ```
547
+
548
+ For slots without props:
549
+
550
+ ```ts
551
+ slotName?: (this: void) => void;
552
+ ```
553
+
554
+ **Why this signature?**
555
+
556
+ - **`this: void`** – Ensures the snippet cannot be called with a `this` context, matching Svelte's internal enforcement that snippets are pure render functions
557
+ - **`...args: [Props]`** – Uses tuple spread for type-safe parameters. This accepts fixed-length tuples (like `[{ row: Row }]`) while rejecting array types (like `Props[]`), matching how Svelte's `Snippet<T>` type works
558
+
559
+ **Default slot (`children` prop):**
560
+
561
+ The default slot generates an optional `children` snippet prop:
562
+
563
+ ```svelte
564
+ <!-- Component with default slot that passes props -->
565
+ <Dropdown {items} selectedId="1">
566
+ {#snippet children({ item, index })}
567
+ <span>{item.text} (#{index})</span>
568
+ {/snippet}
569
+ </Dropdown>
570
+ ```
571
+
572
+ Generated types:
573
+
574
+ ```ts
575
+ type DropdownProps = {
576
+ items: Item[];
577
+ selectedId?: string;
578
+
579
+ // Default slot as children snippet prop
580
+ children?: (this: void, ...args: [{ item: Item; index: number }]) => void;
581
+ };
582
+ ```
583
+
584
+ **Named slots:**
585
+
586
+ ```svelte
587
+ <!-- Using the generated types with Svelte 5 syntax -->
588
+ <DataTable headers={headers} rows={rows}>
589
+ {#snippet cell({ cell, row })}
590
+ {#if cell.key === 'actions'}
591
+ <Button on:click={() => handleAction(row)}>Edit</Button>
592
+ {:else}
593
+ {cell.value}
594
+ {/if}
595
+ {/snippet}
596
+ </DataTable>
597
+ ```
598
+
599
+ The generated TypeScript definition includes both the snippet prop and the traditional slot definition:
600
+
601
+ ```ts
602
+ type DataTableProps<Row> = {
603
+ // ... other props
604
+
605
+ // Snippet prop for Svelte 5 compatibility
606
+ cell?: (
607
+ this: void,
608
+ ...args: [{ row: Row; cell: DataTableCell<Row>; rowIndex: number; cellIndex: number }]
609
+ ) => void;
610
+
611
+ // Default slot as children prop
612
+ children?: (this: void) => void;
613
+ };
614
+
615
+ export default class DataTable<Row> extends SvelteComponentTyped<
616
+ DataTableProps<Row>,
617
+ { /* events */ },
618
+ {
619
+ // Traditional slot definition (Svelte 3/4)
620
+ default: Record<string, never>;
621
+ cell: { row: Row; cell: DataTableCell<Row>; rowIndex: number; cellIndex: number };
622
+ }
623
+ > {}
624
+ ```
625
+
537
626
  ### `@event`
538
627
 
539
628
  Use the `@event` tag to type dispatched events. An event name is required and a description optional.
@@ -95,15 +95,33 @@ function genPropDef(def) {
95
95
  });
96
96
  // Generate snippet props for named slots (Svelte 5 compatibility)
97
97
  // Skip default slots and slots that conflict with existing prop names
98
- const snippet_props = (def.slots || [])
98
+ const named_snippet_props = (def.slots || [])
99
99
  .filter((slot) => !slot.default && slot.name != null && !existingPropNames.has(slot.name))
100
100
  .map((slot) => {
101
101
  const slotName = slot.name;
102
102
  const key = clampKey(slotName);
103
103
  const description = slot.description ? `/** ${slot.description} */\n ` : "";
104
+ // Use Snippet-compatible type: (this: void, ...args: [Props]) => void for slots with props
105
+ // or (this: void) => void for slots without props
106
+ const hasSlotProps = slot.slot_props && slot.slot_props !== "Record<string, never>";
107
+ const snippetType = hasSlotProps ? `(this: void, ...args: [${slot.slot_props}]) => void` : "(this: void) => void";
104
108
  return `
105
- ${description}${key}?: () => void;`;
109
+ ${description}${key}?: ${snippetType};`;
106
110
  });
111
+ // Generate children snippet prop for default slot (Svelte 5 compatibility)
112
+ const default_slot = (def.slots || []).find((slot) => slot.default || slot.name === null);
113
+ const children_snippet_prop = default_slot
114
+ ? (() => {
115
+ const description = default_slot.description ? `/** ${default_slot.description} */\n ` : "";
116
+ const hasSlotProps = default_slot.slot_props && default_slot.slot_props !== "Record<string, never>";
117
+ const snippetType = hasSlotProps
118
+ ? `(this: void, ...args: [${default_slot.slot_props}]) => void`
119
+ : "(this: void) => void";
120
+ return `
121
+ ${description}children?: ${snippetType};`;
122
+ })()
123
+ : "";
124
+ const snippet_props = [...named_snippet_props, children_snippet_prop].filter(Boolean);
107
125
  const props = [...initial_props, ...snippet_props].join("\n");
108
126
  const props_name = `${def.moduleName}Props`;
109
127
  let prop_def = EMPTY_STR;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sveld",
3
- "version": "0.25.5",
3
+ "version": "0.25.7",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Generate TypeScript definitions for your Svelte components.",
6
6
  "main": "./lib/index.js",