reshaped 3.9.0-canary.14 → 3.9.0-canary.16
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/dist/bundle.js +2 -2
- package/dist/components/Flyout/FlyoutControlled.js +7 -4
- package/dist/components/Flyout/useFlyout.d.ts +1 -1
- package/dist/components/Flyout/useFlyout.js +3 -3
- package/dist/components/Flyout/utilities/calculatePosition.js +18 -11
- package/dist/components/Flyout/utilities/constants.d.ts +1 -0
- package/dist/components/Flyout/utilities/constants.js +1 -0
- package/dist/components/Flyout/utilities/flyout.js +6 -1
- package/dist/components/Flyout/utilities/isFullyVisible.d.ts +4 -3
- package/dist/components/Flyout/utilities/isFullyVisible.js +5 -4
- package/package.json +1 -1
|
@@ -55,12 +55,13 @@ const FlyoutControlled = (props) => {
|
|
|
55
55
|
// Touch devices trigger onMouseEnter but we don't need to apply regular hover timeouts
|
|
56
56
|
// So we're saving a flag on touch start and then change the mouse enter behavior
|
|
57
57
|
const hoverTriggeredWithTouchEventRef = React.useRef(false);
|
|
58
|
+
const originCoordinatesRef = React.useRef(originCoordinates ?? null);
|
|
58
59
|
// eslint-disable-next-line react-hooks/refs
|
|
60
|
+
originCoordinatesRef.current = originCoordinates ?? null;
|
|
59
61
|
const flyout = useFlyout({
|
|
60
62
|
triggerElRef: positionRef ?? triggerElRef,
|
|
61
63
|
flyoutElRef,
|
|
62
|
-
|
|
63
|
-
triggerBounds: originCoordinates ?? triggerBoundsRef.current,
|
|
64
|
+
triggerBoundsRef: originCoordinates ? originCoordinatesRef : triggerBoundsRef,
|
|
64
65
|
width,
|
|
65
66
|
position: passedPosition,
|
|
66
67
|
defaultActive: resolvedActive,
|
|
@@ -147,9 +148,11 @@ const FlyoutControlled = (props) => {
|
|
|
147
148
|
}
|
|
148
149
|
}, [clearTimer, handleOpen, groupTimeouts]);
|
|
149
150
|
const handleMouseLeave = React.useCallback((e) => {
|
|
150
|
-
if (e.relatedTarget === flyoutElRef.current
|
|
151
|
+
if (e.relatedTarget === flyoutElRef.current ||
|
|
152
|
+
(e.relatedTarget instanceof Node && flyoutElRef.current?.contains(e.relatedTarget)))
|
|
151
153
|
return;
|
|
152
|
-
if (e.relatedTarget === triggerElRef.current
|
|
154
|
+
if (e.relatedTarget === triggerElRef.current ||
|
|
155
|
+
(e.relatedTarget instanceof Node && triggerElRef.current?.contains(e.relatedTarget)))
|
|
153
156
|
return;
|
|
154
157
|
cooldown.cool();
|
|
155
158
|
clearTimer();
|
|
@@ -6,7 +6,7 @@ type UseFlyout = (args: Pick<T.Props, "width" | "position" | "defaultActive" | "
|
|
|
6
6
|
container?: HTMLElement | null;
|
|
7
7
|
triggerElRef: React.RefObject<HTMLElement | null>;
|
|
8
8
|
flyoutElRef: React.RefObject<HTMLElement | null>;
|
|
9
|
-
|
|
9
|
+
triggerBoundsRef: React.RefObject<DOMRect | G.Coordinates | null>;
|
|
10
10
|
}) => Pick<T.State, "position" | "status"> & {
|
|
11
11
|
updatePosition: (options?: {
|
|
12
12
|
sync?: boolean;
|
|
@@ -26,7 +26,7 @@ const flyoutReducer = (state, action) => {
|
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
28
|
const useFlyout = (args) => {
|
|
29
|
-
const { triggerElRef, flyoutElRef,
|
|
29
|
+
const { triggerElRef, flyoutElRef, triggerBoundsRef, contentGap, contentShift, ...options } = args;
|
|
30
30
|
const { position: defaultPosition = "bottom", fallbackPositions, fallbackAdjustLayout, fallbackMinWidth, fallbackMinHeight, width, container, } = options;
|
|
31
31
|
const lastUsedPositionRef = React.useRef(defaultPosition);
|
|
32
32
|
// Memo the array internally to avoid new arrays triggering useCallback
|
|
@@ -60,7 +60,7 @@ const useFlyout = (args) => {
|
|
|
60
60
|
const nextFlyoutData = flyout({
|
|
61
61
|
triggerEl: triggerElRef.current,
|
|
62
62
|
flyoutEl: flyoutElRef.current,
|
|
63
|
-
triggerBounds,
|
|
63
|
+
triggerBounds: triggerBoundsRef.current,
|
|
64
64
|
width,
|
|
65
65
|
position: changePositon ? defaultPosition : lastUsedPositionRef.current,
|
|
66
66
|
fallbackPositions: changePositon ? cachedFallbackPositions : [],
|
|
@@ -88,7 +88,7 @@ const useFlyout = (args) => {
|
|
|
88
88
|
isRTL,
|
|
89
89
|
flyoutElRef,
|
|
90
90
|
triggerElRef,
|
|
91
|
-
|
|
91
|
+
triggerBoundsRef,
|
|
92
92
|
width,
|
|
93
93
|
contentGap,
|
|
94
94
|
contentShift,
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { SCREEN_OFFSET } from "./constants.js";
|
|
1
2
|
import { getRTLPosition, centerBySize } from "./helpers.js";
|
|
2
|
-
const SCREEN_OFFSET = 8;
|
|
3
3
|
/**
|
|
4
4
|
* Calculate styles for the current position
|
|
5
5
|
*/
|
|
6
6
|
const calculatePosition = (args) => {
|
|
7
|
-
const { triggerBounds, flyoutBounds, containerBounds, position: passedPosition, rtl, width: passedWidth, contentGap = 0, contentShift = 0, passedContainer, fallbackAdjustLayout,
|
|
7
|
+
const { triggerBounds, flyoutBounds, containerBounds, position: passedPosition, rtl, width: passedWidth, contentGap = 0, contentShift = 0, passedContainer, fallbackAdjustLayout,
|
|
8
|
+
// fallbackMinWidth,
|
|
9
|
+
fallbackMinHeight, } = args;
|
|
8
10
|
const isFullWidth = passedWidth === "full" || passedWidth === "100%";
|
|
9
11
|
let left = 0;
|
|
10
12
|
let top = 0;
|
|
@@ -137,15 +139,20 @@ const calculatePosition = (args) => {
|
|
|
137
139
|
if (bottom !== null)
|
|
138
140
|
bottom = bottom + (flyoutHeight - height);
|
|
139
141
|
}
|
|
140
|
-
if
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
142
|
+
// TODO: Decide if we need horizontal scrolling for the fallbacks, might be a bad practice anyways
|
|
143
|
+
// if (updatedOverflow.left > 0) {
|
|
144
|
+
// width = Math.max(
|
|
145
|
+
// fallbackMinWidth ? parseInt(fallbackMinWidth) : 0,
|
|
146
|
+
// flyoutWidth - updatedOverflow.left
|
|
147
|
+
// );
|
|
148
|
+
// left = left + (flyoutWidth - width);
|
|
149
|
+
// } else if (updatedOverflow.right > 0) {
|
|
150
|
+
// width = Math.max(
|
|
151
|
+
// fallbackMinWidth ? parseInt(fallbackMinWidth) : 0,
|
|
152
|
+
// flyoutWidth - updatedOverflow.right
|
|
153
|
+
// );
|
|
154
|
+
// if (right !== null) right = right + (flyoutWidth - width);
|
|
155
|
+
// }
|
|
149
156
|
}
|
|
150
157
|
if (isFullWidth) {
|
|
151
158
|
left = SCREEN_OFFSET;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SCREEN_OFFSET = 8;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SCREEN_OFFSET = 8;
|
|
@@ -41,7 +41,6 @@ const flyout = (args) => {
|
|
|
41
41
|
closestFixedContainer ||
|
|
42
42
|
document.body;
|
|
43
43
|
const renderContainerBounds = container.getBoundingClientRect();
|
|
44
|
-
const visualContainerBounds = (passedContainer || document.body).getBoundingClientRect();
|
|
45
44
|
const applyPosition = (position, options) => {
|
|
46
45
|
return calculatePosition({
|
|
47
46
|
triggerBounds: resolvedTriggerBounds,
|
|
@@ -60,6 +59,12 @@ const flyout = (args) => {
|
|
|
60
59
|
});
|
|
61
60
|
};
|
|
62
61
|
const testVisibility = (calculated) => {
|
|
62
|
+
const visualContainerBounds = passedContainer?.getBoundingClientRect() ?? {
|
|
63
|
+
width: window.innerWidth,
|
|
64
|
+
height: window.innerHeight,
|
|
65
|
+
left: window.scrollX,
|
|
66
|
+
top: window.scrollY,
|
|
67
|
+
};
|
|
63
68
|
return isFullyVisible({
|
|
64
69
|
flyoutBounds: calculated.boundaries,
|
|
65
70
|
visualContainerBounds,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
type Bounds = Pick<DOMRect, "left" | "top" | "width" | "height">;
|
|
1
2
|
/**
|
|
2
3
|
* Check if element visually fits within its render container
|
|
3
4
|
*/
|
|
4
5
|
declare const isFullyVisible: (args: {
|
|
5
6
|
/** Bounds of the flyout content */
|
|
6
|
-
flyoutBounds:
|
|
7
|
+
flyoutBounds: Bounds;
|
|
7
8
|
/** Bounds of the container where the flyout content should fit */
|
|
8
|
-
visualContainerBounds:
|
|
9
|
+
visualContainerBounds: Bounds;
|
|
9
10
|
/** Bounds of the container where flyout content is rendered */
|
|
10
|
-
renderContainerBounds:
|
|
11
|
+
renderContainerBounds: Bounds;
|
|
11
12
|
}) => boolean;
|
|
12
13
|
export default isFullyVisible;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
+
import { SCREEN_OFFSET } from "./constants.js";
|
|
1
2
|
/**
|
|
2
3
|
* Check if element visually fits within its render container
|
|
3
4
|
*/
|
|
4
5
|
const isFullyVisible = (args) => {
|
|
5
6
|
const { flyoutBounds, visualContainerBounds, renderContainerBounds } = args;
|
|
6
|
-
if (renderContainerBounds.left + flyoutBounds.left < visualContainerBounds.left) {
|
|
7
|
+
if (renderContainerBounds.left + flyoutBounds.left < visualContainerBounds.left + SCREEN_OFFSET) {
|
|
7
8
|
return false;
|
|
8
9
|
}
|
|
9
|
-
if (renderContainerBounds.top + flyoutBounds.top < visualContainerBounds.top) {
|
|
10
|
+
if (renderContainerBounds.top + flyoutBounds.top < visualContainerBounds.top + SCREEN_OFFSET) {
|
|
10
11
|
return false;
|
|
11
12
|
}
|
|
12
13
|
if (renderContainerBounds.left + flyoutBounds.left + flyoutBounds.width >
|
|
13
|
-
visualContainerBounds.
|
|
14
|
+
visualContainerBounds.left + visualContainerBounds.width - SCREEN_OFFSET) {
|
|
14
15
|
return false;
|
|
15
16
|
}
|
|
16
17
|
if (renderContainerBounds.top + flyoutBounds.top + flyoutBounds.height >
|
|
17
|
-
visualContainerBounds.
|
|
18
|
+
visualContainerBounds.top + visualContainerBounds.height - SCREEN_OFFSET) {
|
|
18
19
|
return false;
|
|
19
20
|
}
|
|
20
21
|
return true;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reshaped",
|
|
3
3
|
"description": "Professionally crafted design system in React & Figma for building products of any scale and complexity",
|
|
4
|
-
"version": "3.9.0-canary.
|
|
4
|
+
"version": "3.9.0-canary.16",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"email": "hello@reshaped.so",
|
|
7
7
|
"homepage": "https://reshaped.so",
|