@jbrowse/embedded-core 5.0.0-beta.1 → 5.0.0-beta.11

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.
@@ -2,7 +2,23 @@ import TextSearchManager from '@jbrowse/core/TextSearch/TextSearchManager';
2
2
  import assemblyManagerFactory, { assemblyConfigSchemaFactory, } from '@jbrowse/core/assemblyManager';
3
3
  import RpcManager from '@jbrowse/core/rpc/RpcManager';
4
4
  import { cast, types } from '@jbrowse/mobx-state-tree';
5
- import { InternetAccountsRootModelMixin, createConfigModel, } from '@jbrowse/product-core';
5
+ import { InternetAccountsRootModelMixin, createConfigModel, migrateSessionSnapshot, } from '@jbrowse/product-core';
6
+ /**
7
+ * A session an embedder hands over may be a v4 one: a share link, a stored
8
+ * snapshot, a `?session=` param a reader still holds. It names display types
9
+ * this build retired and carries settings that are config slots now, which the
10
+ * session type refuses outright — so the whole engine fails to build rather
11
+ * than one track opening at its defaults. ADR-168.
12
+ *
13
+ * An app root runs this once, in `setSession`, because that is its only door.
14
+ * An embedded root has three: the `session` prop at create, and the two actions
15
+ * that assign over it afterwards.
16
+ */
17
+ function migrated(snapshot, pluginManager) {
18
+ return snapshot && typeof snapshot === 'object'
19
+ ? migrateSessionSnapshot(snapshot, pluginManager)
20
+ : snapshot;
21
+ }
6
22
  /**
7
23
  * #stateModel EmbeddedRootModel
8
24
  * #category root
@@ -15,7 +31,8 @@ import { InternetAccountsRootModelMixin, createConfigModel, } from '@jbrowse/pro
15
31
  */
16
32
  export function createEmbeddedRootModel({ name, version, pluginManager, sessionModelType, makeWorkerInstance, }) {
17
33
  const assemblyConfigSchema = assemblyConfigSchemaFactory(pluginManager);
18
- return types.compose(name, types
34
+ return types
35
+ .compose(name, types
19
36
  .model({
20
37
  /**
21
38
  * #property
@@ -31,11 +48,6 @@ export function createEmbeddedRootModel({ name, version, pluginManager, sessionM
31
48
  assemblyManager: types.optional(assemblyManagerFactory(assemblyConfigSchema, pluginManager), {}),
32
49
  })
33
50
  .volatile(self => ({
34
- /**
35
- * #volatile
36
- */
37
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
38
- error: undefined,
39
51
  /**
40
52
  * #volatile
41
53
  */
@@ -63,9 +75,12 @@ export function createEmbeddedRootModel({ name, version, pluginManager, sessionM
63
75
  .actions(self => ({
64
76
  /**
65
77
  * #action
78
+ * Synchronous: an async caller must
79
+ * `await pluginManager.preloadSessionTypes(snapshot)` first.
66
80
  */
67
81
  setSession(sessionSnapshot) {
68
- self.session = cast(sessionSnapshot);
82
+ pluginManager.assertSessionTypesLoaded(sessionSnapshot);
83
+ self.session = cast(migrated(sessionSnapshot, pluginManager));
69
84
  },
70
85
  /**
71
86
  * #action
@@ -81,7 +96,8 @@ export function createEmbeddedRootModel({ name, version, pluginManager, sessionM
81
96
  * actually matters for a value this app did not author.
82
97
  */
83
98
  restoreSession(sessionSnapshot) {
84
- self.session = cast(sessionSnapshot);
99
+ pluginManager.assertSessionTypesLoaded(sessionSnapshot);
100
+ self.session = cast(migrated(sessionSnapshot, pluginManager));
85
101
  },
86
102
  /**
87
103
  * #action
@@ -89,12 +105,6 @@ export function createEmbeddedRootModel({ name, version, pluginManager, sessionM
89
105
  renameCurrentSession(sessionName) {
90
106
  self.session.setName(sessionName);
91
107
  },
92
- /**
93
- * #action
94
- */
95
- setError(error) {
96
- self.error = error;
97
- },
98
108
  }))
99
109
  .views(self => ({
100
110
  /**
@@ -109,5 +119,8 @@ export function createEmbeddedRootModel({ name, version, pluginManager, sessionM
109
119
  get pluginManager() {
110
120
  return pluginManager;
111
121
  },
112
- })), InternetAccountsRootModelMixin(pluginManager));
122
+ })), InternetAccountsRootModelMixin(pluginManager))
123
+ .preProcessSnapshot(snap => snap && typeof snap === 'object' && 'session' in snap
124
+ ? { ...snap, session: migrated(snap.session, pluginManager) }
125
+ : snap);
113
126
  }
@@ -1,26 +1,26 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Suspense } from 'react';
3
3
  import { getSession } from '@jbrowse/core/util';
4
- import { useWidthSetter } from '@jbrowse/core/util/hooks';
4
+ import { VIEW_HEADER_HEIGHT_VAR, useWidthSetter, } from '@jbrowse/core/util/hooks';
5
5
  import { makeStyles } from '@jbrowse/core/util/tss-react';
6
- import { Paper } from '@mui/material';
7
6
  import { observer } from 'mobx-react';
8
- import ViewTitle from './ViewTitle.js';
9
7
  const useStyles = makeStyles()(theme => ({
10
8
  viewContainer: {
11
9
  width: '100%',
12
10
  // clip (not hidden) so sticky descendant headers keep working
13
- // xref https://stackoverflow.com/questions/43909940/why-does-overflowhidden-prevent-positionsticky-from-working
14
11
  overflow: 'clip',
15
- background: theme.palette.secondary.main,
16
- margin: theme.spacing(0.5),
17
- padding: `0 ${theme.spacing(1)} ${theme.spacing(1)}`,
12
+ background: theme.palette.background.paper,
13
+ border: `1px solid ${theme.palette.divider}`,
14
+ borderRadius: theme.shape.borderRadius,
15
+ // no title bar above the view, so the sticky chrome that clears one pins
16
+ // at the top edge
17
+ [VIEW_HEADER_HEIGHT_VAR]: '0px',
18
18
  },
19
19
  }));
20
20
  const ViewContainer = observer(function ViewContainer({ view, children, }) {
21
21
  const { classes } = useStyles();
22
22
  const session = getSession(view);
23
23
  const ref = useWidthSetter(view);
24
- return (_jsxs(Paper, { elevation: 12, ref: ref, className: classes.viewContainer, children: [session.DialogComponent ? (_jsx(Suspense, { fallback: null, children: _jsx(session.DialogComponent, { ...session.DialogProps }) })) : null, _jsx(ViewTitle, { view: view }), _jsx(Paper, { children: children })] }));
24
+ return (_jsxs("div", { ref: ref, className: classes.viewContainer, children: [session.DialogComponent ? (_jsx(Suspense, { fallback: null, children: _jsx(session.DialogComponent, { ...session.DialogProps }) })) : null, children] }));
25
25
  });
26
26
  export default ViewContainer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/embedded-core",
3
- "version": "5.0.0-beta.1",
3
+ "version": "5.0.0-beta.11",
4
4
  "type": "module",
5
5
  "description": "JBrowse 2 code shared between embedded products",
6
6
  "keywords": [
@@ -24,13 +24,13 @@
24
24
  "esm"
25
25
  ],
26
26
  "dependencies": {
27
- "@jbrowse/mobx-state-tree": "^6.5.1",
28
- "@mui/icons-material": "^9.3.1",
29
- "@mui/material": "^9.3.1",
30
- "mobx": "^7.0.3",
27
+ "@jbrowse/mobx-state-tree": "^6.7.0",
28
+ "@mui/icons-material": "^9.4.0",
29
+ "@mui/material": "^9.4.0",
30
+ "mobx": "^7.0.5",
31
31
  "mobx-react": "^10.0.2",
32
- "@jbrowse/product-core": "^5.0.0-beta.1",
33
- "@jbrowse/core": "^5.0.0-beta.1"
32
+ "@jbrowse/product-core": "^5.0.0-beta.11",
33
+ "@jbrowse/core": "^5.0.0-beta.11"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": ">=19.0.0",
@@ -1,5 +0,0 @@
1
- export default function AboutDialog({ open, version, onClose, }: {
2
- open: boolean;
3
- version: string;
4
- onClose: () => void;
5
- }): import("react").JSX.Element;
@@ -1,13 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { ExternalLink, InfoDialog } from '@jbrowse/core/ui';
3
- import { makeStyles } from '@jbrowse/core/util/tss-react';
4
- import { Typography } from '@mui/material';
5
- const useStyles = makeStyles()({
6
- content: {
7
- minWidth: 800,
8
- },
9
- });
10
- export default function AboutDialog({ open, version, onClose, }) {
11
- const { classes } = useStyles();
12
- return (_jsx(InfoDialog, { open: open, onClose: onClose, maxWidth: "xl", title: `JBrowse v${version}`, children: _jsxs("div", { className: classes.content, children: [_jsx(Typography, { children: "JBrowse is a GMOD project \u00A9 2019-2026, The Evolutionary Software Foundation" }), _jsx(Typography, { children: "Here are some resources and documentation. Please report the version number above when asking questions. Thanks!" }), _jsxs("ul", { children: [_jsx("li", { children: _jsx(ExternalLink, { href: "https://github.com/GMOD/jbrowse-components/discussions", children: "Question & answer forum" }) }), _jsx("li", { children: _jsx(ExternalLink, { href: "https://github.com/GMOD/jbrowse-components/issues/new/choose", children: "Report a bug" }) }), _jsx("li", { children: _jsx(ExternalLink, { href: "https://jbrowse.org/jb2/docs/user_guide", children: "User guide" }) }), _jsx("li", { children: _jsx(ExternalLink, { href: "https://jbrowse.org/jb2/docs/", children: "Documentation" }) })] })] }) }));
13
- }
@@ -1,5 +0,0 @@
1
- import type { IBaseViewModel } from '@jbrowse/core/pluggableElementTypes/models/BaseViewModel';
2
- declare const ViewTitle: ({ view, }: {
3
- view: IBaseViewModel;
4
- }) => import("react").JSX.Element;
5
- export default ViewTitle;
@@ -1,65 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Suspense, lazy, useRef, useState } from 'react';
3
- import { CascadingMenuButton, Logomark, VIEW_HEADER_HEIGHT, } from '@jbrowse/core/ui';
4
- import { getSession } from '@jbrowse/core/util';
5
- import { VIEW_HEADER_HEIGHT_VAR, useChromeHeightVar, } from '@jbrowse/core/util/hooks';
6
- import { makeStyles } from '@jbrowse/core/util/tss-react';
7
- import MenuIcon from '@mui/icons-material/Menu';
8
- import { IconButton, Typography, alpha } from '@mui/material';
9
- import { observer } from 'mobx-react';
10
- const VersionAboutDialog = lazy(() => import('./VersionAboutDialog.js'));
11
- const useStyles = makeStyles()(theme => ({
12
- icon: {
13
- color: theme.palette.secondary.contrastText,
14
- },
15
- displayName: {
16
- marginTop: 2,
17
- color: theme.palette.secondary.contrastText,
18
- },
19
- grow: {
20
- flexGrow: 1,
21
- },
22
- container: {
23
- display: 'flex',
24
- alignItems: 'center',
25
- // A fixed height, unlike the web app's view header, which is a floor. Both
26
- // publish what they measure through `useChromeHeightVar`, so what sticks
27
- // below follows either — this is a density choice and no longer a
28
- // load-bearing constant. It stays fixed because the content that would
29
- // widen the box is the logomark button, whose 22px icon and 5px padding
30
- // want 32: a floor here spends 4px of an embedder's box to stop that button
31
- // painting 2px outside a bar nothing clips.
32
- height: VIEW_HEADER_HEIGHT,
33
- top: 0,
34
- zIndex: 900,
35
- // a sticky element does not carry its parent's background, and what would
36
- // otherwise show through is the tracks scrolling underneath
37
- background: theme.palette.secondary.main,
38
- },
39
- iconRoot: {
40
- '&:hover': {
41
- backgroundColor: alpha(theme.palette.secondary.contrastText, theme.palette.action.hoverOpacity),
42
- '@media (hover: none)': {
43
- backgroundColor: 'transparent',
44
- },
45
- },
46
- },
47
- }));
48
- const ViewTitle = observer(function ViewTitle({ view, }) {
49
- const { classes } = useStyles();
50
- const { displayName } = view;
51
- const [dialogOpen, setDialogOpen] = useState(false);
52
- const session = getSession(view);
53
- // `=== true` because the member is optional on AbstractSessionModel: a
54
- // session with no such notion reads as "don't pin", which is what the LGV
55
- // model's own getter does with it too
56
- const stickyViewHeaders = session.stickyViewHeaders === true;
57
- const ref = useRef(null);
58
- useChromeHeightVar(ref, VIEW_HEADER_HEIGHT_VAR);
59
- return (_jsxs("div", { ref: ref, className: classes.container, style: { position: stickyViewHeaders ? 'sticky' : undefined }, children: [_jsx(CascadingMenuButton, { menuItems: () => view.menuItems(), "data-testid": "view_menu_icon", classes: { root: classes.iconRoot }, edge: "start", children: _jsx(MenuIcon, { className: classes.icon }) }), _jsx("div", { className: classes.grow }), displayName ? (_jsx(Typography, { variant: "body2", className: classes.displayName, children: displayName })) : null, _jsx("div", { className: classes.grow }), _jsx(IconButton, { onClick: () => {
60
- setDialogOpen(true);
61
- }, children: _jsx("div", { style: { width: 22, height: 22 }, children: _jsx(Logomark, { variant: "white" }) }) }), dialogOpen ? (_jsx(Suspense, { fallback: null, children: _jsx(VersionAboutDialog, { open: true, onClose: () => {
62
- setDialogOpen(false);
63
- }, version: session.version }) })) : null] }));
64
- });
65
- export default ViewTitle;