@jbrowse/core 5.0.0-beta.2 → 5.0.0-beta.4
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/README.md +70 -40
- package/esm/BaseFeatureWidget/BaseFeatureDetail/FeatureDetails.d.ts +2 -3
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.d.ts +4 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/ParentFeatureLine.js +17 -0
- package/esm/BaseFeatureWidget/BaseFeatureDetail/index.js +4 -3
- package/esm/BaseFeatureWidget/SequenceFeatureDetails/SequenceFeaturePanel.d.ts +2 -2
- package/esm/BaseFeatureWidget/index.d.ts +1 -1
- package/esm/BaseFeatureWidget/stateModelFactory.d.ts +8 -1
- package/esm/BaseFeatureWidget/stateModelFactory.js +6 -0
- package/esm/BaseFeatureWidget/types.d.ts +10 -2
- package/esm/PluginManager.d.ts +30 -1
- package/esm/PluginManager.js +107 -70
- package/esm/ReExports/BaseFeatureDetails.js +1 -1
- package/esm/ReExports/MuiDataGridReExports.d.ts +1 -0
- package/esm/ReExports/MuiDataGridReExports.js +2 -2
- package/esm/ReExports/barrelOnlyNames.d.ts +5 -0
- package/esm/ReExports/barrelOnlyNames.js +63 -0
- package/esm/ReExports/modules.js +28 -56
- package/esm/ReExports/publicTracks.d.ts +1 -0
- package/esm/ReExports/publicTracks.js +14 -0
- package/esm/ReExports/publicUi.d.ts +4 -0
- package/esm/ReExports/publicUi.js +33 -0
- package/esm/ReExports/publicUtil.d.ts +1 -1
- package/esm/ReExports/publicUtil.js +8 -4
- package/esm/ReExports/sharedModules.d.ts +1 -1
- package/esm/ReExports/sharedModules.js +8 -1
- package/esm/ReExports/uiStub.d.ts +1 -0
- package/esm/ReExports/uiStub.js +6 -8
- package/esm/ReExports/workerModules.js +9 -4
- package/esm/ReExports/workerNamespaceNames.d.ts +11 -0
- package/esm/ReExports/workerNamespaceNames.js +281 -0
- package/esm/configuration/configurationSchema.js +11 -0
- package/esm/configuration/index.d.ts +2 -2
- package/esm/configuration/index.js +1 -1
- package/esm/configuration/promotableDefaults.d.ts +54 -19
- package/esm/configuration/promotableDefaults.js +108 -45
- package/esm/configuration/promotablePin.d.ts +50 -40
- package/esm/configuration/promotableResolve.d.ts +1 -1
- package/esm/configuration/promotableResolve.js +1 -1
- package/esm/configuration/tabixIndexFields.d.ts +2 -2
- package/esm/configuration/tabixIndexFields.js +2 -2
- package/esm/data_adapters/BaseAdapter/BaseFeatureDataAdapter.js +4 -12
- package/esm/data_adapters/BaseAdapter/featureDensity.d.ts +12 -0
- package/esm/data_adapters/BaseAdapter/featureDensity.js +15 -0
- package/esm/data_adapters/BaseAdapter/index.d.ts +2 -2
- package/esm/data_adapters/BaseAdapter/index.js +1 -1
- package/esm/data_adapters/BaseAdapter/types.d.ts +2 -8
- package/esm/pluggableElementTypes/AdapterType.d.ts +2 -1
- package/esm/pluggableElementTypes/AdapterType.js +1 -1
- package/esm/pluggableElementTypes/DisplayType.d.ts +3 -10
- package/esm/pluggableElementTypes/DisplayType.js +3 -45
- package/esm/pluggableElementTypes/LazyStateModelElement.d.ts +27 -0
- package/esm/pluggableElementTypes/LazyStateModelElement.js +71 -0
- package/esm/pluggableElementTypes/ViewType.d.ts +3 -10
- package/esm/pluggableElementTypes/ViewType.js +6 -51
- package/esm/pluggableElementTypes/extendElementType.d.ts +1 -2
- package/esm/pluggableElementTypes/extendElementType.js +1 -2
- package/esm/pluggableElementTypes/models/BaseDisplayModel.d.ts +3 -3
- package/esm/pluggableElementTypes/models/BaseDisplayModel.js +1 -1
- package/esm/pluggableElementTypes/models/BaseTrackModel.js +1 -4
- package/esm/pluggableElementTypes/models/BaseViewModel.d.ts +34 -34
- package/esm/pluggableElementTypes/models/BaseViewModel.js +19 -30
- package/esm/pluggableElementTypes/models/assertDisplayContract.d.ts +4 -3
- package/esm/pluggableElementTypes/models/assertDisplayContract.js +2 -2
- package/esm/pluggableElementTypes/models/baseTrackConfig.js +7 -1
- package/esm/ui/BaseExportSvgDialog.d.ts +1 -1
- package/esm/ui/ErrorMessageStackTraceDialog.js +5 -6
- package/esm/ui/ExportSvgDialog.d.ts +1 -1
- package/esm/ui/MenuTypes.d.ts +3 -3
- package/esm/ui/PinAdornment.js +22 -40
- package/esm/ui/ScrollChrome.d.ts +16 -0
- package/esm/ui/ScrollChrome.js +12 -0
- package/esm/ui/ScrollZoomToggle.d.ts +4 -3
- package/esm/ui/ScrollZoomToggle.js +4 -3
- package/esm/ui/SizeSliderRow.js +1 -1
- package/esm/ui/index.d.ts +2 -2
- package/esm/ui/index.js +3 -3
- package/esm/ui/legendMenuItem.d.ts +9 -15
- package/esm/ui/legendMenuItem.js +8 -19
- package/esm/ui/menuItemAdornment.d.ts +2 -3
- package/esm/ui/menuItemAdornment.js +2 -3
- package/esm/ui/menuItems.d.ts +1 -2
- package/esm/ui/menuItems.js +0 -1
- package/esm/ui/palette.d.ts +11 -11
- package/esm/ui/palette.js +11 -11
- package/esm/ui/promotablePinCoverage.d.ts +16 -2
- package/esm/ui/promotablePinCoverage.js +38 -2
- package/esm/ui/theme.js +5 -0
- package/esm/ui/toggleMenuItems.d.ts +13 -6
- package/esm/ui/toggleMenuItems.js +32 -15
- package/esm/util/Base1DUtils.d.ts +4 -2
- package/esm/util/Base1DUtils.js +12 -4
- package/esm/util/SvgCanvas.js +4 -3
- package/esm/util/adapterConfigKey.d.ts +12 -0
- package/esm/util/adapterConfigKey.js +14 -0
- package/esm/util/adapterMetadata.js +2 -1
- package/esm/util/analytics.js +4 -5
- package/esm/util/clampToContig.d.ts +17 -0
- package/esm/util/clampToContig.js +19 -0
- package/esm/util/colorBits.d.ts +2 -1
- package/esm/util/colorBits.js +2 -5
- package/esm/util/createStopTokenRotation.d.ts +8 -7
- package/esm/util/featureTypes.d.ts +24 -0
- package/esm/util/featureTypes.js +35 -0
- package/esm/util/fetchPhases.d.ts +1 -1
- package/esm/util/index.d.ts +4 -2
- package/esm/util/index.js +3 -1
- package/esm/util/installFetch.d.ts +29 -18
- package/esm/util/installFetch.js +17 -17
- package/esm/util/installInitAutorun.d.ts +6 -5
- package/esm/util/installInitAutorun.js +2 -2
- package/esm/util/installPrerequisiteFetch.d.ts +86 -0
- package/esm/util/installPrerequisiteFetch.js +73 -0
- package/esm/util/openFeatureWidget.d.ts +5 -0
- package/esm/util/openFeatureWidget.js +1 -0
- package/esm/util/openViews.d.ts +16 -0
- package/esm/util/openViews.js +22 -0
- package/esm/util/parentWalk.d.ts +1 -1
- package/esm/util/parentWalk.js +1 -1
- package/esm/util/renderToStaticMarkup.js +10 -0
- package/esm/util/scheduleDetachedDestroy.d.ts +18 -0
- package/esm/util/scheduleDetachedDestroy.js +24 -0
- package/esm/util/scrollLatch.d.ts +1 -0
- package/esm/util/scrollLatch.js +8 -0
- package/esm/util/stopToken.d.ts +6 -5
- package/esm/util/trackConfigDelta.d.ts +6 -6
- package/esm/util/trackConfigDelta.js +3 -3
- package/esm/util/types/index.d.ts +25 -20
- package/esm/util/usePanelVirtualScroll.d.ts +6 -2
- package/esm/util/usePanelVirtualScroll.js +6 -2
- package/esm/util/useRowVirtualScroll.d.ts +1 -1
- package/esm/util/useRowVirtualScroll.js +1 -1
- package/esm/util/useVirtualScrollWheel.js +11 -1
- package/esm/util/wheelZoom.d.ts +3 -1
- package/esm/util/wheelZoom.js +39 -14
- package/esm/util/whenViewSettled.d.ts +31 -6
- package/esm/util/whenViewSettled.js +33 -5
- package/esm/util/withLaunchInput.d.ts +47 -2
- package/esm/util/withLaunchInput.js +56 -11
- package/package.json +10 -5
- package/esm/ui/promotableMenuItems.d.ts +0 -19
- package/esm/ui/promotableMenuItems.js +0 -91
|
@@ -41,6 +41,18 @@ export function defineLaunchKeys() {
|
|
|
41
41
|
// is ever a setting and neither can be lifted off the snapshot.
|
|
42
42
|
const IDENTITY = new Set(['id', 'type']);
|
|
43
43
|
const LAUNCH = 'launch';
|
|
44
|
+
/**
|
|
45
|
+
* The part of a launch spec that belongs on the snapshot: everything but the
|
|
46
|
+
* launch keys, and the identity and `launch` keys no spec may set. For a caller
|
|
47
|
+
* that applies the launch itself and builds the view from a snapshot — a
|
|
48
|
+
* synteny row, whose parent navigates it and opens its tracks — so what it
|
|
49
|
+
* hands MST is settings only, and the view's own partition sorts those into
|
|
50
|
+
* properties and reported typos.
|
|
51
|
+
*/
|
|
52
|
+
export function snapshotSettings(spec, registration) {
|
|
53
|
+
const keys = registration?.keys ?? {};
|
|
54
|
+
return Object.fromEntries(Object.entries(spec).filter(([key]) => !(key in keys) && !IDENTITY.has(key) && key !== LAUNCH));
|
|
55
|
+
}
|
|
44
56
|
function isObject(value) {
|
|
45
57
|
return !!value && typeof value === 'object';
|
|
46
58
|
}
|
|
@@ -80,6 +92,31 @@ function splitEntries(kind, value) {
|
|
|
80
92
|
state: built.length ? (Array.isArray(value) ? built : value) : undefined,
|
|
81
93
|
};
|
|
82
94
|
}
|
|
95
|
+
// The properties a snapshot's keys are classified against are the REGISTERED
|
|
96
|
+
// view type's, read at preprocess time: `extendViewType` composes onto the
|
|
97
|
+
// model after `withLaunchInput` wrapped it, and a set frozen at wrap time sent
|
|
98
|
+
// every added property to `unknown` — restored at its default, with a warning
|
|
99
|
+
// naming it a typo. The wrapped model's own properties are the answer when no
|
|
100
|
+
// registry is given, or the snapshot names a type it does not hold, which is
|
|
101
|
+
// how a factory-built model in a test behaves.
|
|
102
|
+
function knownPropsResolver(model, registry) {
|
|
103
|
+
let cachedProps;
|
|
104
|
+
let cachedKeys = new Set();
|
|
105
|
+
return (snap) => {
|
|
106
|
+
const name = snap.type;
|
|
107
|
+
const registered = registry && typeof name === 'string' && registry.viewTypes.has(name)
|
|
108
|
+
? registry.getViewType(name)
|
|
109
|
+
: undefined;
|
|
110
|
+
const props = registered?.isStateModelLoaded
|
|
111
|
+
? registered.stateModel.properties
|
|
112
|
+
: model.properties;
|
|
113
|
+
if (props !== cachedProps) {
|
|
114
|
+
cachedProps = props;
|
|
115
|
+
cachedKeys = new Set(Object.keys(props));
|
|
116
|
+
}
|
|
117
|
+
return cachedKeys;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
83
120
|
function classify(snap, { keys, passThrough }, known, out) {
|
|
84
121
|
for (const [key, value] of Object.entries(snap)) {
|
|
85
122
|
const spec = keys[key];
|
|
@@ -140,6 +177,11 @@ function legacyInitSnapshot(init, { keys }) {
|
|
|
140
177
|
* are about to be rejected. `afterAttach` — reached only by a snapshot that won
|
|
141
178
|
* — reports what the partition captured.
|
|
142
179
|
*
|
|
180
|
+
* `registry` is the PluginManager. With it the partition classifies against
|
|
181
|
+
* the view type as registered, `extendViewType`'s added properties included;
|
|
182
|
+
* without it, against the model as wrapped here. `materialized` draws the line
|
|
183
|
+
* past which the blob is no longer persisted; see `LaunchInputOptions`.
|
|
184
|
+
*
|
|
143
185
|
* ORDER: MST runs preprocessors in the reverse of the order they were added, so
|
|
144
186
|
* this belongs on the chain BEFORE a view's own legacy-key preprocessor, where
|
|
145
187
|
* it partitions the snapshot MST finally consumes rather than a key that remap
|
|
@@ -156,13 +198,14 @@ function legacyInitSnapshot(init, { keys }) {
|
|
|
156
198
|
* without a word, and `ViewType.stateModel` and every `.properties`
|
|
157
199
|
* introspection site break with it.
|
|
158
200
|
*/
|
|
159
|
-
export function withLaunchInput(model, registration) {
|
|
160
|
-
const
|
|
201
|
+
export function withLaunchInput(model, registration, { registry, materialized }) {
|
|
202
|
+
const knownProps = knownPropsResolver(model, registry);
|
|
161
203
|
const partitioned = model
|
|
162
204
|
.preProcessSnapshot((snap) => {
|
|
163
205
|
if (!isObject(snap)) {
|
|
164
206
|
return snap;
|
|
165
207
|
}
|
|
208
|
+
const known = knownProps(snap);
|
|
166
209
|
const { init, ...rest } = snap;
|
|
167
210
|
const out = {
|
|
168
211
|
state: {},
|
|
@@ -207,20 +250,22 @@ export function withLaunchInput(model, registration) {
|
|
|
207
250
|
reportMalformedRows(self, Object.keys(launch?.malformed ?? {}));
|
|
208
251
|
},
|
|
209
252
|
}))
|
|
210
|
-
//
|
|
211
|
-
//
|
|
212
|
-
//
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
//
|
|
253
|
+
// Whole while the view has yet to materialize, since the pending launch is
|
|
254
|
+
// then the only thing a reload can rebuild the view from, and gone once it
|
|
255
|
+
// has — the report keys with it, so a saved session never carries a
|
|
256
|
+
// typo report about content it no longer holds. `legacyInit` goes either
|
|
257
|
+
// way: it names the SPELLING of the snapshot this view was opened from,
|
|
258
|
+
// and the saved one does not use it, so persisting it would report nesting
|
|
259
|
+
// on every restore forever (`pendingLaunch` excludes the report keys, so
|
|
260
|
+
// no launch run ever clears it).
|
|
217
261
|
.postProcessSnapshot((snap) => {
|
|
218
262
|
const launch = snap[LAUNCH];
|
|
219
|
-
if (!isObject(launch)
|
|
263
|
+
if (!isObject(launch)) {
|
|
220
264
|
return snap;
|
|
221
265
|
}
|
|
222
266
|
const { legacyInit, ...kept } = launch;
|
|
223
|
-
return Object.keys(kept).length
|
|
267
|
+
return Object.keys(kept).length &&
|
|
268
|
+
!materialized(snap)
|
|
224
269
|
? { ...snap, [LAUNCH]: kept }
|
|
225
270
|
: Object.fromEntries(Object.entries(snap).filter(([key]) => key !== LAUNCH));
|
|
226
271
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/core",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "JBrowse 2 core libraries used by plugins",
|
|
6
6
|
"keywords": [
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"./data_adapters/BaseAdapter/getAdapterId": "./esm/data_adapters/BaseAdapter/getAdapterId.js",
|
|
47
47
|
"./data_adapters/BaseAdapter/stats": "./esm/data_adapters/BaseAdapter/stats.js",
|
|
48
48
|
"./data_adapters/BaseAdapter/types": "./esm/data_adapters/BaseAdapter/types.js",
|
|
49
|
+
"./data_adapters/adapterSessionRefcount": "./esm/data_adapters/adapterSessionRefcount.js",
|
|
49
50
|
"./data_adapters/dataAdapterCache": "./esm/data_adapters/dataAdapterCache.js",
|
|
50
51
|
"./data_adapters/getFeatureAdapter": "./esm/data_adapters/getFeatureAdapter.js",
|
|
51
52
|
"./data_adapters/getSequenceSubAdapter": "./esm/data_adapters/getSequenceSubAdapter.js",
|
|
@@ -145,6 +146,7 @@
|
|
|
145
146
|
"./util/SvgCanvas": "./esm/util/SvgCanvas.js",
|
|
146
147
|
"./util/TimeTraveller": "./esm/util/TimeTraveller.js",
|
|
147
148
|
"./util/aborting": "./esm/util/aborting.js",
|
|
149
|
+
"./util/adapterConfigKey": "./esm/util/adapterConfigKey.js",
|
|
148
150
|
"./util/adapterMetadata": "./esm/util/adapterMetadata.js",
|
|
149
151
|
"./util/addRelativeUris": "./esm/util/addRelativeUris.js",
|
|
150
152
|
"./util/analytics": "./esm/util/analytics.js",
|
|
@@ -185,6 +187,7 @@
|
|
|
185
187
|
"./util/installClearHoverOnSurfaceMove": "./esm/util/installClearHoverOnSurfaceMove.js",
|
|
186
188
|
"./util/installFetch": "./esm/util/installFetch.js",
|
|
187
189
|
"./util/installInitAutorun": "./esm/util/installInitAutorun.js",
|
|
190
|
+
"./util/installPrerequisiteFetch": "./esm/util/installPrerequisiteFetch.js",
|
|
188
191
|
"./util/io": "./esm/util/io/index.js",
|
|
189
192
|
"./util/io/RemoteFileWithRangeCache": "./esm/util/io/RemoteFileWithRangeCache.js",
|
|
190
193
|
"./util/isDataCurrent": "./esm/util/isDataCurrent.js",
|
|
@@ -200,10 +203,12 @@
|
|
|
200
203
|
"./util/librpc": "./esm/util/librpc.js",
|
|
201
204
|
"./util/localStorage": "./esm/util/localStorage.js",
|
|
202
205
|
"./util/makeAssembly": "./esm/util/makeAssembly.js",
|
|
206
|
+
"./util/mst-reflection": "./esm/util/mst-reflection.js",
|
|
203
207
|
"./util/mstUtils": "./esm/util/mstUtils.js",
|
|
204
208
|
"./util/nanoid": "./esm/util/nanoid.js",
|
|
205
209
|
"./util/numericUtils": "./esm/util/numericUtils.js",
|
|
206
210
|
"./util/offscreenCanvasPonyfill": "./esm/util/offscreenCanvasPonyfill.js",
|
|
211
|
+
"./util/openViews": "./esm/util/openViews.js",
|
|
207
212
|
"./util/paintLayer": "./esm/util/paintLayer.js",
|
|
208
213
|
"./util/parseLineByLine": "./esm/util/parseLineByLine.js",
|
|
209
214
|
"./util/progress": "./esm/util/progress.js",
|
|
@@ -259,10 +264,10 @@
|
|
|
259
264
|
"@mui/icons-material": "^9.4.0",
|
|
260
265
|
"@mui/material": "^9.4.0",
|
|
261
266
|
"@mui/system": "^9.4.0",
|
|
262
|
-
"@mui/x-data-grid": "^9.
|
|
267
|
+
"@mui/x-data-grid": "^9.13.0",
|
|
263
268
|
"canvas-sequencer-ts": "^3.1.3",
|
|
264
269
|
"compare-versions": "^6.1.1",
|
|
265
|
-
"dompurify": "^3.4.
|
|
270
|
+
"dompurify": "^3.4.15",
|
|
266
271
|
"generic-filehandle2": "^2.4.0",
|
|
267
272
|
"idb": "^8.0.3",
|
|
268
273
|
"mobx": "^7.0.3",
|
|
@@ -270,8 +275,8 @@
|
|
|
270
275
|
"pako-esm2": "^2.0.2",
|
|
271
276
|
"rxjs": "^7.8.2",
|
|
272
277
|
"source-map-js": "^1.2.1",
|
|
273
|
-
"@jbrowse/add-track-core": "^5.0.0-beta.
|
|
274
|
-
"@jbrowse/render-core": "^5.0.0-beta.
|
|
278
|
+
"@jbrowse/add-track-core": "^5.0.0-beta.4",
|
|
279
|
+
"@jbrowse/render-core": "^5.0.0-beta.4"
|
|
275
280
|
},
|
|
276
281
|
"peerDependencies": {
|
|
277
282
|
"react": ">=19.0.0",
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { Pin } from '../configuration/promotablePin.ts';
|
|
2
|
-
import type { CheckboxMenuItem, RadioMenuItem } from './MenuTypes.ts';
|
|
3
|
-
import type { RadioOption, SettingRowOptions } from './toggleMenuItems.ts';
|
|
4
|
-
/** #menuBuilder promotableToggleItem | `checkboxItem` plus an apply-to-open-tracks pin */
|
|
5
|
-
export declare function promotableToggleItem({ label, checked, onToggle, pin, ...opts }: {
|
|
6
|
-
label: string;
|
|
7
|
-
checked: boolean;
|
|
8
|
-
onToggle: () => void;
|
|
9
|
-
pin: Pin;
|
|
10
|
-
} & SettingRowOptions): CheckboxMenuItem;
|
|
11
|
-
/** #menuBuilder promotableRadioItem | `radioItem` plus an apply-to-open-tracks pin */
|
|
12
|
-
export declare function promotableRadioItem({ label, checked, onClick, pin, ...opts }: {
|
|
13
|
-
label: string;
|
|
14
|
-
checked: boolean;
|
|
15
|
-
onClick: () => void;
|
|
16
|
-
pin?: Pin;
|
|
17
|
-
} & SettingRowOptions): RadioMenuItem;
|
|
18
|
-
/** #menuBuilder promotableRadioItems | `radioItems` plus a pin per option, from a factory over the value */
|
|
19
|
-
export declare function promotableRadioItems<T extends string>(options: readonly RadioOption<T>[], current: T | undefined, setMode: (m: T) => void, pin: (value: T) => Pin): RadioMenuItem[];
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { checkboxItem, radioItem, radioItems } from './toggleMenuItems.js';
|
|
2
|
-
// Every builder here describes the trailing pin (`pin`) rather than
|
|
3
|
-
// rendering it. That is what keeps this module — and therefore every state
|
|
4
|
-
// model and menu file that calls it — free of React and of MUI's
|
|
5
|
-
// ToggleButton/Tooltip. `menuItemAdornment.tsx` turns the description into
|
|
6
|
-
// `PinAdornment` at the point the menu is drawn. See
|
|
7
|
-
// reference/EAGER_BUNDLE.md; `menuItems.purity.test.ts` holds it.
|
|
8
|
-
//
|
|
9
|
-
// Each is the plain builder in `toggleMenuItems.ts` plus a pin, and each is
|
|
10
|
-
// written that way — `checkboxItem` / `radioItems` build the row — so the
|
|
11
|
-
// promotable and plain forms of a row can differ only by the pin.
|
|
12
|
-
// A promotable setting as one native checkbox menu row: the value toggles the
|
|
13
|
-
// track (inheriting native hover/sizing/keyboard), and a trailing pin applies
|
|
14
|
-
// this value to every open track of the display type, offering the display-type
|
|
15
|
-
// default as its snackbar's one action. Always shown so the capability is
|
|
16
|
-
// discoverable.
|
|
17
|
-
//
|
|
18
|
-
// **The row itself is `checkboxItem`'s**, so the two builders can only ever
|
|
19
|
-
// differ by the pin. They used to be two literals, and had already drifted: this
|
|
20
|
-
// one accepted `helpText` and `keepMenuOpen` while silently dropping `disabled`
|
|
21
|
-
// and `disabledHelpText`, so a promotable row could not be greyed out the way
|
|
22
|
-
// its plain sibling could. Sharing the body is also what makes a future
|
|
23
|
-
// change to what a checkbox row *is* reach both — the failure `checkboxItem`'s
|
|
24
|
-
// own comment records is a menu regressing by omission.
|
|
25
|
-
//
|
|
26
|
-
// `keepMenuOpen` is left unset by default, so `CascadingMenu` keeps the row open
|
|
27
|
-
// by its checkbox type: these rows only write a setting, users flip several in
|
|
28
|
-
// one visit, and the menu is an observer so the ticks and pins move live. A row
|
|
29
|
-
// whose click opens a dialog instead (colorBy's "Tag...") passes false.
|
|
30
|
-
/** #menuBuilder promotableToggleItem | `checkboxItem` plus an apply-to-open-tracks pin */
|
|
31
|
-
export function promotableToggleItem({ label, checked, onToggle, pin, ...opts }) {
|
|
32
|
-
return {
|
|
33
|
-
...checkboxItem(label, checked, onToggle, opts),
|
|
34
|
-
pin: { control: pin, label },
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
// ONE radio row of a promotable-value group — the escape hatch, for a group the
|
|
38
|
-
// plural builder below can't express. **Reach for `promotableRadioItems` first**:
|
|
39
|
-
// every option in a group has to get a pin, and hand-naming the rows is what
|
|
40
|
-
// leaves one without.
|
|
41
|
-
//
|
|
42
|
-
// The rows that genuinely need this: `pin` is optional here, for a row with no
|
|
43
|
-
// single value to promote yet (the colorBy "Tag..." row before a tag is picked)
|
|
44
|
-
// or a display whose slot isn't promotable at all (the shared colorBy menu on
|
|
45
|
-
// gwas/variants); and the alignments size presets, whose group is gated row by
|
|
46
|
-
// row (`needsContent`) and mixes in a non-promotable "Custom..." peer.
|
|
47
|
-
//
|
|
48
|
-
// **The row itself is `radioItem`'s**, for the reason `promotableToggleItem`'s
|
|
49
|
-
// is `checkboxItem`'s: it was a second literal, and it had drifted the same way
|
|
50
|
-
// its checkbox sibling had — naming `helpText`/`keepMenuOpen` by hand and so
|
|
51
|
-
// silently dropping `disabled` and `disabledHelpText`, which the
|
|
52
|
-
// alignments size presets have to bolt back on afterwards (`needsContent`).
|
|
53
|
-
/** #menuBuilder promotableRadioItem | `radioItem` plus an apply-to-open-tracks pin */
|
|
54
|
-
export function promotableRadioItem({ label, checked, onClick, pin, ...opts }) {
|
|
55
|
-
return {
|
|
56
|
-
...radioItem(label, checked, onClick, opts),
|
|
57
|
-
...(pin && {
|
|
58
|
-
pin: { control: pin, label },
|
|
59
|
-
}),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
// A whole promotable radio group: `radioItems` plus one pin per option. The
|
|
63
|
-
// plural form of the builder above, and the one to reach for on a group whose
|
|
64
|
-
// options differ only in their value — which is all five of them today
|
|
65
|
-
// (`heightMode`, `displayMode`, `showLabels`, `subfeatureLabels`,
|
|
66
|
-
// `sashimiArcsMode`; the two label groups reach it through canvas's
|
|
67
|
-
// `inlineRadioGroup`).
|
|
68
|
-
//
|
|
69
|
-
// **Every option in a group gets a pin, the `promotedBase` value included** —
|
|
70
|
-
// once a non-base value is promoted, pinning the base back is the only per-value
|
|
71
|
-
// way to undo it from its own row, and a radio group with one row silently
|
|
72
|
-
// missing its trailing control reads as a bug. Building the group here is what
|
|
73
|
-
// makes that structural instead of a rule to remember: `sashimiArcsMode`'s base
|
|
74
|
-
// looked unpinnable precisely because each row had been named by hand. Prefer
|
|
75
|
-
// this over `.map(promotableRadioItem)` whenever the pin is a function of the
|
|
76
|
-
// option's value.
|
|
77
|
-
//
|
|
78
|
-
// `pin` is a factory rather than an array so it can't be a row short. Pass
|
|
79
|
-
// `value => makePin(self, slot, value)`, or a model member of that shape where
|
|
80
|
-
// the menu module is handed a duck-typed model (alignments).
|
|
81
|
-
//
|
|
82
|
-
// The rows are `radioItems`' own, so the promotable and plain groups can't drift
|
|
83
|
-
// on anything but the pin. `radioItems` maps `options` in order, which is what
|
|
84
|
-
// lets each row be paired back to the option that built it.
|
|
85
|
-
/** #menuBuilder promotableRadioItems | `radioItems` plus a pin per option, from a factory over the value */
|
|
86
|
-
export function promotableRadioItems(options, current, setMode, pin) {
|
|
87
|
-
return radioItems(options, current, setMode).map((item, i) => {
|
|
88
|
-
const { value, label } = options[i];
|
|
89
|
-
return { ...item, pin: { control: pin(value), label } };
|
|
90
|
-
});
|
|
91
|
-
}
|