Skip to content

Commit

Permalink
Update stories examples
Browse files Browse the repository at this point in the history
  • Loading branch information
xeho91 committed May 16, 2024
1 parent 4322fcf commit 3395b76
Show file tree
Hide file tree
Showing 19 changed files with 456 additions and 443 deletions.
118 changes: 118 additions & 0 deletions src/parser/walkers/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { logger } from "@storybook/client-logger";
import dedent from "dedent";
import type { Attribute, Component, SnippetBlock } from "svelte/compiler";

export function getStoryName(attributes: Component["attributes"]) {
return getStringFromAttribute("name", attributes) ?? "Default";
}

export function getDescription(node: Component) {
const { parent } = node;

if (parent?.type === "Comment") {
return dedent`${parent.data}`;
}
}

export function getStoryId({
attributes,
name,
storiesIds,
}: {
attributes: Component["attributes"];
name: string;
storiesIds: Set<string>;
}) {
const id = getStringFromAttribute("id", attributes);

if (id) {
return id;
}

let generated = name.replace(/\W+(.|$)/g, (_, chr) => chr.toUpperCase());

if (storiesIds.has(generated)) {
logger.warn(
`Story name conflict with exports - Please add an explicit id for story ${name}`,
);
generated += hashCode(name);
}

return generated;
}

function hashCode(str: string) {
const h = str
.split("")
.reduce((prev, curr) => ((prev << 5) - prev + curr.charCodeAt(0)) | 0, 0);

return Math.abs(h).toString(16);
}

export function getStringFromAttribute(
name: string,
attributes: Component["attributes"],
) {
const attribute = lookupAttribute(name, attributes);

if (!attribute) {
return;
}

const { value } = attribute;

if (value === true) {
throw new Error(`Attribute 'name' is not a string`);
}

if (value.length === 1 && value[0].type === "Text") {
return value[0].data;
}

throw new Error(`Attribute "name" is not static`);
}

export function lookupAttribute(
name: string,
attributes: Component["attributes"],
) {
return attributes.find((node) => {
if (node.type === "Attribute" && node.name === name) {
return node.value;
}
}) as Attribute | undefined;
}

export function getChildrenRawSource({
node,
rawSource,
}: {
node: Component;
rawSource: string;
}) {
const { fragment } = node;
const { nodes } = fragment;

// Ignore addon components without children
if (nodes.length === 0) {
return;
}

const snippetBlockChildren = nodes.find(
(c) => c.type === "SnippetBlock" && c.expression.name === "children",
) as SnippetBlock | undefined;

if (snippetBlockChildren) {
const { body } = snippetBlockChildren;
const { nodes } = body;
const { start } = nodes[0];
const { end } = nodes[nodes.length - 1];

return dedent`${rawSource.slice(start, end)}`;
}

const { start } = nodes[0];
const { end } = nodes[nodes.length - 1];

return dedent`${rawSource.slice(start, end)}`;
}
21 changes: 21 additions & 0 deletions stories/Actions.stories.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script context="module">
import { action } from '@storybook/addon-actions';
export const meta = {
title: 'Addon/Actions',
parameters: {
controls: { disable: true },
interactions: { disable: true },
},
};
</script>

<script>
import { Story } from '../src/index';
</script>

<Story>
<button onclick={action('I am logging in the actions tab')}>
Click me to see an a log in the <strong>Actions</strong> tab
</button>
</Story>
76 changes: 0 additions & 76 deletions stories/ArgsTableView.svelte

This file was deleted.

35 changes: 35 additions & 0 deletions stories/Controls.stories.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script context="module">
import { Story } from '@storybook/addon-svelte-csf';
import Controls from './Controls.svelte';
/**
* This is an visual example for using/testing the args table
* @type {import("@storybook/svelte").Meta<Controls>}
*/
export const meta = {
title: 'Addon/Controls',
component: Controls,
parameters: {
actions: { disable: true },
interactions: { disable: true },
},
tags: ['autodocs'],
};
</script>

<Story
name="Playground"
args={{
sampleRequiredBoolean: true,
sampleRequiredString: 'I agree',
sampleRequiredNumber: 10,
sampleRequiredArray: ['I', 'like', 'Svelte', 'and', 'Storybook'],
sampleRequiredEnum: 'storybook',
sampleRequiredObject: { tool: 'storybook', rating: 10 },
}}
>
{#snippet children({ args })}
<Controls {...args} />
{/snippet}
</Story>
137 changes: 137 additions & 0 deletions stories/Controls.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<script>
/**
* Description for `sampleBoolean` component prop.
* NOTE: The type is automatically infered.
*/
export let sampleDefaultBoolean = false;
/**
* Description for `sampleOptionalBoolean` component prop.
* @type {boolean | undefined}
*/
export let sampleOptionalBoolean;
/**
* Description for `sampleRequiredBoolean` component prop.
* @type {boolean}
*/
export let sampleRequiredBoolean;
/**
* Description for `sampleDefaultString` component prop.
* NOTE: The type is automatically infered.
*/
export let sampleDefaultString = 'Storybook 🤝 Svelte';
/**
* Description for `sampleOptionalString` component prop.
* @type {string | undefined}
*/
export let sampleOptionalString;
/**
* Description for `sampleRequiredString` component prop.
* @type {string}
*/
export let sampleRequiredString;
/**
* Description for `sampleDefaultNumber` component prop.
* NOTE: The type is automatically infered.
*/
export let sampleDefaultNumber = 9000;
/**
* Description for `sampleOptionalNumber` component prop.
* @type {number | number}
*/
export let sampleOptionalNumber;
/**
* Description for `sampleRequiredNumber` component prop.
* @type {number}
*/
export let sampleRequiredNumber;
/**
* Description for `sampleDefaultArray` component prop.
* NOTE: The type is automatically infered.
*/
export let sampleDefaultArray = ['Storybook', 'loves', 'Svelte'];
/**
* Description for `sampleOptionalArray` component prop.
* @type {string[] | undefined}
*/
export let sampleOptionalArray;
/**
* Description for `sampleRequiredArray` component prop.
* @type {string[]}
*/
export let sampleRequiredArray;
/**
* @typedef Tool
* @type {'svelte' | 'storybook'}
*/
/**
* Description for `sampleDefaultEnum` component prop.
* @type {Tool}
*/
export let sampleDefaultEnum = 'svelte';
/**
* Description for `sampleOptionalEnum` component prop.
* @type {Tool | undefined}
*/
export let sampleOptionalEnum;
/**
* Description for `sampleRequiredEnum` component prop.
* @type {Tool}
*/
export let sampleRequiredEnum;
/**
* Description for `sampleDefaultObject` component prop.
* NOTE: The type is automatically infered.
*/
export let sampleDefaultObject = {
tool: 'svelte',
rating: 9000,
};
/**
* Description for `sampleOptionalObject` component prop.
* @type {typeof sampleDefaultObject | undefined}
*/
export let sampleOptionalObject;
/**
* Description for `sampleRequiredObject` component prop.
* @type {typeof sampleDefaultObject}
*/
export let sampleRequiredObject;
$: props = {
sampleDefaultBoolean,
sampleOptionalBoolean,
sampleRequiredBoolean,
sampleDefaultString,
sampleOptionalString,
sampleRequiredString,
sampleDefaultNumber,
sampleOptionalNumber,
sampleRequiredNumber,
sampleDefaultArray,
sampleOptionalArray,
sampleRequiredArray,
sampleDefaultEnum,
sampleOptionalEnum,
sampleRequiredEnum,
sampleDefaultObject,
sampleOptionalObject,
sampleRequiredObject,
};
</script>

<code>
{#each Object.entries(props) as [name, value]}
<strong>{name}</strong>: {JSON.stringify(value)}<br />
{/each}
</code>
Loading

0 comments on commit 3395b76

Please sign in to comment.