@storybook/preact 7.0.0-alpha.46 → 7.0.0-alpha.48
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/config.d.ts +3 -0
- package/dist/config.js +2 -2
- package/dist/config.mjs +1 -1
- package/package.json +7 -6
- package/template/cli/.eslintrc.json +7 -0
- package/template/cli/Button.jsx +49 -0
- package/template/cli/Button.stories.jsx +42 -0
- package/template/cli/Header.jsx +58 -0
- package/template/cli/Header.stories.jsx +27 -0
- package/template/cli/Page.jsx +68 -0
- package/template/cli/Page.stories.jsx +25 -0
- package/template/components/Button.jsx +14 -0
- package/template/components/Form.jsx +38 -0
- package/template/components/Html.jsx +10 -0
- package/template/components/Pre.jsx +21 -0
- package/template/components/index.js +9 -0
- package/template/stories/React.js +50 -0
- package/template/stories/react-compat.stories.js +15 -0
package/dist/config.d.ts
CHANGED
@@ -6,6 +6,9 @@ declare const render: ArgsStoryFn<PreactFramework>;
|
|
6
6
|
declare function renderToDOM({ storyFn, title, name, showMain, showError, forceRemount }: Store_RenderContext<PreactFramework>, domElement: Element): void;
|
7
7
|
|
8
8
|
declare const parameters: {
|
9
|
+
docs: {
|
10
|
+
inlineStories: boolean;
|
11
|
+
};
|
9
12
|
framework: "preact";
|
10
13
|
};
|
11
14
|
|
package/dist/config.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"use strict";var
|
1
|
+
"use strict";var h=Object.create;var m=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var x=Object.getPrototypeOf,S=Object.prototype.hasOwnProperty;var g=(e,r)=>{for(var t in r)m(e,t,{get:r[t],enumerable:!0})},c=(e,r,t,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of F(r))!S.call(e,a)&&a!==t&&m(e,a,{get:()=>r[a],enumerable:!(o=w(r,a))||o.enumerable});return e};var P=(e,r,t)=>(t=e!=null?h(x(e)):{},c(r||!e||!e.__esModule?m(t,"default",{value:e,enumerable:!0}):t,e)),E=e=>c(m({},"__esModule",{value:!0}),e);var M={};g(M,{parameters:()=>R,render:()=>f,renderToDOM:()=>u});module.exports=E(M);var i={docs:{inlineStories:!0}};var n=P(require("preact")),y=require("ts-dedent"),{h:k}=n,f=(e,r)=>{let{id:t,component:o}=r;if(!o)throw new Error(`Unable to render story ${t} as the component annotation is missing from the default export`);return k(o,{...e})},d;function l(e,r){n.Fragment?n.render(e,r):d=n.render(e,r,d)}var C=({showError:e,name:r,title:t,storyFn:o,domElement:a})=>{let s=n.h(o,null);return s||(e({title:`Expecting a Preact element from the story: "${r}" of "${t}".`,description:y.dedent`
|
2
2
|
Did you forget to return the Preact element from the story?
|
3
3
|
Use "() => (<MyComp/>)" or "() => { return <MyComp/>; }" when defining the story.
|
4
|
-
`}),null)};function
|
4
|
+
`}),null)};function u({storyFn:e,title:r,name:t,showMain:o,showError:a,forceRemount:s},p){s&&l(null,p),o(),l(n.h(C,{name:t,title:r,showError:a,storyFn:e,domElement:p}),p)}var R={framework:"preact",...i};0&&(module.exports={parameters,render,renderToDOM});
|
package/dist/config.mjs
CHANGED
@@ -1 +1 @@
|
|
1
|
-
import{a as
|
1
|
+
import{a as e,b as o}from"./chunk-VVPUC5MQ.mjs";var r={docs:{inlineStories:!0}};var m={framework:"preact",...r};export{m as parameters,e as render,o as renderToDOM};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@storybook/preact",
|
3
|
-
"version": "7.0.0-alpha.
|
3
|
+
"version": "7.0.0-alpha.48",
|
4
4
|
"description": "Storybook Preact renderer",
|
5
5
|
"keywords": [
|
6
6
|
"storybook"
|
@@ -41,6 +41,7 @@
|
|
41
41
|
"types": "dist/index.d.ts",
|
42
42
|
"files": [
|
43
43
|
"dist/**/*",
|
44
|
+
"template/**/*",
|
44
45
|
"README.md",
|
45
46
|
"*.js",
|
46
47
|
"*.d.ts"
|
@@ -50,10 +51,10 @@
|
|
50
51
|
"prep": "../../../scripts/prepare/bundle.ts"
|
51
52
|
},
|
52
53
|
"dependencies": {
|
53
|
-
"@storybook/addons": "7.0.0-alpha.
|
54
|
-
"@storybook/core-client": "7.0.0-alpha.
|
55
|
-
"@storybook/store": "7.0.0-alpha.
|
56
|
-
"@storybook/types": "7.0.0-alpha.
|
54
|
+
"@storybook/addons": "7.0.0-alpha.48",
|
55
|
+
"@storybook/core-client": "7.0.0-alpha.48",
|
56
|
+
"@storybook/store": "7.0.0-alpha.48",
|
57
|
+
"@storybook/types": "7.0.0-alpha.48",
|
57
58
|
"global": "^4.4.0",
|
58
59
|
"react": "16.14.0",
|
59
60
|
"react-dom": "16.14.0",
|
@@ -79,5 +80,5 @@
|
|
79
80
|
],
|
80
81
|
"platform": "browser"
|
81
82
|
},
|
82
|
-
"gitHead": "
|
83
|
+
"gitHead": "b58a29b785462f8a8b711b6bb2d7223fd6dc17fd"
|
83
84
|
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import PropTypes from 'prop-types';
|
2
|
+
import './button.css';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Primary UI component for user interaction
|
6
|
+
*/
|
7
|
+
export const Button = ({ primary, backgroundColor, size, label, ...props }) => {
|
8
|
+
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
|
9
|
+
return (
|
10
|
+
<button
|
11
|
+
type="button"
|
12
|
+
className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
|
13
|
+
style={backgroundColor && { backgroundColor }}
|
14
|
+
{...props}
|
15
|
+
>
|
16
|
+
{label}
|
17
|
+
</button>
|
18
|
+
);
|
19
|
+
};
|
20
|
+
|
21
|
+
Button.propTypes = {
|
22
|
+
/**
|
23
|
+
* Is this the principal call to action on the page?
|
24
|
+
*/
|
25
|
+
primary: PropTypes.bool,
|
26
|
+
/**
|
27
|
+
* What background color to use
|
28
|
+
*/
|
29
|
+
backgroundColor: PropTypes.string,
|
30
|
+
/**
|
31
|
+
* How large should the button be?
|
32
|
+
*/
|
33
|
+
size: PropTypes.oneOf(['small', 'medium', 'large']),
|
34
|
+
/**
|
35
|
+
* Button contents
|
36
|
+
*/
|
37
|
+
label: PropTypes.string.isRequired,
|
38
|
+
/**
|
39
|
+
* Optional click handler
|
40
|
+
*/
|
41
|
+
onClick: PropTypes.func,
|
42
|
+
};
|
43
|
+
|
44
|
+
Button.defaultProps = {
|
45
|
+
backgroundColor: null,
|
46
|
+
primary: false,
|
47
|
+
size: 'medium',
|
48
|
+
onClick: undefined,
|
49
|
+
};
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import { Button } from './Button';
|
2
|
+
|
3
|
+
// More on default export: https://storybook.js.org/docs/preact/writing-stories/introduction#default-export
|
4
|
+
export default {
|
5
|
+
title: 'Example/Button',
|
6
|
+
component: Button,
|
7
|
+
// This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/preact/writing-docs/docs-page
|
8
|
+
tags: ['docsPage'],
|
9
|
+
// More on argTypes: https://storybook.js.org/docs/preact/api/argtypes
|
10
|
+
argTypes: {
|
11
|
+
backgroundColor: { control: 'color' },
|
12
|
+
onClick: { action: 'onClick' },
|
13
|
+
},
|
14
|
+
};
|
15
|
+
|
16
|
+
// More on component templates: https://storybook.js.org/docs/preact/writing-stories/introduction#using-args
|
17
|
+
export const Primary = {
|
18
|
+
args: {
|
19
|
+
primary: true,
|
20
|
+
label: 'Button',
|
21
|
+
},
|
22
|
+
};
|
23
|
+
|
24
|
+
export const Secondary = {
|
25
|
+
args: {
|
26
|
+
label: 'Button',
|
27
|
+
},
|
28
|
+
};
|
29
|
+
|
30
|
+
export const Large = {
|
31
|
+
args: {
|
32
|
+
size: 'large',
|
33
|
+
label: 'Button',
|
34
|
+
},
|
35
|
+
};
|
36
|
+
|
37
|
+
export const Small = {
|
38
|
+
args: {
|
39
|
+
size: 'small',
|
40
|
+
label: 'Button',
|
41
|
+
},
|
42
|
+
};
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import PropTypes from 'prop-types';
|
2
|
+
|
3
|
+
import { Button } from './Button';
|
4
|
+
import './header.css';
|
5
|
+
|
6
|
+
export const Header = ({ user, onLogin, onLogout, onCreateAccount }) => (
|
7
|
+
<header>
|
8
|
+
<div className="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
|
+
<>
|
31
|
+
<span className="welcome">
|
32
|
+
Welcome, <b>{user.name}</b>!
|
33
|
+
</span>
|
34
|
+
<Button size="small" onClick={onLogout} label="Log out" />
|
35
|
+
</>
|
36
|
+
) : (
|
37
|
+
<>
|
38
|
+
<Button size="small" onClick={onLogin} label="Log in" />
|
39
|
+
<Button primary size="small" onClick={onCreateAccount} label="Sign up" />
|
40
|
+
</>
|
41
|
+
)}
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
</header>
|
45
|
+
);
|
46
|
+
|
47
|
+
Header.propTypes = {
|
48
|
+
user: PropTypes.shape({
|
49
|
+
name: PropTypes.string.isRequired,
|
50
|
+
}),
|
51
|
+
onLogin: PropTypes.func.isRequired,
|
52
|
+
onLogout: PropTypes.func.isRequired,
|
53
|
+
onCreateAccount: PropTypes.func.isRequired,
|
54
|
+
};
|
55
|
+
|
56
|
+
Header.defaultProps = {
|
57
|
+
user: null,
|
58
|
+
};
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { Header } from './Header';
|
2
|
+
|
3
|
+
export default {
|
4
|
+
title: 'Example/Header',
|
5
|
+
component: Header,
|
6
|
+
// This component will have an automatically generated docsPage entry: https://storybook.js.org/docs/preact/writing-docs/docs-page
|
7
|
+
tags: ['docsPage'],
|
8
|
+
parameters: {
|
9
|
+
// More on Story layout: https://storybook.js.org/docs/preact/configure/story-layout
|
10
|
+
layout: 'fullscreen',
|
11
|
+
},
|
12
|
+
argTypes: {
|
13
|
+
onLogin: { action: 'onLogin' },
|
14
|
+
onLogout: { action: 'onLogout' },
|
15
|
+
onCreateAccount: { action: 'onCreateAccount' },
|
16
|
+
},
|
17
|
+
};
|
18
|
+
|
19
|
+
export const LoggedIn = {
|
20
|
+
args: {
|
21
|
+
user: {
|
22
|
+
name: 'Jane Doe',
|
23
|
+
},
|
24
|
+
},
|
25
|
+
};
|
26
|
+
|
27
|
+
export const LoggedOut = {};
|
@@ -0,0 +1,68 @@
|
|
1
|
+
import { useState } from 'preact/hooks';
|
2
|
+
import { Header } from './Header';
|
3
|
+
import './page.css';
|
4
|
+
|
5
|
+
export const Page = () => {
|
6
|
+
const [user, setUser] = useState();
|
7
|
+
|
8
|
+
return (
|
9
|
+
<article>
|
10
|
+
<Header
|
11
|
+
user={user}
|
12
|
+
onLogin={() => setUser({ name: 'Jane Doe' })}
|
13
|
+
onLogout={() => setUser(undefined)}
|
14
|
+
onCreateAccount={() => setUser({ name: 'Jane Doe' })}
|
15
|
+
/>
|
16
|
+
|
17
|
+
<section>
|
18
|
+
<h2>Pages in Storybook</h2>
|
19
|
+
<p>
|
20
|
+
We recommend building UIs with a{' '}
|
21
|
+
<a href="https://componentdriven.org" target="_blank" rel="noopener noreferrer">
|
22
|
+
<strong>component-driven</strong>
|
23
|
+
</a>{' '}
|
24
|
+
process starting with atomic components and ending with pages.
|
25
|
+
</p>
|
26
|
+
<p>
|
27
|
+
Render pages with mock data. This makes it easy to build and review page states without
|
28
|
+
needing to navigate to them in your app. Here are some handy patterns for managing page
|
29
|
+
data in Storybook:
|
30
|
+
</p>
|
31
|
+
<ul>
|
32
|
+
<li>
|
33
|
+
Use a higher-level connected component. Storybook helps you compose such data from the
|
34
|
+
"args" of child component stories
|
35
|
+
</li>
|
36
|
+
<li>
|
37
|
+
Assemble data in the page component from your services. You can mock these services out
|
38
|
+
using Storybook.
|
39
|
+
</li>
|
40
|
+
</ul>
|
41
|
+
<p>
|
42
|
+
Get a guided tutorial on component-driven development at{' '}
|
43
|
+
<a href="https://storybook.js.org/tutorials/" target="_blank" rel="noopener noreferrer">
|
44
|
+
Storybook tutorials
|
45
|
+
</a>
|
46
|
+
. Read more in the{' '}
|
47
|
+
<a href="https://storybook.js.org/docs" target="_blank" rel="noopener noreferrer">
|
48
|
+
docs
|
49
|
+
</a>
|
50
|
+
.
|
51
|
+
</p>
|
52
|
+
<div className="tip-wrapper">
|
53
|
+
<span className="tip">Tip</span> Adjust the width of the canvas with the{' '}
|
54
|
+
<svg width="10" height="10" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
55
|
+
<g fill="none" fillRule="evenodd">
|
56
|
+
<path
|
57
|
+
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"
|
58
|
+
id="a"
|
59
|
+
fill="#999"
|
60
|
+
/>
|
61
|
+
</g>
|
62
|
+
</svg>
|
63
|
+
Viewports addon in the toolbar
|
64
|
+
</div>
|
65
|
+
</section>
|
66
|
+
</article>
|
67
|
+
);
|
68
|
+
};
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { within, userEvent } from '@storybook/testing-library';
|
2
|
+
|
3
|
+
import { Page } from './Page';
|
4
|
+
|
5
|
+
export default {
|
6
|
+
title: 'Example/Page',
|
7
|
+
component: Page,
|
8
|
+
parameters: {
|
9
|
+
// More on Story layout: https://storybook.js.org/docs/preact/configure/story-layout
|
10
|
+
layout: 'fullscreen',
|
11
|
+
},
|
12
|
+
};
|
13
|
+
|
14
|
+
export const LoggedOut = {};
|
15
|
+
|
16
|
+
// More on interaction testing: https://storybook.js.org/docs/preact/writing-tests/interaction-testing
|
17
|
+
export const LoggedIn = {
|
18
|
+
play: async ({ canvasElement }) => {
|
19
|
+
const canvas = within(canvasElement);
|
20
|
+
const loginButton = await canvas.getByRole('button', {
|
21
|
+
name: /Log in/i,
|
22
|
+
});
|
23
|
+
await userEvent.click(loginButton);
|
24
|
+
},
|
25
|
+
};
|
@@ -0,0 +1,14 @@
|
|
1
|
+
/* eslint-disable react/react-in-jsx-scope */
|
2
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
export const Button = ({ onClick, label }) => (
|
6
|
+
<button type="button" onClick={onClick}>
|
7
|
+
{label}
|
8
|
+
</button>
|
9
|
+
);
|
10
|
+
|
11
|
+
Button.propTypes = {
|
12
|
+
onClick: PropTypes.func.isRequired,
|
13
|
+
label: PropTypes.node.isRequired,
|
14
|
+
};
|
@@ -0,0 +1,38 @@
|
|
1
|
+
/* eslint-disable react/react-in-jsx-scope */
|
2
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
import { useState } from 'preact/hooks';
|
5
|
+
|
6
|
+
export const Form = ({ onSuccess }) => {
|
7
|
+
const [value, setValue] = useState('');
|
8
|
+
const [complete, setComplete] = useState(false);
|
9
|
+
|
10
|
+
function onSubmit(event) {
|
11
|
+
event.preventDefault();
|
12
|
+
onSuccess(value);
|
13
|
+
|
14
|
+
setTimeout(() => setComplete(true), 500);
|
15
|
+
setTimeout(() => setComplete(false), 1500);
|
16
|
+
}
|
17
|
+
|
18
|
+
return (
|
19
|
+
<form id="interaction-test-form" onSubmit={onSubmit}>
|
20
|
+
<label>
|
21
|
+
Enter Value
|
22
|
+
<input
|
23
|
+
type="text"
|
24
|
+
data-testid="value"
|
25
|
+
value={value}
|
26
|
+
required
|
27
|
+
onChange={(event) => setValue(event.target.value)}
|
28
|
+
/>
|
29
|
+
</label>
|
30
|
+
<button type="submit">Submit</button>
|
31
|
+
{complete && <p>Completed!!</p>}
|
32
|
+
</form>
|
33
|
+
);
|
34
|
+
};
|
35
|
+
|
36
|
+
Form.propTypes = {
|
37
|
+
onSuccess: PropTypes.func.isRequired,
|
38
|
+
};
|
@@ -0,0 +1,10 @@
|
|
1
|
+
/* eslint-disable react/react-in-jsx-scope */
|
2
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
// eslint-disable-next-line react/no-danger
|
6
|
+
export const Html = ({ content }) => <div dangerouslySetInnerHTML={{ __html: content }} />;
|
7
|
+
|
8
|
+
Html.propTypes = {
|
9
|
+
content: PropTypes.string.isRequired,
|
10
|
+
};
|
@@ -0,0 +1,21 @@
|
|
1
|
+
/* eslint-disable react/react-in-jsx-scope */
|
2
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
export const Pre = ({ style, object, text }) => (
|
6
|
+
<pre style={style} data-testid="pre">
|
7
|
+
{object ? JSON.stringify(object, null, 2) : text}
|
8
|
+
</pre>
|
9
|
+
);
|
10
|
+
|
11
|
+
Pre.propTypes = {
|
12
|
+
style: PropTypes.shape({}),
|
13
|
+
object: PropTypes.shape({}),
|
14
|
+
text: PropTypes.string,
|
15
|
+
};
|
16
|
+
|
17
|
+
Pre.defaultProps = {
|
18
|
+
style: {},
|
19
|
+
object: null,
|
20
|
+
text: '',
|
21
|
+
};
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import globalThis from 'global';
|
2
|
+
|
3
|
+
import { Button } from './Button.jsx';
|
4
|
+
import { Pre } from './Pre.jsx';
|
5
|
+
import { Form } from './Form.jsx';
|
6
|
+
import { Html } from './Html.jsx';
|
7
|
+
|
8
|
+
globalThis.Components = { Button, Pre, Form, Html };
|
9
|
+
globalThis.storybookRenderer = 'preact';
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
|
5
|
+
export const ReactFunctionalComponent = ({ label }) => {
|
6
|
+
const [clicks, setValue] = React.useState(0);
|
7
|
+
return (
|
8
|
+
<div
|
9
|
+
tabIndex={0}
|
10
|
+
onClick={() => setValue(clicks + 1)}
|
11
|
+
style={{ cursor: 'pointer' }}
|
12
|
+
onKeyDown={() => undefined}
|
13
|
+
role="button"
|
14
|
+
>
|
15
|
+
<div style={{ color: 'red' }}>{label}</div>
|
16
|
+
<div>Clicked {clicks} times.</div>
|
17
|
+
</div>
|
18
|
+
);
|
19
|
+
};
|
20
|
+
|
21
|
+
ReactFunctionalComponent.propTypes = {
|
22
|
+
label: PropTypes.string.isRequired,
|
23
|
+
};
|
24
|
+
|
25
|
+
export class ReactClassComponent extends React.Component {
|
26
|
+
state = {
|
27
|
+
clicks: 0,
|
28
|
+
};
|
29
|
+
|
30
|
+
render() {
|
31
|
+
const { label } = this.props;
|
32
|
+
const { clicks } = this.state;
|
33
|
+
return (
|
34
|
+
<div
|
35
|
+
tabIndex={0}
|
36
|
+
onClick={() => this.setState({ clicks: clicks + 1 })}
|
37
|
+
onKeyDown={() => undefined}
|
38
|
+
style={{ cursor: 'pointer' }}
|
39
|
+
role="button"
|
40
|
+
>
|
41
|
+
<div style={{ color: 'green' }}>{label}</div>
|
42
|
+
<div>Clicked {clicks} times.</div>
|
43
|
+
</div>
|
44
|
+
);
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
ReactClassComponent.propTypes = {
|
49
|
+
label: PropTypes.string.isRequired,
|
50
|
+
};
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/* eslint-disable react/react-in-jsx-scope */
|
2
|
+
import { ReactFunctionalComponent, ReactClassComponent } from './React';
|
3
|
+
|
4
|
+
export default {
|
5
|
+
component: ReactFunctionalComponent,
|
6
|
+
};
|
7
|
+
|
8
|
+
export const ReactComponentDemo = () => (
|
9
|
+
<div>
|
10
|
+
<h1>React component demo</h1>
|
11
|
+
<ReactFunctionalComponent label="This is a React functional component rendered by Preact" />
|
12
|
+
<hr />
|
13
|
+
<ReactClassComponent label="This is a React class component rendered by Preact" />
|
14
|
+
</div>
|
15
|
+
);
|