UNPKG

tandem-front-end

Version:

Visual editor for web components

651 lines 27.6 kB
"use strict"; var __assign = (this && this.__assign) || Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); var tandem_common_1 = require("tandem-common"); var paperclip_1 = require("paperclip"); var lodash_1 = require("lodash"); var paperclip_2 = require("paperclip"); var ToolType; (function (ToolType) { ToolType[ToolType["TEXT"] = 0] = "TEXT"; ToolType[ToolType["POINTER"] = 1] = "POINTER"; ToolType[ToolType["COMPONENT"] = 2] = "COMPONENT"; ToolType[ToolType["ELEMENT"] = 3] = "ELEMENT"; })(ToolType = exports.ToolType || (exports.ToolType = {})); var FrameMode; (function (FrameMode) { FrameMode["PREVIEW"] = "preview"; FrameMode["DESIGN"] = "design"; })(FrameMode = exports.FrameMode || (exports.FrameMode = {})); exports.REGISTERED_COMPONENT = "REGISTERED_COMPONENT"; var SyntheticVisibleNodeMetadataKeys; (function (SyntheticVisibleNodeMetadataKeys) { SyntheticVisibleNodeMetadataKeys["EDITING_LABEL"] = "editingLabel"; SyntheticVisibleNodeMetadataKeys["EXPANDED"] = "expanded"; })(SyntheticVisibleNodeMetadataKeys = exports.SyntheticVisibleNodeMetadataKeys || (exports.SyntheticVisibleNodeMetadataKeys = {})); var InsertFileType; (function (InsertFileType) { InsertFileType[InsertFileType["FILE"] = 0] = "FILE"; InsertFileType[InsertFileType["DIRECTORY"] = 1] = "DIRECTORY"; })(InsertFileType = exports.InsertFileType || (exports.InsertFileType = {})); exports.updateRootState = function (properties, root) { return (__assign({}, root, properties)); }; exports.deselectRootProjectFiles = function (state) { return exports.updateRootState({ selectedFileNodeIds: [] }, state); }; exports.persistRootState = function (persistPaperclipState, state, newSelectionScope) { var oldState = state; var oldGraph = state.graph; state = exports.keepActiveFileOpen(exports.updateRootState(persistPaperclipState(state), state)); var modifiedDeps = paperclip_2.getModifiedDependencies(state.graph, oldGraph); state = addHistory(state, modifiedDeps.map(function (dep) { return oldGraph[dep.uri]; })); state = modifiedDeps.reduce(function (state, dep) { return setOpenFileContent(dep, state); }, state); return state; }; var getUpdatedSyntheticVisibleNodes = function (newState, oldState, scope) { var MAX_DEPTH = 0; var oldScope = paperclip_1.getSyntheticNodeById(scope.id, oldState.documents); var newScope = paperclip_1.getSyntheticNodeById(scope.id, newState.documents); var newSyntheticVisibleNodes = []; var model = oldScope; paperclip_1.diffSyntheticNode(oldScope, newScope).forEach(function (ot) { var target = tandem_common_1.getTreeNodeFromPath(ot.nodePath, model); model = paperclip_1.patchSyntheticNode([ot], model); if (ot.nodePath.length > MAX_DEPTH) { return; } // TODO - will need to check if new parent is not in an instance of a component. // Will also need to consider child overrides though. if (ot.type === paperclip_1.SyntheticOperationalTransformType.INSERT_CHILD) { newSyntheticVisibleNodes.push(ot.child); } else if (ot.type === paperclip_1.SyntheticOperationalTransformType.SET_PROPERTY && ot.name === "source") { newSyntheticVisibleNodes.push(target); } }); return lodash_1.uniq(newSyntheticVisibleNodes); }; exports.selectInsertedSyntheticVisibleNodes = function (oldState, newState, scope) { return exports.setSelectedSyntheticVisibleNodeIds.apply(void 0, [newState].concat(getUpdatedSyntheticVisibleNodes(newState, oldState, scope).map(function (node) { return node.id; }))); }; var setOpenFileContent = function (dep, state) { return exports.updateOpenFile({ temporary: false, newContent: new Buffer(JSON.stringify(dep.content, null, 2), "utf8") }, dep.uri, state); }; var addHistory = function (root, modifiedDeps) { return modifiedDeps.reduce(function (state, dep) { var _a; var history = state.history[dep.uri] || { index: 0, snapshots: tandem_common_1.EMPTY_ARRAY }; var snapshots = history.snapshots.slice(0, history.index).concat([dep]); return exports.updateRootState({ history: (_a = {}, _a[dep.uri] = { index: snapshots.length, snapshots: snapshots }, _a) }, state); }, root); }; var moveDependencyRecordHistory = function (uri, pos, root) { var _a; var record = root.history[uri]; if (!record) { return root; } var index = Math.max(0, Math.min(record.snapshots.length, record.index + pos)); // if index exceeds snapshot count, then we're at the end. var dep = record.snapshots[index] || root.graph[uri]; root = exports.updateRootState({ history: (_a = {}, _a[uri] = __assign({}, record, { index: index }), _a), selectedFileNodeIds: [], selectedNodeIds: [], hoveringNodeIds: [] }, root); root = setOpenFileContent(dep, root); root = paperclip_2.replaceDependency(dep, root); return root; }; var DEFAULT_CANVAS = { backgroundColor: "#EEE", translate: { left: 0, top: 0, zoom: 1 } }; exports.undo = function (root) { return root.editorWindows.reduce(function (state, editor) { return moveDependencyRecordHistory(editor.activeFilePath, -1, root); }, root); }; exports.redo = function (root) { return root.editorWindows.reduce(function (state, editor) { return moveDependencyRecordHistory(editor.activeFilePath, 1, root); }, root); }; exports.getOpenFile = function (uri, state) { return state.openFiles.find(function (openFile) { return openFile.uri === uri; }); }; exports.getOpenFilesWithContent = function (state) { return state.openFiles.filter(function (openFile) { return openFile.newContent; }); }; exports.updateOpenFileContent = function (uri, newContent, state) { return exports.updateOpenFile({ temporary: false, newContent: newContent }, uri, state); }; exports.getActiveEditorWindow = function (state) { return exports.getEditorWithActiveFileUri(state.activeEditorFilePath, state); }; exports.updateOpenFile = function (properties, uri, state) { var file = exports.getOpenFile(uri, state); if (!file) { state = exports.addOpenFile(uri, false, state); return exports.updateOpenFile(properties, uri, state); } var index = state.openFiles.indexOf(file); return exports.updateRootState({ openFiles: tandem_common_1.arraySplice(state.openFiles, index, 1, __assign({}, file, properties)) }, state); }; exports.upsertOpenFile = function (uri, temporary, state) { var file = exports.getOpenFile(uri, state); if (file) { if (file.temporary !== temporary) { return exports.updateOpenFile({ temporary: temporary }, uri, state); } return state; } return exports.addOpenFile(uri, temporary, state); }; exports.getEditorWindowWithFileUri = function (uri, state) { return state.editorWindows.find(function (window) { return window.tabUris.indexOf(uri) !== -1; }); }; exports.getEditorWithActiveFileUri = function (uri, state) { return state.editorWindows.find(function (editor) { return editor.activeFilePath === uri; }); }; exports.openSecondEditor = function (uri, state) { var editor = exports.getEditorWindowWithFileUri(uri, state); var i = state.editorWindows.indexOf(editor); if (i === 1) { return exports.openEditorFileUri(uri, state); } if (i === 0 && editor.tabUris.length === 1) { return state; } var newTabUris = tandem_common_1.arraySplice(editor.tabUris, editor.tabUris.indexOf(uri), 1); state = __assign({}, state, { editorWindows: tandem_common_1.arraySplice(state.editorWindows, i, 1, __assign({}, editor, { tabUris: newTabUris, activeFilePath: editor.activeFilePath === uri ? newTabUris[newTabUris.length - 1] : editor.activeFilePath })) }); if (state.editorWindows.length === 1) { state = __assign({}, state, { editorWindows: state.editorWindows.concat([ { tabUris: [], activeFilePath: null } ]) }); } var secondEditor = state.editorWindows[1]; return __assign({}, state, { editors: tandem_common_1.arraySplice(state.editorWindows, state.editorWindows.indexOf(secondEditor), 1, __assign({}, secondEditor, { tabUris: secondEditor.tabUris.concat([uri]), activeFilePath: uri })) }); }; exports.getSyntheticWindowBounds = tandem_common_1.memoize(function (uri, state) { var frames = paperclip_1.getFramesByDependencyUri(uri, state.frames, state.documents, state.graph); if (!window) return tandem_common_1.createZeroBounds(); return tandem_common_1.mergeBounds.apply(void 0, (frames || tandem_common_1.EMPTY_ARRAY).map(function (frame) { return frame.bounds; })); }); exports.isImageMimetype = function (mimeType) { return /^image\//.test(mimeType); }; exports.openEditorFileUri = function (uri, state) { var editor = exports.getEditorWindowWithFileUri(uri, state) || state.editorWindows[0]; return __assign({}, state, { hoveringNodeIds: [], selectedNodeIds: [], activeEditorFilePath: uri, editorWindows: editor ? tandem_common_1.arraySplice(state.editorWindows, state.editorWindows.indexOf(editor), 1, __assign({}, editor, { tabUris: editor.tabUris.indexOf(uri) === -1 ? editor.tabUris.concat([uri]) : editor.tabUris, activeFilePath: uri })) : [ { tabUris: [uri], activeFilePath: uri } ] }); }; var queuePreview = function (uri, state) { return state; }; exports.shiftActiveEditorTab = function (delta, state) { var editor = exports.getActiveEditorWindow(state); // nothing open if (!editor) { return state; } var index = editor.tabUris.indexOf(editor.activeFilePath); var newIndex = index + delta; if (newIndex < 0) { newIndex = editor.tabUris.length + delta; } else if (newIndex >= editor.tabUris.length) { newIndex = -1 + delta; } newIndex = lodash_1.clamp(newIndex, 0, editor.tabUris.length - 1); return exports.openEditorFileUri(editor.tabUris[newIndex], state); }; var removeEditorWindow = function (_a, state) { var activeFilePath = _a.activeFilePath; var editor = exports.getEditorWithActiveFileUri(activeFilePath, state); return __assign({}, state, { editorWindows: tandem_common_1.arraySplice(state.editorWindows, state.editorWindows.indexOf(editor), 1) }); }; exports.closeFile = function (uri, state) { var editorWindow = exports.getEditorWindowWithFileUri(uri, state); if (editorWindow.tabUris.length === 1) { state = removeEditorWindow(editorWindow, state); } else { state = exports.updateEditorWindow({ tabUris: editorWindow.tabUris.filter(function (furi) { return furi !== uri; }) }, uri, state); } state = exports.updateRootState({ openFiles: state.openFiles.filter(function (openFile) { return openFile.uri !== uri; }) }, state); state = exports.setNextOpenFile(state); return state; }; exports.setNextOpenFile = function (state) { var hasOpenFile = state.openFiles.find(function (openFile) { return Boolean(exports.getEditorWithActiveFileUri(openFile.uri, state)); }); if (hasOpenFile) { return state; } state = __assign({}, state, { hoveringNodeIds: [], selectedNodeIds: [] }); if (state.openFiles.length) { state = exports.openEditorFileUri(state.openFiles[0].uri, state); } return state; }; exports.removeTemporaryOpenFiles = function (state) { return __assign({}, state, { openFiles: state.openFiles.filter(function (openFile) { return !openFile.temporary; }) }); }; exports.openSyntheticVisibleNodeOriginFile = function (node, state) { var sourceNode = paperclip_1.getSyntheticSourceNode(node, state.graph); var uri = paperclip_1.getPCNodeDependency(sourceNode.id, state.graph).uri; state = exports.openEditorFileUri(uri, state); var instance = paperclip_1.findRootInstanceOfPCNode(sourceNode, state.documents); state = exports.setActiveFilePath(uri, state); state = exports.setSelectedSyntheticVisibleNodeIds(state, instance.id); return state; }; exports.addOpenFile = function (uri, temporary, state) { var file = exports.getOpenFile(uri, state); if (file) { return state; } state = exports.removeTemporaryOpenFiles(state); return __assign({}, state, { openFiles: state.openFiles.concat([ { uri: uri, temporary: temporary, canvas: DEFAULT_CANVAS } ]) }); }; // export const getInsertedWindowElementIds = ( // oldWindow: SyntheticWindow, // targetFrameId: string, // newBrowser: PCEditorState // ): string[] => { // const elementIds = oldWindow.documents // .filter(document => !targetFrameId || document.id === targetFrameId) // .reduce((nodeIds, oldFrame) => { // return [ // ...nodeIds, // ...getInsertedFrameElementIds(oldFrame, newBrowser) // ]; // }, []); // const newWindow = newBrowser.windows.find( // window => window.location === oldWindow.location // ); // return [ // ...elementIds, // ...newWindow.documents // .filter(document => { // const isInserted = // oldWindow.documents.find(oldFrame => { // return oldFrame.id === document.id; // }) == null; // return isInserted; // }) // .map(document => document.root.id) // ]; // }; // export const getInsertedFrameElementIds = ( // oldFrame: Frame, // newBrowser: PCEditorState // ): string[] => { // const newFrame = getFrameById(oldFrame.id, newBrowser); // if (!newFrame) { // return []; // } // const oldIds = Object.keys(oldFrame.nativeNodeMap); // const newIds = Object.keys(newFrame.nativeNodeMap); // return pull(newIds, ...oldIds); // }; exports.keepActiveFileOpen = function (state) { return __assign({}, state, { openFiles: state.openFiles.map(function (openFile) { return (__assign({}, openFile, { temporary: false })); }) }); }; // export const updateRootStateSyntheticWindowFrame = ( // documentId: string, // properties: Partial<Frame>, // root: RootState // ) => { // const window = getFrameWindow(documentId, root); // const document = getFrameById(documentId, root); // return updateRootState( // { // browser: updateSyntheticWindow( // window.location, // { // documents: arraySplice( // window.documents, // window.documents.indexOf(document), // 1, // { // ...document, // ...properties // } // ) // }, // root // ) // }, // root // ); // }; exports.setRootStateSyntheticVisibleNodeExpanded = function (nodeId, value, state) { var node = paperclip_1.getSyntheticNodeById(nodeId, state.documents); var document = paperclip_1.getSyntheticVisibleNodeDocument(node.id, state.documents); state = paperclip_1.updateSyntheticDocument(setSyntheticVisibleNodeExpanded(node, value, document), document, state); return state; }; var setSyntheticVisibleNodeExpanded = function (node, value, document) { var path = tandem_common_1.getTreeNodePath(node.id, document); var updater = function (node) { var _a; return __assign({}, node, { metadata: __assign({}, node.metadata, (_a = {}, _a[SyntheticVisibleNodeMetadataKeys.EXPANDED] = value, _a)) }); }; return (value ? tandem_common_1.updateNestedNodeTrail(path, document, updater) : tandem_common_1.updateNestedNode(node, document, updater)); }; exports.setRootStateSyntheticVisibleNodeLabelEditing = function (nodeId, value, state) { var _a; var node = paperclip_1.getSyntheticNodeById(nodeId, state.documents); var document = paperclip_1.getSyntheticVisibleNodeDocument(node.id, state.documents); state = paperclip_1.updateSyntheticDocument(paperclip_1.updateSyntheticVisibleNodeMetadata((_a = {}, _a[SyntheticVisibleNodeMetadataKeys.EDITING_LABEL] = value, _a), node, document), document, state); return state; }; exports.setRootStateFileNodeExpanded = function (nodeId, value, state) { return exports.updateRootState({ projectDirectory: tandem_common_1.updateNestedNode(tandem_common_1.getNestedTreeNodeById(nodeId, state.projectDirectory), state.projectDirectory, function (child) { return (__assign({}, child, { expanded: value })); }) }, state); }; exports.updateEditorWindow = function (properties, uri, root) { var window = exports.getEditorWindowWithFileUri(uri, root); var i = root.editorWindows.indexOf(window); return exports.updateRootState({ editorWindows: tandem_common_1.arraySplice(root.editorWindows, i, 1, __assign({}, window, properties)) }, root); }; var INITIAL_ZOOM_PADDING = 50; exports.centerEditorCanvas = function (state, editorFileUri, innerBounds, smooth, zoomOrZoomToFit) { if (smooth === void 0) { smooth = false; } if (zoomOrZoomToFit === void 0) { zoomOrZoomToFit = true; } if (!innerBounds) { var frames_1 = paperclip_1.getFramesByDependencyUri(editorFileUri, state.frames, state.documents, state.graph); if (!frames_1.length) { return state; } innerBounds = exports.getSyntheticWindowBounds(editorFileUri, state); } // no windows loaded if (innerBounds.left + innerBounds.right + innerBounds.top + innerBounds.bottom === 0) { console.warn(" Cannot center when bounds has no size"); return exports.updateOpenFileCanvas({ translate: { left: 0, top: 0, zoom: 1 } }, editorFileUri, state); } var editorWindow = exports.getEditorWindowWithFileUri(editorFileUri, state); var openFile = exports.getOpenFile(editorFileUri, state); var container = editorWindow.container; if (!container) { console.warn("cannot center canvas without a container"); return state; } var translate = openFile.canvas.translate; var _a = container.getBoundingClientRect(), width = _a.width, height = _a.height; var innerSize = tandem_common_1.getBoundsSize(innerBounds); var centered = { left: -innerBounds.left + width / 2 - innerSize.width / 2, top: -innerBounds.top + height / 2 - innerSize.height / 2 }; var scale = typeof zoomOrZoomToFit === "boolean" ? Math.min((width - INITIAL_ZOOM_PADDING) / innerSize.width, (height - INITIAL_ZOOM_PADDING) / innerSize.height) : typeof zoomOrZoomToFit === "number" ? zoomOrZoomToFit : translate.zoom; state = exports.updateEditorWindow({ smooth: smooth }, editorFileUri, state); state = exports.updateOpenFileCanvas({ translate: tandem_common_1.centerTransformZoom(__assign({}, centered, { zoom: 1 }), { left: 0, top: 0, right: width, bottom: height }, Math.min(scale, 1)) }, editorFileUri, state); return state; }; exports.setActiveFilePath = function (newActiveFilePath, root) { if (exports.getEditorWithActiveFileUri(newActiveFilePath, root)) { return root; } root = exports.openEditorFileUri(newActiveFilePath, root); root = exports.addOpenFile(newActiveFilePath, true, root); root = exports.centerEditorCanvas(root, newActiveFilePath); return root; }; exports.updateOpenFileCanvas = function (properties, uri, root) { var openFile = exports.getOpenFile(uri, root); return exports.updateOpenFile({ canvas: __assign({}, openFile.canvas, properties) }, uri, root); }; exports.setInsertFile = function (type, state) { var file = tandem_common_1.getNestedTreeNodeById(state.selectedFileNodeIds[0] || state.projectDirectory.id, state.projectDirectory); return exports.updateRootState({ insertFileInfo: { type: type, directoryId: tandem_common_1.isDirectory(file) ? file.id : tandem_common_1.getParentTreeNode(file.id, state.projectDirectory).id } }, state); }; exports.setTool = function (toolType, root) { if (!root.editorWindows.length) { return root; } root = __assign({}, root, { selectedComponentId: null }); root = exports.updateRootState({ toolType: toolType }, root); root = exports.setSelectedSyntheticVisibleNodeIds(root); return root; }; exports.getActiveFrames = function (root) { return lodash_1.values(root.frames).filter(function (frame) { return root.editorWindows.some(function (editor) { return editor.activeFilePath === paperclip_1.getSyntheticDocumentDependencyUri(paperclip_1.getSyntheticVisibleNodeDocument(frame.contentNodeId, root.documents), root.graph); }); }); }; exports.getCanvasTranslate = function (canvas) { return canvas.translate; }; exports.getScaledMouseCanvasPosition = function (state, point) { var canvas = exports.getOpenFile(state.activeEditorFilePath, state).canvas; var translate = exports.getCanvasTranslate(canvas); var scaledPageX = (point.left - translate.left) / translate.zoom; var scaledPageY = (point.top - translate.top) / translate.zoom; return { left: scaledPageX, top: scaledPageY }; }; exports.getCanvasMouseTargetNodeId = function (state, event, filter) { return exports.getCanvasMouseTargetNodeIdFromPoint(state, { left: event.sourceEvent.pageX, top: event.sourceEvent.pageY }, filter); }; exports.getCanvasMouseTargetNodeIdFromPoint = function (state, point, filter) { var editor = exports.getActiveEditorWindow(state); var canvas = exports.getOpenFile(editor.activeFilePath, state).canvas; var translate = exports.getCanvasTranslate(canvas); var toolType = state.toolType; var scaledMousePos = exports.getScaledMouseCanvasPosition(state, point); var frame = exports.getFrameFromPoint(scaledMousePos, state); if (!frame) return null; var contentNode = paperclip_1.getSyntheticNodeById(frame.contentNodeId, state.documents); var scaledPageX = scaledMousePos.left, scaledPageY = scaledMousePos.top; var deadZone = exports.getSelectionBounds(state); var mouseX = scaledPageX - frame.bounds.left; var mouseY = scaledPageY - frame.bounds.top; var computedInfo = frame.computed || {}; var intersectingBounds = []; var intersectingBoundsMap = new Map(); var mouseFramePoint = { left: mouseX, top: mouseY }; for (var $id in computedInfo) { var bounds = computedInfo[$id].bounds; if (tandem_common_1.pointIntersectsBounds(mouseFramePoint, bounds) && !tandem_common_1.pointIntersectsBounds(scaledMousePos, deadZone) && (toolType == null || tandem_common_1.getNestedTreeNodeById($id, contentNode).name !== paperclip_1.PCSourceTagNames.TEXT) && (!filter || filter(tandem_common_1.getNestedTreeNodeById($id, contentNode)))) { intersectingBounds.push(bounds); intersectingBoundsMap.set(bounds, $id); } } if (!intersectingBounds.length) return null; var smallestBounds = tandem_common_1.getSmallestBounds.apply(void 0, intersectingBounds); return intersectingBoundsMap.get(smallestBounds); }; exports.getCanvasMouseFrame = function (state, event) { return exports.getFrameFromPoint(exports.getScaledMouseCanvasPosition(state, { left: event.sourceEvent.pageX, top: event.sourceEvent.pageY }), state); }; exports.getFrameFromPoint = function (point, state) { var activeFrames = exports.getActiveFrames(state); if (!activeFrames.length) return null; for (var j = activeFrames.length; j--;) { var frame = activeFrames[j]; if (tandem_common_1.pointIntersectsBounds(point, frame.bounds)) { return frame; } } }; exports.setSelectedSyntheticVisibleNodeIds = function (root) { var selectionIds = []; for (var _i = 1; _i < arguments.length; _i++) { selectionIds[_i - 1] = arguments[_i]; } var nodeIds = lodash_1.uniq(selectionIds.slice()).filter(Boolean); root = nodeIds.reduce(function (state, nodeId) { return exports.setRootStateSyntheticVisibleNodeExpanded(nodeId, true, root); }, root); root = exports.updateRootState({ selectedNodeIds: nodeIds }, root); return root; }; exports.setSelectedFileNodeIds = function (root) { var selectionIds = []; for (var _i = 1; _i < arguments.length; _i++) { selectionIds[_i - 1] = arguments[_i]; } var nodeIds = lodash_1.uniq(selectionIds.slice()); root = nodeIds.reduce(function (state, nodeId) { return exports.setRootStateFileNodeExpanded(nodeId, true, root); }, root); root = exports.updateRootState({ selectedFileNodeIds: nodeIds }, root); return root; }; exports.setHoveringSyntheticVisibleNodeIds = function (root) { var selectionIds = []; for (var _i = 1; _i < arguments.length; _i++) { selectionIds[_i - 1] = arguments[_i]; } return exports.updateRootState({ hoveringNodeIds: lodash_1.uniq(selectionIds.slice()) }, root); }; // export const updateRootSyntheticPosition = ( // position: Point, // nodeId: string, // root: RootState // ) => // updateRootState( // { // browser: updateSyntheticItemPosition(position, nodeId, root) // }, // root // ); // export const updateRootSyntheticBounds = ( // bounds: Bounds, // nodeId: string, // root: RootState // ) => // updateRootState( // { // browser: updateSyntheticItemBounds(bounds, nodeId, root) // }, // root // ); exports.getBoundedSelection = tandem_common_1.memoize(function (root) { return root.selectedNodeIds.filter(function (nodeId) { return paperclip_1.getSyntheticVisibleNodeRelativeBounds(paperclip_1.getSyntheticNodeById(nodeId, root.documents), root.frames); }); }); exports.getSelectionBounds = tandem_common_1.memoize(function (root) { return tandem_common_1.mergeBounds.apply(void 0, exports.getBoundedSelection(root).map(function (nodeId) { return paperclip_1.getSyntheticVisibleNodeRelativeBounds(paperclip_1.getSyntheticNodeById(nodeId, root.documents), root.frames); })); }); exports.isSelectionMovable = tandem_common_1.memoize(function (root) { return !root.selectedNodeIds.some(function (nodeId) { var node = paperclip_1.getSyntheticNodeById(nodeId, root.documents); return !paperclip_1.isSyntheticVisibleNodeMovable(node); }); }); exports.isSelectionResizable = tandem_common_1.memoize(function (root) { return !root.selectedNodeIds.some(function (nodeId) { var node = paperclip_1.getSyntheticNodeById(nodeId, root.documents); return !paperclip_1.isSyntheticVisibleNodeResizable(node); }); }); //# sourceMappingURL=index.js.map