@tldraw/editor
Version:
tldraw infinite canvas SDK (editor).
162 lines (161 loc) • 6.5 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 LiveCollaborators_exports = {};
__export(LiveCollaborators_exports, {
LiveCollaborators: () => LiveCollaborators
});
module.exports = __toCommonJS(LiveCollaborators_exports);
var import_jsx_runtime = require("react/jsx-runtime");
var import_state_react = require("@tldraw/state-react");
var import_react = require("react");
var import_useEditor = require("../hooks/useEditor");
var import_useEditorComponents = require("../hooks/useEditorComponents");
var import_usePeerIds = require("../hooks/usePeerIds");
var import_usePresence = require("../hooks/usePresence");
const LiveCollaborators = (0, import_state_react.track)(function Collaborators() {
const peerIds = (0, import_usePeerIds.usePeerIds)();
return peerIds.map((id) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CollaboratorGuard, { collaboratorId: id }, id));
});
const CollaboratorGuard = (0, import_state_react.track)(function CollaboratorGuard2({
collaboratorId
}) {
const editor = (0, import_useEditor.useEditor)();
const presence = (0, import_usePresence.usePresence)(collaboratorId);
const collaboratorState = useCollaboratorState(editor, presence);
if (!(presence && presence.currentPageId === editor.getCurrentPageId())) {
return null;
}
switch (collaboratorState) {
case "inactive": {
const { followingUserId, highlightedUserIds } = editor.getInstanceState();
if (!(followingUserId === presence.userId || highlightedUserIds.includes(presence.userId))) {
return null;
}
break;
}
case "idle": {
const { highlightedUserIds } = editor.getInstanceState();
if (presence.followingUserId === editor.user.getId() && !(presence.chatMessage || highlightedUserIds.includes(presence.userId))) {
return null;
}
break;
}
case "active": {
break;
}
}
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Collaborator, { latestPresence: presence });
});
const Collaborator = (0, import_state_react.track)(function Collaborator2({
latestPresence
}) {
const editor = (0, import_useEditor.useEditor)();
const {
CollaboratorBrush,
CollaboratorScribble,
CollaboratorCursor,
CollaboratorHint,
CollaboratorShapeIndicator
} = (0, import_useEditorComponents.useEditorComponents)();
const zoomLevel = editor.getZoomLevel();
const viewportPageBounds = editor.getViewportPageBounds();
const { userId, chatMessage, brush, scribbles, selectedShapeIds, userName, cursor, color } = latestPresence;
if (!cursor) return null;
const isCursorInViewport = !(cursor.x < viewportPageBounds.minX - 12 / zoomLevel || cursor.y < viewportPageBounds.minY - 16 / zoomLevel || cursor.x > viewportPageBounds.maxX - 12 / zoomLevel || cursor.y > viewportPageBounds.maxY - 16 / zoomLevel);
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
brush && CollaboratorBrush ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
CollaboratorBrush,
{
className: "tl-collaborator__brush",
userId,
brush,
color,
opacity: 0.1
},
userId + "_brush"
) : null,
isCursorInViewport && CollaboratorCursor ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
CollaboratorCursor,
{
className: "tl-collaborator__cursor",
userId,
point: cursor,
color,
zoom: zoomLevel,
name: userName !== "New User" ? userName : null,
chatMessage: chatMessage ?? ""
},
userId + "_cursor"
) : CollaboratorHint ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
CollaboratorHint,
{
className: "tl-collaborator__cursor-hint",
userId,
point: cursor,
color,
zoom: zoomLevel,
viewport: viewportPageBounds
},
userId + "_cursor_hint"
) : null,
CollaboratorScribble && scribbles.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: scribbles.map((scribble) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
CollaboratorScribble,
{
className: "tl-collaborator__scribble",
userId,
scribble,
color,
zoom: zoomLevel,
opacity: scribble.color === "laser" ? 0.5 : 0.1
},
userId + "_scribble_" + scribble.id
)) }) : null,
CollaboratorShapeIndicator && selectedShapeIds.filter((id) => !editor.isShapeHidden(id)).map((shapeId) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
CollaboratorShapeIndicator,
{
className: "tl-collaborator__shape-indicator",
userId,
shapeId,
color,
opacity: 0.5
},
userId + "_" + shapeId
))
] });
});
function getStateFromElapsedTime(editor, elapsed) {
return elapsed > editor.options.collaboratorInactiveTimeoutMs ? "inactive" : elapsed > editor.options.collaboratorIdleTimeoutMs ? "idle" : "active";
}
function useCollaboratorState(editor, latestPresence) {
const rLastActivityTimestamp = (0, import_react.useRef)(latestPresence?.lastActivityTimestamp ?? -1);
const [state, setState] = (0, import_react.useState)(
() => getStateFromElapsedTime(editor, Date.now() - rLastActivityTimestamp.current)
);
(0, import_react.useEffect)(() => {
const interval = editor.timers.setInterval(() => {
setState(getStateFromElapsedTime(editor, Date.now() - rLastActivityTimestamp.current));
}, editor.options.collaboratorCheckIntervalMs);
return () => clearInterval(interval);
}, [editor]);
if (latestPresence) {
rLastActivityTimestamp.current = latestPresence.lastActivityTimestamp ?? Infinity;
}
return state;
}
//# sourceMappingURL=LiveCollaborators.js.map