@jbrowse/plugin-wiggle 3.6.4 → 3.7.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.
Files changed (73) hide show
  1. package/dist/CreateMultiWiggleExtension/ConfirmDialog.js +1 -1
  2. package/dist/CreateMultiWiggleExtension/index.js +1 -1
  3. package/dist/LinearWiggleDisplay/model.d.ts +17 -2
  4. package/dist/MultiLinearWiggleDisplay/components/ColorLegend.js +2 -1
  5. package/dist/MultiLinearWiggleDisplay/components/LegendItem.js +1 -3
  6. package/dist/MultiLinearWiggleDisplay/components/LegendItemText.d.ts +10 -0
  7. package/dist/MultiLinearWiggleDisplay/components/LegendItemText.js +13 -0
  8. package/dist/MultiLinearWiggleDisplay/components/SetColorDialog.js +2 -32
  9. package/dist/MultiLinearWiggleDisplay/components/SourcesGrid.js +1 -1
  10. package/dist/MultiLinearWiggleDisplay/components/Tooltip.js +10 -6
  11. package/dist/MultiLinearWiggleDisplay/components/WiggleClusterDialog/WiggleClusterDialogAuto.js +11 -3
  12. package/dist/MultiLinearWiggleDisplay/components/WiggleClusterDialog/WiggleClusterDialogManual.js +14 -6
  13. package/dist/MultiLinearWiggleDisplay/components/WiggleClusterDialog/types.d.ts +2 -1
  14. package/dist/MultiLinearWiggleDisplay/components/ui/SetColorDialog.d.ts +31 -0
  15. package/dist/MultiLinearWiggleDisplay/components/ui/SetColorDialog.js +51 -0
  16. package/dist/MultiLinearWiggleDisplay/components/ui/SetColorDialogBulkEditPanel.d.ts +10 -0
  17. package/dist/MultiLinearWiggleDisplay/components/ui/SetColorDialogBulkEditPanel.js +84 -0
  18. package/dist/MultiLinearWiggleDisplay/components/ui/SetColorDialogHelpfulTips.d.ts +1 -0
  19. package/dist/MultiLinearWiggleDisplay/components/ui/SetColorDialogHelpfulTips.js +7 -0
  20. package/dist/MultiLinearWiggleDisplay/components/ui/SetColorDialogRowPalettizer.d.ts +10 -0
  21. package/dist/MultiLinearWiggleDisplay/components/ui/SetColorDialogRowPalettizer.js +42 -0
  22. package/dist/MultiLinearWiggleDisplay/components/util.d.ts +4 -8
  23. package/dist/MultiLinearWiggleDisplay/model.d.ts +19 -2
  24. package/dist/MultiLinearWiggleDisplay/model.js +2 -2
  25. package/dist/MultiLinearWiggleDisplay/types.d.ts +1 -0
  26. package/dist/MultiLinearWiggleDisplay/util.d.ts +0 -1
  27. package/dist/MultiLinearWiggleDisplay/util.js +0 -9
  28. package/dist/MultiWiggleAdapter/MultiWiggleAdapter.d.ts +2 -1
  29. package/dist/MultiWiggleAdapter/MultiWiggleAdapter.js +36 -11
  30. package/dist/MultiWiggleAddTrackWorkflow/AddTrackWorkflow.js +1 -1
  31. package/dist/getMultiWiggleSourcesAutorun.d.ts +1 -0
  32. package/dist/shared/SharedWiggleMixin.d.ts +17 -2
  33. package/dist/util.d.ts +1 -0
  34. package/dist/util.js +1 -1
  35. package/esm/CreateMultiWiggleExtension/ConfirmDialog.js +1 -1
  36. package/esm/CreateMultiWiggleExtension/index.js +1 -1
  37. package/esm/LinearWiggleDisplay/model.d.ts +17 -2
  38. package/esm/MultiLinearWiggleDisplay/components/ColorLegend.js +2 -1
  39. package/esm/MultiLinearWiggleDisplay/components/LegendItem.js +1 -3
  40. package/esm/MultiLinearWiggleDisplay/components/LegendItemText.d.ts +10 -0
  41. package/esm/MultiLinearWiggleDisplay/components/LegendItemText.js +11 -0
  42. package/esm/MultiLinearWiggleDisplay/components/SetColorDialog.js +3 -33
  43. package/esm/MultiLinearWiggleDisplay/components/SourcesGrid.js +1 -1
  44. package/esm/MultiLinearWiggleDisplay/components/Tooltip.js +10 -6
  45. package/esm/MultiLinearWiggleDisplay/components/WiggleClusterDialog/WiggleClusterDialogAuto.js +11 -3
  46. package/esm/MultiLinearWiggleDisplay/components/WiggleClusterDialog/WiggleClusterDialogManual.js +14 -6
  47. package/esm/MultiLinearWiggleDisplay/components/WiggleClusterDialog/types.d.ts +2 -1
  48. package/esm/MultiLinearWiggleDisplay/components/ui/SetColorDialog.d.ts +31 -0
  49. package/esm/MultiLinearWiggleDisplay/components/ui/SetColorDialog.js +45 -0
  50. package/esm/MultiLinearWiggleDisplay/components/ui/SetColorDialogBulkEditPanel.d.ts +10 -0
  51. package/esm/MultiLinearWiggleDisplay/components/ui/SetColorDialogBulkEditPanel.js +81 -0
  52. package/esm/MultiLinearWiggleDisplay/components/ui/SetColorDialogHelpfulTips.d.ts +1 -0
  53. package/esm/MultiLinearWiggleDisplay/components/ui/SetColorDialogHelpfulTips.js +4 -0
  54. package/esm/MultiLinearWiggleDisplay/components/ui/SetColorDialogRowPalettizer.d.ts +10 -0
  55. package/esm/MultiLinearWiggleDisplay/components/ui/SetColorDialogRowPalettizer.js +39 -0
  56. package/esm/MultiLinearWiggleDisplay/components/util.d.ts +4 -8
  57. package/esm/MultiLinearWiggleDisplay/model.d.ts +19 -2
  58. package/esm/MultiLinearWiggleDisplay/model.js +2 -2
  59. package/esm/MultiLinearWiggleDisplay/types.d.ts +1 -0
  60. package/esm/MultiLinearWiggleDisplay/util.d.ts +0 -1
  61. package/esm/MultiLinearWiggleDisplay/util.js +1 -7
  62. package/esm/MultiWiggleAdapter/MultiWiggleAdapter.d.ts +2 -1
  63. package/esm/MultiWiggleAdapter/MultiWiggleAdapter.js +36 -11
  64. package/esm/MultiWiggleAddTrackWorkflow/AddTrackWorkflow.js +1 -1
  65. package/esm/getMultiWiggleSourcesAutorun.d.ts +1 -0
  66. package/esm/shared/SharedWiggleMixin.d.ts +17 -2
  67. package/esm/util.d.ts +1 -0
  68. package/esm/util.js +1 -1
  69. package/package.json +5 -5
  70. package/dist/WiggleRPC/type.d.ts +0 -0
  71. package/dist/WiggleRPC/type.js +0 -1
  72. package/esm/WiggleRPC/type.d.ts +0 -0
  73. package/esm/WiggleRPC/type.js +0 -1
@@ -9,7 +9,7 @@ const configuration_1 = require("@jbrowse/core/configuration");
9
9
  const Dialog_1 = __importDefault(require("@jbrowse/core/ui/Dialog"));
10
10
  const material_1 = require("@mui/material");
11
11
  const ConfirmDialog = ({ tracks, onClose, }) => {
12
- const [val, setVal] = (0, react_1.useState)(`MultiWiggle ${Date.now()}`);
12
+ const [val, setVal] = (0, react_1.useState)(() => `MultiWiggle ${Date.now()}`);
13
13
  const allQuant = tracks.every(t => t.type === 'QuantitativeTrack');
14
14
  return ((0, jsx_runtime_1.jsxs)(Dialog_1.default, { open: true, onClose: () => {
15
15
  onClose(false);
@@ -44,7 +44,7 @@ function makeTrack({ model, arg, }) {
44
44
  const subadapters = tracks
45
45
  .map(c => (0, configuration_1.readConfObject)(c, 'adapter'))
46
46
  .map((c, idx) => ({ ...c, source: trackIds[idx] }));
47
- const now = +Date.now();
47
+ const now = Date.now();
48
48
  const trackId = `multitrack-${now}-sessionTrack`;
49
49
  const session = (0, util_1.getSession)(model);
50
50
  if ((0, util_1.isSessionWithAddTracks)(session)) {
@@ -193,6 +193,7 @@ declare function stateModelFactory(pluginManager: PluginManager, configSchema: A
193
193
  regionCannotBeRenderedText(_region: import("@jbrowse/core/util").Region): "" | "Force load to see features";
194
194
  regionCannotBeRendered(_region: import("@jbrowse/core/util").Region): import("react/jsx-runtime").JSX.Element | null;
195
195
  } & {
196
+ mouseoverExtraInformation: string | undefined;
196
197
  featureIdUnderMouse: undefined | string;
197
198
  contextMenuFeature: undefined | import("@jbrowse/core/util").Feature;
198
199
  } & {
@@ -207,9 +208,22 @@ declare function stateModelFactory(pluginManager: PluginManager, configSchema: A
207
208
  } & {
208
209
  readonly features: import("@jbrowse/core/util/compositeMap").default<string, import("@jbrowse/core/util").Feature>;
209
210
  readonly featureUnderMouse: import("@jbrowse/core/util").Feature | undefined;
211
+ readonly layoutFeatures: import("@jbrowse/core/util/compositeMap").default<string, [number, number, number, number] | [number, number, number, number, {
212
+ label?: string;
213
+ description?: string;
214
+ refName: string;
215
+ }]>;
210
216
  getFeatureOverlapping(blockKey: string, x: number, y: number): string | undefined;
211
- getFeatureByID(blockKey: string, id: string): [number, number, number, number] | undefined;
212
- searchFeatureByID(id: string): [number, number, number, number] | undefined;
217
+ getFeatureByID(blockKey: string, id: string): ([number, number, number, number] | [number, number, number, number, {
218
+ label?: string;
219
+ description?: string;
220
+ refName: string;
221
+ }]) | undefined;
222
+ searchFeatureByID(id: string): ([number, number, number, number] | [number, number, number, number, {
223
+ label?: string;
224
+ description?: string;
225
+ refName: string;
226
+ }]) | undefined;
213
227
  } & {
214
228
  addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
215
229
  deleteBlock(key: string): void;
@@ -218,6 +232,7 @@ declare function stateModelFactory(pluginManager: PluginManager, configSchema: A
218
232
  clearFeatureSelection(): void;
219
233
  setFeatureIdUnderMouse(feature?: string): void;
220
234
  setContextMenuFeature(feature?: import("@jbrowse/core/util").Feature): void;
235
+ setMouseoverExtraInformation(extra?: string): void;
221
236
  } & {
222
237
  reload(): Promise<void>;
223
238
  } & {
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const jsx_runtime_1 = require("react/jsx-runtime");
7
7
  const mobx_react_1 = require("mobx-react");
8
8
  const LegendItem_1 = __importDefault(require("./LegendItem"));
9
+ const LegendItemText_1 = __importDefault(require("./LegendItemText"));
9
10
  const RectBg_1 = __importDefault(require("./RectBg"));
10
11
  const ColorLegend = (0, mobx_react_1.observer)(function ({ model, rowHeight, exportSVG, }) {
11
12
  const { graphType, needsFullHeightScalebar, rowHeightTooSmallForScalebar, renderColorBoxes, sources, labelWidth, } = model;
@@ -13,6 +14,6 @@ const ColorLegend = (0, mobx_react_1.observer)(function ({ model, rowHeight, exp
13
14
  const legendWidth = labelWidth + colorBoxWidth + 5;
14
15
  const svgOffset = exportSVG ? 10 : 0;
15
16
  const extraOffset = svgOffset || (graphType && !rowHeightTooSmallForScalebar ? 50 : 0);
16
- return sources ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [needsFullHeightScalebar ? ((0, jsx_runtime_1.jsx)(RectBg_1.default, { y: 0, x: extraOffset, width: legendWidth, height: (sources.length + 0.25) * rowHeight })) : null, sources.map((source, idx) => ((0, jsx_runtime_1.jsx)(LegendItem_1.default, { source: source, idx: idx, model: model, rowHeight: rowHeight, exportSVG: exportSVG, labelWidth: labelWidth }, `${source.name}-${idx}`)))] })) : null;
17
+ return sources ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [needsFullHeightScalebar ? ((0, jsx_runtime_1.jsx)(RectBg_1.default, { y: 0, x: extraOffset, width: legendWidth, height: (sources.length + 0.25) * rowHeight })) : null, sources.map((source, idx) => ((0, jsx_runtime_1.jsx)(LegendItem_1.default, { source: source, idx: idx, model: model, rowHeight: rowHeight, exportSVG: exportSVG, labelWidth: labelWidth }, `${source.name}-${idx}`))), sources.map((source, idx) => ((0, jsx_runtime_1.jsx)(LegendItemText_1.default, { source: source, idx: idx, model: model, rowHeight: rowHeight, exportSVG: exportSVG }, `${source.name}-text-${idx}`)))] })) : null;
17
18
  });
18
19
  exports.default = ColorLegend;
@@ -8,12 +8,10 @@ const RectBg_1 = __importDefault(require("./RectBg"));
8
8
  const LegendItem = function ({ source, idx, rowHeight, labelWidth, model, exportSVG, }) {
9
9
  const boxHeight = Math.min(20, rowHeight);
10
10
  const { needsCustomLegend, graphType, needsFullHeightScalebar, rowHeightTooSmallForScalebar, renderColorBoxes, } = model;
11
- const svgFontSize = Math.min(rowHeight, 12);
12
- const canDisplayLabel = rowHeight > 11;
13
11
  const colorBoxWidth = renderColorBoxes ? 15 : 0;
14
12
  const legendWidth = labelWidth + colorBoxWidth + 5;
15
13
  const svgOffset = exportSVG ? 10 : 0;
16
14
  const extraOffset = svgOffset || (graphType && !rowHeightTooSmallForScalebar ? 50 : 0);
17
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [needsFullHeightScalebar ? null : ((0, jsx_runtime_1.jsx)(RectBg_1.default, { y: idx * rowHeight + 1, x: extraOffset, width: legendWidth, height: boxHeight })), source.color ? ((0, jsx_runtime_1.jsx)(RectBg_1.default, { y: idx * rowHeight + 1, x: extraOffset, width: colorBoxWidth, height: needsCustomLegend ? rowHeight : boxHeight, color: source.color })) : null, canDisplayLabel ? ((0, jsx_runtime_1.jsx)("text", { y: idx * rowHeight + 13, x: extraOffset + colorBoxWidth + 2, fontSize: svgFontSize, children: source.name })) : null] }));
15
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [needsFullHeightScalebar ? null : ((0, jsx_runtime_1.jsx)(RectBg_1.default, { y: idx * rowHeight + 1, x: extraOffset, width: legendWidth, height: boxHeight })), source.color ? ((0, jsx_runtime_1.jsx)(RectBg_1.default, { y: idx * rowHeight + 1, x: extraOffset, width: colorBoxWidth, height: needsCustomLegend ? rowHeight : boxHeight, color: source.color })) : null] }));
18
16
  };
19
17
  exports.default = LegendItem;
@@ -0,0 +1,10 @@
1
+ import type { Source } from '../../util';
2
+ import type { WiggleDisplayModel } from '../model';
3
+ declare const LegendItemText: ({ source, idx, rowHeight, model, exportSVG, }: {
4
+ source: Source;
5
+ idx: number;
6
+ rowHeight: number;
7
+ model: WiggleDisplayModel;
8
+ exportSVG?: boolean;
9
+ }) => import("react/jsx-runtime").JSX.Element | null;
10
+ export default LegendItemText;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const jsx_runtime_1 = require("react/jsx-runtime");
4
+ const LegendItemText = function ({ source, idx, rowHeight, model, exportSVG, }) {
5
+ const { graphType, rowHeightTooSmallForScalebar, renderColorBoxes } = model;
6
+ const svgFontSize = Math.min(rowHeight, 12);
7
+ const canDisplayLabel = rowHeight >= 6;
8
+ const colorBoxWidth = renderColorBoxes ? 15 : 0;
9
+ const svgOffset = exportSVG ? 10 : 0;
10
+ const extraOffset = svgOffset || (graphType && !rowHeightTooSmallForScalebar ? 50 : 0);
11
+ return canDisplayLabel ? ((0, jsx_runtime_1.jsx)("text", { y: idx * rowHeight + 13, x: extraOffset + colorBoxWidth + 2, fontSize: svgFontSize, children: source.name })) : null;
12
+ };
13
+ exports.default = LegendItemText;
@@ -5,38 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.default = SetColorDialog;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
- const react_1 = require("react");
9
- const DraggableDialog_1 = __importDefault(require("@jbrowse/core/ui/DraggableDialog"));
10
- const util_1 = require("@jbrowse/core/util");
11
- const material_1 = require("@mui/material");
12
- const mui_1 = require("tss-react/mui");
13
8
  const SourcesGrid_1 = __importDefault(require("./SourcesGrid"));
14
- const useStyles = (0, mui_1.makeStyles)()({
15
- content: {
16
- minWidth: 800,
17
- },
18
- float: {
19
- float: 'right',
20
- },
21
- });
22
- function HelpfulTips() {
23
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Helpful tips", (0, jsx_runtime_1.jsxs)("ul", { children: [(0, jsx_runtime_1.jsx)("li", { children: "You can select rows in the table with the checkboxes" }), (0, jsx_runtime_1.jsx)("li", { children: "Multi-select is enabled with shift-click and control-click" }), (0, jsx_runtime_1.jsx)("li", { children: "The \"Move selected items up/down\" can re-arrange subtracks" }), (0, jsx_runtime_1.jsx)("li", { children: "Sorting the data grid itself can also re-arrange subtracks" }), (0, jsx_runtime_1.jsx)("li", { children: "Changes are applied when you hit Submit" }), (0, jsx_runtime_1.jsx)("li", { children: "You can click and drag the dialog box to move it on the screen" }), (0, jsx_runtime_1.jsx)("li", { children: "Columns in the table can be hidden using a vertical '...' menu on the right side of each column" })] })] }));
24
- }
9
+ const SetColorDialog_1 = __importDefault(require("./ui/SetColorDialog"));
25
10
  function SetColorDialog({ model, handleClose, }) {
26
- const { classes } = useStyles();
27
- const { sources } = model;
28
- const [currLayout, setCurrLayout] = (0, react_1.useState)(structuredClone(sources || []));
29
- const [showTips, setShowTips] = (0, util_1.useLocalStorage)('multiwiggle-showTips', false);
30
- return ((0, jsx_runtime_1.jsxs)(DraggableDialog_1.default, { open: true, onClose: handleClose, maxWidth: "xl", title: "Multi-wiggle color/arrangement editor", children: [(0, jsx_runtime_1.jsxs)(material_1.DialogContent, { className: classes.content, children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", className: classes.float, onClick: () => {
31
- setShowTips(!showTips);
32
- }, children: showTips ? 'Hide tips' : 'Show tips' }), (0, jsx_runtime_1.jsx)("br", {}), showTips ? (0, jsx_runtime_1.jsx)(HelpfulTips, {}) : null, (0, jsx_runtime_1.jsx)(SourcesGrid_1.default, { rows: currLayout, onChange: setCurrLayout, showTips: showTips })] }), (0, jsx_runtime_1.jsxs)(material_1.DialogActions, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", type: "submit", color: "inherit", onClick: () => {
33
- model.clearLayout();
34
- setCurrLayout(model.sources || []);
35
- }, children: "Clear custom settings" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "secondary", onClick: () => {
36
- handleClose();
37
- setCurrLayout([...(model.sources || [])]);
38
- }, children: "Cancel" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "primary", type: "submit", onClick: () => {
39
- model.setLayout(currLayout);
40
- handleClose();
41
- }, children: "Submit" })] })] }));
11
+ return ((0, jsx_runtime_1.jsx)(SetColorDialog_1.default, { model: model, handleClose: handleClose, title: "Multi-wiggle color/arrangement editor", enableBulkEdit: true, enableRowPalettizer: true, showTipsStorageKey: "multiwiggle-showTips", SourcesGridComponent: SourcesGrid_1.default }));
42
12
  }
@@ -60,7 +60,7 @@ function SourcesGrid({ rows, onChange, showTips, }) {
60
60
  const { classes } = useStyles();
61
61
  const [anchorEl, setAnchorEl] = (0, react_1.useState)(null);
62
62
  const [selected, setSelected] = (0, react_1.useState)([]);
63
- const { name: _name, color: _color, baseUri: _baseUri, ...rest } = rows[0];
63
+ const { name: _name, color: _color, source: _source, baseUri: _baseUri, ...rest } = rows.length > 0 ? rows[0] : {};
64
64
  const [widgetColor, setWidgetColor] = (0, react_1.useState)('blue');
65
65
  const [currSort, setCurrSort] = (0, react_1.useState)({
66
66
  idx: 0,
@@ -19,15 +19,19 @@ const TooltipContents = (0, react_1.forwardRef)(function TooltipContents2({ mode
19
19
  const source = feature.get('source');
20
20
  const summary = feature.get('summary');
21
21
  const obj = Object.fromEntries(model.sources.map(ent => [ent.name, ent]));
22
- return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, children: [[refName, coord].filter(f => !!f).join(':'), (0, jsx_runtime_1.jsx)("br", {}), sources ? ((0, jsx_runtime_1.jsxs)("table", { children: [(0, jsx_runtime_1.jsx)("thead", { children: (0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("th", { children: "color" }), (0, jsx_runtime_1.jsx)("th", { children: "source" }), (0, jsx_runtime_1.jsx)("th", { children: "score" })] }) }), (0, jsx_runtime_1.jsx)("tbody", { children: Object.entries(sources).map(([source, data]) => ((0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("td", { children: (0, jsx_runtime_1.jsx)("div", { style: {
23
- width: 16,
24
- height: 16,
25
- background: obj[source].color,
26
- } }) }), (0, jsx_runtime_1.jsx)("td", { children: source }), (0, jsx_runtime_1.jsx)("td", { children: (0, util_1.toP)(data.score) })] }, source))) })] })) : ((0, jsx_runtime_1.jsxs)("span", { children: [source, ' ', summary
22
+ const obj2 = obj[source];
23
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, children: [[refName, coord].filter(f => !!f).join(':'), (0, jsx_runtime_1.jsx)("br", {}), sources ? ((0, jsx_runtime_1.jsxs)("table", { children: [(0, jsx_runtime_1.jsx)("thead", { children: (0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("th", { children: "color" }), (0, jsx_runtime_1.jsx)("th", { children: "source" }), (0, jsx_runtime_1.jsx)("th", { children: "score" })] }) }), (0, jsx_runtime_1.jsx)("tbody", { children: Object.entries(sources).map(([source, data]) => {
24
+ const sourceInfo = obj[source];
25
+ return ((0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("td", { children: sourceInfo && ((0, jsx_runtime_1.jsx)("div", { style: {
26
+ width: 16,
27
+ height: 16,
28
+ background: sourceInfo.color,
29
+ } })) }), (0, jsx_runtime_1.jsx)("td", { children: (sourceInfo === null || sourceInfo === void 0 ? void 0 : sourceInfo.name) || source }), (0, jsx_runtime_1.jsx)("td", { children: (0, util_1.toP)(data.score) })] }, source));
30
+ }) })] })) : ((0, jsx_runtime_1.jsxs)("span", { children: [(obj2 === null || obj2 === void 0 ? void 0 : obj2.name) || source, ' ', summary
27
31
  ? `min:${(0, util_1.toP)(feature.get('minScore'))} avg:${(0, util_1.toP)(feature.get('score'))} max:${(0, util_1.toP)(feature.get('maxScore'))}`
28
32
  : (0, util_1.toP)(feature.get('score'))] }))] }));
29
33
  });
30
- const WiggleTooltip = (0, mobx_react_1.observer)((props) => {
34
+ const WiggleTooltip = (0, mobx_react_1.observer)(function (props) {
31
35
  return (0, jsx_runtime_1.jsx)(Tooltip_1.default, { useClientY: true, TooltipContents: TooltipContents, ...props });
32
36
  });
33
37
  exports.default = WiggleTooltip;
@@ -23,6 +23,7 @@ const WiggleClusterDialogAuto = (0, mobx_react_1.observer)(function ({ model, ch
23
23
  } })] })) : null] }), (0, jsx_runtime_1.jsxs)("div", { children: [loading ? ((0, jsx_runtime_1.jsxs)("div", { style: { padding: 50 }, children: [(0, jsx_runtime_1.jsx)("span", { children: progress || 'Loading...' }), (0, jsx_runtime_1.jsx)(material_1.Button, { onClick: () => {
24
24
  (0, stopToken_1.stopStopToken)(stopToken);
25
25
  }, children: "Stop" })] })) : null, error ? (0, jsx_runtime_1.jsx)(ui_1.ErrorMessage, { error: error }) : null] })] }), (0, jsx_runtime_1.jsxs)(material_1.DialogActions, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", disabled: loading, onClick: async () => {
26
+ var _a;
26
27
  try {
27
28
  setError(undefined);
28
29
  setProgress('Initializing');
@@ -48,12 +49,19 @@ const WiggleClusterDialogAuto = (0, mobx_react_1.observer)(function ({ model, ch
48
49
  setProgress(arg);
49
50
  },
50
51
  }));
52
+ const currentLayout = ((_a = model.layout) === null || _a === void 0 ? void 0 : _a.length)
53
+ ? model.layout
54
+ : sourcesWithoutLayout;
55
+ const sourcesByName = Object.fromEntries(currentLayout.map((s) => [s.name, s]));
51
56
  model.setLayout(ret.order.map(idx => {
52
- const ret = sourcesWithoutLayout[idx];
53
- if (!ret) {
57
+ const sourceItem = sourcesWithoutLayout[idx];
58
+ if (!sourceItem) {
54
59
  throw new Error(`out of bounds at ${idx}`);
55
60
  }
56
- return ret;
61
+ return {
62
+ ...sourceItem,
63
+ ...sourcesByName[sourceItem.name],
64
+ };
57
65
  }));
58
66
  }
59
67
  handleClose();
@@ -66,7 +66,7 @@ const WiggleClusterDialogManuals = (0, mobx_react_1.observer)(function ({ model,
66
66
  })();
67
67
  }, [model, samplesPerPixel]);
68
68
  const results = ret
69
- ? `inputMatrix<-matrix(c(${Object.values(ret)
69
+ ? String.raw `inputMatrix<-matrix(c(${Object.values(ret)
70
70
  .map(val => val.join(','))
71
71
  .join(',\n')}
72
72
  ),nrow=${Object.values(ret).length},byrow=TRUE)
@@ -74,7 +74,7 @@ rownames(inputMatrix)<-c(${Object.keys(ret)
74
74
  .map(key => `'${key}'`)
75
75
  .join(',')})
76
76
  resultClusters<-hclust(dist(inputMatrix), method='${clusterMethod}')
77
- cat(resultClusters$order,sep='\\n')`
77
+ cat(resultClusters$order,sep='\n')`
78
78
  : undefined;
79
79
  const resultsTsv = ret
80
80
  ? Object.entries(ret)
@@ -107,7 +107,7 @@ cat(resultClusters$order,sep='\\n')`
107
107
  setClusterMethod(key);
108
108
  } }), label: val }, key))) }), (0, jsx_runtime_1.jsxs)("div", { style: { marginTop: 20 }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { children: "This procedure samples the data at each 'pixel' across the visible by default" }), (0, jsx_runtime_1.jsx)(material_1.TextField, { label: "Samples per pixel (>1 for denser sampling, between 0-1 for sparser sampling)", variant: "outlined", size: "small", value: samplesPerPixel, onChange: event => {
109
109
  setSamplesPerPixel(event.target.value);
110
- } })] })] })) : null, results ? ((0, jsx_runtime_1.jsx)("div", {})) : loading ? ((0, jsx_runtime_1.jsx)(ui_1.LoadingEllipses, { variant: "h6", title: "Generating score matrix" })) : error ? ((0, jsx_runtime_1.jsx)(ui_1.ErrorMessage, { error: error })) : null] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle2", gutterBottom: true, style: { marginTop: '16px' }, children: "Clustering Results:" }), (0, jsx_runtime_1.jsx)(material_1.TextField, { multiline: true, fullWidth: true, variant: "outlined", placeholder: "Paste results from Rscript here (sequence of numbers, one per line, specifying the new ordering)", rows: 10, value: paste, onChange: event => {
110
+ } })] })] })) : null, results ? ((0, jsx_runtime_1.jsx)("div", {})) : loading ? ((0, jsx_runtime_1.jsx)(ui_1.LoadingEllipses, { variant: "h6", message: "Generating score matrix" })) : error ? ((0, jsx_runtime_1.jsx)(ui_1.ErrorMessage, { error: error })) : null] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle2", gutterBottom: true, style: { marginTop: '16px' }, children: "Clustering Results:" }), (0, jsx_runtime_1.jsx)(material_1.TextField, { multiline: true, fullWidth: true, variant: "outlined", placeholder: "Paste results from Rscript here (sequence of numbers, one per line, specifying the new ordering)", rows: 10, value: paste, onChange: event => {
111
111
  setPaste(event.target.value);
112
112
  }, slotProps: {
113
113
  input: {
@@ -116,20 +116,28 @@ cat(resultClusters$order,sep='\\n')`
116
116
  },
117
117
  },
118
118
  } })] })] })] }), (0, jsx_runtime_1.jsxs)(material_1.DialogActions, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
119
+ var _a;
119
120
  const { sourcesWithoutLayout } = model;
120
121
  if (sourcesWithoutLayout) {
121
122
  try {
123
+ const currentLayout = ((_a = model.layout) === null || _a === void 0 ? void 0 : _a.length)
124
+ ? model.layout
125
+ : sourcesWithoutLayout;
126
+ const sourcesByName = Object.fromEntries(currentLayout.map((s) => [s.name, s]));
122
127
  model.setLayout(paste
123
128
  .split('\n')
124
129
  .map(t => t.trim())
125
130
  .filter(f => !!f)
126
131
  .map(r => +r)
127
132
  .map(idx => {
128
- const ret = sourcesWithoutLayout[idx - 1];
129
- if (!ret) {
133
+ const sourceItem = sourcesWithoutLayout[idx - 1];
134
+ if (!sourceItem) {
130
135
  throw new Error(`out of bounds at ${idx}`);
131
136
  }
132
- return ret;
137
+ return {
138
+ ...sourceItem,
139
+ ...sourcesByName[sourceItem.name],
140
+ };
133
141
  }));
134
142
  }
135
143
  catch (e) {
@@ -1,7 +1,8 @@
1
- import type { Source } from '../../types';
1
+ import type { Source } from '../../../util';
2
2
  import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
3
3
  export interface ReducedModel {
4
4
  sourcesWithoutLayout?: Source[];
5
+ layout?: Source[];
5
6
  adapterConfig: AnyConfigurationModel;
6
7
  setLayout: (arg: Source[]) => void;
7
8
  }
@@ -0,0 +1,31 @@
1
+ interface SetColorDialogProps {
2
+ model: {
3
+ sources?: {
4
+ name: string;
5
+ [key: string]: unknown;
6
+ }[];
7
+ setLayout: (s: {
8
+ name: string;
9
+ [key: string]: unknown;
10
+ }[]) => void;
11
+ clearLayout: () => void;
12
+ };
13
+ handleClose: () => void;
14
+ title?: string;
15
+ enableBulkEdit?: boolean;
16
+ enableRowPalettizer?: boolean;
17
+ showTipsStorageKey?: string;
18
+ SourcesGridComponent: React.ComponentType<{
19
+ rows: {
20
+ name: string;
21
+ [key: string]: unknown;
22
+ }[];
23
+ onChange: (rows: {
24
+ name: string;
25
+ [key: string]: unknown;
26
+ }[]) => void;
27
+ showTips: boolean;
28
+ }>;
29
+ }
30
+ export default function SetColorDialog({ model, handleClose, title, enableBulkEdit, enableRowPalettizer, showTipsStorageKey, SourcesGridComponent, }: SetColorDialogProps): import("react/jsx-runtime").JSX.Element;
31
+ export {};
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = SetColorDialog;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = require("react");
9
+ const DraggableDialog_1 = __importDefault(require("@jbrowse/core/ui/DraggableDialog"));
10
+ const util_1 = require("@jbrowse/core/util");
11
+ const material_1 = require("@mui/material");
12
+ const mui_1 = require("tss-react/mui");
13
+ const SetColorDialogBulkEditPanel_1 = __importDefault(require("./SetColorDialogBulkEditPanel"));
14
+ const SetColorDialogHelpfulTips_1 = __importDefault(require("./SetColorDialogHelpfulTips"));
15
+ const SetColorDialogRowPalettizer_1 = __importDefault(require("./SetColorDialogRowPalettizer"));
16
+ const useStyles = (0, mui_1.makeStyles)()({
17
+ content: {
18
+ minWidth: 800,
19
+ },
20
+ fr: {
21
+ float: 'right',
22
+ display: 'flex',
23
+ gap: 8,
24
+ },
25
+ });
26
+ function SetColorDialog({ model, handleClose, title = 'Color/arrangement editor', enableBulkEdit = false, enableRowPalettizer = false, showTipsStorageKey = 'setColorDialog-showTips', SourcesGridComponent, }) {
27
+ const { classes } = useStyles();
28
+ const { sources } = model;
29
+ const [showBulkEditor, setShowBulkEditor] = (0, react_1.useState)(false);
30
+ const [currLayout, setCurrLayout] = (0, react_1.useState)(structuredClone(sources || []));
31
+ const [showTips, setShowTips] = (0, util_1.useLocalStorage)(showTipsStorageKey, false);
32
+ return ((0, jsx_runtime_1.jsx)(DraggableDialog_1.default, { open: true, onClose: handleClose, maxWidth: "xl", title: title, children: showBulkEditor && enableBulkEdit ? ((0, jsx_runtime_1.jsx)(SetColorDialogBulkEditPanel_1.default, { currLayout: currLayout, onClose: arg => {
33
+ if (arg) {
34
+ setCurrLayout(arg);
35
+ }
36
+ setShowBulkEditor(false);
37
+ } })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.DialogContent, { className: classes.content, children: [(0, jsx_runtime_1.jsxs)("div", { className: classes.fr, children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
38
+ setShowTips(!showTips);
39
+ }, children: showTips ? 'Hide tips' : 'Show tips' }), enableBulkEdit ? ((0, jsx_runtime_1.jsx)(material_1.Button, { color: "secondary", variant: "contained", onClick: () => {
40
+ setShowBulkEditor(!showBulkEditor);
41
+ }, children: "Show Bulk row editor" })) : null] }), showTips ? (0, jsx_runtime_1.jsx)(SetColorDialogHelpfulTips_1.default, {}) : null, enableRowPalettizer ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("br", {}), (0, jsx_runtime_1.jsx)(SetColorDialogRowPalettizer_1.default, { currLayout: currLayout, setCurrLayout: setCurrLayout })] })) : null, (0, jsx_runtime_1.jsx)(SourcesGridComponent, { rows: currLayout, onChange: setCurrLayout, showTips: showTips })] }), (0, jsx_runtime_1.jsxs)(material_1.DialogActions, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", type: "submit", color: "inherit", onClick: () => {
42
+ model.clearLayout();
43
+ setCurrLayout(model.sources || []);
44
+ }, children: "Clear custom settings" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "secondary", onClick: () => {
45
+ handleClose();
46
+ setCurrLayout([...(model.sources || [])]);
47
+ }, children: "Cancel" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "primary", type: "submit", onClick: () => {
48
+ model.setLayout(currLayout);
49
+ handleClose();
50
+ }, children: "Submit" })] })] })) }));
51
+ }
@@ -0,0 +1,10 @@
1
+ export default function SetColorDialogBulkEditPanel({ onClose, currLayout, }: {
2
+ currLayout: {
3
+ name: string;
4
+ [key: string]: unknown;
5
+ }[];
6
+ onClose: (arg?: {
7
+ name: string;
8
+ [key: string]: unknown;
9
+ }[]) => void;
10
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = SetColorDialogBulkEditPanel;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const ui_1 = require("@jbrowse/core/ui");
7
+ const material_1 = require("@mui/material");
8
+ const mui_1 = require("tss-react/mui");
9
+ const useStyles = (0, mui_1.makeStyles)()({
10
+ textAreaFont: {
11
+ fontFamily: 'Courier New',
12
+ },
13
+ });
14
+ function SetColorDialogBulkEditPanel({ onClose, currLayout, }) {
15
+ const { classes } = useStyles();
16
+ const [val, setVal] = (0, react_1.useState)('');
17
+ const [error, setError] = (0, react_1.useState)();
18
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.DialogContent, { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { children: "Paste CSV or TSV. If a header column is present. First line is a header. If a column called \"name\" is present, it uses that to connect to IDs in the table, otherwise it uses the first column no." }), error ? (0, jsx_runtime_1.jsx)(ui_1.ErrorMessage, { error: error }) : null, (0, jsx_runtime_1.jsx)(material_1.TextField, { variant: "outlined", multiline: true, minRows: 5, placeholder: 'name,population\nHG00098,GBR\nHG00101,GBR\nHG00459,CHS\n...', maxRows: 10, fullWidth: true, value: val, onChange: event => {
19
+ setVal(event.target.value);
20
+ }, slotProps: {
21
+ input: {
22
+ classes: {
23
+ input: classes.textAreaFont,
24
+ },
25
+ },
26
+ } })] }), (0, jsx_runtime_1.jsxs)(material_1.DialogActions, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "secondary", onClick: () => {
27
+ const lines = val
28
+ .split('\n')
29
+ .map(f => f.trim())
30
+ .filter(f => !!f);
31
+ const fields = lines[0].split(/[,\t]/gm);
32
+ if (fields.includes('name')) {
33
+ setError('');
34
+ const oldLayout = Object.fromEntries(currLayout.map(record => [record.name, record]));
35
+ const newData = Object.fromEntries(lines.slice(1).map(line => {
36
+ const cols = line.split(/[,\t]/gm);
37
+ const newRecord = Object.fromEntries(cols.map((col, idx) => [fields[idx], col]));
38
+ return [
39
+ newRecord.name,
40
+ {
41
+ ...newRecord,
42
+ ...oldLayout[newRecord.name],
43
+ },
44
+ ];
45
+ }));
46
+ onClose(currLayout.map(record => ({
47
+ ...record,
48
+ ...newData[record.name],
49
+ })));
50
+ }
51
+ else {
52
+ setError(new Error('No "name" column found on line 1'));
53
+ }
54
+ }, children: "Update rows" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "primary", onClick: () => {
55
+ const lines = val
56
+ .split('\n')
57
+ .map(f => f.trim())
58
+ .filter(f => !!f);
59
+ const fields = lines[0].split(/[,\t]/gm);
60
+ if (fields.includes('name')) {
61
+ setError('');
62
+ const oldLayout = Object.fromEntries(currLayout.map(record => [record.name, record]));
63
+ const newData = Object.fromEntries(lines.slice(1).map(line => {
64
+ const cols = line.split(/[,\t]/gm);
65
+ const newRecord = Object.fromEntries(cols.map((col, idx) => [fields[idx], col]));
66
+ return [
67
+ newRecord.name,
68
+ {
69
+ ...newRecord,
70
+ ...oldLayout[newRecord.name],
71
+ },
72
+ ];
73
+ }));
74
+ onClose(currLayout.map(record => ({
75
+ ...newData[record.name],
76
+ })));
77
+ }
78
+ else {
79
+ setError(new Error('No "name" column found on line 1'));
80
+ }
81
+ }, children: "Replace rows" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "inherit", onClick: () => {
82
+ onClose();
83
+ }, children: "Cancel" })] })] }));
84
+ }
@@ -0,0 +1 @@
1
+ export default function SetColorDialogHelpfulTips(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = SetColorDialogHelpfulTips;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ function SetColorDialogHelpfulTips() {
6
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Helpful tips", (0, jsx_runtime_1.jsxs)("ul", { children: [(0, jsx_runtime_1.jsx)("li", { children: "You can select rows in the table with the checkboxes" }), (0, jsx_runtime_1.jsx)("li", { children: "Multi-select is enabled with shift-click and control-click" }), (0, jsx_runtime_1.jsx)("li", { children: "The \"Move selected items up/down\" can re-arrange subtracks" }), (0, jsx_runtime_1.jsx)("li", { children: "Sorting the data grid itself can also re-arrange subtracks" }), (0, jsx_runtime_1.jsx)("li", { children: "Changes are applied when you hit Submit" }), (0, jsx_runtime_1.jsx)("li", { children: "You can click and drag the dialog box to move it on the screen" }), (0, jsx_runtime_1.jsx)("li", { children: "Columns in the table can be hidden using a vertical '...' menu on the right side of each column" })] })] }));
7
+ }
@@ -0,0 +1,10 @@
1
+ export default function SetColorDialogRowPalettizer({ setCurrLayout, currLayout, }: {
2
+ currLayout: {
3
+ name: string;
4
+ [key: string]: unknown;
5
+ }[];
6
+ setCurrLayout: (arg: {
7
+ name: string;
8
+ [key: string]: unknown;
9
+ }[]) => void;
10
+ }): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = SetColorDialogRowPalettizer;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const colors_1 = require("@jbrowse/core/ui/colors");
6
+ const color_1 = require("@jbrowse/core/util/color");
7
+ const material_1 = require("@mui/material");
8
+ function SetColorDialogRowPalettizer({ setCurrLayout, currLayout, }) {
9
+ if (!currLayout.length || !currLayout[0]) {
10
+ return null;
11
+ }
12
+ const fields = Object.keys(currLayout[0]).filter(f => f !== 'name' &&
13
+ f !== 'color' &&
14
+ f !== 'source' &&
15
+ f !== 'label' &&
16
+ f !== 'id' &&
17
+ f !== 'HP');
18
+ return ((0, jsx_runtime_1.jsxs)("div", { children: ["Create color palette based on...", fields.map(r => ((0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "inherit", onClick: () => {
19
+ const map = new Map();
20
+ for (const row of currLayout) {
21
+ const val = map.get(row[r]);
22
+ if (!val) {
23
+ map.set(row[r], 1);
24
+ }
25
+ else {
26
+ map.set(row[r], val + 1);
27
+ }
28
+ }
29
+ const ret = Object.fromEntries([...map.entries()]
30
+ .sort((a, b) => a[1] - b[1])
31
+ .map((r, idx) => [r[0], colors_1.set1[idx] || (0, color_1.randomColor)(r[0])]));
32
+ setCurrLayout(currLayout.map(row => ({
33
+ ...row,
34
+ color: ret[row[r]],
35
+ })));
36
+ }, children: r }, r))), (0, jsx_runtime_1.jsx)(material_1.Button, { onClick: () => {
37
+ setCurrLayout(currLayout.map(row => ({
38
+ ...row,
39
+ color: undefined,
40
+ })));
41
+ }, children: "Clear colors" })] }));
42
+ }
@@ -1,13 +1,9 @@
1
1
  import type { WiggleDisplayModel } from '../model';
2
2
  import type { GridRowId } from '@mui/x-data-grid';
3
- export declare function moveUp(arr: {
3
+ export declare function moveUp<T extends {
4
4
  name: string;
5
- }[], sel: GridRowId[], by?: number): {
5
+ }>(arr: T[], sel: GridRowId[], by?: number): T[];
6
+ export declare function moveDown<T extends {
6
7
  name: string;
7
- }[];
8
- export declare function moveDown(arr: {
9
- name: string;
10
- }[], sel: GridRowId[], by?: number): {
11
- name: string;
12
- }[];
8
+ }>(arr: T[], sel: GridRowId[], by?: number): T[];
13
9
  export declare function getOffset(model: WiggleDisplayModel): number;