@grafana/scenes 5.14.1 → 5.14.2--canary.889.10727598270.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
  }
@@ -3819,7 +3862,7 @@ const useFloatingInteractions = ({
3819
3862
  onOpenChange,
3820
3863
  activeIndex,
3821
3864
  setActiveIndex,
3822
- operatorIdentifier,
3865
+ outsidePressIdsToIgnore,
3823
3866
  listRef,
3824
3867
  disabledIndicesRef
3825
3868
  }) => {
@@ -3843,7 +3886,13 @@ const useFloatingInteractions = ({
3843
3886
  const role = react.useRole(context, { role: "listbox" });
3844
3887
  const dismiss = react.useDismiss(context, {
3845
3888
  outsidePress: (event) => {
3846
- if (event.currentTarget instanceof HTMLElement && event.currentTarget.id === operatorIdentifier) {
3889
+ var _a;
3890
+ const target = event.currentTarget || event.target;
3891
+ let idToCompare = (target == null ? void 0 : target.id) || "";
3892
+ if ((target == null ? void 0 : target.nodeName) === "path") {
3893
+ idToCompare = ((_a = target.parentElement) == null ? void 0 : _a.id) || "";
3894
+ }
3895
+ if (outsidePressIdsToIgnore.includes(idToCompare)) {
3847
3896
  return false;
3848
3897
  }
3849
3898
  return true;
@@ -3897,6 +3946,14 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
3897
3946
  const [activeIndex, setActiveIndex] = React.useState(null);
3898
3947
  const [filterInputType, setInputType] = React.useState(!isAlwaysWip ? "value" : "key");
3899
3948
  const styles = ui.useStyles2(getStyles$b);
3949
+ const [filterMultiValues, setFilterMultiValues] = React.useState([]);
3950
+ const [_, setForceRefresh] = React.useState({});
3951
+ const multiValueOperators = React.useMemo(
3952
+ () => OPERATORS.reduce((acc, operator) => operator.isMulti ? [...acc, operator.value] : acc, []),
3953
+ []
3954
+ );
3955
+ const hasMultiValueOperator = multiValueOperators.includes((filter == null ? void 0 : filter.operator) || "");
3956
+ const isMultiValueEdit = hasMultiValueOperator && filterInputType === "value";
3900
3957
  const operatorIdentifier = React.useId();
3901
3958
  const listRef = React.useRef([]);
3902
3959
  const disabledIndicesRef = React.useRef([]);
@@ -3908,22 +3965,66 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
3908
3965
  setInputValue("");
3909
3966
  }
3910
3967
  }, [model, isAlwaysWip]);
3968
+ const handleMultiValueFilterCommit = React.useCallback(
3969
+ (model2, filter2, filterMultiValues2, preventFocus) => {
3970
+ if (filterMultiValues2.length) {
3971
+ const valueLabels = [];
3972
+ const values = [];
3973
+ filterMultiValues2.forEach((item) => {
3974
+ var _a2;
3975
+ valueLabels.push((_a2 = item.label) != null ? _a2 : item.value);
3976
+ values.push(item.value);
3977
+ });
3978
+ model2._updateFilter(filter2, { valueLabels, values, value: values[0] });
3979
+ setFilterMultiValues([]);
3980
+ }
3981
+ if (!preventFocus) {
3982
+ setTimeout(() => {
3983
+ var _a2;
3984
+ return (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
3985
+ });
3986
+ }
3987
+ },
3988
+ []
3989
+ );
3990
+ const handleLocalMultiValueChange = React.useCallback((selectedItem) => {
3991
+ setFilterMultiValues((items) => {
3992
+ if (items.some((item) => item.value === selectedItem.value)) {
3993
+ return items.filter((item) => item.value !== selectedItem.value);
3994
+ }
3995
+ return [...items, selectedItem];
3996
+ });
3997
+ }, []);
3911
3998
  const onOpenChange = React.useCallback(
3912
- (nextOpen, _, reason) => {
3999
+ (nextOpen, _2, reason) => {
3913
4000
  setOpen(nextOpen);
3914
4001
  if (reason && ["outside-press", "escape-key"].includes(reason)) {
4002
+ if (isMultiValueEdit) {
4003
+ handleMultiValueFilterCommit(model, filter, filterMultiValues);
4004
+ }
3915
4005
  handleResetWip();
3916
4006
  handleChangeViewMode == null ? void 0 : handleChangeViewMode();
3917
4007
  }
3918
4008
  },
3919
- [handleChangeViewMode, handleResetWip]
4009
+ [
4010
+ filter,
4011
+ filterMultiValues,
4012
+ handleChangeViewMode,
4013
+ handleMultiValueFilterCommit,
4014
+ handleResetWip,
4015
+ isMultiValueEdit,
4016
+ model
4017
+ ]
3920
4018
  );
4019
+ const outsidePressIdsToIgnore = React.useMemo(() => {
4020
+ return [operatorIdentifier, ...filterMultiValues.map((item, i) => `${item.value}-${i}`)];
4021
+ }, [operatorIdentifier, filterMultiValues]);
3921
4022
  const { refs, floatingStyles, context, getReferenceProps, getFloatingProps, getItemProps } = useFloatingInteractions({
3922
4023
  open,
3923
4024
  onOpenChange,
3924
4025
  activeIndex,
3925
4026
  setActiveIndex,
3926
- operatorIdentifier,
4027
+ outsidePressIdsToIgnore,
3927
4028
  listRef,
3928
4029
  disabledIndicesRef
3929
4030
  });
@@ -3936,6 +4037,16 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
3936
4037
  setInputValue(value);
3937
4038
  setActiveIndex(0);
3938
4039
  }
4040
+ const handleRemoveMultiValue = React.useCallback(
4041
+ (item) => {
4042
+ setFilterMultiValues((selected) => selected.filter((option) => option.value !== item.value));
4043
+ setTimeout(() => {
4044
+ var _a2;
4045
+ return (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
4046
+ });
4047
+ },
4048
+ [refs.domReference]
4049
+ );
3939
4050
  const filteredDropDownItems = flattenOptionGroups(handleOptionGroups(optionsSearcher(inputValue, filterInputType)));
3940
4051
  if (filterInputType !== "operator" && inputValue) {
3941
4052
  filteredDropDownItems.push({
@@ -3974,43 +4085,89 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
3974
4085
  const rowVirtualizer = reactVirtual.useVirtualizer({
3975
4086
  count: filteredDropDownItems.length,
3976
4087
  getScrollElement: () => refs.floating.current,
3977
- estimateSize: () => VIRTUAL_LIST_ITEM_HEIGHT,
4088
+ estimateSize: (index) => filteredDropDownItems[index].description ? VIRTUAL_LIST_ITEM_HEIGHT_WITH_DESCRIPTION : VIRTUAL_LIST_ITEM_HEIGHT,
3978
4089
  overscan: VIRTUAL_LIST_OVERSCAN
3979
4090
  });
3980
4091
  const handleBackspaceInput = React.useCallback(
3981
- (event) => {
3982
- if (event.key === "Backspace" && !inputValue && filterInputType === "key") {
3983
- model._removeLastFilter();
3984
- handleFetchOptions(filterInputType);
4092
+ (event, multiValueEdit) => {
4093
+ if (event.key === "Backspace" && !inputValue) {
4094
+ if (multiValueEdit) {
4095
+ setFilterMultiValues((items) => {
4096
+ const updated = [...items];
4097
+ updated.splice(-1, 1);
4098
+ return updated;
4099
+ });
4100
+ } else if (filterInputType === "key") {
4101
+ model._removeLastFilter();
4102
+ handleFetchOptions(filterInputType);
4103
+ }
3985
4104
  }
3986
4105
  },
3987
- [inputValue, filterInputType]
4106
+ [inputValue, filterInputType, model, handleFetchOptions]
4107
+ );
4108
+ const handleTabInput = React.useCallback(
4109
+ (event, multiValueEdit) => {
4110
+ var _a2;
4111
+ if (event.key === "Tab" && !event.shiftKey) {
4112
+ if (multiValueEdit) {
4113
+ event.preventDefault();
4114
+ handleMultiValueFilterCommit(model, filter, filterMultiValues);
4115
+ (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
4116
+ }
4117
+ handleChangeViewMode == null ? void 0 : handleChangeViewMode();
4118
+ handleResetWip();
4119
+ }
4120
+ },
4121
+ [
4122
+ filter,
4123
+ filterMultiValues,
4124
+ handleChangeViewMode,
4125
+ handleMultiValueFilterCommit,
4126
+ handleResetWip,
4127
+ model,
4128
+ refs.domReference
4129
+ ]
4130
+ );
4131
+ const handleShiftTabInput = React.useCallback(
4132
+ (event, multiValueEdit) => {
4133
+ if (event.key === "Tab" && event.shiftKey) {
4134
+ if (multiValueEdit) {
4135
+ event.preventDefault();
4136
+ handleMultiValueFilterCommit(model, filter, filterMultiValues, true);
4137
+ }
4138
+ handleChangeViewMode == null ? void 0 : handleChangeViewMode();
4139
+ handleResetWip();
4140
+ }
4141
+ },
4142
+ [filter, filterMultiValues, handleChangeViewMode, handleMultiValueFilterCommit, handleResetWip, model]
3988
4143
  );
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
4144
  const handleEnterInput = React.useCallback(
4002
- (event) => {
4145
+ (event, multiValueEdit) => {
4003
4146
  if (event.key === "Enter" && activeIndex != null) {
4004
4147
  if (!filteredDropDownItems[activeIndex]) {
4005
4148
  return;
4006
4149
  }
4007
- model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, filteredDropDownItems[activeIndex]));
4150
+ const selectedItem = filteredDropDownItems[activeIndex];
4151
+ if (multiValueEdit) {
4152
+ handleLocalMultiValueChange(selectedItem);
4153
+ } else {
4154
+ model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, selectedItem));
4155
+ switchToNextInputType(filterInputType, setInputType, handleChangeViewMode, refs.domReference.current);
4156
+ setActiveIndex(0);
4157
+ }
4008
4158
  setInputValue("");
4009
- setActiveIndex(0);
4010
- switchToNextInputType(filterInputType, setInputType, handleChangeViewMode, refs.domReference.current);
4011
4159
  }
4012
4160
  },
4013
- [activeIndex, filter, filterInputType, filteredDropDownItems, model]
4161
+ [
4162
+ activeIndex,
4163
+ filter,
4164
+ filterInputType,
4165
+ filteredDropDownItems,
4166
+ handleLocalMultiValueChange,
4167
+ handleChangeViewMode,
4168
+ model,
4169
+ refs.domReference
4170
+ ]
4014
4171
  );
4015
4172
  React.useEffect(() => {
4016
4173
  if (open) {
@@ -4018,13 +4175,34 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4018
4175
  }
4019
4176
  }, [open, filterInputType]);
4020
4177
  React.useEffect(() => {
4021
- var _a2;
4178
+ var _a2, _b2;
4022
4179
  if (!isAlwaysWip) {
4023
4180
  setInputType("value");
4024
4181
  setInputValue("");
4025
- (_a2 = refs.domReference.current) == null ? void 0 : _a2.focus();
4182
+ if (hasMultiValueOperator && ((_a2 = filter == null ? void 0 : filter.values) == null ? void 0 : _a2.length)) {
4183
+ const multiValueOptions = filter.values.reduce(
4184
+ (acc, value, i) => {
4185
+ var _a3;
4186
+ return [
4187
+ ...acc,
4188
+ {
4189
+ label: ((_a3 = filter.valueLabels) == null ? void 0 : _a3[i]) || value,
4190
+ value
4191
+ }
4192
+ ];
4193
+ },
4194
+ []
4195
+ );
4196
+ setFilterMultiValues(multiValueOptions);
4197
+ }
4198
+ (_b2 = refs.domReference.current) == null ? void 0 : _b2.focus();
4026
4199
  }
4027
4200
  }, []);
4201
+ React.useEffect(() => {
4202
+ if (isMultiValueEdit && filterMultiValues) {
4203
+ setTimeout(() => setForceRefresh({}));
4204
+ }
4205
+ }, [filterMultiValues, isMultiValueEdit]);
4028
4206
  React.useLayoutEffect(() => {
4029
4207
  var _a2, _b2;
4030
4208
  if (activeIndex !== null && rowVirtualizer.range && (activeIndex > ((_a2 = rowVirtualizer.range) == null ? void 0 : _a2.endIndex) || activeIndex < ((_b2 = rowVirtualizer.range) == null ? void 0 : _b2.startIndex))) {
@@ -4050,14 +4228,17 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4050
4228
  switchInputType("operator", setInputType, void 0, refs.domReference.current);
4051
4229
  },
4052
4230
  onKeyDown: (event) => {
4053
- handleShiftTabInput(event);
4231
+ handleShiftTabInput(event, hasMultiValueOperator);
4054
4232
  if (event.key === "Enter") {
4055
4233
  switchInputType("operator", setInputType, void 0, refs.domReference.current);
4056
4234
  }
4057
4235
  }
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({
4236
+ }, filter.operator) : null, isMultiValueEdit ? filterMultiValues.map((item, i) => /* @__PURE__ */ React__default["default"].createElement(MultiValuePill, {
4237
+ key: `${item.value}-${i}`,
4238
+ item,
4239
+ index: i,
4240
+ handleRemoveMultiValue
4241
+ })) : null) : null, /* @__PURE__ */ React__default["default"].createElement("input", __spreadProps$n(__spreadValues$A({}, getReferenceProps({
4061
4242
  ref: refs.setReference,
4062
4243
  onChange,
4063
4244
  value: inputValue,
@@ -4071,9 +4252,9 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4071
4252
  if (filterInputType === "operator") {
4072
4253
  handleShiftTabInput(event);
4073
4254
  }
4074
- handleBackspaceInput(event);
4075
- handleTabInput(event);
4076
- handleEnterInput(event);
4255
+ handleBackspaceInput(event, isMultiValueEdit);
4256
+ handleTabInput(event, isMultiValueEdit);
4257
+ handleEnterInput(event, isMultiValueEdit);
4077
4258
  }
4078
4259
  })), {
4079
4260
  className: css.cx(styles.inputStyle, { [styles.loadingInputPadding]: !optionsLoading }),
@@ -4093,7 +4274,7 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4093
4274
  initialFocus: -1,
4094
4275
  visuallyHiddenDismiss: true,
4095
4276
  modal: false
4096
- }, /* @__PURE__ */ React__default["default"].createElement("div", {
4277
+ }, /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("div", {
4097
4278
  style: __spreadProps$n(__spreadValues$A({}, floatingStyles), {
4098
4279
  width: `${optionsError ? ERROR_STATE_DROPDOWN_WIDTH : maxOptionWidth}px`
4099
4280
  }),
@@ -4134,17 +4315,25 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4134
4315
  listRef.current[index] = node;
4135
4316
  },
4136
4317
  onClick(event) {
4318
+ var _a3;
4137
4319
  if (filterInputType !== "value") {
4138
4320
  event.stopPropagation();
4139
4321
  }
4140
- model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, item));
4141
- setInputValue("");
4142
- switchToNextInputType(
4143
- filterInputType,
4144
- setInputType,
4145
- handleChangeViewMode,
4146
- refs.domReference.current
4147
- );
4322
+ if (isMultiValueEdit) {
4323
+ event.preventDefault();
4324
+ event.stopPropagation();
4325
+ handleLocalMultiValueChange(item);
4326
+ (_a3 = refs.domReference.current) == null ? void 0 : _a3.focus();
4327
+ } else {
4328
+ model._updateFilter(filter, generateFilterUpdatePayload(filterInputType, item));
4329
+ setInputValue("");
4330
+ switchToNextInputType(
4331
+ filterInputType,
4332
+ setInputType,
4333
+ handleChangeViewMode,
4334
+ refs.domReference.current
4335
+ );
4336
+ }
4148
4337
  }
4149
4338
  })), {
4150
4339
  active: activeIndex === index,
@@ -4154,19 +4343,56 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({ filter, model,
4154
4343
  transform: `translateY(${virtualItem.start}px)`
4155
4344
  },
4156
4345
  "aria-setsize": filteredDropDownItems.length,
4157
- "aria-posinset": virtualItem.index + 1
4158
- }), item.isCustom ? "Use custom value: " : "", " ", (_a2 = item.label) != null ? _a2 : item.value);
4159
- }))))));
4346
+ "aria-posinset": virtualItem.index + 1,
4347
+ isMultiValueEdit,
4348
+ checked: filterMultiValues.some((val) => val.value === item.value)
4349
+ }), /* @__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", {
4350
+ className: styles.descriptionText
4351
+ }, item.description) : null);
4352
+ }))), isMultiValueEdit && !optionsLoading && !optionsError && filteredDropDownItems.length ? /* @__PURE__ */ React__default["default"].createElement(MultiValueApplyButton, {
4353
+ onClick: () => handleMultiValueFilterCommit(model, filter, filterMultiValues),
4354
+ floatingElement: refs.floating.current,
4355
+ maxOptionWidth
4356
+ }) : null))));
4160
4357
  });
4358
+ const MultiValuePill = ({ item, handleRemoveMultiValue, index }) => {
4359
+ var _a, _b;
4360
+ const styles = ui.useStyles2(getStyles$b);
4361
+ return /* @__PURE__ */ React__default["default"].createElement("div", {
4362
+ className: css.cx(styles.basePill, styles.valuePill)
4363
+ }, /* @__PURE__ */ React__default["default"].createElement("span", null, " ", (_a = item.label) != null ? _a : item.value), /* @__PURE__ */ React__default["default"].createElement(ui.Button, {
4364
+ onClick: (e) => {
4365
+ e.stopPropagation();
4366
+ e.preventDefault();
4367
+ handleRemoveMultiValue(item);
4368
+ },
4369
+ onKeyDownCapture: (e) => {
4370
+ if (e.key === "Enter") {
4371
+ e.preventDefault();
4372
+ e.stopPropagation();
4373
+ handleRemoveMultiValue(item);
4374
+ }
4375
+ },
4376
+ fill: "text",
4377
+ size: "sm",
4378
+ variant: "secondary",
4379
+ className: styles.removeButton,
4380
+ tooltip: `Remove filter value - ${(_b = item.label) != null ? _b : item.value}`
4381
+ }, /* @__PURE__ */ React__default["default"].createElement(ui.Icon, {
4382
+ name: "times",
4383
+ size: "md",
4384
+ id: `${item.value}-${index}`
4385
+ })));
4386
+ };
4161
4387
  const getStyles$b = (theme) => ({
4162
4388
  comboboxWrapper: css.css({
4163
4389
  display: "flex",
4164
- flexWrap: "nowrap"
4390
+ flexWrap: "wrap"
4165
4391
  }),
4166
4392
  pillWrapper: css.css({
4167
4393
  display: "flex",
4168
4394
  alignItems: "center",
4169
- whiteSpace: "nowrap"
4395
+ flexWrap: "wrap"
4170
4396
  }),
4171
4397
  basePill: css.css(__spreadProps$n(__spreadValues$A({
4172
4398
  display: "flex",
@@ -4191,7 +4417,8 @@ const getStyles$b = (theme) => ({
4191
4417
  }
4192
4418
  }),
4193
4419
  valuePill: css.css({
4194
- background: theme.colors.action.selected
4420
+ background: theme.colors.action.selected,
4421
+ padding: theme.spacing(0.125, 0, 0.125, 1)
4195
4422
  }),
4196
4423
  dropdownWrapper: css.css({
4197
4424
  backgroundColor: theme.colors.background.primary,
@@ -4224,6 +4451,25 @@ const getStyles$b = (theme) => ({
4224
4451
  "&:not(:first-child)": {
4225
4452
  borderTop: `1px solid ${theme.colors.border.weak}`
4226
4453
  }
4454
+ }),
4455
+ removeButton: css.css({
4456
+ marginInline: theme.spacing(0.5),
4457
+ height: "100%",
4458
+ padding: 0,
4459
+ cursor: "pointer",
4460
+ "&:hover": {
4461
+ color: theme.colors.text.primary
4462
+ }
4463
+ }),
4464
+ descriptionText: css.css(__spreadProps$n(__spreadValues$A({}, theme.typography.bodySmall), {
4465
+ color: theme.colors.text.secondary,
4466
+ paddingTop: theme.spacing(0.5)
4467
+ })),
4468
+ multiValueApply: css.css({
4469
+ position: "absolute",
4470
+ top: 0,
4471
+ left: 0,
4472
+ display: "flex"
4227
4473
  })
4228
4474
  });
4229
4475
 
@@ -4246,14 +4492,14 @@ var __spreadValues$z = (a, b) => {
4246
4492
  return a;
4247
4493
  };
4248
4494
  var __spreadProps$m = (a, b) => __defProps$m(a, __getOwnPropDescs$m(b));
4249
- function AdHocFilterPill({ filter, model, readOnly }) {
4495
+ function AdHocFilterPill({ filter, model, readOnly, focusOnInputRef }) {
4250
4496
  var _a, _b, _c;
4251
4497
  const styles = ui.useStyles2(getStyles$a);
4252
4498
  const [viewMode, setViewMode] = React.useState(true);
4253
4499
  const [shouldFocus, setShouldFocus] = React.useState(false);
4254
4500
  const pillWrapperRef = React.useRef(null);
4255
4501
  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;
4502
+ const valueLabel = ((_b = filter.valueLabels) == null ? void 0 : _b.join(", ")) || ((_c = filter.values) == null ? void 0 : _c.join(", ")) || filter.value;
4257
4503
  const handleChangeViewMode = React.useCallback(
4258
4504
  (event) => {
4259
4505
  event == null ? void 0 : event.stopPropagation();
@@ -4285,16 +4531,20 @@ function AdHocFilterPill({ filter, model, readOnly }) {
4285
4531
  "aria-label": `Edit filter with key ${keyLabel}`,
4286
4532
  tabIndex: 0,
4287
4533
  ref: pillWrapperRef
4288
- }, /* @__PURE__ */ React__default["default"].createElement("span", null, keyLabel, " ", filter.operator, " ", valueLabel), !readOnly ? /* @__PURE__ */ React__default["default"].createElement(ui.IconButton, {
4534
+ }, /* @__PURE__ */ React__default["default"].createElement("span", {
4535
+ className: styles.pillText
4536
+ }, keyLabel, " ", filter.operator, " ", valueLabel), !readOnly ? /* @__PURE__ */ React__default["default"].createElement(ui.IconButton, {
4289
4537
  onClick: (e) => {
4290
4538
  e.stopPropagation();
4291
4539
  model._removeFilter(filter);
4540
+ setTimeout(() => focusOnInputRef == null ? void 0 : focusOnInputRef());
4292
4541
  },
4293
4542
  onKeyDownCapture: (e) => {
4294
4543
  if (e.key === "Enter") {
4295
4544
  e.preventDefault();
4296
4545
  e.stopPropagation();
4297
4546
  model._removeFilter(filter);
4547
+ setTimeout(() => focusOnInputRef == null ? void 0 : focusOnInputRef());
4298
4548
  }
4299
4549
  },
4300
4550
  name: "times",
@@ -4341,6 +4591,9 @@ const getStyles$a = (theme) => ({
4341
4591
  "&:hover": {
4342
4592
  color: theme.colors.text.primary
4343
4593
  }
4594
+ }),
4595
+ pillText: css.css({
4596
+ whiteSpace: "break-spaces"
4344
4597
  })
4345
4598
  });
4346
4599
 
@@ -4377,7 +4630,8 @@ const AdHocFiltersComboboxRenderer = React.memo(function AdHocFiltersComboboxRen
4377
4630
  key: index,
4378
4631
  filter,
4379
4632
  model,
4380
- readOnly
4633
+ readOnly,
4634
+ focusOnInputRef: focusOnInputRef.current
4381
4635
  })), !readOnly ? /* @__PURE__ */ React__default["default"].createElement(AdHocFiltersAlwaysWipCombobox, {
4382
4636
  model,
4383
4637
  ref: focusOnInputRef
@@ -4606,7 +4860,7 @@ function renderExpression(builder, filters) {
4606
4860
  function AdHocFiltersVariableRenderer({ model }) {
4607
4861
  const { filters, readOnly, addFilterButtonText } = model.useState();
4608
4862
  const styles = ui.useStyles2(getStyles$8);
4609
- if (!model.state.supportsMultiValueOperators && model.state.layout === "combobox") {
4863
+ if (model.state.layout === "combobox") {
4610
4864
  return /* @__PURE__ */ React__default["default"].createElement(AdHocFiltersComboboxRenderer, {
4611
4865
  model
4612
4866
  });