@infinite-canvas-tutorial/webcomponents
Version:
WebComponents UI implementation
207 lines • 8.44 kB
JavaScript
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _API_canvasEntity, _API_idEntityMap, _API_history, _API_store;
import { Camera, Canvas, Children, Cursor, serializedNodesToEntities, Transform, Visibility, Name, } from '@infinite-canvas-tutorial/ecs';
import { Event } from './event';
import { Container } from './components';
import { History, Store, StoreIncrementEvent, } from './history';
import { getDefaultAppState } from './context';
import { arrayToMap } from './utils';
/**
* Since the canvas is created in the system, we need to store them here for later use.
*/
export const pendingCanvases = [];
/**
* Expose the API to the outside world.
*
* @see https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/excalidraw-api
*/
export class API {
constructor(element, commands) {
this.element = element;
this.commands = commands;
_API_canvasEntity.set(this, void 0);
_API_idEntityMap.set(this, void 0);
_API_history.set(this, new History());
_API_store.set(this, new Store());
this.appState = getDefaultAppState();
__classPrivateFieldGet(this, _API_store, "f").onStoreIncrementEmitter.on(StoreIncrementEvent, (event) => {
__classPrivateFieldGet(this, _API_history, "f").record(event.elementsChange, event.appStateChange);
});
}
/**
* Create a new canvas.
*/
createCanvas(canvasProps) {
const canvas = this.commands.spawn(new Canvas(canvasProps)).id();
canvas.add(Container, { element: this.element });
__classPrivateFieldSet(this, _API_canvasEntity, canvas.hold(), "f");
}
/**
* Create a new camera.
*/
createCamera(cameraProps) {
const { zoom } = cameraProps;
this.commands.spawn(new Camera({
canvas: __classPrivateFieldGet(this, _API_canvasEntity, "f"),
}), new Transform({
scale: {
x: 1 / zoom,
y: 1 / zoom,
},
}));
}
/**
* Create a new landmark.
*/
createLandmark() { }
/**
* Go to a landmark.
*/
gotoLandmark() { }
/**
* ZoomLevel system will handle the zoom level.
*/
zoomTo(zoom) {
this.element.dispatchEvent(new CustomEvent(Event.ZOOM_TO, {
detail: {
zoom,
},
}));
}
resizeCanvas(width, height) {
Object.assign(__classPrivateFieldGet(this, _API_canvasEntity, "f").write(Canvas), {
width,
height,
});
this.element.dispatchEvent(new CustomEvent(Event.RESIZED, {
detail: { width, height },
}));
}
setPen(pen) {
Object.assign(__classPrivateFieldGet(this, _API_canvasEntity, "f").write(Canvas), {
pen,
});
const prevAppState = this.getAppState();
this.setAppState(Object.assign(Object.assign({}, prevAppState), { penbarSelected: [pen] }));
this.element.dispatchEvent(new CustomEvent(Event.PEN_CHANGED, {
detail: { selected: [pen] },
}));
}
setTaskbars(selected) {
const prevAppState = this.getAppState();
this.setAppState(Object.assign(Object.assign({}, prevAppState), { taskbarSelected: selected }));
this.element.dispatchEvent(new CustomEvent(Event.TASK_CHANGED, {
detail: { selected },
}));
}
/**
* @see https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/excalidraw-api#setcursor
*/
setCursor(cursor) {
if (!__classPrivateFieldGet(this, _API_canvasEntity, "f").has(Cursor)) {
__classPrivateFieldGet(this, _API_canvasEntity, "f").add(Cursor);
}
Object.assign(__classPrivateFieldGet(this, _API_canvasEntity, "f").write(Cursor), {
value: cursor,
});
}
/**
* Delete Canvas component
*/
destroy() {
__classPrivateFieldGet(this, _API_canvasEntity, "f").delete();
this.element.dispatchEvent(new CustomEvent(Event.DESTROY));
}
/**
* Select nodes.
*/
selectNodes(selected, preserveSelection = false) {
// TODO: select nodes in the canvas.
const prevAppState = this.getAppState();
this.setAppState(Object.assign(Object.assign({}, prevAppState), { layersSelected: preserveSelection
? [...prevAppState.layersSelected, ...selected]
: selected }));
this.element.dispatchEvent(new CustomEvent(Event.SELECTED_NODES_CHANGED, {
detail: { selected, preserveSelection },
}));
}
/**
* If diff is provided, no need to calculate diffs.
*/
updateNode(node, diff) {
const entity = __classPrivateFieldGet(this, _API_idEntityMap, "f").get(node.id).id();
let updated = node;
if (diff) {
const { name, visibility } = diff;
if (name) {
entity.write(Name).value = name;
}
if (visibility) {
entity.write(Visibility).value = visibility;
}
updated = Object.assign(Object.assign({}, node), diff);
}
const nodes = this.getNodes();
const index = nodes.findIndex((n) => n.id === updated.id);
if (index !== -1) {
nodes[index] = updated;
this.setNodes(nodes);
}
this.element.dispatchEvent(new CustomEvent(Event.NODE_UPDATED, {
detail: {
node: updated,
},
}));
}
/**
* Update the scene with new nodes.
* It will calculate diffs and only update the changed nodes.
*
* @see https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/excalidraw-api#updatescene
*/
updateNodes(nodes) {
this.nodes = nodes;
const { cameras } = __classPrivateFieldGet(this, _API_canvasEntity, "f").read(Canvas);
if (cameras.length === 0) {
throw new Error('No camera found');
}
// TODO: Support multiple cameras.
const camera = cameras[0];
const cameraEntityCommands = this.commands.entity(camera);
// TODO: Calculate diffs and only update the changed nodes.
const { entities, idEntityMap } = serializedNodesToEntities(nodes, this.commands);
__classPrivateFieldSet(this, _API_idEntityMap, idEntityMap, "f");
this.commands.execute();
entities.forEach((entity) => {
// Append roots to the camera.
if (!entity.has(Children)) {
cameraEntityCommands.appendChild(this.commands.entity(entity));
}
});
this.commands.execute();
this.setNodes(nodes);
this.element.dispatchEvent(new CustomEvent(Event.NODES_UPDATED, {
detail: {
nodes,
},
}));
}
undo() {
__classPrivateFieldGet(this, _API_history, "f").undo(arrayToMap(this.getNodes()), this.getAppState(), __classPrivateFieldGet(this, _API_store, "f").snapshot);
}
redo() {
__classPrivateFieldGet(this, _API_history, "f").redo(arrayToMap(this.getNodes()), this.getAppState(), __classPrivateFieldGet(this, _API_store, "f").snapshot);
}
}
_API_canvasEntity = new WeakMap(), _API_idEntityMap = new WeakMap(), _API_history = new WeakMap(), _API_store = new WeakMap();
//# sourceMappingURL=API.js.map