newspack-components 4.7.0 → 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/DEVELOPMENT.md +42 -21
  3. package/dist/cjs/_mixins.scss +13 -0
  4. package/dist/cjs/_variables.scss +12 -0
  5. package/dist/cjs/action-card/index.js +18 -10
  6. package/dist/cjs/action-card/index.test.js +91 -0
  7. package/dist/cjs/action-card/style.scss +2 -40
  8. package/dist/cjs/button/index.js +8 -3
  9. package/dist/cjs/button/index.test.js +61 -5
  10. package/dist/cjs/card/core-card.js +0 -2
  11. package/dist/cjs/card/style-core.scss +7 -5
  12. package/dist/cjs/card-feature/index.js +75 -61
  13. package/dist/cjs/card-feature/index.test.js +396 -54
  14. package/dist/cjs/card-feature/style.scss +20 -31
  15. package/dist/cjs/card-form/index.js +5 -5
  16. package/dist/cjs/card-sortable-list/index.js +5 -3
  17. package/dist/cjs/card-sortable-list/index.test.js +50 -0
  18. package/dist/cjs/collapsible-group/context.js +19 -0
  19. package/dist/cjs/collapsible-group/index.js +24 -0
  20. package/dist/cjs/collapsible-group/index.test.js +215 -0
  21. package/dist/cjs/collapsible-group/item.js +61 -0
  22. package/dist/cjs/collapsible-group/root.js +62 -0
  23. package/dist/cjs/collapsible-group/style.scss +47 -0
  24. package/dist/cjs/collapsible-group/types.js +5 -0
  25. package/dist/cjs/empty-state/actions.js +45 -0
  26. package/dist/cjs/empty-state/context.js +41 -0
  27. package/dist/cjs/empty-state/header.js +66 -0
  28. package/dist/cjs/empty-state/index.js +31 -0
  29. package/dist/cjs/empty-state/index.test.js +303 -0
  30. package/dist/cjs/empty-state/root.js +56 -0
  31. package/dist/cjs/empty-state/style.scss +51 -0
  32. package/dist/cjs/empty-state/types.js +5 -0
  33. package/dist/cjs/index.js +34 -20
  34. package/dist/cjs/info-button/index.js +59 -43
  35. package/dist/cjs/info-button/index.test.js +199 -0
  36. package/dist/cjs/info-button/style.scss +41 -9
  37. package/dist/cjs/modal/style.scss +12 -12
  38. package/dist/cjs/newspack-icon/style.scss +4 -4
  39. package/dist/cjs/notice/style.scss +3 -3
  40. package/dist/cjs/page/style.scss +16 -16
  41. package/dist/cjs/plugin-installer/index.js +5 -9
  42. package/dist/cjs/plugin-installer/style.scss +3 -14
  43. package/dist/cjs/section-header/index.js +31 -18
  44. package/dist/cjs/section-header/index.test.js +40 -0
  45. package/dist/cjs/section-header/style.scss +22 -6
  46. package/dist/cjs/settings/DateRangeSetting.js +309 -0
  47. package/dist/cjs/settings/SettingsSection.js +19 -5
  48. package/dist/cjs/settings/SettingsSection.test.js +49 -0
  49. package/dist/cjs/settings/index.js +3 -1
  50. package/dist/cjs/settings/style.scss +40 -7
  51. package/dist/cjs/stat-card/body.js +41 -0
  52. package/dist/cjs/stat-card/constants.js +11 -0
  53. package/dist/cjs/stat-card/context.js +54 -0
  54. package/dist/cjs/stat-card/delta.js +91 -0
  55. package/dist/cjs/stat-card/footer.js +72 -0
  56. package/dist/cjs/stat-card/index.js +47 -0
  57. package/dist/cjs/stat-card/index.test.js +938 -0
  58. package/dist/cjs/stat-card/label.js +66 -0
  59. package/dist/cjs/stat-card/root.js +69 -0
  60. package/dist/cjs/stat-card/secondary.js +38 -0
  61. package/dist/cjs/stat-card/style.scss +89 -0
  62. package/dist/cjs/stat-card/types.js +5 -0
  63. package/dist/cjs/stat-card/value.js +78 -0
  64. package/dist/cjs/status-indicator/index.js +66 -0
  65. package/dist/cjs/status-indicator/index.test.js +101 -0
  66. package/dist/cjs/status-indicator/statuses.js +39 -0
  67. package/dist/cjs/status-indicator/style.scss +9 -0
  68. package/dist/cjs/status-indicator/types.js +5 -0
  69. package/dist/cjs/style.scss +9 -9
  70. package/dist/cjs/tabbed-navigation/style.scss +6 -4
  71. package/dist/cjs/types.js +5 -0
  72. package/dist/cjs/web-preview/style.scss +11 -11
  73. package/dist/cjs/with-wizard/style.scss +10 -10
  74. package/dist/cjs/with-wizard-screen/style.scss +9 -9
  75. package/dist/cjs/wizard/index.js +33 -4
  76. package/dist/cjs/wizard/store/index.js +23 -1
  77. package/dist/esm/_mixins.scss +13 -0
  78. package/dist/esm/_variables.scss +12 -0
  79. package/dist/esm/action-card/index.js +18 -10
  80. package/dist/esm/action-card/index.test.js +89 -0
  81. package/dist/esm/action-card/style.scss +2 -40
  82. package/dist/esm/button/index.js +9 -4
  83. package/dist/esm/button/index.test.js +63 -5
  84. package/dist/esm/card/core-card.js +0 -2
  85. package/dist/esm/card/style-core.scss +7 -5
  86. package/dist/esm/card-feature/index.js +78 -62
  87. package/dist/esm/card-feature/index.test.js +397 -55
  88. package/dist/esm/card-feature/style.scss +20 -31
  89. package/dist/esm/card-form/index.js +5 -5
  90. package/dist/esm/card-sortable-list/index.js +6 -4
  91. package/dist/esm/card-sortable-list/index.test.js +46 -0
  92. package/dist/esm/collapsible-group/context.js +13 -0
  93. package/dist/esm/collapsible-group/index.js +17 -0
  94. package/dist/esm/collapsible-group/index.test.js +215 -0
  95. package/dist/esm/collapsible-group/item.js +53 -0
  96. package/dist/esm/collapsible-group/root.js +54 -0
  97. package/dist/esm/collapsible-group/style.scss +47 -0
  98. package/dist/esm/collapsible-group/types.js +1 -0
  99. package/dist/esm/empty-state/actions.js +37 -0
  100. package/dist/esm/empty-state/context.js +35 -0
  101. package/dist/esm/empty-state/header.js +58 -0
  102. package/dist/esm/empty-state/index.js +23 -0
  103. package/dist/esm/empty-state/index.test.js +299 -0
  104. package/dist/esm/empty-state/root.js +56 -0
  105. package/dist/esm/empty-state/style.scss +51 -0
  106. package/dist/esm/empty-state/types.js +1 -0
  107. package/dist/esm/index.js +4 -2
  108. package/dist/esm/info-button/index.js +54 -43
  109. package/dist/esm/info-button/index.test.js +195 -0
  110. package/dist/esm/info-button/style.scss +41 -9
  111. package/dist/esm/modal/style.scss +12 -12
  112. package/dist/esm/newspack-icon/style.scss +4 -4
  113. package/dist/esm/notice/style.scss +3 -3
  114. package/dist/esm/page/style.scss +16 -16
  115. package/dist/esm/plugin-installer/index.js +5 -9
  116. package/dist/esm/plugin-installer/style.scss +3 -14
  117. package/dist/esm/section-header/index.js +27 -14
  118. package/dist/esm/section-header/index.test.js +36 -0
  119. package/dist/esm/section-header/style.scss +22 -6
  120. package/dist/esm/settings/DateRangeSetting.js +304 -0
  121. package/dist/esm/settings/SettingsSection.js +16 -3
  122. package/dist/esm/settings/SettingsSection.test.js +45 -0
  123. package/dist/esm/settings/index.js +3 -1
  124. package/dist/esm/settings/style.scss +40 -7
  125. package/dist/esm/stat-card/body.js +36 -0
  126. package/dist/esm/stat-card/constants.js +5 -0
  127. package/dist/esm/stat-card/context.js +48 -0
  128. package/dist/esm/stat-card/delta.js +86 -0
  129. package/dist/esm/stat-card/footer.js +67 -0
  130. package/dist/esm/stat-card/index.js +33 -0
  131. package/dist/esm/stat-card/index.test.js +939 -0
  132. package/dist/esm/stat-card/label.js +61 -0
  133. package/dist/esm/stat-card/root.js +64 -0
  134. package/dist/esm/stat-card/secondary.js +33 -0
  135. package/dist/esm/stat-card/style.scss +89 -0
  136. package/dist/esm/stat-card/types.js +1 -0
  137. package/dist/esm/stat-card/value.js +73 -0
  138. package/dist/esm/status-indicator/index.js +52 -0
  139. package/dist/esm/status-indicator/index.test.js +96 -0
  140. package/dist/esm/status-indicator/statuses.js +33 -0
  141. package/dist/esm/status-indicator/style.scss +9 -0
  142. package/dist/esm/status-indicator/types.js +1 -0
  143. package/dist/esm/style.scss +9 -9
  144. package/dist/esm/tabbed-navigation/style.scss +6 -4
  145. package/dist/esm/types.js +1 -0
  146. package/dist/esm/web-preview/style.scss +11 -11
  147. package/dist/esm/with-wizard/style.scss +10 -10
  148. package/dist/esm/with-wizard-screen/style.scss +9 -9
  149. package/dist/esm/wizard/index.js +38 -7
  150. package/dist/esm/wizard/store/index.js +23 -1
  151. package/package.json +1 -1
  152. package/src/_mixins.scss +13 -0
  153. package/src/_variables.scss +12 -0
  154. package/src/action-card/action-card.d.ts +3 -2
  155. package/src/action-card/index.js +12 -12
  156. package/src/action-card/index.test.js +56 -0
  157. package/src/action-card/style.scss +2 -40
  158. package/src/button/index.test.js +52 -5
  159. package/src/button/index.tsx +9 -4
  160. package/src/card/core-card.js +0 -2
  161. package/src/card/style-core.scss +7 -5
  162. package/src/card-feature/README.md +68 -27
  163. package/src/card-feature/index.test.js +242 -27
  164. package/src/card-feature/index.tsx +77 -67
  165. package/src/card-feature/style.scss +20 -31
  166. package/src/card-form/README.md +10 -10
  167. package/src/card-form/index.tsx +4 -8
  168. package/src/card-sortable-list/README.md +4 -5
  169. package/src/card-sortable-list/index.test.js +29 -0
  170. package/src/card-sortable-list/index.tsx +7 -4
  171. package/src/collapsible-group/README.md +50 -0
  172. package/src/collapsible-group/context.ts +13 -0
  173. package/src/collapsible-group/index.test.js +168 -0
  174. package/src/collapsible-group/index.tsx +17 -0
  175. package/src/collapsible-group/item.tsx +42 -0
  176. package/src/collapsible-group/root.tsx +42 -0
  177. package/src/collapsible-group/style.scss +47 -0
  178. package/src/collapsible-group/types.ts +22 -0
  179. package/src/drawer/README.md +2 -2
  180. package/src/empty-state/README.md +165 -0
  181. package/src/empty-state/actions.tsx +37 -0
  182. package/src/empty-state/context.ts +40 -0
  183. package/src/empty-state/header.tsx +48 -0
  184. package/src/empty-state/index.test.js +247 -0
  185. package/src/empty-state/index.tsx +22 -0
  186. package/src/empty-state/root.tsx +39 -0
  187. package/src/empty-state/style.scss +51 -0
  188. package/src/empty-state/types.ts +33 -0
  189. package/src/index.js +4 -2
  190. package/src/info-button/README.md +115 -0
  191. package/src/info-button/index.test.js +163 -0
  192. package/src/info-button/index.tsx +64 -0
  193. package/src/info-button/style.scss +41 -9
  194. package/src/modal/style.scss +12 -12
  195. package/src/newspack-icon/style.scss +4 -4
  196. package/src/notice/style.scss +3 -3
  197. package/src/page/style.scss +16 -16
  198. package/src/plugin-installer/index.js +3 -9
  199. package/src/plugin-installer/style.scss +3 -14
  200. package/src/section-header/index.js +27 -14
  201. package/src/section-header/index.test.js +28 -0
  202. package/src/section-header/style.scss +22 -6
  203. package/src/settings/DateRangeSetting.js +266 -0
  204. package/src/settings/SettingsSection.js +24 -4
  205. package/src/settings/SettingsSection.test.js +45 -0
  206. package/src/settings/index.js +2 -0
  207. package/src/settings/style.scss +40 -7
  208. package/src/stat-card/README.md +434 -0
  209. package/src/stat-card/body.tsx +28 -0
  210. package/src/stat-card/constants.ts +5 -0
  211. package/src/stat-card/context.ts +53 -0
  212. package/src/stat-card/delta.tsx +88 -0
  213. package/src/stat-card/footer.tsx +68 -0
  214. package/src/stat-card/index.test.js +818 -0
  215. package/src/stat-card/index.tsx +48 -0
  216. package/src/stat-card/label.tsx +61 -0
  217. package/src/stat-card/root.tsx +40 -0
  218. package/src/stat-card/secondary.tsx +27 -0
  219. package/src/stat-card/style.scss +89 -0
  220. package/src/stat-card/types.ts +84 -0
  221. package/src/stat-card/value.tsx +72 -0
  222. package/src/status-indicator/README.md +123 -0
  223. package/src/status-indicator/index.test.js +70 -0
  224. package/src/status-indicator/index.tsx +39 -0
  225. package/src/status-indicator/statuses.ts +35 -0
  226. package/src/status-indicator/style.scss +9 -0
  227. package/src/status-indicator/types.ts +28 -0
  228. package/src/style.scss +9 -9
  229. package/src/tabbed-navigation/style.scss +6 -4
  230. package/src/types.ts +25 -0
  231. package/src/web-preview/style.scss +11 -11
  232. package/src/with-wizard/style.scss +10 -10
  233. package/src/with-wizard-screen/style.scss +9 -9
  234. package/src/wizard/index.js +49 -7
  235. package/src/wizard/store/index.js +26 -1
  236. package/dist/cjs/accordion/index.js +0 -72
  237. package/dist/cjs/accordion/index.test.js +0 -80
  238. package/dist/cjs/accordion/style.scss +0 -35
  239. package/dist/cjs/badge/index.js +0 -32
  240. package/dist/cjs/badge/style.scss +0 -36
  241. package/dist/esm/accordion/index.js +0 -63
  242. package/dist/esm/accordion/index.test.js +0 -79
  243. package/dist/esm/accordion/style.scss +0 -35
  244. package/dist/esm/badge/index.js +0 -24
  245. package/dist/esm/badge/style.scss +0 -36
  246. package/src/accordion/index.js +0 -46
  247. package/src/accordion/index.test.js +0 -62
  248. package/src/accordion/style.scss +0 -35
  249. package/src/badge/index.tsx +0 -26
  250. package/src/badge/style.scss +0 -36
  251. package/src/info-button/index.js +0 -38
@@ -2,55 +2,51 @@
2
2
  * CardFeature
3
3
  */
4
4
 
5
- @use "~@wordpress/base-styles/colors" as wp-colors;
5
+ @use "~@wordpress/base-styles/mixins" as wp-mixins;
6
6
  @use "~@wordpress/base-styles/variables" as wp-vars;
7
+ @use "../mixins" as np-mixins;
7
8
 
8
9
  .newspack-card-feature {
9
10
  height: 100%;
10
11
 
11
- .newspack-card--core__header {
12
- height: 100%;
13
- }
14
-
15
- .newspack-card--core__header-content {
16
- gap: 16px;
17
- display: flex;
18
- flex-direction: column;
19
- height: 100%;
12
+ &__actions {
13
+ margin-top: auto;
20
14
 
21
- // Push the action row (buttons + badge) to the bottom.
22
- > :last-child {
23
- margin-top: auto;
15
+ .newspack-card-feature__badge {
16
+ flex-shrink: 1;
17
+ min-width: 0;
24
18
  }
25
19
  }
26
20
 
27
21
  &__content {
28
22
  flex: 1;
29
- min-width: 0; // prevent flex blowout on long words
23
+ min-width: 0;
30
24
  }
31
25
 
32
26
  &__title {
33
- font-size: wp-vars.$font-size-x-large;
34
- line-height: wp-vars.$font-line-height-x-large;
35
- text-align: left;
27
+ @include wp-mixins.heading-x-large();
28
+
29
+ margin: 0;
36
30
  }
37
31
 
38
32
  &__description {
39
- text-align: left;
33
+ @include np-mixins.text-muted;
34
+
35
+ margin: 0;
40
36
  }
41
37
 
42
38
  &__icon {
43
39
  align-items: center;
44
40
  display: flex;
45
- flex: 0 0 40px;
46
- height: 40px;
41
+ flex: 0 0 wp-vars.$grid-unit-50;
42
+ height: wp-vars.$grid-unit-50;
47
43
  justify-content: center;
48
44
 
49
45
  svg {
50
46
  display: block;
51
47
  fill: currentcolor;
52
- height: 24px;
53
- width: 24px;
48
+ height: wp-vars.$grid-unit-30;
49
+ width: wp-vars.$grid-unit-30;
54
50
  }
55
51
 
56
52
  &--radius-small {
@@ -62,14 +58,7 @@
62
58
  }
63
59
  }
64
60
 
65
- // Unmet requirements state: lighter border, muted content.
66
- &.newspack-card-feature--muted {
67
- border-color: wp-colors.$gray-100;
68
- box-shadow: wp-colors.$gray-100 0 0 0 1px;
69
-
70
- .newspack-card-feature__title,
71
- .newspack-card-feature__description {
72
- color: wp-colors.$gray-700;
73
- }
61
+ &.newspack-card-feature--muted &__title {
62
+ @include np-mixins.text-muted;
74
63
  }
75
64
  }
@@ -17,16 +17,16 @@ import classnames from 'classnames';
17
17
  import { useEffect, useRef, createElement } from '@wordpress/element';
18
18
  import { useInstanceId } from '@wordpress/compose';
19
19
  import { __experimentalHStack as HStack, __experimentalVStack as VStack } from '@wordpress/components'; // eslint-disable-line @wordpress/no-unsafe-wp-apis
20
+ import { Badge } from '@wordpress/ui';
20
21
 
21
22
  /**
22
23
  * Internal dependencies
23
24
  */
24
- import Badge from '../badge';
25
25
  import Card from '../card';
26
26
  import './style.scss';
27
27
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
28
28
  var _CardForm = function CardForm(_ref) {
29
- var _badge$level;
29
+ var _badge$intent;
30
30
  var title = _ref.title,
31
31
  description = _ref.description,
32
32
  badge = _ref.badge,
@@ -113,9 +113,9 @@ var _CardForm = function CardForm(_ref) {
113
113
  }), /*#__PURE__*/_jsxs(HStack, {
114
114
  spacing: 2,
115
115
  expanded: false,
116
- children: [badge && /*#__PURE__*/_jsx(Badge, {
117
- text: badge.text,
118
- level: (_badge$level = badge.level) !== null && _badge$level !== void 0 ? _badge$level : 'success'
116
+ children: [(badge === null || badge === void 0 ? void 0 : badge.label) && /*#__PURE__*/_jsx(Badge, {
117
+ intent: (_badge$intent = badge.intent) !== null && _badge$intent !== void 0 ? _badge$intent : 'stable',
118
+ children: badge.label
119
119
  }), actions]
120
120
  })]
121
121
  })
@@ -12,11 +12,12 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
12
12
  */
13
13
  import { Disabled, Draggable, __experimentalVStack as VStack } from '@wordpress/components'; // eslint-disable-line @wordpress/no-unsafe-wp-apis
14
14
  import { useEffect, useLayoutEffect, useRef, useState } from '@wordpress/element';
15
+ import { Badge } from '@wordpress/ui';
15
16
 
16
17
  /**
17
18
  * Internal dependencies
18
19
  */
19
- import { Badge, Card } from '../';
20
+ import { Card } from '../';
20
21
  import './style.scss';
21
22
 
22
23
  /**
@@ -383,6 +384,7 @@ var CardSortableList = function CardSortableList(_ref) {
383
384
  onDragEnd: handleDragEnd,
384
385
  appendToOwnerDocument: true,
385
386
  children: function children(_ref2) {
387
+ var _item$badge, _item$badge$intent;
386
388
  var onDraggableStart = _ref2.onDraggableStart,
387
389
  onDraggableEnd = _ref2.onDraggableEnd;
388
390
  return /*#__PURE__*/_jsx(Card, {
@@ -394,9 +396,9 @@ var CardSortableList = function CardSortableList(_ref) {
394
396
  __experimentalCoreProps: _objectSpread(_objectSpread({
395
397
  header: /*#__PURE__*/_jsxs(_Fragment, {
396
398
  children: [/*#__PURE__*/_jsxs("h3", {
397
- children: [item.title, /*#__PURE__*/_jsx(Badge, {
398
- level: item.badgeLevel,
399
- text: item.badgeText
399
+ children: [item.title, ((_item$badge = item.badge) === null || _item$badge === void 0 ? void 0 : _item$badge.label) && /*#__PURE__*/_jsx(Badge, {
400
+ intent: (_item$badge$intent = item.badge.intent) !== null && _item$badge$intent !== void 0 ? _item$badge$intent : 'none',
401
+ children: item.badge.label
400
402
  })]
401
403
  }), item.description && /*#__PURE__*/_jsx("p", {
402
404
  children: item.description
@@ -0,0 +1,46 @@
1
+ /**
2
+ * External dependencies.
3
+ */
4
+ import { render, screen } from '@testing-library/react';
5
+
6
+ /**
7
+ * Internal dependencies.
8
+ */
9
+ import CardSortableList from './';
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ var items = [{
12
+ id: 1,
13
+ title: 'Homepage',
14
+ badge: {
15
+ label: 'Active',
16
+ intent: 'stable'
17
+ }
18
+ }, {
19
+ id: 2,
20
+ title: 'About',
21
+ badge: {
22
+ label: 'Draft',
23
+ intent: 'draft'
24
+ }
25
+ }];
26
+ describe('CardSortableList', function () {
27
+ it('renders a badge for each item that has badge text', function () {
28
+ render(/*#__PURE__*/_jsx(CardSortableList, {
29
+ items: items
30
+ }));
31
+ expect(screen.getByText('Active')).toBeInTheDocument();
32
+ expect(screen.getByText('Draft')).toBeInTheDocument();
33
+ });
34
+ it('renders no badge for an item without badge text', function () {
35
+ var _render = render(/*#__PURE__*/_jsx(CardSortableList, {
36
+ items: [{
37
+ id: 1,
38
+ title: 'Homepage'
39
+ }]
40
+ })),
41
+ container = _render.container;
42
+ expect(screen.getByText('Homepage')).toBeInTheDocument();
43
+ // An unguarded Badge would still emit an empty span, so assert on element children.
44
+ expect(container.querySelector('h3').children).toHaveLength(0);
45
+ });
46
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { createContext, useContext } from '@wordpress/element';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+
10
+ export var TitleLevelContext = createContext(2);
11
+ export var useTitleLevel = function useTitleLevel() {
12
+ return useContext(TitleLevelContext);
13
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * CollapsibleGroup
3
+ */
4
+
5
+ /**
6
+ * Internal dependencies
7
+ */
8
+ import Item from './item';
9
+ import Root from './root';
10
+
11
+ // The group is itself renderable, so `Item` hangs off it rather than forming a namespace object like `Drawer`.
12
+ var CollapsibleGroup = Object.assign(Root, {
13
+ Item: Item
14
+ });
15
+ CollapsibleGroup.displayName = 'CollapsibleGroup';
16
+ Item.displayName = 'CollapsibleGroup.Item';
17
+ export default CollapsibleGroup;
@@ -0,0 +1,215 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ /**
5
+ * External dependencies
6
+ */
7
+ import { fireEvent, render, screen } from '@testing-library/react';
8
+
9
+ /**
10
+ * Internal dependencies
11
+ */
12
+ import CollapsibleGroup from './index';
13
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
+ var renderItems = function renderItems(count) {
15
+ var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
16
+ return render(/*#__PURE__*/_jsx(CollapsibleGroup, _objectSpread(_objectSpread({}, props), {}, {
17
+ children: Array.from({
18
+ length: count
19
+ }, function (_, i) {
20
+ return /*#__PURE__*/_jsx(CollapsibleGroup.Item, {
21
+ title: "Panel ".concat(i),
22
+ children: "content"
23
+ }, i);
24
+ })
25
+ })));
26
+ };
27
+ var dividers = function dividers(container) {
28
+ return container.querySelectorAll('.newspack-divider');
29
+ };
30
+ var items = function items(container) {
31
+ return container.querySelectorAll('.newspack-collapsible-group__item');
32
+ };
33
+ describe('CollapsibleGroup dividers', function () {
34
+ it('renders no divider for a single item', function () {
35
+ var _renderItems = renderItems(1),
36
+ container = _renderItems.container;
37
+ expect(items(container)).toHaveLength(1);
38
+ expect(dividers(container)).toHaveLength(0);
39
+ });
40
+ it('renders a divider between items but not after the last', function () {
41
+ var _renderItems2 = renderItems(3),
42
+ container = _renderItems2.container;
43
+ expect(items(container)).toHaveLength(3);
44
+ expect(dividers(container)).toHaveLength(2);
45
+ expect(container.querySelector('.newspack-collapsible-group').lastElementChild).not.toHaveClass('newspack-divider');
46
+ });
47
+ it('counts only rendered items when placing dividers', function () {
48
+ var _render = render(/*#__PURE__*/_jsxs(CollapsibleGroup, {
49
+ children: [/*#__PURE__*/_jsx(CollapsibleGroup.Item, {
50
+ title: "Panel 0",
51
+ children: "content"
52
+ }), /*#__PURE__*/_jsx(CollapsibleGroup.Item, {
53
+ title: "Panel 1",
54
+ children: "content"
55
+ }), false, 'trailing text']
56
+ })),
57
+ container = _render.container;
58
+ expect(items(container)).toHaveLength(2);
59
+ expect(dividers(container)).toHaveLength(1);
60
+ expect(container.querySelector('.newspack-collapsible-group').lastElementChild).not.toHaveClass('newspack-divider');
61
+ });
62
+ it('renders tertiary dividers', function () {
63
+ var _renderItems3 = renderItems(2),
64
+ container = _renderItems3.container;
65
+ expect(dividers(container)[0]).toHaveClass('newspack-divider--variant-tertiary');
66
+ });
67
+ });
68
+ describe('CollapsibleGroup titleLevel', function () {
69
+ it('renders item titles as h2 by default', function () {
70
+ renderItems(2);
71
+ expect(screen.getAllByRole('heading', {
72
+ level: 2
73
+ })).toHaveLength(2);
74
+ });
75
+ it('renders every item title at the level given', function () {
76
+ renderItems(2, {
77
+ titleLevel: 3
78
+ });
79
+ expect(screen.getAllByRole('heading', {
80
+ level: 3
81
+ })).toHaveLength(2);
82
+ expect(screen.queryByRole('heading', {
83
+ level: 2
84
+ })).not.toBeInTheDocument();
85
+ });
86
+ it('clamps a level above the heading range', function () {
87
+ renderItems(2, {
88
+ titleLevel: 7
89
+ });
90
+ expect(screen.getAllByRole('heading', {
91
+ level: 6
92
+ })).toHaveLength(2);
93
+ });
94
+ it('clamps a level below the heading range', function () {
95
+ renderItems(1, {
96
+ titleLevel: 0
97
+ });
98
+ expect(screen.getByRole('heading', {
99
+ level: 1
100
+ })).toBeInTheDocument();
101
+ });
102
+ it('inherits the level in a nested group', function () {
103
+ render(/*#__PURE__*/_jsx(CollapsibleGroup, {
104
+ titleLevel: 4,
105
+ children: /*#__PURE__*/_jsx(CollapsibleGroup.Item, {
106
+ title: "Outer",
107
+ defaultOpen: true,
108
+ children: /*#__PURE__*/_jsx(CollapsibleGroup, {
109
+ children: /*#__PURE__*/_jsx(CollapsibleGroup.Item, {
110
+ title: "Inner",
111
+ children: "content"
112
+ })
113
+ })
114
+ })
115
+ }));
116
+ expect(screen.getByRole('heading', {
117
+ level: 4,
118
+ name: 'Inner'
119
+ })).toBeInTheDocument();
120
+ });
121
+ it('inherits the level in a nested group when the title is hidden', function () {
122
+ render(/*#__PURE__*/_jsx(CollapsibleGroup, {
123
+ titleLevel: 4,
124
+ hideSingleTitle: true,
125
+ children: /*#__PURE__*/_jsx(CollapsibleGroup.Item, {
126
+ title: "Outer",
127
+ children: /*#__PURE__*/_jsx(CollapsibleGroup, {
128
+ children: /*#__PURE__*/_jsx(CollapsibleGroup.Item, {
129
+ title: "Inner",
130
+ children: "content"
131
+ })
132
+ })
133
+ })
134
+ }));
135
+ expect(screen.getByRole('heading', {
136
+ level: 4,
137
+ name: 'Inner'
138
+ })).toBeInTheDocument();
139
+ });
140
+ });
141
+ describe('CollapsibleGroup hideSingleTitle', function () {
142
+ it('keeps the title on a lone item by default', function () {
143
+ renderItems(1);
144
+ expect(screen.getByRole('button', {
145
+ name: 'Panel 0'
146
+ })).toBeInTheDocument();
147
+ });
148
+ it('drops the title and opens a lone item when set', function () {
149
+ renderItems(1, {
150
+ hideSingleTitle: true
151
+ });
152
+ expect(screen.queryByRole('button', {
153
+ name: 'Panel 0'
154
+ })).not.toBeInTheDocument();
155
+ expect(screen.getByText('content')).toBeVisible();
156
+ });
157
+ it('leaves titles alone when there is more than one item', function () {
158
+ renderItems(2, {
159
+ hideSingleTitle: true
160
+ });
161
+ expect(screen.getByRole('button', {
162
+ name: 'Panel 0'
163
+ })).toBeInTheDocument();
164
+ expect(screen.getByRole('button', {
165
+ name: 'Panel 1'
166
+ })).toBeInTheDocument();
167
+ });
168
+ });
169
+ describe('CollapsibleGroup item state', function () {
170
+ it('expands only the item marked defaultOpen', function () {
171
+ render(/*#__PURE__*/_jsxs(CollapsibleGroup, {
172
+ children: [/*#__PURE__*/_jsx(CollapsibleGroup.Item, {
173
+ title: "Open",
174
+ defaultOpen: true,
175
+ children: "open content"
176
+ }), /*#__PURE__*/_jsx(CollapsibleGroup.Item, {
177
+ title: "Closed",
178
+ children: "closed content"
179
+ })]
180
+ }));
181
+ expect(screen.getByRole('button', {
182
+ name: 'Open'
183
+ })).toHaveAttribute('aria-expanded', 'true');
184
+ expect(screen.getByRole('button', {
185
+ name: 'Closed'
186
+ })).toHaveAttribute('aria-expanded', 'false');
187
+ });
188
+ it('leaves a collapsed panel reachable by find-in-page', function () {
189
+ var _renderItems4 = renderItems(1),
190
+ container = _renderItems4.container;
191
+ expect(container.querySelector('.newspack-collapsible-group__panel')).toHaveAttribute('hidden', 'until-found');
192
+ expect(screen.getByText('content')).toBeInTheDocument();
193
+ });
194
+ it('opens an item when its trigger is clicked', function () {
195
+ var _renderItems5 = renderItems(1),
196
+ container = _renderItems5.container;
197
+ var trigger = screen.getByRole('button', {
198
+ name: 'Panel 0'
199
+ });
200
+ fireEvent.click(trigger);
201
+ expect(trigger).toHaveAttribute('aria-expanded', 'true');
202
+ expect(container.querySelector('.newspack-collapsible-group__panel')).not.toHaveAttribute('hidden');
203
+ });
204
+ it('closes an open item when its trigger is clicked', function () {
205
+ var _renderItems6 = renderItems(1),
206
+ container = _renderItems6.container;
207
+ var trigger = screen.getByRole('button', {
208
+ name: 'Panel 0'
209
+ });
210
+ fireEvent.click(trigger);
211
+ fireEvent.click(trigger);
212
+ expect(trigger).toHaveAttribute('aria-expanded', 'false');
213
+ expect(container.querySelector('.newspack-collapsible-group__panel')).toHaveAttribute('hidden', 'until-found');
214
+ });
215
+ });
@@ -0,0 +1,53 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { Icon, chevronDown } from '@wordpress/icons';
5
+ import { Collapsible } from '@wordpress/ui';
6
+
7
+ /**
8
+ * External dependencies
9
+ */
10
+ import classNames from 'classnames';
11
+
12
+ /**
13
+ * Internal dependencies
14
+ */
15
+ import { useTitleLevel } from './context';
16
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
17
+ var Item = function Item(_ref) {
18
+ var children = _ref.children,
19
+ className = _ref.className,
20
+ _ref$defaultOpen = _ref.defaultOpen,
21
+ defaultOpen = _ref$defaultOpen === void 0 ? false : _ref$defaultOpen,
22
+ title = _ref.title;
23
+ var titleLevel = useTitleLevel();
24
+ if (!title) {
25
+ return /*#__PURE__*/_jsx("div", {
26
+ className: classNames('newspack-collapsible-group__item', className),
27
+ children: children
28
+ });
29
+ }
30
+ var Heading = "h".concat(titleLevel);
31
+ return /*#__PURE__*/_jsxs(Collapsible.Root, {
32
+ className: classNames('newspack-collapsible-group__item', className),
33
+ defaultOpen: defaultOpen,
34
+ children: [/*#__PURE__*/_jsx(Heading, {
35
+ className: "newspack-collapsible-group__heading",
36
+ children: /*#__PURE__*/_jsxs(Collapsible.Trigger, {
37
+ className: "newspack-collapsible-group__trigger",
38
+ children: [title, /*#__PURE__*/_jsx(Icon, {
39
+ icon: chevronDown,
40
+ size: 24
41
+ })]
42
+ })
43
+ }), /*#__PURE__*/_jsx(Collapsible.Panel, {
44
+ className: "newspack-collapsible-group__panel",
45
+ hiddenUntilFound: true,
46
+ children: /*#__PURE__*/_jsx("div", {
47
+ className: "newspack-collapsible-group__panel-inner",
48
+ children: children
49
+ })
50
+ })]
51
+ });
52
+ };
53
+ export default Item;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { Children, Fragment, cloneElement, isValidElement } from '@wordpress/element';
5
+ import { Stack } from '@wordpress/ui';
6
+
7
+ /**
8
+ * External dependencies
9
+ */
10
+ import classNames from 'classnames';
11
+
12
+ /**
13
+ * Internal dependencies
14
+ */
15
+ import Divider from '../divider';
16
+ import { TitleLevelContext, useTitleLevel } from './context';
17
+ import './style.scss';
18
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
+ var clampTitleLevel = function clampTitleLevel(level) {
20
+ return Number.isFinite(level) ? Math.min(6, Math.max(1, Math.round(level))) : undefined;
21
+ };
22
+ var Root = function Root(_ref) {
23
+ var _clampTitleLevel;
24
+ var children = _ref.children,
25
+ className = _ref.className,
26
+ _ref$gap = _ref.gap,
27
+ gap = _ref$gap === void 0 ? 'xl' : _ref$gap,
28
+ _ref$hideSingleTitle = _ref.hideSingleTitle,
29
+ hideSingleTitle = _ref$hideSingleTitle === void 0 ? false : _ref$hideSingleTitle,
30
+ titleLevel = _ref.titleLevel;
31
+ var inheritedTitleLevel = useTitleLevel();
32
+ var items = Children.toArray(children).filter(isValidElement);
33
+ var hideTitle = hideSingleTitle && items.length === 1;
34
+ return /*#__PURE__*/_jsx(TitleLevelContext.Provider, {
35
+ value: (_clampTitleLevel = clampTitleLevel(titleLevel)) !== null && _clampTitleLevel !== void 0 ? _clampTitleLevel : inheritedTitleLevel,
36
+ children: /*#__PURE__*/_jsx(Stack, {
37
+ className: classNames('newspack-collapsible-group', className),
38
+ direction: "column",
39
+ gap: gap,
40
+ children: items.map(function (item, index) {
41
+ return /*#__PURE__*/_jsxs(Fragment, {
42
+ children: [hideTitle ? cloneElement(item, {
43
+ title: undefined
44
+ }) : item, index < items.length - 1 && /*#__PURE__*/_jsx(Divider, {
45
+ variant: "tertiary",
46
+ marginBottom: 0,
47
+ marginTop: 0
48
+ })]
49
+ }, item.key);
50
+ })
51
+ })
52
+ });
53
+ };
54
+ export default Root;
@@ -0,0 +1,47 @@
1
+ @use "../mixins" as mixins;
2
+ @use "~@wordpress/base-styles/mixins" as wp-mixins;
3
+ @use "~@wordpress/base-styles/variables" as wp-vars;
4
+
5
+ .newspack-collapsible-group {
6
+ &__heading {
7
+ margin: 0;
8
+ }
9
+
10
+ &__trigger {
11
+ @include wp-mixins.heading-large();
12
+ align-items: center;
13
+ background: none;
14
+ border: 0;
15
+ color: inherit;
16
+ cursor: pointer;
17
+ display: flex;
18
+ gap: wp-vars.$grid-unit-10;
19
+ justify-content: space-between;
20
+ padding: 0;
21
+ text-align: left;
22
+ width: 100%;
23
+
24
+ &:focus-visible {
25
+ @include mixins.wpds-focus-ring;
26
+ outline-offset: wp-vars.$grid-unit-05;
27
+ }
28
+
29
+ svg {
30
+ flex-shrink: 0;
31
+ }
32
+
33
+ &[aria-expanded="true"] svg {
34
+ transform: rotate(180deg);
35
+ }
36
+
37
+ @media (prefers-reduced-motion: no-preference) {
38
+ svg {
39
+ transition: transform 0.1s ease-out;
40
+ }
41
+ }
42
+ }
43
+
44
+ &__panel-inner {
45
+ padding-top: wp-vars.$grid-unit-30;
46
+ }
47
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,37 @@
1
+ /**
2
+ * WordPress dependencies.
3
+ */
4
+ import { Stack } from '@wordpress/ui';
5
+
6
+ /**
7
+ * External dependencies.
8
+ */
9
+ import classnames from 'classnames';
10
+
11
+ /**
12
+ * Internal dependencies.
13
+ */
14
+ import { useEmptyStateInvariant } from './context';
15
+ import { jsx as _jsx } from "react/jsx-runtime";
16
+ var Actions = function Actions(_ref) {
17
+ var _ref$orientation = _ref.orientation,
18
+ orientation = _ref$orientation === void 0 ? 'row' : _ref$orientation,
19
+ _ref$gap = _ref.gap,
20
+ gap = _ref$gap === void 0 ? 'sm' : _ref$gap,
21
+ className = _ref.className,
22
+ children = _ref.children;
23
+ useEmptyStateInvariant();
24
+ var isColumn = orientation === 'column';
25
+
26
+ // Rows wrap: the empty state only gets half the grid above 1054px.
27
+ return /*#__PURE__*/_jsx(Stack, {
28
+ direction: isColumn ? 'column' : 'row',
29
+ align: "center",
30
+ justify: "center",
31
+ gap: gap,
32
+ wrap: isColumn ? undefined : 'wrap',
33
+ className: classnames('newspack-empty-state__actions', className),
34
+ children: children
35
+ });
36
+ };
37
+ export default Actions;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * WordPress dependencies.
3
+ */
4
+ import { createContext, useContext } from '@wordpress/element';
5
+
6
+ /**
7
+ * Internal dependencies.
8
+ */
9
+
10
+ export var EmptyStateContext = createContext(null);
11
+ var FALLBACK_CONTEXT = {
12
+ size: 'default'
13
+ };
14
+ export var useEmptyStateContext = function useEmptyStateContext() {
15
+ var context = useContext(EmptyStateContext);
16
+ if (!context && process.env.NODE_ENV !== 'production') {
17
+ throw new Error('EmptyState subcomponents must be rendered inside EmptyState.Root.');
18
+ }
19
+ return context !== null && context !== void 0 ? context : FALLBACK_CONTEXT;
20
+ };
21
+
22
+ /**
23
+ * Assert placement inside a `Root` without depending on the value.
24
+ *
25
+ * For subcomponents that read nothing from context. Both hooks throw in
26
+ * development so the mistake surfaces while it is cheap, and neither throws in
27
+ * production, because a stray subcomponent should not blank an admin screen
28
+ * over a layout hint.
29
+ */
30
+ export var useEmptyStateInvariant = function useEmptyStateInvariant() {
31
+ var context = useContext(EmptyStateContext);
32
+ if (!context && process.env.NODE_ENV !== 'production') {
33
+ throw new Error('EmptyState subcomponents must be rendered inside EmptyState.Root.');
34
+ }
35
+ };