Skip to content

Commit bdb5421

Browse files
committed
feat: export create-addon
ci: node version chore: package-lock chore(release): 0.1.35 chore: publish file chore(release): 0.1.36
1 parent b5cc45e commit bdb5421

File tree

5 files changed

+14151
-8571
lines changed

5 files changed

+14151
-8571
lines changed

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ jobs:
1818
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
1919
fetch-depth: 0
2020

21-
- name: Setup Node.js 14.x
21+
- name: Setup Node.js 18.x
2222
uses: actions/setup-node@master
2323
with:
24-
node-version: 14.x
24+
node-version: 18.x
2525
registry-url: 'https://registry.npmjs.org'
2626

2727
- name: Install Dependencies

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
44

5+
### [0.1.36](https://github.com/modernweb-dev/storybook-prebuilt/compare/v0.1.35...v0.1.36) (2023-07-04)
6+
7+
### [0.1.35](https://github.com/modernweb-dev/storybook-prebuilt/compare/v0.1.34...v0.1.35) (2023-07-04)
8+
9+
10+
### Features
11+
12+
* export create-addon ([e2b8dcf](https://github.com/modernweb-dev/storybook-prebuilt/commit/e2b8dcfb9b21fede12b7406f919d9494245bb0c8))
13+
514
### [0.1.34](https://github.com/modernweb-dev/storybook-prebuilt/compare/v0.1.33...v0.1.34) (2022-02-26)
615

716
### [0.1.33](https://github.com/modernweb-dev/storybook-prebuilt/compare/v0.1.32...v0.1.33) (2022-01-10)

create-addon.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* Storybook addons are React components. The `createAddon` function returns a React component that
3+
* wraps a custom element and passes on properties and events. This allows for creating addons with
4+
* web components (and therefore LitElement).
5+
*
6+
* The wrapper can forward specific events to your addon (web component) as they occur. Your addon
7+
* can listen for these events. Some useful Storybook events are forwarded by default (such as when
8+
* the user changes stories). An `options` parameter can be passed to `createAddon` that contains
9+
* additional events that you may need for your use case.
10+
*
11+
* Storybook expects only 1 addon to be in the DOM, which is the addon that is selected (active).
12+
* This means addons can be continuously connected/disconnected when switching between addons and
13+
* stories. This is important to understand to work effectively with LitElement lifecycle methods
14+
* and events. Addons that rely on events that might occur when it is not active, should have their
15+
* event listeners set up in the `constructor`. Event listeners set up in the `connectedCallback`
16+
* should always also be disconnected.
17+
*/
18+
19+
import { React } from './manager.js';
20+
import {
21+
STORY_SPECIFIED,
22+
STORY_CHANGED,
23+
STORY_RENDERED,
24+
} from './core-events.js';
25+
26+
// A default set of Storybook events that are forwarded to the addon as they occur. If an addon
27+
// needs additional events (either Storybook or custom events), they can be passed via the options.
28+
const storybookEvents = [STORY_SPECIFIED, STORY_CHANGED, STORY_RENDERED];
29+
const { Component, createRef, createElement } = React;
30+
/**
31+
* @param {String} customElementName
32+
* @param {Object} [options]
33+
*/
34+
export function createAddon(customElementName, options = {}) {
35+
return class extends Component {
36+
constructor(props) {
37+
super(props);
38+
this.ref = createRef();
39+
}
40+
41+
componentDidMount() {
42+
const customEvents = options.events ?? [];
43+
const uniqueEvents = Array.from(
44+
new Set([...storybookEvents, ...customEvents])
45+
);
46+
uniqueEvents.forEach(event => {
47+
this.props.api.getChannel().on(event, detail => {
48+
if (!this.addonElement) {
49+
this.updateAddon(event);
50+
}
51+
this.addonElement.dispatchEvent(new CustomEvent(event, { detail }));
52+
});
53+
});
54+
}
55+
56+
componentDidUpdate() {
57+
this.updateAddon();
58+
}
59+
60+
updateAddon() {
61+
if (!this.addonElement) {
62+
this.addonElement = document.createElement(customElementName);
63+
}
64+
65+
const { api, active } = this.props;
66+
Object.assign(this.addonElement, { api, active });
67+
68+
// Here, the element could get added for the first time, or re-added after a switch between addons.
69+
if (this.shouldAddonBeInDom() && !this.ref.current.firstChild) {
70+
this.ref.current.appendChild(this.addonElement);
71+
}
72+
}
73+
74+
shouldAddonBeInDom() {
75+
return this.ref.current && this.props.active;
76+
}
77+
78+
render() {
79+
if (!this.props.active) {
80+
return null;
81+
}
82+
return createElement('div', { ref: this.ref });
83+
}
84+
};
85+
}

0 commit comments

Comments
 (0)