newspack-components 3.0.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 (197) 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 -186
  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 +6 -6
  18. package/dist/cjs/image-upload/index.test.js +2 -2
  19. package/dist/cjs/index.js +7 -21
  20. package/dist/cjs/modal/index.js +16 -18
  21. package/dist/cjs/modal/style.scss +18 -7
  22. package/dist/cjs/newspack-icon/index.js +2 -2
  23. package/dist/cjs/newspack-icon/style.scss +3 -5
  24. package/dist/cjs/notice/index.js +1 -2
  25. package/dist/cjs/notice/style.scss +11 -9
  26. package/dist/cjs/plugin-installer/index.js +3 -3
  27. package/dist/cjs/plugin-settings/SettingsSection.js +2 -0
  28. package/dist/cjs/plugin-settings/index.js +4 -1
  29. package/dist/cjs/plugin-toggle/index.js +2 -0
  30. package/dist/cjs/popover/style.scss +5 -6
  31. package/dist/cjs/progress-bar/index.test.js +8 -9
  32. package/dist/cjs/progress-bar/style.scss +1 -2
  33. package/dist/cjs/proxied-imports/router.js +1 -2
  34. package/dist/cjs/radio-control/style.scss +8 -11
  35. package/dist/cjs/section-header/index.js +21 -1
  36. package/dist/cjs/select-control/ButtonGroupControl.js +2 -0
  37. package/dist/cjs/settings/SettingsCard.js +2 -6
  38. package/dist/cjs/sortable-newsletter-list-control/index.js +7 -5
  39. package/dist/cjs/sortable-newsletter-list-control/style.scss +11 -1
  40. package/dist/cjs/steps-list/style.scss +0 -3
  41. package/dist/cjs/steps-list-item/style.scss +1 -2
  42. package/dist/cjs/style-card/index.js +1 -0
  43. package/dist/cjs/style-card/style.scss +4 -5
  44. package/dist/cjs/style.scss +15 -0
  45. package/dist/cjs/tabbed-navigation/index.js +17 -7
  46. package/dist/cjs/tabbed-navigation/style.scss +2 -6
  47. package/dist/cjs/utils/color.js +35 -0
  48. package/dist/cjs/web-preview/index.js +1 -1
  49. package/dist/cjs/web-preview/style.scss +11 -11
  50. package/dist/cjs/with-wizard/index.js +80 -3
  51. package/dist/cjs/with-wizard/style.scss +34 -13
  52. package/dist/cjs/with-wizard-screen/index.js +3 -3
  53. package/dist/cjs/with-wizard-screen/style.scss +9 -9
  54. package/dist/cjs/wizard/index.js +38 -13
  55. package/dist/cjs/wizard/store/index.js +13 -5
  56. package/dist/cjs/wizard/store/utils.js +3 -1
  57. package/dist/esm/action-card/action-card.d.js +1 -0
  58. package/dist/esm/action-card/index.js +286 -188
  59. package/dist/esm/action-card/style.scss +142 -44
  60. package/dist/esm/autocomplete-tokenfield/index.js +6 -2
  61. package/dist/esm/box-contrast/index.js +44 -0
  62. package/dist/esm/button/index.js +1 -1
  63. package/dist/esm/button-props/button-props.js +34 -0
  64. package/dist/esm/button-props/index.js +1 -0
  65. package/dist/esm/color-picker/index.js +11 -0
  66. package/dist/esm/custom-select-control/style.scss +7 -12
  67. package/dist/esm/footer/index.js +18 -25
  68. package/dist/esm/footer/style.scss +0 -36
  69. package/dist/esm/handoff-message/index.js +0 -3
  70. package/dist/esm/hooks/useObjectState.js +12 -2
  71. package/dist/esm/hooks/useObjectState.test.js +7 -7
  72. package/dist/esm/hooks/usePrompt.js +2 -2
  73. package/dist/esm/image-upload/index.test.js +2 -2
  74. package/dist/esm/index.js +1 -3
  75. package/dist/esm/modal/index.js +17 -19
  76. package/dist/esm/modal/style.scss +18 -7
  77. package/dist/esm/newspack-icon/index.js +2 -2
  78. package/dist/esm/newspack-icon/style.scss +3 -5
  79. package/dist/esm/notice/index.js +1 -2
  80. package/dist/esm/notice/style.scss +11 -9
  81. package/dist/esm/plugin-installer/index.js +3 -3
  82. package/dist/esm/plugin-settings/SettingsSection.js +2 -0
  83. package/dist/esm/plugin-settings/index.js +4 -1
  84. package/dist/esm/plugin-toggle/index.js +2 -0
  85. package/dist/esm/popover/style.scss +5 -6
  86. package/dist/esm/progress-bar/index.test.js +7 -7
  87. package/dist/esm/progress-bar/style.scss +1 -2
  88. package/dist/esm/radio-control/style.scss +8 -11
  89. package/dist/esm/section-header/index.js +22 -0
  90. package/dist/esm/select-control/ButtonGroupControl.js +2 -0
  91. package/dist/esm/settings/SettingsCard.js +2 -6
  92. package/dist/esm/sortable-newsletter-list-control/index.js +8 -6
  93. package/dist/esm/sortable-newsletter-list-control/style.scss +11 -1
  94. package/dist/esm/steps-list/style.scss +0 -3
  95. package/dist/esm/steps-list-item/style.scss +1 -2
  96. package/dist/esm/style-card/index.js +1 -0
  97. package/dist/esm/style-card/style.scss +4 -5
  98. package/dist/esm/style.scss +15 -0
  99. package/dist/esm/tabbed-navigation/index.js +17 -7
  100. package/dist/esm/tabbed-navigation/style.scss +2 -6
  101. package/dist/esm/utils/color.js +29 -0
  102. package/dist/esm/web-preview/index.js +1 -1
  103. package/dist/esm/web-preview/style.scss +11 -11
  104. package/dist/esm/with-wizard/index.js +81 -4
  105. package/dist/esm/with-wizard/style.scss +34 -13
  106. package/dist/esm/with-wizard-screen/index.js +1 -1
  107. package/dist/esm/with-wizard-screen/style.scss +9 -9
  108. package/dist/esm/wizard/index.js +39 -13
  109. package/dist/esm/wizard/store/index.js +14 -6
  110. package/dist/esm/wizard/store/utils.js +3 -1
  111. package/package.json +2 -2
  112. package/src/accordion/index.js +1 -3
  113. package/src/action-card/action-card.d.ts +40 -0
  114. package/src/action-card/index.js +284 -201
  115. package/src/action-card/style.scss +142 -44
  116. package/src/autocomplete-tokenfield/index.js +3 -2
  117. package/src/autocomplete-with-suggestions/index.js +52 -63
  118. package/src/box-contrast/index.tsx +44 -0
  119. package/src/button/index.tsx +1 -1
  120. package/src/button-card/index.js +1 -12
  121. package/src/card/index.js +1 -11
  122. package/src/category-autocomplete/index.js +4 -19
  123. package/src/color-picker/index.js +11 -7
  124. package/src/custom-select-control/style.scss +7 -12
  125. package/src/footer/index.js +6 -18
  126. package/src/footer/style.scss +0 -36
  127. package/src/form-token-field/index.js +1 -2
  128. package/src/grid/index.tsx +1 -8
  129. package/src/handoff/index.js +4 -11
  130. package/src/handoff-message/index.js +0 -3
  131. package/src/hooks/useObjectState.js +10 -2
  132. package/src/hooks/useObjectState.test.js +14 -14
  133. package/src/image-upload/index.js +3 -23
  134. package/src/index.js +1 -3
  135. package/src/modal/index.js +11 -17
  136. package/src/modal/style.scss +18 -7
  137. package/src/newspack-icon/index.js +3 -14
  138. package/src/newspack-icon/style.scss +3 -5
  139. package/src/notice/index.js +0 -2
  140. package/src/notice/style.scss +11 -9
  141. package/src/plugin-installer/index.js +8 -17
  142. package/src/plugin-settings/SettingsSection.js +3 -7
  143. package/src/plugin-settings/index.js +7 -14
  144. package/src/plugin-toggle/README.md +3 -3
  145. package/src/plugin-toggle/index.js +10 -13
  146. package/src/popover/index.js +1 -5
  147. package/src/popover/style.scss +5 -6
  148. package/src/position-control/index.js +65 -75
  149. package/src/progress-bar/index.js +2 -9
  150. package/src/progress-bar/index.test.js +4 -13
  151. package/src/progress-bar/style.scss +1 -2
  152. package/src/radio-control/style.scss +8 -11
  153. package/src/section-header/index.js +20 -0
  154. package/src/select-control/ButtonGroupControl.js +2 -9
  155. package/src/select-control/GroupedSelectControl.js +1 -9
  156. package/src/select-control/index.js +1 -5
  157. package/src/settings/MinMaxSetting.js +2 -14
  158. package/src/settings/SettingsCard.js +2 -11
  159. package/src/sortable-newsletter-list-control/index.js +10 -26
  160. package/src/sortable-newsletter-list-control/style.scss +11 -1
  161. package/src/steps-list/style.scss +0 -3
  162. package/src/steps-list-item/index.js +1 -4
  163. package/src/steps-list-item/style.scss +1 -2
  164. package/src/style-card/index.js +6 -21
  165. package/src/style-card/style.scss +4 -5
  166. package/src/style.scss +15 -0
  167. package/src/tabbed-navigation/index.js +19 -7
  168. package/src/tabbed-navigation/style.scss +2 -6
  169. package/src/text-control/index.tsx +2 -12
  170. package/src/utils/color.ts +32 -0
  171. package/src/web-preview/style.scss +11 -11
  172. package/src/with-wizard/index.js +67 -16
  173. package/src/with-wizard/style.scss +34 -13
  174. package/src/with-wizard-screen/index.js +1 -1
  175. package/src/with-wizard-screen/style.scss +9 -9
  176. package/src/wizard/components/WizardError.js +2 -7
  177. package/src/wizard/index.js +64 -62
  178. package/src/wizard/store/index.js +8 -10
  179. package/src/wizard/store/utils.js +3 -4
  180. package/dist/cjs/date-range-picker/index.js +0 -39
  181. package/dist/cjs/date-range-picker/style.scss +0 -148
  182. package/dist/cjs/newspack-logo/index.js +0 -54
  183. package/dist/cjs/newspack-logo/style.scss +0 -30
  184. package/dist/cjs/patrons-logo/index.js +0 -77
  185. package/dist/esm/date-range-picker/index.js +0 -31
  186. package/dist/esm/date-range-picker/style.scss +0 -148
  187. package/dist/esm/newspack-logo/index.js +0 -46
  188. package/dist/esm/newspack-logo/style.scss +0 -30
  189. package/dist/esm/patrons-logo/index.js +0 -70
  190. package/shared/scss/_colors.scss +0 -27
  191. package/src/date-range-picker/index.js +0 -31
  192. package/src/date-range-picker/style.scss +0 -148
  193. package/src/newspack-logo/index.js +0 -45
  194. package/src/newspack-logo/style.scss +0 -30
  195. package/src/patrons-logo/index.js +0 -76
  196. /package/{shared/js → src/button-props}/button-props.js +0 -0
  197. /package/{shared/js → src/button-props}/index.js +0 -0
@@ -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.
@@ -28,6 +28,7 @@ export default function withWizard( WrappedComponent, requiredPlugins ) {
28
28
  error: null,
29
29
  loading: requiredPlugins && requiredPlugins.length > 0 ? 1 : 0,
30
30
  quietLoading: false,
31
+ confirmation: null,
31
32
  };
32
33
  this.wrappedComponentRef = createRef();
33
34
  }
@@ -80,9 +81,7 @@ export default function withWizard( WrappedComponent, requiredPlugins ) {
80
81
  */
81
82
  getErrorNotice = error => {
82
83
  const { message } = error;
83
- return (
84
- <Notice isError className="newspack-wizard__above-header" noticeText={ message } rawHTML />
85
- );
84
+ return <Notice isError className="newspack-wizard__above-header" noticeText={ message } rawHTML />;
86
85
  };
87
86
 
88
87
  /**
@@ -98,10 +97,7 @@ export default function withWizard( WrappedComponent, requiredPlugins ) {
98
97
  }
99
98
  const { message } = error;
100
99
  return (
101
- <Modal
102
- title={ __( 'Unrecoverable error' ) }
103
- onRequestClose={ () => ( window.location = fallbackURL ) }
104
- >
100
+ <Modal title={ __( 'Unrecoverable error' ) } onRequestClose={ () => ( window.location = fallbackURL ) }>
105
101
  <Notice noticeText={ message } isError rawHTML />
106
102
  <Card buttonsCard noBorder className="justify-end">
107
103
  <Button isPrimary href={ fallbackURL }>
@@ -221,7 +217,7 @@ export default function withWizard( WrappedComponent, requiredPlugins ) {
221
217
  href={ newspack_urls.dashboard }
222
218
  label={ __( 'Return to Dashboard', 'newspack-plugin' ) }
223
219
  showTooltip={ true }
224
- icon={ home }
220
+ icon={ category }
225
221
  iconSize={ 36 }
226
222
  >
227
223
  <NewspackIcon size={ 36 } />
@@ -238,10 +234,7 @@ export default function withWizard( WrappedComponent, requiredPlugins ) {
238
234
  </div>
239
235
  ) }
240
236
  <div className="newspack-wizard newspack-wizard__content">
241
- <PluginInstaller
242
- plugins={ requiredPlugins }
243
- onStatus={ status => this.pluginInstallationStatus( status ) }
244
- />
237
+ <PluginInstaller plugins={ requiredPlugins } onStatus={ status => this.pluginInstallationStatus( status ) } />
245
238
  </div>
246
239
  </Fragment>
247
240
  ) }
@@ -249,6 +242,64 @@ export default function withWizard( WrappedComponent, requiredPlugins ) {
249
242
  );
250
243
  };
251
244
 
245
+ /**
246
+ * Build a confirmation modal with the given title & message.
247
+ * Execute {callback} if confirmed.
248
+ *
249
+ * @property {Object} options Options for the confirmation modal.
250
+ * @property {string} options.title The title for the modal component.
251
+ * @property {string} options.message The message for the modal component body.
252
+ * @property {string} options.confirmText The text for the confirmation button.
253
+ * @property {string} options.cancelText The text for the cancel button.
254
+ * @property {Function} options.callback A function to call if the user confirms the action.
255
+ */
256
+ confirmAction = options => {
257
+ const modalOptions = {
258
+ title: null,
259
+ message: __( 'Are you sure?', 'newpack-plugin' ),
260
+ confirmText: __( 'OK', 'newspack-plugin' ),
261
+ cancelText: __( 'Cancel', 'newspack-plugin' ),
262
+ callback: null,
263
+ ...options,
264
+ };
265
+ this.setState( { confirmation: modalOptions } );
266
+ };
267
+
268
+ /**
269
+ * Show a confirmation modal with the given title & message.
270
+ * Execute {callback} if confirmed.
271
+ *
272
+ * @return {Component} <Modal>
273
+ */
274
+ getModal = () => {
275
+ if ( ! this.state.confirmation ) {
276
+ return null;
277
+ }
278
+ const { title, message, confirmText, cancelText, callback } = this.state.confirmation;
279
+ return (
280
+ message &&
281
+ callback && (
282
+ <Modal isNarrow hideTitle={ ! title } title={ title } onRequestClose={ () => this.setState( { confirmation: null } ) }>
283
+ <p>{ message }</p>
284
+ <Card buttonsCard noBorder className="justify-end">
285
+ <Button variant="secondary" onClick={ () => this.setState( { confirmation: null } ) }>
286
+ { cancelText }
287
+ </Button>
288
+ <Button
289
+ variant="primary"
290
+ onClick={ () => {
291
+ this.setState( { confirmation: null } );
292
+ callback();
293
+ } }
294
+ >
295
+ { confirmText }
296
+ </Button>
297
+ </Card>
298
+ </Modal>
299
+ )
300
+ );
301
+ };
302
+
252
303
  getFallbackURL = () => {
253
304
  if ( typeof newspack_urls !== 'undefined' ) {
254
305
  return newspack_urls.dashboard;
@@ -261,17 +312,17 @@ export default function withWizard( WrappedComponent, requiredPlugins ) {
261
312
  render() {
262
313
  const { simpleFooter } = this.props;
263
314
  const { loading, quietLoading, error } = this.state;
264
- const loadingClasses = [
265
- loading ? 'newspack-wizard__is-loading' : 'newspack-wizard__is-loaded',
266
- ];
315
+ const loadingClasses = [ loading ? 'newspack-wizard__is-loading' : 'newspack-wizard__is-loaded' ];
267
316
  if ( quietLoading ) {
268
317
  loadingClasses.push( 'newspack-wizard__is-loading-quiet' );
269
318
  }
270
319
  return (
271
320
  <Fragment>
272
321
  { this.getError() }
322
+ { this.getModal() }
273
323
  <div className={ loadingClasses.join( ' ' ) }>
274
324
  <WrappedComponent
325
+ confirmAction={ this.confirmAction }
275
326
  pluginRequirements={ requiredPlugins && this.pluginRequirements() }
276
327
  clearError={ this.clearError }
277
328
  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
@@ -33,10 +33,7 @@ const WizardError = () => {
33
33
  if ( 'fatal' === level ) {
34
34
  const fallbackURL = typeof newspack_urls !== 'undefined' && newspack_urls.dashboard;
35
35
  return (
36
- <Modal
37
- title={ __( 'Unrecoverable error' ) }
38
- onRequestClose={ fallbackURL ? () => ( window.location = fallbackURL ) : undefined }
39
- >
36
+ <Modal title={ __( 'Unrecoverable error' ) } onRequestClose={ fallbackURL ? () => ( window.location = fallbackURL ) : undefined }>
40
37
  <Notice noticeText={ message } isError rawHTML />
41
38
  { fallbackURL && (
42
39
  <Card buttonsCard noBorder className="justify-end">
@@ -49,9 +46,7 @@ const WizardError = () => {
49
46
  );
50
47
  }
51
48
 
52
- return (
53
- <Notice isError className="newspack-wizard__above-header" noticeText={ message } rawHTML />
54
- );
49
+ return <Notice isError className="newspack-wizard__above-header" noticeText={ message } rawHTML />;
55
50
  };
56
51
 
57
52
  export default WizardError;
@@ -7,96 +7,107 @@ 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
 
14
14
  /**
15
15
  * Internal dependencies
16
16
  */
17
- import {
18
- Footer,
19
- Notice,
20
- Button,
21
- NewspackIcon,
22
- TabbedNavigation,
23
- PluginInstaller,
24
- HandoffMessage,
25
- } from '../';
17
+ import { Footer, Notice, Button, NewspackIcon, TabbedNavigation, PluginInstaller, HandoffMessage } from '../';
26
18
  import Router from '../proxied-imports/router';
27
19
  import registerStore, { WIZARD_STORE_NAMESPACE } from './store';
28
- import { useWizardData } from './store/utils';
29
20
  import WizardError from './components/WizardError';
30
21
 
31
22
  registerStore();
32
23
 
33
24
  const { HashRouter, Redirect, Route, Switch } = Router;
34
25
 
35
- const Wizard = ( {
36
- sections = [],
37
- apiSlug,
38
- headerText,
39
- subHeaderText,
40
- hasSimpleFooter,
41
- className,
42
- renderAboveSections,
43
- requiredPlugins = [],
44
- } ) => {
26
+ /**
27
+ * @typedef {Object} WizardProps
28
+ * @property {string} headerText The header text.
29
+ * @property {string} [subHeaderText] The sub-header text, optional.
30
+ * @property {string} [apiSlug] The API slug, optional.
31
+ * @property {string} [className] CSS classes, optional.
32
+ * @property {any[]} sections Array of sections.
33
+ * @property {boolean} [hasSimpleFooter] Indicates if a simple footer is used, optional.
34
+ * @property {() => void} [renderAboveSections] Function to render content above sections, optional.
35
+ * @property {string[]} [requiredPlugins] Array of required plugin strings, optional.
36
+ * @property {boolean} [isInitialFetchTriggered] Indicates if the initial fetch should be triggered, optional.
37
+ */
38
+
39
+ /**
40
+ * Wizard Component
41
+ *
42
+ * Provides a tabbed UI with history.
43
+ *
44
+ * @param {WizardProps} props
45
+ * @return {JSX.Element} Wizard component
46
+ */
47
+ const Wizard = (
48
+ {
49
+ sections = [],
50
+ headerText,
51
+ apiSlug,
52
+ subHeaderText,
53
+ hasSimpleFooter,
54
+ className,
55
+ renderAboveSections,
56
+ requiredPlugins = [],
57
+ isInitialFetchTriggered = true,
58
+ },
59
+ ref
60
+ ) => {
45
61
  const isLoading = useSelect( select => select( WIZARD_STORE_NAMESPACE ).isLoading() );
46
62
  const isQuietLoading = useSelect( select => select( WIZARD_STORE_NAMESPACE ).isQuietLoading() );
47
63
 
48
64
  // Trigger initial data fetch. Some sections might not use the wizard data,
49
65
  // but for consistency, fetching is triggered regardless of the section.
50
- useSelect( select => select( WIZARD_STORE_NAMESPACE ).getWizardAPIData( apiSlug ) );
66
+ useSelect( select => isInitialFetchTriggered && select( WIZARD_STORE_NAMESPACE ).getWizardAPIData( apiSlug ) );
51
67
 
52
68
  let displayedSections = sections.filter( section => ! section.isHidden );
53
69
 
54
- const [ pluginRequirementsSatisfied, setPluginRequirementsSatisfied ] = useState(
55
- requiredPlugins.length === 0
56
- );
70
+ const [ pluginRequirementsSatisfied, setPluginRequirementsSatisfied ] = useState( requiredPlugins.length === 0 );
57
71
  if ( ! pluginRequirementsSatisfied ) {
58
- headerText =
59
- requiredPlugins.length > 1
60
- ? __( 'Required plugins', 'newspack-plugin' )
61
- : __( 'Required plugin', 'newspack-plugin' );
72
+ headerText = requiredPlugins.length > 1 ? __( 'Required plugins', 'newspack-plugin' ) : __( 'Required plugin', 'newspack-plugin' );
62
73
  displayedSections = [
63
74
  {
64
75
  path: '/',
65
76
  render: () => (
66
- <PluginInstaller
67
- plugins={ requiredPlugins }
68
- onStatus={ ( { complete } ) => setPluginRequirementsSatisfied( complete ) }
69
- />
77
+ <PluginInstaller plugins={ requiredPlugins } onStatus={ ( { complete } ) => setPluginRequirementsSatisfied( complete ) } />
70
78
  ),
71
79
  },
72
80
  ];
73
81
  }
74
82
 
83
+ const urlWithoutHash = window.location.href.split( '#' )[ 0 ];
84
+
75
85
  return (
76
- <>
86
+ <div ref={ ref }>
77
87
  <div
78
- className={ classnames(
79
- isLoading ? 'newspack-wizard__is-loading' : 'newspack-wizard__is-loaded',
80
- {
81
- 'newspack-wizard__is-loading-quiet': isQuietLoading,
82
- }
83
- ) }
88
+ className={ classnames( isLoading ? 'newspack-wizard__is-loading' : 'newspack-wizard__is-loaded', {
89
+ 'newspack-wizard__is-loading-quiet': isQuietLoading,
90
+ } ) }
84
91
  >
85
92
  <HashRouter hashType="slash">
86
93
  { newspack_aux_data.is_debug_mode && <Notice debugMode /> }
87
94
  <div className="bg-white">
88
95
  <div className="newspack-wizard__header__inner">
89
96
  <div className="newspack-wizard__title">
90
- <Button
91
- isLink
92
- href={ newspack_urls.dashboard }
93
- label={ __( 'Return to Dashboard', 'newspack-plugin' ) }
94
- showTooltip={ true }
95
- icon={ category }
96
- iconSize={ 36 }
97
- >
97
+ { newspack_urls.dashboard !== urlWithoutHash ? (
98
+ <Button
99
+ isLink
100
+ href={ newspack_urls.dashboard }
101
+ label={ __( 'Return to Dashboard', 'newspack-plugin' ) }
102
+ showTooltip={ true }
103
+ icon={ category }
104
+ iconSize={ 36 }
105
+ >
106
+ <NewspackIcon size={ 36 } />
107
+ </Button>
108
+ ) : (
98
109
  <NewspackIcon size={ 36 } />
99
- </Button>
110
+ ) }
100
111
  <div>
101
112
  { headerText && <h2>{ headerText }</h2> }
102
113
  { subHeaderText && <span>{ subHeaderText }</span> }
@@ -116,13 +127,8 @@ const Wizard = ( {
116
127
  { displayedSections.map( ( section, index ) => {
117
128
  const SectionComponent = section.render;
118
129
  return (
119
- <Route key={ index } path={ section.path }>
120
- <div
121
- className={ classnames(
122
- 'newspack-wizard newspack-wizard__content',
123
- className
124
- ) }
125
- >
130
+ <Route key={ index } exact={ section.exact ?? false } path={ section.path }>
131
+ <div className={ classnames( 'newspack-wizard__content', className ) }>
126
132
  { 'function' === typeof renderAboveSections ? renderAboveSections() : null }
127
133
  <SectionComponent />
128
134
  </div>
@@ -134,12 +140,8 @@ const Wizard = ( {
134
140
  </HashRouter>
135
141
  </div>
136
142
  { ! isLoading && <Footer simple={ hasSimpleFooter } /> }
137
- </>
143
+ </div>
138
144
  );
139
145
  };
140
146
 
141
- Wizard.useWizardData = useWizardData;
142
-
143
- Wizard.STORE_NAMESPACE = WIZARD_STORE_NAMESPACE;
144
-
145
- export default Wizard;
147
+ export default forwardRef( Wizard );
@@ -16,7 +16,7 @@ import { createAction } from './utils.js';
16
16
  export const WIZARD_STORE_NAMESPACE = 'newspack/wizards';
17
17
 
18
18
  const DEFAULT_STATE = {
19
- isLoading: true,
19
+ isLoading: false,
20
20
  isQuietLoading: false,
21
21
  apiData: {},
22
22
  error: null,
@@ -59,13 +59,7 @@ const actions = {
59
59
  setError: createAction( 'SET_ERROR' ),
60
60
 
61
61
  // Async actions. These will not show up in Redux devtools.
62
- *saveWizardSettings( {
63
- slug,
64
- section = '',
65
- payloadPath = false,
66
- auxData = {},
67
- updatePayload = null,
68
- } ) {
62
+ *saveWizardSettings( { slug, section = '', payloadPath = false, auxData = {}, updatePayload = null } ) {
69
63
  // Optionally data can be updated before saving - an immediate update case
70
64
  // (without an explicit "save" action).
71
65
  if ( updatePayload ) {
@@ -94,6 +88,7 @@ const selectors = {
94
88
  isLoading: state => state.isLoading,
95
89
  isQuietLoading: state => state.isQuietLoading,
96
90
  getWizardAPIData: ( state, slug ) => state.apiData[ slug ] || {},
91
+ getWizardData: ( state, slug ) => state.apiData[ slug ] ?? {},
97
92
  getError: state => state.error,
98
93
  };
99
94
 
@@ -104,8 +99,9 @@ const store = createReduxStore( WIZARD_STORE_NAMESPACE, {
104
99
 
105
100
  controls: {
106
101
  FETCH_FROM_API: action => {
102
+ const { isLocalError = false, isQuietFetch = false } = action.payload;
107
103
  dispatch( WIZARD_STORE_NAMESPACE ).startLoadingData( {
108
- isQuietLoading: Boolean( action.payload.isQuietFetch ),
104
+ isQuietLoading: Boolean( isQuietFetch ),
109
105
  } );
110
106
  return apiFetch( action.payload )
111
107
  .then( data => {
@@ -113,8 +109,10 @@ const store = createReduxStore( WIZARD_STORE_NAMESPACE, {
113
109
  return data;
114
110
  } )
115
111
  .catch( error => {
112
+ if ( isLocalError ) {
113
+ throw error;
114
+ }
116
115
  dispatch( WIZARD_STORE_NAMESPACE ).setError( error );
117
- return { error };
118
116
  } )
119
117
  .finally( result => {
120
118
  dispatch( WIZARD_STORE_NAMESPACE ).finishLoadingData();
@@ -10,7 +10,6 @@ import { WIZARD_STORE_NAMESPACE } from '.';
10
10
 
11
11
  export const createAction = type => payload => ( { type, payload } );
12
12
 
13
- export const useWizardData = ( wizardName, defaultValue = {} ) =>
14
- useSelect( select =>
15
- select( WIZARD_STORE_NAMESPACE ).getWizardAPIData( `newspack-${ wizardName }-wizard` )
16
- ) || defaultValue;
13
+ export const useWizardData = ( wizardName, defaultValue = {} ) => {
14
+ return useSelect( select => select( WIZARD_STORE_NAMESPACE ).getWizardAPIData( wizardName ) ) || defaultValue;
15
+ };
@@ -1,39 +0,0 @@
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 _reactDaterangePicker = _interopRequireDefault(require("react-daterange-picker"));
9
- var _moment = _interopRequireDefault(require("moment"));
10
- var _momentRange = require("moment-range");
11
- require("react-daterange-picker/dist/css/react-calendar.css");
12
- require("./style.scss");
13
- var _jsxRuntime = require("react/jsx-runtime");
14
- /**
15
- * External dependencies.
16
- */
17
-
18
- /**
19
- * Internal dependencies.
20
- */
21
-
22
- const moment = (0, _momentRange.extendMoment)(_moment.default);
23
- const DateRangePicker = ({
24
- start,
25
- end,
26
- onChange
27
- }) => {
28
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactDaterangePicker.default, {
29
- value: moment.range(moment(start), moment(end)),
30
- firstOfWeek: 1,
31
- onSelect: range => {
32
- onChange({
33
- start: range.start._d,
34
- end: range.end._d
35
- });
36
- }
37
- });
38
- };
39
- var _default = exports.default = DateRangePicker;