newspack-components 4.6.2 → 4.7.0-alpha.1

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.
Files changed (148) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/colors/colors.module.scss +13 -7
  3. package/dist/cjs/autocomplete-tokenfield/style.scss +4 -2
  4. package/dist/cjs/breadcrumbs/format-count.js +33 -0
  5. package/dist/cjs/breadcrumbs/index.js +78 -20
  6. package/dist/cjs/breadcrumbs/index.test.js +110 -0
  7. package/dist/cjs/breadcrumbs/style.scss +6 -0
  8. package/dist/cjs/button/index.js +41 -17
  9. package/dist/cjs/button/index.test.js +273 -0
  10. package/dist/cjs/card/core-card.js +9 -4
  11. package/dist/cjs/card/core-card.test.js +29 -0
  12. package/dist/cjs/card/index.js +4 -2
  13. package/dist/cjs/card/style-core.scss +59 -0
  14. package/dist/cjs/card-feature/index.js +7 -1
  15. package/dist/cjs/card-feature/index.test.js +92 -0
  16. package/dist/cjs/color-picker/index.js +1 -1
  17. package/dist/cjs/confirm-dialog/index.js +26 -9
  18. package/dist/cjs/confirm-dialog/index.test.js +176 -0
  19. package/dist/cjs/dataviews/index.js +11 -2
  20. package/dist/cjs/divider/index.js +13 -0
  21. package/dist/cjs/drawer/action.js +74 -0
  22. package/dist/cjs/drawer/body.js +79 -0
  23. package/dist/cjs/drawer/close-icon.js +45 -0
  24. package/dist/cjs/drawer/content.js +72 -0
  25. package/dist/cjs/drawer/context.js +23 -0
  26. package/dist/cjs/drawer/context.test.js +43 -0
  27. package/dist/cjs/drawer/divider.js +24 -0
  28. package/dist/cjs/drawer/footer.js +26 -0
  29. package/dist/cjs/drawer/header.js +26 -0
  30. package/dist/cjs/drawer/index.js +42 -0
  31. package/dist/cjs/drawer/index.test.js +1287 -0
  32. package/dist/cjs/drawer/root.js +350 -0
  33. package/dist/cjs/drawer/slots.test.js +422 -0
  34. package/dist/cjs/drawer/style.scss +205 -0
  35. package/dist/cjs/drawer/title.js +54 -0
  36. package/dist/cjs/drawer/types.js +5 -0
  37. package/dist/cjs/drawer/use-exit-animation.js +59 -0
  38. package/dist/cjs/hooks/use-confirm-dialog.js +15 -3
  39. package/dist/cjs/hooks/use-unsaved-changes-dialog.js +19 -4
  40. package/dist/cjs/index.js +28 -1
  41. package/dist/cjs/page/index.js +1 -1
  42. package/dist/cjs/page-control/index.js +82 -0
  43. package/dist/cjs/plugin-settings/SettingsSection.js +7 -1
  44. package/dist/cjs/section-header/index.js +5 -2
  45. package/dist/cjs/section-header/style.scss +25 -12
  46. package/dist/cjs/table-card/index.js +67 -0
  47. package/dist/cjs/table-card/index.test.js +153 -0
  48. package/dist/cjs/with-wizard-screen/style.scss +8 -0
  49. package/dist/cjs/wizard/index.js +102 -38
  50. package/dist/esm/autocomplete-tokenfield/style.scss +4 -2
  51. package/dist/esm/breadcrumbs/format-count.js +27 -0
  52. package/dist/esm/breadcrumbs/index.js +81 -20
  53. package/dist/esm/breadcrumbs/index.test.js +110 -0
  54. package/dist/esm/breadcrumbs/style.scss +6 -0
  55. package/dist/esm/button/index.js +42 -18
  56. package/dist/esm/button/index.test.js +273 -0
  57. package/dist/esm/card/core-card.js +9 -4
  58. package/dist/esm/card/core-card.test.js +29 -0
  59. package/dist/esm/card/index.js +4 -2
  60. package/dist/esm/card/style-core.scss +59 -0
  61. package/dist/esm/card-feature/index.js +8 -2
  62. package/dist/esm/card-feature/index.test.js +96 -0
  63. package/dist/esm/color-picker/index.js +1 -1
  64. package/dist/esm/confirm-dialog/index.js +26 -9
  65. package/dist/esm/confirm-dialog/index.test.js +176 -0
  66. package/dist/esm/dataviews/index.js +11 -2
  67. package/dist/esm/divider/index.js +14 -0
  68. package/dist/esm/drawer/action.js +68 -0
  69. package/dist/esm/drawer/body.js +70 -0
  70. package/dist/esm/drawer/close-icon.js +37 -0
  71. package/dist/esm/drawer/content.js +63 -0
  72. package/dist/esm/drawer/context.js +17 -0
  73. package/dist/esm/drawer/context.test.js +40 -0
  74. package/dist/esm/drawer/divider.js +16 -0
  75. package/dist/esm/drawer/footer.js +18 -0
  76. package/dist/esm/drawer/header.js +18 -0
  77. package/dist/esm/drawer/index.js +35 -0
  78. package/dist/esm/drawer/index.test.js +1285 -0
  79. package/dist/esm/drawer/root.js +342 -0
  80. package/dist/esm/drawer/slots.test.js +422 -0
  81. package/dist/esm/drawer/style.scss +205 -0
  82. package/dist/esm/drawer/title.js +46 -0
  83. package/dist/esm/drawer/types.js +1 -0
  84. package/dist/esm/drawer/use-exit-animation.js +52 -0
  85. package/dist/esm/hooks/use-confirm-dialog.js +15 -3
  86. package/dist/esm/hooks/use-unsaved-changes-dialog.js +20 -5
  87. package/dist/esm/index.js +4 -0
  88. package/dist/esm/page/index.js +1 -1
  89. package/dist/esm/page-control/index.js +82 -0
  90. package/dist/esm/plugin-settings/SettingsSection.js +8 -2
  91. package/dist/esm/section-header/index.js +5 -2
  92. package/dist/esm/section-header/style.scss +25 -12
  93. package/dist/esm/table-card/index.js +60 -0
  94. package/dist/esm/table-card/index.test.js +150 -0
  95. package/dist/esm/with-wizard-screen/style.scss +8 -0
  96. package/dist/esm/wizard/index.js +104 -38
  97. package/package.json +2 -2
  98. package/src/autocomplete-tokenfield/style.scss +4 -2
  99. package/src/breadcrumbs/format-count.js +27 -0
  100. package/src/breadcrumbs/index.js +68 -8
  101. package/src/breadcrumbs/index.test.js +57 -0
  102. package/src/breadcrumbs/style.scss +6 -0
  103. package/src/button/index.test.js +143 -0
  104. package/src/button/index.tsx +32 -7
  105. package/src/card/core-card.js +15 -2
  106. package/src/card/core-card.test.js +19 -0
  107. package/src/card/index.js +3 -0
  108. package/src/card/style-core.scss +59 -0
  109. package/src/card-feature/README.md +4 -0
  110. package/src/card-feature/index.test.js +65 -0
  111. package/src/card-feature/index.tsx +13 -2
  112. package/src/color-picker/index.js +1 -1
  113. package/src/confirm-dialog/README.md +3 -2
  114. package/src/confirm-dialog/index.test.js +146 -0
  115. package/src/confirm-dialog/index.tsx +23 -9
  116. package/src/dataviews/index.tsx +11 -2
  117. package/src/divider/index.js +13 -0
  118. package/src/drawer/README.md +454 -0
  119. package/src/drawer/action.tsx +67 -0
  120. package/src/drawer/body.tsx +60 -0
  121. package/src/drawer/close-icon.tsx +37 -0
  122. package/src/drawer/content.tsx +54 -0
  123. package/src/drawer/context.test.js +31 -0
  124. package/src/drawer/context.ts +25 -0
  125. package/src/drawer/divider.tsx +13 -0
  126. package/src/drawer/footer.tsx +15 -0
  127. package/src/drawer/header.tsx +15 -0
  128. package/src/drawer/index.test.js +1012 -0
  129. package/src/drawer/index.tsx +33 -0
  130. package/src/drawer/root.tsx +328 -0
  131. package/src/drawer/slots.test.js +314 -0
  132. package/src/drawer/style.scss +205 -0
  133. package/src/drawer/title.tsx +40 -0
  134. package/src/drawer/types.ts +79 -0
  135. package/src/drawer/use-exit-animation.ts +46 -0
  136. package/src/hooks/use-confirm-dialog.tsx +14 -3
  137. package/src/hooks/use-unsaved-changes-dialog.tsx +17 -5
  138. package/src/index.js +4 -0
  139. package/src/page/index.js +1 -1
  140. package/src/page-control/index.js +63 -0
  141. package/src/plugin-settings/SettingsSection.js +8 -2
  142. package/src/section-header/index.js +5 -2
  143. package/src/section-header/style.scss +25 -12
  144. package/src/table-card/README.md +100 -0
  145. package/src/table-card/index.test.js +112 -0
  146. package/src/table-card/index.tsx +56 -0
  147. package/src/with-wizard-screen/style.scss +8 -0
  148. package/src/wizard/index.js +95 -34
@@ -65,6 +65,34 @@ describe('ConfirmDialog navigation blocking', function () {
65
65
  expect(replaceSpy).toHaveBeenCalledTimes(1);
66
66
  expect(history.location.pathname).toBe('/');
67
67
  });
68
+
69
+ // v5 keeps a single prompt slot, so an unprompted re-sync would be caught by
70
+ // whichever dialog on the screen did install a blocker.
71
+ it('cancels an unprompted dialog without tripping another blocker', function () {
72
+ var historyRef = {
73
+ current: null
74
+ };
75
+ (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactRouterDom.MemoryRouter, {
76
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(HistoryGrabber, {
77
+ historyRef: historyRef
78
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
79
+ when: true,
80
+ confirmButtonText: "Leave",
81
+ cancelButtonText: "Stay",
82
+ children: "Wizard guard"
83
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
84
+ isOpen: true,
85
+ confirmButtonText: "Discard changes",
86
+ cancelButtonText: "Keep editing",
87
+ children: "Unsaved changes"
88
+ })]
89
+ }));
90
+ var replaceSpy = jest.spyOn(historyRef.current, 'replace');
91
+ cancelNavigation();
92
+ expect(dialog()).not.toBeInTheDocument();
93
+ expect(_react.screen.queryByText('Wizard guard')).not.toBeInTheDocument();
94
+ expect(replaceSpy).not.toHaveBeenCalled();
95
+ });
68
96
  it('replays a blocked push on confirm: re-sync replace first, then push, and re-arms the blocker', function () {
69
97
  var history = renderWithHistory();
70
98
  var replaceSpy = jest.spyOn(history, 'replace');
@@ -170,4 +198,152 @@ describe('ConfirmDialog navigation blocking', function () {
170
198
  expect(history.location.pathname).toBe('/');
171
199
  expect(dialog()).toBeInTheDocument();
172
200
  });
201
+ });
202
+
203
+ // `useHistory` returns undefined outside a wizard, where `newspack-multibranded-site`
204
+ // runs react-router v6 against this package's v5.
205
+ describe('ConfirmDialog without a router', function () {
206
+ var renderUnrouted = function renderUnrouted() {
207
+ var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
208
+ return (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], _objectSpread(_objectSpread({
209
+ isOpen: true,
210
+ confirmButtonText: "Discard changes",
211
+ cancelButtonText: "Keep editing"
212
+ }, props), {}, {
213
+ children: "Unsaved changes"
214
+ })));
215
+ };
216
+ it('cancels with no history to re-sync', function () {
217
+ var onCancel = jest.fn();
218
+ renderUnrouted({
219
+ onCancel: onCancel
220
+ });
221
+ expect(dialog()).toBeInTheDocument();
222
+ cancelNavigation();
223
+ expect(onCancel).toHaveBeenCalled();
224
+ expect(dialog()).not.toBeInTheDocument();
225
+ });
226
+ it('confirms with no history to re-sync', function () {
227
+ var onConfirm = jest.fn();
228
+ renderUnrouted({
229
+ onConfirm: onConfirm
230
+ });
231
+ confirmNavigation();
232
+ expect(onConfirm).toHaveBeenCalled();
233
+ expect(dialog()).not.toBeInTheDocument();
234
+ });
235
+ it('installs no blocker when asked to block without a router', function () {
236
+ expect(function () {
237
+ return renderUnrouted({
238
+ when: true
239
+ });
240
+ }).not.toThrow();
241
+ expect(dialog()).toBeInTheDocument();
242
+ });
243
+ });
244
+ describe('ConfirmDialog controlled by isOpen', function () {
245
+ var tree = function tree(isOpen) {
246
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
247
+ isOpen: isOpen,
248
+ confirmButtonText: "Discard changes",
249
+ cancelButtonText: "Keep editing",
250
+ children: "Unsaved changes"
251
+ });
252
+ };
253
+ it('closes when isOpen goes false', function () {
254
+ var _render = (0, _react.render)(tree(true)),
255
+ rerender = _render.rerender;
256
+ expect(dialog()).toBeInTheDocument();
257
+ rerender(tree(false));
258
+ expect(dialog()).not.toBeInTheDocument();
259
+ });
260
+ it('opens again afterwards', function () {
261
+ var _render2 = (0, _react.render)(tree(true)),
262
+ rerender = _render2.rerender;
263
+ rerender(tree(false));
264
+ rerender(tree(true));
265
+ expect(dialog()).toBeInTheDocument();
266
+ });
267
+ it('leaves a blocked navigation prompt up', function () {
268
+ var historyRef = {
269
+ current: null
270
+ };
271
+ (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactRouterDom.MemoryRouter, {
272
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(HistoryGrabber, {
273
+ historyRef: historyRef
274
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
275
+ when: true,
276
+ isOpen: false,
277
+ confirmButtonText: "Discard changes",
278
+ cancelButtonText: "Keep editing",
279
+ children: "Unsaved changes"
280
+ })]
281
+ }));
282
+ (0, _react.act)(function () {
283
+ return historyRef.current.push('/next');
284
+ });
285
+ expect(dialog()).toBeInTheDocument();
286
+ });
287
+ it('withdraws a blocked navigation prompt when isOpen goes false', function () {
288
+ var historyRef = {
289
+ current: null
290
+ };
291
+ var withOpen = function withOpen(isOpen) {
292
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactRouterDom.MemoryRouter, {
293
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(HistoryGrabber, {
294
+ historyRef: historyRef
295
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
296
+ when: true,
297
+ isOpen: isOpen,
298
+ confirmButtonText: "Discard changes",
299
+ cancelButtonText: "Keep editing",
300
+ children: "Unsaved changes"
301
+ })]
302
+ });
303
+ };
304
+ var _render3 = (0, _react.render)(withOpen(true)),
305
+ rerender = _render3.rerender;
306
+ (0, _react.act)(function () {
307
+ return historyRef.current.push('/next');
308
+ });
309
+ expect(dialog()).toBeInTheDocument();
310
+ rerender(withOpen(false));
311
+ expect(dialog()).not.toBeInTheDocument();
312
+ expect(historyRef.current.location.pathname).toBe('/');
313
+
314
+ // Confirming the next prompt must not replay the abandoned destination.
315
+ rerender(withOpen(true));
316
+ confirmNavigation();
317
+ expect(historyRef.current.location.pathname).toBe('/');
318
+ });
319
+ });
320
+ describe('ConfirmDialog named by a hidden title', function () {
321
+ it('takes its accessible name from the title while hiding the header', function () {
322
+ (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
323
+ isOpen: true,
324
+ hideTitle: true,
325
+ title: "Unsaved changes",
326
+ confirmButtonText: "Discard changes",
327
+ children: "You have unsaved changes that will be lost. Discard changes?"
328
+ }));
329
+ var frame = _react.screen.getByRole('dialog', {
330
+ name: 'Unsaved changes'
331
+ });
332
+ expect(frame).toHaveClass('newspack-modal--hide-title');
333
+ expect(frame.querySelector('.components-modal__header')).toContainElement(_react.screen.getByRole('heading', {
334
+ name: 'Unsaved changes'
335
+ }));
336
+ });
337
+ it('has no accessible name without a title', function () {
338
+ (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_["default"], {
339
+ isOpen: true,
340
+ hideTitle: true,
341
+ confirmButtonText: "Discard changes",
342
+ children: "You have unsaved changes that will be lost. Discard changes?"
343
+ }));
344
+ expect(_react.screen.queryByRole('dialog', {
345
+ name: 'Unsaved changes'
346
+ })).not.toBeInTheDocument();
347
+ expect(_react.screen.getByRole('dialog')).not.toHaveAttribute('aria-labelledby');
348
+ });
173
349
  });
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports["default"] = DataViews;
7
+ exports["default"] = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
10
10
  var _dataviews = require("@wordpress/dataviews");
@@ -35,4 +35,13 @@ function DataViews(_ref) {
35
35
  className: (0, _classnames["default"])('newspack-dataviews', className),
36
36
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataviews.DataViews, _objectSpread({}, props))
37
37
  });
38
- }
38
+ }
39
+
40
+ // The implementation is typed against the `unknown` instantiation because
41
+ // BaseDataViews' conditionally-optional `getItemId` prop cannot be related
42
+ // to a JSX spread while `Item` is an unresolved type parameter. The export
43
+ // re-types it with the generic signature so call sites get item-aware
44
+ // typing for `data`, `fields`, `actions`, `getItemId`, etc. The assertion
45
+ // is verified by the compiler: the generic signature is assignable to the
46
+ // implementation's concrete one.
47
+ var _default = exports["default"] = DataViews;
@@ -20,6 +20,19 @@ var _excluded = ["alignment", "className", "marginBottom", "marginTop", "variant
20
20
  /**
21
21
  * External dependencies
22
22
  */
23
+ /**
24
+ * Divider component.
25
+ *
26
+ * Every prop beyond the documented ones is forwarded to the `hr` element.
27
+ *
28
+ * @param {import('react').ComponentPropsWithoutRef<'hr'> & {
29
+ * alignment?: string,
30
+ * marginBottom?: number|string,
31
+ * marginTop?: number|string,
32
+ * variant?: string,
33
+ * }} props - Component props: the documented options plus any `hr` attribute.
34
+ * @return {JSX.Element} Divider component.
35
+ */
23
36
  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; }
24
37
  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; }
25
38
  var Divider = function Divider(_ref) {
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports["default"] = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
10
+ var _element = require("@wordpress/element");
11
+ var _button = _interopRequireDefault(require("../button"));
12
+ var _context = require("./context");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ var _excluded = ["ariaLabel", "closes", "onClick", "href", "children"];
15
+ /**
16
+ * WordPress dependencies.
17
+ */
18
+ /**
19
+ * Internal dependencies.
20
+ */
21
+ 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; }
22
+ 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; }
23
+ var Action = function Action(_ref) {
24
+ var ariaLabel = _ref.ariaLabel,
25
+ _ref$closes = _ref.closes,
26
+ closes = _ref$closes === void 0 ? false : _ref$closes,
27
+ onClick = _ref.onClick,
28
+ href = _ref.href,
29
+ children = _ref.children,
30
+ buttonProps = (0, _objectWithoutProperties2["default"])(_ref, _excluded);
31
+ // Not useDrawerContext: only `closes` requires the context.
32
+ var context = (0, _element.useContext)(_context.DrawerContext);
33
+
34
+ // `href=""` is still an anchor; a null from a JS caller means no link at all.
35
+ var hasHref = 'string' === typeof href;
36
+ (0, _element.useEffect)(function () {
37
+ if ('production' === process.env.NODE_ENV || !hasHref) {
38
+ return;
39
+ }
40
+ if (onClick || closes) {
41
+ // eslint-disable-next-line no-console
42
+ console.warn('Drawer: an action with `href` cannot also take `onClick` or `closes`, and they are ignored. ' + 'A link that ran the close funnel would navigate away while the unsaved-changes confirmation was still opening.');
43
+ }
44
+ }, [hasHref, onClick, closes]);
45
+ (0, _element.useEffect)(function () {
46
+ if ('production' === process.env.NODE_ENV) {
47
+ return;
48
+ }
49
+ if (typeof children === 'string' && ariaLabel && !ariaLabel.toLowerCase().includes(children.toLowerCase())) {
50
+ // eslint-disable-next-line no-console
51
+ console.warn("Drawer: action ariaLabel \"".concat(ariaLabel, "\" does not contain its visible label \"").concat(children, "\". ") + 'Voice control matches spoken commands against the accessible name (WCAG 2.5.3, Label in Name), ' + 'so ariaLabel must extend the visible text rather than replace it.');
52
+ }
53
+ }, [ariaLabel, children]);
54
+ var handleClick = function handleClick(event) {
55
+ onClick === null || onClick === void 0 || onClick(event);
56
+ if (closes) {
57
+ if (!context) {
58
+ throw new Error('Drawer subcomponents must be rendered inside Drawer.Root.');
59
+ }
60
+ context.requestClose();
61
+ }
62
+ };
63
+
64
+ // Button swallows `href` whenever an onClick is present, so a link supplies none.
65
+ var handlesClick = !hasHref && (!!onClick || closes);
66
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_button["default"], _objectSpread(_objectSpread({
67
+ "aria-label": ariaLabel,
68
+ href: hasHref ? href : undefined,
69
+ onClick: handlesClick ? handleClick : undefined
70
+ }, buttonProps), {}, {
71
+ children: children
72
+ }));
73
+ };
74
+ var _default = exports["default"] = Action;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports["default"] = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _components = require("@wordpress/components");
10
+ var _element = require("@wordpress/element");
11
+ var _i18n = require("@wordpress/i18n");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ /**
14
+ * WordPress dependencies.
15
+ */
16
+ // eslint-disable-line @wordpress/no-unsafe-wp-apis
17
+
18
+ /**
19
+ * Internal dependencies.
20
+ */
21
+
22
+ // Core tab-stops its own container once it overflows; the drawer scrolls here.
23
+ var Body = function Body(_ref) {
24
+ var children = _ref.children;
25
+ var _useState = (0, _element.useState)(null),
26
+ _useState2 = (0, _slicedToArray2["default"])(_useState, 2),
27
+ node = _useState2[0],
28
+ setNode = _useState2[1];
29
+ var _useState3 = (0, _element.useState)(false),
30
+ _useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
31
+ isScrollable = _useState4[0],
32
+ setIsScrollable = _useState4[1];
33
+ (0, _element.useEffect)(function () {
34
+ if (!node) {
35
+ return;
36
+ }
37
+ var measure = function measure() {
38
+ return setIsScrollable(node.scrollHeight > node.clientHeight);
39
+ };
40
+ measure();
41
+ if (!window.ResizeObserver) {
42
+ return;
43
+ }
44
+ var resize = new ResizeObserver(measure);
45
+ var observeChildren = function observeChildren() {
46
+ resize.disconnect();
47
+ resize.observe(node);
48
+ // Border box: a section's padding rides on an inline custom property.
49
+ Array.from(node.children).forEach(function (child) {
50
+ return resize.observe(child, {
51
+ box: 'border-box'
52
+ });
53
+ });
54
+ measure();
55
+ };
56
+ observeChildren();
57
+ var mutation = new MutationObserver(observeChildren);
58
+ mutation.observe(node, {
59
+ childList: true
60
+ });
61
+ return function () {
62
+ resize.disconnect();
63
+ mutation.disconnect();
64
+ };
65
+ }, [node]);
66
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalVStack, {
67
+ ref: setNode,
68
+ className: "newspack-drawer__body",
69
+ spacing: 0,
70
+ justify: "flex-start"
71
+ // A bare div is role=generic, where ARIA prohibits an author name.
72
+ ,
73
+ role: isScrollable ? 'group' : undefined,
74
+ tabIndex: isScrollable ? 0 : undefined,
75
+ "aria-label": isScrollable ? (0, _i18n.__)('Scrollable section', 'newspack-plugin') : undefined,
76
+ children: children
77
+ });
78
+ };
79
+ var _default = exports["default"] = Body;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports["default"] = void 0;
8
+ var _icons = require("@wordpress/icons");
9
+ var _i18n = require("@wordpress/i18n");
10
+ var _classnames = _interopRequireDefault(require("classnames"));
11
+ var _button = _interopRequireDefault(require("../button"));
12
+ var _context = require("./context");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ /**
15
+ * WordPress dependencies.
16
+ */
17
+
18
+ /**
19
+ * External dependencies.
20
+ */
21
+
22
+ /**
23
+ * Internal dependencies.
24
+ */
25
+
26
+ var CloseIcon = function CloseIcon(_ref) {
27
+ var label = _ref.label,
28
+ _ref$icon = _ref.icon,
29
+ icon = _ref$icon === void 0 ? _icons.close : _ref$icon,
30
+ className = _ref.className;
31
+ var _useDrawerContext = (0, _context.useDrawerContext)(),
32
+ requestClose = _useDrawerContext.requestClose,
33
+ title = _useDrawerContext.title;
34
+ var defaultLabel = title !== null && title !== void 0 && title.text ?
35
+ // translators: %s: the drawer's title.
36
+ (0, _i18n.sprintf)((0, _i18n.__)('Close %s', 'newspack-plugin'), title.text) : (0, _i18n.__)('Close', 'newspack-plugin');
37
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_button["default"], {
38
+ className: (0, _classnames["default"])('newspack-drawer__dismiss', className),
39
+ icon: icon,
40
+ size: "small",
41
+ label: label || defaultLabel,
42
+ onClick: requestClose
43
+ });
44
+ };
45
+ var _default = exports["default"] = CloseIcon;
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports["default"] = void 0;
8
+ var _components = require("@wordpress/components");
9
+ var _element = require("@wordpress/element");
10
+ var _classnames = _interopRequireDefault(require("classnames"));
11
+ var _jsxRuntime = require("react/jsx-runtime");
12
+ /**
13
+ * WordPress dependencies.
14
+ */
15
+ // eslint-disable-line @wordpress/no-unsafe-wp-apis
16
+
17
+ /**
18
+ * External dependencies.
19
+ */
20
+
21
+ /**
22
+ * Internal dependencies.
23
+ */
24
+
25
+ // VStack drops non-elements, a lone string aside. A run shares one wrapper so
26
+ // `Edited by { name }` is one row, not three.
27
+ var asRows = function asRows(children) {
28
+ if ('string' === typeof children) {
29
+ return children;
30
+ }
31
+ var rows = [];
32
+ var text = [];
33
+ var flushText = function flushText() {
34
+ if (text.some(function (part) {
35
+ return '' !== String(part).trim();
36
+ })) {
37
+ rows.push(/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
38
+ children: text
39
+ }, "text-".concat(rows.length)));
40
+ }
41
+ text = [];
42
+ };
43
+ _element.Children.toArray(children).forEach(function (child) {
44
+ if ((0, _element.isValidElement)(child)) {
45
+ flushText();
46
+ rows.push(child);
47
+ } else {
48
+ text.push(child);
49
+ }
50
+ });
51
+ flushText();
52
+ return rows;
53
+ };
54
+ var Content = function Content(_ref) {
55
+ var _ref$padding = _ref.padding,
56
+ padding = _ref$padding === void 0 ? 6 : _ref$padding,
57
+ _ref$gap = _ref.gap,
58
+ gap = _ref$gap === void 0 ? 4 : _ref$gap,
59
+ className = _ref.className,
60
+ children = _ref.children;
61
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalVStack, {
62
+ className: (0, _classnames["default"])('newspack-drawer__content', className),
63
+ spacing: gap
64
+ // A custom property, not inline padding, so the stylesheet's seam rules win.
65
+ ,
66
+ style: {
67
+ '--newspack-drawer-content-padding': "".concat(padding * 4, "px")
68
+ },
69
+ children: asRows(children)
70
+ });
71
+ };
72
+ var _default = exports["default"] = Content;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useDrawerContext = exports.DrawerContext = void 0;
7
+ var _element = require("@wordpress/element");
8
+ /**
9
+ * WordPress dependencies.
10
+ */
11
+
12
+ /**
13
+ * Internal dependencies.
14
+ */
15
+
16
+ var DrawerContext = exports.DrawerContext = (0, _element.createContext)(null);
17
+ var useDrawerContext = exports.useDrawerContext = function useDrawerContext() {
18
+ var context = (0, _element.useContext)(DrawerContext);
19
+ if (!context) {
20
+ throw new Error('Drawer subcomponents must be rendered inside Drawer.Root.');
21
+ }
22
+ return context;
23
+ };
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ var _context = require("./context");
4
+ var _react = require("@testing-library/react");
5
+ var _jsxRuntime = require("react/jsx-runtime");
6
+ /**
7
+ * Internal dependencies.
8
+ */
9
+
10
+ /**
11
+ * External dependencies.
12
+ */
13
+
14
+ var Probe = function Probe() {
15
+ var _useDrawerContext = (0, _context.useDrawerContext)(),
16
+ title = _useDrawerContext.title;
17
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
18
+ children: title ? title.text : 'no title'
19
+ });
20
+ };
21
+ describe('useDrawerContext', function () {
22
+ it('returns the provided value', function () {
23
+ (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(_context.DrawerContext.Provider, {
24
+ value: {
25
+ requestClose: function requestClose() {},
26
+ title: {
27
+ id: 't1',
28
+ text: 'Hello'
29
+ },
30
+ setTitle: function setTitle() {}
31
+ },
32
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Probe, {})
33
+ }));
34
+ expect(_react.screen.getByText('Hello')).toBeInTheDocument();
35
+ });
36
+ it('throws outside Drawer.Root', function () {
37
+ var consoleError = jest.spyOn(console, 'error').mockImplementation(function () {});
38
+ expect(function () {
39
+ return (0, _react.render)(/*#__PURE__*/(0, _jsxRuntime.jsx)(Probe, {}));
40
+ }).toThrow('Drawer subcomponents must be rendered inside Drawer.Root.');
41
+ consoleError.mockRestore();
42
+ });
43
+ });
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports["default"] = void 0;
8
+ var _classnames = _interopRequireDefault(require("classnames"));
9
+ var _jsxRuntime = require("react/jsx-runtime");
10
+ /**
11
+ * External dependencies.
12
+ */
13
+
14
+ /**
15
+ * Internal dependencies.
16
+ */
17
+
18
+ var Divider = function Divider(_ref) {
19
+ var className = _ref.className;
20
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("hr", {
21
+ className: (0, _classnames["default"])('newspack-drawer__divider', className)
22
+ });
23
+ };
24
+ var _default = exports["default"] = Divider;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports["default"] = void 0;
8
+ var _classnames = _interopRequireDefault(require("classnames"));
9
+ var _jsxRuntime = require("react/jsx-runtime");
10
+ /**
11
+ * External dependencies.
12
+ */
13
+
14
+ /**
15
+ * Internal dependencies.
16
+ */
17
+
18
+ var Footer = function Footer(_ref) {
19
+ var className = _ref.className,
20
+ children = _ref.children;
21
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
22
+ className: (0, _classnames["default"])('newspack-drawer__footer', className),
23
+ children: children
24
+ });
25
+ };
26
+ var _default = exports["default"] = Footer;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports["default"] = void 0;
8
+ var _classnames = _interopRequireDefault(require("classnames"));
9
+ var _jsxRuntime = require("react/jsx-runtime");
10
+ /**
11
+ * External dependencies.
12
+ */
13
+
14
+ /**
15
+ * Internal dependencies.
16
+ */
17
+
18
+ var Header = function Header(_ref) {
19
+ var className = _ref.className,
20
+ children = _ref.children;
21
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
22
+ className: (0, _classnames["default"])('newspack-drawer__header', className),
23
+ children: children
24
+ });
25
+ };
26
+ var _default = exports["default"] = Header;