@jbrowse/plugin-wiggle 2.7.0 → 2.7.2

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 (43) hide show
  1. package/dist/DensityRenderer/DensityRenderer.js +2 -2
  2. package/dist/LinePlotRenderer/LinePlotRenderer.js +2 -2
  3. package/dist/MultiDensityRenderer/MultiDensityRenderer.js +5 -8
  4. package/dist/MultiLineRenderer/MultiLineRenderer.js +5 -9
  5. package/dist/MultiLinearWiggleDisplay/components/SetColorDialog.js +2 -102
  6. package/dist/MultiLinearWiggleDisplay/components/SourcesGrid.d.ts +8 -0
  7. package/dist/MultiLinearWiggleDisplay/components/SourcesGrid.js +138 -0
  8. package/dist/MultiRowLineRenderer/MultiRowLineRenderer.js +5 -5
  9. package/dist/MultiRowXYPlotRenderer/MultiRowXYPlotRenderer.js +5 -9
  10. package/dist/MultiXYPlotRenderer/MultiXYPlotRenderer.js +5 -8
  11. package/dist/Tooltip.js +4 -1
  12. package/dist/XYPlotRenderer/XYPlotRenderer.js +2 -2
  13. package/dist/drawDensity.d.ts +17 -0
  14. package/dist/drawDensity.js +66 -0
  15. package/dist/drawLine.d.ts +19 -0
  16. package/dist/drawLine.js +73 -0
  17. package/dist/drawXY.d.ts +19 -0
  18. package/dist/{drawxy.js → drawXY.js} +11 -147
  19. package/dist/util.d.ts +1 -0
  20. package/dist/util.js +17 -1
  21. package/esm/DensityRenderer/DensityRenderer.js +1 -1
  22. package/esm/LinePlotRenderer/LinePlotRenderer.js +1 -1
  23. package/esm/MultiDensityRenderer/MultiDensityRenderer.js +4 -7
  24. package/esm/MultiLineRenderer/MultiLineRenderer.js +4 -8
  25. package/esm/MultiLinearWiggleDisplay/components/SetColorDialog.js +2 -102
  26. package/esm/MultiLinearWiggleDisplay/components/SourcesGrid.d.ts +8 -0
  27. package/esm/MultiLinearWiggleDisplay/components/SourcesGrid.js +110 -0
  28. package/esm/MultiRowLineRenderer/MultiRowLineRenderer.js +4 -4
  29. package/esm/MultiRowXYPlotRenderer/MultiRowXYPlotRenderer.js +4 -8
  30. package/esm/MultiXYPlotRenderer/MultiXYPlotRenderer.js +4 -7
  31. package/esm/Tooltip.js +5 -2
  32. package/esm/XYPlotRenderer/XYPlotRenderer.js +1 -1
  33. package/esm/drawDensity.d.ts +17 -0
  34. package/esm/drawDensity.js +62 -0
  35. package/esm/drawLine.d.ts +19 -0
  36. package/esm/drawLine.js +69 -0
  37. package/esm/drawXY.d.ts +19 -0
  38. package/esm/{drawxy.js → drawXY.js} +2 -136
  39. package/esm/util.d.ts +1 -0
  40. package/esm/util.js +15 -0
  41. package/package.json +2 -2
  42. package/dist/drawxy.d.ts +0 -49
  43. package/esm/drawxy.d.ts +0 -49
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.drawLine = void 0;
4
+ const configuration_1 = require("@jbrowse/core/configuration");
5
+ const util_1 = require("@jbrowse/core/util");
6
+ // locals
7
+ const util_2 = require("./util");
8
+ const fudgeFactor = 0.3;
9
+ const clipHeight = 2;
10
+ function drawLine(ctx, props) {
11
+ const { features, regions, bpPerPx, scaleOpts, height: unadjustedHeight, ticks: { values }, displayCrossHatches, colorCallback, config, offset = 0, } = props;
12
+ const [region] = regions;
13
+ const width = (region.end - region.start) / bpPerPx;
14
+ // the adjusted height takes into account YSCALEBAR_LABEL_OFFSET from the
15
+ // wiggle display, and makes the height of the actual drawn area add
16
+ // "padding" to the top and bottom of the display
17
+ const height = unadjustedHeight - offset * 2;
18
+ const clipColor = (0, configuration_1.readConfObject)(config, 'clipColor');
19
+ const scale = (0, util_2.getScale)({ ...scaleOpts, range: [0, height] });
20
+ const [niceMin, niceMax] = scale.domain();
21
+ const toY = (n) => (0, util_1.clamp)(height - (scale(n) || 0), 0, height) + offset;
22
+ let lastVal;
23
+ let prevLeftPx = -Infinity;
24
+ const reducedFeatures = [];
25
+ for (const feature of features.values()) {
26
+ const [leftPx, rightPx] = (0, util_1.featureSpanPx)(feature, region, bpPerPx);
27
+ // create reduced features, avoiding multiple features per px
28
+ if (Math.floor(leftPx) !== Math.floor(prevLeftPx)) {
29
+ reducedFeatures.push(feature);
30
+ prevLeftPx = leftPx;
31
+ }
32
+ const score = feature.get('score');
33
+ const lowClipping = score < niceMin;
34
+ const highClipping = score > niceMax;
35
+ const w = rightPx - leftPx + fudgeFactor;
36
+ const c = colorCallback(feature, score);
37
+ ctx.beginPath();
38
+ ctx.strokeStyle = c;
39
+ const startPos = lastVal !== undefined ? lastVal : score;
40
+ if (!region.reversed) {
41
+ ctx.moveTo(leftPx, toY(startPos));
42
+ ctx.lineTo(leftPx, toY(score));
43
+ ctx.lineTo(rightPx, toY(score));
44
+ }
45
+ else {
46
+ ctx.moveTo(rightPx, toY(startPos));
47
+ ctx.lineTo(rightPx, toY(score));
48
+ ctx.lineTo(leftPx, toY(score));
49
+ }
50
+ ctx.stroke();
51
+ lastVal = score;
52
+ if (highClipping) {
53
+ ctx.fillStyle = clipColor;
54
+ ctx.fillRect(leftPx, offset, w, clipHeight);
55
+ }
56
+ else if (lowClipping && scaleOpts.scaleType !== 'log') {
57
+ ctx.fillStyle = clipColor;
58
+ ctx.fillRect(leftPx, height - clipHeight, w, height);
59
+ }
60
+ }
61
+ if (displayCrossHatches) {
62
+ ctx.lineWidth = 1;
63
+ ctx.strokeStyle = 'rgba(200,200,200,0.5)';
64
+ values.forEach(tick => {
65
+ ctx.beginPath();
66
+ ctx.moveTo(0, Math.round(toY(tick)));
67
+ ctx.lineTo(width, Math.round(toY(tick)));
68
+ ctx.stroke();
69
+ });
70
+ }
71
+ return { reducedFeatures };
72
+ }
73
+ exports.drawLine = drawLine;
@@ -0,0 +1,19 @@
1
+ import { AnyConfigurationModel } from '@jbrowse/core/configuration';
2
+ import { Feature, Region } from '@jbrowse/core/util';
3
+ import { ScaleOpts } from './util';
4
+ export declare function drawXY(ctx: CanvasRenderingContext2D, props: {
5
+ features: Map<string, Feature> | Feature[];
6
+ bpPerPx: number;
7
+ regions: Region[];
8
+ scaleOpts: ScaleOpts;
9
+ height: number;
10
+ ticks: {
11
+ values: number[];
12
+ };
13
+ config: AnyConfigurationModel;
14
+ displayCrossHatches: boolean;
15
+ offset?: number;
16
+ colorCallback: (f: Feature, score: number) => string;
17
+ }): {
18
+ reducedFeatures: Feature[];
19
+ };
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.drawDensity = exports.drawLine = exports.drawXY = void 0;
3
+ exports.drawXY = void 0;
4
4
  const configuration_1 = require("@jbrowse/core/configuration");
5
5
  const colord_1 = require("@jbrowse/core/util/colord");
6
6
  const util_1 = require("@jbrowse/core/util");
7
+ // locals
8
+ const util_2 = require("./util");
7
9
  function lighten(color, amount) {
8
10
  const hslColor = color.toHsl();
9
11
  const l = hslColor.l * (1 + amount);
@@ -14,23 +16,6 @@ function darken(color, amount) {
14
16
  const l = hslColor.l * (1 - amount);
15
17
  return (0, colord_1.colord)({ ...hslColor, l: (0, util_1.clamp)(l, 0, 100) });
16
18
  }
17
- // locals
18
- const util_2 = require("./util");
19
- // avoid drawing negative width features for SVG exports
20
- function fillRectCtx(x, y, width, height, ctx, color) {
21
- if (width < 0) {
22
- x += width;
23
- width = -width;
24
- }
25
- if (height < 0) {
26
- y += height;
27
- height = -height;
28
- }
29
- if (color) {
30
- ctx.fillStyle = color;
31
- }
32
- ctx.fillRect(x, y, width, height);
33
- }
34
19
  const fudgeFactor = 0.3;
35
20
  const clipHeight = 2;
36
21
  function drawXY(ctx, props) {
@@ -73,7 +58,7 @@ function drawXY(ctx, props) {
73
58
  : c === lastCol
74
59
  ? lastMix
75
60
  : (lastMix = lighten((0, colord_1.colord)(c), 0.4).toHex());
76
- fillRectCtx(leftPx, toY(max), w, getHeight(max), ctx, effectiveC);
61
+ (0, util_2.fillRectCtx)(leftPx, toY(max), w, getHeight(max), ctx, effectiveC);
77
62
  lastCol = c;
78
63
  }
79
64
  }
@@ -100,7 +85,7 @@ function drawXY(ctx, props) {
100
85
  prevLeftPx = leftPx;
101
86
  }
102
87
  hasClipping = hasClipping || score < niceMin || score > niceMax;
103
- fillRectCtx(leftPx, toY(score), w, getHeight(score), ctx, effectiveC);
88
+ (0, util_2.fillRectCtx)(leftPx, toY(score), w, getHeight(score), ctx, effectiveC);
104
89
  lastCol = c;
105
90
  }
106
91
  lastMix = undefined;
@@ -116,7 +101,7 @@ function drawXY(ctx, props) {
116
101
  : c === lastCol
117
102
  ? lastMix
118
103
  : (lastMix = darken((0, colord_1.colord)(c), 0.4).toHex());
119
- fillRectCtx(leftPx, toY(min), w, getHeight(min), ctx, effectiveC);
104
+ (0, util_2.fillRectCtx)(leftPx, toY(min), w, getHeight(min), ctx, effectiveC);
120
105
  lastCol = c;
121
106
  }
122
107
  }
@@ -135,14 +120,14 @@ function drawXY(ctx, props) {
135
120
  const w = Math.max(rightPx - leftPx + fudgeFactor, minSize);
136
121
  if (summaryScoreMode === 'max') {
137
122
  const s = feature.get('summary') ? feature.get('maxScore') : score;
138
- fillRectCtx(leftPx, toY(s), w, getHeight(s), ctx, c);
123
+ (0, util_2.fillRectCtx)(leftPx, toY(s), w, getHeight(s), ctx, c);
139
124
  }
140
125
  else if (summaryScoreMode === 'min') {
141
126
  const s = feature.get('summary') ? feature.get('minScore') : score;
142
- fillRectCtx(leftPx, toY(s), w, getHeight(s), ctx, c);
127
+ (0, util_2.fillRectCtx)(leftPx, toY(s), w, getHeight(s), ctx, c);
143
128
  }
144
129
  else {
145
- fillRectCtx(leftPx, toY(score), w, getHeight(score), ctx, c);
130
+ (0, util_2.fillRectCtx)(leftPx, toY(score), w, getHeight(score), ctx, c);
146
131
  }
147
132
  }
148
133
  }
@@ -156,10 +141,10 @@ function drawXY(ctx, props) {
156
141
  const w = rightPx - leftPx + fudgeFactor;
157
142
  const score = feature.get('score');
158
143
  if (score > niceMax) {
159
- fillRectCtx(leftPx, offset, w, clipHeight, ctx);
144
+ (0, util_2.fillRectCtx)(leftPx, offset, w, clipHeight, ctx);
160
145
  }
161
146
  else if (score < niceMin && scaleOpts.scaleType !== 'log') {
162
- fillRectCtx(leftPx, unadjustedHeight, w, clipHeight, ctx);
147
+ (0, util_2.fillRectCtx)(leftPx, unadjustedHeight, w, clipHeight, ctx);
163
148
  }
164
149
  }
165
150
  }
@@ -177,124 +162,3 @@ function drawXY(ctx, props) {
177
162
  return { reducedFeatures };
178
163
  }
179
164
  exports.drawXY = drawXY;
180
- function drawLine(ctx, props) {
181
- const { features, regions, bpPerPx, scaleOpts, height: unadjustedHeight, ticks: { values }, displayCrossHatches, colorCallback, config, offset = 0, } = props;
182
- const [region] = regions;
183
- const width = (region.end - region.start) / bpPerPx;
184
- // the adjusted height takes into account YSCALEBAR_LABEL_OFFSET from the
185
- // wiggle display, and makes the height of the actual drawn area add
186
- // "padding" to the top and bottom of the display
187
- const height = unadjustedHeight - offset * 2;
188
- const clipColor = (0, configuration_1.readConfObject)(config, 'clipColor');
189
- const scale = (0, util_2.getScale)({ ...scaleOpts, range: [0, height] });
190
- const [niceMin, niceMax] = scale.domain();
191
- const toY = (n) => (0, util_1.clamp)(height - (scale(n) || 0), 0, height) + offset;
192
- let lastVal;
193
- let prevLeftPx = -Infinity;
194
- const reducedFeatures = [];
195
- for (const feature of features.values()) {
196
- const [leftPx, rightPx] = (0, util_1.featureSpanPx)(feature, region, bpPerPx);
197
- // create reduced features, avoiding multiple features per px
198
- if (Math.floor(leftPx) !== Math.floor(prevLeftPx)) {
199
- reducedFeatures.push(feature);
200
- prevLeftPx = leftPx;
201
- }
202
- const score = feature.get('score');
203
- const lowClipping = score < niceMin;
204
- const highClipping = score > niceMax;
205
- const w = rightPx - leftPx + fudgeFactor;
206
- const c = colorCallback(feature, score);
207
- ctx.beginPath();
208
- ctx.strokeStyle = c;
209
- const startPos = lastVal !== undefined ? lastVal : score;
210
- if (!region.reversed) {
211
- ctx.moveTo(leftPx, toY(startPos));
212
- ctx.lineTo(leftPx, toY(score));
213
- ctx.lineTo(rightPx, toY(score));
214
- }
215
- else {
216
- ctx.moveTo(rightPx, toY(startPos));
217
- ctx.lineTo(rightPx, toY(score));
218
- ctx.lineTo(leftPx, toY(score));
219
- }
220
- ctx.stroke();
221
- lastVal = score;
222
- if (highClipping) {
223
- ctx.fillStyle = clipColor;
224
- ctx.fillRect(leftPx, offset, w, clipHeight);
225
- }
226
- else if (lowClipping && scaleOpts.scaleType !== 'log') {
227
- ctx.fillStyle = clipColor;
228
- ctx.fillRect(leftPx, height - clipHeight, w, height);
229
- }
230
- }
231
- if (displayCrossHatches) {
232
- ctx.lineWidth = 1;
233
- ctx.strokeStyle = 'rgba(200,200,200,0.5)';
234
- values.forEach(tick => {
235
- ctx.beginPath();
236
- ctx.moveTo(0, Math.round(toY(tick)));
237
- ctx.lineTo(width, Math.round(toY(tick)));
238
- ctx.stroke();
239
- });
240
- }
241
- return { reducedFeatures };
242
- }
243
- exports.drawLine = drawLine;
244
- function drawDensity(ctx, props) {
245
- const { features, regions, bpPerPx, scaleOpts, height, config } = props;
246
- const [region] = regions;
247
- const pivot = (0, configuration_1.readConfObject)(config, 'bicolorPivot');
248
- const pivotValue = (0, configuration_1.readConfObject)(config, 'bicolorPivotValue');
249
- const negColor = (0, configuration_1.readConfObject)(config, 'negColor');
250
- const posColor = (0, configuration_1.readConfObject)(config, 'posColor');
251
- const color = (0, configuration_1.readConfObject)(config, 'color');
252
- const clipColor = (0, configuration_1.readConfObject)(config, 'clipColor');
253
- const crossing = pivot !== 'none' && scaleOpts.scaleType !== 'log';
254
- const scale = (0, util_2.getScale)({
255
- ...scaleOpts,
256
- pivotValue: crossing ? pivotValue : undefined,
257
- range: crossing ? [negColor, 'white', posColor] : ['white', posColor],
258
- });
259
- const scale2 = (0, util_2.getScale)({ ...scaleOpts, range: [0, height] });
260
- const cb = color === '#f0f'
261
- ? (_, score) => scale(score)
262
- : (feature, score) => (0, configuration_1.readConfObject)(config, 'color', { feature, score });
263
- const [niceMin, niceMax] = scale2.domain();
264
- let prevLeftPx = -Infinity;
265
- let hasClipping = false;
266
- const reducedFeatures = [];
267
- for (const feature of features.values()) {
268
- const [leftPx, rightPx] = (0, util_1.featureSpanPx)(feature, region, bpPerPx);
269
- // create reduced features, avoiding multiple features per px
270
- if (Math.floor(leftPx) !== Math.floor(prevLeftPx)) {
271
- reducedFeatures.push(feature);
272
- prevLeftPx = leftPx;
273
- }
274
- const score = feature.get('score');
275
- hasClipping = hasClipping || score > niceMax || score < niceMin;
276
- const w = rightPx - leftPx + fudgeFactor;
277
- ctx.fillStyle = cb(feature, score);
278
- ctx.fillRect(leftPx, 0, w, height);
279
- }
280
- // second pass: draw clipping
281
- // avoid persisting the red fillstyle with save/restore
282
- ctx.save();
283
- if (hasClipping) {
284
- ctx.fillStyle = clipColor;
285
- for (const feature of features.values()) {
286
- const [leftPx, rightPx] = (0, util_1.featureSpanPx)(feature, region, bpPerPx);
287
- const w = rightPx - leftPx + fudgeFactor;
288
- const score = feature.get('score');
289
- if (score > niceMax) {
290
- fillRectCtx(leftPx, 0, w, clipHeight, ctx);
291
- }
292
- else if (score < niceMin && scaleOpts.scaleType !== 'log') {
293
- fillRectCtx(leftPx, 0, w, clipHeight, ctx);
294
- }
295
- }
296
- }
297
- ctx.restore();
298
- return { reducedFeatures };
299
- }
300
- exports.drawDensity = drawDensity;
package/dist/util.d.ts CHANGED
@@ -72,3 +72,4 @@ export declare function quantitativeStatsAutorun(self: {
72
72
  }): void;
73
73
  export declare function toP(s?: number): number;
74
74
  export declare function round(value: number): number;
75
+ export declare function fillRectCtx(x: number, y: number, width: number, height: number, ctx: CanvasRenderingContext2D, color?: string): void;
package/dist/util.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.round = exports.toP = exports.quantitativeStatsAutorun = exports.getQuantitativeStats = exports.getNiceDomain = exports.getOrigin = exports.getScale = exports.YSCALEBAR_LABEL_OFFSET = void 0;
3
+ exports.fillRectCtx = exports.round = exports.toP = exports.quantitativeStatsAutorun = exports.getQuantitativeStats = exports.getNiceDomain = exports.getOrigin = exports.getScale = exports.YSCALEBAR_LABEL_OFFSET = void 0;
4
4
  const d3_scale_1 = require("d3-scale");
5
5
  const mobx_1 = require("mobx");
6
6
  const util_1 = require("@jbrowse/core/util");
@@ -231,3 +231,19 @@ function round(value) {
231
231
  return Math.round(value * 1e5) / 1e5;
232
232
  }
233
233
  exports.round = round;
234
+ // avoid drawing negative width features for SVG exports
235
+ function fillRectCtx(x, y, width, height, ctx, color) {
236
+ if (width < 0) {
237
+ x += width;
238
+ width = -width;
239
+ }
240
+ if (height < 0) {
241
+ y += height;
242
+ height = -height;
243
+ }
244
+ if (color) {
245
+ ctx.fillStyle = color;
246
+ }
247
+ ctx.fillRect(x, y, width, height);
248
+ }
249
+ exports.fillRectCtx = fillRectCtx;
@@ -1,4 +1,4 @@
1
- import { drawDensity } from '../drawxy';
1
+ import { drawDensity } from '../drawDensity';
2
2
  import WiggleBaseRenderer from '../WiggleBaseRenderer';
3
3
  export default class DensityRenderer extends WiggleBaseRenderer {
4
4
  async draw(ctx, props) {
@@ -1,6 +1,6 @@
1
1
  import WiggleBaseRenderer from '../WiggleBaseRenderer';
2
2
  import { YSCALEBAR_LABEL_OFFSET } from '../util';
3
- import { drawLine } from '../drawxy';
3
+ import { drawLine } from '../drawLine';
4
4
  export default class LinePlotRenderer extends WiggleBaseRenderer {
5
5
  async draw(ctx, props) {
6
6
  return drawLine(ctx, {
@@ -1,21 +1,18 @@
1
1
  import { groupBy } from '@jbrowse/core/util';
2
2
  import WiggleBaseRenderer from '../WiggleBaseRenderer';
3
- import { drawDensity } from '../drawxy';
3
+ import { drawDensity } from '../drawDensity';
4
4
  export default class MultiXYPlotRenderer extends WiggleBaseRenderer {
5
5
  // @ts-expect-error
6
6
  async draw(ctx, props) {
7
7
  const { bpPerPx, sources, regions, features } = props;
8
8
  const [region] = regions;
9
- const groups = groupBy([...features.values()], f => f.get('source'));
9
+ const groups = groupBy(features.values(), f => f.get('source'));
10
10
  const height = props.height / sources.length;
11
11
  const width = (region.end - region.start) / bpPerPx;
12
12
  let feats = [];
13
13
  ctx.save();
14
14
  sources.forEach(source => {
15
- const features = groups[source.name];
16
- if (!features) {
17
- return;
18
- }
15
+ const features = groups[source.name] || [];
19
16
  const { reducedFeatures } = drawDensity(ctx, {
20
17
  ...props,
21
18
  features,
@@ -27,7 +24,7 @@ export default class MultiXYPlotRenderer extends WiggleBaseRenderer {
27
24
  ctx.lineTo(width, height);
28
25
  ctx.stroke();
29
26
  ctx.translate(0, height);
30
- feats = [...feats, ...reducedFeatures];
27
+ feats = feats.concat(reducedFeatures);
31
28
  });
32
29
  ctx.restore();
33
30
  return { reducedFeatures: feats };
@@ -1,23 +1,19 @@
1
1
  import { groupBy } from '@jbrowse/core/util';
2
- import { drawLine } from '../drawxy';
2
+ import { drawLine } from '../drawLine';
3
3
  import WiggleBaseRenderer from '../WiggleBaseRenderer';
4
4
  export default class MultiLineRenderer extends WiggleBaseRenderer {
5
5
  // @ts-expect-error
6
6
  async draw(ctx, props) {
7
7
  const { sources, features } = props;
8
- const groups = groupBy([...features.values()], f => f.get('source'));
8
+ const groups = groupBy(features.values(), f => f.get('source'));
9
9
  let feats = [];
10
10
  sources.forEach(source => {
11
- const features = groups[source.name];
12
- if (!features) {
13
- return;
14
- }
15
11
  const { reducedFeatures } = drawLine(ctx, {
16
12
  ...props,
17
- features,
13
+ features: groups[source.name] || [],
18
14
  colorCallback: () => source.color || 'blue',
19
15
  });
20
- feats = [...feats, ...reducedFeatures];
16
+ feats = feats.concat(reducedFeatures);
21
17
  });
22
18
  return { reducedFeatures: feats };
23
19
  }
@@ -1,28 +1,15 @@
1
1
  import React, { useState } from 'react';
2
2
  import { Button, DialogContent, DialogActions } from '@mui/material';
3
3
  import { makeStyles } from 'tss-react/mui';
4
- import { getStr, isUriLocation, measureGridWidth, useLocalStorage, } from '@jbrowse/core/util';
5
- import { DataGrid } from '@mui/x-data-grid';
4
+ import { useLocalStorage } from '@jbrowse/core/util';
6
5
  import clone from 'clone';
7
6
  // locals
8
7
  import DraggableDialog from './DraggableDialog';
9
- import ColorPicker, { ColorPopover } from '@jbrowse/core/ui/ColorPicker';
10
- import { moveUp, moveDown } from './util';
11
- // icons
12
- import KeyboardDoubleArrowUpIcon from '@mui/icons-material/KeyboardDoubleArrowUp';
13
- import KeyboardDoubleArrowDownIcon from '@mui/icons-material/KeyboardDoubleArrowDown';
14
- import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
15
- import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
16
- import UriLink from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail/UriLink';
8
+ import SourcesGrid from './SourcesGrid';
17
9
  const useStyles = makeStyles()({
18
10
  content: {
19
11
  minWidth: 800,
20
12
  },
21
- cell: {
22
- whiteSpace: 'nowrap',
23
- overflow: 'hidden',
24
- textOverflow: 'ellipsis',
25
- },
26
13
  });
27
14
  export default function SetColorDialog({ model, handleClose, }) {
28
15
  const { classes } = useStyles();
@@ -58,90 +45,3 @@ export default function SetColorDialog({ model, handleClose, }) {
58
45
  handleClose();
59
46
  } }, "Submit"))));
60
47
  }
61
- function SourcesGrid({ rows, onChange, showTips, }) {
62
- const { classes } = useStyles();
63
- const [anchorEl, setAnchorEl] = useState(null);
64
- const [selected, setSelected] = useState([]);
65
- // @ts-expect-error
66
- const { name: _name, color: _color, baseUri: _baseUri, ...rest } = rows[0];
67
- const [widgetColor, setWidgetColor] = useState('blue');
68
- const [currSort, setCurrSort] = useState({
69
- idx: 0,
70
- field: null,
71
- });
72
- return (React.createElement("div", null,
73
- React.createElement(Button, { disabled: !selected.length, onClick: event => setAnchorEl(event.currentTarget) }, "Change color of selected items"),
74
- React.createElement(Button, { onClick: () => onChange(moveUp([...rows], selected)), disabled: !selected.length },
75
- React.createElement(KeyboardArrowUpIcon, null),
76
- showTips ? 'Move selected items up' : null),
77
- React.createElement(Button, { onClick: () => onChange(moveDown([...rows], selected)), disabled: !selected.length },
78
- React.createElement(KeyboardArrowDownIcon, null),
79
- showTips ? 'Move selected items down' : null),
80
- React.createElement(Button, { onClick: () => onChange(moveUp([...rows], selected, rows.length)), disabled: !selected.length },
81
- React.createElement(KeyboardDoubleArrowUpIcon, null),
82
- showTips ? 'Move selected items to top' : null),
83
- React.createElement(Button, { onClick: () => onChange(moveDown([...rows], selected, rows.length)), disabled: !selected.length },
84
- React.createElement(KeyboardDoubleArrowDownIcon, null),
85
- showTips ? 'Move selected items to bottom' : null),
86
- React.createElement(ColorPopover, { anchorEl: anchorEl, color: widgetColor, onChange: c => {
87
- setWidgetColor(c);
88
- selected.forEach(id => {
89
- const elt = rows.find(f => f.name === id);
90
- if (elt) {
91
- elt.color = c;
92
- }
93
- });
94
- onChange([...rows]);
95
- }, onClose: () => setAnchorEl(null) }),
96
- React.createElement("div", { style: { height: 400, width: '100%' } },
97
- React.createElement(DataGrid, { getRowId: row => row.name, checkboxSelection: true, disableRowSelectionOnClick: true, onRowSelectionModelChange: arg => setSelected(arg), rows: rows, rowHeight: 25, columnHeaderHeight: 33, columns: [
98
- {
99
- field: 'color',
100
- headerName: 'Color',
101
- renderCell: params => {
102
- const { value, id } = params;
103
- return (React.createElement(ColorPicker, { color: value || 'blue', onChange: c => {
104
- const elt = rows.find(f => f.name === id);
105
- if (elt) {
106
- elt.color = c;
107
- }
108
- onChange([...rows]);
109
- } }));
110
- },
111
- },
112
- {
113
- field: 'name',
114
- sortingOrder: [null],
115
- headerName: 'Name',
116
- width: measureGridWidth(rows.map(r => r.name)),
117
- },
118
- ...Object.keys(rest).map(val => ({
119
- field: val,
120
- sortingOrder: [null],
121
- renderCell: (params) => {
122
- const { value } = params;
123
- return (React.createElement("div", { className: classes.cell }, isUriLocation(value) ? (React.createElement(UriLink, { value: value })) : (React.createElement(React.Fragment, null, getStr(value)))));
124
- },
125
- // @ts-ignore
126
- width: measureGridWidth(rows.map(r => r[val])),
127
- })),
128
- ], sortModel: [
129
- /* we control the sort as a controlled component using onSortModelChange */
130
- ], onSortModelChange: args => {
131
- const sort = args[0];
132
- const idx = (currSort.idx + 1) % 2;
133
- const field = (sort === null || sort === void 0 ? void 0 : sort.field) || currSort.field;
134
- setCurrSort({ idx, field });
135
- onChange(field
136
- ? [...rows].sort((a, b) => {
137
- // @ts-expect-error
138
- const aa = getStr(a[field]);
139
- // @ts-expect-error
140
- const bb = getStr(b[field]);
141
- return idx === 1
142
- ? aa.localeCompare(bb)
143
- : bb.localeCompare(aa);
144
- })
145
- : rows);
146
- } }))));
147
- }
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { Source } from '../../util';
3
+ declare function SourcesGrid({ rows, onChange, showTips, }: {
4
+ rows: Source[];
5
+ onChange: (arg: Source[]) => void;
6
+ showTips: boolean;
7
+ }): React.JSX.Element;
8
+ export default SourcesGrid;
@@ -0,0 +1,110 @@
1
+ import React, { useState } from 'react';
2
+ import { Button } from '@mui/material';
3
+ import { getStr, measureGridWidth } from '@jbrowse/core/util';
4
+ import { DataGrid } from '@mui/x-data-grid';
5
+ import { makeStyles } from 'tss-react/mui';
6
+ // locals
7
+ import ColorPicker, { ColorPopover } from '@jbrowse/core/ui/ColorPicker';
8
+ import { moveUp, moveDown } from './util';
9
+ // icons
10
+ import KeyboardDoubleArrowUpIcon from '@mui/icons-material/KeyboardDoubleArrowUp';
11
+ import KeyboardDoubleArrowDownIcon from '@mui/icons-material/KeyboardDoubleArrowDown';
12
+ import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
13
+ import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
14
+ import { SanitizedHTML } from '@jbrowse/core/ui';
15
+ const useStyles = makeStyles()({
16
+ cell: {
17
+ whiteSpace: 'nowrap',
18
+ overflow: 'hidden',
19
+ textOverflow: 'ellipsis',
20
+ },
21
+ });
22
+ function SourcesGrid({ rows, onChange, showTips, }) {
23
+ const { classes } = useStyles();
24
+ const [anchorEl, setAnchorEl] = useState(null);
25
+ const [selected, setSelected] = useState([]);
26
+ // @ts-expect-error
27
+ const { name: _name, color: _color, baseUri: _baseUri, ...rest } = rows[0];
28
+ const [widgetColor, setWidgetColor] = useState('blue');
29
+ const [currSort, setCurrSort] = useState({
30
+ idx: 0,
31
+ field: null,
32
+ });
33
+ return (React.createElement("div", null,
34
+ React.createElement(Button, { disabled: !selected.length, onClick: event => setAnchorEl(event.currentTarget) }, "Change color of selected items"),
35
+ React.createElement(Button, { onClick: () => onChange(moveUp([...rows], selected)), disabled: !selected.length },
36
+ React.createElement(KeyboardArrowUpIcon, null),
37
+ showTips ? 'Move selected items up' : null),
38
+ React.createElement(Button, { onClick: () => onChange(moveDown([...rows], selected)), disabled: !selected.length },
39
+ React.createElement(KeyboardArrowDownIcon, null),
40
+ showTips ? 'Move selected items down' : null),
41
+ React.createElement(Button, { onClick: () => onChange(moveUp([...rows], selected, rows.length)), disabled: !selected.length },
42
+ React.createElement(KeyboardDoubleArrowUpIcon, null),
43
+ showTips ? 'Move selected items to top' : null),
44
+ React.createElement(Button, { onClick: () => onChange(moveDown([...rows], selected, rows.length)), disabled: !selected.length },
45
+ React.createElement(KeyboardDoubleArrowDownIcon, null),
46
+ showTips ? 'Move selected items to bottom' : null),
47
+ React.createElement(ColorPopover, { anchorEl: anchorEl, color: widgetColor, onChange: c => {
48
+ setWidgetColor(c);
49
+ selected.forEach(id => {
50
+ const elt = rows.find(f => f.name === id);
51
+ if (elt) {
52
+ elt.color = c;
53
+ }
54
+ });
55
+ onChange([...rows]);
56
+ }, onClose: () => setAnchorEl(null) }),
57
+ React.createElement("div", { style: { height: 400, width: '100%' } },
58
+ React.createElement(DataGrid, { getRowId: row => row.name, checkboxSelection: true, disableRowSelectionOnClick: true, onRowSelectionModelChange: arg => setSelected(arg), rows: rows, rowHeight: 25, columnHeaderHeight: 33, columns: [
59
+ {
60
+ field: 'color',
61
+ headerName: 'Color',
62
+ renderCell: params => {
63
+ const { value, id } = params;
64
+ return (React.createElement(ColorPicker, { color: value || 'blue', onChange: c => {
65
+ const elt = rows.find(f => f.name === id);
66
+ if (elt) {
67
+ elt.color = c;
68
+ }
69
+ onChange([...rows]);
70
+ } }));
71
+ },
72
+ },
73
+ {
74
+ field: 'name',
75
+ sortingOrder: [null],
76
+ headerName: 'Name',
77
+ width: measureGridWidth(rows.map(r => r.name)),
78
+ },
79
+ ...Object.keys(rest).map(val => ({
80
+ field: val,
81
+ sortingOrder: [null],
82
+ renderCell: (params) => {
83
+ const { value } = params;
84
+ return (React.createElement("div", { className: classes.cell },
85
+ React.createElement(SanitizedHTML, { html: getStr(value) })));
86
+ },
87
+ // @ts-ignore
88
+ width: measureGridWidth(rows.map(r => r[val])),
89
+ })),
90
+ ], sortModel: [
91
+ /* we control the sort as a controlled component using onSortModelChange */
92
+ ], onSortModelChange: args => {
93
+ const sort = args[0];
94
+ const idx = (currSort.idx + 1) % 2;
95
+ const field = (sort === null || sort === void 0 ? void 0 : sort.field) || currSort.field;
96
+ setCurrSort({ idx, field });
97
+ onChange(field
98
+ ? [...rows].sort((a, b) => {
99
+ // @ts-expect-error
100
+ const aa = getStr(a[field]);
101
+ // @ts-expect-error
102
+ const bb = getStr(b[field]);
103
+ return idx === 1
104
+ ? aa.localeCompare(bb)
105
+ : bb.localeCompare(aa);
106
+ })
107
+ : rows);
108
+ } }))));
109
+ }
110
+ export default SourcesGrid;