@k-int/stripes-kint-components 1.5.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/CHANGELOG.md +40 -1
  2. package/es/index.js +80 -25
  3. package/es/lib/ActionList/ActionList.js +92 -33
  4. package/es/lib/ActionList/ActionListFieldArray.js +202 -104
  5. package/es/lib/ActionList/index.js +7 -3
  6. package/es/lib/CustomProperties/Config/CustomPropertiesLookup.js +198 -0
  7. package/es/lib/CustomProperties/Config/CustomPropertiesSettings.js +321 -0
  8. package/es/lib/CustomProperties/Config/CustomPropertiesView.js +166 -0
  9. package/es/lib/CustomProperties/Config/CustomPropertyForm.js +357 -0
  10. package/es/lib/CustomProperties/Config/index.js +41 -0
  11. package/es/lib/EditableRefdataList/EditableRefdataList.js +69 -24
  12. package/es/lib/EditableRefdataList/index.js +7 -3
  13. package/es/lib/EditableSettingsList/EditableSettingsList.js +90 -0
  14. package/es/lib/EditableSettingsList/EditableSettingsListFieldArray.js +90 -0
  15. package/es/lib/EditableSettingsList/EditableSettingsListFieldArray.test.js +181 -0
  16. package/es/lib/{Settings → EditableSettingsList/SettingField}/EditSettingValue.js +72 -9
  17. package/es/lib/EditableSettingsList/SettingField/EditSettingValue.test.js +447 -0
  18. package/es/lib/{Settings → EditableSettingsList/SettingField}/RenderSettingValue.js +45 -7
  19. package/es/lib/EditableSettingsList/SettingField/RenderSettingValue.test.js +495 -0
  20. package/es/lib/EditableSettingsList/SettingField/SettingField.js +187 -0
  21. package/es/lib/EditableSettingsList/SettingField/SettingField.test.js +180 -0
  22. package/es/lib/EditableSettingsList/SettingField/index.js +35 -0
  23. package/es/lib/EditableSettingsList/index.js +35 -0
  24. package/es/lib/FormModal/FormModal.js +126 -0
  25. package/es/lib/FormModal/index.js +19 -0
  26. package/es/lib/NoResultsMessage/NoResultsMessage.js +65 -32
  27. package/es/lib/NoResultsMessage/index.js +7 -3
  28. package/es/lib/QueryTypedown/QueryTypedown.js +48 -9
  29. package/es/lib/QueryTypedown/index.js +6 -2
  30. package/es/lib/RefdataButtons/RefdataButtons.js +143 -0
  31. package/es/lib/RefdataButtons/index.js +19 -0
  32. package/es/lib/SASQLookupComponent/SASQLookupComponent.js +194 -140
  33. package/es/lib/SASQLookupComponent/index.js +6 -2
  34. package/es/lib/SASQRoute/SASQRoute.js +55 -18
  35. package/es/lib/SASQRoute/index.js +6 -2
  36. package/es/lib/SASQViewComponent/SASQViewComponent.js +50 -11
  37. package/es/lib/SASQViewComponent/index.js +6 -2
  38. package/es/lib/SearchField/SearchField.js +48 -13
  39. package/es/lib/SearchField/index.js +6 -2
  40. package/es/lib/SettingPage/SettingPage.js +99 -0
  41. package/es/lib/SettingPage/SettingPagePane.js +83 -0
  42. package/es/lib/SettingPage/index.js +27 -0
  43. package/es/lib/Typedown/Typedown.js +174 -99
  44. package/es/lib/Typedown/index.js +6 -2
  45. package/es/lib/constants/customProperties.js +60 -0
  46. package/es/lib/constants/eventCodes.js +31 -1
  47. package/es/lib/contexts/SettingsContext.js +41 -0
  48. package/es/lib/contexts/index.js +19 -0
  49. package/es/lib/hooks/index.js +44 -10
  50. package/es/lib/hooks/settingsHooks/index.js +27 -0
  51. package/es/lib/hooks/settingsHooks/useSettingSection.js +74 -0
  52. package/es/lib/hooks/settingsHooks/useSettings.js +175 -0
  53. package/es/lib/hooks/typedownHooks/index.js +8 -28
  54. package/es/lib/hooks/typedownHooks/useTypedown.js +129 -12
  55. package/es/lib/hooks/typedownHooks/useTypedownData.js +35 -2
  56. package/es/lib/hooks/typedownHooks/useTypedownToggle.js +39 -6
  57. package/es/lib/hooks/useActiveElement.js +33 -2
  58. package/es/lib/hooks/useCustomProperties.js +112 -0
  59. package/es/lib/hooks/useHelperApp.js +44 -11
  60. package/es/lib/hooks/useKiwtFieldArray.js +37 -4
  61. package/es/lib/hooks/useKiwtSASQuery.js +43 -9
  62. package/es/lib/hooks/useLocalStorageState.js +37 -4
  63. package/es/lib/hooks/useMutateCustomProperties.js +143 -0
  64. package/es/lib/hooks/useMutateRefdataValue.js +42 -9
  65. package/es/lib/hooks/useQIndex.js +42 -9
  66. package/es/lib/hooks/useRefdata.js +43 -16
  67. package/es/lib/hooks/useTemplates.js +36 -3
  68. package/es/lib/utils/buildUrl.js +43 -10
  69. package/es/lib/utils/generateKiwtQuery.js +33 -4
  70. package/es/lib/utils/generateKiwtQueryParams.js +31 -2
  71. package/es/lib/utils/index.js +41 -5
  72. package/es/lib/utils/refdataOptions.js +43 -0
  73. package/es/lib/utils/renderHelpText.js +109 -0
  74. package/es/lib/utils/selectorSafe.js +31 -2
  75. package/es/lib/utils/sortByLabel.js +55 -0
  76. package/es/lib/utils/toCamelCase.js +48 -0
  77. package/jest.config.js +15 -1
  78. package/package.json +19 -10
  79. package/src/index.js +25 -10
  80. package/src/lib/ActionList/ActionList.js +32 -22
  81. package/src/lib/ActionList/ActionListFieldArray.js +56 -10
  82. package/src/lib/ActionList/README.md +5 -1
  83. package/src/lib/ActionList/index.js +1 -1
  84. package/src/lib/CustomProperties/Config/CustomPropertiesLookup.js +111 -0
  85. package/src/lib/CustomProperties/Config/CustomPropertiesSettings.js +237 -0
  86. package/src/lib/CustomProperties/Config/CustomPropertiesView.js +150 -0
  87. package/src/lib/CustomProperties/Config/CustomPropertyForm.js +295 -0
  88. package/src/lib/CustomProperties/Config/index.js +4 -0
  89. package/src/lib/EditableRefdataList/EditableRefdataList.js +10 -5
  90. package/src/lib/EditableRefdataList/index.js +1 -1
  91. package/src/lib/{Settings → EditableSettingsList}/EditableSettingsList.js +0 -0
  92. package/src/lib/{Settings → EditableSettingsList}/EditableSettingsListFieldArray.js +2 -2
  93. package/src/lib/EditableSettingsList/EditableSettingsListFieldArray.test.js +111 -0
  94. package/src/lib/{Settings → EditableSettingsList/SettingField}/EditSettingValue.js +24 -1
  95. package/src/lib/EditableSettingsList/SettingField/EditSettingValue.test.js +379 -0
  96. package/src/lib/{Settings → EditableSettingsList/SettingField}/RenderSettingValue.js +2 -1
  97. package/src/lib/EditableSettingsList/SettingField/RenderSettingValue.test.js +368 -0
  98. package/src/lib/{Settings → EditableSettingsList/SettingField}/SettingField.js +7 -7
  99. package/src/lib/EditableSettingsList/SettingField/SettingField.test.js +80 -0
  100. package/src/lib/EditableSettingsList/SettingField/index.js +3 -0
  101. package/src/lib/EditableSettingsList/index.js +3 -0
  102. package/src/lib/FormModal/FormModal.js +71 -0
  103. package/src/lib/FormModal/index.js +1 -0
  104. package/src/lib/NoResultsMessage/NoResultsMessage.js +2 -2
  105. package/src/lib/NoResultsMessage/index.js +1 -1
  106. package/src/lib/{Settings → RefdataButtons}/RefdataButtons.js +1 -1
  107. package/src/lib/RefdataButtons/index.js +1 -0
  108. package/src/lib/SASQLookupComponent/SASQLookupComponent.js +7 -1
  109. package/src/lib/{Settings → SettingPage}/SettingPage.js +5 -5
  110. package/src/lib/{Settings → SettingPage}/SettingPagePane.js +12 -2
  111. package/src/lib/SettingPage/index.js +2 -0
  112. package/src/lib/Typedown/Typedown.js +52 -9
  113. package/src/lib/constants/customProperties.js +9 -0
  114. package/src/lib/{Settings → contexts}/SettingsContext.js +1 -1
  115. package/src/lib/contexts/index.js +2 -0
  116. package/src/lib/hooks/index.js +3 -0
  117. package/src/lib/hooks/settingsHooks/index.js +2 -0
  118. package/src/lib/{Settings → hooks/settingsHooks}/useSettingSection.js +0 -0
  119. package/src/lib/{Settings → hooks/settingsHooks}/useSettings.js +14 -6
  120. package/src/lib/hooks/typedownHooks/index.js +0 -3
  121. package/src/lib/hooks/typedownHooks/useTypedown.js +93 -11
  122. package/src/lib/hooks/useCustomProperties.js +73 -0
  123. package/src/lib/hooks/useMutateCustomProperties.js +62 -0
  124. package/src/lib/hooks/useRefdata.js +2 -8
  125. package/src/lib/utils/index.js +7 -0
  126. package/src/lib/utils/refdataOptions.js +7 -0
  127. package/src/lib/{Settings/utils → utils}/renderHelpText.js +1 -1
  128. package/src/lib/{Settings/utils → utils}/sortByLabel.js +1 -1
  129. package/src/lib/{Settings/utils → utils}/toCamelCase.js +0 -0
  130. package/test/helpers/index.js +1 -0
  131. package/test/helpers/translationsProperties.js +40 -0
  132. package/test/jest/helpers/KintHarness.js +36 -0
  133. package/test/jest/helpers/index.js +2 -0
  134. package/test/jest/helpers/renderWithKintHarness.js +15 -0
  135. package/test/jest/jest-transformer.js +4 -0
  136. package/test/jest/setupTests.js +1 -0
  137. package/translations/stripes-kint-components/en.json +48 -1
  138. package/yarn-error.log +14118 -0
  139. package/babelOptions.js +0 -30
  140. package/es/lib/Settings/EditableSettingsList.js +0 -57
  141. package/es/lib/Settings/EditableSettingsListFieldArray.js +0 -59
  142. package/es/lib/Settings/RefdataButtons.js +0 -100
  143. package/es/lib/Settings/SettingField.js +0 -144
  144. package/es/lib/Settings/SettingPage.js +0 -64
  145. package/es/lib/Settings/SettingPagePane.js +0 -43
  146. package/es/lib/Settings/SettingsContext.js +0 -18
  147. package/es/lib/Settings/index.js +0 -71
  148. package/es/lib/Settings/useSettingSection.js +0 -41
  149. package/es/lib/Settings/useSettings.js +0 -126
  150. package/es/lib/Settings/utils/index.js +0 -31
  151. package/es/lib/Settings/utils/renderHelpText.js +0 -57
  152. package/es/lib/Settings/utils/sortByLabel.js +0 -26
  153. package/es/lib/Settings/utils/toCamelCase.js +0 -19
  154. package/es/lib/TypeDown/TypeDown.js +0 -209
  155. package/es/lib/TypeDown/index.js +0 -15
  156. package/es/lib/hooks/typedownHooks/useTypedownFooter.js +0 -47
  157. package/es/lib/hooks/typedownHooks/useTypedownList.js +0 -45
  158. package/es/lib/hooks/typedownHooks/useTypedownSearchField.js +0 -47
  159. package/es/lib/utils/getFocusableElements.js +0 -132
  160. package/src/lib/Settings/index.js +0 -8
  161. package/src/lib/Settings/utils/index.js +0 -3
  162. package/src/lib/TypeDown/README.md +0 -1
  163. package/src/lib/TypeDown/TypeDown.js +0 -226
  164. package/src/lib/TypeDown/index.js +0 -1
  165. package/src/lib/hooks/typedownHooks/useTypedownFooter.js +0 -43
  166. package/src/lib/hooks/typedownHooks/useTypedownList.js +0 -36
  167. package/src/lib/hooks/typedownHooks/useTypedownSearchField.js +0 -39
  168. package/src/lib/utils/getFocusableElements.js +0 -99
@@ -1,132 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.getFirstFocusable = getFirstFocusable;
7
- exports.getLastFocusable = getLastFocusable;
8
- exports.getNextFocusable = getNextFocusable;
9
- exports.getPreviousFocusable = getPreviousFocusable;
10
-
11
- var _contains = _interopRequireDefault(require("dom-helpers/query/contains"));
12
-
13
- var _matches = _interopRequireDefault(require("dom-helpers/query/matches"));
14
-
15
- var _first = _interopRequireDefault(require("lodash/first"));
16
-
17
- var _last = _interopRequireDefault(require("lodash/last"));
18
-
19
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
20
-
21
- // THIS FILE IS ADAPTED FROM https://github.com/folio-org/stripes-components/blob/master/util/getFocusableElements.js
22
- // With the option included to return null if run out of options
23
- // TODO swap to stripes-components export once available (Will need <= peer dep bump)
24
- function getVisibleFocusableElements() {
25
- var container = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : document;
26
- var includeContained = arguments.length > 1 ? arguments[1] : undefined;
27
- var currentElement = arguments.length > 2 ? arguments[2] : undefined;
28
-
29
- if (container.querySelectorAll) {
30
- // eslint-disable-next-line max-len
31
- var focusableSelector = 'a:not([disabled]), button:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"]), [tabIndex="-1"]:not([disabled]):focus';
32
- return Array.from(container.querySelectorAll(focusableSelector)).filter(function (element) {
33
- if (!includeContained) {
34
- if (element === currentElement) {
35
- return true;
36
- }
37
-
38
- if (currentElement && (0, _contains["default"])(currentElement, element)) {
39
- return false;
40
- }
41
- }
42
-
43
- if ((0, _matches["default"])(element, '[data-focus-exclude]')) {
44
- return false;
45
- } // check for visibility while always include the current activeElement
46
-
47
-
48
- return element.offsetWidth > 0 || element.offsetHeight > 0 || element === document.activeElement;
49
- });
50
- }
51
-
52
- return [];
53
- }
54
-
55
- function getNextorPrevious(collection, current, loop, next) {
56
- var nullOnExit = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
57
- var index = collection.indexOf(current);
58
-
59
- if (index === -1) {
60
- index = collection.indexOf(document.activeElement);
61
- }
62
-
63
- var nextElement = collection[index + 1];
64
- var previousElement = collection[index - 1]; // First determine if travelling forwards or backwards through the list
65
-
66
- if (next) {
67
- // If looping then loop to beginning if nextElement is null
68
- if (loop) {
69
- return nextElement || collection[0];
70
- } // If nullOnExit then return null if nextElement is null
71
-
72
-
73
- if (nullOnExit) {
74
- return nextElement;
75
- } // Else return end of the list if nextElement is null
76
-
77
-
78
- return collection[index + 1] || collection[collection.length - 1];
79
- } else {
80
- // If looping then loop to end if previousElement is null
81
- if (loop) {
82
- return previousElement || collection[collection.length - 1];
83
- } // If nullOnExit then return null if previousElement is null
84
-
85
-
86
- if (nullOnExit) {
87
- return previousElement;
88
- } // Else return beginning of the list if previousElement is null
89
-
90
-
91
- return collection[index - 1] || collection[0];
92
- }
93
- }
94
-
95
- function getFocusableElement(next, currentElement) {
96
- var includeContained = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
97
- var onlyContained = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
98
- var loop = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
99
- var nullOnExit = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
100
- var container = includeContained && onlyContained ? currentElement : document;
101
- var focusable = getVisibleFocusableElements(container, includeContained, currentElement);
102
-
103
- if (focusable.length > 0) {
104
- return getNextorPrevious(focusable, currentElement, loop, next, nullOnExit);
105
- }
106
-
107
- return null;
108
- }
109
-
110
- function getNextFocusable() {
111
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
112
- args[_key] = arguments[_key];
113
- }
114
-
115
- return getFocusableElement.apply(void 0, [true].concat(args));
116
- }
117
-
118
- function getPreviousFocusable() {
119
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
120
- args[_key2] = arguments[_key2];
121
- }
122
-
123
- return getFocusableElement.apply(void 0, [false].concat(args));
124
- }
125
-
126
- function getLastFocusable(container) {
127
- return (0, _last["default"])(getVisibleFocusableElements(container));
128
- }
129
-
130
- function getFirstFocusable(container) {
131
- return (0, _first["default"])(getVisibleFocusableElements(container));
132
- }
@@ -1,8 +0,0 @@
1
- export { default as EditableSettingsList } from './EditableSettingsList';
2
- export { default as EditableSettingsListFieldArray } from './EditableSettingsListFieldArray';
3
- export { default as SettingField } from './SettingField';
4
- export { default as SettingPagePane } from './SettingPagePane';
5
- export { default as SettingPage } from './SettingPage';
6
- export { default as RefdataButtons } from './RefdataButtons';
7
- export { default as useSettings } from './useSettings';
8
- export { default as SettingsContext } from './SettingsContext';
@@ -1,3 +0,0 @@
1
- export { default as renderHelpText } from './renderHelpText';
2
- export { default as toCamelCase } from './toCamelCase';
3
- export { default as sortByLabel } from './sortByLabel';
@@ -1 +0,0 @@
1
- DEPRECATED - DO NOT USE. You probably want Typedown
@@ -1,226 +0,0 @@
1
- import React, { useCallback, useEffect, useState } from 'react';
2
- import PropTypes from 'prop-types';
3
- import classnames from 'classnames';
4
-
5
- import get from 'lodash/get';
6
-
7
- import { EndOfList, IconButton, Popper } from '@folio/stripes/components';
8
-
9
- // eslint-disable-next-line import/no-extraneous-dependencies
10
- import { interactionStyles } from '@folio/stripes-components/lib/sharedStyles/interactionStyles.css';
11
-
12
- import SearchField from '../SearchField';
13
- import css from '../../../styles/TypeDown.css';
14
-
15
- import { useTypedown, useTypedownData } from '../hooks/typedownHooks';
16
- import selectorSafe from '../utils/selectorSafe';
17
-
18
- /* @deprecated
19
- * Replaced by Typedown and QueryTypedown.
20
- */
21
- const TypeDown = ({
22
- input,
23
- meta,
24
- onChange,
25
- path,
26
- pathMutator,
27
- renderFooter = null,
28
- renderListItem = null,
29
- uniqueIdentificationPath = 'id'
30
- }) => {
31
- useEffect(() => {
32
- if (process.env.NODE_ENV === 'development') {
33
- console.warn('TypeDown component is deprecated, you likely want either Typedown or QueryTypedown');
34
- }
35
- }, []);
36
-
37
- const selectedUniqueId = get(input.value, uniqueIdentificationPath);
38
-
39
- const [callPath, setCallPath] = useState(pathMutator(null, path));
40
- const data = useTypedownData(callPath);
41
-
42
- // Hook to set up all the essentials
43
- const {
44
- refs: {
45
- listRef,
46
- triggerRef,
47
- overlayRef,
48
- footerRef
49
- },
50
- handlers: {
51
- handleNextFocus,
52
- listKeyDownHandler,
53
- searchFieldKeyDownHandler
54
- },
55
- variables: {
56
- open,
57
- portal,
58
- resizeRef,
59
- searchWidth
60
- }
61
- } = useTypedown(input.name);
62
-
63
- const renderItem = useCallback((option) => (
64
- <div
65
- className={css.listItem}
66
- >
67
- {renderListItem ?
68
- renderListItem(option) :
69
- get(option, uniqueIdentificationPath)
70
- }
71
- </div>
72
- ), [renderListItem, uniqueIdentificationPath]);
73
-
74
- const handleChange = value => {
75
- input.onChange(value);
76
-
77
- if (typeof onChange === 'function') {
78
- onChange(value);
79
- }
80
- };
81
-
82
- const dropDown = useCallback(() => {
83
- return (
84
- <div
85
- className={css.dropdownMenu}
86
- id={`typedown-parent-${selectorSafe(input.name)}-menu`}
87
- style={{ '--searchWidth': `${searchWidth}px` }}
88
- >
89
- <div
90
- ref={listRef}
91
- className={css.listContainer}
92
- id="typedown-list"
93
- >
94
- {data?.length ? data?.map((d, index) => {
95
- const isSelected = get(input.value, uniqueIdentificationPath) === get(d, uniqueIdentificationPath);
96
- return (
97
- <button
98
- key={`typedown-button-[${index}]`}
99
- className={classnames(
100
- interactionStyles,
101
- css.fullWidth,
102
- css.menuButton
103
- )}
104
- data-selected={isSelected}
105
- id={`typedown-button-[${index}]`}
106
- onClick={() => {
107
- handleChange(d);
108
- handleNextFocus();
109
- }}
110
- onKeyDown={listKeyDownHandler}
111
- type="button"
112
- >
113
- {renderItem(d)}
114
- </button>
115
- );
116
- }) :
117
- // TODO test this
118
- <EndOfList />
119
- }
120
- </div>
121
- {renderFooter &&
122
- <div
123
- ref={footerRef}
124
- className={css.footer}
125
- id="typedown-footer"
126
- >
127
- {renderFooter()}
128
- </div>
129
- }
130
- </div>
131
- );
132
- }, [
133
- data,
134
- footerRef,
135
- handleNextFocus,
136
- input,
137
- listKeyDownHandler,
138
- listRef,
139
- renderFooter,
140
- renderItem,
141
- searchWidth,
142
- uniqueIdentificationPath
143
- ]);
144
-
145
- const renderSearchField = () => {
146
- return (
147
- <div
148
- ref={triggerRef}
149
- id={`typedown-parent-${selectorSafe(input.name)}-searchField`}
150
- >
151
- <SearchField
152
- // Pass meta through so correct styling gets applied to the TextField
153
- id="typedown-searchField"
154
- marginBottom0
155
- meta={meta}
156
- onChange={e => {
157
- setCallPath(pathMutator(e.target.value, path));
158
- }}
159
- onKeyDown={searchFieldKeyDownHandler}
160
- />
161
- </div>
162
- );
163
- };
164
-
165
- return (
166
- <div
167
- ref={resizeRef}
168
- >
169
- {renderSearchField()}
170
- <Popper
171
- key="typedown-menu-toggle"
172
- anchorRef={triggerRef}
173
- className={classnames(
174
- css.dropdown,
175
- css.fullWidth
176
- )}
177
- isOpen={open}
178
- modifiers={{
179
- flip: { boundariesElement: 'viewport', padding: 10 },
180
- preventOverflow: { boundariesElement: 'viewport', padding: 10 }
181
- }}
182
- overlayProps={{
183
- 'ref': overlayRef,
184
- 'tabIndex': '-1',
185
- 'onClick': (e) => { e.stopPropagation(); } // prevent propagation of click events
186
- }}
187
- overlayRef={overlayRef}
188
- portal={portal}
189
- >
190
- {dropDown()}
191
- </Popper>
192
- {selectedUniqueId && !open &&
193
- <div
194
- className={classnames(
195
- css.selected,
196
- css.selectedDisplay
197
- )}
198
- >
199
- <div
200
- className={css.selectedItem}
201
- >
202
- {renderItem(input.value)}
203
- </div>
204
- <IconButton
205
- className={css.clearItem}
206
- icon="times-circle-solid"
207
- onClick={() => handleChange()}
208
- />
209
- </div>
210
- }
211
- </div>
212
- );
213
- };
214
-
215
- TypeDown.propTypes = {
216
- input: PropTypes.object,
217
- meta: PropTypes.object,
218
- onChange: PropTypes.func,
219
- path: PropTypes.string,
220
- pathMutator: PropTypes.func,
221
- renderFooter: PropTypes.func,
222
- renderListItem: PropTypes.func,
223
- uniqueIdentificationPath: PropTypes.string
224
- };
225
-
226
- export default TypeDown;
@@ -1 +0,0 @@
1
- export { default } from './TypeDown';
@@ -1,43 +0,0 @@
1
- import { useEffect, useRef } from 'react';
2
-
3
- // TODO swap to stripes-components export once available (Will need <= peer dep bump)
4
- import {
5
- getNextFocusable,
6
- getPreviousFocusable,
7
- } from '../../utils/getFocusableElements';
8
- import { TAB } from '../../constants/eventCodes';
9
-
10
- const useTypedownFooter = (searchField) => {
11
- const footerRef = useRef();
12
-
13
- const footer = document.getElementById('typedown-footer');
14
- // Add an event listener to the footer, so that we can control tab behaviour between footer elements
15
- useEffect(() => {
16
- if (footer) {
17
- footer.addEventListener('keydown', e => {
18
- // We want special behaviour on tab
19
- if (e.code === TAB) {
20
- // Prevent the default behaviour
21
- e.preventDefault();
22
- const focusFunc = e.shiftKey ? getPreviousFocusable : getNextFocusable;
23
- const elem = focusFunc(footerRef.current, true, true, false, true);
24
-
25
- if (elem) {
26
- // Focus on next focusable element
27
- elem.focus();
28
- } else if (e.shiftKey) {
29
- // We are at the beginning of the list, refocus on search bar
30
- searchField.focus();
31
- } else {
32
- // We are at the end of the list, move onto next focusable element in page
33
- getNextFocusable(searchField, false).focus();
34
- }
35
- }
36
- });
37
- }
38
- }, [footer, searchField]);
39
-
40
- return footerRef;
41
- };
42
-
43
- export default useTypedownFooter;
@@ -1,36 +0,0 @@
1
- // TODO swap to stripes-components export once available (Will need <= peer dep bump)
2
- import {
3
- getNextFocusable,
4
- getPreviousFocusable,
5
- } from '../../utils/getFocusableElements';
6
-
7
- import { UP_ARROW, DOWN_ARROW, TAB } from '../../constants/eventCodes';
8
-
9
- const useTypedownList = (listRef, footerRef, searchField) => {
10
- return e => {
11
- if (e.code === DOWN_ARROW) {
12
- const elem = getNextFocusable(listRef.current, true, true);
13
- elem.focus();
14
- }
15
-
16
- if (e.code === UP_ARROW) {
17
- const elem = getPreviousFocusable(listRef.current, true, true);
18
- elem.focus();
19
- }
20
-
21
- if (e.code === TAB) {
22
- e.preventDefault();
23
- let elem;
24
- if (!e.shiftKey && !footerRef.current) {
25
- elem = getNextFocusable(searchField, false);
26
- } else if (!e.shiftKey) {
27
- elem = getNextFocusable(footerRef.current, true, true, true, true);
28
- } else {
29
- elem = searchField;
30
- }
31
- elem.focus();
32
- }
33
- };
34
- };
35
-
36
- export default useTypedownList;
@@ -1,39 +0,0 @@
1
- // TODO swap to stripes-components export once available (Will need <= peer dep bump)
2
- import {
3
- getNextFocusable,
4
- getFirstFocusable,
5
- getLastFocusable
6
- } from '../../utils/getFocusableElements';
7
- import { UP_ARROW, DOWN_ARROW, TAB } from '../../constants/eventCodes';
8
-
9
- const useTypedownSearchField = (listRef, footerRef, searchField) => {
10
- return e => {
11
- if (e.code === UP_ARROW) {
12
- const elem = getLastFocusable(listRef.current, true, true);
13
- if (elem) {
14
- elem.focus();
15
- }
16
- }
17
-
18
- if (e.code === DOWN_ARROW) {
19
- const elem = getFirstFocusable(listRef.current, true, true);
20
- if (elem) {
21
- elem.focus();
22
- }
23
- }
24
-
25
- // Tab key (But not while shifting)
26
- if (e.code === TAB && !e.shiftKey) {
27
- e.preventDefault();
28
- // If we have focusable elements in the footer, then focus on them, else unfocus searchbar
29
- const elem = getNextFocusable(footerRef.current, true, true, true, true);
30
- if (elem) {
31
- elem.focus();
32
- } else {
33
- getNextFocusable(searchField, false).focus();
34
- }
35
- }
36
- };
37
- };
38
-
39
- export default useTypedownSearchField;
@@ -1,99 +0,0 @@
1
- // THIS FILE IS ADAPTED FROM https://github.com/folio-org/stripes-components/blob/master/util/getFocusableElements.js
2
- // With the option included to return null if run out of options
3
- // TODO swap to stripes-components export once available (Will need <= peer dep bump)
4
-
5
- import contains from 'dom-helpers/query/contains';
6
- import matches from 'dom-helpers/query/matches';
7
- import first from 'lodash/first';
8
- import last from 'lodash/last';
9
-
10
- function getVisibleFocusableElements(container = document, includeContained, currentElement) {
11
- if (container.querySelectorAll) {
12
- // eslint-disable-next-line max-len
13
- const focusableSelector = 'a:not([disabled]), button:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"]), [tabIndex="-1"]:not([disabled]):focus';
14
- return Array.from(container.querySelectorAll(focusableSelector))
15
- .filter((element) => {
16
- if (!includeContained) {
17
- if (element === currentElement) {
18
- return true;
19
- }
20
- if (currentElement && contains(currentElement, element)) {
21
- return false;
22
- }
23
- }
24
-
25
- if (matches(element, '[data-focus-exclude]')) {
26
- return false;
27
- }
28
-
29
- // check for visibility while always include the current activeElement
30
- return element.offsetWidth > 0 ||
31
- element.offsetHeight > 0 ||
32
- element === document.activeElement;
33
- });
34
- }
35
- return [];
36
- }
37
-
38
- function getNextorPrevious(collection, current, loop, next, nullOnExit = false) {
39
- let index = collection.indexOf(current);
40
- if (index === -1) {
41
- index = collection.indexOf(document.activeElement);
42
- }
43
- const nextElement = collection[index + 1];
44
- const previousElement = collection[index - 1];
45
-
46
- // First determine if travelling forwards or backwards through the list
47
- if (next) {
48
- // If looping then loop to beginning if nextElement is null
49
- if (loop) {
50
- return nextElement || collection[0];
51
- }
52
-
53
- // If nullOnExit then return null if nextElement is null
54
- if (nullOnExit) {
55
- return nextElement;
56
- }
57
-
58
- // Else return end of the list if nextElement is null
59
- return collection[index + 1] || collection[collection.length - 1];
60
- } else {
61
- // If looping then loop to end if previousElement is null
62
- if (loop) {
63
- return previousElement || collection[collection.length - 1];
64
- }
65
-
66
- // If nullOnExit then return null if previousElement is null
67
- if (nullOnExit) {
68
- return previousElement;
69
- }
70
-
71
- // Else return beginning of the list if previousElement is null
72
- return collection[index - 1] || collection[0];
73
- }
74
- }
75
-
76
- function getFocusableElement(next, currentElement, includeContained = true, onlyContained = false, loop = true, nullOnExit = false) {
77
- const container = includeContained && onlyContained ? currentElement : document;
78
- const focusable = getVisibleFocusableElements(container, includeContained, currentElement);
79
- if (focusable.length > 0) {
80
- return getNextorPrevious(focusable, currentElement, loop, next, nullOnExit);
81
- }
82
- return null;
83
- }
84
-
85
- export function getNextFocusable(...args) {
86
- return getFocusableElement(true, ...args);
87
- }
88
-
89
- export function getPreviousFocusable(...args) {
90
- return getFocusableElement(false, ...args);
91
- }
92
-
93
- export function getLastFocusable(container) {
94
- return last(getVisibleFocusableElements(container));
95
- }
96
-
97
- export function getFirstFocusable(container) {
98
- return first(getVisibleFocusableElements(container));
99
- }