@grafana/scenes 0.29.0 → 0.29.2

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/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ # v0.29.2 (Wed Sep 06 2023)
2
+
3
+ #### 🐛 Bug Fix
4
+
5
+ - SceneObject: Support changing $data, $timeRange and $variables during the active phase [#324](https://github.com/grafana/scenes/pull/324) ([@torkelo](https://github.com/torkelo))
6
+
7
+ #### Authors: 1
8
+
9
+ - Torkel Ödegaard ([@torkelo](https://github.com/torkelo))
10
+
11
+ ---
12
+
13
+ # v0.29.1 (Tue Sep 05 2023)
14
+
15
+ #### 🐛 Bug Fix
16
+
17
+ - SceneGridRow: Small design change and fixes, add actions support [#321](https://github.com/grafana/scenes/pull/321) ([@torkelo](https://github.com/torkelo))
18
+
19
+ #### Authors: 1
20
+
21
+ - Torkel Ödegaard ([@torkelo](https://github.com/torkelo))
22
+
23
+ ---
24
+
1
25
  # v0.29.0 (Tue Sep 05 2023)
2
26
 
3
27
  #### 🚀 Enhancement
@@ -3,9 +3,9 @@ import React from 'react';
3
3
  import { useStyles2, Icon } from '@grafana/ui';
4
4
  import { SceneObjectBase } from '../../../core/SceneObjectBase.js';
5
5
  import { SceneObjectUrlSyncConfig } from '../../../services/SceneObjectUrlSyncConfig.js';
6
- import { SceneDragHandle } from '../../SceneDragHandle.js';
7
6
  import { SceneGridLayout } from './SceneGridLayout.js';
8
7
  import { GRID_COLUMN_COUNT } from './constants.js';
8
+ import { sceneGraph } from '../../../core/sceneGraph/index.js';
9
9
 
10
10
  var __defProp = Object.defineProperty;
11
11
  var __defProps = Object.defineProperties;
@@ -69,14 +69,10 @@ class SceneGridRow extends SceneObjectBase {
69
69
  SceneGridRow.Component = SceneGridRowRenderer;
70
70
  function SceneGridRowRenderer({ model }) {
71
71
  const styles = useStyles2(getSceneGridRowStyles);
72
- const { isCollapsible, isCollapsed, title, isDraggable } = model.useState();
73
- const dragHandle = /* @__PURE__ */ React.createElement(SceneDragHandle, {
74
- dragClass: model.getGridLayout().getDragClass()
75
- });
72
+ const { isCollapsible, isCollapsed, title, isDraggable, actions } = model.useState();
73
+ const layoutDragClass = model.getGridLayout().getDragClass();
76
74
  return /* @__PURE__ */ React.createElement("div", {
77
- className: styles.row
78
- }, /* @__PURE__ */ React.createElement("div", {
79
- className: cx(styles.rowHeader, isCollapsed && styles.rowHeaderCollapsed)
75
+ className: cx(styles.row, isCollapsed && styles.rowCollapsed)
80
76
  }, /* @__PURE__ */ React.createElement("button", {
81
77
  onClick: model.onCollapseToggle,
82
78
  className: styles.rowTitleButton
@@ -84,25 +80,24 @@ function SceneGridRowRenderer({ model }) {
84
80
  name: isCollapsed ? "angle-right" : "angle-down"
85
81
  }), /* @__PURE__ */ React.createElement("span", {
86
82
  className: styles.rowTitle
87
- }, title)), isDraggable && isCollapsed && /* @__PURE__ */ React.createElement("div", null, dragHandle)));
83
+ }, sceneGraph.interpolate(model, title, void 0, "text"))), isCollapsed && /* @__PURE__ */ React.createElement("div", {
84
+ className: styles.collapsedInfo
85
+ }, "(", model.state.children.length, " panels)"), actions && /* @__PURE__ */ React.createElement(actions.Component, {
86
+ model: actions
87
+ }), isDraggable && isCollapsed && /* @__PURE__ */ React.createElement("div", {
88
+ className: cx(styles.dragHandle, layoutDragClass)
89
+ }, /* @__PURE__ */ React.createElement(Icon, {
90
+ name: "draggabledots"
91
+ })));
88
92
  }
89
93
  const getSceneGridRowStyles = (theme) => {
90
94
  return {
91
95
  row: css({
92
- width: "100%",
93
- height: "100%",
94
- position: "relative",
95
- zIndex: 0,
96
- display: "flex",
97
- flexDirection: "column"
98
- }),
99
- rowHeader: css({
100
96
  width: "100%",
101
97
  height: "30px",
102
98
  display: "flex",
103
99
  justifyContent: "space-between",
104
- marginBottom: "8px",
105
- border: `1px solid transparent`
100
+ gap: theme.spacing(1)
106
101
  }),
107
102
  rowTitleButton: css({
108
103
  display: "flex",
@@ -112,15 +107,31 @@ const getSceneGridRowStyles = (theme) => {
112
107
  border: "none",
113
108
  gap: theme.spacing(1)
114
109
  }),
115
- rowHeaderCollapsed: css({
116
- marginBottom: "0px",
117
- background: theme.colors.background.primary,
118
- border: `1px solid ${theme.colors.border.weak}`,
119
- borderRadius: theme.shape.borderRadius(1)
110
+ rowCollapsed: css({
111
+ background: theme.colors.background.secondary,
112
+ borderBottom: `1px solid ${theme.colors.border.weak}`
120
113
  }),
121
114
  rowTitle: css({
122
115
  fontSize: theme.typography.h5.fontSize,
123
116
  fontWeight: theme.typography.fontWeightMedium
117
+ }),
118
+ collapsedInfo: css({
119
+ fontSize: theme.typography.bodySmall.fontSize,
120
+ color: theme.colors.text.secondary,
121
+ display: "flex",
122
+ alignItems: "center",
123
+ flexGrow: 1
124
+ }),
125
+ dragHandle: css({
126
+ display: "flex",
127
+ padding: theme.spacing(0, 1),
128
+ alignItems: "center",
129
+ justifyContent: "flex-end",
130
+ cursor: "move",
131
+ color: theme.colors.text.secondary,
132
+ "&:hover": {
133
+ color: theme.colors.text.primary
134
+ }
124
135
  })
125
136
  };
126
137
  };
@@ -1 +1 @@
1
- {"version":3,"file":"SceneGridRow.js","sources":["../../../../../src/components/layout/grid/SceneGridRow.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport React from 'react';\n\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { Icon, useStyles2 } from '@grafana/ui';\n\nimport { SceneObjectBase } from '../../../core/SceneObjectBase';\nimport { SceneComponentProps, SceneObjectUrlValues } from '../../../core/types';\nimport { SceneObjectUrlSyncConfig } from '../../../services/SceneObjectUrlSyncConfig';\nimport { SceneDragHandle } from '../../SceneDragHandle';\n\nimport { SceneGridLayout } from './SceneGridLayout';\nimport { GRID_COLUMN_COUNT } from './constants';\nimport { SceneGridItemLike, SceneGridItemStateLike } from './types';\n\nexport interface SceneGridRowState extends SceneGridItemStateLike {\n title: string;\n isCollapsible?: boolean;\n isCollapsed?: boolean;\n children: SceneGridItemLike[];\n}\n\nexport class SceneGridRow extends SceneObjectBase<SceneGridRowState> {\n public static Component = SceneGridRowRenderer;\n\n protected _urlSync = new SceneObjectUrlSyncConfig(this, { keys: ['rowc'] });\n\n public constructor(state: Partial<SceneGridRowState>) {\n super({\n children: state.children || [],\n isCollapsible: state.isCollapsible || true,\n title: state.title || '',\n isDraggable: state.isDraggable || true,\n isResizable: state.isResizable || false,\n ...state,\n x: 0,\n height: 1,\n width: GRID_COLUMN_COUNT,\n });\n }\n\n public getGridLayout(): SceneGridLayout {\n const layout = this.parent;\n\n if (!layout || !(layout instanceof SceneGridLayout)) {\n throw new Error('SceneGridRow must be a child of SceneGridLayout');\n }\n\n return layout;\n }\n\n public onCollapseToggle = () => {\n if (!this.state.isCollapsible) {\n return;\n }\n\n this.getGridLayout().toggleRow(this);\n };\n\n public getUrlState() {\n return { rowc: this.state.isCollapsed ? '1' : '0' };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues) {\n if (values.rowc == null) {\n return;\n }\n\n if (values.rowc !== this.getUrlState().rowc) {\n this.onCollapseToggle();\n }\n }\n}\n\nexport function SceneGridRowRenderer({ model }: SceneComponentProps<SceneGridRow>) {\n const styles = useStyles2(getSceneGridRowStyles);\n const { isCollapsible, isCollapsed, title, isDraggable } = model.useState();\n const dragHandle = <SceneDragHandle dragClass={model.getGridLayout().getDragClass()} />;\n\n return (\n <div className={styles.row}>\n <div className={cx(styles.rowHeader, isCollapsed && styles.rowHeaderCollapsed)}>\n <button onClick={model.onCollapseToggle} className={styles.rowTitleButton}>\n {isCollapsible && <Icon name={isCollapsed ? 'angle-right' : 'angle-down'} />}\n <span className={styles.rowTitle}>{title}</span>\n </button>\n {isDraggable && isCollapsed && <div>{dragHandle}</div>}\n </div>\n </div>\n );\n}\n\nconst getSceneGridRowStyles = (theme: GrafanaTheme2) => {\n return {\n row: css({\n width: '100%',\n height: '100%',\n position: 'relative',\n zIndex: 0,\n display: 'flex',\n flexDirection: 'column',\n }),\n rowHeader: css({\n width: '100%',\n height: '30px',\n display: 'flex',\n justifyContent: 'space-between',\n marginBottom: '8px',\n border: `1px solid transparent`,\n }),\n rowTitleButton: css({\n display: 'flex',\n alignItems: 'center',\n cursor: 'pointer',\n background: 'transparent',\n border: 'none',\n gap: theme.spacing(1),\n }),\n rowHeaderCollapsed: css({\n marginBottom: '0px',\n background: theme.colors.background.primary,\n border: `1px solid ${theme.colors.border.weak}`,\n borderRadius: theme.shape.borderRadius(1),\n }),\n rowTitle: css({\n fontSize: theme.typography.h5.fontSize,\n fontWeight: theme.typography.fontWeightMedium,\n }),\n };\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SceneGridRow.js","sources":["../../../../../src/components/layout/grid/SceneGridRow.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport React from 'react';\n\nimport { GrafanaTheme2 } from '@grafana/data';\nimport { Icon, useStyles2 } from '@grafana/ui';\n\nimport { SceneObjectBase } from '../../../core/SceneObjectBase';\nimport { SceneComponentProps, SceneObject, SceneObjectUrlValues } from '../../../core/types';\nimport { SceneObjectUrlSyncConfig } from '../../../services/SceneObjectUrlSyncConfig';\n\nimport { SceneGridLayout } from './SceneGridLayout';\nimport { GRID_COLUMN_COUNT } from './constants';\nimport { SceneGridItemLike, SceneGridItemStateLike } from './types';\nimport { sceneGraph } from '../../../core/sceneGraph';\n\nexport interface SceneGridRowState extends SceneGridItemStateLike {\n title: string;\n isCollapsible?: boolean;\n isCollapsed?: boolean;\n actions?: SceneObject;\n children: SceneGridItemLike[];\n}\n\nexport class SceneGridRow extends SceneObjectBase<SceneGridRowState> {\n public static Component = SceneGridRowRenderer;\n\n protected _urlSync = new SceneObjectUrlSyncConfig(this, { keys: ['rowc'] });\n\n public constructor(state: Partial<SceneGridRowState>) {\n super({\n children: state.children || [],\n isCollapsible: state.isCollapsible || true,\n title: state.title || '',\n isDraggable: state.isDraggable || true,\n isResizable: state.isResizable || false,\n ...state,\n x: 0,\n height: 1,\n width: GRID_COLUMN_COUNT,\n });\n }\n\n public getGridLayout(): SceneGridLayout {\n const layout = this.parent;\n\n if (!layout || !(layout instanceof SceneGridLayout)) {\n throw new Error('SceneGridRow must be a child of SceneGridLayout');\n }\n\n return layout;\n }\n\n public onCollapseToggle = () => {\n if (!this.state.isCollapsible) {\n return;\n }\n\n this.getGridLayout().toggleRow(this);\n };\n\n public getUrlState() {\n return { rowc: this.state.isCollapsed ? '1' : '0' };\n }\n\n public updateFromUrl(values: SceneObjectUrlValues) {\n if (values.rowc == null) {\n return;\n }\n\n if (values.rowc !== this.getUrlState().rowc) {\n this.onCollapseToggle();\n }\n }\n}\n\nexport function SceneGridRowRenderer({ model }: SceneComponentProps<SceneGridRow>) {\n const styles = useStyles2(getSceneGridRowStyles);\n const { isCollapsible, isCollapsed, title, isDraggable, actions } = model.useState();\n const layoutDragClass = model.getGridLayout().getDragClass();\n\n return (\n <div className={cx(styles.row, isCollapsed && styles.rowCollapsed)}>\n <button onClick={model.onCollapseToggle} className={styles.rowTitleButton}>\n {isCollapsible && <Icon name={isCollapsed ? 'angle-right' : 'angle-down'} />}\n <span className={styles.rowTitle}>{sceneGraph.interpolate(model, title, undefined, 'text')}</span>\n </button>\n {isCollapsed && <div className={styles.collapsedInfo}>({model.state.children.length} panels)</div>}\n {actions && <actions.Component model={actions} />}\n {isDraggable && isCollapsed && (\n <div className={cx(styles.dragHandle, layoutDragClass)}>\n <Icon name=\"draggabledots\" />\n </div>\n )}\n </div>\n );\n}\n\nconst getSceneGridRowStyles = (theme: GrafanaTheme2) => {\n return {\n row: css({\n width: '100%',\n height: '30px',\n display: 'flex',\n justifyContent: 'space-between',\n gap: theme.spacing(1),\n }),\n rowTitleButton: css({\n display: 'flex',\n alignItems: 'center',\n cursor: 'pointer',\n background: 'transparent',\n border: 'none',\n gap: theme.spacing(1),\n }),\n rowCollapsed: css({\n background: theme.colors.background.secondary,\n borderBottom: `1px solid ${theme.colors.border.weak}`,\n }),\n rowTitle: css({\n fontSize: theme.typography.h5.fontSize,\n fontWeight: theme.typography.fontWeightMedium,\n }),\n collapsedInfo: css({\n fontSize: theme.typography.bodySmall.fontSize,\n color: theme.colors.text.secondary,\n display: 'flex',\n alignItems: 'center',\n flexGrow: 1,\n }),\n dragHandle: css({\n display: 'flex',\n padding: theme.spacing(0, 1),\n alignItems: 'center',\n justifyContent: 'flex-end',\n cursor: 'move',\n color: theme.colors.text.secondary,\n '&:hover': {\n color: theme.colors.text.primary,\n },\n }),\n };\n};\n"],"names":[],"mappings":"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"}
@@ -26,7 +26,7 @@ class SceneObjectBase {
26
26
  constructor(state) {
27
27
  this._isActive = false;
28
28
  this._activationHandlers = [];
29
- this._deactivationHandlers = [];
29
+ this._deactivationHandlers = /* @__PURE__ */ new Map();
30
30
  this._subs = new Subscription();
31
31
  this._refCount = 0;
32
32
  if (!state.key) {
@@ -81,6 +81,7 @@ class SceneObjectBase {
81
81
  const newState = __spreadValues(__spreadValues({}, this._state), update);
82
82
  this._state = Object.freeze(newState);
83
83
  this._setParent();
84
+ this._handleActivationOfChangedStateProps(prevState, newState);
84
85
  this.publishEvent(
85
86
  new SceneObjectStateChangedEvent({
86
87
  prevState,
@@ -91,6 +92,32 @@ class SceneObjectBase {
91
92
  true
92
93
  );
93
94
  }
95
+ _handleActivationOfChangedStateProps(prevState, newState) {
96
+ if (!this.isActive) {
97
+ return;
98
+ }
99
+ if (prevState.$data !== newState.$data) {
100
+ this._handleChangedStateActivation(prevState.$data, newState.$data);
101
+ }
102
+ if (prevState.$variables !== newState.$variables) {
103
+ this._handleChangedStateActivation(prevState.$variables, newState.$variables);
104
+ }
105
+ if (prevState.$timeRange !== newState.$timeRange) {
106
+ this._handleChangedStateActivation(prevState.$timeRange, newState.$timeRange);
107
+ }
108
+ }
109
+ _handleChangedStateActivation(oldValue, newValue) {
110
+ if (oldValue) {
111
+ const deactivationHandler = this._deactivationHandlers.get(oldValue);
112
+ if (deactivationHandler) {
113
+ deactivationHandler();
114
+ this._deactivationHandlers.delete(oldValue);
115
+ }
116
+ }
117
+ if (newValue) {
118
+ this._deactivationHandlers.set(newValue, newValue.activate());
119
+ }
120
+ }
94
121
  publishEvent(event, bubble) {
95
122
  this._events.publish(event);
96
123
  if (bubble && this.parent) {
@@ -104,22 +131,22 @@ class SceneObjectBase {
104
131
  this._isActive = true;
105
132
  const { $data, $variables, $timeRange, $behaviors } = this.state;
106
133
  if ($timeRange && !$timeRange.isActive) {
107
- this._deactivationHandlers.push($timeRange.activate());
134
+ this._deactivationHandlers.set($timeRange, $timeRange.activate());
108
135
  }
109
136
  if ($variables && !$variables.isActive) {
110
- this._deactivationHandlers.push($variables.activate());
137
+ this._deactivationHandlers.set($variables, $variables.activate());
111
138
  }
112
139
  if ($data && !$data.isActive) {
113
- this._deactivationHandlers.push($data.activate());
140
+ this._deactivationHandlers.set($data, $data.activate());
114
141
  }
115
142
  if ($behaviors) {
116
143
  for (const behavior of $behaviors) {
117
144
  if (behavior instanceof SceneObjectBase) {
118
- this._deactivationHandlers.push(behavior.activate());
145
+ this._deactivationHandlers.set(behavior, behavior.activate());
119
146
  } else if (typeof behavior === "function") {
120
147
  const deactivationHandler = behavior(this);
121
148
  if (deactivationHandler) {
122
- this._deactivationHandlers.push();
149
+ this._deactivationHandlers.set(behavior, deactivationHandler);
123
150
  }
124
151
  }
125
152
  }
@@ -127,7 +154,7 @@ class SceneObjectBase {
127
154
  this._activationHandlers.forEach((handler) => {
128
155
  const result = handler();
129
156
  if (result) {
130
- this._deactivationHandlers.push(result);
157
+ this._deactivationHandlers.set(result, result);
131
158
  }
132
159
  });
133
160
  }
@@ -152,8 +179,10 @@ class SceneObjectBase {
152
179
  }
153
180
  _internalDeactivate() {
154
181
  this._isActive = false;
155
- this._deactivationHandlers.forEach((handler) => handler());
156
- this._deactivationHandlers = [];
182
+ for (let handler of this._deactivationHandlers.values()) {
183
+ handler();
184
+ }
185
+ this._deactivationHandlers.clear();
157
186
  this._events.removeAllListeners();
158
187
  this._subs.unsubscribe();
159
188
  this._subs = new Subscription();
@@ -1 +1 @@
1
- {"version":3,"file":"SceneObjectBase.js","sources":["../../../src/core/SceneObjectBase.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Subscription, Unsubscribable } from 'rxjs';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { BusEvent, BusEventHandler, BusEventType, EventBus, EventBusSrv } from '@grafana/data';\nimport {\n SceneObject,\n SceneComponent,\n SceneObjectUrlSyncHandler,\n SceneStateChangedHandler,\n SceneActivationHandler,\n SceneDeactivationHandler,\n CancelActivationHandler,\n SceneObjectState,\n} from './types';\n\nimport { SceneComponentWrapper } from './SceneComponentWrapper';\nimport { SceneObjectStateChangedEvent } from './events';\nimport { cloneSceneObject } from './sceneGraph/utils';\nimport { SceneVariableDependencyConfigLike } from '../variables/types';\n\nexport abstract class SceneObjectBase<TState extends SceneObjectState = SceneObjectState>\n implements SceneObject<TState>\n{\n private _isActive = false;\n private _state: TState;\n private _activationHandlers: SceneActivationHandler[] = [];\n private _deactivationHandlers: SceneDeactivationHandler[] = [];\n\n protected _events?: EventBus;\n protected _parent?: SceneObject;\n protected _subs = new Subscription();\n protected _refCount = 0;\n\n protected _variableDependency: SceneVariableDependencyConfigLike | undefined;\n protected _urlSync: SceneObjectUrlSyncHandler | undefined;\n\n public constructor(state: TState) {\n if (!state.key) {\n state.key = uuidv4();\n }\n\n this._events = new EventBusSrv();\n\n this._state = Object.freeze(state);\n this._setParent();\n }\n\n /** Current state */\n public get state(): TState {\n return this._state;\n }\n\n /** True if currently being active (ie displayed for visual objects) */\n public get isActive(): boolean {\n return this._isActive;\n }\n\n /** Returns the parent, undefined for root object */\n public get parent(): SceneObject | undefined {\n return this._parent;\n }\n\n /** Returns variable dependency config */\n public get variableDependency(): SceneVariableDependencyConfigLike | undefined {\n return this._variableDependency;\n }\n\n /** Returns url sync config */\n public get urlSync(): SceneObjectUrlSyncHandler | undefined {\n return this._urlSync;\n }\n\n /**\n * Used in render functions when rendering a SceneObject.\n * Wraps the component in an EditWrapper that handles edit mode\n */\n public get Component(): SceneComponent<this> {\n return SceneComponentWrapper;\n }\n\n private _setParent() {\n this.forEachChild((child) => {\n // If we already have a parent and it's not this, then we likely have a bug\n if (child._parent && child._parent !== this) {\n console.warn(\n 'SceneObject already has a parent set that is different from the new parent. You cannot share the same SceneObject instance in multiple scenes or in multiple different places of the same scene graph. Use SceneObject.clone() to duplicate a SceneObject or store a state key reference and use sceneGraph.findObject to locate it.',\n child,\n this\n );\n }\n child._parent = this;\n });\n }\n\n /**\n * Subscribe to the scene state subject\n **/\n public subscribeToState(handler: SceneStateChangedHandler<TState>): Unsubscribable {\n return this._events!.subscribe(SceneObjectStateChangedEvent, (event) => {\n if (event.payload.changedObject === this) {\n handler(event.payload.newState as TState, event.payload.prevState as TState);\n }\n });\n }\n\n /**\n * Subscribe to the scene event\n **/\n public subscribeToEvent<T extends BusEvent>(eventType: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable {\n return this._events!.subscribe(eventType, handler);\n }\n\n public setState(update: Partial<TState>) {\n const prevState = this._state;\n const newState: TState = {\n ...this._state,\n ...update,\n };\n\n this._state = Object.freeze(newState);\n\n this._setParent();\n\n // Bubble state change event. This is event is subscribed to by UrlSyncManager and UndoManager\n this.publishEvent(\n new SceneObjectStateChangedEvent({\n prevState,\n newState,\n partialUpdate: update,\n changedObject: this,\n }),\n true\n );\n }\n /*\n * Publish an event and optionally bubble it up the scene\n **/\n public publishEvent(event: BusEvent, bubble?: boolean) {\n this._events!.publish(event);\n\n if (bubble && this.parent) {\n this.parent.publishEvent(event, bubble);\n }\n }\n\n public getRoot(): SceneObject {\n return !this._parent ? this : this._parent.getRoot();\n }\n\n private _internalActivate() {\n this._isActive = true;\n\n const { $data, $variables, $timeRange, $behaviors } = this.state;\n\n if ($timeRange && !$timeRange.isActive) {\n this._deactivationHandlers.push($timeRange.activate());\n }\n\n if ($variables && !$variables.isActive) {\n this._deactivationHandlers.push($variables.activate());\n }\n\n if ($data && !$data.isActive) {\n this._deactivationHandlers.push($data.activate());\n }\n\n if ($behaviors) {\n for (const behavior of $behaviors) {\n if (behavior instanceof SceneObjectBase) {\n this._deactivationHandlers.push(behavior.activate());\n } else if (typeof behavior === 'function') {\n const deactivationHandler = behavior(this);\n if (deactivationHandler) {\n this._deactivationHandlers.push();\n }\n }\n }\n }\n\n this._activationHandlers.forEach((handler) => {\n const result = handler();\n if (result) {\n this._deactivationHandlers.push(result);\n }\n });\n }\n\n /**\n * This is primarily called from SceneComponentWrapper when the SceneObject's Component is mounted.\n * But in some scenarios this can also be called directly from another scene object. When called manually from another scene object\n * make sure to call the returned function when the source scene object is deactivated.\n */\n public activate(): CancelActivationHandler {\n if (!this.isActive) {\n this._internalActivate();\n }\n\n this._refCount++;\n\n let called = false;\n\n return () => {\n this._refCount--;\n\n if (called) {\n const msg = `SceneObject cancelation handler returned by activate() called a second time`;\n console.error(msg, this);\n throw new Error(msg);\n }\n\n called = true;\n\n if (this._refCount === 0) {\n this._internalDeactivate();\n }\n };\n }\n\n /**\n * Called by the SceneComponentWrapper when the react component is unmounted.\n * Don't override this, instead use addActivationHandler. The activation handler can return a deactivation handler.\n */\n private _internalDeactivate(): void {\n this._isActive = false;\n\n this._deactivationHandlers.forEach((handler) => handler());\n this._deactivationHandlers = [];\n\n // Clear subscriptions and listeners\n this._events!.removeAllListeners();\n this._subs.unsubscribe();\n this._subs = new Subscription();\n }\n\n /**\n * Utility hook to get and subscribe to state\n */\n public useState() {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useSceneObjectState(this);\n }\n\n /** Force a re-render, should only be needed when variable values change */\n public forceRender(): void {\n this.setState({});\n }\n\n /**\n * Will create new SceneObject with shallow-cloned state, but all state items of type SceneObject are deep cloned\n */\n public clone(withState?: Partial<TState>): this {\n return cloneSceneObject(this, withState);\n }\n\n /**\n * Allows external code to register code that is executed on activate and deactivate. This allow you\n * to wire up scene objects that need to respond to state changes in other objects from the outside.\n **/\n public addActivationHandler(handler: SceneActivationHandler) {\n this._activationHandlers.push(handler);\n }\n\n /**\n * Loop through state and call callback for each direct child scene object.\n * Checks 1 level deep properties and arrays. So a scene object hidden in a nested plain object will not be detected.\n */\n public forEachChild(callback: (child: SceneObjectBase) => void) {\n for (const propValue of Object.values(this.state)) {\n if (propValue instanceof SceneObjectBase) {\n callback(propValue);\n }\n\n if (Array.isArray(propValue)) {\n for (const child of propValue) {\n if (child instanceof SceneObjectBase) {\n callback(child);\n }\n }\n }\n }\n }\n}\n\n/**\n * This hook is always returning model.state instead of a useState that remembers the last state emitted on the subject\n * The reason for this is so that if the model instance change this function will always return the latest state.\n */\nfunction useSceneObjectState<TState extends SceneObjectState>(model: SceneObjectBase<TState>): TState {\n const [_, setState] = useState<TState>(model.state);\n const stateAtFirstRender = model.state;\n\n useEffect(() => {\n const s = model.subscribeToState(setState);\n\n // Re-render component if the state changed between first render and useEffect (mount)\n if (model.state !== stateAtFirstRender) {\n setState(model.state);\n }\n\n return () => s.unsubscribe();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [model]);\n\n return model.state;\n}\n"],"names":["uuidv4"],"mappings":"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"}
1
+ {"version":3,"file":"SceneObjectBase.js","sources":["../../../src/core/SceneObjectBase.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Subscription, Unsubscribable } from 'rxjs';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { BusEvent, BusEventHandler, BusEventType, EventBus, EventBusSrv } from '@grafana/data';\nimport {\n SceneObject,\n SceneComponent,\n SceneObjectUrlSyncHandler,\n SceneStateChangedHandler,\n SceneActivationHandler,\n SceneDeactivationHandler,\n CancelActivationHandler,\n SceneObjectState,\n} from './types';\n\nimport { SceneComponentWrapper } from './SceneComponentWrapper';\nimport { SceneObjectStateChangedEvent } from './events';\nimport { cloneSceneObject } from './sceneGraph/utils';\nimport { SceneVariableDependencyConfigLike } from '../variables/types';\n\nexport abstract class SceneObjectBase<TState extends SceneObjectState = SceneObjectState>\n implements SceneObject<TState>\n{\n private _isActive = false;\n private _state: TState;\n private _activationHandlers: SceneActivationHandler[] = [];\n private _deactivationHandlers = new Map<object, SceneDeactivationHandler>();\n\n protected _events?: EventBus;\n protected _parent?: SceneObject;\n protected _subs = new Subscription();\n protected _refCount = 0;\n\n protected _variableDependency: SceneVariableDependencyConfigLike | undefined;\n protected _urlSync: SceneObjectUrlSyncHandler | undefined;\n\n public constructor(state: TState) {\n if (!state.key) {\n state.key = uuidv4();\n }\n\n this._events = new EventBusSrv();\n\n this._state = Object.freeze(state);\n this._setParent();\n }\n\n /** Current state */\n public get state(): TState {\n return this._state;\n }\n\n /** True if currently being active (ie displayed for visual objects) */\n public get isActive(): boolean {\n return this._isActive;\n }\n\n /** Returns the parent, undefined for root object */\n public get parent(): SceneObject | undefined {\n return this._parent;\n }\n\n /** Returns variable dependency config */\n public get variableDependency(): SceneVariableDependencyConfigLike | undefined {\n return this._variableDependency;\n }\n\n /** Returns url sync config */\n public get urlSync(): SceneObjectUrlSyncHandler | undefined {\n return this._urlSync;\n }\n\n /**\n * Used in render functions when rendering a SceneObject.\n * Wraps the component in an EditWrapper that handles edit mode\n */\n public get Component(): SceneComponent<this> {\n return SceneComponentWrapper;\n }\n\n private _setParent() {\n this.forEachChild((child) => {\n // If we already have a parent and it's not this, then we likely have a bug\n if (child._parent && child._parent !== this) {\n console.warn(\n 'SceneObject already has a parent set that is different from the new parent. You cannot share the same SceneObject instance in multiple scenes or in multiple different places of the same scene graph. Use SceneObject.clone() to duplicate a SceneObject or store a state key reference and use sceneGraph.findObject to locate it.',\n child,\n this\n );\n }\n child._parent = this;\n });\n }\n\n /**\n * Subscribe to the scene state subject\n **/\n public subscribeToState(handler: SceneStateChangedHandler<TState>): Unsubscribable {\n return this._events!.subscribe(SceneObjectStateChangedEvent, (event) => {\n if (event.payload.changedObject === this) {\n handler(event.payload.newState as TState, event.payload.prevState as TState);\n }\n });\n }\n\n /**\n * Subscribe to the scene event\n **/\n public subscribeToEvent<T extends BusEvent>(eventType: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable {\n return this._events!.subscribe(eventType, handler);\n }\n\n public setState(update: Partial<TState>) {\n const prevState = this._state;\n const newState: TState = {\n ...this._state,\n ...update,\n };\n\n this._state = Object.freeze(newState);\n this._setParent();\n\n // Handles cases when $data, $timeRange, or $variables are changed\n this._handleActivationOfChangedStateProps(prevState, newState);\n\n // Bubble state change event. This is event is subscribed to by UrlSyncManager and UndoManager\n this.publishEvent(\n new SceneObjectStateChangedEvent({\n prevState,\n newState,\n partialUpdate: update,\n changedObject: this,\n }),\n true\n );\n }\n\n /**\n * This handles activation and deactivation of $data, $timeRange and $variables when they change\n * during the active phase of the scene object.\n */\n private _handleActivationOfChangedStateProps(prevState: TState, newState: TState) {\n if (!this.isActive) {\n return;\n }\n\n if (prevState.$data !== newState.$data) {\n this._handleChangedStateActivation(prevState.$data, newState.$data);\n }\n\n if (prevState.$variables !== newState.$variables) {\n this._handleChangedStateActivation(prevState.$variables, newState.$variables);\n }\n\n if (prevState.$timeRange !== newState.$timeRange) {\n this._handleChangedStateActivation(prevState.$timeRange, newState.$timeRange);\n }\n }\n\n private _handleChangedStateActivation(oldValue: SceneObject | undefined, newValue: SceneObject | undefined) {\n if (oldValue) {\n const deactivationHandler = this._deactivationHandlers.get(oldValue);\n if (deactivationHandler) {\n deactivationHandler();\n this._deactivationHandlers.delete(oldValue);\n }\n }\n\n if (newValue) {\n this._deactivationHandlers.set(newValue, newValue.activate());\n }\n }\n\n /*\n * Publish an event and optionally bubble it up the scene\n **/\n public publishEvent(event: BusEvent, bubble?: boolean) {\n this._events!.publish(event);\n\n if (bubble && this.parent) {\n this.parent.publishEvent(event, bubble);\n }\n }\n\n public getRoot(): SceneObject {\n return !this._parent ? this : this._parent.getRoot();\n }\n\n private _internalActivate() {\n this._isActive = true;\n\n const { $data, $variables, $timeRange, $behaviors } = this.state;\n\n if ($timeRange && !$timeRange.isActive) {\n this._deactivationHandlers.set($timeRange, $timeRange.activate());\n }\n\n if ($variables && !$variables.isActive) {\n this._deactivationHandlers.set($variables, $variables.activate());\n }\n\n if ($data && !$data.isActive) {\n this._deactivationHandlers.set($data, $data.activate());\n }\n\n if ($behaviors) {\n for (const behavior of $behaviors) {\n if (behavior instanceof SceneObjectBase) {\n this._deactivationHandlers.set(behavior, behavior.activate());\n } else if (typeof behavior === 'function') {\n const deactivationHandler = behavior(this);\n if (deactivationHandler) {\n this._deactivationHandlers.set(behavior, deactivationHandler);\n }\n }\n }\n }\n\n this._activationHandlers.forEach((handler) => {\n const result = handler();\n if (result) {\n this._deactivationHandlers.set(result, result);\n }\n });\n }\n\n /**\n * This is primarily called from SceneComponentWrapper when the SceneObject's Component is mounted.\n * But in some scenarios this can also be called directly from another scene object. When called manually from another scene object\n * make sure to call the returned function when the source scene object is deactivated.\n */\n public activate(): CancelActivationHandler {\n if (!this.isActive) {\n this._internalActivate();\n }\n\n this._refCount++;\n\n let called = false;\n\n return () => {\n this._refCount--;\n\n if (called) {\n const msg = `SceneObject cancelation handler returned by activate() called a second time`;\n console.error(msg, this);\n throw new Error(msg);\n }\n\n called = true;\n\n if (this._refCount === 0) {\n this._internalDeactivate();\n }\n };\n }\n\n /**\n * Called by the SceneComponentWrapper when the react component is unmounted.\n * Don't override this, instead use addActivationHandler. The activation handler can return a deactivation handler.\n */\n private _internalDeactivate(): void {\n this._isActive = false;\n\n for (let handler of this._deactivationHandlers.values()) {\n handler();\n }\n\n this._deactivationHandlers.clear();\n\n // Clear subscriptions and listeners\n this._events!.removeAllListeners();\n this._subs.unsubscribe();\n this._subs = new Subscription();\n }\n\n /**\n * Utility hook to get and subscribe to state\n */\n public useState() {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return useSceneObjectState(this);\n }\n\n /** Force a re-render, should only be needed when variable values change */\n public forceRender(): void {\n this.setState({});\n }\n\n /**\n * Will create new SceneObject with shallow-cloned state, but all state items of type SceneObject are deep cloned\n */\n public clone(withState?: Partial<TState>): this {\n return cloneSceneObject(this, withState);\n }\n\n /**\n * Allows external code to register code that is executed on activate and deactivate. This allow you\n * to wire up scene objects that need to respond to state changes in other objects from the outside.\n **/\n public addActivationHandler(handler: SceneActivationHandler) {\n this._activationHandlers.push(handler);\n }\n\n /**\n * Loop through state and call callback for each direct child scene object.\n * Checks 1 level deep properties and arrays. So a scene object hidden in a nested plain object will not be detected.\n */\n public forEachChild(callback: (child: SceneObjectBase) => void) {\n for (const propValue of Object.values(this.state)) {\n if (propValue instanceof SceneObjectBase) {\n callback(propValue);\n }\n\n if (Array.isArray(propValue)) {\n for (const child of propValue) {\n if (child instanceof SceneObjectBase) {\n callback(child);\n }\n }\n }\n }\n }\n}\n\n/**\n * This hook is always returning model.state instead of a useState that remembers the last state emitted on the subject\n * The reason for this is so that if the model instance change this function will always return the latest state.\n */\nfunction useSceneObjectState<TState extends SceneObjectState>(model: SceneObjectBase<TState>): TState {\n const [_, setState] = useState<TState>(model.state);\n const stateAtFirstRender = model.state;\n\n useEffect(() => {\n const s = model.subscribeToState(setState);\n\n // Re-render component if the state changed between first render and useEffect (mount)\n if (model.state !== stateAtFirstRender) {\n setState(model.state);\n }\n\n return () => s.unsubscribe();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [model]);\n\n return model.state;\n}\n"],"names":["uuidv4"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -304,6 +304,12 @@ declare abstract class SceneObjectBase<TState extends SceneObjectState = SceneOb
304
304
  **/
305
305
  subscribeToEvent<T extends BusEvent>(eventType: BusEventType<T>, handler: BusEventHandler<T>): Unsubscribable;
306
306
  setState(update: Partial<TState>): void;
307
+ /**
308
+ * This handles activation and deactivation of $data, $timeRange and $variables when they change
309
+ * during the active phase of the scene object.
310
+ */
311
+ private _handleActivationOfChangedStateProps;
312
+ private _handleChangedStateActivation;
307
313
  publishEvent(event: BusEvent, bubble?: boolean): void;
308
314
  getRoot(): SceneObject;
309
315
  private _internalActivate;
@@ -1167,6 +1173,7 @@ interface SceneGridRowState extends SceneGridItemStateLike {
1167
1173
  title: string;
1168
1174
  isCollapsible?: boolean;
1169
1175
  isCollapsed?: boolean;
1176
+ actions?: SceneObject;
1170
1177
  children: SceneGridItemLike[];
1171
1178
  }
1172
1179
  declare class SceneGridRow extends SceneObjectBase<SceneGridRowState> {
package/dist/index.js CHANGED
@@ -201,7 +201,7 @@ class SceneObjectBase {
201
201
  constructor(state) {
202
202
  this._isActive = false;
203
203
  this._activationHandlers = [];
204
- this._deactivationHandlers = [];
204
+ this._deactivationHandlers = /* @__PURE__ */ new Map();
205
205
  this._subs = new rxjs.Subscription();
206
206
  this._refCount = 0;
207
207
  if (!state.key) {
@@ -256,6 +256,7 @@ class SceneObjectBase {
256
256
  const newState = __spreadValues$s(__spreadValues$s({}, this._state), update);
257
257
  this._state = Object.freeze(newState);
258
258
  this._setParent();
259
+ this._handleActivationOfChangedStateProps(prevState, newState);
259
260
  this.publishEvent(
260
261
  new SceneObjectStateChangedEvent({
261
262
  prevState,
@@ -266,6 +267,32 @@ class SceneObjectBase {
266
267
  true
267
268
  );
268
269
  }
270
+ _handleActivationOfChangedStateProps(prevState, newState) {
271
+ if (!this.isActive) {
272
+ return;
273
+ }
274
+ if (prevState.$data !== newState.$data) {
275
+ this._handleChangedStateActivation(prevState.$data, newState.$data);
276
+ }
277
+ if (prevState.$variables !== newState.$variables) {
278
+ this._handleChangedStateActivation(prevState.$variables, newState.$variables);
279
+ }
280
+ if (prevState.$timeRange !== newState.$timeRange) {
281
+ this._handleChangedStateActivation(prevState.$timeRange, newState.$timeRange);
282
+ }
283
+ }
284
+ _handleChangedStateActivation(oldValue, newValue) {
285
+ if (oldValue) {
286
+ const deactivationHandler = this._deactivationHandlers.get(oldValue);
287
+ if (deactivationHandler) {
288
+ deactivationHandler();
289
+ this._deactivationHandlers.delete(oldValue);
290
+ }
291
+ }
292
+ if (newValue) {
293
+ this._deactivationHandlers.set(newValue, newValue.activate());
294
+ }
295
+ }
269
296
  publishEvent(event, bubble) {
270
297
  this._events.publish(event);
271
298
  if (bubble && this.parent) {
@@ -279,22 +306,22 @@ class SceneObjectBase {
279
306
  this._isActive = true;
280
307
  const { $data, $variables, $timeRange, $behaviors } = this.state;
281
308
  if ($timeRange && !$timeRange.isActive) {
282
- this._deactivationHandlers.push($timeRange.activate());
309
+ this._deactivationHandlers.set($timeRange, $timeRange.activate());
283
310
  }
284
311
  if ($variables && !$variables.isActive) {
285
- this._deactivationHandlers.push($variables.activate());
312
+ this._deactivationHandlers.set($variables, $variables.activate());
286
313
  }
287
314
  if ($data && !$data.isActive) {
288
- this._deactivationHandlers.push($data.activate());
315
+ this._deactivationHandlers.set($data, $data.activate());
289
316
  }
290
317
  if ($behaviors) {
291
318
  for (const behavior of $behaviors) {
292
319
  if (behavior instanceof SceneObjectBase) {
293
- this._deactivationHandlers.push(behavior.activate());
320
+ this._deactivationHandlers.set(behavior, behavior.activate());
294
321
  } else if (typeof behavior === "function") {
295
322
  const deactivationHandler = behavior(this);
296
323
  if (deactivationHandler) {
297
- this._deactivationHandlers.push();
324
+ this._deactivationHandlers.set(behavior, deactivationHandler);
298
325
  }
299
326
  }
300
327
  }
@@ -302,7 +329,7 @@ class SceneObjectBase {
302
329
  this._activationHandlers.forEach((handler) => {
303
330
  const result = handler();
304
331
  if (result) {
305
- this._deactivationHandlers.push(result);
332
+ this._deactivationHandlers.set(result, result);
306
333
  }
307
334
  });
308
335
  }
@@ -327,8 +354,10 @@ class SceneObjectBase {
327
354
  }
328
355
  _internalDeactivate() {
329
356
  this._isActive = false;
330
- this._deactivationHandlers.forEach((handler) => handler());
331
- this._deactivationHandlers = [];
357
+ for (let handler of this._deactivationHandlers.values()) {
358
+ handler();
359
+ }
360
+ this._deactivationHandlers.clear();
332
361
  this._events.removeAllListeners();
333
362
  this._subs.unsubscribe();
334
363
  this._subs = new rxjs.Subscription();
@@ -5161,19 +5190,6 @@ const GRID_CELL_HEIGHT = 30;
5161
5190
  const GRID_CELL_VMARGIN = 8;
5162
5191
  const GRID_COLUMN_COUNT = 24;
5163
5192
 
5164
- function SceneDragHandle({ className, dragClass }) {
5165
- return /* @__PURE__ */ React__default["default"].createElement("div", {
5166
- className: `${className} ${dragClass}`,
5167
- style: {
5168
- width: "20px",
5169
- height: "20px",
5170
- cursor: "move"
5171
- }
5172
- }, /* @__PURE__ */ React__default["default"].createElement(ui.Icon, {
5173
- name: "draggabledots"
5174
- }));
5175
- }
5176
-
5177
5193
  var __defProp$5 = Object.defineProperty;
5178
5194
  var __defProps$2 = Object.defineProperties;
5179
5195
  var __getOwnPropDescs$2 = Object.getOwnPropertyDescriptors;
@@ -5236,14 +5252,10 @@ class SceneGridRow extends SceneObjectBase {
5236
5252
  SceneGridRow.Component = SceneGridRowRenderer;
5237
5253
  function SceneGridRowRenderer({ model }) {
5238
5254
  const styles = ui.useStyles2(getSceneGridRowStyles);
5239
- const { isCollapsible, isCollapsed, title, isDraggable } = model.useState();
5240
- const dragHandle = /* @__PURE__ */ React__default["default"].createElement(SceneDragHandle, {
5241
- dragClass: model.getGridLayout().getDragClass()
5242
- });
5255
+ const { isCollapsible, isCollapsed, title, isDraggable, actions } = model.useState();
5256
+ const layoutDragClass = model.getGridLayout().getDragClass();
5243
5257
  return /* @__PURE__ */ React__default["default"].createElement("div", {
5244
- className: styles.row
5245
- }, /* @__PURE__ */ React__default["default"].createElement("div", {
5246
- className: css.cx(styles.rowHeader, isCollapsed && styles.rowHeaderCollapsed)
5258
+ className: css.cx(styles.row, isCollapsed && styles.rowCollapsed)
5247
5259
  }, /* @__PURE__ */ React__default["default"].createElement("button", {
5248
5260
  onClick: model.onCollapseToggle,
5249
5261
  className: styles.rowTitleButton
@@ -5251,25 +5263,24 @@ function SceneGridRowRenderer({ model }) {
5251
5263
  name: isCollapsed ? "angle-right" : "angle-down"
5252
5264
  }), /* @__PURE__ */ React__default["default"].createElement("span", {
5253
5265
  className: styles.rowTitle
5254
- }, title)), isDraggable && isCollapsed && /* @__PURE__ */ React__default["default"].createElement("div", null, dragHandle)));
5266
+ }, sceneGraph.interpolate(model, title, void 0, "text"))), isCollapsed && /* @__PURE__ */ React__default["default"].createElement("div", {
5267
+ className: styles.collapsedInfo
5268
+ }, "(", model.state.children.length, " panels)"), actions && /* @__PURE__ */ React__default["default"].createElement(actions.Component, {
5269
+ model: actions
5270
+ }), isDraggable && isCollapsed && /* @__PURE__ */ React__default["default"].createElement("div", {
5271
+ className: css.cx(styles.dragHandle, layoutDragClass)
5272
+ }, /* @__PURE__ */ React__default["default"].createElement(ui.Icon, {
5273
+ name: "draggabledots"
5274
+ })));
5255
5275
  }
5256
5276
  const getSceneGridRowStyles = (theme) => {
5257
5277
  return {
5258
5278
  row: css.css({
5259
- width: "100%",
5260
- height: "100%",
5261
- position: "relative",
5262
- zIndex: 0,
5263
- display: "flex",
5264
- flexDirection: "column"
5265
- }),
5266
- rowHeader: css.css({
5267
5279
  width: "100%",
5268
5280
  height: "30px",
5269
5281
  display: "flex",
5270
5282
  justifyContent: "space-between",
5271
- marginBottom: "8px",
5272
- border: `1px solid transparent`
5283
+ gap: theme.spacing(1)
5273
5284
  }),
5274
5285
  rowTitleButton: css.css({
5275
5286
  display: "flex",
@@ -5279,15 +5290,31 @@ const getSceneGridRowStyles = (theme) => {
5279
5290
  border: "none",
5280
5291
  gap: theme.spacing(1)
5281
5292
  }),
5282
- rowHeaderCollapsed: css.css({
5283
- marginBottom: "0px",
5284
- background: theme.colors.background.primary,
5285
- border: `1px solid ${theme.colors.border.weak}`,
5286
- borderRadius: theme.shape.borderRadius(1)
5293
+ rowCollapsed: css.css({
5294
+ background: theme.colors.background.secondary,
5295
+ borderBottom: `1px solid ${theme.colors.border.weak}`
5287
5296
  }),
5288
5297
  rowTitle: css.css({
5289
5298
  fontSize: theme.typography.h5.fontSize,
5290
5299
  fontWeight: theme.typography.fontWeightMedium
5300
+ }),
5301
+ collapsedInfo: css.css({
5302
+ fontSize: theme.typography.bodySmall.fontSize,
5303
+ color: theme.colors.text.secondary,
5304
+ display: "flex",
5305
+ alignItems: "center",
5306
+ flexGrow: 1
5307
+ }),
5308
+ dragHandle: css.css({
5309
+ display: "flex",
5310
+ padding: theme.spacing(0, 1),
5311
+ alignItems: "center",
5312
+ justifyContent: "flex-end",
5313
+ cursor: "move",
5314
+ color: theme.colors.text.secondary,
5315
+ "&:hover": {
5316
+ color: theme.colors.text.primary
5317
+ }
5291
5318
  })
5292
5319
  };
5293
5320
  };