newspack-components 2.2.1 → 3.0.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 (168) hide show
  1. package/dist/cjs/action-card/index.js +3 -4
  2. package/dist/cjs/autocomplete-tokenfield/index.js +52 -15
  3. package/dist/cjs/autocomplete-tokenfield/style.scss +11 -5
  4. package/dist/cjs/autocomplete-with-suggestions/index.js +45 -57
  5. package/dist/cjs/autocomplete-with-suggestions/style.scss +1 -9
  6. package/dist/cjs/button/index.js +8 -9
  7. package/dist/cjs/button-card/index.js +1 -2
  8. package/dist/cjs/card/index.js +1 -2
  9. package/dist/cjs/category-autocomplete/index.js +4 -8
  10. package/dist/cjs/color-picker/index.js +7 -9
  11. package/dist/cjs/consts.js +2 -7
  12. package/dist/cjs/custom-select-control/index.js +1 -2
  13. package/dist/cjs/footer/index.js +24 -29
  14. package/dist/cjs/form-token-field/index.js +1 -2
  15. package/dist/cjs/global-notices/index.js +1 -2
  16. package/dist/cjs/grid/index.js +14 -31
  17. package/dist/cjs/handoff/index.js +7 -8
  18. package/dist/cjs/hooks/index.js +2 -3
  19. package/dist/cjs/hooks/useObjectState.js +1 -2
  20. package/dist/cjs/hooks/useOnClickOutside.js +1 -2
  21. package/dist/cjs/hooks/usePrompt.js +1 -4
  22. package/dist/cjs/image-upload/index.js +5 -6
  23. package/dist/cjs/index.js +0 -14
  24. package/dist/cjs/info-button/index.js +1 -2
  25. package/dist/cjs/modal/index.js +1 -2
  26. package/dist/cjs/newspack-icon/index.js +1 -2
  27. package/dist/cjs/newspack-logo/index.js +1 -2
  28. package/dist/cjs/notice/index.js +2 -3
  29. package/dist/cjs/patrons-logo/index.js +4 -5
  30. package/dist/cjs/plugin-installer/index.js +9 -13
  31. package/dist/cjs/plugin-settings/SettingsSection.js +2 -4
  32. package/dist/cjs/plugin-settings/index.js +2 -3
  33. package/dist/cjs/plugin-toggle/index.js +16 -20
  34. package/dist/cjs/popover/index.js +1 -2
  35. package/dist/cjs/position-control/index.js +22 -23
  36. package/dist/cjs/progress-bar/index.js +1 -2
  37. package/dist/cjs/progress-bar/index.test.js +4 -5
  38. package/dist/cjs/proxied-imports/router.js +1 -2
  39. package/dist/cjs/radio-control/index.js +1 -2
  40. package/dist/cjs/section-header/index.js +13 -14
  41. package/dist/cjs/section-header/style.scss +4 -0
  42. package/dist/cjs/select-control/ButtonGroupControl.js +10 -12
  43. package/dist/cjs/select-control/GroupedSelectControl.js +21 -25
  44. package/dist/cjs/select-control/index.js +1 -2
  45. package/dist/cjs/settings/MinMaxSetting.js +17 -15
  46. package/dist/cjs/settings/SettingsCard.js +10 -12
  47. package/dist/cjs/settings/SettingsSection.js +20 -24
  48. package/dist/cjs/settings/index.js +2 -3
  49. package/dist/cjs/settings/style.scss +14 -1
  50. package/dist/cjs/sortable-newsletter-list-control/index.js +134 -0
  51. package/dist/cjs/sortable-newsletter-list-control/style.scss +45 -0
  52. package/dist/cjs/steps-list/index.js +1 -2
  53. package/dist/cjs/steps-list-item/index.js +1 -2
  54. package/dist/cjs/style-card/index.js +6 -7
  55. package/dist/cjs/style.scss +13 -1
  56. package/dist/cjs/tabbed-navigation/index.js +11 -14
  57. package/dist/cjs/text-control/index.js +32 -42
  58. package/dist/cjs/utils/index.js +15 -19
  59. package/dist/cjs/waiting/index.js +1 -2
  60. package/dist/cjs/web-preview/index.js +7 -8
  61. package/dist/cjs/with-wizard/index.js +6 -7
  62. package/dist/cjs/with-wizard-screen/index.js +20 -24
  63. package/dist/cjs/wizard/components/WizardError.js +7 -9
  64. package/dist/cjs/wizard/index.js +16 -21
  65. package/dist/cjs/wizard/store/index.js +36 -37
  66. package/dist/cjs/wizard/store/utils.js +1 -4
  67. package/dist/esm/action-card/index.js +3 -4
  68. package/dist/esm/autocomplete-tokenfield/index.js +52 -15
  69. package/dist/esm/autocomplete-tokenfield/style.scss +11 -5
  70. package/dist/esm/autocomplete-with-suggestions/index.js +46 -59
  71. package/dist/esm/autocomplete-with-suggestions/style.scss +1 -9
  72. package/dist/esm/button/index.js +7 -7
  73. package/dist/esm/button-card/index.js +1 -2
  74. package/dist/esm/category-autocomplete/index.js +4 -8
  75. package/dist/esm/color-picker/index.js +7 -9
  76. package/dist/esm/consts.js +0 -2
  77. package/dist/esm/footer/index.js +24 -29
  78. package/dist/esm/form-token-field/index.js +1 -2
  79. package/dist/esm/grid/index.js +13 -29
  80. package/dist/esm/handoff/index.js +7 -8
  81. package/dist/esm/hooks/useObjectState.js +1 -2
  82. package/dist/esm/hooks/useObjectState.test.js +1 -2
  83. package/dist/esm/hooks/usePrompt.js +1 -4
  84. package/dist/esm/image-upload/index.js +5 -7
  85. package/dist/esm/index.js +0 -2
  86. package/dist/esm/notice/index.js +2 -3
  87. package/dist/esm/patrons-logo/index.js +4 -5
  88. package/dist/esm/plugin-installer/index.js +9 -14
  89. package/dist/esm/plugin-settings/SettingsSection.js +2 -4
  90. package/dist/esm/plugin-settings/index.js +2 -3
  91. package/dist/esm/plugin-toggle/index.js +16 -20
  92. package/dist/esm/position-control/index.js +23 -25
  93. package/dist/esm/progress-bar/index.js +1 -2
  94. package/dist/esm/progress-bar/index.test.js +4 -5
  95. package/dist/esm/section-header/index.js +13 -14
  96. package/dist/esm/section-header/style.scss +4 -0
  97. package/dist/esm/select-control/ButtonGroupControl.js +9 -10
  98. package/dist/esm/select-control/GroupedSelectControl.js +22 -27
  99. package/dist/esm/settings/MinMaxSetting.js +17 -16
  100. package/dist/esm/settings/SettingsCard.js +9 -10
  101. package/dist/esm/settings/SettingsSection.js +20 -24
  102. package/dist/esm/settings/style.scss +14 -1
  103. package/dist/esm/sortable-newsletter-list-control/index.js +128 -0
  104. package/dist/esm/sortable-newsletter-list-control/style.scss +45 -0
  105. package/dist/esm/steps-list-item/index.js +1 -2
  106. package/dist/esm/style-card/index.js +6 -7
  107. package/dist/esm/style.scss +13 -1
  108. package/dist/esm/tabbed-navigation/index.js +11 -14
  109. package/dist/esm/text-control/index.js +32 -41
  110. package/dist/esm/utils/index.js +13 -16
  111. package/dist/esm/web-preview/index.js +7 -8
  112. package/dist/esm/with-wizard/index.js +7 -9
  113. package/dist/esm/with-wizard-screen/index.js +21 -27
  114. package/dist/esm/wizard/components/WizardError.js +7 -9
  115. package/dist/esm/wizard/index.js +16 -22
  116. package/dist/esm/wizard/store/index.js +35 -35
  117. package/dist/esm/wizard/store/utils.js +1 -4
  118. package/package.json +7 -8
  119. package/src/autocomplete-tokenfield/index.js +48 -15
  120. package/src/autocomplete-tokenfield/style.scss +11 -5
  121. package/src/autocomplete-with-suggestions/index.js +17 -22
  122. package/src/autocomplete-with-suggestions/style.scss +1 -9
  123. package/src/button/{index.js → index.tsx} +12 -5
  124. package/src/consts.js +0 -2
  125. package/src/footer/index.js +7 -7
  126. package/src/grid/index.tsx +34 -0
  127. package/src/handoff/index.js +7 -6
  128. package/src/hooks/{index.js → index.ts} +1 -1
  129. package/src/hooks/{usePrompt.js → usePrompt.ts} +4 -8
  130. package/src/image-upload/index.js +4 -4
  131. package/src/index.js +0 -2
  132. package/src/notice/index.js +1 -1
  133. package/src/patrons-logo/index.js +4 -1
  134. package/src/plugin-installer/index.js +7 -7
  135. package/src/plugin-settings/index.js +1 -1
  136. package/src/plugin-toggle/index.js +7 -5
  137. package/src/position-control/index.js +13 -13
  138. package/src/section-header/index.js +3 -3
  139. package/src/section-header/style.scss +4 -0
  140. package/src/select-control/GroupedSelectControl.js +1 -1
  141. package/src/settings/MinMaxSetting.js +8 -6
  142. package/src/settings/style.scss +14 -1
  143. package/src/sortable-newsletter-list-control/index.js +137 -0
  144. package/src/sortable-newsletter-list-control/style.scss +45 -0
  145. package/src/style-card/index.js +11 -5
  146. package/src/style.scss +13 -1
  147. package/src/tabbed-navigation/index.js +1 -1
  148. package/src/text-control/index.tsx +65 -0
  149. package/src/web-preview/index.js +6 -6
  150. package/src/with-wizard/index.js +4 -4
  151. package/src/with-wizard-screen/index.js +1 -1
  152. package/src/wizard/components/WizardError.js +1 -1
  153. package/src/wizard/index.js +3 -3
  154. package/src/wizard/store/index.js +9 -2
  155. package/dist/cjs/accordion/index.js +0 -46
  156. package/dist/cjs/accordion/style.scss +0 -27
  157. package/dist/cjs/date-range-picker/index.js +0 -41
  158. package/dist/cjs/date-range-picker/style.scss +0 -148
  159. package/dist/esm/accordion/index.js +0 -38
  160. package/dist/esm/accordion/style.scss +0 -27
  161. package/dist/esm/date-range-picker/index.js +0 -32
  162. package/dist/esm/date-range-picker/style.scss +0 -148
  163. package/src/accordion/index.js +0 -32
  164. package/src/accordion/style.scss +0 -27
  165. package/src/date-range-picker/index.js +0 -31
  166. package/src/date-range-picker/style.scss +0 -148
  167. package/src/grid/index.js +0 -44
  168. package/src/text-control/index.js +0 -56
@@ -20,9 +20,7 @@ import Router from '../proxied-imports/router';
20
20
  import registerStore, { WIZARD_STORE_NAMESPACE } from './store';
21
21
  import { useWizardData } from './store/utils';
22
22
  import WizardError from './components/WizardError';
23
- import { jsx as _jsx } from "@emotion/react/jsx-runtime";
24
- import { jsxs as _jsxs } from "@emotion/react/jsx-runtime";
25
- import { Fragment as _Fragment } from "@emotion/react/jsx-runtime";
23
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@emotion/react/jsx-runtime";
26
24
  registerStore();
27
25
  const {
28
26
  HashRouter,
@@ -30,17 +28,16 @@ const {
30
28
  Route,
31
29
  Switch
32
30
  } = Router;
33
- const Wizard = _ref => {
34
- let {
35
- sections = [],
36
- apiSlug,
37
- headerText,
38
- subHeaderText,
39
- hasSimpleFooter,
40
- className,
41
- renderAboveSections,
42
- requiredPlugins = []
43
- } = _ref;
31
+ const Wizard = ({
32
+ sections = [],
33
+ apiSlug,
34
+ headerText,
35
+ subHeaderText,
36
+ hasSimpleFooter,
37
+ className,
38
+ renderAboveSections,
39
+ requiredPlugins = []
40
+ }) => {
44
41
  const isLoading = useSelect(select => select(WIZARD_STORE_NAMESPACE).isLoading());
45
42
  const isQuietLoading = useSelect(select => select(WIZARD_STORE_NAMESPACE).isQuietLoading());
46
43
 
@@ -50,17 +47,14 @@ const Wizard = _ref => {
50
47
  let displayedSections = sections.filter(section => !section.isHidden);
51
48
  const [pluginRequirementsSatisfied, setPluginRequirementsSatisfied] = useState(requiredPlugins.length === 0);
52
49
  if (!pluginRequirementsSatisfied) {
53
- headerText = requiredPlugins.length > 1 ? __('Required plugins', 'newspack') : __('Required plugin', 'newspack');
50
+ headerText = requiredPlugins.length > 1 ? __('Required plugins', 'newspack-plugin') : __('Required plugin', 'newspack-plugin');
54
51
  displayedSections = [{
55
52
  path: '/',
56
53
  render: () => _jsx(PluginInstaller, {
57
54
  plugins: requiredPlugins,
58
- onStatus: _ref2 => {
59
- let {
60
- complete
61
- } = _ref2;
62
- return setPluginRequirementsSatisfied(complete);
63
- }
55
+ onStatus: ({
56
+ complete
57
+ }) => setPluginRequirementsSatisfied(complete)
64
58
  })
65
59
  }];
66
60
  }
@@ -82,7 +76,7 @@ const Wizard = _ref => {
82
76
  children: [_jsx(Button, {
83
77
  isLink: true,
84
78
  href: newspack_urls.dashboard,
85
- label: __('Return to Dashboard', 'newspack'),
79
+ label: __('Return to Dashboard', 'newspack-plugin'),
86
80
  showTooltip: true,
87
81
  icon: category,
88
82
  iconSize: 36,
@@ -25,12 +25,10 @@ const DEFAULT_STATE = {
25
25
  * unless the state was cloned first.
26
26
  */
27
27
  const clone = objectToClone => JSON.parse(JSON.stringify(objectToClone));
28
- const reducer = function () {
29
- let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_STATE;
30
- let {
31
- type,
32
- payload = {}
33
- } = arguments.length > 1 ? arguments[1] : undefined;
28
+ const reducer = (state = DEFAULT_STATE, {
29
+ type,
30
+ payload = {}
31
+ }) => {
34
32
  switch (type) {
35
33
  case 'START_LOADING_DATA':
36
34
  if (payload.isQuietLoading) {
@@ -71,36 +69,38 @@ const actions = {
71
69
  updateWizardSettings: createAction('UPDATE_WIZARD_SETTINGS'),
72
70
  setError: createAction('SET_ERROR'),
73
71
  // Async actions. These will not show up in Redux devtools.
74
- saveWizardSettings(_ref) {
75
- let {
76
- slug,
77
- section = '',
78
- payloadPath = false,
79
- updatePayload = null
80
- } = _ref;
81
- return function* () {
82
- // Optionally data can be updated before saving - an immediate update case
83
- // (without an explicit "save" action).
84
- if (updatePayload) {
85
- yield actions.updateWizardSettings({
86
- slug,
87
- ...updatePayload
88
- });
89
- }
90
- const wizardState = select(WIZARD_STORE_NAMESPACE).getWizardAPIData(slug);
91
- const updatedData = yield actions.fetchFromAPI({
92
- path: `/newspack/v1/wizard/${slug}/${section}`,
93
- method: 'POST',
94
- data: payloadPath ? get(wizardState, payloadPath) : wizardState,
95
- isQuietFetch: true
72
+ *saveWizardSettings({
73
+ slug,
74
+ section = '',
75
+ payloadPath = false,
76
+ auxData = {},
77
+ updatePayload = null
78
+ }) {
79
+ // Optionally data can be updated before saving - an immediate update case
80
+ // (without an explicit "save" action).
81
+ if (updatePayload) {
82
+ yield actions.updateWizardSettings({
83
+ slug,
84
+ ...updatePayload
96
85
  });
97
- if (!isEmpty(updatedData) && !updatedData.error) {
98
- return actions.setAPIDataForWizard({
99
- slug,
100
- data: updatedData
101
- });
102
- }
103
- }();
86
+ }
87
+ const wizardState = select(WIZARD_STORE_NAMESPACE).getWizardAPIData(slug);
88
+ const data = payloadPath ? get(wizardState, payloadPath) : wizardState;
89
+ const updatedData = yield actions.fetchFromAPI({
90
+ path: `/newspack/v1/wizard/${slug}/${section}`,
91
+ method: 'POST',
92
+ data: {
93
+ ...data,
94
+ ...auxData
95
+ },
96
+ isQuietFetch: true
97
+ });
98
+ if (!isEmpty(updatedData) && !updatedData.error) {
99
+ return actions.setAPIDataForWizard({
100
+ slug,
101
+ data: updatedData
102
+ });
103
+ }
104
104
  },
105
105
  *wizardApiFetch(fetchConfig) {
106
106
  // Just a proxy to fetchFromAPI, but it has to be a generator.
@@ -11,7 +11,4 @@ export const createAction = type => payload => ({
11
11
  type,
12
12
  payload
13
13
  });
14
- export const useWizardData = function (wizardName) {
15
- let defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
16
- return useSelect(select => select(WIZARD_STORE_NAMESPACE).getWizardAPIData(`newspack-${wizardName}-wizard`)) || defaultValue;
17
- };
14
+ export const useWizardData = (wizardName, defaultValue = {}) => useSelect(select => select(WIZARD_STORE_NAMESPACE).getWizardAPIData(`newspack-${wizardName}-wizard`)) || defaultValue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newspack-components",
3
- "version": "2.2.1",
3
+ "version": "3.0.0-alpha.1",
4
4
  "description": "Newspack design system components",
5
5
  "author": "Automattic",
6
6
  "license": "GPL-2.0-or-later",
@@ -23,22 +23,21 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@wordpress/base-styles": "^4.0.0",
27
- "@wordpress/components": "^23.6.0",
28
- "@wordpress/element": "^5.5.0",
29
- "@wordpress/i18n": "^4.2.2",
30
- "@wordpress/icons": "^9.11.0",
26
+ "@wordpress/base-styles": "^5.1.0",
27
+ "@wordpress/components": "^28.1.0",
28
+ "@wordpress/element": "^6.1.0",
29
+ "@wordpress/i18n": "^5.1.0",
30
+ "@wordpress/icons": "^10.1.0",
31
31
  "classnames": "^2.3.1",
32
32
  "lodash": "^4.17.21",
33
- "moment-range": "^3.1.1",
34
33
  "qs": "^6.10.1",
35
- "react-daterange-picker": "^2.0.1",
36
34
  "react-router-dom": "^5.3.0"
37
35
  },
38
36
  "devDependencies": {
39
37
  "@automattic/calypso-build": "^10.0.0",
40
38
  "@babel/cli": "^7.15.0",
41
39
  "@babel/core": "^7.15.0",
40
+ "@types/wordpress__components": "^23.0.11",
42
41
  "recursive-copy": "^2.0.13"
43
42
  },
44
43
  "babel": {
@@ -57,6 +57,26 @@ class AutocompleteTokenField extends Component {
57
57
  }
58
58
  }
59
59
 
60
+ /**
61
+ * When the component updates, fetch information about the tokens so we can populate
62
+ * the tokens with the correct labels.
63
+ */
64
+ componentDidUpdate( prevProps ) {
65
+ const { tokens, fetchSavedInfo } = this.props;
66
+
67
+ if ( tokens !== prevProps.tokens && this.isFetchingInfoOnLoad() ) {
68
+ fetchSavedInfo( tokens ).then( results => {
69
+ const { validValues } = this.state;
70
+
71
+ results.forEach( suggestion => {
72
+ validValues[ suggestion.value ] = suggestion.label;
73
+ } );
74
+
75
+ this.setState( { validValues, loading: false } );
76
+ } );
77
+ }
78
+ }
79
+
60
80
  /**
61
81
  * Clean up any unfinished autocomplete api call requests.
62
82
  */
@@ -99,7 +119,9 @@ class AutocompleteTokenField extends Component {
99
119
  return labels.reduce( ( acc, label ) => {
100
120
  Object.keys( validValues ).forEach( key => {
101
121
  if ( validValues[ key ] === label ) {
102
- acc.push( { value: key, label } );
122
+ // Preserve numeric or string type of values. Object.keys will convert numbers to strings.
123
+ const value = isNaN( parseInt( key ) ) ? key.toString() : parseInt( key );
124
+ acc.push( { value, label } );
103
125
  }
104
126
  } );
105
127
 
@@ -108,7 +130,9 @@ class AutocompleteTokenField extends Component {
108
130
  }
109
131
 
110
132
  return labels.map( label =>
111
- Object.keys( validValues ).find( key => validValues[ key ] === label )
133
+ Object.keys( validValues )
134
+ .map( key => ( isNaN( parseInt( key ) ) ? key.toString() : parseInt( key ) ) )
135
+ .find( key => validValues[ key ] === label )
112
136
  );
113
137
  }
114
138
 
@@ -134,16 +158,16 @@ class AutocompleteTokenField extends Component {
134
158
  return;
135
159
  }
136
160
 
161
+ const { validValues } = this.state;
137
162
  const currentSuggestions = [ ...suggestions ];
138
- const currentValidValues = {};
139
163
 
140
164
  suggestions.forEach( suggestion => {
141
- currentValidValues[ suggestion.value ] = suggestion.label;
165
+ validValues[ suggestion.value ] = suggestion.label;
142
166
  } );
143
167
 
144
168
  this.setState( {
145
169
  suggestions: currentSuggestions,
146
- validValues: currentValidValues,
170
+ validValues,
147
171
  loading: false,
148
172
  } );
149
173
  } )
@@ -183,20 +207,29 @@ class AutocompleteTokenField extends Component {
183
207
  * Render.
184
208
  */
185
209
  render() {
186
- const { help, label = '', maxLength } = this.props;
210
+ const { help, label = '', placeholder = '', maxLength } = this.props;
187
211
  const { suggestions, loading } = this.state;
188
212
 
213
+ const classNames = [ 'newspack-autocomplete-tokenfield__input-container' ];
214
+
215
+ if ( label ) {
216
+ classNames.push( 'has-label' );
217
+ }
218
+
189
219
  return (
190
220
  <div className="newspack-autocomplete-tokenfield">
191
- <FormTokenField
192
- value={ this.getTokens() }
193
- suggestions={ suggestions.map( suggestion => suggestion.label ) }
194
- onChange={ tokens => this.handleOnChange( tokens ) }
195
- onInputChange={ input => this.debouncedUpdateSuggestions( input ) }
196
- label={ label }
197
- maxLength={ maxLength }
198
- />
199
- { loading && <Spinner /> }
221
+ <div className={ classNames.join( ' ' ) }>
222
+ <FormTokenField
223
+ value={ this.getTokens() }
224
+ suggestions={ suggestions.map( suggestion => suggestion.label ) }
225
+ onChange={ tokens => this.handleOnChange( tokens ) }
226
+ onInputChange={ input => this.debouncedUpdateSuggestions( input ) }
227
+ label={ label }
228
+ maxLength={ maxLength }
229
+ placeholder={ placeholder }
230
+ />
231
+ { loading && <Spinner /> }
232
+ </div>
200
233
  { help && <p className="newspack-autocomplete-tokenfield__help">{ help }</p> }
201
234
  </div>
202
235
  );
@@ -5,13 +5,19 @@
5
5
  @use '~@wordpress/base-styles/colors' as wp-colors;
6
6
 
7
7
  .newspack-autocomplete-tokenfield {
8
- position: relative;
9
-
10
8
  .components-spinner {
11
- margin: 8px;
9
+ margin: 0;
12
10
  position: absolute;
13
- right: 0;
14
- top: calc( 1.4em + 8px );
11
+ right: 8px;
12
+ top: 8px;
13
+ }
14
+
15
+ &__input-container {
16
+ position: relative;
17
+
18
+ &.has-label .components-spinner {
19
+ top: 32px;
20
+ }
15
21
  }
16
22
 
17
23
  /* Workaround for hard-coded help text in FormTokenField. */
@@ -2,7 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import apiFetch from '@wordpress/api-fetch';
5
- import { Button, CheckboxControl, SelectControl, Spinner } from '@wordpress/components';
5
+ import { Button, CheckboxControl, SelectControl } from '@wordpress/components';
6
6
  import { decodeEntities } from '@wordpress/html-entities';
7
7
  import { useEffect, useState } from '@wordpress/element';
8
8
  import { __, _x, sprintf } from '@wordpress/i18n';
@@ -17,16 +17,16 @@ import './style.scss';
17
17
  const AutocompleteWithSuggestions = ( {
18
18
  fetchSavedPosts = false, // If passed, will use this function to fetch saved data.
19
19
  fetchSuggestions = false, // If passed, will use this function to fetch suggestions data.
20
- help = __( 'Begin typing search term, click autocomplete result to select.', 'newspack' ),
20
+ help = __( 'Begin typing search term, click autocomplete result to select.', 'newspack-plugin' ),
21
21
  hideHelp = false, // If true, all help text will be hidden.
22
- label = __( 'Search', 'newspack' ),
22
+ label = __( 'Search', 'newspack-plugin' ),
23
23
  maxItemsToSuggest = 0, // If passed, will be used to determine "load more" state. Necessary if you want "load more" functionality when using a custom `fetchSuggestions` function.
24
24
  multiSelect = false, // If true, component can select multiple values at once.
25
25
  onChange = false, // Function to call when selections change.
26
26
  onPostTypeChange = false, // Funciton to call when the post type selector is changed.
27
27
  postTypes = [ { slug: 'post', label: 'Post' } ], // If passed, will render a selector to change the post type queried for suggestions.
28
- postTypeLabel = __( 'item', 'newspack' ), // String to describe the data being shown.
29
- postTypeLabelPlural = __( 'items', 'newspack' ), // Plural string to describe the data being shown.
28
+ postTypeLabel = __( 'item', 'newspack-plugin' ), // String to describe the data being shown.
29
+ postTypeLabelPlural = __( 'items', 'newspack-plugin' ), // Plural string to describe the data being shown.
30
30
  selectedItems = [], // Array of saved items.
31
31
  selectedPost = 0, // Legacy prop when single-select was the only option.
32
32
  suggestionsToFetch = 10, // Number of suggestions to fetch per query.
@@ -96,7 +96,7 @@ const AutocompleteWithSuggestions = ( {
96
96
 
97
97
  return posts.map( post => ( {
98
98
  value: parseInt( post.id ),
99
- label: decodeEntities( post.title ) || __( '(no title)', 'newspack' ),
99
+ label: decodeEntities( post.title ) || __( '(no title)', 'newspack-plugin' ),
100
100
  } ) );
101
101
  };
102
102
 
@@ -130,7 +130,7 @@ const AutocompleteWithSuggestions = ( {
130
130
  return posts.reduce( ( acc, post ) => {
131
131
  acc.push( {
132
132
  value: parseInt( post.id ),
133
- label: decodeEntities( post?.title.rendered ) || __( '(no title)', 'newspack' ),
133
+ label: decodeEntities( post?.title.rendered ) || __( '(no title)', 'newspack-plugin' ),
134
134
  } );
135
135
 
136
136
  return acc;
@@ -177,21 +177,21 @@ const AutocompleteWithSuggestions = ( {
177
177
  const selectedMessage = multiSelect
178
178
  ? sprintf(
179
179
  // Translators: %1: the length of selections. %2: the selection leabel.
180
- __( '%1$s %2$s selected', 'newspack' ),
180
+ __( '%1$s %2$s selected', 'newspack-plugin' ),
181
181
  selections.length,
182
182
  selections.length > 1 ? postTypeLabelPlural : postTypeLabel
183
183
  )
184
184
  : // Translators: %s: The label for the selection.
185
- sprintf( __( 'Selected %s', 'newspack' ), postTypeLabel );
185
+ sprintf( __( 'Selected %s', 'newspack-plugin' ), postTypeLabel );
186
186
 
187
187
  return (
188
188
  <div className="newspack-autocomplete-with-suggestions__selected-items">
189
189
  <p className="newspack-autocomplete-with-suggestions__label">
190
190
  { selectedMessage }
191
- { 1 < selections.length && _x( ' – ', 'separator character', 'newspack' ) }
191
+ { 1 < selections.length && _x( ' – ', 'separator character', 'newspack-plugin' ) }
192
192
  { 1 < selections.length && (
193
193
  <Button onClick={ () => onChange( [] ) } isLink isDestructive>
194
- { __( 'Clear all', 'newspack' ) }
194
+ { __( 'Clear all', 'newspack-plugin' ) }
195
195
  </Button>
196
196
  ) }
197
197
  </p>
@@ -219,7 +219,7 @@ const AutocompleteWithSuggestions = ( {
219
219
  <SelectControl
220
220
  label={ sprintf(
221
221
  // Translators: %s: The name of the type.
222
- __( '%s type', 'newspack' ),
222
+ __( '%s type', 'newspack-plugin' ),
223
223
  postTypeLabel.charAt( 0 ).toUpperCase() + postTypeLabel.slice( 1 )
224
224
  ) }
225
225
  value={ postTypeToSearch }
@@ -265,14 +265,6 @@ const AutocompleteWithSuggestions = ( {
265
265
  * Render a list of suggestions that can be clicked to select instead of searching by title.
266
266
  */
267
267
  const renderSuggestions = () => {
268
- if ( isLoading ) {
269
- return (
270
- <div className="newspack-autocomplete-with-suggestions__suggestions-spinner">
271
- <Spinner />
272
- </div>
273
- );
274
- }
275
-
276
268
  if ( 0 === suggestions.length ) {
277
269
  return null;
278
270
  }
@@ -287,7 +279,7 @@ const AutocompleteWithSuggestions = ( {
287
279
  <p className="newspack-autocomplete-with-suggestions__label">
288
280
  {
289
281
  /* Translators: %s: the name of a post type. */ sprintf(
290
- __( 'Or, select a recent %s:', 'newspack' ),
282
+ __( 'Or, select a recent %s:', 'newspack-plugin' ),
291
283
  postTypeLabel
292
284
  )
293
285
  }
@@ -301,7 +293,9 @@ const AutocompleteWithSuggestions = ( {
301
293
  isSecondary
302
294
  onClick={ () => setIsLoadingMore( true ) }
303
295
  >
304
- { isLoadingMore ? __( 'Loading…', 'newspack' ) : __( 'Load more', 'newspack' ) }
296
+ { isLoadingMore
297
+ ? __( 'Loading…', 'newspack-plugin' )
298
+ : __( 'Load more', 'newspack-plugin' ) }
305
299
  </Button>
306
300
  ) }
307
301
  </div>
@@ -319,6 +313,7 @@ const AutocompleteWithSuggestions = ( {
319
313
  fetchSuggestions={ async search => handleFetchSuggestions( search, 0, postTypeToSearch ) }
320
314
  fetchSavedInfo={ postIds => handleFetchSaved( postIds ) }
321
315
  label={ label }
316
+ loading={ isLoading }
322
317
  help={ ! hideHelp && help }
323
318
  returnFullObjects
324
319
  />
@@ -15,13 +15,6 @@
15
15
  margin-top: 16px;
16
16
  }
17
17
  }
18
-
19
- .components-spinner {
20
- margin: 8px;
21
- right: 0;
22
- top: calc( 1.4em + 8px );
23
- }
24
-
25
18
  .components-select-control__input {
26
19
  max-width: none;
27
20
  }
@@ -119,8 +112,7 @@
119
112
  border-radius: 2px;
120
113
  border: 1px solid wp-colors.$gray-700;
121
114
  max-height: 178px;
122
- overflow-x: visible;
123
- overflow-y: auto;
115
+ overflow: visible auto;
124
116
  padding: 8px 8px 0;
125
117
 
126
118
  .components-button {
@@ -16,25 +16,32 @@ import './style.scss';
16
16
 
17
17
  const { useHistory } = Router;
18
18
 
19
- const Button = ( { href, onClick, ...otherProps } ) => {
19
+ type OriginalButtonProps = typeof BaseComponent.defaultProps;
20
+ type Props = OriginalButtonProps & {
21
+ href?: string;
22
+ onClick?: () => void;
23
+ };
24
+
25
+ const Button = ( { href, onClick, ...otherProps }: Props ) => {
20
26
  const history = useHistory();
21
27
  const [ isAwaitingOnClick, setIsAwaitingOnClick ] = useState( false );
22
28
 
23
29
  // If both onClick and href are present, await the onClick action an then redirect.
24
30
  if ( href && onClick ) {
25
- otherProps.onClick = async () => {
31
+ ( otherProps as Props ).onClick = async () => {
26
32
  setIsAwaitingOnClick( true );
27
33
  await onClick();
28
34
  setIsAwaitingOnClick( false );
29
- history.push( href.replace( '#', '' ) );
35
+ history.push( ( href || '' ).replace( '#', '' ) );
30
36
  };
31
37
  } else {
32
- otherProps.href = href;
33
- otherProps.onClick = onClick;
38
+ ( otherProps as Props ).href = href;
39
+ ( otherProps as Props ).onClick = onClick;
34
40
  }
35
41
  if ( isAwaitingOnClick ) {
36
42
  otherProps.disabled = true;
37
43
  }
44
+ // @ts-ignore - @wordpress/components' Button can only have either href or onClick, not both.
38
45
  return <BaseComponent { ...otherProps } />;
39
46
  };
40
47
 
package/src/consts.js CHANGED
@@ -1,3 +1 @@
1
- export const NEWSPACK_SITE_URL = 'https://newspack.com';
2
- export const NEWSPACK_SUPPORT_URL = `${ NEWSPACK_SITE_URL }/support`;
3
1
  export const HANDOFF_KEY = 'newspack_wizard_handoff_message';
@@ -32,43 +32,43 @@ const Footer = ( { simple } ) => {
32
32
  external: true,
33
33
  },
34
34
  {
35
- label: __( 'About', 'newspack' ),
35
+ label: __( 'About', 'newspack-plugin' ),
36
36
  url: 'https://newspack.com/',
37
37
  external: true,
38
38
  },
39
39
  {
40
- label: __( 'Documentation', 'newspack' ),
40
+ label: __( 'Documentation', 'newspack-plugin' ),
41
41
  url: support,
42
42
  external: true,
43
43
  },
44
44
  ];
45
45
  if ( componentsDemo ) {
46
46
  footerElements.push( {
47
- label: __( 'Components Demo', 'newspack' ),
47
+ label: __( 'Components Demo', 'newspack-plugin' ),
48
48
  url: componentsDemo,
49
49
  } );
50
50
  }
51
51
  if ( setupWizard ) {
52
52
  footerElements.push( {
53
- label: __( 'Setup Wizard', 'newspack' ),
53
+ label: __( 'Setup Wizard', 'newspack-plugin' ),
54
54
  url: setupWizard,
55
55
  } );
56
56
  }
57
57
  if ( resetUrl ) {
58
58
  footerElements.push( {
59
- label: __( 'Reset Newspack', 'newspack' ),
59
+ label: __( 'Reset Newspack', 'newspack-plugin' ),
60
60
  url: resetUrl,
61
61
  } );
62
62
  }
63
63
  if ( removeStarterContent ) {
64
64
  footerElements.push( {
65
- label: __( 'Remove Starter Content', 'newspack' ),
65
+ label: __( 'Remove Starter Content', 'newspack-plugin' ),
66
66
  url: removeStarterContent,
67
67
  } );
68
68
  }
69
69
  if ( supportEmail ) {
70
70
  footerElements.push( {
71
- label: __( 'Contact Support', 'newspack' ),
71
+ label: __( 'Contact Support', 'newspack-plugin' ),
72
72
  url: `mailto:${ supportEmail }`,
73
73
  } );
74
74
  }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Grid
3
+ */
4
+
5
+ /**
6
+ * Internal dependencies
7
+ */
8
+ import './style.scss';
9
+
10
+ /**
11
+ * External dependencies
12
+ */
13
+ import classnames from 'classnames';
14
+
15
+ const Grid = ( {
16
+ className = '',
17
+ columns = 2,
18
+ gutter = 32,
19
+ noMargin = false,
20
+ rowGap = 0,
21
+ ...otherProps
22
+ } ) => {
23
+ const classes = classnames(
24
+ 'newspack-grid',
25
+ noMargin && 'newspack-grid--no-margin',
26
+ columns && 'newspack-grid__columns-' + columns,
27
+ gutter && 'newspack-grid__gutter-' + gutter,
28
+ rowGap && 'newspack-grid__row-gap-' + rowGap,
29
+ className
30
+ );
31
+ return <div className={ classes } { ...otherProps } />;
32
+ };
33
+
34
+ export default Grid;
@@ -52,10 +52,11 @@ class Handoff extends Component {
52
52
  textForPlugin = pluginInfo => {
53
53
  const defaults = {
54
54
  modalBody: null,
55
- modalTitle: pluginInfo.Name && `${ __( 'Manage', 'newspack' ) } ${ pluginInfo.Name }`,
56
- primaryButton: pluginInfo.Name && `${ __( 'Manage', 'newspack' ) } ${ pluginInfo.Name }`,
57
- primaryModalButton: __( 'Manage', 'newspack' ),
58
- dismissModalButton: __( 'Dismiss', 'newspack' ),
55
+ modalTitle: pluginInfo.Name && `${ __( 'Manage', 'newspack-plugin' ) } ${ pluginInfo.Name }`,
56
+ primaryButton:
57
+ pluginInfo.Name && `${ __( 'Manage', 'newspack-plugin' ) } ${ pluginInfo.Name }`,
58
+ primaryModalButton: __( 'Manage', 'newspack-plugin' ),
59
+ dismissModalButton: __( 'Dismiss', 'newspack-plugin' ),
59
60
  };
60
61
  return assign( defaults, this.props );
61
62
  };
@@ -115,7 +116,7 @@ class Handoff extends Component {
115
116
  ) }
116
117
  { Name && 'active' !== Status && (
117
118
  <Button className={ classes } variant="secondary" disabled { ...otherProps }>
118
- { Name + __( ' not installed', 'newspack' ) }
119
+ { Name + __( ' not installed', 'newspack-plugin' ) }
119
120
  </Button>
120
121
  ) }
121
122
  { ! Name && (
@@ -126,7 +127,7 @@ class Handoff extends Component {
126
127
  >
127
128
  <Fragment>
128
129
  { ! compact && <Waiting isLeft /> }
129
- { __( 'Retrieving Plugin Info', 'newspack' ) }
130
+ { __( 'Retrieving Plugin Info', 'newspack-plugin' ) }
130
131
  </Fragment>
131
132
  </Button>
132
133
  ) }
@@ -7,7 +7,7 @@ import usePrompt from './usePrompt';
7
7
  import useObjectState from './useObjectState';
8
8
  import useOnClickOutside from './useOnClickOutside';
9
9
 
10
- const useUniqueId = prefix => {
10
+ const useUniqueId = ( prefix: string ) => {
11
11
  const id = useRef( `${ prefix }-${ Math.round( Math.random() * 99999 ) }` );
12
12
  return id.current;
13
13
  };