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.
@@ -0,0 +1,208 @@
1
+ import {
2
+ EXCLUDED_PSEUDO_ELEMENTS,
3
+ PSEUDO_STATES
4
+ } from "./chunk-A7FPDXSC.mjs";
5
+
6
+ // src/preview/withPseudoState.ts
7
+ import {
8
+ DOCS_RENDERED,
9
+ STORY_CHANGED,
10
+ STORY_RENDERED,
11
+ UPDATE_GLOBALS
12
+ } from "@storybook/core-events";
13
+ import { addons, useEffect, useMemo } from "@storybook/preview-api";
14
+
15
+ // src/preview/splitSelectors.ts
16
+ var isAtRule = (selector) => selector.indexOf("@") === 0;
17
+ var splitSelectors = (selectors) => {
18
+ if (isAtRule(selectors))
19
+ return [selectors];
20
+ let result = [];
21
+ let parentheses = 0;
22
+ let brackets = 0;
23
+ let selector = "";
24
+ for (let i = 0, len = selectors.length; i < len; i++) {
25
+ const char = selectors[i];
26
+ if (char === "(") {
27
+ parentheses += 1;
28
+ } else if (char === ")") {
29
+ parentheses -= 1;
30
+ } else if (char === "[") {
31
+ brackets += 1;
32
+ } else if (char === "]") {
33
+ brackets -= 1;
34
+ } else if (char === ",") {
35
+ if (!parentheses && !brackets) {
36
+ result.push(selector.trim());
37
+ selector = "";
38
+ continue;
39
+ }
40
+ }
41
+ selector += char;
42
+ }
43
+ result.push(selector.trim());
44
+ return result;
45
+ };
46
+
47
+ // src/preview/rewriteStyleSheet.ts
48
+ var pseudoStates = Object.values(PSEUDO_STATES);
49
+ var matchOne = new RegExp(`:(${pseudoStates.join("|")})`);
50
+ var matchAll = new RegExp(`:(${pseudoStates.join("|")})`, "g");
51
+ var warnings = /* @__PURE__ */ new Set();
52
+ var warnOnce = (message) => {
53
+ if (warnings.has(message))
54
+ return;
55
+ console.warn(message);
56
+ warnings.add(message);
57
+ };
58
+ var isExcludedPseudoElement = (selector, pseudoState) => EXCLUDED_PSEUDO_ELEMENTS.some((element) => selector.endsWith(`${element}:${pseudoState}`));
59
+ var rewriteRule = ({ cssText, selectorText }, shadowRoot) => {
60
+ return cssText.replace(
61
+ selectorText,
62
+ splitSelectors(selectorText).flatMap((selector) => {
63
+ if (selector.includes(".pseudo-")) {
64
+ return [];
65
+ }
66
+ if (!matchOne.test(selector)) {
67
+ return [selector];
68
+ }
69
+ const states = [];
70
+ const plainSelector = selector.replace(matchAll, (_, state) => {
71
+ states.push(state);
72
+ return "";
73
+ });
74
+ const classSelector = states.reduce((acc, state) => {
75
+ if (isExcludedPseudoElement(selector, state))
76
+ return "";
77
+ return acc.replace(new RegExp(`(?<!Y):${state}`, "g"), `.pseudo-${state}`);
78
+ }, selector);
79
+ if (selector.startsWith(":host(") || selector.startsWith("::slotted(")) {
80
+ return [selector, classSelector].filter(Boolean);
81
+ }
82
+ const ancestorSelector = shadowRoot ? `:host(${states.map((s) => `.pseudo-${s}`).join("")}) ${plainSelector}` : `${states.map((s) => `.pseudo-${s}`).join("")} ${plainSelector}`;
83
+ return [selector, classSelector, ancestorSelector].filter(
84
+ (selector2) => selector2 && !selector2.includes(":not()")
85
+ );
86
+ }).join(", ")
87
+ );
88
+ };
89
+ var rewriteStyleSheet = (sheet, shadowRoot, shadowHosts2) => {
90
+ if (sheet.__pseudoStatesRewritten)
91
+ return;
92
+ sheet.__pseudoStatesRewritten = true;
93
+ try {
94
+ let index = 0;
95
+ for (const cssRule of sheet.cssRules) {
96
+ if (!("selectorText" in cssRule))
97
+ continue;
98
+ const styleRule = cssRule;
99
+ if (matchOne.test(styleRule.selectorText)) {
100
+ const newRule = rewriteRule(styleRule, shadowRoot);
101
+ sheet.deleteRule(index);
102
+ sheet.insertRule(newRule, index);
103
+ if (shadowRoot && shadowHosts2)
104
+ shadowHosts2.add(shadowRoot.host);
105
+ }
106
+ index++;
107
+ if (index > 1e3) {
108
+ warnOnce("Reached maximum of 1000 pseudo selectors per sheet, skipping the rest.");
109
+ break;
110
+ }
111
+ }
112
+ } catch (e) {
113
+ if (String(e).includes("cssRules")) {
114
+ warnOnce(`Can't access cssRules, likely due to CORS restrictions: ${sheet.href}`);
115
+ } else {
116
+ console.error(e, sheet.href);
117
+ }
118
+ }
119
+ };
120
+
121
+ // src/preview/withPseudoState.ts
122
+ var channel = addons.getChannel();
123
+ var shadowHosts = /* @__PURE__ */ new Set();
124
+ var applyClasses = (element, classnames) => {
125
+ Object.values(PSEUDO_STATES).forEach((state) => element.classList.remove(`pseudo-${state}`));
126
+ classnames.forEach((classname) => element.classList.add(classname));
127
+ };
128
+ var applyParameter = (rootElement, parameter) => {
129
+ const map = /* @__PURE__ */ new Map([[rootElement, /* @__PURE__ */ new Set()]]);
130
+ const add = (target, state) => map.set(target, /* @__PURE__ */ new Set([...map.get(target) || [], state]));
131
+ Object.entries(parameter || {}).forEach(([state, value]) => {
132
+ if (typeof value === "boolean") {
133
+ if (value)
134
+ add(rootElement, state);
135
+ } else if (typeof value === "string") {
136
+ rootElement.querySelectorAll(value).forEach((el) => add(el, state));
137
+ } else if (Array.isArray(value)) {
138
+ value.forEach((sel) => rootElement.querySelectorAll(sel).forEach((el) => add(el, state)));
139
+ }
140
+ });
141
+ map.forEach((states, target) => {
142
+ const classnames = /* @__PURE__ */ new Set();
143
+ states.forEach((key) => PSEUDO_STATES[key] && classnames.add(`pseudo-${PSEUDO_STATES[key]}`));
144
+ applyClasses(target, classnames);
145
+ });
146
+ };
147
+ var updateShadowHost = (shadowHost) => {
148
+ const classnames = /* @__PURE__ */ new Set();
149
+ for (let element = shadowHost.parentElement; element; element = element.parentElement) {
150
+ if (!element.className)
151
+ continue;
152
+ element.className.split(" ").filter((classname) => classname.indexOf("pseudo-") === 0).forEach((classname) => classnames.add(classname));
153
+ }
154
+ applyClasses(shadowHost, classnames);
155
+ };
156
+ var withPseudoState = (StoryFn, { viewMode, parameters, id, globals: globalsArgs }) => {
157
+ const { pseudo: parameter } = parameters;
158
+ const { pseudo: globals } = globalsArgs;
159
+ const canvasElement = useMemo(() => {
160
+ if (viewMode === "docs") {
161
+ return document.getElementById(`story--${id}`);
162
+ }
163
+ return document.getElementById("storybook-root") || document.getElementById("root");
164
+ }, [viewMode, id]);
165
+ useEffect(() => {
166
+ if (parameter !== globals && viewMode === "story") {
167
+ channel.emit(UPDATE_GLOBALS, {
168
+ globals: { pseudo: parameter }
169
+ });
170
+ }
171
+ }, [parameter, viewMode]);
172
+ useEffect(() => {
173
+ if (!canvasElement)
174
+ return;
175
+ const timeout = setTimeout(() => {
176
+ applyParameter(canvasElement, globals || parameter);
177
+ shadowHosts.forEach(updateShadowHost);
178
+ }, 0);
179
+ return () => clearTimeout(timeout);
180
+ }, [canvasElement, globals, parameter]);
181
+ return StoryFn();
182
+ };
183
+ var rewriteStyleSheets = (shadowRoot) => {
184
+ let styleSheets = Array.from(shadowRoot ? shadowRoot.styleSheets : document.styleSheets);
185
+ if (shadowRoot?.adoptedStyleSheets?.length)
186
+ styleSheets = shadowRoot.adoptedStyleSheets;
187
+ styleSheets.forEach((sheet) => rewriteStyleSheet(sheet, shadowRoot, shadowHosts));
188
+ };
189
+ channel.on(STORY_CHANGED, () => shadowHosts.clear());
190
+ channel.on(STORY_RENDERED, () => rewriteStyleSheets());
191
+ channel.on(DOCS_RENDERED, () => rewriteStyleSheets());
192
+ if (Element.prototype.attachShadow) {
193
+ Element.prototype._attachShadow = Element.prototype.attachShadow;
194
+ Element.prototype.attachShadow = function attachShadow(init) {
195
+ const shadowRoot = this._attachShadow({ ...init, mode: "open" });
196
+ requestAnimationFrame(() => {
197
+ rewriteStyleSheets(shadowRoot);
198
+ updateShadowHost(shadowRoot.host);
199
+ });
200
+ return shadowRoot;
201
+ };
202
+ }
203
+
204
+ // src/preview.ts
205
+ var decorators = [withPseudoState];
206
+ export {
207
+ decorators
208
+ };
package/manager.js ADDED
@@ -0,0 +1 @@
1
+ import "./dist/manager.mjs"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storybook-addon-pseudo-states",
3
- "version": "1.15.2",
3
+ "version": "1.15.3",
4
4
  "description": "CSS pseudo states for Storybook",
5
5
  "keywords": [
6
6
  "storybook-addons",
@@ -14,21 +14,39 @@
14
14
  },
15
15
  "author": "ghengeveld",
16
16
  "license": "MIT",
17
- "main": "dist/cjs/preset.js",
18
- "module": "dist/esm/preset.js",
17
+ "main": "dist/index.js",
18
+ "module": "dist/index.mjs",
19
+ "types": "dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "require": "./dist/index.js",
23
+ "import": "./dist/index.mjs",
24
+ "types": "./dist/index.d.ts"
25
+ },
26
+ "./manager": {
27
+ "require": "./dist/manager.js",
28
+ "import": "./dist/manager.mjs",
29
+ "types": "./dist/manager.d.ts"
30
+ },
31
+ "./preview": {
32
+ "require": "./dist/preview.js",
33
+ "import": "./dist/preview.mjs",
34
+ "types": "./dist/preview.d.ts"
35
+ },
36
+ "./package.json": "./package.json"
37
+ },
19
38
  "files": [
20
- "dist/**/*",
21
- "README.md",
22
- "*.js"
39
+ "*.js",
40
+ "dist/**/*"
23
41
  ],
24
42
  "scripts": {
25
43
  "clean": "rimraf ./dist",
26
44
  "start": "concurrently \"yarn storybook --no-manager-cache --quiet\" \"yarn build:dist --watch\"",
27
- "storybook": "start-storybook -p 6006",
45
+ "storybook": "storybook dev -p 6006",
28
46
  "test": "jest src",
29
- "chromatic": "chromatic",
30
- "build:dist": "babel ./src --out-dir ./dist/cjs && BABEL_ESM=\"true\" babel ./src --out-dir ./dist/esm",
31
- "build:storybook": "build-storybook",
47
+ "chromatic": "npx chromatic",
48
+ "build:dist": "tsup",
49
+ "build:storybook": "storybook build",
32
50
  "prepublish": "yarn clean && yarn build:dist",
33
51
  "release": "auto shipit --base-branch=main"
34
52
  },
@@ -38,25 +56,32 @@
38
56
  "@babel/core": "^7.20.5",
39
57
  "@babel/preset-env": "^7.20.2",
40
58
  "@babel/preset-react": "^7.18.6",
41
- "@storybook/addon-docs": "^6.5.14",
42
- "@storybook/builder-webpack5": "^6.5.14",
43
- "@storybook/manager-webpack5": "^6.5.14",
44
- "@storybook/react": "^6.5.14",
59
+ "@babel/preset-typescript": "^7.18.6",
60
+ "@storybook/addon-essentials": "^7.0.0-beta.3",
61
+ "@storybook/addon-interactions": "^7.0.0-beta.3",
62
+ "@storybook/addon-links": "^7.0.0-beta.3",
63
+ "@storybook/react": "^7.0.0-beta.3",
64
+ "@storybook/react-webpack5": "^7.0.0-beta.3",
65
+ "@storybook/testing-library": "^0.0.13",
66
+ "@storybook/types": "^7.0.0-beta.3",
67
+ "@types/jest": "^29.2.4",
45
68
  "auto": "^10.16.8",
46
69
  "babel-loader": "^9.1.0",
47
- "chromatic": "^6.12.0",
48
70
  "concurrently": "^5.3.0",
49
71
  "jest": "^27.5.1",
50
72
  "react": "^17.0.1",
51
73
  "react-dom": "^17.0.1",
52
- "rimraf": "^3.0.2"
74
+ "rimraf": "^3.0.2",
75
+ "storybook": "^7.0.0-beta.3",
76
+ "tsup": "^6.5.0",
77
+ "typescript": "^4.9.4"
53
78
  },
54
79
  "peerDependencies": {
55
- "@storybook/addons": "^6.5.0",
56
- "@storybook/api": "^6.5.0",
57
- "@storybook/components": "^6.5.0",
58
- "@storybook/core-events": "^6.5.0",
59
- "@storybook/theming": "^6.5.0",
80
+ "@storybook/components": "next",
81
+ "@storybook/core-events": "next",
82
+ "@storybook/manager-api": "next",
83
+ "@storybook/preview-api": "next",
84
+ "@storybook/theming": "next",
60
85
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
61
86
  "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
62
87
  },
package/preview.js ADDED
@@ -0,0 +1 @@
1
+ export * from "./dist/preview.mjs"
@@ -1,72 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.PseudoStateTool = void 0;
7
- var _react = _interopRequireWildcard(require("react"));
8
- var _api = require("@storybook/api");
9
- var _components = require("@storybook/components");
10
- var _theming = require("@storybook/theming");
11
- var _constants = require("./constants");
12
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
14
- const LinkTitle = _theming.styled.span(_ref => {
15
- let {
16
- active
17
- } = _ref;
18
- return {
19
- color: active ? _theming.color.secondary : "inherit"
20
- };
21
- });
22
- const LinkIcon = (0, _theming.styled)(_components.Icons)(_ref2 => {
23
- let {
24
- active
25
- } = _ref2;
26
- return {
27
- opacity: active ? 1 : 0,
28
- path: {
29
- fill: active ? _theming.color.secondary : "inherit"
30
- }
31
- };
32
- });
33
- const options = Object.keys(_constants.PSEUDO_STATES).sort();
34
- const PseudoStateTool = () => {
35
- const [{
36
- pseudo
37
- }, updateGlobals] = (0, _api.useGlobals)();
38
- const isActive = (0, _react.useCallback)(option => pseudo?.[option] === true, [pseudo]);
39
- const toggleOption = (0, _react.useCallback)(option => () => updateGlobals({
40
- pseudo: {
41
- ...pseudo,
42
- [option]: !isActive(option)
43
- }
44
- }), [pseudo]);
45
- return /*#__PURE__*/_react.default.createElement(_components.WithTooltip, {
46
- placement: "top",
47
- trigger: "click",
48
- tooltip: () => /*#__PURE__*/_react.default.createElement(_components.TooltipLinkList, {
49
- links: options.map(option => ({
50
- id: option,
51
- title: /*#__PURE__*/_react.default.createElement(LinkTitle, {
52
- active: isActive(option)
53
- }, ":", _constants.PSEUDO_STATES[option]),
54
- right: /*#__PURE__*/_react.default.createElement(LinkIcon, {
55
- icon: "check",
56
- width: 12,
57
- height: 12,
58
- active: isActive(option)
59
- }),
60
- onClick: toggleOption(option),
61
- active: isActive(option)
62
- }))
63
- })
64
- }, /*#__PURE__*/_react.default.createElement(_components.IconButton, {
65
- key: "pseudo-state",
66
- title: "Select CSS pseudo states",
67
- active: options.some(isActive)
68
- }, /*#__PURE__*/_react.default.createElement(_components.Icons, {
69
- icon: "button"
70
- })));
71
- };
72
- exports.PseudoStateTool = PseudoStateTool;
@@ -1,30 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.TOOL_ID = exports.PSEUDO_STATES = exports.EXCLUDED_PSEUDO_ELEMENTS = exports.ADDON_ID = void 0;
7
- const ADDON_ID = "storybook/pseudo-states";
8
- exports.ADDON_ID = ADDON_ID;
9
- const TOOL_ID = `${ADDON_ID}/tool`;
10
-
11
- // Pseudo-elements which are not allowed to have classes applied on them
12
- // E.g. ::-webkit-scrollbar-thumb.pseudo-hover is not a valid selector
13
- exports.TOOL_ID = TOOL_ID;
14
- const EXCLUDED_PSEUDO_ELEMENTS = ["::-webkit-scrollbar-thumb"];
15
-
16
- // Dynamic pseudo-classes
17
- // @see https://www.w3.org/TR/2018/REC-selectors-3-20181106/#dynamic-pseudos
18
- exports.EXCLUDED_PSEUDO_ELEMENTS = EXCLUDED_PSEUDO_ELEMENTS;
19
- const PSEUDO_STATES = {
20
- hover: "hover",
21
- active: "active",
22
- focusVisible: "focus-visible",
23
- focusWithin: "focus-within",
24
- focus: "focus",
25
- // must come after its alternatives
26
- visited: "visited",
27
- link: "link",
28
- target: "target"
29
- };
30
- exports.PSEUDO_STATES = PSEUDO_STATES;
@@ -1,18 +0,0 @@
1
- "use strict";
2
-
3
- var _addons = require("@storybook/addons");
4
- var _constants = require("../constants");
5
- var _PseudoStateTool = require("../PseudoStateTool");
6
- _addons.addons.register(_constants.ADDON_ID, () => {
7
- _addons.addons.add(_constants.TOOL_ID, {
8
- type: _addons.types.TOOL,
9
- title: "CSS pseudo states",
10
- match: _ref => {
11
- let {
12
- viewMode
13
- } = _ref;
14
- return viewMode === "story";
15
- },
16
- render: _PseudoStateTool.PseudoStateTool
17
- });
18
- });
@@ -1,9 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.decorators = void 0;
7
- var _withPseudoState = require("../withPseudoState");
8
- const decorators = [_withPseudoState.withPseudoState];
9
- exports.decorators = decorators;
@@ -1,74 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.rewriteStyleSheet = void 0;
7
- var _constants = require("./constants");
8
- var _splitSelectors = require("./splitSelectors");
9
- const pseudoStates = Object.values(_constants.PSEUDO_STATES);
10
- const matchOne = new RegExp(`:(${pseudoStates.join("|")})`);
11
- const matchAll = new RegExp(`:(${pseudoStates.join("|")})`, "g");
12
- const warnings = new Set();
13
- const warnOnce = message => {
14
- if (warnings.has(message)) return;
15
- // eslint-disable-next-line no-console
16
- console.warn(message);
17
- warnings.add(message);
18
- };
19
- const isExcludedPseudoElement = (selector, pseudoState) => _constants.EXCLUDED_PSEUDO_ELEMENTS.some(element => selector.endsWith(`${element}:${pseudoState}`));
20
- const rewriteRule = (cssText, selectorText, shadowRoot) => {
21
- return cssText.replace(selectorText, (0, _splitSelectors.splitSelectors)(selectorText).flatMap(selector => {
22
- if (selector.includes(".pseudo-")) {
23
- return [];
24
- }
25
- if (!matchOne.test(selector)) {
26
- return [selector];
27
- }
28
- const states = [];
29
- const plainSelector = selector.replace(matchAll, (_, state) => {
30
- states.push(state);
31
- return "";
32
- });
33
- const classSelector = states.reduce((acc, state) => !isExcludedPseudoElement(selector, state) && acc.replace(new RegExp(`(?<!Y):${state}`, "g"), `.pseudo-${state}`), selector);
34
- if (selector.startsWith(":host(") || selector.startsWith("::slotted(")) {
35
- return [selector, classSelector].filter(Boolean);
36
- }
37
- const ancestorSelector = shadowRoot ? `:host(${states.map(s => `.pseudo-${s}`).join("")}) ${plainSelector}` : `${states.map(s => `.pseudo-${s}`).join("")} ${plainSelector}`;
38
- return [selector, classSelector, ancestorSelector].filter(selector => selector && !selector.includes(":not()"));
39
- }).join(", "));
40
- };
41
-
42
- // Rewrites the style sheet to add alternative selectors for any rule that targets a pseudo state.
43
- // A sheet can only be rewritten once, and may carry over between stories.
44
- const rewriteStyleSheet = (sheet, shadowRoot, shadowHosts) => {
45
- if (sheet.__pseudoStatesRewritten) return;
46
- sheet.__pseudoStatesRewritten = true;
47
- try {
48
- let index = 0;
49
- for (const {
50
- cssText,
51
- selectorText
52
- } of sheet.cssRules) {
53
- if (matchOne.test(selectorText)) {
54
- const newRule = rewriteRule(cssText, selectorText, shadowRoot);
55
- sheet.deleteRule(index);
56
- sheet.insertRule(newRule, index);
57
- if (shadowRoot) shadowHosts.add(shadowRoot.host);
58
- }
59
- index++;
60
- if (index > 1000) {
61
- warnOnce("Reached maximum of 1000 pseudo selectors per sheet, skipping the rest.");
62
- break;
63
- }
64
- }
65
- } catch (e) {
66
- if (e.toString().includes("cssRules")) {
67
- warnOnce(`Can't access cssRules, likely due to CORS restrictions: ${sheet.href}`);
68
- } else {
69
- // eslint-disable-next-line no-console
70
- console.error(e, sheet.href);
71
- }
72
- }
73
- };
74
- exports.rewriteStyleSheet = rewriteStyleSheet;
@@ -1,69 +0,0 @@
1
- "use strict";
2
-
3
- var _rewriteStyleSheet = require("./rewriteStyleSheet");
4
- class Sheet {
5
- constructor() {
6
- this.__pseudoStatesRewritten = false;
7
- for (var _len = arguments.length, rules = new Array(_len), _key = 0; _key < _len; _key++) {
8
- rules[_key] = arguments[_key];
9
- }
10
- this.cssRules = rules.map(cssText => ({
11
- cssText,
12
- selectorText: cssText.slice(0, cssText.indexOf(" {"))
13
- }));
14
- }
15
- deleteRule(index) {
16
- this.cssRules.splice(index, 1);
17
- }
18
- insertRule(cssText, index) {
19
- this.cssRules.splice(index, 0, cssText);
20
- }
21
- }
22
- describe("rewriteStyleSheet", () => {
23
- it("adds alternative selector targeting the element directly", () => {
24
- const sheet = new Sheet("a:hover { color: red }");
25
- (0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
26
- expect(sheet.cssRules[0]).toContain("a.pseudo-hover");
27
- });
28
- it("adds alternative selector targeting an ancestor", () => {
29
- const sheet = new Sheet("a:hover { color: red }");
30
- (0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
31
- expect(sheet.cssRules[0]).toContain(".pseudo-hover a");
32
- });
33
- it("does not add .pseudo-<class> to pseudo-class, which does not support classes", () => {
34
- const sheet = new Sheet("::-webkit-scrollbar-thumb:hover { border-color: transparent; }");
35
- (0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
36
- console.log(sheet.cssRules[0]);
37
- expect(sheet.cssRules[0]).not.toContain("::-webkit-scrollbar-thumb.pseudo-hover");
38
- });
39
- it("adds alternative selector for each pseudo selector", () => {
40
- const sheet = new Sheet("a:hover, a:focus { color: red }");
41
- (0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
42
- expect(sheet.cssRules[0]).toContain("a.pseudo-hover");
43
- expect(sheet.cssRules[0]).toContain("a.pseudo-focus");
44
- expect(sheet.cssRules[0]).toContain(".pseudo-hover a");
45
- expect(sheet.cssRules[0]).toContain(".pseudo-focus a");
46
- });
47
- it("keeps non-pseudo selectors as-is", () => {
48
- const sheet = new Sheet("a.class, a:hover, a:focus, a#id { color: red }");
49
- (0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
50
- expect(sheet.cssRules[0]).toContain("a.class");
51
- expect(sheet.cssRules[0]).toContain("a#id");
52
- });
53
- it("supports combined pseudo selectors", () => {
54
- const sheet = new Sheet("a:hover:focus { color: red }");
55
- (0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
56
- expect(sheet.cssRules[0]).toContain("a.pseudo-hover.pseudo-focus");
57
- expect(sheet.cssRules[0]).toContain(".pseudo-hover.pseudo-focus a");
58
- });
59
- it('supports ":host"', () => {
60
- const sheet = new Sheet(":host(:hover) { color: red }");
61
- (0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
62
- expect(sheet.cssRules[0]).toEqual(":host(:hover), :host(.pseudo-hover) { color: red }");
63
- });
64
- it('supports ":not"', () => {
65
- const sheet = new Sheet(":not(:hover) { color: red }");
66
- (0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
67
- expect(sheet.cssRules[0]).toEqual(":not(:hover), :not(.pseudo-hover) { color: red }");
68
- });
69
- });
@@ -1,36 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.splitSelectors = void 0;
7
- const isAtRule = selector => selector.indexOf("@") === 0;
8
- const splitSelectors = selectors => {
9
- if (isAtRule(selectors)) return [selectors];
10
- let result = [];
11
- let parentheses = 0;
12
- let brackets = 0;
13
- let selector = "";
14
- for (let i = 0, len = selectors.length; i < len; i++) {
15
- const char = selectors[i];
16
- if (char === "(") {
17
- parentheses += 1;
18
- } else if (char === ")") {
19
- parentheses -= 1;
20
- } else if (char === "[") {
21
- brackets += 1;
22
- } else if (char === "]") {
23
- brackets -= 1;
24
- } else if (char === ",") {
25
- if (!parentheses && !brackets) {
26
- result.push(selector.trim());
27
- selector = "";
28
- continue;
29
- }
30
- }
31
- selector += char;
32
- }
33
- result.push(selector.trim());
34
- return result;
35
- };
36
- exports.splitSelectors = splitSelectors;
@@ -1,17 +0,0 @@
1
- "use strict";
2
-
3
- var _splitSelectors = require("./splitSelectors");
4
- describe("splitSelectors", () => {
5
- test("handles basic selectors", () => {
6
- expect((0, _splitSelectors.splitSelectors)(".a")).toEqual([".a"]);
7
- expect((0, _splitSelectors.splitSelectors)(".a, .b")).toEqual([".a", ".b"]);
8
- });
9
- test("supports ::slotted and :is", () => {
10
- expect((0, _splitSelectors.splitSelectors)("::slotted(:is(button, a):active)")).toEqual(["::slotted(:is(button, a):active)"]);
11
- expect((0, _splitSelectors.splitSelectors)("::slotted(:is(button, a):active), ::slotted(:is(button, a):hover)")).toEqual(["::slotted(:is(button, a):active)", "::slotted(:is(button, a):hover)"]);
12
- });
13
- test("supports :host", () => {
14
- expect((0, _splitSelectors.splitSelectors)(":host([type='secondary']) ::slotted(:is(button, a)), :host([type='primary']) ::slotted(:is(button, a):active)")).toEqual([":host([type='secondary']) ::slotted(:is(button, a))", ":host([type='primary']) ::slotted(:is(button, a):active)"]);
15
- expect((0, _splitSelectors.splitSelectors)(":host([outline]) ::slotted(:is(button, a):focus-within:focus-visible:not(:active))")).toEqual([":host([outline]) ::slotted(:is(button, a):focus-within:focus-visible:not(:active))"]);
16
- });
17
- });