Skip to content

Commit

Permalink
Merge pull request #219 from storybookjs/fix-types
Browse files Browse the repository at this point in the history
fix: Resolve existing type issues
  • Loading branch information
xeho91 authored Nov 5, 2024
2 parents 8a7172b + 161a0fb commit 73be782
Show file tree
Hide file tree
Showing 26 changed files with 398 additions and 362 deletions.
5 changes: 2 additions & 3 deletions examples/Button.stories.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
component: Button,
tags: ['autodocs'],
args: {
children: 'Click me',
onclick: onclickFn,
},
argTypes: {
Expand All @@ -37,8 +36,8 @@
setTemplate(template);
</script>

{#snippet template({ children, ...args }: Args<typeof Story>, context: StoryContext<typeof Story>)}
<Button {...args}>{children}</Button>
{#snippet template(args: Args<typeof Story>, context: StoryContext<typeof Story>)}
<Button {...args}>{'Click me'}</Button>
{/snippet}

<!-- Only use this sparingly as the main CTA. -->
Expand Down
20 changes: 3 additions & 17 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 3 additions & 15 deletions src/compiler/pre-transform/codemods/template-to-snippet.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,7 @@ describe(transformTemplateToSnippet.name, () => {
`;
const component = await parseAndExtractSvelteNode<SvelteAST.Component>(code, 'Component');

expect(
print(
transformTemplateToSnippet({ component })
)
).toMatchInlineSnapshot(`
expect(print(transformTemplateToSnippet({ component }))).toMatchInlineSnapshot(`
"{#snippet sb_default_template(args)}
<Button {...args} variant="primary" />
{/snippet}"
Expand All @@ -43,11 +39,7 @@ describe(transformTemplateToSnippet.name, () => {
`;
const component = await parseAndExtractSvelteNode<SvelteAST.Component>(code, 'Component');

expect(
print(
transformTemplateToSnippet({ component })
)
).toMatchInlineSnapshot(`
expect(print(transformTemplateToSnippet({ component }))).toMatchInlineSnapshot(`
"{#snippet coolTemplate(args)}
<Button {...args} variant="primary" />
{/snippet}"
Expand All @@ -66,11 +58,7 @@ describe(transformTemplateToSnippet.name, () => {
`;
const component = await parseAndExtractSvelteNode<SvelteAST.Component>(code, 'Component');

expect(
print(
transformTemplateToSnippet({ component })
)
).toMatchInlineSnapshot(`
expect(print(transformTemplateToSnippet({ component }))).toMatchInlineSnapshot(`
"{#snippet sb_default_template(_args, context)}
<p>{context.args}</p>
{/snippet}"
Expand Down
75 changes: 26 additions & 49 deletions src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,28 @@
import type { PlayFunctionContext } from '@storybook/types';
import type { ComponentProps, Snippet } from 'svelte';
import type { EmptyObject, Primitive } from 'type-fest';
import type { StoryContext as StorybookStoryContext } from '@storybook/types';
import { createRawSnippet, type ComponentProps, type Snippet } from 'svelte';
import type { Primitive } from 'type-fest';
import { describe, expectTypeOf, it } from 'vitest';

import { defineMeta, type Args, type StoryContext } from '#index';
import StoryComponent from './runtime/Story.svelte';

import { defineMeta, type Args, type StoryContext } from './index';
import type {
Meta,
StoryAnnotations,
StoryCmp,
StoryContext as BaseStoryContext,
SvelteRenderer,
MapSnippetsToAcceptPrimitives,
} from '#types';

import Button from '../examples/components/Button.svelte';

describe(defineMeta.name, () => {
// it('works when no meta entry "component" is provided', () => {
// const { Story, meta } = defineMeta({
// args: {
// sample: 0,
// },
// play(context) {
// expectTypeOf(context).not.toBeAny();
// expectTypeOf(context).toMatchTypeOf<
// PlayFunctionContext<SvelteRenderer<Component<{ sample: 0 }>>>
// >();
// expectTypeOf(context.args).not.toBeAny();
// expectTypeOf(context.args).toMatchTypeOf<MapSnippetsToAcceptPrimitives<{ sample: 0 }>>();
// },
// });

// expectTypeOf(Story).toMatchTypeOf<StoryCmp<EmptyObject, { sample: 0 }, Meta<{ sample: 0 }>>>();
// expectTypeOf(meta).toMatchTypeOf<Meta<Component<{ sample: 0 }>>>();
// });

it('works with provided meta entry "component" entry', () => {
const { Story, meta } = defineMeta({
component: Button,
args: {
children: 'Click me',
children: createRawSnippet(() => ({
render: () => 'Click me',
})),
onclick: (event) => {
expectTypeOf(event).not.toBeAny();
expectTypeOf(event).toEqualTypeOf<
Expand All @@ -49,14 +32,11 @@ describe(defineMeta.name, () => {
},
play(context) {
expectTypeOf(context).not.toBeAny();
expectTypeOf(context).toMatchTypeOf<PlayFunctionContext<SvelteRenderer<typeof Button>>>();
expectTypeOf(context.args).toMatchTypeOf<
MapSnippetsToAcceptPrimitives<ComponentProps<Button>>
>();
expectTypeOf(context).toMatchTypeOf<StorybookStoryContext<SvelteRenderer<typeof Button>>>();
},
});

expectTypeOf(Story).toMatchTypeOf<StoryCmp<EmptyObject, typeof Button, Meta<typeof Button>>>();
expectTypeOf(Story).toMatchTypeOf<typeof StoryComponent<typeof Button>>();
expectTypeOf(meta).toMatchTypeOf<Meta<typeof Button>>();
});
});
Expand All @@ -66,7 +46,9 @@ describe("type helper for snippets 'Args'", () => {
const { Story } = defineMeta({
component: Button,
args: {
children: 'Click me',
children: createRawSnippet(() => ({
render: () => 'Click me',
})),
onclick: (event) => {
expectTypeOf(event).not.toBeAny();
expectTypeOf(event).toEqualTypeOf<
Expand All @@ -76,17 +58,12 @@ describe("type helper for snippets 'Args'", () => {
},
play(context) {
expectTypeOf(context).not.toBeAny();
expectTypeOf(context).toMatchTypeOf<PlayFunctionContext<SvelteRenderer<typeof Button>>>();
expectTypeOf(context.args).toMatchTypeOf<
MapSnippetsToAcceptPrimitives<ComponentProps<Button>>
>();
expectTypeOf(context).toMatchTypeOf<StorybookStoryContext<SvelteRenderer<typeof Button>>>();
},
});
expectTypeOf<Args<typeof Story>>().not.toBeNever();
expectTypeOf<Args<typeof Story>>().not.toBeNullable();
expectTypeOf<Args<typeof Story>>().toMatchTypeOf<
StoryAnnotations<typeof Button, Meta<typeof Button>>['args']
>();
expectTypeOf<Args<typeof Story>>().toMatchTypeOf<StoryAnnotations<typeof Button>['args']>();
expectTypeOf<Args<typeof Story>['children']>().toMatchTypeOf<Snippet | Primitive>();
expectTypeOf<Args<typeof Story>['children']>().toBeNullable();
});
Expand All @@ -97,7 +74,9 @@ describe("type helper for snippets 'StoryContext'", () => {
const { Story, meta } = defineMeta({
component: Button,
args: {
children: 'Click me',
children: createRawSnippet(() => ({
render: () => 'Click me',
})),
onclick: (event) => {
expectTypeOf(event).not.toBeAny();
expectTypeOf(event).toEqualTypeOf<
Expand All @@ -107,16 +86,12 @@ describe("type helper for snippets 'StoryContext'", () => {
},
play(context) {
expectTypeOf(context).not.toBeAny();
expectTypeOf(context).toMatchTypeOf<PlayFunctionContext<SvelteRenderer<typeof Button>>>();
expectTypeOf(context.args).toMatchTypeOf<
MapSnippetsToAcceptPrimitives<ComponentProps<Button>>
>();
expectTypeOf(context).toMatchTypeOf<StorybookStoryContext<SvelteRenderer<typeof Button>>>();
},
});

expectTypeOf<StoryContext<typeof Story>>().toMatchTypeOf<
BaseStoryContext<typeof Button, typeof meta>
>();
expectTypeOf<StoryContext<typeof Story>>().toMatchTypeOf<BaseStoryContext<typeof Button>>();
expectTypeOf(meta).toMatchTypeOf<Meta<typeof Button>>();
});
});

Expand All @@ -125,13 +100,15 @@ describe("component 'Story' destructured from 'defineMeta", () => {
const { Story } = defineMeta({
component: Button,
args: {
children: 'Click me',
children: createRawSnippet(() => ({
render: () => 'Click me',
})),
},
});

type TStoryProps = ComponentProps<typeof Story>;

expectTypeOf(Story).toMatchTypeOf<StoryCmp<EmptyObject, typeof Button, Meta<typeof Button>>>();
expectTypeOf(Story).toMatchTypeOf<typeof StoryComponent<typeof Button>>();
expectTypeOf<TStoryProps>().not.toBeNever();
expectTypeOf<Meta<typeof Button>['args']>().toBeNullable();
expectTypeOf<NonNullable<Meta<typeof Button>['args']>['children']>().toBeNullable();
Expand Down
43 changes: 19 additions & 24 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
import type { Args as BaseArgs } from '@storybook/types';
import type { EmptyObject } from 'type-fest';

import type {
Meta as MetaType,
StoryCmp,
StoryContext as BaseStoryContext,
StoryAnnotations,
Cmp,
} from '#types';

import StoryComponent from './runtime/Story.svelte';
// TODO: Remove in next major release
import LegacyMetaComponent from './runtime/LegacyMeta.svelte';
Expand All @@ -18,26 +7,29 @@ import LegacyStoryComponent from './runtime/LegacyStory.svelte';
import LegacyTemplateComponent from './runtime/LegacyTemplate.svelte';

export { setTemplate } from './runtime/contexts/template.svelte';
import type {
Meta as MetaType,
StoryContext as BaseStoryContext,
StoryAnnotations,
Cmp,
} from './types';

export function defineMeta<
const TOverrideArgs extends BaseArgs = EmptyObject,
const TCmp extends Cmp = Cmp,
>(meta: MetaType<TCmp>) {
export function defineMeta<const TCmp extends Cmp>(meta: MetaType<TCmp>) {
return {
Story: StoryComponent as StoryCmp<EmptyObject, TCmp, typeof meta>,
Story: StoryComponent as typeof StoryComponent<TCmp>,
meta,
};
}

export type Args<TStoryCmp> =
TStoryCmp extends StoryCmp<infer _TOverrideArgs, infer TCmpOrArgs, infer TMeta>
? NonNullable<StoryAnnotations<TCmpOrArgs, TMeta>['args']>
: never;
export type Args<TStoryCmp> = TStoryCmp extends typeof StoryComponent<infer TCmp extends Cmp>
? NonNullable<StoryAnnotations<TCmp>['args']>
: never;

export type StoryContext<TStoryCmp> =
TStoryCmp extends StoryCmp<infer _TOverrideArgs, infer TCmpOrArgs, infer TMeta>
? BaseStoryContext<TCmpOrArgs, TMeta>
: never;
export type StoryContext<TStoryCmp> = TStoryCmp extends typeof StoryComponent<
infer TCmp extends Cmp
>
? BaseStoryContext<TCmp>
: never;

// TODO: Remove in next major release
export {
Expand All @@ -57,3 +49,6 @@ export {
*/
LegacyTemplateComponent as Template,
};

// TODO: Remove in next major release
export * from './legacy-types.d';
Loading

0 comments on commit 73be782

Please sign in to comment.