sveld 0.25.4 → 0.25.6

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,67 @@ 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 named 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
+ **Example usage with Svelte 5 snippets:**
560
+
561
+ ```svelte
562
+ <!-- Using the generated types with Svelte 5 syntax -->
563
+ <DataTable headers={headers} rows={rows}>
564
+ {#snippet cell({ cell, row })}
565
+ {#if cell.key === 'actions'}
566
+ <Button on:click={() => handleAction(row)}>Edit</Button>
567
+ {:else}
568
+ {cell.value}
569
+ {/if}
570
+ {/snippet}
571
+ </DataTable>
572
+ ```
573
+
574
+ The generated TypeScript definition includes both the snippet prop and the traditional slot definition:
575
+
576
+ ```ts
577
+ type DataTableProps<Row> = {
578
+ // ... other props
579
+
580
+ // Snippet prop for Svelte 5 compatibility
581
+ cell?: (
582
+ this: void,
583
+ ...args: [{ row: Row; cell: DataTableCell<Row>; rowIndex: number; cellIndex: number }]
584
+ ) => void;
585
+ };
586
+
587
+ export default class DataTable<Row> extends SvelteComponentTyped<
588
+ DataTableProps<Row>,
589
+ { /* events */ },
590
+ {
591
+ // Traditional slot definition (Svelte 3/4)
592
+ cell: { row: Row; cell: DataTableCell<Row>; rowIndex: number; cellIndex: number };
593
+ }
594
+ > {}
595
+ ```
596
+
597
+ > **Note:** Snippet props are only generated for named slots. The default slot does not generate a snippet prop to avoid conflicts with the `children` prop pattern.
598
+
537
599
  ### `@event`
538
600
 
539
601
  Use the `@event` tag to type dispatched events. An event name is required and a description optional.
@@ -68,6 +68,8 @@ function addCommentLine(value, returnValue) {
68
68
  return `* ${returnValue || value}\n`;
69
69
  }
70
70
  function genPropDef(def) {
71
+ // Collect existing prop names to avoid conflicts with snippet props
72
+ const existingPropNames = new Set(def.props.filter((prop) => !prop.isFunctionDeclaration && prop.kind !== "const").map((prop) => prop.name));
71
73
  const initial_props = def.props
72
74
  .filter((prop) => !prop.isFunctionDeclaration && prop.kind !== "const")
73
75
  .map((prop) => {
@@ -91,7 +93,22 @@ function genPropDef(def) {
91
93
  ${prop_comments.length > 0 ? `/**\n${prop_comments}*/` : EMPTY_STR}
92
94
  ${prop.name}${prop.isRequired ? "" : "?"}: ${prop_value};`;
93
95
  });
94
- const props = initial_props.join("\n");
96
+ // Generate snippet props for named slots (Svelte 5 compatibility)
97
+ // Skip default slots and slots that conflict with existing prop names
98
+ const snippet_props = (def.slots || [])
99
+ .filter((slot) => !slot.default && slot.name != null && !existingPropNames.has(slot.name))
100
+ .map((slot) => {
101
+ const slotName = slot.name;
102
+ const key = clampKey(slotName);
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";
108
+ return `
109
+ ${description}${key}?: ${snippetType};`;
110
+ });
111
+ const props = [...initial_props, ...snippet_props].join("\n");
95
112
  const props_name = `${def.moduleName}Props`;
96
113
  let prop_def = EMPTY_STR;
97
114
  const genericsName = def.generics ? `<${def.generics[0]}>` : "";
@@ -443,6 +460,7 @@ function writeTsDefinition(component) {
443
460
  rest_props,
444
461
  extends: _extends,
445
462
  generics,
463
+ slots,
446
464
  });
447
465
  const generic = generics ? `<${generics[1]}>` : "";
448
466
  const genericProps = generics ? `${props_name}<${generics[0]}>` : props_name;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sveld",
3
- "version": "0.25.4",
3
+ "version": "0.25.6",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Generate TypeScript definitions for your Svelte components.",
6
6
  "main": "./lib/index.js",