@jbrowse/core 5.0.0-beta.1 → 5.0.0-beta.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 (199) hide show
  1. package/README.md +112 -43
  2. package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +2 -3
  3. package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.d.ts +4 -0
  4. package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.js +17 -0
  5. package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +4 -3
  6. package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.d.ts +2 -2
  7. package/esm/BaseFeatureWidget/SequenceFeatureDetails/test_data/NCDN.d.ts +2 -2
  8. package/esm/BaseFeatureWidget/index.d.ts +1 -1
  9. package/esm/BaseFeatureWidget/stateModelFactory.d.ts +8 -1
  10. package/esm/BaseFeatureWidget/stateModelFactory.js +6 -0
  11. package/esm/BaseFeatureWidget/types.d.ts +10 -2
  12. package/esm/PluginLoader.d.ts +1 -0
  13. package/esm/PluginLoader.js +52 -8
  14. package/esm/PluginManager.d.ts +99 -17
  15. package/esm/PluginManager.js +194 -26
  16. package/esm/ReExports/BaseFeatureDetails.js +1 -1
  17. package/esm/ReExports/MuiDataGridReExports.d.ts +1 -0
  18. package/esm/ReExports/MuiDataGridReExports.js +2 -2
  19. package/esm/ReExports/barrelOnlyNames.d.ts +5 -0
  20. package/esm/ReExports/barrelOnlyNames.js +63 -0
  21. package/esm/ReExports/modules.js +31 -109
  22. package/esm/ReExports/publicTracks.d.ts +1 -0
  23. package/esm/ReExports/publicTracks.js +14 -0
  24. package/esm/ReExports/publicUi.d.ts +4 -0
  25. package/esm/ReExports/publicUi.js +33 -0
  26. package/esm/ReExports/publicUtil.d.ts +1 -1
  27. package/esm/ReExports/publicUtil.js +8 -4
  28. package/esm/ReExports/sharedModules.d.ts +96 -0
  29. package/esm/ReExports/sharedModules.js +66 -0
  30. package/esm/ReExports/uiStub.d.ts +2 -0
  31. package/esm/ReExports/uiStub.js +11 -0
  32. package/esm/ReExports/workerModules.d.ts +2 -0
  33. package/esm/ReExports/workerModules.js +15 -0
  34. package/esm/ReExports/workerNamespaceNames.d.ts +11 -0
  35. package/esm/ReExports/workerNamespaceNames.js +281 -0
  36. package/esm/configuration/configurationSchema.d.ts +5 -38
  37. package/esm/configuration/configurationSchema.js +64 -40
  38. package/esm/configuration/index.d.ts +2 -2
  39. package/esm/configuration/index.js +1 -1
  40. package/esm/configuration/promotableDefaults.d.ts +54 -19
  41. package/esm/configuration/promotableDefaults.js +117 -48
  42. package/esm/configuration/promotablePin.d.ts +50 -40
  43. package/esm/configuration/promotableResolve.d.ts +1 -1
  44. package/esm/configuration/promotableResolve.js +1 -1
  45. package/esm/configuration/tabixIndexFields.d.ts +2 -2
  46. package/esm/configuration/tabixIndexFields.js +2 -2
  47. package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.d.ts +12 -0
  48. package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +35 -4
  49. package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +41 -0
  50. package/esm/data_adapters/BaseAdapter/featureDensity.js +32 -0
  51. package/esm/data_adapters/BaseAdapter/index.d.ts +2 -1
  52. package/esm/data_adapters/BaseAdapter/index.js +1 -0
  53. package/esm/data_adapters/BaseAdapter/stats.d.ts +33 -1
  54. package/esm/data_adapters/BaseAdapter/stats.js +52 -13
  55. package/esm/data_adapters/BaseAdapter/types.d.ts +3 -8
  56. package/esm/pluggableElementTypes/AdapterType.d.ts +2 -1
  57. package/esm/pluggableElementTypes/AdapterType.js +1 -1
  58. package/esm/pluggableElementTypes/DisplayType.d.ts +4 -12
  59. package/esm/pluggableElementTypes/DisplayType.js +3 -10
  60. package/esm/pluggableElementTypes/LazyStateModelElement.d.ts +27 -0
  61. package/esm/pluggableElementTypes/LazyStateModelElement.js +71 -0
  62. package/esm/pluggableElementTypes/ViewType.d.ts +20 -4
  63. package/esm/pluggableElementTypes/ViewType.js +32 -4
  64. package/esm/pluggableElementTypes/extendElementType.d.ts +1 -2
  65. package/esm/pluggableElementTypes/extendElementType.js +9 -5
  66. package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +44 -3
  67. package/esm/pluggableElementTypes/models/BaseDisplayModel.js +75 -2
  68. package/esm/pluggableElementTypes/models/BaseTrackModel.d.ts +21 -0
  69. package/esm/pluggableElementTypes/models/BaseTrackModel.js +34 -2
  70. package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +49 -0
  71. package/esm/pluggableElementTypes/models/BaseViewModel.js +28 -0
  72. package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +14 -10
  73. package/esm/pluggableElementTypes/models/assertDisplayContract.js +25 -32
  74. package/esm/pluggableElementTypes/models/baseTrackConfig.js +7 -1
  75. package/esm/rpc/RpcRegistry.d.ts +10 -0
  76. package/esm/rpc/byteBudget.d.ts +9 -0
  77. package/esm/rpc/coreRpcMethods.d.ts +1 -0
  78. package/esm/rpc/coreRpcMethods.js +1 -0
  79. package/esm/rpc/methods/CoreGetFeatureDensity.d.ts +11 -0
  80. package/esm/rpc/methods/CoreGetFeatureDensity.js +22 -0
  81. package/esm/svg/svgReady.d.ts +1 -0
  82. package/esm/ui/BaseExportSvgDialog.d.ts +1 -1
  83. package/esm/ui/CascadingMenu.js +30 -8
  84. package/esm/ui/ErrorMessageStackTraceDialog.js +5 -6
  85. package/esm/ui/ExportSvgDialog.d.ts +1 -1
  86. package/esm/ui/LoadingOverlay.d.ts +14 -0
  87. package/esm/ui/LoadingOverlay.js +1 -1
  88. package/esm/ui/MenuTypes.d.ts +14 -5
  89. package/esm/ui/MenuTypes.js +3 -0
  90. package/esm/ui/PaletteContext.d.ts +11 -4
  91. package/esm/ui/PaletteContext.js +34 -5
  92. package/esm/ui/PinAdornment.js +31 -43
  93. package/esm/ui/ScrollChrome.d.ts +16 -0
  94. package/esm/ui/ScrollChrome.js +12 -0
  95. package/esm/ui/ScrollZoomToggle.d.ts +4 -3
  96. package/esm/ui/ScrollZoomToggle.js +4 -3
  97. package/esm/ui/SizeSliderRow.js +1 -1
  98. package/esm/ui/index.d.ts +3 -3
  99. package/esm/ui/index.js +4 -4
  100. package/esm/ui/launchViewMenu.js +7 -1
  101. package/esm/ui/legendMenuItem.d.ts +10 -16
  102. package/esm/ui/legendMenuItem.js +9 -20
  103. package/esm/ui/makeSizeMenu.js +1 -1
  104. package/esm/ui/menuItemAdornment.d.ts +2 -3
  105. package/esm/ui/menuItemAdornment.js +2 -3
  106. package/esm/ui/menuItems.d.ts +2 -3
  107. package/esm/ui/menuItems.js +1 -2
  108. package/esm/ui/palette.d.ts +11 -11
  109. package/esm/ui/palette.js +11 -11
  110. package/esm/ui/promotablePinCoverage.d.ts +16 -2
  111. package/esm/ui/promotablePinCoverage.js +40 -3
  112. package/esm/ui/theme.js +5 -0
  113. package/esm/ui/toggleMenuItems.d.ts +14 -9
  114. package/esm/ui/toggleMenuItems.js +32 -15
  115. package/esm/util/Base1DUtils.d.ts +4 -2
  116. package/esm/util/Base1DUtils.js +12 -4
  117. package/esm/util/SvgCanvas.js +4 -3
  118. package/esm/util/adapterConfigKey.d.ts +12 -0
  119. package/esm/util/adapterConfigKey.js +14 -0
  120. package/esm/util/adapterMetadata.js +2 -1
  121. package/esm/util/addAndShowTrack.d.ts +1 -1
  122. package/esm/util/addAndShowTrack.js +5 -1
  123. package/esm/util/addTrackFromWidget.js +2 -2
  124. package/esm/util/analytics.js +4 -5
  125. package/esm/util/cacheBudgets.d.ts +22 -19
  126. package/esm/util/cacheBudgets.js +22 -19
  127. package/esm/util/clampToContig.d.ts +17 -0
  128. package/esm/util/clampToContig.js +19 -0
  129. package/esm/util/colorBits.d.ts +2 -1
  130. package/esm/util/colorBits.js +2 -5
  131. package/esm/util/createStopTokenRotation.d.ts +9 -7
  132. package/esm/util/createStopTokenRotation.js +7 -27
  133. package/esm/util/featureTypes.d.ts +24 -0
  134. package/esm/util/featureTypes.js +35 -0
  135. package/esm/util/fetchContext.d.ts +2 -2
  136. package/esm/util/fetchContext.js +2 -2
  137. package/esm/util/fetchPhases.d.ts +10 -10
  138. package/esm/util/hooks.d.ts +8 -0
  139. package/esm/util/hooks.js +27 -0
  140. package/esm/util/index.d.ts +6 -5
  141. package/esm/util/index.js +5 -4
  142. package/esm/util/installFetch.d.ts +71 -34
  143. package/esm/util/installFetch.js +57 -29
  144. package/esm/util/installInitAutorun.d.ts +14 -13
  145. package/esm/util/installInitAutorun.js +17 -17
  146. package/esm/util/installPrerequisiteFetch.d.ts +86 -0
  147. package/esm/util/installPrerequisiteFetch.js +73 -0
  148. package/esm/util/lazyAfterAttach.d.ts +13 -0
  149. package/esm/util/lazyAfterAttach.js +31 -0
  150. package/esm/util/legendCandidates.d.ts +50 -0
  151. package/esm/util/legendCandidates.js +87 -0
  152. package/esm/util/mstUtils.d.ts +12 -1
  153. package/esm/util/mstUtils.js +20 -2
  154. package/esm/util/openFeatureWidget.d.ts +5 -0
  155. package/esm/util/openFeatureWidget.js +1 -0
  156. package/esm/util/openViews.d.ts +16 -0
  157. package/esm/util/openViews.js +22 -0
  158. package/esm/util/parentWalk.d.ts +1 -1
  159. package/esm/util/parentWalk.js +1 -1
  160. package/esm/util/pluginStore.d.ts +1 -0
  161. package/esm/util/pluginStore.js +8 -1
  162. package/esm/util/range.d.ts +13 -9
  163. package/esm/util/range.js +17 -8
  164. package/esm/util/renderToStaticMarkup.js +10 -0
  165. package/esm/util/rxjs.d.ts +16 -0
  166. package/esm/util/rxjs.js +49 -0
  167. package/esm/util/scheduleDetachedDestroy.d.ts +18 -0
  168. package/esm/util/scheduleDetachedDestroy.js +24 -0
  169. package/esm/util/scrollLatch.d.ts +1 -0
  170. package/esm/util/scrollLatch.js +8 -0
  171. package/esm/util/stopToken.d.ts +6 -5
  172. package/esm/util/tabix.d.ts +10 -4
  173. package/esm/util/tabix.js +11 -5
  174. package/esm/util/trackConfigDelta.d.ts +6 -6
  175. package/esm/util/trackConfigDelta.js +3 -3
  176. package/esm/util/tracks.d.ts +48 -0
  177. package/esm/util/tracks.js +192 -66
  178. package/esm/util/types/index.d.ts +58 -10
  179. package/esm/util/types/index.js +3 -0
  180. package/esm/util/unknownSnapshotKeys.d.ts +36 -0
  181. package/esm/util/unknownSnapshotKeys.js +69 -0
  182. package/esm/util/usePanelVirtualScroll.d.ts +6 -2
  183. package/esm/util/usePanelVirtualScroll.js +6 -2
  184. package/esm/util/useRowVirtualScroll.d.ts +1 -1
  185. package/esm/util/useRowVirtualScroll.js +1 -1
  186. package/esm/util/useVirtualScrollWheel.js +11 -1
  187. package/esm/util/viewStatus.d.ts +23 -0
  188. package/esm/util/viewStatus.js +17 -0
  189. package/esm/util/wheelZoom.d.ts +3 -1
  190. package/esm/util/wheelZoom.js +39 -14
  191. package/esm/util/whenViewSettled.d.ts +17 -4
  192. package/esm/util/whenViewSettled.js +19 -6
  193. package/esm/util/withLaunchInput.d.ts +168 -0
  194. package/esm/util/withLaunchInput.js +273 -0
  195. package/package.json +19 -11
  196. package/esm/ui/promotableMenuItems.d.ts +0 -19
  197. package/esm/ui/promotableMenuItems.js +0 -89
  198. package/esm/util/applyInitSettings.d.ts +0 -79
  199. package/esm/util/applyInitSettings.js +0 -91
@@ -66,7 +66,7 @@ export interface BaseMenuItem {
66
66
  */
67
67
  endAdornment?: React.ReactNode;
68
68
  /**
69
- * #menuField the "apply this to all open tracks of this type" pin; set it with a promotable builder
69
+ * #menuField the "apply this to all open tracks of this type" pin; set it through a row builder's `pin` option
70
70
  *
71
71
  * The trailing "default for all tracks of this type" pin, as a **description**
72
72
  * rather than an element — the renderer builds `PinAdornment` from
@@ -76,8 +76,8 @@ export interface BaseMenuItem {
76
76
  * into every host's first paint. It did, until 2026-08-05; see
77
77
  * reference/EAGER_BUNDLE.md.
78
78
  *
79
- * Set it through `promotableToggleItem` / `promotableRadioItems` (or
80
- * `promotableRadioItem` for a lone row), not by hand.
79
+ * Set it through the `pin` option of `checkboxItem` / `toggleItem` /
80
+ * `radioItem` / `radioItems`, not by hand.
81
81
  *
82
82
  * A `type: 'custom'` row (`makePromotableSizeMenu`) draws its own pin inside
83
83
  * its rendered content and still sets this — the declaration is what lets a
@@ -127,11 +127,20 @@ export interface RadioMenuItem extends BaseMenuItem {
127
127
  checked: boolean;
128
128
  onClick: MenuItemClickHandler;
129
129
  }
130
- /** #menuItem subMenu | nests another `MenuItem[]`, to any depth */
130
+ /**
131
+ * #menuItem subMenu | nests another `MenuItem[]`, or a function building one, to any depth
132
+ *
133
+ * The function form is called when the submenu opens (or a walker asks for its
134
+ * rows), not when the parent menu is built — for a submenu whose rows cost a
135
+ * scan of the display's data to name. Read the field through `resolveSubMenu`
136
+ * rather than by hand, so the two forms stay one thing to the renderer, the
137
+ * pin-coverage walk and every test helper that flattens a menu.
138
+ */
131
139
  export interface SubMenuItem extends BaseMenuItem {
132
140
  type?: 'subMenu';
133
- subMenu: MenuItem[];
141
+ subMenu: MenuItem[] | (() => MenuItem[]);
134
142
  }
143
+ export declare function resolveSubMenu(item: SubMenuItem): MenuItem[];
135
144
  /**
136
145
  * #menuItem custom | renders arbitrary React content inline, e.g. a slider
137
146
  *
@@ -1,3 +1,6 @@
1
+ export function resolveSubMenu(item) {
2
+ return typeof item.subMenu === 'function' ? item.subMenu() : item.subMenu;
3
+ }
1
4
  // #endregion
2
5
  /**
3
6
  * Whether clicking a row leaves the menu up — the rule `CascadingMenu` applies,
@@ -40,8 +40,9 @@ export interface ThemeModeSession {
40
40
  * hook and the provider in one.
41
41
  *
42
42
  * How the host knows its own mode is the host's business — an attribute on
43
- * `<html>`, a `prefers-color-scheme` media query, a design-system context —
44
- * and deliberately not this hook's.
43
+ * `<html>`, a design-system context, a toggle in its own state. Pass no mode
44
+ * and JBrowse follows `prefers-color-scheme` instead, tracking OS changes; a
45
+ * host whose mode is only ever the OS preference has nothing to write.
45
46
  *
46
47
  * **Both halves are load-bearing, which is why the pairing is published as a
47
48
  * component.** The palette is what *React* draws with; the config `theme` slot
@@ -55,7 +56,7 @@ export interface ThemeModeSession {
55
56
  * the previous palette. That is a frame on a canvas that is about to be
56
57
  * redrawn anyway; it is not somewhere to add a suspense boundary.
57
58
  */
58
- export declare function useSessionPalette(session: ThemeModeSession, mode: 'light' | 'dark'): JBrowsePalette;
59
+ export declare function useSessionPalette(session: ThemeModeSession, mode?: 'light' | 'dark'): JBrowsePalette;
59
60
  /**
60
61
  * #api
61
62
  * Make JBrowse follow the host's light/dark state — the whole of it, in one
@@ -67,6 +68,12 @@ export declare function useSessionPalette(session: ThemeModeSession, mode: 'ligh
67
68
  * </SessionPaletteProvider>
68
69
  * ```
69
70
  *
71
+ * `mode` is optional. Left out, JBrowse follows `prefers-color-scheme` and
72
+ * re-themes when the OS preference changes, through the same session write an
73
+ * explicit mode takes — so a host whose dark mode *is* the OS preference mounts
74
+ * this with a session and nothing else. Pass a mode as soon as the host has a
75
+ * toggle of its own, since the media query cannot see it.
76
+ *
70
77
  * A component rather than a documented pair of calls because the pair has a
71
78
  * half that can be left out with nothing to show for it. `PaletteProvider` is
72
79
  * the name a host reaches for, and it colors the React side alone; the session
@@ -80,6 +87,6 @@ export declare function useSessionPalette(session: ThemeModeSession, mode: 'ligh
80
87
  */
81
88
  export declare function SessionPaletteProvider({ session, mode, children, }: {
82
89
  session: ThemeModeSession;
83
- mode: 'light' | 'dark';
90
+ mode?: 'light' | 'dark';
84
91
  children: ReactNode;
85
92
  }): import("react").JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createContext, use, useEffect, useMemo } from 'react';
2
+ import { createContext, use, useEffect, useMemo, useSyncExternalStore, } from 'react';
3
3
  import { defaultStyleTheme } from './styleTheme.js';
4
4
  /**
5
5
  * How a React component asks for JBrowse's design tokens.
@@ -47,6 +47,27 @@ export function useStyleTheme() {
47
47
  export function usePalette() {
48
48
  return useStyleTheme().palette;
49
49
  }
50
+ function darkSchemeQuery() {
51
+ return typeof window.matchMedia === 'function'
52
+ ? window.matchMedia('(prefers-color-scheme: dark)')
53
+ : undefined;
54
+ }
55
+ function subscribeToColorScheme(onChange) {
56
+ const media = darkSchemeQuery();
57
+ media?.addEventListener('change', onChange);
58
+ return () => {
59
+ media?.removeEventListener('change', onChange);
60
+ };
61
+ }
62
+ function readColorScheme() {
63
+ return darkSchemeQuery()?.matches ? 'dark' : 'light';
64
+ }
65
+ const alwaysLight = () => 'light';
66
+ const subscribeToNothing = () => () => { };
67
+ function useResolvedMode(mode) {
68
+ const systemMode = useSyncExternalStore(mode === undefined ? subscribeToColorScheme : subscribeToNothing, mode === undefined ? readColorScheme : alwaysLight, alwaysLight);
69
+ return mode === undefined ? systemMode : mode;
70
+ }
50
71
  /**
51
72
  * Point a session at light or dark and get back the palette it resolves to,
52
73
  * for a host that wants the palette itself — to read a color out of, or to
@@ -55,8 +76,9 @@ export function usePalette() {
55
76
  * hook and the provider in one.
56
77
  *
57
78
  * How the host knows its own mode is the host's business — an attribute on
58
- * `<html>`, a `prefers-color-scheme` media query, a design-system context —
59
- * and deliberately not this hook's.
79
+ * `<html>`, a design-system context, a toggle in its own state. Pass no mode
80
+ * and JBrowse follows `prefers-color-scheme` instead, tracking OS changes; a
81
+ * host whose mode is only ever the OS preference has nothing to write.
60
82
  *
61
83
  * **Both halves are load-bearing, which is why the pairing is published as a
62
84
  * component.** The palette is what *React* draws with; the config `theme` slot
@@ -71,9 +93,10 @@ export function usePalette() {
71
93
  * redrawn anyway; it is not somewhere to add a suspense boundary.
72
94
  */
73
95
  export function useSessionPalette(session, mode) {
96
+ const resolved = useResolvedMode(mode);
74
97
  useEffect(() => {
75
- session.setThemeMode(mode);
76
- }, [session, mode]);
98
+ session.setThemeMode(resolved);
99
+ }, [session, resolved]);
77
100
  return session.palette;
78
101
  }
79
102
  /**
@@ -87,6 +110,12 @@ export function useSessionPalette(session, mode) {
87
110
  * </SessionPaletteProvider>
88
111
  * ```
89
112
  *
113
+ * `mode` is optional. Left out, JBrowse follows `prefers-color-scheme` and
114
+ * re-themes when the OS preference changes, through the same session write an
115
+ * explicit mode takes — so a host whose dark mode *is* the OS preference mounts
116
+ * this with a session and nothing else. Pass a mode as soon as the host has a
117
+ * toggle of its own, since the media query cannot see it.
118
+ *
90
119
  * A component rather than a documented pair of calls because the pair has a
91
120
  * half that can be left out with nothing to show for it. `PaletteProvider` is
92
121
  * the name a host reaches for, and it colors the React side alone; the session
@@ -18,62 +18,50 @@ const useStyles = makeStyles()(theme => ({
18
18
  display: 'inline-flex',
19
19
  },
20
20
  }));
21
- // How the pin names what it acts on. Two shapes, decided by the on-value:
21
+ // A toggle pin sits on a checkbox row: the copy names the state the click
22
+ // applies, and the fill mirrors the checkbox. A value pin's on-value IS what
23
+ // the label says — a radio option ("Compact"), a size row whose caller folds
24
+ // the value into the label ("Line width (2px)") — and there the fill means the
25
+ // value is the promoted default, so a click clears it.
22
26
  //
23
- // - **A boolean on-value carries a state**, and the row's label names the
24
- // setting rather than a value ("Show legend", "Show soft clipping"). A pin on
25
- // an unchecked such row applies the setting *off*, so the value-shaped copy
26
- // below stated the opposite of what the click does — and then, once filled,
27
- // claimed the setting was on by default when it had just been turned off.
28
- // - **Everything else IS what the label says**: a radio option ("Compact"), a
29
- // size row whose caller folds the value into the label ("Line width (2px)").
30
- //
31
- // One `typeof` rather than a flag on the row, because the two forms of
32
- // `makePin` are exactly this distinction: a symmetric pin over a `maybeBoolean`
33
- // slot is the only way a pin's value and its label can disagree.
34
- function pinPredicate(onValue) {
35
- return typeof onValue === 'boolean'
36
- ? `${onValue ? 'on' : 'off'} by default`
37
- : 'the default';
38
- }
39
- // The click, which is not the state the pin draws: an outline pin applies the
40
- // value to the open tracks, a filled one clears the default it stands for.
41
- function pinCopy(label, onValue, isDefault) {
42
- return isDefault
27
+ // The aria-label carries "of this type" wherever the tooltip does: it used to
28
+ // stop at "for all open tracks", stating a wider blast radius than the control
29
+ // has.
30
+ function pinCopy(label, control) {
31
+ const { kind, active } = control;
32
+ return kind === 'toggle'
43
33
  ? {
44
- title: `${label} is ${pinPredicate(onValue)} for all tracks of this type (click to clear)`,
45
- ariaLabel: `clear the default for ${label}`,
34
+ title: `Turn ${label} ${active ? 'off' : 'on'} for all open tracks of this type`,
35
+ ariaLabel: `turn ${label} ${active ? 'off' : 'on'} for all open tracks of this type`,
46
36
  }
47
- : typeof onValue === 'boolean'
37
+ : active
48
38
  ? {
49
- title: `Turn ${label} ${onValue ? 'on' : 'off'} for all open tracks of this type`,
50
- ariaLabel: `turn ${label} ${onValue ? 'on' : 'off'} for all open tracks`,
39
+ title: `${label} is the default for all tracks of this type (click to clear)`,
40
+ ariaLabel: `clear the default for ${label} for all tracks of this type`,
51
41
  }
52
42
  : {
53
43
  title: `Apply ${label} to all open tracks of this type`,
54
- ariaLabel: `apply ${label} to all open tracks`,
44
+ ariaLabel: `apply ${label} to all open tracks of this type`,
55
45
  };
56
46
  }
57
- // Trailing pin for a promotable setting, rendered as a menu item's
58
- // `endAdornment` beside the value check. A ToggleButton (native button a11y + a
59
- // clear selected tint) with a pin — distinct from the value checkbox.
47
+ // Trailing pin for a promotable setting, drawn beside the value check from the
48
+ // row's `pin` declaration (`menuItemAdornment` builds this; a row never
49
+ // constructs it, which is what keeps MUI out of the eager menu-builder graph). A
50
+ // ToggleButton (native button a11y + a clear selected tint) with a pin —
51
+ // distinct from the value checkbox.
60
52
  //
61
- // **The click and the state are two different things.** One click writes the
62
- // value into every open track of this display type and raises a snackbar
63
- // offering to keep it as the display type's default; the filled pin means that
64
- // default is in place, so a click on a filled pin clears it and touches no
65
- // track. A default therefore takes two deliberate clicks, which is what it costs
66
- // to govern every track of the type opened later (ADR-048). Always shown so the
67
- // capability is discoverable. stopPropagation keeps the click off the row value
68
- // / menu dismissal. "of this type" because a promoted default is scoped to the
69
- // display type (e.g. every LinearAlignmentsDisplay), not literally all tracks.
53
+ // One click writes the value into every open track of this display type and
54
+ // raises a snackbar offering to keep it as the display type's default, so a
55
+ // default takes two deliberate clicks (ADR-048). Always shown so the capability
56
+ // is discoverable. stopPropagation keeps the click off the row value / menu
57
+ // dismissal. "of this type" because a promoted default is scoped to the display
58
+ // type (e.g. every LinearAlignmentsDisplay), not literally all tracks.
70
59
  export function PinAdornment({ pin, disabled, }) {
71
60
  const { classes } = useStyles();
72
61
  const { label, control } = pin;
73
- const isDefault = control.active;
74
- const { title, ariaLabel } = pinCopy(label, control.onValue, isDefault);
75
- return (_jsx(Tooltip, { title: title, children: _jsx("span", { className: classes.wrapper, children: _jsx(ToggleButton, { className: classes.button, value: "default", disabled: disabled, selected: isDefault, color: "primary", size: "small", "aria-label": ariaLabel, onChange: e => {
62
+ const { title, ariaLabel } = pinCopy(label, control);
63
+ return (_jsx(Tooltip, { title: title, children: _jsx("span", { className: classes.wrapper, children: _jsx(ToggleButton, { className: classes.button, value: "default", disabled: disabled, selected: control.active, color: "primary", size: "small", "aria-label": ariaLabel, onChange: e => {
76
64
  e.stopPropagation();
77
65
  control.toggle();
78
- }, children: isDefault ? (_jsx(PushPinIcon, { fontSize: "small" })) : (_jsx(PushPinOutlinedIcon, { fontSize: "small" })) }) }) }));
66
+ }, children: control.active ? (_jsx(PushPinIcon, { fontSize: "small" })) : (_jsx(PushPinOutlinedIcon, { fontSize: "small" })) }) }) }));
79
67
  }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The chrome a display that scrolls its content virtually mounts over its
3
+ * viewport: `ScrollEdgeShadow` saying content is hidden past an edge, and
4
+ * `VerticalScrollbar` to reach it. Both read the same three numbers, so a
5
+ * display hands them over once here. Renders nothing when the content fits.
6
+ */
7
+ export default function ScrollChrome({ scrollTop, setScrollTop, viewportHeight, contentHeight, controlsId, top, }: {
8
+ scrollTop: number;
9
+ setScrollTop: (n: number) => void;
10
+ viewportHeight: number;
11
+ contentHeight: number;
12
+ /** `id` of the scrolled viewport element, for `aria-controls`. */
13
+ controlsId: string;
14
+ /** Viewport offset from the top, for a display with a sticky band above it. */
15
+ top?: number;
16
+ }): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import ScrollEdgeShadow from './ScrollEdgeShadow.js';
3
+ import VerticalScrollbar from './VerticalScrollbar.js';
4
+ /**
5
+ * The chrome a display that scrolls its content virtually mounts over its
6
+ * viewport: `ScrollEdgeShadow` saying content is hidden past an edge, and
7
+ * `VerticalScrollbar` to reach it. Both read the same three numbers, so a
8
+ * display hands them over once here. Renders nothing when the content fits.
9
+ */
10
+ export default function ScrollChrome({ scrollTop, setScrollTop, viewportHeight, contentHeight, controlsId, top = 0, }) {
11
+ return (_jsxs(_Fragment, { children: [_jsx(ScrollEdgeShadow, { scrollTop: scrollTop, viewportHeight: viewportHeight, contentHeight: contentHeight, top: top }), _jsx(VerticalScrollbar, { scrollTop: scrollTop, setScrollTop: setScrollTop, viewportHeight: viewportHeight, contentHeight: contentHeight, controlsId: controlsId, top: top })] }));
12
+ }
@@ -27,9 +27,10 @@ export interface ScrollZoomToggleModel {
27
27
  * of this button pulse with it, which is the preference being session-wide made
28
28
  * visible.
29
29
  *
30
- * `iconOnly` is for a header where this sits inside a run of icon buttons (the
31
- * comparative views), where a single labelled button reads as a mistake rather
32
- * than as emphasis. The tooltip carries the same words either way.
30
+ * `iconOnly` is for a header with no room for the words, or one where this sits
31
+ * inside a run of icon buttons with nothing else labelled — a single labelled
32
+ * button there reads as a mistake rather than as emphasis. The tooltip carries
33
+ * the same words either way.
33
34
  */
34
35
  declare const ScrollZoomToggle: ({ model, iconOnly, }: {
35
36
  model: ScrollZoomToggleModel;
@@ -67,9 +67,10 @@ const useStyles = makeStyles()(theme => {
67
67
  * of this button pulse with it, which is the preference being session-wide made
68
68
  * visible.
69
69
  *
70
- * `iconOnly` is for a header where this sits inside a run of icon buttons (the
71
- * comparative views), where a single labelled button reads as a mistake rather
72
- * than as emphasis. The tooltip carries the same words either way.
70
+ * `iconOnly` is for a header with no room for the words, or one where this sits
71
+ * inside a run of icon buttons with nothing else labelled — a single labelled
72
+ * button there reads as a mistake rather than as emphasis. The tooltip carries
73
+ * the same words either way.
73
74
  */
74
75
  const ScrollZoomToggle = observer(function ScrollZoomToggle({ model, iconOnly, }) {
75
76
  const { classes } = useStyles();
@@ -33,7 +33,7 @@ export const SizeSliderRow = observer(function SizeSliderRow({ title, getValue,
33
33
  const slug = title.toLowerCase().replaceAll(' ', '-');
34
34
  return (_jsxs("div", { className: classes.root, children: [_jsxs("div", { className: classes.header, children: [_jsxs(Typography, { variant: "caption", color: "textSecondary", className: classes.label, children: [title, ": ", format(value)] }), _jsx(ResetToDefaultButton, { disabled: isDefault, onClick: () => {
35
35
  onReset();
36
- } }), pin ? (_jsx(PinAdornment, { pin: { control: pin, label: `${title} (${format(value)})` } })) : null] }), _jsx(SingleSlider, { value: toSlider(value), min: toSlider(min), max: toSlider(max), step: sliderStep ?? step, size: "small", "aria-label": title.toLowerCase(), "data-testid": `${slug}-slider`, valueLabelDisplay: "auto", valueLabelFormat: (v) => format(fromSlider(v)), sx: { py: 0.5, display: 'block' }, onChange: v => {
36
+ } }), pin ? (_jsx(PinAdornment, { pin: { control: pin, label: `${title} (${format(modelValue)})` } })) : null] }), _jsx(SingleSlider, { value: toSlider(value), min: toSlider(min), max: toSlider(max), step: sliderStep ?? step, size: "small", "aria-label": title.toLowerCase(), "data-testid": `${slug}-slider`, valueLabelDisplay: "auto", valueLabelFormat: (v) => format(fromSlider(v)), sx: { py: 0.5, display: 'block' }, onChange: v => {
37
37
  const n = fromSlider(v);
38
38
  if (commitOnRelease) {
39
39
  setDragValue(n);
package/esm/ui/index.d.ts CHANGED
@@ -48,6 +48,7 @@ export { default as StatusProgressBar } from './StatusProgressBar.tsx';
48
48
  export { default as Menu } from './Menu.tsx';
49
49
  export { default as PrerenderedCanvas } from './PrerenderedCanvas.tsx';
50
50
  export { default as ResizeHandle } from './ResizeHandle.tsx';
51
+ export { default as ScrollChrome } from './ScrollChrome.tsx';
51
52
  export { default as ScrollEdgeShadow } from './ScrollEdgeShadow.tsx';
52
53
  export { default as VerticalScrollbar } from './VerticalScrollbar.tsx';
53
54
  export { default as SubmitDialog } from './SubmitDialog.tsx';
@@ -70,7 +71,7 @@ export type { SlotExtensionPointName, SlotProps, WrapperProps, } from './wrapCom
70
71
  export { matchesTrackSelector } from './extensionSelectors.ts';
71
72
  export type { TrackSelector } from './extensionSelectors.ts';
72
73
  export type { BaseMenuItem, CheckboxMenuItem, ClickableMenuItem, CustomMenuItem, MenuDivider, MenuItem, MenuItemClickHandler, MenuItemsGetter, MenuSubHeader, NormalMenuItem, RadioMenuItem, SubMenuItem, } from './MenuTypes.ts';
73
- export { staysOpenOnClick } from './MenuTypes.ts';
74
+ export { resolveSubMenu, staysOpenOnClick } from './MenuTypes.ts';
74
75
  export { LAUNCH_LABEL, pushIntoSubMenu, pushLaunchViewMenuItem, } from './launchViewMenu.ts';
75
76
  export { launchTargetsMenuItem } from './launchTargetsMenuItem.ts';
76
77
  export { default as Crosshairs } from './Crosshairs.tsx';
@@ -78,8 +79,7 @@ export { hoverBoxStyle } from './hoverBoxStyle.ts';
78
79
  export { useMouseState, useMouseTracking } from './useMouseTracking.ts';
79
80
  export type { MouseState, MouseTracker } from './useMouseTracking.ts';
80
81
  export { PinAdornment } from './PinAdornment.tsx';
81
- export { promotableRadioItem, promotableRadioItems, promotableToggleItem, } from './promotableMenuItems.ts';
82
- export { displayTypesWithPromotableSlots, promotableSlotsWithoutPin, } from './promotablePinCoverage.ts';
82
+ export { displayTypesWithPromotableSlots, misKindedPins, promotableSlotsWithoutPin, } from './promotablePinCoverage.ts';
83
83
  export declare const VIEW_HEADER_HEIGHT = 28;
84
84
  export { GRADIENT_LEGEND_HEIGHT, GRADIENT_LEGEND_SVG_AREA_WIDTH, GRADIENT_LEGEND_WIDTH, default as SvgGradientLegend, } from './SvgGradientLegend.tsx';
85
85
  export type { GradientLabel, GradientStop } from './SvgGradientLegend.tsx';
package/esm/ui/index.js CHANGED
@@ -44,6 +44,7 @@ export { default as StatusProgressBar } from './StatusProgressBar.js';
44
44
  export { default as Menu } from './Menu.js';
45
45
  export { default as PrerenderedCanvas } from './PrerenderedCanvas.js';
46
46
  export { default as ResizeHandle } from './ResizeHandle.js';
47
+ export { default as ScrollChrome } from './ScrollChrome.js';
47
48
  export { default as ScrollEdgeShadow } from './ScrollEdgeShadow.js';
48
49
  export { default as VerticalScrollbar } from './VerticalScrollbar.js';
49
50
  export { default as SubmitDialog } from './SubmitDialog.js';
@@ -65,15 +66,14 @@ export { default as PluggableElements } from './PluggableElements.js';
65
66
  export { addExtensionElement } from './addExtensionElement.js';
66
67
  export { wrapComponent } from './wrapComponent.js';
67
68
  export { matchesTrackSelector } from './extensionSelectors.js';
68
- export { staysOpenOnClick } from './MenuTypes.js';
69
+ export { resolveSubMenu, staysOpenOnClick } from './MenuTypes.js';
69
70
  export { LAUNCH_LABEL, pushIntoSubMenu, pushLaunchViewMenuItem, } from './launchViewMenu.js';
70
71
  export { launchTargetsMenuItem } from './launchTargetsMenuItem.js';
71
72
  export { default as Crosshairs } from './Crosshairs.js';
72
73
  export { hoverBoxStyle } from './hoverBoxStyle.js';
73
74
  export { useMouseState, useMouseTracking } from './useMouseTracking.js';
74
75
  export { PinAdornment } from './PinAdornment.js';
75
- export { promotableRadioItem, promotableRadioItems, promotableToggleItem, } from './promotableMenuItems.js';
76
- // Not on the React-free `menuItems.ts` entry beside the two builders above: this
76
+ // Not on the React-free `menuItems.ts` entry beside the row builders: this
77
77
  // reads a config's slot table, so it pulls `configuration/promotableSlots.ts`
78
78
  // in, and that entry exists precisely to stay out of every plugin's eager graph.
79
79
  //
@@ -81,7 +81,7 @@ export { promotableRadioItem, promotableRadioItems, promotableToggleItem, } from
81
81
  // caller has is "which promotable slots does this menu miss", and answering the
82
82
  // half of it that lists what a menu *does* offer needs the schema's slot table
83
83
  // to mean anything.
84
- export { displayTypesWithPromotableSlots, promotableSlotsWithoutPin, } from './promotablePinCoverage.js';
84
+ export { displayTypesWithPromotableSlots, misKindedPins, promotableSlotsWithoutPin, } from './promotablePinCoverage.js';
85
85
  export const VIEW_HEADER_HEIGHT = 28;
86
86
  export { GRADIENT_LEGEND_HEIGHT, GRADIENT_LEGEND_SVG_AREA_WIDTH, GRADIENT_LEGEND_WIDTH, default as SvgGradientLegend, } from './SvgGradientLegend.js';
87
87
  export { LEGEND_ROW_HEIGHT, LEGEND_SWATCH, default as SvgColorLegend, } from './SvgColorLegend.js';
@@ -10,7 +10,13 @@ export const LAUNCH_LABEL = 'Launch';
10
10
  export function pushIntoSubMenu(items, label, item) {
11
11
  const existing = items.find((i) => i.type === 'subMenu' && i.label === label);
12
12
  if (existing) {
13
- existing.subMenu.push(item);
13
+ const { subMenu } = existing;
14
+ if (typeof subMenu === 'function') {
15
+ existing.subMenu = () => [...subMenu(), item];
16
+ }
17
+ else {
18
+ subMenu.push(item);
19
+ }
14
20
  }
15
21
  else {
16
22
  items.push({ label, type: 'subMenu', subMenu: [item] });
@@ -1,5 +1,5 @@
1
- import type { Pin } from '../configuration/promotablePin.ts';
2
1
  import type { MenuItem } from './MenuTypes.ts';
2
+ import type { CheckboxRowOptions } from './toggleMenuItems.ts';
3
3
  /**
4
4
  * The "Show legend" checkbox, which seven displays build by hand — Hi-C, LD,
5
5
  * alignments, LGVSynteny, multi-wiggle, multi-row features, both multi-sample
@@ -14,25 +14,19 @@ import type { MenuItem } from './MenuTypes.ts';
14
14
  * values legitimately differ (a Hi-C color scale is off by default, a variant
15
15
  * genotype key on), and their descriptions describe genuinely different legends.
16
16
  * What they now share is being *promotable* — pass `opts.pin` and the row gains
17
- * the pin that makes the current state this display type's session-wide
18
- * default. Every display whose legend is backed by a config slot passes one,
19
- * and gets it from `LegendMixin`'s `showLegendDisplayTypeDefault` rather than
20
- * calling `makePin` itself: the slot is the per-display half, the accessors
21
- * over it are not.
17
+ * the pin that toggles the legend on every open track of this display type,
18
+ * offering the new state as the display-type default in its snackbar. Every
19
+ * display whose legend is backed by a config slot passes one, and gets it from
20
+ * `LegendMixin`'s `showLegendDisplayTypeDefault` rather than calling
21
+ * `makeTogglePin` itself: the slot is the per-display half, the accessors over
22
+ * it are not.
22
23
  *
23
24
  * `pin` is optional because two callers have no slot to promote: the Manhattan
24
25
  * plot's LD legend and `LinearBasicDisplay`'s color key are a volatile and a
25
26
  * per-legend `dismissed` flag respectively, neither of which is config at all.
26
- * They get the plain row, which is what `checkboxItem` builds either way — the
27
- * promotable form is that same row plus the pin, per `promotableToggleItem`.
28
27
  *
29
- * Deliberately not used by `synteny-core`'s "Show color legend", which sits
30
- * inside a "Color by..." submenu where the bare word would not say which legend.
28
+ * `synteny-core`'s color-by legend has no toggle at all: it comes up with the
29
+ * modes that have a key and is dismissed from its own close button.
31
30
  */
32
31
  /** #menuBuilder showLegendCheckboxItem | the shared "Show legend" checkbox */
33
- export declare function showLegendCheckboxItem(checked: boolean, onToggle: () => void, opts?: {
34
- helpText?: string;
35
- disabled?: boolean;
36
- disabledHelpText?: string;
37
- pin?: Pin;
38
- }): MenuItem;
32
+ export declare function showLegendCheckboxItem(checked: boolean, onToggle: () => void, opts?: CheckboxRowOptions): MenuItem;
@@ -1,4 +1,3 @@
1
- import { promotableToggleItem } from './promotableMenuItems.js';
2
1
  import { checkboxItem } from './toggleMenuItems.js';
3
2
  /**
4
3
  * The "Show legend" checkbox, which seven displays build by hand — Hi-C, LD,
@@ -14,31 +13,21 @@ import { checkboxItem } from './toggleMenuItems.js';
14
13
  * values legitimately differ (a Hi-C color scale is off by default, a variant
15
14
  * genotype key on), and their descriptions describe genuinely different legends.
16
15
  * What they now share is being *promotable* — pass `opts.pin` and the row gains
17
- * the pin that makes the current state this display type's session-wide
18
- * default. Every display whose legend is backed by a config slot passes one,
19
- * and gets it from `LegendMixin`'s `showLegendDisplayTypeDefault` rather than
20
- * calling `makePin` itself: the slot is the per-display half, the accessors
21
- * over it are not.
16
+ * the pin that toggles the legend on every open track of this display type,
17
+ * offering the new state as the display-type default in its snackbar. Every
18
+ * display whose legend is backed by a config slot passes one, and gets it from
19
+ * `LegendMixin`'s `showLegendDisplayTypeDefault` rather than calling
20
+ * `makeTogglePin` itself: the slot is the per-display half, the accessors over
21
+ * it are not.
22
22
  *
23
23
  * `pin` is optional because two callers have no slot to promote: the Manhattan
24
24
  * plot's LD legend and `LinearBasicDisplay`'s color key are a volatile and a
25
25
  * per-legend `dismissed` flag respectively, neither of which is config at all.
26
- * They get the plain row, which is what `checkboxItem` builds either way — the
27
- * promotable form is that same row plus the pin, per `promotableToggleItem`.
28
26
  *
29
- * Deliberately not used by `synteny-core`'s "Show color legend", which sits
30
- * inside a "Color by..." submenu where the bare word would not say which legend.
27
+ * `synteny-core`'s color-by legend has no toggle at all: it comes up with the
28
+ * modes that have a key and is dismissed from its own close button.
31
29
  */
32
30
  /** #menuBuilder showLegendCheckboxItem | the shared "Show legend" checkbox */
33
31
  export function showLegendCheckboxItem(checked, onToggle, opts) {
34
- const { pin, ...rest } = opts ?? {};
35
- return pin
36
- ? promotableToggleItem({
37
- label: 'Show legend',
38
- checked,
39
- onToggle,
40
- pin,
41
- ...rest,
42
- })
43
- : checkboxItem('Show legend', checked, onToggle, rest);
32
+ return checkboxItem('Show legend', checked, onToggle, opts);
44
33
  }
@@ -51,7 +51,7 @@ export function makeSizeSubMenu(opts) {
51
51
  // The same row over a **promotable** slot, which derives both halves the plain
52
52
  // form takes by hand — the reset button's enablement (`isSlotCustomized`) and
53
53
  // the "default for all tracks of this type" pin — from the one slot name. A
54
- // slider has no fixed on-value, so the pin promotes whatever the track is
54
+ // slider has no fixed on-value, so the pin carries whatever the track is
55
55
  // currently showing.
56
56
  //
57
57
  // Naming the slot once is the point: the call sites used to spell it twice, in
@@ -6,9 +6,8 @@ import type { MenuItem } from './MenuTypes.ts';
6
6
  * the builder already made — the escape hatch, for content nothing else can
7
7
  * describe. `pin` is a *description* of the "default for all tracks of
8
8
  * this type" pin, and turning it into `PinAdornment` here is the whole
9
- * point: the builders that set it (`promotableToggleItem`,
10
- * `promotableRadioItem`) are called from state models and menu modules, which
11
- * are eager, so a module that constructs the element instead puts MUI's
9
+ * point: the row builders that set it (`toggleMenuItems.ts`) are called from
10
+ * state models and menu modules, which are eager, so a module that constructs the element instead puts MUI's
12
11
  * `ToggleButton`, `Tooltip` and two icons into every host's first paint.
13
12
  *
14
13
  * Live in one place rather than at each of the four render sites, because the
@@ -7,9 +7,8 @@ import { PinAdornment } from './PinAdornment.js';
7
7
  * the builder already made — the escape hatch, for content nothing else can
8
8
  * describe. `pin` is a *description* of the "default for all tracks of
9
9
  * this type" pin, and turning it into `PinAdornment` here is the whole
10
- * point: the builders that set it (`promotableToggleItem`,
11
- * `promotableRadioItem`) are called from state models and menu modules, which
12
- * are eager, so a module that constructs the element instead puts MUI's
10
+ * point: the row builders that set it (`toggleMenuItems.ts`) are called from
11
+ * state models and menu modules, which are eager, so a module that constructs the element instead puts MUI's
13
12
  * `ToggleButton`, `Tooltip` and two icons into every host's first paint.
14
13
  *
15
14
  * Live in one place rather than at each of the four render sites, because the
@@ -22,7 +22,6 @@ export { checkboxItem, radioItem, radioItems, toggleItem, withSubHeader, } from
22
22
  export { withHint } from './menuLabels.ts';
23
23
  export { makeRadioSubMenu } from './radioSubMenu.ts';
24
24
  export { showLegendCheckboxItem } from './legendMenuItem.ts';
25
- export { promotableRadioItem, promotableRadioItems, promotableToggleItem, } from './promotableMenuItems.ts';
26
- export type { RadioOption, SettingRowOptions } from './toggleMenuItems.ts';
27
- export { staysOpenOnClick } from './MenuTypes.ts';
25
+ export type { CheckboxRowOptions, RadioOption, RadioRowOptions, SettingRowOptions, } from './toggleMenuItems.ts';
26
+ export { resolveSubMenu, staysOpenOnClick } from './MenuTypes.ts';
28
27
  export type { BaseMenuItem, CheckboxMenuItem, ClickableMenuItem, CustomMenuItem, MenuDivider, MenuItem, MenuItemClickHandler, MenuItemPin, MenuItemsGetter, MenuSubHeader, NormalMenuItem, RadioMenuItem, SubMenuItem, } from './MenuTypes.ts';
@@ -22,5 +22,4 @@ export { checkboxItem, radioItem, radioItems, toggleItem, withSubHeader, } from
22
22
  export { withHint } from './menuLabels.js';
23
23
  export { makeRadioSubMenu } from './radioSubMenu.js';
24
24
  export { showLegendCheckboxItem } from './legendMenuItem.js';
25
- export { promotableRadioItem, promotableRadioItems, promotableToggleItem, } from './promotableMenuItems.js';
26
- export { staysOpenOnClick } from './MenuTypes.js';
25
+ export { resolveSubMenu, staysOpenOnClick } from './MenuTypes.js';
@@ -117,33 +117,33 @@ export interface SemanticColors {
117
117
  export declare const colorFwdStrand = "#EC8B8B";
118
118
  /** #color alignments-strand | Reverse strand | Read maps to the reverse strand */
119
119
  export declare const colorRevStrand = "#8F8FD8";
120
- /** #color alignments-pair-orientation | LR (→ ←, normal proper pair) | Concordant */
120
+ /** #color alignments-pair-orientation | LR (→ ←) | Normal proper pair */
121
121
  export declare const colorPairLR = "#d3d3d3";
122
122
  export declare const colorPairLRDark = "#8a8a8a";
123
- /** #color alignments-pair-orientation | RL (← →, mates point away from each other) | Abnormal orientation */
123
+ /** #color alignments-pair-orientation | RL (← →) | Mates point away from each other */
124
124
  export declare const colorPairRL = "#0099bb";
125
- /** #color alignments-pair-orientation | LL (→ →, both mates forward strand) | Abnormal orientation */
125
+ /** #color alignments-pair-orientation | LL (→ →) | Both mates on the forward strand */
126
126
  export declare const colorPairLL = "#4d9a4d";
127
- /** #color alignments-pair-orientation | RR (← ←, both mates reverse strand) | Abnormal orientation */
127
+ /** #color alignments-pair-orientation | RR (← ←) | Both mates on the reverse strand */
128
128
  export declare const colorPairRR = "#5555bb";
129
129
  export declare const colorNeutralRead = "#c8c8c8";
130
130
  /**
131
- * #color alignments-pair-orientation | Inter-chromosomal | Mate maps to a different chromosome; colored distinctly rather than by orientation
132
- * #color alignments-insert-size | Mate on a different chromosome | Suggests an inter-chromosomal event
131
+ * #color alignments-pair-orientation | Inter-chromosomal | Mate on another chromosome
132
+ * #color alignments-insert-size | Inter-chromosomal | Mate on another chromosome
133
133
  */
134
134
  export declare const colorInterchrom = "#af4d19";
135
- /** #color alignments-insert-size | Insert larger than expected | Suggests a deletion spanning the pair */
135
+ /** #color alignments-insert-size | Insert larger than expected | Deletion between the mates */
136
136
  export declare const colorLongInsert = "#ff0000";
137
- /** #color alignments-insert-size | Insert smaller than expected | Suggests an insertion between the pair */
137
+ /** #color alignments-insert-size | Insert smaller than expected | Insertion between the mates */
138
138
  export declare const colorShortInsert = "#f582c0";
139
139
  /**
140
- * #color alignments-pair-orientation | Mate unmapped | The other end of the pair aligned nowhere, so orientation and insert size say nothing
141
- * #color alignments-insert-size | Mate unmapped | The other end of the pair aligned nowhere, so insert size says nothing
140
+ * #color alignments-pair-orientation | Mate unmapped | Mate aligned nowhere
141
+ * #color alignments-insert-size | Mate unmapped | Mate aligned nowhere
142
142
  */
143
143
  export declare const colorUnmappedMate = "#000000";
144
144
  export declare const colorUnmappedMateDark = "#4a4a4a";
145
145
  export declare const colorLongreadInv = "#7755bb";
146
- /** #color alignments-pair-orientation | Split paired-end read (inverted) | A paired read's supplementary segment maps opposite-strand to its primary, so the junction is inverted — an inversion or an inverted duplication */
146
+ /** #color alignments-pair-orientation | Split read (inverted) | Supplementary segment on the opposite strand to its primary */
147
147
  export declare const colorSplitReadInversion = "#9b30b0";
148
148
  export declare const colorSupplementary = "#f0b878";
149
149
  export declare const tagColorPalette: string[];