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.
@@ -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
- // eslint-disable-next-line react-hooks/refs
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
- triggerBounds?: DOMRect | G.Coordinates | null;
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, triggerBounds, contentGap, contentShift, ...options } = args;
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
- triggerBounds,
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, fallbackMinWidth, fallbackMinHeight, } = args;
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 (updatedOverflow.left > 0) {
141
- width = Math.max(fallbackMinWidth ? parseInt(fallbackMinWidth) : 0, flyoutWidth - updatedOverflow.left);
142
- left = left + (flyoutWidth - width);
143
- }
144
- else if (updatedOverflow.right > 0) {
145
- width = Math.max(fallbackMinWidth ? parseInt(fallbackMinWidth) : 0, flyoutWidth - updatedOverflow.right);
146
- if (right !== null)
147
- right = right + (flyoutWidth - width);
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: Pick<DOMRect, "left" | "top" | "width" | "height">;
7
+ flyoutBounds: Bounds;
7
8
  /** Bounds of the container where the flyout content should fit */
8
- visualContainerBounds: DOMRect;
9
+ visualContainerBounds: Bounds;
9
10
  /** Bounds of the container where flyout content is rendered */
10
- renderContainerBounds: DOMRect;
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.right) {
14
+ visualContainerBounds.left + visualContainerBounds.width - SCREEN_OFFSET) {
14
15
  return false;
15
16
  }
16
17
  if (renderContainerBounds.top + flyoutBounds.top + flyoutBounds.height >
17
- visualContainerBounds.bottom) {
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.14",
4
+ "version": "3.9.0-canary.16",
5
5
  "license": "MIT",
6
6
  "email": "hello@reshaped.so",
7
7
  "homepage": "https://reshaped.so",