@grafana/scenes 5.13.0--canary.878.10702174754.0 β 5.13.1--canary.889.10720020573.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +26 -0
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/AdHocFilterPill.js +7 -2
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/AdHocFilterPill.js.map +1 -1
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersCombobox.js +213 -47
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersCombobox.js.map +1 -1
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/DropdownItem.js +40 -4
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/DropdownItem.js.map +1 -1
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/useFloatingInteractions.js +8 -2
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/useFloatingInteractions.js.map +1 -1
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/utils.js +6 -2
- package/dist/esm/variables/adhoc/AdHocFiltersCombobox/utils.js.map +1 -1
- package/dist/esm/variables/adhoc/AdHocFiltersVariable.js +2 -2
- package/dist/esm/variables/adhoc/AdHocFiltersVariable.js.map +1 -1
- package/dist/index.js +267 -51
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
# v5.13.0 (Wed Sep 04 2024)
|
2
|
+
|
3
|
+
### Release Notes
|
4
|
+
|
5
|
+
#### UrlSync: Support browser history steps, remove singleton ([#878](https://github.com/grafana/scenes/pull/878))
|
6
|
+
|
7
|
+
getUrlSyncManager is no longer exported as UrlSyncManager is now no longer global singleton but local to the UrlSyncContextProvider.
|
8
|
+
If you called getUrlSyncManager().getUrlState that util function is available via the exported object sceneUtils.
|
9
|
+
|
10
|
+
---
|
11
|
+
|
12
|
+
#### π Enhancement
|
13
|
+
|
14
|
+
- UrlSync: Support browser history steps, remove singleton [#878](https://github.com/grafana/scenes/pull/878) ([@torkelo](https://github.com/torkelo))
|
15
|
+
|
16
|
+
#### π Bug Fix
|
17
|
+
|
18
|
+
- chore: export SceneDataTransformerState [#888](https://github.com/grafana/scenes/pull/888) ([@jewbetcha](https://github.com/jewbetcha))
|
19
|
+
|
20
|
+
#### Authors: 2
|
21
|
+
|
22
|
+
- Coleman Rollins ([@jewbetcha](https://github.com/jewbetcha))
|
23
|
+
- Torkel Γdegaard ([@torkelo](https://github.com/torkelo))
|
24
|
+
|
25
|
+
---
|
26
|
+
|
1
27
|
# v5.12.0 (Tue Sep 03 2024)
|
2
28
|
|
3
29
|
#### π Enhancement
|
@@ -29,7 +29,7 @@ function AdHocFilterPill({ filter, model, readOnly }) {
|
|
29
29
|
const [shouldFocus, setShouldFocus] = useState(false);
|
30
30
|
const pillWrapperRef = useRef(null);
|
31
31
|
const keyLabel = (_a = filter.keyLabel) != null ? _a : filter.key;
|
32
|
-
const valueLabel = (
|
32
|
+
const valueLabel = ((_b = filter.valueLabels) == null ? void 0 : _b.join(", ")) || ((_c = filter.values) == null ? void 0 : _c.join(", ")) || filter.value;
|
33
33
|
const handleChangeViewMode = useCallback(
|
34
34
|
(event) => {
|
35
35
|
event == null ? void 0 : event.stopPropagation();
|
@@ -61,7 +61,9 @@ function AdHocFilterPill({ filter, model, readOnly }) {
|
|
61
61
|
"aria-label": `Edit filter with key ${keyLabel}`,
|
62
62
|
tabIndex: 0,
|
63
63
|
ref: pillWrapperRef
|
64
|
-
}, /* @__PURE__ */ React.createElement("span",
|
64
|
+
}, /* @__PURE__ */ React.createElement("span", {
|
65
|
+
className: styles.pillText
|
66
|
+
}, keyLabel, " ", filter.operator, " ", valueLabel), !readOnly ? /* @__PURE__ */ React.createElement(IconButton, {
|
65
67
|
onClick: (e) => {
|
66
68
|
e.stopPropagation();
|
67
69
|
model._removeFilter(filter);
|
@@ -117,6 +119,9 @@ const getStyles = (theme) => ({
|
|
117
119
|
"&:hover": {
|
118
120
|
color: theme.colors.text.primary
|
119
121
|
}
|
122
|
+
}),
|
123
|
+
pillText: css({
|
124
|
+
whiteSpace: "break-spaces"
|
120
125
|
})
|
121
126
|
});
|
122
127
|
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"AdHocFilterPill.js","sources":["../../../../../src/variables/adhoc/AdHocFiltersCombobox/AdHocFilterPill.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { useStyles2, IconButton } from '@grafana/ui';\nimport React, { useState, useRef, useCallback, useEffect } from 'react';\nimport { AdHocCombobox } from './AdHocFiltersCombobox';\nimport { AdHocFilterWithLabels, AdHocFiltersVariable } from '../AdHocFiltersVariable';\n\ninterface Props {\n filter: AdHocFilterWithLabels;\n model: AdHocFiltersVariable;\n readOnly?: boolean;\n}\n\nexport function AdHocFilterPill({ filter, model, readOnly }: Props) {\n const styles = useStyles2(getStyles);\n const [viewMode, setViewMode] = useState(true);\n const [shouldFocus, setShouldFocus] = useState(false);\n const pillWrapperRef = useRef<HTMLDivElement>(null);\n\n const keyLabel = filter.keyLabel ?? filter.key;\n const valueLabel = filter.valueLabels?.
|
1
|
+
{"version":3,"file":"AdHocFilterPill.js","sources":["../../../../../src/variables/adhoc/AdHocFiltersCombobox/AdHocFilterPill.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { useStyles2, IconButton } from '@grafana/ui';\nimport React, { useState, useRef, useCallback, useEffect } from 'react';\nimport { AdHocCombobox } from './AdHocFiltersCombobox';\nimport { AdHocFilterWithLabels, AdHocFiltersVariable } from '../AdHocFiltersVariable';\n\ninterface Props {\n filter: AdHocFilterWithLabels;\n model: AdHocFiltersVariable;\n readOnly?: boolean;\n}\n\nexport function AdHocFilterPill({ filter, model, readOnly }: Props) {\n const styles = useStyles2(getStyles);\n const [viewMode, setViewMode] = useState(true);\n const [shouldFocus, setShouldFocus] = useState(false);\n const pillWrapperRef = useRef<HTMLDivElement>(null);\n\n const keyLabel = filter.keyLabel ?? filter.key;\n //@ts-expect-error\n const valueLabel = filter.valueLabels?.join(', ') || filter.values?.join(', ') || filter.value;\n\n const handleChangeViewMode = useCallback(\n (event?: React.MouseEvent) => {\n event?.stopPropagation();\n if (readOnly) {\n return;\n }\n\n setShouldFocus(!viewMode);\n setViewMode(!viewMode);\n },\n [readOnly, viewMode]\n );\n\n useEffect(() => {\n if (shouldFocus) {\n pillWrapperRef.current?.focus();\n setShouldFocus(false);\n }\n }, [shouldFocus]);\n\n if (viewMode) {\n return (\n <div\n className={cx(styles.combinedFilterPill, { [styles.readOnlyCombinedFilter]: readOnly })}\n onClick={handleChangeViewMode}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n handleChangeViewMode();\n }\n }}\n role=\"button\"\n aria-label={`Edit filter with key ${keyLabel}`}\n tabIndex={0}\n ref={pillWrapperRef}\n >\n <span className={styles.pillText}>\n {keyLabel} {filter.operator} {valueLabel}\n </span>\n {!readOnly ? (\n <IconButton\n onClick={(e) => {\n e.stopPropagation();\n model._removeFilter(filter);\n }}\n onKeyDownCapture={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n e.stopPropagation();\n model._removeFilter(filter);\n }\n }}\n name=\"times\"\n size=\"md\"\n className={styles.removeButton}\n tooltip={`Remove filter with key ${keyLabel}`}\n />\n ) : null}\n </div>\n );\n }\n\n return <AdHocCombobox filter={filter} model={model} handleChangeViewMode={handleChangeViewMode} />;\n}\n\nconst getStyles = (theme: GrafanaTheme2) => ({\n combinedFilterPill: css({\n display: 'flex',\n alignItems: 'center',\n background: theme.colors.action.selected,\n borderRadius: theme.shape.radius.default,\n border: `1px solid ${theme.colors.border.weak}`,\n padding: theme.spacing(0.125, 0, 0.125, 1),\n color: theme.colors.text.primary,\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n minHeight: theme.spacing(2.75),\n ...theme.typography.bodySmall,\n fontWeight: theme.typography.fontWeightBold,\n cursor: 'pointer',\n\n '&:hover': {\n background: theme.colors.action.hover,\n },\n }),\n readOnlyCombinedFilter: css({\n paddingRight: theme.spacing(1),\n cursor: 'text',\n '&:hover': {\n background: theme.colors.action.selected,\n },\n }),\n removeButton: css({\n marginInline: theme.spacing(0.5),\n cursor: 'pointer',\n '&:hover': {\n color: theme.colors.text.primary,\n },\n }),\n pillText: css({\n whiteSpace: 'break-spaces',\n }),\n});\n"],"names":["_a"],"mappings":"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"}
|
@@ -1,10 +1,11 @@
|
|
1
|
-
import React, { forwardRef, useState, useId, useRef,
|
1
|
+
import React, { forwardRef, useState, useMemo, useId, useRef, useCallback, useImperativeHandle, useEffect, useLayoutEffect } from 'react';
|
2
2
|
import { FloatingPortal, FloatingFocusManager } from '@floating-ui/react';
|
3
|
-
import { useStyles2, Spinner, Text } from '@grafana/ui';
|
3
|
+
import { useStyles2, Spinner, Text, Button, Icon } from '@grafana/ui';
|
4
4
|
import { cx, css } from '@emotion/css';
|
5
|
+
import { OPERATORS } from '../AdHocFiltersVariable.js';
|
5
6
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
6
|
-
import { LoadingOptionsPlaceholder, OptionsErrorPlaceholder, NoOptionsPlaceholder, DropdownItem } from './DropdownItem.js';
|
7
|
-
import { fuzzySearchOptions, flattenOptionGroups, setupDropdownAccessibility, VIRTUAL_LIST_ITEM_HEIGHT, VIRTUAL_LIST_OVERSCAN, generateFilterUpdatePayload, switchToNextInputType, switchInputType, ERROR_STATE_DROPDOWN_WIDTH } from './utils.js';
|
7
|
+
import { LoadingOptionsPlaceholder, OptionsErrorPlaceholder, NoOptionsPlaceholder, DropdownItem, MultiValueApplyButton } from './DropdownItem.js';
|
8
|
+
import { fuzzySearchOptions, flattenOptionGroups, setupDropdownAccessibility, VIRTUAL_LIST_ITEM_HEIGHT_WITH_DESCRIPTION, VIRTUAL_LIST_ITEM_HEIGHT, VIRTUAL_LIST_OVERSCAN, generateFilterUpdatePayload, switchToNextInputType, switchInputType, ERROR_STATE_DROPDOWN_WIDTH } from './utils.js';
|
8
9
|
import { handleOptionGroups } from '../../utils.js';
|
9
10
|
import { useFloatingInteractions } from './useFloatingInteractions.js';
|
10
11
|
|
@@ -37,6 +38,14 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
|
|
37
38
|
const [activeIndex, setActiveIndex] = useState(null);
|
38
39
|
const [filterInputType, setInputType] = useState(!isAlwaysWip ? "value" : "key");
|
39
40
|
const styles = useStyles2(getStyles);
|
41
|
+
const [filterMultiValues, setFilterMultiValues] = useState([]);
|
42
|
+
const [_, setForceRefresh] = useState({});
|
43
|
+
const multiValueOperators = useMemo(
|
44
|
+
() => OPERATORS.reduce((acc, operator) => operator.isMulti ? [...acc, operator.value] : acc, []),
|
45
|
+
[]
|
46
|
+
);
|
47
|
+
const hasMultiValueOperator = multiValueOperators.includes((filter == null ? void 0 : filter.operator) || "");
|
48
|
+
const isMultiValueEdit = hasMultiValueOperator && filterInputType === "value";
|
40
49
|
const operatorIdentifier = useId();
|
41
50
|
const listRef = useRef([]);
|
42
51
|
const disabledIndicesRef = useRef([]);
|
@@ -48,22 +57,60 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
|
|
48
57
|
setInputValue("");
|
49
58
|
}
|
50
59
|
}, [model, isAlwaysWip]);
|
60
|
+
const handleMultiValueUpdate = useCallback(
|
61
|
+
(model2, filter2, filterMultiValues2) => {
|
62
|
+
if (filterMultiValues2.length) {
|
63
|
+
const valueLabels = [];
|
64
|
+
const values = [];
|
65
|
+
filterMultiValues2.forEach((item) => {
|
66
|
+
var _a2;
|
67
|
+
valueLabels.push((_a2 = item.label) != null ? _a2 : item.value);
|
68
|
+
values.push(item.value);
|
69
|
+
});
|
70
|
+
model2._updateFilter(filter2, { valueLabels, values, value: values[0] });
|
71
|
+
setFilterMultiValues([]);
|
72
|
+
}
|
73
|
+
setTimeout(() => {
|
74
|
+
var _a2;
|
75
|
+
return (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
|
76
|
+
});
|
77
|
+
},
|
78
|
+
[]
|
79
|
+
);
|
80
|
+
const handleAddMultiValue = useCallback((selectedItem) => {
|
81
|
+
setFilterMultiValues((items) => {
|
82
|
+
if (items.some((item) => item.value === selectedItem.value)) {
|
83
|
+
return items.filter((item) => item.value !== selectedItem.value);
|
84
|
+
}
|
85
|
+
return [...items, selectedItem];
|
86
|
+
});
|
87
|
+
}, []);
|
88
|
+
const handleRemoveMultiValue = useCallback(
|
89
|
+
(item) => setFilterMultiValues((selected) => selected.filter((option) => option.value !== item.value)),
|
90
|
+
[]
|
91
|
+
);
|
51
92
|
const onOpenChange = useCallback(
|
52
|
-
(nextOpen,
|
93
|
+
(nextOpen, _2, reason) => {
|
53
94
|
setOpen(nextOpen);
|
54
95
|
if (reason && ["outside-press", "escape-key"].includes(reason)) {
|
96
|
+
if (isMultiValueEdit) {
|
97
|
+
handleMultiValueUpdate(model, filter, filterMultiValues);
|
98
|
+
}
|
55
99
|
handleResetWip();
|
56
100
|
handleChangeViewMode == null ? void 0 : handleChangeViewMode();
|
57
101
|
}
|
58
102
|
},
|
59
|
-
[handleChangeViewMode, handleResetWip]
|
103
|
+
[filter, filterMultiValues, handleChangeViewMode, handleMultiValueUpdate, handleResetWip, isMultiValueEdit, model]
|
60
104
|
);
|
105
|
+
const outsidePressIdsToIgnore = useMemo(() => {
|
106
|
+
return [operatorIdentifier, ...filterMultiValues.map((item, i) => `${item.value}-${i}`)];
|
107
|
+
}, [operatorIdentifier, filterMultiValues]);
|
61
108
|
const { refs, floatingStyles, context, getReferenceProps, getFloatingProps, getItemProps } = useFloatingInteractions({
|
62
109
|
open,
|
63
110
|
onOpenChange,
|
64
111
|
activeIndex,
|
65
112
|
setActiveIndex,
|
66
|
-
|
113
|
+
outsidePressIdsToIgnore,
|
67
114
|
listRef,
|
68
115
|
disabledIndicesRef
|
69
116
|
});
|
@@ -114,24 +161,41 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
|
|
114
161
|
const rowVirtualizer = useVirtualizer({
|
115
162
|
count: filteredDropDownItems.length,
|
116
163
|
getScrollElement: () => refs.floating.current,
|
117
|
-
estimateSize: () => VIRTUAL_LIST_ITEM_HEIGHT,
|
164
|
+
estimateSize: (index) => filteredDropDownItems[index].description ? VIRTUAL_LIST_ITEM_HEIGHT_WITH_DESCRIPTION : VIRTUAL_LIST_ITEM_HEIGHT,
|
118
165
|
overscan: VIRTUAL_LIST_OVERSCAN
|
119
166
|
});
|
120
167
|
const handleBackspaceInput = useCallback(
|
121
|
-
(event) => {
|
122
|
-
if (event.key === "Backspace" && !inputValue
|
123
|
-
|
124
|
-
|
168
|
+
(event, multiValueEdit) => {
|
169
|
+
if (event.key === "Backspace" && !inputValue) {
|
170
|
+
if (multiValueEdit) {
|
171
|
+
setFilterMultiValues((items) => {
|
172
|
+
const updated = [...items];
|
173
|
+
updated.splice(-1, 1);
|
174
|
+
return updated;
|
175
|
+
});
|
176
|
+
} else if (filterInputType === "key") {
|
177
|
+
model._removeLastFilter();
|
178
|
+
handleFetchOptions(filterInputType);
|
179
|
+
}
|
125
180
|
}
|
126
181
|
},
|
127
|
-
[inputValue, filterInputType]
|
182
|
+
[inputValue, filterInputType, model, handleFetchOptions]
|
183
|
+
);
|
184
|
+
const handleTabInput = useCallback(
|
185
|
+
(event, multiValueEdit) => {
|
186
|
+
var _a2;
|
187
|
+
if (event.key === "Tab" && !event.shiftKey) {
|
188
|
+
if (multiValueEdit) {
|
189
|
+
event.preventDefault();
|
190
|
+
handleMultiValueUpdate(model, filter, filterMultiValues);
|
191
|
+
(_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
|
192
|
+
}
|
193
|
+
handleChangeViewMode == null ? void 0 : handleChangeViewMode();
|
194
|
+
handleResetWip();
|
195
|
+
}
|
196
|
+
},
|
197
|
+
[filter, filterMultiValues, handleChangeViewMode, handleMultiValueUpdate, handleResetWip, model, refs.domReference]
|
128
198
|
);
|
129
|
-
const handleTabInput = useCallback((event) => {
|
130
|
-
if (event.key === "Tab" && !event.shiftKey) {
|
131
|
-
handleChangeViewMode == null ? void 0 : handleChangeViewMode();
|
132
|
-
handleResetWip();
|
133
|
-
}
|
134
|
-
}, []);
|
135
199
|
const handleShiftTabInput = useCallback((event) => {
|
136
200
|
if (event.key === "Tab" && event.shiftKey) {
|
137
201
|
handleChangeViewMode == null ? void 0 : handleChangeViewMode();
|
@@ -139,18 +203,32 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
|
|
139
203
|
}
|
140
204
|
}, []);
|
141
205
|
const handleEnterInput = useCallback(
|
142
|
-
(event) => {
|
206
|
+
(event, multiValueEdit) => {
|
143
207
|
if (event.key === "Enter" && activeIndex != null) {
|
144
208
|
if (!filteredDropDownItems[activeIndex]) {
|
145
209
|
return;
|
146
210
|
}
|
147
|
-
|
211
|
+
const selectedItem = filteredDropDownItems[activeIndex];
|
212
|
+
if (multiValueEdit) {
|
213
|
+
handleAddMultiValue(selectedItem);
|
214
|
+
} else {
|
215
|
+
model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, selectedItem));
|
216
|
+
switchToNextInputType(filterInputType, setInputType, handleChangeViewMode, refs.domReference.current);
|
217
|
+
setActiveIndex(0);
|
218
|
+
}
|
148
219
|
setInputValue("");
|
149
|
-
setActiveIndex(0);
|
150
|
-
switchToNextInputType(filterInputType, setInputType, handleChangeViewMode, refs.domReference.current);
|
151
220
|
}
|
152
221
|
},
|
153
|
-
[
|
222
|
+
[
|
223
|
+
activeIndex,
|
224
|
+
filter,
|
225
|
+
filterInputType,
|
226
|
+
filteredDropDownItems,
|
227
|
+
handleAddMultiValue,
|
228
|
+
handleChangeViewMode,
|
229
|
+
model,
|
230
|
+
refs.domReference
|
231
|
+
]
|
154
232
|
);
|
155
233
|
useEffect(() => {
|
156
234
|
if (open) {
|
@@ -158,13 +236,34 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
|
|
158
236
|
}
|
159
237
|
}, [open, filterInputType]);
|
160
238
|
useEffect(() => {
|
161
|
-
var _a2;
|
239
|
+
var _a2, _b2;
|
162
240
|
if (!isAlwaysWip) {
|
163
241
|
setInputType("value");
|
164
242
|
setInputValue("");
|
165
|
-
(_a2 =
|
243
|
+
if (hasMultiValueOperator && ((_a2 = filter == null ? void 0 : filter.values) == null ? void 0 : _a2.length)) {
|
244
|
+
const multiValueOptions = filter.values.reduce(
|
245
|
+
(acc, value, i) => {
|
246
|
+
var _a3;
|
247
|
+
return [
|
248
|
+
...acc,
|
249
|
+
{
|
250
|
+
label: ((_a3 = filter.valueLabels) == null ? void 0 : _a3[i]) || value,
|
251
|
+
value
|
252
|
+
}
|
253
|
+
];
|
254
|
+
},
|
255
|
+
[]
|
256
|
+
);
|
257
|
+
setFilterMultiValues(multiValueOptions);
|
258
|
+
}
|
259
|
+
(_b2 = refs.domReference.current) == null ? void 0 : _b2.focus();
|
166
260
|
}
|
167
261
|
}, []);
|
262
|
+
useEffect(() => {
|
263
|
+
if (isMultiValueEdit && filterMultiValues) {
|
264
|
+
setTimeout(() => setForceRefresh({}));
|
265
|
+
}
|
266
|
+
}, [filterMultiValues, isMultiValueEdit]);
|
168
267
|
useLayoutEffect(() => {
|
169
268
|
var _a2, _b2;
|
170
269
|
if (activeIndex !== null && rowVirtualizer.range && (activeIndex > ((_a2 = rowVirtualizer.range) == null ? void 0 : _a2.endIndex) || activeIndex < ((_b2 = rowVirtualizer.range) == null ? void 0 : _b2.startIndex))) {
|
@@ -195,9 +294,12 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
|
|
195
294
|
switchInputType("operator", setInputType, void 0, refs.domReference.current);
|
196
295
|
}
|
197
296
|
}
|
198
|
-
}, filter.operator) : null,
|
199
|
-
|
200
|
-
|
297
|
+
}, filter.operator) : null, isMultiValueEdit ? filterMultiValues.map((item, i) => /* @__PURE__ */ React.createElement(MultiValuePill, {
|
298
|
+
key: `${item.value}-${i}`,
|
299
|
+
item,
|
300
|
+
index: i,
|
301
|
+
handleRemoveMultiValue
|
302
|
+
})) : null) : null, /* @__PURE__ */ React.createElement("input", __spreadProps(__spreadValues({}, getReferenceProps({
|
201
303
|
ref: refs.setReference,
|
202
304
|
onChange,
|
203
305
|
value: inputValue,
|
@@ -211,9 +313,9 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
|
|
211
313
|
if (filterInputType === "operator") {
|
212
314
|
handleShiftTabInput(event);
|
213
315
|
}
|
214
|
-
handleBackspaceInput(event);
|
215
|
-
handleTabInput(event);
|
216
|
-
handleEnterInput(event);
|
316
|
+
handleBackspaceInput(event, isMultiValueEdit);
|
317
|
+
handleTabInput(event, isMultiValueEdit);
|
318
|
+
handleEnterInput(event, isMultiValueEdit);
|
217
319
|
}
|
218
320
|
})), {
|
219
321
|
className: cx(styles.inputStyle, { [styles.loadingInputPadding]: !optionsLoading }),
|
@@ -233,7 +335,7 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
|
|
233
335
|
initialFocus: -1,
|
234
336
|
visuallyHiddenDismiss: true,
|
235
337
|
modal: false
|
236
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
338
|
+
}, /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
|
237
339
|
style: __spreadProps(__spreadValues({}, floatingStyles), {
|
238
340
|
width: `${optionsError ? ERROR_STATE_DROPDOWN_WIDTH : maxOptionWidth}px`
|
239
341
|
}),
|
@@ -274,17 +376,24 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
|
|
274
376
|
listRef.current[index] = node;
|
275
377
|
},
|
276
378
|
onClick(event) {
|
379
|
+
var _a3;
|
277
380
|
if (filterInputType !== "value") {
|
278
381
|
event.stopPropagation();
|
279
382
|
}
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
383
|
+
if (isMultiValueEdit) {
|
384
|
+
event.stopPropagation();
|
385
|
+
handleAddMultiValue(item);
|
386
|
+
(_a3 = refs.domReference.current) == null ? void 0 : _a3.focus();
|
387
|
+
} else {
|
388
|
+
model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, item));
|
389
|
+
setInputValue("");
|
390
|
+
switchToNextInputType(
|
391
|
+
filterInputType,
|
392
|
+
setInputType,
|
393
|
+
handleChangeViewMode,
|
394
|
+
refs.domReference.current
|
395
|
+
);
|
396
|
+
}
|
288
397
|
}
|
289
398
|
})), {
|
290
399
|
active: activeIndex === index,
|
@@ -294,19 +403,56 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
|
|
294
403
|
transform: `translateY(${virtualItem.start}px)`
|
295
404
|
},
|
296
405
|
"aria-setsize": filteredDropDownItems.length,
|
297
|
-
"aria-posinset": virtualItem.index + 1
|
298
|
-
|
299
|
-
|
406
|
+
"aria-posinset": virtualItem.index + 1,
|
407
|
+
isMultiValueEdit,
|
408
|
+
checked: filterMultiValues.some((val) => val.value === item.value)
|
409
|
+
}), /* @__PURE__ */ React.createElement("span", null, item.isCustom ? "Use custom value: " : "", " ", (_a2 = item.label) != null ? _a2 : item.value), item.description ? /* @__PURE__ */ React.createElement("div", {
|
410
|
+
className: styles.descriptionText
|
411
|
+
}, item.description) : null);
|
412
|
+
}))), isMultiValueEdit && !optionsLoading && !optionsError && filteredDropDownItems.length ? /* @__PURE__ */ React.createElement(MultiValueApplyButton, {
|
413
|
+
onClick: () => handleMultiValueUpdate(model, filter, filterMultiValues),
|
414
|
+
floatingElement: refs.floating.current,
|
415
|
+
maxOptionWidth
|
416
|
+
}) : null))));
|
300
417
|
});
|
418
|
+
const MultiValuePill = ({ item, handleRemoveMultiValue, index }) => {
|
419
|
+
var _a, _b;
|
420
|
+
const styles = useStyles2(getStyles);
|
421
|
+
return /* @__PURE__ */ React.createElement("div", {
|
422
|
+
className: cx(styles.basePill, styles.valuePill)
|
423
|
+
}, /* @__PURE__ */ React.createElement("span", null, " ", (_a = item.label) != null ? _a : item.value), /* @__PURE__ */ React.createElement(Button, {
|
424
|
+
onClick: (e) => {
|
425
|
+
e.stopPropagation();
|
426
|
+
e.preventDefault();
|
427
|
+
handleRemoveMultiValue(item);
|
428
|
+
},
|
429
|
+
onKeyDownCapture: (e) => {
|
430
|
+
if (e.key === "Enter") {
|
431
|
+
e.preventDefault();
|
432
|
+
e.stopPropagation();
|
433
|
+
handleRemoveMultiValue(item);
|
434
|
+
}
|
435
|
+
},
|
436
|
+
fill: "text",
|
437
|
+
size: "sm",
|
438
|
+
variant: "secondary",
|
439
|
+
className: styles.removeButton,
|
440
|
+
tooltip: `Remove filter value - ${(_b = item.label) != null ? _b : item.value}`
|
441
|
+
}, /* @__PURE__ */ React.createElement(Icon, {
|
442
|
+
name: "times",
|
443
|
+
size: "md",
|
444
|
+
id: `${item.value}-${index}`
|
445
|
+
})));
|
446
|
+
};
|
301
447
|
const getStyles = (theme) => ({
|
302
448
|
comboboxWrapper: css({
|
303
449
|
display: "flex",
|
304
|
-
flexWrap: "
|
450
|
+
flexWrap: "wrap"
|
305
451
|
}),
|
306
452
|
pillWrapper: css({
|
307
453
|
display: "flex",
|
308
454
|
alignItems: "center",
|
309
|
-
|
455
|
+
flexWrap: "wrap"
|
310
456
|
}),
|
311
457
|
basePill: css(__spreadProps(__spreadValues({
|
312
458
|
display: "flex",
|
@@ -331,7 +477,8 @@ const getStyles = (theme) => ({
|
|
331
477
|
}
|
332
478
|
}),
|
333
479
|
valuePill: css({
|
334
|
-
background: theme.colors.action.selected
|
480
|
+
background: theme.colors.action.selected,
|
481
|
+
padding: theme.spacing(0.125, 0, 0.125, 1)
|
335
482
|
}),
|
336
483
|
dropdownWrapper: css({
|
337
484
|
backgroundColor: theme.colors.background.primary,
|
@@ -364,6 +511,25 @@ const getStyles = (theme) => ({
|
|
364
511
|
"&:not(:first-child)": {
|
365
512
|
borderTop: `1px solid ${theme.colors.border.weak}`
|
366
513
|
}
|
514
|
+
}),
|
515
|
+
removeButton: css({
|
516
|
+
marginInline: theme.spacing(0.5),
|
517
|
+
height: "100%",
|
518
|
+
padding: 0,
|
519
|
+
cursor: "pointer",
|
520
|
+
"&:hover": {
|
521
|
+
color: theme.colors.text.primary
|
522
|
+
}
|
523
|
+
}),
|
524
|
+
descriptionText: css(__spreadProps(__spreadValues({}, theme.typography.bodySmall), {
|
525
|
+
color: theme.colors.text.secondary,
|
526
|
+
paddingTop: theme.spacing(0.5)
|
527
|
+
})),
|
528
|
+
multiValueApply: css({
|
529
|
+
position: "absolute",
|
530
|
+
top: 0,
|
531
|
+
left: 0,
|
532
|
+
display: "flex"
|
367
533
|
})
|
368
534
|
});
|
369
535
|
|