@grafana/scenes 5.14.1 → 5.14.2--canary.889.10728276286.0

Sign up to get free protection for your applications and to get access to all the features.
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
  });