@grafana/scenes 5.12.0 → 5.13.0--canary.878.10702174754.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,11 @@
1
1
  import { locationService } from '@grafana/runtime';
2
2
  import { SceneObjectStateChangedEvent } from '../core/events.js';
3
3
  import { writeSceneLog } from '../utils/writeSceneLog.js';
4
+ import { Subscription } from 'rxjs';
4
5
  import { UniqueUrlKeyMapper } from './UniqueUrlKeyMapper.js';
5
- import { syncStateFromUrl, getUrlState, isUrlValueEqual } from './utils.js';
6
+ import { getUrlState, syncStateFromUrl, isUrlValueEqual } from './utils.js';
7
+ import { BusEventWithPayload } from '@grafana/data';
8
+ import { useMemo } from 'react';
6
9
 
7
10
  var __accessCheck = (obj, member, msg) => {
8
11
  if (!member.has(obj))
@@ -22,54 +25,53 @@ var __privateSet = (obj, member, value, setter) => {
22
25
  setter ? setter.call(obj, value) : member.set(obj, value);
23
26
  return value;
24
27
  };
25
- var _onStateChanged, _cache, _location;
28
+ var _cache, _location;
29
+ class NewSceneObjectAddedEvent extends BusEventWithPayload {
30
+ }
31
+ NewSceneObjectAddedEvent.type = "new-scene-object-added";
26
32
  class UrlSyncManager {
27
- constructor() {
33
+ constructor(_options = {}) {
28
34
  this._urlKeyMapper = new UniqueUrlKeyMapper();
29
- this._stateSub = null;
30
35
  this._paramsCache = new UrlParamsCache();
31
- __privateAdd(this, _onStateChanged, ({ payload }) => {
32
- const changedObject = payload.changedObject;
33
- if (changedObject.urlSync) {
34
- const newUrlState = changedObject.urlSync.getUrlState();
35
- const searchParams = locationService.getSearch();
36
- const mappedUpdated = {};
37
- for (const [key, newUrlValue] of Object.entries(newUrlState)) {
38
- const uniqueKey = this._urlKeyMapper.getUniqueKey(key, changedObject);
39
- const currentUrlValue = searchParams.getAll(uniqueKey);
40
- if (!isUrlValueEqual(currentUrlValue, newUrlValue)) {
41
- mappedUpdated[uniqueKey] = newUrlValue;
42
- }
43
- }
44
- if (Object.keys(mappedUpdated).length > 0) {
45
- writeSceneLog("UrlSyncManager", "onStateChange updating URL");
46
- locationService.partial(mappedUpdated, true);
47
- this._lastLocation = locationService.getLocation();
48
- }
49
- }
50
- });
36
+ this._options = _options;
51
37
  }
52
38
  initSync(root) {
53
39
  var _a;
54
- if (this._stateSub) {
40
+ if (this._subs) {
55
41
  writeSceneLog("UrlSyncManager", "Unregister previous scene state subscription", (_a = this._sceneRoot) == null ? void 0 : _a.state.key);
56
- this._stateSub.unsubscribe();
42
+ this._subs.unsubscribe();
57
43
  }
58
44
  writeSceneLog("UrlSyncManager", "init", root.state.key);
59
45
  this._sceneRoot = root;
60
- this._stateSub = root.subscribeToEvent(SceneObjectStateChangedEvent, __privateGet(this, _onStateChanged));
46
+ this._subs = new Subscription();
47
+ this._subs.add(
48
+ root.subscribeToEvent(SceneObjectStateChangedEvent, (evt) => {
49
+ this.handleSceneObjectStateChanged(evt.payload.changedObject);
50
+ })
51
+ );
52
+ this._subs.add(
53
+ root.subscribeToEvent(NewSceneObjectAddedEvent, (evt) => {
54
+ this.handleNewObject(evt.payload);
55
+ })
56
+ );
61
57
  this._urlKeyMapper.clear();
62
58
  this._lastLocation = locationService.getLocation();
63
59
  this.handleNewObject(this._sceneRoot);
60
+ if (this._options.updateUrlOnInit) {
61
+ const urlState = getUrlState(root);
62
+ if (isUrlStateDifferent(urlState, this._paramsCache.getParams())) {
63
+ locationService.partial(urlState, true);
64
+ }
65
+ }
64
66
  }
65
67
  cleanUp(root) {
66
68
  if (this._sceneRoot !== root) {
67
69
  return;
68
70
  }
69
71
  writeSceneLog("UrlSyncManager", "Clean up");
70
- if (this._stateSub) {
71
- this._stateSub.unsubscribe();
72
- this._stateSub = null;
72
+ if (this._subs) {
73
+ this._subs.unsubscribe();
74
+ this._subs = void 0;
73
75
  writeSceneLog(
74
76
  "UrlSyncManager",
75
77
  "Root deactived, unsub to state",
@@ -94,11 +96,33 @@ class UrlSyncManager {
94
96
  }
95
97
  syncStateFromUrl(sceneObj, this._paramsCache.getParams(), this._urlKeyMapper);
96
98
  }
99
+ handleSceneObjectStateChanged(changedObject) {
100
+ var _a, _b;
101
+ if (!changedObject.urlSync) {
102
+ return;
103
+ }
104
+ const newUrlState = changedObject.urlSync.getUrlState();
105
+ const searchParams = locationService.getSearch();
106
+ const mappedUpdated = {};
107
+ for (const [key, newUrlValue] of Object.entries(newUrlState)) {
108
+ const uniqueKey = this._urlKeyMapper.getUniqueKey(key, changedObject);
109
+ const currentUrlValue = searchParams.getAll(uniqueKey);
110
+ if (!isUrlValueEqual(currentUrlValue, newUrlValue)) {
111
+ mappedUpdated[uniqueKey] = newUrlValue;
112
+ }
113
+ }
114
+ if (Object.keys(mappedUpdated).length > 0) {
115
+ const shouldCreateHistoryEntry = (_b = (_a = changedObject.urlSync).shouldCreateHistoryStep) == null ? void 0 : _b.call(_a, newUrlState);
116
+ const shouldReplace = shouldCreateHistoryEntry !== true;
117
+ writeSceneLog("UrlSyncManager", "onStateChange updating URL");
118
+ locationService.partial(mappedUpdated, shouldReplace);
119
+ this._lastLocation = locationService.getLocation();
120
+ }
121
+ }
97
122
  getUrlState(root) {
98
123
  return getUrlState(root);
99
124
  }
100
125
  }
101
- _onStateChanged = new WeakMap();
102
126
  class UrlParamsCache {
103
127
  constructor() {
104
128
  __privateAdd(this, _cache, void 0);
@@ -116,13 +140,23 @@ class UrlParamsCache {
116
140
  }
117
141
  _cache = new WeakMap();
118
142
  _location = new WeakMap();
119
- let urlSyncManager;
120
- function getUrlSyncManager() {
121
- if (!urlSyncManager) {
122
- urlSyncManager = new UrlSyncManager();
143
+ function isUrlStateDifferent(sceneUrlState, currentParams) {
144
+ for (let key in sceneUrlState) {
145
+ if (!isUrlValueEqual(currentParams.getAll(key), sceneUrlState[key])) {
146
+ return true;
147
+ }
123
148
  }
124
- return urlSyncManager;
149
+ return false;
150
+ }
151
+ function useUrlSyncManager(options) {
152
+ return useMemo(
153
+ () => new UrlSyncManager({
154
+ updateUrlOnInit: options.updateUrlOnInit,
155
+ createBrowserHistorySteps: options.createBrowserHistorySteps
156
+ }),
157
+ [options.updateUrlOnInit, options.createBrowserHistorySteps]
158
+ );
125
159
  }
126
160
 
127
- export { UrlSyncManager, getUrlSyncManager };
161
+ export { NewSceneObjectAddedEvent, UrlSyncManager, useUrlSyncManager };
128
162
  //# sourceMappingURL=UrlSyncManager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UrlSyncManager.js","sources":["../../../src/services/UrlSyncManager.ts"],"sourcesContent":["import { Location } from 'history';\n\nimport { locationService } from '@grafana/runtime';\n\nimport { SceneObjectStateChangedEvent } from '../core/events';\nimport { SceneObject, SceneObjectUrlValues } from '../core/types';\nimport { writeSceneLog } from '../utils/writeSceneLog';\nimport { Unsubscribable } from 'rxjs';\nimport { UniqueUrlKeyMapper } from './UniqueUrlKeyMapper';\nimport { getUrlState, isUrlValueEqual, syncStateFromUrl } from './utils';\n\nexport interface UrlSyncManagerLike {\n initSync(root: SceneObject): void;\n cleanUp(root: SceneObject): void;\n getUrlState(root: SceneObject): SceneObjectUrlValues;\n handleNewLocation(location: Location): void;\n handleNewObject(sceneObj: SceneObject): void;\n}\n\nexport class UrlSyncManager implements UrlSyncManagerLike {\n private _urlKeyMapper = new UniqueUrlKeyMapper();\n private _sceneRoot?: SceneObject;\n private _stateSub: Unsubscribable | null = null;\n private _lastLocation: Location | undefined;\n private _paramsCache = new UrlParamsCache();\n\n /**\n * Updates the current scene state to match URL state.\n */\n public initSync(root: SceneObject) {\n if (this._stateSub) {\n writeSceneLog('UrlSyncManager', 'Unregister previous scene state subscription', this._sceneRoot?.state.key);\n this._stateSub.unsubscribe();\n }\n\n writeSceneLog('UrlSyncManager', 'init', root.state.key);\n\n this._sceneRoot = root;\n this._stateSub = root.subscribeToEvent(SceneObjectStateChangedEvent, this.#onStateChanged);\n\n this._urlKeyMapper.clear();\n this._lastLocation = locationService.getLocation();\n\n this.handleNewObject(this._sceneRoot);\n }\n\n public cleanUp(root: SceneObject) {\n // Ignore this if we have a new or different root\n if (this._sceneRoot !== root) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'Clean up');\n\n if (this._stateSub) {\n this._stateSub.unsubscribe();\n this._stateSub = null;\n writeSceneLog(\n 'UrlSyncManager',\n 'Root deactived, unsub to state',\n 'same key',\n this._sceneRoot.state.key === root.state.key\n );\n }\n\n this._sceneRoot = undefined;\n this._lastLocation = undefined;\n }\n\n public handleNewLocation(location: Location) {\n if (!this._sceneRoot || this._lastLocation === location) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'handleNewLocation');\n\n this._lastLocation = location;\n\n // Sync scene state tree from url\n syncStateFromUrl(this._sceneRoot!, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n public handleNewObject(sceneObj: SceneObject) {\n if (!this._sceneRoot) {\n return;\n }\n\n syncStateFromUrl(sceneObj, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n #onStateChanged = ({ payload }: SceneObjectStateChangedEvent) => {\n const changedObject = payload.changedObject;\n\n if (changedObject.urlSync) {\n const newUrlState = changedObject.urlSync.getUrlState();\n\n const searchParams = locationService.getSearch();\n const mappedUpdated: SceneObjectUrlValues = {};\n\n for (const [key, newUrlValue] of Object.entries(newUrlState)) {\n const uniqueKey = this._urlKeyMapper.getUniqueKey(key, changedObject);\n const currentUrlValue = searchParams.getAll(uniqueKey);\n\n if (!isUrlValueEqual(currentUrlValue, newUrlValue)) {\n mappedUpdated[uniqueKey] = newUrlValue;\n }\n }\n\n if (Object.keys(mappedUpdated).length > 0) {\n writeSceneLog('UrlSyncManager', 'onStateChange updating URL');\n locationService.partial(mappedUpdated, true);\n\n /// Mark the location already handled\n this._lastLocation = locationService.getLocation();\n }\n }\n };\n\n public getUrlState(root: SceneObject): SceneObjectUrlValues {\n return getUrlState(root);\n }\n}\n\nclass UrlParamsCache {\n #cache: URLSearchParams | undefined;\n #location: Location | undefined;\n\n public getParams(): URLSearchParams {\n const location = locationService.getLocation();\n\n if (this.#location === location) {\n return this.#cache!;\n }\n\n this.#location = location;\n this.#cache = new URLSearchParams(location.search);\n\n return this.#cache;\n }\n}\n\nlet urlSyncManager: UrlSyncManagerLike | undefined;\n\nexport function getUrlSyncManager(): UrlSyncManagerLike {\n if (!urlSyncManager) {\n urlSyncManager = new UrlSyncManager();\n }\n\n return urlSyncManager;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"UrlSyncManager.js","sources":["../../../src/services/UrlSyncManager.ts"],"sourcesContent":["import { Location } from 'history';\n\nimport { locationService } from '@grafana/runtime';\n\nimport { SceneObjectStateChangedEvent } from '../core/events';\nimport { SceneObject, SceneObjectUrlValues, SceneUrlSyncOptions } from '../core/types';\nimport { writeSceneLog } from '../utils/writeSceneLog';\nimport { Subscription } from 'rxjs';\nimport { UniqueUrlKeyMapper } from './UniqueUrlKeyMapper';\nimport { getUrlState, isUrlValueEqual, syncStateFromUrl } from './utils';\nimport { BusEventWithPayload } from '@grafana/data';\nimport { useMemo } from 'react';\n\nexport interface UrlSyncManagerLike {\n initSync(root: SceneObject): void;\n cleanUp(root: SceneObject): void;\n handleNewLocation(location: Location): void;\n handleNewObject(sceneObj: SceneObject): void;\n}\n\n/**\n * Notify the url sync manager of a new object that has been added to the scene\n * that needs to init state from URL.\n */\nexport class NewSceneObjectAddedEvent extends BusEventWithPayload<SceneObject> {\n public static readonly type = 'new-scene-object-added';\n}\n\nexport class UrlSyncManager implements UrlSyncManagerLike {\n private _urlKeyMapper = new UniqueUrlKeyMapper();\n private _sceneRoot?: SceneObject;\n private _subs: Subscription | undefined;\n private _lastLocation: Location | undefined;\n private _paramsCache = new UrlParamsCache();\n private _options: SceneUrlSyncOptions;\n\n public constructor(_options: SceneUrlSyncOptions = {}) {\n this._options = _options;\n }\n\n /**\n * Updates the current scene state to match URL state.\n */\n public initSync(root: SceneObject) {\n if (this._subs) {\n writeSceneLog('UrlSyncManager', 'Unregister previous scene state subscription', this._sceneRoot?.state.key);\n this._subs.unsubscribe();\n }\n\n writeSceneLog('UrlSyncManager', 'init', root.state.key);\n\n this._sceneRoot = root;\n this._subs = new Subscription();\n\n this._subs.add(\n root.subscribeToEvent(SceneObjectStateChangedEvent, (evt) => {\n this.handleSceneObjectStateChanged(evt.payload.changedObject);\n })\n );\n\n this._subs.add(\n root.subscribeToEvent(NewSceneObjectAddedEvent, (evt) => {\n this.handleNewObject(evt.payload);\n })\n );\n\n this._urlKeyMapper.clear();\n this._lastLocation = locationService.getLocation();\n\n // Sync current url with state\n this.handleNewObject(this._sceneRoot);\n\n if (this._options.updateUrlOnInit) {\n // Get current url state and update url to match\n const urlState = getUrlState(root);\n\n if (isUrlStateDifferent(urlState, this._paramsCache.getParams())) {\n locationService.partial(urlState, true);\n }\n }\n }\n\n public cleanUp(root: SceneObject) {\n // Ignore this if we have a new or different root\n if (this._sceneRoot !== root) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'Clean up');\n\n if (this._subs) {\n this._subs.unsubscribe();\n this._subs = undefined;\n\n writeSceneLog(\n 'UrlSyncManager',\n 'Root deactived, unsub to state',\n 'same key',\n this._sceneRoot.state.key === root.state.key\n );\n }\n\n this._sceneRoot = undefined;\n this._lastLocation = undefined;\n }\n\n public handleNewLocation(location: Location) {\n if (!this._sceneRoot || this._lastLocation === location) {\n return;\n }\n\n writeSceneLog('UrlSyncManager', 'handleNewLocation');\n\n this._lastLocation = location;\n\n // Sync scene state tree from url\n syncStateFromUrl(this._sceneRoot!, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n public handleNewObject(sceneObj: SceneObject) {\n if (!this._sceneRoot) {\n return;\n }\n\n syncStateFromUrl(sceneObj, this._paramsCache.getParams(), this._urlKeyMapper);\n }\n\n private handleSceneObjectStateChanged(changedObject: SceneObject) {\n if (!changedObject.urlSync) {\n return;\n }\n\n const newUrlState = changedObject.urlSync.getUrlState();\n\n const searchParams = locationService.getSearch();\n const mappedUpdated: SceneObjectUrlValues = {};\n\n for (const [key, newUrlValue] of Object.entries(newUrlState)) {\n const uniqueKey = this._urlKeyMapper.getUniqueKey(key, changedObject);\n const currentUrlValue = searchParams.getAll(uniqueKey);\n\n if (!isUrlValueEqual(currentUrlValue, newUrlValue)) {\n mappedUpdated[uniqueKey] = newUrlValue;\n }\n }\n\n if (Object.keys(mappedUpdated).length > 0) {\n const shouldCreateHistoryEntry = changedObject.urlSync.shouldCreateHistoryStep?.(newUrlState);\n const shouldReplace = shouldCreateHistoryEntry !== true;\n\n writeSceneLog('UrlSyncManager', 'onStateChange updating URL');\n locationService.partial(mappedUpdated, shouldReplace);\n\n /// Mark the location already handled\n this._lastLocation = locationService.getLocation();\n }\n }\n\n public getUrlState(root: SceneObject): SceneObjectUrlValues {\n return getUrlState(root);\n }\n}\n\nclass UrlParamsCache {\n #cache: URLSearchParams | undefined;\n #location: Location | undefined;\n\n public getParams(): URLSearchParams {\n const location = locationService.getLocation();\n\n if (this.#location === location) {\n return this.#cache!;\n }\n\n this.#location = location;\n this.#cache = new URLSearchParams(location.search);\n\n return this.#cache;\n }\n}\n\nfunction isUrlStateDifferent(sceneUrlState: SceneObjectUrlValues, currentParams: URLSearchParams) {\n for (let key in sceneUrlState) {\n if (!isUrlValueEqual(currentParams.getAll(key), sceneUrlState[key])) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Creates a new memoized instance of the UrlSyncManager based on options\n */\nexport function useUrlSyncManager(options: SceneUrlSyncOptions): UrlSyncManagerLike {\n return useMemo(\n () =>\n new UrlSyncManager({\n updateUrlOnInit: options.updateUrlOnInit,\n createBrowserHistorySteps: options.createBrowserHistorySteps,\n }),\n [options.updateUrlOnInit, options.createBrowserHistorySteps]\n );\n}\n"],"names":[],"mappings":"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"}
@@ -1,13 +1,13 @@
1
1
  import { useState, useEffect } from 'react';
2
2
  import { useLocation } from 'react-router-dom';
3
- import { getUrlSyncManager } from './UrlSyncManager.js';
4
3
  import { locationService } from '@grafana/runtime';
5
4
  import { writeSceneLog } from '../utils/writeSceneLog.js';
5
+ import { useUrlSyncManager } from './UrlSyncManager.js';
6
6
 
7
- function useUrlSync(sceneRoot) {
8
- const urlSyncManager = getUrlSyncManager();
7
+ function useUrlSync(sceneRoot, options = {}) {
9
8
  const location = useLocation();
10
9
  const [isInitialized, setIsInitialized] = useState(false);
10
+ const urlSyncManager = useUrlSyncManager(options);
11
11
  useEffect(() => {
12
12
  urlSyncManager.initSync(sceneRoot);
13
13
  setIsInitialized(true);
@@ -1 +1 @@
1
- {"version":3,"file":"useUrlSync.js","sources":["../../../src/services/useUrlSync.ts"],"sourcesContent":["import { SceneObject } from '../core/types';\nimport { useEffect, useState } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { getUrlSyncManager } from './UrlSyncManager';\nimport { locationService } from '@grafana/runtime';\nimport { writeSceneLog } from '../utils/writeSceneLog';\n\nexport function useUrlSync(sceneRoot: SceneObject): boolean {\n const urlSyncManager = getUrlSyncManager();\n const location = useLocation();\n const [isInitialized, setIsInitialized] = useState(false);\n\n useEffect(() => {\n urlSyncManager.initSync(sceneRoot);\n setIsInitialized(true);\n return () => urlSyncManager.cleanUp(sceneRoot);\n }, [sceneRoot, urlSyncManager]);\n\n useEffect(() => {\n // Use latest location, as by the time this effect runs, the location might have changed again\n const latestLocation = locationService.getLocation();\n const locationToHandle = latestLocation !== location ? latestLocation : location;\n\n if (latestLocation !== location) {\n writeSceneLog('useUrlSync', 'latestLocation different from location')\n }\n\n urlSyncManager.handleNewLocation(locationToHandle);\n }, [sceneRoot, urlSyncManager, location]);\n\n return isInitialized;\n}\n\nexport interface UrlSyncContextProviderProps {\n scene: SceneObject;\n children: React.ReactNode;\n}\n"],"names":[],"mappings":";;;;;;AAOO,SAAS,WAAW,SAAiC,EAAA;AAC1D,EAAA,MAAM,iBAAiB,iBAAkB,EAAA,CAAA;AACzC,EAAA,MAAM,WAAW,WAAY,EAAA,CAAA;AAC7B,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,KAAK,CAAA,CAAA;AAExD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,cAAA,CAAe,SAAS,SAAS,CAAA,CAAA;AACjC,IAAA,gBAAA,CAAiB,IAAI,CAAA,CAAA;AACrB,IAAO,OAAA,MAAM,cAAe,CAAA,OAAA,CAAQ,SAAS,CAAA,CAAA;AAAA,GAC5C,EAAA,CAAC,SAAW,EAAA,cAAc,CAAC,CAAA,CAAA;AAE9B,EAAA,SAAA,CAAU,MAAM;AAEd,IAAM,MAAA,cAAA,GAAiB,gBAAgB,WAAY,EAAA,CAAA;AACnD,IAAM,MAAA,gBAAA,GAAmB,cAAmB,KAAA,QAAA,GAAW,cAAiB,GAAA,QAAA,CAAA;AAExE,IAAA,IAAI,mBAAmB,QAAU,EAAA;AAC/B,MAAA,aAAA,CAAc,cAAc,wCAAwC,CAAA,CAAA;AAAA,KACtE;AAEA,IAAA,cAAA,CAAe,kBAAkB,gBAAgB,CAAA,CAAA;AAAA,GAChD,EAAA,CAAC,SAAW,EAAA,cAAA,EAAgB,QAAQ,CAAC,CAAA,CAAA;AAExC,EAAO,OAAA,aAAA,CAAA;AACT;;;;"}
1
+ {"version":3,"file":"useUrlSync.js","sources":["../../../src/services/useUrlSync.ts"],"sourcesContent":["import { SceneObject, SceneUrlSyncOptions } from '../core/types';\nimport { useEffect, useState } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { locationService } from '@grafana/runtime';\nimport { writeSceneLog } from '../utils/writeSceneLog';\nimport { useUrlSyncManager } from './UrlSyncManager';\n\nexport function useUrlSync(sceneRoot: SceneObject, options: SceneUrlSyncOptions = {}): boolean {\n const location = useLocation();\n const [isInitialized, setIsInitialized] = useState(false);\n const urlSyncManager = useUrlSyncManager(options);\n\n useEffect(() => {\n urlSyncManager.initSync(sceneRoot);\n setIsInitialized(true);\n return () => urlSyncManager.cleanUp(sceneRoot);\n }, [sceneRoot, urlSyncManager]);\n\n useEffect(() => {\n // Use latest location, as by the time this effect runs, the location might have changed again\n const latestLocation = locationService.getLocation();\n const locationToHandle = latestLocation !== location ? latestLocation : location;\n\n if (latestLocation !== location) {\n writeSceneLog('useUrlSync', 'latestLocation different from location');\n }\n\n urlSyncManager.handleNewLocation(locationToHandle);\n }, [sceneRoot, urlSyncManager, location]);\n\n return isInitialized;\n}\n\nexport interface UrlSyncContextProviderProps {\n scene: SceneObject;\n children: React.ReactNode;\n}\n"],"names":[],"mappings":";;;;;;AAOO,SAAS,UAAW,CAAA,SAAA,EAAwB,OAA+B,GAAA,EAAa,EAAA;AAC7F,EAAA,MAAM,WAAW,WAAY,EAAA,CAAA;AAC7B,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAI,SAAS,KAAK,CAAA,CAAA;AACxD,EAAM,MAAA,cAAA,GAAiB,kBAAkB,OAAO,CAAA,CAAA;AAEhD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,cAAA,CAAe,SAAS,SAAS,CAAA,CAAA;AACjC,IAAA,gBAAA,CAAiB,IAAI,CAAA,CAAA;AACrB,IAAO,OAAA,MAAM,cAAe,CAAA,OAAA,CAAQ,SAAS,CAAA,CAAA;AAAA,GAC5C,EAAA,CAAC,SAAW,EAAA,cAAc,CAAC,CAAA,CAAA;AAE9B,EAAA,SAAA,CAAU,MAAM;AAEd,IAAM,MAAA,cAAA,GAAiB,gBAAgB,WAAY,EAAA,CAAA;AACnD,IAAM,MAAA,gBAAA,GAAmB,cAAmB,KAAA,QAAA,GAAW,cAAiB,GAAA,QAAA,CAAA;AAExE,IAAA,IAAI,mBAAmB,QAAU,EAAA;AAC/B,MAAA,aAAA,CAAc,cAAc,wCAAwC,CAAA,CAAA;AAAA,KACtE;AAEA,IAAA,cAAA,CAAe,kBAAkB,gBAAgB,CAAA,CAAA;AAAA,GAChD,EAAA,CAAC,SAAW,EAAA,cAAA,EAAgB,QAAQ,CAAC,CAAA,CAAA;AAExC,EAAO,OAAA,aAAA,CAAA;AACT;;;;"}
package/dist/index.d.ts CHANGED
@@ -262,11 +262,13 @@ declare function isSceneObject(obj: any): obj is SceneObject;
262
262
  interface SceneObjectWithUrlSync extends SceneObject {
263
263
  getUrlState(): SceneObjectUrlValues;
264
264
  updateFromUrl(values: SceneObjectUrlValues): void;
265
+ shouldCreateHistoryStep?(values: SceneObjectUrlValues): boolean;
265
266
  }
266
267
  interface SceneObjectUrlSyncHandler {
267
268
  getKeys(): string[];
268
269
  getUrlState(): SceneObjectUrlValues;
269
270
  updateFromUrl(values: SceneObjectUrlValues): void;
271
+ shouldCreateHistoryStep?(values: SceneObjectUrlValues): boolean;
270
272
  }
271
273
  interface DataRequestEnricher {
272
274
  enrichDataRequest(source: SceneObject): Partial<DataQueryRequest> | null;
@@ -330,6 +332,19 @@ interface SceneDataQuery extends DataQuery {
330
332
  [key: string]: any;
331
333
  timeRangeCompare?: boolean;
332
334
  }
335
+ interface SceneUrlSyncOptions {
336
+ /**
337
+ * This will update the url to contain all scene url state
338
+ * when the scene is initialized. Important for browser history "back" actions.
339
+ */
340
+ updateUrlOnInit?: boolean;
341
+ /**
342
+ * This is only supported by some objects if they implement
343
+ * shouldCreateHistoryStep where they can control what changes
344
+ * url changes should add a new browser history entry.
345
+ */
346
+ createBrowserHistorySteps?: boolean;
347
+ }
333
348
 
334
349
  /**
335
350
  *
@@ -959,6 +974,38 @@ declare class SceneQueryController extends SceneObjectBase<SceneQueryStateContro
959
974
  cancelAll(): void;
960
975
  }
961
976
 
977
+ interface UrlSyncManagerLike {
978
+ initSync(root: SceneObject): void;
979
+ cleanUp(root: SceneObject): void;
980
+ handleNewLocation(location: Location): void;
981
+ handleNewObject(sceneObj: SceneObject): void;
982
+ }
983
+ /**
984
+ * Notify the url sync manager of a new object that has been added to the scene
985
+ * that needs to init state from URL.
986
+ */
987
+ declare class NewSceneObjectAddedEvent extends BusEventWithPayload<SceneObject> {
988
+ static readonly type = "new-scene-object-added";
989
+ }
990
+ declare class UrlSyncManager implements UrlSyncManagerLike {
991
+ private _urlKeyMapper;
992
+ private _sceneRoot?;
993
+ private _subs;
994
+ private _lastLocation;
995
+ private _paramsCache;
996
+ private _options;
997
+ constructor(_options?: SceneUrlSyncOptions);
998
+ /**
999
+ * Updates the current scene state to match URL state.
1000
+ */
1001
+ initSync(root: SceneObject): void;
1002
+ cleanUp(root: SceneObject): void;
1003
+ handleNewLocation(location: Location): void;
1004
+ handleNewObject(sceneObj: SceneObject): void;
1005
+ private handleSceneObjectStateChanged;
1006
+ getUrlState(root: SceneObject): SceneObjectUrlValues;
1007
+ }
1008
+
962
1009
  /**
963
1010
  * Get the closest node with variables
964
1011
  */
@@ -1027,6 +1074,11 @@ declare function getAncestor<ParentType>(sceneObject: SceneObject, ancestorType:
1027
1074
  * Returns the closest query controller undefined if none found
1028
1075
  */
1029
1076
  declare function getQueryController(sceneObject: SceneObject): SceneQueryControllerLike | undefined;
1077
+ /**
1078
+ * Returns the closest SceneObject that has a state property with the
1079
+ * name urlSyncManager that is of type UrlSyncManager
1080
+ */
1081
+ declare function getUrlSyncManager(sceneObject: SceneObject): UrlSyncManagerLike | undefined;
1030
1082
 
1031
1083
  declare const sceneGraph: {
1032
1084
  getVariables: typeof getVariables;
@@ -1043,6 +1095,7 @@ declare const sceneGraph: {
1043
1095
  findAllObjects: typeof findAllObjects;
1044
1096
  getAncestor: typeof getAncestor;
1045
1097
  getQueryController: typeof getQueryController;
1098
+ getUrlSyncManager: typeof getUrlSyncManager;
1046
1099
  };
1047
1100
 
1048
1101
  interface ActWhenVariableChangedState extends SceneObjectState {
@@ -1213,10 +1266,13 @@ interface SceneObjectUrlSyncConfigOptions {
1213
1266
  declare class SceneObjectUrlSyncConfig implements SceneObjectUrlSyncHandler {
1214
1267
  private _sceneObject;
1215
1268
  private _keys;
1269
+ private _nextChangeShouldAddHistoryStep;
1216
1270
  constructor(_sceneObject: SceneObjectWithUrlSync, _options: SceneObjectUrlSyncConfigOptions);
1217
1271
  getKeys(): string[];
1218
1272
  getUrlState(): SceneObjectUrlValues;
1219
1273
  updateFromUrl(values: SceneObjectUrlValues): void;
1274
+ performBrowserHistoryAction(callback: () => void): void;
1275
+ shouldCreateHistoryStep(values: SceneObjectUrlValues): boolean;
1220
1276
  }
1221
1277
 
1222
1278
  declare class SceneTimeRange extends SceneObjectBase<SceneTimeRangeState> implements SceneTimeRangeLike {
@@ -1597,41 +1653,16 @@ declare class LocalValueVariable extends SceneObjectBase<LocalValueVariableState
1597
1653
  isAncestorLoading(): boolean;
1598
1654
  }
1599
1655
 
1600
- interface UrlSyncManagerLike {
1601
- initSync(root: SceneObject): void;
1602
- cleanUp(root: SceneObject): void;
1603
- getUrlState(root: SceneObject): SceneObjectUrlValues;
1604
- handleNewLocation(location: Location): void;
1605
- handleNewObject(sceneObj: SceneObject): void;
1606
- }
1607
- declare class UrlSyncManager implements UrlSyncManagerLike {
1608
- #private;
1609
- private _urlKeyMapper;
1610
- private _sceneRoot?;
1611
- private _stateSub;
1612
- private _lastLocation;
1613
- private _paramsCache;
1614
- /**
1615
- * Updates the current scene state to match URL state.
1616
- */
1617
- initSync(root: SceneObject): void;
1618
- cleanUp(root: SceneObject): void;
1619
- handleNewLocation(location: Location): void;
1620
- handleNewObject(sceneObj: SceneObject): void;
1621
- getUrlState(root: SceneObject): SceneObjectUrlValues;
1622
- }
1623
- declare function getUrlSyncManager(): UrlSyncManagerLike;
1624
-
1625
- declare function useUrlSync(sceneRoot: SceneObject): boolean;
1656
+ declare function useUrlSync(sceneRoot: SceneObject, options?: SceneUrlSyncOptions): boolean;
1626
1657
 
1627
- interface UrlSyncContextProviderProps {
1658
+ interface UrlSyncContextProviderProps extends SceneUrlSyncOptions {
1628
1659
  scene: SceneObject;
1629
1660
  children: React.ReactNode;
1630
1661
  }
1631
1662
  /**
1632
1663
  * Right now this is actually not defining a context, but think it might in the future (with UrlSyncManager as the context value)
1633
1664
  */
1634
- declare function UrlSyncContextProvider({ children, scene }: UrlSyncContextProviderProps): React$1.ReactNode;
1665
+ declare function UrlSyncContextProvider({ children, scene, updateUrlOnInit, createBrowserHistorySteps, }: UrlSyncContextProviderProps): React$1.ReactNode;
1635
1666
 
1636
1667
  interface EmbeddedSceneState extends SceneObjectState {
1637
1668
  /**
@@ -2159,6 +2190,7 @@ interface SceneRouteMatch<Params extends {
2159
2190
  interface SceneAppState extends SceneObjectState {
2160
2191
  pages: SceneAppPageLike[];
2161
2192
  name?: string;
2193
+ urlSyncOptions?: SceneUrlSyncOptions;
2162
2194
  }
2163
2195
  interface SceneAppRoute {
2164
2196
  path: string;
@@ -2712,4 +2744,4 @@ declare const sceneUtils: {
2712
2744
  isGroupByVariable: typeof isGroupByVariable;
2713
2745
  };
2714
2746
 
2715
- export { AdHocFiltersVariable, CancelActivationHandler, ConstantVariable, ControlsLayout, CustomFormatterVariable, CustomTransformOperator, CustomTransformerDefinition, CustomVariable, CustomVariableValue, DataLayerFilter, DataRequestEnricher, DataSourceVariable, DeepPartial, EmbeddedScene, EmbeddedSceneState, ExtraQueryDataProcessor, ExtraQueryDescriptor, ExtraQueryProvider, FieldConfigBuilder, FieldConfigBuilders, FieldConfigOverridesBuilder, FiltersRequestEnricher, FormatVariable, GroupByVariable, InterpolationFormatParameter, IntervalVariable, LocalValueVariable, MacroVariableConstructor, MultiValueVariable, MultiValueVariableState, NestedScene, PanelBuilders, PanelOptionsBuilders, QueryRunnerState, QueryVariable, RuntimeDataSource, SafeSerializableSceneObject, SceneActivationHandler, SceneApp, SceneAppDrilldownView, SceneAppPage, SceneAppPageLike, SceneAppPageState, SceneAppRoute, SceneByFrameRepeater, SceneByVariableRepeater, SceneCSSGridItem, SceneCSSGridLayout, SceneCanvasText, SceneComponent, SceneComponentProps, SceneControlsSpacer, SceneDataLayerBase, SceneDataLayerControls, SceneDataLayerProvider, SceneDataLayerProviderState, SceneDataLayerSet, SceneDataLayerSetBase, SceneDataNode, SceneDataProvider, SceneDataProviderResult, SceneDataQuery, SceneDataState, SceneDataTransformer, SceneDeactivationHandler, SceneDebugger, SceneFlexItem, SceneFlexItemLike, SceneFlexItemState, SceneFlexLayout, SceneGridItem, SceneGridItemLike, SceneGridItemStateLike, SceneGridLayout, SceneGridRow, SceneLayout, SceneLayoutChildOptions, SceneLayoutState, SceneObject, SceneObjectBase, SceneObjectRef, SceneObjectState, SceneObjectStateChangedEvent, SceneObjectStateChangedPayload, SceneObjectUrlSyncConfig, SceneObjectUrlSyncHandler, SceneObjectUrlValue, SceneObjectUrlValues, SceneObjectWithUrlSync, SceneQueryControllerEntry, SceneQueryControllerEntryType, SceneQueryControllerLike, SceneQueryRunner, SceneReactObject, SceneRefreshPicker, SceneRefreshPickerState, SceneRouteMatch, SceneStateChangedHandler, SceneStatelessBehavior, SceneTimePicker, SceneTimeRange, SceneTimeRangeCompare, SceneTimeRangeLike, SceneTimeRangeState, SceneTimeRangeTransformerBase, SceneTimeZoneOverride, SceneToolbarButton, SceneToolbarInput, SceneVariable, SceneVariableDependencyConfigLike, SceneVariableSet, SceneVariableSetState, SceneVariableState, SceneVariableValueChangedEvent, SceneVariables, SplitLayout, TestVariable, TextBoxVariable, UrlSyncContextProvider, UrlSyncManager, UrlSyncManagerLike, UseStateHookOptions, UserActionEvent, ValidateAndUpdateResult, VariableCustomFormatterFn, VariableDependencyConfig, VariableGetOptionsArgs, VariableValue, VariableValueControl, VariableValueOption, VariableValueSelectWrapper, VariableValueSelectors, VariableValueSingle, VizConfig, VizConfigBuilder, VizConfigBuilders, VizPanel, VizPanelBuilder, VizPanelMenu, VizPanelState, index$1 as behaviors, index as dataLayers, formatRegistry, getUrlSyncManager, isCustomVariableValue, isDataLayer, isDataRequestEnricher, isFiltersRequestEnricher, isSceneObject, registerQueryWithController, registerRuntimeDataSource, renderSelectForVariable, sceneGraph, sceneUtils, useSceneApp, useSceneObjectState, useUrlSync };
2747
+ export { AdHocFiltersVariable, CancelActivationHandler, ConstantVariable, ControlsLayout, CustomFormatterVariable, CustomTransformOperator, CustomTransformerDefinition, CustomVariable, CustomVariableValue, DataLayerFilter, DataRequestEnricher, DataSourceVariable, DeepPartial, EmbeddedScene, EmbeddedSceneState, ExtraQueryDataProcessor, ExtraQueryDescriptor, ExtraQueryProvider, FieldConfigBuilder, FieldConfigBuilders, FieldConfigOverridesBuilder, FiltersRequestEnricher, FormatVariable, GroupByVariable, InterpolationFormatParameter, IntervalVariable, LocalValueVariable, MacroVariableConstructor, MultiValueVariable, MultiValueVariableState, NestedScene, NewSceneObjectAddedEvent, PanelBuilders, PanelOptionsBuilders, QueryRunnerState, QueryVariable, RuntimeDataSource, SafeSerializableSceneObject, SceneActivationHandler, SceneApp, SceneAppDrilldownView, SceneAppPage, SceneAppPageLike, SceneAppPageState, SceneAppRoute, SceneByFrameRepeater, SceneByVariableRepeater, SceneCSSGridItem, SceneCSSGridLayout, SceneCanvasText, SceneComponent, SceneComponentProps, SceneControlsSpacer, SceneDataLayerBase, SceneDataLayerControls, SceneDataLayerProvider, SceneDataLayerProviderState, SceneDataLayerSet, SceneDataLayerSetBase, SceneDataNode, SceneDataProvider, SceneDataProviderResult, SceneDataQuery, SceneDataState, SceneDataTransformer, SceneDataTransformerState, SceneDeactivationHandler, SceneDebugger, SceneFlexItem, SceneFlexItemLike, SceneFlexItemState, SceneFlexLayout, SceneGridItem, SceneGridItemLike, SceneGridItemStateLike, SceneGridLayout, SceneGridRow, SceneLayout, SceneLayoutChildOptions, SceneLayoutState, SceneObject, SceneObjectBase, SceneObjectRef, SceneObjectState, SceneObjectStateChangedEvent, SceneObjectStateChangedPayload, SceneObjectUrlSyncConfig, SceneObjectUrlSyncHandler, SceneObjectUrlValue, SceneObjectUrlValues, SceneObjectWithUrlSync, SceneQueryControllerEntry, SceneQueryControllerEntryType, SceneQueryControllerLike, SceneQueryRunner, SceneReactObject, SceneRefreshPicker, SceneRefreshPickerState, SceneRouteMatch, SceneStateChangedHandler, SceneStatelessBehavior, SceneTimePicker, SceneTimeRange, SceneTimeRangeCompare, SceneTimeRangeLike, SceneTimeRangeState, SceneTimeRangeTransformerBase, SceneTimeZoneOverride, SceneToolbarButton, SceneToolbarInput, SceneUrlSyncOptions, SceneVariable, SceneVariableDependencyConfigLike, SceneVariableSet, SceneVariableSetState, SceneVariableState, SceneVariableValueChangedEvent, SceneVariables, SplitLayout, TestVariable, TextBoxVariable, UrlSyncContextProvider, UrlSyncManager, UrlSyncManagerLike, UseStateHookOptions, UserActionEvent, ValidateAndUpdateResult, VariableCustomFormatterFn, VariableDependencyConfig, VariableGetOptionsArgs, VariableValue, VariableValueControl, VariableValueOption, VariableValueSelectWrapper, VariableValueSelectors, VariableValueSingle, VizConfig, VizConfigBuilder, VizConfigBuilders, VizPanel, VizPanelBuilder, VizPanelMenu, VizPanelState, index$1 as behaviors, index as dataLayers, formatRegistry, isCustomVariableValue, isDataLayer, isDataRequestEnricher, isFiltersRequestEnricher, isSceneObject, registerQueryWithController, registerRuntimeDataSource, renderSelectForVariable, sceneGraph, sceneUtils, useSceneApp, useSceneObjectState, useUrlSync };