@jbrowse/display-ui 5.0.0-beta.11 → 5.0.0-beta.13

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.
@@ -223,7 +223,7 @@ const LegendItemList = observer(function LegendItemList({ items, maxItems, onIte
223
223
  }
224
224
  const row = (_jsxs(_Fragment, { children: [_jsx("div", { className: classes.swatches, style: { minWidth: columns * SWATCH + (columns - 1) * 2 }, children: legendSwatches(item).map(swatch => (_jsx("svg", { width: SWATCH, height: SWATCH, children: _jsx(LegendSwatchGlyph, { swatch: swatch, size: SWATCH }) }, `${swatch.shape}-${swatch.color}`))) }), _jsx("span", { className: classes.label, children: item.label })] }));
225
225
  const itemClass = cx(classes.item, item.hidden && classes.hiddenItem);
226
- return onItemClick ? (_jsx("button", { type: "button", className: cx(itemClass, classes.itemButton), title: "Show only these rows", onClick: () => {
226
+ return onItemClick && legendSwatches(item).length > 0 ? (_jsx("button", { type: "button", className: cx(itemClass, classes.itemButton), title: "Show only these rows", onClick: () => {
227
227
  onItemClick(item);
228
228
  }, children: row }, `${item.label}-${i}`)) : (_jsx("div", { className: itemClass, children: row }, `${item.label}-${i}`));
229
229
  }), collapsible ? (_jsx("button", { type: "button", className: classes.toggle, onClick: () => {
@@ -239,6 +239,10 @@ const LegendItemList = observer(function LegendItemList({ items, maxItems, onIte
239
239
  // `onItemClick` makes the rows of a section declaring `focusesRows` act —
240
240
  // clicking an entry focuses the rows it names. A section coloring features or
241
241
  // cells stays inert text beside it.
242
+ //
243
+ // The key covers data at the lane's top right, an overlap Colin accepted on
244
+ // 2026-09-30. A lane shorter than the key scrolls it rather than clipping it,
245
+ // which a still cannot show, so a figure gives that lane more height.
242
246
  const FloatingLegend = observer(function FloatingLegend({ sections, title, onDismiss, onDismissSection, onItemClick, maxItems = DEFAULT_MAX_ITEMS, maxWidth = DEFAULT_MAX_WIDTH, top = FLOATING_LEGEND_TOP_PX, right = FLOATING_LEGEND_RIGHT_PX, }) {
243
247
  const { classes } = useStyles();
244
248
  const nonEmpty = nonEmptyLegendSections(sections);
@@ -34,8 +34,9 @@ export declare function FloatingText({ x, y, color, fontSize, halo, style, child
34
34
  * The same line in an SVG export: two `<text>`s at the baseline `y`, a stroke
35
35
  * in the surface colour under the glyphs, since SVG paints stroke over fill
36
36
  * and a thick stroke beneath a second copy is how a halo is drawn there. Both
37
- * carry the size and family explicitly, because a `<text>` with neither takes
38
- * SVG's 16px default in a saved file.
37
+ * carry the size, because a `<text>` without one takes SVG's 16px default in a
38
+ * saved file. An export leaves `fontFamily` out, so the label inherits the
39
+ * family the export dialog put on the root.
39
40
  */
40
41
  export declare function SvgHaloText({ x, y, fill, halo, haloWidth, fontSize, fontFamily, anchor, children, }: {
41
42
  x: number;
@@ -44,7 +45,7 @@ export declare function SvgHaloText({ x, y, fill, halo, haloWidth, fontSize, fon
44
45
  halo: string;
45
46
  haloWidth: number | string;
46
47
  fontSize: number;
47
- fontFamily: string;
48
+ fontFamily?: string;
48
49
  anchor?: 'start' | 'middle' | 'end';
49
50
  children: ReactNode;
50
51
  }): import("react").JSX.Element;
@@ -39,8 +39,9 @@ export function FloatingText({ x, y, color, fontSize, halo, style, children, ...
39
39
  * The same line in an SVG export: two `<text>`s at the baseline `y`, a stroke
40
40
  * in the surface colour under the glyphs, since SVG paints stroke over fill
41
41
  * and a thick stroke beneath a second copy is how a halo is drawn there. Both
42
- * carry the size and family explicitly, because a `<text>` with neither takes
43
- * SVG's 16px default in a saved file.
42
+ * carry the size, because a `<text>` without one takes SVG's 16px default in a
43
+ * saved file. An export leaves `fontFamily` out, so the label inherits the
44
+ * family the export dialog put on the root.
44
45
  */
45
46
  export function SvgHaloText({ x, y, fill, halo, haloWidth, fontSize, fontFamily, anchor = 'start', children, }) {
46
47
  const attrs = { x, y, fontSize, fontFamily, textAnchor: anchor };
@@ -30,11 +30,12 @@ export declare function axisCaptionY(axis: Pick<YAxis, 'ticks'>, bandTops: numbe
30
30
  */
31
31
  export declare function axisGutterWidth(axis: Pick<YAxis, 'ticks' | 'caption'>): number;
32
32
  /**
33
- * Px the export's left margin holds for these axes: the widest left-side axis
34
- * that draws, 0 when none does. A sidebar the export parks left of the figure
35
- * sits past this strip so the scalebars stay beside the plot.
33
+ * Px the export's left margin holds for these axes, 0 when no left-side axis
34
+ * draws. `axisGutterLeft` puts every left axis's outer edge this far out, a
35
+ * wider gutter growing inward over the plot, so a sidebar the export parks left
36
+ * of the figure sits past this strip.
36
37
  */
37
- export declare function leftAxisGutterWidth(axes: readonly Pick<YAxis, 'side' | 'ticks' | 'caption' | 'height' | 'bandTops'>[]): number;
38
+ export declare function leftAxisGutterWidth(axes: readonly Pick<YAxis, 'side' | 'height' | 'bandTops'>[]): 0 | 50;
38
39
  /** How far in from the plot's right edge a right-side gutter ends in an export. */
39
40
  export declare const AXIS_RIGHT_INSET_PX = 4;
40
41
  /**
@@ -48,14 +48,15 @@ export function axisGutterWidth(axis) {
48
48
  return Math.max(AXIS_GUTTER_WIDTH_PX, Math.ceil(CAPTION_BAND_PX + widest + TICK_LABEL_X_PX));
49
49
  }
50
50
  /**
51
- * Px the export's left margin holds for these axes: the widest left-side axis
52
- * that draws, 0 when none does. A sidebar the export parks left of the figure
53
- * sits past this strip so the scalebars stay beside the plot.
51
+ * Px the export's left margin holds for these axes, 0 when no left-side axis
52
+ * draws. `axisGutterLeft` puts every left axis's outer edge this far out, a
53
+ * wider gutter growing inward over the plot, so a sidebar the export parks left
54
+ * of the figure sits past this strip.
54
55
  */
55
56
  export function leftAxisGutterWidth(axes) {
56
- return Math.max(0, ...axes
57
- .filter(axis => axis.side !== 'right' && axisDrawn(axis))
58
- .map(axisGutterWidth));
57
+ return axes.some(axis => axis.side !== 'right' && axisDrawn(axis))
58
+ ? AXIS_GUTTER_WIDTH_PX
59
+ : 0;
59
60
  }
60
61
  /** How far in from the plot's right edge a right-side gutter ends in an export. */
61
62
  export const AXIS_RIGHT_INSET_PX = 4;
@@ -1,4 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { isRegionTooLargeError } from '@jbrowse/core/rpc/byteBudget';
2
3
  // the subpath, not the `@jbrowse/core/ui` barrel: this file is the MUI-free
3
4
  // chrome, and gpuFallback.ts is React-free for exactly that reason
4
5
  import { GPU_FALLBACK_LABEL, GPU_FALLBACK_TOOLTIP, disableGpuRendering, shouldOfferGpuFallback, } from '@jbrowse/core/ui/gpuFallback';
@@ -137,9 +138,13 @@ const PlainTooLarge = observer(function PlainTooLarge({ model, }) {
137
138
  }, children: "Force load" })] }));
138
139
  });
139
140
  const PlainErrorBar = observer(function PlainErrorBar({ model, visible, }) {
140
- return visible && model.error ? (_jsx("div", { style: overlayBox, role: "alert", children: _jsxs("div", { style: chip, children: [_jsx("span", { style: { wordBreak: 'break-word' }, children: errorText(model.error) }), _jsx("button", { type: "button", style: button, "data-testid": "reload_button", onClick: () => {
141
+ const { error } = model;
142
+ if (!visible || !error) {
143
+ return null;
144
+ }
145
+ return isRegionTooLargeError(error) ? (_jsx("div", { style: overlayBox, role: "status", children: _jsx("div", { style: chip, children: _jsx("span", { style: { wordBreak: 'break-word' }, children: error.message }) }) })) : (_jsx("div", { style: overlayBox, role: "alert", children: _jsxs("div", { style: chip, children: [_jsx("span", { style: { wordBreak: 'break-word' }, children: errorText(error) }), _jsx("button", { type: "button", style: button, "data-testid": "reload_button", onClick: () => {
141
146
  model.reload();
142
- }, children: "Retry" })] }) })) : null;
147
+ }, children: "Retry" })] }) }));
143
148
  });
144
149
  // No anti-flash delay here, unlike the MUI set: that timing is a product
145
150
  // judgment JBrowse made for its own UI, and an embedder pacing their own
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/display-ui",
3
- "version": "5.0.0-beta.11",
3
+ "version": "5.0.0-beta.13",
4
4
  "type": "module",
5
5
  "description": "The UI a display draws that is not data: the swappable chrome contract, its toolkit-free implementations, and the track overlay layer",
6
6
  "keywords": [
@@ -30,9 +30,9 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@jbrowse/mobx-state-tree": "^6.7.0",
33
- "mobx": "^7.0.5",
33
+ "mobx": "^7.0.6",
34
34
  "mobx-react": "^10.0.2",
35
- "@jbrowse/core": "^5.0.0-beta.11"
35
+ "@jbrowse/core": "^5.0.0-beta.13"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "react": ">=19.0.0",