storybook-addon-pseudo-states 1.15.2 → 1.15.3

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/.babelrc.js CHANGED
@@ -1,14 +1,4 @@
1
- const modules = process.env.BABEL_ESM === 'true' ? false : 'auto';
2
-
3
1
  module.exports = {
4
- presets: [
5
- [
6
- "@babel/preset-env",
7
- {
8
- targets: 'defaults',
9
- modules
10
- }
11
- ],
12
- "@babel/preset-react"
13
- ],
2
+ targets: "defaults",
3
+ presets: ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"],
14
4
  }
@@ -0,0 +1,21 @@
1
+ // src/constants.ts
2
+ var ADDON_ID = "storybook/pseudo-states";
3
+ var TOOL_ID = `${ADDON_ID}/tool`;
4
+ var EXCLUDED_PSEUDO_ELEMENTS = ["::-webkit-scrollbar-thumb"];
5
+ var PSEUDO_STATES = {
6
+ hover: "hover",
7
+ active: "active",
8
+ focusVisible: "focus-visible",
9
+ focusWithin: "focus-within",
10
+ focus: "focus",
11
+ visited: "visited",
12
+ link: "link",
13
+ target: "target"
14
+ };
15
+
16
+ export {
17
+ ADDON_ID,
18
+ TOOL_ID,
19
+ EXCLUDED_PSEUDO_ELEMENTS,
20
+ PSEUDO_STATES
21
+ };
@@ -0,0 +1,3 @@
1
+ declare const _default: {};
2
+
3
+ export { _default as default };
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ default: () => src_default
24
+ });
25
+ module.exports = __toCommonJS(src_exports);
26
+ if (module && module.hot && module.hot.decline) {
27
+ module.hot.decline();
28
+ }
29
+ var src_default = {};
30
+ // Annotate the CommonJS export names for ESM import in node:
31
+ 0 && (module.exports = {});
package/dist/index.mjs ADDED
@@ -0,0 +1,8 @@
1
+ // src/index.ts
2
+ if (module && module.hot && module.hot.decline) {
3
+ module.hot.decline();
4
+ }
5
+ var src_default = {};
6
+ export {
7
+ src_default as default
8
+ };
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
18
+ mod
19
+ ));
20
+
21
+ // src/manager.ts
22
+ var import_manager_api2 = require("@storybook/manager-api");
23
+
24
+ // src/constants.ts
25
+ var ADDON_ID = "storybook/pseudo-states";
26
+ var TOOL_ID = `${ADDON_ID}/tool`;
27
+ var PSEUDO_STATES = {
28
+ hover: "hover",
29
+ active: "active",
30
+ focusVisible: "focus-visible",
31
+ focusWithin: "focus-within",
32
+ focus: "focus",
33
+ visited: "visited",
34
+ link: "link",
35
+ target: "target"
36
+ };
37
+
38
+ // src/manager/PseudoStateTool.tsx
39
+ var import_react = __toESM(require("react"));
40
+ var import_components = require("@storybook/components");
41
+ var import_manager_api = require("@storybook/manager-api");
42
+ var import_theming = require("@storybook/theming");
43
+ var LinkTitle = import_theming.styled.span(({ active }) => ({
44
+ color: active ? import_theming.color.secondary : "inherit"
45
+ }));
46
+ var LinkIcon = (0, import_theming.styled)(import_components.Icons)(({ active }) => ({
47
+ opacity: active ? 1 : 0,
48
+ path: { fill: active ? import_theming.color.secondary : "inherit" }
49
+ }));
50
+ var options = Object.keys(PSEUDO_STATES).sort();
51
+ var PseudoStateTool = () => {
52
+ const [{ pseudo }, updateGlobals] = (0, import_manager_api.useGlobals)();
53
+ const isActive = (0, import_react.useCallback)((option) => pseudo?.[option] === true, [pseudo]);
54
+ const toggleOption = (0, import_react.useCallback)(
55
+ (option) => () => updateGlobals({ pseudo: { ...pseudo, [option]: !isActive(option) } }),
56
+ [pseudo]
57
+ );
58
+ return /* @__PURE__ */ import_react.default.createElement(
59
+ import_components.WithTooltip,
60
+ {
61
+ placement: "top",
62
+ trigger: "click",
63
+ tooltip: () => /* @__PURE__ */ import_react.default.createElement(
64
+ import_components.TooltipLinkList,
65
+ {
66
+ links: options.map((option) => ({
67
+ id: option,
68
+ title: /* @__PURE__ */ import_react.default.createElement(LinkTitle, { active: isActive(option) }, ":", PSEUDO_STATES[option]),
69
+ right: /* @__PURE__ */ import_react.default.createElement(LinkIcon, { icon: "check", width: 12, height: 12, active: isActive(option) }),
70
+ onClick: toggleOption(option),
71
+ active: isActive(option)
72
+ }))
73
+ }
74
+ )
75
+ },
76
+ /* @__PURE__ */ import_react.default.createElement(
77
+ import_components.IconButton,
78
+ {
79
+ key: "pseudo-state",
80
+ title: "Select CSS pseudo states",
81
+ active: options.some(isActive)
82
+ },
83
+ /* @__PURE__ */ import_react.default.createElement(import_components.Icons, { icon: "button" })
84
+ )
85
+ );
86
+ };
87
+
88
+ // src/manager.ts
89
+ import_manager_api2.addons.register(ADDON_ID, () => {
90
+ import_manager_api2.addons.add(TOOL_ID, {
91
+ type: import_manager_api2.types.TOOL,
92
+ title: "CSS pseudo states",
93
+ match: ({ viewMode }) => viewMode === "story",
94
+ render: PseudoStateTool
95
+ });
96
+ });
@@ -0,0 +1,68 @@
1
+ import {
2
+ ADDON_ID,
3
+ PSEUDO_STATES,
4
+ TOOL_ID
5
+ } from "./chunk-A7FPDXSC.mjs";
6
+
7
+ // src/manager.ts
8
+ import { addons, types } from "@storybook/manager-api";
9
+
10
+ // src/manager/PseudoStateTool.tsx
11
+ import React, { useCallback } from "react";
12
+ import { Icons, IconButton, WithTooltip, TooltipLinkList } from "@storybook/components";
13
+ import { useGlobals } from "@storybook/manager-api";
14
+ import { styled, color } from "@storybook/theming";
15
+ var LinkTitle = styled.span(({ active }) => ({
16
+ color: active ? color.secondary : "inherit"
17
+ }));
18
+ var LinkIcon = styled(Icons)(({ active }) => ({
19
+ opacity: active ? 1 : 0,
20
+ path: { fill: active ? color.secondary : "inherit" }
21
+ }));
22
+ var options = Object.keys(PSEUDO_STATES).sort();
23
+ var PseudoStateTool = () => {
24
+ const [{ pseudo }, updateGlobals] = useGlobals();
25
+ const isActive = useCallback((option) => pseudo?.[option] === true, [pseudo]);
26
+ const toggleOption = useCallback(
27
+ (option) => () => updateGlobals({ pseudo: { ...pseudo, [option]: !isActive(option) } }),
28
+ [pseudo]
29
+ );
30
+ return /* @__PURE__ */ React.createElement(
31
+ WithTooltip,
32
+ {
33
+ placement: "top",
34
+ trigger: "click",
35
+ tooltip: () => /* @__PURE__ */ React.createElement(
36
+ TooltipLinkList,
37
+ {
38
+ links: options.map((option) => ({
39
+ id: option,
40
+ title: /* @__PURE__ */ React.createElement(LinkTitle, { active: isActive(option) }, ":", PSEUDO_STATES[option]),
41
+ right: /* @__PURE__ */ React.createElement(LinkIcon, { icon: "check", width: 12, height: 12, active: isActive(option) }),
42
+ onClick: toggleOption(option),
43
+ active: isActive(option)
44
+ }))
45
+ }
46
+ )
47
+ },
48
+ /* @__PURE__ */ React.createElement(
49
+ IconButton,
50
+ {
51
+ key: "pseudo-state",
52
+ title: "Select CSS pseudo states",
53
+ active: options.some(isActive)
54
+ },
55
+ /* @__PURE__ */ React.createElement(Icons, { icon: "button" })
56
+ )
57
+ );
58
+ };
59
+
60
+ // src/manager.ts
61
+ addons.register(ADDON_ID, () => {
62
+ addons.add(TOOL_ID, {
63
+ type: types.TOOL,
64
+ title: "CSS pseudo states",
65
+ match: ({ viewMode }) => viewMode === "story",
66
+ render: PseudoStateTool
67
+ });
68
+ });
@@ -0,0 +1,5 @@
1
+ import * as _storybook_types from '@storybook/types';
2
+
3
+ declare const decorators: _storybook_types.DecoratorFunction<_storybook_types.Renderer, _storybook_types.Args>[];
4
+
5
+ export { decorators };
@@ -0,0 +1,240 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/preview.ts
21
+ var preview_exports = {};
22
+ __export(preview_exports, {
23
+ decorators: () => decorators
24
+ });
25
+ module.exports = __toCommonJS(preview_exports);
26
+
27
+ // src/preview/withPseudoState.ts
28
+ var import_core_events = require("@storybook/core-events");
29
+ var import_preview_api = require("@storybook/preview-api");
30
+
31
+ // src/constants.ts
32
+ var ADDON_ID = "storybook/pseudo-states";
33
+ var TOOL_ID = `${ADDON_ID}/tool`;
34
+ var EXCLUDED_PSEUDO_ELEMENTS = ["::-webkit-scrollbar-thumb"];
35
+ var PSEUDO_STATES = {
36
+ hover: "hover",
37
+ active: "active",
38
+ focusVisible: "focus-visible",
39
+ focusWithin: "focus-within",
40
+ focus: "focus",
41
+ visited: "visited",
42
+ link: "link",
43
+ target: "target"
44
+ };
45
+
46
+ // src/preview/splitSelectors.ts
47
+ var isAtRule = (selector) => selector.indexOf("@") === 0;
48
+ var splitSelectors = (selectors) => {
49
+ if (isAtRule(selectors))
50
+ return [selectors];
51
+ let result = [];
52
+ let parentheses = 0;
53
+ let brackets = 0;
54
+ let selector = "";
55
+ for (let i = 0, len = selectors.length; i < len; i++) {
56
+ const char = selectors[i];
57
+ if (char === "(") {
58
+ parentheses += 1;
59
+ } else if (char === ")") {
60
+ parentheses -= 1;
61
+ } else if (char === "[") {
62
+ brackets += 1;
63
+ } else if (char === "]") {
64
+ brackets -= 1;
65
+ } else if (char === ",") {
66
+ if (!parentheses && !brackets) {
67
+ result.push(selector.trim());
68
+ selector = "";
69
+ continue;
70
+ }
71
+ }
72
+ selector += char;
73
+ }
74
+ result.push(selector.trim());
75
+ return result;
76
+ };
77
+
78
+ // src/preview/rewriteStyleSheet.ts
79
+ var pseudoStates = Object.values(PSEUDO_STATES);
80
+ var matchOne = new RegExp(`:(${pseudoStates.join("|")})`);
81
+ var matchAll = new RegExp(`:(${pseudoStates.join("|")})`, "g");
82
+ var warnings = /* @__PURE__ */ new Set();
83
+ var warnOnce = (message) => {
84
+ if (warnings.has(message))
85
+ return;
86
+ console.warn(message);
87
+ warnings.add(message);
88
+ };
89
+ var isExcludedPseudoElement = (selector, pseudoState) => EXCLUDED_PSEUDO_ELEMENTS.some((element) => selector.endsWith(`${element}:${pseudoState}`));
90
+ var rewriteRule = ({ cssText, selectorText }, shadowRoot) => {
91
+ return cssText.replace(
92
+ selectorText,
93
+ splitSelectors(selectorText).flatMap((selector) => {
94
+ if (selector.includes(".pseudo-")) {
95
+ return [];
96
+ }
97
+ if (!matchOne.test(selector)) {
98
+ return [selector];
99
+ }
100
+ const states = [];
101
+ const plainSelector = selector.replace(matchAll, (_, state) => {
102
+ states.push(state);
103
+ return "";
104
+ });
105
+ const classSelector = states.reduce((acc, state) => {
106
+ if (isExcludedPseudoElement(selector, state))
107
+ return "";
108
+ return acc.replace(new RegExp(`(?<!Y):${state}`, "g"), `.pseudo-${state}`);
109
+ }, selector);
110
+ if (selector.startsWith(":host(") || selector.startsWith("::slotted(")) {
111
+ return [selector, classSelector].filter(Boolean);
112
+ }
113
+ const ancestorSelector = shadowRoot ? `:host(${states.map((s) => `.pseudo-${s}`).join("")}) ${plainSelector}` : `${states.map((s) => `.pseudo-${s}`).join("")} ${plainSelector}`;
114
+ return [selector, classSelector, ancestorSelector].filter(
115
+ (selector2) => selector2 && !selector2.includes(":not()")
116
+ );
117
+ }).join(", ")
118
+ );
119
+ };
120
+ var rewriteStyleSheet = (sheet, shadowRoot, shadowHosts2) => {
121
+ if (sheet.__pseudoStatesRewritten)
122
+ return;
123
+ sheet.__pseudoStatesRewritten = true;
124
+ try {
125
+ let index = 0;
126
+ for (const cssRule of sheet.cssRules) {
127
+ if (!("selectorText" in cssRule))
128
+ continue;
129
+ const styleRule = cssRule;
130
+ if (matchOne.test(styleRule.selectorText)) {
131
+ const newRule = rewriteRule(styleRule, shadowRoot);
132
+ sheet.deleteRule(index);
133
+ sheet.insertRule(newRule, index);
134
+ if (shadowRoot && shadowHosts2)
135
+ shadowHosts2.add(shadowRoot.host);
136
+ }
137
+ index++;
138
+ if (index > 1e3) {
139
+ warnOnce("Reached maximum of 1000 pseudo selectors per sheet, skipping the rest.");
140
+ break;
141
+ }
142
+ }
143
+ } catch (e) {
144
+ if (String(e).includes("cssRules")) {
145
+ warnOnce(`Can't access cssRules, likely due to CORS restrictions: ${sheet.href}`);
146
+ } else {
147
+ console.error(e, sheet.href);
148
+ }
149
+ }
150
+ };
151
+
152
+ // src/preview/withPseudoState.ts
153
+ var channel = import_preview_api.addons.getChannel();
154
+ var shadowHosts = /* @__PURE__ */ new Set();
155
+ var applyClasses = (element, classnames) => {
156
+ Object.values(PSEUDO_STATES).forEach((state) => element.classList.remove(`pseudo-${state}`));
157
+ classnames.forEach((classname) => element.classList.add(classname));
158
+ };
159
+ var applyParameter = (rootElement, parameter) => {
160
+ const map = /* @__PURE__ */ new Map([[rootElement, /* @__PURE__ */ new Set()]]);
161
+ const add = (target, state) => map.set(target, /* @__PURE__ */ new Set([...map.get(target) || [], state]));
162
+ Object.entries(parameter || {}).forEach(([state, value]) => {
163
+ if (typeof value === "boolean") {
164
+ if (value)
165
+ add(rootElement, state);
166
+ } else if (typeof value === "string") {
167
+ rootElement.querySelectorAll(value).forEach((el) => add(el, state));
168
+ } else if (Array.isArray(value)) {
169
+ value.forEach((sel) => rootElement.querySelectorAll(sel).forEach((el) => add(el, state)));
170
+ }
171
+ });
172
+ map.forEach((states, target) => {
173
+ const classnames = /* @__PURE__ */ new Set();
174
+ states.forEach((key) => PSEUDO_STATES[key] && classnames.add(`pseudo-${PSEUDO_STATES[key]}`));
175
+ applyClasses(target, classnames);
176
+ });
177
+ };
178
+ var updateShadowHost = (shadowHost) => {
179
+ const classnames = /* @__PURE__ */ new Set();
180
+ for (let element = shadowHost.parentElement; element; element = element.parentElement) {
181
+ if (!element.className)
182
+ continue;
183
+ element.className.split(" ").filter((classname) => classname.indexOf("pseudo-") === 0).forEach((classname) => classnames.add(classname));
184
+ }
185
+ applyClasses(shadowHost, classnames);
186
+ };
187
+ var withPseudoState = (StoryFn, { viewMode, parameters, id, globals: globalsArgs }) => {
188
+ const { pseudo: parameter } = parameters;
189
+ const { pseudo: globals } = globalsArgs;
190
+ const canvasElement = (0, import_preview_api.useMemo)(() => {
191
+ if (viewMode === "docs") {
192
+ return document.getElementById(`story--${id}`);
193
+ }
194
+ return document.getElementById("storybook-root") || document.getElementById("root");
195
+ }, [viewMode, id]);
196
+ (0, import_preview_api.useEffect)(() => {
197
+ if (parameter !== globals && viewMode === "story") {
198
+ channel.emit(import_core_events.UPDATE_GLOBALS, {
199
+ globals: { pseudo: parameter }
200
+ });
201
+ }
202
+ }, [parameter, viewMode]);
203
+ (0, import_preview_api.useEffect)(() => {
204
+ if (!canvasElement)
205
+ return;
206
+ const timeout = setTimeout(() => {
207
+ applyParameter(canvasElement, globals || parameter);
208
+ shadowHosts.forEach(updateShadowHost);
209
+ }, 0);
210
+ return () => clearTimeout(timeout);
211
+ }, [canvasElement, globals, parameter]);
212
+ return StoryFn();
213
+ };
214
+ var rewriteStyleSheets = (shadowRoot) => {
215
+ let styleSheets = Array.from(shadowRoot ? shadowRoot.styleSheets : document.styleSheets);
216
+ if (shadowRoot?.adoptedStyleSheets?.length)
217
+ styleSheets = shadowRoot.adoptedStyleSheets;
218
+ styleSheets.forEach((sheet) => rewriteStyleSheet(sheet, shadowRoot, shadowHosts));
219
+ };
220
+ channel.on(import_core_events.STORY_CHANGED, () => shadowHosts.clear());
221
+ channel.on(import_core_events.STORY_RENDERED, () => rewriteStyleSheets());
222
+ channel.on(import_core_events.DOCS_RENDERED, () => rewriteStyleSheets());
223
+ if (Element.prototype.attachShadow) {
224
+ Element.prototype._attachShadow = Element.prototype.attachShadow;
225
+ Element.prototype.attachShadow = function attachShadow(init) {
226
+ const shadowRoot = this._attachShadow({ ...init, mode: "open" });
227
+ requestAnimationFrame(() => {
228
+ rewriteStyleSheets(shadowRoot);
229
+ updateShadowHost(shadowRoot.host);
230
+ });
231
+ return shadowRoot;
232
+ };
233
+ }
234
+
235
+ // src/preview.ts
236
+ var decorators = [withPseudoState];
237
+ // Annotate the CommonJS export names for ESM import in node:
238
+ 0 && (module.exports = {
239
+ decorators
240
+ });