@grafana/scenes 6.51.0 → 6.53.0--canary.1315.20365173522.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.
Files changed (24) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/esm/packages/scenes/src/locales/en-US/grafana-scenes.json.js +4 -0
  3. package/dist/esm/packages/scenes/src/locales/en-US/grafana-scenes.json.js.map +1 -1
  4. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersAlwaysWipCombobox.js +2 -2
  5. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersAlwaysWipCombobox.js.map +1 -1
  6. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersCombobox.js +3 -1
  7. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersCombobox.js.map +1 -1
  8. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersComboboxRenderer.js +115 -23
  9. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersComboboxRenderer.js.map +1 -1
  10. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/utils.js +3 -0
  11. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/utils.js.map +1 -1
  12. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersVariable.js +12 -0
  13. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersVariable.js.map +1 -1
  14. package/dist/esm/packages/scenes/src/variables/adhoc/controller/AdHocFiltersVariableController.js +4 -0
  15. package/dist/esm/packages/scenes/src/variables/adhoc/controller/AdHocFiltersVariableController.js.map +1 -1
  16. package/dist/esm/packages/scenes/src/variables/groupby/GroupByVariable.js +30 -6
  17. package/dist/esm/packages/scenes/src/variables/groupby/GroupByVariable.js.map +1 -1
  18. package/dist/esm/packages/scenes/src/variables/types.js.map +1 -1
  19. package/dist/{grafana-scenes-C9F_2hih.js → grafana-scenes-DrGXYYn6.js} +5 -1
  20. package/dist/{grafana-scenes-C9F_2hih.js.map → grafana-scenes-DrGXYYn6.js.map} +1 -1
  21. package/dist/index.d.ts +30 -1
  22. package/dist/index.js +167 -32
  23. package/dist/index.js.map +1 -1
  24. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -15,11 +15,11 @@ var ui = require('@grafana/ui');
15
15
  var e2eSelectors = require('@grafana/e2e-selectors');
16
16
  var css = require('@emotion/css');
17
17
  var uFuzzy = require('@leeoniya/ufuzzy');
18
+ var reactUse = require('react-use');
18
19
  var react$1 = require('@floating-ui/react');
19
20
  var reactVirtual = require('@tanstack/react-virtual');
20
21
  var react = require('@emotion/react');
21
22
  require('react-dom');
22
- var reactUse = require('react-use');
23
23
  var operators = require('rxjs/operators');
24
24
  var ReactGridLayout = require('react-grid-layout');
25
25
  var BarChartPanelCfg_types_gen = require('@grafana/schema/dist/esm/raw/composable/barchart/panelcfg/x/BarChartPanelCfg_types.gen');
@@ -4614,6 +4614,9 @@ const generatePlaceholder = (filter, filterInputType, isMultiValueEdit, isAlways
4614
4614
  }
4615
4615
  return ((_a = filter.valueLabels) == null ? void 0 : _a[0]) || "";
4616
4616
  }
4617
+ if (isAlwaysWip && filterInputType === "operator") {
4618
+ return "";
4619
+ }
4617
4620
  return filter[filterInputType] && !isAlwaysWip ? `${filter[filterInputType]}` : inputPlaceholder || INPUT_PLACEHOLDER_DEFAULT;
4618
4621
  };
4619
4622
  const populateInputValueOnInputTypeSwitch = ({
@@ -4802,7 +4805,8 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({
4802
4805
  isAlwaysWip,
4803
4806
  handleChangeViewMode,
4804
4807
  focusOnWipInputRef,
4805
- populateInputOnEdit
4808
+ populateInputOnEdit,
4809
+ onInputClick
4806
4810
  }, parentRef) {
4807
4811
  var _a, _b, _c;
4808
4812
  const [open, setOpen] = React.useState(false);
@@ -5285,6 +5289,7 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({
5285
5289
  className: css.cx(styles.inputStyle, { [styles.loadingInputPadding]: !optionsLoading }),
5286
5290
  onClick: (event) => {
5287
5291
  event.stopPropagation();
5292
+ onInputClick == null ? void 0 : onInputClick();
5288
5293
  setOpen(true);
5289
5294
  },
5290
5295
  onFocus: () => {
@@ -5746,53 +5751,100 @@ const getStyles$d = (theme) => ({
5746
5751
  ...getNonApplicablePillStyles(theme)
5747
5752
  });
5748
5753
 
5749
- const AdHocFiltersAlwaysWipCombobox = React.forwardRef(function AdHocFiltersAlwaysWipCombobox2({ controller }, parentRef) {
5754
+ const AdHocFiltersAlwaysWipCombobox = React.forwardRef(function AdHocFiltersAlwaysWipCombobox2({ controller, onInputClick }, parentRef) {
5750
5755
  const { wip } = controller.useState();
5751
5756
  React.useLayoutEffect(() => {
5752
5757
  if (!wip) {
5753
5758
  controller.addWip();
5754
5759
  }
5755
5760
  }, [wip]);
5756
- return /* @__PURE__ */ React__default.default.createElement(AdHocCombobox, { controller, filter: wip, isAlwaysWip: true, ref: parentRef });
5761
+ return /* @__PURE__ */ React__default.default.createElement(AdHocCombobox, { controller, filter: wip, isAlwaysWip: true, ref: parentRef, onInputClick });
5757
5762
  });
5758
5763
 
5764
+ const MAX_VISIBLE_FILTERS = 5;
5759
5765
  const AdHocFiltersComboboxRenderer = React.memo(function AdHocFiltersComboboxRenderer2({ controller }) {
5760
- const { originFilters, filters, readOnly, valueRecommendations } = controller.useState();
5766
+ var _a;
5767
+ const { originFilters, filters, readOnly, collapsible, valueRecommendations } = controller.useState();
5761
5768
  const styles = ui.useStyles2(getStyles$c);
5769
+ const theme = ui.useTheme2();
5770
+ const [collapsed, setCollapsed] = React.useState(true);
5771
+ const [wrapperRef, { height: wrapperHeight }] = reactUse.useMeasure();
5772
+ const clearAll = () => {
5773
+ var _a2;
5774
+ (_a2 = controller.clearAll) == null ? void 0 : _a2.call(controller);
5775
+ };
5762
5776
  const focusOnWipInputRef = React.useRef();
5777
+ const singleLineThreshold = theme.spacing.gridSize * 5;
5778
+ const isMultiLine = collapsible && wrapperHeight > singleLineThreshold;
5779
+ const handleCollapseToggle = (event) => {
5780
+ event.stopPropagation();
5781
+ if (collapsible) {
5782
+ setCollapsed(true);
5783
+ }
5784
+ };
5785
+ const handleExpand = () => {
5786
+ var _a2, _b;
5787
+ if (!collapsible) {
5788
+ (_a2 = focusOnWipInputRef.current) == null ? void 0 : _a2.call(focusOnWipInputRef);
5789
+ return;
5790
+ }
5791
+ if (collapsed) {
5792
+ setCollapsed(false);
5793
+ } else {
5794
+ (_b = focusOnWipInputRef.current) == null ? void 0 : _b.call(focusOnWipInputRef);
5795
+ }
5796
+ };
5797
+ const visibleOriginFilters = (_a = originFilters == null ? void 0 : originFilters.filter((f) => f.origin)) != null ? _a : [];
5798
+ const visibleFilters = filters.filter((f) => !f.hidden);
5799
+ const allFilters = [...visibleOriginFilters, ...visibleFilters];
5800
+ const totalFiltersCount = allFilters.length;
5801
+ const shouldCollapse = collapsible && collapsed && totalFiltersCount > 0;
5802
+ const filtersToRender = shouldCollapse ? allFilters.slice(0, MAX_VISIBLE_FILTERS) : allFilters;
5803
+ React.useEffect(() => {
5804
+ if (collapsible && totalFiltersCount === 0 && collapsed) {
5805
+ setCollapsed(false);
5806
+ }
5807
+ }, [collapsible, totalFiltersCount, collapsed]);
5808
+ const showCollapseButton = collapsible && isMultiLine && !collapsed;
5763
5809
  return /* @__PURE__ */ React__default.default.createElement(
5764
5810
  "div",
5765
5811
  {
5766
- className: css.cx(styles.comboboxWrapper, { [styles.comboboxFocusOutline]: !readOnly }),
5767
- onClick: () => {
5768
- var _a;
5769
- (_a = focusOnWipInputRef.current) == null ? void 0 : _a.call(focusOnWipInputRef);
5770
- }
5812
+ ref: wrapperRef,
5813
+ className: css.cx(styles.comboboxWrapper, {
5814
+ [styles.comboboxFocusOutline]: !readOnly,
5815
+ [styles.collapsed]: shouldCollapse,
5816
+ [styles.clickableCollapsed]: shouldCollapse
5817
+ }),
5818
+ onClick: handleExpand
5771
5819
  },
5772
5820
  /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "filter", className: styles.filterIcon, size: "lg" }),
5773
5821
  valueRecommendations && /* @__PURE__ */ React__default.default.createElement(valueRecommendations.Component, { model: valueRecommendations }),
5774
- originFilters == null ? void 0 : originFilters.map(
5775
- (filter, index) => filter.origin ? /* @__PURE__ */ React__default.default.createElement(
5776
- AdHocFilterPill,
5777
- {
5778
- key: `${index}-${filter.key}`,
5779
- filter,
5780
- controller,
5781
- focusOnWipInputRef: focusOnWipInputRef.current
5782
- }
5783
- ) : null
5784
- ),
5785
- filters.filter((filter) => !filter.hidden).map((filter, index) => /* @__PURE__ */ React__default.default.createElement(
5822
+ filtersToRender.map((filter, index) => /* @__PURE__ */ React__default.default.createElement(
5786
5823
  AdHocFilterPill,
5787
5824
  {
5788
- key: `${index}-${filter.key}`,
5825
+ key: `${filter.origin ? "origin-" : ""}${index}-${filter.key}`,
5789
5826
  filter,
5790
5827
  controller,
5791
5828
  readOnly: readOnly || filter.readOnly,
5792
5829
  focusOnWipInputRef: focusOnWipInputRef.current
5793
5830
  }
5794
5831
  )),
5795
- !readOnly ? /* @__PURE__ */ React__default.default.createElement(AdHocFiltersAlwaysWipCombobox, { controller, ref: focusOnWipInputRef }) : null
5832
+ !readOnly && !shouldCollapse ? /* @__PURE__ */ React__default.default.createElement(AdHocFiltersAlwaysWipCombobox, { controller, ref: focusOnWipInputRef }) : null,
5833
+ /* @__PURE__ */ React__default.default.createElement("div", { className: styles.rightControls }, showCollapseButton && /* @__PURE__ */ React__default.default.createElement(
5834
+ ui.Button,
5835
+ {
5836
+ className: styles.collapseButton,
5837
+ fill: "text",
5838
+ onClick: handleCollapseToggle,
5839
+ "aria-label": i18n.t(
5840
+ "grafana-scenes.variables.adhoc-filters-combobox-renderer.collapse-filters",
5841
+ "Collapse filters"
5842
+ ),
5843
+ "aria-expanded": !collapsed
5844
+ },
5845
+ i18n.t("grafana-scenes.variables.adhoc-filters-combobox-renderer.collapse", "Collapse"),
5846
+ /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "angle-up", size: "md" })
5847
+ ), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.clearAllButton }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "times", size: "md", onClick: clearAll })), shouldCollapse && /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, totalFiltersCount > MAX_VISIBLE_FILTERS && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.moreIndicator }, "(+", totalFiltersCount - MAX_VISIBLE_FILTERS, ")"), /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "angle-down", className: styles.dropdownIndicator })))
5796
5848
  );
5797
5849
  });
5798
5850
  const getStyles$c = (theme) => ({
@@ -5808,7 +5860,8 @@ const getStyles$c = (theme) => ({
5808
5860
  borderRadius: theme.shape.radius.default,
5809
5861
  paddingInline: theme.spacing(1),
5810
5862
  paddingBlock: theme.spacing(0.5),
5811
- flexGrow: 1
5863
+ flexGrow: 1,
5864
+ width: "100%"
5812
5865
  }),
5813
5866
  comboboxFocusOutline: css.css({
5814
5867
  "&:focus-within": {
@@ -5824,6 +5877,48 @@ const getStyles$c = (theme) => ({
5824
5877
  filterIcon: css.css({
5825
5878
  color: theme.colors.text.secondary,
5826
5879
  alignSelf: "center"
5880
+ }),
5881
+ collapsed: css.css({
5882
+ flexWrap: "nowrap",
5883
+ overflow: "hidden"
5884
+ }),
5885
+ clickableCollapsed: css.css({
5886
+ cursor: "pointer",
5887
+ "&:hover": {
5888
+ borderColor: theme.colors.border.medium
5889
+ }
5890
+ }),
5891
+ rightControls: css.css({
5892
+ display: "flex",
5893
+ alignItems: "center",
5894
+ marginLeft: "auto",
5895
+ flexShrink: 0
5896
+ }),
5897
+ moreIndicator: css.css({
5898
+ color: theme.colors.text.secondary,
5899
+ whiteSpace: "nowrap"
5900
+ }),
5901
+ dropdownIndicator: css.css({
5902
+ color: theme.colors.text.secondary,
5903
+ flexShrink: 0
5904
+ }),
5905
+ collapseButton: css.css({
5906
+ color: theme.colors.text.secondary,
5907
+ padding: 0,
5908
+ fontSize: theme.typography.bodySmall.fontSize,
5909
+ border: "none",
5910
+ "&:hover": {
5911
+ background: "transparent",
5912
+ color: theme.colors.text.primary
5913
+ }
5914
+ }),
5915
+ clearAllButton: css.css({
5916
+ fontSize: theme.typography.bodySmall.fontSize,
5917
+ cursor: "pointer",
5918
+ color: theme.colors.text.secondary,
5919
+ "&:hover": {
5920
+ color: theme.colors.text.primary
5921
+ }
5827
5922
  })
5828
5923
  });
5829
5924
 
@@ -5928,6 +6023,7 @@ class AdHocFiltersVariableController {
5928
6023
  supportsMultiValueOperators: state.supportsMultiValueOperators,
5929
6024
  onAddCustomValue: state.onAddCustomValue,
5930
6025
  wip: state._wip,
6026
+ collapsible: state.collapsible,
5931
6027
  valueRecommendations: this.model.getRecommendations(),
5932
6028
  drilldownRecommendationsEnabled: state.drilldownRecommendationsEnabled
5933
6029
  };
@@ -5965,6 +6061,9 @@ class AdHocFiltersVariableController {
5965
6061
  restoreOriginalFilter(filter) {
5966
6062
  this.model.restoreOriginalFilter(filter);
5967
6063
  }
6064
+ clearAll() {
6065
+ this.model.clearAll();
6066
+ }
5968
6067
  startProfile(name) {
5969
6068
  const queryController = getQueryController(this.model);
5970
6069
  queryController == null ? void 0 : queryController.startProfile(name);
@@ -6196,6 +6295,18 @@ class AdHocFiltersVariable extends SceneObjectBase {
6196
6295
  this._updateFilter(filter, original);
6197
6296
  }
6198
6297
  }
6298
+ /**
6299
+ * Clear all user-added filters and restore origin filters to their original values.
6300
+ */
6301
+ clearAll() {
6302
+ var _a;
6303
+ (_a = this.state.originFilters) == null ? void 0 : _a.forEach((filter) => {
6304
+ if (filter.restorable) {
6305
+ this.restoreOriginalFilter(filter);
6306
+ }
6307
+ });
6308
+ this.setState({ filters: [] });
6309
+ }
6199
6310
  getValue(fieldPath) {
6200
6311
  if (fieldPath === ORIGIN_FILTERS_KEY) {
6201
6312
  const originFilters = this.state.originFilters;
@@ -7064,6 +7175,7 @@ class GroupByVariable extends MultiValueVariable {
7064
7175
  }
7065
7176
  GroupByVariable.Component = GroupByVariableRenderer;
7066
7177
  function GroupByVariableRenderer({ model }) {
7178
+ var _a, _b;
7067
7179
  const {
7068
7180
  value,
7069
7181
  text,
@@ -7084,10 +7196,10 @@ function GroupByVariableRenderer({ model }) {
7084
7196
  const arrayValue = lodash.isArray(value) ? value : [value];
7085
7197
  const arrayText = lodash.isArray(text) ? text : [text];
7086
7198
  return arrayValue.map((value2, idx) => {
7087
- var _a;
7199
+ var _a2;
7088
7200
  return {
7089
7201
  value: value2,
7090
- label: String((_a = arrayText[idx]) != null ? _a : value2)
7202
+ label: String((_a2 = arrayText[idx]) != null ? _a2 : value2)
7091
7203
  };
7092
7204
  });
7093
7205
  }, [value, text]);
@@ -7118,7 +7230,8 @@ function GroupByVariableRenderer({ model }) {
7118
7230
  () => handleOptionGroups(optionSearcher(inputValue).map(toSelectableValue)),
7119
7231
  [optionSearcher, inputValue]
7120
7232
  );
7121
- const select = isMulti ? /* @__PURE__ */ React__default.default.createElement(
7233
+ const WideInputWrapper = (children) => /* @__PURE__ */ React__default.default.createElement("div", { className: styles.selectWrapper }, children);
7234
+ const select = isMulti ? /* @__PURE__ */ React__default.default.createElement(ConditionalWrapper, { condition: (_a = model.state.wideInput) != null ? _a : false, wrapper: WideInputWrapper }, /* @__PURE__ */ React__default.default.createElement(
7122
7235
  ui.MultiSelect,
7123
7236
  {
7124
7237
  "aria-label": i18n.t(
@@ -7188,7 +7301,7 @@ function GroupByVariableRenderer({ model }) {
7188
7301
  setIsOptionsOpen(false);
7189
7302
  }
7190
7303
  }
7191
- ) : /* @__PURE__ */ React__default.default.createElement(
7304
+ )) : /* @__PURE__ */ React__default.default.createElement(ConditionalWrapper, { condition: (_b = model.state.wideInput) != null ? _b : false, wrapper: WideInputWrapper }, /* @__PURE__ */ React__default.default.createElement(
7192
7305
  ui.Select,
7193
7306
  {
7194
7307
  "aria-label": i18n.t(
@@ -7202,7 +7315,6 @@ function GroupByVariableRenderer({ model }) {
7202
7315
  "Group by label"
7203
7316
  ),
7204
7317
  width: "auto",
7205
- className: css.cx(drilldownRecommendationsEnabled && styles.selectStylesInWrapper),
7206
7318
  inputValue,
7207
7319
  value: uncommittedValue && uncommittedValue.length > 0 ? uncommittedValue : null,
7208
7320
  allowCustomValue,
@@ -7246,12 +7358,19 @@ function GroupByVariableRenderer({ model }) {
7246
7358
  setIsOptionsOpen(false);
7247
7359
  }
7248
7360
  }
7249
- );
7361
+ ));
7250
7362
  if (!recommendations) {
7251
7363
  return select;
7252
7364
  }
7253
7365
  return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.wrapper }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.recommendations }, /* @__PURE__ */ React__default.default.createElement(recommendations.Component, { model: recommendations })), select);
7254
7366
  }
7367
+ const ConditionalWrapper = ({
7368
+ condition,
7369
+ wrapper,
7370
+ children
7371
+ }) => {
7372
+ return condition ? wrapper(children) : /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, children);
7373
+ };
7255
7374
  const filterNoOp = () => true;
7256
7375
  function WideMenu(props) {
7257
7376
  return /* @__PURE__ */ React__default.default.createElement(components.Menu, { ...props }, /* @__PURE__ */ React__default.default.createElement("div", { style: { minWidth: "220px" } }, props.children));
@@ -7268,6 +7387,22 @@ function toSelectableValue(input) {
7268
7387
  return result;
7269
7388
  }
7270
7389
  const getStyles$a = (theme) => ({
7390
+ selectWrapper: css.css({
7391
+ display: "flex",
7392
+ minWidth: 0,
7393
+ width: "100%"
7394
+ }),
7395
+ // Fix for noMultiValueWrap grid layout - prevent pills from stretching
7396
+ // when the select is full width. The grid layout uses gridAutoFlow: column
7397
+ // which stretches items by default.
7398
+ fullWidthMultiSelect: css.css({
7399
+ width: "100%",
7400
+ // Target the value container (has data-testid) which uses grid layout
7401
+ "& [data-testid]": {
7402
+ gridAutoColumns: "max-content",
7403
+ justifyItems: "start"
7404
+ }
7405
+ }),
7271
7406
  wrapper: css.css({
7272
7407
  display: "flex"
7273
7408
  }),
@@ -16807,7 +16942,7 @@ function __variableDynamicImportRuntime0__(path) {
16807
16942
  switch (path) {
16808
16943
  case '../locales/cs-CZ/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-DPdlSPjz.js'); });
16809
16944
  case '../locales/de-DE/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-BHIE4ld0.js'); });
16810
- case '../locales/en-US/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-C9F_2hih.js'); });
16945
+ case '../locales/en-US/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-DrGXYYn6.js'); });
16811
16946
  case '../locales/es-ES/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-D4tq59Dc.js'); });
16812
16947
  case '../locales/fr-FR/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-Ce77KCbO.js'); });
16813
16948
  case '../locales/hu-HU/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-DMYCnFop.js'); });