newspack-components 3.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/colors/colors.module.scss +277 -0
  2. package/copy-styles.js +8 -1
  3. package/dist/cjs/action-card/action-card.d.js +5 -0
  4. package/dist/cjs/action-card/index.js +282 -187
  5. package/dist/cjs/action-card/style.scss +142 -44
  6. package/dist/cjs/autocomplete-tokenfield/index.js +6 -2
  7. package/dist/cjs/box-contrast/index.js +49 -0
  8. package/dist/cjs/button/index.js +1 -1
  9. package/dist/cjs/button-props/button-props.js +41 -0
  10. package/dist/cjs/button-props/index.js +13 -0
  11. package/dist/cjs/color-picker/index.js +11 -0
  12. package/dist/cjs/custom-select-control/style.scss +7 -12
  13. package/dist/cjs/footer/index.js +17 -24
  14. package/dist/cjs/footer/style.scss +0 -36
  15. package/dist/cjs/handoff-message/index.js +0 -3
  16. package/dist/cjs/hooks/useObjectState.js +9 -0
  17. package/dist/cjs/hooks/useObjectState.test.js +5 -5
  18. package/dist/cjs/index.js +7 -21
  19. package/dist/cjs/modal/index.js +4 -1
  20. package/dist/cjs/modal/style.scss +18 -7
  21. package/dist/cjs/newspack-icon/index.js +2 -2
  22. package/dist/cjs/newspack-icon/style.scss +3 -5
  23. package/dist/cjs/notice/index.js +1 -2
  24. package/dist/cjs/notice/style.scss +11 -9
  25. package/dist/cjs/plugin-installer/index.js +3 -3
  26. package/dist/cjs/plugin-settings/SettingsSection.js +2 -0
  27. package/dist/cjs/plugin-settings/index.js +4 -1
  28. package/dist/cjs/plugin-toggle/index.js +2 -0
  29. package/dist/cjs/popover/style.scss +5 -6
  30. package/dist/cjs/progress-bar/index.test.js +1 -2
  31. package/dist/cjs/progress-bar/style.scss +1 -2
  32. package/dist/cjs/proxied-imports/router.js +1 -2
  33. package/dist/cjs/radio-control/style.scss +4 -10
  34. package/dist/cjs/section-header/index.js +21 -1
  35. package/dist/cjs/select-control/ButtonGroupControl.js +2 -0
  36. package/dist/cjs/settings/SettingsCard.js +2 -6
  37. package/dist/cjs/sortable-newsletter-list-control/index.js +7 -5
  38. package/dist/cjs/sortable-newsletter-list-control/style.scss +11 -1
  39. package/dist/cjs/steps-list/style.scss +0 -3
  40. package/dist/cjs/steps-list-item/style.scss +1 -2
  41. package/dist/cjs/style-card/index.js +1 -0
  42. package/dist/cjs/style-card/style.scss +4 -5
  43. package/dist/cjs/style.scss +15 -0
  44. package/dist/cjs/tabbed-navigation/index.js +17 -7
  45. package/dist/cjs/tabbed-navigation/style.scss +2 -6
  46. package/dist/cjs/utils/color.js +35 -0
  47. package/dist/cjs/web-preview/style.scss +11 -11
  48. package/dist/cjs/with-wizard/index.js +80 -3
  49. package/dist/cjs/with-wizard/style.scss +34 -13
  50. package/dist/cjs/with-wizard-screen/index.js +3 -3
  51. package/dist/cjs/with-wizard-screen/style.scss +9 -9
  52. package/dist/cjs/wizard/index.js +38 -13
  53. package/dist/cjs/wizard/store/index.js +13 -5
  54. package/dist/cjs/wizard/store/utils.js +3 -1
  55. package/dist/esm/action-card/action-card.d.js +1 -0
  56. package/dist/esm/action-card/index.js +286 -189
  57. package/dist/esm/action-card/style.scss +142 -44
  58. package/dist/esm/autocomplete-tokenfield/index.js +6 -2
  59. package/dist/esm/box-contrast/index.js +44 -0
  60. package/dist/esm/button/index.js +1 -1
  61. package/dist/esm/button-props/button-props.js +34 -0
  62. package/dist/esm/button-props/index.js +1 -0
  63. package/dist/esm/color-picker/index.js +11 -0
  64. package/dist/esm/custom-select-control/style.scss +7 -12
  65. package/dist/esm/footer/index.js +18 -25
  66. package/dist/esm/footer/style.scss +0 -36
  67. package/dist/esm/handoff-message/index.js +0 -3
  68. package/dist/esm/hooks/useObjectState.js +10 -0
  69. package/dist/esm/hooks/useObjectState.test.js +6 -6
  70. package/dist/esm/index.js +1 -3
  71. package/dist/esm/modal/index.js +4 -1
  72. package/dist/esm/modal/style.scss +18 -7
  73. package/dist/esm/newspack-icon/index.js +2 -2
  74. package/dist/esm/newspack-icon/style.scss +3 -5
  75. package/dist/esm/notice/index.js +1 -2
  76. package/dist/esm/notice/style.scss +11 -9
  77. package/dist/esm/plugin-installer/index.js +3 -3
  78. package/dist/esm/plugin-settings/SettingsSection.js +2 -0
  79. package/dist/esm/plugin-settings/index.js +4 -1
  80. package/dist/esm/plugin-toggle/index.js +2 -0
  81. package/dist/esm/popover/style.scss +5 -6
  82. package/dist/esm/progress-bar/style.scss +1 -2
  83. package/dist/esm/radio-control/style.scss +4 -10
  84. package/dist/esm/section-header/index.js +22 -0
  85. package/dist/esm/select-control/ButtonGroupControl.js +2 -0
  86. package/dist/esm/settings/SettingsCard.js +2 -6
  87. package/dist/esm/sortable-newsletter-list-control/index.js +8 -6
  88. package/dist/esm/sortable-newsletter-list-control/style.scss +11 -1
  89. package/dist/esm/steps-list/style.scss +0 -3
  90. package/dist/esm/steps-list-item/style.scss +1 -2
  91. package/dist/esm/style-card/index.js +1 -0
  92. package/dist/esm/style-card/style.scss +4 -5
  93. package/dist/esm/style.scss +15 -0
  94. package/dist/esm/tabbed-navigation/index.js +17 -7
  95. package/dist/esm/tabbed-navigation/style.scss +2 -6
  96. package/dist/esm/utils/color.js +29 -0
  97. package/dist/esm/web-preview/style.scss +11 -11
  98. package/dist/esm/with-wizard/index.js +81 -4
  99. package/dist/esm/with-wizard/style.scss +34 -13
  100. package/dist/esm/with-wizard-screen/index.js +1 -1
  101. package/dist/esm/with-wizard-screen/style.scss +9 -9
  102. package/dist/esm/wizard/index.js +39 -13
  103. package/dist/esm/wizard/store/index.js +13 -5
  104. package/dist/esm/wizard/store/utils.js +3 -1
  105. package/package.json +1 -1
  106. package/src/accordion/index.js +1 -3
  107. package/src/action-card/action-card.d.ts +40 -0
  108. package/src/action-card/index.js +284 -202
  109. package/src/action-card/style.scss +142 -44
  110. package/src/autocomplete-tokenfield/index.js +3 -2
  111. package/src/autocomplete-with-suggestions/index.js +52 -63
  112. package/src/box-contrast/index.tsx +44 -0
  113. package/src/button/index.tsx +1 -1
  114. package/src/button-card/index.js +1 -12
  115. package/src/card/index.js +1 -11
  116. package/src/category-autocomplete/index.js +4 -19
  117. package/src/color-picker/index.js +11 -7
  118. package/src/custom-select-control/style.scss +7 -12
  119. package/src/footer/index.js +6 -18
  120. package/src/footer/style.scss +0 -36
  121. package/src/form-token-field/index.js +1 -2
  122. package/src/grid/index.tsx +1 -8
  123. package/src/handoff/index.js +4 -11
  124. package/src/handoff-message/index.js +0 -3
  125. package/src/hooks/useObjectState.js +10 -2
  126. package/src/hooks/useObjectState.test.js +14 -14
  127. package/src/image-upload/index.js +3 -23
  128. package/src/index.js +1 -3
  129. package/src/modal/index.js +2 -2
  130. package/src/modal/style.scss +18 -7
  131. package/src/newspack-icon/index.js +3 -14
  132. package/src/newspack-icon/style.scss +3 -5
  133. package/src/notice/index.js +0 -2
  134. package/src/notice/style.scss +11 -9
  135. package/src/plugin-installer/index.js +8 -17
  136. package/src/plugin-settings/SettingsSection.js +3 -7
  137. package/src/plugin-settings/index.js +7 -14
  138. package/src/plugin-toggle/README.md +3 -3
  139. package/src/plugin-toggle/index.js +10 -13
  140. package/src/popover/index.js +1 -5
  141. package/src/popover/style.scss +5 -6
  142. package/src/position-control/index.js +65 -75
  143. package/src/progress-bar/index.js +2 -9
  144. package/src/progress-bar/index.test.js +4 -13
  145. package/src/progress-bar/style.scss +1 -2
  146. package/src/radio-control/style.scss +4 -10
  147. package/src/section-header/index.js +20 -0
  148. package/src/select-control/ButtonGroupControl.js +2 -9
  149. package/src/select-control/GroupedSelectControl.js +1 -9
  150. package/src/select-control/index.js +1 -5
  151. package/src/settings/MinMaxSetting.js +2 -14
  152. package/src/settings/SettingsCard.js +2 -11
  153. package/src/sortable-newsletter-list-control/index.js +10 -26
  154. package/src/sortable-newsletter-list-control/style.scss +11 -1
  155. package/src/steps-list/style.scss +0 -3
  156. package/src/steps-list-item/index.js +1 -4
  157. package/src/steps-list-item/style.scss +1 -2
  158. package/src/style-card/index.js +6 -21
  159. package/src/style-card/style.scss +4 -5
  160. package/src/style.scss +15 -0
  161. package/src/tabbed-navigation/index.js +19 -7
  162. package/src/tabbed-navigation/style.scss +2 -6
  163. package/src/text-control/index.tsx +2 -12
  164. package/src/utils/color.ts +32 -0
  165. package/src/web-preview/style.scss +11 -11
  166. package/src/with-wizard/index.js +67 -16
  167. package/src/with-wizard/style.scss +34 -13
  168. package/src/with-wizard-screen/index.js +1 -1
  169. package/src/with-wizard-screen/style.scss +9 -9
  170. package/src/wizard/components/WizardError.js +2 -7
  171. package/src/wizard/index.js +64 -62
  172. package/src/wizard/store/index.js +8 -10
  173. package/src/wizard/store/utils.js +3 -4
  174. package/dist/cjs/date-range-picker/index.js +0 -39
  175. package/dist/cjs/date-range-picker/style.scss +0 -148
  176. package/dist/cjs/newspack-logo/index.js +0 -54
  177. package/dist/cjs/newspack-logo/style.scss +0 -30
  178. package/dist/cjs/patrons-logo/index.js +0 -77
  179. package/dist/esm/date-range-picker/index.js +0 -31
  180. package/dist/esm/date-range-picker/style.scss +0 -148
  181. package/dist/esm/newspack-logo/index.js +0 -46
  182. package/dist/esm/newspack-logo/style.scss +0 -30
  183. package/dist/esm/patrons-logo/index.js +0 -70
  184. package/shared/scss/_colors.scss +0 -27
  185. package/src/date-range-picker/index.js +0 -31
  186. package/src/date-range-picker/style.scss +0 -148
  187. package/src/newspack-logo/index.js +0 -45
  188. package/src/newspack-logo/style.scss +0 -30
  189. package/src/patrons-logo/index.js +0 -76
  190. /package/{shared/js → src/button-props}/button-props.js +0 -0
  191. /package/{shared/js → src/button-props}/index.js +0 -0
@@ -25,6 +25,21 @@ const TabbedNavigation = ({
25
25
  location
26
26
  } = useHistory();
27
27
  const currentIndex = findIndex(displayedItems, ['path', location.pathname]);
28
+ function isActive(item, match, pathname) {
29
+ if (item.path === pathname) {
30
+ return true;
31
+ }
32
+ if (Array.isArray(item?.activeTabPaths)) {
33
+ return item.activeTabPaths.some(path => {
34
+ if (path.endsWith('*')) {
35
+ const basePath = path.slice(0, -1);
36
+ return pathname.startsWith(basePath);
37
+ }
38
+ return item.activeTabPaths.includes(pathname);
39
+ });
40
+ }
41
+ return match;
42
+ }
28
43
  return /*#__PURE__*/_jsxs("div", {
29
44
  className: classnames('newspack-tabbed-navigation', className),
30
45
  children: [/*#__PURE__*/_jsx("ul", {
@@ -33,13 +48,8 @@ const TabbedNavigation = ({
33
48
  to: item.path,
34
49
  isActive: (match, {
35
50
  pathname
36
- }) => {
37
- if (item.activeTabPaths) {
38
- return item.activeTabPaths.includes(pathname);
39
- }
40
- return match;
41
- },
42
- exact: true,
51
+ }) => isActive(item, match, pathname),
52
+ exact: item.hasOwnProperty('exact') ? item.exact : true,
43
53
  activeClassName: 'selected',
44
54
  className: classnames({
45
55
  disabled: disableUpcoming && index > currentIndex
@@ -39,6 +39,7 @@
39
39
  display: flex;
40
40
  font-weight: bold;
41
41
  height: 48px;
42
+ outline: none;
42
43
  padding: 12px 15px;
43
44
  text-decoration: none;
44
45
 
@@ -51,15 +52,10 @@
51
52
  &:focus,
52
53
  &:hover {
53
54
  color: var(--wp-admin-theme-color);
54
- outline: none;
55
- }
56
-
57
- &:focus {
58
- box-shadow: none;
59
55
  }
60
56
 
61
57
  &:focus-visible {
62
- outline: 2px solid;
58
+ outline: 2px solid var(--wp-admin-theme-color);
63
59
  outline-offset: -2px;
64
60
  }
65
61
 
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Determine if black or white should be used based on a contrast ratio.
3
+ *
4
+ * @param hexcolor Hex code for determining contrast
5
+ * @return black or white string
6
+ */
7
+ export function getContrast(hexcolor) {
8
+ if (hexcolor.charAt(0) === '#') {
9
+ hexcolor = hexcolor.slice(1);
10
+ }
11
+
12
+ // Normalize to 6 character hex code if needed
13
+ if (hexcolor.length === 3) {
14
+ hexcolor = hexcolor.split('').map(function (hex) {
15
+ return hex + hex;
16
+ }).join('');
17
+ }
18
+
19
+ // Convert to RGB value
20
+ const r = parseInt(hexcolor.substring(0, 2), 16);
21
+ const g = parseInt(hexcolor.substring(2, 4), 16);
22
+ const b = parseInt(hexcolor.substring(4), 16);
23
+
24
+ // Get YIQ ratio
25
+ const yiq = (r * 299 + g * 587 + b * 114) / 1000;
26
+
27
+ // Check contrast
28
+ return yiq >= 128 ? 'black' : 'white';
29
+ }
@@ -2,19 +2,19 @@
2
2
  * Web Preview
3
3
  */
4
4
 
5
- @use "../../../shared/scss/colors";
6
5
  @use "~@wordpress/base-styles/colors" as wp-colors;
6
+ @use "../../../colors/colors.module" as colors;
7
7
 
8
8
  .newspack-web-preview {
9
9
  // Color
10
- --wp-admin-theme-color: #{colors.$primary-500};
11
- --wp-admin-theme-color--rgb: #{colors.$primary-500--rgb};
12
- --wp-admin-theme-color-darker-10: #{colors.$primary-600};
13
- --wp-admin-theme-color-darker-10--rgb: #{colors.$primary-600--rgb};
14
- --wp-admin-theme-color-darker-20: #{colors.$primary-700};
15
- --wp-admin-theme-color-darker-20--rgb: #{colors.$primary-700--rgb};
16
-
17
- background: rgba(black, 0.7);
10
+ --wp-admin-theme-color: #{colors.$primary-600};
11
+ --wp-admin-theme-color--rgb: #{colors.$primary-600--rgb};
12
+ --wp-admin-theme-color-darker-10: #{colors.$primary-700};
13
+ --wp-admin-theme-color-darker-10--rgb: #{colors.$primary-700--rgb};
14
+ --wp-admin-theme-color-darker-20: #{colors.$primary-800};
15
+ --wp-admin-theme-color-darker-20--rgb: #{colors.$primary-800--rgb};
16
+
17
+ background: #{colors.$neutral-700};
18
18
  box-sizing: border-box;
19
19
  height: 100%;
20
20
  left: 0;
@@ -102,7 +102,7 @@
102
102
  padding: 0 !important;
103
103
 
104
104
  &.is-selected {
105
- background: colors.$primary-500;
105
+ background: var(--wp-admin-theme-color);
106
106
  color: white;
107
107
 
108
108
  &:active,
@@ -114,7 +114,7 @@
114
114
  }
115
115
 
116
116
  &:focus {
117
- box-shadow: inset 0 0 0 1px colors.$primary-500, inset 0 0 0 3px white !important;
117
+ box-shadow: inset 0 0 0 1px var(--wp-admin-theme-color), inset 0 0 0 3px white !important;
118
118
  }
119
119
  }
120
120
 
@@ -4,7 +4,7 @@
4
4
  import { Component, createRef, Fragment } from '@wordpress/element';
5
5
  import { __ } from '@wordpress/i18n';
6
6
  import apiFetch from '@wordpress/api-fetch';
7
- import { home } from '@wordpress/icons';
7
+ import { category } from '@wordpress/icons';
8
8
 
9
9
  /**
10
10
  * Internal dependencies.
@@ -30,7 +30,8 @@ export default function withWizard(WrappedComponent, requiredPlugins) {
30
30
  complete: null,
31
31
  error: null,
32
32
  loading: requiredPlugins && requiredPlugins.length > 0 ? 1 : 0,
33
- quietLoading: false
33
+ quietLoading: false,
34
+ confirmation: null
34
35
  };
35
36
  this.wrappedComponentRef = createRef();
36
37
  }
@@ -251,7 +252,7 @@ export default function withWizard(WrappedComponent, requiredPlugins) {
251
252
  href: newspack_urls.dashboard,
252
253
  label: __('Return to Dashboard', 'newspack-plugin'),
253
254
  showTooltip: true,
254
- icon: home,
255
+ icon: category,
255
256
  iconSize: 36,
256
257
  children: /*#__PURE__*/_jsx(NewspackIcon, {
257
258
  size: 36
@@ -273,6 +274,81 @@ export default function withWizard(WrappedComponent, requiredPlugins) {
273
274
  })
274
275
  });
275
276
  };
277
+
278
+ /**
279
+ * Build a confirmation modal with the given title & message.
280
+ * Execute {callback} if confirmed.
281
+ *
282
+ * @property {Object} options Options for the confirmation modal.
283
+ * @property {string} options.title The title for the modal component.
284
+ * @property {string} options.message The message for the modal component body.
285
+ * @property {string} options.confirmText The text for the confirmation button.
286
+ * @property {string} options.cancelText The text for the cancel button.
287
+ * @property {Function} options.callback A function to call if the user confirms the action.
288
+ */
289
+ confirmAction = options => {
290
+ const modalOptions = {
291
+ title: null,
292
+ message: __('Are you sure?', 'newpack-plugin'),
293
+ confirmText: __('OK', 'newspack-plugin'),
294
+ cancelText: __('Cancel', 'newspack-plugin'),
295
+ callback: null,
296
+ ...options
297
+ };
298
+ this.setState({
299
+ confirmation: modalOptions
300
+ });
301
+ };
302
+
303
+ /**
304
+ * Show a confirmation modal with the given title & message.
305
+ * Execute {callback} if confirmed.
306
+ *
307
+ * @return {Component} <Modal>
308
+ */
309
+ getModal = () => {
310
+ if (!this.state.confirmation) {
311
+ return null;
312
+ }
313
+ const {
314
+ title,
315
+ message,
316
+ confirmText,
317
+ cancelText,
318
+ callback
319
+ } = this.state.confirmation;
320
+ return message && callback && /*#__PURE__*/_jsxs(Modal, {
321
+ isNarrow: true,
322
+ hideTitle: !title,
323
+ title: title,
324
+ onRequestClose: () => this.setState({
325
+ confirmation: null
326
+ }),
327
+ children: [/*#__PURE__*/_jsx("p", {
328
+ children: message
329
+ }), /*#__PURE__*/_jsxs(Card, {
330
+ buttonsCard: true,
331
+ noBorder: true,
332
+ className: "justify-end",
333
+ children: [/*#__PURE__*/_jsx(Button, {
334
+ variant: "secondary",
335
+ onClick: () => this.setState({
336
+ confirmation: null
337
+ }),
338
+ children: cancelText
339
+ }), /*#__PURE__*/_jsx(Button, {
340
+ variant: "primary",
341
+ onClick: () => {
342
+ this.setState({
343
+ confirmation: null
344
+ });
345
+ callback();
346
+ },
347
+ children: confirmText
348
+ })]
349
+ })]
350
+ });
351
+ };
276
352
  getFallbackURL = () => {
277
353
  if (typeof newspack_urls !== 'undefined') {
278
354
  return newspack_urls.dashboard;
@@ -296,9 +372,10 @@ export default function withWizard(WrappedComponent, requiredPlugins) {
296
372
  loadingClasses.push('newspack-wizard__is-loading-quiet');
297
373
  }
298
374
  return /*#__PURE__*/_jsxs(Fragment, {
299
- children: [this.getError(), /*#__PURE__*/_jsx("div", {
375
+ children: [this.getError(), this.getModal(), /*#__PURE__*/_jsx("div", {
300
376
  className: loadingClasses.join(' '),
301
377
  children: /*#__PURE__*/_jsx(WrappedComponent, {
378
+ confirmAction: this.confirmAction,
302
379
  pluginRequirements: requiredPlugins && this.pluginRequirements(),
303
380
  clearError: this.clearError,
304
381
  getError: this.getError,
@@ -3,15 +3,13 @@
3
3
  */
4
4
 
5
5
  @use "~@wordpress/base-styles/colors" as wp-colors;
6
- @use "../../../shared/scss/colors";
7
6
 
8
- // Reset Padding of the Admin Page
7
+ // Styling for full-page-react Wizards (ignoring admin-header-only wizards).
8
+ body.newspack-wizard-page:not(.newspack-admin-header) {
9
9
 
10
- .toplevel_page_newspack:not(.menu-top),
11
- body[class*="newspack_page_newspack-"],
12
- body[class*="admin_page_newspack-"] {
13
10
  background: white;
14
11
 
12
+ // Reset Padding
15
13
  #wpcontent {
16
14
  padding-left: 0;
17
15
  }
@@ -20,6 +18,13 @@ body[class*="admin_page_newspack-"] {
20
18
  padding-bottom: 220px;
21
19
  min-height: 100vh;
22
20
 
21
+ // For admin notices directly ">" at top of page above the Wizard header.
22
+ // PHP code should hide these notices, but just incase add this style.
23
+ > .notice {
24
+ margin-bottom: 20px;
25
+ margin-left: 22px;
26
+ }
27
+
23
28
  @media screen and ( min-width: 783px ) {
24
29
  padding-bottom: 202px;
25
30
  }
@@ -30,6 +35,24 @@ body[class*="admin_page_newspack-"] {
30
35
  }
31
36
  }
32
37
 
38
+ // Styling for wizards that are admin-header-only.
39
+ body.newspack-wizard-page.newspack-admin-header {
40
+
41
+ // For mobile.
42
+ @media screen and (max-width: 600px) {
43
+
44
+ // The header bar (and tabs) need padding.
45
+ #newspack-wizards-admin-header {
46
+ padding-top: 46px;
47
+ }
48
+
49
+ // Since the padding was added to the header bar, remove from body.
50
+ #wpbody {
51
+ padding-top: 0;
52
+ }
53
+ }
54
+ }
55
+
33
56
  svg {
34
57
  &.newspack--error {
35
58
  fill: wp-colors.$alert-red;
@@ -41,15 +64,14 @@ svg {
41
64
  }
42
65
 
43
66
  // Blue Screen
44
-
45
67
  .newspack-wizard__blue {
46
68
  #wpwrap {
47
- background: colors.$primary-500;
69
+ background: var(--wp-admin-theme-color);
48
70
  }
49
71
 
50
72
  .newspack-footer {
51
- background: colors.$primary-500;
52
- border-color: colors.$primary-500;
73
+ background: var(--wp-admin-theme-color);
74
+ border-color: var(--wp-admin-theme-color);
53
75
  justify-content: center;
54
76
 
55
77
  &__logo {
@@ -73,7 +95,6 @@ svg {
73
95
  }
74
96
 
75
97
  // Loading
76
-
77
98
  .newspack-wizard__is-loading {
78
99
  background: white;
79
100
  cursor: wait;
@@ -92,7 +113,7 @@ svg {
92
113
  }
93
114
 
94
115
  &::before {
95
- background: colors.$primary-500;
116
+ background: var(--wp-admin-theme-color);
96
117
  box-shadow:
97
118
  24px 0 0 white,
98
119
  69px 0 0 -15px wp-colors.$gray-900,
@@ -137,7 +158,7 @@ svg {
137
158
 
138
159
  // Blue Screen
139
160
  .newspack-wizard__blue & {
140
- background: colors.$primary-500;
161
+ background: var(--wp-admin-theme-color);
141
162
 
142
163
  &::before {
143
164
  animation: loading-quiet 1.25s ease-in-out infinite;
@@ -193,7 +214,7 @@ svg {
193
214
 
194
215
  &::before {
195
216
  animation: loading-quiet 1.25s ease-in-out infinite;
196
- background: colors.$primary-500;
217
+ background: var(--wp-admin-theme-color);
197
218
  height: 8px;
198
219
  right: 100%;
199
220
  z-index: 9999;
@@ -8,7 +8,7 @@ import { category } from '@wordpress/icons';
8
8
  * Internal dependencies
9
9
  */
10
10
  import { Button, Handoff, NewspackIcon, Notice, HandoffMessage, TabbedNavigation } from '../';
11
- import { buttonProps } from '../../../shared/js/';
11
+ import { buttonProps } from '../button-props';
12
12
  import './style.scss';
13
13
 
14
14
  /**
@@ -3,16 +3,16 @@
3
3
  */
4
4
 
5
5
  @use "~@wordpress/base-styles/colors" as wp-colors;
6
- @use "../../../shared/scss/colors";
6
+ @use "../../../colors/colors.module" as colors;
7
7
 
8
8
  .newspack-wizard {
9
9
  // Color
10
- --wp-admin-theme-color: #{colors.$primary-500};
11
- --wp-admin-theme-color--rgb: #{colors.$primary-500--rgb};
12
- --wp-admin-theme-color-darker-10: #{colors.$primary-600};
13
- --wp-admin-theme-color-darker-10--rgb: #{colors.$primary-600--rgb};
14
- --wp-admin-theme-color-darker-20: #{colors.$primary-700};
15
- --wp-admin-theme-color-darker-20--rgb: #{colors.$primary-700--rgb};
10
+ --wp-admin-theme-color: #{colors.$primary-600};
11
+ --wp-admin-theme-color--rgb: #{colors.$primary-600--rgb};
12
+ --wp-admin-theme-color-darker-10: #{colors.$primary-700};
13
+ --wp-admin-theme-color-darker-10--rgb: #{colors.$primary-700--rgb};
14
+ --wp-admin-theme-color-darker-20: #{colors.$primary-800};
15
+ --wp-admin-theme-color-darker-20--rgb: #{colors.$primary-800--rgb};
16
16
 
17
17
  color: wp-colors.$gray-900;
18
18
 
@@ -83,7 +83,7 @@
83
83
  }
84
84
 
85
85
  &:not(.newspack-icon) {
86
- background: colors.$primary-500;
86
+ background: var(--wp-admin-theme-color);
87
87
  left: 50%;
88
88
  margin: -28px 0 0 -28px !important;
89
89
  opacity: 0;
@@ -125,7 +125,7 @@
125
125
  padding: 0 16px;
126
126
 
127
127
  @media screen and ( min-width: 744px ) {
128
- padding: 32px 84px;
128
+ padding: 40px 84px;
129
129
  }
130
130
 
131
131
  // Typography
@@ -7,7 +7,7 @@ import classnames from 'classnames';
7
7
  * WordPress dependencies.
8
8
  */
9
9
  import { useSelect } from '@wordpress/data';
10
- import { useState } from '@wordpress/element';
10
+ import { useState, forwardRef } from '@wordpress/element';
11
11
  import { __ } from '@wordpress/i18n';
12
12
  import { category } from '@wordpress/icons';
13
13
 
@@ -17,9 +17,8 @@ import { category } from '@wordpress/icons';
17
17
  import { Footer, Notice, Button, NewspackIcon, TabbedNavigation, PluginInstaller, HandoffMessage } from '../';
18
18
  import Router from '../proxied-imports/router';
19
19
  import registerStore, { WIZARD_STORE_NAMESPACE } from './store';
20
- import { useWizardData } from './store/utils';
21
20
  import WizardError from './components/WizardError';
22
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
21
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
23
22
  registerStore();
24
23
  const {
25
24
  HashRouter,
@@ -27,22 +26,45 @@ const {
27
26
  Route,
28
27
  Switch
29
28
  } = Router;
29
+
30
+ /**
31
+ * @typedef {Object} WizardProps
32
+ * @property {string} headerText The header text.
33
+ * @property {string} [subHeaderText] The sub-header text, optional.
34
+ * @property {string} [apiSlug] The API slug, optional.
35
+ * @property {string} [className] CSS classes, optional.
36
+ * @property {any[]} sections Array of sections.
37
+ * @property {boolean} [hasSimpleFooter] Indicates if a simple footer is used, optional.
38
+ * @property {() => void} [renderAboveSections] Function to render content above sections, optional.
39
+ * @property {string[]} [requiredPlugins] Array of required plugin strings, optional.
40
+ * @property {boolean} [isInitialFetchTriggered] Indicates if the initial fetch should be triggered, optional.
41
+ */
42
+
43
+ /**
44
+ * Wizard Component
45
+ *
46
+ * Provides a tabbed UI with history.
47
+ *
48
+ * @param {WizardProps} props
49
+ * @return {JSX.Element} Wizard component
50
+ */
30
51
  const Wizard = ({
31
52
  sections = [],
32
- apiSlug,
33
53
  headerText,
54
+ apiSlug,
34
55
  subHeaderText,
35
56
  hasSimpleFooter,
36
57
  className,
37
58
  renderAboveSections,
38
- requiredPlugins = []
39
- }) => {
59
+ requiredPlugins = [],
60
+ isInitialFetchTriggered = true
61
+ }, ref) => {
40
62
  const isLoading = useSelect(select => select(WIZARD_STORE_NAMESPACE).isLoading());
41
63
  const isQuietLoading = useSelect(select => select(WIZARD_STORE_NAMESPACE).isQuietLoading());
42
64
 
43
65
  // Trigger initial data fetch. Some sections might not use the wizard data,
44
66
  // but for consistency, fetching is triggered regardless of the section.
45
- useSelect(select => select(WIZARD_STORE_NAMESPACE).getWizardAPIData(apiSlug));
67
+ useSelect(select => isInitialFetchTriggered && select(WIZARD_STORE_NAMESPACE).getWizardAPIData(apiSlug));
46
68
  let displayedSections = sections.filter(section => !section.isHidden);
47
69
  const [pluginRequirementsSatisfied, setPluginRequirementsSatisfied] = useState(requiredPlugins.length === 0);
48
70
  if (!pluginRequirementsSatisfied) {
@@ -57,7 +79,9 @@ const Wizard = ({
57
79
  })
58
80
  }];
59
81
  }
60
- return /*#__PURE__*/_jsxs(_Fragment, {
82
+ const urlWithoutHash = window.location.href.split('#')[0];
83
+ return /*#__PURE__*/_jsxs("div", {
84
+ ref: ref,
61
85
  children: [/*#__PURE__*/_jsx("div", {
62
86
  className: classnames(isLoading ? 'newspack-wizard__is-loading' : 'newspack-wizard__is-loaded', {
63
87
  'newspack-wizard__is-loading-quiet': isQuietLoading
@@ -72,7 +96,7 @@ const Wizard = ({
72
96
  className: "newspack-wizard__header__inner",
73
97
  children: /*#__PURE__*/_jsxs("div", {
74
98
  className: "newspack-wizard__title",
75
- children: [/*#__PURE__*/_jsx(Button, {
99
+ children: [newspack_urls.dashboard !== urlWithoutHash ? /*#__PURE__*/_jsx(Button, {
76
100
  isLink: true,
77
101
  href: newspack_urls.dashboard,
78
102
  label: __('Return to Dashboard', 'newspack-plugin'),
@@ -82,6 +106,8 @@ const Wizard = ({
82
106
  children: /*#__PURE__*/_jsx(NewspackIcon, {
83
107
  size: 36
84
108
  })
109
+ }) : /*#__PURE__*/_jsx(NewspackIcon, {
110
+ size: 36
85
111
  }), /*#__PURE__*/_jsxs("div", {
86
112
  children: [headerText && /*#__PURE__*/_jsx("h2", {
87
113
  children: headerText
@@ -96,11 +122,13 @@ const Wizard = ({
96
122
  children: /*#__PURE__*/_jsx(WizardError, {})
97
123
  }), /*#__PURE__*/_jsx(HandoffMessage, {}), /*#__PURE__*/_jsxs(Switch, {
98
124
  children: [displayedSections.map((section, index) => {
125
+ var _section$exact;
99
126
  const SectionComponent = section.render;
100
127
  return /*#__PURE__*/_jsx(Route, {
128
+ exact: (_section$exact = section.exact) !== null && _section$exact !== void 0 ? _section$exact : false,
101
129
  path: section.path,
102
130
  children: /*#__PURE__*/_jsxs("div", {
103
- className: classnames('newspack-wizard newspack-wizard__content', className),
131
+ className: classnames('newspack-wizard__content', className),
104
132
  children: ['function' === typeof renderAboveSections ? renderAboveSections() : null, /*#__PURE__*/_jsx(SectionComponent, {})]
105
133
  })
106
134
  }, index);
@@ -114,6 +142,4 @@ const Wizard = ({
114
142
  })]
115
143
  });
116
144
  };
117
- Wizard.useWizardData = useWizardData;
118
- Wizard.STORE_NAMESPACE = WIZARD_STORE_NAMESPACE;
119
- export default Wizard;
145
+ export default forwardRef(Wizard);
@@ -13,7 +13,7 @@ import { createReduxStore, register, dispatch, select } from '@wordpress/data';
13
13
  import { createAction } from './utils.js';
14
14
  export const WIZARD_STORE_NAMESPACE = 'newspack/wizards';
15
15
  const DEFAULT_STATE = {
16
- isLoading: true,
16
+ isLoading: false,
17
17
  isQuietLoading: false,
18
18
  apiData: {},
19
19
  error: null
@@ -112,6 +112,10 @@ const selectors = {
112
112
  isLoading: state => state.isLoading,
113
113
  isQuietLoading: state => state.isQuietLoading,
114
114
  getWizardAPIData: (state, slug) => state.apiData[slug] || {},
115
+ getWizardData: (state, slug) => {
116
+ var _state$apiData$slug;
117
+ return (_state$apiData$slug = state.apiData[slug]) !== null && _state$apiData$slug !== void 0 ? _state$apiData$slug : {};
118
+ },
115
119
  getError: state => state.error
116
120
  };
117
121
  const store = createReduxStore(WIZARD_STORE_NAMESPACE, {
@@ -120,17 +124,21 @@ const store = createReduxStore(WIZARD_STORE_NAMESPACE, {
120
124
  selectors,
121
125
  controls: {
122
126
  FETCH_FROM_API: action => {
127
+ const {
128
+ isLocalError = false,
129
+ isQuietFetch = false
130
+ } = action.payload;
123
131
  dispatch(WIZARD_STORE_NAMESPACE).startLoadingData({
124
- isQuietLoading: Boolean(action.payload.isQuietFetch)
132
+ isQuietLoading: Boolean(isQuietFetch)
125
133
  });
126
134
  return apiFetch(action.payload).then(data => {
127
135
  dispatch(WIZARD_STORE_NAMESPACE).setError(null);
128
136
  return data;
129
137
  }).catch(error => {
138
+ if (isLocalError) {
139
+ throw error;
140
+ }
130
141
  dispatch(WIZARD_STORE_NAMESPACE).setError(error);
131
- return {
132
- error
133
- };
134
142
  }).finally(result => {
135
143
  dispatch(WIZARD_STORE_NAMESPACE).finishLoadingData();
136
144
  return result;
@@ -11,4 +11,6 @@ export const createAction = type => payload => ({
11
11
  type,
12
12
  payload
13
13
  });
14
- export const useWizardData = (wizardName, defaultValue = {}) => useSelect(select => select(WIZARD_STORE_NAMESPACE).getWizardAPIData(`newspack-${wizardName}-wizard`)) || defaultValue;
14
+ export const useWizardData = (wizardName, defaultValue = {}) => {
15
+ return useSelect(select => select(WIZARD_STORE_NAMESPACE).getWizardAPIData(wizardName)) || defaultValue;
16
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newspack-components",
3
- "version": "3.1.0",
3
+ "version": "4.0.0",
4
4
  "description": "Newspack design system components",
5
5
  "author": "Automattic",
6
6
  "license": "GPL-2.0-or-later",
@@ -20,9 +20,7 @@ import './style.scss';
20
20
  const Accordion = ( { children, title } ) => {
21
21
  const [ isOpen, setIsOpen ] = useState( false );
22
22
  return (
23
- <details
24
- className={ classNames( 'newspack-accordion', { 'newspack-accordion--is-open': isOpen } ) }
25
- >
23
+ <details className={ classNames( 'newspack-accordion', { 'newspack-accordion--is-open': isOpen } ) }>
26
24
  <summary onClick={ () => setIsOpen( ! isOpen ) }>
27
25
  { title }
28
26
  <Icon className="newspack-accordion__icon" icon={ chevronRight } size={ 24 } />
@@ -0,0 +1,40 @@
1
+ export interface ActionCardProps {
2
+ id?: string | number;
3
+ title?: string | React.ReactNode;
4
+ titleLink?: string;
5
+ href?: string;
6
+ description?: string | React.ReactNode;
7
+ actionText?: React.ReactNode | string | null;
8
+ badge?: string;
9
+ className?: string;
10
+ indent?: string;
11
+ notification?: string | Error | null;
12
+ notificationLevel?: 'error' | 'warning' | 'info';
13
+ isMedium?: boolean;
14
+ disabled?: boolean | string;
15
+ hasGreyHeader?: boolean;
16
+ toggleChecked?: boolean;
17
+ toggleOnChange?: ( a: boolean ) => void;
18
+ actionContent?: boolean | React.ReactNode | null;
19
+ error?: Error | string | null;
20
+ handoff?: string | null;
21
+ isErrorStatus?: boolean;
22
+ checkbox?: 'checked' | 'unchecked';
23
+ isChecked?: boolean;
24
+ children?: boolean | React.ReactNode;
25
+ isSmall?: boolean;
26
+ editLink?: string;
27
+ simple?: boolean;
28
+ secondaryActionText?: string;
29
+ onSecondaryActionClick?: () => void;
30
+ secondaryDestructive?: boolean;
31
+ hasWhiteHeader?: boolean;
32
+ noBorder?: boolean;
33
+ noMargin?: boolean;
34
+ collapse?: boolean;
35
+ expandable?: boolean;
36
+ draggable?: boolean;
37
+ dragIndex?: number;
38
+ onDragCallback?: ( index: number ) => void;
39
+ dragWrapperRef?: React.MutableRefObject< HTMLDivElement | null >;
40
+ }