@tldraw/editor
Version:
tldraw infinite canvas SDK (editor).
156 lines (155 loc) • 7.14 kB
JavaScript
;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var Shape_exports = {};
__export(Shape_exports, {
InnerShape: () => InnerShape,
InnerShapeBackground: () => InnerShapeBackground,
Shape: () => Shape
});
module.exports = __toCommonJS(Shape_exports);
var import_jsx_runtime = require("react/jsx-runtime");
var import_state = require("@tldraw/state");
var import_state_react = require("@tldraw/state-react");
var import_react = require("react");
var import_EditorComponentsContext = require("../hooks/EditorComponentsContext");
var import_useEditor = require("../hooks/useEditor");
var import_useShapeCulling = require("../hooks/useShapeCulling");
var import_Mat = require("../primitives/Mat");
var import_areShapesContentEqual = require("../utils/areShapesContentEqual");
var import_dom = require("../utils/dom");
var import_ErrorBoundary = require("./ErrorBoundary");
const Shape = (0, import_react.memo)(function Shape2({
id,
shape,
util,
index,
backgroundIndex,
opacity
}) {
const editor = (0, import_useEditor.useEditor)();
const { ShapeErrorFallback, ShapeWrapper } = (0, import_EditorComponentsContext.useEditorComponents)();
const containerRef = (0, import_react.useRef)(null);
const bgContainerRef = (0, import_react.useRef)(null);
(0, import_react.useEffect)(() => {
return (0, import_state.react)("load fonts", () => {
const fonts = editor.fonts.getShapeFontFaces(id);
editor.fonts.requestFonts(fonts);
});
}, [editor, id]);
const memoizedStuffRef = (0, import_react.useRef)({
transform: "",
clipPath: "none",
width: 0,
height: 0,
x: 0,
y: 0
});
(0, import_state_react.useQuickReactor)(
"set shape stuff",
() => {
const shape2 = editor.getShape(id);
if (!shape2) return;
const prev = memoizedStuffRef.current;
const clipPath = editor.getShapeClipPath(id) ?? "none";
if (clipPath !== prev.clipPath) {
(0, import_dom.setStyleProperty)(containerRef.current, "clip-path", clipPath);
(0, import_dom.setStyleProperty)(bgContainerRef.current, "clip-path", clipPath);
prev.clipPath = clipPath;
}
const pageTransform = editor.getShapePageTransform(id);
const transform = import_Mat.Mat.toCssString(pageTransform);
const bounds = editor.getShapeGeometry(shape2).bounds;
if (transform !== prev.transform) {
(0, import_dom.setStyleProperty)(containerRef.current, "transform", transform);
(0, import_dom.setStyleProperty)(bgContainerRef.current, "transform", transform);
prev.transform = transform;
}
const width = Math.max(bounds.width, 1);
const height = Math.max(bounds.height, 1);
if (width !== prev.width || height !== prev.height) {
(0, import_dom.setStyleProperty)(containerRef.current, "width", width + "px");
(0, import_dom.setStyleProperty)(containerRef.current, "height", height + "px");
(0, import_dom.setStyleProperty)(bgContainerRef.current, "width", width + "px");
(0, import_dom.setStyleProperty)(bgContainerRef.current, "height", height + "px");
prev.width = width;
prev.height = height;
}
},
[editor]
);
(0, import_react.useLayoutEffect)(() => {
const container = containerRef.current;
const bgContainer = bgContainerRef.current;
(0, import_dom.setStyleProperty)(container, "opacity", opacity);
(0, import_dom.setStyleProperty)(bgContainer, "opacity", opacity);
(0, import_dom.setStyleProperty)(container, "z-index", index);
(0, import_dom.setStyleProperty)(bgContainer, "z-index", backgroundIndex);
}, [opacity, index, backgroundIndex]);
const { register, unregister } = (0, import_useShapeCulling.useShapeCulling)();
(0, import_react.useLayoutEffect)(() => {
const container = containerRef.current;
if (!container) return;
const isCulled = editor.getCulledShapes().has(id);
register(id, container, bgContainerRef.current, isCulled);
return () => {
unregister(id);
};
}, [editor, id, register, unregister]);
const annotateError = (0, import_react.useCallback)(
(error) => editor.annotateError(error, { origin: "shape", willCrashApp: false }),
[editor]
);
if (!shape || !ShapeWrapper) return null;
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
util.backgroundComponent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShapeWrapper, { ref: bgContainerRef, shape, isBackground: true, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ErrorBoundary.OptionalErrorBoundary, { fallback: ShapeErrorFallback, onError: annotateError, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InnerShapeBackground, { shape, util }) }) }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ShapeWrapper, { ref: containerRef, shape, isBackground: false, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ErrorBoundary.OptionalErrorBoundary, { fallback: ShapeErrorFallback, onError: annotateError, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InnerShape, { shape, util }) }) })
] });
});
const InnerShape = (0, import_react.memo)(
function InnerShape2({ shape, util }) {
return (0, import_state_react.useStateTracking)(
"InnerShape:" + shape.type,
() => (
// always fetch the latest shape from the store even if the props/meta have not changed, to avoid
// calling the render method with stale data.
util.component(util.editor.store.unsafeGetWithoutCapture(shape.id))
),
[util, shape.id]
);
},
(prev, next) => (0, import_areShapesContentEqual.areShapesContentEqual)(prev.shape, next.shape) && prev.util === next.util
);
const InnerShapeBackground = (0, import_react.memo)(
function InnerShapeBackground2({
shape,
util
}) {
return (0, import_state_react.useStateTracking)(
"InnerShape:" + shape.type,
() => (
// always fetch the latest shape from the store even if the props/meta have not changed, to avoid
// calling the render method with stale data.
util.backgroundComponent?.(util.editor.store.unsafeGetWithoutCapture(shape.id))
),
[util, shape.id]
);
},
(prev, next) => prev.shape.props === next.shape.props && prev.shape.meta === next.shape.meta && prev.util === next.util
);
//# sourceMappingURL=Shape.js.map