newspack-components 4.3.0 → 4.4.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 (263) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/DEVELOPMENT.md +868 -0
  3. package/colors/colors.module.scss +52 -2
  4. package/copy-styles.js +3 -2
  5. package/dist/cjs/accordion/index.js +17 -12
  6. package/dist/cjs/action-card/index.js +176 -139
  7. package/dist/cjs/autocomplete-tokenfield/index.js +254 -234
  8. package/dist/cjs/autocomplete-with-latest-posts/index.js +172 -110
  9. package/dist/cjs/autocomplete-with-suggestions/index.js +229 -126
  10. package/dist/cjs/badge/index.js +7 -7
  11. package/dist/cjs/box-contrast/index.js +19 -15
  12. package/dist/cjs/button/index.js +41 -26
  13. package/dist/cjs/button-props/button-props.js +5 -5
  14. package/dist/cjs/button-props/index.js +2 -2
  15. package/dist/cjs/card/core-card.js +110 -52
  16. package/dist/cjs/card/index.js +74 -67
  17. package/dist/cjs/card/style-core.scss +93 -25
  18. package/dist/cjs/card/style.scss +2 -2
  19. package/dist/cjs/card-feature/index.js +141 -0
  20. package/dist/cjs/card-feature/style.scss +75 -0
  21. package/dist/cjs/card-form/index.js +144 -0
  22. package/dist/cjs/card-form/style.scss +20 -0
  23. package/dist/cjs/card-settings-group/index.js +36 -16
  24. package/dist/cjs/card-sortable-list/index.js +176 -140
  25. package/dist/cjs/category-autocomplete/index.js +175 -155
  26. package/dist/cjs/color-picker/index.js +41 -23
  27. package/dist/cjs/color-picker/index.test.js +82 -0
  28. package/dist/cjs/color-picker/style.scss +11 -13
  29. package/dist/cjs/confirm-dialog/index.js +86 -22
  30. package/dist/cjs/consts.js +1 -1
  31. package/dist/cjs/custom-select-control/index.js +39 -28
  32. package/dist/cjs/dataviews/index.js +38 -0
  33. package/dist/cjs/dataviews/style.scss +9 -0
  34. package/dist/cjs/divider/index.js +26 -21
  35. package/dist/cjs/footer/index.js +36 -30
  36. package/dist/cjs/form-token-field/index.js +51 -40
  37. package/dist/cjs/global-notices/index.js +5 -5
  38. package/dist/cjs/grid/index.js +25 -19
  39. package/dist/cjs/grid/style.scss +6 -1
  40. package/dist/cjs/handoff/index.js +204 -156
  41. package/dist/cjs/handoff-message/index.js +12 -7
  42. package/dist/cjs/hooks/index.js +10 -8
  43. package/dist/cjs/hooks/use-confirm-dialog.js +79 -0
  44. package/dist/cjs/hooks/use-unsaved-changes-dialog.js +144 -0
  45. package/dist/cjs/hooks/useObjectState.js +21 -12
  46. package/dist/cjs/hooks/useObjectState.test.js +55 -33
  47. package/dist/cjs/hooks/useOnClickOutside.js +6 -6
  48. package/dist/cjs/hooks/usePrompt.js +10 -13
  49. package/dist/cjs/image-upload/index.js +114 -123
  50. package/dist/cjs/image-upload/index.test.js +11 -13
  51. package/dist/cjs/image-upload/style.scss +12 -40
  52. package/dist/cjs/index.js +136 -104
  53. package/dist/cjs/info-button/index.js +43 -32
  54. package/dist/cjs/integration-icons/active-campaign.js +22 -0
  55. package/dist/cjs/integration-icons/constant-contact.js +28 -0
  56. package/dist/cjs/integration-icons/fundraise-up.js +25 -0
  57. package/dist/cjs/integration-icons/index.js +48 -0
  58. package/dist/cjs/integration-icons/mailchimp.js +19 -0
  59. package/dist/cjs/integration-icons/salesforce.js +17 -0
  60. package/dist/cjs/integration-icons/wisepops.js +20 -0
  61. package/dist/cjs/modal/index.js +22 -19
  62. package/dist/cjs/modal/style.scss +4 -0
  63. package/dist/cjs/newspack-icon/index.js +45 -38
  64. package/dist/cjs/notice/index.js +64 -55
  65. package/dist/cjs/plugin-installer/index.js +259 -253
  66. package/dist/cjs/plugin-settings/SettingsSection.js +66 -60
  67. package/dist/cjs/plugin-settings/index.js +217 -200
  68. package/dist/cjs/plugin-toggle/index.js +192 -199
  69. package/dist/cjs/popover/index.js +41 -28
  70. package/dist/cjs/position-control/index.js +24 -23
  71. package/dist/cjs/progress-bar/index.js +71 -59
  72. package/dist/cjs/progress-bar/index.test.js +62 -68
  73. package/dist/cjs/proxied-imports/router.js +3 -3
  74. package/dist/cjs/radio-control/index.js +40 -27
  75. package/dist/cjs/section-header/index.js +103 -58
  76. package/dist/cjs/section-header/style.scss +31 -11
  77. package/dist/cjs/select-control/ButtonGroupControl.js +26 -21
  78. package/dist/cjs/select-control/GroupedSelectControl.js +41 -35
  79. package/dist/cjs/select-control/index.js +52 -40
  80. package/dist/cjs/settings/MinMaxSetting.js +30 -20
  81. package/dist/cjs/settings/SettingsCard.js +20 -17
  82. package/dist/cjs/settings/SettingsSection.js +22 -21
  83. package/dist/cjs/settings/index.js +5 -5
  84. package/dist/cjs/sortable-newsletter-list-control/index.js +78 -57
  85. package/dist/cjs/steps-list/index.js +44 -34
  86. package/dist/cjs/steps-list-item/index.js +47 -39
  87. package/dist/cjs/style-card/index.js +70 -63
  88. package/dist/cjs/tabbed-navigation/index.js +38 -36
  89. package/dist/cjs/text-control/index.js +27 -25
  90. package/dist/cjs/utils/color.js +4 -4
  91. package/dist/cjs/utils/editor-toolbar-back-button.js +61 -0
  92. package/dist/cjs/utils/index.js +31 -19
  93. package/dist/cjs/utils/style.scss +8 -0
  94. package/dist/cjs/waiting/index.js +48 -37
  95. package/dist/cjs/web-preview/index.js +217 -211
  96. package/dist/cjs/with-wizard/index.js +362 -364
  97. package/dist/cjs/with-wizard/style.scss +4 -54
  98. package/dist/cjs/with-wizard-screen/index.js +54 -58
  99. package/dist/cjs/with-wizard-screen/style.scss +41 -3
  100. package/dist/cjs/wizard/components/WizardError.js +20 -18
  101. package/dist/cjs/wizard/components/WizardSnackbar.js +26 -23
  102. package/dist/cjs/wizard/index.js +176 -114
  103. package/dist/cjs/wizard/store/index.js +171 -123
  104. package/dist/cjs/wizard/store/utils.js +13 -8
  105. package/dist/esm/accordion/index.js +14 -9
  106. package/dist/esm/action-card/index.js +168 -123
  107. package/dist/esm/autocomplete-tokenfield/index.js +248 -222
  108. package/dist/esm/autocomplete-with-latest-posts/index.js +169 -103
  109. package/dist/esm/autocomplete-with-suggestions/index.js +226 -119
  110. package/dist/esm/badge/index.js +5 -5
  111. package/dist/esm/box-contrast/index.js +15 -11
  112. package/dist/esm/button/index.js +39 -21
  113. package/dist/esm/button-props/button-props.js +1 -1
  114. package/dist/esm/card/core-card.js +109 -47
  115. package/dist/esm/card/index.js +69 -54
  116. package/dist/esm/card/style-core.scss +93 -25
  117. package/dist/esm/card/style.scss +2 -2
  118. package/dist/esm/card-feature/index.js +131 -0
  119. package/dist/esm/card-feature/style.scss +75 -0
  120. package/dist/esm/card-form/index.js +134 -0
  121. package/dist/esm/card-form/style.scss +20 -0
  122. package/dist/esm/card-settings-group/index.js +33 -14
  123. package/dist/esm/card-sortable-list/index.js +170 -126
  124. package/dist/esm/category-autocomplete/index.js +168 -140
  125. package/dist/esm/color-picker/index.js +39 -21
  126. package/dist/esm/color-picker/index.test.js +78 -0
  127. package/dist/esm/color-picker/style.scss +11 -13
  128. package/dist/esm/confirm-dialog/index.js +85 -18
  129. package/dist/esm/consts.js +1 -1
  130. package/dist/esm/custom-select-control/index.js +34 -15
  131. package/dist/esm/dataviews/index.js +34 -0
  132. package/dist/esm/dataviews/style.scss +9 -0
  133. package/dist/esm/divider/index.js +24 -16
  134. package/dist/esm/footer/index.js +34 -28
  135. package/dist/esm/form-token-field/index.js +46 -27
  136. package/dist/esm/global-notices/index.js +3 -3
  137. package/dist/esm/grid/index.js +23 -14
  138. package/dist/esm/grid/style.scss +6 -1
  139. package/dist/esm/handoff/index.js +199 -143
  140. package/dist/esm/handoff-message/index.js +10 -6
  141. package/dist/esm/hooks/index.js +8 -6
  142. package/dist/esm/hooks/use-confirm-dialog.js +73 -0
  143. package/dist/esm/hooks/use-unsaved-changes-dialog.js +136 -0
  144. package/dist/esm/hooks/useObjectState.js +19 -9
  145. package/dist/esm/hooks/useObjectState.test.js +54 -32
  146. package/dist/esm/hooks/useOnClickOutside.js +4 -4
  147. package/dist/esm/hooks/usePrompt.js +9 -11
  148. package/dist/esm/image-upload/index.js +110 -111
  149. package/dist/esm/image-upload/index.test.js +11 -13
  150. package/dist/esm/image-upload/style.scss +12 -40
  151. package/dist/esm/index.js +7 -1
  152. package/dist/esm/info-button/index.js +38 -19
  153. package/dist/esm/integration-icons/active-campaign.js +16 -0
  154. package/dist/esm/integration-icons/constant-contact.js +22 -0
  155. package/dist/esm/integration-icons/fundraise-up.js +19 -0
  156. package/dist/esm/integration-icons/index.js +6 -0
  157. package/dist/esm/integration-icons/mailchimp.js +13 -0
  158. package/dist/esm/integration-icons/salesforce.js +11 -0
  159. package/dist/esm/integration-icons/wisepops.js +14 -0
  160. package/dist/esm/modal/index.js +20 -13
  161. package/dist/esm/modal/style.scss +4 -0
  162. package/dist/esm/newspack-icon/index.js +40 -25
  163. package/dist/esm/notice/index.js +59 -42
  164. package/dist/esm/plugin-installer/index.js +255 -243
  165. package/dist/esm/plugin-settings/SettingsSection.js +61 -50
  166. package/dist/esm/plugin-settings/index.js +212 -189
  167. package/dist/esm/plugin-toggle/index.js +187 -190
  168. package/dist/esm/popover/index.js +35 -16
  169. package/dist/esm/position-control/index.js +22 -18
  170. package/dist/esm/progress-bar/index.js +66 -49
  171. package/dist/esm/progress-bar/index.test.js +61 -67
  172. package/dist/esm/radio-control/index.js +34 -15
  173. package/dist/esm/section-header/index.js +102 -57
  174. package/dist/esm/section-header/style.scss +31 -11
  175. package/dist/esm/select-control/ButtonGroupControl.js +23 -18
  176. package/dist/esm/select-control/GroupedSelectControl.js +38 -30
  177. package/dist/esm/select-control/index.js +47 -27
  178. package/dist/esm/settings/MinMaxSetting.js +27 -16
  179. package/dist/esm/settings/SettingsCard.js +18 -13
  180. package/dist/esm/settings/SettingsSection.js +20 -19
  181. package/dist/esm/settings/index.js +3 -3
  182. package/dist/esm/sortable-newsletter-list-control/index.js +74 -53
  183. package/dist/esm/steps-list/index.js +39 -21
  184. package/dist/esm/steps-list-item/index.js +42 -26
  185. package/dist/esm/style-card/index.js +65 -50
  186. package/dist/esm/tabbed-navigation/index.js +35 -33
  187. package/dist/esm/text-control/index.js +25 -19
  188. package/dist/esm/utils/color.js +4 -4
  189. package/dist/esm/utils/editor-toolbar-back-button.js +53 -0
  190. package/dist/esm/utils/index.js +29 -16
  191. package/dist/esm/utils/style.scss +8 -0
  192. package/dist/esm/waiting/index.js +43 -24
  193. package/dist/esm/web-preview/index.js +213 -201
  194. package/dist/esm/with-wizard/index.js +360 -358
  195. package/dist/esm/with-wizard/style.scss +4 -54
  196. package/dist/esm/with-wizard-screen/index.js +48 -46
  197. package/dist/esm/with-wizard-screen/style.scss +41 -3
  198. package/dist/esm/wizard/components/WizardError.js +18 -16
  199. package/dist/esm/wizard/components/WizardSnackbar.js +23 -17
  200. package/dist/esm/wizard/index.js +171 -103
  201. package/dist/esm/wizard/store/index.js +169 -116
  202. package/dist/esm/wizard/store/utils.js +13 -6
  203. package/package.json +30 -16
  204. package/release.config.js +1 -0
  205. package/shared/hooks/use-coauthors.js +195 -27
  206. package/shared/hooks/use-coauthors.test.js +232 -6
  207. package/shared/scss/_mixins.scss +13 -5
  208. package/src/accordion/index.js +8 -7
  209. package/src/action-card/index.js +15 -1
  210. package/src/badge/index.tsx +3 -1
  211. package/src/card/core-card.js +95 -18
  212. package/src/card/index.js +1 -0
  213. package/src/card/style-core.scss +93 -25
  214. package/src/card/style.scss +2 -2
  215. package/src/card-feature/README.md +188 -0
  216. package/src/card-feature/index.tsx +186 -0
  217. package/src/card-feature/style.scss +75 -0
  218. package/src/card-form/README.md +113 -0
  219. package/src/card-form/index.tsx +128 -0
  220. package/src/card-form/style.scss +20 -0
  221. package/src/card-settings-group/index.tsx +28 -3
  222. package/src/card-sortable-list/index.tsx +27 -4
  223. package/src/color-picker/index.js +15 -8
  224. package/src/color-picker/index.test.js +52 -0
  225. package/src/color-picker/style.scss +11 -13
  226. package/src/confirm-dialog/README.md +128 -0
  227. package/src/confirm-dialog/index.tsx +74 -6
  228. package/src/dataviews/index.tsx +34 -0
  229. package/src/dataviews/style.scss +9 -0
  230. package/src/grid/style.scss +6 -1
  231. package/src/handoff/README.md +93 -0
  232. package/src/handoff/index.js +46 -8
  233. package/src/hooks/index.ts +2 -1
  234. package/src/hooks/use-confirm-dialog.tsx +80 -0
  235. package/src/hooks/use-unsaved-changes-dialog.tsx +140 -0
  236. package/src/image-upload/index.js +10 -15
  237. package/src/image-upload/style.scss +12 -40
  238. package/src/index.js +7 -1
  239. package/src/integration-icons/active-campaign.js +14 -0
  240. package/src/integration-icons/constant-contact.js +22 -0
  241. package/src/integration-icons/fundraise-up.js +18 -0
  242. package/src/integration-icons/index.js +6 -0
  243. package/src/integration-icons/mailchimp.js +10 -0
  244. package/src/integration-icons/salesforce.js +10 -0
  245. package/src/integration-icons/wisepops.js +14 -0
  246. package/src/modal/style.scss +4 -0
  247. package/src/plugin-installer/index.js +30 -19
  248. package/src/section-header/index.js +56 -24
  249. package/src/section-header/style.scss +31 -11
  250. package/src/select-control/index.js +4 -0
  251. package/src/utils/editor-toolbar-back-button.tsx +48 -0
  252. package/src/utils/index.js +6 -0
  253. package/src/utils/style.scss +8 -0
  254. package/src/with-wizard/style.scss +4 -54
  255. package/src/with-wizard-screen/style.scss +41 -3
  256. package/src/wizard/index.js +90 -53
  257. package/src/wizard/store/index.js +2 -2
  258. package/dist/cjs/button-card/index.js +0 -72
  259. package/dist/cjs/button-card/style.scss +0 -180
  260. package/dist/esm/button-card/index.js +0 -64
  261. package/dist/esm/button-card/style.scss +0 -180
  262. package/src/button-card/index.js +0 -52
  263. package/src/button-card/style.scss +0 -180
@@ -7,8 +7,8 @@
7
7
  */
8
8
  import { __ } from '@wordpress/i18n';
9
9
  import { useEffect, useRef } from '@wordpress/element';
10
- import { Tooltip } from '@wordpress/components'; // eslint-disable-line @wordpress/no-unsafe-wp-apis
11
- import { Icon, chevronLeft } from '@wordpress/icons';
10
+ import { DropdownMenu, MenuItem, Tooltip, __experimentalHStack as HStack } from '@wordpress/components'; // eslint-disable-line @wordpress/no-unsafe-wp-apis
11
+ import { Icon, chevronLeft, moreVertical } from '@wordpress/icons';
12
12
 
13
13
  /**
14
14
  * Internal dependencies
@@ -59,6 +59,7 @@ const SectionHeader = ( {
59
59
  pageHeader = false,
60
60
  title,
61
61
  id = null,
62
+ menu,
62
63
  primaryAction,
63
64
  secondaryAction,
64
65
  children = null,
@@ -86,6 +87,48 @@ const SectionHeader = ( {
86
87
 
87
88
  const HeadingTag = pageHeader ? 'h1' : `h${ heading }`;
88
89
 
90
+ let titleContent = null;
91
+
92
+ if ( typeof title === 'string' ) {
93
+ titleContent = (
94
+ <div className="newspack-section-header__title-container">
95
+ <HeadingTag>
96
+ { title }
97
+ { badges?.length
98
+ ? badges.map( ( badge, i ) => <Badge key={ i } text={ badge.label } level={ badge.level || 'default' } /> )
99
+ : null }
100
+ </HeadingTag>
101
+ { menu?.length > 0 && (
102
+ <DropdownMenu className="newspack-section-header__menu" icon={ moreVertical } label={ __( 'More options', 'newspack-plugin' ) }>
103
+ { () =>
104
+ menu.map( ( item, index ) => (
105
+ <MenuItem
106
+ key={ index }
107
+ icon={ item.icon }
108
+ href={ item.href }
109
+ onClick={ item.action }
110
+ disabled={ item.disabled || false }
111
+ isDestructive={ item.destructive || false }
112
+ >
113
+ { item.label }
114
+ </MenuItem>
115
+ ) )
116
+ }
117
+ </DropdownMenu>
118
+ ) }
119
+ { secondaryAction && (
120
+ <div className="newspack-section-header__secondary-action">
121
+ <Button variant="link" href={ secondaryAction.href } onClick={ secondaryAction.action }>
122
+ { secondaryAction.label }
123
+ </Button>
124
+ </div>
125
+ ) }
126
+ </div>
127
+ );
128
+ } else if ( typeof title === 'function' ) {
129
+ titleContent = <HeadingTag>{ title() }</HeadingTag>;
130
+ }
131
+
89
132
  return (
90
133
  <div
91
134
  id={ id }
@@ -103,29 +146,18 @@ const SectionHeader = ( {
103
146
  <Icon icon={ icon } size={ 48 } />
104
147
  </div>
105
148
  ) }
106
- { backNav && (
107
- <div className="newspack-section-header__back-nav">
108
- <Tooltip text={ __( 'Go back', 'newspack-plugin' ) }>
109
- <Button href={ backNav } icon={ chevronLeft } variant="tertiary" />
110
- </Tooltip>
111
- </div>
112
- ) }
113
- { typeof title === 'string' && (
114
- <div className="newspack-section-header__title-container">
115
- <HeadingTag>{ title }</HeadingTag>
116
- { badges?.length
117
- ? badges.map( ( badge, i ) => <Badge key={ i } text={ badge.label } level={ badge.level || 'default' } /> )
118
- : null }
119
- { secondaryAction && (
120
- <div className="newspack-section-header__secondary-action">
121
- <Button variant="link" href={ secondaryAction.href } onClick={ secondaryAction.action }>
122
- { secondaryAction.label }
123
- </Button>
124
- </div>
125
- ) }
126
- </div>
149
+ { backNav ? (
150
+ <HStack alignment="left" style={ { position: 'relative' } }>
151
+ <div className="newspack-section-header__back-nav">
152
+ <Tooltip text={ __( 'Go back', 'newspack-plugin' ) }>
153
+ <Button href={ backNav } icon={ chevronLeft } variant="tertiary" />
154
+ </Tooltip>
155
+ </div>
156
+ { titleContent }
157
+ </HStack>
158
+ ) : (
159
+ titleContent
127
160
  ) }
128
- { typeof title === 'function' && <HeadingTag>{ title() }</HeadingTag> }
129
161
  { description && typeof description === 'string' && <p>{ description }</p> }
130
162
  { typeof description === 'function' && <p>{ description() }</p> }
131
163
  { description && typeof description !== 'string' && typeof description !== 'function' && <p>{ description }</p> }
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  @use "~@wordpress/base-styles/colors" as wp-colors;
6
+ @use "~@wordpress/base-styles/variables" as wp-vars;
6
7
  @use "../../../colors/colors.module" as colors;
7
8
 
8
9
  .newspack-section-header {
@@ -14,6 +15,9 @@
14
15
  &:not(:first-child) {
15
16
  margin-top: 48px;
16
17
  }
18
+ &:has(> .newspack-section-header--no-margin) {
19
+ margin-top: 0;
20
+ }
17
21
  &.newspack-section-header--has-primary-action {
18
22
  display: flex;
19
23
  flex-direction: column;
@@ -24,18 +28,22 @@
24
28
  }
25
29
  }
26
30
  &.newspack-section-header--has-back-nav {
27
- --back-nav-button-size: 36px;
28
- margin-left: calc(var(--back-nav-button-size) + 8px);
29
31
  @media (min-width: 782px) {
30
- margin-left: 0;
32
+ .newspack-section-header__title-container,
33
+ p {
34
+ max-width: calc(50% - 16px);
35
+ }
31
36
  }
32
37
  }
33
38
  }
34
39
 
35
40
  &__back-nav {
36
- left: calc((var(--back-nav-button-size) + 8px) * -1);
37
- position: absolute;
38
- top: calc(50% - (var(--back-nav-button-size) / 2));
41
+ @media (min-width: 1280px) {
42
+ left: 0;
43
+ position: absolute;
44
+ top: 50%;
45
+ transform: translate(calc(-100% - 8px), -50%);
46
+ }
39
47
  a,
40
48
  button {
41
49
  color: inherit !important;
@@ -77,15 +85,27 @@
77
85
  }
78
86
 
79
87
  &__title-container {
80
- align-items: baseline;
88
+ align-items: center;
81
89
  display: flex;
82
90
  gap: 8px;
83
91
 
92
+ h2 {
93
+ font-size: wp-vars.$font-size-x-large;
94
+ font-weight: wp-vars.$font-weight-medium;
95
+ line-height: wp-vars.$font-line-height-x-large;
96
+ }
97
+
98
+ .newspack-section-header__menu,
99
+ .newspack-section-header__secondary-action,
84
100
  .newspack-badge {
85
- transform: translateY(-4px);
101
+ margin-top: 8px;
86
102
  }
87
103
  }
88
104
 
105
+ &__menu {
106
+ align-self: center;
107
+ }
108
+
89
109
  &__primary-action {
90
110
  @media (min-width: 782px) {
91
111
  display: flex;
@@ -142,9 +162,9 @@
142
162
  }
143
163
  }
144
164
  h1 {
145
- font-size: 1.25rem;
146
- font-weight: 500;
147
- line-height: 1.5;
165
+ font-size: wp-vars.$font-size-x-large;
166
+ font-weight: wp-vars.$font-weight-medium;
167
+ line-height: wp-vars.$font-line-height-x-large;
148
168
  }
149
169
  }
150
170
  }
@@ -1,5 +1,9 @@
1
1
  /**
2
2
  * Select Control
3
+ *
4
+ * @deprecated For new features, use the core `SelectControl` (and `__experimentalToggleGroupControl` for
5
+ * grouped/button-style selections) from `@wordpress/components` instead of this wrapper. This component
6
+ * is kept only for existing usages and should not be used in new code.
3
7
  */
4
8
 
5
9
  /**
@@ -0,0 +1,48 @@
1
+ /**
2
+ * A utility to add a back button to the editor toolbar.
3
+ */
4
+
5
+ /**
6
+ * WordPress dependencies
7
+ */
8
+ import { __ } from '@wordpress/i18n';
9
+ import { Button, Tooltip } from '@wordpress/components';
10
+ import { subscribe } from '@wordpress/data';
11
+ import domReady from '@wordpress/dom-ready';
12
+ import { createRoot } from '@wordpress/element';
13
+ import { arrowUpLeft } from '@wordpress/icons';
14
+
15
+ /**
16
+ * Internal dependencies
17
+ */
18
+ import './style.scss';
19
+
20
+ const WRAPPER_ID = 'newspack-editor-toolbar-wrapper';
21
+
22
+ const ToolbarButton = ( { href }: { href: string } ) => (
23
+ <Tooltip text={ __( 'Go back', 'newspack-plugin' ) }>
24
+ <Button icon={ arrowUpLeft } label={ __( 'Go back', 'newspack-plugin' ) } href={ href } />
25
+ </Tooltip>
26
+ );
27
+
28
+ export const addToolbarBackButton = ( href: string = '' ) => {
29
+ const unsubscribe = subscribe( () => {
30
+ domReady( () => {
31
+ if ( document.getElementById( WRAPPER_ID ) ) {
32
+ return;
33
+ }
34
+ const toolbar = document.querySelector( '.editor-header__toolbar' );
35
+ if ( ! toolbar ) {
36
+ return;
37
+ }
38
+
39
+ const wrapper = document.createElement( 'div' );
40
+ wrapper.id = WRAPPER_ID;
41
+ toolbar.prepend( wrapper );
42
+
43
+ const root = createRoot( wrapper );
44
+ root.render( <ToolbarButton href={ href } /> );
45
+ unsubscribe();
46
+ } );
47
+ } );
48
+ };
@@ -3,6 +3,11 @@
3
3
  */
4
4
  import { ENTER } from '@wordpress/keycodes';
5
5
 
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import { addToolbarBackButton } from './editor-toolbar-back-button';
10
+
6
11
  const InteractiveDiv = ( { style = {}, ...props } ) => (
7
12
  <div
8
13
  tabIndex="0"
@@ -24,4 +29,5 @@ const confirmAction = message => {
24
29
  export default {
25
30
  InteractiveDiv,
26
31
  confirmAction,
32
+ addToolbarBackButton,
27
33
  };
@@ -0,0 +1,8 @@
1
+ @use "~@wordpress/base-styles/variables" as wp-vars;
2
+
3
+ #newspack-editor-toolbar-wrapper {
4
+ margin-right: wp-vars.$grid-unit-10;
5
+ .is-fullscreen-mode & {
6
+ display: none;
7
+ }
8
+ }
@@ -51,6 +51,10 @@ body.newspack-wizard-page:not(.newspack-admin-header) {
51
51
  padding-bottom: 136px;
52
52
  }
53
53
  }
54
+
55
+ .components-popover__content {
56
+ min-width: 192px;
57
+ }
54
58
  }
55
59
 
56
60
  // Styling for wizards that are admin-header-only.
@@ -81,37 +85,6 @@ svg {
81
85
  }
82
86
  }
83
87
 
84
- // Blue Screen
85
- .newspack-wizard__blue {
86
- #wpwrap {
87
- background: var(--wp-admin-theme-color);
88
- }
89
-
90
- .newspack-footer {
91
- background: var(--wp-admin-theme-color);
92
- border-color: var(--wp-admin-theme-color);
93
- justify-content: center;
94
-
95
- &__logo {
96
- background: inherit;
97
- }
98
- }
99
-
100
- #wpfooter {
101
- color: white;
102
-
103
- a {
104
- color: inherit;
105
-
106
- &:active,
107
- &:focus,
108
- &:hover {
109
- opacity: 0.75;
110
- }
111
- }
112
- }
113
- }
114
-
115
88
  // Loading
116
89
  .newspack-wizard__is-loading {
117
90
  background: white;
@@ -174,29 +147,6 @@ svg {
174
147
  }
175
148
  }
176
149
 
177
- // Blue Screen
178
- .newspack-wizard__blue & {
179
- background: var(--wp-admin-theme-color);
180
-
181
- &::before {
182
- animation: loading-quiet 1.25s ease-in-out infinite;
183
- background: white;
184
- border-radius: 0;
185
- box-shadow: 0;
186
- height: 8px;
187
- left: 0;
188
- margin: 0;
189
- position: absolute;
190
- right: 100%;
191
- top: 0;
192
- width: auto;
193
- }
194
-
195
- &::after {
196
- display: none;
197
- }
198
- }
199
-
200
150
  // Quiet
201
151
  &-quiet {
202
152
  position: relative;
@@ -65,18 +65,38 @@
65
65
  }
66
66
  }
67
67
  &__inner {
68
- flex: 1;
68
+ flex: 1 1 100%;
69
69
  }
70
70
  &__actions {
71
71
  align-items: center;
72
72
  display: flex;
73
- flex: 1 1 auto;
74
73
  gap: 8px;
75
74
  justify-content: flex-end;
76
75
  padding: 0 24px 0 0;
76
+ > .newspack-wizard__header__actions__main {
77
+ display: none;
78
+ }
79
+ @media only screen and ( min-width: 782px ) {
80
+ flex: 1 1 auto;
81
+ > .newspack-wizard__header__actions__main {
82
+ display: flex;
83
+ }
84
+ &__more {
85
+ &--primary-only,
86
+ .newspack-wizard__header__actions__more__main {
87
+ display: none;
88
+ }
89
+ }
90
+ }
77
91
  }
78
92
  }
79
93
 
94
+ &__main {
95
+ overflow-x: hidden;
96
+ padding-bottom: 1px; /* Prevents borders from being cut off */
97
+ }
98
+
99
+
80
100
  &__title {
81
101
  align-items: center;
82
102
  display: flex;
@@ -149,7 +169,15 @@
149
169
  }
150
170
 
151
171
  &__section-header {
152
- margin-bottom: 32px;
172
+ margin: 0 auto 32px;
173
+ max-width: calc(calc(var(--newspack-wizard-section-space) * 2) + var(--newspack-wizard-section-width));
174
+ &:not(.newspack-section-header--has-primary-action) {
175
+ @media (min-width: 782px) {
176
+ .newspack-section-header__title-container + p {
177
+ max-width: 50%;
178
+ }
179
+ }
180
+ }
153
181
  }
154
182
 
155
183
  &__content {
@@ -180,6 +208,16 @@
180
208
  margin: 64px 0;
181
209
  }
182
210
  }
211
+ &:not(.newspack-wizard__content--full-width) {
212
+ .newspack-dataviews {
213
+ margin-left: -24px;
214
+ margin-right: -24px;
215
+ @media (min-width: 380px) {
216
+ margin-left: -48px;
217
+ margin-right: -48px;
218
+ }
219
+ }
220
+ }
183
221
  }
184
222
 
185
223
  &__above-header {
@@ -10,7 +10,7 @@ import { DropdownMenu, MenuItem } from '@wordpress/components';
10
10
  import { useDispatch, useSelect } from '@wordpress/data';
11
11
  import { useEffect, useState, forwardRef } from '@wordpress/element';
12
12
  import { __ } from '@wordpress/i18n';
13
- import { category, moreVertical } from '@wordpress/icons';
13
+ import { category, chevronLeft, moreVertical } from '@wordpress/icons';
14
14
 
15
15
  /**
16
16
  * Internal dependencies
@@ -23,6 +23,19 @@ import WizardError from './components/WizardError';
23
23
 
24
24
  registerStore();
25
25
 
26
+ /**
27
+ * Icon registry for resolving icon name strings passed through the data store.
28
+ * React elements from @wordpress/icons can't cross webpack entry point boundaries
29
+ * because each bundle has its own copy of the icon primitives.
30
+ */
31
+ const ICON_REGISTRY = { chevronLeft, category, moreVertical };
32
+ const resolveIcon = icon => {
33
+ if ( typeof icon === 'string' ) {
34
+ return ICON_REGISTRY[ icon ] || null;
35
+ }
36
+ return icon;
37
+ };
38
+
26
39
  const { HashRouter, Redirect, Route, Switch, useLocation } = Router;
27
40
 
28
41
  /**
@@ -34,6 +47,7 @@ const ResetHeaderData = () => {
34
47
 
35
48
  useEffect( () => {
36
49
  resetHeaderData();
50
+ window.scrollTo( 0, 0 );
37
51
  }, [ location.pathname, resetHeaderData ] );
38
52
 
39
53
  return null;
@@ -80,7 +94,8 @@ const Wizard = (
80
94
  const isQuietLoading = useSelect( select => select( WIZARD_STORE_NAMESPACE ).isQuietLoading() );
81
95
  const headerData = useSelect( select => select( WIZARD_STORE_NAMESPACE ).getHeaderData() );
82
96
  const notices = useSelect( select => select( WIZARD_STORE_NAMESPACE ).getNotices() );
83
- const { actions, backNav, badges, sectionDescription, sectionName, sectionTitle, sectionPrimaryAction, sectionSecondaryAction } = headerData;
97
+ const { actions, backNav, badges, sectionDescription, sectionMenu, sectionName, sectionTitle, sectionPrimaryAction, sectionSecondaryAction } =
98
+ headerData;
84
99
 
85
100
  const mainActions = actions?.filter( action => action.type === 'primary' || action.type === 'secondary' );
86
101
  const moreActions = actions?.filter( action => action.type === 'more' );
@@ -104,6 +119,10 @@ const Wizard = (
104
119
  ];
105
120
  }
106
121
 
122
+ // When plugins are required but not yet satisfied, `displayedSections` is replaced with
123
+ // the PluginInstaller. Use it for routing so the installer actually mounts and runs.
124
+ const routedSections = pluginRequirementsSatisfied ? sections : displayedSections;
125
+
107
126
  const urlWithoutHash = window.location.href.split( '#' )[ 0 ];
108
127
 
109
128
  return (
@@ -153,7 +172,9 @@ const Wizard = (
153
172
  { mainActions.map( ( action, index ) => (
154
173
  <Button
155
174
  key={ index }
156
- icon={ action.icon }
175
+ className="newspack-wizard__header__actions__main"
176
+ href={ action.href }
177
+ icon={ resolveIcon( action.icon ) }
157
178
  variant={ action.type }
158
179
  onClick={ action.action }
159
180
  disabled={ action.disabled || false }
@@ -162,23 +183,32 @@ const Wizard = (
162
183
  { action.label }
163
184
  </Button>
164
185
  ) ) }
165
- { moreActions.length > 0 && (
166
- <DropdownMenu icon={ moreVertical } label={ __( 'More', 'newspack-plugin' ) }>
167
- { () =>
168
- moreActions.map( ( action, index ) => (
169
- <MenuItem
170
- key={ index }
171
- icon={ action.icon }
172
- onClick={ action.action }
173
- disabled={ action.disabled || false }
174
- isDestructive={ action.destructive || false }
175
- >
176
- { action.label }
177
- </MenuItem>
178
- ) )
179
- }
180
- </DropdownMenu>
181
- ) }
186
+ <DropdownMenu
187
+ className={ moreActions?.length === 0 ? 'newspack-wizard__header__actions__more--primary-only' : '' }
188
+ icon={ moreVertical }
189
+ label={ __( 'More', 'newspack-plugin' ) }
190
+ popoverProps={ { className: 'newspack-wizard__header__actions__more' } }
191
+ >
192
+ { () =>
193
+ actions.map( ( action, index ) => (
194
+ <MenuItem
195
+ key={ index }
196
+ className={
197
+ action.type === 'primary' || action.type === 'secondary'
198
+ ? 'newspack-wizard__header__actions__more__main'
199
+ : 'newspack-wizard__header__actions__more__more'
200
+ }
201
+ icon={ action.icon }
202
+ href={ action.href }
203
+ onClick={ action.action }
204
+ disabled={ action.disabled || false }
205
+ isDestructive={ action.destructive || false }
206
+ >
207
+ { action.label }
208
+ </MenuItem>
209
+ ) )
210
+ }
211
+ </DropdownMenu>
182
212
  </div>
183
213
  ) }
184
214
  </div>
@@ -192,39 +222,46 @@ const Wizard = (
192
222
 
193
223
  { sections.length > 1 && <ResetHeaderData /> }
194
224
 
195
- <Switch>
196
- { sections.map( ( section, index ) => {
197
- const SectionComponent = section.render;
198
- const sectionProps = section.props || {};
199
- return (
200
- <Route
201
- key={ index }
202
- exact={ section.exact ?? false }
203
- path={ section.path }
204
- render={ routerProps => (
205
- <div className={ classnames( 'newspack-wizard__content', className ) }>
206
- { 'function' === typeof renderAboveSections ? renderAboveSections() : null }
207
- { ( sectionTitle || section.title ) && (
208
- <SectionHeader
209
- className="newspack-wizard__section-header"
210
- backNav={ backNav || section.backNav }
211
- title={ sectionTitle || section.title }
212
- description={ sectionDescription || section.description }
213
- badges={ badges || section.badges }
214
- primaryAction={ sectionPrimaryAction || section.primaryAction }
215
- secondaryAction={ sectionSecondaryAction || section.secondaryAction }
216
- heading={ 1 }
217
- noMargin
218
- />
219
- ) }
220
- <SectionComponent { ...routerProps } { ...sectionProps } { ...sharedProps } />
221
- </div>
222
- ) }
223
- />
224
- );
225
- } ) }
226
- <Redirect to={ displayedSections[ 0 ].path } />
227
- </Switch>
225
+ <div className="newspack-wizard__main">
226
+ <Switch>
227
+ { routedSections.map( ( section, index ) => {
228
+ const SectionComponent = section.render;
229
+ const sectionProps = section.props || {};
230
+ return (
231
+ <Route
232
+ key={ index }
233
+ exact={ section.exact ?? false }
234
+ path={ section.path }
235
+ render={ routerProps => (
236
+ <div
237
+ className={ classnames( 'newspack-wizard__content', className, {
238
+ 'newspack-wizard__content--full-width': section.fullWidth,
239
+ } ) }
240
+ >
241
+ { 'function' === typeof renderAboveSections ? renderAboveSections() : null }
242
+ { ( sectionTitle || section.title ) && (
243
+ <SectionHeader
244
+ className="newspack-wizard__section-header"
245
+ backNav={ backNav || section.backNav }
246
+ title={ sectionTitle || section.title }
247
+ description={ sectionDescription || section.description }
248
+ badges={ badges || section.badges }
249
+ menu={ sectionMenu || section.menu }
250
+ primaryAction={ sectionPrimaryAction || section.primaryAction }
251
+ secondaryAction={ sectionSecondaryAction || section.secondaryAction }
252
+ heading={ 1 }
253
+ noMargin
254
+ />
255
+ ) }
256
+ <SectionComponent { ...routerProps } { ...sectionProps } { ...sharedProps } />
257
+ </div>
258
+ ) }
259
+ />
260
+ );
261
+ } ) }
262
+ <Redirect to={ displayedSections[ 0 ].path } />
263
+ </Switch>
264
+ </div>
228
265
  </HashRouter>
229
266
  { notices?.length > 0 &&
230
267
  notices.map( ( notice, index ) => (
@@ -52,9 +52,9 @@ const reducer = ( state = DEFAULT_STATE, { type, payload = {} } ) => {
52
52
  case 'FINISH_LOADING_DATA':
53
53
  return { ...state, isLoading: false, isQuietLoading: false };
54
54
  case 'SET_API_DATA':
55
- return set( clone( state ), [ 'apiData', payload.slug ], payload.data );
55
+ return { ...state, apiData: set( clone( state.apiData ), [ payload.slug ], payload.data ) };
56
56
  case 'UPDATE_WIZARD_SETTINGS':
57
- return set( clone( state ), [ 'apiData', payload.slug, ...payload.path ], payload.value );
57
+ return { ...state, apiData: set( clone( state.apiData ), [ payload.slug, ...payload.path ], payload.value ) };
58
58
  case 'ADD_NOTICE':
59
59
  return { ...state, notices: [ ...state.notices, payload ] };
60
60
  case 'REMOVE_NOTICE':