@spaced-out/ui-design-system 0.3.37 → 0.3.38
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/.cspell/custom-words.txt +1 -0
- package/CHANGELOG.md +9 -0
- package/lib/components/Chip/Chip.js +2 -1
- package/lib/components/Chip/Chip.js.flow +2 -0
- package/lib/components/TokenListInput/TokenListInput.js +237 -0
- package/lib/components/TokenListInput/TokenListInput.js.flow +344 -0
- package/lib/components/TokenListInput/TokenListInput.module.css +147 -0
- package/lib/components/TokenListInput/TokenValueChips.js +59 -0
- package/lib/components/TokenListInput/TokenValueChips.js.flow +71 -0
- package/lib/components/TokenListInput/index.js +16 -0
- package/lib/components/TokenListInput/index.js.flow +3 -0
- package/lib/components/index.js +11 -0
- package/lib/components/index.js.flow +1 -0
- package/lib/hooks/index.js +22 -0
- package/lib/hooks/index.js.flow +2 -0
- package/lib/hooks/useArbitraryOptionAddition/index.js +16 -0
- package/lib/hooks/useArbitraryOptionAddition/index.js.flow +3 -0
- package/lib/hooks/useArbitraryOptionAddition/useArbitraryOptionAddition.js +98 -0
- package/lib/hooks/useArbitraryOptionAddition/useArbitraryOptionAddition.js.flow +117 -0
- package/lib/hooks/useFilteredOptions/index.js +16 -0
- package/lib/hooks/useFilteredOptions/index.js.flow +3 -0
- package/lib/hooks/useFilteredOptions/useFilteredOptions.js +62 -0
- package/lib/hooks/useFilteredOptions/useFilteredOptions.js.flow +81 -0
- package/lib/hooks/useInputState/useInputState.js +5 -3
- package/lib/hooks/useInputState/useInputState.js.flow +3 -3
- package/lib/utils/token-list-input/token-list-input.js +28 -0
- package/lib/utils/token-list-input/token-list-input.js.flow +37 -0
- package/package.json +1 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
@value (
|
|
2
|
+
spaceNone,
|
|
3
|
+
spaceSmall,
|
|
4
|
+
spaceXSmall,
|
|
5
|
+
spaceXXSmall
|
|
6
|
+
) from '../../styles/variables/_space.css';
|
|
7
|
+
|
|
8
|
+
@value (
|
|
9
|
+
colorFocusPrimary,
|
|
10
|
+
colorFocusDanger,
|
|
11
|
+
|
|
12
|
+
colorFillDisabled,
|
|
13
|
+
|
|
14
|
+
colorBorderPrimary,
|
|
15
|
+
colorBorderTertiary,
|
|
16
|
+
colorBorderDanger,
|
|
17
|
+
|
|
18
|
+
colorFillPrimary
|
|
19
|
+
) from '../../styles/variables/_color.css';
|
|
20
|
+
|
|
21
|
+
@value (
|
|
22
|
+
borderWidthPrimary,
|
|
23
|
+
borderRadiusMedium,
|
|
24
|
+
borderRadiusSmall,
|
|
25
|
+
borderWidthNone,
|
|
26
|
+
borderWidthTertiary
|
|
27
|
+
) from '../../styles/variables/_border.css';
|
|
28
|
+
|
|
29
|
+
@value (
|
|
30
|
+
size2,
|
|
31
|
+
size8,
|
|
32
|
+
size4,
|
|
33
|
+
size228,
|
|
34
|
+
sizeFluid
|
|
35
|
+
) from '../../styles/variables/_size.css';
|
|
36
|
+
|
|
37
|
+
@value tokenListHeaderHeight: 18px;
|
|
38
|
+
@value smallBoxHeight: 34px;
|
|
39
|
+
@value mediumBoxHeight: 42px;
|
|
40
|
+
|
|
41
|
+
.box {
|
|
42
|
+
display: flex;
|
|
43
|
+
gap: size8;
|
|
44
|
+
align-items: center;
|
|
45
|
+
flex-wrap: wrap;
|
|
46
|
+
width: sizeFluid;
|
|
47
|
+
max-height: size228;
|
|
48
|
+
flex: 0 0 auto;
|
|
49
|
+
overflow: auto;
|
|
50
|
+
cursor: pointer;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.box:not(.withError):not(.inputDisabled):not(.inputLocked):not(.inputHidden) {
|
|
54
|
+
border: borderWidthPrimary solid colorBorderPrimary;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.box:not(.withError):not(.inputDisabled):not(.inputLocked):not(.inputHidden):hover {
|
|
58
|
+
border: borderWidthPrimary solid colorBorderTertiary;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.box:not(.withError):not(.inputDisabled):not(.inputLocked):not(.inputHidden):focus-within {
|
|
62
|
+
border: borderWidthPrimary solid colorFillPrimary;
|
|
63
|
+
box-shadow: borderWidthNone borderWidthNone borderWidthNone
|
|
64
|
+
borderWidthTertiary colorFocusPrimary;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.box.withError {
|
|
68
|
+
border: borderWidthPrimary solid colorBorderDanger;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.box.withError:focus-within {
|
|
72
|
+
border: borderWidthPrimary solid colorBorderDanger;
|
|
73
|
+
box-shadow: borderWidthNone borderWidthNone borderWidthNone
|
|
74
|
+
borderWidthTertiary colorFocusDanger;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.box.inputLocked {
|
|
78
|
+
border: borderWidthPrimary solid colorBorderPrimary;
|
|
79
|
+
border-style: dashed;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.box.inputDisabled {
|
|
83
|
+
border: borderWidthPrimary solid colorBorderPrimary;
|
|
84
|
+
background-color: colorFillDisabled;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.tokenListContainer {
|
|
88
|
+
display: flex;
|
|
89
|
+
position: relative;
|
|
90
|
+
flex-flow: column;
|
|
91
|
+
width: sizeFluid;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.tokenListHeader {
|
|
95
|
+
display: flex;
|
|
96
|
+
width: sizeFluid;
|
|
97
|
+
height: tokenListHeaderHeight;
|
|
98
|
+
justify-content: space-between;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.clearAllButton {
|
|
102
|
+
cursor: pointer;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.clearAllButton:focus-visible {
|
|
106
|
+
box-shadow: borderWidthNone borderWidthNone borderWidthNone
|
|
107
|
+
borderWidthTertiary colorFocusPrimary;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.medium {
|
|
111
|
+
border-radius: borderRadiusMedium;
|
|
112
|
+
padding: spaceXSmall spaceSmall;
|
|
113
|
+
min-height: mediumBoxHeight;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.small {
|
|
117
|
+
border-radius: borderRadiusSmall;
|
|
118
|
+
padding: spaceXXSmall spaceSmall;
|
|
119
|
+
min-height: smallBoxHeight;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.inputMedium {
|
|
123
|
+
composes: formInputMedium from '../../styles/typography.module.css';
|
|
124
|
+
min-width: calc(sizeFluid/4);
|
|
125
|
+
outline: none;
|
|
126
|
+
border: none;
|
|
127
|
+
background-color: transparent;
|
|
128
|
+
padding: spaceNone spaceNone spaceNone spaceNone;
|
|
129
|
+
flex: 1 0;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.inputSmall {
|
|
133
|
+
composes: formInputSmall from '../../styles/typography.module.css';
|
|
134
|
+
min-width: calc(sizeFluid/4);
|
|
135
|
+
outline: none;
|
|
136
|
+
border: none;
|
|
137
|
+
background-color: transparent;
|
|
138
|
+
padding: spaceNone spaceNone spaceNone spaceNone;
|
|
139
|
+
flex: 1 0;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.lockIcon {
|
|
143
|
+
display: flex;
|
|
144
|
+
align-items: center;
|
|
145
|
+
justify-content: center;
|
|
146
|
+
margin-left: auto;
|
|
147
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TokenValueChips = TokenValueChips;
|
|
7
|
+
var React = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _without = _interopRequireDefault(require("lodash/without"));
|
|
9
|
+
var _Chip = require("../Chip");
|
|
10
|
+
var _Tooltip = require("../Tooltip");
|
|
11
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
13
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
14
|
+
|
|
15
|
+
function defaultResolveTokenValue(_ref) {
|
|
16
|
+
let {
|
|
17
|
+
token,
|
|
18
|
+
disabled,
|
|
19
|
+
onDismiss
|
|
20
|
+
} = _ref;
|
|
21
|
+
// $FlowFixMe[prop-missing] - assumes token has label and key
|
|
22
|
+
return (
|
|
23
|
+
/*#__PURE__*/
|
|
24
|
+
// $FlowFixMe - assumes token has label and key
|
|
25
|
+
React.createElement(_Tooltip.Tooltip, {
|
|
26
|
+
body: token?.label
|
|
27
|
+
}, /*#__PURE__*/React.createElement(_Chip.Chip
|
|
28
|
+
// $FlowFixMe - assumes token has key
|
|
29
|
+
, {
|
|
30
|
+
key: token?.key,
|
|
31
|
+
onDismiss: onDismiss,
|
|
32
|
+
dismissable: true,
|
|
33
|
+
semantic: 'primary',
|
|
34
|
+
disabled: disabled
|
|
35
|
+
}, token?.label))
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
function TokenValueChips(props) {
|
|
39
|
+
const {
|
|
40
|
+
values,
|
|
41
|
+
disabled,
|
|
42
|
+
locked,
|
|
43
|
+
onChange,
|
|
44
|
+
resolveTokenValue = defaultResolveTokenValue
|
|
45
|
+
} = props;
|
|
46
|
+
return values.map(token => {
|
|
47
|
+
const onDismiss = e => {
|
|
48
|
+
!disabled && !locked && onChange((0, _without.default)(values, token));
|
|
49
|
+
};
|
|
50
|
+
const resolvedTokenValue = resolveTokenValue({
|
|
51
|
+
token,
|
|
52
|
+
onDismiss,
|
|
53
|
+
disabled,
|
|
54
|
+
locked
|
|
55
|
+
});
|
|
56
|
+
return resolvedTokenValue;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
TokenValueChips.displayName = 'TokenValueChips';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// @flow strict
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import without from 'lodash/without';
|
|
4
|
+
|
|
5
|
+
import {Chip} from '../Chip';
|
|
6
|
+
import {Tooltip} from '../Tooltip';
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
type Props<T> = {
|
|
10
|
+
values: Array<T>,
|
|
11
|
+
disabled?: boolean,
|
|
12
|
+
locked?: boolean,
|
|
13
|
+
onChange: (Array<T>) => mixed,
|
|
14
|
+
resolveTokenValue?: (ResolveTokenValueProps<T>) => React.Node,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type ResolveTokenValueProps<T> = {
|
|
18
|
+
token: T,
|
|
19
|
+
disabled?: boolean,
|
|
20
|
+
onDismiss?: (e: SyntheticEvent<HTMLElement>) => mixed,
|
|
21
|
+
locked?: boolean,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
function defaultResolveTokenValue<T>({
|
|
25
|
+
token,
|
|
26
|
+
disabled,
|
|
27
|
+
onDismiss,
|
|
28
|
+
}: ResolveTokenValueProps<T>): React.Node {
|
|
29
|
+
// $FlowFixMe[prop-missing] - assumes token has label and key
|
|
30
|
+
return (
|
|
31
|
+
// $FlowFixMe - assumes token has label and key
|
|
32
|
+
<Tooltip body={token?.label}>
|
|
33
|
+
<Chip
|
|
34
|
+
// $FlowFixMe - assumes token has key
|
|
35
|
+
key={token?.key}
|
|
36
|
+
onDismiss={onDismiss}
|
|
37
|
+
dismissable={true}
|
|
38
|
+
semantic={'primary'}
|
|
39
|
+
disabled={disabled}
|
|
40
|
+
>
|
|
41
|
+
{/* $FlowFixMe - assumes token has label */}
|
|
42
|
+
{token?.label}
|
|
43
|
+
</Chip>
|
|
44
|
+
</Tooltip>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function TokenValueChips<T>(props: Props<T>): React.Node {
|
|
49
|
+
const {
|
|
50
|
+
values,
|
|
51
|
+
disabled,
|
|
52
|
+
locked,
|
|
53
|
+
onChange,
|
|
54
|
+
resolveTokenValue = defaultResolveTokenValue,
|
|
55
|
+
} = props;
|
|
56
|
+
|
|
57
|
+
return values.map((token) => {
|
|
58
|
+
const onDismiss = (e) => {
|
|
59
|
+
!disabled && !locked && onChange(without(values, token));
|
|
60
|
+
};
|
|
61
|
+
const resolvedTokenValue = resolveTokenValue({
|
|
62
|
+
token,
|
|
63
|
+
onDismiss,
|
|
64
|
+
disabled,
|
|
65
|
+
locked,
|
|
66
|
+
});
|
|
67
|
+
return resolvedTokenValue;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
TokenValueChips.displayName = 'TokenValueChips';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _TokenListInput = require("./TokenListInput");
|
|
7
|
+
Object.keys(_TokenListInput).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _TokenListInput[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _TokenListInput[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
package/lib/components/index.js
CHANGED
|
@@ -718,6 +718,17 @@ Object.keys(_Toggle).forEach(function (key) {
|
|
|
718
718
|
}
|
|
719
719
|
});
|
|
720
720
|
});
|
|
721
|
+
var _TokenListInput = require("./TokenListInput");
|
|
722
|
+
Object.keys(_TokenListInput).forEach(function (key) {
|
|
723
|
+
if (key === "default" || key === "__esModule") return;
|
|
724
|
+
if (key in exports && exports[key] === _TokenListInput[key]) return;
|
|
725
|
+
Object.defineProperty(exports, key, {
|
|
726
|
+
enumerable: true,
|
|
727
|
+
get: function () {
|
|
728
|
+
return _TokenListInput[key];
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
});
|
|
721
732
|
var _Tooltip = require("./Tooltip");
|
|
722
733
|
Object.keys(_Tooltip).forEach(function (key) {
|
|
723
734
|
if (key === "default" || key === "__esModule") return;
|
package/lib/hooks/index.js
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
var _useArbitraryOptionAddition = require("./useArbitraryOptionAddition");
|
|
7
|
+
Object.keys(_useArbitraryOptionAddition).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _useArbitraryOptionAddition[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _useArbitraryOptionAddition[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
|
6
17
|
var _useCopyToClipboard = require("./useCopyToClipboard");
|
|
7
18
|
Object.keys(_useCopyToClipboard).forEach(function (key) {
|
|
8
19
|
if (key === "default" || key === "__esModule") return;
|
|
@@ -25,6 +36,17 @@ Object.keys(_useFileUpload).forEach(function (key) {
|
|
|
25
36
|
}
|
|
26
37
|
});
|
|
27
38
|
});
|
|
39
|
+
var _useFilteredOptions = require("./useFilteredOptions");
|
|
40
|
+
Object.keys(_useFilteredOptions).forEach(function (key) {
|
|
41
|
+
if (key === "default" || key === "__esModule") return;
|
|
42
|
+
if (key in exports && exports[key] === _useFilteredOptions[key]) return;
|
|
43
|
+
Object.defineProperty(exports, key, {
|
|
44
|
+
enumerable: true,
|
|
45
|
+
get: function () {
|
|
46
|
+
return _useFilteredOptions[key];
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
});
|
|
28
50
|
var _useInputState = require("./useInputState");
|
|
29
51
|
Object.keys(_useInputState).forEach(function (key) {
|
|
30
52
|
if (key === "default" || key === "__esModule") return;
|
package/lib/hooks/index.js.flow
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// @flow strict
|
|
2
2
|
|
|
3
|
+
export * from './useArbitraryOptionAddition';
|
|
3
4
|
export * from './useCopyToClipboard';
|
|
4
5
|
export * from './useFileUpload';
|
|
6
|
+
export * from './useFilteredOptions';
|
|
5
7
|
export * from './useInputState';
|
|
6
8
|
export * from './useLockedBody';
|
|
7
9
|
export * from './useModal';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _useArbitraryOptionAddition = require("./useArbitraryOptionAddition");
|
|
7
|
+
Object.keys(_useArbitraryOptionAddition).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _useArbitraryOptionAddition[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _useArbitraryOptionAddition[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useArbitraryOptionAddition = useArbitraryOptionAddition;
|
|
7
|
+
var _useFilteredOptions = require("../useFilteredOptions");
|
|
8
|
+
|
|
9
|
+
function useArbitraryOptionAddition(_ref) {
|
|
10
|
+
let {
|
|
11
|
+
searchTerm,
|
|
12
|
+
options = [],
|
|
13
|
+
excludedKeys = [],
|
|
14
|
+
allowArbitraryValues = true,
|
|
15
|
+
allowMultiArbitraryValues = false,
|
|
16
|
+
validateArbitraryValue = value => value.trim() !== '',
|
|
17
|
+
// $FlowFixMe[incompatible-return] - Object literal is compatible with V due to type constraint
|
|
18
|
+
makeArbitraryValue = searchTerm => ({
|
|
19
|
+
key: searchTerm,
|
|
20
|
+
label: searchTerm,
|
|
21
|
+
arbitrary: true
|
|
22
|
+
}),
|
|
23
|
+
// $FlowFixMe[incompatible-return] - Object literal is compatible with V due to type constraint
|
|
24
|
+
makeMultiArbitraryValue = searchTerm => {
|
|
25
|
+
const regex = /^(?=.*[,\n]).+$/s;
|
|
26
|
+
if (regex.test(searchTerm)) {
|
|
27
|
+
// $FlowFixMe - Object literal is compatible with V due to type constraint
|
|
28
|
+
return {
|
|
29
|
+
key: searchTerm,
|
|
30
|
+
label: searchTerm,
|
|
31
|
+
multiArbitrary: true
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
groupTitleOptions = [],
|
|
36
|
+
arbitraryGroup = {
|
|
37
|
+
groupTitle: '',
|
|
38
|
+
showLineDivider: false,
|
|
39
|
+
options: []
|
|
40
|
+
},
|
|
41
|
+
searchOptionsBy = (option, searchTerm) => {
|
|
42
|
+
// $FlowFixMe
|
|
43
|
+
const {
|
|
44
|
+
label,
|
|
45
|
+
key
|
|
46
|
+
} = option;
|
|
47
|
+
return key.toLowerCase().includes(searchTerm) || label.toLowerCase().includes(searchTerm);
|
|
48
|
+
}
|
|
49
|
+
} = _ref;
|
|
50
|
+
const trimmedSearchTerm = (searchTerm || '').trim().toLowerCase();
|
|
51
|
+
const {
|
|
52
|
+
filteredOptions,
|
|
53
|
+
filteredGroupTitleOptions
|
|
54
|
+
} = (0, _useFilteredOptions.useFilteredOptions)({
|
|
55
|
+
searchTerm: trimmedSearchTerm,
|
|
56
|
+
options,
|
|
57
|
+
// $FlowFixMe[incompatible-call]
|
|
58
|
+
groupTitleOptions,
|
|
59
|
+
searchOptionsBy
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// Find if an arbitrary option should be added
|
|
63
|
+
const arbitraryOption = allowArbitraryValues && trimmedSearchTerm &&
|
|
64
|
+
// $FlowFixMe - Array methods are valid here
|
|
65
|
+
!filteredOptions.some(option => option.key === trimmedSearchTerm) &&
|
|
66
|
+
// $FlowFixMe - Array methods are valid here
|
|
67
|
+
!filteredGroupTitleOptions.some(group => Array.isArray(group.options) &&
|
|
68
|
+
// $FlowFixMe- option has key property
|
|
69
|
+
group.options.some(option => option.key === trimmedSearchTerm)) && !excludedKeys.includes(trimmedSearchTerm) && validateArbitraryValue(trimmedSearchTerm) && makeArbitraryValue(trimmedSearchTerm);
|
|
70
|
+
|
|
71
|
+
// Find if a multi-arbitrary option should be added
|
|
72
|
+
const multiArbitraryOption = allowMultiArbitraryValues && trimmedSearchTerm && makeMultiArbitraryValue(trimmedSearchTerm);
|
|
73
|
+
|
|
74
|
+
// Compose the results
|
|
75
|
+
let optionsWithArbitrary = filteredOptions;
|
|
76
|
+
let groupTitleOptionsWithArbitrary = groupTitleOptions;
|
|
77
|
+
if (arbitraryOption) {
|
|
78
|
+
// $FlowFixMe[incompatible-type] - Array spread is valid here
|
|
79
|
+
optionsWithArbitrary = [arbitraryOption, ...optionsWithArbitrary];
|
|
80
|
+
groupTitleOptionsWithArbitrary = [{
|
|
81
|
+
...arbitraryGroup,
|
|
82
|
+
options: [arbitraryOption]
|
|
83
|
+
}, ...groupTitleOptionsWithArbitrary];
|
|
84
|
+
}
|
|
85
|
+
if (multiArbitraryOption) {
|
|
86
|
+
// $FlowFixMe[incompatible-type] - Array spread is valid here
|
|
87
|
+
optionsWithArbitrary = [multiArbitraryOption, ...optionsWithArbitrary];
|
|
88
|
+
groupTitleOptionsWithArbitrary = [{
|
|
89
|
+
...arbitraryGroup,
|
|
90
|
+
options: [multiArbitraryOption]
|
|
91
|
+
}, ...groupTitleOptionsWithArbitrary];
|
|
92
|
+
}
|
|
93
|
+
// $FlowFixMe[incompatible-return]
|
|
94
|
+
return {
|
|
95
|
+
optionsWithArbitrary,
|
|
96
|
+
groupTitleOptionsWithArbitrary
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// @flow strict
|
|
2
|
+
|
|
3
|
+
import type {GroupTitleOption} from '../useFilteredOptions';
|
|
4
|
+
import {useFilteredOptions} from '../useFilteredOptions';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
export type ArbitraryOption = {
|
|
8
|
+
key: string,
|
|
9
|
+
label: string,
|
|
10
|
+
arbitrary?: boolean,
|
|
11
|
+
multiArbitrary?: boolean,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function useArbitraryOptionAddition<V>({
|
|
15
|
+
searchTerm,
|
|
16
|
+
options = [],
|
|
17
|
+
excludedKeys = [],
|
|
18
|
+
allowArbitraryValues = true,
|
|
19
|
+
allowMultiArbitraryValues = false,
|
|
20
|
+
validateArbitraryValue = (value: string): boolean => value.trim() !== '',
|
|
21
|
+
// $FlowFixMe[incompatible-return] - Object literal is compatible with V due to type constraint
|
|
22
|
+
makeArbitraryValue = (searchTerm): V => ({
|
|
23
|
+
key: searchTerm,
|
|
24
|
+
label: searchTerm,
|
|
25
|
+
arbitrary: true,
|
|
26
|
+
}),
|
|
27
|
+
// $FlowFixMe[incompatible-return] - Object literal is compatible with V due to type constraint
|
|
28
|
+
makeMultiArbitraryValue = (searchTerm): V => {
|
|
29
|
+
const regex = /^(?=.*[,\n]).+$/s;
|
|
30
|
+
if (regex.test(searchTerm)) {
|
|
31
|
+
// $FlowFixMe - Object literal is compatible with V due to type constraint
|
|
32
|
+
return {key: searchTerm, label: searchTerm, multiArbitrary: true};
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
groupTitleOptions = [],
|
|
36
|
+
arbitraryGroup = {groupTitle: '', showLineDivider: false, options: []},
|
|
37
|
+
searchOptionsBy = (option: V, searchTerm: string): boolean => {
|
|
38
|
+
// $FlowFixMe
|
|
39
|
+
const {label, key}: {label: string, key: string} = option;
|
|
40
|
+
return (
|
|
41
|
+
key.toLowerCase().includes(searchTerm) ||
|
|
42
|
+
label.toLowerCase().includes(searchTerm)
|
|
43
|
+
);
|
|
44
|
+
},
|
|
45
|
+
}: {
|
|
46
|
+
searchTerm: string,
|
|
47
|
+
options?: V[],
|
|
48
|
+
excludedKeys?: string[],
|
|
49
|
+
allowArbitraryValues?: boolean,
|
|
50
|
+
allowMultiArbitraryValues?: boolean,
|
|
51
|
+
validateArbitraryValue?: (string) => boolean,
|
|
52
|
+
makeArbitraryValue?: (string) => V,
|
|
53
|
+
makeMultiArbitraryValue?: (string) => V,
|
|
54
|
+
groupTitleOptions?: GroupTitleOption<V>[],
|
|
55
|
+
arbitraryGroup?: GroupTitleOption<V>,
|
|
56
|
+
searchOptionsBy?: (option: V, searchTerm: string) => boolean,
|
|
57
|
+
}): {
|
|
58
|
+
optionsWithArbitrary: Array<V>,
|
|
59
|
+
groupTitleOptionsWithArbitrary: Array<GroupTitleOption<V>>,
|
|
60
|
+
} {
|
|
61
|
+
const trimmedSearchTerm = (searchTerm || '').trim().toLowerCase();
|
|
62
|
+
|
|
63
|
+
const {filteredOptions, filteredGroupTitleOptions} = useFilteredOptions({
|
|
64
|
+
searchTerm: trimmedSearchTerm,
|
|
65
|
+
options,
|
|
66
|
+
// $FlowFixMe[incompatible-call]
|
|
67
|
+
groupTitleOptions,
|
|
68
|
+
searchOptionsBy,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Find if an arbitrary option should be added
|
|
72
|
+
const arbitraryOption =
|
|
73
|
+
allowArbitraryValues &&
|
|
74
|
+
trimmedSearchTerm &&
|
|
75
|
+
// $FlowFixMe - Array methods are valid here
|
|
76
|
+
!filteredOptions.some((option) => option.key === trimmedSearchTerm) &&
|
|
77
|
+
// $FlowFixMe - Array methods are valid here
|
|
78
|
+
!filteredGroupTitleOptions.some(
|
|
79
|
+
(group) =>
|
|
80
|
+
Array.isArray(group.options) &&
|
|
81
|
+
// $FlowFixMe- option has key property
|
|
82
|
+
group.options.some((option) => option.key === trimmedSearchTerm),
|
|
83
|
+
) &&
|
|
84
|
+
!excludedKeys.includes(trimmedSearchTerm) &&
|
|
85
|
+
validateArbitraryValue(trimmedSearchTerm) &&
|
|
86
|
+
makeArbitraryValue(trimmedSearchTerm);
|
|
87
|
+
|
|
88
|
+
// Find if a multi-arbitrary option should be added
|
|
89
|
+
const multiArbitraryOption =
|
|
90
|
+
allowMultiArbitraryValues &&
|
|
91
|
+
trimmedSearchTerm &&
|
|
92
|
+
makeMultiArbitraryValue(trimmedSearchTerm);
|
|
93
|
+
|
|
94
|
+
// Compose the results
|
|
95
|
+
let optionsWithArbitrary = filteredOptions;
|
|
96
|
+
let groupTitleOptionsWithArbitrary = groupTitleOptions;
|
|
97
|
+
|
|
98
|
+
if (arbitraryOption) {
|
|
99
|
+
// $FlowFixMe[incompatible-type] - Array spread is valid here
|
|
100
|
+
optionsWithArbitrary = [arbitraryOption, ...optionsWithArbitrary];
|
|
101
|
+
groupTitleOptionsWithArbitrary = [
|
|
102
|
+
{...arbitraryGroup, options: [arbitraryOption]},
|
|
103
|
+
...groupTitleOptionsWithArbitrary,
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (multiArbitraryOption) {
|
|
108
|
+
// $FlowFixMe[incompatible-type] - Array spread is valid here
|
|
109
|
+
optionsWithArbitrary = [multiArbitraryOption, ...optionsWithArbitrary];
|
|
110
|
+
groupTitleOptionsWithArbitrary = [
|
|
111
|
+
{...arbitraryGroup, options: [multiArbitraryOption]},
|
|
112
|
+
...groupTitleOptionsWithArbitrary,
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
// $FlowFixMe[incompatible-return]
|
|
116
|
+
return {optionsWithArbitrary, groupTitleOptionsWithArbitrary};
|
|
117
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _useFilteredOptions = require("./useFilteredOptions");
|
|
7
|
+
Object.keys(_useFilteredOptions).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _useFilteredOptions[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _useFilteredOptions[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|