@itwin/itwinui-react 2.12.16 → 2.12.18
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/CHANGELOG.md +12 -0
- package/cjs/core/Dialog/DialogMain.js +25 -4
- package/cjs/core/Menu/MenuItem.js +9 -7
- package/cjs/core/utils/components/Resizer.js +1 -1
- package/cjs/core/utils/functions/dom.d.ts +2 -1
- package/cjs/core/utils/functions/dom.js +6 -2
- package/cjs/core/utils/functions/numbers.d.ts +7 -0
- package/cjs/core/utils/functions/numbers.js +12 -1
- package/cjs/core/utils/hooks/useDragAndDrop.js +2 -2
- package/esm/core/Dialog/DialogMain.js +26 -5
- package/esm/core/Menu/MenuItem.js +9 -7
- package/esm/core/utils/components/Resizer.js +2 -2
- package/esm/core/utils/functions/dom.d.ts +2 -1
- package/esm/core/utils/functions/dom.js +4 -1
- package/esm/core/utils/functions/numbers.d.ts +7 -0
- package/esm/core/utils/functions/numbers.js +10 -0
- package/esm/core/utils/hooks/useDragAndDrop.js +3 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.12.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a68561cf: Fixed an issue where Dialog content was appearing blurred on Windows.
|
|
8
|
+
|
|
9
|
+
## 2.12.17
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#1698](https://github.com/iTwin/iTwinUI/pull/1698): Fixed an issue where submenu items were not appearing because of overflow on parent menu.
|
|
14
|
+
|
|
3
15
|
## 2.12.16
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -64,7 +64,7 @@ exports.DialogMain = React.forwardRef((props, ref) => {
|
|
|
64
64
|
(0, index_js_1.useTheme)();
|
|
65
65
|
const [style, setStyle] = React.useState();
|
|
66
66
|
const dialogRef = React.useRef(null);
|
|
67
|
-
const
|
|
67
|
+
const [dialogElement, setDialogElement] = React.useState();
|
|
68
68
|
const hasBeenResized = React.useRef(false);
|
|
69
69
|
const previousFocusedElement = React.useRef();
|
|
70
70
|
const originalBodyOverflow = React.useRef('');
|
|
@@ -118,7 +118,7 @@ exports.DialogMain = React.forwardRef((props, ref) => {
|
|
|
118
118
|
return;
|
|
119
119
|
}
|
|
120
120
|
const rect = (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
121
|
-
const [translateX, translateY] = (0, index_js_1.
|
|
121
|
+
const [translateX, translateY] = (0, index_js_1.getTranslateValuesFromElement)(dialogRef.current);
|
|
122
122
|
setStyle((oldStyle) => {
|
|
123
123
|
var _a, _b;
|
|
124
124
|
return ({
|
|
@@ -137,13 +137,17 @@ exports.DialogMain = React.forwardRef((props, ref) => {
|
|
|
137
137
|
...newStyle,
|
|
138
138
|
}));
|
|
139
139
|
}, []);
|
|
140
|
+
const roundedTransform = useRoundedTransform({
|
|
141
|
+
element: dialogElement,
|
|
142
|
+
transform,
|
|
143
|
+
});
|
|
140
144
|
const content = (React.createElement("div", { className: (0, classnames_1.default)('iui-dialog', {
|
|
141
145
|
'iui-dialog-default': styleType === 'default',
|
|
142
146
|
'iui-dialog-full-page': styleType === 'fullPage',
|
|
143
147
|
'iui-dialog-visible': isOpen,
|
|
144
148
|
'iui-dialog-draggable': isDraggable,
|
|
145
|
-
}, className), role: 'dialog', ref:
|
|
146
|
-
transform,
|
|
149
|
+
}, className), role: 'dialog', ref: (0, index_js_1.useMergedRefs)(dialogRef, ref, setDialogElement), onKeyDown: handleKeyDown, tabIndex: -1, "data-iui-placement": placement, style: {
|
|
150
|
+
transform: roundedTransform,
|
|
147
151
|
...style,
|
|
148
152
|
...propStyle,
|
|
149
153
|
}, ...rest },
|
|
@@ -176,3 +180,20 @@ exports.DialogMain = React.forwardRef((props, ref) => {
|
|
|
176
180
|
!trapFocus && content)));
|
|
177
181
|
});
|
|
178
182
|
exports.default = exports.DialogMain;
|
|
183
|
+
// ----------------------------------------------------------------------------
|
|
184
|
+
/**
|
|
185
|
+
* Rounds off an element's transform value based on the device's pixel grid, to avoid blurring.
|
|
186
|
+
*/
|
|
187
|
+
const useRoundedTransform = ({ element, transform, }) => {
|
|
188
|
+
const [roundedStyles, setRoundedStyles] = React.useState(transform);
|
|
189
|
+
(0, index_js_1.useIsomorphicLayoutEffect)(() => {
|
|
190
|
+
if (!element || typeof DOMMatrix === 'undefined') {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const [x, y] = transform
|
|
194
|
+
? (0, index_js_1.getTranslateValues)(transform)
|
|
195
|
+
: (0, index_js_1.getTranslateValuesFromElement)(element);
|
|
196
|
+
setRoundedStyles(`translate(${(0, index_js_1.roundByDPR)(x)}px, ${(0, index_js_1.roundByDPR)(y)}px)`);
|
|
197
|
+
}, [element, transform]);
|
|
198
|
+
return roundedStyles;
|
|
199
|
+
};
|
|
@@ -67,13 +67,11 @@ exports.MenuItem = React.forwardRef((props, ref) => {
|
|
|
67
67
|
if (subMenuItems.length > 0) {
|
|
68
68
|
setIsSubmenuVisible(true);
|
|
69
69
|
event.preventDefault();
|
|
70
|
-
event.stopPropagation();
|
|
71
70
|
}
|
|
72
71
|
break;
|
|
73
72
|
}
|
|
74
73
|
case 'ArrowLeft': {
|
|
75
74
|
(_a = parentMenuItemRef === null || parentMenuItemRef === void 0 ? void 0 : parentMenuItemRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
76
|
-
event.stopPropagation();
|
|
77
75
|
event.preventDefault();
|
|
78
76
|
break;
|
|
79
77
|
}
|
|
@@ -105,12 +103,16 @@ exports.MenuItem = React.forwardRef((props, ref) => {
|
|
|
105
103
|
className: (0, classnames_1.default)(badge.props.className, 'iui-icon'),
|
|
106
104
|
})));
|
|
107
105
|
return subMenuItems.length === 0 ? (listItem) : (React.createElement(MenuItemContext.Provider, { value: { ref: menuItemRef } },
|
|
108
|
-
React.createElement(index_js_1.Popover, { placement: 'right-start', visible: isSubmenuVisible, appendTo:
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
106
|
+
React.createElement(index_js_1.Popover, { placement: 'right-start', visible: isSubmenuVisible, appendTo: (item) => {
|
|
107
|
+
var _a;
|
|
108
|
+
// we want the div wrapping the parent menu because the menu has overflow,
|
|
109
|
+
// which can cause the submenu to be cut off
|
|
110
|
+
return (_a = item.parentElement) === null || _a === void 0 ? void 0 : _a.parentElement;
|
|
111
|
+
}, delay: 100, content: React.createElement("div", { onMouseLeave: () => setIsSubmenuVisible(false), onKeyDown: (e) => {
|
|
112
|
+
if (!e.altKey && e.key === 'ArrowLeft') {
|
|
113
113
|
setIsSubmenuVisible(false);
|
|
114
|
+
e.stopPropagation();
|
|
115
|
+
}
|
|
114
116
|
} },
|
|
115
117
|
React.createElement(Menu_js_1.Menu, { ref: subMenuRef, className: 'iui-scroll' }, subMenuItems)) }, listItem)));
|
|
116
118
|
});
|
|
@@ -51,7 +51,7 @@ const Resizer = (props) => {
|
|
|
51
51
|
}
|
|
52
52
|
const initialPointerX = event.clientX;
|
|
53
53
|
const initialPointerY = event.clientY;
|
|
54
|
-
const [initialTranslateX, initialTranslateY] = (0, index_js_1.
|
|
54
|
+
const [initialTranslateX, initialTranslateY] = (0, index_js_1.getTranslateValuesFromElement)(elementRef.current);
|
|
55
55
|
const { width: initialWidth, height: initialHeight } = elementRef.current.getBoundingClientRect();
|
|
56
56
|
let width = `${initialWidth}px`;
|
|
57
57
|
let height = `${initialHeight}px`;
|
|
@@ -27,4 +27,5 @@ export declare const mergeEventHandlers: <E extends import("react").SyntheticEve
|
|
|
27
27
|
* @param element HTML element you want to get translate value of
|
|
28
28
|
* @returns Translate values in pixels in an array `[translateX, translateY]`
|
|
29
29
|
*/
|
|
30
|
-
export declare const
|
|
30
|
+
export declare const getTranslateValuesFromElement: (element: HTMLElement | null | undefined) => number[];
|
|
31
|
+
export declare const getTranslateValues: (transformValue: string) => number[];
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
5
|
*--------------------------------------------------------------------------------------------*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.getTranslateValues = exports.mergeEventHandlers = exports.getWindow = exports.getDocument = exports.getContainer = void 0;
|
|
7
|
+
exports.getTranslateValues = exports.getTranslateValuesFromElement = exports.mergeEventHandlers = exports.getWindow = exports.getDocument = exports.getContainer = void 0;
|
|
8
8
|
/**
|
|
9
9
|
* Get the container as a child of body, or create one if it doesn't exist.
|
|
10
10
|
* Mostly used for dynamic components like Modal or Toast.
|
|
@@ -58,11 +58,15 @@ exports.mergeEventHandlers = mergeEventHandlers;
|
|
|
58
58
|
* @param element HTML element you want to get translate value of
|
|
59
59
|
* @returns Translate values in pixels in an array `[translateX, translateY]`
|
|
60
60
|
*/
|
|
61
|
-
const
|
|
61
|
+
const getTranslateValuesFromElement = (element) => {
|
|
62
62
|
if (!element) {
|
|
63
63
|
return [];
|
|
64
64
|
}
|
|
65
65
|
const transformValue = getComputedStyle(element).getPropertyValue('transform');
|
|
66
|
+
return (0, exports.getTranslateValues)(transformValue);
|
|
67
|
+
};
|
|
68
|
+
exports.getTranslateValuesFromElement = getTranslateValuesFromElement;
|
|
69
|
+
const getTranslateValues = (transformValue) => {
|
|
66
70
|
const matrix = new DOMMatrix(transformValue);
|
|
67
71
|
return [matrix.m41, matrix.m42];
|
|
68
72
|
};
|
|
@@ -6,3 +6,10 @@ export declare const getBoundedValue: (val: number, min: number, max: number) =>
|
|
|
6
6
|
* Returns a random value of a given length containing `A-Za-z0-9_-` symbols.
|
|
7
7
|
*/
|
|
8
8
|
export declare const getRandomValue: (length?: number) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Rounds a pixel value based on the device's pixel ratio. This ensures that values can be
|
|
11
|
+
* placed evenly on the device’s pixel grid, avoiding any blurring.
|
|
12
|
+
*
|
|
13
|
+
* @see https://floating-ui.com/docs/misc#subpixel-and-accelerated-positioning
|
|
14
|
+
*/
|
|
15
|
+
export declare const roundByDPR: (value: number) => number;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
5
|
*--------------------------------------------------------------------------------------------*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.getRandomValue = exports.getBoundedValue = void 0;
|
|
7
|
+
exports.roundByDPR = exports.getRandomValue = exports.getBoundedValue = void 0;
|
|
8
8
|
/**
|
|
9
9
|
* Return input value bounded by specified range.
|
|
10
10
|
*/
|
|
@@ -24,3 +24,14 @@ const getRandomValue = (length = 21) => {
|
|
|
24
24
|
return id;
|
|
25
25
|
};
|
|
26
26
|
exports.getRandomValue = getRandomValue;
|
|
27
|
+
/**
|
|
28
|
+
* Rounds a pixel value based on the device's pixel ratio. This ensures that values can be
|
|
29
|
+
* placed evenly on the device’s pixel grid, avoiding any blurring.
|
|
30
|
+
*
|
|
31
|
+
* @see https://floating-ui.com/docs/misc#subpixel-and-accelerated-positioning
|
|
32
|
+
*/
|
|
33
|
+
const roundByDPR = (value) => {
|
|
34
|
+
const dpr = window.devicePixelRatio || 1;
|
|
35
|
+
return Math.round(value * dpr) / dpr;
|
|
36
|
+
};
|
|
37
|
+
exports.roundByDPR = roundByDPR;
|
|
@@ -62,7 +62,7 @@ const useDragAndDrop = (elementRef, containerRef, enabled = true) => {
|
|
|
62
62
|
return;
|
|
63
63
|
}
|
|
64
64
|
const { top, right, bottom, left } = (_a = elementRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
65
|
-
let [newTranslateX, newTranslateY] = (0, index_js_1.
|
|
65
|
+
let [newTranslateX, newTranslateY] = (0, index_js_1.getTranslateValuesFromElement)(elementRef.current);
|
|
66
66
|
containerRectRef.current = getContainerRect(containerRef);
|
|
67
67
|
if (bottom > containerRectRef.current.bottom) {
|
|
68
68
|
newTranslateY -= bottom - containerRectRef.current.bottom;
|
|
@@ -108,7 +108,7 @@ const useDragAndDrop = (elementRef, containerRef, enabled = true) => {
|
|
|
108
108
|
if (!elementRef.current || e.button !== 0 || !enabled) {
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
111
|
-
const [x, y] = (0, index_js_1.
|
|
111
|
+
const [x, y] = (0, index_js_1.getTranslateValuesFromElement)(elementRef.current);
|
|
112
112
|
grabOffsetX.current = e.clientX - x;
|
|
113
113
|
grabOffsetY.current = e.clientY - y;
|
|
114
114
|
originalUserSelect.current = elementRef.current.style.userSelect;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import cx from 'classnames';
|
|
7
|
-
import { FocusTrap,
|
|
7
|
+
import { FocusTrap, getTranslateValuesFromElement, Resizer, useMergedRefs, useTheme, useIsomorphicLayoutEffect, getTranslateValues, roundByDPR, } from '../utils/index.js';
|
|
8
8
|
import { useDialogContext } from './DialogContext.js';
|
|
9
9
|
import { CSSTransition } from 'react-transition-group';
|
|
10
10
|
import { DialogDragContext } from './DialogDragContext.js';
|
|
@@ -35,7 +35,7 @@ export const DialogMain = React.forwardRef((props, ref) => {
|
|
|
35
35
|
useTheme();
|
|
36
36
|
const [style, setStyle] = React.useState();
|
|
37
37
|
const dialogRef = React.useRef(null);
|
|
38
|
-
const
|
|
38
|
+
const [dialogElement, setDialogElement] = React.useState();
|
|
39
39
|
const hasBeenResized = React.useRef(false);
|
|
40
40
|
const previousFocusedElement = React.useRef();
|
|
41
41
|
const originalBodyOverflow = React.useRef('');
|
|
@@ -89,7 +89,7 @@ export const DialogMain = React.forwardRef((props, ref) => {
|
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
91
|
const rect = (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
92
|
-
const [translateX, translateY] =
|
|
92
|
+
const [translateX, translateY] = getTranslateValuesFromElement(dialogRef.current);
|
|
93
93
|
setStyle((oldStyle) => {
|
|
94
94
|
var _a, _b;
|
|
95
95
|
return ({
|
|
@@ -108,13 +108,17 @@ export const DialogMain = React.forwardRef((props, ref) => {
|
|
|
108
108
|
...newStyle,
|
|
109
109
|
}));
|
|
110
110
|
}, []);
|
|
111
|
+
const roundedTransform = useRoundedTransform({
|
|
112
|
+
element: dialogElement,
|
|
113
|
+
transform,
|
|
114
|
+
});
|
|
111
115
|
const content = (React.createElement("div", { className: cx('iui-dialog', {
|
|
112
116
|
'iui-dialog-default': styleType === 'default',
|
|
113
117
|
'iui-dialog-full-page': styleType === 'fullPage',
|
|
114
118
|
'iui-dialog-visible': isOpen,
|
|
115
119
|
'iui-dialog-draggable': isDraggable,
|
|
116
|
-
}, className), role: 'dialog', ref:
|
|
117
|
-
transform,
|
|
120
|
+
}, className), role: 'dialog', ref: useMergedRefs(dialogRef, ref, setDialogElement), onKeyDown: handleKeyDown, tabIndex: -1, "data-iui-placement": placement, style: {
|
|
121
|
+
transform: roundedTransform,
|
|
118
122
|
...style,
|
|
119
123
|
...propStyle,
|
|
120
124
|
}, ...rest },
|
|
@@ -147,3 +151,20 @@ export const DialogMain = React.forwardRef((props, ref) => {
|
|
|
147
151
|
!trapFocus && content)));
|
|
148
152
|
});
|
|
149
153
|
export default DialogMain;
|
|
154
|
+
// ----------------------------------------------------------------------------
|
|
155
|
+
/**
|
|
156
|
+
* Rounds off an element's transform value based on the device's pixel grid, to avoid blurring.
|
|
157
|
+
*/
|
|
158
|
+
const useRoundedTransform = ({ element, transform, }) => {
|
|
159
|
+
const [roundedStyles, setRoundedStyles] = React.useState(transform);
|
|
160
|
+
useIsomorphicLayoutEffect(() => {
|
|
161
|
+
if (!element || typeof DOMMatrix === 'undefined') {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const [x, y] = transform
|
|
165
|
+
? getTranslateValues(transform)
|
|
166
|
+
: getTranslateValuesFromElement(element);
|
|
167
|
+
setRoundedStyles(`translate(${roundByDPR(x)}px, ${roundByDPR(y)}px)`);
|
|
168
|
+
}, [element, transform]);
|
|
169
|
+
return roundedStyles;
|
|
170
|
+
};
|
|
@@ -38,13 +38,11 @@ export const MenuItem = React.forwardRef((props, ref) => {
|
|
|
38
38
|
if (subMenuItems.length > 0) {
|
|
39
39
|
setIsSubmenuVisible(true);
|
|
40
40
|
event.preventDefault();
|
|
41
|
-
event.stopPropagation();
|
|
42
41
|
}
|
|
43
42
|
break;
|
|
44
43
|
}
|
|
45
44
|
case 'ArrowLeft': {
|
|
46
45
|
(_a = parentMenuItemRef === null || parentMenuItemRef === void 0 ? void 0 : parentMenuItemRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
47
|
-
event.stopPropagation();
|
|
48
46
|
event.preventDefault();
|
|
49
47
|
break;
|
|
50
48
|
}
|
|
@@ -76,12 +74,16 @@ export const MenuItem = React.forwardRef((props, ref) => {
|
|
|
76
74
|
className: cx(badge.props.className, 'iui-icon'),
|
|
77
75
|
})));
|
|
78
76
|
return subMenuItems.length === 0 ? (listItem) : (React.createElement(MenuItemContext.Provider, { value: { ref: menuItemRef } },
|
|
79
|
-
React.createElement(Popover, { placement: 'right-start', visible: isSubmenuVisible, appendTo:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
77
|
+
React.createElement(Popover, { placement: 'right-start', visible: isSubmenuVisible, appendTo: (item) => {
|
|
78
|
+
var _a;
|
|
79
|
+
// we want the div wrapping the parent menu because the menu has overflow,
|
|
80
|
+
// which can cause the submenu to be cut off
|
|
81
|
+
return (_a = item.parentElement) === null || _a === void 0 ? void 0 : _a.parentElement;
|
|
82
|
+
}, delay: 100, content: React.createElement("div", { onMouseLeave: () => setIsSubmenuVisible(false), onKeyDown: (e) => {
|
|
83
|
+
if (!e.altKey && e.key === 'ArrowLeft') {
|
|
84
84
|
setIsSubmenuVisible(false);
|
|
85
|
+
e.stopPropagation();
|
|
86
|
+
}
|
|
85
87
|
} },
|
|
86
88
|
React.createElement(Menu, { ref: subMenuRef, className: 'iui-scroll' }, subMenuItems)) }, listItem)));
|
|
87
89
|
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as React from 'react';
|
|
6
|
-
import { getBoundedValue,
|
|
6
|
+
import { getBoundedValue, getTranslateValuesFromElement, } from '../functions/index.js';
|
|
7
7
|
/**
|
|
8
8
|
* Component that allows to resize parent element.
|
|
9
9
|
* Parent must have `position: relative`.
|
|
@@ -25,7 +25,7 @@ export const Resizer = (props) => {
|
|
|
25
25
|
}
|
|
26
26
|
const initialPointerX = event.clientX;
|
|
27
27
|
const initialPointerY = event.clientY;
|
|
28
|
-
const [initialTranslateX, initialTranslateY] =
|
|
28
|
+
const [initialTranslateX, initialTranslateY] = getTranslateValuesFromElement(elementRef.current);
|
|
29
29
|
const { width: initialWidth, height: initialHeight } = elementRef.current.getBoundingClientRect();
|
|
30
30
|
let width = `${initialWidth}px`;
|
|
31
31
|
let height = `${initialHeight}px`;
|
|
@@ -27,4 +27,5 @@ export declare const mergeEventHandlers: <E extends import("react").SyntheticEve
|
|
|
27
27
|
* @param element HTML element you want to get translate value of
|
|
28
28
|
* @returns Translate values in pixels in an array `[translateX, translateY]`
|
|
29
29
|
*/
|
|
30
|
-
export declare const
|
|
30
|
+
export declare const getTranslateValuesFromElement: (element: HTMLElement | null | undefined) => number[];
|
|
31
|
+
export declare const getTranslateValues: (transformValue: string) => number[];
|
|
@@ -51,11 +51,14 @@ export const mergeEventHandlers = (...callbacks) => (event) => {
|
|
|
51
51
|
* @param element HTML element you want to get translate value of
|
|
52
52
|
* @returns Translate values in pixels in an array `[translateX, translateY]`
|
|
53
53
|
*/
|
|
54
|
-
export const
|
|
54
|
+
export const getTranslateValuesFromElement = (element) => {
|
|
55
55
|
if (!element) {
|
|
56
56
|
return [];
|
|
57
57
|
}
|
|
58
58
|
const transformValue = getComputedStyle(element).getPropertyValue('transform');
|
|
59
|
+
return getTranslateValues(transformValue);
|
|
60
|
+
};
|
|
61
|
+
export const getTranslateValues = (transformValue) => {
|
|
59
62
|
const matrix = new DOMMatrix(transformValue);
|
|
60
63
|
return [matrix.m41, matrix.m42];
|
|
61
64
|
};
|
|
@@ -6,3 +6,10 @@ export declare const getBoundedValue: (val: number, min: number, max: number) =>
|
|
|
6
6
|
* Returns a random value of a given length containing `A-Za-z0-9_-` symbols.
|
|
7
7
|
*/
|
|
8
8
|
export declare const getRandomValue: (length?: number) => string;
|
|
9
|
+
/**
|
|
10
|
+
* Rounds a pixel value based on the device's pixel ratio. This ensures that values can be
|
|
11
|
+
* placed evenly on the device’s pixel grid, avoiding any blurring.
|
|
12
|
+
*
|
|
13
|
+
* @see https://floating-ui.com/docs/misc#subpixel-and-accelerated-positioning
|
|
14
|
+
*/
|
|
15
|
+
export declare const roundByDPR: (value: number) => number;
|
|
@@ -19,3 +19,13 @@ export const getRandomValue = (length = 21) => {
|
|
|
19
19
|
}
|
|
20
20
|
return id;
|
|
21
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* Rounds a pixel value based on the device's pixel ratio. This ensures that values can be
|
|
24
|
+
* placed evenly on the device’s pixel grid, avoiding any blurring.
|
|
25
|
+
*
|
|
26
|
+
* @see https://floating-ui.com/docs/misc#subpixel-and-accelerated-positioning
|
|
27
|
+
*/
|
|
28
|
+
export const roundByDPR = (value) => {
|
|
29
|
+
const dpr = window.devicePixelRatio || 1;
|
|
30
|
+
return Math.round(value * dpr) / dpr;
|
|
31
|
+
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as React from 'react';
|
|
6
|
-
import {
|
|
6
|
+
import { getTranslateValuesFromElement, getWindow, } from '../functions/index.js';
|
|
7
7
|
import { useEventListener } from './useEventListener.js';
|
|
8
8
|
import { useResizeObserver } from './useResizeObserver.js';
|
|
9
9
|
const getContainerRect = (containerRef) => {
|
|
@@ -36,7 +36,7 @@ export const useDragAndDrop = (elementRef, containerRef, enabled = true) => {
|
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
const { top, right, bottom, left } = (_a = elementRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
39
|
-
let [newTranslateX, newTranslateY] =
|
|
39
|
+
let [newTranslateX, newTranslateY] = getTranslateValuesFromElement(elementRef.current);
|
|
40
40
|
containerRectRef.current = getContainerRect(containerRef);
|
|
41
41
|
if (bottom > containerRectRef.current.bottom) {
|
|
42
42
|
newTranslateY -= bottom - containerRectRef.current.bottom;
|
|
@@ -82,7 +82,7 @@ export const useDragAndDrop = (elementRef, containerRef, enabled = true) => {
|
|
|
82
82
|
if (!elementRef.current || e.button !== 0 || !enabled) {
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
85
|
-
const [x, y] =
|
|
85
|
+
const [x, y] = getTranslateValuesFromElement(elementRef.current);
|
|
86
86
|
grabOffsetX.current = e.clientX - x;
|
|
87
87
|
grabOffsetY.current = e.clientY - y;
|
|
88
88
|
originalUserSelect.current = elementRef.current.style.userSelect;
|