-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
39 changed files
with
1,109 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
import { addParameters } from '@storybook/web-components'; | ||
import { DocsPage, DocsContainer } from '@storybook/addon-docs/blocks'; | ||
|
||
addParameters({ | ||
docs: { | ||
container: DocsContainer, | ||
page: DocsPage, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('../dist/frameworks/web-components/config'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('../dist/frameworks/common/index'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
module.exports = require('../dist/frameworks/common/makePreset').default('web-components'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# Storybook for web-components | ||
|
||
--- | ||
|
||
Storybook for web-components is a UI development environment for your plain web-component snippets. | ||
With it, you can visualize different states of your UI components and develop them interactively. | ||
|
||
![Storybook Screenshot](https://github.com/storybookjs/storybook/blob/master/media/storybook-intro.gif) | ||
|
||
Storybook runs outside of your app. | ||
So you can develop UI components in isolation without worrying about app specific dependencies and requirements. | ||
|
||
## Getting Started | ||
|
||
```sh | ||
cd my-app | ||
npx -p @storybook/cli sb init -t web-components | ||
``` | ||
|
||
For more information visit: [storybook.js.org](https://storybook.js.org) | ||
|
||
--- | ||
|
||
Storybook also comes with a lot of [addons](https://storybook.js.org/addons/introduction) and a great API to customize as you wish. | ||
You can also build a [static version](https://storybook.js.org/basics/exporting-storybook) of your storybook and deploy it anywhere you want. | ||
|
||
# Setup page reload via HMR | ||
|
||
As web components register on a global registry which only accepts a certain name/class once it can lead to errors when using classical HMR. | ||
There are ideas on how to archive HMR with a static registry but there is no proven solution yet. | ||
|
||
Therefore the best approach for now is to do full page reloads. | ||
If you keep your stories to specific states of components (which we would recommend anyways) this usually means it is fast. | ||
To activate full page reload | ||
|
||
```js | ||
// ==> REPLACE | ||
configure(require.context('../stories', true, /\.stories\.(js|mdx)$/), module); | ||
|
||
// ==> WITH | ||
// force full reload to not reregister web components | ||
const req = require.context('../stories', true, /\.stories\.(js|mdx)$/); | ||
configure(req, module); | ||
if (module.hot) { | ||
module.hot.accept(req.id, () => { | ||
const currentLocationHref = window.location.href; | ||
window.history.pushState(null, null, currentLocationHref); | ||
window.location.reload(); | ||
}); | ||
} | ||
``` | ||
|
||
# Setup es6/7 dependencies | ||
|
||
By default storybook only works with precompiled es5 code but as most web components themselves and their libs are distributed as es7 you will need to manually mark those packages as "needs transpilation". | ||
|
||
For example if you have a library called `my-library` which is in es7 then you can add it like so | ||
|
||
```js | ||
// .storybook/webpack.config.js | ||
|
||
module.exports = ({ config }) => { | ||
// find web-components rule for extra transpilation | ||
const webComponentsRule = config.module.rules.find( | ||
rule => rule.use && rule.use.options && rule.use.options.babelrc === false | ||
); | ||
// add your own `my-library` | ||
webComponentsRule.test.push(new RegExp(`node_modules(\\/|\\\\)my-library(.*)\\.js$`)); | ||
|
||
return config; | ||
}; | ||
``` | ||
|
||
By default the following folders are included | ||
|
||
- `src/*.js` | ||
- `packages/*/src/*.js` | ||
- `node_modules/lit-html/*.js` | ||
- `node_modules/lit-element/*.js` | ||
- `node_modules/@open-wc/*.js` | ||
- `node_modules/@polymer/*.js` | ||
- `node_modules/@vaadin/*.js` | ||
|
||
As you can see the `src` folder is also included. | ||
The reason for that is as it has some extra configuration to allow for example `import.meta`. | ||
If you use a different folder you will need to make sure webpack/babel can handle it. | ||
|
||
# FAQ | ||
|
||
- While working on my component I get the error `Failed to execute 'define' on 'CustomElementRegistry': the name "..." has already been used with this registry` | ||
=> please see <a href="#user-content-setup-page-reload-via-hmr">Setup page reload via HMR</a> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#!/usr/bin/env node | ||
|
||
process.env.NODE_ENV = process.env.NODE_ENV || 'production'; | ||
require('../dist/server/build'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/usr/bin/env node | ||
|
||
require('../dist/server'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
{ | ||
"name": "@storybook/web-components", | ||
"version": "5.3.0-alpha.23", | ||
"description": "Storybook for web-components: View web components snippets in isolation with Hot Reloading.", | ||
"keywords": [ | ||
"lit-html", | ||
"storybook", | ||
"web-components" | ||
], | ||
"homepage": "https://github.com/storybookjs/storybook/tree/master/app/web-components", | ||
"bugs": { | ||
"url": "https://github.com/storybookjs/storybook/issues" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/storybookjs/storybook.git", | ||
"directory": "app/web-components" | ||
}, | ||
"license": "MIT", | ||
"files": [ | ||
"bin/**/*", | ||
"dist/**/*", | ||
"README.md", | ||
"*.js", | ||
"*.d.ts" | ||
], | ||
"main": "dist/client/index.js", | ||
"types": "dist/client/index.d.ts", | ||
"bin": { | ||
"build-storybook": "./bin/build.js", | ||
"start-storybook": "./bin/index.js", | ||
"storybook-server": "./bin/index.js" | ||
}, | ||
"scripts": { | ||
"prepare": "node ../../scripts/prepare.js" | ||
}, | ||
"dependencies": { | ||
"@babel/plugin-syntax-dynamic-import": "^7.2.0", | ||
"@babel/plugin-syntax-import-meta": "^7.2.0", | ||
"@storybook/addons": "5.3.0-alpha.23", | ||
"@storybook/core": "5.3.0-alpha.23", | ||
"@types/webpack-env": "^1.13.9", | ||
"babel-plugin-bundled-import-meta": "^0.3.1", | ||
"core-js": "^3.0.1", | ||
"global": "^4.3.2", | ||
"regenerator-runtime": "^0.13.3", | ||
"ts-dedent": "^1.1.0" | ||
}, | ||
"devDependencies": { | ||
"lit-html": "^1.0.0" | ||
}, | ||
"peerDependencies": { | ||
"babel-loader": "^7.0.0 || ^8.0.0", | ||
"lit-html": "^1.0.0" | ||
}, | ||
"engines": { | ||
"node": ">=8.0.0" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export { | ||
storiesOf, | ||
setAddon, | ||
addDecorator, | ||
addParameters, | ||
configure, | ||
getStorybook, | ||
forceReRender, | ||
raw, | ||
} from './preview'; | ||
|
||
if (module && module.hot && module.hot.decline) { | ||
module.hot.decline(); | ||
} | ||
|
||
// TODO: disable HMR and do full page loads because of customElements.define |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { window } from 'global'; | ||
|
||
window.STORYBOOK_ENV = 'web-components'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* eslint-disable prefer-destructuring */ | ||
import { start } from '@storybook/core/client'; | ||
import { ClientStoryApi, Loadable } from '@storybook/addons'; | ||
|
||
import './globals'; | ||
import render from './render'; | ||
import { StoryFnHtmlReturnType, IStorybookSection } from './types'; | ||
|
||
const framework = 'html'; | ||
|
||
interface ClientApi extends ClientStoryApi<StoryFnHtmlReturnType> { | ||
setAddon(addon: any): void; | ||
configure(loader: Loadable, module: NodeModule): void; | ||
getStorybook(): IStorybookSection[]; | ||
clearDecorators(): void; | ||
forceReRender(): void; | ||
raw: () => any; // todo add type | ||
} | ||
|
||
const api = start(render); | ||
|
||
export const storiesOf: ClientApi['storiesOf'] = (kind, m) => { | ||
return (api.clientApi.storiesOf(kind, m) as ReturnType<ClientApi['storiesOf']>).addParameters({ | ||
framework, | ||
}); | ||
}; | ||
|
||
export const configure: ClientApi['configure'] = (...args) => api.configure(...args, framework); | ||
export const addDecorator: ClientApi['addDecorator'] = api.clientApi.addDecorator; | ||
export const addParameters: ClientApi['addParameters'] = api.clientApi.addParameters; | ||
export const clearDecorators: ClientApi['clearDecorators'] = api.clientApi.clearDecorators; | ||
export const setAddon: ClientApi['setAddon'] = api.clientApi.setAddon; | ||
export const forceReRender: ClientApi['forceReRender'] = api.forceReRender; | ||
export const getStorybook: ClientApi['getStorybook'] = api.clientApi.getStorybook; | ||
export const raw: ClientApi['raw'] = api.clientApi.raw; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { document, Node } from 'global'; | ||
import dedent from 'ts-dedent'; | ||
import { render, TemplateResult } from 'lit-html'; | ||
import { RenderMainArgs } from './types'; | ||
|
||
const rootElement = document.getElementById('root'); | ||
|
||
export default function renderMain({ | ||
storyFn, | ||
selectedKind, | ||
selectedStory, | ||
showMain, | ||
showError, | ||
forceRender, | ||
}: RenderMainArgs) { | ||
const element = storyFn(); | ||
|
||
showMain(); | ||
if (element instanceof TemplateResult) { | ||
// `render` stores the TemplateInstance in the Node and tries to update based on that. | ||
// Since we reuse `rootElement` for all stories, remove the stored instance first. | ||
// But forceRender means that it's the same story, so we want too keep the state in that case. | ||
if (!forceRender || !rootElement.querySelector('[id="root-inner"]')) { | ||
rootElement.innerHTML = '<div id="root-inner"></div>'; | ||
} | ||
const renderTo = rootElement.querySelector('[id="root-inner"]'); | ||
|
||
render(element, renderTo); | ||
} else if (typeof element === 'string') { | ||
rootElement.innerHTML = element; | ||
} else if (element instanceof Node) { | ||
// Don't re-mount the element if it didn't change and neither did the story | ||
if (rootElement.firstChild === element && forceRender === true) { | ||
return; | ||
} | ||
|
||
rootElement.innerHTML = ''; | ||
rootElement.appendChild(element); | ||
} else { | ||
showError({ | ||
title: `Expecting an HTML snippet or DOM node from the story: "${selectedStory}" of "${selectedKind}".`, | ||
description: dedent` | ||
Did you forget to return the HTML snippet from the story? | ||
Use "() => <your snippet or node>" or when defining the story. | ||
`, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { StoryFn } from '@storybook/addons'; | ||
|
||
export type StoryFnHtmlReturnType = string | Node; | ||
|
||
export interface IStorybookStory { | ||
name: string; | ||
render: () => any; | ||
} | ||
|
||
export interface IStorybookSection { | ||
kind: string; | ||
stories: IStorybookStory[]; | ||
} | ||
|
||
export interface ShowErrorArgs { | ||
title: string; | ||
description: string; | ||
} | ||
|
||
export interface RenderMainArgs { | ||
storyFn: () => StoryFn<StoryFnHtmlReturnType>; | ||
selectedKind: string; | ||
selectedStory: string; | ||
showMain: () => void; | ||
showError: (args: ShowErrorArgs) => void; | ||
forceRender: boolean; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { buildStatic } from '@storybook/core/server'; | ||
import options from './options'; | ||
|
||
buildStatic(options); |
46 changes: 46 additions & 0 deletions
46
app/web-components/src/server/framework-preset-web-components.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// eslint-disable-next-line import/no-extraneous-dependencies | ||
import { Configuration } from 'webpack'; | ||
|
||
export function webpack(config: Configuration) { | ||
return { | ||
...config, | ||
module: { | ||
...config.module, | ||
rules: [ | ||
...config.module.rules, | ||
{ | ||
test: [ | ||
new RegExp(`src(.*)\\.js$`), | ||
new RegExp(`packages(\\/|\\\\)*(\\/|\\\\)src(\\/|\\\\)(.*)\\.js$`), | ||
new RegExp(`node_modules(\\/|\\\\)lit-html(.*)\\.js$`), | ||
new RegExp(`node_modules(\\/|\\\\)lit-element(.*)\\.js$`), | ||
new RegExp(`node_modules(\\/|\\\\)@open-wc(.*)\\.js$`), | ||
new RegExp(`node_modules(\\/|\\\\)@polymer(.*)\\.js$`), | ||
new RegExp(`node_modules(\\/|\\\\)@vaadin(.*)\\.js$`), | ||
], | ||
use: { | ||
loader: 'babel-loader', | ||
options: { | ||
plugins: [ | ||
'@babel/plugin-syntax-dynamic-import', | ||
'@babel/plugin-syntax-import-meta', | ||
// webpack does not support import.meta.url yet, so we rewrite them in babel | ||
['bundled-import-meta', { importStyle: 'baseURI' }], | ||
], | ||
presets: [ | ||
[ | ||
'@babel/preset-env', | ||
{ | ||
useBuiltIns: 'entry', | ||
corejs: 3, | ||
}, | ||
], | ||
], | ||
babelrc: false, | ||
}, | ||
}, | ||
}, | ||
], | ||
}, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { buildDev } from '@storybook/core/server'; | ||
import options from './options'; | ||
|
||
buildDev(options); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// tslint:disable-next-line: no-var-requires | ||
const packageJson = require('../../package.json'); | ||
|
||
export default { | ||
packageJson, | ||
frameworkPresets: [require.resolve('./framework-preset-web-components.js')], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
declare module '@storybook/core/*'; | ||
declare module 'global'; | ||
|
||
// will be provided by the webpack define plugin | ||
declare var NODE_ENV: string | undefined; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const build = require('@storybook/core/standalone'); | ||
const frameworkOptions = require('./dist/server/options').default; | ||
|
||
async function buildStandalone(options) { | ||
return build(options, frameworkOptions); | ||
} | ||
|
||
module.exports = buildStandalone; |
Oops, something went wrong.