170 lines
6.2 KiB
JavaScript
170 lines
6.2 KiB
JavaScript
'use client';
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
function _export(target, all) {
|
|
for(var name in all)Object.defineProperty(target, name, {
|
|
enumerable: true,
|
|
get: all[name]
|
|
});
|
|
}
|
|
_export(exports, {
|
|
SafeZoneArea: function() {
|
|
return SafeZoneArea;
|
|
},
|
|
isSameCoordinates: function() {
|
|
return isSameCoordinates;
|
|
},
|
|
isSameRect: function() {
|
|
return isSameRect;
|
|
}
|
|
});
|
|
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
|
|
const _react = require("@griffel/react");
|
|
const _reactutilities = require("@fluentui/react-utilities");
|
|
const _react1 = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
|
const _shim = require("use-sync-external-store/shim");
|
|
const _getRectCorners = require("./getRectCorners");
|
|
const _getMouseAnchor = require("./getMouseAnchor");
|
|
const _pointsToSvgPath = require("./pointsToSvgPath");
|
|
const _SafeZoneAreastyles = require("./SafeZoneArea.styles");
|
|
const _computeOutsideClipPath = require("./computeOutsideClipPath");
|
|
// ---
|
|
const EMPTY_RECT = {
|
|
top: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
left: 0,
|
|
width: 0,
|
|
height: 0,
|
|
x: 0,
|
|
y: 0,
|
|
toJSON () {
|
|
return '';
|
|
}
|
|
};
|
|
function isSameRect(a, b) {
|
|
return a.top === b.top && a.right === b.right && a.bottom === b.bottom && a.left === b.left && a.width === b.width && a.height === b.height;
|
|
}
|
|
function isSameCoordinates(a, b) {
|
|
return a[0] === b[0] && a[1] === b[1];
|
|
}
|
|
const SafeZoneArea = /*#__PURE__*/ _react1.memo((props)=>{
|
|
const { debug, onMouseEnter, onMouseMove, onMouseLeave, stateStore } = props;
|
|
const clipPathId = (0, _reactutilities.useId)();
|
|
const styles = (0, _SafeZoneAreastyles.useStyles)();
|
|
const active = (0, _shim.useSyncExternalStore)(stateStore.subscribe, stateStore.isActive);
|
|
const svgRef = _react1.useRef(null);
|
|
const [state, setState] = _react1.useState(()=>({
|
|
containerRect: EMPTY_RECT,
|
|
targetRect: EMPTY_RECT,
|
|
mouseCoordinates: [
|
|
0,
|
|
0
|
|
]
|
|
}));
|
|
_react1.useImperativeHandle(props.imperativeRef, ()=>({
|
|
updateSVG (newState) {
|
|
setState((prevState)=>{
|
|
// Heads up!
|
|
// A small optimization to avoid unnecessary re-renders
|
|
if (isSameRect(prevState.containerRect, newState.containerRect) && isSameRect(prevState.targetRect, newState.targetRect) && isSameCoordinates(prevState.mouseCoordinates, newState.mouseCoordinates)) {
|
|
return prevState;
|
|
}
|
|
return newState;
|
|
});
|
|
}
|
|
}), []);
|
|
const { containerRect, targetRect, mouseCoordinates } = state;
|
|
const topOffset = Math.min(targetRect.top, containerRect.top);
|
|
const leftOffset = Math.min(targetRect.left, containerRect.left);
|
|
const bottomOffset = Math.max(targetRect.bottom, containerRect.bottom);
|
|
const rightOffset = Math.max(targetRect.right, containerRect.right);
|
|
// ---
|
|
const containerCorners = (0, _getRectCorners.getRectCorners)(containerRect, [
|
|
leftOffset,
|
|
topOffset
|
|
]);
|
|
const targetCorners = (0, _getRectCorners.getRectCorners)(targetRect, [
|
|
leftOffset,
|
|
topOffset
|
|
]);
|
|
// Heads up!
|
|
// The SVG coordinate system starts at the top-left corner of the SVG element,
|
|
// so we need to adjust the mouse coordinates relative to the SVG's top-left corner.
|
|
const relativeMouseCoordinates = [
|
|
mouseCoordinates[0] - leftOffset,
|
|
mouseCoordinates[1] - topOffset
|
|
];
|
|
const mouseAnchor = (0, _getMouseAnchor.getMouseAnchor)(containerCorners.topLeft, containerCorners.bottomRight, relativeMouseCoordinates);
|
|
const triangleA = [
|
|
mouseAnchor,
|
|
containerCorners.topLeft,
|
|
containerCorners.topRight
|
|
];
|
|
const triangleB = [
|
|
mouseAnchor,
|
|
containerCorners.topRight,
|
|
containerCorners.bottomRight
|
|
];
|
|
const triangleC = [
|
|
mouseAnchor,
|
|
containerCorners.bottomRight,
|
|
containerCorners.bottomLeft
|
|
];
|
|
const triangleD = [
|
|
mouseAnchor,
|
|
containerCorners.bottomLeft,
|
|
containerCorners.topLeft
|
|
];
|
|
const svgWidth = rightOffset - leftOffset;
|
|
const svgHeight = bottomOffset - topOffset;
|
|
const clipPath = (0, _computeOutsideClipPath.computeOutsideClipPath)(svgWidth, svgHeight, {
|
|
x: targetCorners.topLeft[0],
|
|
y: targetCorners.topLeft[1],
|
|
width: targetRect.width,
|
|
height: targetRect.height
|
|
}, {
|
|
x: containerCorners.topLeft[0],
|
|
y: containerCorners.topLeft[1],
|
|
width: containerRect.width,
|
|
height: containerRect.height
|
|
});
|
|
return /*#__PURE__*/ _react1.createElement("div", {
|
|
className: (0, _react.mergeClasses)(styles.wrapper, active && styles.wrapperActive),
|
|
"data-safe-zone": ""
|
|
}, active ? /*#__PURE__*/ _react1.createElement("svg", {
|
|
"aria-hidden": true,
|
|
className: styles.svg,
|
|
xmlns: "http://www.w3.org/2000/svg",
|
|
ref: svgRef,
|
|
style: {
|
|
width: `${svgWidth}px`,
|
|
height: `${svgHeight}px`,
|
|
transform: `translate(${leftOffset}px, ${topOffset}px)`
|
|
}
|
|
}, /*#__PURE__*/ _react1.createElement("g", {
|
|
className: (0, _react.mergeClasses)(styles.triangle, debug && styles.triangleDebug),
|
|
clipPath: `url(#${clipPathId})`,
|
|
onMouseEnter: onMouseEnter,
|
|
onMouseMove: onMouseMove,
|
|
onMouseLeave: onMouseLeave
|
|
}, /*#__PURE__*/ _react1.createElement("path", {
|
|
d: (0, _pointsToSvgPath.pointsToSvgPath)(triangleA)
|
|
}), /*#__PURE__*/ _react1.createElement("path", {
|
|
d: (0, _pointsToSvgPath.pointsToSvgPath)(triangleB)
|
|
}), /*#__PURE__*/ _react1.createElement("path", {
|
|
d: (0, _pointsToSvgPath.pointsToSvgPath)(triangleC)
|
|
}), /*#__PURE__*/ _react1.createElement("path", {
|
|
d: (0, _pointsToSvgPath.pointsToSvgPath)(triangleD)
|
|
})), /*#__PURE__*/ _react1.createElement("clipPath", {
|
|
id: clipPathId
|
|
}, /*#__PURE__*/ _react1.createElement("path", {
|
|
d: clipPath
|
|
})), debug && /*#__PURE__*/ _react1.createElement("path", {
|
|
className: styles.rectDebug,
|
|
d: clipPath
|
|
})) : null);
|
|
});
|