@jbrowse/app-core 2.6.1 → 2.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/HistoryManagement/index.js +5 -2
  2. package/dist/JBrowseConfig/index.d.ts +29 -18
  3. package/dist/JBrowseConfig/index.js +8 -47
  4. package/dist/JBrowseModel/index.d.ts +38 -9
  5. package/dist/ui/App/DrawerHeader.d.ts +7 -0
  6. package/dist/ui/App/DrawerHeader.js +114 -0
  7. package/dist/ui/App/DrawerWidget.js +2 -76
  8. package/esm/HistoryManagement/index.js +5 -2
  9. package/esm/JBrowseConfig/index.d.ts +29 -18
  10. package/esm/JBrowseConfig/index.js +8 -47
  11. package/esm/JBrowseModel/index.d.ts +38 -9
  12. package/esm/ui/App/DrawerHeader.d.ts +7 -0
  13. package/esm/ui/App/DrawerHeader.js +86 -0
  14. package/esm/ui/App/DrawerWidget.js +1 -75
  15. package/package.json +6 -7
  16. package/src/Assemblies/SessionAssembliesMixin.ts +0 -50
  17. package/src/Assemblies/TemporaryAssembliesMixin.ts +0 -51
  18. package/src/Assemblies/index.ts +0 -2
  19. package/src/HistoryManagement/index.ts +0 -56
  20. package/src/JBrowseConfig/index.ts +0 -173
  21. package/src/JBrowseModel/index.ts +0 -150
  22. package/src/RootMenu/index.ts +0 -157
  23. package/src/index.ts +0 -6
  24. package/src/ui/App/App.tsx +0 -117
  25. package/src/ui/App/AppFab.tsx +0 -45
  26. package/src/ui/App/AppToolbar.tsx +0 -89
  27. package/src/ui/App/DialogQueue.tsx +0 -22
  28. package/src/ui/App/Drawer.tsx +0 -56
  29. package/src/ui/App/DrawerWidget.tsx +0 -238
  30. package/src/ui/App/ViewContainer.tsx +0 -76
  31. package/src/ui/App/ViewContainerTitle.tsx +0 -55
  32. package/src/ui/App/ViewLauncher.tsx +0 -64
  33. package/src/ui/App/ViewMenu.tsx +0 -54
  34. package/src/ui/App/ViewPanel.tsx +0 -63
  35. package/src/ui/App/index.ts +0 -1
  36. package/src/ui/index.ts +0 -1
@@ -1,5 +1,6 @@
1
1
  import { ConfigurationSchema, } from '@jbrowse/core/configuration';
2
2
  import RpcManager from '@jbrowse/core/rpc/RpcManager';
3
+ import { FormatAboutConfigSchemaFactory, FormatDetailsConfigSchemaFactory, HierarchicalConfigSchemaFactory, } from '@jbrowse/product-core';
3
4
  import { types } from 'mobx-state-tree';
4
5
  /**
5
6
  * #config JBrowseRootConfig
@@ -20,52 +21,8 @@ export function JBrowseConfigF({ pluginManager, assemblyConfigSchema, }) {
20
21
  type: 'number',
21
22
  defaultValue: 2,
22
23
  },
23
- formatDetails: ConfigurationSchema('FormatDetails', {
24
- /**
25
- * #slot configuration.formatDetails.feature
26
- */
27
- feature: {
28
- type: 'frozen',
29
- description: 'adds extra fields to the feature details',
30
- defaultValue: {},
31
- contextVariable: ['feature'],
32
- },
33
- /**
34
- * #slot configuration.formatDetails.subfeatures
35
- */
36
- subfeatures: {
37
- type: 'frozen',
38
- description: 'adds extra fields to the subfeatures of a feature',
39
- defaultValue: {},
40
- contextVariable: ['feature'],
41
- },
42
- /**
43
- * #slot configuration.formatDetails.depth
44
- */
45
- depth: {
46
- type: 'number',
47
- defaultValue: 2,
48
- description: 'depth to iterate on subfeatures',
49
- },
50
- }),
51
- formatAbout: ConfigurationSchema('FormatAbout', {
52
- /**
53
- * #slot configuration.formatAbout.config
54
- */
55
- config: {
56
- type: 'frozen',
57
- description: 'formats configuration object in about dialog',
58
- defaultValue: {},
59
- contextVariable: ['config'],
60
- },
61
- /**
62
- * #slot configuration.formatAbout.hideUris
63
- */
64
- hideUris: {
65
- type: 'boolean',
66
- defaultValue: false,
67
- },
68
- }),
24
+ formatDetails: FormatDetailsConfigSchemaFactory(),
25
+ formatAbout: FormatAboutConfigSchemaFactory(),
69
26
  /*
70
27
  * #slot configuration.shareURL
71
28
  */
@@ -80,6 +37,7 @@ export function JBrowseConfigF({ pluginManager, assemblyConfigSchema, }) {
80
37
  type: 'boolean',
81
38
  defaultValue: false,
82
39
  },
40
+ hierarchical: HierarchicalConfigSchemaFactory(),
83
41
  /**
84
42
  * #slot configuration.theme
85
43
  */
@@ -90,7 +48,10 @@ export function JBrowseConfigF({ pluginManager, assemblyConfigSchema, }) {
90
48
  /**
91
49
  * #slot configuration.extraThemes
92
50
  */
93
- extraThemes: { type: 'frozen', defaultValue: {} },
51
+ extraThemes: {
52
+ type: 'frozen',
53
+ defaultValue: {},
54
+ },
94
55
  /**
95
56
  * #slot configuration.logoPath
96
57
  */
@@ -29,12 +29,16 @@ export declare function JBrowseModelF({ pluginManager, assemblyConfigSchema, }:
29
29
  };
30
30
  subfeatures: {
31
31
  type: string;
32
- description: string;
32
+ description: string; /**
33
+ * #getter
34
+ */
33
35
  defaultValue: {};
34
36
  contextVariable: string[];
35
37
  };
36
38
  depth: {
37
- type: string;
39
+ type: string; /**
40
+ * #getter
41
+ */
38
42
  defaultValue: number;
39
43
  description: string;
40
44
  };
@@ -59,21 +63,46 @@ export declare function JBrowseModelF({ pluginManager, assemblyConfigSchema, }:
59
63
  type: string;
60
64
  defaultValue: boolean;
61
65
  };
66
+ hierarchical: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
67
+ sort: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
68
+ trackNames: {
69
+ type: string;
70
+ defaultValue: boolean;
71
+ };
72
+ categories: {
73
+ type: string;
74
+ defaultValue: boolean;
75
+ };
76
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
77
+ defaultCollapsed: import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaType<{
78
+ categoryNames: {
79
+ type: string;
80
+ defaultValue: never[];
81
+ };
82
+ topLevelCategories: {
83
+ type: string;
84
+ defaultValue: boolean; /**
85
+ * #action
86
+ */
87
+ };
88
+ subCategories: {
89
+ type: string;
90
+ defaultValue: boolean;
91
+ };
92
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
93
+ }, import("@jbrowse/core/configuration/configurationSchema").ConfigurationSchemaOptions<undefined, undefined>>;
62
94
  theme: {
63
95
  type: string;
64
- defaultValue: {}; /**
65
- * #action
66
- */
96
+ defaultValue: {};
67
97
  };
68
98
  extraThemes: {
69
- type: string;
99
+ type: string; /**
100
+ * #action
101
+ */
70
102
  defaultValue: {};
71
103
  };
72
104
  logoPath: {
73
105
  type: string;
74
- /**
75
- * #action
76
- */
77
106
  defaultValue: {
78
107
  uri: string;
79
108
  locationType: string;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import { SessionWithDrawerWidgets } from '@jbrowse/core/util/types';
3
+ declare const _default: ({ session, setToolbarHeight, }: {
4
+ session: SessionWithDrawerWidgets;
5
+ setToolbarHeight: (arg: number) => void;
6
+ }) => React.JSX.Element;
7
+ export default _default;
@@ -0,0 +1,86 @@
1
+ import React, { useState } from 'react';
2
+ import { AppBar, FormControl, IconButton, Menu, MenuItem, Select, Toolbar, Tooltip, Typography, } from '@mui/material';
3
+ import { makeStyles } from 'tss-react/mui';
4
+ import { observer } from 'mobx-react';
5
+ import { getEnv } from '@jbrowse/core/util';
6
+ // icons
7
+ import DeleteIcon from '@mui/icons-material/Delete';
8
+ import CloseIcon from '@mui/icons-material/Close';
9
+ import MinimizeIcon from '@mui/icons-material/Minimize';
10
+ import MoreVertIcon from '@mui/icons-material/MoreVert';
11
+ const useStyles = makeStyles()(theme => ({
12
+ formControl: {
13
+ margin: 0,
14
+ },
15
+ spacer: {
16
+ flexGrow: 1,
17
+ },
18
+ drawerSelect: {
19
+ margin: 0,
20
+ color: theme.palette.secondary.contrastText,
21
+ },
22
+ dropDownIcon: {
23
+ color: theme.palette.secondary.contrastText,
24
+ },
25
+ header: {
26
+ background: theme.palette.secondary.main,
27
+ },
28
+ }));
29
+ export default observer(function ({ session, setToolbarHeight, }) {
30
+ const { classes } = useStyles();
31
+ return (React.createElement(AppBar, { position: "sticky", className: classes.header, ref: ref => setToolbarHeight((ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect().height) || 0) },
32
+ React.createElement(Toolbar, { disableGutters: true },
33
+ React.createElement(DrawerWidgetSelector, { session: session }),
34
+ React.createElement("div", { className: classes.spacer }),
35
+ React.createElement(DrawerControls, { session: session }))));
36
+ });
37
+ const DrawerWidgetSelector = observer(function ({ session, }) {
38
+ const { visibleWidget, activeWidgets } = session;
39
+ const { classes } = useStyles();
40
+ const { pluginManager } = getEnv(session);
41
+ return (React.createElement(FormControl, { className: classes.formControl },
42
+ React.createElement(Select, { value: visibleWidget === null || visibleWidget === void 0 ? void 0 : visibleWidget.id, "data-testid": "widget-drawer-selects", className: classes.drawerSelect, classes: { icon: classes.dropDownIcon }, renderValue: widgetId => {
43
+ const widget = session.activeWidgets.get(widgetId);
44
+ if (!widget) {
45
+ return (React.createElement(Typography, { variant: "h6", color: "inherit" }, "Unknown widget"));
46
+ }
47
+ const widgetType = pluginManager.getWidgetType(widget.type);
48
+ const { HeadingComponent, heading } = widgetType;
49
+ return HeadingComponent ? (React.createElement(HeadingComponent, { model: widget })) : (React.createElement(Typography, { variant: "h6", color: "inherit" }, heading));
50
+ }, onChange: e => {
51
+ const w = session.activeWidgets.get(e.target.value);
52
+ if (w) {
53
+ session.showWidget(w);
54
+ }
55
+ else {
56
+ session.notify(`Widget not found ${e.target.value}`, 'warning');
57
+ }
58
+ } }, [...activeWidgets.values()].map(widget => {
59
+ const widgetType = pluginManager.getWidgetType(widget.type);
60
+ const { HeadingComponent, heading } = widgetType;
61
+ return (React.createElement(MenuItem, { "data-testid": `widget-drawer-selects-item-${widget.type}`, key: widget.id, value: widget.id },
62
+ HeadingComponent ? (React.createElement(HeadingComponent, { model: widget })) : (React.createElement(Typography, { variant: "h6", color: "inherit" }, heading)),
63
+ React.createElement(IconButton, { "data-testid": `${widget.type}-drawer-delete`, color: "inherit", "aria-label": "Delete", onClick: () => session.hideWidget(widget) },
64
+ React.createElement(DeleteIcon, null))));
65
+ }))));
66
+ });
67
+ const DrawerControls = observer(function ({ session, }) {
68
+ const [anchorEl, setAnchorEl] = useState(null);
69
+ const { drawerPosition, visibleWidget } = session;
70
+ return (React.createElement(React.Fragment, null,
71
+ React.createElement(IconButton, { color: "inherit", onClick: event => setAnchorEl(event.currentTarget) },
72
+ React.createElement(MoreVertIcon, null)),
73
+ React.createElement(Tooltip, { title: "Minimize drawer" },
74
+ React.createElement(IconButton, { "data-testid": "drawer-minimize", color: "inherit", onClick: () => {
75
+ session.notify(`Drawer minimized, click button on ${drawerPosition} side of screen to re-open`, 'info');
76
+ session.minimizeWidgetDrawer();
77
+ } },
78
+ React.createElement(MinimizeIcon, null))),
79
+ React.createElement(Tooltip, { title: "Close drawer" },
80
+ React.createElement(IconButton, { color: "inherit", onClick: () => session.hideWidget(visibleWidget) },
81
+ React.createElement(CloseIcon, null))),
82
+ React.createElement(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () => setAnchorEl(null) }, ['left', 'right'].map(option => (React.createElement(MenuItem, { key: option, selected: drawerPosition === 'option', onClick: () => {
83
+ session.setDrawerPosition(option);
84
+ setAnchorEl(null);
85
+ } }, option))))));
86
+ });
@@ -1,86 +1,12 @@
1
1
  import React, { Suspense, useState } from 'react';
2
2
  import { ErrorBoundary } from 'react-error-boundary';
3
- import { AppBar, FormControl, IconButton, Menu, MenuItem, Select, Toolbar, Tooltip, Typography, } from '@mui/material';
4
- import { makeStyles } from 'tss-react/mui';
5
3
  import { observer } from 'mobx-react';
6
4
  import { getEnv } from '@jbrowse/core/util';
7
5
  import LoadingEllipses from '@jbrowse/core/ui/LoadingEllipses';
8
6
  import ErrorMessage from '@jbrowse/core/ui/ErrorMessage';
9
- // icons
10
- import DeleteIcon from '@mui/icons-material/Delete';
11
- import CloseIcon from '@mui/icons-material/Close';
12
- import MinimizeIcon from '@mui/icons-material/Minimize';
13
- import MoreVertIcon from '@mui/icons-material/MoreVert';
14
7
  // locals
15
8
  import Drawer from './Drawer';
16
- const useStyles = makeStyles()(theme => ({
17
- formControl: {
18
- margin: 0,
19
- },
20
- spacer: {
21
- flexGrow: 1,
22
- },
23
- drawerSelect: {
24
- margin: 0,
25
- color: theme.palette.secondary.contrastText,
26
- },
27
- dropDownIcon: {
28
- color: theme.palette.secondary.contrastText,
29
- },
30
- header: {
31
- background: theme.palette.secondary.main,
32
- },
33
- }));
34
- const DrawerHeader = observer(function ({ session, setToolbarHeight, }) {
35
- const { pluginManager } = getEnv(session);
36
- const { visibleWidget, activeWidgets, drawerPosition } = session;
37
- const { classes } = useStyles();
38
- const [anchorEl, setAnchorEl] = useState(null);
39
- return (React.createElement(AppBar, { position: "sticky", className: classes.header, ref: ref => setToolbarHeight((ref === null || ref === void 0 ? void 0 : ref.getBoundingClientRect().height) || 0) },
40
- React.createElement(Toolbar, { disableGutters: true },
41
- React.createElement(FormControl, { className: classes.formControl },
42
- React.createElement(Select, { value: visibleWidget === null || visibleWidget === void 0 ? void 0 : visibleWidget.id, "data-testid": "widget-drawer-selects", className: classes.drawerSelect, classes: { icon: classes.dropDownIcon }, renderValue: widgetId => {
43
- const widget = session.activeWidgets.get(widgetId);
44
- if (!widget) {
45
- return (React.createElement(Typography, { variant: "h6", color: "inherit" }, "Unknown widget"));
46
- }
47
- const widgetType = pluginManager.getWidgetType(widget.type);
48
- const { HeadingComponent, heading } = widgetType;
49
- return HeadingComponent ? (React.createElement(HeadingComponent, { model: widget })) : (React.createElement(Typography, { variant: "h6", color: "inherit" }, heading));
50
- }, onChange: e => {
51
- const w = session.activeWidgets.get(e.target.value);
52
- if (w) {
53
- session.showWidget(w);
54
- }
55
- else {
56
- session.notify(`Widget not found ${e.target.value}`, 'warning');
57
- }
58
- } }, [...activeWidgets.values()].map(widget => {
59
- const widgetType = pluginManager.getWidgetType(widget.type);
60
- const { HeadingComponent, heading } = widgetType;
61
- return (React.createElement(MenuItem, { "data-testid": `widget-drawer-selects-item-${widget.type}`, key: widget.id, value: widget.id },
62
- HeadingComponent ? (React.createElement(HeadingComponent, { model: widget })) : (React.createElement(Typography, { variant: "h6", color: "inherit" }, heading)),
63
- React.createElement(IconButton, { "data-testid": `${widget.type}-drawer-delete`, color: "inherit", "aria-label": "Delete", onClick: () => session.hideWidget(widget) },
64
- React.createElement(DeleteIcon, null))));
65
- }))),
66
- React.createElement("div", { className: classes.spacer }),
67
- React.createElement("div", null,
68
- React.createElement(IconButton, { "data-testid": "drawer-close", color: "inherit", onClick: event => setAnchorEl(event.currentTarget) },
69
- React.createElement(MoreVertIcon, null)),
70
- React.createElement(Tooltip, { title: "Minimize drawer" },
71
- React.createElement(IconButton, { "data-testid": "drawer-minimize", color: "inherit", onClick: () => {
72
- session.notify(`Drawer minimized, click button on ${drawerPosition} side of screen to re-open`, 'info');
73
- session.minimizeWidgetDrawer();
74
- } },
75
- React.createElement(MinimizeIcon, null))),
76
- React.createElement(Tooltip, { title: "Close drawer" },
77
- React.createElement(IconButton, { "data-testid": "drawer-close", color: "inherit", onClick: () => session.hideWidget(visibleWidget) },
78
- React.createElement(CloseIcon, null))))),
79
- React.createElement(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: () => setAnchorEl(null) }, ['left', 'right'].map(option => (React.createElement(MenuItem, { key: option, selected: drawerPosition === 'option', onClick: () => {
80
- session.setDrawerPosition(option);
81
- setAnchorEl(null);
82
- } }, option))))));
83
- });
9
+ import DrawerHeader from './DrawerHeader';
84
10
  const DrawerWidget = observer(function ({ session, }) {
85
11
  const { visibleWidget } = session;
86
12
  const { pluginManager } = getEnv(session);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/app-core",
3
- "version": "2.6.1",
3
+ "version": "2.6.3",
4
4
  "description": "JBrowse 2 code shared between the 'full featured' apps e.g. jbrowse-web and jbrowse-desktop",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -26,13 +26,12 @@
26
26
  "module": "esm/index.js",
27
27
  "files": [
28
28
  "dist",
29
- "esm",
30
- "src"
29
+ "esm"
31
30
  ],
32
31
  "scripts": {
33
32
  "build:esm": "tsc --build tsconfig.build.esm.json",
34
- "build:es5": "tsc --build tsconfig.build.es5.json",
35
- "build": "npm run build:esm && npm run build:es5",
33
+ "build:commonjs": "tsc --build tsconfig.build.commonjs.json",
34
+ "build": "npm run build:esm && npm run build:commonjs",
36
35
  "test": "cd ../..; jest packages/app-core",
37
36
  "clean": "rimraf dist esm *.tsbuildinfo",
38
37
  "prebuild": "yarn clean",
@@ -43,7 +42,7 @@
43
42
  },
44
43
  "dependencies": {
45
44
  "@babel/runtime": "^7.16.3",
46
- "@jbrowse/product-core": "^2.6.1",
45
+ "@jbrowse/product-core": "^2.6.3",
47
46
  "@mui/icons-material": "^5.0.0",
48
47
  "@mui/material": "^5.10.17",
49
48
  "copy-to-clipboard": "^3.3.1",
@@ -62,5 +61,5 @@
62
61
  "publishConfig": {
63
62
  "access": "public"
64
63
  },
65
- "gitHead": "1cbe7ba097fb2d2763c776e5e429e4670cdd583c"
64
+ "gitHead": "ed402c87efb0904858d602c363bd1757d5742129"
66
65
  }
@@ -1,50 +0,0 @@
1
- import { types } from 'mobx-state-tree'
2
-
3
- import PluginManager from '@jbrowse/core/PluginManager'
4
- import { AnyConfiguration } from '@jbrowse/core/configuration'
5
- import { BaseSession } from '@jbrowse/product-core'
6
- import { BaseAssemblyConfigSchema } from '@jbrowse/core/assemblyManager'
7
-
8
- /**
9
- * #stateModel SessionAssembliesMixin
10
- * #category root
11
- */
12
- export function SessionAssembliesMixin(
13
- pluginManager: PluginManager,
14
- assemblyConfigSchemasType: BaseAssemblyConfigSchema,
15
- ) {
16
- return types
17
- .model({
18
- /**
19
- * #property
20
- */
21
- sessionAssemblies: types.array(assemblyConfigSchemasType),
22
- })
23
- .actions(s => {
24
- const self = s as typeof s & BaseSession
25
- return {
26
- /**
27
- * #action
28
- */
29
- addSessionAssembly(conf: AnyConfiguration) {
30
- const asm = self.sessionAssemblies.find(f => f.name === conf.name)
31
- if (asm) {
32
- console.warn(`Assembly ${conf.name} already exists`)
33
- return asm
34
- }
35
- const length = self.sessionAssemblies.push(conf)
36
- return self.sessionAssemblies[length - 1]
37
- },
38
-
39
- /**
40
- * #action
41
- */
42
- removeSessionAssembly(assemblyName: string) {
43
- const elt = self.sessionAssemblies.find(a => a.name === assemblyName)
44
- if (elt) {
45
- self.sessionAssemblies.remove(elt)
46
- }
47
- },
48
- }
49
- })
50
- }
@@ -1,51 +0,0 @@
1
- import { types } from 'mobx-state-tree'
2
-
3
- import PluginManager from '@jbrowse/core/PluginManager'
4
- import { AnyConfiguration } from '@jbrowse/core/configuration'
5
- import { BaseSession } from '@jbrowse/product-core'
6
-
7
- /**
8
- * #stateModel TemporaryAssembliesMixin
9
- * #category root
10
- */
11
- export function TemporaryAssembliesMixin(
12
- pluginManager: PluginManager,
13
- assemblyConfigSchemasType = types.frozen(),
14
- ) {
15
- return types
16
- .model({
17
- /**
18
- * #property
19
- */
20
- temporaryAssemblies: types.array(assemblyConfigSchemasType),
21
- })
22
-
23
- .actions(s => {
24
- const self = s as typeof s & BaseSession
25
- return {
26
- /**
27
- * #action
28
- * used for read vs ref type assemblies.
29
- */
30
- addTemporaryAssembly(conf: AnyConfiguration) {
31
- const asm = self.temporaryAssemblies.find(f => f.name === conf.name)
32
- if (asm) {
33
- console.warn(`Assembly ${conf.name} was already existing`)
34
- return asm
35
- }
36
- const length = self.temporaryAssemblies.push(conf)
37
- return self.temporaryAssemblies[length - 1]
38
- },
39
-
40
- /**
41
- * #action
42
- */
43
- removeTemporaryAssembly(name: string) {
44
- const elt = self.temporaryAssemblies.find(a => a.name === name)
45
- if (elt) {
46
- self.temporaryAssemblies.remove(elt)
47
- }
48
- },
49
- }
50
- })
51
- }
@@ -1,2 +0,0 @@
1
- export * from './SessionAssembliesMixin'
2
- export * from './TemporaryAssembliesMixin'
@@ -1,56 +0,0 @@
1
- import TimeTraveller from '@jbrowse/core/util/TimeTraveller'
2
- import type { BaseRootModel } from '@jbrowse/product-core'
3
- import { autorun } from 'mobx'
4
- import { addDisposer, types } from 'mobx-state-tree'
5
-
6
- /**
7
- * #stateModel HistoryManagementMixin
8
- * #category root
9
- */
10
- export function HistoryManagementMixin() {
11
- return types
12
- .model({
13
- /**
14
- * #property
15
- * used for undo/redo
16
- */
17
- history: types.optional(TimeTraveller, { targetPath: '../session' }),
18
- })
19
- .actions(self => ({
20
- afterCreate() {
21
- document.addEventListener('keydown', e => {
22
- if (
23
- self.history.canRedo &&
24
- // ctrl+shift+z or cmd+shift+z
25
- (((e.ctrlKey || e.metaKey) && e.shiftKey && e.code === 'KeyZ') ||
26
- // ctrl+y
27
- (e.ctrlKey && !e.shiftKey && e.code === 'KeyY'))
28
- ) {
29
- self.history.redo()
30
- }
31
- if (
32
- self.history.canUndo &&
33
- // ctrl+z or cmd+z
34
- (e.ctrlKey || e.metaKey) &&
35
- !e.shiftKey &&
36
- e.code === 'KeyZ'
37
- ) {
38
- self.history.undo()
39
- }
40
- })
41
- addDisposer(
42
- self,
43
- autorun(() => {
44
- const { session } = self as typeof self & BaseRootModel
45
- if (session) {
46
- // we use a specific initialization routine after session is
47
- // created to get it to start tracking itself sort of related
48
- // issue here
49
- // https://github.com/mobxjs/mobx-state-tree/issues/1089#issuecomment-441207911
50
- self.history.initialize()
51
- }
52
- }),
53
- )
54
- },
55
- }))
56
- }