storybook-addon-pseudo-states 1.8.0 → 1.11.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 CHANGED
@@ -1,4 +1,4 @@
1
- # v1.0.0 (Wed Apr 06 2022)
1
+ # v1.0.0 (Mon May 23 2022)
2
2
 
3
3
  #### 🚀 Enhancement
4
4
 
@@ -7,11 +7,14 @@
7
7
 
8
8
  #### 🐛 Bug Fix
9
9
 
10
+ - fix: Resolve crash for stories that use internal State [#28](https://github.com/chromaui/storybook-addon-pseudo-states/pull/28) (david.maulick@coinbase.com)
11
+ - Fix CSS selector splitting [#24](https://github.com/chromaui/storybook-addon-pseudo-states/pull/24) ([@ilanus](https://github.com/ilanus) [@ghengeveld](https://github.com/ghengeveld))
10
12
  - Add support for slotted lit elements [#23](https://github.com/chromaui/storybook-addon-pseudo-states/pull/23) ([@ilanus](https://github.com/ilanus))
11
13
  - Setup auto [#7](https://github.com/chromaui/storybook-addon-pseudo-states/pull/7) ([@ghengeveld](https://github.com/ghengeveld))
12
14
 
13
15
  #### ⚠️ Pushed to `main`
14
16
 
17
+ - Use chromatic@next ([@ghengeveld](https://github.com/ghengeveld))
15
18
  - [skip release] Revert back to disabling CustomElement stories ([@ghengeveld](https://github.com/ghengeveld))
16
19
  - Another attempt at dealing with IE ([@ghengeveld](https://github.com/ghengeveld))
17
20
  - Don't disable stories, just ignore IE ([@ghengeveld](https://github.com/ghengeveld))
@@ -23,8 +26,9 @@
23
26
  - Upgrade Storybook ([@ghengeveld](https://github.com/ghengeveld))
24
27
  - Ignore .env file ([@ghengeveld](https://github.com/ghengeveld))
25
28
 
26
- #### Authors: 3
29
+ #### Authors: 4
27
30
 
31
+ - David Maulick ([@dmaulick](https://github.com/dmaulick))
28
32
  - Gert Hengeveld ([@ghengeveld](https://github.com/ghengeveld))
29
33
  - Ilan ([@ilanus](https://github.com/ilanus))
30
34
  - Jeroen Zwartepoorte ([@jpzwarte](https://github.com/jpzwarte))
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.splitSelectors = void 0;
7
+
8
+ var isAtRule = function isAtRule(selector) {
9
+ return selector.indexOf("@") === 0;
10
+ };
11
+
12
+ var splitSelectors = function splitSelectors(selectors) {
13
+ if (isAtRule(selectors)) return [selectors];
14
+ var result = [];
15
+ var parentheses = 0;
16
+ var brackets = 0;
17
+ var selector = "";
18
+
19
+ for (var i = 0, len = selectors.length; i < len; i++) {
20
+ var char = selectors[i];
21
+
22
+ if (char === "(") {
23
+ parentheses += 1;
24
+ } else if (char === ")") {
25
+ parentheses -= 1;
26
+ } else if (char === "[") {
27
+ brackets += 1;
28
+ } else if (char === "]") {
29
+ brackets -= 1;
30
+ } else if (char === ",") {
31
+ if (!parentheses && !brackets) {
32
+ result.push(selector.trim());
33
+ selector = "";
34
+ continue;
35
+ }
36
+ }
37
+
38
+ selector += char;
39
+ }
40
+
41
+ result.push(selector.trim());
42
+ return result;
43
+ };
44
+
45
+ exports.splitSelectors = splitSelectors;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ var _splitSelectors = require("./splitSelectors");
4
+
5
+ describe("splitSelectors", function () {
6
+ test("handles basic selectors", function () {
7
+ expect((0, _splitSelectors.splitSelectors)(".a")).toEqual([".a"]);
8
+ expect((0, _splitSelectors.splitSelectors)(".a, .b")).toEqual([".a", ".b"]);
9
+ });
10
+ test("supports ::slotted and :is", function () {
11
+ expect((0, _splitSelectors.splitSelectors)("::slotted(:is(button, a):active)")).toEqual(["::slotted(:is(button, a):active)"]);
12
+ 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)"]);
13
+ });
14
+ test("supports :host", function () {
15
+ 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)"]);
16
+ 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))"]);
17
+ });
18
+ });
@@ -11,6 +11,8 @@ var _coreEvents = require("@storybook/core-events");
11
11
 
12
12
  var _constants = require("./constants");
13
13
 
14
+ var _splitSelectors = require("./splitSelectors");
15
+
14
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; }
15
17
 
16
18
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
@@ -95,20 +97,23 @@ _addons.addons.getChannel().on(_coreEvents.STORY_CHANGED, function () {
95
97
  var withPseudoState = function withPseudoState(StoryFn, _ref5) {
96
98
  var viewMode = _ref5.viewMode,
97
99
  parameters = _ref5.parameters,
98
- id = _ref5.id;
100
+ id = _ref5.id,
101
+ globalsArgs = _ref5.globals;
99
102
  var parameter = parameters.pseudo;
103
+ var globals = globalsArgs.pseudo;
100
104
 
101
- var _useGlobals = (0, _addons.useGlobals)(),
102
- _useGlobals2 = _slicedToArray(_useGlobals, 2),
103
- globals = _useGlobals2[0].pseudo,
104
- updateGlobals = _useGlobals2[1]; // Sync parameter to globals, used by the toolbar (only in canvas as this
105
+ var channel = _addons.addons.getChannel(); // Sync parameter to globals, used by the toolbar (only in canvas as this
105
106
  // doesn't make sense for docs because many stories are displayed at once)
106
107
 
107
108
 
108
109
  (0, _addons.useEffect)(function () {
109
- if (parameter !== globals && viewMode === "story") updateGlobals({
110
- pseudo: parameter
111
- });
110
+ if (parameter !== globals && viewMode === "story") {
111
+ channel.emit(_coreEvents.UPDATE_GLOBALS, {
112
+ globals: {
113
+ pseudo: parameter
114
+ }
115
+ });
116
+ }
112
117
  }, [parameter, viewMode]); // Convert selected states to classnames and apply them to the story root element.
113
118
  // Then update each shadow host to redetermine its own pseudo classnames.
114
119
 
@@ -168,7 +173,8 @@ function rewriteStyleSheets(shadowRoot) {
168
173
  selectorText = _step2$value.selectorText;
169
174
 
170
175
  if (matchOne.test(selectorText)) {
171
- var newRule = cssText.replace(selectorText, selectorText.split(", ").flatMap(function (selector) {
176
+ var selectors = (0, _splitSelectors.splitSelectors)(selectorText);
177
+ var newRule = cssText.replace(selectorText, selectors.flatMap(function (selector) {
172
178
  if (selector.includes(".pseudo-")) return [];
173
179
  var states = [];
174
180
  var plainSelector = selector.replace(matchAll, function (_, state) {
@@ -0,0 +1,36 @@
1
+ var isAtRule = function isAtRule(selector) {
2
+ return selector.indexOf("@") === 0;
3
+ };
4
+
5
+ export var splitSelectors = function splitSelectors(selectors) {
6
+ if (isAtRule(selectors)) return [selectors];
7
+ var result = [];
8
+ var parentheses = 0;
9
+ var brackets = 0;
10
+ var selector = "";
11
+
12
+ for (var i = 0, len = selectors.length; i < len; i++) {
13
+ var char = selectors[i];
14
+
15
+ if (char === "(") {
16
+ parentheses += 1;
17
+ } else if (char === ")") {
18
+ parentheses -= 1;
19
+ } else if (char === "[") {
20
+ brackets += 1;
21
+ } else if (char === "]") {
22
+ brackets -= 1;
23
+ } else if (char === ",") {
24
+ if (!parentheses && !brackets) {
25
+ result.push(selector.trim());
26
+ selector = "";
27
+ continue;
28
+ }
29
+ }
30
+
31
+ selector += char;
32
+ }
33
+
34
+ result.push(selector.trim());
35
+ return result;
36
+ };
@@ -0,0 +1,15 @@
1
+ import { splitSelectors } from "./splitSelectors";
2
+ describe("splitSelectors", function () {
3
+ test("handles basic selectors", function () {
4
+ expect(splitSelectors(".a")).toEqual([".a"]);
5
+ expect(splitSelectors(".a, .b")).toEqual([".a", ".b"]);
6
+ });
7
+ test("supports ::slotted and :is", function () {
8
+ expect(splitSelectors("::slotted(:is(button, a):active)")).toEqual(["::slotted(:is(button, a):active)"]);
9
+ expect(splitSelectors("::slotted(:is(button, a):active), ::slotted(:is(button, a):hover)")).toEqual(["::slotted(:is(button, a):active)", "::slotted(:is(button, a):hover)"]);
10
+ });
11
+ test("supports :host", function () {
12
+ expect(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)"]);
13
+ expect(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))"]);
14
+ });
15
+ });
@@ -27,9 +27,11 @@ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToAr
27
27
  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; }
28
28
 
29
29
  /* eslint-env browser */
30
- import { addons, useEffect, useGlobals } from "@storybook/addons";
30
+ import { addons, useEffect } from "@storybook/addons";
31
31
  import { DOCS_RENDERED, STORY_CHANGED, STORY_RENDERED } from "@storybook/core-events";
32
+ import { UPDATE_GLOBALS } from '@storybook/core-events';
32
33
  import { PSEUDO_STATES } from "./constants";
34
+ import { splitSelectors } from "./splitSelectors";
33
35
  var pseudoStates = Object.values(PSEUDO_STATES);
34
36
  var matchOne = new RegExp(":(".concat(pseudoStates.join("|"), ")"));
35
37
  var matchAll = new RegExp(":(".concat(pseudoStates.join("|"), ")"), "g"); // Drops any existing pseudo state classnames that carried over from a previously viewed story
@@ -84,20 +86,21 @@ addons.getChannel().on(STORY_CHANGED, function () {
84
86
  export var withPseudoState = function withPseudoState(StoryFn, _ref5) {
85
87
  var viewMode = _ref5.viewMode,
86
88
  parameters = _ref5.parameters,
87
- id = _ref5.id;
89
+ id = _ref5.id,
90
+ globalsArgs = _ref5.globals;
88
91
  var parameter = parameters.pseudo;
89
-
90
- var _useGlobals = useGlobals(),
91
- _useGlobals2 = _slicedToArray(_useGlobals, 2),
92
- globals = _useGlobals2[0].pseudo,
93
- updateGlobals = _useGlobals2[1]; // Sync parameter to globals, used by the toolbar (only in canvas as this
92
+ var globals = globalsArgs.pseudo;
93
+ var channel = addons.getChannel(); // Sync parameter to globals, used by the toolbar (only in canvas as this
94
94
  // doesn't make sense for docs because many stories are displayed at once)
95
95
 
96
-
97
96
  useEffect(function () {
98
- if (parameter !== globals && viewMode === "story") updateGlobals({
99
- pseudo: parameter
100
- });
97
+ if (parameter !== globals && viewMode === "story") {
98
+ channel.emit(UPDATE_GLOBALS, {
99
+ globals: {
100
+ pseudo: parameter
101
+ }
102
+ });
103
+ }
101
104
  }, [parameter, viewMode]); // Convert selected states to classnames and apply them to the story root element.
102
105
  // Then update each shadow host to redetermine its own pseudo classnames.
103
106
 
@@ -155,7 +158,8 @@ function rewriteStyleSheets(shadowRoot) {
155
158
  selectorText = _step2$value.selectorText;
156
159
 
157
160
  if (matchOne.test(selectorText)) {
158
- var newRule = cssText.replace(selectorText, selectorText.split(", ").flatMap(function (selector) {
161
+ var selectors = splitSelectors(selectorText);
162
+ var newRule = cssText.replace(selectorText, selectors.flatMap(function (selector) {
159
163
  if (selector.includes(".pseudo-")) return [];
160
164
  var states = [];
161
165
  var plainSelector = selector.replace(matchAll, function (_, state) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storybook-addon-pseudo-states",
3
- "version": "1.8.0",
3
+ "version": "1.11.0",
4
4
  "description": "CSS pseudo states for Storybook",
5
5
  "keywords": [
6
6
  "storybook-addons",
@@ -25,6 +25,7 @@
25
25
  "clean": "rimraf ./dist",
26
26
  "start": "concurrently \"yarn storybook --no-manager-cache --quiet\" \"yarn build:dist --watch\"",
27
27
  "storybook": "start-storybook -p 6006",
28
+ "test": "jest src",
28
29
  "chromatic": "chromatic",
29
30
  "build:dist": "babel ./src --out-dir ./dist/cjs && BABEL_ESM=\"true\" babel ./src --out-dir ./dist/esm",
30
31
  "build:storybook": "build-storybook",
@@ -43,6 +44,7 @@
43
44
  "babel-loader": "^8.1.0",
44
45
  "chromatic": "^5.6.0",
45
46
  "concurrently": "^5.3.0",
47
+ "jest": "^27.5.1",
46
48
  "react": "^17.0.1",
47
49
  "react-dom": "^17.0.1",
48
50
  "rimraf": "^3.0.2"