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 +63 -1
- package/lib/writer/writer-ts-definitions-core.js +19 -1
- package/package.json +1 -1
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
|
-
**
|
|
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
|
-
|
|
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;
|