@bundle-stats/ui 3.3.0-alpha.1 → 3.4.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 (190) hide show
  1. package/CHANGELOG.md +65 -13
  2. package/lib/app/app.js +137 -102
  3. package/lib/app/app.module.css +11 -4
  4. package/lib/app/header/header.js +1 -10
  5. package/lib/components/asset-info/asset-info.module.css +1 -0
  6. package/lib/components/bundle-assets/bundle-assets.js +104 -52
  7. package/lib/components/bundle-assets/bundle-assets.module.css +24 -26
  8. package/lib/components/bundle-assets-totals-table/bundle-assets-totals-table.js +13 -3
  9. package/lib/components/bundle-modules/bundle-modules.js +68 -68
  10. package/lib/components/bundle-modules/bundle-modules.module.css +11 -2
  11. package/lib/components/bundle-modules/bundle-modules.utils.js +14 -10
  12. package/lib/components/bundle-modules/index.js +4 -4
  13. package/lib/components/bundle-packages/bundle-packages.js +100 -44
  14. package/lib/components/bundle-packages/bundle-packages.module.css +17 -21
  15. package/lib/components/delta/delta.module.css +1 -0
  16. package/lib/components/job-header/job-header.js +3 -1
  17. package/lib/components/job-header/job-header.module.css +6 -8
  18. package/lib/components/jobs-header/jobs-header.module.css +5 -0
  19. package/lib/components/metrics-table/metrics-table.js +72 -59
  20. package/lib/components/metrics-table/metrics-table.module.css +18 -7
  21. package/lib/components/metrics-table-search/metrics-table-search.module.css +5 -4
  22. package/lib/components/metrics-table-title/metrics-table-title.js +9 -7
  23. package/lib/components/metrics-table-title/metrics-table-title.module.css +2 -0
  24. package/lib/components/module-info/module-info.js +2 -2
  25. package/lib/components/module-info/module-info.module.css +1 -0
  26. package/lib/components/summary/summary.js +1 -1
  27. package/lib/components/summary-item/summary-item.js +15 -18
  28. package/lib/components/summary-item/summary-item.module.css +1 -23
  29. package/lib/components/total-size-type-title/total-size-type-title.js +7 -3
  30. package/lib/constants.js +1 -1
  31. package/lib/css/default.css +14 -3
  32. package/lib/css/variables.css +17 -17
  33. package/lib/hooks/search-params.js +31 -31
  34. package/lib/layout/box/box.module.css +9 -0
  35. package/lib/layout/footer/footer.module.css +1 -1
  36. package/lib/layout/index.js +8 -0
  37. package/lib/layout/separator.js +48 -0
  38. package/lib/layout/separator.module.css +5 -0
  39. package/lib/ui/dropdown/dropdown.js +21 -26
  40. package/lib/ui/dropdown/dropdown.module.css +11 -12
  41. package/lib/ui/dropdown/dropdown.stories.js +2 -9
  42. package/lib/ui/empty-set/empty-set.js +5 -4
  43. package/lib/ui/empty-set/empty-set.module.css +2 -2
  44. package/lib/ui/filters/filters.container.js +1 -1
  45. package/lib/ui/filters/filters.js +22 -7
  46. package/lib/ui/filters/filters.module.css +3 -3
  47. package/lib/ui/horizontal-bar-chart/horizontal-bar-chart.js +1 -1
  48. package/lib/ui/hover-card/hover-card.js +102 -0
  49. package/lib/ui/hover-card/hover-card.module.css +29 -0
  50. package/lib/ui/hover-card/hover-card.stories.js +56 -0
  51. package/lib/ui/hover-card/index.js +18 -0
  52. package/lib/ui/icon/icon.js +6 -6
  53. package/lib/ui/icon/icon.module.css +1 -0
  54. package/lib/ui/index.js +8 -8
  55. package/lib/ui/table/table.js +5 -74
  56. package/lib/ui/table/table.module.css +41 -25
  57. package/lib/ui/table/table.stories.js +1 -1
  58. package/lib/ui/{popover → tag}/index.js +4 -4
  59. package/lib/ui/tag/tag.js +72 -0
  60. package/lib/ui/tag/tag.module.css +55 -0
  61. package/lib/ui/tag/tag.stories.js +38 -0
  62. package/lib/ui/tooltip/tooltip.js +10 -9
  63. package/lib/ui/tooltip/tooltip.module.css +2 -1
  64. package/lib-esm/app/app.js +132 -102
  65. package/lib-esm/app/app.module.css +11 -4
  66. package/lib-esm/app/header/header.js +1 -9
  67. package/lib-esm/components/asset-info/asset-info.module.css +1 -0
  68. package/lib-esm/components/bundle-assets/bundle-assets.js +97 -56
  69. package/lib-esm/components/bundle-assets/bundle-assets.module.css +24 -26
  70. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.js +7 -3
  71. package/lib-esm/components/bundle-modules/bundle-modules.js +50 -51
  72. package/lib-esm/components/bundle-modules/bundle-modules.module.css +11 -2
  73. package/lib-esm/components/bundle-modules/bundle-modules.utils.js +14 -6
  74. package/lib-esm/components/bundle-modules/index.js +5 -3
  75. package/lib-esm/components/bundle-packages/bundle-packages.js +88 -41
  76. package/lib-esm/components/bundle-packages/bundle-packages.module.css +17 -21
  77. package/lib-esm/components/delta/delta.module.css +1 -0
  78. package/lib-esm/components/job-header/job-header.js +2 -1
  79. package/lib-esm/components/job-header/job-header.module.css +6 -8
  80. package/lib-esm/components/jobs-header/jobs-header.module.css +5 -0
  81. package/lib-esm/components/metrics-table/metrics-table.js +61 -53
  82. package/lib-esm/components/metrics-table/metrics-table.module.css +18 -7
  83. package/lib-esm/components/metrics-table-search/metrics-table-search.module.css +5 -4
  84. package/lib-esm/components/metrics-table-title/metrics-table-title.js +8 -7
  85. package/lib-esm/components/metrics-table-title/metrics-table-title.module.css +2 -0
  86. package/lib-esm/components/module-info/module-info.js +2 -2
  87. package/lib-esm/components/module-info/module-info.module.css +1 -0
  88. package/lib-esm/components/summary/summary.js +1 -1
  89. package/lib-esm/components/summary-item/summary-item.js +14 -18
  90. package/lib-esm/components/summary-item/summary-item.module.css +1 -23
  91. package/lib-esm/components/total-size-type-title/total-size-type-title.js +6 -3
  92. package/lib-esm/constants.js +1 -1
  93. package/lib-esm/css/default.css +14 -3
  94. package/lib-esm/css/variables.css +17 -17
  95. package/lib-esm/hooks/search-params.js +27 -28
  96. package/lib-esm/layout/box/box.module.css +9 -0
  97. package/lib-esm/layout/footer/footer.module.css +1 -1
  98. package/lib-esm/layout/index.js +1 -0
  99. package/lib-esm/layout/separator.js +28 -0
  100. package/lib-esm/layout/separator.module.css +5 -0
  101. package/lib-esm/ui/dropdown/dropdown.js +20 -25
  102. package/lib-esm/ui/dropdown/dropdown.module.css +11 -12
  103. package/lib-esm/ui/dropdown/dropdown.stories.js +2 -7
  104. package/lib-esm/ui/empty-set/empty-set.js +4 -4
  105. package/lib-esm/ui/empty-set/empty-set.module.css +2 -2
  106. package/lib-esm/ui/filters/filters.js +20 -5
  107. package/lib-esm/ui/filters/filters.module.css +3 -3
  108. package/lib-esm/ui/hover-card/hover-card.js +83 -0
  109. package/lib-esm/ui/hover-card/hover-card.module.css +29 -0
  110. package/lib-esm/ui/hover-card/hover-card.stories.js +35 -0
  111. package/lib-esm/ui/hover-card/index.js +1 -0
  112. package/lib-esm/ui/icon/icon.js +3 -3
  113. package/lib-esm/ui/icon/icon.module.css +1 -0
  114. package/lib-esm/ui/index.js +1 -1
  115. package/lib-esm/ui/table/table.js +5 -65
  116. package/lib-esm/ui/table/table.module.css +41 -25
  117. package/lib-esm/ui/table/table.stories.js +1 -1
  118. package/lib-esm/ui/tag/index.js +1 -0
  119. package/lib-esm/ui/tag/tag.js +45 -0
  120. package/lib-esm/ui/tag/tag.module.css +55 -0
  121. package/lib-esm/ui/tag/tag.stories.js +23 -0
  122. package/lib-esm/ui/tooltip/tooltip.js +10 -9
  123. package/lib-esm/ui/tooltip/tooltip.module.css +2 -1
  124. package/package.json +33 -31
  125. package/src/app/app.jsx +142 -145
  126. package/src/app/app.module.css +11 -4
  127. package/src/app/header/header.jsx +0 -10
  128. package/src/components/asset-info/asset-info.module.css +1 -0
  129. package/src/components/bundle-assets/bundle-assets.jsx +85 -31
  130. package/src/components/bundle-assets/bundle-assets.module.css +24 -26
  131. package/src/components/bundle-assets-totals-table/bundle-assets-totals-table.jsx +2 -0
  132. package/src/components/bundle-modules/bundle-modules.jsx +53 -36
  133. package/src/components/bundle-modules/bundle-modules.module.css +11 -2
  134. package/src/components/bundle-modules/bundle-modules.utils.js +16 -4
  135. package/src/components/bundle-modules/index.jsx +3 -0
  136. package/src/components/bundle-packages/bundle-packages.jsx +89 -39
  137. package/src/components/bundle-packages/bundle-packages.module.css +17 -21
  138. package/src/components/delta/delta.module.css +1 -0
  139. package/src/components/job-header/job-header.jsx +2 -1
  140. package/src/components/job-header/job-header.module.css +6 -8
  141. package/src/components/jobs-header/jobs-header.module.css +5 -0
  142. package/src/components/metrics-table/metrics-table.jsx +53 -44
  143. package/src/components/metrics-table/metrics-table.module.css +18 -7
  144. package/src/components/metrics-table-search/metrics-table-search.module.css +5 -4
  145. package/src/components/metrics-table-title/metrics-table-title.jsx +20 -21
  146. package/src/components/metrics-table-title/metrics-table-title.module.css +2 -0
  147. package/src/components/module-info/module-info.jsx +3 -7
  148. package/src/components/module-info/module-info.module.css +1 -0
  149. package/src/components/summary/summary.jsx +1 -1
  150. package/src/components/summary-item/summary-item.jsx +21 -27
  151. package/src/components/summary-item/summary-item.module.css +1 -23
  152. package/src/components/total-size-type-title/total-size-type-title.jsx +6 -9
  153. package/src/constants.js +1 -1
  154. package/src/css/default.css +14 -3
  155. package/src/css/variables.css +17 -17
  156. package/src/hooks/search-params.js +42 -33
  157. package/src/layout/box/box.module.css +9 -0
  158. package/src/layout/footer/footer.module.css +1 -1
  159. package/src/layout/index.js +1 -0
  160. package/src/layout/separator.jsx +25 -0
  161. package/src/layout/separator.module.css +5 -0
  162. package/src/ui/dropdown/dropdown.jsx +16 -22
  163. package/src/ui/dropdown/dropdown.module.css +11 -12
  164. package/src/ui/empty-set/empty-set.jsx +25 -21
  165. package/src/ui/empty-set/empty-set.module.css +2 -2
  166. package/src/ui/filters/filters.jsx +64 -53
  167. package/src/ui/filters/filters.module.css +3 -3
  168. package/src/ui/hover-card/hover-card.jsx +73 -0
  169. package/src/ui/hover-card/hover-card.module.css +29 -0
  170. package/src/ui/hover-card/index.js +1 -0
  171. package/src/ui/icon/icon.jsx +11 -7
  172. package/src/ui/icon/icon.module.css +1 -0
  173. package/src/ui/index.js +1 -1
  174. package/src/ui/table/table.jsx +5 -52
  175. package/src/ui/table/table.module.css +41 -25
  176. package/src/ui/tag/index.js +1 -0
  177. package/src/ui/tag/tag.jsx +49 -0
  178. package/src/ui/tag/tag.module.css +55 -0
  179. package/src/ui/tooltip/tooltip.jsx +10 -14
  180. package/src/ui/tooltip/tooltip.module.css +2 -1
  181. package/lib/ui/popover/popover.js +0 -92
  182. package/lib/ui/popover/popover.module.css +0 -66
  183. package/lib/ui/popover/popover.stories.js +0 -26
  184. package/lib-esm/ui/popover/index.js +0 -1
  185. package/lib-esm/ui/popover/popover.js +0 -71
  186. package/lib-esm/ui/popover/popover.module.css +0 -66
  187. package/lib-esm/ui/popover/popover.stories.js +0 -14
  188. package/src/ui/popover/index.js +0 -1
  189. package/src/ui/popover/popover.jsx +0 -79
  190. package/src/ui/popover/popover.module.css +0 -66
@@ -3,7 +3,8 @@ import PropTypes from 'prop-types';
3
3
  import cx from 'classnames';
4
4
  import { getGlobalMetricType, getMetricRunInfo } from '@bundle-stats/utils';
5
5
 
6
- import { Popover } from '../../ui/popover';
6
+ import { HoverCard } from '../../ui/hover-card';
7
+ import { Icon } from '../../ui/icon';
7
8
  import { Skeleton } from '../../ui/skeleton';
8
9
  import { Stack } from '../../layout/stack';
9
10
  import { FlexStack } from '../../layout/flex-stack';
@@ -12,32 +13,25 @@ import { Delta } from '../delta';
12
13
  import { BudgetInfo } from '../budget-info';
13
14
  import css from './summary-item.module.css';
14
15
 
15
- const MetricInfoPopover = ({ description, url }) => {
16
- // Workaround cases where the parent is a link
17
- const readMoreOnClick = () => {
18
- window.open(url);
19
- };
20
-
21
- return (
22
- <Stack space="xxxsmall">
23
- <p>{description}</p>
24
- {url && (
25
- <p>
26
- <button type="button" className={css.readMoreBtn} onClick={readMoreOnClick}>
27
- Read more
28
- </button>
29
- </p>
30
- )}
31
- </Stack>
32
- );
33
- };
34
-
35
- MetricInfoPopover.propTypes = {
16
+ const MetricInfo = ({ description, url }) => (
17
+ <Stack space="xxxsmall">
18
+ <p>{description}</p>
19
+ {url && (
20
+ <p>
21
+ <a href={url} className={css.readMoreLink}>
22
+ Read more
23
+ </a>
24
+ </p>
25
+ )}
26
+ </Stack>
27
+ );
28
+
29
+ MetricInfo.propTypes = {
36
30
  description: PropTypes.string.isRequired,
37
31
  url: PropTypes.string,
38
32
  };
39
33
 
40
- MetricInfoPopover.defaultProps = {
34
+ MetricInfo.defaultProps = {
41
35
  url: '',
42
36
  };
43
37
 
@@ -61,14 +55,14 @@ export const SummaryItem = ({
61
55
  const rootClassName = cx(css.root, className, css[size], showDelta && css.showDelta);
62
56
 
63
57
  return (
64
- <Stack space="xxsmall" as={Component} className={rootClassName} {...props}>
58
+ <Stack space="xxxsmall" as={Component} className={rootClassName} {...props}>
65
59
  <FlexStack as="h3" space="xxxsmall" className={css.title}>
66
60
  <span className={css.titleLabel}>{metric.label}</span>
67
61
 
68
62
  {showMetricDescriptionTooltip && (
69
- <Popover className={css.icon} icon="help">
70
- <MetricInfoPopover {...metric} />
71
- </Popover>
63
+ <HoverCard className={css.icon} label={<Icon glyph="help" />}>
64
+ <MetricInfo {...metric} />
65
+ </HoverCard>
72
66
  )}
73
67
 
74
68
  {budget && <BudgetInfo className={css.budgetInfo} metricId={id} budgetInsight={budget} />}
@@ -4,6 +4,7 @@
4
4
  }
5
5
 
6
6
  .title {
7
+ align-items: center;
7
8
  color: var(--color-text-ultra-light);
8
9
  font-weight: bold;
9
10
  font-size: var(--size-xsmall);
@@ -12,29 +13,6 @@
12
13
  white-space: nowrap;
13
14
  }
14
15
 
15
- .titleLabel {
16
- flex: 0 0 auto;
17
- }
18
-
19
- .readMoreBtn {
20
- appearance: none;
21
- padding: 0;
22
- border: 0;
23
- background: none;
24
- cursor: pointer;
25
- /* simulate link */
26
- color: var(--color-primary);
27
- text-decoration: underline;
28
- line-height: var(--space-small);
29
- }
30
-
31
- .readMoreBtn:hover,
32
- .readMoreBtn:active,
33
- .readMoreBtn:focus {
34
- color: var(--color-primary-dark);
35
- text-decoration: none;
36
- }
37
-
38
16
  .budgetInfo {
39
17
  position: absolute;
40
18
  right: 0;
@@ -1,31 +1,28 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import cx from 'classnames'
3
+ import cx from 'classnames';
4
4
 
5
5
  import config from '../../config.json';
6
6
  import I18N from '../../i18n';
7
7
  import { FlexStack } from '../../layout/flex-stack';
8
8
  import { Stack } from '../../layout/stack';
9
- import { Popover } from '../../ui/popover';
9
+ import { Icon } from '../../ui/icon';
10
+ import { HoverCard } from '../../ui/hover-card';
10
11
  import css from './total-size-type-title.module.css';
11
12
 
12
13
  export const TotalSizeTypeTitle = ({ className }) => (
13
14
  <FlexStack space="xxxsmall" className={cx(css.title, className)}>
14
15
  <span>{I18N.ASSET_TOTALS}</span>
15
- <Popover icon="help">
16
+ <HoverCard label={<Icon glyph="help" />}>
16
17
  <Stack space="xxxsmall">
17
18
  <p>{I18N.ASSET_TOTALS_INFO}</p>
18
19
  <p>
19
- <a
20
- href={config.documentation.assets}
21
- target="_blank"
22
- rel="noreferrer"
23
- >
20
+ <a href={config.documentation.assets} target="_blank" rel="noreferrer">
24
21
  {I18N.READ_MORE}
25
22
  </a>
26
23
  </p>
27
24
  </Stack>
28
- </Popover>
25
+ </HoverCard>
29
26
  </FlexStack>
30
27
  );
31
28
 
package/src/constants.js CHANGED
@@ -53,5 +53,5 @@ export const METRICS_WEBPACK_GENERAL = [
53
53
  'cacheInvalidation',
54
54
  ];
55
55
  export const METRICS_WEBPACK_ASSETS = ['assetCount', 'chunkCount'];
56
- export const METRICS_WEBPACK_MODULES = ['moduleCount'];
56
+ export const METRICS_WEBPACK_MODULES = ['moduleCount', 'duplicateModulesCount', 'duplicateCode'];
57
57
  export const METRICS_WEBPACK_PACKAGES = ['packageCount', 'duplicatePackagesCount'];
@@ -1,18 +1,29 @@
1
+ @import url("~modern-css-reset/dist/reset.css");
2
+
1
3
  :root {
2
4
  --chart-height: 180px;
3
5
  }
4
6
 
7
+ /** modern-css-reset updates */
8
+ pre,
9
+ ul,
10
+ ol,
11
+ button {
12
+ margin: 0;
13
+ }
14
+
5
15
  html {
16
+ font-family: var(--font-family);
6
17
  font-size: 81.25%;
7
- line-height: 1.8461;
18
+ line-height: 1.6;
8
19
  }
9
20
 
10
21
  body {
22
+ background: var(--color-background);
11
23
  color: var(--color-text);
12
24
  }
13
25
 
14
- h1, h2, h3, h4, h5 {
15
- margin-bottom: var(--space-small);
26
+ h1, h2, h3, h4, h5, h6 {
16
27
  color: var(--color-heading);
17
28
  font-weight: 500;
18
29
  }
@@ -23,30 +23,30 @@
23
23
  --size-xxlarge: 1.424rem;
24
24
  --size-xxxlarge: 1.602rem;
25
25
 
26
- --line-height: var(--space-medium);
26
+ --line-height: 1.6em;
27
27
 
28
28
  /*
29
29
  * Color scheme:
30
- * http://mcg.mbitson.com/#!?mcgpalette0=%23dd555e&mcgpalette1=%2363bf5e&mcgpalette2=%23f7e37d&mcgpalette3=%23636568&mcgpalette4=%233385d6&themename=mcgtheme
31
30
  * https://coolors.co/3385d6-dd555e-63bf5e-f7e37d-192339
31
+ * http://mcg.mbitson.com/#!?mcgpalette0=%23dd555e&mcgpalette1=%2363bf5e&mcgpalette2=%23f7e37d&mcgpalette3=%235b5d60&mcgpalette4=%233385d6&themename=mcgtheme
32
32
  */
33
33
  --color-gray-25: #fafafa;
34
- --color-gray-50: #eceded;
35
- --color-gray-100: #d0d1d2;
36
- --color-gray-200: #b1b2b4;
37
- --color-gray-300: #929395;
38
- --color-gray-400: #7a7c7f;
39
- --color-gray-500: #636568;
40
- --color-gray-600: #5b5d60;
41
- --color-gray-700: #515355;
42
- --color-gray-800: #47494b;
43
- --color-gray-900: #35373a;
34
+ --color-gray-50: #e4e4e5;
35
+ --color-gray-100: #cececf;
36
+ --color-gray-200: #adaeb0;
37
+ --color-gray-300: #8c8e90;
38
+ --color-gray-400: #747578;
39
+ --color-gray-500: #5b5d60;
40
+ --color-gray-600: #535558;
41
+ --color-gray-700: #494b4e;
42
+ --color-gray-800: #404144;
43
+ --color-gray-900: #2f3033;
44
44
 
45
45
  --color-gray-ultra-light: var(--color-gray-200);
46
46
  --color-gray-light: var(--color-gray-300);
47
47
  --color-gray: var(--color-gray-500);
48
- --color-gray-dark: var(--color-gray-700);
49
- --color-gray-ultra-dark: var(--color-gray-900);
48
+ --color-gray-dark: var(--color-gray-600);
49
+ --color-gray-ultra-dark: var(--color-gray-700);
50
50
 
51
51
  --color-red-25: #fdf5f6;
52
52
  --color-red-50: #fbebec;
@@ -181,9 +181,9 @@
181
181
  --layer-high: 1000;
182
182
  --layer-xhigh: 10000;
183
183
 
184
- --radius-small: var(--space-xxxsmall);
185
- --radius-medium: var(--space-xxsmall);
186
- --radius-large: var(--space-small);
184
+ --radius-small: 3px;
185
+ --radius-medium: var(--space-xxxsmall);
186
+ --radius-large: var(--space-xxsmall);
187
187
 
188
188
  /** Layout */
189
189
  --max-width: 80rem;
@@ -7,8 +7,11 @@ const ACTION_RESET_DEFAULT = 'RESET_DEFAULT';
7
7
  const ACTION_RESET_ALL = 'RESET_ALL';
8
8
  const ACTION_SET = 'SET';
9
9
 
10
+ const SEARCH_DEFAULT = '';
11
+ const SEARCH_DEFAULT_PATTERN = /.*/;
12
+
10
13
  const getSearchPattern = (search) => {
11
- let searchPattern = /.*/;
14
+ let searchPattern = SEARCH_DEFAULT_PATTERN;
12
15
 
13
16
  if (!search || !search.trim()) {
14
17
  return searchPattern;
@@ -25,57 +28,57 @@ const getSearchPattern = (search) => {
25
28
  };
26
29
 
27
30
  const getSearchReducer =
28
- ({ defaultFilters, allEntriesFilters, setParentState }) => (state, action) => {
31
+ ({ defaultFilters, allEntriesFilters, setParentState }) =>
32
+ (state, action) => {
29
33
  const { type, payload } = action;
30
34
 
31
35
  switch (type) {
32
36
  case ACTION_SET_FILTERS: {
33
- setParentState({
37
+ const newState = {
34
38
  filters: payload,
35
39
  search: state.search,
36
- });
37
-
38
- return {
39
- ...state,
40
- filters: payload,
41
40
  };
41
+ setParentState(newState);
42
+ return newState;
42
43
  }
43
44
 
44
45
  case ACTION_SET_SEARCH: {
45
- setParentState({
46
+ const newState = {
46
47
  filters: state.filters,
47
48
  search: payload,
48
- });
49
+ };
50
+
51
+ setParentState(newState);
49
52
 
50
53
  return {
51
- ...state,
52
- search: payload,
54
+ ...newState,
53
55
  searchPattern: getSearchPattern(payload),
54
56
  };
55
57
  }
56
58
 
57
59
  case ACTION_RESET_DEFAULT: {
58
- setParentState({
60
+ const newState = {
59
61
  filters: defaultFilters,
60
- search: '',
61
- });
62
+ search: SEARCH_DEFAULT,
63
+ };
64
+
65
+ setParentState(newState);
62
66
 
63
67
  return {
64
- filters: defaultFilters,
65
- search: '',
68
+ ...newState,
66
69
  searchPattern: getSearchPattern(),
67
70
  };
68
71
  }
69
72
 
70
73
  case ACTION_RESET_ALL: {
71
- setParentState({
74
+ const newState = {
72
75
  filters: allEntriesFilters,
73
- search: '',
74
- });
76
+ search: SEARCH_DEFAULT,
77
+ };
78
+ setParentState(newState);
75
79
 
76
80
  return {
77
- filters: allEntriesFilters,
78
- search: '',
81
+ ...newState,
79
82
  searchPattern: getSearchPattern(),
80
83
  };
81
84
  }
@@ -96,7 +99,7 @@ export const generateState = (filters, search) => ({
96
99
  });
97
100
 
98
101
  export const useSearchParams = ({
99
- search: parentSearch,
102
+ search: parentSearch = SEARCH_DEFAULT,
100
103
 
101
104
  filters: parentFilters,
102
105
  defaultFilters,
@@ -116,29 +119,35 @@ export const useSearchParams = ({
116
119
  // Update state when the custom filters/search are changing - initial load or route updates
117
120
  useLayoutEffect(() => {
118
121
  // Run a deep comparison to prevent circular setState triggering
119
- if (parentSearch === search || isEqual(parentFilters, filters)) {
122
+ if (parentSearch === search && isEqual(initialFilters, filters)) {
120
123
  return;
121
124
  }
122
125
 
123
126
  dispatch({ type: ACTION_SET, payload: generateState(initialFilters, parentSearch) });
124
- }, [search, filters, parentFilters, parentSearch]);
127
+ }, [dispatch, search, filters, parentSearch, initialFilters]);
125
128
 
126
129
  /** Callbacks */
127
- const handleUpdateSearch = useCallback((newValue) => {
128
- dispatch({ type: ACTION_SET_SEARCH, payload: newValue });
129
- }, []);
130
+ const handleUpdateSearch = useCallback(
131
+ (newValue) => {
132
+ dispatch({ type: ACTION_SET_SEARCH, payload: newValue });
133
+ },
134
+ [dispatch],
135
+ );
130
136
 
131
- const handleUpdateFilters = useCallback((newFilters) => {
132
- dispatch({ type: ACTION_SET_FILTERS, payload: newFilters });
133
- }, []);
137
+ const handleUpdateFilters = useCallback(
138
+ (newFilters) => {
139
+ dispatch({ type: ACTION_SET_FILTERS, payload: newFilters });
140
+ },
141
+ [dispatch],
142
+ );
134
143
 
135
144
  const handleResetFilters = useCallback(() => {
136
145
  dispatch({ type: ACTION_RESET_DEFAULT });
137
- }, []);
146
+ }, [dispatch]);
138
147
 
139
148
  const handleResetAllFilters = useCallback(() => {
140
149
  dispatch({ type: ACTION_RESET_ALL });
141
- }, []);
150
+ }, [dispatch]);
142
151
 
143
152
  return {
144
153
  search,
@@ -4,6 +4,15 @@
4
4
 
5
5
  .outline {
6
6
  border: 1px solid var(--color-outline);
7
+ border-radius: var(--radius-medium);
8
+ }
9
+
10
+ .outline > :first-child {
11
+ border-radius: var(--radius-medium) var(--radius-medium) 0 0;
12
+ }
13
+
14
+ .outline > :last-child {
15
+ border-radius: 0 0 var(--radius-medium) var(--radius-medium);
7
16
  }
8
17
 
9
18
  .padding-xxxsmall {
@@ -3,7 +3,7 @@
3
3
  }
4
4
 
5
5
  .inner {
6
- border-top: 2px solid var(--color-outline);
6
+ border-top: 1px solid var(--color-outline);
7
7
  }
8
8
 
9
9
  .navItem {
@@ -1,6 +1,7 @@
1
1
  export { Box } from './box';
2
2
  export { Footer } from './footer';
3
3
  export { Header } from './header';
4
+ export { Separator } from './separator';
4
5
  export { SubHeader } from './sub-header';
5
6
  export { Stack } from './stack';
6
7
  export { FlexStack } from './flex-stack';
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import cx from 'classnames';
4
+
5
+ import css from './separator.module.css';
6
+
7
+ const propTypes = {
8
+ className: PropTypes.string,
9
+ };
10
+
11
+ const defaultProps = {
12
+ className: '',
13
+ };
14
+
15
+ /**
16
+ * @param {PropTypes.InferProps<typeof propTypes>} props
17
+ * @return {React.FunctionComponentElement}
18
+ */
19
+ export const Separator = (props) => {
20
+ const { className, ...restProps } = props;
21
+ return <div className={cx(css.root, className)} {...restProps} />;
22
+ };
23
+
24
+ Separator.propTypes = propTypes;
25
+ Separator.defaultProps = defaultProps;
@@ -0,0 +1,5 @@
1
+ .root {
2
+ background: var(--color-outline);
3
+ width: 100%;
4
+ height: 1px;
5
+ }
@@ -1,54 +1,54 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import cx from 'classnames';
4
- import { Menu, MenuItem, MenuButton, useMenuState } from 'reakit/Menu';
4
+ import { Menu, MenuButton, MenuItem, useMenuState } from 'ariakit/menu';
5
5
 
6
6
  import { FlexStack } from '../../layout/flex-stack';
7
7
  import { Icon } from '../icon';
8
8
  import css from './dropdown.module.css';
9
9
 
10
10
  export const Dropdown = (props) => {
11
- const { className, label, ariaLabel, glyph, activeLabel, children } = props;
12
- const rootClassName = cx(css.root, activeLabel && css.activeLabel, className);
13
-
14
- const menu = useMenuState({baseId: process.env.NODE_ENV === 'test' && 'id-test', modal: true });
11
+ const { className, buttonClassName, label, ariaLabel, glyph, children } = props;
12
+ const rootClassName = cx(css.root, className);
13
+ const menuState = useMenuState();
15
14
 
16
15
  return (
17
- <>
18
- <MenuButton {...menu} className={rootClassName} tabIndex={null}>
19
- <FlexStack space="xxxsmall" className={css.label}>
16
+ <div className={rootClassName}>
17
+ <MenuButton state={menuState} className={cx(css.button, buttonClassName)} tabIndex={null}>
18
+ <FlexStack space="xxxsmall">
20
19
  {glyph && <Icon className={css.labelIcon} glyph={glyph} />}
21
20
  {label}
22
21
  </FlexStack>
23
22
  </MenuButton>
24
- <Menu {...menu} aria-label={ariaLabel || label} className={css.dropdown}>
23
+ <Menu state={menuState} aria-label={ariaLabel || label} className={css.dropdown}>
25
24
  {typeof children === 'function'
26
- ?
27
- children({
25
+ ? children({
28
26
  MenuItem,
29
- menu,
27
+ menu: menuState,
30
28
  menuItemClassName: css.menuItem,
31
29
  menuItemActiveClassName: css.menuItemActive,
32
30
  })
33
- : children
34
- }
31
+ : children}
35
32
  </Menu>
36
- </>
33
+ </div>
37
34
  );
38
35
  };
39
36
 
40
37
  Dropdown.defaultProps = {
41
38
  className: '',
39
+ buttonClassName: '',
42
40
  label: null,
43
41
  ariaLabel: '',
44
42
  glyph: null,
45
- activeLabel: false,
46
43
  };
47
44
 
48
45
  Dropdown.propTypes = {
49
46
  /** Adopted child class name */
50
47
  className: PropTypes.string,
51
48
 
49
+ /** Button adopted child class name */
50
+ buttonClassName: PropTypes.string,
51
+
52
52
  /** Button label */
53
53
  label: PropTypes.node,
54
54
 
@@ -58,12 +58,6 @@ Dropdown.propTypes = {
58
58
  /** Icon glyph */
59
59
  glyph: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
60
60
 
61
- /** Dropdown open state */
62
- open: PropTypes.bool.isRequired,
63
-
64
- /** Active label flag */
65
- activeLabel: PropTypes.bool,
66
-
67
61
  /** Content */
68
62
  children: PropTypes.oneOfType([PropTypes.string, PropTypes.element, PropTypes.func]).isRequired,
69
63
  };
@@ -1,16 +1,14 @@
1
1
  .root {
2
+ display: inline-block;
3
+ }
4
+
5
+ .button {
2
6
  background: none;
3
7
  border: none;
4
8
  padding: 0;
5
- }
6
-
7
- .root:focus {
8
- outline: none;
9
- box-shadow: 0 0 var(--space-xxxsmall) var(--color-shadow);
10
- }
11
9
 
12
- .label {
13
10
  border: 1px solid var(--color-outline);
11
+ border-radius: var(--radius-small);
14
12
  padding: calc(var(--space-xxsmall) - 1px);
15
13
  display: flex;
16
14
  align-items: center;
@@ -24,7 +22,11 @@
24
22
  color: var(--color-text-light);
25
23
  }
26
24
 
27
- .label:hover {
25
+ .button:hover,
26
+ .button:focus,
27
+ .button:active {
28
+ outline: none;
29
+ box-shadow: 0 0 var(--space-xxxsmall) var(--color-shadow);
28
30
  border-color: var(--color-outline-dark);
29
31
  color: var(--color-text);
30
32
  }
@@ -33,6 +35,7 @@
33
35
  position: absolute;
34
36
  left: 0;
35
37
  top: 100%;
38
+ border-radius: var(--radius-medium);
36
39
  box-shadow: 0 2px var(--space-xxsmall) var(--color-shadow);
37
40
  background: var(--color-background);
38
41
  min-width: 180px;
@@ -45,10 +48,6 @@
45
48
  box-shadow: 0 2px var(--space-xsmall) var(--color-shadow);
46
49
  }
47
50
 
48
- .activeLabel .label {
49
- color: var(--color-text);
50
- }
51
-
52
51
  .menuItem {
53
52
  display: block;
54
53
  appearance: none;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
 
4
+ import { Stack } from '../../layout/stack';
4
5
  import I18N from '../../i18n';
5
6
  import css from './empty-set.module.css';
6
7
 
@@ -9,30 +10,33 @@ export const EmptySet = (props) => {
9
10
 
10
11
  const message = filtered ? `No ${resources} found.` : `No ${resources} available.`;
11
12
  const actions = [
12
- ...handleResetFilters ? [
13
- (
14
- <button className={css.action} type="button" onClick={handleResetFilters}>
15
- {I18N.RESET_FILTERS}
16
- </button>
17
- )
18
- ] : [],
19
- ...handleViewAll ? [(
20
- <button className={css.action} type="button" onClick={handleViewAll}>
21
- {I18N.VIEW_ALL}
22
- </button>
23
- )] : [],
13
+ ...(handleResetFilters
14
+ ? [
15
+ <button className={css.action} type="button" onClick={handleResetFilters}>
16
+ {I18N.RESET_FILTERS}
17
+ </button>,
18
+ ]
19
+ : []),
20
+ ...(handleViewAll
21
+ ? [
22
+ <button className={css.action} type="button" onClick={handleViewAll}>
23
+ {I18N.VIEW_ALL}
24
+ </button>,
25
+ ]
26
+ : []),
24
27
  ];
25
28
 
26
29
  return (
27
- <div className={css.root}>
28
- <p className={css.text}>{message}</p>
29
- {filtered && actions.map((action, index) => (
30
- <>
31
- {index > 0 && ' or '}
32
- {action}
33
- </>
34
- ))}
35
- </div>
30
+ <Stack space="xxsmall" className={css.root}>
31
+ <p>{message}</p>
32
+ {filtered &&
33
+ actions.map((action, index) => (
34
+ <>
35
+ {index > 0 && ' or '}
36
+ {action}
37
+ </>
38
+ ))}
39
+ </Stack>
36
40
  );
37
41
  };
38
42
 
@@ -1,5 +1,5 @@
1
- .text {
2
- margin-bottom: 0;
1
+ .root {
2
+ color: var(--color-text-light);
3
3
  }
4
4
 
5
5
  .action {