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
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
|
|
2
|
+
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 }; })(); }
|
|
3
|
+
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); }
|
|
4
|
+
/**
|
|
5
|
+
* External dependencies.
|
|
6
|
+
*/
|
|
7
|
+
import { act, render, screen } from '@testing-library/react';
|
|
8
|
+
import { MemoryRouter, useHistory } from 'react-router-dom';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Internal dependencies.
|
|
12
|
+
*/
|
|
13
|
+
import Button from './';
|
|
14
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
|
+
var HistoryGrabber = function HistoryGrabber(_ref) {
|
|
16
|
+
var historyRef = _ref.historyRef;
|
|
17
|
+
historyRef.current = useHistory();
|
|
18
|
+
return null;
|
|
19
|
+
};
|
|
20
|
+
var clickButton = /*#__PURE__*/function () {
|
|
21
|
+
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
22
|
+
return _regenerator().w(function (_context2) {
|
|
23
|
+
while (1) switch (_context2.n) {
|
|
24
|
+
case 0:
|
|
25
|
+
_context2.n = 1;
|
|
26
|
+
return act(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
27
|
+
return _regenerator().w(function (_context) {
|
|
28
|
+
while (1) switch (_context.n) {
|
|
29
|
+
case 0:
|
|
30
|
+
screen.getByRole('button', {
|
|
31
|
+
name: 'Save'
|
|
32
|
+
}).click();
|
|
33
|
+
case 1:
|
|
34
|
+
return _context.a(2);
|
|
35
|
+
}
|
|
36
|
+
}, _callee);
|
|
37
|
+
})));
|
|
38
|
+
case 1:
|
|
39
|
+
return _context2.a(2);
|
|
40
|
+
}
|
|
41
|
+
}, _callee2);
|
|
42
|
+
}));
|
|
43
|
+
return function clickButton() {
|
|
44
|
+
return _ref2.apply(this, arguments);
|
|
45
|
+
};
|
|
46
|
+
}();
|
|
47
|
+
describe('Button href with onClick', function () {
|
|
48
|
+
it('awaits the onClick, then pushes the route', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() {
|
|
49
|
+
var historyRef, onClick;
|
|
50
|
+
return _regenerator().w(function (_context3) {
|
|
51
|
+
while (1) switch (_context3.n) {
|
|
52
|
+
case 0:
|
|
53
|
+
historyRef = {
|
|
54
|
+
current: null
|
|
55
|
+
};
|
|
56
|
+
onClick = jest.fn().mockResolvedValue(undefined);
|
|
57
|
+
render(/*#__PURE__*/_jsxs(MemoryRouter, {
|
|
58
|
+
children: [/*#__PURE__*/_jsx(HistoryGrabber, {
|
|
59
|
+
historyRef: historyRef
|
|
60
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
61
|
+
href: "#/next",
|
|
62
|
+
onClick: onClick,
|
|
63
|
+
children: "Save"
|
|
64
|
+
})]
|
|
65
|
+
}));
|
|
66
|
+
_context3.n = 1;
|
|
67
|
+
return clickButton();
|
|
68
|
+
case 1:
|
|
69
|
+
expect(onClick).toHaveBeenCalled();
|
|
70
|
+
// The leading '#' is stripped so the router sees a route, not a fragment.
|
|
71
|
+
expect(historyRef.current.location.pathname).toBe('/next');
|
|
72
|
+
case 2:
|
|
73
|
+
return _context3.a(2);
|
|
74
|
+
}
|
|
75
|
+
}, _callee3);
|
|
76
|
+
})));
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// `useHistory` returns undefined outside a wizard, leaving no route table for the
|
|
80
|
+
// href to name.
|
|
81
|
+
describe('Button href with onClick outside a router', function () {
|
|
82
|
+
// jsdom's real location logs "Not implemented: navigation" rather than
|
|
83
|
+
// navigating, so swap in a plain object to assert against and put the
|
|
84
|
+
// original back afterwards.
|
|
85
|
+
var withStubbedLocation = /*#__PURE__*/function () {
|
|
86
|
+
var _ref5 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(fn) {
|
|
87
|
+
var original;
|
|
88
|
+
return _regenerator().w(function (_context4) {
|
|
89
|
+
while (1) switch (_context4.p = _context4.n) {
|
|
90
|
+
case 0:
|
|
91
|
+
original = window.location;
|
|
92
|
+
delete window.location;
|
|
93
|
+
window.location = {
|
|
94
|
+
href: ''
|
|
95
|
+
};
|
|
96
|
+
_context4.p = 1;
|
|
97
|
+
_context4.n = 2;
|
|
98
|
+
return fn();
|
|
99
|
+
case 2:
|
|
100
|
+
return _context4.a(2, _context4.v);
|
|
101
|
+
case 3:
|
|
102
|
+
_context4.p = 3;
|
|
103
|
+
window.location = original;
|
|
104
|
+
return _context4.f(3);
|
|
105
|
+
case 4:
|
|
106
|
+
return _context4.a(2);
|
|
107
|
+
}
|
|
108
|
+
}, _callee4, null, [[1,, 3, 4]]);
|
|
109
|
+
}));
|
|
110
|
+
return function withStubbedLocation(_x) {
|
|
111
|
+
return _ref5.apply(this, arguments);
|
|
112
|
+
};
|
|
113
|
+
}();
|
|
114
|
+
it('awaits the onClick, then navigates to the href', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee6() {
|
|
115
|
+
var onClick;
|
|
116
|
+
return _regenerator().w(function (_context6) {
|
|
117
|
+
while (1) switch (_context6.n) {
|
|
118
|
+
case 0:
|
|
119
|
+
onClick = jest.fn().mockResolvedValue(undefined);
|
|
120
|
+
_context6.n = 1;
|
|
121
|
+
return withStubbedLocation(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee5() {
|
|
122
|
+
return _regenerator().w(function (_context5) {
|
|
123
|
+
while (1) switch (_context5.n) {
|
|
124
|
+
case 0:
|
|
125
|
+
render(/*#__PURE__*/_jsx(Button, {
|
|
126
|
+
href: "/wp-admin/admin.php?page=next",
|
|
127
|
+
onClick: onClick,
|
|
128
|
+
children: "Save"
|
|
129
|
+
}));
|
|
130
|
+
_context5.n = 1;
|
|
131
|
+
return clickButton();
|
|
132
|
+
case 1:
|
|
133
|
+
expect(onClick).toHaveBeenCalled();
|
|
134
|
+
expect(window.location.href).toBe('/wp-admin/admin.php?page=next');
|
|
135
|
+
case 2:
|
|
136
|
+
return _context5.a(2);
|
|
137
|
+
}
|
|
138
|
+
}, _callee5);
|
|
139
|
+
})));
|
|
140
|
+
case 1:
|
|
141
|
+
return _context6.a(2);
|
|
142
|
+
}
|
|
143
|
+
}, _callee6);
|
|
144
|
+
})));
|
|
145
|
+
it('hands the click event to a combined href and onClick handler', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee8() {
|
|
146
|
+
var onClick;
|
|
147
|
+
return _regenerator().w(function (_context8) {
|
|
148
|
+
while (1) switch (_context8.n) {
|
|
149
|
+
case 0:
|
|
150
|
+
onClick = jest.fn();
|
|
151
|
+
_context8.n = 1;
|
|
152
|
+
return withStubbedLocation(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee7() {
|
|
153
|
+
return _regenerator().w(function (_context7) {
|
|
154
|
+
while (1) switch (_context7.n) {
|
|
155
|
+
case 0:
|
|
156
|
+
render(/*#__PURE__*/_jsx(Button, {
|
|
157
|
+
href: "/wp-admin/admin.php?page=next",
|
|
158
|
+
onClick: onClick,
|
|
159
|
+
children: "Save"
|
|
160
|
+
}));
|
|
161
|
+
_context7.n = 1;
|
|
162
|
+
return clickButton();
|
|
163
|
+
case 1:
|
|
164
|
+
expect(onClick).toHaveBeenCalledWith(expect.objectContaining({
|
|
165
|
+
type: 'click'
|
|
166
|
+
}));
|
|
167
|
+
case 2:
|
|
168
|
+
return _context7.a(2);
|
|
169
|
+
}
|
|
170
|
+
}, _callee7);
|
|
171
|
+
})));
|
|
172
|
+
case 1:
|
|
173
|
+
return _context8.a(2);
|
|
174
|
+
}
|
|
175
|
+
}, _callee8);
|
|
176
|
+
})));
|
|
177
|
+
it('runs an onClick with no href without touching navigation', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee0() {
|
|
178
|
+
var onClick;
|
|
179
|
+
return _regenerator().w(function (_context0) {
|
|
180
|
+
while (1) switch (_context0.n) {
|
|
181
|
+
case 0:
|
|
182
|
+
onClick = jest.fn();
|
|
183
|
+
_context0.n = 1;
|
|
184
|
+
return withStubbedLocation(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee9() {
|
|
185
|
+
return _regenerator().w(function (_context9) {
|
|
186
|
+
while (1) switch (_context9.n) {
|
|
187
|
+
case 0:
|
|
188
|
+
render(/*#__PURE__*/_jsx(Button, {
|
|
189
|
+
onClick: onClick,
|
|
190
|
+
children: "Save"
|
|
191
|
+
}));
|
|
192
|
+
_context9.n = 1;
|
|
193
|
+
return clickButton();
|
|
194
|
+
case 1:
|
|
195
|
+
expect(onClick).toHaveBeenCalled();
|
|
196
|
+
expect(window.location.href).toBe('');
|
|
197
|
+
case 2:
|
|
198
|
+
return _context9.a(2);
|
|
199
|
+
}
|
|
200
|
+
}, _callee9);
|
|
201
|
+
})));
|
|
202
|
+
case 1:
|
|
203
|
+
return _context0.a(2);
|
|
204
|
+
}
|
|
205
|
+
}, _callee0);
|
|
206
|
+
})));
|
|
207
|
+
it('drops a javascript: href and still runs the onClick', /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee10() {
|
|
208
|
+
var warn, onClick;
|
|
209
|
+
return _regenerator().w(function (_context10) {
|
|
210
|
+
while (1) switch (_context10.n) {
|
|
211
|
+
case 0:
|
|
212
|
+
warn = jest.spyOn(console, 'warn').mockImplementation(function () {});
|
|
213
|
+
onClick = jest.fn().mockResolvedValue(undefined);
|
|
214
|
+
_context10.n = 1;
|
|
215
|
+
return withStubbedLocation(/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee1() {
|
|
216
|
+
return _regenerator().w(function (_context1) {
|
|
217
|
+
while (1) switch (_context1.n) {
|
|
218
|
+
case 0:
|
|
219
|
+
// eslint-disable-next-line no-script-url
|
|
220
|
+
render(/*#__PURE__*/_jsx(Button, {
|
|
221
|
+
href: "javascript:alert(1)",
|
|
222
|
+
onClick: onClick,
|
|
223
|
+
children: "Save"
|
|
224
|
+
}));
|
|
225
|
+
_context1.n = 1;
|
|
226
|
+
return clickButton();
|
|
227
|
+
case 1:
|
|
228
|
+
expect(onClick).toHaveBeenCalled();
|
|
229
|
+
expect(window.location.href).toBe('');
|
|
230
|
+
case 2:
|
|
231
|
+
return _context1.a(2);
|
|
232
|
+
}
|
|
233
|
+
}, _callee1);
|
|
234
|
+
})));
|
|
235
|
+
case 1:
|
|
236
|
+
expect(warn).toHaveBeenCalledWith(expect.stringContaining('javascript:'));
|
|
237
|
+
warn.mockRestore();
|
|
238
|
+
case 2:
|
|
239
|
+
return _context10.a(2);
|
|
240
|
+
}
|
|
241
|
+
}, _callee10);
|
|
242
|
+
})));
|
|
243
|
+
});
|
|
244
|
+
describe('Button with a javascript: href alone', function () {
|
|
245
|
+
var link = function link() {
|
|
246
|
+
return screen.getByText('Save').closest('a');
|
|
247
|
+
};
|
|
248
|
+
it('renders no link', function () {
|
|
249
|
+
var warn = jest.spyOn(console, 'warn').mockImplementation(function () {});
|
|
250
|
+
render(/*#__PURE__*/_jsx(Button, {
|
|
251
|
+
href: "JavaScript:alert(1)",
|
|
252
|
+
children: "Save"
|
|
253
|
+
}));
|
|
254
|
+
expect(link()).toBeNull();
|
|
255
|
+
warn.mockRestore();
|
|
256
|
+
});
|
|
257
|
+
it('sees through interleaved control characters', function () {
|
|
258
|
+
var warn = jest.spyOn(console, 'warn').mockImplementation(function () {});
|
|
259
|
+
render(/*#__PURE__*/_jsx(Button, {
|
|
260
|
+
href: 'java\nscript:alert(1)',
|
|
261
|
+
children: "Save"
|
|
262
|
+
}));
|
|
263
|
+
expect(link()).toBeNull();
|
|
264
|
+
warn.mockRestore();
|
|
265
|
+
});
|
|
266
|
+
it('leaves an ordinary href alone', function () {
|
|
267
|
+
render(/*#__PURE__*/_jsx(Button, {
|
|
268
|
+
href: "/wp-admin/admin.php?page=next",
|
|
269
|
+
children: "Save"
|
|
270
|
+
}));
|
|
271
|
+
expect(link()).toHaveAttribute('href', '/wp-admin/admin.php?page=next');
|
|
272
|
+
});
|
|
273
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
3
|
-
var _excluded = ["actions", "actionType", "as", "buttonsCard", "className", "footer", "header", "headerAction", "headerStyle", "childrenStyle", "footerStyle", "disabled", "icon", "iconElement", "iconBackgroundColor", "isActive", "isDraggable", "isFirstTarget", "isLastTarget", "isNarrow", "isSmall", "dragIndex", "onDragCallback", "onToggle", "onHeaderClick", "noBorder", "noMargin", "children", "hasGreyHeader", "hasHeaderBorder"];
|
|
3
|
+
var _excluded = ["actions", "actionType", "as", "buttonsCard", "className", "footer", "header", "headerAction", "headerStyle", "childrenStyle", "footerStyle", "disabled", "icon", "iconElement", "iconBackgroundColor", "isActive", "isDraggable", "isFirstTarget", "isLastTarget", "isNarrow", "isSelectable", "isSmall", "isVertical", "size", "dragIndex", "onDragCallback", "onToggle", "onHeaderClick", "noBorder", "noMargin", "children", "hasGreyHeader", "hasHeaderBorder"];
|
|
4
4
|
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; }
|
|
5
5
|
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) { _defineProperty(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; }
|
|
6
6
|
/**
|
|
@@ -46,7 +46,10 @@ var CoreCard = function CoreCard(_ref) {
|
|
|
46
46
|
isFirstTarget = _ref.isFirstTarget,
|
|
47
47
|
isLastTarget = _ref.isLastTarget,
|
|
48
48
|
isNarrow = _ref.isNarrow,
|
|
49
|
+
isSelectable = _ref.isSelectable,
|
|
49
50
|
isSmall = _ref.isSmall,
|
|
51
|
+
isVertical = _ref.isVertical,
|
|
52
|
+
size = _ref.size,
|
|
50
53
|
dragIndex = _ref.dragIndex,
|
|
51
54
|
_ref$onDragCallback = _ref.onDragCallback,
|
|
52
55
|
onDragCallback = _ref$onDragCallback === void 0 ? function () {} : _ref$onDragCallback,
|
|
@@ -61,8 +64,9 @@ var CoreCard = function CoreCard(_ref) {
|
|
|
61
64
|
_ref$hasHeaderBorder = _ref.hasHeaderBorder,
|
|
62
65
|
hasHeaderBorder = _ref$hasHeaderBorder === void 0 ? true : _ref$hasHeaderBorder,
|
|
63
66
|
otherProps = _objectWithoutProperties(_ref, _excluded);
|
|
64
|
-
var
|
|
65
|
-
var
|
|
67
|
+
var bodySize = isSmall ? undefined : size;
|
|
68
|
+
var classes = classNames('newspack-card--core', className, (buttonsCard || as === 'a') && 'newspack-card--core__buttons-card', (actions === null || actions === void 0 ? void 0 : actions.length) > 0 && 'newspack-card--core__header--has-actions', isDraggable && 'newspack-card--core__is-draggable', isNarrow && 'newspack-card--core__is-narrow', isSmall && 'newspack-card--core__is-small', isSelectable && 'newspack-card--core__is-selectable', bodySize === 'large' && 'newspack-card--core__is-large', isVertical && 'newspack-card--core__is-vertical', (icon || iconElement) && 'newspack-card--core__has-icon', iconBackgroundColor && 'newspack-card--core__has-icon-background-color', isActive && 'newspack-card--core__is-active', disabled && 'newspack-card--core__is-disabled', children && 'newspack-card--core__has-children', noMargin && 'newspack-card--core__no-margin', hasGreyHeader && 'newspack-card--core__has-grey-header');
|
|
69
|
+
var sizeProps = isSmall ? 'small' : size;
|
|
66
70
|
if (buttonsCard || as === 'a') {
|
|
67
71
|
if (!isSmall) {
|
|
68
72
|
sizeProps = 'large';
|
|
@@ -81,7 +85,8 @@ var CoreCard = function CoreCard(_ref) {
|
|
|
81
85
|
var headerIsButton = !!onHeaderClick && !hasInteractiveHeaderChildren;
|
|
82
86
|
return /*#__PURE__*/_jsxs(CardWrapper, _objectSpread(_objectSpread({
|
|
83
87
|
as: as,
|
|
84
|
-
className: classes
|
|
88
|
+
className: classes,
|
|
89
|
+
size: bodySize
|
|
85
90
|
}, otherProps), {}, {
|
|
86
91
|
children: [(header || icon || iconElement) && /*#__PURE__*/_jsxs(CardHeader, {
|
|
87
92
|
as: headerIsButton ? 'button' : undefined,
|
|
@@ -62,4 +62,33 @@ describe('CoreCard', function () {
|
|
|
62
62
|
container = _render5.container;
|
|
63
63
|
expect(getHeader(container).tagName).not.toBe('BUTTON');
|
|
64
64
|
});
|
|
65
|
+
it('gives the body large padding when size is large', function () {
|
|
66
|
+
var _render6 = render(/*#__PURE__*/_jsx(CoreCard, {
|
|
67
|
+
size: "large"
|
|
68
|
+
})),
|
|
69
|
+
container = _render6.container;
|
|
70
|
+
expect(container.querySelector('.newspack-card--core__is-large')).not.toBeNull();
|
|
71
|
+
});
|
|
72
|
+
it('lets isSmall win over a large size', function () {
|
|
73
|
+
var _render7 = render(/*#__PURE__*/_jsx(CoreCard, {
|
|
74
|
+
size: "large",
|
|
75
|
+
isSmall: true
|
|
76
|
+
})),
|
|
77
|
+
container = _render7.container;
|
|
78
|
+
expect(container.querySelector('.newspack-card--core__is-large')).toBeNull();
|
|
79
|
+
expect(container.querySelector('.newspack-card--core__is-small')).not.toBeNull();
|
|
80
|
+
});
|
|
81
|
+
it('marks the card vertical only when isVertical is passed', function () {
|
|
82
|
+
var _render8 = render(/*#__PURE__*/_jsx(CoreCard, {
|
|
83
|
+
header: "Settings"
|
|
84
|
+
})),
|
|
85
|
+
plain = _render8.container;
|
|
86
|
+
expect(plain.querySelector('.newspack-card--core__is-vertical')).toBeNull();
|
|
87
|
+
var _render9 = render(/*#__PURE__*/_jsx(CoreCard, {
|
|
88
|
+
header: "Settings",
|
|
89
|
+
isVertical: true
|
|
90
|
+
})),
|
|
91
|
+
vertical = _render9.container;
|
|
92
|
+
expect(vertical.querySelector('.newspack-card--core__is-vertical')).not.toBeNull();
|
|
93
|
+
});
|
|
65
94
|
});
|
package/dist/esm/card/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import _createClass from "@babel/runtime/helpers/createClass";
|
|
|
5
5
|
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
|
|
6
6
|
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
|
|
7
7
|
import _inherits from "@babel/runtime/helpers/inherits";
|
|
8
|
-
var _excluded = ["buttonsCard", "className", "headerActions", "isNarrow", "isMedium", "isSmall", "isWhite", "noBorder", "__experimentalCoreCard", "__experimentalCoreProps"];
|
|
8
|
+
var _excluded = ["buttonsCard", "className", "headerActions", "isNarrow", "isMedium", "isSmall", "isWhite", "noBorder", "size", "__experimentalCoreCard", "__experimentalCoreProps"];
|
|
9
9
|
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; }
|
|
10
10
|
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) { _defineProperty(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; }
|
|
11
11
|
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
|
|
@@ -52,6 +52,7 @@ var Card = /*#__PURE__*/function (_Component) {
|
|
|
52
52
|
isSmall = _this$props.isSmall,
|
|
53
53
|
isWhite = _this$props.isWhite,
|
|
54
54
|
noBorder = _this$props.noBorder,
|
|
55
|
+
size = _this$props.size,
|
|
55
56
|
__experimentalCoreCard = _this$props.__experimentalCoreCard,
|
|
56
57
|
_this$props$__experim = _this$props.__experimentalCoreProps,
|
|
57
58
|
__experimentalCoreProps = _this$props$__experim === void 0 ? {
|
|
@@ -77,7 +78,8 @@ var Card = /*#__PURE__*/function (_Component) {
|
|
|
77
78
|
isNarrow: isNarrow,
|
|
78
79
|
isSmall: isSmall,
|
|
79
80
|
isWhite: isWhite,
|
|
80
|
-
noBorder: noBorder
|
|
81
|
+
noBorder: noBorder,
|
|
82
|
+
size: size
|
|
81
83
|
}, otherProps), __experimentalCoreProps);
|
|
82
84
|
return /*#__PURE__*/_jsx(CoreCard, _objectSpread({}, props));
|
|
83
85
|
}
|
|
@@ -59,6 +59,19 @@
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
+
&__is-vertical {
|
|
63
|
+
.newspack-card--core__header {
|
|
64
|
+
align-items: flex-start;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
height: 100%;
|
|
67
|
+
justify-content: flex-start;
|
|
68
|
+
}
|
|
69
|
+
.newspack-card--core__header-content {
|
|
70
|
+
display: flex;
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
gap: wp-vars.$grid-unit-10;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
62
75
|
&__no-margin .components-card__body {
|
|
63
76
|
padding: 0 !important;
|
|
64
77
|
}
|
|
@@ -202,6 +215,48 @@
|
|
|
202
215
|
}
|
|
203
216
|
}
|
|
204
217
|
}
|
|
218
|
+
&__is-selectable {
|
|
219
|
+
appearance: none;
|
|
220
|
+
border: 0;
|
|
221
|
+
color: inherit;
|
|
222
|
+
cursor: pointer;
|
|
223
|
+
font: inherit;
|
|
224
|
+
margin: 0;
|
|
225
|
+
padding: 0;
|
|
226
|
+
text-align: inherit;
|
|
227
|
+
|
|
228
|
+
&:hover {
|
|
229
|
+
box-shadow: var(--wp-admin-theme-color) 0 0 0 1px;
|
|
230
|
+
|
|
231
|
+
.newspack-card--core__header,
|
|
232
|
+
.newspack-card--core__header h1,
|
|
233
|
+
.newspack-card--core__header h2,
|
|
234
|
+
.newspack-card--core__header h3,
|
|
235
|
+
.newspack-card--core__header h4,
|
|
236
|
+
.newspack-card--core__header h5,
|
|
237
|
+
.newspack-card--core__header h6 {
|
|
238
|
+
color: var(--wp-admin-theme-color);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
&:focus-visible {
|
|
243
|
+
box-shadow: inset 0 0 0 2px var(--wp-admin-theme-color);
|
|
244
|
+
outline: 2px solid transparent;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
@media ( prefers-contrast: more ) {
|
|
248
|
+
&.newspack-card--core__is-active {
|
|
249
|
+
box-shadow: var(--wp-admin-theme-color) 0 0 0 2px;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@media ( forced-colors: active ) {
|
|
254
|
+
&.newspack-card--core__is-active {
|
|
255
|
+
outline: 3px solid CanvasText;
|
|
256
|
+
outline-offset: -3px;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
205
260
|
&__is-active:not(.newspack-card--core__is-draggable) {
|
|
206
261
|
border-color: var(--wp-admin-theme-color);
|
|
207
262
|
box-shadow: var(--wp-admin-theme-color) 0 0 0 1px;
|
|
@@ -298,6 +353,10 @@
|
|
|
298
353
|
.newspack-card--core__is-small & {
|
|
299
354
|
padding: 16px;
|
|
300
355
|
}
|
|
356
|
+
|
|
357
|
+
.newspack-card--core__is-large & {
|
|
358
|
+
padding: wp-vars.$grid-unit-60;
|
|
359
|
+
}
|
|
301
360
|
.newspack-card--core__no-margin & {
|
|
302
361
|
padding: 0;
|
|
303
362
|
}
|
|
@@ -6,7 +6,7 @@ import classnames from 'classnames';
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
|
-
import { __ } from '@wordpress/i18n';
|
|
9
|
+
import { __, _x, sprintf } from '@wordpress/i18n';
|
|
10
10
|
import { isValidElement } from '@wordpress/element';
|
|
11
11
|
import { DropdownMenu, __experimentalHStack as HStack } from '@wordpress/components'; // eslint-disable-line @wordpress/no-unsafe-wp-apis
|
|
12
12
|
import { moreVertical } from '@wordpress/icons';
|
|
@@ -64,6 +64,9 @@ var CardFeature = function CardFeature(_ref) {
|
|
|
64
64
|
}
|
|
65
65
|
var isConfigureState = enabled && !requirements;
|
|
66
66
|
var buttonLabel = isConfigureState ? configureLabel !== null && configureLabel !== void 0 ? configureLabel : __('Configure', 'newspack-plugin') : enableLabel !== null && enableLabel !== void 0 ? enableLabel : __('Enable', 'newspack-plugin');
|
|
67
|
+
var buttonAccessibleLabel = sprintf(
|
|
68
|
+
// translators: %1$s: the button's visible action label, e.g. "Enable". %2$s: the feature's name. The visible label must stay first (WCAG 2.5.3).
|
|
69
|
+
_x('%1$s %2$s', 'accessible button name: visible action label, then feature name', 'newspack-plugin'), buttonLabel, title);
|
|
67
70
|
var showMoreControls = enabled && !!(moreControls !== null && moreControls !== void 0 && moreControls.length) && (!requirements || requirementsActionable);
|
|
68
71
|
var handleButtonClick = function handleButtonClick() {
|
|
69
72
|
if (isConfigureState) {
|
|
@@ -122,10 +125,13 @@ var CardFeature = function CardFeature(_ref) {
|
|
|
122
125
|
isBusy: busy,
|
|
123
126
|
onClick: handleButtonClick,
|
|
124
127
|
size: "compact",
|
|
128
|
+
"aria-label": buttonAccessibleLabel,
|
|
125
129
|
children: buttonLabel
|
|
126
130
|
}), showMoreControls && /*#__PURE__*/_jsx(DropdownMenu, {
|
|
127
131
|
icon: moreVertical,
|
|
128
|
-
label:
|
|
132
|
+
label: sprintf(
|
|
133
|
+
// translators: %s: the feature's name.
|
|
134
|
+
__('More options for %s', 'newspack-plugin'), title),
|
|
129
135
|
controls: moreControls,
|
|
130
136
|
toggleProps: {
|
|
131
137
|
size: 'compact'
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
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; }
|
|
3
|
+
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) { _defineProperty(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; }
|
|
4
|
+
/**
|
|
5
|
+
* External dependencies.
|
|
6
|
+
*/
|
|
7
|
+
import { render, screen } from '@testing-library/react';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* WordPress dependencies.
|
|
11
|
+
*/
|
|
12
|
+
import { _x } from '@wordpress/i18n';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Internal dependencies.
|
|
16
|
+
*/
|
|
17
|
+
import CardFeature from './index';
|
|
18
|
+
|
|
19
|
+
// The spy lives in the factory: @wordpress/components calls _x while it loads,
|
|
20
|
+
// before a module-scope const would be initialized.
|
|
21
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
22
|
+
jest.mock('@wordpress/i18n', function () {
|
|
23
|
+
var actual = jest.requireActual('@wordpress/i18n');
|
|
24
|
+
return _objectSpread(_objectSpread({}, actual), {}, {
|
|
25
|
+
_x: jest.fn(function (text) {
|
|
26
|
+
return text;
|
|
27
|
+
})
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
describe('CardFeature', function () {
|
|
31
|
+
beforeEach(function () {
|
|
32
|
+
_x.mockClear();
|
|
33
|
+
});
|
|
34
|
+
it('names the feature in the primary button, keeping the visible label first', function () {
|
|
35
|
+
render(/*#__PURE__*/_jsx(CardFeature, {
|
|
36
|
+
title: "Metered Countdown"
|
|
37
|
+
}));
|
|
38
|
+
var button = screen.getByRole('button', {
|
|
39
|
+
name: 'Enable Metered Countdown'
|
|
40
|
+
});
|
|
41
|
+
expect(button).toHaveTextContent('Enable');
|
|
42
|
+
expect(button.getAttribute('aria-label').startsWith(button.textContent)).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
it('carries a custom label into the accessible name', function () {
|
|
45
|
+
render(/*#__PURE__*/_jsx(CardFeature, {
|
|
46
|
+
title: "Subscription retention",
|
|
47
|
+
enableLabel: "Change"
|
|
48
|
+
}));
|
|
49
|
+
expect(screen.getByRole('button', {
|
|
50
|
+
name: 'Change Subscription retention'
|
|
51
|
+
})).toHaveTextContent('Change');
|
|
52
|
+
});
|
|
53
|
+
it('names the feature in the configure state too', function () {
|
|
54
|
+
render(/*#__PURE__*/_jsx(CardFeature, {
|
|
55
|
+
title: "Content Gifting",
|
|
56
|
+
enabled: true
|
|
57
|
+
}));
|
|
58
|
+
expect(screen.getByRole('button', {
|
|
59
|
+
name: 'Configure Content Gifting'
|
|
60
|
+
})).toBeInTheDocument();
|
|
61
|
+
});
|
|
62
|
+
it('names the feature in the More menu', function () {
|
|
63
|
+
render(/*#__PURE__*/_jsx(CardFeature, {
|
|
64
|
+
title: "Content Gifting",
|
|
65
|
+
enabled: true,
|
|
66
|
+
moreControls: [{
|
|
67
|
+
title: 'Disable',
|
|
68
|
+
onClick: function onClick() {}
|
|
69
|
+
}]
|
|
70
|
+
}));
|
|
71
|
+
expect(screen.getByRole('button', {
|
|
72
|
+
name: 'More options for Content Gifting'
|
|
73
|
+
})).toBeInTheDocument();
|
|
74
|
+
});
|
|
75
|
+
it('gives the accessible-name order its own catalogue entry', function () {
|
|
76
|
+
render(/*#__PURE__*/_jsx(CardFeature, {
|
|
77
|
+
title: "Metered Countdown"
|
|
78
|
+
}));
|
|
79
|
+
expect(_x).toHaveBeenCalledWith('%1$s %2$s', 'accessible button name: visible action label, then feature name', 'newspack-plugin');
|
|
80
|
+
});
|
|
81
|
+
it('distinguishes two cards that share a button label', function () {
|
|
82
|
+
render(/*#__PURE__*/_jsxs(_Fragment, {
|
|
83
|
+
children: [/*#__PURE__*/_jsx(CardFeature, {
|
|
84
|
+
title: "Metered Countdown"
|
|
85
|
+
}), /*#__PURE__*/_jsx(CardFeature, {
|
|
86
|
+
title: "Content Gifting"
|
|
87
|
+
})]
|
|
88
|
+
}));
|
|
89
|
+
expect(screen.getByRole('button', {
|
|
90
|
+
name: 'Enable Metered Countdown'
|
|
91
|
+
})).toBeInTheDocument();
|
|
92
|
+
expect(screen.getByRole('button', {
|
|
93
|
+
name: 'Enable Content Gifting'
|
|
94
|
+
})).toBeInTheDocument();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
@@ -28,7 +28,7 @@ var InteractiveDiv = utils.InteractiveDiv;
|
|
|
28
28
|
*
|
|
29
29
|
* @param {Object} props - Component props.
|
|
30
30
|
* @param {JSX.Element|string} props.label - Label for the color picker.
|
|
31
|
-
* @param {JSX.Element|string} props.help
|
|
31
|
+
* @param {JSX.Element|string} [props.help] - Help text for the color picker.
|
|
32
32
|
* @param {string} [props.color] - Default color.
|
|
33
33
|
* @param {Function} props.onChange - Function to call when the color changes.
|
|
34
34
|
* @param {string} [props.className] - Additional class name.
|
|
@@ -72,21 +72,26 @@ function ConfirmDialog(_ref, ref) {
|
|
|
72
72
|
}, [onConfirm, pendingNavigation]);
|
|
73
73
|
var handleOnCancel = useCallback(function () {
|
|
74
74
|
setShowDialog(false);
|
|
75
|
+
var hadPendingNavigation = !!pendingNavigation.current;
|
|
75
76
|
pendingNavigation.current = null;
|
|
76
77
|
// A POP may have moved the URL to the target before it was blocked; put
|
|
77
78
|
// it back so the address bar matches the page the user chose to stay on.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
// Only when this instance blocked it: v5 keeps one prompt slot, so an
|
|
80
|
+
// unprompted replace is caught by whichever dialog did install a blocker.
|
|
81
|
+
if (hadPendingNavigation && history) {
|
|
82
|
+
bypassBlock.current = true;
|
|
83
|
+
try {
|
|
84
|
+
history.replace(history.location);
|
|
85
|
+
} finally {
|
|
86
|
+
bypassBlock.current = false;
|
|
87
|
+
}
|
|
83
88
|
}
|
|
84
89
|
onCancel();
|
|
85
90
|
}, [onCancel, history]);
|
|
86
91
|
|
|
87
92
|
// Block navigation when there are unsaved changes.
|
|
88
93
|
useEffect(function () {
|
|
89
|
-
if (!when) {
|
|
94
|
+
if (!when || !history) {
|
|
90
95
|
return;
|
|
91
96
|
}
|
|
92
97
|
var unblock = history.block(function (location, action) {
|
|
@@ -117,10 +122,22 @@ function ConfirmDialog(_ref, ref) {
|
|
|
117
122
|
return unblock;
|
|
118
123
|
}, [when, history]);
|
|
119
124
|
|
|
120
|
-
//
|
|
125
|
+
// During render: a commit later the dialog would still hold focus while the
|
|
126
|
+
// caller unmounted. The blocker above raises it without touching `isOpen`.
|
|
127
|
+
var _useState3 = useState(isOpen),
|
|
128
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
129
|
+
wasOpen = _useState4[0],
|
|
130
|
+
setWasOpen = _useState4[1];
|
|
131
|
+
if (wasOpen !== isOpen) {
|
|
132
|
+
setWasOpen(isOpen);
|
|
133
|
+
setShowDialog(isOpen);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// A withdrawn prompt releases what the blocker held, as confirm and cancel do.
|
|
137
|
+
// After the commit, so a discarded render cannot drop a live one.
|
|
121
138
|
useEffect(function () {
|
|
122
|
-
if (isOpen) {
|
|
123
|
-
|
|
139
|
+
if (!isOpen) {
|
|
140
|
+
pendingNavigation.current = null;
|
|
124
141
|
}
|
|
125
142
|
}, [isOpen]);
|
|
126
143
|
if (!showDialog) {
|