higlass 2.2.2 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/scripts/Autocomplete.jsx +12 -3
- package/app/scripts/Button.jsx +20 -24
- package/app/scripts/ContextMenuContainer.jsx +1 -3
- package/app/scripts/ContextMenuItem.jsx +15 -16
- package/app/scripts/Dialog.jsx +30 -29
- package/app/scripts/HiGlassComponent.jsx +54 -36
- package/app/scripts/HorizontalItem.jsx +50 -21
- package/app/scripts/HorizontalTrack.jsx +1 -0
- package/app/scripts/ListWrapper.jsx +6 -17
- package/app/scripts/Modal.jsx +14 -13
- package/app/scripts/PopupMenu.jsx +6 -12
- package/app/scripts/SortableList.jsx +119 -64
- package/app/scripts/TrackArea.jsx +19 -24
- package/app/scripts/TrackControl.jsx +16 -27
- package/app/scripts/VerticalItem.jsx +53 -22
- package/app/scripts/VerticalTrack.jsx +1 -0
- package/app/scripts/api.js +5 -4
- package/app/scripts/hglib.jsx +38 -5
- package/app/scripts/test-helpers/test-helpers.jsx +2 -2
- package/app/scripts/utils/get-higlass-components.js +2 -2
- package/app/scripts/utils/react-dom-compat.js +100 -0
- package/app/styles/HiGlass.scss +1 -0
- package/dist/app/scripts/Autocomplete.d.ts +3 -1
- package/dist/app/scripts/ContextMenuContainer.d.ts +0 -1
- package/dist/app/scripts/ContextMenuItem.d.ts +9 -15
- package/dist/app/scripts/HiGlassComponent.d.ts +0 -3
- package/dist/app/scripts/HorizontalItem.d.ts +1 -1
- package/dist/app/scripts/ListWrapper.d.ts +2 -7
- package/dist/app/scripts/PopupMenu.d.ts +2 -4
- package/dist/app/scripts/SortableList.d.ts +6 -2
- package/dist/app/scripts/VerticalItem.d.ts +1 -1
- package/dist/app/scripts/hglib.d.ts +2 -2
- package/dist/app/scripts/utils/react-dom-compat.d.ts +27 -0
- package/dist/hglib.js +13136 -11155
- package/dist/hglib.min.js +89 -89
- package/dist/higlass.mjs +13144 -11163
- package/dist/package.json +7 -5
- package/package.json +7 -5
|
@@ -17,6 +17,9 @@ class Autocomplete extends React.Component {
|
|
|
17
17
|
isOpen: false,
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
+
this.itemRefs = {};
|
|
21
|
+
this.menuRef = null;
|
|
22
|
+
|
|
20
23
|
this.keyDownHandlers = {
|
|
21
24
|
ArrowDown(event) {
|
|
22
25
|
event.preventDefault();
|
|
@@ -139,7 +142,7 @@ class Autocomplete extends React.Component {
|
|
|
139
142
|
|
|
140
143
|
maybeScrollItemIntoView() {
|
|
141
144
|
if (this.state.isOpen === true && this.state.highlightedIndex !== null) {
|
|
142
|
-
const itemNode = this.
|
|
145
|
+
const itemNode = this.itemRefs[this.state.highlightedIndex];
|
|
143
146
|
itemNode?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
144
147
|
}
|
|
145
148
|
}
|
|
@@ -250,7 +253,9 @@ class Autocomplete extends React.Component {
|
|
|
250
253
|
// Ignore blur to prevent menu from de-rendering before we can process click
|
|
251
254
|
onMouseEnter: () => this.highlightItemFromMouse(index),
|
|
252
255
|
onClick: () => this.selectItemFromMouse(item),
|
|
253
|
-
ref:
|
|
256
|
+
ref: (el) => {
|
|
257
|
+
this.itemRefs[index] = el;
|
|
258
|
+
},
|
|
254
259
|
});
|
|
255
260
|
});
|
|
256
261
|
const style = {
|
|
@@ -260,7 +265,11 @@ class Autocomplete extends React.Component {
|
|
|
260
265
|
};
|
|
261
266
|
if (!items.length) return null;
|
|
262
267
|
const menu = this.props.renderMenu(items, this.props.value, style);
|
|
263
|
-
return React.cloneElement(menu, {
|
|
268
|
+
return React.cloneElement(menu, {
|
|
269
|
+
ref: (el) => {
|
|
270
|
+
this.menuRef = el;
|
|
271
|
+
},
|
|
272
|
+
});
|
|
264
273
|
}
|
|
265
274
|
|
|
266
275
|
handleInputBlur() {
|
package/app/scripts/Button.jsx
CHANGED
|
@@ -4,30 +4,26 @@ import React from 'react';
|
|
|
4
4
|
|
|
5
5
|
import classes from '../styles/Button.module.scss';
|
|
6
6
|
|
|
7
|
-
const Button = React.forwardRef(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
onClick: () => {},
|
|
28
|
-
styleName: '',
|
|
29
|
-
type: 'button',
|
|
30
|
-
};
|
|
7
|
+
const Button = React.forwardRef(
|
|
8
|
+
({ onClick = () => {}, styleName = '', children, ...props }, ref) => (
|
|
9
|
+
<button
|
|
10
|
+
ref={ref}
|
|
11
|
+
className={classes[styleName] ?? classes.button}
|
|
12
|
+
disabled={props.disable}
|
|
13
|
+
onBlur={props.onBlur}
|
|
14
|
+
onClick={onClick}
|
|
15
|
+
onMouseDown={props.onMouseDown}
|
|
16
|
+
onMouseOut={props.onMouseOut}
|
|
17
|
+
onMouseUp={props.onMouseUp}
|
|
18
|
+
type="button"
|
|
19
|
+
>
|
|
20
|
+
{children}
|
|
21
|
+
{props.shortcut && (
|
|
22
|
+
<span className={classes['button-shortcut']}>{props.shortcut}</span>
|
|
23
|
+
)}
|
|
24
|
+
</button>
|
|
25
|
+
),
|
|
26
|
+
);
|
|
31
27
|
|
|
32
28
|
Button.propTypes = {
|
|
33
29
|
children: PropTypes.any,
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import React from 'react';
|
|
5
|
-
import ReactDOM from 'react-dom';
|
|
6
5
|
|
|
7
6
|
import { THEME_DARK } from './configs';
|
|
8
7
|
|
|
@@ -101,8 +100,7 @@ class ContextMenuContainer extends React.Component {
|
|
|
101
100
|
if (this.adjusted) return;
|
|
102
101
|
|
|
103
102
|
this.adjusted = true;
|
|
104
|
-
|
|
105
|
-
const bbox = this.divDom.getBoundingClientRect();
|
|
103
|
+
const bbox = this.div.getBoundingClientRect();
|
|
106
104
|
|
|
107
105
|
const parentBbox = this.props.parentBbox
|
|
108
106
|
? this.props.parentBbox
|
|
@@ -9,37 +9,36 @@ import classes from '../styles/ContextMenu.module.scss';
|
|
|
9
9
|
* @typedef ContextMenuItemProps
|
|
10
10
|
* @prop {string} [className]
|
|
11
11
|
* @prop {(evt: React.MouseEvent) => void} onClick
|
|
12
|
-
* @prop {(evt: React.MouseEvent) => void} onMouseEnter
|
|
13
|
-
* @prop {(evt: React.MouseEvent) => void} onMouseLeave
|
|
12
|
+
* @prop {(evt: React.MouseEvent) => void} [onMouseEnter]
|
|
13
|
+
* @prop {(evt: React.MouseEvent) => void} [onMouseLeave]
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* @param {React.PropsWithChildren<ContextMenuItemProps>} props
|
|
18
18
|
*/
|
|
19
|
-
function ContextMenuItem(
|
|
19
|
+
function ContextMenuItem({
|
|
20
|
+
onMouseEnter = () => undefined,
|
|
21
|
+
onMouseLeave = () => undefined,
|
|
22
|
+
onClick,
|
|
23
|
+
className,
|
|
24
|
+
children,
|
|
25
|
+
}) {
|
|
20
26
|
return (
|
|
21
27
|
<div
|
|
22
|
-
data-menu-item-for={
|
|
23
|
-
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
onMouseEnter={(e) => props.onMouseEnter(e)}
|
|
28
|
-
onMouseLeave={(e) => props.onMouseLeave(e)}
|
|
28
|
+
data-menu-item-for={typeof children === 'string' ? children : null}
|
|
29
|
+
className={clsx(classes['context-menu-item'], className)}
|
|
30
|
+
onClick={(e) => onClick(e)}
|
|
31
|
+
onMouseEnter={(e) => onMouseEnter(e)}
|
|
32
|
+
onMouseLeave={(e) => onMouseLeave(e)}
|
|
29
33
|
// biome-ignore lint/a11y/useSemanticElements:
|
|
30
34
|
role="button"
|
|
31
35
|
tabIndex={0}
|
|
32
36
|
>
|
|
33
|
-
<span className={classes['context-menu-span']}>{
|
|
37
|
+
<span className={classes['context-menu-span']}>{children}</span>
|
|
34
38
|
</div>
|
|
35
39
|
);
|
|
36
40
|
}
|
|
37
41
|
|
|
38
|
-
ContextMenuItem.defaultProps = {
|
|
39
|
-
onMouseEnter: () => undefined,
|
|
40
|
-
onMouseLeave: () => undefined,
|
|
41
|
-
};
|
|
42
|
-
|
|
43
42
|
ContextMenuItem.propTypes = {
|
|
44
43
|
children: PropTypes.node.isRequired,
|
|
45
44
|
onClick: PropTypes.func.isRequired,
|
package/app/scripts/Dialog.jsx
CHANGED
|
@@ -10,53 +10,62 @@ import withModal from './hocs/with-modal';
|
|
|
10
10
|
|
|
11
11
|
import classes from '../styles/Dialog.module.scss';
|
|
12
12
|
|
|
13
|
-
function Dialog(
|
|
13
|
+
function Dialog({
|
|
14
|
+
cancelTitle = 'Cancel',
|
|
15
|
+
hide = false,
|
|
16
|
+
maxHeight = false,
|
|
17
|
+
okayOnly = false,
|
|
18
|
+
okayTitle = 'Ok',
|
|
19
|
+
modal,
|
|
20
|
+
onCancel,
|
|
21
|
+
onOkay,
|
|
22
|
+
title,
|
|
23
|
+
cancelShortcut,
|
|
24
|
+
okayShortcut,
|
|
25
|
+
children,
|
|
26
|
+
}) {
|
|
14
27
|
const handleCancel = () => {
|
|
15
|
-
|
|
16
|
-
if (
|
|
28
|
+
modal.close();
|
|
29
|
+
if (onCancel) onCancel();
|
|
17
30
|
};
|
|
18
31
|
|
|
19
32
|
const handleOkay = () => {
|
|
20
|
-
|
|
21
|
-
if (
|
|
33
|
+
modal.close();
|
|
34
|
+
if (onOkay) onOkay();
|
|
22
35
|
};
|
|
23
36
|
|
|
24
37
|
return (
|
|
25
|
-
<Modal closeButton={false} hide={
|
|
38
|
+
<Modal closeButton={false} hide={hide} maxHeight={maxHeight}>
|
|
26
39
|
<>
|
|
27
40
|
<header className={classes['dialog-header']}>
|
|
28
|
-
<h3>{
|
|
41
|
+
<h3>{title}</h3>
|
|
29
42
|
<Button onClick={handleCancel}>
|
|
30
43
|
<Cross />
|
|
31
44
|
</Button>
|
|
32
45
|
</header>
|
|
33
|
-
{
|
|
46
|
+
{maxHeight ? (
|
|
34
47
|
<main
|
|
35
|
-
className={clsx(
|
|
36
|
-
props.maxHeight && classes['dialog-main-max-height'],
|
|
37
|
-
)}
|
|
48
|
+
className={clsx(maxHeight && classes['dialog-main-max-height'])}
|
|
38
49
|
>
|
|
39
|
-
{
|
|
50
|
+
{children}
|
|
40
51
|
</main>
|
|
41
52
|
) : (
|
|
42
|
-
<main>{
|
|
53
|
+
<main>{children}</main>
|
|
43
54
|
)}
|
|
44
55
|
<footer
|
|
45
56
|
className={
|
|
46
|
-
classes[
|
|
47
|
-
props.maxHeight ? 'dialog-footer-max-height' : 'dialog-footer'
|
|
48
|
-
]
|
|
57
|
+
classes[maxHeight ? 'dialog-footer-max-height' : 'dialog-footer']
|
|
49
58
|
}
|
|
50
59
|
>
|
|
51
|
-
{
|
|
60
|
+
{okayOnly ? (
|
|
52
61
|
<div />
|
|
53
62
|
) : (
|
|
54
|
-
<Button onClick={handleCancel} shortcut={
|
|
55
|
-
{
|
|
63
|
+
<Button onClick={handleCancel} shortcut={cancelShortcut}>
|
|
64
|
+
{cancelTitle}
|
|
56
65
|
</Button>
|
|
57
66
|
)}
|
|
58
|
-
<Button onClick={handleOkay} shortcut={
|
|
59
|
-
{
|
|
67
|
+
<Button onClick={handleOkay} shortcut={okayShortcut}>
|
|
68
|
+
{okayTitle}
|
|
60
69
|
</Button>
|
|
61
70
|
</footer>
|
|
62
71
|
</>
|
|
@@ -64,14 +73,6 @@ function Dialog(props) {
|
|
|
64
73
|
);
|
|
65
74
|
}
|
|
66
75
|
|
|
67
|
-
Dialog.defaultProps = {
|
|
68
|
-
cancelTitle: 'Cancel',
|
|
69
|
-
hide: false,
|
|
70
|
-
maxHeight: false,
|
|
71
|
-
okayOnly: false,
|
|
72
|
-
okayTitle: 'Ok',
|
|
73
|
-
};
|
|
74
|
-
|
|
75
76
|
Dialog.propTypes = {
|
|
76
77
|
cancelShortcut: PropTypes.string,
|
|
77
78
|
cancelTitle: PropTypes.string,
|
|
@@ -7,9 +7,8 @@ import * as PIXI from 'pixi.js';
|
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import createPubSub, { globalPubSub } from 'pub-sub-es';
|
|
9
9
|
import React from 'react';
|
|
10
|
-
import ReactGridLayout from 'react-grid-layout';
|
|
10
|
+
import ReactGridLayout, { getCompactor } from 'react-grid-layout';
|
|
11
11
|
import slugid from 'slugid';
|
|
12
|
-
import parse from 'url-parse';
|
|
13
12
|
import vkbeautify from 'vkbeautify';
|
|
14
13
|
|
|
15
14
|
import ChromosomeInfo from './ChromosomeInfo';
|
|
@@ -290,7 +289,6 @@ class HiGlassComponent extends React.Component {
|
|
|
290
289
|
this.pluginDataFetchers = pluginDataFetchers;
|
|
291
290
|
|
|
292
291
|
this.state = {
|
|
293
|
-
currentBreakpoint: 'lg',
|
|
294
292
|
width: 0,
|
|
295
293
|
height: 0,
|
|
296
294
|
rowHeight,
|
|
@@ -555,10 +553,18 @@ class HiGlassComponent extends React.Component {
|
|
|
555
553
|
this.fitPixiToParentContainer();
|
|
556
554
|
|
|
557
555
|
// keep track of the width and height of this element, because it
|
|
558
|
-
// needs to be reflected in the size of our drawing surface
|
|
556
|
+
// needs to be reflected in the size of our drawing surface.
|
|
557
|
+
// Also measure initial width so that ReactGridLayout renders grid items
|
|
558
|
+
// with valid dimensions on the first mounted render. Without this,
|
|
559
|
+
// width=0 causes react-grid-layout v2 to calculate negative column
|
|
560
|
+
// widths, and TiledPlot's ResizeSensor fails to detect the subsequent
|
|
561
|
+
// resize from zero to the actual size.
|
|
562
|
+
const [initialWidth, initialHeight] = getElementDim(this.element);
|
|
559
563
|
this.setState({
|
|
560
564
|
svgElement: this.svgElement,
|
|
561
565
|
canvasElement: this.canvasElement,
|
|
566
|
+
...(initialWidth > 0 ? { width: initialWidth } : {}),
|
|
567
|
+
...(initialHeight > 0 ? { height: initialHeight } : {}),
|
|
562
568
|
});
|
|
563
569
|
|
|
564
570
|
this.waitForDOMAttachment(() => {
|
|
@@ -588,11 +594,11 @@ class HiGlassComponent extends React.Component {
|
|
|
588
594
|
}
|
|
589
595
|
|
|
590
596
|
getTrackObject(viewUid, trackUid) {
|
|
591
|
-
return this.tiledPlots[viewUid]
|
|
597
|
+
return this.tiledPlots[viewUid]?.trackRenderer?.getTrackObject(trackUid);
|
|
592
598
|
}
|
|
593
599
|
|
|
594
600
|
getTrackRenderer(viewUid) {
|
|
595
|
-
return this.tiledPlots[viewUid]
|
|
601
|
+
return this.tiledPlots[viewUid]?.trackRenderer;
|
|
596
602
|
}
|
|
597
603
|
|
|
598
604
|
UNSAFE_componentWillReceiveProps(newProps) {
|
|
@@ -985,12 +991,6 @@ class HiGlassComponent extends React.Component {
|
|
|
985
991
|
this.resizeHandler();
|
|
986
992
|
}
|
|
987
993
|
|
|
988
|
-
onBreakpointChange(breakpoint) {
|
|
989
|
-
this.setState({
|
|
990
|
-
currentBreakpoint: breakpoint,
|
|
991
|
-
});
|
|
992
|
-
}
|
|
993
|
-
|
|
994
994
|
handleOverlayMouseEnter(uid) {
|
|
995
995
|
this.setState({
|
|
996
996
|
mouseOverOverlayUid: uid,
|
|
@@ -1316,7 +1316,7 @@ class HiGlassComponent extends React.Component {
|
|
|
1316
1316
|
) > epsilon;
|
|
1317
1317
|
|
|
1318
1318
|
const hasBrushMoved =
|
|
1319
|
-
sourceTrack
|
|
1319
|
+
sourceTrack?.options &&
|
|
1320
1320
|
lockedTrack.options &&
|
|
1321
1321
|
typeof sourceTrack.options.scaleStartPercent !== 'undefined' &&
|
|
1322
1322
|
typeof sourceTrack.options.scaleEndPercent !== 'undefined' &&
|
|
@@ -4196,6 +4196,7 @@ class HiGlassComponent extends React.Component {
|
|
|
4196
4196
|
}
|
|
4197
4197
|
|
|
4198
4198
|
triggerViewChange() {
|
|
4199
|
+
if (!this.mounted) return;
|
|
4199
4200
|
const viewsString = this.getViewsAsString();
|
|
4200
4201
|
this.viewChangeListener.forEach((callback) => callback(viewsString));
|
|
4201
4202
|
}
|
|
@@ -5317,8 +5318,29 @@ class HiGlassComponent extends React.Component {
|
|
|
5317
5318
|
/>
|
|
5318
5319
|
) : null;
|
|
5319
5320
|
|
|
5321
|
+
// Constrain the grid item child to the expected pixel height
|
|
5322
|
+
// derived from view.layout.h. react-grid-layout v2 syncs its
|
|
5323
|
+
// internal layout state via useEffect (async), so after a layout
|
|
5324
|
+
// change (e.g. track removal) the grid item's DOM dimensions can
|
|
5325
|
+
// be stale (too large). maxHeight ensures TiledPlot.measureSize()
|
|
5326
|
+
// reads the correct (new) height even before the grid re-syncs.
|
|
5327
|
+
const marginY = this.isEditable() ? 10 : 0;
|
|
5328
|
+
const expectedPixelHeight = view.layout
|
|
5329
|
+
? Math.round(
|
|
5330
|
+
this.state.rowHeight * view.layout.h +
|
|
5331
|
+
Math.max(0, view.layout.h - 1) * marginY,
|
|
5332
|
+
)
|
|
5333
|
+
: undefined;
|
|
5334
|
+
|
|
5320
5335
|
return (
|
|
5321
|
-
<div
|
|
5336
|
+
<div
|
|
5337
|
+
key={view.uid}
|
|
5338
|
+
style={
|
|
5339
|
+
expectedPixelHeight !== undefined
|
|
5340
|
+
? { maxHeight: expectedPixelHeight, overflow: 'hidden' }
|
|
5341
|
+
: undefined
|
|
5342
|
+
}
|
|
5343
|
+
>
|
|
5322
5344
|
<div
|
|
5323
5345
|
ref={(c) => {
|
|
5324
5346
|
this.tiledAreasDivs[view.uid] = c;
|
|
@@ -5360,34 +5382,30 @@ class HiGlassComponent extends React.Component {
|
|
|
5360
5382
|
|
|
5361
5383
|
const gridLayout = (
|
|
5362
5384
|
<ReactGridLayout
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
this.
|
|
5385
|
+
gridConfig={{
|
|
5386
|
+
cols: 12,
|
|
5387
|
+
rowHeight: this.state.rowHeight,
|
|
5388
|
+
// for some reason, this becomes 40 within the react-grid component
|
|
5389
|
+
// (try resizing the component to see how much the height changes)
|
|
5390
|
+
// Programming by coincidence FTW :-/
|
|
5391
|
+
margin: this.isEditable() ? [10, 10] : [0, 0],
|
|
5392
|
+
containerPadding: [containerPaddingX, containerPaddingY],
|
|
5393
|
+
}}
|
|
5394
|
+
dragConfig={{
|
|
5395
|
+
enabled: this.isEditable(),
|
|
5396
|
+
handle: `.${stylesMTHeader['multitrack-header-grabber']}`,
|
|
5397
|
+
}}
|
|
5398
|
+
resizeConfig={{
|
|
5399
|
+
enabled: this.isEditable(),
|
|
5366
5400
|
}}
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
draggableHandle={`.${stylesMTHeader['multitrack-header-grabber']}`}
|
|
5371
|
-
isDraggable={this.isEditable()}
|
|
5372
|
-
isResizable={this.isEditable()}
|
|
5401
|
+
compactor={getCompactor(
|
|
5402
|
+
this.state.viewConfig.compactLayout === false ? null : 'vertical',
|
|
5403
|
+
)}
|
|
5373
5404
|
layout={layouts}
|
|
5374
|
-
margin={this.isEditable() ? [10, 10] : [0, 0]}
|
|
5375
|
-
measureBeforeMount={false}
|
|
5376
|
-
onBreakpointChange={this.onBreakpointChange.bind(this)}
|
|
5377
5405
|
onDragStart={this.handleDragStart.bind(this)}
|
|
5378
5406
|
onDragStop={this.handleDragStop.bind(this)}
|
|
5379
5407
|
onLayoutChange={this.handleLayoutChange.bind(this)}
|
|
5380
5408
|
onResize={this.resizeHandler.bind(this)}
|
|
5381
|
-
rowHeight={this.state.rowHeight}
|
|
5382
|
-
// for some reason, this becomes 40 within the react-grid component
|
|
5383
|
-
// (try resizing the component to see how much the height changes)
|
|
5384
|
-
// Programming by coincidence FTW :-/
|
|
5385
|
-
// WidthProvider option
|
|
5386
|
-
// I like to have it animate on mount. If you don't, delete
|
|
5387
|
-
// `useCSSTransforms` (it's default `true`)
|
|
5388
|
-
// and set `measureBeforeMount={true}`.
|
|
5389
|
-
useCSSTransforms={this.mounted}
|
|
5390
|
-
verticalCompact={this.state.viewConfig.compactLayout}
|
|
5391
5409
|
width={this.state.width}
|
|
5392
5410
|
>
|
|
5393
5411
|
{this.tiledAreas}
|
|
@@ -1,30 +1,59 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
|
+
|
|
3
|
+
import { useSortable } from '@dnd-kit/sortable';
|
|
4
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
2
5
|
import React from 'react';
|
|
3
|
-
import { SortableElement } from 'react-sortable-hoc';
|
|
4
6
|
|
|
5
7
|
import HorizontalTrack from './HorizontalTrack';
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
function HorizontalItem(props) {
|
|
10
|
+
const {
|
|
11
|
+
attributes,
|
|
12
|
+
listeners,
|
|
13
|
+
setNodeRef,
|
|
14
|
+
transform,
|
|
15
|
+
transition,
|
|
16
|
+
isDragging,
|
|
17
|
+
} = useSortable({ id: props.uid });
|
|
18
|
+
|
|
19
|
+
const adjustedTransform = transform ? { ...transform, x: 0 } : transform;
|
|
20
|
+
|
|
21
|
+
const style = {
|
|
22
|
+
transform: CSS.Transform.toString(adjustedTransform),
|
|
23
|
+
transition,
|
|
24
|
+
...(isDragging
|
|
25
|
+
? {
|
|
26
|
+
zIndex: 10,
|
|
27
|
+
background: 'rgba(0, 0, 0, 0.1)',
|
|
28
|
+
border: '2px dashed rgba(0, 0, 0, 0.3)',
|
|
29
|
+
borderRadius: 4,
|
|
30
|
+
}
|
|
31
|
+
: {}),
|
|
32
|
+
};
|
|
33
|
+
|
|
8
34
|
return (
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
<div ref={setNodeRef} style={style}>
|
|
36
|
+
<HorizontalTrack
|
|
37
|
+
className={props.className}
|
|
38
|
+
dragHandleProps={{ ...attributes, ...listeners }}
|
|
39
|
+
editable={props.editable}
|
|
40
|
+
handleConfigTrack={props.handleConfigTrack}
|
|
41
|
+
handleResizeTrack={props.handleResizeTrack}
|
|
42
|
+
height={props.height}
|
|
43
|
+
isCollapsed={props.isCollapsed}
|
|
44
|
+
item={props.item}
|
|
45
|
+
onAddSeries={props.onAddSeries}
|
|
46
|
+
onCollapseTrack={props.onCollapseTrack}
|
|
47
|
+
onExpandTrack={props.onExpandTrack}
|
|
48
|
+
onCloseTrack={props.onCloseTrack}
|
|
49
|
+
onCloseTrackMenuOpened={props.onCloseTrackMenuOpened}
|
|
50
|
+
onConfigTrackMenuOpened={props.onConfigTrackMenuOpened}
|
|
51
|
+
resizeHandles={props.resizeHandles}
|
|
52
|
+
uid={props.uid}
|
|
53
|
+
width={props.width}
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
27
56
|
);
|
|
28
|
-
}
|
|
57
|
+
}
|
|
29
58
|
|
|
30
59
|
export default HorizontalItem;
|
|
@@ -17,6 +17,7 @@ class HorizontalTrack extends MoveableTrack {
|
|
|
17
17
|
// center.
|
|
18
18
|
expandCollapseAvailable={true}
|
|
19
19
|
configMenuVisible={this.props.item.configMenuVisible}
|
|
20
|
+
dragHandleProps={this.props.dragHandleProps}
|
|
20
21
|
imgStyleAdd={STYLES}
|
|
21
22
|
imgStyleClose={STYLES}
|
|
22
23
|
imgStyleMove={STYLES}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
|
|
3
|
+
import { arrayMove } from '@dnd-kit/sortable';
|
|
3
4
|
import PropTypes from 'prop-types';
|
|
4
5
|
import React from 'react';
|
|
5
|
-
import { arrayMove } from 'react-sortable-hoc';
|
|
6
6
|
|
|
7
7
|
class ListWrapper extends React.Component {
|
|
8
8
|
constructor({ items }) {
|
|
@@ -19,8 +19,7 @@ class ListWrapper extends React.Component {
|
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
onSortStart({
|
|
23
|
-
e.stopImmediatePropagation();
|
|
22
|
+
onSortStart({ index }) {
|
|
24
23
|
const { onSortStart } = this.props;
|
|
25
24
|
this.setState({ isSorting: true });
|
|
26
25
|
|
|
@@ -29,9 +28,6 @@ class ListWrapper extends React.Component {
|
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
this.sortingIndex = index;
|
|
32
|
-
|
|
33
|
-
this.sortStartTop = e.offsetTop;
|
|
34
|
-
this.sortStartLeft = e.offsetLeft;
|
|
35
31
|
}
|
|
36
32
|
|
|
37
33
|
onSortMove() {}
|
|
@@ -39,14 +35,15 @@ class ListWrapper extends React.Component {
|
|
|
39
35
|
onSortEnd({ oldIndex, newIndex }) {
|
|
40
36
|
const { onSortEnd } = this.props;
|
|
41
37
|
const { items } = this.state;
|
|
38
|
+
const sortedItems = arrayMove(items, oldIndex, newIndex);
|
|
42
39
|
|
|
43
40
|
this.setState({
|
|
44
|
-
items:
|
|
41
|
+
items: sortedItems,
|
|
45
42
|
isSorting: false,
|
|
46
43
|
});
|
|
47
44
|
|
|
48
45
|
if (onSortEnd) {
|
|
49
|
-
onSortEnd(
|
|
46
|
+
onSortEnd(sortedItems);
|
|
50
47
|
}
|
|
51
48
|
|
|
52
49
|
this.sortingIndex = null;
|
|
@@ -63,15 +60,7 @@ class ListWrapper extends React.Component {
|
|
|
63
60
|
onSortMove: this.onSortMove.bind(this),
|
|
64
61
|
};
|
|
65
62
|
|
|
66
|
-
return
|
|
67
|
-
<Component
|
|
68
|
-
{...this.props}
|
|
69
|
-
{...props}
|
|
70
|
-
ref={(element) => {
|
|
71
|
-
this.ref = element;
|
|
72
|
-
}}
|
|
73
|
-
/>
|
|
74
|
-
);
|
|
63
|
+
return <Component {...this.props} {...props} />;
|
|
75
64
|
}
|
|
76
65
|
}
|
|
77
66
|
|
package/app/scripts/Modal.jsx
CHANGED
|
@@ -9,42 +9,43 @@ import withModal from './hocs/with-modal';
|
|
|
9
9
|
|
|
10
10
|
import classes from '../styles/Modal.module.scss';
|
|
11
11
|
|
|
12
|
-
function Modal(
|
|
12
|
+
function Modal({
|
|
13
|
+
closeButton = true,
|
|
14
|
+
hide = false,
|
|
15
|
+
maxHeight = false,
|
|
16
|
+
modal,
|
|
17
|
+
onClose,
|
|
18
|
+
children,
|
|
19
|
+
}) {
|
|
13
20
|
const handleClose = () => {
|
|
14
|
-
|
|
15
|
-
if (
|
|
21
|
+
modal.close();
|
|
22
|
+
if (onClose) onClose();
|
|
16
23
|
};
|
|
17
24
|
|
|
18
25
|
return (
|
|
19
26
|
<div
|
|
20
27
|
className={clsx(classes['modal-background'], {
|
|
21
|
-
[classes['modal-hide']]:
|
|
28
|
+
[classes['modal-hide']]: hide,
|
|
22
29
|
})}
|
|
23
30
|
>
|
|
24
31
|
<div className={classes['modal-wrap']}>
|
|
25
32
|
<div
|
|
26
33
|
className={clsx(classes['modal-window'], {
|
|
27
|
-
[classes['modal-window-max-height']]:
|
|
34
|
+
[classes['modal-window-max-height']]: maxHeight,
|
|
28
35
|
})}
|
|
29
36
|
>
|
|
30
|
-
{
|
|
37
|
+
{closeButton && (
|
|
31
38
|
<Button onClick={handleClose}>
|
|
32
39
|
<Cross />
|
|
33
40
|
</Button>
|
|
34
41
|
)}
|
|
35
|
-
<div className={classes['modal-content']}>{
|
|
42
|
+
<div className={classes['modal-content']}>{children}</div>
|
|
36
43
|
</div>
|
|
37
44
|
</div>
|
|
38
45
|
</div>
|
|
39
46
|
);
|
|
40
47
|
}
|
|
41
48
|
|
|
42
|
-
Modal.defaultProps = {
|
|
43
|
-
closeButton: true,
|
|
44
|
-
hide: false,
|
|
45
|
-
maxHeight: false,
|
|
46
|
-
};
|
|
47
|
-
|
|
48
49
|
Modal.propTypes = {
|
|
49
50
|
children: PropTypes.element.isRequired,
|
|
50
51
|
closeButton: PropTypes.bool,
|