storybook-addon-pseudo-states 1.14.1 → 1.15.0
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/CHANGELOG.md +14 -0
- package/README.md +24 -1
- package/dist/cjs/PseudoStateTool.js +8 -11
- package/dist/cjs/rewriteStyleSheet.js +111 -0
- package/dist/cjs/rewriteStyleSheet.test.js +85 -0
- package/dist/cjs/withPseudoState.js +58 -138
- package/dist/esm/PseudoStateTool.js +8 -11
- package/dist/esm/rewriteStyleSheet.js +100 -0
- package/dist/esm/rewriteStyleSheet.test.js +83 -0
- package/dist/esm/withPseudoState.js +56 -133
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# v1.15.0 (Thu Jun 16 2022)
|
|
2
|
+
|
|
3
|
+
#### 🚀 Enhancement
|
|
4
|
+
|
|
5
|
+
- Add support for targeting specific elements [#25](https://github.com/chromaui/storybook-addon-pseudo-states/pull/25) (sagiv.bengiat@appsflyer.com [@ghengeveld](https://github.com/ghengeveld) [@sag1v](https://github.com/sag1v))
|
|
6
|
+
|
|
7
|
+
#### Authors: 3
|
|
8
|
+
|
|
9
|
+
- Gert Hengeveld ([@ghengeveld](https://github.com/ghengeveld))
|
|
10
|
+
- Sagiv ben giat ([@sag1v](https://github.com/sag1v))
|
|
11
|
+
- sagiv.bengiat (sagiv.bengiat@appsflyer.com)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
1
15
|
# v1.14.1 (Wed Jun 15 2022)
|
|
2
16
|
|
|
3
17
|
#### ⚠️ Pushed to `main`
|
package/README.md
CHANGED
|
@@ -41,9 +41,32 @@ module.exports = {
|
|
|
41
41
|
|
|
42
42
|
You can have your stories automatically use a specific set of pseudo states, by setting the `pseudo` property on `parameters`:
|
|
43
43
|
|
|
44
|
-
```
|
|
44
|
+
```jsx
|
|
45
45
|
export const Hover = () => <Button>Label</Button>
|
|
46
46
|
Hover.parameters = { pseudo: { hover: true } }
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
This is what enables snapshot testing your pseudo states in [Chromatic](https://www.chromatic.com/).
|
|
50
|
+
|
|
51
|
+
### Targeting specific elements
|
|
52
|
+
|
|
53
|
+
If you don't want to force or toggle pseudo styles to all elements that use them, but rather only enable them on specific elements, you can set a string or array value instead of a boolean:
|
|
54
|
+
|
|
55
|
+
```jsx
|
|
56
|
+
export const Buttons = () => (
|
|
57
|
+
<>
|
|
58
|
+
<Button id="one">Hover</Button>
|
|
59
|
+
<Button id="two">Hover focus</Button>
|
|
60
|
+
<Button id="three">Hover focus active</Button>
|
|
61
|
+
</>
|
|
62
|
+
)
|
|
63
|
+
Buttons.parameters = {
|
|
64
|
+
pseudo: {
|
|
65
|
+
hover: ["#one", "#two", "#three"],
|
|
66
|
+
focus: ["#two", "#three"],
|
|
67
|
+
active: "#three",
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
This accepts a single CSS selector (string), or an array of CSS selectors on which to enable that pseudo style.
|
|
@@ -63,19 +63,16 @@ var PseudoStateTool = function PseudoStateTool() {
|
|
|
63
63
|
pseudo = _useGlobals2[0].pseudo,
|
|
64
64
|
updateGlobals = _useGlobals2[1];
|
|
65
65
|
|
|
66
|
-
var
|
|
67
|
-
return
|
|
68
|
-
}, [pseudo]);
|
|
69
|
-
var getValue = (0, _react.useCallback)(function (option) {
|
|
70
|
-
return pseudo ? pseudo[option] : false;
|
|
66
|
+
var isActive = (0, _react.useCallback)(function (option) {
|
|
67
|
+
return (pseudo === null || pseudo === void 0 ? void 0 : pseudo[option]) === true;
|
|
71
68
|
}, [pseudo]);
|
|
72
69
|
var toggleOption = (0, _react.useCallback)(function (option) {
|
|
73
70
|
return function () {
|
|
74
71
|
return updateGlobals({
|
|
75
|
-
pseudo: _objectSpread(_objectSpread({}, pseudo), {}, _defineProperty({}, option, !
|
|
72
|
+
pseudo: _objectSpread(_objectSpread({}, pseudo), {}, _defineProperty({}, option, !isActive(option)))
|
|
76
73
|
});
|
|
77
74
|
};
|
|
78
|
-
}, [pseudo
|
|
75
|
+
}, [pseudo]);
|
|
79
76
|
return /*#__PURE__*/_react.default.createElement(_components.WithTooltip, {
|
|
80
77
|
placement: "top",
|
|
81
78
|
trigger: "click",
|
|
@@ -85,16 +82,16 @@ var PseudoStateTool = function PseudoStateTool() {
|
|
|
85
82
|
return {
|
|
86
83
|
id: option,
|
|
87
84
|
title: /*#__PURE__*/_react.default.createElement(LinkTitle, {
|
|
88
|
-
active:
|
|
85
|
+
active: isActive(option)
|
|
89
86
|
}, ":", _constants.PSEUDO_STATES[option]),
|
|
90
87
|
right: /*#__PURE__*/_react.default.createElement(LinkIcon, {
|
|
91
88
|
icon: "check",
|
|
92
89
|
width: 12,
|
|
93
90
|
height: 12,
|
|
94
|
-
active:
|
|
91
|
+
active: isActive(option)
|
|
95
92
|
}),
|
|
96
93
|
onClick: toggleOption(option),
|
|
97
|
-
active:
|
|
94
|
+
active: isActive(option)
|
|
98
95
|
};
|
|
99
96
|
})
|
|
100
97
|
});
|
|
@@ -102,7 +99,7 @@ var PseudoStateTool = function PseudoStateTool() {
|
|
|
102
99
|
}, /*#__PURE__*/_react.default.createElement(_components.IconButton, {
|
|
103
100
|
key: "pseudo-state",
|
|
104
101
|
title: "Select CSS pseudo states",
|
|
105
|
-
active:
|
|
102
|
+
active: options.some(isActive)
|
|
106
103
|
}, /*#__PURE__*/_react.default.createElement(_components.Icons, {
|
|
107
104
|
icon: "button"
|
|
108
105
|
})));
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.rewriteStyleSheet = void 0;
|
|
7
|
+
|
|
8
|
+
var _constants = require("./constants");
|
|
9
|
+
|
|
10
|
+
var _splitSelectors = require("./splitSelectors");
|
|
11
|
+
|
|
12
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
13
|
+
|
|
14
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
15
|
+
|
|
16
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
17
|
+
|
|
18
|
+
var pseudoStates = Object.values(_constants.PSEUDO_STATES);
|
|
19
|
+
var matchOne = new RegExp(":(".concat(pseudoStates.join("|"), ")"));
|
|
20
|
+
var matchAll = new RegExp(":(".concat(pseudoStates.join("|"), ")"), "g");
|
|
21
|
+
var warnings = new Set();
|
|
22
|
+
|
|
23
|
+
var warnOnce = function warnOnce(message) {
|
|
24
|
+
if (warnings.has(message)) return; // eslint-disable-next-line no-console
|
|
25
|
+
|
|
26
|
+
console.warn(message);
|
|
27
|
+
warnings.add(message);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
var rewriteRule = function rewriteRule(cssText, selectorText, shadowRoot) {
|
|
31
|
+
return cssText.replace(selectorText, (0, _splitSelectors.splitSelectors)(selectorText).flatMap(function (selector) {
|
|
32
|
+
if (selector.includes(".pseudo-")) {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!matchOne.test(selector)) {
|
|
37
|
+
return [selector];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
var states = [];
|
|
41
|
+
var plainSelector = selector.replace(matchAll, function (_, state) {
|
|
42
|
+
states.push(state);
|
|
43
|
+
return "";
|
|
44
|
+
});
|
|
45
|
+
var classSelector = states.reduce(function (acc, state) {
|
|
46
|
+
return acc.replace(new RegExp(":".concat(state), "g"), ".pseudo-".concat(state));
|
|
47
|
+
}, selector);
|
|
48
|
+
|
|
49
|
+
if (selector.startsWith(":host(") || selector.startsWith("::slotted(")) {
|
|
50
|
+
return [selector, classSelector];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
var ancestorSelector = shadowRoot ? ":host(".concat(states.map(function (s) {
|
|
54
|
+
return ".pseudo-".concat(s);
|
|
55
|
+
}).join(""), ") ").concat(plainSelector) : "".concat(states.map(function (s) {
|
|
56
|
+
return ".pseudo-".concat(s);
|
|
57
|
+
}).join(""), " ").concat(plainSelector);
|
|
58
|
+
return [selector, classSelector, ancestorSelector].filter(function (selector) {
|
|
59
|
+
return !selector.includes(":not()");
|
|
60
|
+
});
|
|
61
|
+
}).join(", "));
|
|
62
|
+
}; // Rewrites the style sheet to add alternative selectors for any rule that targets a pseudo state.
|
|
63
|
+
// A sheet can only be rewritten once, and may carry over between stories.
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
var rewriteStyleSheet = function rewriteStyleSheet(sheet, shadowRoot, shadowHosts) {
|
|
67
|
+
if (sheet.__pseudoStatesRewritten) return;
|
|
68
|
+
sheet.__pseudoStatesRewritten = true;
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
var index = 0;
|
|
72
|
+
|
|
73
|
+
var _iterator = _createForOfIteratorHelper(sheet.cssRules),
|
|
74
|
+
_step;
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
78
|
+
var _step$value = _step.value,
|
|
79
|
+
cssText = _step$value.cssText,
|
|
80
|
+
selectorText = _step$value.selectorText;
|
|
81
|
+
|
|
82
|
+
if (matchOne.test(selectorText)) {
|
|
83
|
+
var newRule = rewriteRule(cssText, selectorText, shadowRoot);
|
|
84
|
+
sheet.deleteRule(index);
|
|
85
|
+
sheet.insertRule(newRule, index);
|
|
86
|
+
if (shadowRoot) shadowHosts.add(shadowRoot.host);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
index++;
|
|
90
|
+
|
|
91
|
+
if (index > 1000) {
|
|
92
|
+
warnOnce("Reached maximum of 1000 pseudo selectors per sheet, skipping the rest.");
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
} catch (err) {
|
|
97
|
+
_iterator.e(err);
|
|
98
|
+
} finally {
|
|
99
|
+
_iterator.f();
|
|
100
|
+
}
|
|
101
|
+
} catch (e) {
|
|
102
|
+
if (e.toString().includes("cssRules")) {
|
|
103
|
+
warnOnce("Can't access cssRules, likely due to CORS restrictions: ".concat(sheet.href));
|
|
104
|
+
} else {
|
|
105
|
+
// eslint-disable-next-line no-console
|
|
106
|
+
console.error(e, sheet.href);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
exports.rewriteStyleSheet = rewriteStyleSheet;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _rewriteStyleSheet = require("./rewriteStyleSheet");
|
|
4
|
+
|
|
5
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
6
|
+
|
|
7
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
8
|
+
|
|
9
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
10
|
+
|
|
11
|
+
var Sheet = /*#__PURE__*/function () {
|
|
12
|
+
function Sheet() {
|
|
13
|
+
_classCallCheck(this, Sheet);
|
|
14
|
+
|
|
15
|
+
this.__pseudoStatesRewritten = false;
|
|
16
|
+
|
|
17
|
+
for (var _len = arguments.length, rules = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
18
|
+
rules[_key] = arguments[_key];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
this.cssRules = rules.map(function (cssText) {
|
|
22
|
+
return {
|
|
23
|
+
cssText: cssText,
|
|
24
|
+
selectorText: cssText.slice(0, cssText.indexOf(" {"))
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
_createClass(Sheet, [{
|
|
30
|
+
key: "deleteRule",
|
|
31
|
+
value: function deleteRule(index) {
|
|
32
|
+
this.cssRules.splice(index, 1);
|
|
33
|
+
}
|
|
34
|
+
}, {
|
|
35
|
+
key: "insertRule",
|
|
36
|
+
value: function insertRule(cssText, index) {
|
|
37
|
+
this.cssRules.splice(index, 0, cssText);
|
|
38
|
+
}
|
|
39
|
+
}]);
|
|
40
|
+
|
|
41
|
+
return Sheet;
|
|
42
|
+
}();
|
|
43
|
+
|
|
44
|
+
describe("rewriteStyleSheet", function () {
|
|
45
|
+
it("adds alternative selector targeting the element directly", function () {
|
|
46
|
+
var sheet = new Sheet("a:hover { color: red }");
|
|
47
|
+
(0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
|
|
48
|
+
expect(sheet.cssRules[0]).toContain("a.pseudo-hover");
|
|
49
|
+
});
|
|
50
|
+
it("adds alternative selector targeting an ancestor", function () {
|
|
51
|
+
var sheet = new Sheet("a:hover { color: red }");
|
|
52
|
+
(0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
|
|
53
|
+
expect(sheet.cssRules[0]).toContain(".pseudo-hover a");
|
|
54
|
+
});
|
|
55
|
+
it("adds alternative selector for each pseudo selector", function () {
|
|
56
|
+
var sheet = new Sheet("a:hover, a:focus { color: red }");
|
|
57
|
+
(0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
|
|
58
|
+
expect(sheet.cssRules[0]).toContain("a.pseudo-hover");
|
|
59
|
+
expect(sheet.cssRules[0]).toContain("a.pseudo-focus");
|
|
60
|
+
expect(sheet.cssRules[0]).toContain(".pseudo-hover a");
|
|
61
|
+
expect(sheet.cssRules[0]).toContain(".pseudo-focus a");
|
|
62
|
+
});
|
|
63
|
+
it("keeps non-pseudo selectors as-is", function () {
|
|
64
|
+
var sheet = new Sheet("a.class, a:hover, a:focus, a#id { color: red }");
|
|
65
|
+
(0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
|
|
66
|
+
expect(sheet.cssRules[0]).toContain("a.class");
|
|
67
|
+
expect(sheet.cssRules[0]).toContain("a#id");
|
|
68
|
+
});
|
|
69
|
+
it("supports combined pseudo selectors", function () {
|
|
70
|
+
var sheet = new Sheet("a:hover:focus { color: red }");
|
|
71
|
+
(0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
|
|
72
|
+
expect(sheet.cssRules[0]).toContain("a.pseudo-hover.pseudo-focus");
|
|
73
|
+
expect(sheet.cssRules[0]).toContain(".pseudo-hover.pseudo-focus a");
|
|
74
|
+
});
|
|
75
|
+
it('supports ":host"', function () {
|
|
76
|
+
var sheet = new Sheet(":host(:hover) { color: red }");
|
|
77
|
+
(0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
|
|
78
|
+
expect(sheet.cssRules[0]).toEqual(":host(:hover), :host(.pseudo-hover) { color: red }");
|
|
79
|
+
});
|
|
80
|
+
it('supports ":not"', function () {
|
|
81
|
+
var sheet = new Sheet(":not(:hover) { color: red }");
|
|
82
|
+
(0, _rewriteStyleSheet.rewriteStyleSheet)(sheet);
|
|
83
|
+
expect(sheet.cssRules[0]).toEqual(":not(:hover), :not(.pseudo-hover) { color: red }");
|
|
84
|
+
});
|
|
85
|
+
});
|
|
@@ -11,7 +11,7 @@ var _coreEvents = require("@storybook/core-events");
|
|
|
11
11
|
|
|
12
12
|
var _constants = require("./constants");
|
|
13
13
|
|
|
14
|
-
var
|
|
14
|
+
var _rewriteStyleSheet = require("./rewriteStyleSheet");
|
|
15
15
|
|
|
16
16
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
17
17
|
|
|
@@ -19,8 +19,6 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
|
|
|
19
19
|
|
|
20
20
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
21
21
|
|
|
22
|
-
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
23
|
-
|
|
24
22
|
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
25
23
|
|
|
26
24
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
@@ -41,9 +39,9 @@ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToAr
|
|
|
41
39
|
|
|
42
40
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
43
41
|
|
|
44
|
-
var
|
|
45
|
-
|
|
46
|
-
var
|
|
42
|
+
var channel = _addons.addons.getChannel();
|
|
43
|
+
|
|
44
|
+
var shadowHosts = new Set(); // Drops any existing pseudo state classnames that carried over from a previously viewed story
|
|
47
45
|
// before adding the new classnames. We do this the old-fashioned way, for IE compatibility.
|
|
48
46
|
|
|
49
47
|
var applyClasses = function applyClasses(element, classnames) {
|
|
@@ -54,19 +52,42 @@ var applyClasses = function applyClasses(element, classnames) {
|
|
|
54
52
|
})).concat.apply(_element$className$sp, _toConsumableArray(classnames)).join(" ");
|
|
55
53
|
};
|
|
56
54
|
|
|
57
|
-
var applyParameter = function applyParameter(
|
|
58
|
-
|
|
55
|
+
var applyParameter = function applyParameter(rootElement, parameter) {
|
|
56
|
+
var map = new Map([[rootElement, new Set()]]);
|
|
57
|
+
|
|
58
|
+
var add = function add(target, state) {
|
|
59
|
+
return map.set(target, new Set([].concat(_toConsumableArray(map.get(target) || []), [state])));
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
Object.entries(parameter || {}).forEach(function (_ref) {
|
|
59
63
|
var _ref2 = _slicedToArray(_ref, 2),
|
|
60
|
-
|
|
64
|
+
state = _ref2[0],
|
|
61
65
|
value = _ref2[1];
|
|
62
66
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
if (typeof value === "boolean") {
|
|
68
|
+
// default API - applying pseudo class to root element.
|
|
69
|
+
add(rootElement, value && state);
|
|
70
|
+
} else if (typeof value === "string") {
|
|
71
|
+
// explicit selectors API - applying pseudo class to a specific element
|
|
72
|
+
rootElement.querySelectorAll(value).forEach(function (el) {
|
|
73
|
+
return add(el, state);
|
|
74
|
+
});
|
|
75
|
+
} else if (Array.isArray(value)) {
|
|
76
|
+
// explicit selectors API - we have an array (of strings) recursively handle each one
|
|
77
|
+
value.forEach(function (sel) {
|
|
78
|
+
return rootElement.querySelectorAll(sel).forEach(function (el) {
|
|
79
|
+
return add(el, state);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
map.forEach(function (states, target) {
|
|
85
|
+
var classnames = [];
|
|
86
|
+
states.forEach(function (key) {
|
|
87
|
+
return _constants.PSEUDO_STATES[key] && classnames.push("pseudo-".concat(_constants.PSEUDO_STATES[key]));
|
|
88
|
+
});
|
|
89
|
+
applyClasses(target, classnames);
|
|
90
|
+
});
|
|
70
91
|
}; // Traverses ancestry to collect relevant pseudo classnames, and applies them to the shadow host.
|
|
71
92
|
// Shadow DOM can only access classes on its host. Traversing is needed to mimic the CSS cascade.
|
|
72
93
|
|
|
@@ -84,28 +105,18 @@ var updateShadowHost = function updateShadowHost(shadowHost) {
|
|
|
84
105
|
}
|
|
85
106
|
|
|
86
107
|
applyClasses(shadowHost, classnames);
|
|
87
|
-
}; //
|
|
108
|
+
}; // Global decorator that rewrites stylesheets and applies classnames to render pseudo styles
|
|
88
109
|
|
|
89
110
|
|
|
90
|
-
var
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
var withPseudoState = function withPseudoState(StoryFn, _ref5) {
|
|
98
|
-
var viewMode = _ref5.viewMode,
|
|
99
|
-
parameters = _ref5.parameters,
|
|
100
|
-
id = _ref5.id,
|
|
101
|
-
globalsArgs = _ref5.globals;
|
|
111
|
+
var withPseudoState = function withPseudoState(StoryFn, _ref3) {
|
|
112
|
+
var viewMode = _ref3.viewMode,
|
|
113
|
+
parameters = _ref3.parameters,
|
|
114
|
+
id = _ref3.id,
|
|
115
|
+
globalsArgs = _ref3.globals;
|
|
102
116
|
var parameter = parameters.pseudo;
|
|
103
|
-
var globals = globalsArgs.pseudo;
|
|
104
|
-
|
|
105
|
-
var channel = _addons.addons.getChannel(); // Sync parameter to globals, used by the toolbar (only in canvas as this
|
|
117
|
+
var globals = globalsArgs.pseudo; // Sync parameter to globals, used by the toolbar (only in canvas as this
|
|
106
118
|
// doesn't make sense for docs because many stories are displayed at once)
|
|
107
119
|
|
|
108
|
-
|
|
109
120
|
(0, _addons.useEffect)(function () {
|
|
110
121
|
if (parameter !== globals && viewMode === "story") {
|
|
111
122
|
channel.emit(_coreEvents.UPDATE_GLOBALS, {
|
|
@@ -120,133 +131,42 @@ var withPseudoState = function withPseudoState(StoryFn, _ref5) {
|
|
|
120
131
|
(0, _addons.useEffect)(function () {
|
|
121
132
|
var timeout = setTimeout(function () {
|
|
122
133
|
var element = document.getElementById(viewMode === "docs" ? "story--".concat(id) : "root");
|
|
123
|
-
applyParameter(element, globals);
|
|
134
|
+
applyParameter(element, globals || parameter);
|
|
124
135
|
shadowHosts.forEach(updateShadowHost);
|
|
125
136
|
}, 0);
|
|
126
137
|
return function () {
|
|
127
138
|
return clearTimeout(timeout);
|
|
128
139
|
};
|
|
129
|
-
}, [globals, viewMode]);
|
|
140
|
+
}, [globals, parameter, viewMode]);
|
|
130
141
|
return StoryFn();
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
exports.withPseudoState = withPseudoState;
|
|
134
|
-
var warnings = new Set();
|
|
135
|
-
|
|
136
|
-
var warnOnce = function warnOnce(message) {
|
|
137
|
-
if (warnings.has(message)) return; // eslint-disable-next-line no-console
|
|
138
|
-
|
|
139
|
-
console.warn(message);
|
|
140
|
-
warnings.add(message);
|
|
141
142
|
}; // Rewrite CSS rules for pseudo-states on all stylesheets to add an alternative selector
|
|
142
143
|
|
|
143
144
|
|
|
144
|
-
|
|
145
|
+
exports.withPseudoState = withPseudoState;
|
|
146
|
+
|
|
147
|
+
var rewriteStyleSheets = function rewriteStyleSheets(shadowRoot) {
|
|
145
148
|
var _shadowRoot$adoptedSt;
|
|
146
149
|
|
|
147
150
|
var styleSheets = shadowRoot ? shadowRoot.styleSheets : document.styleSheets;
|
|
148
151
|
if (shadowRoot !== null && shadowRoot !== void 0 && (_shadowRoot$adoptedSt = shadowRoot.adoptedStyleSheets) !== null && _shadowRoot$adoptedSt !== void 0 && _shadowRoot$adoptedSt.length) styleSheets = shadowRoot.adoptedStyleSheets;
|
|
152
|
+
Array.from(styleSheets).forEach(function (sheet) {
|
|
153
|
+
return (0, _rewriteStyleSheet.rewriteStyleSheet)(sheet, shadowRoot, shadowHosts);
|
|
154
|
+
});
|
|
155
|
+
}; // Only track shadow hosts for the current story
|
|
149
156
|
|
|
150
|
-
var _iterator = _createForOfIteratorHelper(styleSheets),
|
|
151
|
-
_step;
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
155
|
-
var sheet = _step.value;
|
|
156
|
-
|
|
157
|
-
if (sheet._pseudoStatesRewritten) {
|
|
158
|
-
continue;
|
|
159
|
-
} else {
|
|
160
|
-
sheet._pseudoStatesRewritten = true;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
try {
|
|
164
|
-
var index = 0;
|
|
165
|
-
|
|
166
|
-
var _iterator2 = _createForOfIteratorHelper(sheet.cssRules),
|
|
167
|
-
_step2;
|
|
168
|
-
|
|
169
|
-
try {
|
|
170
|
-
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
171
|
-
var _step2$value = _step2.value,
|
|
172
|
-
cssText = _step2$value.cssText,
|
|
173
|
-
selectorText = _step2$value.selectorText;
|
|
174
|
-
|
|
175
|
-
if (matchOne.test(selectorText)) {
|
|
176
|
-
var selectors = (0, _splitSelectors.splitSelectors)(selectorText);
|
|
177
|
-
var newRule = cssText.replace(selectorText, selectors.flatMap(function (selector) {
|
|
178
|
-
if (selector.includes(".pseudo-")) return [];
|
|
179
|
-
var states = [];
|
|
180
|
-
var plainSelector = selector.replace(matchAll, function (_, state) {
|
|
181
|
-
states.push(state);
|
|
182
|
-
return "";
|
|
183
|
-
});
|
|
184
|
-
var stateSelector;
|
|
185
|
-
|
|
186
|
-
if (!matchOne.test(selector)) {
|
|
187
|
-
return [selector];
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
if (selector.startsWith(":host(") || selector.startsWith("::slotted(")) {
|
|
191
|
-
stateSelector = states.reduce(function (acc, state) {
|
|
192
|
-
return acc.replaceAll(":".concat(state), ".pseudo-".concat(state));
|
|
193
|
-
}, selector);
|
|
194
|
-
} else if (shadowRoot) {
|
|
195
|
-
stateSelector = ":host(".concat(states.map(function (s) {
|
|
196
|
-
return ".pseudo-".concat(s);
|
|
197
|
-
}).join(""), ") ").concat(plainSelector);
|
|
198
|
-
} else {
|
|
199
|
-
stateSelector = "".concat(states.map(function (s) {
|
|
200
|
-
return ".pseudo-".concat(s);
|
|
201
|
-
}).join(""), " ").concat(plainSelector);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return [selector, stateSelector];
|
|
205
|
-
}).join(", "));
|
|
206
|
-
sheet.deleteRule(index);
|
|
207
|
-
sheet.insertRule(newRule, index);
|
|
208
|
-
if (shadowRoot) shadowHosts.add(shadowRoot.host);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
index++;
|
|
212
|
-
|
|
213
|
-
if (index > 1000) {
|
|
214
|
-
warnOnce("Reached maximum of 1000 pseudo selectors per sheet, skipping the rest.");
|
|
215
|
-
break;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
} catch (err) {
|
|
219
|
-
_iterator2.e(err);
|
|
220
|
-
} finally {
|
|
221
|
-
_iterator2.f();
|
|
222
|
-
}
|
|
223
|
-
} catch (e) {
|
|
224
|
-
if (e.toString().includes("cssRules")) {
|
|
225
|
-
warnOnce("Can't access cssRules, likely due to CORS restrictions: ".concat(sheet.href));
|
|
226
|
-
} else {
|
|
227
|
-
// eslint-disable-next-line no-console
|
|
228
|
-
console.error(e, sheet.href);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
} catch (err) {
|
|
233
|
-
_iterator.e(err);
|
|
234
|
-
} finally {
|
|
235
|
-
_iterator.f();
|
|
236
|
-
}
|
|
237
|
-
} // Reinitialize CSS enhancements every time the story changes
|
|
238
157
|
|
|
158
|
+
channel.on(_coreEvents.STORY_CHANGED, function () {
|
|
159
|
+
return shadowHosts.clear();
|
|
160
|
+
}); // Reinitialize CSS enhancements every time the story changes
|
|
239
161
|
|
|
240
|
-
|
|
162
|
+
channel.on(_coreEvents.STORY_RENDERED, function () {
|
|
241
163
|
return rewriteStyleSheets();
|
|
242
164
|
}); // Reinitialize CSS enhancements every time a docs page is rendered
|
|
243
165
|
|
|
244
|
-
|
|
245
|
-
_addons.addons.getChannel().on(_coreEvents.DOCS_RENDERED, function () {
|
|
166
|
+
channel.on(_coreEvents.DOCS_RENDERED, function () {
|
|
246
167
|
return rewriteStyleSheets();
|
|
247
168
|
}); // IE doesn't support shadow DOM
|
|
248
169
|
|
|
249
|
-
|
|
250
170
|
if (Element.prototype.attachShadow) {
|
|
251
171
|
// Monkeypatch the attachShadow method so we can handle pseudo styles inside shadow DOM
|
|
252
172
|
Element.prototype._attachShadow = Element.prototype.attachShadow;
|
|
@@ -43,19 +43,16 @@ export var PseudoStateTool = function PseudoStateTool() {
|
|
|
43
43
|
pseudo = _useGlobals2[0].pseudo,
|
|
44
44
|
updateGlobals = _useGlobals2[1];
|
|
45
45
|
|
|
46
|
-
var
|
|
47
|
-
return
|
|
48
|
-
}, [pseudo]);
|
|
49
|
-
var getValue = useCallback(function (option) {
|
|
50
|
-
return pseudo ? pseudo[option] : false;
|
|
46
|
+
var isActive = useCallback(function (option) {
|
|
47
|
+
return (pseudo === null || pseudo === void 0 ? void 0 : pseudo[option]) === true;
|
|
51
48
|
}, [pseudo]);
|
|
52
49
|
var toggleOption = useCallback(function (option) {
|
|
53
50
|
return function () {
|
|
54
51
|
return updateGlobals({
|
|
55
|
-
pseudo: _objectSpread(_objectSpread({}, pseudo), {}, _defineProperty({}, option, !
|
|
52
|
+
pseudo: _objectSpread(_objectSpread({}, pseudo), {}, _defineProperty({}, option, !isActive(option)))
|
|
56
53
|
});
|
|
57
54
|
};
|
|
58
|
-
}, [pseudo
|
|
55
|
+
}, [pseudo]);
|
|
59
56
|
return /*#__PURE__*/React.createElement(WithTooltip, {
|
|
60
57
|
placement: "top",
|
|
61
58
|
trigger: "click",
|
|
@@ -65,16 +62,16 @@ export var PseudoStateTool = function PseudoStateTool() {
|
|
|
65
62
|
return {
|
|
66
63
|
id: option,
|
|
67
64
|
title: /*#__PURE__*/React.createElement(LinkTitle, {
|
|
68
|
-
active:
|
|
65
|
+
active: isActive(option)
|
|
69
66
|
}, ":", PSEUDO_STATES[option]),
|
|
70
67
|
right: /*#__PURE__*/React.createElement(LinkIcon, {
|
|
71
68
|
icon: "check",
|
|
72
69
|
width: 12,
|
|
73
70
|
height: 12,
|
|
74
|
-
active:
|
|
71
|
+
active: isActive(option)
|
|
75
72
|
}),
|
|
76
73
|
onClick: toggleOption(option),
|
|
77
|
-
active:
|
|
74
|
+
active: isActive(option)
|
|
78
75
|
};
|
|
79
76
|
})
|
|
80
77
|
});
|
|
@@ -82,7 +79,7 @@ export var PseudoStateTool = function PseudoStateTool() {
|
|
|
82
79
|
}, /*#__PURE__*/React.createElement(IconButton, {
|
|
83
80
|
key: "pseudo-state",
|
|
84
81
|
title: "Select CSS pseudo states",
|
|
85
|
-
active:
|
|
82
|
+
active: options.some(isActive)
|
|
86
83
|
}, /*#__PURE__*/React.createElement(Icons, {
|
|
87
84
|
icon: "button"
|
|
88
85
|
})));
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
2
|
+
|
|
3
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
4
|
+
|
|
5
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
6
|
+
|
|
7
|
+
import { PSEUDO_STATES } from "./constants";
|
|
8
|
+
import { splitSelectors } from "./splitSelectors";
|
|
9
|
+
var pseudoStates = Object.values(PSEUDO_STATES);
|
|
10
|
+
var matchOne = new RegExp(":(".concat(pseudoStates.join("|"), ")"));
|
|
11
|
+
var matchAll = new RegExp(":(".concat(pseudoStates.join("|"), ")"), "g");
|
|
12
|
+
var warnings = new Set();
|
|
13
|
+
|
|
14
|
+
var warnOnce = function warnOnce(message) {
|
|
15
|
+
if (warnings.has(message)) return; // eslint-disable-next-line no-console
|
|
16
|
+
|
|
17
|
+
console.warn(message);
|
|
18
|
+
warnings.add(message);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
var rewriteRule = function rewriteRule(cssText, selectorText, shadowRoot) {
|
|
22
|
+
return cssText.replace(selectorText, splitSelectors(selectorText).flatMap(function (selector) {
|
|
23
|
+
if (selector.includes(".pseudo-")) {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!matchOne.test(selector)) {
|
|
28
|
+
return [selector];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
var states = [];
|
|
32
|
+
var plainSelector = selector.replace(matchAll, function (_, state) {
|
|
33
|
+
states.push(state);
|
|
34
|
+
return "";
|
|
35
|
+
});
|
|
36
|
+
var classSelector = states.reduce(function (acc, state) {
|
|
37
|
+
return acc.replace(new RegExp(":".concat(state), "g"), ".pseudo-".concat(state));
|
|
38
|
+
}, selector);
|
|
39
|
+
|
|
40
|
+
if (selector.startsWith(":host(") || selector.startsWith("::slotted(")) {
|
|
41
|
+
return [selector, classSelector];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
var ancestorSelector = shadowRoot ? ":host(".concat(states.map(function (s) {
|
|
45
|
+
return ".pseudo-".concat(s);
|
|
46
|
+
}).join(""), ") ").concat(plainSelector) : "".concat(states.map(function (s) {
|
|
47
|
+
return ".pseudo-".concat(s);
|
|
48
|
+
}).join(""), " ").concat(plainSelector);
|
|
49
|
+
return [selector, classSelector, ancestorSelector].filter(function (selector) {
|
|
50
|
+
return !selector.includes(":not()");
|
|
51
|
+
});
|
|
52
|
+
}).join(", "));
|
|
53
|
+
}; // Rewrites the style sheet to add alternative selectors for any rule that targets a pseudo state.
|
|
54
|
+
// A sheet can only be rewritten once, and may carry over between stories.
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
export var rewriteStyleSheet = function rewriteStyleSheet(sheet, shadowRoot, shadowHosts) {
|
|
58
|
+
if (sheet.__pseudoStatesRewritten) return;
|
|
59
|
+
sheet.__pseudoStatesRewritten = true;
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
var index = 0;
|
|
63
|
+
|
|
64
|
+
var _iterator = _createForOfIteratorHelper(sheet.cssRules),
|
|
65
|
+
_step;
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
69
|
+
var _step$value = _step.value,
|
|
70
|
+
cssText = _step$value.cssText,
|
|
71
|
+
selectorText = _step$value.selectorText;
|
|
72
|
+
|
|
73
|
+
if (matchOne.test(selectorText)) {
|
|
74
|
+
var newRule = rewriteRule(cssText, selectorText, shadowRoot);
|
|
75
|
+
sheet.deleteRule(index);
|
|
76
|
+
sheet.insertRule(newRule, index);
|
|
77
|
+
if (shadowRoot) shadowHosts.add(shadowRoot.host);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
index++;
|
|
81
|
+
|
|
82
|
+
if (index > 1000) {
|
|
83
|
+
warnOnce("Reached maximum of 1000 pseudo selectors per sheet, skipping the rest.");
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
} catch (err) {
|
|
88
|
+
_iterator.e(err);
|
|
89
|
+
} finally {
|
|
90
|
+
_iterator.f();
|
|
91
|
+
}
|
|
92
|
+
} catch (e) {
|
|
93
|
+
if (e.toString().includes("cssRules")) {
|
|
94
|
+
warnOnce("Can't access cssRules, likely due to CORS restrictions: ".concat(sheet.href));
|
|
95
|
+
} else {
|
|
96
|
+
// eslint-disable-next-line no-console
|
|
97
|
+
console.error(e, sheet.href);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
2
|
+
|
|
3
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
4
|
+
|
|
5
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
6
|
+
|
|
7
|
+
import { rewriteStyleSheet } from "./rewriteStyleSheet";
|
|
8
|
+
|
|
9
|
+
var Sheet = /*#__PURE__*/function () {
|
|
10
|
+
function Sheet() {
|
|
11
|
+
_classCallCheck(this, Sheet);
|
|
12
|
+
|
|
13
|
+
this.__pseudoStatesRewritten = false;
|
|
14
|
+
|
|
15
|
+
for (var _len = arguments.length, rules = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
16
|
+
rules[_key] = arguments[_key];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
this.cssRules = rules.map(function (cssText) {
|
|
20
|
+
return {
|
|
21
|
+
cssText: cssText,
|
|
22
|
+
selectorText: cssText.slice(0, cssText.indexOf(" {"))
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
_createClass(Sheet, [{
|
|
28
|
+
key: "deleteRule",
|
|
29
|
+
value: function deleteRule(index) {
|
|
30
|
+
this.cssRules.splice(index, 1);
|
|
31
|
+
}
|
|
32
|
+
}, {
|
|
33
|
+
key: "insertRule",
|
|
34
|
+
value: function insertRule(cssText, index) {
|
|
35
|
+
this.cssRules.splice(index, 0, cssText);
|
|
36
|
+
}
|
|
37
|
+
}]);
|
|
38
|
+
|
|
39
|
+
return Sheet;
|
|
40
|
+
}();
|
|
41
|
+
|
|
42
|
+
describe("rewriteStyleSheet", function () {
|
|
43
|
+
it("adds alternative selector targeting the element directly", function () {
|
|
44
|
+
var sheet = new Sheet("a:hover { color: red }");
|
|
45
|
+
rewriteStyleSheet(sheet);
|
|
46
|
+
expect(sheet.cssRules[0]).toContain("a.pseudo-hover");
|
|
47
|
+
});
|
|
48
|
+
it("adds alternative selector targeting an ancestor", function () {
|
|
49
|
+
var sheet = new Sheet("a:hover { color: red }");
|
|
50
|
+
rewriteStyleSheet(sheet);
|
|
51
|
+
expect(sheet.cssRules[0]).toContain(".pseudo-hover a");
|
|
52
|
+
});
|
|
53
|
+
it("adds alternative selector for each pseudo selector", function () {
|
|
54
|
+
var sheet = new Sheet("a:hover, a:focus { color: red }");
|
|
55
|
+
rewriteStyleSheet(sheet);
|
|
56
|
+
expect(sheet.cssRules[0]).toContain("a.pseudo-hover");
|
|
57
|
+
expect(sheet.cssRules[0]).toContain("a.pseudo-focus");
|
|
58
|
+
expect(sheet.cssRules[0]).toContain(".pseudo-hover a");
|
|
59
|
+
expect(sheet.cssRules[0]).toContain(".pseudo-focus a");
|
|
60
|
+
});
|
|
61
|
+
it("keeps non-pseudo selectors as-is", function () {
|
|
62
|
+
var sheet = new Sheet("a.class, a:hover, a:focus, a#id { color: red }");
|
|
63
|
+
rewriteStyleSheet(sheet);
|
|
64
|
+
expect(sheet.cssRules[0]).toContain("a.class");
|
|
65
|
+
expect(sheet.cssRules[0]).toContain("a#id");
|
|
66
|
+
});
|
|
67
|
+
it("supports combined pseudo selectors", function () {
|
|
68
|
+
var sheet = new Sheet("a:hover:focus { color: red }");
|
|
69
|
+
rewriteStyleSheet(sheet);
|
|
70
|
+
expect(sheet.cssRules[0]).toContain("a.pseudo-hover.pseudo-focus");
|
|
71
|
+
expect(sheet.cssRules[0]).toContain(".pseudo-hover.pseudo-focus a");
|
|
72
|
+
});
|
|
73
|
+
it('supports ":host"', function () {
|
|
74
|
+
var sheet = new Sheet(":host(:hover) { color: red }");
|
|
75
|
+
rewriteStyleSheet(sheet);
|
|
76
|
+
expect(sheet.cssRules[0]).toEqual(":host(:hover), :host(.pseudo-hover) { color: red }");
|
|
77
|
+
});
|
|
78
|
+
it('supports ":not"', function () {
|
|
79
|
+
var sheet = new Sheet(":not(:hover) { color: red }");
|
|
80
|
+
rewriteStyleSheet(sheet);
|
|
81
|
+
expect(sheet.cssRules[0]).toEqual(":not(:hover), :not(.pseudo-hover) { color: red }");
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -4,8 +4,6 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
|
|
|
4
4
|
|
|
5
5
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
6
6
|
|
|
7
|
-
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
8
|
-
|
|
9
7
|
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
10
8
|
|
|
11
9
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
@@ -28,13 +26,11 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
|
|
|
28
26
|
|
|
29
27
|
/* eslint-env browser */
|
|
30
28
|
import { addons, useEffect } from "@storybook/addons";
|
|
31
|
-
import { DOCS_RENDERED, STORY_CHANGED, STORY_RENDERED } from "@storybook/core-events";
|
|
32
|
-
import { UPDATE_GLOBALS } from "@storybook/core-events";
|
|
29
|
+
import { DOCS_RENDERED, STORY_CHANGED, STORY_RENDERED, UPDATE_GLOBALS } from "@storybook/core-events";
|
|
33
30
|
import { PSEUDO_STATES } from "./constants";
|
|
34
|
-
import {
|
|
35
|
-
var
|
|
36
|
-
var
|
|
37
|
-
var matchAll = new RegExp(":(".concat(pseudoStates.join("|"), ")"), "g"); // Drops any existing pseudo state classnames that carried over from a previously viewed story
|
|
31
|
+
import { rewriteStyleSheet } from "./rewriteStyleSheet";
|
|
32
|
+
var channel = addons.getChannel();
|
|
33
|
+
var shadowHosts = new Set(); // Drops any existing pseudo state classnames that carried over from a previously viewed story
|
|
38
34
|
// before adding the new classnames. We do this the old-fashioned way, for IE compatibility.
|
|
39
35
|
|
|
40
36
|
var applyClasses = function applyClasses(element, classnames) {
|
|
@@ -45,19 +41,42 @@ var applyClasses = function applyClasses(element, classnames) {
|
|
|
45
41
|
})).concat.apply(_element$className$sp, _toConsumableArray(classnames)).join(" ");
|
|
46
42
|
};
|
|
47
43
|
|
|
48
|
-
var applyParameter = function applyParameter(
|
|
49
|
-
|
|
44
|
+
var applyParameter = function applyParameter(rootElement, parameter) {
|
|
45
|
+
var map = new Map([[rootElement, new Set()]]);
|
|
46
|
+
|
|
47
|
+
var add = function add(target, state) {
|
|
48
|
+
return map.set(target, new Set([].concat(_toConsumableArray(map.get(target) || []), [state])));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
Object.entries(parameter || {}).forEach(function (_ref) {
|
|
50
52
|
var _ref2 = _slicedToArray(_ref, 2),
|
|
51
|
-
|
|
53
|
+
state = _ref2[0],
|
|
52
54
|
value = _ref2[1];
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
if (typeof value === "boolean") {
|
|
57
|
+
// default API - applying pseudo class to root element.
|
|
58
|
+
add(rootElement, value && state);
|
|
59
|
+
} else if (typeof value === "string") {
|
|
60
|
+
// explicit selectors API - applying pseudo class to a specific element
|
|
61
|
+
rootElement.querySelectorAll(value).forEach(function (el) {
|
|
62
|
+
return add(el, state);
|
|
63
|
+
});
|
|
64
|
+
} else if (Array.isArray(value)) {
|
|
65
|
+
// explicit selectors API - we have an array (of strings) recursively handle each one
|
|
66
|
+
value.forEach(function (sel) {
|
|
67
|
+
return rootElement.querySelectorAll(sel).forEach(function (el) {
|
|
68
|
+
return add(el, state);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
map.forEach(function (states, target) {
|
|
74
|
+
var classnames = [];
|
|
75
|
+
states.forEach(function (key) {
|
|
76
|
+
return PSEUDO_STATES[key] && classnames.push("pseudo-".concat(PSEUDO_STATES[key]));
|
|
77
|
+
});
|
|
78
|
+
applyClasses(target, classnames);
|
|
79
|
+
});
|
|
61
80
|
}; // Traverses ancestry to collect relevant pseudo classnames, and applies them to the shadow host.
|
|
62
81
|
// Shadow DOM can only access classes on its host. Traversing is needed to mimic the CSS cascade.
|
|
63
82
|
|
|
@@ -75,22 +94,16 @@ var updateShadowHost = function updateShadowHost(shadowHost) {
|
|
|
75
94
|
}
|
|
76
95
|
|
|
77
96
|
applyClasses(shadowHost, classnames);
|
|
78
|
-
}; //
|
|
79
|
-
|
|
97
|
+
}; // Global decorator that rewrites stylesheets and applies classnames to render pseudo styles
|
|
80
98
|
|
|
81
|
-
var shadowHosts = new Set();
|
|
82
|
-
addons.getChannel().on(STORY_CHANGED, function () {
|
|
83
|
-
return shadowHosts.clear();
|
|
84
|
-
}); // Global decorator that rewrites stylesheets and applies classnames to render pseudo styles
|
|
85
99
|
|
|
86
|
-
export var withPseudoState = function withPseudoState(StoryFn,
|
|
87
|
-
var viewMode =
|
|
88
|
-
parameters =
|
|
89
|
-
id =
|
|
90
|
-
globalsArgs =
|
|
100
|
+
export var withPseudoState = function withPseudoState(StoryFn, _ref3) {
|
|
101
|
+
var viewMode = _ref3.viewMode,
|
|
102
|
+
parameters = _ref3.parameters,
|
|
103
|
+
id = _ref3.id,
|
|
104
|
+
globalsArgs = _ref3.globals;
|
|
91
105
|
var parameter = parameters.pseudo;
|
|
92
|
-
var globals = globalsArgs.pseudo;
|
|
93
|
-
var channel = addons.getChannel(); // Sync parameter to globals, used by the toolbar (only in canvas as this
|
|
106
|
+
var globals = globalsArgs.pseudo; // Sync parameter to globals, used by the toolbar (only in canvas as this
|
|
94
107
|
// doesn't make sense for docs because many stories are displayed at once)
|
|
95
108
|
|
|
96
109
|
useEffect(function () {
|
|
@@ -107,126 +120,36 @@ export var withPseudoState = function withPseudoState(StoryFn, _ref5) {
|
|
|
107
120
|
useEffect(function () {
|
|
108
121
|
var timeout = setTimeout(function () {
|
|
109
122
|
var element = document.getElementById(viewMode === "docs" ? "story--".concat(id) : "root");
|
|
110
|
-
applyParameter(element, globals);
|
|
123
|
+
applyParameter(element, globals || parameter);
|
|
111
124
|
shadowHosts.forEach(updateShadowHost);
|
|
112
125
|
}, 0);
|
|
113
126
|
return function () {
|
|
114
127
|
return clearTimeout(timeout);
|
|
115
128
|
};
|
|
116
|
-
}, [globals, viewMode]);
|
|
129
|
+
}, [globals, parameter, viewMode]);
|
|
117
130
|
return StoryFn();
|
|
118
|
-
};
|
|
119
|
-
var warnings = new Set();
|
|
120
|
-
|
|
121
|
-
var warnOnce = function warnOnce(message) {
|
|
122
|
-
if (warnings.has(message)) return; // eslint-disable-next-line no-console
|
|
123
|
-
|
|
124
|
-
console.warn(message);
|
|
125
|
-
warnings.add(message);
|
|
126
131
|
}; // Rewrite CSS rules for pseudo-states on all stylesheets to add an alternative selector
|
|
127
132
|
|
|
128
|
-
|
|
129
|
-
function rewriteStyleSheets(shadowRoot) {
|
|
133
|
+
var rewriteStyleSheets = function rewriteStyleSheets(shadowRoot) {
|
|
130
134
|
var _shadowRoot$adoptedSt;
|
|
131
135
|
|
|
132
136
|
var styleSheets = shadowRoot ? shadowRoot.styleSheets : document.styleSheets;
|
|
133
137
|
if (shadowRoot !== null && shadowRoot !== void 0 && (_shadowRoot$adoptedSt = shadowRoot.adoptedStyleSheets) !== null && _shadowRoot$adoptedSt !== void 0 && _shadowRoot$adoptedSt.length) styleSheets = shadowRoot.adoptedStyleSheets;
|
|
138
|
+
Array.from(styleSheets).forEach(function (sheet) {
|
|
139
|
+
return rewriteStyleSheet(sheet, shadowRoot, shadowHosts);
|
|
140
|
+
});
|
|
141
|
+
}; // Only track shadow hosts for the current story
|
|
134
142
|
|
|
135
|
-
var _iterator = _createForOfIteratorHelper(styleSheets),
|
|
136
|
-
_step;
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
140
|
-
var sheet = _step.value;
|
|
141
|
-
|
|
142
|
-
if (sheet._pseudoStatesRewritten) {
|
|
143
|
-
continue;
|
|
144
|
-
} else {
|
|
145
|
-
sheet._pseudoStatesRewritten = true;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
var index = 0;
|
|
150
|
-
|
|
151
|
-
var _iterator2 = _createForOfIteratorHelper(sheet.cssRules),
|
|
152
|
-
_step2;
|
|
153
|
-
|
|
154
|
-
try {
|
|
155
|
-
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
156
|
-
var _step2$value = _step2.value,
|
|
157
|
-
cssText = _step2$value.cssText,
|
|
158
|
-
selectorText = _step2$value.selectorText;
|
|
159
|
-
|
|
160
|
-
if (matchOne.test(selectorText)) {
|
|
161
|
-
var selectors = splitSelectors(selectorText);
|
|
162
|
-
var newRule = cssText.replace(selectorText, selectors.flatMap(function (selector) {
|
|
163
|
-
if (selector.includes(".pseudo-")) return [];
|
|
164
|
-
var states = [];
|
|
165
|
-
var plainSelector = selector.replace(matchAll, function (_, state) {
|
|
166
|
-
states.push(state);
|
|
167
|
-
return "";
|
|
168
|
-
});
|
|
169
|
-
var stateSelector;
|
|
170
|
-
|
|
171
|
-
if (!matchOne.test(selector)) {
|
|
172
|
-
return [selector];
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (selector.startsWith(":host(") || selector.startsWith("::slotted(")) {
|
|
176
|
-
stateSelector = states.reduce(function (acc, state) {
|
|
177
|
-
return acc.replaceAll(":".concat(state), ".pseudo-".concat(state));
|
|
178
|
-
}, selector);
|
|
179
|
-
} else if (shadowRoot) {
|
|
180
|
-
stateSelector = ":host(".concat(states.map(function (s) {
|
|
181
|
-
return ".pseudo-".concat(s);
|
|
182
|
-
}).join(""), ") ").concat(plainSelector);
|
|
183
|
-
} else {
|
|
184
|
-
stateSelector = "".concat(states.map(function (s) {
|
|
185
|
-
return ".pseudo-".concat(s);
|
|
186
|
-
}).join(""), " ").concat(plainSelector);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return [selector, stateSelector];
|
|
190
|
-
}).join(", "));
|
|
191
|
-
sheet.deleteRule(index);
|
|
192
|
-
sheet.insertRule(newRule, index);
|
|
193
|
-
if (shadowRoot) shadowHosts.add(shadowRoot.host);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
index++;
|
|
197
|
-
|
|
198
|
-
if (index > 1000) {
|
|
199
|
-
warnOnce("Reached maximum of 1000 pseudo selectors per sheet, skipping the rest.");
|
|
200
|
-
break;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
} catch (err) {
|
|
204
|
-
_iterator2.e(err);
|
|
205
|
-
} finally {
|
|
206
|
-
_iterator2.f();
|
|
207
|
-
}
|
|
208
|
-
} catch (e) {
|
|
209
|
-
if (e.toString().includes("cssRules")) {
|
|
210
|
-
warnOnce("Can't access cssRules, likely due to CORS restrictions: ".concat(sheet.href));
|
|
211
|
-
} else {
|
|
212
|
-
// eslint-disable-next-line no-console
|
|
213
|
-
console.error(e, sheet.href);
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
} catch (err) {
|
|
218
|
-
_iterator.e(err);
|
|
219
|
-
} finally {
|
|
220
|
-
_iterator.f();
|
|
221
|
-
}
|
|
222
|
-
} // Reinitialize CSS enhancements every time the story changes
|
|
223
143
|
|
|
144
|
+
channel.on(STORY_CHANGED, function () {
|
|
145
|
+
return shadowHosts.clear();
|
|
146
|
+
}); // Reinitialize CSS enhancements every time the story changes
|
|
224
147
|
|
|
225
|
-
|
|
148
|
+
channel.on(STORY_RENDERED, function () {
|
|
226
149
|
return rewriteStyleSheets();
|
|
227
150
|
}); // Reinitialize CSS enhancements every time a docs page is rendered
|
|
228
151
|
|
|
229
|
-
|
|
152
|
+
channel.on(DOCS_RENDERED, function () {
|
|
230
153
|
return rewriteStyleSheets();
|
|
231
154
|
}); // IE doesn't support shadow DOM
|
|
232
155
|
|