diff --git a/code/renderers/svelte/src/components/PreviewRender.svelte b/code/renderers/svelte/src/components/PreviewRender.svelte
index b2900a0ddb24..3a3ef4ad5801 100644
--- a/code/renderers/svelte/src/components/PreviewRender.svelte
+++ b/code/renderers/svelte/src/components/PreviewRender.svelte
@@ -15,6 +15,8 @@
props = {},
/** @type {{[string]: () => {}}} Attach svelte event handlers */
on,
+ /** @type {any} whether this level of the decorator chain is the last, ie. the actual story */
+ argTypes,
} = storyFn();
let firstTime = true;
@@ -29,20 +31,16 @@
Component,
props,
on,
+ argTypes,
};
}
return storyFn();
}
// reactive, re-render on storyFn change
- $: ({ Component, props = {}, on } = getStoryFnValue(storyFn));
-
- const eventsFromArgTypes = Object.fromEntries(
- Object.entries(storyContext.argTypes)
- .filter(([k, v]) => v.action && props[k] != null)
- .map(([k, v]) => [v.action, props[k]])
- );
+ $: ({ Component, props = {}, on, argTypes } = getStoryFnValue(storyFn));
+ // set the argTypes context, read by the last SlotDecorator that renders the original story
if (!Component) {
showError({
title: `Expecting a Svelte component from the story: "${name}" of "${title}".`,
@@ -55,4 +53,4 @@
}
-
+
diff --git a/code/renderers/svelte/src/components/SlotDecorator.svelte b/code/renderers/svelte/src/components/SlotDecorator.svelte
index 8391eb0af6e3..27b80aae3412 100644
--- a/code/renderers/svelte/src/components/SlotDecorator.svelte
+++ b/code/renderers/svelte/src/components/SlotDecorator.svelte
@@ -6,20 +6,36 @@
export let Component;
export let props = {};
export let on = undefined;
+ export let argTypes = undefined;
let instance;
let decoratorInstance;
const svelteVersion = VERSION[0];
+
+ /*
+ Svelte Docgen will create argTypes for events with the name 'event_eventName'
+ The Actions addon will convert these to args because they are type: 'action'
+ We need to filter these args out so they are not passed to the component
+ */
+ let propsWithoutDocgenEvents;
+ $: propsWithoutDocgenEvents = Object.fromEntries(
+ Object.entries(props).filter(([key]) => !key.startsWith('event_'))
+ );
- if (on && svelteVersion < 5) {
+ if (argTypes && svelteVersion < 5) {
+ const eventsFromArgTypes = Object.fromEntries(
+ Object.entries(argTypes)
+ .filter(([key, value]) => value.action && props[key] != null)
+ .map(([key, value]) => [value.action, props[key]])
+ );
// Attach Svelte event listeners in Svelte v4
// In Svelte v5 this is not possible anymore as instances are no longer classes with $on() properties, so it will be a no-op
onMount(() => {
- Object.entries(on).forEach(([eventName, eventCallback]) => {
- // instance can be undefined if a decorator doesn't have
+ Object.entries({ ...eventsFromArgTypes, ...on }).forEach(([eventName, eventCallback]) => {
+ // instance can be undefined if a decorator doesn't have a
const inst = instance ?? decoratorInstance;
- inst?.$on?.(eventName, eventCallback)
+ inst?.$on?.(eventName, eventCallback);
});
});
}
@@ -27,8 +43,8 @@
{#if decorator}
-
+
{:else}
-
+
{/if}
diff --git a/code/renderers/svelte/src/decorators.ts b/code/renderers/svelte/src/decorators.ts
index 15ba2acf4831..200c6b41f006 100644
--- a/code/renderers/svelte/src/decorators.ts
+++ b/code/renderers/svelte/src/decorators.ts
@@ -74,7 +74,8 @@ function prepareStory(
};
}
- return preparedStory;
+ // no innerStory means this is the last story in the decorator chain, so it should create events from argTypes
+ return { ...preparedStory, argTypes: context.argTypes };
}
export function decorateStory(storyFn: any, decorators: any[]) {