From 535a76275e0401044b4cdbfedbf4c1dc8b7d7721 Mon Sep 17 00:00:00 2001 From: Segun Adebayo Date: Fri, 25 Aug 2023 09:21:14 +0100 Subject: [PATCH] refactor: context menu positioning --- packages/machines/menu/src/menu.connect.ts | 1 - packages/machines/menu/src/menu.machine.ts | 36 +++++++++------------ packages/utilities/popper/src/get-styles.ts | 13 +++----- 3 files changed, 20 insertions(+), 30 deletions(-) diff --git a/packages/machines/menu/src/menu.connect.ts b/packages/machines/menu/src/menu.connect.ts index 73253adce6..e79bb5f885 100644 --- a/packages/machines/menu/src/menu.connect.ts +++ b/packages/machines/menu/src/menu.connect.ts @@ -35,7 +35,6 @@ export function connect(state: State, send: Send, normalize const popperStyles = getPlacementStyles({ ...state.context.positioning, placement: state.context.currentPlacement, - anchorPoint: state.context.anchorPoint, }) const api = { diff --git a/packages/machines/menu/src/menu.machine.ts b/packages/machines/menu/src/menu.machine.ts index 701d615e33..32f3b6aa72 100644 --- a/packages/machines/menu/src/menu.machine.ts +++ b/packages/machines/menu/src/menu.machine.ts @@ -44,7 +44,7 @@ export function machine(userContext: UserDefinedContext) { watch: { isSubmenu: "setSubmenuPlacement", - anchorPoint: "applyAnchorPoint", + anchorPoint: "setPositioning", }, on: { @@ -388,22 +388,6 @@ export function machine(userContext: UserDefinedContext) { clearAnchorPoint(ctx) { ctx.anchorPoint = null }, - applyAnchorPoint(ctx) { - const point = ctx.anchorPoint - if (!point) return - - const el = dom.getPositionerEl(ctx) - if (!el) return - - raf(() => { - Object.assign(el.style, { - position: "absolute", - top: "0", - left: "0", - transform: `translate3d(${point.x}px, ${point.y}px, 0)`, - }) - }) - }, setSubmenuPlacement(ctx) { if (!ctx.isSubmenu) return ctx.positioning.placement = ctx.isRtl ? "left-start" : "right-start" @@ -411,11 +395,23 @@ export function machine(userContext: UserDefinedContext) { }, setPositioning(ctx, evt) { const getPositionerEl = () => dom.getPositionerEl(ctx) - getPlacement(dom.getTriggerEl(ctx), getPositionerEl, { + + const virtualAnchorEl = ctx.anchorPoint + ? { + getBoundingClientRect: () => { + const win = dom.getWin(ctx) + return win.DOMRect.fromRect({ width: 0, height: 0, ...ctx.anchorPoint }) + }, + } + : undefined + + const anchorEl = virtualAnchorEl ?? dom.getTriggerEl(ctx) + + void getPlacement(anchorEl, getPositionerEl, { ...ctx.positioning, - ...evt.options, - defer: true, + ...(evt.options ?? {}), listeners: false, + // defer: true, }) }, invokeOnValueChange(ctx, evt) { diff --git a/packages/utilities/popper/src/get-styles.ts b/packages/utilities/popper/src/get-styles.ts index 9e7be15c0a..5e918630f1 100644 --- a/packages/utilities/popper/src/get-styles.ts +++ b/packages/utilities/popper/src/get-styles.ts @@ -13,13 +13,8 @@ const ARROW_FLOATING_STYLE = { right: "rotate(315deg)", } as const -type PlacementStyleOptions = PositioningOptions & { - anchorPoint?: { x: number; y: number } | null -} - -export function getPlacementStyles(options: PlacementStyleOptions = {}) { - const { placement = "bottom", sameWidth, fitViewport, strategy = "absolute", anchorPoint } = options - const point = anchorPoint || { x: 0, y: 0 } +export function getPlacementStyles(options: PositioningOptions = {}) { + const { placement = "bottom", sameWidth, fitViewport, strategy = "absolute" } = options return { arrow: { @@ -47,8 +42,8 @@ export function getPlacementStyles(options: PlacementStyleOptions = {}) { width: sameWidth ? "var(--reference-width)" : undefined, maxWidth: fitViewport ? "var(--available-width)" : undefined, maxHeight: fitViewport ? "var(--available-height)" : undefined, - top: `${point.y}px`, - left: `${point.x}px`, + top: "0px", + left: "0px", transform: `translate3d(var(--x), var(--y), 0)`, } as const, }