@jbrowse/core 5.0.0-beta.4 → 5.0.0-beta.8

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 (110) hide show
  1. package/README.md +278 -250
  2. package/esm/PluginManager.js +1 -1
  3. package/esm/ReExports/publicUi.d.ts +1 -1
  4. package/esm/ReExports/publicUi.js +1 -1
  5. package/esm/ReExports/publicUtil.d.ts +1 -1
  6. package/esm/ReExports/publicUtil.js +1 -1
  7. package/esm/ReExports/workerNamespaceNames.js +3 -9
  8. package/esm/assemblyManager/assemblyConfigSchema.d.ts +2 -1
  9. package/esm/assemblyManager/assemblyConfigSchema.js +2 -1
  10. package/esm/assemblyManager/expandAssemblyConfigShorthand.d.ts +15 -15
  11. package/esm/assemblyManager/expandAssemblyConfigShorthand.js +34 -18
  12. package/esm/configuration/configurationSchema.d.ts +1 -2
  13. package/esm/configuration/configurationSchema.js +3 -8
  14. package/esm/configuration/configurationSlot.d.ts +0 -47
  15. package/esm/configuration/configurationSlot.js +4 -54
  16. package/esm/configuration/fillLocations.d.ts +14 -0
  17. package/esm/configuration/fillLocations.js +14 -0
  18. package/esm/configuration/fullConfSnapshot.d.ts +0 -15
  19. package/esm/configuration/fullConfSnapshot.js +0 -28
  20. package/esm/configuration/getConf.d.ts +4 -34
  21. package/esm/configuration/getConf.js +3 -38
  22. package/esm/configuration/index.d.ts +3 -4
  23. package/esm/configuration/index.js +3 -2
  24. package/esm/configuration/schemaRegistry.d.ts +1 -2
  25. package/esm/configuration/schemaRegistry.js +1 -2
  26. package/esm/configuration/slotFacade.d.ts +1 -16
  27. package/esm/configuration/slotFacade.js +1 -2
  28. package/esm/configuration/tabixShorthand.js +3 -3
  29. package/esm/configuration/types.d.ts +4 -16
  30. package/esm/data_adapters/CytobandAdapter/configSchema.js +3 -4
  31. package/esm/pluggableElementTypes/DisplayType.d.ts +5 -3
  32. package/esm/pluggableElementTypes/DisplayType.js +3 -1
  33. package/esm/pluggableElementTypes/models/BaseTrackModel.d.ts +30 -0
  34. package/esm/pluggableElementTypes/models/BaseTrackModel.js +45 -17
  35. package/esm/rpc/RpcRegistry.d.ts +7 -1
  36. package/esm/rpc/coreRpcMethods.d.ts +1 -0
  37. package/esm/rpc/coreRpcMethods.js +1 -0
  38. package/esm/rpc/methods/CoreEncodeFeatures.d.ts +15 -0
  39. package/esm/rpc/methods/CoreEncodeFeatures.js +62 -0
  40. package/esm/svg/svgId.d.ts +1 -1
  41. package/esm/svg/svgId.js +1 -1
  42. package/esm/ui/LegendSwatchGlyph.js +26 -21
  43. package/esm/ui/MenuTypes.d.ts +5 -52
  44. package/esm/ui/SizeSliderRow.d.ts +1 -3
  45. package/esm/ui/SizeSliderRow.js +4 -6
  46. package/esm/ui/SvgColorLegend.d.ts +9 -3
  47. package/esm/ui/SvgColorLegend.js +74 -33
  48. package/esm/ui/colorScale.d.ts +64 -0
  49. package/esm/ui/colorScale.js +41 -0
  50. package/esm/ui/colors.d.ts +11 -0
  51. package/esm/ui/colors.js +7 -0
  52. package/esm/ui/index.d.ts +5 -7
  53. package/esm/ui/index.js +3 -13
  54. package/esm/ui/legendMenuItem.d.ts +5 -16
  55. package/esm/ui/legendMenuItem.js +3 -14
  56. package/esm/ui/legendSpec.d.ts +11 -5
  57. package/esm/ui/legendSpec.js +8 -11
  58. package/esm/ui/makeSizeMenu.d.ts +0 -6
  59. package/esm/ui/makeSizeMenu.js +6 -30
  60. package/esm/ui/measureLegendText.js +1 -1
  61. package/esm/ui/menuItemAdornment.d.ts +9 -19
  62. package/esm/ui/menuItemAdornment.js +10 -31
  63. package/esm/ui/menuItems.d.ts +2 -6
  64. package/esm/ui/menuItems.js +0 -4
  65. package/esm/ui/palette.js +2 -1
  66. package/esm/ui/toggleMenuItems.d.ts +6 -13
  67. package/esm/ui/toggleMenuItems.js +13 -29
  68. package/esm/util/colorRamp.d.ts +3 -3
  69. package/esm/util/colorRamp.js +2 -2
  70. package/esm/util/featureTransforms.d.ts +15 -0
  71. package/esm/util/featureTransforms.js +342 -0
  72. package/esm/util/freezeDeep.d.ts +8 -10
  73. package/esm/util/freezeDeep.js +8 -10
  74. package/esm/util/glyphNames.d.ts +8 -0
  75. package/esm/util/glyphNames.js +12 -0
  76. package/esm/util/index.d.ts +0 -1
  77. package/esm/util/index.js +0 -1
  78. package/esm/util/markEncoding.d.ts +76 -0
  79. package/esm/util/markEncoding.js +436 -0
  80. package/esm/util/markEncodingTypes.d.ts +331 -0
  81. package/esm/util/markEncodingTypes.js +8 -0
  82. package/esm/util/renderToStaticMarkup.js +1 -1
  83. package/esm/util/starFusion.d.ts +26 -0
  84. package/esm/util/starFusion.js +37 -0
  85. package/esm/util/trackConfigDelta.d.ts +4 -8
  86. package/esm/util/trackConfigDelta.js +2 -4
  87. package/esm/util/tracks.d.ts +7 -1
  88. package/esm/util/tracks.js +72 -7
  89. package/esm/util/types/index.d.ts +12 -4
  90. package/esm/util/whenViewSettled.d.ts +9 -0
  91. package/esm/util/whenViewSettled.js +12 -4
  92. package/package.json +13 -3
  93. package/esm/configuration/promotableDefaults.d.ts +0 -234
  94. package/esm/configuration/promotableDefaults.js +0 -395
  95. package/esm/configuration/promotablePin.d.ts +0 -65
  96. package/esm/configuration/promotablePin.js +0 -1
  97. package/esm/configuration/promotableResolve.d.ts +0 -108
  98. package/esm/configuration/promotableResolve.js +0 -117
  99. package/esm/configuration/promotableSlots.d.ts +0 -12
  100. package/esm/configuration/promotableSlots.js +0 -45
  101. package/esm/configuration/slotShape.d.ts +0 -12
  102. package/esm/configuration/slotShape.js +0 -84
  103. package/esm/ui/PinAdornment.d.ts +0 -5
  104. package/esm/ui/PinAdornment.js +0 -67
  105. package/esm/ui/SvgGradientLegend.d.ts +0 -26
  106. package/esm/ui/SvgGradientLegend.js +0 -26
  107. package/esm/ui/promotablePinCoverage.d.ts +0 -58
  108. package/esm/ui/promotablePinCoverage.js +0 -124
  109. package/esm/util/openDisplays.d.ts +0 -23
  110. package/esm/util/openDisplays.js +0 -79
@@ -1,8 +1,13 @@
1
- import type { ReactNode } from 'react';
2
- export type LegendMark = 'fill' | 'line' | 'curve';
1
+ import type { GlyphName } from '../util/markEncodingTypes.ts';
2
+ import type { RampStop } from './colorScale.ts';
3
3
  export interface LegendSwatch {
4
4
  color: string;
5
- mark?: LegendMark;
5
+ glyph?: GlyphName;
6
+ }
7
+ export interface LegendGradient {
8
+ stops: RampStop[];
9
+ minLabel: string;
10
+ maxLabel: string;
6
11
  }
7
12
  export interface ColorLegendEntry {
8
13
  key: string;
@@ -10,12 +15,13 @@ export interface ColorLegendEntry {
10
15
  color?: string;
11
16
  swatches?: LegendSwatch[];
12
17
  hidden?: boolean;
13
- marker?: ReactNode;
18
+ gradient?: LegendGradient;
14
19
  }
15
20
  export interface LegendItem {
21
+ value?: string;
16
22
  color?: string;
17
- mark?: LegendMark;
18
23
  swatches?: LegendSwatch[];
24
+ gradient?: LegendGradient;
19
25
  label: string;
20
26
  hidden?: boolean;
21
27
  }
@@ -1,8 +1,7 @@
1
- // The marks a row draws: its explicit list, else its single color/mark pair,
2
- // else nothing at all (a heading).
1
+ // The boxes a row draws: its explicit list, else its single color, else nothing
2
+ // at all (a heading).
3
3
  export function legendSwatches(item) {
4
- return (item.swatches ??
5
- (item.color === undefined ? [] : [{ color: item.color, mark: item.mark }]));
4
+ return (item.swatches ?? (item.color === undefined ? [] : [{ color: item.color }]));
6
5
  }
7
6
  // Drop sections with nothing in them, so a heading can never end up with no
8
7
  // swatches under it.
@@ -32,19 +31,17 @@ export function legendEntries(spec) {
32
31
  color: item.color,
33
32
  swatches: exportSwatches(item),
34
33
  hidden: item.hidden,
34
+ gradient: item.gradient,
35
35
  })),
36
36
  ]),
37
37
  ];
38
38
  }
39
- // A single filled swatch is what `color` alone already draws, so only a row
40
- // that says something more — several marks, or one that isn't a fill — carries
41
- // the list into the export. Keeps the common entry the three fields it has
42
- // always been.
39
+ // A single swatch is what `color` alone already draws, so only a row showing
40
+ // several colors carries the list into the export. Keeps the common entry the
41
+ // three fields it has always been.
43
42
  function exportSwatches(item) {
44
43
  const swatches = legendSwatches(item);
45
- return swatches.length > 1 || swatches.some(s => s.mark && s.mark !== 'fill')
46
- ? swatches
47
- : undefined;
44
+ return swatches.length > 1 ? swatches : undefined;
48
45
  }
49
46
  /**
50
47
  * How many rows a color key may have and still be one. Past this it is a list
@@ -1,5 +1,3 @@
1
- import type { ResolvableDisplay } from '../configuration/promotableResolve.ts';
2
- import type { AnyConfigurationModel, ConfigurationSchemaForModel, ConfigurationSlotName } from '../configuration/types.ts';
3
1
  import type { MenuItem } from './MenuTypes.ts';
4
2
  import type { SliderScale } from './sliderScale.ts';
5
3
  interface SizeMenuOptions {
@@ -23,8 +21,4 @@ export declare function makeSizeMenu(opts: SizeMenuOptions & {
23
21
  export declare function makeSizeSubMenu(opts: SizeMenuOptions & {
24
22
  isDefault: boolean;
25
23
  }): MenuItem;
26
- export declare function makePromotableSizeMenu<CONFMODEL extends AnyConfigurationModel, SLOT extends ConfigurationSlotName<ConfigurationSchemaForModel<CONFMODEL>>>(opts: SizeMenuOptions & {
27
- display: ResolvableDisplay<CONFMODEL>;
28
- slot: SLOT;
29
- }): MenuItem;
30
24
  export {};
@@ -1,10 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Suspense, lazy } from 'react';
3
- import { isSlotCustomized, makePin, } from '../configuration/promotableDefaults.js';
4
3
  import { INLINE_MENU_ROW_WIDTH } from './inlineMenuRowWidth.js';
5
- // The row's drawn half is `lazy()` for the reason the promotable pin is a
6
- // description rather than an element: this builder is called from state models
7
- // and menu modules, which are eager, and the row is the only route by which MUI
4
+ // The row's drawn half is `lazy()` because this builder is called from state
5
+ // models and menu modules, which are eager, and the row is the only route by
6
+ // which MUI
8
7
  // `Slider` — the largest single Material component in the eager graph — reached
9
8
  // a host's first paint. `type: 'custom'` already made `render` a thunk, so the
10
9
  // laziness is free at call time; it is the module edge that had to go.
@@ -20,10 +19,8 @@ const sizeRowFallbackHeight = 46;
20
19
  // accessors + a title (which also derives the slider's test id). Used by wiggle
21
20
  // point-size/line-width, GWAS Manhattan point-size, arc width, the alignments
22
21
  // modification threshold and GC-content window/step sizes, so the
23
- // slider/reset/pin behavior can't drift. Pass `scale: 'log'` for values spanning
22
+ // slider/reset behavior can't drift. Pass `scale: 'log'` for values spanning
24
23
  // orders of magnitude, and `format` to label non-`px` units.
25
- //
26
- // For a row over a promotable slot use `makePromotableSizeMenu`.
27
24
  export function makeSizeMenu(opts) {
28
25
  return sizeMenu(opts, opts.isDefault);
29
26
  }
@@ -48,35 +45,14 @@ export function makeSizeSubMenu(opts) {
48
45
  subMenu: [makeSizeMenu(opts)],
49
46
  };
50
47
  }
51
- // The same row over a **promotable** slot, which derives both halves the plain
52
- // form takes by hand — the reset button's enablement (`isSlotCustomized`) and
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 carries whatever the track is
55
- // currently showing.
56
- //
57
- // Naming the slot once is the point: the call sites used to spell it twice, in
58
- // `isDefault` and again in the pin, with nothing checking the two agreed.
59
- export function makePromotableSizeMenu(opts) {
60
- const { display, slot } = opts;
61
- return sizeMenu(opts, !isSlotCustomized(display, slot), makePin(display, slot));
62
- }
63
- function sizeMenu(opts, isDefault, pin) {
48
+ function sizeMenu(opts, isDefault) {
64
49
  const { label, title, getValue, min = 0.5, max = 12, step = 0.5, unit = 'px', scale = 'linear', format = (n) => `${n}${unit}`, commitOnRelease, onChange, onReset, } = opts;
65
50
  return {
66
51
  label,
67
52
  type: 'custom',
68
- // Declared even though `SizeSliderRow` below is what draws it: a custom row
69
- // never reaches the shared trailing column, so without this the pin exists
70
- // on screen and is invisible to `pinnedSlots` — which is the difference
71
- // between a promotable slot that is genuinely unreachable and one that just
72
- // renders its own control. See `hasMenuItemAdornment` for why declaring it
73
- // costs no layout.
74
- ...(pin && {
75
- pin: { control: pin, label: title },
76
- }),
77
53
  render: () => (_jsx(Suspense, { fallback: _jsx("div", { style: {
78
54
  width: INLINE_MENU_ROW_WIDTH,
79
55
  height: sizeRowFallbackHeight,
80
- } }), children: _jsx(SizeSliderRow, { title: title, getValue: getValue, min: min, max: max, step: step, scale: scale, format: format, isDefault: isDefault, commitOnRelease: commitOnRelease, onChange: onChange, onReset: onReset, pin: pin }) })),
56
+ } }), children: _jsx(SizeSliderRow, { title: title, getValue: getValue, min: min, max: max, step: step, scale: scale, format: format, isDefault: isDefault, commitOnRelease: commitOnRelease, onChange: onChange, onReset: onReset }) })),
81
57
  };
82
58
  }
@@ -1,4 +1,4 @@
1
- import { measureText } from '../util/index.js';
1
+ import { measureText } from '../util/measureText.js';
2
2
  // measureText uses a Helvetica width table, but SVG legend <text> nodes have no
3
3
  // font-family and render in the wider app font (Roboto), so scale the estimate
4
4
  // up before sizing the white paper behind a label or it clips.
@@ -2,31 +2,21 @@ import type { MenuItem } from './MenuTypes.ts';
2
2
  /**
3
3
  * The trailing control a menu row draws, resolved at the point of drawing.
4
4
  *
5
- * Two fields feed it and they are not equivalent. `endAdornment` is an element
6
- * the builder already made — the escape hatch, for content nothing else can
7
- * describe. `pin` is a *description* of the "default for all tracks of
8
- * this type" pin, and turning it into `PinAdornment` here is the whole
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
11
- * `ToggleButton`, `Tooltip` and two icons into every host's first paint.
5
+ * `endAdornment` is an element the builder already made — synteny's and
6
+ * wiggle's colour swatches — so the row hands it straight through.
12
7
  *
13
- * Live in one place rather than at each of the four render sites, because the
14
- * "does any row have one?" predicates and the rendering have to agree — a row
15
- * that draws a pin the column-reservation pass didn't count is a misaligned
16
- * menu, not a crash.
8
+ * Lives in one place rather than at each of the four render sites, because the
9
+ * "does any row have one?" predicate and the rendering have to agree — a row
10
+ * that draws an adornment the column-reservation pass didn't count is a
11
+ * misaligned menu, not a crash.
17
12
  */
18
- export declare function menuItemAdornment(item: MenuItem): string | number | bigint | true | import("react").JSX.Element | Iterable<import("react").ReactNode> | Promise<string | number | bigint | boolean | Iterable<import("react").ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | undefined;
13
+ export declare function menuItemAdornment(item: MenuItem): import("react").ReactNode;
19
14
  /**
20
15
  * Whether this row draws something in the shared trailing column — the question
21
16
  * `getMenuColumnFlags` asks to decide whether to reserve that column on every
22
17
  * row of the menu.
23
18
  *
24
- * **Not the same question as "does this row offer a pin"** (`pinnedSlots`, which
25
- * counts a `pin` wherever it appears). A `type: 'custom'` row renders
26
- * its own content edge to edge and never reaches `menuItemAdornment`, so it
27
- * cannot draw in that column however it is declared — counting it would reserve
28
- * a spacer on its siblings for a control that never appears. It still declares
29
- * `pin` when it draws a pin of its own (`makePromotableSizeMenu`),
30
- * which is what keeps the pin findable. Don't "fix" the two into agreement.
19
+ * A `type: 'custom'` row renders its own content edge to edge and never reaches
20
+ * `menuItemAdornment`, so it cannot draw in that column however it is declared.
31
21
  */
32
22
  export declare function hasMenuItemAdornment(item: MenuItem): boolean;
@@ -1,49 +1,28 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { PinAdornment } from './PinAdornment.js';
3
1
  /**
4
2
  * The trailing control a menu row draws, resolved at the point of drawing.
5
3
  *
6
- * Two fields feed it and they are not equivalent. `endAdornment` is an element
7
- * the builder already made — the escape hatch, for content nothing else can
8
- * describe. `pin` is a *description* of the "default for all tracks of
9
- * this type" pin, and turning it into `PinAdornment` here is the whole
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
12
- * `ToggleButton`, `Tooltip` and two icons into every host's first paint.
4
+ * `endAdornment` is an element the builder already made — synteny's and
5
+ * wiggle's colour swatches — so the row hands it straight through.
13
6
  *
14
- * Live in one place rather than at each of the four render sites, because the
15
- * "does any row have one?" predicates and the rendering have to agree — a row
16
- * that draws a pin the column-reservation pass didn't count is a misaligned
17
- * menu, not a crash.
7
+ * Lives in one place rather than at each of the four render sites, because the
8
+ * "does any row have one?" predicate and the rendering have to agree — a row
9
+ * that draws an adornment the column-reservation pass didn't count is a
10
+ * misaligned menu, not a crash.
18
11
  */
19
12
  export function menuItemAdornment(item) {
20
- if ('endAdornment' in item && item.endAdornment) {
21
- return item.endAdornment;
22
- }
23
- // A disabled row is `pointer-events: none` (see `DisabledTooltip`, which
24
- // exists because that also swallows a Tooltip's hover), so a pin drawn in one
25
- // takes no click while looking exactly like a live one. Greying it is what
26
- // the help "?" does on such a row by not rendering at all; the pin stays
27
- // drawn so the trailing column keeps its alignment.
28
- return 'pin' in item && item.pin ? (_jsx(PinAdornment, { pin: item.pin, disabled: item.disabled })) : undefined;
13
+ return 'endAdornment' in item ? item.endAdornment : undefined;
29
14
  }
30
15
  /**
31
16
  * Whether this row draws something in the shared trailing column — the question
32
17
  * `getMenuColumnFlags` asks to decide whether to reserve that column on every
33
18
  * row of the menu.
34
19
  *
35
- * **Not the same question as "does this row offer a pin"** (`pinnedSlots`, which
36
- * counts a `pin` wherever it appears). A `type: 'custom'` row renders
37
- * its own content edge to edge and never reaches `menuItemAdornment`, so it
38
- * cannot draw in that column however it is declared — counting it would reserve
39
- * a spacer on its siblings for a control that never appears. It still declares
40
- * `pin` when it draws a pin of its own (`makePromotableSizeMenu`),
41
- * which is what keeps the pin findable. Don't "fix" the two into agreement.
20
+ * A `type: 'custom'` row renders its own content edge to edge and never reaches
21
+ * `menuItemAdornment`, so it cannot draw in that column however it is declared.
42
22
  */
43
23
  export function hasMenuItemAdornment(item) {
44
24
  if (item.type === 'custom') {
45
25
  return false;
46
26
  }
47
- return (('endAdornment' in item && !!item.endAdornment) ||
48
- ('pin' in item && !!item.pin));
27
+ return 'endAdornment' in item && !!item.endAdornment;
49
28
  }
@@ -13,15 +13,11 @@
13
13
  * from `@jbrowse/core/ui`.** This entry must never reach react, @mui or
14
14
  * @emotion, and `menuItems.purity.test.ts` fails if it starts to — including
15
15
  * transitively, which is the only way the failure would ever show up.
16
- *
17
- * The other half of keeping that true is `MenuItemPin`: a row's pin is
18
- * described here and built by the renderer, because an element in a descriptor
19
- * pulls its whole component graph back in.
20
16
  */
21
17
  export { checkboxItem, radioItem, radioItems, toggleItem, withSubHeader, } from './toggleMenuItems.ts';
22
18
  export { withHint } from './menuLabels.ts';
23
19
  export { makeRadioSubMenu } from './radioSubMenu.ts';
24
20
  export { showLegendCheckboxItem } from './legendMenuItem.ts';
25
- export type { CheckboxRowOptions, RadioOption, RadioRowOptions, SettingRowOptions, } from './toggleMenuItems.ts';
21
+ export type { RadioOption, SettingRowOptions } from './toggleMenuItems.ts';
26
22
  export { resolveSubMenu, staysOpenOnClick } from './MenuTypes.ts';
27
- export type { BaseMenuItem, CheckboxMenuItem, ClickableMenuItem, CustomMenuItem, MenuDivider, MenuItem, MenuItemClickHandler, MenuItemPin, MenuItemsGetter, MenuSubHeader, NormalMenuItem, RadioMenuItem, SubMenuItem, } from './MenuTypes.ts';
23
+ export type { BaseMenuItem, CheckboxMenuItem, ClickableMenuItem, CustomMenuItem, MenuDivider, MenuItem, MenuItemClickHandler, MenuItemsGetter, MenuSubHeader, NormalMenuItem, RadioMenuItem, SubMenuItem, } from './MenuTypes.ts';
@@ -13,10 +13,6 @@
13
13
  * from `@jbrowse/core/ui`.** This entry must never reach react, @mui or
14
14
  * @emotion, and `menuItems.purity.test.ts` fails if it starts to — including
15
15
  * transitively, which is the only way the failure would ever show up.
16
- *
17
- * The other half of keeping that true is `MenuItemPin`: a row's pin is
18
- * described here and built by the renderer, because an element in a descriptor
19
- * pulls its whole component graph back in.
20
16
  */
21
17
  export { checkboxItem, radioItem, radioItems, toggleItem, withSubHeader, } from './toggleMenuItems.js';
22
18
  export { withHint } from './menuLabels.js';
package/esm/ui/palette.js CHANGED
@@ -263,7 +263,8 @@ export const colorPairRR = '#5555bb';
263
263
  // close enough that `readTagColors.ts` moved its untagged-read case off this one
264
264
  // and onto that one, because only that one darkens under the dark theme. Whether
265
265
  // two neutrals are wanted at all is the open question here; this rename does not
266
- // settle it, and the dark-mode half is `agent-docs/TODO.md`.
266
+ // settle it, and the dark-mode half is
267
+ // `agent-docs/ideas/dark-theme-palette-gaps.md`.
267
268
  export const colorNeutralRead = '#c8c8c8';
268
269
  /**
269
270
  * #color alignments-pair-orientation | Inter-chromosomal | Mate on another chromosome
@@ -1,4 +1,3 @@
1
- import type { TogglePin, ValuePin } from '../configuration/promotablePin.ts';
2
1
  import type { CheckboxMenuItem, MenuItem, RadioMenuItem } from './MenuTypes.ts';
3
2
  export interface SettingRowOptions {
4
3
  helpText?: string;
@@ -6,14 +5,8 @@ export interface SettingRowOptions {
6
5
  disabledHelpText?: string;
7
6
  keepMenuOpen?: boolean;
8
7
  }
9
- export interface CheckboxRowOptions extends SettingRowOptions {
10
- pin?: TogglePin;
11
- }
12
- export interface RadioRowOptions extends SettingRowOptions {
13
- pin?: ValuePin;
14
- }
15
- /** #menuBuilder checkboxItem | one checkbox setting row, with a toggle pin when the setting is promotable */
16
- export declare function checkboxItem(label: string, checked: boolean, onToggle: () => void, opts?: CheckboxRowOptions): CheckboxMenuItem;
8
+ /** #menuBuilder checkboxItem | one checkbox setting row */
9
+ export declare function checkboxItem(label: string, checked: boolean, onToggle: () => void, opts?: SettingRowOptions): CheckboxMenuItem;
17
10
  /**
18
11
  * #menuBuilder toggleItem | a checkbox row whose setter takes the new value
19
12
  *
@@ -30,15 +23,15 @@ export declare function checkboxItem(label: string, checked: boolean, onToggle:
30
23
  * `SettingRowOptions` to a hand-narrowed one-field bag — the exact drift the
31
24
  * comment on that interface warns about.
32
25
  */
33
- export declare function toggleItem(label: string, value: boolean, setValue: (value: boolean) => void, opts?: CheckboxRowOptions): CheckboxMenuItem;
26
+ export declare function toggleItem(label: string, value: boolean, setValue: (value: boolean) => void, opts?: SettingRowOptions): CheckboxMenuItem;
34
27
  /** #menuBuilder radioItem | one radio setting row; the singular of `radioItems` */
35
- export declare function radioItem(label: string, checked: boolean, onClick: () => void, opts?: RadioRowOptions): RadioMenuItem;
28
+ export declare function radioItem(label: string, checked: boolean, onClick: () => void, opts?: SettingRowOptions): RadioMenuItem;
36
29
  export interface RadioOption<T extends string> extends SettingRowOptions {
37
30
  value: T;
38
31
  label: string;
39
32
  }
40
- /** #menuBuilder radioItems | a radio group, one row per option, with a value pin per option when the setting is promotable */
41
- export declare function radioItems<T extends string>(options: readonly RadioOption<T>[], current: T | undefined, setMode: (m: T) => void, pin?: (value: T) => ValuePin): RadioMenuItem[];
33
+ /** #menuBuilder radioItems | a radio group, one row per option */
34
+ export declare function radioItems<T extends string>(options: readonly RadioOption<T>[], current: T | undefined, setMode: (m: T) => void): RadioMenuItem[];
42
35
  /**
43
36
  * #menuBuilder withSubHeader | a section heading, present only if the section is
44
37
  *
@@ -1,16 +1,12 @@
1
- function withPin(row, pin) {
2
- return pin ? { ...row, pin: { control: pin, label: row.label } } : row;
3
- }
4
- /** #menuBuilder checkboxItem | one checkbox setting row, with a toggle pin when the setting is promotable */
1
+ /** #menuBuilder checkboxItem | one checkbox setting row */
5
2
  export function checkboxItem(label, checked, onToggle, opts = {}) {
6
- const { pin, ...rest } = opts;
7
- return withPin({
3
+ return {
8
4
  label,
9
5
  type: 'checkbox',
10
6
  checked,
11
7
  onClick: onToggle,
12
- ...rest,
13
- }, pin);
8
+ ...opts,
9
+ };
14
10
  }
15
11
  /**
16
12
  * #menuBuilder toggleItem | a checkbox row whose setter takes the new value
@@ -34,36 +30,24 @@ export function toggleItem(label, value, setValue, opts) {
34
30
  }, opts);
35
31
  }
36
32
  // One radio row. The singular of `radioItems`, for a group the plural form
37
- // can't express: a row with no single value to promote yet (the colorBy
38
- // "Tag..." row before a tag is picked), a display whose slot isn't promotable
39
- // at all (the shared colorBy menu on gwas/variants), or a group gated row by
40
- // row and mixing in a non-promotable peer (the alignments size presets and
41
- // their "Custom..." row). **Reach for `radioItems` first**: every option in a
42
- // group has to get a pin, and hand-naming the rows is what leaves one without.
33
+ // can't express: a row with no single value (the colorBy "Tag..." row before a
34
+ // tag is picked), or a group gated row by row and mixing in a non-uniform peer
35
+ // (the alignments size presets and their "Custom..." row).
43
36
  /** #menuBuilder radioItem | one radio setting row; the singular of `radioItems` */
44
37
  export function radioItem(label, checked, onClick, opts = {}) {
45
- const { pin, ...rest } = opts;
46
- return withPin({
38
+ return {
47
39
  label,
48
40
  type: 'radio',
49
41
  checked,
50
42
  onClick,
51
- ...rest,
52
- }, pin);
43
+ ...opts,
44
+ };
53
45
  }
54
- // `pin` is a factory rather than a per-option field so a promotable group can't
55
- // be a row short. **Every option in a group gets a pin, the `promotedBase`
56
- // value included**: once a non-base value is promoted, taking the base row's
57
- // offer is the per-value way to undo it, and a radio group with one row silently
58
- // missing its trailing control reads as a bug. `sashimiArcsMode`'s base looked
59
- // unpinnable precisely because each row had been named by hand. Pass
60
- // `value => makePin(self, slot, value)`, or a model member of that shape where
61
- // the menu module is handed a duck-typed model (alignments).
62
- /** #menuBuilder radioItems | a radio group, one row per option, with a value pin per option when the setting is promotable */
63
- export function radioItems(options, current, setMode, pin) {
46
+ /** #menuBuilder radioItems | a radio group, one row per option */
47
+ export function radioItems(options, current, setMode) {
64
48
  return options.map(({ value, label, ...opts }) => radioItem(label, current === value, () => {
65
49
  setMode(value);
66
- }, { ...opts, pin: pin?.(value) }));
50
+ }, opts));
67
51
  }
68
52
  /**
69
53
  * #menuBuilder withSubHeader | a section heading, present only if the section is
@@ -1,4 +1,4 @@
1
- import type { GradientStop } from '../ui/SvgGradientLegend.tsx';
1
+ import type { RampStop } from '../ui/colorScale.ts';
2
2
  /** One evenly-spaced ramp stop: 8-bit red, green, blue, alpha. */
3
3
  export type ColorRampStop = readonly [number, number, number, number];
4
4
  /**
@@ -29,9 +29,9 @@ export declare function buildColorRampLut(stops: readonly ColorRampStop[]): Uint
29
29
  * `n` evenly spaced legend stops read straight out of a
30
30
  * {@link buildColorRampLut} byte table — the same 256×1 RGBA array
31
31
  * `uploadColorRampLut` hands the GPU and the Canvas2D fillStyle LUTs index —
32
- * formatted for `SvgGradientLegend`. It holds one claim by construction: the
32
+ * as the stops of a `RampScale`. It holds one claim by construction: the
33
33
  * swatch at bar fraction `t` is byte-identical to the ramp entry at `t` on
34
34
  * both backends. Alpha rides `opacity` (the juicebox fade), never baked into
35
35
  * the color string.
36
36
  */
37
- export declare function stopsFromRampLut(lut: Uint8Array, n: number): GradientStop[];
37
+ export declare function stopsFromRampLut(lut: Uint8Array, n: number): RampStop[];
@@ -72,7 +72,7 @@ export function buildColorRampLut(stops) {
72
72
  * `n` evenly spaced legend stops read straight out of a
73
73
  * {@link buildColorRampLut} byte table — the same 256×1 RGBA array
74
74
  * `uploadColorRampLut` hands the GPU and the Canvas2D fillStyle LUTs index —
75
- * formatted for `SvgGradientLegend`. It holds one claim by construction: the
75
+ * as the stops of a `RampScale`. It holds one claim by construction: the
76
76
  * swatch at bar fraction `t` is byte-identical to the ramp entry at `t` on
77
77
  * both backends. Alpha rides `opacity` (the juicebox fade), never baked into
78
78
  * the color string.
@@ -84,7 +84,7 @@ export function stopsFromRampLut(lut, n) {
84
84
  const t = n === 1 ? 0 : i / (n - 1);
85
85
  const o = Math.round(t * lastEntry) * 4;
86
86
  out.push({
87
- offset: `${+(t * 100).toFixed(2)}%`,
87
+ offset: t,
88
88
  color: `rgb(${lut[o]},${lut[o + 1]},${lut[o + 2]})`,
89
89
  opacity: lut[o + 3] / 255,
90
90
  });
@@ -0,0 +1,15 @@
1
+ import type { JexlInstance } from './jexlStrings.ts';
2
+ import type { AggregateOp, TransformStep } from './markEncodingTypes.ts';
3
+ import type { Feature } from './simpleFeature.ts';
4
+ export declare const DEFAULT_BIN_AS: [string, string];
5
+ export declare const DEFAULT_COVERAGE_AS = "coverage";
6
+ export declare const DEFAULT_STACK_AS = "row";
7
+ export declare const DEFAULT_STACK_FIELDS: [string, string];
8
+ export declare function aggregateFieldName({ op, field, as }: AggregateOp): string;
9
+ /**
10
+ * #api
11
+ * Run the transform steps over a feature list, in order, in the worker. The
12
+ * list a step answers is what the next one reads, and the last one is what
13
+ * the encoder walks.
14
+ */
15
+ export declare function runTransforms(features: readonly Feature[], steps: readonly TransformStep[], jexl?: JexlInstance): readonly Feature[];