@jbrowse/core 2.1.4 → 2.1.5

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/ui/App.d.ts CHANGED
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { NotificationLevel, SessionWithDrawerWidgets, SnackAction } from '../util';
3
3
  import { MenuItem as JBMenuItem } from './index';
4
4
  declare type SnackbarMessage = [string, NotificationLevel, SnackAction];
5
- declare const App: ({ session, HeaderButtons, }: {
5
+ declare const App: (props: {
6
6
  HeaderButtons?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | undefined;
7
7
  session: SessionWithDrawerWidgets & {
8
8
  savedSessionNames: string[];
package/ui/App.js CHANGED
@@ -30,12 +30,14 @@ const react_1 = __importStar(require("react"));
30
30
  const material_1 = require("@mui/material");
31
31
  const mui_1 = require("tss-react/mui");
32
32
  const Launch_1 = __importDefault(require("@mui/icons-material/Launch"));
33
+ const react_error_boundary_1 = require("react-error-boundary");
33
34
  const mobx_react_1 = require("mobx-react");
34
35
  const mobx_state_tree_1 = require("mobx-state-tree");
35
36
  // locals
36
37
  const configuration_1 = require("../configuration");
37
38
  const DrawerWidget_1 = __importDefault(require("./DrawerWidget"));
38
39
  const DropDownMenu_1 = __importDefault(require("./DropDownMenu"));
40
+ const ErrorMessage_1 = __importDefault(require("./ErrorMessage"));
39
41
  const EditableTypography_1 = __importDefault(require("./EditableTypography"));
40
42
  const Logo_1 = require("./Logo");
41
43
  const Snackbar_1 = __importDefault(require("./Snackbar"));
@@ -104,13 +106,9 @@ const Logo = (0, mobx_react_1.observer)(({ session }) => {
104
106
  return react_1.default.createElement("img", { src: logoPath.uri, alt: "Custom logo" });
105
107
  }
106
108
  });
107
- const App = (0, mobx_react_1.observer)(({ session, HeaderButtons = react_1.default.createElement("div", null), }) => {
108
- var _a;
109
+ const AppToolbar = ({ session, HeaderButtons = react_1.default.createElement("div", null), }) => {
109
110
  const { classes } = useStyles();
110
- const { pluginManager } = (0, mobx_state_tree_1.getEnv)(session);
111
- const viewTypes = pluginManager.getElementTypeRecord('view').all();
112
- const [value, setValue] = (0, react_1.useState)((_a = viewTypes[0]) === null || _a === void 0 ? void 0 : _a.name);
113
- const { visibleWidget, drawerWidth, minimized, activeWidgets, savedSessionNames, name, menus, views, drawerPosition, } = session;
111
+ const { savedSessionNames, name, menus } = session;
114
112
  function handleNameChange(newName) {
115
113
  if (savedSessionNames === null || savedSessionNames === void 0 ? void 0 : savedSessionNames.includes(newName)) {
116
114
  session.notify(`Cannot rename session to "${newName}", a saved session with that name already exists`, 'warning');
@@ -119,6 +117,48 @@ const App = (0, mobx_react_1.observer)(({ session, HeaderButtons = react_1.defau
119
117
  session.renameCurrentSession(newName);
120
118
  }
121
119
  }
120
+ return (react_1.default.createElement(material_1.Toolbar, null,
121
+ menus.map(menu => (react_1.default.createElement(DropDownMenu_1.default, { key: menu.label, menuTitle: menu.label, menuItems: menu.menuItems, session: session }))),
122
+ react_1.default.createElement("div", { className: classes.grow }),
123
+ react_1.default.createElement(material_1.Tooltip, { title: "Rename Session", arrow: true },
124
+ react_1.default.createElement(EditableTypography_1.default, { value: name, setValue: handleNameChange, variant: "body1", classes: {
125
+ inputBase: classes.inputBase,
126
+ inputRoot: classes.inputRoot,
127
+ inputFocused: classes.inputFocused,
128
+ } })),
129
+ HeaderButtons,
130
+ react_1.default.createElement("div", { className: classes.grow }),
131
+ react_1.default.createElement("div", { style: { width: 150, maxHeight: 48 } },
132
+ react_1.default.createElement(Logo, { session: session }))));
133
+ };
134
+ const ViewLauncher = (0, mobx_react_1.observer)(({ session }) => {
135
+ var _a;
136
+ const { classes } = useStyles();
137
+ const { pluginManager } = (0, mobx_state_tree_1.getEnv)(session);
138
+ const viewTypes = pluginManager.getElementTypeRecord('view').all();
139
+ const [value, setValue] = (0, react_1.useState)((_a = viewTypes[0]) === null || _a === void 0 ? void 0 : _a.name);
140
+ return (react_1.default.createElement(material_1.Paper, { className: classes.selectPaper },
141
+ react_1.default.createElement(material_1.Typography, null, "Select a view to launch"),
142
+ react_1.default.createElement(material_1.Select, { value: value, onChange: event => setValue(event.target.value) }, viewTypes.map(({ name }) => (react_1.default.createElement(material_1.MenuItem, { key: name, value: name }, name)))),
143
+ react_1.default.createElement(material_1.Button, { onClick: () => {
144
+ session.addView(value, {});
145
+ }, variant: "contained", color: "primary" }, "Launch view")));
146
+ });
147
+ const ViewPanel = (0, mobx_react_1.observer)(({ view, session }) => {
148
+ const { pluginManager } = (0, mobx_state_tree_1.getEnv)(session);
149
+ const viewType = pluginManager.getViewType(view.type);
150
+ if (!viewType) {
151
+ throw new Error(`unknown view type ${view.type}`);
152
+ }
153
+ const { ReactComponent } = viewType;
154
+ return (react_1.default.createElement(ViewContainer_1.default, { view: view, onClose: () => session.removeView(view) },
155
+ react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement("div", null, "Loading...") },
156
+ react_1.default.createElement(ReactComponent, { model: view, session: session, getTrackType: pluginManager.getTrackType }))));
157
+ });
158
+ const App = (0, mobx_react_1.observer)((props) => {
159
+ const { session } = props;
160
+ const { classes } = useStyles();
161
+ const { minimized, visibleWidget, drawerWidth, activeWidgets, views, drawerPosition, } = session;
122
162
  const drawerVisible = visibleWidget && !minimized;
123
163
  let grid;
124
164
  if (drawerPosition === 'right') {
@@ -142,43 +182,10 @@ const App = (0, mobx_react_1.observer)(({ session, HeaderButtons = react_1.defau
142
182
  react_1.default.createElement("div", { className: classes.menuBarAndComponents },
143
183
  react_1.default.createElement("div", { className: classes.menuBar },
144
184
  react_1.default.createElement(material_1.AppBar, { className: classes.appBar, position: "static" },
145
- react_1.default.createElement(material_1.Toolbar, null,
146
- menus.map(menu => (react_1.default.createElement(DropDownMenu_1.default, { key: menu.label, menuTitle: menu.label, menuItems: menu.menuItems, session: session }))),
147
- react_1.default.createElement("div", { className: classes.grow }),
148
- react_1.default.createElement(material_1.Tooltip, { title: "Rename Session", arrow: true },
149
- react_1.default.createElement(EditableTypography_1.default, { value: name, setValue: handleNameChange, variant: "body1", classes: {
150
- inputBase: classes.inputBase,
151
- inputRoot: classes.inputRoot,
152
- inputFocused: classes.inputFocused,
153
- } })),
154
- HeaderButtons,
155
- react_1.default.createElement("div", { className: classes.grow }),
156
- react_1.default.createElement("div", { style: { width: 150, maxHeight: 48 } },
157
- react_1.default.createElement(Logo, { session: session }))))),
185
+ react_1.default.createElement(AppToolbar, { ...props }))),
158
186
  react_1.default.createElement("div", { className: classes.components },
159
- views.length ? (views.map(view => {
160
- const viewType = pluginManager.getViewType(view.type);
161
- if (!viewType) {
162
- throw new Error(`unknown view type ${view.type}`);
163
- }
164
- const { ReactComponent } = viewType;
165
- return (react_1.default.createElement(ViewContainer_1.default, { key: `view-${view.id}`, view: view, onClose: () => {
166
- session.removeView(view);
167
- session.notify(`A view has been closed`, 'info', {
168
- name: 'undo',
169
- onClick: () => {
170
- pluginManager.rootModel.history.undo();
171
- },
172
- });
173
- } },
174
- react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement("div", null, "Loading...") },
175
- react_1.default.createElement(ReactComponent, { model: view, session: session, getTrackType: pluginManager.getTrackType }))));
176
- })) : (react_1.default.createElement(material_1.Paper, { className: classes.selectPaper },
177
- react_1.default.createElement(material_1.Typography, null, "Select a view to launch"),
178
- react_1.default.createElement(material_1.Select, { value: value, onChange: event => setValue(event.target.value) }, viewTypes.map(({ name }) => (react_1.default.createElement(material_1.MenuItem, { key: name, value: name }, name)))),
179
- react_1.default.createElement(material_1.Button, { onClick: () => {
180
- session.addView(value, {});
181
- }, variant: "contained", color: "primary" }, "Launch view"))),
187
+ views.length ? (views.map(view => (react_1.default.createElement(react_error_boundary_1.ErrorBoundary, { key: `view-${view.id}`, FallbackComponent: ({ error }) => (react_1.default.createElement(ErrorMessage_1.default, { error: error })) },
188
+ react_1.default.createElement(ViewPanel, { view: view, session: session }))))) : (react_1.default.createElement(ViewLauncher, { ...props })),
182
189
  react_1.default.createElement("div", { style: { height: 300 } }))),
183
190
  activeWidgets.size > 0 && minimized ? (react_1.default.createElement(material_1.Tooltip, { title: "Open drawer widget" },
184
191
  react_1.default.createElement(material_1.Fab, { className: drawerPosition === 'right' ? classes.fabRight : classes.fabLeft, color: "primary", "data-testid": "drawer-maximize", onClick: () => session.showWidgetDrawer() },
@@ -27,6 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  const react_1 = __importStar(require("react"));
30
+ const react_error_boundary_1 = require("react-error-boundary");
30
31
  const material_1 = require("@mui/material");
31
32
  const mui_1 = require("tss-react/mui");
32
33
  const mobx_react_1 = require("mobx-react");
@@ -38,6 +39,7 @@ const Minimize_1 = __importDefault(require("@mui/icons-material/Minimize"));
38
39
  const MoreVert_1 = __importDefault(require("@mui/icons-material/MoreVert"));
39
40
  // locals
40
41
  const Drawer_1 = __importDefault(require("./Drawer"));
42
+ const ErrorMessage_1 = __importDefault(require("./ErrorMessage"));
41
43
  const useStyles = (0, mui_1.makeStyles)()(theme => ({
42
44
  formControl: {
43
45
  margin: 0,
@@ -119,6 +121,7 @@ const DrawerWidget = (0, mobx_react_1.observer)(({ session }) => {
119
121
  return (react_1.default.createElement(Drawer_1.default, { session: session },
120
122
  react_1.default.createElement(DrawerHeader, { session: session, setToolbarHeight: setToolbarHeight }),
121
123
  react_1.default.createElement(react_1.Suspense, { fallback: react_1.default.createElement("div", null, "Loading...") },
122
- react_1.default.createElement(DrawerComponent, { model: visibleWidget, session: session, toolbarHeight: toolbarHeight }))));
124
+ react_1.default.createElement(react_error_boundary_1.ErrorBoundary, { FallbackComponent: ({ error }) => react_1.default.createElement(ErrorMessage_1.default, { error: error }) },
125
+ react_1.default.createElement(DrawerComponent, { model: visibleWidget, session: session, toolbarHeight: toolbarHeight })))));
123
126
  });
124
127
  exports.default = DrawerWidget;
package/ui/theme.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ThemeOptions } from '@mui/material/styles';
1
2
  import type { PaletteOptions } from '@mui/material/styles/createPalette';
2
3
  declare module '@mui/material/styles/createPalette' {
3
4
  interface Palette {
@@ -43,7 +44,7 @@ export declare function createJBrowseDefaultProps(): {
43
44
  components: {
44
45
  MuiButton: {
45
46
  defaultProps: {
46
- size: string;
47
+ size: "small";
47
48
  };
48
49
  };
49
50
  MuiAccordion: {
@@ -56,43 +57,43 @@ export declare function createJBrowseDefaultProps(): {
56
57
  };
57
58
  MuiFilledInput: {
58
59
  defaultProps: {
59
- margin: string;
60
+ margin: "dense";
60
61
  };
61
62
  };
62
63
  MuiFormControl: {
63
64
  defaultProps: {
64
- margin: string;
65
- size: string;
65
+ margin: "dense";
66
+ size: "small";
66
67
  };
67
68
  };
68
69
  MuiFormHelperText: {
69
70
  defaultProps: {
70
- margin: string;
71
+ margin: "dense";
71
72
  };
72
73
  };
73
74
  MuiIconButton: {
74
75
  defaultProps: {
75
- size: string;
76
+ size: "small";
76
77
  };
77
78
  };
78
79
  MuiInputBase: {
79
80
  defaultProps: {
80
- margin: string;
81
+ margin: "dense";
81
82
  };
82
83
  };
83
84
  MuiAutocomplete: {
84
85
  defaultProps: {
85
- size: string;
86
+ size: "small";
86
87
  };
87
88
  };
88
89
  MuiInputLabel: {
89
90
  defaultProps: {
90
- margin: string;
91
+ margin: "dense";
91
92
  };
92
93
  };
93
94
  MuiToolbar: {
94
95
  defaultProps: {
95
- variant: string;
96
+ variant: "dense";
96
97
  };
97
98
  };
98
99
  MuiListItem: {
@@ -102,17 +103,17 @@ export declare function createJBrowseDefaultProps(): {
102
103
  };
103
104
  MuiOutlinedInput: {
104
105
  defaultProps: {
105
- margin: string;
106
+ margin: "dense";
106
107
  };
107
108
  };
108
109
  MuiFab: {
109
110
  defaultProps: {
110
- size: string;
111
+ size: "small";
111
112
  };
112
113
  };
113
114
  MuiTable: {
114
115
  defaultProps: {
115
- size: string;
116
+ size: "small";
116
117
  };
117
118
  };
118
119
  MuiMenuList: {
@@ -127,8 +128,8 @@ export declare function createJBrowseDefaultProps(): {
127
128
  };
128
129
  MuiTextField: {
129
130
  defaultProps: {
130
- margin: string;
131
- variant: string;
131
+ margin: "dense";
132
+ variant: "standard";
132
133
  };
133
134
  };
134
135
  };
@@ -175,159 +176,5 @@ export declare function createJBrowseDefaultOverrides(palette?: PaletteOptions):
175
176
  };
176
177
  };
177
178
  };
178
- export declare const jbrowseBaseTheme: {
179
- components: {
180
- MuiButton: {
181
- defaultProps: {
182
- size: string;
183
- };
184
- };
185
- MuiAccordion: {
186
- defaultProps: {
187
- disableGutters: boolean;
188
- TransitionProps: {
189
- timeout: number;
190
- };
191
- };
192
- };
193
- MuiFilledInput: {
194
- defaultProps: {
195
- margin: string;
196
- };
197
- };
198
- MuiFormControl: {
199
- defaultProps: {
200
- margin: string;
201
- size: string;
202
- };
203
- };
204
- MuiFormHelperText: {
205
- defaultProps: {
206
- margin: string;
207
- };
208
- };
209
- MuiIconButton: {
210
- defaultProps: {
211
- size: string;
212
- };
213
- };
214
- MuiInputBase: {
215
- defaultProps: {
216
- margin: string;
217
- };
218
- };
219
- MuiAutocomplete: {
220
- defaultProps: {
221
- size: string;
222
- };
223
- };
224
- MuiInputLabel: {
225
- defaultProps: {
226
- margin: string;
227
- };
228
- };
229
- MuiToolbar: {
230
- defaultProps: {
231
- variant: string;
232
- };
233
- };
234
- MuiListItem: {
235
- defaultProps: {
236
- dense: boolean;
237
- };
238
- };
239
- MuiOutlinedInput: {
240
- defaultProps: {
241
- margin: string;
242
- };
243
- };
244
- MuiFab: {
245
- defaultProps: {
246
- size: string;
247
- };
248
- };
249
- MuiTable: {
250
- defaultProps: {
251
- size: string;
252
- };
253
- };
254
- MuiMenuList: {
255
- defaultProps: {
256
- dense: boolean;
257
- };
258
- };
259
- MuiMenuItem: {
260
- defaultProps: {
261
- dense: boolean;
262
- };
263
- };
264
- MuiTextField: {
265
- defaultProps: {
266
- margin: string;
267
- variant: string;
268
- };
269
- };
270
- } & {
271
- MuiIconButton: {
272
- styleOverrides: {
273
- colorSecondary: {
274
- color: string;
275
- };
276
- };
277
- };
278
- MuiButton: {
279
- styleOverrides: {
280
- textSecondary: {
281
- color: string;
282
- };
283
- };
284
- };
285
- MuiFab: {
286
- styleOverrides: {
287
- secondary: {
288
- backgroundColor: string;
289
- };
290
- };
291
- };
292
- MuiLink: {
293
- styleOverrides: {
294
- root: {
295
- color: string;
296
- };
297
- };
298
- };
299
- MuiAccordionSummary: {
300
- styleOverrides: {
301
- root: {
302
- backgroundColor: string;
303
- };
304
- content: {
305
- color: string;
306
- };
307
- };
308
- };
309
- };
310
- palette: {
311
- primary: {
312
- main: string;
313
- };
314
- secondary: {
315
- main: string;
316
- };
317
- tertiary: import("@mui/material/styles").PaletteColor;
318
- quaternary: import("@mui/material/styles").PaletteColor;
319
- stopCodon: string;
320
- startCodon: string;
321
- bases: {
322
- A: import("@mui/material/styles").PaletteColor;
323
- C: import("@mui/material/styles").PaletteColor;
324
- G: import("@mui/material/styles").PaletteColor;
325
- T: import("@mui/material/styles").PaletteColor;
326
- };
327
- };
328
- typography: {
329
- fontSize: number;
330
- };
331
- spacing: number;
332
- };
333
- export declare function createJBrowseTheme(theme?: any): import("@mui/material/styles").Theme;
179
+ export declare function createJBrowseBaseTheme(palette?: PaletteOptions): ThemeOptions;
180
+ export declare function createJBrowseTheme(theme?: ThemeOptions): import("@mui/material/styles").Theme;
package/ui/theme.js CHANGED
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.createJBrowseTheme = exports.jbrowseBaseTheme = exports.createJBrowseDefaultOverrides = exports.createJBrowseDefaultProps = exports.jbrowseDefaultPalette = void 0;
6
+ exports.createJBrowseTheme = exports.createJBrowseBaseTheme = exports.createJBrowseDefaultOverrides = exports.createJBrowseDefaultProps = exports.jbrowseDefaultPalette = void 0;
7
7
  const colors_1 = require("@mui/material/colors");
8
8
  const styles_1 = require("@mui/material/styles");
9
9
  const deepmerge_1 = __importDefault(require("deepmerge"));
@@ -168,38 +168,35 @@ function createJBrowseDefaultOverrides(palette = {}) {
168
168
  };
169
169
  }
170
170
  exports.createJBrowseDefaultOverrides = createJBrowseDefaultOverrides;
171
- exports.jbrowseBaseTheme = {
172
- palette: exports.jbrowseDefaultPalette,
173
- typography: { fontSize: 12 },
174
- spacing: 4,
175
- ...(0, deepmerge_1.default)(createJBrowseDefaultProps(), createJBrowseDefaultOverrides()),
176
- };
177
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
171
+ function createJBrowseBaseTheme(palette) {
172
+ return {
173
+ palette: exports.jbrowseDefaultPalette,
174
+ typography: { fontSize: 12 },
175
+ spacing: 4,
176
+ ...(0, deepmerge_1.default)(createJBrowseDefaultProps(), createJBrowseDefaultOverrides(palette)),
177
+ };
178
+ }
179
+ exports.createJBrowseBaseTheme = createJBrowseBaseTheme;
178
180
  function createJBrowseTheme(theme) {
179
- var _a, _b, _c, _d;
181
+ var _a, _b;
180
182
  if ((_a = theme === null || theme === void 0 ? void 0 : theme.palette) === null || _a === void 0 ? void 0 : _a.tertiary) {
181
183
  theme = (0, deepmerge_1.default)(theme, {
182
184
  palette: {
183
- tertiary: refTheme.palette.augmentColor(((_b = theme.palette.tertiary) === null || _b === void 0 ? void 0 : _b.color)
185
+ tertiary: refTheme.palette.augmentColor('color' in theme.palette.tertiary
184
186
  ? theme.palette.tertiary
185
- : {
186
- color: theme.palette.tertiary,
187
- }),
187
+ : { color: theme.palette.tertiary }),
188
188
  },
189
189
  });
190
190
  }
191
- if ((_c = theme === null || theme === void 0 ? void 0 : theme.palette) === null || _c === void 0 ? void 0 : _c.quaternary) {
191
+ if ((_b = theme === null || theme === void 0 ? void 0 : theme.palette) === null || _b === void 0 ? void 0 : _b.quaternary) {
192
192
  theme = (0, deepmerge_1.default)(theme, {
193
193
  palette: {
194
- quaternary: refTheme.palette.augmentColor(((_d = theme.palette.quaternary) === null || _d === void 0 ? void 0 : _d.color)
194
+ quaternary: refTheme.palette.augmentColor('color' in theme.palette.quaternary
195
195
  ? theme.palette.quaternary
196
- : {
197
- color: theme.palette.quaternary,
198
- }),
196
+ : { color: theme.palette.quaternary }),
199
197
  },
200
198
  });
201
199
  }
202
- // @ts-ignore
203
- return (0, styles_1.createTheme)((0, deepmerge_1.default)(exports.jbrowseBaseTheme, theme || {}));
200
+ return (0, styles_1.createTheme)((0, deepmerge_1.default)(createJBrowseBaseTheme(theme === null || theme === void 0 ? void 0 : theme.palette), theme || {}));
204
201
  }
205
202
  exports.createJBrowseTheme = createJBrowseTheme;
@@ -3,15 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const mobx_state_tree_1 = require("mobx-state-tree");
4
4
  const _1 = require(".");
5
5
  const blockTypes_1 = require("./blockTypes");
6
- function calculateStaticBlocks(model, padding = true, elision = true, extra = 0,
7
- // on the main thread, window.innerWidth is used because this reduces
8
- // recalculating the blocks, otherwise, model.width for cases such as
9
- // off-main-thread. also this is not a ternary because our window.innerWidth
10
- // might be undefined on off-main-thread, so instead use || model.width
11
- width = (typeof window !== 'undefined' && window.innerWidth) || model.width) {
12
- const { offsetPx, displayedRegions, bpPerPx, minimumBlockWidth, interRegionPaddingWidth, } = model;
6
+ function calculateStaticBlocks(model, padding = true, elision = true, extra = 0, width = 800) {
7
+ const { offsetPx, displayedRegions, bpPerPx, minimumBlockWidth, interRegionPaddingWidth, width: modelWidth, } = model;
13
8
  const windowLeftBp = offsetPx * bpPerPx;
14
- const windowRightBp = (offsetPx + width) * bpPerPx;
9
+ const windowRightBp = (offsetPx + modelWidth) * bpPerPx;
15
10
  const blockSizePx = width;
16
11
  const blockSizeBp = Math.ceil(blockSizePx * bpPerPx);
17
12
  // for each displayed region
package/util/index.d.ts CHANGED
@@ -327,7 +327,7 @@ export declare function getLayoutId({ sessionId, layoutId, }: {
327
327
  sessionId: string;
328
328
  layoutId: string;
329
329
  }): string;
330
- export declare const useLocalStorage: (key: string, defaultValue?: string) => [string, (arg: string) => void];
330
+ export declare function useLocalStorage<T>(key: string, initialValue: T): readonly [T, (value: T | ((val: T) => T)) => void];
331
331
  export declare function getUriLink(value: {
332
332
  uri: string;
333
333
  baseUri?: string;
package/util/index.js CHANGED
@@ -941,16 +941,35 @@ function getLayoutId({ sessionId, layoutId, }) {
941
941
  return sessionId + '-' + layoutId;
942
942
  }
943
943
  exports.getLayoutId = getLayoutId;
944
- // similar to https://blog.logrocket.com/using-localstorage-react-hooks/
945
- const useLocalStorage = (key, defaultValue = '') => {
946
- const [value, setValue] = (0, react_1.useState)(() => localStorage.getItem(key) || defaultValue);
947
- (0, react_1.useEffect)(() => {
948
- localStorage.setItem(key, value);
949
- }, [key, value]);
950
- // without this cast, tsc complained that the type of setValue could be a
951
- // string or a callback
952
- return [value, setValue];
953
- };
944
+ // Hook from https://usehooks.com/useLocalStorage/
945
+ function useLocalStorage(key, initialValue) {
946
+ const [storedValue, setStoredValue] = (0, react_1.useState)(() => {
947
+ if (typeof window === 'undefined') {
948
+ return initialValue;
949
+ }
950
+ try {
951
+ const item = window.localStorage.getItem(key);
952
+ return item ? JSON.parse(item) : initialValue;
953
+ }
954
+ catch (error) {
955
+ console.error(error);
956
+ return initialValue;
957
+ }
958
+ });
959
+ const setValue = (value) => {
960
+ try {
961
+ const valueToStore = value instanceof Function ? value(storedValue) : value;
962
+ setStoredValue(valueToStore);
963
+ if (typeof window !== 'undefined') {
964
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
965
+ }
966
+ }
967
+ catch (error) {
968
+ console.error(error);
969
+ }
970
+ };
971
+ return [storedValue, setValue];
972
+ }
954
973
  exports.useLocalStorage = useLocalStorage;
955
974
  function getUriLink(value) {
956
975
  const { uri, baseUri = '' } = value;
@@ -42,7 +42,7 @@ export interface SimpleFeatureArgs {
42
42
  /** unique identifier. can also be in data.uniqueId */
43
43
  id: string | number;
44
44
  }
45
- interface SimpleFeatureSerializedNoId {
45
+ export interface SimpleFeatureSerializedNoId {
46
46
  [key: string]: unknown;
47
47
  parentId?: string;
48
48
  subfeatures?: SimpleFeatureSerializedNoId[];
@@ -94,4 +94,3 @@ export default class SimpleFeature implements Feature {
94
94
  toJSON(): SimpleFeatureSerialized;
95
95
  static fromJSON(json: SimpleFeatureSerialized): SimpleFeature;
96
96
  }
97
- export {};
@@ -73,7 +73,7 @@ export interface AbstractSessionModel extends AbstractViewContainer {
73
73
  addWidget?: Function;
74
74
  DialogComponent?: DialogComponentType;
75
75
  DialogProps: any;
76
- queueDialog: (callback: (doneCallback: Function) => [DialogComponentType, any]) => void;
76
+ queueDialog<T extends DialogComponentType>(callback: (doneCallback: () => void) => [T, React.ComponentProps<T>]): void;
77
77
  name: string;
78
78
  id?: string;
79
79
  tracks: AnyConfigurationModel[];
@@ -36,7 +36,9 @@ function isSessionModelWithConfigEditing(thing) {
36
36
  }
37
37
  exports.isSessionModelWithConfigEditing = isSessionModelWithConfigEditing;
38
38
  function isSessionWithAddTracks(thing) {
39
- return isSessionModel(thing) && 'addTrackConf' in thing;
39
+ return (
40
+ // @ts-ignore
41
+ isSessionModel(thing) && 'addTrackConf' in thing && !thing.disableAddTracks);
40
42
  }
41
43
  exports.isSessionWithAddTracks = isSessionWithAddTracks;
42
44
  function isSessionModelWithWidgets(thing) {