@grafana/scenes 5.14.0 → 5.14.1--canary.889.10722729172.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 = (_c = (_b = filter.valueLabels) == null ? void 0 : _b[0]) != null ? _c : filter.value;
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", null, keyLabel, " ", filter.operator, " ", valueLabel), !readOnly ? /* @__PURE__ */ React.createElement(IconButton, {
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?.[0] ?? 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>\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});\n"],"names":["_a"],"mappings":"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"}
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 // TODO remove when we're on the latest version of @grafana/data\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, useMemo, useCallback, useImperativeHandle, useEffect, useLayoutEffect } from 'react';
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,70 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
48
57
  setInputValue("");
49
58
  }
50
59
  }, [model, isAlwaysWip]);
60
+ const handleMultiValueFilterCommit = useCallback(
61
+ (model2, filter2, filterMultiValues2, preventFocus) => {
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
+ if (!preventFocus) {
74
+ setTimeout(() => {
75
+ var _a2;
76
+ return (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
77
+ });
78
+ }
79
+ },
80
+ []
81
+ );
82
+ const handleLocalMultiValueChange = useCallback((selectedItem) => {
83
+ setFilterMultiValues((items) => {
84
+ if (items.some((item) => item.value === selectedItem.value)) {
85
+ return items.filter((item) => item.value !== selectedItem.value);
86
+ }
87
+ return [...items, selectedItem];
88
+ });
89
+ }, []);
90
+ const handleRemoveMultiValue = useCallback(
91
+ (item) => setFilterMultiValues((selected) => selected.filter((option) => option.value !== item.value)),
92
+ []
93
+ );
51
94
  const onOpenChange = useCallback(
52
- (nextOpen, _, reason) => {
95
+ (nextOpen, _2, reason) => {
53
96
  setOpen(nextOpen);
54
97
  if (reason && ["outside-press", "escape-key"].includes(reason)) {
98
+ if (isMultiValueEdit) {
99
+ handleMultiValueFilterCommit(model, filter, filterMultiValues);
100
+ }
55
101
  handleResetWip();
56
102
  handleChangeViewMode == null ? void 0 : handleChangeViewMode();
57
103
  }
58
104
  },
59
- [handleChangeViewMode, handleResetWip]
105
+ [
106
+ filter,
107
+ filterMultiValues,
108
+ handleChangeViewMode,
109
+ handleMultiValueFilterCommit,
110
+ handleResetWip,
111
+ isMultiValueEdit,
112
+ model
113
+ ]
60
114
  );
115
+ const outsidePressIdsToIgnore = useMemo(() => {
116
+ return [operatorIdentifier, ...filterMultiValues.map((item, i) => `${item.value}-${i}`)];
117
+ }, [operatorIdentifier, filterMultiValues]);
61
118
  const { refs, floatingStyles, context, getReferenceProps, getFloatingProps, getItemProps } = useFloatingInteractions({
62
119
  open,
63
120
  onOpenChange,
64
121
  activeIndex,
65
122
  setActiveIndex,
66
- operatorIdentifier,
123
+ outsidePressIdsToIgnore,
67
124
  listRef,
68
125
  disabledIndicesRef
69
126
  });
@@ -114,43 +171,89 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
114
171
  const rowVirtualizer = useVirtualizer({
115
172
  count: filteredDropDownItems.length,
116
173
  getScrollElement: () => refs.floating.current,
117
- estimateSize: () => VIRTUAL_LIST_ITEM_HEIGHT,
174
+ estimateSize: (index) => filteredDropDownItems[index].description ? VIRTUAL_LIST_ITEM_HEIGHT_WITH_DESCRIPTION : VIRTUAL_LIST_ITEM_HEIGHT,
118
175
  overscan: VIRTUAL_LIST_OVERSCAN
119
176
  });
120
177
  const handleBackspaceInput = useCallback(
121
- (event) => {
122
- if (event.key === "Backspace" && !inputValue && filterInputType === "key") {
123
- model._removeLastFilter();
124
- handleFetchOptions(filterInputType);
178
+ (event, multiValueEdit) => {
179
+ if (event.key === "Backspace" && !inputValue) {
180
+ if (multiValueEdit) {
181
+ setFilterMultiValues((items) => {
182
+ const updated = [...items];
183
+ updated.splice(-1, 1);
184
+ return updated;
185
+ });
186
+ } else if (filterInputType === "key") {
187
+ model._removeLastFilter();
188
+ handleFetchOptions(filterInputType);
189
+ }
125
190
  }
126
191
  },
127
- [inputValue, filterInputType]
192
+ [inputValue, filterInputType, model, handleFetchOptions]
193
+ );
194
+ const handleTabInput = useCallback(
195
+ (event, multiValueEdit) => {
196
+ var _a2;
197
+ if (event.key === "Tab" && !event.shiftKey) {
198
+ if (multiValueEdit) {
199
+ event.preventDefault();
200
+ handleMultiValueFilterCommit(model, filter, filterMultiValues);
201
+ (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
202
+ }
203
+ handleChangeViewMode == null ? void 0 : handleChangeViewMode();
204
+ handleResetWip();
205
+ }
206
+ },
207
+ [
208
+ filter,
209
+ filterMultiValues,
210
+ handleChangeViewMode,
211
+ handleMultiValueFilterCommit,
212
+ handleResetWip,
213
+ model,
214
+ refs.domReference
215
+ ]
216
+ );
217
+ const handleShiftTabInput = useCallback(
218
+ (event, multiValueEdit) => {
219
+ if (event.key === "Tab" && event.shiftKey) {
220
+ if (multiValueEdit) {
221
+ event.preventDefault();
222
+ handleMultiValueFilterCommit(model, filter, filterMultiValues, true);
223
+ }
224
+ handleChangeViewMode == null ? void 0 : handleChangeViewMode();
225
+ handleResetWip();
226
+ }
227
+ },
228
+ [filter, filterMultiValues, handleChangeViewMode, handleMultiValueFilterCommit, handleResetWip, model]
128
229
  );
129
- const handleTabInput = useCallback((event) => {
130
- if (event.key === "Tab" && !event.shiftKey) {
131
- handleChangeViewMode == null ? void 0 : handleChangeViewMode();
132
- handleResetWip();
133
- }
134
- }, []);
135
- const handleShiftTabInput = useCallback((event) => {
136
- if (event.key === "Tab" && event.shiftKey) {
137
- handleChangeViewMode == null ? void 0 : handleChangeViewMode();
138
- handleResetWip();
139
- }
140
- }, []);
141
230
  const handleEnterInput = useCallback(
142
- (event) => {
231
+ (event, multiValueEdit) => {
143
232
  if (event.key === "Enter" && activeIndex != null) {
144
233
  if (!filteredDropDownItems[activeIndex]) {
145
234
  return;
146
235
  }
147
- model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, filteredDropDownItems[activeIndex]));
236
+ const selectedItem = filteredDropDownItems[activeIndex];
237
+ if (multiValueEdit) {
238
+ handleLocalMultiValueChange(selectedItem);
239
+ } else {
240
+ model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, selectedItem));
241
+ switchToNextInputType(filterInputType, setInputType, handleChangeViewMode, refs.domReference.current);
242
+ setActiveIndex(0);
243
+ }
148
244
  setInputValue("");
149
- setActiveIndex(0);
150
- switchToNextInputType(filterInputType, setInputType, handleChangeViewMode, refs.domReference.current);
151
245
  }
152
246
  },
153
- [activeIndex, filter, filterInputType, filteredDropDownItems, model]
247
+ [
248
+ activeIndex,
249
+ filter,
250
+ filterInputType,
251
+ filteredDropDownItems,
252
+ handleLocalMultiValueChange,
253
+ handleChangeViewMode,
254
+ model,
255
+ refs.domReference
256
+ ]
154
257
  );
155
258
  useEffect(() => {
156
259
  if (open) {
@@ -158,13 +261,34 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
158
261
  }
159
262
  }, [open, filterInputType]);
160
263
  useEffect(() => {
161
- var _a2;
264
+ var _a2, _b2;
162
265
  if (!isAlwaysWip) {
163
266
  setInputType("value");
164
267
  setInputValue("");
165
- (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
268
+ if (hasMultiValueOperator && ((_a2 = filter == null ? void 0 : filter.values) == null ? void 0 : _a2.length)) {
269
+ const multiValueOptions = filter.values.reduce(
270
+ (acc, value, i) => {
271
+ var _a3;
272
+ return [
273
+ ...acc,
274
+ {
275
+ label: ((_a3 = filter.valueLabels) == null ? void 0 : _a3[i]) || value,
276
+ value
277
+ }
278
+ ];
279
+ },
280
+ []
281
+ );
282
+ setFilterMultiValues(multiValueOptions);
283
+ }
284
+ (_b2 = refs.domReference.current) == null ? void 0 : _b2.focus();
166
285
  }
167
286
  }, []);
287
+ useEffect(() => {
288
+ if (isMultiValueEdit && filterMultiValues) {
289
+ setTimeout(() => setForceRefresh({}));
290
+ }
291
+ }, [filterMultiValues, isMultiValueEdit]);
168
292
  useLayoutEffect(() => {
169
293
  var _a2, _b2;
170
294
  if (activeIndex !== null && rowVirtualizer.range && (activeIndex > ((_a2 = rowVirtualizer.range) == null ? void 0 : _a2.endIndex) || activeIndex < ((_b2 = rowVirtualizer.range) == null ? void 0 : _b2.startIndex))) {
@@ -190,14 +314,17 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
190
314
  switchInputType("operator", setInputType, void 0, refs.domReference.current);
191
315
  },
192
316
  onKeyDown: (event) => {
193
- handleShiftTabInput(event);
317
+ handleShiftTabInput(event, hasMultiValueOperator);
194
318
  if (event.key === "Enter") {
195
319
  switchInputType("operator", setInputType, void 0, refs.domReference.current);
196
320
  }
197
321
  }
198
- }, filter.operator) : null, (filter == null ? void 0 : filter.key) && (filter == null ? void 0 : filter.operator) && (filter == null ? void 0 : filter.value) && !["operator", "value"].includes(filterInputType) ? /* @__PURE__ */ React.createElement("div", {
199
- className: cx(styles.basePill, styles.valuePill)
200
- }, valueLabel) : null) : null, /* @__PURE__ */ React.createElement("input", __spreadProps(__spreadValues({}, getReferenceProps({
322
+ }, filter.operator) : null, isMultiValueEdit ? filterMultiValues.map((item, i) => /* @__PURE__ */ React.createElement(MultiValuePill, {
323
+ key: `${item.value}-${i}`,
324
+ item,
325
+ index: i,
326
+ handleRemoveMultiValue
327
+ })) : null) : null, /* @__PURE__ */ React.createElement("input", __spreadProps(__spreadValues({}, getReferenceProps({
201
328
  ref: refs.setReference,
202
329
  onChange,
203
330
  value: inputValue,
@@ -211,9 +338,9 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
211
338
  if (filterInputType === "operator") {
212
339
  handleShiftTabInput(event);
213
340
  }
214
- handleBackspaceInput(event);
215
- handleTabInput(event);
216
- handleEnterInput(event);
341
+ handleBackspaceInput(event, isMultiValueEdit);
342
+ handleTabInput(event, isMultiValueEdit);
343
+ handleEnterInput(event, isMultiValueEdit);
217
344
  }
218
345
  })), {
219
346
  className: cx(styles.inputStyle, { [styles.loadingInputPadding]: !optionsLoading }),
@@ -233,7 +360,7 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
233
360
  initialFocus: -1,
234
361
  visuallyHiddenDismiss: true,
235
362
  modal: false
236
- }, /* @__PURE__ */ React.createElement("div", {
363
+ }, /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
237
364
  style: __spreadProps(__spreadValues({}, floatingStyles), {
238
365
  width: `${optionsError ? ERROR_STATE_DROPDOWN_WIDTH : maxOptionWidth}px`
239
366
  }),
@@ -274,17 +401,24 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
274
401
  listRef.current[index] = node;
275
402
  },
276
403
  onClick(event) {
404
+ var _a3;
277
405
  if (filterInputType !== "value") {
278
406
  event.stopPropagation();
279
407
  }
280
- model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, item));
281
- setInputValue("");
282
- switchToNextInputType(
283
- filterInputType,
284
- setInputType,
285
- handleChangeViewMode,
286
- refs.domReference.current
287
- );
408
+ if (isMultiValueEdit) {
409
+ event.stopPropagation();
410
+ handleLocalMultiValueChange(item);
411
+ (_a3 = refs.domReference.current) == null ? void 0 : _a3.focus();
412
+ } else {
413
+ model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, item));
414
+ setInputValue("");
415
+ switchToNextInputType(
416
+ filterInputType,
417
+ setInputType,
418
+ handleChangeViewMode,
419
+ refs.domReference.current
420
+ );
421
+ }
288
422
  }
289
423
  })), {
290
424
  active: activeIndex === index,
@@ -294,19 +428,56 @@ const AdHocCombobox = forwardRef(function AdHocCombobox2({ filter, model, isAlwa
294
428
  transform: `translateY(${virtualItem.start}px)`
295
429
  },
296
430
  "aria-setsize": filteredDropDownItems.length,
297
- "aria-posinset": virtualItem.index + 1
298
- }), item.isCustom ? "Use custom value: " : "", " ", (_a2 = item.label) != null ? _a2 : item.value);
299
- }))))));
431
+ "aria-posinset": virtualItem.index + 1,
432
+ isMultiValueEdit,
433
+ checked: filterMultiValues.some((val) => val.value === item.value)
434
+ }), /* @__PURE__ */ React.createElement("span", null, item.isCustom ? "Use custom value: " : "", " ", (_a2 = item.label) != null ? _a2 : item.value), item.description ? /* @__PURE__ */ React.createElement("div", {
435
+ className: styles.descriptionText
436
+ }, item.description) : null);
437
+ }))), isMultiValueEdit && !optionsLoading && !optionsError && filteredDropDownItems.length ? /* @__PURE__ */ React.createElement(MultiValueApplyButton, {
438
+ onClick: () => handleMultiValueFilterCommit(model, filter, filterMultiValues),
439
+ floatingElement: refs.floating.current,
440
+ maxOptionWidth
441
+ }) : null))));
300
442
  });
443
+ const MultiValuePill = ({ item, handleRemoveMultiValue, index }) => {
444
+ var _a, _b;
445
+ const styles = useStyles2(getStyles);
446
+ return /* @__PURE__ */ React.createElement("div", {
447
+ className: cx(styles.basePill, styles.valuePill)
448
+ }, /* @__PURE__ */ React.createElement("span", null, " ", (_a = item.label) != null ? _a : item.value), /* @__PURE__ */ React.createElement(Button, {
449
+ onClick: (e) => {
450
+ e.stopPropagation();
451
+ e.preventDefault();
452
+ handleRemoveMultiValue(item);
453
+ },
454
+ onKeyDownCapture: (e) => {
455
+ if (e.key === "Enter") {
456
+ e.preventDefault();
457
+ e.stopPropagation();
458
+ handleRemoveMultiValue(item);
459
+ }
460
+ },
461
+ fill: "text",
462
+ size: "sm",
463
+ variant: "secondary",
464
+ className: styles.removeButton,
465
+ tooltip: `Remove filter value - ${(_b = item.label) != null ? _b : item.value}`
466
+ }, /* @__PURE__ */ React.createElement(Icon, {
467
+ name: "times",
468
+ size: "md",
469
+ id: `${item.value}-${index}`
470
+ })));
471
+ };
301
472
  const getStyles = (theme) => ({
302
473
  comboboxWrapper: css({
303
474
  display: "flex",
304
- flexWrap: "nowrap"
475
+ flexWrap: "wrap"
305
476
  }),
306
477
  pillWrapper: css({
307
478
  display: "flex",
308
479
  alignItems: "center",
309
- whiteSpace: "nowrap"
480
+ flexWrap: "wrap"
310
481
  }),
311
482
  basePill: css(__spreadProps(__spreadValues({
312
483
  display: "flex",
@@ -331,7 +502,8 @@ const getStyles = (theme) => ({
331
502
  }
332
503
  }),
333
504
  valuePill: css({
334
- background: theme.colors.action.selected
505
+ background: theme.colors.action.selected,
506
+ padding: theme.spacing(0.125, 0, 0.125, 1)
335
507
  }),
336
508
  dropdownWrapper: css({
337
509
  backgroundColor: theme.colors.background.primary,
@@ -364,6 +536,25 @@ const getStyles = (theme) => ({
364
536
  "&:not(:first-child)": {
365
537
  borderTop: `1px solid ${theme.colors.border.weak}`
366
538
  }
539
+ }),
540
+ removeButton: css({
541
+ marginInline: theme.spacing(0.5),
542
+ height: "100%",
543
+ padding: 0,
544
+ cursor: "pointer",
545
+ "&:hover": {
546
+ color: theme.colors.text.primary
547
+ }
548
+ }),
549
+ descriptionText: css(__spreadProps(__spreadValues({}, theme.typography.bodySmall), {
550
+ color: theme.colors.text.secondary,
551
+ paddingTop: theme.spacing(0.5)
552
+ })),
553
+ multiValueApply: css({
554
+ position: "absolute",
555
+ top: 0,
556
+ left: 0,
557
+ display: "flex"
367
558
  })
368
559
  });
369
560