[REF] web_tour: replace a deprecated function
**Before this commit** The TourPointer component make use of a deprecated function (reposition) in order to position itself. **After this commit** The TourPointer now make use of the usePosition hook, which is the recommended way to compute this kind of positioning. Part-of: odoo/odoo#135188
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { Component, useEffect, useRef } from "@odoo/owl";
|
||||
import { reposition } from "@web/core/position_hook";
|
||||
import { usePosition } from "@web/core/position_hook";
|
||||
|
||||
/**
|
||||
* @typedef {import("../tour_service/tour_pointer_state").TourPointerState} TourPointerState
|
||||
@@ -48,6 +48,26 @@ export class TourPointer extends Component {
|
||||
static height = 28; // in pixels
|
||||
|
||||
setup() {
|
||||
const positionOptions = {
|
||||
margin: 6,
|
||||
onPositioned: (pointer, position) => {
|
||||
const popperRect = pointer.getBoundingClientRect();
|
||||
const { top, left, direction } = position;
|
||||
if (direction === "top") {
|
||||
// position from the bottom instead of the top as it is needed
|
||||
// to ensure the expand animation is properly done
|
||||
pointer.style.bottom = `${window.innerHeight - top - popperRect.height}px`;
|
||||
pointer.style.removeProperty("top");
|
||||
} else if (direction === "left") {
|
||||
// position from the right instead of the left as it is needed
|
||||
// to ensure the expand animation is properly done
|
||||
pointer.style.right = `${window.innerWidth - left - popperRect.width}px`;
|
||||
pointer.style.removeProperty("left");
|
||||
}
|
||||
},
|
||||
};
|
||||
Object.defineProperty(positionOptions, "position", { get: () => this.position, enumerable: true });
|
||||
const position = usePosition("pointer", () => this.props.pointerState.anchor, positionOptions);
|
||||
const rootRef = useRef("pointer");
|
||||
/** @type {DOMREct | null} */
|
||||
let dimensions = null;
|
||||
@@ -55,96 +75,66 @@ export class TourPointer extends Component {
|
||||
let lastOpenState = this.isOpen;
|
||||
let lastAnchor;
|
||||
let [anchorX, anchorY] = [0, 0];
|
||||
useEffect(() => {
|
||||
const { el: pointer } = rootRef;
|
||||
if (pointer) {
|
||||
const hasContentChanged = lastMeasuredContent !== this.content;
|
||||
const hasOpenStateChanged = lastOpenState !== this.isOpen;
|
||||
lastOpenState = this.isOpen;
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
const { el: pointer } = rootRef;
|
||||
if (pointer) {
|
||||
const hasContentChanged = lastMeasuredContent !== this.content;
|
||||
const hasOpenStateChanged = lastOpenState !== this.isOpen;
|
||||
lastOpenState = this.isOpen;
|
||||
|
||||
// Content changed: we must re-measure the dimensions of the text.
|
||||
if (hasContentChanged) {
|
||||
lastMeasuredContent = this.content;
|
||||
pointer.style.removeProperty("width");
|
||||
pointer.style.removeProperty("height");
|
||||
dimensions = pointer.getBoundingClientRect();
|
||||
}
|
||||
|
||||
// If the content or the "is open" state changed: we must apply
|
||||
// new width and height properties
|
||||
if (hasContentChanged || hasOpenStateChanged) {
|
||||
const [width, height] = this.isOpen
|
||||
? [dimensions.width, dimensions.height]
|
||||
: [this.constructor.width, this.constructor.height];
|
||||
if (this.isOpen) {
|
||||
pointer.style.removeProperty("transition");
|
||||
} else {
|
||||
// No transition if switching from open to closed
|
||||
pointer.style.setProperty("transition", "none");
|
||||
}
|
||||
pointer.style.setProperty("width", `${width}px`);
|
||||
pointer.style.setProperty("height", `${height}px`);
|
||||
}
|
||||
|
||||
if (!this.isOpen) {
|
||||
const { anchor } = this.props.pointerState;
|
||||
if (anchor === lastAnchor) {
|
||||
const { x, y, width } = anchor.getBoundingClientRect();
|
||||
const [lastAnchorX, lastAnchorY] = [anchorX, anchorY];
|
||||
[anchorX, anchorY] = [x, y];
|
||||
// Let's just say that the anchor is static if it moved less than 1px.
|
||||
const delta = Math.sqrt(
|
||||
Math.pow(x - lastAnchorX, 2) + Math.pow(y - lastAnchorY, 2)
|
||||
);
|
||||
if (delta < 1) {
|
||||
return;
|
||||
}
|
||||
const wouldOverflow =
|
||||
window.innerWidth - x - width / 2 < dimensions?.width;
|
||||
pointer.classList.toggle("o_expand_left", wouldOverflow);
|
||||
}
|
||||
lastAnchor = anchor;
|
||||
pointer.style.bottom = "";
|
||||
pointer.style.right = "";
|
||||
reposition(
|
||||
pointer,
|
||||
anchor,
|
||||
{
|
||||
position: this.position,
|
||||
margin: 6,
|
||||
onPositioned: (_, position) => {
|
||||
const popperRect = pointer.getBoundingClientRect();
|
||||
const { top, left, direction } = position;
|
||||
if (direction === "top") {
|
||||
// position from the bottom instead of the top as it is needed
|
||||
// to ensure the expand animation is properly done
|
||||
pointer.style.bottom = `${
|
||||
window.innerHeight - top - popperRect.height
|
||||
}px`;
|
||||
pointer.style.removeProperty("top");
|
||||
} else if (direction === "left") {
|
||||
// position from the right instead of the left as it is needed
|
||||
// to ensure the expand animation is properly done
|
||||
pointer.style.right = `${
|
||||
window.innerWidth - left - popperRect.width
|
||||
}px`;
|
||||
pointer.style.removeProperty("left");
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
} else {
|
||||
lastMeasuredContent = null;
|
||||
lastOpenState = false;
|
||||
lastAnchor = null;
|
||||
dimensions = null;
|
||||
// Content changed: we must re-measure the dimensions of the text.
|
||||
if (hasContentChanged) {
|
||||
lastMeasuredContent = this.content;
|
||||
pointer.style.removeProperty("width");
|
||||
pointer.style.removeProperty("height");
|
||||
dimensions = pointer.getBoundingClientRect();
|
||||
}
|
||||
},
|
||||
() => [this.props.pointerState.rev]
|
||||
);
|
||||
|
||||
// If the content or the "is open" state changed: we must apply
|
||||
// new width and height properties
|
||||
if (hasContentChanged || hasOpenStateChanged) {
|
||||
const [width, height] = this.isOpen
|
||||
? [dimensions.width, dimensions.height]
|
||||
: [this.constructor.width, this.constructor.height];
|
||||
if (this.isOpen) {
|
||||
pointer.style.removeProperty("transition");
|
||||
} else {
|
||||
// No transition if switching from open to closed
|
||||
pointer.style.setProperty("transition", "none");
|
||||
}
|
||||
pointer.style.setProperty("width", `${width}px`);
|
||||
pointer.style.setProperty("height", `${height}px`);
|
||||
}
|
||||
|
||||
if (!this.isOpen) {
|
||||
const { anchor } = this.props.pointerState;
|
||||
if (anchor === lastAnchor) {
|
||||
const { x, y, width } = anchor.getBoundingClientRect();
|
||||
const [lastAnchorX, lastAnchorY] = [anchorX, anchorY];
|
||||
[anchorX, anchorY] = [x, y];
|
||||
// Let's just say that the anchor is static if it moved less than 1px.
|
||||
const delta = Math.sqrt(
|
||||
Math.pow(x - lastAnchorX, 2) + Math.pow(y - lastAnchorY, 2)
|
||||
);
|
||||
if (delta < 1) {
|
||||
position.lock();
|
||||
return;
|
||||
}
|
||||
const wouldOverflow = window.innerWidth - x - width / 2 < dimensions?.width;
|
||||
pointer.classList.toggle("o_expand_left", wouldOverflow);
|
||||
}
|
||||
lastAnchor = anchor;
|
||||
pointer.style.bottom = "";
|
||||
pointer.style.right = "";
|
||||
position.unlock();
|
||||
}
|
||||
} else {
|
||||
lastMeasuredContent = null;
|
||||
lastOpenState = false;
|
||||
lastAnchor = null;
|
||||
dimensions = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get content() {
|
||||
|
||||
@@ -94,7 +94,7 @@ export function createPointerState() {
|
||||
* @param {Partial<TourPointerState>} newState
|
||||
*/
|
||||
const setState = (newState) => {
|
||||
Object.assign(state, newState, { rev: currentRev++ });
|
||||
Object.assign(state, newState);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -171,7 +171,6 @@ export function createPointerState() {
|
||||
}
|
||||
}
|
||||
|
||||
let currentRev = 1;
|
||||
/** @type {TourPointerState} */
|
||||
const state = reactive({});
|
||||
const intersection = new Intersection();
|
||||
|
||||
Reference in New Issue
Block a user