@grafana/scenes 5.14.1 → 5.14.2--canary.889.10728276286.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/dist/index.js CHANGED
@@ -3636,7 +3636,7 @@ var __objRest$3 = (source, exclude) => {
3636
3636
  };
3637
3637
  const DropdownItem = React.forwardRef(
3638
3638
  function DropdownItem2(_a, ref) {
3639
- var _b = _a, { children, active, addGroupBottomBorder } = _b, rest = __objRest$3(_b, ["children", "active", "addGroupBottomBorder"]);
3639
+ var _b = _a, { children, active, addGroupBottomBorder, isMultiValueEdit, checked } = _b, rest = __objRest$3(_b, ["children", "active", "addGroupBottomBorder", "isMultiValueEdit", "checked"]);
3640
3640
  const styles = ui.useStyles2(getStyles$c);
3641
3641
  const id = React.useId();
3642
3642
  return /* @__PURE__ */ React__default["default"].createElement("div", __spreadValues$B({
@@ -3648,7 +3648,11 @@ const DropdownItem = React.forwardRef(
3648
3648
  }, rest), /* @__PURE__ */ React__default["default"].createElement("div", {
3649
3649
  className: styles.optionBody,
3650
3650
  "data-testid": `data-testid ad hoc filter option value ${children}`
3651
- }, /* @__PURE__ */ React__default["default"].createElement("span", null, children)));
3651
+ }, /* @__PURE__ */ React__default["default"].createElement("span", null, isMultiValueEdit ? /* @__PURE__ */ React__default["default"].createElement(ui.Checkbox, {
3652
+ tabIndex: -1,
3653
+ checked,
3654
+ className: styles.checkbox
3655
+ }) : null, children)));
3652
3656
  }
3653
3657
  );
3654
3658
  const getStyles$c = (theme) => ({
@@ -3688,6 +3692,22 @@ const getStyles$c = (theme) => ({
3688
3692
  }),
3689
3693
  groupBottomBorder: css.css({
3690
3694
  borderBottom: `1px solid ${theme.colors.border.weak}`
3695
+ }),
3696
+ checkbox: css.css({
3697
+ paddingRight: theme.spacing(0.5)
3698
+ }),
3699
+ multiValueApply: css.css({
3700
+ position: "absolute",
3701
+ top: 0,
3702
+ left: 0,
3703
+ display: "flex"
3704
+ }),
3705
+ dropdownWrapper: css.css({
3706
+ backgroundColor: theme.colors.background.primary,
3707
+ color: theme.colors.text.primary,
3708
+ boxShadow: theme.shadows.z2,
3709
+ overflowY: "auto",
3710
+ zIndex: theme.zIndex.dropdown
3691
3711
  })
3692
3712
  });
3693
3713
  const LoadingOptionsPlaceholder = () => {
@@ -3705,11 +3725,29 @@ const OptionsErrorPlaceholder = ({ handleFetchOptions }) => {
3705
3725
  onClick: handleFetchOptions
3706
3726
  }, "An error has occurred fetching labels. Click to retry");
3707
3727
  };
3728
+ const MultiValueApplyButton = ({ onClick, floatingElement, maxOptionWidth }) => {
3729
+ const styles = ui.useStyles2(getStyles$c);
3730
+ const floatingElementRect = floatingElement == null ? void 0 : floatingElement.getBoundingClientRect();
3731
+ return /* @__PURE__ */ React__default["default"].createElement("div", {
3732
+ className: css.cx(styles.dropdownWrapper, styles.multiValueApply),
3733
+ style: {
3734
+ width: `${maxOptionWidth}px`,
3735
+ transform: `translate(${floatingElementRect == null ? void 0 : floatingElementRect.left}px,${floatingElementRect == null ? void 0 : floatingElementRect.bottom}px)`
3736
+ }
3737
+ }, /* @__PURE__ */ React__default["default"].createElement(ui.Button, {
3738
+ onClick,
3739
+ fill: "text",
3740
+ fullWidth: true,
3741
+ tabIndex: -1
3742
+ }, "Apply"));
3743
+ };
3708
3744
 
3709
3745
  const VIRTUAL_LIST_WIDTH_ESTIMATE_MULTIPLIER = 8;
3746
+ const VIRTUAL_LIST_DESCRIPTION_WIDTH_ESTIMATE_MULTIPLIER = 6;
3710
3747
  const VIRTUAL_LIST_PADDING = 8;
3711
3748
  const VIRTUAL_LIST_OVERSCAN = 5;
3712
3749
  const VIRTUAL_LIST_ITEM_HEIGHT = 38;
3750
+ const VIRTUAL_LIST_ITEM_HEIGHT_WITH_DESCRIPTION = 60;
3713
3751
  const ERROR_STATE_DROPDOWN_WIDTH = 366;
3714
3752
  function fuzzySearchOptions(options) {
3715
3753
  const ufuzzy = new uFuzzy__default["default"]();
@@ -3760,7 +3798,7 @@ function fuzzySearchOptions(options) {
3760
3798
  }
3761
3799
  const flattenOptionGroups = (options) => options.flatMap((option) => option.options ? [option, ...option.options] : [option]);
3762
3800
  const setupDropdownAccessibility = (options, listRef, disabledIndicesRef) => {
3763
- var _a, _b, _c;
3801
+ var _a, _b, _c, _d;
3764
3802
  let maxOptionWidth = 182;
3765
3803
  const listRefArr = [];
3766
3804
  const disabledIndices = [];
@@ -3770,7 +3808,12 @@ const setupDropdownAccessibility = (options, listRef, disabledIndicesRef) => {
3770
3808
  disabledIndices.push(i);
3771
3809
  }
3772
3810
  let label = (_c = (_b = options[i].label) != null ? _b : options[i].value) != null ? _c : "";
3773
- const widthEstimate = (options[i].isCustom ? label.length + 18 : label.length) * VIRTUAL_LIST_WIDTH_ESTIMATE_MULTIPLIER + VIRTUAL_LIST_PADDING * 2;
3811
+ let multiplierToUse = VIRTUAL_LIST_WIDTH_ESTIMATE_MULTIPLIER;
3812
+ if (label.length * VIRTUAL_LIST_WIDTH_ESTIMATE_MULTIPLIER < (((_d = options[i].description) == null ? void 0 : _d.length) || 0) * VIRTUAL_LIST_DESCRIPTION_WIDTH_ESTIMATE_MULTIPLIER) {
3813
+ label = options[i].description;
3814
+ multiplierToUse = VIRTUAL_LIST_DESCRIPTION_WIDTH_ESTIMATE_MULTIPLIER;
3815
+ }
3816
+ const widthEstimate = (options[i].isCustom ? label.length + 18 : label.length) * multiplierToUse + VIRTUAL_LIST_PADDING * 2;
3774
3817
  if (widthEstimate > maxOptionWidth) {
3775
3818
  maxOptionWidth = widthEstimate;
3776
3819
  }
@@ -3812,6 +3855,20 @@ const generateFilterUpdatePayload = (filterInputType, item) => {
3812
3855
  [filterInputType]: item.value
3813
3856
  };
3814
3857
  };
3858
+ const INPUT_PLACEHOLDER = "Filter by label values";
3859
+ const generatePlaceholder = (filter, filterInputType, isMultiValueEdit, isAlwaysWip) => {
3860
+ var _a;
3861
+ if (filterInputType === "key") {
3862
+ return INPUT_PLACEHOLDER;
3863
+ }
3864
+ if (filterInputType === "value") {
3865
+ if (isMultiValueEdit) {
3866
+ return INPUT_PLACEHOLDER;
3867
+ }
3868
+ return ((_a = filter.valueLabels) == null ? void 0 : _a[0]) || "";
3869
+ }
3870
+ return filter[filterInputType] && !isAlwaysWip ? `${filter[filterInputType]}` : INPUT_PLACEHOLDER;
3871
+ };
3815
3872
 
3816
3873
  const MAX_MENU_HEIGHT = 300;
3817
3874
  const useFloatingInteractions = ({
@@ -3819,7 +3876,7 @@ const useFloatingInteractions = ({
3819
3876
  onOpenChange,
3820
3877
  activeIndex,
3821
3878
  setActiveIndex,
3822
- operatorIdentifier,
3879
+ outsidePressIdsToIgnore,
3823
3880
  listRef,
3824
3881
  disabledIndicesRef
3825
3882
  }) => {
@@ -3843,7 +3900,13 @@ const useFloatingInteractions = ({
3843
3900
  const role = react.useRole(context, { role: "listbox" });
3844
3901
  const dismiss = react.useDismiss(context, {
3845
3902
  outsidePress: (event) => {
3846
- if (event.currentTarget instanceof HTMLElement && event.currentTarget.id === operatorIdentifier) {
3903
+ var _a;
3904
+ const target = event.currentTarget || event.target;
3905
+ let idToCompare = (target == null ? void 0 : target.id) || "";
3906
+ if ((target == null ? void 0 : target.nodeName) === "path") {
3907
+ idToCompare = ((_a = target.parentElement) == null ? void 0 : _a.id) || "";
3908
+ }
3909
+ if (outsidePressIdsToIgnore.includes(idToCompare)) {
3847
3910
  return false;
3848
3911
  }
3849
3912
  return true;
@@ -3897,6 +3960,15 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
3897
3960
  const [activeIndex, setActiveIndex] = React.useState(null);
3898
3961
  const [filterInputType, setInputType] = React.useState(!isAlwaysWip ? "value" : "key");
3899
3962
  const styles = ui.useStyles2(getStyles$b);
3963
+ const [filterMultiValues, setFilterMultiValues] = React.useState([]);
3964
+ const [_, setForceRefresh] = React.useState({});
3965
+ const multiValuePillWrapperRef = React.useRef(null);
3966
+ const multiValueOperators = React.useMemo(
3967
+ () => OPERATORS.reduce((acc, operator) => operator.isMulti ? [...acc, operator.value] : acc, []),
3968
+ []
3969
+ );
3970
+ const hasMultiValueOperator = multiValueOperators.includes((filter == null ? void 0 : filter.operator) || "");
3971
+ const isMultiValueEdit = hasMultiValueOperator && filterInputType === "value";
3900
3972
  const operatorIdentifier = React.useId();
3901
3973
  const listRef = React.useRef([]);
3902
3974
  const disabledIndicesRef = React.useRef([]);
@@ -3908,22 +3980,66 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
3908
3980
  setInputValue("");
3909
3981
  }
3910
3982
  }, [model, isAlwaysWip]);
3983
+ const handleMultiValueFilterCommit = React.useCallback(
3984
+ (model2, filter2, filterMultiValues2, preventFocus) => {
3985
+ if (filterMultiValues2.length) {
3986
+ const valueLabels = [];
3987
+ const values = [];
3988
+ filterMultiValues2.forEach((item) => {
3989
+ var _a2;
3990
+ valueLabels.push((_a2 = item.label) != null ? _a2 : item.value);
3991
+ values.push(item.value);
3992
+ });
3993
+ model2._updateFilter(filter2, { valueLabels, values, value: values[0] });
3994
+ setFilterMultiValues([]);
3995
+ }
3996
+ if (!preventFocus) {
3997
+ setTimeout(() => {
3998
+ var _a2;
3999
+ return (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
4000
+ });
4001
+ }
4002
+ },
4003
+ []
4004
+ );
4005
+ const handleLocalMultiValueChange = React.useCallback((selectedItem) => {
4006
+ setFilterMultiValues((items) => {
4007
+ if (items.some((item) => item.value === selectedItem.value)) {
4008
+ return items.filter((item) => item.value !== selectedItem.value);
4009
+ }
4010
+ return [...items, selectedItem];
4011
+ });
4012
+ }, []);
3911
4013
  const onOpenChange = React.useCallback(
3912
- (nextOpen, _, reason) => {
4014
+ (nextOpen, _2, reason) => {
3913
4015
  setOpen(nextOpen);
3914
4016
  if (reason && ["outside-press", "escape-key"].includes(reason)) {
4017
+ if (isMultiValueEdit) {
4018
+ handleMultiValueFilterCommit(model, filter, filterMultiValues);
4019
+ }
3915
4020
  handleResetWip();
3916
4021
  handleChangeViewMode == null ? void 0 : handleChangeViewMode();
3917
4022
  }
3918
4023
  },
3919
- [handleChangeViewMode, handleResetWip]
4024
+ [
4025
+ filter,
4026
+ filterMultiValues,
4027
+ handleChangeViewMode,
4028
+ handleMultiValueFilterCommit,
4029
+ handleResetWip,
4030
+ isMultiValueEdit,
4031
+ model
4032
+ ]
3920
4033
  );
4034
+ const outsidePressIdsToIgnore = React.useMemo(() => {
4035
+ return [operatorIdentifier, ...filterMultiValues.map((item, i) => `${item.value}-${i}`)];
4036
+ }, [operatorIdentifier, filterMultiValues]);
3921
4037
  const { refs, floatingStyles, context, getReferenceProps, getFloatingProps, getItemProps } = useFloatingInteractions({
3922
4038
  open,
3923
4039
  onOpenChange,
3924
4040
  activeIndex,
3925
4041
  setActiveIndex,
3926
- operatorIdentifier,
4042
+ outsidePressIdsToIgnore,
3927
4043
  listRef,
3928
4044
  disabledIndicesRef
3929
4045
  });
@@ -3936,6 +4052,16 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
3936
4052
  setInputValue(value);
3937
4053
  setActiveIndex(0);
3938
4054
  }
4055
+ const handleRemoveMultiValue = React.useCallback(
4056
+ (item) => {
4057
+ setFilterMultiValues((selected) => selected.filter((option) => option.value !== item.value));
4058
+ setTimeout(() => {
4059
+ var _a2;
4060
+ return (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
4061
+ });
4062
+ },
4063
+ [refs.domReference]
4064
+ );
3939
4065
  const filteredDropDownItems = flattenOptionGroups(handleOptionGroups(optionsSearcher(inputValue, filterInputType)));
3940
4066
  if (filterInputType !== "operator" && inputValue) {
3941
4067
  filteredDropDownItems.push({
@@ -3974,43 +4100,89 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
3974
4100
  const rowVirtualizer = reactVirtual.useVirtualizer({
3975
4101
  count: filteredDropDownItems.length,
3976
4102
  getScrollElement: () => refs.floating.current,
3977
- estimateSize: () => VIRTUAL_LIST_ITEM_HEIGHT,
4103
+ estimateSize: (index) => filteredDropDownItems[index].description ? VIRTUAL_LIST_ITEM_HEIGHT_WITH_DESCRIPTION : VIRTUAL_LIST_ITEM_HEIGHT,
3978
4104
  overscan: VIRTUAL_LIST_OVERSCAN
3979
4105
  });
3980
4106
  const handleBackspaceInput = React.useCallback(
3981
- (event) => {
3982
- if (event.key === "Backspace" && !inputValue && filterInputType === "key") {
3983
- model._removeLastFilter();
3984
- handleFetchOptions(filterInputType);
4107
+ (event, multiValueEdit) => {
4108
+ if (event.key === "Backspace" && !inputValue) {
4109
+ if (multiValueEdit) {
4110
+ setFilterMultiValues((items) => {
4111
+ const updated = [...items];
4112
+ updated.splice(-1, 1);
4113
+ return updated;
4114
+ });
4115
+ } else if (filterInputType === "key") {
4116
+ model._removeLastFilter();
4117
+ handleFetchOptions(filterInputType);
4118
+ }
3985
4119
  }
3986
4120
  },
3987
- [inputValue, filterInputType]
4121
+ [inputValue, filterInputType, model, handleFetchOptions]
4122
+ );
4123
+ const handleTabInput = React.useCallback(
4124
+ (event, multiValueEdit) => {
4125
+ var _a2;
4126
+ if (event.key === "Tab" && !event.shiftKey) {
4127
+ if (multiValueEdit) {
4128
+ event.preventDefault();
4129
+ handleMultiValueFilterCommit(model, filter, filterMultiValues);
4130
+ (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
4131
+ }
4132
+ handleChangeViewMode == null ? void 0 : handleChangeViewMode();
4133
+ handleResetWip();
4134
+ }
4135
+ },
4136
+ [
4137
+ filter,
4138
+ filterMultiValues,
4139
+ handleChangeViewMode,
4140
+ handleMultiValueFilterCommit,
4141
+ handleResetWip,
4142
+ model,
4143
+ refs.domReference
4144
+ ]
4145
+ );
4146
+ const handleShiftTabInput = React.useCallback(
4147
+ (event, multiValueEdit) => {
4148
+ if (event.key === "Tab" && event.shiftKey) {
4149
+ if (multiValueEdit) {
4150
+ event.preventDefault();
4151
+ handleMultiValueFilterCommit(model, filter, filterMultiValues, true);
4152
+ }
4153
+ handleChangeViewMode == null ? void 0 : handleChangeViewMode();
4154
+ handleResetWip();
4155
+ }
4156
+ },
4157
+ [filter, filterMultiValues, handleChangeViewMode, handleMultiValueFilterCommit, handleResetWip, model]
3988
4158
  );
3989
- const handleTabInput = React.useCallback((event) => {
3990
- if (event.key === "Tab" && !event.shiftKey) {
3991
- handleChangeViewMode == null ? void 0 : handleChangeViewMode();
3992
- handleResetWip();
3993
- }
3994
- }, []);
3995
- const handleShiftTabInput = React.useCallback((event) => {
3996
- if (event.key === "Tab" && event.shiftKey) {
3997
- handleChangeViewMode == null ? void 0 : handleChangeViewMode();
3998
- handleResetWip();
3999
- }
4000
- }, []);
4001
4159
  const handleEnterInput = React.useCallback(
4002
- (event) => {
4160
+ (event, multiValueEdit) => {
4003
4161
  if (event.key === "Enter" && activeIndex != null) {
4004
4162
  if (!filteredDropDownItems[activeIndex]) {
4005
4163
  return;
4006
4164
  }
4007
- model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, filteredDropDownItems[activeIndex]));
4165
+ const selectedItem = filteredDropDownItems[activeIndex];
4166
+ if (multiValueEdit) {
4167
+ handleLocalMultiValueChange(selectedItem);
4168
+ } else {
4169
+ model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, selectedItem));
4170
+ switchToNextInputType(filterInputType, setInputType, handleChangeViewMode, refs.domReference.current);
4171
+ setActiveIndex(0);
4172
+ }
4008
4173
  setInputValue("");
4009
- setActiveIndex(0);
4010
- switchToNextInputType(filterInputType, setInputType, handleChangeViewMode, refs.domReference.current);
4011
4174
  }
4012
4175
  },
4013
- [activeIndex, filter, filterInputType, filteredDropDownItems, model]
4176
+ [
4177
+ activeIndex,
4178
+ filter,
4179
+ filterInputType,
4180
+ filteredDropDownItems,
4181
+ handleLocalMultiValueChange,
4182
+ handleChangeViewMode,
4183
+ model,
4184
+ refs.domReference
4185
+ ]
4014
4186
  );
4015
4187
  React.useEffect(() => {
4016
4188
  if (open) {
@@ -4018,13 +4190,34 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4018
4190
  }
4019
4191
  }, [open, filterInputType]);
4020
4192
  React.useEffect(() => {
4021
- var _a2;
4193
+ var _a2, _b2;
4022
4194
  if (!isAlwaysWip) {
4023
4195
  setInputType("value");
4024
4196
  setInputValue("");
4025
- (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
4197
+ if (hasMultiValueOperator && ((_a2 = filter == null ? void 0 : filter.values) == null ? void 0 : _a2.length)) {
4198
+ const multiValueOptions = filter.values.reduce(
4199
+ (acc, value, i) => {
4200
+ var _a3;
4201
+ return [
4202
+ ...acc,
4203
+ {
4204
+ label: ((_a3 = filter.valueLabels) == null ? void 0 : _a3[i]) || value,
4205
+ value
4206
+ }
4207
+ ];
4208
+ },
4209
+ []
4210
+ );
4211
+ setFilterMultiValues(multiValueOptions);
4212
+ }
4213
+ (_b2 = refs.domReference.current) == null ? void 0 : _b2.focus();
4026
4214
  }
4027
4215
  }, []);
4216
+ React.useEffect(() => {
4217
+ if (isMultiValueEdit && filterMultiValues) {
4218
+ setTimeout(() => setForceRefresh({}));
4219
+ }
4220
+ }, [filterMultiValues, isMultiValueEdit]);
4028
4221
  React.useLayoutEffect(() => {
4029
4222
  var _a2, _b2;
4030
4223
  if (activeIndex !== null && rowVirtualizer.range && (activeIndex > ((_a2 = rowVirtualizer.range) == null ? void 0 : _a2.endIndex) || activeIndex < ((_b2 = rowVirtualizer.range) == null ? void 0 : _b2.startIndex))) {
@@ -4032,7 +4225,6 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4032
4225
  }
4033
4226
  }, [activeIndex, rowVirtualizer]);
4034
4227
  const keyLabel = (_a = filter == null ? void 0 : filter.keyLabel) != null ? _a : filter == null ? void 0 : filter.key;
4035
- const valueLabel = (_c = (_b = filter == null ? void 0 : filter.valueLabels) == null ? void 0 : _b[0]) != null ? _c : filter == null ? void 0 : filter.value;
4036
4228
  return /* @__PURE__ */ React__default["default"].createElement("div", {
4037
4229
  className: styles.comboboxWrapper
4038
4230
  }, filter ? /* @__PURE__ */ React__default["default"].createElement("div", {
@@ -4050,18 +4242,23 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4050
4242
  switchInputType("operator", setInputType, void 0, refs.domReference.current);
4051
4243
  },
4052
4244
  onKeyDown: (event) => {
4053
- handleShiftTabInput(event);
4245
+ handleShiftTabInput(event, hasMultiValueOperator);
4054
4246
  if (event.key === "Enter") {
4055
4247
  switchInputType("operator", setInputType, void 0, refs.domReference.current);
4056
4248
  }
4057
4249
  }
4058
- }, 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__default["default"].createElement("div", {
4059
- className: css.cx(styles.basePill, styles.valuePill)
4060
- }, valueLabel) : null) : null, /* @__PURE__ */ React__default["default"].createElement("input", __spreadProps$n(__spreadValues$A({}, getReferenceProps({
4250
+ }, filter.operator) : null, /* @__PURE__ */ React__default["default"].createElement("div", {
4251
+ ref: multiValuePillWrapperRef
4252
+ }), isMultiValueEdit ? filterMultiValues.map((item, i) => /* @__PURE__ */ React__default["default"].createElement(MultiValuePill, {
4253
+ key: `${item.value}-${i}`,
4254
+ item,
4255
+ index: i,
4256
+ handleRemoveMultiValue
4257
+ })) : null) : null, /* @__PURE__ */ React__default["default"].createElement("input", __spreadProps$n(__spreadValues$A({}, getReferenceProps({
4061
4258
  ref: refs.setReference,
4062
4259
  onChange,
4063
4260
  value: inputValue,
4064
- placeholder: !isAlwaysWip ? filterInputType === "operator" ? `${filter[filterInputType]} ${valueLabel}` : filter[filterInputType] : "Filter by label values",
4261
+ placeholder: generatePlaceholder(filter, filterInputType, isMultiValueEdit, isAlwaysWip),
4065
4262
  "aria-autocomplete": "list",
4066
4263
  onKeyDown(event) {
4067
4264
  if (!open) {
@@ -4071,9 +4268,9 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4071
4268
  if (filterInputType === "operator") {
4072
4269
  handleShiftTabInput(event);
4073
4270
  }
4074
- handleBackspaceInput(event);
4075
- handleTabInput(event);
4076
- handleEnterInput(event);
4271
+ handleBackspaceInput(event, isMultiValueEdit);
4272
+ handleTabInput(event, isMultiValueEdit);
4273
+ handleEnterInput(event, isMultiValueEdit);
4077
4274
  }
4078
4275
  })), {
4079
4276
  className: css.cx(styles.inputStyle, { [styles.loadingInputPadding]: !optionsLoading }),
@@ -4093,9 +4290,10 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4093
4290
  initialFocus: -1,
4094
4291
  visuallyHiddenDismiss: true,
4095
4292
  modal: false
4096
- }, /* @__PURE__ */ React__default["default"].createElement("div", {
4293
+ }, /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("div", {
4097
4294
  style: __spreadProps$n(__spreadValues$A({}, floatingStyles), {
4098
- width: `${optionsError ? ERROR_STATE_DROPDOWN_WIDTH : maxOptionWidth}px`
4295
+ width: `${optionsError ? ERROR_STATE_DROPDOWN_WIDTH : maxOptionWidth}px`,
4296
+ transform: isMultiValueEdit ? `translate(${((_b = multiValuePillWrapperRef.current) == null ? void 0 : _b.getBoundingClientRect().left) || 0}px, ${(((_c = refs.domReference.current) == null ? void 0 : _c.getBoundingClientRect().bottom) || 0) + 10}px )` : floatingStyles.transform
4099
4297
  }),
4100
4298
  ref: refs.setFloating,
4101
4299
  className: styles.dropdownWrapper,
@@ -4134,17 +4332,25 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4134
4332
  listRef.current[index] = node;
4135
4333
  },
4136
4334
  onClick(event) {
4335
+ var _a3;
4137
4336
  if (filterInputType !== "value") {
4138
4337
  event.stopPropagation();
4139
4338
  }
4140
- model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, item));
4141
- setInputValue("");
4142
- switchToNextInputType(
4143
- filterInputType,
4144
- setInputType,
4145
- handleChangeViewMode,
4146
- refs.domReference.current
4147
- );
4339
+ if (isMultiValueEdit) {
4340
+ event.preventDefault();
4341
+ event.stopPropagation();
4342
+ handleLocalMultiValueChange(item);
4343
+ (_a3 = refs.domReference.current) == null ? void 0 : _a3.focus();
4344
+ } else {
4345
+ model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, item));
4346
+ setInputValue("");
4347
+ switchToNextInputType(
4348
+ filterInputType,
4349
+ setInputType,
4350
+ handleChangeViewMode,
4351
+ refs.domReference.current
4352
+ );
4353
+ }
4148
4354
  }
4149
4355
  })), {
4150
4356
  active: activeIndex === index,
@@ -4154,19 +4360,56 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4154
4360
  transform: `translateY(${virtualItem.start}px)`
4155
4361
  },
4156
4362
  "aria-setsize": filteredDropDownItems.length,
4157
- "aria-posinset": virtualItem.index + 1
4158
- }), item.isCustom ? "Use custom value: " : "", " ", (_a2 = item.label) != null ? _a2 : item.value);
4159
- }))))));
4363
+ "aria-posinset": virtualItem.index + 1,
4364
+ isMultiValueEdit,
4365
+ checked: filterMultiValues.some((val) => val.value === item.value)
4366
+ }), /* @__PURE__ */ React__default["default"].createElement("span", null, item.isCustom ? "Use custom value: " : "", " ", (_a2 = item.label) != null ? _a2 : item.value), item.description ? /* @__PURE__ */ React__default["default"].createElement("div", {
4367
+ className: styles.descriptionText
4368
+ }, item.description) : null);
4369
+ }))), isMultiValueEdit && !optionsLoading && !optionsError && filteredDropDownItems.length ? /* @__PURE__ */ React__default["default"].createElement(MultiValueApplyButton, {
4370
+ onClick: () => handleMultiValueFilterCommit(model, filter, filterMultiValues),
4371
+ floatingElement: refs.floating.current,
4372
+ maxOptionWidth
4373
+ }) : null))));
4160
4374
  });
4375
+ const MultiValuePill = ({ item, handleRemoveMultiValue, index }) => {
4376
+ var _a, _b;
4377
+ const styles = ui.useStyles2(getStyles$b);
4378
+ return /* @__PURE__ */ React__default["default"].createElement("div", {
4379
+ className: css.cx(styles.basePill, styles.valuePill)
4380
+ }, /* @__PURE__ */ React__default["default"].createElement("span", null, " ", (_a = item.label) != null ? _a : item.value), /* @__PURE__ */ React__default["default"].createElement(ui.Button, {
4381
+ onClick: (e) => {
4382
+ e.stopPropagation();
4383
+ e.preventDefault();
4384
+ handleRemoveMultiValue(item);
4385
+ },
4386
+ onKeyDownCapture: (e) => {
4387
+ if (e.key === "Enter") {
4388
+ e.preventDefault();
4389
+ e.stopPropagation();
4390
+ handleRemoveMultiValue(item);
4391
+ }
4392
+ },
4393
+ fill: "text",
4394
+ size: "sm",
4395
+ variant: "secondary",
4396
+ className: styles.removeButton,
4397
+ tooltip: `Remove filter value - ${(_b = item.label) != null ? _b : item.value}`
4398
+ }, /* @__PURE__ */ React__default["default"].createElement(ui.Icon, {
4399
+ name: "times",
4400
+ size: "md",
4401
+ id: `${item.value}-${index}`
4402
+ })));
4403
+ };
4161
4404
  const getStyles$b = (theme) => ({
4162
4405
  comboboxWrapper: css.css({
4163
4406
  display: "flex",
4164
- flexWrap: "nowrap"
4407
+ flexWrap: "wrap"
4165
4408
  }),
4166
4409
  pillWrapper: css.css({
4167
4410
  display: "flex",
4168
4411
  alignItems: "center",
4169
- whiteSpace: "nowrap"
4412
+ flexWrap: "wrap"
4170
4413
  }),
4171
4414
  basePill: css.css(__spreadProps$n(__spreadValues$A({
4172
4415
  display: "flex",
@@ -4191,7 +4434,8 @@ const getStyles$b = (theme) => ({
4191
4434
  }
4192
4435
  }),
4193
4436
  valuePill: css.css({
4194
- background: theme.colors.action.selected
4437
+ background: theme.colors.action.selected,
4438
+ padding: theme.spacing(0.125, 0, 0.125, 1)
4195
4439
  }),
4196
4440
  dropdownWrapper: css.css({
4197
4441
  backgroundColor: theme.colors.background.primary,
@@ -4224,6 +4468,25 @@ const getStyles$b = (theme) => ({
4224
4468
  "&:not(:first-child)": {
4225
4469
  borderTop: `1px solid ${theme.colors.border.weak}`
4226
4470
  }
4471
+ }),
4472
+ removeButton: css.css({
4473
+ marginInline: theme.spacing(0.5),
4474
+ height: "100%",
4475
+ padding: 0,
4476
+ cursor: "pointer",
4477
+ "&:hover": {
4478
+ color: theme.colors.text.primary
4479
+ }
4480
+ }),
4481
+ descriptionText: css.css(__spreadProps$n(__spreadValues$A({}, theme.typography.bodySmall), {
4482
+ color: theme.colors.text.secondary,
4483
+ paddingTop: theme.spacing(0.5)
4484
+ })),
4485
+ multiValueApply: css.css({
4486
+ position: "absolute",
4487
+ top: 0,
4488
+ left: 0,
4489
+ display: "flex"
4227
4490
  })
4228
4491
  });
4229
4492
 
@@ -4246,14 +4509,14 @@ var __spreadValues$z = (a, b) => {
4246
4509
  return a;
4247
4510
  };
4248
4511
  var __spreadProps$m = (a, b) => __defProps$m(a, __getOwnPropDescs$m(b));
4249
- function AdHocFilterPill({ filter, model, readOnly }) {
4512
+ function AdHocFilterPill({ filter, model, readOnly, focusOnInputRef }) {
4250
4513
  var _a, _b, _c;
4251
4514
  const styles = ui.useStyles2(getStyles$a);
4252
4515
  const [viewMode, setViewMode] = React.useState(true);
4253
4516
  const [shouldFocus, setShouldFocus] = React.useState(false);
4254
4517
  const pillWrapperRef = React.useRef(null);
4255
4518
  const keyLabel = (_a = filter.keyLabel) != null ? _a : filter.key;
4256
- const valueLabel = (_c = (_b = filter.valueLabels) == null ? void 0 : _b[0]) != null ? _c : filter.value;
4519
+ const valueLabel = ((_b = filter.valueLabels) == null ? void 0 : _b.join(", ")) || ((_c = filter.values) == null ? void 0 : _c.join(", ")) || filter.value;
4257
4520
  const handleChangeViewMode = React.useCallback(
4258
4521
  (event) => {
4259
4522
  event == null ? void 0 : event.stopPropagation();
@@ -4285,16 +4548,20 @@ function AdHocFilterPill({ filter, model, readOnly }) {
4285
4548
  "aria-label": `Edit filter with key ${keyLabel}`,
4286
4549
  tabIndex: 0,
4287
4550
  ref: pillWrapperRef
4288
- }, /* @__PURE__ */ React__default["default"].createElement("span", null, keyLabel, " ", filter.operator, " ", valueLabel), !readOnly ? /* @__PURE__ */ React__default["default"].createElement(ui.IconButton, {
4551
+ }, /* @__PURE__ */ React__default["default"].createElement("span", {
4552
+ className: styles.pillText
4553
+ }, keyLabel, " ", filter.operator, " ", valueLabel), !readOnly ? /* @__PURE__ */ React__default["default"].createElement(ui.IconButton, {
4289
4554
  onClick: (e) => {
4290
4555
  e.stopPropagation();
4291
4556
  model._removeFilter(filter);
4557
+ setTimeout(() => focusOnInputRef == null ? void 0 : focusOnInputRef());
4292
4558
  },
4293
4559
  onKeyDownCapture: (e) => {
4294
4560
  if (e.key === "Enter") {
4295
4561
  e.preventDefault();
4296
4562
  e.stopPropagation();
4297
4563
  model._removeFilter(filter);
4564
+ setTimeout(() => focusOnInputRef == null ? void 0 : focusOnInputRef());
4298
4565
  }
4299
4566
  },
4300
4567
  name: "times",
@@ -4341,6 +4608,9 @@ const getStyles$a = (theme) => ({
4341
4608
  "&:hover": {
4342
4609
  color: theme.colors.text.primary
4343
4610
  }
4611
+ }),
4612
+ pillText: css.css({
4613
+ whiteSpace: "break-spaces"
4344
4614
  })
4345
4615
  });
4346
4616
 
@@ -4377,7 +4647,8 @@ const AdHocFiltersComboboxRenderer = React.memo(function AdHocFiltersComboboxRen
4377
4647
  key: index,
4378
4648
  filter,
4379
4649
  model,
4380
- readOnly
4650
+ readOnly,
4651
+ focusOnInputRef: focusOnInputRef.current
4381
4652
  })), !readOnly ? /* @__PURE__ */ React__default["default"].createElement(AdHocFiltersAlwaysWipCombobox, {
4382
4653
  model,
4383
4654
  ref: focusOnInputRef
@@ -4606,7 +4877,7 @@ function renderExpression(builder, filters) {
4606
4877
  function AdHocFiltersVariableRenderer({ model }) {
4607
4878
  const { filters, readOnly, addFilterButtonText } = model.useState();
4608
4879
  const styles = ui.useStyles2(getStyles$8);
4609
- if (!model.state.supportsMultiValueOperators && model.state.layout === "combobox") {
4880
+ if (model.state.layout === "combobox") {
4610
4881
  return /* @__PURE__ */ React__default["default"].createElement(AdHocFiltersComboboxRenderer, {
4611
4882
  model
4612
4883
  });