Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Addon-docs: Add Controls argument autodetection for svelte #12347

Merged
merged 16 commits into from
Sep 2, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions addons/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
"js-string-escape": "^1.0.1",
"lodash": "^4.17.15",
"prop-types": "^15.7.2",
"sveltedoc-parser": "^3.0.4",
BlackFenix2 marked this conversation as resolved.
Show resolved Hide resolved
"react-element-to-jsx-string": "^14.3.1",
"regenerator-runtime": "^0.13.3",
"remark-external-links": "^6.0.0",
Expand Down
1 change: 1 addition & 0 deletions addons/docs/src/frameworks/svelte/HOC.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
});
</script>

<svelte:options accessors={true} />
BlackFenix2 marked this conversation as resolved.
Show resolved Hide resolved
<div id={hash} />
4 changes: 4 additions & 0 deletions addons/docs/src/frameworks/svelte/config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { extractArgTypes } from './extractArgTypes';
BlackFenix2 marked this conversation as resolved.
Show resolved Hide resolved
import { extractComponentDescription } from '../../lib/docgen';
import { prepareForInline } from './prepareForInline';

export const parameters = {
docs: {
inlineStories: true,
prepareForInline,
extractArgTypes,
extractComponentDescription,
},
};
75 changes: 75 additions & 0 deletions addons/docs/src/frameworks/svelte/extractArgTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/* eslint-disable new-cap */
BlackFenix2 marked this conversation as resolved.
Show resolved Hide resolved
/* eslint-disable no-underscore-dangle */
import { ArgTypes } from '@storybook/api';

import { ArgTypesExtractor, hasDocgen, extractComponentProps } from '../../lib/docgen';

type ComponentWithDocgen = {
__docgen: {
components: [];
computed: [];
data: [
{
defaultValue: any;
description: string;
keywords: [];
kind: string;
name: string;
readonly: boolean;
static: boolean;
type: { kind: string; text: string; type: string };
visibility: string;
}
];
description: null;
events: [];
keywords: [];
methods: [];
name: string;
refs: [];
slots: [];
version: number;
};
};

export const extractArgTypes: ArgTypesExtractor = (component) => {
const comp: ComponentWithDocgen = new component({ props: {} });
const docs = comp.__docgen;

const results: ArgTypes = {};
docs.data.forEach((item) => {
results[item.name] = {
control: { type: parseType(item.type.type) },
name: item.name,
description: item.description,
type: {},
defaultValue: item.defaultValue,
table: {
defaultValue: {
summary: item.defaultValue,
},
},
};
});

return results;
};

/**
* Function to convert the type from sveltedoc-parser to a storybook type
* @param typeName
* @returns string
*/
const parseType = (typeName: string) => {
switch (typeName) {
case 'string':
return 'text';

BlackFenix2 marked this conversation as resolved.
Show resolved Hide resolved
case 'enum':
return 'radio';
case 'any':
return 'object';
default:
return typeName;
}
};
13 changes: 13 additions & 0 deletions addons/docs/src/frameworks/svelte/preset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import path from 'path';

import { Configuration } from 'webpack';

export function webpackFinal(webpackConfig: Configuration, options: any = {}) {
webpackConfig.module.rules.push({
test: /\.svelte$/,
loader: path.resolve(`${__dirname}/svelte-docgen-loader`),
enforce: 'pre',
});

return webpackConfig;
}
39 changes: 39 additions & 0 deletions addons/docs/src/frameworks/svelte/svelte-docgen-loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* eslint-disable no-param-reassign */
// @ts-ignore
BlackFenix2 marked this conversation as resolved.
Show resolved Hide resolved
import svelteDoc from 'sveltedoc-parser';

import * as path from 'path';

/**
* webpack loader for sveltedoc-parser
* @param source raw svelte component
*/
export default async function svelteDocgen(source: string) {
// get filename for source content
const file = path.basename(this._module.resource);

// set SvelteDoc options
const options = {
fileContent: source,
version: 3,
};

let docgen = '';

try {
const componentDoc = await svelteDoc.parse(options);

// populate filename in docgen
componentDoc.name = path.basename(file);

docgen = `
export const __docgen = ${JSON.stringify(componentDoc)};
`;
} catch (error) {
console.error(error);
}
// inject __docgen prop in svelte component
const output = source.replace('</script>', `${docgen}</script>`);

return output;
}
46 changes: 29 additions & 17 deletions examples/svelte-kitchen-sink/src/stories/addon-controls.stories.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,38 @@
import ButtonView from './views/ButtonView.svelte';
import ControlShowcaseView from './views/ControlShowcaseView.svelte';

export default {
title: 'Addon/Controls',
component: ControlShowcaseView,
argTypes: {
rounded: { type: { name: 'boolean' } },
text: { type: { name: 'string' } },
range: { defaultValue: '0', control: { type: 'range', min: 0, max: 100 } },
BlackFenix2 marked this conversation as resolved.
Show resolved Hide resolved
loadingState: {
control: {
type: 'inline-radio',
options: ['loading', 'error', 'ready'],
},
},
food: {
control: {
type: 'inline-check',
options: ['apple', 'banana', 'orange'],
},
},
car: {
control: {
type: 'select',
options: ['Truck', 'SUV', 'Tesla'],
},
},
color: {
control: 'color',
},
date: {
control: 'date',
},
},
};

const Template = (args) => ({
Component: ButtonView,
export const ShowCase = (args) => ({
Component: ControlShowcaseView,
props: args,
});

export const Rounded = Template.bind({});
Rounded.args = {
rounded: true,
text: 'Rounded text',
};

export const Square = Template.bind({});
Square.args = {
rounded: false,
text: 'Squared text',
};
29 changes: 22 additions & 7 deletions examples/svelte-kitchen-sink/src/stories/views/ButtonView.svelte
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
<h1>Button view</h1>
<Button {rounded} on:click={handleClick}>{text}: {count}</Button>
<p>A little text to show this is a view.</p>
<p>If we need to test components in a Svelte environment, for instance to test slot behaviour,</p>
<p>then wrapping the component up in a view</p>
<p>made just for the story is the simplest way to achieve this.</p>

<script>
import Button from '../../components/Button.svelte';

/**
* @component Button View
*/

/**
* Rounds the button
*/
export let rounded = false;

/**
* Displays the count
*/
export let count = 0;

/**
* Button text
*/
export let text = 'You clicked';

function handleClick(event) {
count += 1;
}
</script>

<h1>Button view</h1>
<Button {rounded} on:click={handleClick}>{text}: {count}</Button>
<p>A little text to show this is a view.</p>
<p>If we need to test components in a Svelte environment, for instance to test slot behaviour,</p>
<p>then wrapping the component up in a view</p>
<p>made just for the story is the simplest way to achieve this.</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<script>
import Button from '../../components/Button.svelte';

/**
* Rounds the button
*/
export let rounded = false;

/**
* Displays the count
*/
export let count = 0;

/**
* Button text
*/
export let text = 'You clicked';

/**
* Array object
*/
export let arrayTest = [];

/**
* number range
*/
export let range = 0;

/**
* Loading State
*/
export let loadingState = 'loading';

/**
* Food items
*/
export let food = [];

/**
* car choice
*/
export let car = 'car';

/**
* color choice
*/
export let color = '#000000';

/**
* date choice
*/
export let date = '';

function handleClick(event) {
count += 1;
}
</script>

<style>
.Box {
width: 200px;
height: 200px;
}
</style>

<h1>Control Showcase</h1>
<Button {rounded} on:click={handleClick}>{text}: {count}</Button>

<h2>Array Range</h2>
<div>{JSON.stringify(arrayTest)}</div>

<h2>Progress Bar</h2>
<progress value={range} min={0} max={100} step={1} />

<h2>Enum Selectors</h2>

<h3>inline radio</h3>
<div>
<p>Loading State: {loadingState}</p>
</div>

<h3>inline check</h3>
<div>
<p>Food Items: {JSON.stringify(food)}</p>
</div>

<h3>inline select</h3>
<div>
<p>Car choice: {car}</p>
</div>

<h2>Color Picker</h2>
<div>
<div class="Box" style="background-color: {color}" />
</div>

<h2>Date Picker</h2>
<div>
<p>Date: {new Date(date)}</p>
</div>
Loading