@storybook/web-components 7.0.0-alpha.45 → 7.0.0-alpha.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/package.json +11 -10
- package/template/cli/.eslintrc.json +5 -0
- package/template/cli/js/Button.js +21 -0
- package/template/cli/js/Button.stories.js +44 -0
- package/template/cli/js/Header.js +45 -0
- package/template/cli/js/Header.stories.js +16 -0
- package/template/cli/js/Page.js +61 -0
- package/template/cli/js/Page.stories.js +20 -0
- package/template/cli/ts/Button.stories.ts +49 -0
- package/template/cli/ts/Button.ts +43 -0
- package/template/cli/ts/Header.stories.ts +21 -0
- package/template/cli/ts/Header.ts +56 -0
- package/template/cli/ts/Page.stories.ts +26 -0
- package/template/cli/ts/Page.ts +72 -0
- package/template/components/Button.js +71 -0
- package/template/components/Form.js +81 -0
- package/template/components/Html.js +34 -0
- package/template/components/Pre.js +42 -0
- package/template/components/button.css +30 -0
- package/template/components/index.js +14 -0
- package/template/stories/custom-elements-experimental.json +95 -0
- package/template/stories/custom-elements.json +162 -0
- package/template/stories/demo-wc-card/DemoWcCard.js +101 -0
- package/template/stories/demo-wc-card/demoWcCardStyle.css.js +97 -0
- package/template/stories/demo-wc-card/index.js +5 -0
- package/template/stories/demo-wc-card.stories.js +16 -0
- package/template/stories/preview.js +6 -0
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var M=Object.create;var d=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var h=Object.getPrototypeOf,R=Object.prototype.hasOwnProperty;var x=(e,o)=>{for(var r in o)d(e,r,{get:o[r],enumerable:!0})},l=(e,o,r,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let i of b(o))!R.call(e,i)&&i!==r&&d(e,i,{get:()=>o[i],enumerable:!(n=A(o,i))||n.enumerable});return e};var f=(e,o,r)=>(r=e!=null?M(h(e)):{},l(o||!e||!e.__esModule?d(r,"default",{value:e,enumerable:!0}):r,e)),E=e=>l(d({},"__esModule",{value:!0}),e);var V={};x(V,{configure:()=>v,forceReRender:()=>N,getCustomElements:()=>Y,isValidComponent:()=>D,isValidMetaData:()=>H,raw:()=>W,setCustomElements:()=>K,setCustomElementsManifest:()=>U,storiesOf:()=>k});module.exports=E(V);var S=f(require("global"));var c=f(require("global")),{window:L}=c.default;L.STORYBOOK_ENV="web-components";var C=require("@storybook/core-client");var u=f(require("global")),
|
|
1
|
+
var M=Object.create;var d=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var h=Object.getPrototypeOf,R=Object.prototype.hasOwnProperty;var x=(e,o)=>{for(var r in o)d(e,r,{get:o[r],enumerable:!0})},l=(e,o,r,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let i of b(o))!R.call(e,i)&&i!==r&&d(e,i,{get:()=>o[i],enumerable:!(n=A(o,i))||n.enumerable});return e};var f=(e,o,r)=>(r=e!=null?M(h(e)):{},l(o||!e||!e.__esModule?d(r,"default",{value:e,enumerable:!0}):r,e)),E=e=>l(d({},"__esModule",{value:!0}),e);var V={};x(V,{configure:()=>v,forceReRender:()=>N,getCustomElements:()=>Y,isValidComponent:()=>D,isValidMetaData:()=>H,raw:()=>W,setCustomElements:()=>K,setCustomElementsManifest:()=>U,storiesOf:()=>k});module.exports=E(V);var S=f(require("global"));var c=f(require("global")),{window:L}=c.default;L.STORYBOOK_ENV="web-components";var C=require("@storybook/core-client");var u=f(require("global")),y=require("ts-dedent"),_=require("lit-html"),w=require("lit-html/directive-helpers.js"),a=require("@storybook/preview-web"),{Node:F}=u.default;function O({storyFn:e,kind:o,name:r,showMain:n,showError:i,forceRemount:m},t){let s=e();if(n(),(0,w.isTemplateResult)(s)){(m||!t.querySelector('[id="root-inner"]'))&&(t.innerHTML='<div id="root-inner"></div>');let T=t.querySelector('[id="root-inner"]');(0,_.render)(s,T),(0,a.simulatePageLoad)(t)}else if(typeof s=="string")t.innerHTML=s,(0,a.simulatePageLoad)(t);else if(s instanceof F){if(t.firstChild===s&&!m)return;t.innerHTML="",t.appendChild(s),(0,a.simulateDOMContentLoaded)()}else i({title:`Expecting an HTML snippet or DOM node from the story: "${r}" of "${o}".`,description:y.dedent`
|
|
2
2
|
Did you forget to return the HTML snippet from the story?
|
|
3
3
|
Use "() => <your snippet or node>" or when defining the story.
|
|
4
4
|
`})}var g="web-components",p=(0,C.start)(O),k=(e,o)=>p.clientApi.storiesOf(e,o).addParameters({framework:g}),v=(...e)=>p.configure(g,...e),N=p.forceReRender,W=p.clientApi.raw;function D(e){if(!e)return!1;if(typeof e=="string")return!0;throw new Error('Provided component needs to be a string. e.g. component: "my-element"')}function H(e){if(!e)return!1;if(e.tags&&Array.isArray(e.tags)||e.modules&&Array.isArray(e.modules))return!0;throw new Error(`You need to setup valid meta data in your config.js via setCustomElements().
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storybook/web-components",
|
|
3
|
-
"version": "7.0.0-alpha.
|
|
3
|
+
"version": "7.0.0-alpha.47",
|
|
4
4
|
"description": "Storybook web-components renderer",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"lit-html",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"types": "dist/index.d.ts",
|
|
44
44
|
"files": [
|
|
45
45
|
"dist/**/*",
|
|
46
|
+
"template/**/*",
|
|
46
47
|
"README.md",
|
|
47
48
|
"*.js",
|
|
48
49
|
"*.d.ts"
|
|
@@ -52,14 +53,14 @@
|
|
|
52
53
|
"prep": "../../../scripts/prepare/bundle.ts"
|
|
53
54
|
},
|
|
54
55
|
"dependencies": {
|
|
55
|
-
"@storybook/addons": "7.0.0-alpha.
|
|
56
|
-
"@storybook/api": "7.0.0-alpha.
|
|
57
|
-
"@storybook/client-logger": "7.0.0-alpha.
|
|
58
|
-
"@storybook/core-client": "7.0.0-alpha.
|
|
59
|
-
"@storybook/docs-tools": "7.0.0-alpha.
|
|
60
|
-
"@storybook/preview-web": "7.0.0-alpha.
|
|
61
|
-
"@storybook/store": "7.0.0-alpha.
|
|
62
|
-
"@storybook/types": "7.0.0-alpha.
|
|
56
|
+
"@storybook/addons": "7.0.0-alpha.47",
|
|
57
|
+
"@storybook/api": "7.0.0-alpha.47",
|
|
58
|
+
"@storybook/client-logger": "7.0.0-alpha.47",
|
|
59
|
+
"@storybook/core-client": "7.0.0-alpha.47",
|
|
60
|
+
"@storybook/docs-tools": "7.0.0-alpha.47",
|
|
61
|
+
"@storybook/preview-web": "7.0.0-alpha.47",
|
|
62
|
+
"@storybook/store": "7.0.0-alpha.47",
|
|
63
|
+
"@storybook/types": "7.0.0-alpha.47",
|
|
63
64
|
"global": "^4.4.0",
|
|
64
65
|
"react": "16.14.0",
|
|
65
66
|
"react-dom": "16.14.0",
|
|
@@ -86,5 +87,5 @@
|
|
|
86
87
|
],
|
|
87
88
|
"platform": "browser"
|
|
88
89
|
},
|
|
89
|
-
"gitHead": "
|
|
90
|
+
"gitHead": "1c706a4a778831e012343c905f86225fa71491a7"
|
|
90
91
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { html } from 'lit-html';
|
|
2
|
+
import { styleMap } from 'lit-html/directives/style-map.js';
|
|
3
|
+
import './button.css';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Primary UI component for user interaction
|
|
7
|
+
*/
|
|
8
|
+
export const Button = ({ primary, backgroundColor = null, size, label, onClick }) => {
|
|
9
|
+
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
|
|
10
|
+
|
|
11
|
+
return html`
|
|
12
|
+
<button
|
|
13
|
+
type="button"
|
|
14
|
+
class=${['storybook-button', `storybook-button--${size || 'medium'}`, mode].join(' ')}
|
|
15
|
+
style=${styleMap({ backgroundColor })}
|
|
16
|
+
@click=${onClick}
|
|
17
|
+
>
|
|
18
|
+
${label}
|
|
19
|
+
</button>
|
|
20
|
+
`;
|
|
21
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Button } from './Button';
|
|
2
|
+
|
|
3
|
+
// More on default export: https://storybook.js.org/docs/web-components/writing-stories/introduction#default-export
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Example/Button',
|
|
6
|
+
// More on component templates: https://storybook.js.org/docs/web-components/writing-stories/introduction#using-args
|
|
7
|
+
render: (args) => Button(args),
|
|
8
|
+
// More on argTypes: https://storybook.js.org/docs/web-components/api/argtypes
|
|
9
|
+
argTypes: {
|
|
10
|
+
backgroundColor: { control: 'color' },
|
|
11
|
+
onClick: { action: 'onClick' },
|
|
12
|
+
size: {
|
|
13
|
+
control: { type: 'select' },
|
|
14
|
+
options: ['small', 'medium', 'large'],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const Primary = {
|
|
20
|
+
args: {
|
|
21
|
+
primary: true,
|
|
22
|
+
label: 'Button',
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const Secondary = {
|
|
27
|
+
args: {
|
|
28
|
+
label: 'Button',
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const Large = {
|
|
33
|
+
args: {
|
|
34
|
+
size: 'large',
|
|
35
|
+
label: 'Button',
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const Small = {
|
|
40
|
+
args: {
|
|
41
|
+
size: 'small',
|
|
42
|
+
label: 'Button',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { html } from 'lit-html';
|
|
2
|
+
|
|
3
|
+
import { Button } from './Button';
|
|
4
|
+
import './header.css';
|
|
5
|
+
|
|
6
|
+
export const Header = ({ user, onLogin, onLogout, onCreateAccount }) => html`
|
|
7
|
+
<header>
|
|
8
|
+
<div class="wrapper">
|
|
9
|
+
<div>
|
|
10
|
+
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
|
11
|
+
<g fill="none" fillRule="evenodd">
|
|
12
|
+
<path
|
|
13
|
+
d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
|
|
14
|
+
fill="#FFF"
|
|
15
|
+
/>
|
|
16
|
+
<path
|
|
17
|
+
d="M5.3 10.6l10.4 6v11.1l-10.4-6v-11zm11.4-6.2l9.7 5.5-9.7 5.6V4.4z"
|
|
18
|
+
fill="#555AB9"
|
|
19
|
+
/>
|
|
20
|
+
<path
|
|
21
|
+
d="M27.2 10.6v11.2l-10.5 6V16.5l10.5-6zM15.7 4.4v11L6 10l9.7-5.5z"
|
|
22
|
+
fill="#91BAF8"
|
|
23
|
+
/>
|
|
24
|
+
</g>
|
|
25
|
+
</svg>
|
|
26
|
+
<h1>Acme</h1>
|
|
27
|
+
</div>
|
|
28
|
+
<div>
|
|
29
|
+
${user
|
|
30
|
+
? Button({ size: 'small', onClick: onLogout, label: 'Log out' })
|
|
31
|
+
: html`${Button({
|
|
32
|
+
size: 'small',
|
|
33
|
+
onClick: onLogin,
|
|
34
|
+
label: 'Log in',
|
|
35
|
+
})}
|
|
36
|
+
${Button({
|
|
37
|
+
primary: true,
|
|
38
|
+
size: 'small',
|
|
39
|
+
onClick: onCreateAccount,
|
|
40
|
+
label: 'Sign up',
|
|
41
|
+
})}`}
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</header>
|
|
45
|
+
`;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { html } from 'lit-html';
|
|
2
|
+
import { Header } from './Header';
|
|
3
|
+
import './page.css';
|
|
4
|
+
|
|
5
|
+
export const Page = ({ user, onLogin, onLogout, onCreateAccount }) => html`
|
|
6
|
+
<article>
|
|
7
|
+
${Header({
|
|
8
|
+
user,
|
|
9
|
+
onLogin,
|
|
10
|
+
onLogout,
|
|
11
|
+
onCreateAccount,
|
|
12
|
+
})}
|
|
13
|
+
|
|
14
|
+
<section>
|
|
15
|
+
<h2>Pages in Storybook</h2>
|
|
16
|
+
<p>
|
|
17
|
+
We recommend building UIs with a
|
|
18
|
+
<a href="https://componentdriven.org" target="_blank" rel="noopener noreferrer">
|
|
19
|
+
<strong>component-driven</strong> </a
|
|
20
|
+
>process starting with atomic components and ending with pages.
|
|
21
|
+
</p>
|
|
22
|
+
<p>
|
|
23
|
+
Render pages with mock data. This makes it easy to build and review page states without
|
|
24
|
+
needing to navigate to them in your app. Here are some handy patterns for managing page data
|
|
25
|
+
in Storybook:
|
|
26
|
+
</p>
|
|
27
|
+
<ul>
|
|
28
|
+
<li>
|
|
29
|
+
Use a higher-level connected component. Storybook helps you compose such data from the
|
|
30
|
+
"args" of child component stories
|
|
31
|
+
</li>
|
|
32
|
+
<li>
|
|
33
|
+
Assemble data in the page component from your services. You can mock these services out
|
|
34
|
+
using Storybook.
|
|
35
|
+
</li>
|
|
36
|
+
</ul>
|
|
37
|
+
<p>
|
|
38
|
+
Get a guided tutorial on component-driven development at
|
|
39
|
+
<a href="https://storybook.js.org/tutorials/" target="_blank" rel="noopener noreferrer">
|
|
40
|
+
Storybook tutorials
|
|
41
|
+
</a>
|
|
42
|
+
. Read more in the
|
|
43
|
+
<a href="https://storybook.js.org/docs" target="_blank" rel="noopener noreferrer"> docs </a>
|
|
44
|
+
.
|
|
45
|
+
</p>
|
|
46
|
+
<div class="tip-wrapper">
|
|
47
|
+
<span class="tip">Tip</span> Adjust the width of the canvas with the
|
|
48
|
+
<svg width="10" height="10" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
|
49
|
+
<g fill="none" fillRule="evenodd">
|
|
50
|
+
<path
|
|
51
|
+
d="M1.5 5.2h4.8c.3 0 .5.2.5.4v5.1c-.1.2-.3.3-.4.3H1.4a.5.5 0 01-.5-.4V5.7c0-.3.2-.5.5-.5zm0-2.1h6.9c.3 0 .5.2.5.4v7a.5.5 0 01-1 0V4H1.5a.5.5 0 010-1zm0-2.1h9c.3 0 .5.2.5.4v9.1a.5.5 0 01-1 0V2H1.5a.5.5 0 010-1zm4.3 5.2H2V10h3.8V6.2z"
|
|
52
|
+
id="a"
|
|
53
|
+
fill="#999"
|
|
54
|
+
/>
|
|
55
|
+
</g>
|
|
56
|
+
</svg>
|
|
57
|
+
Viewports addon in the toolbar
|
|
58
|
+
</div>
|
|
59
|
+
</section>
|
|
60
|
+
</article>
|
|
61
|
+
`;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Page } from './Page';
|
|
2
|
+
import * as HeaderStories from './Header.stories';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Example/Page',
|
|
6
|
+
render: (args) => Page(args),
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const LoggedIn = {
|
|
10
|
+
args: {
|
|
11
|
+
// More on composing args: https://storybook.js.org/docs/web-components/writing-stories/args#args-composition
|
|
12
|
+
...HeaderStories.LoggedIn.args,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const LoggedOut = {
|
|
17
|
+
args: {
|
|
18
|
+
...HeaderStories.LoggedOut.args,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/web-components';
|
|
2
|
+
import type { ButtonProps } from './Button';
|
|
3
|
+
import { Button } from './Button';
|
|
4
|
+
|
|
5
|
+
// More on how to set up stories at: https://storybook.js.org/docs/web-components/writing-stories/introduction#default-export
|
|
6
|
+
const meta: Meta<ButtonProps> = {
|
|
7
|
+
title: 'Example/Button',
|
|
8
|
+
render: (args) => Button(args),
|
|
9
|
+
// More on argTypes: https://storybook.js.org/docs/web-components/api/argtypes
|
|
10
|
+
argTypes: {
|
|
11
|
+
backgroundColor: { control: 'color' },
|
|
12
|
+
onClick: { action: 'onClick' },
|
|
13
|
+
size: {
|
|
14
|
+
control: { type: 'select' },
|
|
15
|
+
options: ['small', 'medium', 'large'],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
type Story = StoryObj<ButtonProps>;
|
|
22
|
+
|
|
23
|
+
// More on component templates: https://storybook.js.org/docs/web-components/writing-stories/introduction#using-args
|
|
24
|
+
export const Primary: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
primary: true,
|
|
27
|
+
label: 'Button',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Secondary: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
label: 'Button',
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const Large: Story = {
|
|
38
|
+
args: {
|
|
39
|
+
size: 'large',
|
|
40
|
+
label: 'Button',
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const Small: Story = {
|
|
45
|
+
args: {
|
|
46
|
+
size: 'small',
|
|
47
|
+
label: 'Button',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { html } from 'lit-html';
|
|
2
|
+
import { styleMap } from 'lit-html/directives/style-map.js';
|
|
3
|
+
import './button.css';
|
|
4
|
+
|
|
5
|
+
export interface ButtonProps {
|
|
6
|
+
/**
|
|
7
|
+
* Is this the principal call to action on the page?
|
|
8
|
+
*/
|
|
9
|
+
primary?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* What background color to use
|
|
12
|
+
*/
|
|
13
|
+
backgroundColor?: string;
|
|
14
|
+
/**
|
|
15
|
+
* How large should the button be?
|
|
16
|
+
*/
|
|
17
|
+
size?: 'small' | 'medium' | 'large';
|
|
18
|
+
/**
|
|
19
|
+
* Button contents
|
|
20
|
+
*/
|
|
21
|
+
label: string;
|
|
22
|
+
/**
|
|
23
|
+
* Optional click handler
|
|
24
|
+
*/
|
|
25
|
+
onClick?: () => void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Primary UI component for user interaction
|
|
29
|
+
*/
|
|
30
|
+
export const Button = ({ primary, backgroundColor = null, size, label, onClick }: ButtonProps) => {
|
|
31
|
+
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
|
|
32
|
+
|
|
33
|
+
return html`
|
|
34
|
+
<button
|
|
35
|
+
type="button"
|
|
36
|
+
class=${['storybook-button', `storybook-button--${size || 'medium'}`, mode].join(' ')}
|
|
37
|
+
style=${styleMap({ backgroundColor })}
|
|
38
|
+
@click=${onClick}
|
|
39
|
+
>
|
|
40
|
+
${label}
|
|
41
|
+
</button>
|
|
42
|
+
`;
|
|
43
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/web-components';
|
|
2
|
+
import type { HeaderProps } from './Header';
|
|
3
|
+
import { Header } from './Header';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<HeaderProps> = {
|
|
6
|
+
title: 'Example/Header',
|
|
7
|
+
render: (args) => Header(args),
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<HeaderProps>;
|
|
12
|
+
|
|
13
|
+
export const LoggedIn: Story = {
|
|
14
|
+
args: {
|
|
15
|
+
user: {
|
|
16
|
+
name: 'Jonh Doe',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const LoggedOut: Story = {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { html } from 'lit-html';
|
|
2
|
+
|
|
3
|
+
import { Button } from './Button';
|
|
4
|
+
import './header.css';
|
|
5
|
+
|
|
6
|
+
type User = {
|
|
7
|
+
name: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export interface HeaderProps {
|
|
11
|
+
user?: User;
|
|
12
|
+
onLogin: () => void;
|
|
13
|
+
onLogout: () => void;
|
|
14
|
+
onCreateAccount: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const Header = ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps) => html`
|
|
18
|
+
<header>
|
|
19
|
+
<div class="wrapper">
|
|
20
|
+
<div>
|
|
21
|
+
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
|
|
22
|
+
<g fill="none" fillRule="evenodd">
|
|
23
|
+
<path
|
|
24
|
+
d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
|
|
25
|
+
fill="#FFF"
|
|
26
|
+
/>
|
|
27
|
+
<path
|
|
28
|
+
d="M5.3 10.6l10.4 6v11.1l-10.4-6v-11zm11.4-6.2l9.7 5.5-9.7 5.6V4.4z"
|
|
29
|
+
fill="#555AB9"
|
|
30
|
+
/>
|
|
31
|
+
<path
|
|
32
|
+
d="M27.2 10.6v11.2l-10.5 6V16.5l10.5-6zM15.7 4.4v11L6 10l9.7-5.5z"
|
|
33
|
+
fill="#91BAF8"
|
|
34
|
+
/>
|
|
35
|
+
</g>
|
|
36
|
+
</svg>
|
|
37
|
+
<h1>Acme</h1>
|
|
38
|
+
</div>
|
|
39
|
+
<div>
|
|
40
|
+
${user
|
|
41
|
+
? Button({ size: 'small', onClick: onLogout, label: 'Log out' })
|
|
42
|
+
: html`${Button({
|
|
43
|
+
size: 'small',
|
|
44
|
+
onClick: onLogin,
|
|
45
|
+
label: 'Log in',
|
|
46
|
+
})}
|
|
47
|
+
${Button({
|
|
48
|
+
primary: true,
|
|
49
|
+
size: 'small',
|
|
50
|
+
onClick: onCreateAccount,
|
|
51
|
+
label: 'Sign up',
|
|
52
|
+
})}`}
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</header>
|
|
56
|
+
`;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/web-components';
|
|
2
|
+
|
|
3
|
+
import type { PageProps } from './Page';
|
|
4
|
+
import { Page } from './Page';
|
|
5
|
+
import * as HeaderStories from './Header.stories';
|
|
6
|
+
|
|
7
|
+
const meta: Meta<PageProps> = {
|
|
8
|
+
title: 'Example/Page',
|
|
9
|
+
render: (args) => Page(args),
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
type Story = StoryObj<PageProps>;
|
|
14
|
+
|
|
15
|
+
export const LoggedIn: Story = {
|
|
16
|
+
args: {
|
|
17
|
+
// More on composing args: https://storybook.js.org/docs/web-components/writing-stories/args#args-composition
|
|
18
|
+
...HeaderStories.LoggedIn.args,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const LoggedOut: Story = {
|
|
23
|
+
args: {
|
|
24
|
+
...HeaderStories.LoggedOut.args,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { html } from 'lit-html';
|
|
2
|
+
import { Header } from './Header';
|
|
3
|
+
import './page.css';
|
|
4
|
+
|
|
5
|
+
type User = {
|
|
6
|
+
name: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export interface PageProps {
|
|
10
|
+
user?: User;
|
|
11
|
+
onLogin: () => void;
|
|
12
|
+
onLogout: () => void;
|
|
13
|
+
onCreateAccount: () => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const Page = ({ user, onLogin, onLogout, onCreateAccount }: PageProps) => html`
|
|
17
|
+
<article>
|
|
18
|
+
${Header({
|
|
19
|
+
user,
|
|
20
|
+
onLogin,
|
|
21
|
+
onLogout,
|
|
22
|
+
onCreateAccount,
|
|
23
|
+
})}
|
|
24
|
+
|
|
25
|
+
<section>
|
|
26
|
+
<h2>Pages in Storybook</h2>
|
|
27
|
+
<p>
|
|
28
|
+
We recommend building UIs with a
|
|
29
|
+
<a href="https://componentdriven.org" target="_blank" rel="noopener noreferrer">
|
|
30
|
+
<strong>component-driven</strong> </a
|
|
31
|
+
>process starting with atomic components and ending with pages.
|
|
32
|
+
</p>
|
|
33
|
+
<p>
|
|
34
|
+
Render pages with mock data. This makes it easy to build and review page states without
|
|
35
|
+
needing to navigate to them in your app. Here are some handy patterns for managing page data
|
|
36
|
+
in Storybook:
|
|
37
|
+
</p>
|
|
38
|
+
<ul>
|
|
39
|
+
<li>
|
|
40
|
+
Use a higher-level connected component. Storybook helps you compose such data from the
|
|
41
|
+
"args" of child component stories
|
|
42
|
+
</li>
|
|
43
|
+
<li>
|
|
44
|
+
Assemble data in the page component from your services. You can mock these services out
|
|
45
|
+
using Storybook.
|
|
46
|
+
</li>
|
|
47
|
+
</ul>
|
|
48
|
+
<p>
|
|
49
|
+
Get a guided tutorial on component-driven development at
|
|
50
|
+
<a href="https://storybook.js.org/tutorials/" target="_blank" rel="noopener noreferrer">
|
|
51
|
+
Storybook tutorials
|
|
52
|
+
</a>
|
|
53
|
+
. Read more in the
|
|
54
|
+
<a href="https://storybook.js.org/docs" target="_blank" rel="noopener noreferrer"> docs </a>
|
|
55
|
+
.
|
|
56
|
+
</p>
|
|
57
|
+
<div class="tip-wrapper">
|
|
58
|
+
<span class="tip">Tip</span> Adjust the width of the canvas with the
|
|
59
|
+
<svg width="10" height="10" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
|
60
|
+
<g fill="none" fillRule="evenodd">
|
|
61
|
+
<path
|
|
62
|
+
d="M1.5 5.2h4.8c.3 0 .5.2.5.4v5.1c-.1.2-.3.3-.4.3H1.4a.5.5 0 01-.5-.4V5.7c0-.3.2-.5.5-.5zm0-2.1h6.9c.3 0 .5.2.5.4v7a.5.5 0 01-1 0V4H1.5a.5.5 0 010-1zm0-2.1h9c.3 0 .5.2.5.4v9.1a.5.5 0 01-1 0V2H1.5a.5.5 0 010-1zm4.3 5.2H2V10h3.8V6.2z"
|
|
63
|
+
id="a"
|
|
64
|
+
fill="#999"
|
|
65
|
+
/>
|
|
66
|
+
</g>
|
|
67
|
+
</svg>
|
|
68
|
+
Viewports addon in the toolbar
|
|
69
|
+
</div>
|
|
70
|
+
</section>
|
|
71
|
+
</article>
|
|
72
|
+
`;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
2
|
+
import globalThis from 'global';
|
|
3
|
+
import { html, LitElement } from 'lit';
|
|
4
|
+
|
|
5
|
+
const { CustomEvent, customElements } = globalThis;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @attr {string} label - Label of the button
|
|
9
|
+
* @attr {string} size - Size of the button, can be "small", "medium" or "large"; default is "medium".
|
|
10
|
+
* @attr {string} backgroundColor - Color of the button's background
|
|
11
|
+
*
|
|
12
|
+
* @cssprop [--sb-primary-color=#1ea7fd] - Controls the color of bar
|
|
13
|
+
*
|
|
14
|
+
* @prop {boolean} primary - Set button in primary mode
|
|
15
|
+
*
|
|
16
|
+
* @event {CustomEvent} sb-button:click - Custom event send when the button is clicked
|
|
17
|
+
*
|
|
18
|
+
* @summary This is a simple Storybook Button
|
|
19
|
+
*
|
|
20
|
+
* @tag sb-button
|
|
21
|
+
*/
|
|
22
|
+
export class SbButton extends LitElement {
|
|
23
|
+
// Currently TS decorators are not reflected so we have to use static `properties` function
|
|
24
|
+
// https://github.com/Polymer/lit-html/issues/1476
|
|
25
|
+
static get properties() {
|
|
26
|
+
return {
|
|
27
|
+
label: { type: String, reflect: true },
|
|
28
|
+
primary: { type: Boolean },
|
|
29
|
+
size: { type: String },
|
|
30
|
+
backgroundColor: { type: String, attribute: 'background-color' },
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
constructor() {
|
|
35
|
+
super();
|
|
36
|
+
this.primary = undefined;
|
|
37
|
+
this.backgroundColor = undefined;
|
|
38
|
+
this.size = 'medium';
|
|
39
|
+
this.label = '';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
onClick() {
|
|
43
|
+
const options = {
|
|
44
|
+
bubbles: true,
|
|
45
|
+
composed: true,
|
|
46
|
+
};
|
|
47
|
+
this.dispatchEvent(new CustomEvent('sb-button:click', options));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
render() {
|
|
51
|
+
const mode = this.primary ? 'storybook-button--primary' : 'storybook-button--secondary';
|
|
52
|
+
|
|
53
|
+
return html`
|
|
54
|
+
<button
|
|
55
|
+
type="button"
|
|
56
|
+
class=${['storybook-button', `storybook-button--${this.size ?? 'medium'}`, mode].join(' ')}
|
|
57
|
+
@click="${this.onClick}"
|
|
58
|
+
>
|
|
59
|
+
${this.label}
|
|
60
|
+
</button>
|
|
61
|
+
`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// render into the light dom so we can test this
|
|
65
|
+
createRenderRoot() {
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const ButtonTag = 'sb-button';
|
|
71
|
+
customElements.define(ButtonTag, SbButton);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
2
|
+
import globalThis from 'global';
|
|
3
|
+
import { html, LitElement } from 'lit';
|
|
4
|
+
|
|
5
|
+
const { CustomEvent, customElements } = globalThis;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Form test component for framework-independent stories
|
|
9
|
+
*
|
|
10
|
+
* @tag sb-form
|
|
11
|
+
*/
|
|
12
|
+
export class SbForm extends LitElement {
|
|
13
|
+
// Currently TS decorators are not reflected so we have to use static `properties` function
|
|
14
|
+
// https://github.com/Polymer/lit-html/issues/1476
|
|
15
|
+
static get properties() {
|
|
16
|
+
return {
|
|
17
|
+
value: { type: String },
|
|
18
|
+
complete: { type: Boolean },
|
|
19
|
+
onSuccess: { type: Function },
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
constructor() {
|
|
24
|
+
super();
|
|
25
|
+
this.value = '';
|
|
26
|
+
this.complete = false;
|
|
27
|
+
this.onSuccess = undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onSubmit(event) {
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
const options = {
|
|
33
|
+
bubbles: true,
|
|
34
|
+
composed: true,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
this.dispatchEvent(new CustomEvent('sb-form:success', options));
|
|
38
|
+
if (this.onSuccess) {
|
|
39
|
+
this.onSuccess(this.value);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
this.complete = true;
|
|
44
|
+
}, 500);
|
|
45
|
+
|
|
46
|
+
setTimeout(() => {
|
|
47
|
+
this.complete = false;
|
|
48
|
+
}, 1500);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
render() {
|
|
52
|
+
return html`
|
|
53
|
+
<form id="interaction-test-form" @submit=${this.onSubmit}>
|
|
54
|
+
<label>
|
|
55
|
+
Enter Value
|
|
56
|
+
<input
|
|
57
|
+
type="text"
|
|
58
|
+
data-testid="value"
|
|
59
|
+
value=${this.value}
|
|
60
|
+
required
|
|
61
|
+
@change=${(event) => {
|
|
62
|
+
event.preventDefault();
|
|
63
|
+
this.value = event.target.value;
|
|
64
|
+
return false;
|
|
65
|
+
}}
|
|
66
|
+
/>
|
|
67
|
+
</label>
|
|
68
|
+
<button type="submit">Submit</button>
|
|
69
|
+
${this.complete ? 'Completed!!' : ''}
|
|
70
|
+
</form>
|
|
71
|
+
`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// render into the light dom so we can test this
|
|
75
|
+
createRenderRoot() {
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const FormTag = 'sb-form';
|
|
81
|
+
customElements.define(FormTag, SbForm);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
2
|
+
import globalThis from 'global';
|
|
3
|
+
import { LitElement } from 'lit';
|
|
4
|
+
|
|
5
|
+
const { customElements } = globalThis;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @tag sb-html
|
|
10
|
+
*/
|
|
11
|
+
export class SbHtml extends LitElement {
|
|
12
|
+
static get properties() {
|
|
13
|
+
return {
|
|
14
|
+
content: { type: String },
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
super();
|
|
20
|
+
this.content = '';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
render() {
|
|
24
|
+
this.renderRoot.innerHTML = this.content;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// render into the light dom so we can test this
|
|
28
|
+
createRenderRoot() {
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const HtmlTag = 'sb-html';
|
|
34
|
+
customElements.define(HtmlTag, SbHtml);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* eslint-disable import/extensions, import/no-extraneous-dependencies */
|
|
2
|
+
import globalThis from 'global';
|
|
3
|
+
import { html, LitElement } from 'lit';
|
|
4
|
+
import { styleMap } from 'lit-html/directives/style-map.js';
|
|
5
|
+
|
|
6
|
+
const { customElements } = globalThis;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @tag sb-pre
|
|
11
|
+
*/
|
|
12
|
+
export class SbPre extends LitElement {
|
|
13
|
+
// Currently TS decorators are not reflected so we have to use static `properties` function
|
|
14
|
+
// https://github.com/Polymer/lit-html/issues/1476
|
|
15
|
+
static get properties() {
|
|
16
|
+
return {
|
|
17
|
+
style: { type: Object },
|
|
18
|
+
object: { type: Object },
|
|
19
|
+
text: { type: String },
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
constructor() {
|
|
24
|
+
super();
|
|
25
|
+
this.style = {};
|
|
26
|
+
this.object = undefined;
|
|
27
|
+
this.text = undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
render() {
|
|
31
|
+
const text = this.object ? JSON.stringify(this.object, null, 2) : this.text;
|
|
32
|
+
return html`<pre data-testid="pre" style=${styleMap(this.style)}>${text}</pre>`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// render into the light dom so we can test this
|
|
36
|
+
createRenderRoot() {
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const PreTag = 'sb-pre';
|
|
42
|
+
customElements.define(PreTag, SbPre);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
.storybook-button {
|
|
2
|
+
font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
|
3
|
+
font-weight: 700;
|
|
4
|
+
border: 0;
|
|
5
|
+
border-radius: 3em;
|
|
6
|
+
cursor: pointer;
|
|
7
|
+
display: inline-block;
|
|
8
|
+
line-height: 1;
|
|
9
|
+
}
|
|
10
|
+
.storybook-button--primary {
|
|
11
|
+
color: white;
|
|
12
|
+
background-color: #1ea7fd;
|
|
13
|
+
}
|
|
14
|
+
.storybook-button--secondary {
|
|
15
|
+
color: #333;
|
|
16
|
+
background-color: transparent;
|
|
17
|
+
box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
|
|
18
|
+
}
|
|
19
|
+
.storybook-button--small {
|
|
20
|
+
font-size: 12px;
|
|
21
|
+
padding: 10px 16px;
|
|
22
|
+
}
|
|
23
|
+
.storybook-button--medium {
|
|
24
|
+
font-size: 14px;
|
|
25
|
+
padding: 11px 20px;
|
|
26
|
+
}
|
|
27
|
+
.storybook-button--large {
|
|
28
|
+
font-size: 16px;
|
|
29
|
+
padding: 12px 24px;
|
|
30
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import globalThis from 'global';
|
|
2
|
+
|
|
3
|
+
import { ButtonTag } from './Button';
|
|
4
|
+
import { FormTag } from './Form';
|
|
5
|
+
import { HtmlTag } from './Html';
|
|
6
|
+
import { PreTag } from './Pre';
|
|
7
|
+
|
|
8
|
+
globalThis.Components = {
|
|
9
|
+
Button: ButtonTag,
|
|
10
|
+
Form: FormTag,
|
|
11
|
+
Html: HtmlTag,
|
|
12
|
+
Pre: PreTag,
|
|
13
|
+
};
|
|
14
|
+
globalThis.storybookRenderer = 'web-components';
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "experimental",
|
|
3
|
+
"tags": [
|
|
4
|
+
{
|
|
5
|
+
"name": "demo-wc-card",
|
|
6
|
+
"path": "./demo-wc-card.js",
|
|
7
|
+
"description": "This is a container looking like a card with a back and front side you can switch",
|
|
8
|
+
"attributes": [
|
|
9
|
+
{
|
|
10
|
+
"name": "back-side",
|
|
11
|
+
"description": "Indicates that the back of the card is shown",
|
|
12
|
+
"type": "boolean",
|
|
13
|
+
"default": "false"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "header",
|
|
17
|
+
"description": "Header message",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"default": "\"Your Message\""
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"name": "rows",
|
|
23
|
+
"description": "Data rows",
|
|
24
|
+
"type": "object",
|
|
25
|
+
"default": "[]"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"properties": [
|
|
29
|
+
{
|
|
30
|
+
"name": "backSide",
|
|
31
|
+
"attribute": "back-side",
|
|
32
|
+
"description": "Indicates that the back of the card is shown",
|
|
33
|
+
"type": "boolean",
|
|
34
|
+
"default": "false"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "header",
|
|
38
|
+
"attribute": "header",
|
|
39
|
+
"description": "Header message",
|
|
40
|
+
"type": "string",
|
|
41
|
+
"default": "\"Your Message\""
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "rows",
|
|
45
|
+
"attribute": "rows",
|
|
46
|
+
"description": "Data rows",
|
|
47
|
+
"type": "object",
|
|
48
|
+
"default": "[]"
|
|
49
|
+
}
|
|
50
|
+
],
|
|
51
|
+
"events": [
|
|
52
|
+
{
|
|
53
|
+
"name": "side-changed",
|
|
54
|
+
"description": "Fires whenever it switches between front/back"
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"methods": [
|
|
58
|
+
{
|
|
59
|
+
"name": "testMethod",
|
|
60
|
+
"description": "Some web component frameworks like Stencil generate extra docs for methods. These are also displayed in the ArgsTable."
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"slots": [
|
|
64
|
+
{
|
|
65
|
+
"name": "",
|
|
66
|
+
"description": "This is an unnamed slot (the default slot)"
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"cssProperties": [
|
|
70
|
+
{
|
|
71
|
+
"name": "--demo-wc-card-header-font-size",
|
|
72
|
+
"description": "Header font size"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "--demo-wc-card-front-color",
|
|
76
|
+
"description": "Font color for front"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "--demo-wc-card-back-color",
|
|
80
|
+
"description": "Font color for back"
|
|
81
|
+
}
|
|
82
|
+
],
|
|
83
|
+
"cssParts": [
|
|
84
|
+
{
|
|
85
|
+
"name": "front",
|
|
86
|
+
"description": "Front of the card"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"name": "back",
|
|
90
|
+
"description": "Back of the card"
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"readme": "",
|
|
4
|
+
"modules": [
|
|
5
|
+
{
|
|
6
|
+
"kind": "javascript-module",
|
|
7
|
+
"path": "demo-wc-card/index.js",
|
|
8
|
+
"declarations": [],
|
|
9
|
+
"exports": [
|
|
10
|
+
{
|
|
11
|
+
"kind": "custom-element-definition",
|
|
12
|
+
"name": "demo-wc-card",
|
|
13
|
+
"declaration": {
|
|
14
|
+
"name": "DemoWcCard",
|
|
15
|
+
"module": "demo-wc-card/DemoWcCard.js"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"kind": "javascript-module",
|
|
22
|
+
"path": "demo-wc-card/DemoWcCard.js",
|
|
23
|
+
"declarations": [
|
|
24
|
+
{
|
|
25
|
+
"kind": "class",
|
|
26
|
+
"description": "This is a container looking like a card with a back and front side you can switch",
|
|
27
|
+
"name": "DemoWcCard",
|
|
28
|
+
"cssProperties": [
|
|
29
|
+
{
|
|
30
|
+
"description": "Header font size",
|
|
31
|
+
"name": "--demo-wc-card-header-font-size"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"description": "Font color for front",
|
|
35
|
+
"name": "--demo-wc-card-front-color"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"description": "Font color for back",
|
|
39
|
+
"name": "--demo-wc-card-back-color"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"cssParts": [
|
|
43
|
+
{
|
|
44
|
+
"description": "Front of the card",
|
|
45
|
+
"name": "front"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"description": "Back of the card",
|
|
49
|
+
"name": "back"
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"slots": [
|
|
53
|
+
{
|
|
54
|
+
"description": "This is an unnamed slot (the default slot)",
|
|
55
|
+
"name": ""
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
"members": [
|
|
59
|
+
{
|
|
60
|
+
"kind": "method",
|
|
61
|
+
"name": "toggle"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"kind": "field",
|
|
65
|
+
"name": "backSide",
|
|
66
|
+
"type": {
|
|
67
|
+
"text": "boolean"
|
|
68
|
+
},
|
|
69
|
+
"description": "Indicates that the back of the card is shown",
|
|
70
|
+
"default": "false",
|
|
71
|
+
"privacy": "public",
|
|
72
|
+
"attribute": "back-side",
|
|
73
|
+
"reflects": true
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"kind": "field",
|
|
77
|
+
"name": "header",
|
|
78
|
+
"type": {
|
|
79
|
+
"text": "string"
|
|
80
|
+
},
|
|
81
|
+
"description": "Header message",
|
|
82
|
+
"default": "'Your Message'",
|
|
83
|
+
"privacy": "public",
|
|
84
|
+
"attribute": "header"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"kind": "field",
|
|
88
|
+
"name": "rows",
|
|
89
|
+
"type": {
|
|
90
|
+
"text": "array"
|
|
91
|
+
},
|
|
92
|
+
"description": "Data rows",
|
|
93
|
+
"default": "[]",
|
|
94
|
+
"privacy": "public",
|
|
95
|
+
"attribute": "rows"
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"events": [
|
|
99
|
+
{
|
|
100
|
+
"name": "side-changed",
|
|
101
|
+
"type": {
|
|
102
|
+
"text": "CustomEvent"
|
|
103
|
+
},
|
|
104
|
+
"description": "Fires whenever it switches between front/back"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"attributes": [
|
|
108
|
+
{
|
|
109
|
+
"name": "back-side",
|
|
110
|
+
"fieldName": "backSide"
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"name": "header",
|
|
114
|
+
"fieldName": "header"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "rows",
|
|
118
|
+
"fieldName": "rows"
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
"superclass": {
|
|
122
|
+
"name": "LitElement",
|
|
123
|
+
"package": "lit"
|
|
124
|
+
},
|
|
125
|
+
"tagName": "demo-wc-card",
|
|
126
|
+
"customElement": true
|
|
127
|
+
}
|
|
128
|
+
],
|
|
129
|
+
"exports": [
|
|
130
|
+
{
|
|
131
|
+
"kind": "js",
|
|
132
|
+
"name": "DemoWcCard",
|
|
133
|
+
"declaration": {
|
|
134
|
+
"name": "DemoWcCard",
|
|
135
|
+
"module": "demo-wc-card/DemoWcCard.js"
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"kind": "javascript-module",
|
|
142
|
+
"path": "demo-wc-card/demoWcCardStyle.css.js",
|
|
143
|
+
"declarations": [
|
|
144
|
+
{
|
|
145
|
+
"kind": "variable",
|
|
146
|
+
"name": "demoWcCardStyle",
|
|
147
|
+
"default": "css`\n :host {\n display: block;\n position: relative;\n width: 250px;\n height: 200px;\n border-radius: 10px;\n transform-style: preserve-3d;\n transition: all 0.8s ease;\n }\n\n .header {\n font-weight: bold;\n font-size: var(--demo-wc-card-header-font-size, 16px);\n text-align: center;\n }\n\n .content {\n padding: 20px 10px 0 10px;\n flex-grow: 1;\n }\n\n .footer {\n display: flex;\n }\n\n dl {\n margin: 0;\n text-align: left;\n }\n\n dd {\n margin-left: 15px;\n }\n\n button {\n border-radius: 15px;\n width: 30px;\n height: 30px;\n background: #fff;\n border: 1px solid #ccc;\n color: #000;\n font-size: 21px;\n line-height: 27px;\n font-weight: bold;\n cursor: pointer;\n margin: 5px;\n }\n\n .note {\n flex-grow: 1;\n color: #666;\n font-size: 16px;\n font-weight: bold;\n text-align: left;\n padding-top: 15px;\n }\n\n :host([back-side]) {\n transform: rotateY(180deg);\n }\n\n #front,\n #back {\n position: absolute;\n width: 250px;\n box-sizing: border-box;\n box-shadow: #ccc 3px 3px 2px 1px;\n padding: 10px;\n display: flex;\n flex-flow: column;\n top: 0;\n left: 0;\n height: 100%;\n border-radius: 10px;\n backface-visibility: hidden;\n overflow: hidden;\n }\n\n #front {\n background: linear-gradient(141deg, #aaa 25%, #eee 40%, #ddd 55%);\n color: var(--demo-wc-card-front-color, #000);\n }\n\n #back {\n background: linear-gradient(141deg, #333 25%, #aaa 40%, #666 55%);\n color: var(--demo-wc-card-back-color, #fff);\n text-align: center;\n transform: rotateY(180deg) translate3d(0px, 0, 1px);\n }\n\n #back .note {\n color: #fff;\n }\n`"
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
"exports": [
|
|
151
|
+
{
|
|
152
|
+
"kind": "js",
|
|
153
|
+
"name": "demoWcCardStyle",
|
|
154
|
+
"declaration": {
|
|
155
|
+
"name": "demoWcCardStyle",
|
|
156
|
+
"module": "demo-wc-card/demoWcCardStyle.css.js"
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import global from 'global';
|
|
2
|
+
import { LitElement, html } from 'lit';
|
|
3
|
+
// eslint-disable-next-line import/extensions
|
|
4
|
+
import { demoWcCardStyle } from './demoWcCardStyle.css.js';
|
|
5
|
+
|
|
6
|
+
const { CustomEvent } = global;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* This is a container looking like a card with a back and front side you can switch
|
|
10
|
+
*
|
|
11
|
+
* @slot - This is an unnamed slot (the default slot)
|
|
12
|
+
* @fires side-changed - Fires whenever it switches between front/back
|
|
13
|
+
* @cssprop --demo-wc-card-header-font-size - Header font size
|
|
14
|
+
* @cssprop --demo-wc-card-front-color - Font color for front
|
|
15
|
+
* @cssprop --demo-wc-card-back-color - Font color for back
|
|
16
|
+
* @csspart front - Front of the card
|
|
17
|
+
* @csspart back - Back of the card
|
|
18
|
+
*/
|
|
19
|
+
export class DemoWcCard extends LitElement {
|
|
20
|
+
static get properties() {
|
|
21
|
+
return {
|
|
22
|
+
backSide: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
reflect: true,
|
|
25
|
+
attribute: 'back-side',
|
|
26
|
+
},
|
|
27
|
+
header: { type: String },
|
|
28
|
+
rows: { type: Object },
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static get styles() {
|
|
33
|
+
return demoWcCardStyle;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
constructor() {
|
|
37
|
+
super();
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Indicates that the back of the card is shown
|
|
41
|
+
*/
|
|
42
|
+
this.backSide = false;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Header message
|
|
46
|
+
*/
|
|
47
|
+
this.header = 'Your Message';
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Data rows
|
|
51
|
+
*/
|
|
52
|
+
this.rows = [];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
toggle() {
|
|
56
|
+
this.backSide = !this.backSide;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
render() {
|
|
60
|
+
return html`
|
|
61
|
+
<div id="front" part="front">
|
|
62
|
+
<div class="header">${this.header}</div>
|
|
63
|
+
<div class="content">
|
|
64
|
+
<slot></slot>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="footer">
|
|
67
|
+
<div class="note">A</div>
|
|
68
|
+
<button @click=${this.toggle}>></button>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
<div id="back" part="back">
|
|
72
|
+
<div class="header">${this.header}</div>
|
|
73
|
+
|
|
74
|
+
<div class="content">
|
|
75
|
+
${this.rows.length === 0
|
|
76
|
+
? html``
|
|
77
|
+
: html`
|
|
78
|
+
<dl>
|
|
79
|
+
${this.rows.map(
|
|
80
|
+
(row) => html`
|
|
81
|
+
<dt>${row.header}</dt>
|
|
82
|
+
<dd>${row.value}</dd>
|
|
83
|
+
`
|
|
84
|
+
)}
|
|
85
|
+
</dl>
|
|
86
|
+
`}
|
|
87
|
+
</div>
|
|
88
|
+
<div class="footer">
|
|
89
|
+
<div class="note">B</div>
|
|
90
|
+
<button @click=${this.toggle}>></button>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
updated(changedProperties) {
|
|
97
|
+
if (changedProperties.has('backSide') && changedProperties.get('backSide') !== undefined) {
|
|
98
|
+
this.dispatchEvent(new CustomEvent('side-changed'));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
|
|
3
|
+
export const demoWcCardStyle = css`
|
|
4
|
+
:host {
|
|
5
|
+
display: block;
|
|
6
|
+
position: relative;
|
|
7
|
+
width: 250px;
|
|
8
|
+
height: 200px;
|
|
9
|
+
border-radius: 10px;
|
|
10
|
+
transform-style: preserve-3d;
|
|
11
|
+
transition: all 0.8s ease;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.header {
|
|
15
|
+
font-weight: bold;
|
|
16
|
+
font-size: var(--demo-wc-card-header-font-size, 16px);
|
|
17
|
+
text-align: center;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.content {
|
|
21
|
+
padding: 20px 10px 0 10px;
|
|
22
|
+
flex-grow: 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.footer {
|
|
26
|
+
display: flex;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
dl {
|
|
30
|
+
margin: 0;
|
|
31
|
+
text-align: left;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
dd {
|
|
35
|
+
margin-left: 15px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
button {
|
|
39
|
+
border-radius: 15px;
|
|
40
|
+
width: 30px;
|
|
41
|
+
height: 30px;
|
|
42
|
+
background: #fff;
|
|
43
|
+
border: 1px solid #ccc;
|
|
44
|
+
color: #000;
|
|
45
|
+
font-size: 21px;
|
|
46
|
+
line-height: 27px;
|
|
47
|
+
font-weight: bold;
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
margin: 5px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.note {
|
|
53
|
+
flex-grow: 1;
|
|
54
|
+
color: #666;
|
|
55
|
+
font-size: 16px;
|
|
56
|
+
font-weight: bold;
|
|
57
|
+
text-align: left;
|
|
58
|
+
padding-top: 15px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
:host([back-side]) {
|
|
62
|
+
transform: rotateY(180deg);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
#front,
|
|
66
|
+
#back {
|
|
67
|
+
position: absolute;
|
|
68
|
+
width: 250px;
|
|
69
|
+
box-sizing: border-box;
|
|
70
|
+
box-shadow: #ccc 3px 3px 2px 1px;
|
|
71
|
+
padding: 10px;
|
|
72
|
+
display: flex;
|
|
73
|
+
flex-flow: column;
|
|
74
|
+
top: 0;
|
|
75
|
+
left: 0;
|
|
76
|
+
height: 100%;
|
|
77
|
+
border-radius: 10px;
|
|
78
|
+
backface-visibility: hidden;
|
|
79
|
+
overflow: hidden;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
#front {
|
|
83
|
+
background: linear-gradient(141deg, #aaa 25%, #eee 40%, #ddd 55%);
|
|
84
|
+
color: var(--demo-wc-card-front-color, #000);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#back {
|
|
88
|
+
background: linear-gradient(141deg, #333 25%, #aaa 40%, #666 55%);
|
|
89
|
+
color: var(--demo-wc-card-back-color, #fff);
|
|
90
|
+
text-align: center;
|
|
91
|
+
transform: rotateY(180deg) translate3d(0px, 0, 1px);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#back .note {
|
|
95
|
+
color: #fff;
|
|
96
|
+
}
|
|
97
|
+
`;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import './demo-wc-card';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
component: 'demo-wc-card',
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const Template = ({ backSide, header, rows }) =>
|
|
9
|
+
html`
|
|
10
|
+
<demo-wc-card .backSide="${backSide}" .header="${header}" .rows="${rows}"
|
|
11
|
+
>A simple card</demo-wc-card
|
|
12
|
+
>
|
|
13
|
+
`;
|
|
14
|
+
|
|
15
|
+
export const Front = Template.bind({});
|
|
16
|
+
Front.args = { backSide: false, header: undefined, rows: [] };
|