newspack-components 3.0.0-alpha.2 → 3.0.0-alpha.3

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 (217) hide show
  1. package/babel.config.cjs.js +26 -0
  2. package/babel.config.js +1 -0
  3. package/copy-styles.js +10 -2
  4. package/dist/esm/accordion/index.js +42 -0
  5. package/dist/esm/accordion/style.scss +31 -0
  6. package/dist/esm/action-card/index.js +218 -0
  7. package/dist/esm/action-card/style.scss +483 -0
  8. package/dist/esm/autocomplete-tokenfield/index.js +261 -0
  9. package/dist/esm/autocomplete-tokenfield/style.scss +49 -0
  10. package/dist/esm/autocomplete-with-suggestions/index.js +274 -0
  11. package/dist/esm/autocomplete-with-suggestions/style.scss +163 -0
  12. package/dist/esm/button/style.scss +11 -0
  13. package/dist/esm/button-card/index.js +64 -0
  14. package/dist/esm/button-card/style.scss +180 -0
  15. package/dist/esm/card/index.js +43 -0
  16. package/dist/esm/card/style.scss +168 -0
  17. package/dist/esm/category-autocomplete/index.js +183 -0
  18. package/dist/esm/category-autocomplete/style.scss +34 -0
  19. package/dist/esm/color-picker/index.js +59 -0
  20. package/dist/esm/color-picker/style.scss +37 -0
  21. package/dist/esm/consts.js +1 -0
  22. package/dist/esm/custom-select-control/index.js +37 -0
  23. package/dist/esm/custom-select-control/style.scss +93 -0
  24. package/dist/esm/date-range-picker/index.js +31 -0
  25. package/dist/esm/date-range-picker/style.scss +148 -0
  26. package/dist/esm/footer/index.js +99 -0
  27. package/dist/esm/footer/style.scss +82 -0
  28. package/dist/esm/form-token-field/index.js +49 -0
  29. package/dist/esm/form-token-field/style.scss +37 -0
  30. package/dist/esm/global-notices/index.js +30 -0
  31. package/dist/esm/grid/style.scss +166 -0
  32. package/dist/esm/handoff/index.js +175 -0
  33. package/dist/esm/handoff-message/index.js +47 -0
  34. package/dist/esm/hooks/useObjectState.js +30 -0
  35. package/dist/esm/hooks/useObjectState.test.js +82 -0
  36. package/dist/esm/hooks/useOnClickOutside.js +31 -0
  37. package/dist/esm/image-upload/index.js +140 -0
  38. package/dist/esm/image-upload/index.test.js +34 -0
  39. package/dist/esm/image-upload/style.scss +103 -0
  40. package/dist/esm/index.js +47 -0
  41. package/dist/esm/info-button/index.js +42 -0
  42. package/dist/esm/info-button/style.scss +18 -0
  43. package/dist/esm/modal/index.js +39 -0
  44. package/dist/esm/modal/style.scss +56 -0
  45. package/dist/esm/newspack-icon/index.js +50 -0
  46. package/dist/esm/newspack-icon/style.scss +26 -0
  47. package/dist/esm/newspack-logo/index.js +46 -0
  48. package/dist/esm/newspack-logo/style.scss +30 -0
  49. package/dist/esm/notice/index.js +65 -0
  50. package/dist/esm/notice/style.scss +111 -0
  51. package/dist/esm/patrons-logo/index.js +70 -0
  52. package/dist/esm/plugin-installer/index.js +289 -0
  53. package/dist/esm/plugin-installer/style.scss +72 -0
  54. package/dist/esm/plugin-settings/SettingsSection.js +133 -0
  55. package/dist/esm/plugin-settings/index.js +220 -0
  56. package/dist/esm/plugin-settings/style.scss +7 -0
  57. package/dist/esm/plugin-toggle/index.js +216 -0
  58. package/dist/esm/plugin-toggle/style.scss +20 -0
  59. package/dist/esm/popover/index.js +41 -0
  60. package/dist/esm/popover/style.scss +161 -0
  61. package/dist/esm/position-control/index.js +106 -0
  62. package/dist/esm/position-control/style.scss +66 -0
  63. package/dist/esm/progress-bar/index.js +68 -0
  64. package/dist/esm/progress-bar/index.test.js +108 -0
  65. package/dist/esm/progress-bar/style.scss +42 -0
  66. package/dist/esm/proxied-imports/router.js +8 -0
  67. package/dist/esm/radio-control/index.js +37 -0
  68. package/dist/esm/radio-control/style.scss +92 -0
  69. package/dist/esm/section-header/index.js +67 -0
  70. package/dist/esm/section-header/style.scss +45 -0
  71. package/dist/esm/select-control/ButtonGroupControl.js +53 -0
  72. package/dist/esm/select-control/GroupedSelectControl.js +78 -0
  73. package/dist/esm/select-control/index.js +51 -0
  74. package/dist/esm/select-control/style.scss +108 -0
  75. package/dist/esm/settings/MinMaxSetting.js +53 -0
  76. package/dist/esm/settings/SettingsCard.js +38 -0
  77. package/dist/esm/settings/SettingsSection.js +26 -0
  78. package/dist/esm/settings/index.js +9 -0
  79. package/dist/esm/settings/style.scss +119 -0
  80. package/dist/esm/sortable-newsletter-list-control/index.js +127 -0
  81. package/dist/esm/sortable-newsletter-list-control/style.scss +45 -0
  82. package/dist/esm/steps-list/index.js +43 -0
  83. package/dist/esm/steps-list/style.scss +11 -0
  84. package/dist/esm/steps-list-item/index.js +47 -0
  85. package/dist/esm/steps-list-item/style.scss +47 -0
  86. package/dist/esm/style-card/index.js +74 -0
  87. package/dist/esm/style-card/style.scss +94 -0
  88. package/dist/esm/style.scss +55 -0
  89. package/dist/esm/tabbed-navigation/index.js +53 -0
  90. package/dist/esm/tabbed-navigation/style.scss +86 -0
  91. package/dist/esm/text-control/style.scss +32 -0
  92. package/dist/esm/utils/index.js +29 -0
  93. package/dist/esm/waiting/index.js +44 -0
  94. package/dist/esm/waiting/style.scss +27 -0
  95. package/dist/esm/web-preview/index.js +183 -0
  96. package/dist/esm/web-preview/style.scss +155 -0
  97. package/dist/esm/with-wizard/index.js +320 -0
  98. package/dist/esm/with-wizard/style.scss +282 -0
  99. package/dist/esm/with-wizard-screen/index.js +109 -0
  100. package/dist/esm/with-wizard-screen/style.scss +160 -0
  101. package/dist/esm/wizard/components/WizardError.js +66 -0
  102. package/dist/esm/wizard/index.js +119 -0
  103. package/dist/esm/wizard/store/index.js +155 -0
  104. package/dist/esm/wizard/store/utils.js +14 -0
  105. package/package.json +7 -4
  106. package/dist/button/index.js +0 -51
  107. package/dist/button/index.tsx +0 -48
  108. package/dist/grid/index.js +0 -44
  109. package/dist/grid/index.tsx +0 -34
  110. package/dist/hooks/index.js +0 -29
  111. package/dist/hooks/index.ts +0 -15
  112. package/dist/hooks/usePrompt.js +0 -47
  113. package/dist/hooks/usePrompt.ts +0 -46
  114. package/dist/plugin-toggle/README.md +0 -53
  115. package/dist/text-control/index.js +0 -76
  116. package/dist/text-control/index.tsx +0 -71
  117. /package/dist/{accordion → cjs/accordion}/index.js +0 -0
  118. /package/dist/{accordion → cjs/accordion}/style.scss +0 -0
  119. /package/dist/{action-card → cjs/action-card}/index.js +0 -0
  120. /package/dist/{action-card → cjs/action-card}/style.scss +0 -0
  121. /package/dist/{autocomplete-tokenfield → cjs/autocomplete-tokenfield}/index.js +0 -0
  122. /package/dist/{autocomplete-tokenfield → cjs/autocomplete-tokenfield}/style.scss +0 -0
  123. /package/dist/{autocomplete-with-suggestions → cjs/autocomplete-with-suggestions}/index.js +0 -0
  124. /package/dist/{autocomplete-with-suggestions → cjs/autocomplete-with-suggestions}/style.scss +0 -0
  125. /package/dist/{button → cjs/button}/style.scss +0 -0
  126. /package/dist/{button-card → cjs/button-card}/index.js +0 -0
  127. /package/dist/{button-card → cjs/button-card}/style.scss +0 -0
  128. /package/dist/{card → cjs/card}/index.js +0 -0
  129. /package/dist/{card → cjs/card}/style.scss +0 -0
  130. /package/dist/{category-autocomplete → cjs/category-autocomplete}/index.js +0 -0
  131. /package/dist/{category-autocomplete → cjs/category-autocomplete}/style.scss +0 -0
  132. /package/dist/{color-picker → cjs/color-picker}/index.js +0 -0
  133. /package/dist/{color-picker → cjs/color-picker}/style.scss +0 -0
  134. /package/dist/{consts.js → cjs/consts.js} +0 -0
  135. /package/dist/{custom-select-control → cjs/custom-select-control}/index.js +0 -0
  136. /package/dist/{custom-select-control → cjs/custom-select-control}/style.scss +0 -0
  137. /package/dist/{date-range-picker → cjs/date-range-picker}/index.js +0 -0
  138. /package/dist/{date-range-picker → cjs/date-range-picker}/style.scss +0 -0
  139. /package/dist/{footer → cjs/footer}/index.js +0 -0
  140. /package/dist/{footer → cjs/footer}/style.scss +0 -0
  141. /package/dist/{form-token-field → cjs/form-token-field}/index.js +0 -0
  142. /package/dist/{form-token-field → cjs/form-token-field}/style.scss +0 -0
  143. /package/dist/{global-notices → cjs/global-notices}/index.js +0 -0
  144. /package/dist/{grid → cjs/grid}/style.scss +0 -0
  145. /package/dist/{handoff → cjs/handoff}/index.js +0 -0
  146. /package/dist/{handoff-message → cjs/handoff-message}/index.js +0 -0
  147. /package/dist/{hooks → cjs/hooks}/useObjectState.js +0 -0
  148. /package/dist/{hooks → cjs/hooks}/useObjectState.test.js +0 -0
  149. /package/dist/{hooks → cjs/hooks}/useOnClickOutside.js +0 -0
  150. /package/dist/{image-upload → cjs/image-upload}/index.js +0 -0
  151. /package/dist/{image-upload → cjs/image-upload}/index.test.js +0 -0
  152. /package/dist/{image-upload → cjs/image-upload}/style.scss +0 -0
  153. /package/dist/{index.js → cjs/index.js} +0 -0
  154. /package/dist/{info-button → cjs/info-button}/index.js +0 -0
  155. /package/dist/{info-button → cjs/info-button}/style.scss +0 -0
  156. /package/dist/{modal → cjs/modal}/index.js +0 -0
  157. /package/dist/{modal → cjs/modal}/style.scss +0 -0
  158. /package/dist/{newspack-icon → cjs/newspack-icon}/index.js +0 -0
  159. /package/dist/{newspack-icon → cjs/newspack-icon}/style.scss +0 -0
  160. /package/dist/{newspack-logo → cjs/newspack-logo}/index.js +0 -0
  161. /package/dist/{newspack-logo → cjs/newspack-logo}/style.scss +0 -0
  162. /package/dist/{notice → cjs/notice}/index.js +0 -0
  163. /package/dist/{notice → cjs/notice}/style.scss +0 -0
  164. /package/dist/{patrons-logo → cjs/patrons-logo}/index.js +0 -0
  165. /package/dist/{plugin-installer → cjs/plugin-installer}/index.js +0 -0
  166. /package/dist/{plugin-installer → cjs/plugin-installer}/style.scss +0 -0
  167. /package/dist/{plugin-settings → cjs/plugin-settings}/SettingsSection.js +0 -0
  168. /package/dist/{plugin-settings → cjs/plugin-settings}/index.js +0 -0
  169. /package/dist/{plugin-settings → cjs/plugin-settings}/style.scss +0 -0
  170. /package/dist/{plugin-toggle → cjs/plugin-toggle}/index.js +0 -0
  171. /package/dist/{plugin-toggle → cjs/plugin-toggle}/style.scss +0 -0
  172. /package/dist/{popover → cjs/popover}/index.js +0 -0
  173. /package/dist/{popover → cjs/popover}/style.scss +0 -0
  174. /package/dist/{position-control → cjs/position-control}/index.js +0 -0
  175. /package/dist/{position-control → cjs/position-control}/style.scss +0 -0
  176. /package/dist/{progress-bar → cjs/progress-bar}/index.js +0 -0
  177. /package/dist/{progress-bar → cjs/progress-bar}/index.test.js +0 -0
  178. /package/dist/{progress-bar → cjs/progress-bar}/style.scss +0 -0
  179. /package/dist/{proxied-imports → cjs/proxied-imports}/router.js +0 -0
  180. /package/dist/{radio-control → cjs/radio-control}/index.js +0 -0
  181. /package/dist/{radio-control → cjs/radio-control}/style.scss +0 -0
  182. /package/dist/{section-header → cjs/section-header}/index.js +0 -0
  183. /package/dist/{section-header → cjs/section-header}/style.scss +0 -0
  184. /package/dist/{select-control → cjs/select-control}/ButtonGroupControl.js +0 -0
  185. /package/dist/{select-control → cjs/select-control}/GroupedSelectControl.js +0 -0
  186. /package/dist/{select-control → cjs/select-control}/index.js +0 -0
  187. /package/dist/{select-control → cjs/select-control}/style.scss +0 -0
  188. /package/dist/{settings → cjs/settings}/MinMaxSetting.js +0 -0
  189. /package/dist/{settings → cjs/settings}/SettingsCard.js +0 -0
  190. /package/dist/{settings → cjs/settings}/SettingsSection.js +0 -0
  191. /package/dist/{settings → cjs/settings}/index.js +0 -0
  192. /package/dist/{settings → cjs/settings}/style.scss +0 -0
  193. /package/dist/{sortable-newsletter-list-control → cjs/sortable-newsletter-list-control}/index.js +0 -0
  194. /package/dist/{sortable-newsletter-list-control → cjs/sortable-newsletter-list-control}/style.scss +0 -0
  195. /package/dist/{steps-list → cjs/steps-list}/index.js +0 -0
  196. /package/dist/{steps-list → cjs/steps-list}/style.scss +0 -0
  197. /package/dist/{steps-list-item → cjs/steps-list-item}/index.js +0 -0
  198. /package/dist/{steps-list-item → cjs/steps-list-item}/style.scss +0 -0
  199. /package/dist/{style-card → cjs/style-card}/index.js +0 -0
  200. /package/dist/{style-card → cjs/style-card}/style.scss +0 -0
  201. /package/dist/{style.scss → cjs/style.scss} +0 -0
  202. /package/dist/{tabbed-navigation → cjs/tabbed-navigation}/index.js +0 -0
  203. /package/dist/{tabbed-navigation → cjs/tabbed-navigation}/style.scss +0 -0
  204. /package/dist/{text-control → cjs/text-control}/style.scss +0 -0
  205. /package/dist/{utils → cjs/utils}/index.js +0 -0
  206. /package/dist/{waiting → cjs/waiting}/index.js +0 -0
  207. /package/dist/{waiting → cjs/waiting}/style.scss +0 -0
  208. /package/dist/{web-preview → cjs/web-preview}/index.js +0 -0
  209. /package/dist/{web-preview → cjs/web-preview}/style.scss +0 -0
  210. /package/dist/{with-wizard → cjs/with-wizard}/index.js +0 -0
  211. /package/dist/{with-wizard → cjs/with-wizard}/style.scss +0 -0
  212. /package/dist/{with-wizard-screen → cjs/with-wizard-screen}/index.js +0 -0
  213. /package/dist/{with-wizard-screen → cjs/with-wizard-screen}/style.scss +0 -0
  214. /package/dist/{wizard → cjs/wizard}/components/WizardError.js +0 -0
  215. /package/dist/{wizard → cjs/wizard}/index.js +0 -0
  216. /package/dist/{wizard → cjs/wizard}/store/index.js +0 -0
  217. /package/dist/{wizard → cjs/wizard}/store/utils.js +0 -0
@@ -0,0 +1,220 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import classnames from 'classnames';
5
+
6
+ /**
7
+ * WordPress dependencies.
8
+ */
9
+ import apiFetch from '@wordpress/api-fetch';
10
+ import { Component, Fragment } from '@wordpress/element';
11
+ import { __ } from '@wordpress/i18n';
12
+
13
+ /**
14
+ * Internal dependencies.
15
+ */
16
+ import { SectionHeader, Notice } from '../';
17
+ import SettingsSection from './SettingsSection';
18
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
+ class PluginSettings extends Component {
20
+ constructor() {
21
+ super(...arguments);
22
+ this.state = {
23
+ inFlight: false,
24
+ settings: {},
25
+ error: null
26
+ };
27
+ }
28
+ fetchSettings = () => {
29
+ const {
30
+ afterFetch,
31
+ pluginSlug,
32
+ isWizard
33
+ } = this.props;
34
+ this.setState({
35
+ inFlight: true
36
+ });
37
+ apiFetch({
38
+ path: isWizard ? `/newspack/v1/wizard/${pluginSlug}/settings` : `/${pluginSlug}/v1/settings`
39
+ }).then(settings => {
40
+ this.setState({
41
+ settings,
42
+ error: null
43
+ });
44
+ if ('function' === typeof afterFetch) {
45
+ afterFetch(settings);
46
+ }
47
+ }).catch(error => {
48
+ this.setState({
49
+ error
50
+ });
51
+ }).finally(() => {
52
+ this.setState({
53
+ inFlight: false
54
+ });
55
+ });
56
+ };
57
+ componentDidMount() {
58
+ this.fetchSettings();
59
+ }
60
+ getSettingsValues = sectionKey => {
61
+ return this.state.settings[sectionKey]?.reduce((map, setting) => {
62
+ map[setting.key] = setting.value;
63
+ return map;
64
+ }, {}) || {};
65
+ };
66
+ handleSettingChange = sectionKey => (key, value) => {
67
+ const sectionSettings = [...this.state.settings[sectionKey]];
68
+ sectionSettings.forEach(setting => {
69
+ if (setting.key === key) {
70
+ setting.value = value;
71
+ }
72
+ });
73
+ this.setState({
74
+ settings: {
75
+ ...this.state.settings,
76
+ [sectionKey]: sectionSettings
77
+ }
78
+ });
79
+ };
80
+ handleSectionUpdate = sectionKey => data => {
81
+ const {
82
+ afterUpdate,
83
+ pluginSlug,
84
+ isWizard
85
+ } = this.props;
86
+ this.setState({
87
+ inFlight: true
88
+ });
89
+ apiFetch({
90
+ path: isWizard ? `/newspack/v1/wizard/${pluginSlug}/settings` : `/${pluginSlug}/v1/settings`,
91
+ method: 'POST',
92
+ data: {
93
+ section: sectionKey,
94
+ settings: data ? data : this.getSettingsValues(sectionKey)
95
+ }
96
+ }).then(settings => {
97
+ this.setState({
98
+ settings: {
99
+ ...this.state.settings,
100
+ [sectionKey]: settings[sectionKey]
101
+ },
102
+ error: null
103
+ });
104
+ if ('function' === typeof afterUpdate) {
105
+ afterUpdate(settings);
106
+ }
107
+ }).catch(error => {
108
+ this.setState({
109
+ error
110
+ });
111
+ }).finally(() => {
112
+ this.setState({
113
+ inFlight: false
114
+ });
115
+ });
116
+ };
117
+
118
+ /**
119
+ * Get the section setting containing section information.
120
+ *
121
+ * @param {string} sectionKey The section name.
122
+ * @return {Object} The section setting.
123
+ */
124
+ getSectionInfo = sectionKey => {
125
+ return this.state.settings[sectionKey]?.find(setting => !setting.key || setting.key === 'active');
126
+ };
127
+
128
+ /**
129
+ * Get the section title.
130
+ *
131
+ * @param {string} sectionKey The section name.
132
+ * @return {string} The section title.
133
+ */
134
+ getSectionTitle = sectionKey => {
135
+ return this.getSectionInfo(sectionKey)?.description;
136
+ };
137
+
138
+ /**
139
+ * Get the section description.
140
+ *
141
+ * @param {string} sectionKey The section name.
142
+ * @return {string} The section description.
143
+ */
144
+ getSectionDescription = sectionKey => {
145
+ return this.getSectionInfo(sectionKey)?.help;
146
+ };
147
+
148
+ /**
149
+ * Get whether a section is active.
150
+ *
151
+ * @param {string} sectionKey The section name.
152
+ * @return {?boolean} Whether the section is active or not. Null if the section is not found or does not support activation.
153
+ */
154
+ isSectionActive = sectionKey => {
155
+ const {
156
+ settings
157
+ } = this.state;
158
+ const activation = settings[sectionKey]?.find(setting => setting.key === 'active');
159
+ if (!activation) {
160
+ return null;
161
+ }
162
+ return activation.value;
163
+ };
164
+
165
+ /**
166
+ * Get list of section field settings.
167
+ *
168
+ * @param {string} sectionKey The section name.
169
+ * @return {?Array} List of section fields.
170
+ */
171
+ getSectionFields = sectionKey => {
172
+ return this.state.settings[sectionKey]?.filter(setting => setting.key && setting.key !== 'active');
173
+ };
174
+
175
+ /**
176
+ * Render.
177
+ */
178
+ render() {
179
+ const {
180
+ title,
181
+ description,
182
+ hasGreyHeader,
183
+ children
184
+ } = this.props;
185
+ const {
186
+ settings,
187
+ inFlight,
188
+ error
189
+ } = this.state;
190
+ return /*#__PURE__*/_jsxs(Fragment, {
191
+ children: [title && /*#__PURE__*/_jsx(SectionHeader, {
192
+ title: title,
193
+ description: description
194
+ }), error && /*#__PURE__*/_jsx(Notice, {
195
+ isError: true,
196
+ noticeText: error.message
197
+ }), /*#__PURE__*/_jsxs("div", {
198
+ className: classnames('newspack-plugin-settings', {
199
+ 'newspack-wizard-section__is-loading': inFlight && !Object.keys(settings).length
200
+ }),
201
+ children: [Object.keys(settings).map(sectionKey => /*#__PURE__*/_jsx(SettingsSection, {
202
+ disabled: inFlight,
203
+ sectionKey: sectionKey,
204
+ title: this.getSectionTitle(sectionKey),
205
+ description: this.getSectionDescription(sectionKey),
206
+ active: this.isSectionActive(sectionKey),
207
+ fields: this.getSectionFields(sectionKey),
208
+ onChange: this.handleSettingChange(sectionKey),
209
+ onUpdate: this.handleSectionUpdate(sectionKey),
210
+ hasGreyHeader: hasGreyHeader
211
+ }, sectionKey)), children]
212
+ })]
213
+ });
214
+ }
215
+ }
216
+ PluginSettings.defaultProps = {
217
+ title: __('General Settings', 'newspack-plugin')
218
+ };
219
+ PluginSettings.Section = SettingsSection;
220
+ export default PluginSettings;
@@ -0,0 +1,7 @@
1
+ .newspack-card:not(.newspack-settings__no-border) {
2
+ .newspack-action-card__region-children {
3
+ > .newspack-grid {
4
+ margin: 32px 0 0 !important;
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,216 @@
1
+ /**
2
+ * WordPress dependencies.
3
+ */
4
+ import apiFetch from '@wordpress/api-fetch';
5
+ import { Component, Fragment } from '@wordpress/element';
6
+ import { __ } from '@wordpress/i18n';
7
+
8
+ /**
9
+ * Internal dependencies.
10
+ */
11
+ import { ActionCard, Waiting } from '../';
12
+ import './style.scss';
13
+
14
+ /**
15
+ * Plugin toggle group component.
16
+ */
17
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
+ class PluginToggle extends Component {
19
+ state = {
20
+ pluginInfo: {}
21
+ };
22
+ componentDidMount = () => {
23
+ this.retrievePluginInfo();
24
+ };
25
+
26
+ /**
27
+ * Retrieve complete data about Newspack plugins.
28
+ */
29
+ retrievePluginInfo = () => {
30
+ return new Promise(() => {
31
+ apiFetch({
32
+ path: '/newspack/v1/plugins/'
33
+ }).then(pluginInfo => this.setState({
34
+ pluginInfo
35
+ }));
36
+ });
37
+ };
38
+
39
+ /**
40
+ * Install/activate or remove a plugin.
41
+ */
42
+ managePlugin = (plugin, value) => {
43
+ const {
44
+ plugins
45
+ } = this.props;
46
+ const {
47
+ pluginInfo
48
+ } = this.state;
49
+ const action = value ? 'configure' : 'deactivate';
50
+ const params = {
51
+ path: `/newspack/v1/plugins/${plugin}/${action}/`,
52
+ method: 'post'
53
+ };
54
+ this.setState({
55
+ pluginInfo: {
56
+ ...pluginInfo,
57
+ [plugin]: {
58
+ ...pluginInfo[plugin],
59
+ inFlight: action
60
+ }
61
+ }
62
+ }, () => {
63
+ apiFetch(params).then(response => {
64
+ const {
65
+ shouldRefreshAfterUpdate
66
+ } = plugins[plugin];
67
+ this.setState(({
68
+ pluginInfo: currentPluginInfo
69
+ }) => ({
70
+ pluginInfo: {
71
+ ...currentPluginInfo,
72
+ [plugin]: response
73
+ }
74
+ }), () => shouldRefreshAfterUpdate && location.reload());
75
+ }).catch(e => {
76
+ this.setState({
77
+ pluginInfo: {
78
+ ...pluginInfo,
79
+ [plugin]: {
80
+ ...pluginInfo[plugin],
81
+ error: e.message || __('There was an error managing this plugin.', 'newspack-plugin')
82
+ }
83
+ }
84
+ });
85
+ });
86
+ });
87
+ };
88
+
89
+ /**
90
+ * Render.
91
+ */
92
+ render() {
93
+ const {
94
+ plugins
95
+ } = this.props;
96
+ const {
97
+ pluginInfo
98
+ } = this.state;
99
+ return this.prepareDataForRender(plugins, pluginInfo).map((plugin, index) => {
100
+ const {
101
+ name,
102
+ description,
103
+ href,
104
+ slug,
105
+ editPath
106
+ } = plugin;
107
+ const pluginStatus = this.isPluginInstalledAndActive(plugin);
108
+ const handoff = !href && pluginStatus && editPath ? slug : null;
109
+ const error = this.errorForPlugin(plugin);
110
+ return /*#__PURE__*/_jsx(ActionCard, {
111
+ className: this.classNameForPlugin(plugin),
112
+ title: name,
113
+ description: description,
114
+ actionText: this.actionTextForPlugin(plugin),
115
+ handoff: handoff,
116
+ href: href,
117
+ toggle: true,
118
+ toggleChecked: this.isPluginInstalledAndActive(plugin),
119
+ toggleOnChange: value => this.managePlugin(slug, value),
120
+ notification: error,
121
+ notificationHTML: error,
122
+ notificationLevel: "error"
123
+ }, index);
124
+ });
125
+ }
126
+
127
+ /**
128
+ * Prepare plugins data for render. Change all keys to camelCase, merge API-fetched data with prop.
129
+ */
130
+ prepareDataForRender = (pluginsFromProps, pluginsFromAPI) => Object.keys(pluginsFromProps).map(pluginSlug => pluginsFromAPI[pluginSlug] ? Object.keys(pluginsFromAPI[pluginSlug]).reduce((accumulator, key) => ({
131
+ ...accumulator,
132
+ [key.charAt(0).toLowerCase() + key.slice(1)]: pluginsFromAPI[pluginSlug][key]
133
+ }), {}) : {}).map(plugin => Object.assign(plugin, pluginsFromProps[plugin.slug]));
134
+
135
+ /**
136
+ * Generate a classname for the ActionCard based on plugin state. Applies 'in-flight' class if an API is underway and 'loading' if the plugin data is not yet available.
137
+ */
138
+ classNameForPlugin = plugin => {
139
+ const {
140
+ status,
141
+ inFlight
142
+ } = plugin;
143
+ if (inFlight) {
144
+ return 'in-flight';
145
+ }
146
+ if (!status) {
147
+ return 'loading';
148
+ }
149
+ };
150
+
151
+ /**
152
+ * Generate the ActionCard action text for a plugin.
153
+ */
154
+ actionTextForPlugin = plugin => {
155
+ const {
156
+ actionText,
157
+ editPath,
158
+ href,
159
+ inFlight,
160
+ name
161
+ } = plugin;
162
+ // Show spinner when plugin data is unavailable, or when an API call is in flight.
163
+ if ('configure' === inFlight) {
164
+ return /*#__PURE__*/_jsxs(Fragment, {
165
+ children: [__('Installing…', 'newspack-plugin'), " ", /*#__PURE__*/_jsx(Waiting, {
166
+ isRight: true
167
+ })]
168
+ });
169
+ }
170
+ if ('deactivate' === inFlight) {
171
+ return /*#__PURE__*/_jsxs(Fragment, {
172
+ children: [__('Deactivating…', 'newspack-plugin'), " ", /*#__PURE__*/_jsx(Waiting, {
173
+ isRight: true
174
+ })]
175
+ });
176
+ }
177
+ if (!name) {
178
+ return /*#__PURE__*/_jsxs(Fragment, {
179
+ children: [__('Loading…', 'newspack-plugin'), " ", /*#__PURE__*/_jsx(Waiting, {
180
+ isRight: true
181
+ })]
182
+ });
183
+ }
184
+ // No action button at all if the plugin isn't installed and active.
185
+ if (!this.isPluginInstalledAndActive(plugin)) {
186
+ return null;
187
+ }
188
+ if (href || editPath) {
189
+ return actionText ? actionText : __('Configure', 'newspack-plugin');
190
+ }
191
+ };
192
+
193
+ /**
194
+ * Get error message for this plugin.
195
+ */
196
+ errorForPlugin = plugin => {
197
+ const {
198
+ slug
199
+ } = plugin;
200
+ const {
201
+ pluginInfo
202
+ } = this.state;
203
+ return pluginInfo[slug]?.error || null;
204
+ };
205
+
206
+ /**
207
+ * Get installation/activation status for a plugin.
208
+ */
209
+ isPluginInstalledAndActive = plugin => {
210
+ const {
211
+ status
212
+ } = plugin;
213
+ return status === 'active';
214
+ };
215
+ }
216
+ export default PluginToggle;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Plugin Toggle
3
+ */
4
+
5
+ @use "~@wordpress/base-styles/colors" as wp-colors;
6
+
7
+ .newspack-action-card {
8
+ &.in-flight,
9
+ &.loading {
10
+ opacity: 0.5;
11
+
12
+ .newspack-action-card__region-right {
13
+ .newspack-button {
14
+ color: wp-colors.$gray-700;
15
+ pointer-events: none;
16
+ text-decoration: none;
17
+ }
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { Popover as BaseComponent } from '@wordpress/components';
5
+ import { Component } from '@wordpress/element';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import './style.scss';
11
+
12
+ /**
13
+ * External dependencies
14
+ */
15
+ import classnames from 'classnames';
16
+
17
+ /**
18
+ * Popover
19
+ */
20
+ import { jsx as _jsx } from "react/jsx-runtime";
21
+ class Popover extends Component {
22
+ /**
23
+ * Render
24
+ */
25
+ render() {
26
+ const {
27
+ className,
28
+ padding,
29
+ ...otherProps
30
+ } = this.props;
31
+ const classes = classnames('newspack-popover', padding && 'newspack-popover__padding-' + padding, className);
32
+ return /*#__PURE__*/_jsx(BaseComponent, {
33
+ className: classes,
34
+ ...otherProps
35
+ });
36
+ }
37
+ }
38
+ Popover.defaultProps = {
39
+ padding: false
40
+ };
41
+ export default Popover;
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Popover
3
+ */
4
+
5
+ @use "../../../shared/scss/colors";
6
+ @use "~@wordpress/base-styles/colors" as wp-colors;
7
+
8
+ .newspack-popover {
9
+ .components-popover__content {
10
+ min-width: 238px;
11
+
12
+ .newspack-button {
13
+ color: wp-colors.$gray-700;
14
+ display: flex;
15
+ font-weight: normal;
16
+ padding: 6px 8px;
17
+
18
+ &:hover {
19
+ color: colors.$primary-500;
20
+
21
+ .components-menu-items__item-icon {
22
+ fill: currentcolor;
23
+ }
24
+ }
25
+
26
+ &:focus:not(:disabled) {
27
+ box-shadow: inset 0 0 0 2px colors.$primary-500;
28
+ position: relative;
29
+ z-index: 1;
30
+ }
31
+
32
+ &.is-link {
33
+ border-radius: 2px;
34
+ padding: 6px 8px;
35
+ text-decoration: none;
36
+
37
+ &:not(.is-destructive) {
38
+ color: wp-colors.$gray-700;
39
+
40
+ &:active,
41
+ &:active:enabled,
42
+ &:focus,
43
+ &:focus:enabled &:hover,
44
+ &:not(:disabled, [aria-disabled="true"], .is-default):hover {
45
+ color: colors.$primary-500;
46
+ }
47
+ }
48
+
49
+ &:focus,
50
+ &:focus:enabled {
51
+ outline: none;
52
+ }
53
+ }
54
+
55
+ &.is-destructive:not(:focus) {
56
+ box-shadow: none !important;
57
+ }
58
+
59
+ .components-menu-items__item-icon {
60
+ fill: wp-colors.$gray-900;
61
+ }
62
+
63
+ .components-menu-item__item {
64
+ display: flex;
65
+ width: 100%;
66
+ }
67
+ }
68
+
69
+ .components-menu-group__label {
70
+ color: wp-colors.$gray-900;
71
+ font-size: 12px;
72
+ font-weight: bold;
73
+ line-height: 16px;
74
+ margin: 0;
75
+ padding: 10px 8px;
76
+ }
77
+
78
+ .screen-reader-text {
79
+ display: flex;
80
+ }
81
+
82
+ .newspack-select-control {
83
+ margin: 0;
84
+ width: 100%;
85
+
86
+ .components-select-control {
87
+ select.components-select-control__input {
88
+ height: 36px;
89
+ min-height: 36px;
90
+
91
+ &:focus ~ div.components-input-control__backdrop {
92
+ border-color: colors.$primary-500;
93
+ box-shadow: inset 0 0 0 1px colors.$primary-500;
94
+ }
95
+ }
96
+
97
+ div.components-input-control__backdrop {
98
+ padding: 0;
99
+ }
100
+ }
101
+ }
102
+
103
+ .newspack-form-token-field {
104
+ margin: 0;
105
+ text-align: left;
106
+
107
+ .newspack-form-token-field__input-container {
108
+ min-height: 36px;
109
+ padding: 3px 5px;
110
+ }
111
+
112
+ .components-form-token-field__suggestions-list {
113
+ margin: 5px -3px -11px;
114
+ }
115
+
116
+ .components-form-token-field__label {
117
+ display: block;
118
+ }
119
+ }
120
+
121
+ .newspack-toggle-control {
122
+ margin: 0;
123
+
124
+ .components-base-control__field {
125
+ margin: 3px 0;
126
+ }
127
+
128
+ .components-form-toggle {
129
+ border-top: 0;
130
+ }
131
+ }
132
+ }
133
+
134
+ &:not(.is-without-arrow)::before {
135
+ border-color: wp-colors.$gray-300;
136
+ }
137
+
138
+ &.is-from-bottom {
139
+ margin-bottom: 2px;
140
+ }
141
+
142
+ &.is-from-top {
143
+ margin-top: 2px;
144
+ }
145
+
146
+ &.components-animate__appear {
147
+ animation: none;
148
+ }
149
+
150
+ &__padding-8 {
151
+ .components-popover__content {
152
+ padding: 8px;
153
+ }
154
+ }
155
+
156
+ &__padding-16 {
157
+ .components-popover__content {
158
+ padding: 16px;
159
+ }
160
+ }
161
+ }