@jbrowse/display-ui 4.3.0
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/LICENSE +201 -0
- package/README.md +433 -0
- package/esm/DisplayUIProvider.d.ts +70 -0
- package/esm/DisplayUIProvider.js +96 -0
- package/esm/FloatingLegend.d.ts +16 -0
- package/esm/FloatingLegend.js +213 -0
- package/esm/PointerLayer.d.ts +26 -0
- package/esm/PointerLayer.js +27 -0
- package/esm/bottomRightCorner.d.ts +58 -0
- package/esm/bottomRightCorner.js +59 -0
- package/esm/chromeOverlayContext.d.ts +7 -0
- package/esm/chromeOverlayContext.js +44 -0
- package/esm/chromeOverlays.d.ts +88 -0
- package/esm/chromeOverlays.js +1 -0
- package/esm/index.d.ts +22 -0
- package/esm/index.js +51 -0
- package/esm/isLiveModel.d.ts +21 -0
- package/esm/isLiveModel.js +24 -0
- package/esm/plainChromeOverlays.d.ts +18 -0
- package/esm/plainChromeOverlays.js +189 -0
- package/esm/tooLargeBannerText.d.ts +18 -0
- package/esm/tooLargeBannerText.js +34 -0
- package/esm/tooltip/Tooltip.d.ts +52 -0
- package/esm/tooltip/Tooltip.js +67 -0
- package/esm/tooltip/useTooltip.d.ts +50 -0
- package/esm/tooltip/useTooltip.js +116 -0
- package/esm/trackControl/plainTrackControl.d.ts +17 -0
- package/esm/trackControl/plainTrackControl.js +133 -0
- package/esm/trackControl/trackControlContext.d.ts +7 -0
- package/esm/trackControl/trackControlContext.js +30 -0
- package/esm/trackControl/types.d.ts +58 -0
- package/esm/trackControl/types.js +1 -0
- package/esm/trackControl/useTrackControlMenu.d.ts +51 -0
- package/esm/trackControl/useTrackControlMenu.js +163 -0
- package/esm/trackOverlay/TrackOverlayContext.d.ts +1 -0
- package/esm/trackOverlay/TrackOverlayContext.js +18 -0
- package/esm/trackOverlay/TrackOverlayPortal.d.ts +18 -0
- package/esm/trackOverlay/TrackOverlayPortal.js +66 -0
- package/esm/trackOverlay/TrackOverlaySlot.d.ts +54 -0
- package/esm/trackOverlay/TrackOverlaySlot.js +60 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [2020] [Evolutionary Software Foundation]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
# @jbrowse/display-ui
|
|
2
|
+
|
|
3
|
+
The UI a display draws that is **not data** — loading scrims, error bars, the
|
|
4
|
+
too-large gate, the controls in a track's corner, and the overlay layer floating
|
|
5
|
+
chrome escapes into. The contract, and implementations of it that reach no UI
|
|
6
|
+
toolkit.
|
|
7
|
+
|
|
8
|
+
```tsx
|
|
9
|
+
import { DisplayUIProvider } from '@jbrowse/display-ui'
|
|
10
|
+
|
|
11
|
+
;<DisplayUIProvider>{tracks}</DisplayUIProvider>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
That is the whole common case: JBrowse's own stock displays render no Material
|
|
15
|
+
UI beneath it, with no `ThemeProvider` to mount and no emotion in your page.
|
|
16
|
+
Supply `overlays` (a partial set, merged over the plain one) or `trackControl`
|
|
17
|
+
to bring your own.
|
|
18
|
+
|
|
19
|
+
## Why it is a package
|
|
20
|
+
|
|
21
|
+
**This package has no UI-toolkit dependency, and that is the feature.** The
|
|
22
|
+
contract used to live beside the Material implementations it exists to replace,
|
|
23
|
+
so importing the seam pulled 45 `@mui/*` modules in behind it — the whole
|
|
24
|
+
Material overlay set, and (through one barrel import) `FileSelector`,
|
|
25
|
+
`FatalErrorDialog` and `PluginManager`. Every check in the repo counted
|
|
26
|
+
_rendered_ elements and stayed green. Here, npm decides instead of a test: the
|
|
27
|
+
Material bindings live in `@jbrowse/plugin-linear-genome-view`, which depends on
|
|
28
|
+
this, never the other way round.
|
|
29
|
+
|
|
30
|
+
It also puts the contract somewhere `packages/*` can reach. `tree-sidebar`
|
|
31
|
+
depended on the LGV **plugin** for `TrackOverlayPortal` alone; the comparative
|
|
32
|
+
displays could not read the overlay contract at all, because it sat one layer
|
|
33
|
+
above them.
|
|
34
|
+
|
|
35
|
+
## What is here
|
|
36
|
+
|
|
37
|
+
| | |
|
|
38
|
+
| ------------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
39
|
+
| `DisplayChromeOverlays` | the five `displayPhase` states, as a component set, with the model shape each is handed |
|
|
40
|
+
| `DisplayChromeOverlayProvider` | redirects those states for JBrowse's own displays |
|
|
41
|
+
| `TrackControlComponent` | one shape for every ambient bottom-right control, icons named rather than passed |
|
|
42
|
+
| `TrackControlProvider` | redirects those |
|
|
43
|
+
| `DisplayUIProvider` | both at once, defaulting to the plain sets — what an embedder mounts |
|
|
44
|
+
| `plainChromeOverlays` / `plainTrackControl` | the toolkit-free sets, CSS system colours, no theme object |
|
|
45
|
+
| `TrackOverlaySlot` / `TrackOverlayPortal` | the per-track overlay layer, and the host's half of it |
|
|
46
|
+
| `FloatingLegend` | the one legend box every display with colours to explain draws |
|
|
47
|
+
| `BottomRightCornerContext` | the corner `BackgroundProgress` is laid out in, which its prop types cannot express |
|
|
48
|
+
| `tooLargeBannerText` | what the byte gate says, shared by every set that renders it |
|
|
49
|
+
| `isLiveModel` | the liveness guard an overlay's one button needs, for an MST node or a plain object |
|
|
50
|
+
|
|
51
|
+
## What is _not_ here, and cannot be
|
|
52
|
+
|
|
53
|
+
Redirecting what a stock display **renders** is not the same as keeping a
|
|
54
|
+
toolkit out of its **bundle**. `DisplayChrome` and `TrackControl` live in the
|
|
55
|
+
LGV plugin and import Material UI; a provider only stops them rendering it.
|
|
56
|
+
Dropping the weight means writing your own display component over
|
|
57
|
+
`DisplayChromeBase`, which takes `overlays` as a prop.
|
|
58
|
+
|
|
59
|
+
See `agent-docs/reference/DISPLAYCHROME.md` for the seams in full, and
|
|
60
|
+
`products/jbrowse-build-your-own` for a site built on them.
|
|
61
|
+
|
|
62
|
+
<!-- API_DOCS_START -->
|
|
63
|
+
|
|
64
|
+
## API
|
|
65
|
+
|
|
66
|
+
Auto-generated from `#api` JSDoc tags in this package. Do not edit by hand.
|
|
67
|
+
|
|
68
|
+
### BottomRightCornerContext
|
|
69
|
+
|
|
70
|
+
The one box per display that owns the bottom-right corner.
|
|
71
|
+
|
|
72
|
+
It lives beside the overlay contract rather than with the chrome that mounts it,
|
|
73
|
+
because it is the half of that contract the types cannot carry:
|
|
74
|
+
`DisplayChromeOverlays.BackgroundProgress` is the one state told to render an
|
|
75
|
+
in-flow chip with no `position` and no corner offsets, and this is the box it is
|
|
76
|
+
laid out in. A host writing their own display over `DisplayChromeBase` needs to
|
|
77
|
+
be able to build that corner; while this sat one layer up in the LGV plugin, the
|
|
78
|
+
rule was a paragraph they could only obey by hand.
|
|
79
|
+
|
|
80
|
+
Two independent things want that corner and neither could see the other: the
|
|
81
|
+
display's own control row (`BottomRightIndicators` — track sizing, the isoform
|
|
82
|
+
notice, the solo chip) and the chrome's background-progress chip
|
|
83
|
+
(`DisplayChromeOverlays.BackgroundProgress`, the status channel for work with no
|
|
84
|
+
fetch behind it). Both portal into the _same_ per-track overlay node, and both
|
|
85
|
+
used to claim `bottom: 2; right: 2` there with their own `position: absolute`
|
|
86
|
+
box — so they simply drew on top of each other, the controls winning on z-index
|
|
87
|
+
and the status text disappearing under them.
|
|
88
|
+
|
|
89
|
+
It has never been reachable: the two displays that render the control row
|
|
90
|
+
(alignments, canvas) are not among the four that report a `ready`-phase status
|
|
91
|
+
(clustering, on multi-wiggle / multi-row features / maf / the multi-sample
|
|
92
|
+
variant pair). That is the _reason_ to make it structural rather than to leave
|
|
93
|
+
it — nothing on either side is aware of the constraint, so the first display to
|
|
94
|
+
want both would find the bug, and it presents as a status message that silently
|
|
95
|
+
never appears.
|
|
96
|
+
|
|
97
|
+
`BottomRightIndicators` already described itself as "the single anchor point for
|
|
98
|
+
every bottom-right overlay ... so they lay out as one row instead of each
|
|
99
|
+
picking their own position and colliding". This makes that true of the chip too:
|
|
100
|
+
the chrome renders the anchor, puts its chip in it, and publishes the node here
|
|
101
|
+
so the display's row — rendered several components away, inside the chrome's
|
|
102
|
+
body — lands in the same flex box instead of over it.
|
|
103
|
+
|
|
104
|
+
`null` outside a chrome (a display an embedder mounts standalone, a unit test,
|
|
105
|
+
the SVG export), where `BottomRightIndicators` keeps its own anchored box. That
|
|
106
|
+
fallback is why this can be added without every consumer changing.
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
// type signature
|
|
110
|
+
Context<HTMLElement | null>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/bottomRightCorner.ts)
|
|
114
|
+
|
|
115
|
+
### DisplayUIProvider
|
|
116
|
+
|
|
117
|
+
Both bring-your-own seams at once: what a display draws that is not data.
|
|
118
|
+
|
|
119
|
+
There are two contexts underneath because two different things render them — the
|
|
120
|
+
chrome around a display draws the status states, the display itself draws its
|
|
121
|
+
bottom-right controls — and that split is real at the implementation level,
|
|
122
|
+
since `DisplayChromeBase` takes its overlay set as a _prop_ and never renders a
|
|
123
|
+
track control. It is not real for an embedder: nobody wants stock Material
|
|
124
|
+
loading scrims with plain corner controls, or the reverse. Every consumer in
|
|
125
|
+
this repo mounts the two together.
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
<DisplayUIProvider>{tracks}</DisplayUIProvider>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Both props default to the plain, toolkit-free sets, so the common case — "I do
|
|
132
|
+
not want Material UI in my app" — needs no arguments and no second import.
|
|
133
|
+
|
|
134
|
+
**`overlays` is a partial set**, merged over the plain one, so replacing a
|
|
135
|
+
single state is one entry rather than five:
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
<DisplayUIProvider overlays={{ ErrorBar: MyErrorBar }}>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Partial rather than whole for two reasons. A host writing four of the five
|
|
142
|
+
states by hand only ever wanted one of them, and every example of this had
|
|
143
|
+
spread `plainChromeOverlays` in to say so. And a _sixth_ state is a thing
|
|
144
|
+
JBrowse can add: with a whole set the host's object goes stale on upgrade — a
|
|
145
|
+
compile error if they typecheck, a missing component if they ship JS — while a
|
|
146
|
+
partial one keeps working and picks up the new plain default.
|
|
147
|
+
|
|
148
|
+
Declare that object at module scope if you can. The merge is stable per object
|
|
149
|
+
(`resolveOverlays`), so a constant costs one merge for the life of the app; a
|
|
150
|
+
literal written inline in JSX is a new object every render, and this value goes
|
|
151
|
+
into a context, so every display beneath re-renders with it.
|
|
152
|
+
|
|
153
|
+
**The contexts themselves still default to `undefined`, and that stays true.** A
|
|
154
|
+
display rendering outside any provider — a unit test, the SVG export,
|
|
155
|
+
breakpoint-split-view's `overlayUtils` — keeps JBrowse's own Material look,
|
|
156
|
+
because a plain ambient default would degrade those invisibly. Defaulting _this
|
|
157
|
+
component's props_ is a different thing: mounting it is a deliberate act, and
|
|
158
|
+
the act means "not the Material default". Nothing gets a plain set without
|
|
159
|
+
someone having asked.
|
|
160
|
+
|
|
161
|
+
Colors are not a seam and are not here. A display reads `usePalette()` for its
|
|
162
|
+
own content colors, which is a palette of strings rather than a UI toolkit, so
|
|
163
|
+
it arrives through `SessionPaletteProvider` (`@jbrowse/core/ui/PaletteContext`)
|
|
164
|
+
whatever these are set to. A feature track needs it even with plain chrome.
|
|
165
|
+
|
|
166
|
+
This module reaches no `@mui/*` module, and `muiFree.test.ts` keeps it that way
|
|
167
|
+
— asking for less Material UI must not download more of it. What it cannot do is
|
|
168
|
+
unship the Material components a _stock display_ imports: `DisplayChrome` and
|
|
169
|
+
`TrackControl` are in that display's chunk either way, and merely stop
|
|
170
|
+
rendering. Keeping them out of the graph means writing your own display
|
|
171
|
+
component over `DisplayChromeBase`, which takes `overlays` as a prop and imports
|
|
172
|
+
no toolkit. See
|
|
173
|
+
[DISPLAYCHROME.md](https://github.com/GMOD/jbrowse-components/blob/main/agent-docs/reference/DISPLAYCHROME.md).
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
// type signature
|
|
177
|
+
({ overlays, trackControl, children, }: { overlays?: Partial<…> | undefined; trackControl?: TrackControlComponent | undefined; children: ReactNode; }) => Element
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/DisplayUIProvider.tsx)
|
|
181
|
+
|
|
182
|
+
### isLiveModel
|
|
183
|
+
|
|
184
|
+
Whether an overlay's model can still be called into.
|
|
185
|
+
|
|
186
|
+
The terminal states unmount the canvas, so a click landing after the track was
|
|
187
|
+
closed would otherwise run an action on a destroyed node — which is why both
|
|
188
|
+
overlay sets guard their one button with `isAlive`.
|
|
189
|
+
|
|
190
|
+
**`isAlive` alone is wrong here, and it throws rather than answering.** The four
|
|
191
|
+
model shapes in `chromeOverlays.ts` are structural on purpose ("A display
|
|
192
|
+
satisfies one by having the fields; no mixin has to be composed"), so a host
|
|
193
|
+
writing their own display over `DisplayChromeBase` may hand these components a
|
|
194
|
+
plain object. `isAlive` runs `assertIsStateTreeNode` and throws on one, inside
|
|
195
|
+
an event handler, where React logs it and moves on — leaving the Force load
|
|
196
|
+
button looking live and doing nothing, which is the exact state
|
|
197
|
+
`DisplayChromeOverlays.TooLarge` documents itself as existing to prevent.
|
|
198
|
+
|
|
199
|
+
A plain object is never destroyed, so it is always callable. The liveness
|
|
200
|
+
question only exists for an MST node.
|
|
201
|
+
|
|
202
|
+
```js
|
|
203
|
+
// type signature
|
|
204
|
+
(model: unknown) => boolean
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/isLiveModel.ts)
|
|
208
|
+
|
|
209
|
+
### plainChromeOverlays
|
|
210
|
+
|
|
211
|
+
The five `displayPhase` states drawn with no UI toolkit: no theme provider to
|
|
212
|
+
mount, no emotion in the host page, and nothing that reads as a stray Material
|
|
213
|
+
widget inside someone else's design system.
|
|
214
|
+
|
|
215
|
+
`DisplayUIProvider` installs this by default, so mount that rather than naming
|
|
216
|
+
this — reach for it directly only to wrap a state or to build a context value by
|
|
217
|
+
hand. Colours come from `currentColor` and the CSS system colours, so the host's
|
|
218
|
+
own cascade drives them in both light and dark.
|
|
219
|
+
|
|
220
|
+
The `data-testid` values it renders are a contract four of JBrowse's test
|
|
221
|
+
systems key on, so a replacement set that keeps them can be driven by those
|
|
222
|
+
suites too.
|
|
223
|
+
|
|
224
|
+
```js
|
|
225
|
+
// type signature
|
|
226
|
+
DisplayChromeOverlays
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/plainChromeOverlays.tsx)
|
|
230
|
+
|
|
231
|
+
### PlainTrackControl
|
|
232
|
+
|
|
233
|
+
A display's ambient bottom-right control — track sizing, the isoform notice, the
|
|
234
|
+
show-only badge — drawn with no UI toolkit, the corner-control counterpart of
|
|
235
|
+
`plainChromeOverlays`.
|
|
236
|
+
|
|
237
|
+
`DisplayUIProvider` installs this by default. The behaviour is not in here:
|
|
238
|
+
dismissal, the keyboard, focus, the top layer and the anchoring are
|
|
239
|
+
`useTrackControlMenu`, so writing your own control means writing markup rather
|
|
240
|
+
than re-deriving why the menu opens upward.
|
|
241
|
+
|
|
242
|
+
The package exports it as `plainTrackControl`, lower-cased to match
|
|
243
|
+
`plainChromeOverlays` — the two are a pair, and both are things you hand to a
|
|
244
|
+
provider rather than render yourself.
|
|
245
|
+
|
|
246
|
+
```js
|
|
247
|
+
// type signature
|
|
248
|
+
({ icon, tooltip, label, options, onClick, onMenuClose, onDelete, warning, }: TrackControlProps) => Element
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/trackControl/plainTrackControl.tsx)
|
|
252
|
+
|
|
253
|
+
### tooLargeBannerText
|
|
254
|
+
|
|
255
|
+
Which axis tripped (empty when the display gates without a reason), then the way
|
|
256
|
+
out.
|
|
257
|
+
|
|
258
|
+
`zoomCanRelease` decides whether "zoom in" is offered, and it has to be asked
|
|
259
|
+
because the advice is not always true. It was, once: the `AUTO_FORCE_LOAD_BP`
|
|
260
|
+
floor turned the byte gate off below 20kb, so zooming far enough always worked.
|
|
261
|
+
The byte gate no longer stops at any floor, and an index quotes whole blocks —
|
|
262
|
+
so for a file whose blocks are large the same bytes come down however far the
|
|
263
|
+
user goes, and telling them to keep zooming into a fetch whose cost cannot fall
|
|
264
|
+
is the one thing the banner must not do. `zoomCanReleaseGate` answers it from
|
|
265
|
+
two consecutive measurements rather than from a threshold; see
|
|
266
|
+
`ByteEstimate.zoomIneffective`.
|
|
267
|
+
|
|
268
|
+
```js
|
|
269
|
+
// type signature
|
|
270
|
+
(regionTooLargeReason: string, { zoomCanRelease }?: { zoomCanRelease?: boolean | undefined; }) => string
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/tooLargeBannerText.ts)
|
|
274
|
+
|
|
275
|
+
### Tooltip
|
|
276
|
+
|
|
277
|
+
A hover/focus label for a control, drawn rather than delegated to the browser's
|
|
278
|
+
`title` attribute — positioned so it clears the display's `contain: strict` box
|
|
279
|
+
and the window edge, dismissed by Escape, and drawn like every other JBrowse
|
|
280
|
+
tooltip instead of like whatever the host OS renders.
|
|
281
|
+
|
|
282
|
+
`title` is what this chrome used to use, and it was the wrong tool three ways:
|
|
283
|
+
it can be neither styled nor positioned, it waits about a second and then
|
|
284
|
+
disappears on a timer of its own, and on a control that already carries an
|
|
285
|
+
`aria-label` some screen readers announce both strings. This reaches no UI
|
|
286
|
+
toolkit, so the package's no-Material-UI guarantee holds.
|
|
287
|
+
|
|
288
|
+
Takes a single element child and clones it rather than wrapping it: the controls
|
|
289
|
+
that want a tooltip are absolutely positioned inside a legend or sit in a flex
|
|
290
|
+
row, where an extra `<span>` moves them. The child keeps its own handlers —
|
|
291
|
+
these compose on top of them. This is the same trigger pattern MUI's own
|
|
292
|
+
`Tooltip` uses, which is what the rest of JBrowse's chrome is built on; the
|
|
293
|
+
toolkit is what differs here, not the shape.
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
<Tooltip title="Hide legend">
|
|
297
|
+
<button type="button" aria-label="Hide legend" onClick={onDismiss}>
|
|
298
|
+
×
|
|
299
|
+
</button>
|
|
300
|
+
</Tooltip>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**The child still needs its own accessible name**, because this sets
|
|
304
|
+
`aria-describedby` and never `aria-label` — see useTooltip, which is this
|
|
305
|
+
without the cloning, for a host writing its own markup.
|
|
306
|
+
|
|
307
|
+
```js
|
|
308
|
+
// type signature
|
|
309
|
+
({ title, placement, children, }: { title: ReactNode; placement?: TooltipPlacement | undefined; children: ReactElement<…>; }) => Element
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/tooltip/Tooltip.tsx)
|
|
313
|
+
|
|
314
|
+
### TrackOverlayPortal
|
|
315
|
+
|
|
316
|
+
Lift floating track chrome out of the display's `contain: strict` sandbox and
|
|
317
|
+
into the host's overlay node, so the LGV's inter-region masks cannot bury it at
|
|
318
|
+
multi-region scale. `TrackOverlaySlot` is the other end.
|
|
319
|
+
|
|
320
|
+
The overlay node takes no pointer events, so anything of yours the user hovers
|
|
321
|
+
or clicks sets `pointer-events: auto` on its own positioned box.
|
|
322
|
+
|
|
323
|
+
With no slot above it this renders the children in place (`fallbackInline`, the
|
|
324
|
+
default), which preserves chrome that is still meaningful unescaped. Pass
|
|
325
|
+
`fallbackInline={false}` for chrome that only makes sense above the masks and
|
|
326
|
+
draws itself some other way elsewhere.
|
|
327
|
+
|
|
328
|
+
```js
|
|
329
|
+
// type signature
|
|
330
|
+
({ children, fallbackInline, }: { children: ReactNode; fallbackInline?: boolean | undefined; }) => ReactNode
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/trackOverlay/TrackOverlayPortal.tsx)
|
|
334
|
+
|
|
335
|
+
### TrackOverlaySlot
|
|
336
|
+
|
|
337
|
+
The box a display is mounted in, plus the overlay node its floating chrome
|
|
338
|
+
escapes into. Pair to `TrackOverlayPortal`, which is the other end.
|
|
339
|
+
|
|
340
|
+
A display's React tree is sealed in a `contain: strict` sandbox — that is what
|
|
341
|
+
isolates its paint, and dropping it is measured and rejected (ADR-058). A
|
|
342
|
+
stacking context comes with the isolation, so floating chrome a display draws (a
|
|
343
|
+
colour key, hi-c's overlay panel, maf's row labels) cannot out-z-index anything
|
|
344
|
+
painted over the track stack from outside. The escape is a node mounted _beside_
|
|
345
|
+
the sandbox rather than inside it, published through `TrackOverlayContext`; this
|
|
346
|
+
component is that node, its context and the paint order between them, in the one
|
|
347
|
+
place they have to agree.
|
|
348
|
+
|
|
349
|
+
`TrackContainer` uses it, so JBrowse's own layout and an embedder's go through
|
|
350
|
+
the same code rather than two copies of one rule. **An embedder mounting
|
|
351
|
+
`RenderingComponent` directly needs it too**, and that is the case it was added
|
|
352
|
+
for: with no provider the context is null, the portal falls back to rendering
|
|
353
|
+
inline, and a host that paints region seams over its column buries the chrome
|
|
354
|
+
under them with nothing to say so.
|
|
355
|
+
|
|
356
|
+
```tsx
|
|
357
|
+
<TrackOverlaySlot zIndex={3} style={{ height: display.height }}>
|
|
358
|
+
<div style={{ position: 'absolute', inset: 0, contain: 'strict' }}>
|
|
359
|
+
<RenderingComponent model={display} />
|
|
360
|
+
</div>
|
|
361
|
+
</TrackOverlaySlot>
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**`zIndex` is required, and deliberately has no default.** It is the answer to
|
|
365
|
+
"above what?", and that is a fact about the caller's layout rather than about
|
|
366
|
+
this component: JBrowse's own track container passes 100, which is positioned
|
|
367
|
+
above `PaddingBlocks` and below `TrackLabel` at 200, and means nothing to a host
|
|
368
|
+
whose masks sit at 2. A default would be a number that is right in one layout
|
|
369
|
+
and silently wrong in every other, and the failure — chrome painted under a mask
|
|
370
|
+
— is invisible until someone looks at the right zoom.
|
|
371
|
+
|
|
372
|
+
The node takes no pointer events, so it does not eat the canvas's. Chrome that
|
|
373
|
+
wants them takes them back on its own positioned box; it also carries
|
|
374
|
+
`data-gesture-owner`, so anything that does is already exempt from the LGV's
|
|
375
|
+
click-drag pan.
|
|
376
|
+
|
|
377
|
+
```js
|
|
378
|
+
// type signature
|
|
379
|
+
({ children, zIndex, style, overlayStyle, }: { children: ReactNode; zIndex: number; style?: CSSProperties | undefined; overlayStyle?: CSSProperties | undefined; }) => Element
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/trackOverlay/TrackOverlaySlot.tsx)
|
|
383
|
+
|
|
384
|
+
### useTooltip
|
|
385
|
+
|
|
386
|
+
A hover/focus label for one control, as props to spread — the headless half of
|
|
387
|
+
Tooltip, for a host writing its own chrome rather than restyling ours. Same
|
|
388
|
+
relationship `useTrackControlMenu` has to `plainTrackControl`.
|
|
389
|
+
|
|
390
|
+
```tsx
|
|
391
|
+
const { triggerProps, tooltip } = useTooltip('Hide legend')
|
|
392
|
+
return (
|
|
393
|
+
<>
|
|
394
|
+
<button {...triggerProps} aria-label="Hide legend" onClick={onDismiss}>
|
|
395
|
+
×
|
|
396
|
+
</button>
|
|
397
|
+
{tooltip}
|
|
398
|
+
</>
|
|
399
|
+
)
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
`triggerProps` carries no `onClick`, so a control's own handler does not collide
|
|
403
|
+
with it. Any other handler on this list has to compose rather than replace —
|
|
404
|
+
spread first, then call `triggerProps.onFocus` from yours.
|
|
405
|
+
|
|
406
|
+
```js
|
|
407
|
+
// type signature
|
|
408
|
+
(title: ReactNode, { placement }?: { placement?: TooltipPlacement | undefined; }) => TooltipTrigger
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/tooltip/useTooltip.tsx)
|
|
412
|
+
|
|
413
|
+
### useTrackControlMenu
|
|
414
|
+
|
|
415
|
+
The behaviour behind a bottom-right track control's menu, as prop getters to
|
|
416
|
+
spread — dismissal (Escape, an outside press, an ancestor scrolling), the
|
|
417
|
+
keyboard (arrows, Home/End), focus, and the anchoring that clears both the
|
|
418
|
+
display's `contain: strict` box and the window edge.
|
|
419
|
+
|
|
420
|
+
For writing your own control rather than restyling `plainTrackControl`: each of
|
|
421
|
+
those rules is a bug when missed and none of them shows up in a screenshot.
|
|
422
|
+
Render `menuProps` only while `open`, and portal it to `document.body` —
|
|
423
|
+
`createPortal` is the caller's to aim, the maths is here. `menuProps.style`
|
|
424
|
+
carries position only.
|
|
425
|
+
|
|
426
|
+
```js
|
|
427
|
+
// type signature
|
|
428
|
+
(onClose?: (() => void) | undefined) => TrackControlMenu
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
[Source code](https://github.com/GMOD/jbrowse-components/blob/main/packages/display-ui/src/trackControl/useTrackControlMenu.tsx)
|
|
432
|
+
|
|
433
|
+
<!-- API_DOCS_END -->
|