@automattic/vip-design-system 0.8.0 → 0.9.2

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 (92) hide show
  1. package/.eslines.json +10 -0
  2. package/.eslintignore +7 -0
  3. package/.eslintrc.json +23 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  5. package/.github/workflows/codeql-analysis.yml +71 -0
  6. package/.github/workflows/nodejs.yaml +29 -0
  7. package/.prettierrc +9 -0
  8. package/.storybook/preview.js +5 -0
  9. package/README.md +38 -1
  10. package/babel.config.js +10 -10
  11. package/build/system/Avatar/Avatar.js +1 -1
  12. package/build/system/Avatar/Avatar.test.js +54 -0
  13. package/build/system/Card/Card.js +2 -1
  14. package/build/system/Dialog/DialogButton.js +0 -2
  15. package/build/system/Dialog/DialogContent.js +1 -1
  16. package/build/system/Form/InlineSelect.js +2 -2
  17. package/build/system/Form/Input.js +2 -1
  18. package/build/system/Form/RadioBoxGroup.js +0 -2
  19. package/build/system/Form/SearchSelect.js +1 -1
  20. package/build/system/Form/Select.js +3 -3
  21. package/build/system/Form/Textarea.js +3 -2
  22. package/build/system/Form/ToggleGroup.js +0 -4
  23. package/build/system/Notice/Notice.js +50 -29
  24. package/build/system/ResourceList/ResourceItem.js +89 -0
  25. package/build/system/ResourceList/ResourceList.js +121 -0
  26. package/build/system/ResourceList/index.js +11 -0
  27. package/build/system/Time/index.js +91 -0
  28. package/build/system/Timeline/index.js +11 -9
  29. package/build/system/Tooltip/Tooltip.js +4 -3
  30. package/build/system/index.js +9 -0
  31. package/build/system/theme/index.js +1 -1
  32. package/package.json +47 -7
  33. package/src/system/Avatar/Avatar.js +1 -1
  34. package/src/system/Avatar/Avatar.stories.js +0 -5
  35. package/src/system/Avatar/Avatar.test.js +31 -0
  36. package/src/system/Badge/Badge.js +1 -1
  37. package/src/system/Badge/Badge.stories.js +0 -5
  38. package/src/system/BlankState/BlankState.js +2 -2
  39. package/src/system/BlankState/BlankState.stories.js +0 -5
  40. package/src/system/Box/Box.stories.js +0 -5
  41. package/src/system/Button/Button.js +1 -1
  42. package/src/system/Card/Card.js +16 -12
  43. package/src/system/Card/Card.stories.js +0 -5
  44. package/src/system/Code/Code.stories.js +4 -1
  45. package/src/system/ConfirmationDialog/ConfirmationDialog.stories.js +0 -5
  46. package/src/system/Dialog/Dialog.stories.js +0 -5
  47. package/src/system/Dialog/DialogButton.js +0 -1
  48. package/src/system/Dialog/DialogContent.js +14 -1
  49. package/src/system/Flex/Flex.stories.js +0 -5
  50. package/src/system/Form/InlineSelect.js +6 -6
  51. package/src/system/Form/Input.js +2 -0
  52. package/src/system/Form/Input.stories.js +0 -5
  53. package/src/system/Form/RadioBoxGroup.js +1 -2
  54. package/src/system/Form/RadioBoxGroup.stories.js +4 -5
  55. package/src/system/Form/SearchSelect.js +4 -4
  56. package/src/system/Form/Select.js +18 -18
  57. package/src/system/Form/Select.stories.js +1 -1
  58. package/src/system/Form/Textarea.js +3 -1
  59. package/src/system/Form/ToggleGroup.js +34 -37
  60. package/src/system/Form/ToggleGroup.stories.js +30 -32
  61. package/src/system/Form/ToggleRow.js +1 -1
  62. package/src/system/Grid/Grid.stories.js +0 -5
  63. package/src/system/Heading/Heading.stories.js +0 -5
  64. package/src/system/Link/Link.stories.js +0 -5
  65. package/src/system/Notice/Notice.js +30 -11
  66. package/src/system/Notification/Notification.js +2 -2
  67. package/src/system/Notification/Notification.stories.js +0 -5
  68. package/src/system/OptionRow/OptionRow.js +23 -23
  69. package/src/system/OptionRow/OptionRow.stories.js +0 -5
  70. package/src/system/Progress/Progress.stories.js +0 -5
  71. package/src/system/ResourceList/ResourceItem.js +66 -0
  72. package/src/system/ResourceList/ResourceList.js +96 -0
  73. package/src/system/ResourceList/ResourceList.stories.js +300 -0
  74. package/src/system/ResourceList/index.js +7 -0
  75. package/src/system/Spinner/Spinner.stories.js +0 -5
  76. package/src/system/Table/Table.stories.js +0 -5
  77. package/src/system/Table/TableRow.js +1 -1
  78. package/src/system/Tabs/Tabs.stories.js +0 -5
  79. package/src/system/Text/Text.stories.js +0 -5
  80. package/src/system/{Timeline/Timeline.stories.js → Time/Time.stories.js} +5 -5
  81. package/src/system/Time/index.js +62 -0
  82. package/src/system/Timeline/index.js +11 -5
  83. package/src/system/Tooltip/Tooltip.js +5 -4
  84. package/src/system/Tooltip/Tooltip.stories.js +0 -5
  85. package/src/system/Wizard/Wizard.js +7 -7
  86. package/src/system/Wizard/WizardStep.js +5 -5
  87. package/src/system/Wizard/WizardStepHorizontal.js +1 -1
  88. package/src/system/index.js +27 -2
  89. package/src/system/theme/colors.js +1 -1
  90. package/src/system/theme/index.js +248 -248
  91. package/test/setupAfterEnv.js +13 -0
  92. package/test/setupTests.js +4 -0
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.ResourceItem = void 0;
5
+
6
+ var _propTypes = _interopRequireDefault(require("prop-types"));
7
+
8
+ var _ = require("..");
9
+
10
+ var _jsxRuntime = require("theme-ui/jsx-runtime");
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
13
+
14
+ /** @jsxImportSource theme-ui */
15
+
16
+ /**
17
+ * External dependencies
18
+ */
19
+
20
+ /**
21
+ * Internal dependencies
22
+ */
23
+ var ResourceItem = function ResourceItem(_ref) {
24
+ var children = _ref.children,
25
+ item = _ref.item,
26
+ renderActions = _ref.renderActions,
27
+ _ref$relativeTime = _ref.relativeTime,
28
+ relativeTime = _ref$relativeTime === void 0 ? false : _ref$relativeTime,
29
+ _ref$timeOnly = _ref.timeOnly,
30
+ timeOnly = _ref$timeOnly === void 0 ? false : _ref$timeOnly,
31
+ dateKey = _ref.dateKey,
32
+ _ref$icon = _ref.icon,
33
+ icon = _ref$icon === void 0 ? null : _ref$icon;
34
+ return (0, _jsxRuntime.jsxs)(_.Flex, {
35
+ sx: {
36
+ alignItems: 'center',
37
+ gap: 3
38
+ },
39
+ children: [icon, (0, _jsxRuntime.jsx)(_.Box, {
40
+ sx: {
41
+ flex: '1 1 auto'
42
+ },
43
+ children: children
44
+ }), (0, _jsxRuntime.jsxs)(_.Flex, {
45
+ sx: {
46
+ flex: '0 0 auto',
47
+ alignItems: 'center',
48
+ gap: 3
49
+ },
50
+ children: [(0, _jsxRuntime.jsx)(_.Time, {
51
+ className: "time",
52
+ relativeTime: relativeTime,
53
+ timeOnly: timeOnly,
54
+ time: item[dateKey],
55
+ sx: {
56
+ color: 'muted',
57
+ mb: 0,
58
+ textAlign: 'right',
59
+ flex: '0 0 auto'
60
+ }
61
+ }), renderActions && (0, _jsxRuntime.jsxs)(_.Flex, {
62
+ className: "actions",
63
+ sx: {
64
+ alignItems: 'center',
65
+ gap: 3
66
+ },
67
+ children: [(0, _jsxRuntime.jsx)(_.Box, {
68
+ sx: {
69
+ width: 4,
70
+ height: 4,
71
+ borderRadius: 4,
72
+ bg: 'border'
73
+ }
74
+ }), renderActions(item)]
75
+ })]
76
+ })]
77
+ });
78
+ };
79
+
80
+ exports.ResourceItem = ResourceItem;
81
+ ResourceItem.propTypes = {
82
+ children: _propTypes["default"].node,
83
+ item: _propTypes["default"].object,
84
+ icon: _propTypes["default"].node,
85
+ relativeTime: _propTypes["default"].bool,
86
+ timeOnly: _propTypes["default"].bool,
87
+ dateKey: _propTypes["default"].string,
88
+ renderActions: _propTypes["default"].func
89
+ };
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.ResourceList = void 0;
5
+
6
+ var _propTypes = _interopRequireDefault(require("prop-types"));
7
+
8
+ var _ = require("..");
9
+
10
+ var _jsxRuntime = require("theme-ui/jsx-runtime");
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
13
+
14
+ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
15
+
16
+ var formatterOptions = {
17
+ weekday: 'long',
18
+ year: 'numeric',
19
+ month: 'long',
20
+ day: 'numeric'
21
+ };
22
+
23
+ var formatDate = function formatDate(date) {
24
+ var today = new Date();
25
+
26
+ if (date.getFullYear() !== today.getFullYear()) {
27
+ return date.toLocaleDateString(formatterOptions);
28
+ } else if (date.getMonth() !== today.getMonth()) {
29
+ return date.toLocaleDateString(formatterOptions);
30
+ } else if (date.getDate() < today.getDate() - 1) {
31
+ return date.toLocaleDateString(formatterOptions);
32
+ } else if (date.getDate() === today.getDate() - 1) {
33
+ return 'Yesterday';
34
+ }
35
+
36
+ return 'Today';
37
+ };
38
+
39
+ var StyledListItem = function StyledListItem(props) {
40
+ return (0, _jsxRuntime.jsx)(_.Box, _extends({
41
+ as: "li",
42
+ sx: {
43
+ py: 2,
44
+ borderBottom: '1px solid',
45
+ borderColor: 'border',
46
+ listStyleType: 'none',
47
+ margin: 0,
48
+ px: 0
49
+ }
50
+ }, props));
51
+ };
52
+
53
+ var ResourceList = function ResourceList(_ref) {
54
+ var _ref$groupedByDay = _ref.groupedByDay,
55
+ groupedByDay = _ref$groupedByDay === void 0 ? false : _ref$groupedByDay,
56
+ items = _ref.items,
57
+ renderItem = _ref.renderItem,
58
+ dateKey = _ref.dateKey;
59
+ var groupedItems = {};
60
+
61
+ if (groupedByDay) {
62
+ groupedItems = items == null ? void 0 : items.reduce(function (itemGroups, item) {
63
+ var _extends2;
64
+
65
+ var formattedDate = formatDate(item[dateKey]);
66
+ var itemsAtDate = itemGroups[formattedDate];
67
+ return _extends({}, itemGroups, (_extends2 = {}, _extends2[formattedDate] = itemsAtDate ? [].concat(itemsAtDate, [item]) : [item], _extends2));
68
+ }, {});
69
+ }
70
+
71
+ var renderItemList = function renderItemList(itemsList) {
72
+ return itemsList.map(function (item, index) {
73
+ return (0, _jsxRuntime.jsx)(StyledListItem, {
74
+ children: renderItem(item)
75
+ }, index);
76
+ });
77
+ };
78
+
79
+ return (0, _jsxRuntime.jsx)(_.Box, {
80
+ as: "ul",
81
+ sx: {
82
+ listStyleType: 'none',
83
+ m: 0,
84
+ p: 0
85
+ },
86
+ children: groupedByDay ? Object.keys(groupedItems).map(function (groupName, index) {
87
+ return (0, _jsxRuntime.jsxs)(_.Box, {
88
+ sx: {
89
+ mb: 4
90
+ },
91
+ children: [(0, _jsxRuntime.jsx)(_.Heading, {
92
+ variant: "h4",
93
+ as: "h4",
94
+ sx: {
95
+ mb: 3
96
+ },
97
+ children: groupName
98
+ }), (0, _jsxRuntime.jsx)(_.Box, {
99
+ as: "ul",
100
+ sx: {
101
+ listStyleType: 'none',
102
+ m: 0,
103
+ p: 0,
104
+ borderTop: '1px solid',
105
+ borderColor: 'border'
106
+ },
107
+ children: renderItemList(groupedItems[groupName])
108
+ })]
109
+ }, index);
110
+ }) : renderItemList(items)
111
+ });
112
+ };
113
+
114
+ exports.ResourceList = ResourceList;
115
+ ResourceList.propTypes = {
116
+ groupedByDay: _propTypes["default"].bool,
117
+ items: _propTypes["default"].array,
118
+ renderItem: _propTypes["default"].func,
119
+ relativeTime: _propTypes["default"].bool,
120
+ dateKey: _propTypes["default"].string
121
+ };
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+
5
+ var _ResourceList = require("./ResourceList");
6
+
7
+ exports.ResourceList = _ResourceList.ResourceList;
8
+
9
+ var _ResourceItem = require("./ResourceItem");
10
+
11
+ exports.ResourceItem = _ResourceItem.ResourceItem;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.Time = void 0;
5
+
6
+ var _themeUi = require("theme-ui");
7
+
8
+ var _propTypes = _interopRequireDefault(require("prop-types"));
9
+
10
+ var _jsxRuntime = require("theme-ui/jsx-runtime");
11
+
12
+ var _excluded = ["time", "relativeTime", "timeOnly"];
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
15
+
16
+ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
17
+
18
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
19
+
20
+ var formatter = new Intl.RelativeTimeFormat(undefined, {
21
+ numeric: 'auto'
22
+ });
23
+ var DIVISIONS = [{
24
+ amount: 60,
25
+ name: 'seconds'
26
+ }, {
27
+ amount: 60,
28
+ name: 'minutes'
29
+ }, {
30
+ amount: 24,
31
+ name: 'hours'
32
+ }, {
33
+ amount: 7,
34
+ name: 'days'
35
+ }, {
36
+ amount: 12,
37
+ name: 'months'
38
+ }, {
39
+ amount: Number.POSITIVE_INFINITY,
40
+ name: 'years'
41
+ }];
42
+
43
+ function formatTimeAgo(date) {
44
+ var duration = (date - new Date()) / 1000;
45
+
46
+ for (var i = 0; i <= DIVISIONS.length; i++) {
47
+ var division = DIVISIONS[i];
48
+
49
+ if (Math.abs(duration) < division.amount) {
50
+ return formatter.format(Math.round(duration), division.name);
51
+ }
52
+
53
+ duration /= division.amount;
54
+ }
55
+ }
56
+
57
+ var Time = function Time(_ref) {
58
+ var time = _ref.time,
59
+ _ref$relativeTime = _ref.relativeTime,
60
+ relativeTime = _ref$relativeTime === void 0 ? false : _ref$relativeTime,
61
+ _ref$timeOnly = _ref.timeOnly,
62
+ timeOnly = _ref$timeOnly === void 0 ? false : _ref$timeOnly,
63
+ props = _objectWithoutPropertiesLoose(_ref, _excluded);
64
+
65
+ var formattedTime;
66
+
67
+ if (relativeTime) {
68
+ formattedTime = formatTimeAgo(time);
69
+ } else if (timeOnly) {
70
+ formattedTime = time.toLocaleTimeString();
71
+ } else {
72
+ formattedTime = time.toLocaleString();
73
+ }
74
+
75
+ return (0, _jsxRuntime.jsx)(_themeUi.Text, _extends({
76
+ title: time.toLocaleString('sv', {
77
+ timeZoneName: 'short'
78
+ }),
79
+ datetime: time,
80
+ as: "time"
81
+ }, props, {
82
+ children: formattedTime
83
+ }));
84
+ };
85
+
86
+ exports.Time = Time;
87
+ Time.propTypes = {
88
+ time: _propTypes["default"].string,
89
+ timeOnly: _propTypes["default"].bool,
90
+ relativeTime: _propTypes["default"].bool
91
+ };
@@ -11,7 +11,7 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
11
11
 
12
12
  var _jsxRuntime = require("theme-ui/jsx-runtime");
13
13
 
14
- var _excluded = ["time"];
14
+ var _excluded = ["time", "first", "last"];
15
15
 
16
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
17
17
 
@@ -32,6 +32,10 @@ var VerticalLine = function VerticalLine() {
32
32
 
33
33
  var Timeline = function Timeline(_ref) {
34
34
  var time = _ref.time,
35
+ _ref$first = _ref.first,
36
+ first = _ref$first === void 0 ? false : _ref$first,
37
+ _ref$last = _ref.last,
38
+ last = _ref$last === void 0 ? false : _ref$last,
35
39
  props = _objectWithoutPropertiesLoose(_ref, _excluded);
36
40
 
37
41
  return (0, _jsxRuntime.jsxs)(_themeUi.Flex, _extends({}, props, {
@@ -41,22 +45,18 @@ var Timeline = function Timeline(_ref) {
41
45
  justifyContent: 'space-evenly',
42
46
  alignItems: 'center'
43
47
  },
44
- children: [(0, _jsxRuntime.jsx)(VerticalLine, {}), (0, _jsxRuntime.jsx)(_md.MdWatchLater, {
48
+ children: [!first && (0, _jsxRuntime.jsx)(VerticalLine, {}), (0, _jsxRuntime.jsx)(_md.MdWatchLater, {
45
49
  sx: {
46
50
  color: 'border'
47
51
  },
48
52
  size: 18
49
- }), (0, _jsxRuntime.jsx)(VerticalLine, {})]
53
+ }), !last && (0, _jsxRuntime.jsx)(VerticalLine, {})]
50
54
  }), (0, _jsxRuntime.jsx)(_themeUi.Flex, {
51
55
  sx: {
52
56
  alignItems: 'center',
53
57
  ml: 2
54
58
  },
55
- children: (0, _jsxRuntime.jsx)(_themeUi.Text, {
56
- as: "span",
57
- sx: {
58
- color: 'muted'
59
- },
59
+ children: (0, _jsxRuntime.jsx)("span", {
60
60
  children: time
61
61
  })
62
62
  })]
@@ -65,5 +65,7 @@ var Timeline = function Timeline(_ref) {
65
65
 
66
66
  exports.Timeline = Timeline;
67
67
  Timeline.propTypes = {
68
- time: _propTypes["default"].string
68
+ first: _propTypes["default"].bool,
69
+ time: _propTypes["default"].string,
70
+ last: _propTypes["default"].bool
69
71
  };
@@ -92,8 +92,9 @@ var Tooltip = function Tooltip(_ref) {
92
92
 
93
93
  exports.Tooltip = Tooltip;
94
94
  Tooltip.propTypes = {
95
- trigger: _propTypes["default"].string,
96
- width: _propTypes["default"].number,
95
+ children: _propTypes["default"].object,
97
96
  text: _propTypes["default"].string,
98
- children: _propTypes["default"].object
97
+ tooltipProps: _propTypes["default"].object,
98
+ trigger: _propTypes["default"].string,
99
+ width: _propTypes["default"].number
99
100
  };
@@ -86,10 +86,19 @@ var _Spinner = require("./Spinner");
86
86
 
87
87
  exports.Spinner = _Spinner.Spinner;
88
88
 
89
+ var _ResourceList = require("./ResourceList");
90
+
91
+ exports.ResourceList = _ResourceList.ResourceList;
92
+ exports.ResourceItem = _ResourceList.ResourceItem;
93
+
89
94
  var _Tooltip = require("./Tooltip");
90
95
 
91
96
  exports.Tooltip = _Tooltip.Tooltip;
92
97
 
98
+ var _Time = require("./Time");
99
+
100
+ exports.Time = _Time.Time;
101
+
93
102
  var _Timeline = require("./Timeline");
94
103
 
95
104
  exports.Timeline = _Timeline.Timeline;
@@ -60,7 +60,7 @@ var _default = {
60
60
  body: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", sans-serif',
61
61
  heading: 'inherit',
62
62
  monospace: '"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace',
63
- serif: '"Recoleta-Regular", Georgia, serif'
63
+ serif: 'recoletaregular, Georgia, serif'
64
64
  },
65
65
  fontSizes: [10, 12, 14, 19, 32, 40, 56, 64, 96],
66
66
  fontWeights: {
package/package.json CHANGED
@@ -1,21 +1,26 @@
1
1
  {
2
2
  "name": "@automattic/vip-design-system",
3
- "version": "0.8.0",
3
+ "version": "0.9.2",
4
4
  "main": "build/system/index.js",
5
5
  "scripts": {
6
6
  "build-storybook": "build-storybook",
7
7
  "build": "cross-env NODE_ENV=production babel src --out-dir build",
8
- "watch": "npm run build -- --watch",
9
- "storybook": "start-storybook -p 6006"
8
+ "format": "eslint . --fix",
9
+ "jest": "NODE_ENV=test jest --detectOpenHandles",
10
+ "jest:watch": "npm run jest --watch",
11
+ "lint": "eslint . -f json | eslines --quiet",
12
+ "storybook": "start-storybook -p 6006",
13
+ "test": "npm run lint && npm run jest",
14
+ "watch": "npm run build -- --watch"
10
15
  },
11
16
  "dependencies": {
17
+ "@radix-ui/react-checkbox": "^0.1.0",
18
+ "@radix-ui/react-radio-group": "^0.1.0",
19
+ "@radix-ui/react-tooltip": "^0.1.0",
12
20
  "babel-loader": "^8.2.2",
13
21
  "framer-motion": "^3.9.1",
14
22
  "react-icons": "^4.2.0",
15
- "react-select": "^4.3.1",
16
- "@radix-ui/react-checkbox": "^0.1.0",
17
- "@radix-ui/react-radio-group": "^0.1.0",
18
- "@radix-ui/react-tooltip": "^0.1.0"
23
+ "react-select": "^4.3.1"
19
24
  },
20
25
  "peerDependencies": {
21
26
  "react": "*",
@@ -28,9 +33,27 @@
28
33
  "**/react": "17.0.1",
29
34
  "**/react-dom": "17.0.1"
30
35
  },
36
+ "jest": {
37
+ "testURL": "http://localhost",
38
+ "setupFiles": [
39
+ "./test/setupTests.js"
40
+ ],
41
+ "setupFilesAfterEnv": [
42
+ "./test/setupAfterEnv.js"
43
+ ],
44
+ "transformIgnorePatterns": [
45
+ ".*.stories.js$"
46
+ ],
47
+ "transform": {
48
+ "\\.[jt]sx?$": "babel-jest"
49
+ }
50
+ },
31
51
  "devDependencies": {
52
+ "immer": ">=9.0.6",
53
+ "@axe-core/react": "4.3.2",
32
54
  "@babel/cli": "^7.14.3",
33
55
  "@babel/core": "7.14.0",
56
+ "@babel/eslint-parser": "7.15.7",
34
57
  "@babel/plugin-proposal-class-properties": "7.13.0",
35
58
  "@babel/plugin-proposal-class-static-block": "^7.14.5",
36
59
  "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
@@ -44,11 +67,28 @@
44
67
  "@storybook/addon-actions": "5.3.21",
45
68
  "@storybook/addon-links": "5.3.21",
46
69
  "@storybook/addons": "5.3.21",
70
+ "@storybook/node-logger": "^6.4.0",
47
71
  "@storybook/preset-create-react-app": "^3.2.0",
48
72
  "@storybook/react": "5.3.21",
73
+ "@testing-library/dom": "^8.11.1",
74
+ "@testing-library/jest-dom": "^5.15.0",
75
+ "@testing-library/react": "^12.1.2",
76
+ "babel-jest": "^27.3.1",
49
77
  "cross-env": "^7.0.3",
78
+ "eslines": "2.1.0",
79
+ "eslint": "7.32.0",
80
+ "eslint-config-react-app": "6.0.0",
81
+ "eslint-config-wpvip": "automattic/eslint-config-wpvip#c6605d1c3a545d43ac2149cd464ec3c38ebc58d5",
82
+ "eslint-plugin-jest": "24.4.2",
83
+ "eslint-plugin-json": "3.1.0",
84
+ "eslint-plugin-jsx-a11y": "6.4.1",
85
+ "eslint-plugin-no-async-foreach": "0.1.1",
86
+ "eslint-plugin-react": "7.25.3",
87
+ "eslint-plugin-wpcalypso": "4.1.0",
88
+ "jest-axe": "5.0.1",
50
89
  "optimize-css-assets-webpack-plugin": "^6.0.1",
51
90
  "react-input-autosize": "^3.0.0",
91
+ "react-refresh": "^0.9.0",
52
92
  "react-scripts": "^4.0.3"
53
93
  }
54
94
  }
@@ -39,7 +39,7 @@ const Avatar = ( {
39
39
  { src ? (
40
40
  <Image
41
41
  src={ src }
42
- alt={ name }
42
+ alt={ `Avatar image from ${ name }` }
43
43
  sx={ {
44
44
  borderRadius: 9999,
45
45
  width: '100%',
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import React from 'react';
5
-
6
1
  /**
7
2
  * Internal dependencies
8
3
  */
@@ -0,0 +1,31 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render, screen } from '@testing-library/react';
5
+ import { axe } from 'jest-axe';
6
+
7
+ /**
8
+ * Internal dependencies
9
+ */
10
+ import { Avatar } from './Avatar';
11
+
12
+ describe( '<Avatar />', () => {
13
+ it( 'renders the Avatar without an image', () => {
14
+ render( <Avatar name="John Doe" /> );
15
+
16
+ expect( screen.getByText( 'J' ) ).toBeInTheDocument();
17
+ } );
18
+
19
+ it( 'renders the Avatar with image', () => {
20
+ render( <Avatar name="John Doe" src="path/to/image" /> );
21
+
22
+ expect( screen.getByAltText( 'Avatar image from John Doe' ) ).toBeInTheDocument();
23
+ } );
24
+
25
+ it( 'should not have basic accessibility issues', async () => {
26
+ const { container } = render( <Avatar name="John Doe" src="path/to/image" /> );
27
+ const results = await axe( container );
28
+
29
+ expect( results ).toHaveNoViolations();
30
+ } );
31
+ } );
@@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
8
8
  /**
9
9
  * Internal dependencies
10
10
  */
11
- import { Text } from '../';
11
+ import { Text } from '../';
12
12
 
13
13
  const Badge = ( { variant = 'blue', sx, ...props } ) => (
14
14
  <Text
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import React from 'react';
5
-
6
1
  /**
7
2
  * Internal dependencies
8
3
  */
@@ -10,7 +10,7 @@ import PropTypes from 'prop-types';
10
10
  */
11
11
  import { Box, Heading, Text } from '..';
12
12
 
13
- const BlankState = ({ image, icon, title, body, cta }) => {
13
+ const BlankState = ( { image, icon, title, body, cta } ) => {
14
14
  return (
15
15
  <Box sx={{ textAlign: 'center', padding: 5 }}>
16
16
  {icon ? icon : <img src={image} sx={{ mb: 3 }} alt="Icon representing the blank state" />}
@@ -22,7 +22,7 @@ const BlankState = ({ image, icon, title, body, cta }) => {
22
22
  };
23
23
 
24
24
  BlankState.propTypes = {
25
- image: PropTypes.oneOfType([ PropTypes.object, PropTypes.string ]),
25
+ image: PropTypes.oneOfType( [ PropTypes.object, PropTypes.string ] ),
26
26
  icon: PropTypes.node,
27
27
  title: PropTypes.node,
28
28
  body: PropTypes.node,
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import React from 'react';
5
-
6
1
  /**
7
2
  * Internal dependencies
8
3
  */
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import React from 'react';
5
-
6
1
  /**
7
2
  * Internal dependencies
8
3
  */
@@ -6,7 +6,7 @@
6
6
  import { Button as ThemeButton } from 'theme-ui';
7
7
  import PropTypes from 'prop-types';
8
8
 
9
- const Button = ({ sx, ...props }) => (
9
+ const Button = ( { sx, ...props } ) => (
10
10
  <ThemeButton
11
11
  sx={{
12
12
  verticalAlign: 'middle',
@@ -11,22 +11,26 @@ import PropTypes from 'prop-types';
11
11
  */
12
12
  import { Box } from '..';
13
13
 
14
- const Card = React.forwardRef(({ variant = 'primary', sx = {}, ...props }, ref) => (
15
- <Box
16
- ref={ref}
17
- sx={{
18
- // pass variant prop to sx
19
- variant: `cards.${variant}`,
20
- overflow: 'hidden',
21
- ...sx,
22
- }}
23
- {...props}
24
- />
25
- ));
14
+ const Card = React.forwardRef( ( { variant = 'primary', sx = {}, ...props }, ref ) => {
15
+ return (
16
+ <Box
17
+ ref={ref}
18
+ sx={{
19
+ // pass variant prop to sx
20
+ variant: `cards.${ variant }`,
21
+ overflow: 'hidden',
22
+ ...sx,
23
+ }}
24
+ {...props}
25
+ />
26
+ );
27
+ } );
26
28
 
27
29
  Card.propTypes = {
28
30
  variant: PropTypes.string,
29
31
  sx: PropTypes.object,
30
32
  };
31
33
 
34
+ Card.displayName = 'Card';
35
+
32
36
  export { Card };
@@ -1,8 +1,3 @@
1
- /**
2
- * External dependencies
3
- */
4
- import React from 'react';
5
-
6
1
  /**
7
2
  * Internal dependencies
8
3
  */