UNPKG

react-konva-utils

Version:

Useful components and hooks for react-konva

104 lines (103 loc) 3.96 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; import React from 'react'; import ReactDOM from 'react-dom/client'; import { Group } from 'react-konva'; import { useContextBridge } from 'its-fine'; import { flushSync } from 'react-dom'; const needForceStyle = (el) => { const pos = window.getComputedStyle(el).position; const ok = pos === 'absolute' || pos === 'relative'; return !ok; }; export function useEvent(fn = () => { }) { const ref = React.useRef(fn); ref.current = fn; return React.useCallback((...args) => { return ref.current.apply(null, args); }, []); } export const Html = ({ children, groupProps, divProps, transform, transformFunc, parentNodeFunc, }) => { const Bridge = useContextBridge(); const groupRef = React.useRef(null); const [div] = React.useState(() => document.createElement('div')); const root = React.useMemo(() => ReactDOM.createRoot(div), [div]); const shouldTransform = transform !== null && transform !== void 0 ? transform : true; const handleTransform = useEvent(() => { if (shouldTransform && groupRef.current) { const tr = groupRef.current.getAbsoluteTransform(); let attrs = tr.decompose(); if (transformFunc) { attrs = transformFunc(attrs); } div.style.position = 'absolute'; div.style.zIndex = '10'; div.style.top = '0px'; div.style.left = '0px'; div.style.transform = `translate(${attrs.x}px, ${attrs.y}px) rotate(${attrs.rotation}deg) scaleX(${attrs.scaleX}) scaleY(${attrs.scaleY})`; div.style.transformOrigin = 'top left'; } else { div.style.position = ''; div.style.zIndex = ''; div.style.top = ''; div.style.left = ''; div.style.transform = ``; div.style.transformOrigin = ''; } const _a = divProps || {}, { style } = _a, restProps = __rest(_a, ["style"]); Object.assign(div.style, style); Object.assign(div, restProps); }); React.useLayoutEffect(() => { var _a; const group = groupRef.current; if (!group) { return; } const parent = parentNodeFunc ? parentNodeFunc({ stage: group.getStage() }) : (_a = group.getStage()) === null || _a === void 0 ? void 0 : _a.container(); if (!parent) { return; } parent.appendChild(div); if (shouldTransform && needForceStyle(parent)) { parent.style.position = 'relative'; } group.on('absoluteTransformChange', handleTransform); handleTransform(); return () => { var _a; group.off('absoluteTransformChange', handleTransform); (_a = div.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(div); }; }, [shouldTransform, parentNodeFunc]); React.useLayoutEffect(() => { handleTransform(); }, [divProps, transformFunc]); React.useLayoutEffect(() => { queueMicrotask(() => { flushSync(() => { root.render(React.createElement(Bridge, null, children)); }); }); }); React.useLayoutEffect(() => { return () => { setTimeout(() => { root.unmount(); }); }; }, []); return React.createElement(Group, Object.assign({ ref: groupRef }, groupProps)); };