@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.
- package/CHANGELOG.md +40 -1
- package/es/index.js +80 -25
- package/es/lib/ActionList/ActionList.js +92 -33
- package/es/lib/ActionList/ActionListFieldArray.js +202 -104
- package/es/lib/ActionList/index.js +7 -3
- package/es/lib/CustomProperties/Config/CustomPropertiesLookup.js +198 -0
- package/es/lib/CustomProperties/Config/CustomPropertiesSettings.js +321 -0
- package/es/lib/CustomProperties/Config/CustomPropertiesView.js +166 -0
- package/es/lib/CustomProperties/Config/CustomPropertyForm.js +357 -0
- package/es/lib/CustomProperties/Config/index.js +41 -0
- package/es/lib/EditableRefdataList/EditableRefdataList.js +69 -24
- package/es/lib/EditableRefdataList/index.js +7 -3
- package/es/lib/EditableSettingsList/EditableSettingsList.js +90 -0
- package/es/lib/EditableSettingsList/EditableSettingsListFieldArray.js +90 -0
- package/es/lib/EditableSettingsList/EditableSettingsListFieldArray.test.js +181 -0
- package/es/lib/{Settings → EditableSettingsList/SettingField}/EditSettingValue.js +72 -9
- package/es/lib/EditableSettingsList/SettingField/EditSettingValue.test.js +447 -0
- package/es/lib/{Settings → EditableSettingsList/SettingField}/RenderSettingValue.js +45 -7
- package/es/lib/EditableSettingsList/SettingField/RenderSettingValue.test.js +495 -0
- package/es/lib/EditableSettingsList/SettingField/SettingField.js +187 -0
- package/es/lib/EditableSettingsList/SettingField/SettingField.test.js +180 -0
- package/es/lib/EditableSettingsList/SettingField/index.js +35 -0
- package/es/lib/EditableSettingsList/index.js +35 -0
- package/es/lib/FormModal/FormModal.js +126 -0
- package/es/lib/FormModal/index.js +19 -0
- package/es/lib/NoResultsMessage/NoResultsMessage.js +65 -32
- package/es/lib/NoResultsMessage/index.js +7 -3
- package/es/lib/QueryTypedown/QueryTypedown.js +48 -9
- package/es/lib/QueryTypedown/index.js +6 -2
- package/es/lib/RefdataButtons/RefdataButtons.js +143 -0
- package/es/lib/RefdataButtons/index.js +19 -0
- package/es/lib/SASQLookupComponent/SASQLookupComponent.js +194 -140
- package/es/lib/SASQLookupComponent/index.js +6 -2
- package/es/lib/SASQRoute/SASQRoute.js +55 -18
- package/es/lib/SASQRoute/index.js +6 -2
- package/es/lib/SASQViewComponent/SASQViewComponent.js +50 -11
- package/es/lib/SASQViewComponent/index.js +6 -2
- package/es/lib/SearchField/SearchField.js +48 -13
- package/es/lib/SearchField/index.js +6 -2
- package/es/lib/SettingPage/SettingPage.js +99 -0
- package/es/lib/SettingPage/SettingPagePane.js +83 -0
- package/es/lib/SettingPage/index.js +27 -0
- package/es/lib/Typedown/Typedown.js +174 -99
- package/es/lib/Typedown/index.js +6 -2
- package/es/lib/constants/customProperties.js +60 -0
- package/es/lib/constants/eventCodes.js +31 -1
- package/es/lib/contexts/SettingsContext.js +41 -0
- package/es/lib/contexts/index.js +19 -0
- package/es/lib/hooks/index.js +44 -10
- package/es/lib/hooks/settingsHooks/index.js +27 -0
- package/es/lib/hooks/settingsHooks/useSettingSection.js +74 -0
- package/es/lib/hooks/settingsHooks/useSettings.js +175 -0
- package/es/lib/hooks/typedownHooks/index.js +8 -28
- package/es/lib/hooks/typedownHooks/useTypedown.js +129 -12
- package/es/lib/hooks/typedownHooks/useTypedownData.js +35 -2
- package/es/lib/hooks/typedownHooks/useTypedownToggle.js +39 -6
- package/es/lib/hooks/useActiveElement.js +33 -2
- package/es/lib/hooks/useCustomProperties.js +112 -0
- package/es/lib/hooks/useHelperApp.js +44 -11
- package/es/lib/hooks/useKiwtFieldArray.js +37 -4
- package/es/lib/hooks/useKiwtSASQuery.js +43 -9
- package/es/lib/hooks/useLocalStorageState.js +37 -4
- package/es/lib/hooks/useMutateCustomProperties.js +143 -0
- package/es/lib/hooks/useMutateRefdataValue.js +42 -9
- package/es/lib/hooks/useQIndex.js +42 -9
- package/es/lib/hooks/useRefdata.js +43 -16
- package/es/lib/hooks/useTemplates.js +36 -3
- package/es/lib/utils/buildUrl.js +43 -10
- package/es/lib/utils/generateKiwtQuery.js +33 -4
- package/es/lib/utils/generateKiwtQueryParams.js +31 -2
- package/es/lib/utils/index.js +41 -5
- package/es/lib/utils/refdataOptions.js +43 -0
- package/es/lib/utils/renderHelpText.js +109 -0
- package/es/lib/utils/selectorSafe.js +31 -2
- package/es/lib/utils/sortByLabel.js +55 -0
- package/es/lib/utils/toCamelCase.js +48 -0
- package/jest.config.js +15 -1
- package/package.json +19 -10
- package/src/index.js +25 -10
- package/src/lib/ActionList/ActionList.js +32 -22
- package/src/lib/ActionList/ActionListFieldArray.js +56 -10
- package/src/lib/ActionList/README.md +5 -1
- package/src/lib/ActionList/index.js +1 -1
- package/src/lib/CustomProperties/Config/CustomPropertiesLookup.js +111 -0
- package/src/lib/CustomProperties/Config/CustomPropertiesSettings.js +237 -0
- package/src/lib/CustomProperties/Config/CustomPropertiesView.js +150 -0
- package/src/lib/CustomProperties/Config/CustomPropertyForm.js +295 -0
- package/src/lib/CustomProperties/Config/index.js +4 -0
- package/src/lib/EditableRefdataList/EditableRefdataList.js +10 -5
- package/src/lib/EditableRefdataList/index.js +1 -1
- package/src/lib/{Settings → EditableSettingsList}/EditableSettingsList.js +0 -0
- package/src/lib/{Settings → EditableSettingsList}/EditableSettingsListFieldArray.js +2 -2
- package/src/lib/EditableSettingsList/EditableSettingsListFieldArray.test.js +111 -0
- package/src/lib/{Settings → EditableSettingsList/SettingField}/EditSettingValue.js +24 -1
- package/src/lib/EditableSettingsList/SettingField/EditSettingValue.test.js +379 -0
- package/src/lib/{Settings → EditableSettingsList/SettingField}/RenderSettingValue.js +2 -1
- package/src/lib/EditableSettingsList/SettingField/RenderSettingValue.test.js +368 -0
- package/src/lib/{Settings → EditableSettingsList/SettingField}/SettingField.js +7 -7
- package/src/lib/EditableSettingsList/SettingField/SettingField.test.js +80 -0
- package/src/lib/EditableSettingsList/SettingField/index.js +3 -0
- package/src/lib/EditableSettingsList/index.js +3 -0
- package/src/lib/FormModal/FormModal.js +71 -0
- package/src/lib/FormModal/index.js +1 -0
- package/src/lib/NoResultsMessage/NoResultsMessage.js +2 -2
- package/src/lib/NoResultsMessage/index.js +1 -1
- package/src/lib/{Settings → RefdataButtons}/RefdataButtons.js +1 -1
- package/src/lib/RefdataButtons/index.js +1 -0
- package/src/lib/SASQLookupComponent/SASQLookupComponent.js +7 -1
- package/src/lib/{Settings → SettingPage}/SettingPage.js +5 -5
- package/src/lib/{Settings → SettingPage}/SettingPagePane.js +12 -2
- package/src/lib/SettingPage/index.js +2 -0
- package/src/lib/Typedown/Typedown.js +52 -9
- package/src/lib/constants/customProperties.js +9 -0
- package/src/lib/{Settings → contexts}/SettingsContext.js +1 -1
- package/src/lib/contexts/index.js +2 -0
- package/src/lib/hooks/index.js +3 -0
- package/src/lib/hooks/settingsHooks/index.js +2 -0
- package/src/lib/{Settings → hooks/settingsHooks}/useSettingSection.js +0 -0
- package/src/lib/{Settings → hooks/settingsHooks}/useSettings.js +14 -6
- package/src/lib/hooks/typedownHooks/index.js +0 -3
- package/src/lib/hooks/typedownHooks/useTypedown.js +93 -11
- package/src/lib/hooks/useCustomProperties.js +73 -0
- package/src/lib/hooks/useMutateCustomProperties.js +62 -0
- package/src/lib/hooks/useRefdata.js +2 -8
- package/src/lib/utils/index.js +7 -0
- package/src/lib/utils/refdataOptions.js +7 -0
- package/src/lib/{Settings/utils → utils}/renderHelpText.js +1 -1
- package/src/lib/{Settings/utils → utils}/sortByLabel.js +1 -1
- package/src/lib/{Settings/utils → utils}/toCamelCase.js +0 -0
- package/test/helpers/index.js +1 -0
- package/test/helpers/translationsProperties.js +40 -0
- package/test/jest/helpers/KintHarness.js +36 -0
- package/test/jest/helpers/index.js +2 -0
- package/test/jest/helpers/renderWithKintHarness.js +15 -0
- package/test/jest/jest-transformer.js +4 -0
- package/test/jest/setupTests.js +1 -0
- package/translations/stripes-kint-components/en.json +48 -1
- package/yarn-error.log +14118 -0
- package/babelOptions.js +0 -30
- package/es/lib/Settings/EditableSettingsList.js +0 -57
- package/es/lib/Settings/EditableSettingsListFieldArray.js +0 -59
- package/es/lib/Settings/RefdataButtons.js +0 -100
- package/es/lib/Settings/SettingField.js +0 -144
- package/es/lib/Settings/SettingPage.js +0 -64
- package/es/lib/Settings/SettingPagePane.js +0 -43
- package/es/lib/Settings/SettingsContext.js +0 -18
- package/es/lib/Settings/index.js +0 -71
- package/es/lib/Settings/useSettingSection.js +0 -41
- package/es/lib/Settings/useSettings.js +0 -126
- package/es/lib/Settings/utils/index.js +0 -31
- package/es/lib/Settings/utils/renderHelpText.js +0 -57
- package/es/lib/Settings/utils/sortByLabel.js +0 -26
- package/es/lib/Settings/utils/toCamelCase.js +0 -19
- package/es/lib/TypeDown/TypeDown.js +0 -209
- package/es/lib/TypeDown/index.js +0 -15
- package/es/lib/hooks/typedownHooks/useTypedownFooter.js +0 -47
- package/es/lib/hooks/typedownHooks/useTypedownList.js +0 -45
- package/es/lib/hooks/typedownHooks/useTypedownSearchField.js +0 -47
- package/es/lib/utils/getFocusableElements.js +0 -132
- package/src/lib/Settings/index.js +0 -8
- package/src/lib/Settings/utils/index.js +0 -3
- package/src/lib/TypeDown/README.md +0 -1
- package/src/lib/TypeDown/TypeDown.js +0 -226
- package/src/lib/TypeDown/index.js +0 -1
- package/src/lib/hooks/typedownHooks/useTypedownFooter.js +0 -43
- package/src/lib/hooks/typedownHooks/useTypedownList.js +0 -36
- package/src/lib/hooks/typedownHooks/useTypedownSearchField.js +0 -39
- 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 +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
|
-
}
|