@reltio/components 1.4.1909 → 1.4.1910

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 (29) hide show
  1. package/cjs/ProfileResizablePanes/ProfileResizablePanes.spec.js +113 -68
  2. package/cjs/ResizablePanes/ResizablePanes.d.ts +3 -2
  3. package/cjs/ResizablePanes/ResizablePanes.js +83 -16
  4. package/cjs/ResizablePanes/ResizablePanes.test.js +289 -0
  5. package/cjs/ResizablePanes/styles.d.ts +1 -1
  6. package/cjs/ResizablePanes/styles.js +47 -38
  7. package/cjs/SimpleMatchRulesBlock/SimpleMatchRulesBlock.js +1 -1
  8. package/cjs/SimpleMatchRulesBlock/SimpleMatchRulesBlock.test.js +1 -1
  9. package/cjs/index.d.ts +1 -1
  10. package/cjs/index.js +2 -1
  11. package/cjs/test-utils/index.d.ts +1 -0
  12. package/cjs/test-utils/index.js +15 -1
  13. package/esm/ProfileResizablePanes/ProfileResizablePanes.spec.js +113 -68
  14. package/esm/ResizablePanes/ResizablePanes.d.ts +3 -2
  15. package/esm/ResizablePanes/ResizablePanes.js +84 -17
  16. package/esm/ResizablePanes/ResizablePanes.test.js +284 -0
  17. package/esm/ResizablePanes/styles.d.ts +1 -1
  18. package/esm/ResizablePanes/styles.js +47 -38
  19. package/esm/SimpleMatchRulesBlock/SimpleMatchRulesBlock.js +1 -1
  20. package/esm/SimpleMatchRulesBlock/SimpleMatchRulesBlock.test.js +1 -1
  21. package/esm/index.d.ts +1 -1
  22. package/esm/index.js +1 -1
  23. package/esm/test-utils/index.d.ts +1 -0
  24. package/esm/test-utils/index.js +13 -0
  25. package/package.json +3 -3
  26. package/cjs/ResizablePanes/ResizablePanes.spec.js +0 -192
  27. package/esm/ResizablePanes/ResizablePanes.spec.js +0 -164
  28. /package/cjs/ResizablePanes/{ResizablePanes.spec.d.ts → ResizablePanes.test.d.ts} +0 -0
  29. /package/esm/ResizablePanes/{ResizablePanes.spec.d.ts → ResizablePanes.test.d.ts} +0 -0
@@ -94,11 +94,28 @@ var setUp = function (props) {
94
94
  React.createElement(PaneStub, { key: 0, id: "content" }),
95
95
  React.createElement(PaneStub, { key: 1, id: "rightPanel" })), { wrapper: Providers })), { user: user });
96
96
  };
97
- var getSplitPane1 = function (container) { return container.getElementsByClassName('Pane1')[0]; };
98
- var getSplitPane2 = function (container) { return container.getElementsByClassName('Pane2')[0]; };
99
- var getSplitPanesResizer = function (container) { return container.getElementsByClassName('Resizer')[0]; };
100
- var isResizingDisabled = function (container) { return getSplitPanesResizer(container).classList.contains('disabled'); };
97
+ var getSplitPane1 = function (container) { return container.querySelectorAll('[data-panel-id]')[0]; };
98
+ var getSplitPane2 = function (container) { return container.querySelectorAll('[data-panel-id]')[1]; };
99
+ var getSplitPanesResizer = function (container) { return container.querySelector('[data-resize-handle]'); };
100
+ var isResizingDisabled = function (container) {
101
+ return getSplitPanesResizer(container).getAttribute('data-panel-resize-handle-enabled') === 'false';
102
+ };
103
+ var checkPanelSize = function (panel, size) { return expect(panel.getAttribute('data-panel-size')).toBe(size); };
101
104
  describe('ProfileResizablePanes tests', function () {
105
+ beforeAll(function () {
106
+ jest.spyOn(HTMLElement.prototype, 'clientWidth', 'get').mockReturnValue(1000);
107
+ jest.spyOn(HTMLElement.prototype, 'getBoundingClientRect').mockReturnValue({
108
+ width: 1000,
109
+ height: 1000,
110
+ top: 0,
111
+ left: 0,
112
+ right: 1000,
113
+ bottom: 1000,
114
+ x: 0,
115
+ y: 0,
116
+ toJSON: function () { return ''; }
117
+ });
118
+ });
102
119
  it('should render resizable panes with closed second pane (active is undefined)', function () {
103
120
  var container = setUp().container;
104
121
  expect(screen.getByTestId('content')).toBeInTheDocument();
@@ -106,10 +123,11 @@ describe('ProfileResizablePanes tests', function () {
106
123
  expect(getSplitPane1(container)).toBeInTheDocument();
107
124
  expect(getSplitPane2(container)).toBeInTheDocument();
108
125
  expect(isResizingDisabled(container)).toBe(true);
109
- expect(getSplitPane2(container).style.width).toBe('0px');
126
+ checkPanelSize(getSplitPane1(container), '100.0');
127
+ checkPanelSize(getSplitPane2(container), '0.0');
110
128
  expect(screen.getByRole('button', { name: 'Button 1' })).toBeInTheDocument();
111
129
  expect(screen.getByRole('button', { name: 'Button 2' })).toBeInTheDocument();
112
- expect(screen.getByRole('presentation')).toBeInTheDocument();
130
+ expect(screen.getByRole('separator')).toBeInTheDocument();
113
131
  });
114
132
  it('should render resizable panes with open second pane', function () { return __awaiter(void 0, void 0, void 0, function () {
115
133
  var _a, container, user, button2;
@@ -122,7 +140,8 @@ describe('ProfileResizablePanes tests', function () {
122
140
  expect(getSplitPane1(container)).toBeInTheDocument();
123
141
  expect(getSplitPane2(container)).toBeInTheDocument();
124
142
  expect(isResizingDisabled(container)).toBe(true);
125
- expect(getSplitPane2(container).style.width).toBe('0px');
143
+ checkPanelSize(getSplitPane1(container), '100.0');
144
+ checkPanelSize(getSplitPane2(container), '0.0');
126
145
  expect(screen.getByRole('button', { name: 'Button 1' })).toBeInTheDocument();
127
146
  expect(screen.getByRole('button', { name: 'Button 2' })).toBeInTheDocument();
128
147
  button2 = screen.getByRole('button', { name: 'Button 2' });
@@ -130,7 +149,8 @@ describe('ProfileResizablePanes tests', function () {
130
149
  case 1:
131
150
  _b.sent();
132
151
  expect(isResizingDisabled(container)).toBe(false);
133
- expect(getSplitPane2(container).style.width).toBe('480px');
152
+ checkPanelSize(getSplitPane1(container), '52.0');
153
+ checkPanelSize(getSplitPane2(container), '48.0');
134
154
  expect(screen.getByRole('button', { name: 'Button 1' })).toBeInTheDocument();
135
155
  expect(screen.getByTestId('reltio-profile-right-side-button-2')).toBeInTheDocument();
136
156
  return [2 /*return*/];
@@ -141,11 +161,11 @@ describe('ProfileResizablePanes tests', function () {
141
161
  var container;
142
162
  return __generator(this, function (_a) {
143
163
  container = setUp(__assign(__assign({}, defaultProps), { disabled: true })).container;
144
- expect(getSplitPane2(container).style.width).toBe('0px');
164
+ checkPanelSize(getSplitPane2(container), '0.0');
145
165
  expect(screen.getByRole('button', { name: 'Button 1' })).toBeInTheDocument();
146
166
  expect(screen.getByRole('button', { name: 'Button 2' })).toBeInTheDocument();
147
167
  expect(isResizingDisabled(container)).toBe(true);
148
- expect(getSplitPane2(container).style.width).toBe('0px');
168
+ checkPanelSize(getSplitPane2(container), '0.0');
149
169
  expect(screen.getByRole('button', { name: 'Button 1' }).hasAttribute('disabled')).toBe(true);
150
170
  expect(screen.getByRole('button', { name: 'Button 2' }).hasAttribute('disabled')).toBe(true);
151
171
  return [2 /*return*/];
@@ -158,80 +178,105 @@ describe('ProfileResizablePanes tests', function () {
158
178
  case 0:
159
179
  _a = setUp(__assign(__assign({}, defaultProps), { perspectiveId: 'graph' })), container = _a.container, user = _a.user;
160
180
  expect(isResizingDisabled(container)).toBe(false);
161
- expect(getSplitPane2(container).style.width).toBe('320px');
181
+ checkPanelSize(getSplitPane1(container), '68.0');
182
+ checkPanelSize(getSplitPane2(container), '32.0');
162
183
  expect(screen.getByRole('button', { name: 'Button 1' })).toBeInTheDocument();
163
184
  expect(screen.getByRole('button', { name: 'Button 2' })).toBeInTheDocument();
164
- Divider = screen.getByRole('presentation');
185
+ Divider = screen.getByRole('separator');
165
186
  expect(Divider).toBeInTheDocument();
166
187
  // move mouse to an x-coordinate between MIN_R_PANE_SIZE and MAX_R_PANE_SIZE
167
- return [4 /*yield*/, user.pointer({
168
- keys: '[MouseLeft>]',
169
- target: Divider,
170
- coords: {
171
- x: 0,
172
- y: 0
188
+ return [4 /*yield*/, user.pointer([
189
+ {
190
+ keys: '[MouseLeft>]',
191
+ target: Divider,
192
+ coords: {
193
+ x: 680,
194
+ y: 0
195
+ }
196
+ },
197
+ {
198
+ target: Divider,
199
+ coords: {
200
+ x: 500,
201
+ y: 20
202
+ }
203
+ },
204
+ {
205
+ keys: '[/MouseLeft]',
206
+ target: Divider,
207
+ coords: {
208
+ x: 500,
209
+ y: 20
210
+ }
173
211
  }
174
- })];
212
+ ])];
175
213
  case 1:
176
214
  // move mouse to an x-coordinate between MIN_R_PANE_SIZE and MAX_R_PANE_SIZE
177
215
  _b.sent();
178
- return [4 /*yield*/, user.pointer({
179
- keys: '[/MouseLeft]',
180
- target: Divider,
181
- coords: {
182
- x: -500,
183
- y: 20
184
- }
185
- })];
186
- case 2:
187
- _b.sent();
188
- expect(getSplitPane2(container).style.width).toBe('500px');
216
+ checkPanelSize(getSplitPane1(container), '50.0');
217
+ checkPanelSize(getSplitPane2(container), '50.0');
189
218
  // move mouse to a larger x-coordinate than MAX_R_PANE_SIZE
190
- return [4 /*yield*/, user.pointer({
191
- keys: '[MouseLeft>]',
192
- target: Divider,
193
- coords: {
194
- x: 0,
195
- y: 0
219
+ return [4 /*yield*/, user.pointer([
220
+ {
221
+ keys: '[MouseLeft>]',
222
+ target: Divider,
223
+ coords: {
224
+ x: 500,
225
+ y: 0
226
+ }
227
+ },
228
+ {
229
+ target: Divider,
230
+ coords: {
231
+ x: 300,
232
+ y: 20
233
+ }
234
+ },
235
+ {
236
+ keys: '[/MouseLeft]',
237
+ target: Divider,
238
+ coords: {
239
+ x: 300,
240
+ y: 20
241
+ }
196
242
  }
197
- })];
198
- case 3:
243
+ ])];
244
+ case 2:
199
245
  // move mouse to a larger x-coordinate than MAX_R_PANE_SIZE
200
246
  _b.sent();
201
- return [4 /*yield*/, user.pointer({
202
- keys: '[/MouseLeft]',
203
- target: Divider,
204
- coords: {
205
- x: -650,
206
- y: 0
207
- }
208
- })];
209
- case 4:
210
- _b.sent();
211
- expect(getSplitPane2(container).style.width).toBe('640px');
247
+ checkPanelSize(getSplitPane1(container), '36.0');
248
+ checkPanelSize(getSplitPane2(container), '64.0');
212
249
  // move mouse to a smaller x-coordinate than MIN_R_PANE_SIZE
213
- return [4 /*yield*/, user.pointer({
214
- keys: '[MouseLeft>]',
215
- target: Divider,
216
- coords: {
217
- x: 0,
218
- y: 0
250
+ return [4 /*yield*/, user.pointer([
251
+ {
252
+ keys: '[MouseLeft>]',
253
+ target: Divider,
254
+ coords: {
255
+ x: 360,
256
+ y: 0
257
+ }
258
+ },
259
+ {
260
+ target: Divider,
261
+ coords: {
262
+ x: 690,
263
+ y: 20
264
+ }
265
+ },
266
+ {
267
+ keys: '[/MouseLeft]',
268
+ target: Divider,
269
+ coords: {
270
+ x: 690,
271
+ y: 20
272
+ }
219
273
  }
220
- })];
221
- case 5:
274
+ ])];
275
+ case 3:
222
276
  // move mouse to a smaller x-coordinate than MIN_R_PANE_SIZE
223
277
  _b.sent();
224
- return [4 /*yield*/, user.pointer({
225
- keys: '[/MouseLeft]',
226
- target: Divider,
227
- coords: {
228
- x: -310,
229
- y: 0
230
- }
231
- })];
232
- case 6:
233
- _b.sent();
234
- expect(getSplitPane2(container).style.width).toBe('320px');
278
+ checkPanelSize(getSplitPane1(container), '68.0');
279
+ checkPanelSize(getSplitPane2(container), '32.0');
235
280
  return [2 /*return*/];
236
281
  }
237
282
  });
@@ -12,15 +12,16 @@ type Props = {
12
12
  allowResize?: boolean;
13
13
  primary?: 'first' | 'second';
14
14
  minSize?: Size;
15
+ /** if you set the maxSize to negative value (e.g. -200), then the splitter stops 200px before the border (in other words it sets the minimal size of the 'resizable' pane in this case) */
15
16
  maxSize?: Size;
16
- defaultSize?: Size;
17
17
  debounceInterval?: number;
18
+ /** Can be a positive or negative number (e.g., 250, -250), a percentage string (e.g., "50%"), or a string with pixels (e.g., "50px") */
18
19
  size?: Size;
19
20
  orientation?: 'vertical' | 'horizontal';
20
21
  onChange?: ({ size, percentageSize, isMaxSize, isMinSize }: OnChange) => void;
21
22
  };
22
23
  export declare const ResizablePanes: {
23
- ({ className, children, orientation, primary, defaultSize, size, minSize, maxSize, allowResize, debounceInterval, onChange }: Props): JSX.Element;
24
+ ({ className, children, orientation, primary, size, minSize, maxSize, allowResize, debounceInterval, onChange }: Props): JSX.Element;
24
25
  displayName: string;
25
26
  };
26
27
  export {};
@@ -1,39 +1,106 @@
1
- import React, { useCallback, useMemo, useState } from 'react';
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import React, { useCallback, useMemo, useState, useRef, useEffect } from 'react';
2
13
  import classnames from 'classnames';
3
- import SplitPane from 'react-split-pane';
14
+ import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
4
15
  import { useTheme } from '@mui/material/styles';
16
+ import ReactResizeDetector from 'react-resize-detector';
5
17
  import { debounce } from '@reltio/mdm-sdk';
6
18
  import { useStyles } from './styles';
7
19
  var HANDLE_CHANGE_DEBOUNCE_INTERVAL = 250;
8
20
  var isHorizontal = function (orientation) { return orientation === 'horizontal'; };
21
+ var isEqualSize = function (a, b) { return a.toFixed(2) === b.toFixed(2); };
9
22
  export var ResizablePanes = function (_a) {
10
- var className = _a.className, children = _a.children, orientation = _a.orientation, primary = _a.primary, defaultSize = _a.defaultSize, size = _a.size, minSize = _a.minSize, maxSize = _a.maxSize, allowResize = _a.allowResize, _b = _a.debounceInterval, debounceInterval = _b === void 0 ? HANDLE_CHANGE_DEBOUNCE_INTERVAL : _b, onChange = _a.onChange;
23
+ var _b;
24
+ var className = _a.className, children = _a.children, _c = _a.orientation, orientation = _c === void 0 ? 'vertical' : _c, _d = _a.primary, primary = _d === void 0 ? 'first' : _d, size = _a.size, minSize = _a.minSize, maxSize = _a.maxSize, allowResize = _a.allowResize, _e = _a.debounceInterval, debounceInterval = _e === void 0 ? HANDLE_CHANGE_DEBOUNCE_INTERVAL : _e, onChange = _a.onChange;
11
25
  var styles = useStyles();
12
26
  var theme = useTheme();
13
- var _c = useState(null), containerEl = _c[0], setContainerEl = _c[1];
14
- var _d = useState(true), isPaneAnimationEnabled = _d[0], setIsPaneAnimationEnabled = _d[1];
27
+ var panelRef = useRef();
28
+ var _f = useState(null), containerEl = _f[0], setContainerEl = _f[1];
29
+ var _g = useState(0), percentageMinSize = _g[0], setPercentageMinSize = _g[1];
30
+ var _h = useState(0), percentageMaxSize = _h[0], setPercentageMaxSize = _h[1];
31
+ var _j = useState(true), isPaneAnimationEnabled = _j[0], setIsPaneAnimationEnabled = _j[1];
15
32
  var enableAnimation = useCallback(function () { return setIsPaneAnimationEnabled(true); }, []);
16
33
  var disableAnimation = useCallback(function () { return setIsPaneAnimationEnabled(false); }, []);
17
- var getContainerSize = function () { return (isHorizontal(orientation) ? containerEl === null || containerEl === void 0 ? void 0 : containerEl.clientHeight : containerEl === null || containerEl === void 0 ? void 0 : containerEl.clientWidth); };
34
+ var getContainerSize = useCallback(function () { return (isHorizontal(orientation) ? containerEl === null || containerEl === void 0 ? void 0 : containerEl.clientHeight : containerEl === null || containerEl === void 0 ? void 0 : containerEl.clientWidth); }, [containerEl, orientation]);
35
+ if (typeof size === 'number' && size < 0) {
36
+ size = (getContainerSize() || 0) + size;
37
+ }
38
+ var convertSize = useCallback(function (size) {
39
+ if (typeof size === 'string' && size.endsWith('%')) {
40
+ return +size.replace('%', '');
41
+ }
42
+ if (typeof size === 'string' && size.endsWith('px')) {
43
+ size = size.replace('px', '');
44
+ }
45
+ return isNaN(+size) ? null : (+size / getContainerSize()) * 100;
46
+ }, [getContainerSize]);
47
+ var convertMinMaxSize = useCallback(function (size, minMaxSize) {
48
+ if (size === 0 || size === 100)
49
+ return 0;
50
+ return convertSize(minMaxSize) || 0;
51
+ }, [convertSize]);
52
+ var actualizeSizes = useCallback(function () {
53
+ if (containerEl && panelRef.current) {
54
+ var convertedSize = convertSize(size);
55
+ if (convertedSize != null && !isNaN(convertedSize)) {
56
+ setPercentageMaxSize(convertMinMaxSize(convertedSize, maxSize));
57
+ setPercentageMinSize(convertMinMaxSize(convertedSize, minSize));
58
+ panelRef.current.resize(convertedSize);
59
+ }
60
+ }
61
+ }, [convertSize, convertMinMaxSize, minSize, maxSize, size, containerEl]);
62
+ useEffect(function () {
63
+ actualizeSizes();
64
+ }, [actualizeSizes, percentageMaxSize, percentageMinSize]);
18
65
  var handleChange = useCallback(debounce(function (size) {
66
+ if (size === undefined)
67
+ return;
19
68
  var containerSize = getContainerSize();
20
69
  onChange({
21
- percentageSize: "".concat((size / containerSize) * 100, "%"),
22
- isMaxSize: +maxSize > 0 ? size === maxSize : size === containerSize + maxSize,
23
- isMinSize: size === minSize,
24
- size: size
70
+ percentageSize: size + '%',
71
+ isMaxSize: +percentageMaxSize > 0
72
+ ? isEqualSize(size, percentageMaxSize)
73
+ : isEqualSize(size, 100 + percentageMaxSize),
74
+ isMinSize: isEqualSize(size, percentageMinSize),
75
+ size: Math.round((size * containerSize) / 100)
25
76
  });
26
- }, debounceInterval), [onChange, orientation, maxSize, containerEl]);
77
+ }, debounceInterval), [onChange, percentageMaxSize, percentageMinSize, getContainerSize]);
78
+ var handleDragging = useCallback(function (isDragging) {
79
+ if (isDragging) {
80
+ // Why do we need handleChange() here?
81
+ // Case - user resized panels, and then immediately started resizing again.
82
+ // We need to prevent onChange calling with "previous" data (handleChange is debounced calling of onChange)
83
+ handleChange();
84
+ disableAnimation();
85
+ }
86
+ else {
87
+ handleChange(panelRef.current.getSize());
88
+ enableAnimation();
89
+ }
90
+ }, [disableAnimation, enableAnimation, handleChange]);
27
91
  var paneAnimationStyle = useMemo(function () { return ({
28
- transition: theme.transitions.create(isHorizontal(orientation) ? 'height' : 'width', {
92
+ transition: theme.transitions.create('flex', {
29
93
  easing: theme.transitions.easing.sharp,
30
94
  duration: theme.transitions.duration.leavingScreen
31
95
  })
32
- }); }, [orientation, theme]);
33
- if (typeof size === 'number' && size < 0) {
34
- size = (getContainerSize() || 0) + size;
35
- }
96
+ }); }, [theme]);
97
+ var primaryPanelProps = __assign(__assign({ className: styles.panel, minSize: percentageMinSize }, (percentageMaxSize > 0 ? { maxSize: percentageMaxSize } : {})), { ref: panelRef, style: isPaneAnimationEnabled ? paneAnimationStyle : undefined });
98
+ var secondaryPanelProps = __assign({ className: styles.panel, style: isPaneAnimationEnabled ? paneAnimationStyle : undefined }, (percentageMaxSize < 0 ? { minSize: -percentageMaxSize } : {}));
36
99
  return (React.createElement("div", { ref: setContainerEl, className: classnames(styles.container, className) },
37
- React.createElement(SplitPane, { split: orientation, size: size, primary: primary, allowResize: allowResize, onChange: handleChange, defaultSize: defaultSize, minSize: minSize, maxSize: maxSize, onDragStarted: disableAnimation, onDragFinished: enableAnimation, pane1Style: isPaneAnimationEnabled ? paneAnimationStyle : undefined }, children)));
100
+ React.createElement(ReactResizeDetector, { handleHeight: isHorizontal(orientation), handleWidth: !isHorizontal(orientation), onResize: actualizeSizes, refreshMode: "debounce", refreshRate: 50 }),
101
+ React.createElement(PanelGroup, { direction: isHorizontal(orientation) ? 'vertical' : 'horizontal' },
102
+ React.createElement(Panel, __assign({}, (primary === 'first' ? primaryPanelProps : secondaryPanelProps)), children[0]),
103
+ React.createElement(PanelResizeHandle, { className: classnames(styles.resizer, styles[orientation], (_b = {}, _b[styles.disabled] = !allowResize, _b)), disabled: !allowResize, hitAreaMargins: { coarse: 0, fine: 0 }, onDragging: handleDragging }),
104
+ React.createElement(Panel, __assign({}, (primary === 'second' ? primaryPanelProps : secondaryPanelProps)), children[1]))));
38
105
  };
39
106
  ResizablePanes.displayName = 'ResizablePanes';