@grafana/scenes 6.35.2 → 6.35.3

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.d.ts CHANGED
@@ -601,6 +601,15 @@ interface SceneDataProvider<T extends SceneObjectState = SceneDataState> extends
601
601
  isDataReadyToDisplay?: () => boolean;
602
602
  cancelQuery?: () => void;
603
603
  getResultsStream(): Observable<SceneDataProviderResult>;
604
+ /**
605
+ * Can be used to disable query execution for scene elements that are out of view
606
+ */
607
+ isInViewChanged?(isInView: boolean): void;
608
+ /**
609
+ * Allow activating or deactivating the isInView behavior
610
+ * This is useful for external consumers of a data provider (i.e., the Dashboard datasource)
611
+ */
612
+ bypassIsInViewChanged?(bypassIsInView: boolean): void;
604
613
  }
605
614
  interface SceneDataLayerProviderState extends SceneDataState {
606
615
  name: string;
@@ -1810,6 +1819,9 @@ declare class SceneQueryRunner extends SceneObjectBase<QueryRunnerState> impleme
1810
1819
  private _scopedVars;
1811
1820
  private _layerAnnotations?;
1812
1821
  private _resultAnnotations?;
1822
+ private _isInView;
1823
+ private _bypassIsInView;
1824
+ private _queryNotExecutedWhenOutOfView;
1813
1825
  getResultsStream(): ReplaySubject<SceneDataProviderResult>;
1814
1826
  protected _variableDependency: VariableDependencyConfig<QueryRunnerState>;
1815
1827
  private _drilldownDependenciesManager;
@@ -1858,6 +1870,8 @@ declare class SceneQueryRunner extends SceneObjectBase<QueryRunnerState> impleme
1858
1870
  */
1859
1871
  private getClosestExtraQueryProviders;
1860
1872
  private isQueryModeAuto;
1873
+ isInViewChanged(isInView: boolean): void;
1874
+ bypassIsInViewChanged(bypassIsInView: boolean): void;
1861
1875
  }
1862
1876
 
1863
1877
  interface DataProviderSharerState extends SceneDataState {
@@ -1950,6 +1964,8 @@ declare class SceneDataTransformer extends SceneObjectBase<SceneDataTransformerS
1950
1964
  cancelQuery(): void;
1951
1965
  getResultsStream(): ReplaySubject<SceneDataProviderResult>;
1952
1966
  clone(withState?: Partial<SceneDataTransformerState>): this;
1967
+ isInViewChanged(isInView: boolean): void;
1968
+ bypassIsInViewChanged(bypassIsInView: boolean): void;
1953
1969
  private haveAlreadyTransformedData;
1954
1970
  private transform;
1955
1971
  private _interpolateVariablesInTransformationConfigs;
package/dist/index.js CHANGED
@@ -6746,6 +6746,9 @@ class SceneQueryRunner extends SceneObjectBase {
6746
6746
  this._variableValueRecorder = new VariableValueRecorder();
6747
6747
  this._results = new rxjs.ReplaySubject(1);
6748
6748
  this._scopedVars = { __sceneObject: wrapInSafeSerializableSceneObject(this) };
6749
+ this._isInView = true;
6750
+ this._bypassIsInView = false;
6751
+ this._queryNotExecutedWhenOutOfView = false;
6749
6752
  this._variableDependency = new VariableDependencyConfig(this, {
6750
6753
  statePaths: ["queries", "datasource", "minInterval"],
6751
6754
  onVariableUpdateCompleted: this.onVariableUpdatesCompleted.bind(this),
@@ -6985,6 +6988,11 @@ class SceneQueryRunner extends SceneObjectBase {
6985
6988
  if (!this.state.maxDataPoints && this.state.maxDataPointsFromWidth && !this._containerWidth) {
6986
6989
  return;
6987
6990
  }
6991
+ if (this.isQueryModeAuto() && !this._isInView && !this._bypassIsInView) {
6992
+ this._queryNotExecutedWhenOutOfView = true;
6993
+ return;
6994
+ }
6995
+ this._queryNotExecutedWhenOutOfView = false;
6988
6996
  if (!this._dataLayersSub) {
6989
6997
  this._handleDataLayers();
6990
6998
  }
@@ -7148,6 +7156,20 @@ class SceneQueryRunner extends SceneObjectBase {
7148
7156
  var _a;
7149
7157
  return ((_a = this.state.runQueriesMode) != null ? _a : "auto") === "auto";
7150
7158
  }
7159
+ isInViewChanged(isInView) {
7160
+ writeSceneLog("SceneQueryRunner", `isInViewChanged: ${isInView}`, this.state.key);
7161
+ this._isInView = isInView;
7162
+ if (isInView && this._queryNotExecutedWhenOutOfView) {
7163
+ this.runQueries();
7164
+ }
7165
+ }
7166
+ bypassIsInViewChanged(bypassIsInView) {
7167
+ writeSceneLog("SceneQueryRunner", `bypassIsInViewChanged: ${bypassIsInView}`, this.state.key);
7168
+ this._bypassIsInView = bypassIsInView;
7169
+ if (bypassIsInView && this._queryNotExecutedWhenOutOfView) {
7170
+ this.runQueries();
7171
+ }
7172
+ }
7151
7173
  }
7152
7174
  function findFirstDatasource(targets) {
7153
7175
  var _a, _b;
@@ -8588,6 +8610,71 @@ const getStyles$8 = (theme) => ({
8588
8610
  })
8589
8611
  });
8590
8612
 
8613
+ function useUniqueId() {
8614
+ var _a;
8615
+ const idRefLazy = React.useRef(void 0);
8616
+ (_a = idRefLazy.current) != null ? _a : idRefLazy.current = lodash.uniqueId();
8617
+ return idRefLazy.current;
8618
+ }
8619
+ const LazyLoader = React__default.default.forwardRef(
8620
+ ({ children, onLoad, onChange, className, ...rest }, ref) => {
8621
+ const id = useUniqueId();
8622
+ const { hideEmpty } = ui.useStyles2(getStyles$7);
8623
+ const [loaded, setLoaded] = React.useState(false);
8624
+ const [isInView, setIsInView] = React.useState(false);
8625
+ const innerRef = React.useRef(null);
8626
+ React.useImperativeHandle(ref, () => innerRef.current);
8627
+ reactUse.useEffectOnce(() => {
8628
+ LazyLoader.addCallback(id, (entry) => {
8629
+ if (!loaded && entry.isIntersecting) {
8630
+ setLoaded(true);
8631
+ onLoad == null ? void 0 : onLoad();
8632
+ }
8633
+ setIsInView(entry.isIntersecting);
8634
+ onChange == null ? void 0 : onChange(entry.isIntersecting);
8635
+ });
8636
+ const wrapperEl = innerRef.current;
8637
+ if (wrapperEl) {
8638
+ LazyLoader.observer.observe(wrapperEl);
8639
+ }
8640
+ return () => {
8641
+ wrapperEl && LazyLoader.observer.unobserve(wrapperEl);
8642
+ delete LazyLoader.callbacks[id];
8643
+ if (Object.keys(LazyLoader.callbacks).length === 0) {
8644
+ LazyLoader.observer.disconnect();
8645
+ }
8646
+ };
8647
+ });
8648
+ return /* @__PURE__ */ React__default.default.createElement("div", { id, ref: innerRef, className: `${hideEmpty} ${className}`, ...rest }, !loaded ? i18n.t("grafana-scenes.components.lazy-loader.placeholder", "\xA0") : /* @__PURE__ */ React__default.default.createElement(LazyLoaderInViewContext.Provider, { value: isInView }, children));
8649
+ }
8650
+ );
8651
+ function getStyles$7() {
8652
+ return {
8653
+ hideEmpty: css.css({
8654
+ "&:empty": {
8655
+ display: "none"
8656
+ }
8657
+ })
8658
+ };
8659
+ }
8660
+ LazyLoader.displayName = "LazyLoader";
8661
+ LazyLoader.callbacks = {};
8662
+ LazyLoader.addCallback = (id, c) => LazyLoader.callbacks[id] = c;
8663
+ LazyLoader.observer = new IntersectionObserver(
8664
+ (entries) => {
8665
+ for (const entry of entries) {
8666
+ if (typeof LazyLoader.callbacks[entry.target.id] === "function") {
8667
+ LazyLoader.callbacks[entry.target.id](entry);
8668
+ }
8669
+ }
8670
+ },
8671
+ { rootMargin: "100px" }
8672
+ );
8673
+ const LazyLoaderInViewContext = React__default.default.createContext(true);
8674
+ function useLazyLoaderIsInView() {
8675
+ return React__default.default.useContext(LazyLoaderInViewContext);
8676
+ }
8677
+
8591
8678
  function VizPanelRenderer({ model }) {
8592
8679
  var _a;
8593
8680
  const {
@@ -8630,6 +8717,12 @@ function VizPanelRenderer({ model }) {
8630
8717
  const sceneTimeRange = sceneGraph.getTimeRange(model);
8631
8718
  const timeZone = sceneTimeRange.getTimeZone();
8632
8719
  const timeRange = model.getTimeRange(dataWithFieldConfig);
8720
+ const isInView = useLazyLoaderIsInView();
8721
+ React.useEffect(() => {
8722
+ if (dataObject.isInViewChanged) {
8723
+ dataObject.isInViewChanged(isInView);
8724
+ }
8725
+ }, [isInView, dataObject]);
8633
8726
  const titleInterpolated = model.interpolate(title, void 0, "text");
8634
8727
  const alertStateStyles = ui.useStyles2(getAlertStateStyles);
8635
8728
  if (!plugin) {
@@ -9190,6 +9283,14 @@ class SceneDataTransformer extends SceneObjectBase {
9190
9283
  }
9191
9284
  return clone;
9192
9285
  }
9286
+ isInViewChanged(isInView) {
9287
+ var _a, _b;
9288
+ (_b = (_a = this.state.$data) == null ? void 0 : _a.isInViewChanged) == null ? void 0 : _b.call(_a, isInView);
9289
+ }
9290
+ bypassIsInViewChanged(bypassIsInView) {
9291
+ var _a, _b;
9292
+ (_b = (_a = this.state.$data) == null ? void 0 : _a.bypassIsInViewChanged) == null ? void 0 : _b.call(_a, bypassIsInView);
9293
+ }
9193
9294
  haveAlreadyTransformedData(data) {
9194
9295
  if (!this._prevDataFromSource) {
9195
9296
  return false;
@@ -11497,10 +11598,10 @@ class EmbeddedScene extends SceneObjectBase {
11497
11598
  EmbeddedScene.Component = EmbeddedSceneRenderer;
11498
11599
  function EmbeddedSceneRenderer({ model }) {
11499
11600
  const { body, controls } = model.useState();
11500
- const styles = ui.useStyles2(getStyles$7);
11601
+ const styles = ui.useStyles2(getStyles$6);
11501
11602
  return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.container }, controls && /* @__PURE__ */ React__default.default.createElement("div", { className: styles.controls }, controls.map((control) => /* @__PURE__ */ React__default.default.createElement(control.Component, { key: control.state.key, model: control }))), /* @__PURE__ */ React__default.default.createElement("div", { className: styles.body }, /* @__PURE__ */ React__default.default.createElement(body.Component, { model: body })));
11502
11603
  }
11503
- const getStyles$7 = (theme) => {
11604
+ const getStyles$6 = (theme) => {
11504
11605
  return {
11505
11606
  container: css.css({
11506
11607
  flexGrow: 1,
@@ -11686,67 +11787,6 @@ function isSceneGridLayout(child) {
11686
11787
  return child instanceof SceneGridLayout;
11687
11788
  }
11688
11789
 
11689
- function useUniqueId() {
11690
- var _a;
11691
- const idRefLazy = React.useRef(void 0);
11692
- (_a = idRefLazy.current) != null ? _a : idRefLazy.current = lodash.uniqueId();
11693
- return idRefLazy.current;
11694
- }
11695
- const LazyLoader = React__default.default.forwardRef(
11696
- ({ children, onLoad, onChange, className, ...rest }, ref) => {
11697
- const id = useUniqueId();
11698
- const { hideEmpty } = ui.useStyles2(getStyles$6);
11699
- const [loaded, setLoaded] = React.useState(false);
11700
- const [isInView, setIsInView] = React.useState(false);
11701
- const innerRef = React.useRef(null);
11702
- React.useImperativeHandle(ref, () => innerRef.current);
11703
- reactUse.useEffectOnce(() => {
11704
- LazyLoader.addCallback(id, (entry) => {
11705
- if (!loaded && entry.isIntersecting) {
11706
- setLoaded(true);
11707
- onLoad == null ? void 0 : onLoad();
11708
- }
11709
- setIsInView(entry.isIntersecting);
11710
- onChange == null ? void 0 : onChange(entry.isIntersecting);
11711
- });
11712
- const wrapperEl = innerRef.current;
11713
- if (wrapperEl) {
11714
- LazyLoader.observer.observe(wrapperEl);
11715
- }
11716
- return () => {
11717
- wrapperEl && LazyLoader.observer.unobserve(wrapperEl);
11718
- delete LazyLoader.callbacks[id];
11719
- if (Object.keys(LazyLoader.callbacks).length === 0) {
11720
- LazyLoader.observer.disconnect();
11721
- }
11722
- };
11723
- });
11724
- return /* @__PURE__ */ React__default.default.createElement("div", { id, ref: innerRef, className: `${hideEmpty} ${className}`, ...rest }, !loaded || !isInView ? i18n.t("grafana-scenes.components.lazy-loader.placeholder", "\xA0") : children);
11725
- }
11726
- );
11727
- function getStyles$6() {
11728
- return {
11729
- hideEmpty: css.css({
11730
- "&:empty": {
11731
- display: "none"
11732
- }
11733
- })
11734
- };
11735
- }
11736
- LazyLoader.displayName = "LazyLoader";
11737
- LazyLoader.callbacks = {};
11738
- LazyLoader.addCallback = (id, c) => LazyLoader.callbacks[id] = c;
11739
- LazyLoader.observer = new IntersectionObserver(
11740
- (entries) => {
11741
- for (const entry of entries) {
11742
- if (typeof LazyLoader.callbacks[entry.target.id] === "function") {
11743
- LazyLoader.callbacks[entry.target.id](entry);
11744
- }
11745
- }
11746
- },
11747
- { rootMargin: "100px" }
11748
- );
11749
-
11750
11790
  function SceneGridLayoutRenderer({ model }) {
11751
11791
  const { children, isLazy, isDraggable, isResizable } = model.useState();
11752
11792
  const [outerDivRef, { width, height }] = reactUse.useMeasure();