Skip to content

Commit

Permalink
Move to render(args, context) pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
xeho91 committed May 21, 2024
1 parent 2fe01cb commit 94eac84
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 188 deletions.
14 changes: 6 additions & 8 deletions src/components/Story.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
import type { Meta, StoryObj } from '@storybook/svelte';
import type { Snippet } from 'svelte';
import type { Template } from '../index.js';
import type { TArgs, TContext } from '../index.js';
import {useStoriesExtractor, useStoryRenderer, useStoriesTemplate } from './context.svelte.js';
type Props = {
children?: Snippet<[Template<M>]>;
type Props = StoryObj<M> & {
children?: Snippet<[TArgs<M>, TContext<M>]>;
/**
* Id of the story.
*
Expand Down Expand Up @@ -35,7 +35,7 @@
source?: boolean | string;
}
const { children, name = "Default", id, play, ...restProps }:Props & StoryObj<M> = $props();
const { children, name = "Default", id, play, ...restProps }: Props = $props();
const extractor = useStoriesExtractor<M>();
const renderer = useStoryRenderer<M>();
Expand All @@ -59,14 +59,12 @@
injectIntoPlayFunction(renderer.storyContext, play);
}
});
const templateProps = $derived({ args: renderer.args, context: renderer.storyContext });
</script>

{#if isCurrentlyViewed}
{#if children}
{@render children(templateProps)}
{@render children(renderer.args, renderer.storyContext)}
{:else if storiesTemplate}
{@render storiesTemplate(templateProps)}
{@render storiesTemplate(renderer.args, renderer.storyContext)}
{/if}
{/if}
4 changes: 2 additions & 2 deletions src/components/context.svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Meta, StoryContext, StoryObj } from '@storybook/svelte';
import type { StoryName } from '@storybook/types';
import { getContext, hasContext, setContext, type Snippet } from 'svelte';

import type { Template } from '../index.js';
import type { TArgs, TContext } from '../index.js';

const KEYS = {
extractor: 'storybook-stories-extractor-context',
Expand Down Expand Up @@ -121,7 +121,7 @@ export function useStoryRenderer<M extends Meta>() {
}

function createStoriesTemplateContext<M extends Meta>() {
let template = $state<Snippet<[Template<M>]> | undefined>();
let template = $state<Snippet<[TArgs<M>, TContext<M>]> | undefined>();

function set(snippet?: typeof template) {
template = snippet;
Expand Down
6 changes: 2 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ if (module?.hot?.decline) {
}

// TODO: Consult if these are correct types
export type Template<M extends Meta> = {
args: M['args'] & StoryObj<M>['args'];
context: StoryContext<M['args']>;
};
export type TArgs<M extends Meta> = StoryObj<M>['args'];
export type TContext<M extends Meta> = StoryContext<M['args']>;

export function defineMeta<const M extends Meta>(meta: M) {
return {
Expand Down
32 changes: 16 additions & 16 deletions src/parser/extract-stories.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { compile, type Root } from "svelte/compiler";
import { compile, type Root } from 'svelte/compiler';

import type { StoriesFileMeta } from "./types.js";
import { walkOnModule } from "./walkers/module.js";
import { walkOnFragment } from "./walkers/fragment.js";
import type { StoriesFileMeta } from './types.js';
import { walkOnModule } from './walkers/module.js';
import { walkOnFragment } from './walkers/fragment.js';

/**
* Parse raw stories file component in Svelte format,
* and extract the most stories file meta,
* which are required to generate `StoryFn's` for `@storybook/svelte` components.
*/
export function extractStories(rawSource: string): StoriesFileMeta {
const { ast }: { ast: Root } = compile(rawSource, { modernAst: true });
const { module, fragment } = ast;
const { ast }: { ast: Root } = compile(rawSource, { modernAst: true });
const { module, fragment } = ast;

const moduleMeta = walkOnModule(module);
const fragmentMeta = walkOnFragment({
fragment,
rawSource,
addonComponentName: moduleMeta.addonComponentName,
});
const moduleMeta = walkOnModule(module);
const fragmentMeta = walkOnFragment({
fragment,
rawSource,
addonComponentName: moduleMeta.addonComponentName,
});

return {
module: moduleMeta,
fragment: fragmentMeta,
};
return {
module: moduleMeta,
fragment: fragmentMeta,
};
}
62 changes: 31 additions & 31 deletions src/parser/types.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,59 @@
import type { Meta } from "@storybook/svelte";
import type { Meta } from '@storybook/svelte';

import type { defineMeta } from "../index.js";
import type { defineMeta } from '../index.js';

export const ADDON_FN_NAME = "defineMeta";
export const ADDON_COMPONENT_NAME = "Story";
export const ADDON_META_VAR_NAME = "meta";
export const ADDON_FN_NAME = 'defineMeta';
export const ADDON_COMPONENT_NAME = 'Story';
export const ADDON_META_VAR_NAME = 'meta';

/**
* Data extracted from the static analytic of a single stories file - `*.stories.svelte`.
*/
export interface StoriesFileMeta {
module: ModuleMeta;
fragment: FragmentMeta;
module: ModuleMeta;
fragment: FragmentMeta;
}

/**
* Meta extracted from static analysis of the module tag _(`<script context="module">`)_
* from the single stories file - `*.stories.svelte`.
*/
export interface ModuleMeta extends Pick<Meta, "tags"> {
description?: string;
// NOTE: Why? It could be overriden with `import { defineMeta as d } ...`
addonFnName: typeof defineMeta.name | (string & {});
// NOTE: Why? It could be overriden with `const { Story: S } ...`
addonComponentName: typeof ADDON_COMPONENT_NAME | (string & {});
// NOTE: Why? It could be overriden with `const { meta: m } ...`
addonMetaVarName: typeof ADDON_META_VAR_NAME | (string & {});
export interface ModuleMeta extends Pick<Meta, 'tags'> {
description?: string;
// NOTE: Why? It could be overriden with `import { defineMeta as d } ...`
addonFnName: typeof defineMeta.name | (string & {});
// NOTE: Why? It could be overriden with `const { Story: S } ...`
addonComponentName: typeof ADDON_COMPONENT_NAME | (string & {});
// NOTE: Why? It could be overriden with `const { meta: m } ...`
addonMetaVarName: typeof ADDON_META_VAR_NAME | (string & {});
}

/**
* Meta extracted from static analysis of the `Fragment` _(html-like code)_
* from the single stories file - `*.stories.svelte`.
*/
export interface FragmentMeta {
stories: Record<StoryMeta["id"], StoryMeta>;
stories: Record<StoryMeta['id'], StoryMeta>;
}

/**
* Meta extracted from static analysis of the single <Story /> component
* in the stories file - `*.stories.svelte`.
*/
export interface StoryMeta {
/**
* Id of the story. By default is hashed, otherwise can be overriden.
*/
id: string;
/**
* Name of the story.
* @default "Default"
*/
name: string;
/**
* Description of the story, will display above the sample in docs mode.
*/
description?: string;
/** Raw source for children _(what is inside the <Story>...</Story> tags)_ */
rawSource?: string;
/**
* Id of the story. By default is hashed, otherwise can be overriden.
*/
id: string;
/**
* Name of the story.
* @default "Default"
*/
name: string;
/**
* Description of the story, will display above the sample in docs mode.
*/
description?: string;
/** Raw source for children _(what is inside the <Story>...</Story> tags)_ */
rawSource?: string;
}
7 changes: 3 additions & 4 deletions stories/Controls.stories.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
<script context="module">
import Controls from './Controls.svelte';
import { defineMeta } from '../src/index';
import Controls from './Controls.svelte';
/**
* This is an visual example for using/testing the args table
* @type {import("@storybook/svelte").Meta<Controls>}
*/
const { Story, meta } = defineMeta({
title: 'Addon/Controls',
Expand All @@ -29,7 +28,7 @@
sampleRequiredObject: { tool: 'storybook', rating: 10 },
}}
>
{#snippet children({ args })}
{#snippet children(args)}
<Controls {...args} />
{/snippet}
</Story>
Loading

0 comments on commit 94eac84

Please sign in to comment.