newspack-components 4.6.3 → 4.7.0-alpha.2
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 +7 -0
- package/colors/colors.module.scss +13 -7
- package/dist/cjs/autocomplete-tokenfield/style.scss +4 -2
- package/dist/cjs/breadcrumbs/format-count.js +33 -0
- package/dist/cjs/breadcrumbs/index.js +78 -20
- package/dist/cjs/breadcrumbs/index.test.js +110 -0
- package/dist/cjs/breadcrumbs/style.scss +6 -0
- package/dist/cjs/button/index.js +41 -17
- package/dist/cjs/button/index.test.js +273 -0
- package/dist/cjs/card/core-card.js +9 -4
- package/dist/cjs/card/core-card.test.js +29 -0
- package/dist/cjs/card/index.js +4 -2
- package/dist/cjs/card/style-core.scss +59 -0
- package/dist/cjs/card-feature/index.js +7 -1
- package/dist/cjs/card-feature/index.test.js +92 -0
- package/dist/cjs/color-picker/index.js +1 -1
- package/dist/cjs/confirm-dialog/index.js +26 -9
- package/dist/cjs/confirm-dialog/index.test.js +176 -0
- package/dist/cjs/dataviews/index.js +11 -2
- package/dist/cjs/divider/index.js +13 -0
- package/dist/cjs/drawer/action.js +74 -0
- package/dist/cjs/drawer/body.js +79 -0
- package/dist/cjs/drawer/close-icon.js +45 -0
- package/dist/cjs/drawer/content.js +72 -0
- package/dist/cjs/drawer/context.js +23 -0
- package/dist/cjs/drawer/context.test.js +43 -0
- package/dist/cjs/drawer/divider.js +24 -0
- package/dist/cjs/drawer/footer.js +26 -0
- package/dist/cjs/drawer/header.js +26 -0
- package/dist/cjs/drawer/index.js +42 -0
- package/dist/cjs/drawer/index.test.js +1287 -0
- package/dist/cjs/drawer/root.js +350 -0
- package/dist/cjs/drawer/slots.test.js +422 -0
- package/dist/cjs/drawer/style.scss +205 -0
- package/dist/cjs/drawer/title.js +54 -0
- package/dist/cjs/drawer/types.js +5 -0
- package/dist/cjs/drawer/use-exit-animation.js +59 -0
- package/dist/cjs/hooks/use-confirm-dialog.js +15 -3
- package/dist/cjs/hooks/use-unsaved-changes-dialog.js +19 -4
- package/dist/cjs/index.js +28 -1
- package/dist/cjs/page/index.js +1 -1
- package/dist/cjs/page-control/index.js +82 -0
- package/dist/cjs/plugin-settings/SettingsSection.js +7 -1
- package/dist/cjs/section-header/index.js +5 -2
- package/dist/cjs/section-header/style.scss +25 -12
- package/dist/cjs/table-card/index.js +67 -0
- package/dist/cjs/table-card/index.test.js +153 -0
- package/dist/cjs/with-wizard-screen/style.scss +8 -0
- package/dist/cjs/wizard/index.js +102 -38
- package/dist/esm/autocomplete-tokenfield/style.scss +4 -2
- package/dist/esm/breadcrumbs/format-count.js +27 -0
- package/dist/esm/breadcrumbs/index.js +81 -20
- package/dist/esm/breadcrumbs/index.test.js +110 -0
- package/dist/esm/breadcrumbs/style.scss +6 -0
- package/dist/esm/button/index.js +42 -18
- package/dist/esm/button/index.test.js +273 -0
- package/dist/esm/card/core-card.js +9 -4
- package/dist/esm/card/core-card.test.js +29 -0
- package/dist/esm/card/index.js +4 -2
- package/dist/esm/card/style-core.scss +59 -0
- package/dist/esm/card-feature/index.js +8 -2
- package/dist/esm/card-feature/index.test.js +96 -0
- package/dist/esm/color-picker/index.js +1 -1
- package/dist/esm/confirm-dialog/index.js +26 -9
- package/dist/esm/confirm-dialog/index.test.js +176 -0
- package/dist/esm/dataviews/index.js +11 -2
- package/dist/esm/divider/index.js +14 -0
- package/dist/esm/drawer/action.js +68 -0
- package/dist/esm/drawer/body.js +70 -0
- package/dist/esm/drawer/close-icon.js +37 -0
- package/dist/esm/drawer/content.js +63 -0
- package/dist/esm/drawer/context.js +17 -0
- package/dist/esm/drawer/context.test.js +40 -0
- package/dist/esm/drawer/divider.js +16 -0
- package/dist/esm/drawer/footer.js +18 -0
- package/dist/esm/drawer/header.js +18 -0
- package/dist/esm/drawer/index.js +35 -0
- package/dist/esm/drawer/index.test.js +1285 -0
- package/dist/esm/drawer/root.js +342 -0
- package/dist/esm/drawer/slots.test.js +422 -0
- package/dist/esm/drawer/style.scss +205 -0
- package/dist/esm/drawer/title.js +46 -0
- package/dist/esm/drawer/types.js +1 -0
- package/dist/esm/drawer/use-exit-animation.js +52 -0
- package/dist/esm/hooks/use-confirm-dialog.js +15 -3
- package/dist/esm/hooks/use-unsaved-changes-dialog.js +20 -5
- package/dist/esm/index.js +4 -0
- package/dist/esm/page/index.js +1 -1
- package/dist/esm/page-control/index.js +82 -0
- package/dist/esm/plugin-settings/SettingsSection.js +8 -2
- package/dist/esm/section-header/index.js +5 -2
- package/dist/esm/section-header/style.scss +25 -12
- package/dist/esm/table-card/index.js +60 -0
- package/dist/esm/table-card/index.test.js +150 -0
- package/dist/esm/with-wizard-screen/style.scss +8 -0
- package/dist/esm/wizard/index.js +104 -38
- package/package.json +2 -2
- package/src/autocomplete-tokenfield/style.scss +4 -2
- package/src/breadcrumbs/format-count.js +27 -0
- package/src/breadcrumbs/index.js +68 -8
- package/src/breadcrumbs/index.test.js +57 -0
- package/src/breadcrumbs/style.scss +6 -0
- package/src/button/index.test.js +143 -0
- package/src/button/index.tsx +32 -7
- package/src/card/core-card.js +15 -2
- package/src/card/core-card.test.js +19 -0
- package/src/card/index.js +3 -0
- package/src/card/style-core.scss +59 -0
- package/src/card-feature/README.md +4 -0
- package/src/card-feature/index.test.js +65 -0
- package/src/card-feature/index.tsx +13 -2
- package/src/color-picker/index.js +1 -1
- package/src/confirm-dialog/README.md +3 -2
- package/src/confirm-dialog/index.test.js +146 -0
- package/src/confirm-dialog/index.tsx +23 -9
- package/src/dataviews/index.tsx +11 -2
- package/src/divider/index.js +13 -0
- package/src/drawer/README.md +454 -0
- package/src/drawer/action.tsx +67 -0
- package/src/drawer/body.tsx +60 -0
- package/src/drawer/close-icon.tsx +37 -0
- package/src/drawer/content.tsx +54 -0
- package/src/drawer/context.test.js +31 -0
- package/src/drawer/context.ts +25 -0
- package/src/drawer/divider.tsx +13 -0
- package/src/drawer/footer.tsx +15 -0
- package/src/drawer/header.tsx +15 -0
- package/src/drawer/index.test.js +1012 -0
- package/src/drawer/index.tsx +33 -0
- package/src/drawer/root.tsx +328 -0
- package/src/drawer/slots.test.js +314 -0
- package/src/drawer/style.scss +205 -0
- package/src/drawer/title.tsx +40 -0
- package/src/drawer/types.ts +79 -0
- package/src/drawer/use-exit-animation.ts +46 -0
- package/src/hooks/use-confirm-dialog.tsx +14 -3
- package/src/hooks/use-unsaved-changes-dialog.tsx +17 -5
- package/src/index.js +4 -0
- package/src/page/index.js +1 -1
- package/src/page-control/index.js +63 -0
- package/src/plugin-settings/SettingsSection.js +8 -2
- package/src/section-header/index.js +5 -2
- package/src/section-header/style.scss +25 -12
- package/src/table-card/README.md +100 -0
- package/src/table-card/index.test.js +112 -0
- package/src/table-card/index.tsx +56 -0
- package/src/with-wizard-screen/style.scss +8 -0
- package/src/wizard/index.js +95 -34
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# newspack-components [4.7.0-alpha.2](https://github.com/Automattic/newspack-workspace/compare/newspack-components@4.7.0-alpha.1...newspack-components@4.7.0-alpha.2) (2026-08-20)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **wizard:** refetch data after the installer adds required plugins ([#893](https://github.com/Automattic/newspack-workspace/issues/893)) ([6b23902](https://github.com/Automattic/newspack-workspace/commit/6b239026e4a3dad5118443d9bc384d53248f38fa))
|
|
7
|
+
|
|
1
8
|
## newspack-components [4.6.3](https://github.com/Automattic/newspack-workspace/compare/newspack-components@4.6.2...newspack-components@4.6.3) (2026-08-20)
|
|
2
9
|
|
|
3
10
|
|
|
@@ -7,12 +7,18 @@
|
|
|
7
7
|
@use "sass:math";
|
|
8
8
|
|
|
9
9
|
@function to-rgb($color) {
|
|
10
|
-
@return color.channel($color, "red", $space: rgb) + ", " + color.channel($color, "green", $space: rgb) + ", " +
|
|
10
|
+
@return color.channel($color, "red", $space: rgb) + ", " + color.channel($color, "green", $space: rgb) + ", " +
|
|
11
|
+
color.channel($color, "blue", $space: rgb);
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
@function to-rgba($color) {
|
|
14
15
|
$alpha: math.div(math.round(color.channel($color, "alpha") * 100), 100);
|
|
15
|
-
@return rgba(
|
|
16
|
+
@return rgba(
|
|
17
|
+
color.channel($color, "red", $space: rgb),
|
|
18
|
+
color.channel($color, "green", $space: rgb),
|
|
19
|
+
color.channel($color, "blue", $space: rgb),
|
|
20
|
+
$alpha
|
|
21
|
+
);
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
// Primary: Hex
|
|
@@ -75,7 +81,7 @@ $secondary-1000--rgb: to-rgb($secondary-1000);
|
|
|
75
81
|
$tertiary-000: #fff4f6;
|
|
76
82
|
$tertiary-050: #fee8ed;
|
|
77
83
|
$tertiary-100: #fedbe3;
|
|
78
|
-
$tertiary-200: #
|
|
84
|
+
$tertiary-200: #fdced8;
|
|
79
85
|
$tertiary-300: #fdbfcd;
|
|
80
86
|
$tertiary-400: #fcaec0;
|
|
81
87
|
$tertiary-500: #fc9bb3;
|
|
@@ -161,13 +167,13 @@ $neutral-1000--rgb: to-rgb($neutral-1000);
|
|
|
161
167
|
$overlay-000: #0000000d;
|
|
162
168
|
$overlay-050: #0000001a;
|
|
163
169
|
$overlay-100: #00000026;
|
|
164
|
-
$overlay-200: #
|
|
170
|
+
$overlay-200: #0003;
|
|
165
171
|
$overlay-300: #0000004d;
|
|
166
|
-
$overlay-400: #
|
|
172
|
+
$overlay-400: #0006;
|
|
167
173
|
$overlay-500: #00000080;
|
|
168
|
-
$overlay-600: #
|
|
174
|
+
$overlay-600: #0009;
|
|
169
175
|
$overlay-700: #000000b3;
|
|
170
|
-
$overlay-800: #
|
|
176
|
+
$overlay-800: #000c;
|
|
171
177
|
$overlay-900: #000000e6;
|
|
172
178
|
$overlay-1000: #000000f2;
|
|
173
179
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
@use "~@wordpress/base-styles/colors" as wp-colors;
|
|
6
|
+
@use "~@wordpress/base-styles/variables" as wp-vars;
|
|
6
7
|
|
|
7
8
|
.newspack-autocomplete-tokenfield {
|
|
8
9
|
.components-spinner {
|
|
@@ -34,8 +35,9 @@
|
|
|
34
35
|
|
|
35
36
|
.newspack-autocomplete-tokenfield__help {
|
|
36
37
|
color: wp-colors.$gray-700;
|
|
37
|
-
font-size:
|
|
38
|
-
|
|
38
|
+
font-size: wp-vars.$helptext-font-size;
|
|
39
|
+
line-height: wp-vars.$default-line-height;
|
|
40
|
+
margin: wp-vars.$grid-unit-10 0 0;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
.components-form-token-field__suggestions-list {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.formatCount = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Group a number for the site's locale rather than the browser's, so a crumb's count
|
|
9
|
+
* matches both the translated phrasing beside it and every server-rendered figure on
|
|
10
|
+
* the page. Callers that build their own `countLabel` share this so the visible count
|
|
11
|
+
* and the spoken one are grouped the same way.
|
|
12
|
+
*
|
|
13
|
+
* WordPress ships locales `Intl` rejects outright — `pt_PT_ao90` yields the BCP-47
|
|
14
|
+
* tag `pt-PT-ao90`, whose four-character variant subtag must start with a digit — so
|
|
15
|
+
* the tag is shortened a subtag at a time until one is accepted. Falling straight
|
|
16
|
+
* through to the browser's locale would group `1,234` beside a server-rendered
|
|
17
|
+
* `1.234`, which is the divergence this helper exists to prevent.
|
|
18
|
+
*
|
|
19
|
+
* @param {number} count Number to format.
|
|
20
|
+
* @return {string} The grouped number.
|
|
21
|
+
*/
|
|
22
|
+
var formatCount = exports.formatCount = function formatCount(count) {
|
|
23
|
+
var lang = typeof document !== 'undefined' && document.documentElement.lang || '';
|
|
24
|
+
var subtags = lang.replace(/_/g, '-').split('-').filter(Boolean);
|
|
25
|
+
while (subtags.length) {
|
|
26
|
+
try {
|
|
27
|
+
return Number(count).toLocaleString(subtags.join('-'));
|
|
28
|
+
} catch (_unused) {
|
|
29
|
+
subtags.pop();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return Number(count).toLocaleString();
|
|
33
|
+
};
|
|
@@ -1,20 +1,72 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
3
4
|
Object.defineProperty(exports, "__esModule", {
|
|
4
5
|
value: true
|
|
5
6
|
});
|
|
6
7
|
exports["default"] = void 0;
|
|
8
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
7
9
|
var _i18n = require("@wordpress/i18n");
|
|
8
10
|
var _ui = require("@wordpress/ui");
|
|
11
|
+
var _formatCount = require("./format-count");
|
|
9
12
|
require("./style.scss");
|
|
10
13
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
11
|
-
|
|
14
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
15
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /**
|
|
12
16
|
* WordPress dependencies.
|
|
17
|
+
*/ /**
|
|
18
|
+
* Internal dependencies.
|
|
19
|
+
*/ /**
|
|
20
|
+
* A crumb's count, shown in parentheses and spoken as a phrase.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} props
|
|
23
|
+
* @param {number} [props.count] Item count.
|
|
24
|
+
* @param {string} [props.countLabel] Translated accessible phrasing for the count.
|
|
25
|
+
* @return {JSX.Element|null} The count, or null when the crumb carries none.
|
|
13
26
|
*/
|
|
27
|
+
var CrumbCount = function CrumbCount(_ref) {
|
|
28
|
+
var count = _ref.count,
|
|
29
|
+
countLabel = _ref.countLabel;
|
|
30
|
+
if (!Number.isFinite(count)) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
var formatted = (0, _formatCount.formatCount)(count);
|
|
34
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("span", {
|
|
35
|
+
className: "newspack-breadcrumbs__count",
|
|
36
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
37
|
+
"aria-hidden": "true",
|
|
38
|
+
children: "(".concat(formatted, ")")
|
|
39
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
40
|
+
className: "screen-reader-text",
|
|
41
|
+
children: countLabel || (0, _i18n.sprintf)(/* translators: %s: number of items in the current view. */
|
|
42
|
+
(0, _i18n._n)('%s item', '%s items', count, 'newspack-plugin'), formatted)
|
|
43
|
+
})]
|
|
44
|
+
});
|
|
45
|
+
};
|
|
14
46
|
|
|
15
47
|
/**
|
|
16
|
-
*
|
|
48
|
+
* A crumb's label, with its count appended when the item carries one.
|
|
49
|
+
*
|
|
50
|
+
* @param {Object} props
|
|
51
|
+
* @param {string} props.label Crumb label.
|
|
52
|
+
* @param {number} [props.count] Item count to annotate the label with.
|
|
53
|
+
* @param {string} [props.countLabel] Translated accessible phrasing for the count.
|
|
54
|
+
* @return {JSX.Element|string} The label, annotated when a count is present.
|
|
17
55
|
*/
|
|
56
|
+
var CrumbLabel = function CrumbLabel(_ref2) {
|
|
57
|
+
var label = _ref2.label,
|
|
58
|
+
count = _ref2.count,
|
|
59
|
+
countLabel = _ref2.countLabel;
|
|
60
|
+
if (!Number.isFinite(count)) {
|
|
61
|
+
return label;
|
|
62
|
+
}
|
|
63
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
64
|
+
children: [label, " ", /*#__PURE__*/(0, _jsxRuntime.jsx)(CrumbCount, {
|
|
65
|
+
count: count,
|
|
66
|
+
countLabel: countLabel
|
|
67
|
+
})]
|
|
68
|
+
});
|
|
69
|
+
};
|
|
18
70
|
|
|
19
71
|
/**
|
|
20
72
|
* Newspack breadcrumb trail.
|
|
@@ -25,11 +77,12 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
25
77
|
* component needs no router context.
|
|
26
78
|
*
|
|
27
79
|
* @param {Object} props
|
|
28
|
-
* @param {Array} props.items Trail items: `{ label, url? }`.
|
|
80
|
+
* @param {Array} props.items Trail items: `{ label, url?, count?, countLabel? }`.
|
|
29
81
|
* @return {JSX.Element|null} Breadcrumbs component.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
|
|
82
|
+
*/
|
|
83
|
+
var Breadcrumbs = function Breadcrumbs(_ref3) {
|
|
84
|
+
var _ref3$items = _ref3.items,
|
|
85
|
+
items = _ref3$items === void 0 ? [] : _ref3$items;
|
|
33
86
|
if (!items.length) {
|
|
34
87
|
return null;
|
|
35
88
|
}
|
|
@@ -44,21 +97,26 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
44
97
|
className: "newspack-breadcrumbs__list",
|
|
45
98
|
children: [preceding.map(function (item, index) {
|
|
46
99
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("li", {
|
|
47
|
-
children: [item.url ?
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}),
|
|
58
|
-
|
|
100
|
+
children: [item.url ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
101
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_ui.Text, {
|
|
102
|
+
variant: "body-lg",
|
|
103
|
+
render: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ui.Link, {
|
|
104
|
+
tone: "neutral",
|
|
105
|
+
render: /*#__PURE__*/(0, _jsxRuntime.jsx)("a", {
|
|
106
|
+
href: item.url
|
|
107
|
+
})
|
|
108
|
+
}),
|
|
109
|
+
children: item.label
|
|
110
|
+
}), Number.isFinite(item.count) && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_ui.Text, {
|
|
111
|
+
variant: "body-lg",
|
|
112
|
+
children: [' ', /*#__PURE__*/(0, _jsxRuntime.jsx)(CrumbCount, {
|
|
113
|
+
count: item.count,
|
|
114
|
+
countLabel: item.countLabel
|
|
115
|
+
})]
|
|
116
|
+
})]
|
|
59
117
|
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_ui.Text, {
|
|
60
118
|
variant: "body-lg",
|
|
61
|
-
children: item
|
|
119
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(CrumbLabel, _objectSpread({}, item))
|
|
62
120
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_ui.Text, {
|
|
63
121
|
variant: "body-lg",
|
|
64
122
|
"aria-hidden": "true",
|
|
@@ -71,7 +129,7 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
71
129
|
variant: "heading-lg",
|
|
72
130
|
render: /*#__PURE__*/(0, _jsxRuntime.jsx)("h1", {}),
|
|
73
131
|
className: "newspack-breadcrumbs__current",
|
|
74
|
-
children: last
|
|
132
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(CrumbLabel, _objectSpread({}, last))
|
|
75
133
|
})
|
|
76
134
|
})]
|
|
77
135
|
})
|
|
@@ -13,6 +13,10 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
describe('Breadcrumbs', function () {
|
|
16
|
+
// Unconditional, so a failing assertion cannot leak a language into later tests.
|
|
17
|
+
afterEach(function () {
|
|
18
|
+
document.documentElement.lang = '';
|
|
19
|
+
});
|
|
16
20
|
it('renders the last item as the only h1 and never a link', function () {
|
|
17
21
|
(0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
|
|
18
22
|
items: [{
|
|
@@ -106,4 +110,110 @@ describe('Breadcrumbs', function () {
|
|
|
106
110
|
container = _render3.container;
|
|
107
111
|
expect(container.querySelector('nav')).not.toBeInTheDocument();
|
|
108
112
|
});
|
|
113
|
+
it('annotates a crumb with its count, hiding the parens from assistive tech', function () {
|
|
114
|
+
var _render4 = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
|
|
115
|
+
items: [{
|
|
116
|
+
label: 'Plans'
|
|
117
|
+
}, {
|
|
118
|
+
label: 'Subscriptions',
|
|
119
|
+
count: 33
|
|
120
|
+
}]
|
|
121
|
+
})),
|
|
122
|
+
container = _render4.container;
|
|
123
|
+
var count = container.querySelector('.newspack-breadcrumbs__count');
|
|
124
|
+
expect(count).not.toBeNull();
|
|
125
|
+
expect(count.querySelector('[aria-hidden="true"]')).toHaveTextContent('(33)');
|
|
126
|
+
expect(count.querySelector('.screen-reader-text')).toHaveTextContent('33 items');
|
|
127
|
+
expect(_react.screen.getByRole('heading', {
|
|
128
|
+
level: 1
|
|
129
|
+
})).toContainElement(count);
|
|
130
|
+
});
|
|
131
|
+
it('announces a single item in the singular', function () {
|
|
132
|
+
var _render5 = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
|
|
133
|
+
items: [{
|
|
134
|
+
label: 'Donations',
|
|
135
|
+
count: 1
|
|
136
|
+
}]
|
|
137
|
+
})),
|
|
138
|
+
container = _render5.container;
|
|
139
|
+
expect(container.querySelector('.newspack-breadcrumbs__count .screen-reader-text').textContent).toBe('1 item');
|
|
140
|
+
});
|
|
141
|
+
it('renders a zero count rather than dropping the annotation', function () {
|
|
142
|
+
var _render6 = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
|
|
143
|
+
items: [{
|
|
144
|
+
label: 'Donations',
|
|
145
|
+
count: 0
|
|
146
|
+
}]
|
|
147
|
+
})),
|
|
148
|
+
container = _render6.container;
|
|
149
|
+
expect(container.querySelector('.newspack-breadcrumbs__count [aria-hidden="true"]')).toHaveTextContent('(0)');
|
|
150
|
+
});
|
|
151
|
+
it('omits the annotation when a crumb carries no usable count', function () {
|
|
152
|
+
var _render7 = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
|
|
153
|
+
items: [{
|
|
154
|
+
label: 'Plans'
|
|
155
|
+
}, {
|
|
156
|
+
label: 'Bundles',
|
|
157
|
+
count: undefined
|
|
158
|
+
}]
|
|
159
|
+
})),
|
|
160
|
+
container = _render7.container;
|
|
161
|
+
expect(container.querySelector('.newspack-breadcrumbs__count')).toBeNull();
|
|
162
|
+
expect(_react.screen.getByRole('heading', {
|
|
163
|
+
level: 1
|
|
164
|
+
})).toHaveTextContent('Bundles');
|
|
165
|
+
});
|
|
166
|
+
it('prefers a supplied countLabel for the accessible phrasing', function () {
|
|
167
|
+
var _render8 = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
|
|
168
|
+
items: [{
|
|
169
|
+
label: 'Subscribers',
|
|
170
|
+
count: 85,
|
|
171
|
+
countLabel: '85 subscribers total'
|
|
172
|
+
}]
|
|
173
|
+
})),
|
|
174
|
+
container = _render8.container;
|
|
175
|
+
expect(container.querySelector('.newspack-breadcrumbs__count .screen-reader-text')).toHaveTextContent('85 subscribers total');
|
|
176
|
+
});
|
|
177
|
+
it('annotates a linked crumb outside the link, so the link is named for its destination', function () {
|
|
178
|
+
var _render9 = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
|
|
179
|
+
items: [{
|
|
180
|
+
label: 'Plans',
|
|
181
|
+
url: '#/',
|
|
182
|
+
count: 12
|
|
183
|
+
}, {
|
|
184
|
+
label: 'Add plan'
|
|
185
|
+
}]
|
|
186
|
+
})),
|
|
187
|
+
container = _render9.container;
|
|
188
|
+
var link = _react.screen.getByRole('link', {
|
|
189
|
+
name: 'Plans'
|
|
190
|
+
});
|
|
191
|
+
expect(link.getAttribute('href')).toBe('#/');
|
|
192
|
+
expect(link).not.toHaveTextContent('(12)');
|
|
193
|
+
var count = container.querySelector('.newspack-breadcrumbs__count');
|
|
194
|
+
expect(count.querySelector('[aria-hidden="true"]')).toHaveTextContent('(12)');
|
|
195
|
+
expect(link).not.toContainElement(count);
|
|
196
|
+
});
|
|
197
|
+
it('groups the count for the document language', function () {
|
|
198
|
+
document.documentElement.lang = 'de-DE';
|
|
199
|
+
var _render0 = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
|
|
200
|
+
items: [{
|
|
201
|
+
label: 'Abonnenten',
|
|
202
|
+
count: 1234
|
|
203
|
+
}]
|
|
204
|
+
})),
|
|
205
|
+
container = _render0.container;
|
|
206
|
+
expect(container.querySelector('.newspack-breadcrumbs__count [aria-hidden="true"]')).toHaveTextContent('(1.234)');
|
|
207
|
+
});
|
|
208
|
+
it('falls back to the default grouping when the document language is not a locale Intl accepts', function () {
|
|
209
|
+
document.documentElement.lang = 'pt-PT-ao90';
|
|
210
|
+
var _render1 = (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
|
|
211
|
+
items: [{
|
|
212
|
+
label: 'Planos',
|
|
213
|
+
count: 1234
|
|
214
|
+
}]
|
|
215
|
+
})),
|
|
216
|
+
container = _render1.container;
|
|
217
|
+
expect(container.querySelector('.newspack-breadcrumbs__count [aria-hidden="true"]').textContent).toMatch(/^\(1\D?234\)$/);
|
|
218
|
+
});
|
|
109
219
|
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
@use "~@wordpress/base-styles/colors" as wp-colors;
|
|
2
|
+
@use "~@wordpress/base-styles/variables" as wp-vars;
|
|
2
3
|
|
|
3
4
|
.newspack-breadcrumbs__list {
|
|
4
5
|
list-style: none;
|
|
@@ -26,6 +27,11 @@
|
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
.newspack-breadcrumbs__count {
|
|
31
|
+
color: var(--wpds-color-foreground-content-neutral-weak, #{wp-colors.$gray-700});
|
|
32
|
+
font-weight: wp-vars.$font-weight-regular;
|
|
33
|
+
}
|
|
34
|
+
|
|
29
35
|
.newspack-breadcrumbs__separator {
|
|
30
36
|
color: var(--wpds-color-stroke-surface-neutral, #dbdbdb);
|
|
31
37
|
margin: 0 var(--wpds-dimension-gap-sm, 8px);
|
package/dist/cjs/button/index.js
CHANGED
|
@@ -29,6 +29,11 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
29
29
|
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
30
30
|
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
31
31
|
var useHistory = _router["default"].useHistory;
|
|
32
|
+
// Control characters are stripped first, as browsers do, so `java\nscript:`
|
|
33
|
+
// cannot slip past.
|
|
34
|
+
var isJavascriptHref = function isJavascriptHref(href) {
|
|
35
|
+
return 'string' === typeof href && href.replace(/[\u0000-\u0020]/g, '').toLowerCase().startsWith('javascript:');
|
|
36
|
+
};
|
|
32
37
|
var Button = function Button(_ref) {
|
|
33
38
|
var href = _ref.href,
|
|
34
39
|
_ref$loading = _ref.loading,
|
|
@@ -40,26 +45,45 @@ var Button = function Button(_ref) {
|
|
|
40
45
|
_useState2 = (0, _slicedToArray2["default"])(_useState, 2),
|
|
41
46
|
isAwaitingOnClick = _useState2[0],
|
|
42
47
|
setIsAwaitingOnClick = _useState2[1];
|
|
48
|
+
var isUnsafeHref = isJavascriptHref(href);
|
|
49
|
+
var safeHref = isUnsafeHref ? undefined : href;
|
|
50
|
+
(0, _element.useEffect)(function () {
|
|
51
|
+
if ('production' === process.env.NODE_ENV || !isUnsafeHref) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// eslint-disable-next-line no-console
|
|
55
|
+
console.warn('Button: a `javascript:` href is not a link and has been dropped.');
|
|
56
|
+
}, [isUnsafeHref]);
|
|
43
57
|
|
|
44
58
|
// If both onClick and href are present, await the onClick action an then redirect.
|
|
45
|
-
if (
|
|
46
|
-
otherProps.onClick = /*#__PURE__*/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
if (safeHref && onClick) {
|
|
60
|
+
otherProps.onClick = /*#__PURE__*/function () {
|
|
61
|
+
var _ref2 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator().m(function _callee(event) {
|
|
62
|
+
return _regenerator().w(function (_context) {
|
|
63
|
+
while (1) switch (_context.n) {
|
|
64
|
+
case 0:
|
|
65
|
+
setIsAwaitingOnClick(true);
|
|
66
|
+
_context.n = 1;
|
|
67
|
+
return onClick(event);
|
|
68
|
+
case 1:
|
|
69
|
+
setIsAwaitingOnClick(false);
|
|
70
|
+
// Outside a Router the href can only mean a real URL.
|
|
71
|
+
if (history) {
|
|
72
|
+
history.push(safeHref.replace('#', ''));
|
|
73
|
+
} else {
|
|
74
|
+
window.location.href = safeHref;
|
|
75
|
+
}
|
|
76
|
+
case 2:
|
|
77
|
+
return _context.a(2);
|
|
78
|
+
}
|
|
79
|
+
}, _callee);
|
|
80
|
+
}));
|
|
81
|
+
return function (_x) {
|
|
82
|
+
return _ref2.apply(this, arguments);
|
|
83
|
+
};
|
|
84
|
+
}();
|
|
61
85
|
} else {
|
|
62
|
-
otherProps.href =
|
|
86
|
+
otherProps.href = safeHref;
|
|
63
87
|
otherProps.onClick = onClick;
|
|
64
88
|
}
|
|
65
89
|
if (isAwaitingOnClick) {
|