@pingux/astro 2.32.0-alpha.1 → 2.32.0-alpha.11

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 (143) hide show
  1. package/lib/cjs/components/AccordionGroup/AccordionGroup.stories.js +1 -1
  2. package/lib/cjs/components/Badge/Badge.stories.js +1 -1
  3. package/lib/cjs/components/Badge/Convenience/ConvenienceBadges.stories.js +1 -1
  4. package/lib/cjs/components/Bracket/Bracket.stories.js +1 -1
  5. package/lib/cjs/components/Breadcrumbs/Breadcrumbs.stories.js +1 -1
  6. package/lib/cjs/components/Button/Button.stories.d.ts +1 -1
  7. package/lib/cjs/components/Button/Button.stories.js +1 -1
  8. package/lib/cjs/components/Calendar/Calendar.stories.js +1 -1
  9. package/lib/cjs/components/Calendar/Calendar.test.js +9 -32
  10. package/lib/cjs/components/Callout/Callout.stories.js +1 -1
  11. package/lib/cjs/components/Card/Card.stories.js +1 -1
  12. package/lib/cjs/components/CodeView/CodeView.stories.js +1 -1
  13. package/lib/cjs/components/CollapsiblePanel/CollapsiblePanel.stories.js +1 -1
  14. package/lib/cjs/components/CopyText/CopyText.stories.js +1 -1
  15. package/lib/cjs/components/HelpHint/HelpHint.stories.js +1 -1
  16. package/lib/cjs/components/Icon/Icon.stories.js +1 -1
  17. package/lib/cjs/components/IconBadge/IconBadge.stories.js +1 -1
  18. package/lib/cjs/components/IconButton/IconButton.stories.js +1 -1
  19. package/lib/cjs/components/ImageUploadField/ImageUploadField.test.js +47 -14
  20. package/lib/cjs/components/Label/Label.test.js +10 -7
  21. package/lib/cjs/components/Link/Link.stories.js +1 -1
  22. package/lib/cjs/components/Loader/Loader.stories.js +1 -1
  23. package/lib/cjs/components/Menu/Menu.stories.js +1 -1
  24. package/lib/cjs/components/Messages/Messages.js +42 -9
  25. package/lib/cjs/components/Messages/Messages.stories.js +1 -1
  26. package/lib/cjs/components/Messages/Messages.test.js +7 -4
  27. package/lib/cjs/components/Modal/Modal.stories.js +1 -1
  28. package/lib/cjs/components/NavBar/NavBar.stories.js +1 -1
  29. package/lib/cjs/components/OverlayPanel/OverlayPanel.stories.js +3 -17
  30. package/lib/cjs/components/PanelHeader/PanelHeader.stories.js +1 -1
  31. package/lib/cjs/components/PanelHeader/PanelHeader.test.js +7 -3
  32. package/lib/cjs/components/PopoverMenu/PopoverMenu.stories.js +1 -1
  33. package/lib/cjs/components/RequirementsList/RequirementsList.stories.js +1 -1
  34. package/lib/cjs/components/ScrollBox/ScrollBox.stories.js +1 -1
  35. package/lib/cjs/components/Separator/Separator.stories.js +1 -1
  36. package/lib/cjs/components/Stepper/Stepper.stories.js +1 -1
  37. package/lib/cjs/components/TreeView/TreeView.js +99 -11
  38. package/lib/cjs/components/TreeView/TreeView.stories.js +23 -10
  39. package/lib/cjs/components/TreeView/TreeView.styles.js +22 -2
  40. package/lib/cjs/components/TreeView/TreeView.test.js +91 -11
  41. package/lib/cjs/components/TreeView/TreeViewItem.js +112 -14
  42. package/lib/cjs/components/TreeView/TreeViewKeyboardDelegate.js +200 -0
  43. package/lib/cjs/components/TreeView/TreeViewKeyboardDelegate.test.js +511 -0
  44. package/lib/cjs/components/TreeView/TreeViewRow.js +20 -5
  45. package/lib/cjs/components/TreeView/TreeViewSection.js +164 -16
  46. package/lib/cjs/components/TreeView/TreeViewWrapper.js +40 -0
  47. package/lib/cjs/hooks/useComponentToggle/index.d.ts +1 -0
  48. package/lib/cjs/hooks/useComponentToggle/useComponentToggle.d.ts +32 -0
  49. package/lib/cjs/hooks/useComponentToggle/useComponentToggle.js +4 -20
  50. package/lib/cjs/hooks/useComponentToggle/useComponentToggle.test.d.ts +1 -0
  51. package/lib/cjs/hooks/useComponentToggle/useComponentToggle.test.js +8 -9
  52. package/lib/cjs/hooks/useFallbackImage/index.d.ts +1 -0
  53. package/lib/cjs/hooks/useFallbackImage/useFallbackImage.d.ts +10 -0
  54. package/lib/cjs/hooks/useFallbackImage/useFallbackImage.js +1 -2
  55. package/lib/cjs/hooks/useFallbackImage/useFallbackImage.test.d.ts +1 -0
  56. package/lib/cjs/hooks/useFallbackImage/useFallbackImage.test.js +9 -9
  57. package/lib/cjs/hooks/useImageUploadState/index.d.ts +1 -0
  58. package/lib/cjs/hooks/useImageUploadState/useImageUploadState.d.ts +28 -0
  59. package/lib/cjs/hooks/useImageUploadState/useImageUploadState.js +9 -6
  60. package/lib/cjs/hooks/useModalState/index.d.ts +1 -0
  61. package/lib/cjs/hooks/useModalState/useModalState.d.ts +21 -0
  62. package/lib/cjs/hooks/useModalState/useModalState.js +0 -9
  63. package/lib/cjs/hooks/useModalState/useModalState.test.d.ts +1 -0
  64. package/lib/cjs/recipes/AttributeMapping.stories.js +1 -1
  65. package/lib/cjs/recipes/ConditionFilter.stories.js +1 -1
  66. package/lib/cjs/recipes/MaskedValue.stories.js +1 -1
  67. package/lib/cjs/recipes/MultipagePopup.stories.js +1 -1
  68. package/lib/cjs/recipes/OneWayToBidirectionalArrow.stories.js +1 -1
  69. package/lib/cjs/recipes/PanelContent.stories.js +1 -1
  70. package/lib/cjs/recipes/Slider.stories.js +1 -1
  71. package/lib/cjs/recipes/TrialExperienceIndustryButtons.stories.js +1 -1
  72. package/lib/cjs/recipes/TrialExperienceStatusBar.stories.js +1 -1
  73. package/lib/cjs/utils/designUtils/figmaLinks.d.ts +7 -0
  74. package/lib/cjs/utils/testUtils/setupTests.d.ts +4 -0
  75. package/lib/cjs/utils/testUtils/testAxe.d.ts +2 -0
  76. package/lib/cjs/utils/testUtils/testTheme.d.ts +21 -0
  77. package/lib/cjs/utils/testUtils/testWrapper.d.ts +5 -0
  78. package/lib/cjs/utils/testUtils/testWrapper.js +3 -2
  79. package/lib/cjs/utils/testUtils/universalComponentTest.d.ts +5 -0
  80. package/lib/cjs/utils/testUtils/universalComponentTest.js +86 -0
  81. package/lib/components/AccordionGroup/AccordionGroup.stories.js +1 -1
  82. package/lib/components/Badge/Badge.stories.js +1 -1
  83. package/lib/components/Badge/Convenience/ConvenienceBadges.stories.js +1 -1
  84. package/lib/components/Bracket/Bracket.stories.js +1 -1
  85. package/lib/components/Breadcrumbs/Breadcrumbs.stories.js +1 -1
  86. package/lib/components/Button/Button.stories.js +1 -1
  87. package/lib/components/Calendar/Calendar.stories.js +1 -1
  88. package/lib/components/Calendar/Calendar.test.js +9 -32
  89. package/lib/components/Callout/Callout.stories.js +1 -1
  90. package/lib/components/Card/Card.stories.js +1 -1
  91. package/lib/components/CodeView/CodeView.stories.js +1 -1
  92. package/lib/components/CollapsiblePanel/CollapsiblePanel.stories.js +1 -1
  93. package/lib/components/CopyText/CopyText.stories.js +1 -1
  94. package/lib/components/HelpHint/HelpHint.stories.js +1 -1
  95. package/lib/components/Icon/Icon.stories.js +1 -1
  96. package/lib/components/IconBadge/IconBadge.stories.js +1 -1
  97. package/lib/components/IconButton/IconButton.stories.js +1 -1
  98. package/lib/components/ImageUploadField/ImageUploadField.test.js +47 -14
  99. package/lib/components/Label/Label.test.js +8 -5
  100. package/lib/components/Link/Link.stories.js +1 -1
  101. package/lib/components/Loader/Loader.stories.js +1 -1
  102. package/lib/components/Menu/Menu.stories.js +1 -1
  103. package/lib/components/Messages/Messages.js +47 -15
  104. package/lib/components/Messages/Messages.stories.js +1 -1
  105. package/lib/components/Messages/Messages.test.js +7 -4
  106. package/lib/components/Modal/Modal.stories.js +1 -1
  107. package/lib/components/NavBar/NavBar.stories.js +1 -1
  108. package/lib/components/OverlayPanel/OverlayPanel.stories.js +4 -18
  109. package/lib/components/PanelHeader/PanelHeader.stories.js +1 -1
  110. package/lib/components/PanelHeader/PanelHeader.test.js +7 -3
  111. package/lib/components/PopoverMenu/PopoverMenu.stories.js +1 -1
  112. package/lib/components/RequirementsList/RequirementsList.stories.js +1 -1
  113. package/lib/components/ScrollBox/ScrollBox.stories.js +1 -1
  114. package/lib/components/Separator/Separator.stories.js +1 -1
  115. package/lib/components/Stepper/Stepper.stories.js +1 -1
  116. package/lib/components/TreeView/TreeView.js +100 -12
  117. package/lib/components/TreeView/TreeView.stories.js +23 -10
  118. package/lib/components/TreeView/TreeView.styles.js +22 -2
  119. package/lib/components/TreeView/TreeView.test.js +92 -12
  120. package/lib/components/TreeView/TreeViewItem.js +111 -14
  121. package/lib/components/TreeView/TreeViewKeyboardDelegate.js +176 -0
  122. package/lib/components/TreeView/TreeViewKeyboardDelegate.test.js +496 -0
  123. package/lib/components/TreeView/TreeViewRow.js +20 -5
  124. package/lib/components/TreeView/TreeViewSection.js +161 -16
  125. package/lib/components/TreeView/TreeViewWrapper.js +31 -0
  126. package/lib/hooks/useComponentToggle/useComponentToggle.js +4 -21
  127. package/lib/hooks/useComponentToggle/useComponentToggle.test.js +8 -9
  128. package/lib/hooks/useFallbackImage/useFallbackImage.js +1 -2
  129. package/lib/hooks/useFallbackImage/useFallbackImage.test.js +6 -6
  130. package/lib/hooks/useImageUploadState/useImageUploadState.js +9 -6
  131. package/lib/hooks/useModalState/useModalState.js +0 -10
  132. package/lib/recipes/AttributeMapping.stories.js +1 -1
  133. package/lib/recipes/ConditionFilter.stories.js +1 -1
  134. package/lib/recipes/MaskedValue.stories.js +1 -1
  135. package/lib/recipes/MultipagePopup.stories.js +1 -1
  136. package/lib/recipes/OneWayToBidirectionalArrow.stories.js +1 -1
  137. package/lib/recipes/PanelContent.stories.js +1 -1
  138. package/lib/recipes/Slider.stories.js +1 -1
  139. package/lib/recipes/TrialExperienceIndustryButtons.stories.js +1 -1
  140. package/lib/recipes/TrialExperienceStatusBar.stories.js +1 -1
  141. package/lib/utils/testUtils/testWrapper.js +3 -2
  142. package/lib/utils/testUtils/universalComponentTest.js +74 -0
  143. package/package.json +5 -1
@@ -8,13 +8,14 @@ import _Object$defineProperties from "@babel/runtime-corejs3/core-js-stable/obje
8
8
  import _Object$defineProperty from "@babel/runtime-corejs3/core-js-stable/object/define-property";
9
9
  import _extends from "@babel/runtime-corejs3/helpers/esm/extends";
10
10
  import _defineProperty from "@babel/runtime-corejs3/helpers/esm/defineProperty";
11
+ import _slicedToArray from "@babel/runtime-corejs3/helpers/esm/slicedToArray";
11
12
  import _objectWithoutProperties from "@babel/runtime-corejs3/helpers/esm/objectWithoutProperties";
12
- var _excluded = ["tree", "disabledKeys", "onExpandedChange"];
13
+ var _excluded = ["tree", "disabledKeys", "onExpandedChange", "onKeyDown", "pageLength"];
13
14
  import _mapInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/map";
14
15
  import _Array$from from "@babel/runtime-corejs3/core-js-stable/array/from";
15
16
  function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
16
17
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context2, _context3; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context2 = ownKeys(Object(source), !0)).call(_context2, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context3 = ownKeys(Object(source))).call(_context3, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; }
17
- import React, { forwardRef, useImperativeHandle, useMemo, useRef } from 'react';
18
+ import React, { forwardRef, useImperativeHandle, useMemo, useRef, useState } from 'react';
18
19
  import { useTreeState } from 'react-stately';
19
20
  import { useCollator } from '@react-aria/i18n';
20
21
  import { useListBox } from '@react-aria/listbox';
@@ -23,6 +24,7 @@ import PropTypes from 'prop-types';
23
24
  import { TreeViewContext } from '../../context/TreeViewContext';
24
25
  import { Box, TreeViewItem, TreeViewSection } from '../../index';
25
26
  import { isIterableProp } from '../../utils/devUtils/props/isIterable';
27
+ import TreeViewWrapper from './TreeViewWrapper';
26
28
 
27
29
  // split out and exported for ease of use across components
28
30
  // and to facilitate easier testing (eliminates redundant conditional renders)
@@ -46,11 +48,23 @@ export function useTreeViewLayout(state) {
46
48
  return layout;
47
49
  }
48
50
  var TreeView = /*#__PURE__*/forwardRef(function (props, ref) {
49
- var _context;
51
+ var _tree$items$, _context;
50
52
  var tree = props.tree,
51
53
  disabledKeys = props.disabledKeys,
52
54
  onExpandedChange = props.onExpandedChange,
55
+ onKeyDown = props.onKeyDown,
56
+ _props$pageLength = props.pageLength,
57
+ pageLength = _props$pageLength === void 0 ? 5 : _props$pageLength,
53
58
  others = _objectWithoutProperties(props, _excluded);
59
+
60
+ // we are tracking the last focused item.
61
+ // this enables us to have focus jump back to the item, after focus
62
+ // leaves the tree, and then returns.
63
+ var _useState = useState(tree === null || tree === void 0 || (_tree$items$ = tree.items[0]) === null || _tree$items$ === void 0 ? void 0 : _tree$items$.key),
64
+ _useState2 = _slicedToArray(_useState, 2),
65
+ lastFocusedItem = _useState2[0],
66
+ setLastFocusedItem = _useState2[1];
67
+ var level = 0;
54
68
  var treeViewRef = useRef();
55
69
  var selectedKeys = tree.selectedKeys;
56
70
 
@@ -65,7 +79,66 @@ var TreeView = /*#__PURE__*/forwardRef(function (props, ref) {
65
79
  selectionMode: 'single',
66
80
  disallowEmptySelection: true
67
81
  }, others));
68
- var level = 0;
82
+ var flattenNestedData = function flattenNestedData(_data) {
83
+ var returnArray = [];
84
+ var checkItemNesting = function checkItemNesting(item) {
85
+ var _item$value, _item$items;
86
+ if (((_item$value = item.value) === null || _item$value === void 0 || (_item$value = _item$value.items) === null || _item$value === void 0 ? void 0 : _item$value.length) > 0) {
87
+ return {
88
+ isTopLevel: true,
89
+ hasChildren: true
90
+ };
91
+ }
92
+ if (((_item$items = item.items) === null || _item$items === void 0 ? void 0 : _item$items.length) > 0) {
93
+ return {
94
+ isTopLevel: false,
95
+ hasChildren: true
96
+ };
97
+ }
98
+ return {
99
+ isTopLevel: false,
100
+ hasChildren: false
101
+ };
102
+ };
103
+ var checkSection = function checkSection(isRendered, hasItems) {
104
+ return isRendered && hasItems;
105
+ };
106
+ var loop = function loop(data) {
107
+ for (var i = 0; i < data.length; i += 1) {
108
+ var obj = {
109
+ key: data[i].key
110
+ };
111
+ returnArray.push(obj);
112
+ var _checkItemNesting = checkItemNesting(data[i]),
113
+ hasChildren = _checkItemNesting.hasChildren,
114
+ isTopLevel = _checkItemNesting.isTopLevel;
115
+ if (checkSection(state.expandedKeys.has(data[i].key), hasChildren) === true) {
116
+ if (isTopLevel) {
117
+ var _data$i$value;
118
+ loop((_data$i$value = data[i].value) === null || _data$i$value === void 0 ? void 0 : _data$i$value.items);
119
+ } else {
120
+ loop(data[i].items);
121
+ }
122
+ }
123
+ }
124
+ };
125
+ loop(_data);
126
+ return returnArray;
127
+ };
128
+
129
+ // list of value pairs of keys and refs
130
+ // does not need to be in order, because they are values pairs
131
+ var _useState3 = useState([]),
132
+ _useState4 = _slicedToArray(_useState3, 2),
133
+ refArray = _useState4[0],
134
+ setRefs = _useState4[1];
135
+
136
+ // creates a flattened list of keys for up/down keyboard use
137
+ // this DOES need to be in the same order as the HTML appears in the DOM.
138
+ // we are essentially turning all rendered items into a flat list, for up/down
139
+ var flatKeyArray = useMemo(function () {
140
+ return flattenNestedData(props.items);
141
+ }, [state.expandedKeys]);
69
142
  var ariaLabel = props['aria-label'];
70
143
  var listBoxOptions = {
71
144
  disabledKeys: disabledKeys,
@@ -79,7 +152,13 @@ var TreeView = /*#__PURE__*/forwardRef(function (props, ref) {
79
152
  return ___EmotionJSX(TreeViewContext.Provider, {
80
153
  value: {
81
154
  state: state,
82
- tree: tree
155
+ tree: tree,
156
+ refArray: refArray,
157
+ setRefs: setRefs,
158
+ flatKeyArray: flatKeyArray,
159
+ pageLength: pageLength,
160
+ setLastFocusedItem: setLastFocusedItem,
161
+ lastFocusedItem: lastFocusedItem
83
162
  }
84
163
  }, ___EmotionJSX(Box, _extends({
85
164
  as: "ul"
@@ -88,14 +167,17 @@ var TreeView = /*#__PURE__*/forwardRef(function (props, ref) {
88
167
  "aria-label": ariaLabel,
89
168
  role: "treegrid",
90
169
  sx: {
91
- overflow: 'hidden'
170
+ overflow: 'hidden',
171
+ p: '5px',
172
+ border: 'none !important'
92
173
  }
93
- }, others), _mapInstanceProperty(_context = _Array$from(state.collection)).call(_context, function (item, index) {
174
+ }, others), ___EmotionJSX(TreeViewWrapper, null, _mapInstanceProperty(_context = _Array$from(state.collection)).call(_context, function (item, index) {
94
175
  return SectionOrItemRender(item.props.items.length > 0, ___EmotionJSX(TreeViewSection, {
95
176
  item: item,
96
177
  items: item.props.items,
97
178
  title: item.props.title,
98
179
  key: item.props.title,
180
+ onKeyDown: onKeyDown,
99
181
  level: level + 1,
100
182
  setSize: state.collection.size,
101
183
  position: index
@@ -103,17 +185,19 @@ var TreeView = /*#__PURE__*/forwardRef(function (props, ref) {
103
185
  item: item,
104
186
  title: item.value.value.title,
105
187
  key: item.value.value.title,
188
+ onKeyDown: onKeyDown,
106
189
  level: level + 1,
107
- position: index,
108
- setSize: state.collection.size
190
+ setSize: state.collection.size,
191
+ position: index
109
192
  }));
110
- })));
193
+ }))));
111
194
  });
112
195
  TreeView.propTypes = {
113
196
  /** data object prop that is required to make the tree function
114
197
  this is returned from the useTreeData hook in React-Aria */
115
198
  tree: PropTypes.shape({
116
- selectedKeys: isIterableProp
199
+ selectedKeys: isIterableProp,
200
+ items: isIterableProp
117
201
  }).isRequired,
118
202
  /** The currently disabled keys in the collection. */
119
203
  disabledKeys: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object])),
@@ -122,6 +206,10 @@ TreeView.propTypes = {
122
206
  /** The list of TreeView items. */
123
207
  items: isIterableProp,
124
208
  /** String that describes the treeview when using a screen reader. */
125
- 'aria-label': PropTypes.string
209
+ 'aria-label': PropTypes.string,
210
+ /** Handler that is called when a key is pressed. */
211
+ onKeyDown: PropTypes.func,
212
+ /** Number of items to move the focus when page up or page down is pressed */
213
+ pageLength: PropTypes.number
126
214
  };
127
215
  export default TreeView;
@@ -20,36 +20,50 @@ export default {
20
20
  };
21
21
  var data = [{
22
22
  title: 'Policies',
23
+ key: 'Policies',
23
24
  items: [{
24
25
  title: 'Registration',
26
+ key: 'Registration',
25
27
  items: [{
26
- title: 'Registration A'
28
+ title: 'Registration A',
29
+ key: 'Registration A'
27
30
  }, {
28
31
  title: 'Registration B',
32
+ key: 'Registration B',
29
33
  items: [{
30
- title: 'Registration B1'
34
+ title: 'Registration B1',
35
+ key: 'Registration B1'
31
36
  }, {
32
- title: 'Registration B2'
37
+ title: 'Registration B2',
38
+ key: 'Registration B2'
33
39
  }]
34
40
  }, {
35
- title: 'Registration C'
41
+ title: 'Registration C',
42
+ key: 'Registration C'
36
43
  }, {
37
- title: 'Registration D'
44
+ title: 'Registration D',
45
+ key: 'Registration D'
38
46
  }]
39
47
  }, {
40
48
  title: 'Authentication',
49
+ key: 'Authentication',
41
50
  items: [{
42
- title: 'Authentication A'
51
+ title: 'Authentication A',
52
+ key: 'Authentication A'
43
53
  }, {
44
- title: 'Authentication B'
54
+ title: 'Authentication B',
55
+ key: 'Authentication B'
45
56
  }]
46
57
  }]
47
58
  }, {
48
59
  title: 'Other',
60
+ key: 'Other',
49
61
  items: [{
50
- title: 'Other A'
62
+ title: 'Other A',
63
+ key: 'Other A'
51
64
  }]
52
65
  }, {
66
+ key: 'Single Item',
53
67
  title: 'Single Item'
54
68
  }];
55
69
  export var Default = function Default(args) {
@@ -65,8 +79,7 @@ export var Default = function Default(args) {
65
79
  return ___EmotionJSX(TreeView, _extends({}, args, {
66
80
  items: tree.items,
67
81
  tree: tree,
68
- "aria-label": "Example Tree",
69
- disabledKeys: ['Single Item']
82
+ "aria-label": "Example Tree"
70
83
  }), function (section) {
71
84
  var _section$value;
72
85
  return ___EmotionJSX(Item, {
@@ -3,7 +3,7 @@ var treeRow = {
3
3
  cursor: 'pointer',
4
4
  height: '31px',
5
5
  outline: 'none',
6
- '&.is-selected, &.is-hovered, &.is-focused': {
6
+ '&.is-selected, &.is-hovered': {
7
7
  backgroundColor: 'active',
8
8
  '& span': {
9
9
  color: 'white'
@@ -17,8 +17,28 @@ var treeRow = {
17
17
  },
18
18
  '&.is-expanded': {
19
19
  marginBottom: 'xs'
20
+ },
21
+ '& :focus': {
22
+ border: 'none'
20
23
  }
21
24
  };
25
+ var wrapper = {
26
+ '&.is-focused': {
27
+ boxSizing: 'unset',
28
+ outline: '1px solid',
29
+ outlineColor: 'focus',
30
+ outlineOffset: '2px'
31
+ },
32
+ width: '100%',
33
+ ':not(:last-child)': {
34
+ mb: 'sm'
35
+ },
36
+ ':focus': {
37
+ border: 'none'
38
+ },
39
+ outline: 'none'
40
+ };
22
41
  export default {
23
- treeRow: treeRow
42
+ treeRow: treeRow,
43
+ wrapper: wrapper
24
44
  };
@@ -1,9 +1,13 @@
1
1
  import _extends from "@babel/runtime-corejs3/helpers/esm/extends";
2
2
  import React from 'react';
3
3
  import { useTreeData } from 'react-stately';
4
+ import userEvent from '@testing-library/user-event';
5
+ import PropTypes from 'prop-types';
4
6
  import { Item } from '../../index';
5
- import { fireEvent, render, screen } from '../../utils/testUtils/testWrapper';
7
+ import { render, screen } from '../../utils/testUtils/testWrapper';
6
8
  import { SectionOrItemRender } from './TreeView';
9
+ import { refArray } from './TreeViewKeyboardDelegate.test';
10
+ import { addRefToArrayHelper, removeRefFromArrayHelper } from './TreeViewSection';
7
11
  import TreeView from '.';
8
12
  import { jsx as ___EmotionJSX } from "@emotion/react";
9
13
  var testId = 'test-TreeView';
@@ -40,9 +44,12 @@ var data = [{
40
44
  }, {
41
45
  title: 'Single Item'
42
46
  }];
47
+ var singleData = [{
48
+ title: 'Single Item'
49
+ }];
43
50
  var TreeViewComponent = function TreeViewComponent(props) {
44
51
  var tree = useTreeData({
45
- initialItems: data,
52
+ initialItems: props.data,
46
53
  getKey: function getKey(item) {
47
54
  return item.title;
48
55
  },
@@ -62,6 +69,9 @@ var TreeViewComponent = function TreeViewComponent(props) {
62
69
  });
63
70
  });
64
71
  };
72
+ TreeViewComponent.propTypes = {
73
+ data: PropTypes.arrayOf(PropTypes.shape({}))
74
+ };
65
75
  var offsetWidth;
66
76
  var offsetHeight;
67
77
  var scrollHeight;
@@ -95,16 +105,20 @@ test('TreeView component does load', function () {
95
105
  expect(element).toBeInTheDocument();
96
106
  });
97
107
  test('Can select an Item using the mouse', function () {
98
- render(___EmotionJSX(TreeViewComponent, null));
108
+ render(___EmotionJSX(TreeViewComponent, {
109
+ data: data
110
+ }));
99
111
  var element = screen.queryByRole('treegrid');
100
112
  expect(element).toBeInTheDocument();
101
113
  var peopleElement = screen.queryByText('Single Item');
102
114
  expect(peopleElement).not.toHaveClass('is-selected');
103
- fireEvent.click(peopleElement);
115
+ userEvent.click(peopleElement);
104
116
  expect(peopleElement).toHaveClass('is-selected');
105
117
  });
106
118
  test('Renders both Sections and Items', function () {
107
- render(___EmotionJSX(TreeViewComponent, null));
119
+ render(___EmotionJSX(TreeViewComponent, {
120
+ data: data
121
+ }));
108
122
  var peopleElement = screen.getByText('Single Item');
109
123
  expect(peopleElement).toBeInTheDocument();
110
124
  var plantElement = screen.getByText('Other');
@@ -113,7 +127,9 @@ test('Renders both Sections and Items', function () {
113
127
  expect(allListItems).toHaveLength(3);
114
128
  });
115
129
  test('Can expand an Item using the mouse', function () {
116
- render(___EmotionJSX(TreeViewComponent, null));
130
+ render(___EmotionJSX(TreeViewComponent, {
131
+ data: data
132
+ }));
117
133
 
118
134
  // The children of collapsed sections will not
119
135
  // be rendered by default.
@@ -122,47 +138,91 @@ test('Can expand an Item using the mouse', function () {
122
138
  // Clicking the dropdown icon, renders the children
123
139
  // of the collapsed section.
124
140
  var buttons = screen.queryAllByRole('button');
125
- fireEvent.click(buttons[0]);
141
+ userEvent.click(buttons[0]);
126
142
  expect(screen.queryByText(data[0].items[0].title)).toBeInTheDocument();
127
143
  });
128
144
  test('onExpandedChange change prop calls when used', function () {
129
145
  var onPress = jest.fn();
130
146
  render(___EmotionJSX(TreeViewComponent, {
147
+ data: data,
131
148
  onExpandedChange: onPress
132
149
  }));
133
150
  expect(onPress).not.toHaveBeenCalled();
134
151
  var buttons = screen.queryAllByRole('button');
135
- fireEvent.click(buttons[0]);
152
+ userEvent.click(buttons[0]);
136
153
  expect(onPress).toHaveBeenCalled();
137
154
  });
138
155
  test('disabledKeys prop disables items in the tree -- rendering them unclickable', function () {
139
156
  render(___EmotionJSX(TreeViewComponent, {
157
+ data: data,
140
158
  disabledKeys: ['Single Item']
141
159
  }));
142
160
  var listItems = screen.queryAllByRole('treeitem');
143
161
  var thisItem = listItems[2];
144
162
  expect(thisItem).not.toHaveClass('is-selected');
145
163
  expect(thisItem).toHaveAttribute('aria-disabled', 'true');
146
- fireEvent.mouseDown(thisItem);
147
- fireEvent.mouseUp(thisItem);
164
+ userEvent.click(thisItem);
148
165
  expect(thisItem).not.toHaveClass('is-selected');
149
166
  expect(thisItem).toHaveAttribute('aria-selected', 'false');
150
167
  });
151
168
  test('displays correct aria attributes', function () {
152
- render(___EmotionJSX(TreeViewComponent, null));
169
+ render(___EmotionJSX(TreeViewComponent, {
170
+ data: data
171
+ }));
153
172
  var listItems = screen.getAllByRole('treeitem');
154
173
  var lastTreeItem = listItems[2];
155
174
  expect(lastTreeItem).toHaveAttribute('aria-level', '1');
156
175
  expect(lastTreeItem).toHaveAttribute('aria-posinset', '3');
157
176
  expect(lastTreeItem).toHaveAttribute('aria-setsize', '3');
158
177
  var buttons = screen.queryAllByRole('button');
159
- fireEvent.click(buttons[1]);
178
+ userEvent.click(buttons[1]);
160
179
  var expandedItems = screen.getAllByRole('treeitem');
161
180
  var nestedItem = expandedItems[2];
162
181
  expect(nestedItem).toHaveAttribute('aria-level', '2');
163
182
  expect(nestedItem).toHaveAttribute('aria-posinset', '1');
164
183
  expect(nestedItem).toHaveAttribute('aria-setsize', '1');
165
184
  });
185
+ test('onKeyDown calls passed in prop call back function', function () {
186
+ var callback = jest.fn();
187
+ render(___EmotionJSX(TreeViewComponent, {
188
+ data: data,
189
+ onKeyDown: callback
190
+ }));
191
+ var listItems = screen.queryAllByRole('treeitem');
192
+ var thisItem = listItems[0];
193
+ userEvent.type(thisItem, '{arrowleft}');
194
+ expect(callback).toHaveBeenCalled();
195
+ });
196
+ test('onKeyDown calls passed in prop call back function', function () {
197
+ var callback = jest.fn();
198
+ render(___EmotionJSX(TreeViewComponent, {
199
+ data: data,
200
+ onKeyDown: callback
201
+ }));
202
+ var listItems = screen.queryAllByRole('treeitem');
203
+ var thisItem = listItems[2];
204
+ userEvent.type(thisItem, '{arrowleft}');
205
+ expect(callback).toHaveBeenCalled();
206
+ });
207
+ test('onKeyDown does not call passed in prop call back function', function () {
208
+ var callback = jest.fn();
209
+ render(___EmotionJSX(TreeViewComponent, {
210
+ data: data
211
+ }));
212
+ var listItems = screen.queryAllByRole('treeitem');
213
+ var thisItem = listItems[2];
214
+ userEvent.type(thisItem, '{arrowleft}');
215
+ expect(callback).not.toHaveBeenCalled();
216
+ });
217
+ test('items still render if there is only one provided', function () {
218
+ var callback = jest.fn();
219
+ render(___EmotionJSX(TreeViewComponent, {
220
+ data: singleData,
221
+ onKeyDown: callback
222
+ }));
223
+ var listItem = screen.queryByText('Single Item');
224
+ expect(listItem).toBeInTheDocument();
225
+ });
166
226
  var firstJSX = ___EmotionJSX("p", null, "first");
167
227
  var secondJSX = ___EmotionJSX("p", null, "second");
168
228
  test('Section or Item Render renders first item if condition is true', function () {
@@ -176,4 +236,24 @@ test('Section or Item Render renders second item if condition is false', functio
176
236
  var thisItem = screen.getByText('second');
177
237
  expect(thisItem).toBeInTheDocument();
178
238
  expect(screen.queryByText('first')).not.toBeInTheDocument();
239
+ });
240
+ test('Handler function removes ref from array', function () {
241
+ var newArray = removeRefFromArrayHelper(refArray, 'test');
242
+ expect(newArray).toHaveLength(2);
243
+ });
244
+ test('Handler function does not remove ref from array', function () {
245
+ var newArray = removeRefFromArrayHelper(refArray, 'anothertest');
246
+ expect(newArray).toHaveLength(3);
247
+ });
248
+ test('Handler function does add ref to array', function () {
249
+ var newArray = addRefToArrayHelper(refArray, 'yetanothertest', {
250
+ current: 'currentlystilltesting'
251
+ });
252
+ expect(newArray).toHaveLength(4);
253
+ });
254
+ test('Handler function does not add ref to array', function () {
255
+ var newArray = addRefToArrayHelper(refArray, 'test', {
256
+ current: 'currentlystilltesting'
257
+ });
258
+ expect(newArray).toHaveLength(3);
179
259
  });
@@ -1,15 +1,61 @@
1
1
  import _extends from "@babel/runtime-corejs3/helpers/esm/extends";
2
- import React, { forwardRef, useImperativeHandle, useRef } from 'react';
2
+ import React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
3
3
  import FileIcon from '@pingux/mdi-react/FileIcon';
4
+ import { useFocusRing } from '@react-aria/focus';
4
5
  import { useOption } from '@react-aria/listbox';
6
+ import { mergeProps } from '@react-aria/utils';
5
7
  import PropTypes from 'prop-types';
6
8
  import { useTreeViewContext } from '../../context/TreeViewContext';
9
+ import { useStatusClasses } from '../../hooks';
7
10
  import { Box } from '../../index';
11
+ import { itemPressHandlers } from './TreeViewKeyboardDelegate';
8
12
  import TreeViewRow from './TreeViewRow';
13
+ import { addRefToArrayHelper, removeRefFromArrayHelper } from './TreeViewSection';
9
14
  import { jsx as ___EmotionJSX } from "@emotion/react";
15
+ export var onKeyDownItem = function onKeyDownItem(e, state, key, tree, isSelected, isExpanded, focusManager, flatKeyArray, refArray, pageLength) {
16
+ switch (e.which) {
17
+ case 32:
18
+ itemPressHandlers.onSpacePress(e, tree, key, isSelected);
19
+ break;
20
+ case 38:
21
+ itemPressHandlers.onUpPress(e, key, refArray, flatKeyArray);
22
+ e.preventDefault();
23
+ e.stopPropagation();
24
+ break;
25
+ case 40:
26
+ itemPressHandlers.onDownPress(e, key, refArray, flatKeyArray);
27
+ e.preventDefault();
28
+ e.stopPropagation();
29
+ break;
30
+ case 37:
31
+ case 39:
32
+ itemPressHandlers.onRightLeftItemPress(e);
33
+ break;
34
+ case 33:
35
+ itemPressHandlers.onPageUpPress(e, key, flatKeyArray, refArray, pageLength);
36
+ break;
37
+ case 34:
38
+ itemPressHandlers.onPageDownPress(e, key, flatKeyArray, refArray, pageLength);
39
+ break;
40
+ case 36:
41
+ itemPressHandlers.onHomePress(key, flatKeyArray, refArray);
42
+ e.preventDefault();
43
+ e.stopPropagation();
44
+ break;
45
+ case 35:
46
+ itemPressHandlers.onEndPress(key, flatKeyArray, refArray);
47
+ e.preventDefault();
48
+ e.stopPropagation();
49
+ break;
50
+ default:
51
+ break;
52
+ }
53
+ };
10
54
  var TreeViewItem = /*#__PURE__*/forwardRef(function (props, ref) {
11
55
  var item = props.item,
12
56
  title = props.title,
57
+ focusManager = props.focusManager,
58
+ onKeyDown = props.onKeyDown,
13
59
  level = props.level,
14
60
  position = props.position,
15
61
  setSize = props.setSize;
@@ -19,8 +65,16 @@ var TreeViewItem = /*#__PURE__*/forwardRef(function (props, ref) {
19
65
  useImperativeHandle(ref, function () {
20
66
  return treeItemRef.current;
21
67
  });
68
+
69
+ /* istanbul ignore next */
22
70
  var _useTreeViewContext = useTreeViewContext(),
23
- state = _useTreeViewContext.state;
71
+ state = _useTreeViewContext.state,
72
+ tree = _useTreeViewContext.tree,
73
+ refArray = _useTreeViewContext.refArray,
74
+ setRefs = _useTreeViewContext.setRefs,
75
+ flatKeyArray = _useTreeViewContext.flatKeyArray,
76
+ pageLength = _useTreeViewContext.pageLength,
77
+ setLastFocusedItem = _useTreeViewContext.setLastFocusedItem;
24
78
  var _useOption = useOption({
25
79
  key: key
26
80
  }, state, treeItemRef),
@@ -28,24 +82,65 @@ var TreeViewItem = /*#__PURE__*/forwardRef(function (props, ref) {
28
82
  isSelected = _useOption.isSelected,
29
83
  isDisabled = _useOption.isDisabled;
30
84
  var isExpanded = state.expandedKeys.has(key);
85
+ var onKeyDownFunction = function onKeyDownFunction(e) {
86
+ /* istanbul ignore next */
87
+ onKeyDownItem(e, state, key, tree, isSelected, isExpanded, focusManager, flatKeyArray, refArray, pageLength);
88
+ if (onKeyDown) {
89
+ onKeyDown(e, key);
90
+ }
91
+ };
92
+
93
+ // ignoring from tests, but this is actually being unit tested
94
+ /* istanbul ignore next */
95
+ var removeRefFromArray = function removeRefFromArray() {
96
+ setRefs(function (prev) {
97
+ return removeRefFromArrayHelper(prev, key);
98
+ });
99
+ };
100
+ var addRefToArray = function addRefToArray() {
101
+ setRefs(function (prev) {
102
+ return addRefToArrayHelper(prev, key, treeItemRef);
103
+ });
104
+ };
105
+
106
+ // adds and removes refs on mount and dismount
107
+ /* istanbul ignore next */
108
+ useEffect(function () {
109
+ // this runs on mount
110
+ addRefToArray();
111
+ return function () {
112
+ // this runs on cleanup
113
+ removeRefFromArray(key, refArray);
114
+ };
115
+ }, []);
116
+ var _useFocusRing = useFocusRing(),
117
+ isFocusVisible = _useFocusRing.isFocusVisible,
118
+ focusProps = _useFocusRing.focusProps;
119
+ var mergedProps = mergeProps(focusProps, optionProps, {
120
+ onFocus: function onFocus() {
121
+ return setLastFocusedItem(key);
122
+ }
123
+ });
124
+ var _useStatusClasses = useStatusClasses('', {
125
+ isFocused: isFocusVisible
126
+ }),
127
+ classNames = _useStatusClasses.classNames;
31
128
  return ___EmotionJSX(Box, _extends({
32
129
  as: "li",
33
130
  isRow: true,
34
131
  ref: treeItemRef,
35
- "aria-disabled": isDisabled,
132
+ "aria-disabled": isDisabled
133
+ }, mergedProps, {
134
+ role: "treeitem",
135
+ variant: "treeView.wrapper",
136
+ className: classNames,
137
+ "aria-selected": isSelected,
36
138
  "aria-level": level,
37
139
  "aria-posinset": position + 1,
38
- "aria-setsize": setSize
39
- }, optionProps, {
40
- role: "treeitem",
41
- sx: {
42
- width: '100%',
43
- ml: '36px',
44
- ':not(:last-child)': {
45
- pb: 'sm'
46
- }
47
- },
48
- "aria-selected": isSelected
140
+ "aria-setsize": setSize,
141
+ onKeyDown: function onKeyDown(e) {
142
+ return onKeyDownFunction(e);
143
+ }
49
144
  }), ___EmotionJSX(TreeViewRow, {
50
145
  item: item,
51
146
  title: title,
@@ -59,8 +154,10 @@ TreeViewItem.propTypes = {
59
154
  item: PropTypes.shape({
60
155
  key: PropTypes.string
61
156
  }),
157
+ focusManager: PropTypes.shape({}),
62
158
  name: PropTypes.string,
63
159
  title: PropTypes.string,
160
+ onKeyDown: PropTypes.func,
64
161
  level: PropTypes.number,
65
162
  position: PropTypes.number,
66
163
  setSize: PropTypes.number