@mocanvas/editor 4.0.2 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +8 -2
- package/MIGRATION.md +48 -22
- package/README.md +5 -0
- package/UI.md +24 -2
- package/dist/index.d.ts +322 -41
- package/dist/index.js +449 -153
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { atom, computed, unsafe__withoutCapture, transact, react } from '@mocanvas/state';
|
|
2
2
|
export { AtomMap, atom, computed, react, reactor, transact, transaction } from '@mocanvas/state';
|
|
3
|
-
import { createRecordType, isIndexKey, createMigrationIds, uniqueId, isRecordsDiffEmpty, squashRecordDiffs, reverseRecordsDiff,
|
|
3
|
+
import { createRecordType, isIndexKey, createMigrationIds, uniqueId, isRecordsDiffEmpty, squashRecordDiffs, reverseRecordsDiff, sortByIndex, getIndexAbove, ZERO_INDEX_KEY, getIndexBetween, getIndexBelow, getIndicesAbove, indexKeyToZKey, parseMigrationId, createMigrationSequence, StoreSchema, Store } from '@mocanvas/store';
|
|
4
4
|
export { ZERO_INDEX_KEY, createComputedCache, getGraphemeLength, getGraphemes, getIndexAbove, getIndexBelow, getIndexBetween, getIndices, getIndicesAbove, getIndicesBelow, getIndicesBetween, iterateGraphemes, sortByIndex } from '@mocanvas/store';
|
|
5
5
|
import { PATH_OP, FLAG, GEO_FLAG, EngineBridge, VERTEX_FLOATS, BATCH_WORDS, readClip } from '@mocanvas/wasm';
|
|
6
6
|
export { EngineBridge, FLAG, GEO_FLAG, GEO_KIND, PATH_OP, getLoadedEngine, loadEngine, loadEngineSync } from '@mocanvas/wasm';
|
|
@@ -2483,6 +2483,8 @@ var DOCUMENT_ID = DocumentRecordType.createId("document");
|
|
|
2483
2483
|
var PageRecordType = createRecordType("page", { scope: "document" }).withDefaultProperties(() => ({
|
|
2484
2484
|
meta: {}
|
|
2485
2485
|
}));
|
|
2486
|
+
var DEFAULT_PAGE_ID = PageRecordType.createId("page");
|
|
2487
|
+
var FIRST_PAGE_INDEX = "a1";
|
|
2486
2488
|
function isPage(record) {
|
|
2487
2489
|
return record?.typeName === "page";
|
|
2488
2490
|
}
|
|
@@ -3073,6 +3075,51 @@ function sourceSize(source) {
|
|
|
3073
3075
|
const s = source;
|
|
3074
3076
|
return [s.naturalWidth || s.videoWidth || s.width || 0, s.naturalHeight || s.videoHeight || s.height || 0];
|
|
3075
3077
|
}
|
|
3078
|
+
var PRESENCE_COLORS = [
|
|
3079
|
+
"#e0575b",
|
|
3080
|
+
"#ef8b3a",
|
|
3081
|
+
"#d8a72e",
|
|
3082
|
+
"#4f9d55",
|
|
3083
|
+
"#2fa39a",
|
|
3084
|
+
"#3f86d8",
|
|
3085
|
+
"#7a63d8",
|
|
3086
|
+
"#c05aa8"
|
|
3087
|
+
];
|
|
3088
|
+
function randomPresenceColor() {
|
|
3089
|
+
return PRESENCE_COLORS[Math.floor(Math.random() * PRESENCE_COLORS.length)];
|
|
3090
|
+
}
|
|
3091
|
+
var InstancePresenceRecordType = createRecordType("instance_presence", {
|
|
3092
|
+
scope: "presence"
|
|
3093
|
+
}).withDefaultProperties(() => ({
|
|
3094
|
+
userName: "",
|
|
3095
|
+
color: PRESENCE_COLORS[0],
|
|
3096
|
+
cursor: { x: 0, y: 0, type: "default", rotation: 0 },
|
|
3097
|
+
camera: { x: 0, y: 0, z: 1 },
|
|
3098
|
+
selectedShapeIds: [],
|
|
3099
|
+
brush: null,
|
|
3100
|
+
scribbles: [],
|
|
3101
|
+
followingUserId: null,
|
|
3102
|
+
lastActivityTimestamp: 0,
|
|
3103
|
+
chatMessage: "",
|
|
3104
|
+
meta: {}
|
|
3105
|
+
}));
|
|
3106
|
+
function isInstancePresenceId(id) {
|
|
3107
|
+
return id.startsWith("instance_presence:");
|
|
3108
|
+
}
|
|
3109
|
+
function createUserPreferences(init = {}) {
|
|
3110
|
+
const id = init.id ?? `user:${uniqueId(12)}`;
|
|
3111
|
+
const state = atom("editor.user", {
|
|
3112
|
+
name: init.name ?? `User ${id.slice(-4)}`,
|
|
3113
|
+
color: init.color ?? randomPresenceColor()
|
|
3114
|
+
});
|
|
3115
|
+
return {
|
|
3116
|
+
getId: () => id,
|
|
3117
|
+
getName: () => state.get().name,
|
|
3118
|
+
getColor: () => state.get().color,
|
|
3119
|
+
setName: (name) => state.update((s) => ({ ...s, name })),
|
|
3120
|
+
setColor: (color) => state.update((s) => ({ ...s, color }))
|
|
3121
|
+
};
|
|
3122
|
+
}
|
|
3076
3123
|
|
|
3077
3124
|
// src/validation/validator.ts
|
|
3078
3125
|
function formatValidationPath(path) {
|
|
@@ -3514,53 +3561,6 @@ function createMemoryUserStore(users, currentUserId) {
|
|
|
3514
3561
|
resolve: (userId) => byId.get(userId) ?? null
|
|
3515
3562
|
};
|
|
3516
3563
|
}
|
|
3517
|
-
var PRESENCE_COLORS = [
|
|
3518
|
-
"#e0575b",
|
|
3519
|
-
"#ef8b3a",
|
|
3520
|
-
"#d8a72e",
|
|
3521
|
-
"#4f9d55",
|
|
3522
|
-
"#2fa39a",
|
|
3523
|
-
"#3f86d8",
|
|
3524
|
-
"#7a63d8",
|
|
3525
|
-
"#c05aa8"
|
|
3526
|
-
];
|
|
3527
|
-
function randomPresenceColor() {
|
|
3528
|
-
return PRESENCE_COLORS[Math.floor(Math.random() * PRESENCE_COLORS.length)];
|
|
3529
|
-
}
|
|
3530
|
-
var InstancePresenceRecordType = createRecordType("instance_presence", {
|
|
3531
|
-
scope: "presence"
|
|
3532
|
-
}).withDefaultProperties(() => ({
|
|
3533
|
-
userName: "",
|
|
3534
|
-
color: PRESENCE_COLORS[0],
|
|
3535
|
-
cursor: { x: 0, y: 0, type: "default", rotation: 0 },
|
|
3536
|
-
camera: { x: 0, y: 0, z: 1 },
|
|
3537
|
-
selectedShapeIds: [],
|
|
3538
|
-
brush: null,
|
|
3539
|
-
scribbles: [],
|
|
3540
|
-
followingUserId: null,
|
|
3541
|
-
lastActivityTimestamp: 0,
|
|
3542
|
-
chatMessage: "",
|
|
3543
|
-
meta: {}
|
|
3544
|
-
}));
|
|
3545
|
-
function isInstancePresenceId(id) {
|
|
3546
|
-
return id.startsWith("instance_presence:");
|
|
3547
|
-
}
|
|
3548
|
-
function createUserPreferences(init = {}) {
|
|
3549
|
-
const id = init.id ?? `user:${uniqueId(12)}`;
|
|
3550
|
-
const state = atom("editor.user", {
|
|
3551
|
-
name: init.name ?? `User ${id.slice(-4)}`,
|
|
3552
|
-
color: init.color ?? randomPresenceColor()
|
|
3553
|
-
});
|
|
3554
|
-
return {
|
|
3555
|
-
getId: () => id,
|
|
3556
|
-
getName: () => state.get().name,
|
|
3557
|
-
getColor: () => state.get().color,
|
|
3558
|
-
setName: (name) => state.update((s) => ({ ...s, name })),
|
|
3559
|
-
setColor: (color) => state.update((s) => ({ ...s, color }))
|
|
3560
|
-
};
|
|
3561
|
-
}
|
|
3562
|
-
|
|
3563
|
-
// src/user/userPreferences.ts
|
|
3564
3564
|
var DEFAULT_PRESENCE_COLOR = PRESENCE_COLORS[0];
|
|
3565
3565
|
var USER_PREFERENCES_DEFAULTS = {
|
|
3566
3566
|
name: "",
|
|
@@ -3572,7 +3572,8 @@ var USER_PREFERENCES_DEFAULTS = {
|
|
|
3572
3572
|
isWrapMode: false,
|
|
3573
3573
|
isDynamicSizeMode: false,
|
|
3574
3574
|
isPasteAtCursorMode: false,
|
|
3575
|
-
areKeyboardShortcutsEnabled: true
|
|
3575
|
+
areKeyboardShortcutsEnabled: true,
|
|
3576
|
+
isEnhancedA11yMode: false
|
|
3576
3577
|
};
|
|
3577
3578
|
function getFreshUserPreferences() {
|
|
3578
3579
|
return { id: createUserId(), color: randomPresenceColor() };
|
|
@@ -3621,8 +3622,19 @@ var UserPreferencesManager = class {
|
|
|
3621
3622
|
getLocale() {
|
|
3622
3623
|
return this.getUserPreferences().locale ?? USER_PREFERENCES_DEFAULTS.locale;
|
|
3623
3624
|
}
|
|
3625
|
+
/**
|
|
3626
|
+
* How fast the editor animates; `0` means "do not animate".
|
|
3627
|
+
*
|
|
3628
|
+
* A user who has expressed no preference inherits the operating system's,
|
|
3629
|
+
* the same way `colorScheme: "system"` does. Reduced motion is an
|
|
3630
|
+
* accessibility setting people set once, for every application, and an
|
|
3631
|
+
* editor that ignored it until it was told a second time would be reading
|
|
3632
|
+
* the setting and then disregarding it.
|
|
3633
|
+
*/
|
|
3624
3634
|
getAnimationSpeed() {
|
|
3625
|
-
|
|
3635
|
+
const own = this.getUserPreferences().animationSpeed;
|
|
3636
|
+
if (own !== void 0) return own;
|
|
3637
|
+
return prefersReducedMotion() ? 0 : USER_PREFERENCES_DEFAULTS.animationSpeed;
|
|
3626
3638
|
}
|
|
3627
3639
|
getEdgeScrollSpeed() {
|
|
3628
3640
|
return this.getUserPreferences().edgeScrollSpeed ?? USER_PREFERENCES_DEFAULTS.edgeScrollSpeed;
|
|
@@ -3647,6 +3659,9 @@ var UserPreferencesManager = class {
|
|
|
3647
3659
|
getIsPasteAtCursorMode() {
|
|
3648
3660
|
return this.getUserPreferences().isPasteAtCursorMode ?? USER_PREFERENCES_DEFAULTS.isPasteAtCursorMode;
|
|
3649
3661
|
}
|
|
3662
|
+
getIsEnhancedA11yMode() {
|
|
3663
|
+
return this.getUserPreferences().isEnhancedA11yMode ?? USER_PREFERENCES_DEFAULTS.isEnhancedA11yMode;
|
|
3664
|
+
}
|
|
3650
3665
|
getAreKeyboardShortcutsEnabled() {
|
|
3651
3666
|
return this.getUserPreferences().areKeyboardShortcutsEnabled ?? USER_PREFERENCES_DEFAULTS.areKeyboardShortcutsEnabled;
|
|
3652
3667
|
}
|
|
@@ -3665,6 +3680,10 @@ function prefersDarkMode() {
|
|
|
3665
3680
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
3666
3681
|
return window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
3667
3682
|
}
|
|
3683
|
+
function prefersReducedMotion() {
|
|
3684
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
3685
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
3686
|
+
}
|
|
3668
3687
|
function useCurrentUser({ userPreferences, setUserPreferences: setUserPreferences2 }) {
|
|
3669
3688
|
const $preferences2 = useMemo(() => atom("react.userPreferences", userPreferences), []);
|
|
3670
3689
|
const setter = useRef(setUserPreferences2);
|
|
@@ -6664,6 +6683,8 @@ var EdgeScrollManager = class extends EditorManager {
|
|
|
6664
6683
|
const step = edgeScrollSpeed * ease * (elapsed / 16);
|
|
6665
6684
|
const offset = new Vec(-direction.x * step, -direction.y * step);
|
|
6666
6685
|
this.editor.pan(offset);
|
|
6686
|
+
const inputs = this.editor.inputs;
|
|
6687
|
+
inputs.currentPagePoint = this.editor.viewportToPage(inputs.currentScreenPoint);
|
|
6667
6688
|
return offset;
|
|
6668
6689
|
}
|
|
6669
6690
|
/**
|
|
@@ -6989,10 +7010,11 @@ var ScribbleManager = class extends EditorManager {
|
|
|
6989
7010
|
for (const item of [...this.items.values()]) {
|
|
6990
7011
|
const points = [...item.scribble.points];
|
|
6991
7012
|
let state = item.scribble.state;
|
|
7013
|
+
let moved = false;
|
|
6992
7014
|
if (item.next && (!item.prev || item.prev.x !== item.next.x || item.prev.y !== item.next.y)) {
|
|
6993
7015
|
points.push(item.next);
|
|
6994
7016
|
item.prev = item.next;
|
|
6995
|
-
|
|
7017
|
+
moved = true;
|
|
6996
7018
|
}
|
|
6997
7019
|
item.next = null;
|
|
6998
7020
|
if (state === "starting" && points.length > 1) state = "active";
|
|
@@ -7002,7 +7024,7 @@ var ScribbleManager = class extends EditorManager {
|
|
|
7002
7024
|
const shed = Math.max(1, Math.ceil(points.length * item.scribble.shrink));
|
|
7003
7025
|
if (points.length > 0) {
|
|
7004
7026
|
points.splice(0, shed);
|
|
7005
|
-
|
|
7027
|
+
moved = true;
|
|
7006
7028
|
}
|
|
7007
7029
|
}
|
|
7008
7030
|
if (points.length === 0 && (state === "stopping" || state === "paused")) {
|
|
@@ -7011,13 +7033,26 @@ var ScribbleManager = class extends EditorManager {
|
|
|
7011
7033
|
changed = true;
|
|
7012
7034
|
continue;
|
|
7013
7035
|
}
|
|
7014
|
-
if (
|
|
7036
|
+
if (moved || state !== item.scribble.state) {
|
|
7015
7037
|
item.scribble = { ...item.scribble, points, state };
|
|
7016
7038
|
changed = true;
|
|
7017
7039
|
}
|
|
7018
7040
|
}
|
|
7019
7041
|
if (changed) this.flush();
|
|
7020
7042
|
}
|
|
7043
|
+
/**
|
|
7044
|
+
* Whether anything here still needs frames.
|
|
7045
|
+
*
|
|
7046
|
+
* A host's frame loop asks this to decide whether to schedule another one. It
|
|
7047
|
+
* is deliberately "is there a scribble at all" rather than "is there anything
|
|
7048
|
+
* visible to redraw": a point offered through {@link addPoint} is held in
|
|
7049
|
+
* `next` and writes nothing to the store, so a loop that parked itself
|
|
7050
|
+
* because the picture had settled would never wake up to commit it, and the
|
|
7051
|
+
* trail would stop dead under a moving pointer.
|
|
7052
|
+
*/
|
|
7053
|
+
hasPendingWork() {
|
|
7054
|
+
return this.items.size > 0;
|
|
7055
|
+
}
|
|
7021
7056
|
/** Every live scribble, in the order they were started. */
|
|
7022
7057
|
getItems() {
|
|
7023
7058
|
return [...this.items.values()];
|
|
@@ -7523,7 +7558,7 @@ var OverlayManager = class extends EditorManager {
|
|
|
7523
7558
|
for (const util of this.getOverlayUtilsInZOrder()) {
|
|
7524
7559
|
const interactive = util;
|
|
7525
7560
|
if (interactive.isActive && !interactive.isActive()) continue;
|
|
7526
|
-
util.render(ctx);
|
|
7561
|
+
util.render(ctx, interactive.getOverlays?.());
|
|
7527
7562
|
}
|
|
7528
7563
|
}
|
|
7529
7564
|
/** The minimap pass: only utils that opt in by implementing `renderMinimap`. */
|
|
@@ -7786,6 +7821,19 @@ var WHEEL_ZOOM_DELTA_CAP = 50;
|
|
|
7786
7821
|
var MIDDLE_BUTTON = 1;
|
|
7787
7822
|
var COLLABORATOR_INACTIVE_TIMEOUT = 6e4;
|
|
7788
7823
|
var editorSequence = 0;
|
|
7824
|
+
var warnedKeys = /* @__PURE__ */ new Set();
|
|
7825
|
+
function warnOnce(key, message) {
|
|
7826
|
+
let isProduction = false;
|
|
7827
|
+
try {
|
|
7828
|
+
isProduction = typeof process !== "undefined" && process.env?.["NODE_ENV"] === "production";
|
|
7829
|
+
} catch {
|
|
7830
|
+
isProduction = false;
|
|
7831
|
+
}
|
|
7832
|
+
if (isProduction) return;
|
|
7833
|
+
if (warnedKeys.has(key)) return;
|
|
7834
|
+
warnedKeys.add(key);
|
|
7835
|
+
console.warn(message);
|
|
7836
|
+
}
|
|
7789
7837
|
var Editor = class extends EventEmitter {
|
|
7790
7838
|
store;
|
|
7791
7839
|
engine;
|
|
@@ -7880,6 +7928,20 @@ var Editor = class extends EventEmitter {
|
|
|
7880
7928
|
richTextEditor = null;
|
|
7881
7929
|
/** Tools added or removed after construction, by id. */
|
|
7882
7930
|
removedToolIds = /* @__PURE__ */ new Set();
|
|
7931
|
+
/**
|
|
7932
|
+
* This editor's own presence identity. See {@link getInstancePresenceId}.
|
|
7933
|
+
*
|
|
7934
|
+
* Minted per editor rather than per user: presence is about an *instance*,
|
|
7935
|
+
* and one person may have several.
|
|
7936
|
+
*/
|
|
7937
|
+
_instancePresenceId = InstancePresenceRecordType.createId();
|
|
7938
|
+
/**
|
|
7939
|
+
* A {@link zoomToBounds} that arrived before the container had been measured,
|
|
7940
|
+
* waiting for the first non-empty viewport. See {@link zoomToBounds}.
|
|
7941
|
+
*/
|
|
7942
|
+
pendingViewportFit = null;
|
|
7943
|
+
/** Whether a host has ever measured the canvas. See {@link getHasMeasuredViewport}. */
|
|
7944
|
+
hasMeasuredViewport = false;
|
|
7883
7945
|
constructor(opts) {
|
|
7884
7946
|
super();
|
|
7885
7947
|
this.store = opts.store;
|
|
@@ -8064,7 +8126,7 @@ var Editor = class extends EventEmitter {
|
|
|
8064
8126
|
}
|
|
8065
8127
|
let pages = this.store.query.records("page").get();
|
|
8066
8128
|
if (pages.length === 0) {
|
|
8067
|
-
const page = PageRecordType.create({ id:
|
|
8129
|
+
const page = PageRecordType.create({ id: DEFAULT_PAGE_ID, name: "Page 1", index: FIRST_PAGE_INDEX });
|
|
8068
8130
|
this.store.put([page]);
|
|
8069
8131
|
pages = [page];
|
|
8070
8132
|
}
|
|
@@ -8558,6 +8620,18 @@ var Editor = class extends EventEmitter {
|
|
|
8558
8620
|
getHitTestMargin() {
|
|
8559
8621
|
return this.getInstanceState().isCoarsePointer ? this.options.coarseHitTestMargin : this.options.hitTestMargin;
|
|
8560
8622
|
}
|
|
8623
|
+
/**
|
|
8624
|
+
* `opts.filter` with `renderingOnly` folded in.
|
|
8625
|
+
*
|
|
8626
|
+
* Returned as one predicate so each query applies both in the same place;
|
|
8627
|
+
* the culled set is read once per call rather than per candidate shape.
|
|
8628
|
+
*/
|
|
8629
|
+
hitFilter(opts) {
|
|
8630
|
+
if (!opts.renderingOnly) return opts.filter;
|
|
8631
|
+
const culled = this.getCulledShapes();
|
|
8632
|
+
const filter = opts.filter;
|
|
8633
|
+
return filter ? (shape) => !culled.has(shape.id) && filter(shape) : (shape) => !culled.has(shape.id);
|
|
8634
|
+
}
|
|
8561
8635
|
hitFilterBits(opts) {
|
|
8562
8636
|
let bits = 0;
|
|
8563
8637
|
if (opts.hitLocked) bits |= 1;
|
|
@@ -8589,13 +8663,14 @@ var Editor = class extends EventEmitter {
|
|
|
8589
8663
|
this.flushEngine();
|
|
8590
8664
|
const margin = (opts.margin ?? this.getHitTestMargin()) / this.getZoomLevel();
|
|
8591
8665
|
const bits = this.hitFilterBits(opts) | (opts.hitInside ? 0 : 4);
|
|
8592
|
-
|
|
8666
|
+
const filter = this.hitFilter(opts);
|
|
8667
|
+
if (!filter) {
|
|
8593
8668
|
const h = this.engine.hitTest(point.x, point.y, margin, bits);
|
|
8594
8669
|
const id = this.handles.id(h);
|
|
8595
8670
|
return id ? this.getShape(id) : void 0;
|
|
8596
8671
|
}
|
|
8597
8672
|
for (const shape of this.getShapesAtPoint(point, opts)) {
|
|
8598
|
-
if (
|
|
8673
|
+
if (filter(shape)) return shape;
|
|
8599
8674
|
}
|
|
8600
8675
|
return void 0;
|
|
8601
8676
|
}
|
|
@@ -8604,12 +8679,13 @@ var Editor = class extends EventEmitter {
|
|
|
8604
8679
|
this.flushEngine();
|
|
8605
8680
|
const margin = (opts.margin ?? this.getHitTestMargin()) / this.getZoomLevel();
|
|
8606
8681
|
const handles = this.engine.queryBox(point.x - margin, point.y - margin, point.x + margin, point.y + margin, 0, this.hitFilterBits(opts));
|
|
8682
|
+
const filter = this.hitFilter(opts);
|
|
8607
8683
|
const out = [];
|
|
8608
8684
|
for (let i = handles.length - 1; i >= 0; i--) {
|
|
8609
8685
|
const id = this.handles.id(handles[i]);
|
|
8610
8686
|
const shape = id ? this.getShape(id) : void 0;
|
|
8611
8687
|
if (!shape) continue;
|
|
8612
|
-
if (
|
|
8688
|
+
if (filter && !filter(shape)) continue;
|
|
8613
8689
|
const local = this.getPointInShapeSpace(shape, point);
|
|
8614
8690
|
const geo = this.getShapeGeometry(shape);
|
|
8615
8691
|
if (geo.hitTestPoint(local, margin, opts.hitInside ?? false)) out.push(shape);
|
|
@@ -8620,13 +8696,13 @@ var Editor = class extends EventEmitter {
|
|
|
8620
8696
|
getShapesInsideBounds(box, opts = {}) {
|
|
8621
8697
|
this.flushEngine();
|
|
8622
8698
|
const handles = this.engine.queryBox(box.x, box.y, box.x + box.w, box.y + box.h, 1, this.hitFilterBits(opts));
|
|
8623
|
-
return this.handlesToShapes(handles, opts
|
|
8699
|
+
return this.handlesToShapes(handles, this.hitFilter(opts));
|
|
8624
8700
|
}
|
|
8625
8701
|
/** Shapes whose outline touches a page box, in draw order. */
|
|
8626
8702
|
getShapesIntersectingBounds(box, opts = {}) {
|
|
8627
8703
|
this.flushEngine();
|
|
8628
8704
|
const handles = this.engine.queryBox(box.x, box.y, box.x + box.w, box.y + box.h, 0, this.hitFilterBits(opts));
|
|
8629
|
-
return this.handlesToShapes(handles, opts
|
|
8705
|
+
return this.handlesToShapes(handles, this.hitFilter(opts));
|
|
8630
8706
|
}
|
|
8631
8707
|
handlesToShapes(handles, filter) {
|
|
8632
8708
|
const out = [];
|
|
@@ -8753,6 +8829,7 @@ var Editor = class extends EventEmitter {
|
|
|
8753
8829
|
if (ps.editingShapeId && toDelete.has(ps.editingShapeId)) this.setEditingShape(null);
|
|
8754
8830
|
this.store.remove([...toDelete]);
|
|
8755
8831
|
});
|
|
8832
|
+
this.emit("deleted-shapes", [...toDelete]);
|
|
8756
8833
|
return this;
|
|
8757
8834
|
}
|
|
8758
8835
|
/**
|
|
@@ -9514,13 +9591,16 @@ var Editor = class extends EventEmitter {
|
|
|
9514
9591
|
*/
|
|
9515
9592
|
setCamera(point, opts = {}) {
|
|
9516
9593
|
this.stopCameraAnimation();
|
|
9594
|
+
this.pendingViewportFit = null;
|
|
9517
9595
|
if (this._cameraOptions.get().isLocked && opts.force !== true) return this;
|
|
9518
9596
|
const cam = this.getCamera();
|
|
9519
9597
|
const z = Math.min(this.options.zoomMax, Math.max(this.options.zoomMin, point.z ?? cam.z));
|
|
9520
9598
|
const x = point.x ?? cam.x;
|
|
9521
9599
|
const y = point.y ?? cam.y;
|
|
9522
9600
|
if (cam.x === x && cam.y === y && cam.z === z) return this;
|
|
9523
|
-
const
|
|
9601
|
+
const speed = this.user.getAnimationSpeed();
|
|
9602
|
+
const requested = opts.immediate === true ? 0 : opts.animation?.duration ?? 0;
|
|
9603
|
+
const duration = speed > 0 ? requested / speed : 0;
|
|
9524
9604
|
if (duration > 0) {
|
|
9525
9605
|
this.animateCameraTo({ x, y, z }, duration, opts.animation?.easing ?? easeInOutCubic);
|
|
9526
9606
|
return this;
|
|
@@ -9612,6 +9692,19 @@ var Editor = class extends EventEmitter {
|
|
|
9612
9692
|
const b = this.getInstanceState().screenBounds;
|
|
9613
9693
|
return new Box(b.x, b.y, b.w, b.h);
|
|
9614
9694
|
}
|
|
9695
|
+
/**
|
|
9696
|
+
* Whether a host has ever told us how big the canvas is
|
|
9697
|
+
* ({@link updateViewportScreenBounds}).
|
|
9698
|
+
*
|
|
9699
|
+
* Until it has, {@link getViewportScreenBounds} answers with the instance
|
|
9700
|
+
* record's default — a plausible-looking 1080x720 that is not this canvas —
|
|
9701
|
+
* or with zeros once a container that has not been laid out yet has been
|
|
9702
|
+
* measured. Both are wrong in the same way and neither announces itself,
|
|
9703
|
+
* which is why anything that needs the viewport asks this first.
|
|
9704
|
+
*/
|
|
9705
|
+
getHasMeasuredViewport() {
|
|
9706
|
+
return this.hasMeasuredViewport;
|
|
9707
|
+
}
|
|
9615
9708
|
getViewportScreenCenter() {
|
|
9616
9709
|
const b = this.getViewportScreenBounds();
|
|
9617
9710
|
return new Vec(b.w / 2, b.h / 2);
|
|
@@ -9633,10 +9726,18 @@ var Editor = class extends EventEmitter {
|
|
|
9633
9726
|
* would otherwise fail on a `getBoundingClientRect` that was never there.
|
|
9634
9727
|
*/
|
|
9635
9728
|
updateViewportScreenBounds(bounds, center = false) {
|
|
9729
|
+
this.hasMeasuredViewport = true;
|
|
9636
9730
|
const prev = this.getViewportScreenBounds();
|
|
9637
9731
|
const measured = typeof HTMLElement !== "undefined" && bounds instanceof HTMLElement ? (({ x, y, width, height }) => ({ x, y, w: width, h: height }))(bounds.getBoundingClientRect()) : bounds;
|
|
9638
9732
|
const next = Box.From(measured);
|
|
9639
|
-
|
|
9733
|
+
const unchanged = prev.x === next.x && prev.y === next.y && prev.w === next.w && prev.h === next.h;
|
|
9734
|
+
const pending = this.pendingViewportFit;
|
|
9735
|
+
this.pendingViewportFit = null;
|
|
9736
|
+
if (unchanged) {
|
|
9737
|
+
if (pending && next.w > 0 && next.h > 0) this.zoomToBounds(pending.bounds, pending.opts);
|
|
9738
|
+
else this.pendingViewportFit = pending;
|
|
9739
|
+
return this;
|
|
9740
|
+
}
|
|
9640
9741
|
this.run(
|
|
9641
9742
|
() => {
|
|
9642
9743
|
this.updateInstanceState({ screenBounds: next.toJson() });
|
|
@@ -9647,6 +9748,8 @@ var Editor = class extends EventEmitter {
|
|
|
9647
9748
|
},
|
|
9648
9749
|
{ history: "ignore" }
|
|
9649
9750
|
);
|
|
9751
|
+
if (pending && next.w > 0 && next.h > 0) this.zoomToBounds(pending.bounds, pending.opts);
|
|
9752
|
+
else this.pendingViewportFit = pending;
|
|
9650
9753
|
return this;
|
|
9651
9754
|
}
|
|
9652
9755
|
// Two screen-ish spaces, and the difference between them matters:
|
|
@@ -9710,6 +9813,15 @@ var Editor = class extends EventEmitter {
|
|
|
9710
9813
|
*/
|
|
9711
9814
|
zoomToBounds(bounds, opts = {}) {
|
|
9712
9815
|
const vp = this.getViewportScreenBounds();
|
|
9816
|
+
if (!this.hasMeasuredViewport || vp.w <= 0 || vp.h <= 0) {
|
|
9817
|
+
this.pendingViewportFit = { bounds: { x: bounds.x, y: bounds.y, w: bounds.w, h: bounds.h }, opts };
|
|
9818
|
+
warnOnce(
|
|
9819
|
+
`editor.zoom:${this.id}`,
|
|
9820
|
+
"mocanvas: zoomToFit / zoomToBounds was called before this canvas had a measured viewport \u2014 which is what onMount looks like, because the canvas component measures itself after the editor exists. Fitting against the placeholder bounds would put the camera somewhere that is not the shapes, so the move is deferred until the container reports a size; reading getCamera() straight afterwards therefore still sees the old camera. In a headless editor, call editor.updateViewportScreenBounds({ x: 0, y: 0, w, h }) first."
|
|
9821
|
+
);
|
|
9822
|
+
return this;
|
|
9823
|
+
}
|
|
9824
|
+
this.pendingViewportFit = null;
|
|
9713
9825
|
const inset = opts.inset ?? Math.min(256, vp.w * 0.28);
|
|
9714
9826
|
let z = Math.min((vp.w - inset) / bounds.w, (vp.h - inset) / bounds.h);
|
|
9715
9827
|
if (opts.targetZoom !== void 0) z = Math.min(z, opts.targetZoom);
|
|
@@ -10280,11 +10392,36 @@ var Editor = class extends EventEmitter {
|
|
|
10280
10392
|
* dynamic-size mode. Session-only, never persisted with the document.
|
|
10281
10393
|
*/
|
|
10282
10394
|
user;
|
|
10283
|
-
/**
|
|
10395
|
+
/**
|
|
10396
|
+
* This editor instance's presence record id — who *this tab* is, as opposed
|
|
10397
|
+
* to `user.getId()`, which is who the person is.
|
|
10398
|
+
*
|
|
10399
|
+
* The two are not interchangeable and conflating them was a bug: a user id
|
|
10400
|
+
* is per browser (it is the same in every tab, and the same on a phone and a
|
|
10401
|
+
* laptop signed in as one person), while a presence record is per editor
|
|
10402
|
+
* instance. Two tabs of one browser are two presences of one user, and they
|
|
10403
|
+
* must see each other.
|
|
10404
|
+
*
|
|
10405
|
+
* `@mocanvas/sync` publishes this tab's presence record under this id, which
|
|
10406
|
+
* is what lets {@link getCollaborators} drop our own record — and only our
|
|
10407
|
+
* own record — should it ever come back to us.
|
|
10408
|
+
*/
|
|
10409
|
+
getInstancePresenceId() {
|
|
10410
|
+
return this._instancePresenceId;
|
|
10411
|
+
}
|
|
10412
|
+
/**
|
|
10413
|
+
* Presence records of everyone else in the room, in arrival order.
|
|
10414
|
+
*
|
|
10415
|
+
* "Else" means *another instance*, not another person: the filter is on the
|
|
10416
|
+
* presence record id ({@link getInstancePresenceId}), so a second tab, a
|
|
10417
|
+
* second window, or the same person on a phone and a laptop all show up as
|
|
10418
|
+
* collaborators. Filtering by user id instead made two tabs of one browser
|
|
10419
|
+
* invisible to each other while every message arrived correctly.
|
|
10420
|
+
*/
|
|
10284
10421
|
getCollaborators() {
|
|
10285
|
-
const me = this.
|
|
10422
|
+
const me = this.getInstancePresenceId();
|
|
10286
10423
|
const records = this.store.query.records("instance_presence").get();
|
|
10287
|
-
return records.filter((p) => p.
|
|
10424
|
+
return records.filter((p) => p.id !== me);
|
|
10288
10425
|
}
|
|
10289
10426
|
/** The subset of `getCollaborators()` looking at the page we are on. */
|
|
10290
10427
|
getCollaboratorsOnCurrentPage() {
|
|
@@ -11589,6 +11726,29 @@ function createPropsMigrationSequences(options) {
|
|
|
11589
11726
|
collect("binding", options.bindingUtils);
|
|
11590
11727
|
return out;
|
|
11591
11728
|
}
|
|
11729
|
+
|
|
11730
|
+
// src/records/defaultSchemas.ts
|
|
11731
|
+
var shapeSchemas = {};
|
|
11732
|
+
var bindingSchemas = {};
|
|
11733
|
+
var assetSchemas = {};
|
|
11734
|
+
var defaultShapeSchemas = shapeSchemas;
|
|
11735
|
+
var defaultBindingSchemas = bindingSchemas;
|
|
11736
|
+
var defaultAssetSchemas = assetSchemas;
|
|
11737
|
+
function registerDefaultShapeSchema(type, info) {
|
|
11738
|
+
return register(shapeSchemas, type, info);
|
|
11739
|
+
}
|
|
11740
|
+
function registerDefaultBindingSchema(type, info) {
|
|
11741
|
+
return register(bindingSchemas, type, info);
|
|
11742
|
+
}
|
|
11743
|
+
function registerDefaultAssetSchema(type, info) {
|
|
11744
|
+
return register(assetSchemas, type, info);
|
|
11745
|
+
}
|
|
11746
|
+
function register(map, type, info) {
|
|
11747
|
+
map[type] = info;
|
|
11748
|
+
return () => {
|
|
11749
|
+
if (map[type] === info) delete map[type];
|
|
11750
|
+
};
|
|
11751
|
+
}
|
|
11592
11752
|
var CUSTOM_RECORD_TYPE_NAME = "custom";
|
|
11593
11753
|
function createCustomRecordId(type, id) {
|
|
11594
11754
|
return `${CUSTOM_RECORD_TYPE_NAME}:${type}:${id ?? uniqueId()}`;
|
|
@@ -11615,52 +11775,6 @@ function getCustomRecordIdType(id) {
|
|
|
11615
11775
|
return colon > 0 ? rest.slice(0, colon) : void 0;
|
|
11616
11776
|
}
|
|
11617
11777
|
|
|
11618
|
-
// src/migrations/customRecordMigrations.ts
|
|
11619
|
-
var CUSTOM_RECORD_MIGRATION_SEQUENCE_PREFIX = "com.tldraw.record";
|
|
11620
|
-
function customRecordMigrationSequenceId(type) {
|
|
11621
|
-
return `${CUSTOM_RECORD_MIGRATION_SEQUENCE_PREFIX}.${type}`;
|
|
11622
|
-
}
|
|
11623
|
-
function createCustomRecordMigrationIds(recordType, versions) {
|
|
11624
|
-
return createMigrationIds(
|
|
11625
|
-
customRecordMigrationSequenceId(recordType),
|
|
11626
|
-
versions
|
|
11627
|
-
);
|
|
11628
|
-
}
|
|
11629
|
-
function createCustomRecordMigrationSequence(migrations) {
|
|
11630
|
-
return createShapePropsMigrationSequence(migrations);
|
|
11631
|
-
}
|
|
11632
|
-
function isPlainObject3(value) {
|
|
11633
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
11634
|
-
}
|
|
11635
|
-
function toCustomRecordMigrationSequence(type, migrations) {
|
|
11636
|
-
const first = migrations.sequence[0];
|
|
11637
|
-
const sequenceId = first ? parseMigrationId(first.id).sequenceId : customRecordMigrationSequenceId(type);
|
|
11638
|
-
if (!sequenceId.endsWith(`.${type}`)) {
|
|
11639
|
-
throw new Error(
|
|
11640
|
-
`Migration sequence "${sequenceId}" does not name custom record "${type}"; ids must end in ".${type}"`
|
|
11641
|
-
);
|
|
11642
|
-
}
|
|
11643
|
-
const matches2 = (record) => record.typeName === CUSTOM_RECORD_TYPE_NAME && record.type === type;
|
|
11644
|
-
const wrap = (fn) => (record) => {
|
|
11645
|
-
const props = record.props;
|
|
11646
|
-
if (!isPlainObject3(props)) return record;
|
|
11647
|
-
const next = { ...props };
|
|
11648
|
-
const replacement = fn(next);
|
|
11649
|
-
return { ...record, props: replacement ?? next };
|
|
11650
|
-
};
|
|
11651
|
-
return createMigrationSequence({
|
|
11652
|
-
sequenceId,
|
|
11653
|
-
...migrations.retroactive === void 0 ? {} : { retroactive: migrations.retroactive },
|
|
11654
|
-
sequence: migrations.sequence.map((migration) => ({
|
|
11655
|
-
id: migration.id,
|
|
11656
|
-
scope: "record",
|
|
11657
|
-
filter: matches2,
|
|
11658
|
-
up: wrap(migration.up),
|
|
11659
|
-
...migration.down ? { down: wrap(migration.down) } : {}
|
|
11660
|
-
}))
|
|
11661
|
-
});
|
|
11662
|
-
}
|
|
11663
|
-
|
|
11664
11778
|
// src/records/uiValues.ts
|
|
11665
11779
|
var TL_CANVAS_UI_COLOR_TYPES = [
|
|
11666
11780
|
"accent",
|
|
@@ -11692,10 +11806,11 @@ var parentIdValidator = T.string.refine((value) => {
|
|
|
11692
11806
|
});
|
|
11693
11807
|
|
|
11694
11808
|
// src/records/recordValidators.ts
|
|
11695
|
-
function propsValidator(props) {
|
|
11696
|
-
|
|
11809
|
+
function propsValidator(props, unknownProps = "reject") {
|
|
11810
|
+
const validator = T.object(props);
|
|
11811
|
+
return unknownProps === "keep" ? validator.allowUnknownProperties() : validator;
|
|
11697
11812
|
}
|
|
11698
|
-
function createShapeValidator(type, props, meta) {
|
|
11813
|
+
function createShapeValidator(type, props, meta, options) {
|
|
11699
11814
|
return T.model(
|
|
11700
11815
|
`shape:${type}`,
|
|
11701
11816
|
T.object({
|
|
@@ -11709,7 +11824,7 @@ function createShapeValidator(type, props, meta) {
|
|
|
11709
11824
|
parentId: parentIdValidator,
|
|
11710
11825
|
isLocked: T.boolean,
|
|
11711
11826
|
opacity: opacityValidator,
|
|
11712
|
-
props: propsValidator(props),
|
|
11827
|
+
props: propsValidator(props, options?.unknownProps),
|
|
11713
11828
|
meta: meta ? propsValidator(meta) : T.jsonObject
|
|
11714
11829
|
})
|
|
11715
11830
|
// The config above describes exactly the record type named, but `T.object`
|
|
@@ -11718,7 +11833,65 @@ function createShapeValidator(type, props, meta) {
|
|
|
11718
11833
|
// parameter. Restate what was actually built.
|
|
11719
11834
|
);
|
|
11720
11835
|
}
|
|
11721
|
-
function
|
|
11836
|
+
function createBaseShapeValidator() {
|
|
11837
|
+
return T.model(
|
|
11838
|
+
"shape",
|
|
11839
|
+
T.object({
|
|
11840
|
+
id: T.idOfType("shape"),
|
|
11841
|
+
typeName: T.literal("shape"),
|
|
11842
|
+
type: T.string,
|
|
11843
|
+
x: T.number,
|
|
11844
|
+
y: T.number,
|
|
11845
|
+
rotation: T.number,
|
|
11846
|
+
index: T.indexKey,
|
|
11847
|
+
parentId: parentIdValidator,
|
|
11848
|
+
isLocked: T.boolean,
|
|
11849
|
+
opacity: opacityValidator,
|
|
11850
|
+
// Anything, deliberately — see above.
|
|
11851
|
+
props: T.jsonObject,
|
|
11852
|
+
meta: T.jsonObject
|
|
11853
|
+
})
|
|
11854
|
+
);
|
|
11855
|
+
}
|
|
11856
|
+
function createAssetPropsValidator(type, props, options) {
|
|
11857
|
+
return T.model(
|
|
11858
|
+
`${type}_asset`,
|
|
11859
|
+
T.object({
|
|
11860
|
+
id: T.idOfType("asset"),
|
|
11861
|
+
typeName: T.literal("asset"),
|
|
11862
|
+
type: T.literal(type),
|
|
11863
|
+
props: propsValidator(props, options?.unknownProps),
|
|
11864
|
+
meta: T.jsonObject
|
|
11865
|
+
})
|
|
11866
|
+
);
|
|
11867
|
+
}
|
|
11868
|
+
function createBaseAssetValidator() {
|
|
11869
|
+
return T.model(
|
|
11870
|
+
"asset",
|
|
11871
|
+
T.object({
|
|
11872
|
+
id: T.idOfType("asset"),
|
|
11873
|
+
typeName: T.literal("asset"),
|
|
11874
|
+
type: T.string,
|
|
11875
|
+
props: T.jsonObject,
|
|
11876
|
+
meta: T.jsonObject
|
|
11877
|
+
})
|
|
11878
|
+
);
|
|
11879
|
+
}
|
|
11880
|
+
function createBaseBindingValidator() {
|
|
11881
|
+
return T.model(
|
|
11882
|
+
"binding",
|
|
11883
|
+
T.object({
|
|
11884
|
+
id: T.idOfType("binding"),
|
|
11885
|
+
typeName: T.literal("binding"),
|
|
11886
|
+
type: T.string,
|
|
11887
|
+
fromId: T.idOfType("shape"),
|
|
11888
|
+
toId: T.idOfType("shape"),
|
|
11889
|
+
props: T.jsonObject,
|
|
11890
|
+
meta: T.jsonObject
|
|
11891
|
+
})
|
|
11892
|
+
);
|
|
11893
|
+
}
|
|
11894
|
+
function createBindingValidator(type, props, meta, options) {
|
|
11722
11895
|
return T.model(
|
|
11723
11896
|
`binding:${type}`,
|
|
11724
11897
|
T.object({
|
|
@@ -11727,7 +11900,7 @@ function createBindingValidator(type, props, meta) {
|
|
|
11727
11900
|
type: T.literal(type),
|
|
11728
11901
|
fromId: T.idOfType("shape"),
|
|
11729
11902
|
toId: T.idOfType("shape"),
|
|
11730
|
-
props: propsValidator(props),
|
|
11903
|
+
props: propsValidator(props, options?.unknownProps),
|
|
11731
11904
|
meta: meta ? propsValidator(meta) : T.jsonObject
|
|
11732
11905
|
})
|
|
11733
11906
|
);
|
|
@@ -11763,6 +11936,111 @@ function createCustomRecordValidator(type, props, meta) {
|
|
|
11763
11936
|
);
|
|
11764
11937
|
}
|
|
11765
11938
|
|
|
11939
|
+
// src/records/validatedRecordTypes.ts
|
|
11940
|
+
function collectProps(utils, defaults2) {
|
|
11941
|
+
const out = {};
|
|
11942
|
+
for (const [type, info] of Object.entries(defaults2)) {
|
|
11943
|
+
if (info.props) out[type] = info.props;
|
|
11944
|
+
}
|
|
11945
|
+
for (const util of utils ?? []) {
|
|
11946
|
+
if (util.props) out[util.type] = util.props;
|
|
11947
|
+
}
|
|
11948
|
+
return out;
|
|
11949
|
+
}
|
|
11950
|
+
function dispatchingValidator(kind, byType, base) {
|
|
11951
|
+
return {
|
|
11952
|
+
validate(value) {
|
|
11953
|
+
const type = value?.type;
|
|
11954
|
+
if (typeof type !== "string") {
|
|
11955
|
+
throw new ValidationError(
|
|
11956
|
+
`Expected a ${kind} type, got ${type === void 0 ? "undefined" : typeof type}`,
|
|
11957
|
+
["type"]
|
|
11958
|
+
);
|
|
11959
|
+
}
|
|
11960
|
+
const validator = byType.get(type);
|
|
11961
|
+
if (!validator) return base.validate(value);
|
|
11962
|
+
return validator.validate(value);
|
|
11963
|
+
}
|
|
11964
|
+
};
|
|
11965
|
+
}
|
|
11966
|
+
function createShapeRecordType(propsByType) {
|
|
11967
|
+
const byType = new Map(
|
|
11968
|
+
Object.entries(propsByType).map(
|
|
11969
|
+
([type, props]) => [type, createShapeValidator(type, props, void 0, { unknownProps: "keep" })]
|
|
11970
|
+
)
|
|
11971
|
+
);
|
|
11972
|
+
return createRecordType("shape", {
|
|
11973
|
+
scope: "document",
|
|
11974
|
+
validator: dispatchingValidator("shape", byType, createBaseShapeValidator())
|
|
11975
|
+
}).withDefaultProperties(() => ({ x: 0, y: 0, rotation: 0, isLocked: false, opacity: 1, meta: {} }));
|
|
11976
|
+
}
|
|
11977
|
+
function createAssetRecordType(propsByType) {
|
|
11978
|
+
const byType = new Map(
|
|
11979
|
+
Object.entries(propsByType).map(
|
|
11980
|
+
([type, props]) => [type, createAssetPropsValidator(type, props, { unknownProps: "keep" })]
|
|
11981
|
+
)
|
|
11982
|
+
);
|
|
11983
|
+
return createRecordType("asset", {
|
|
11984
|
+
scope: "document",
|
|
11985
|
+
validator: dispatchingValidator("asset", byType, createBaseAssetValidator())
|
|
11986
|
+
}).withDefaultProperties(() => ({ meta: {} }));
|
|
11987
|
+
}
|
|
11988
|
+
function createBindingRecordType(propsByType) {
|
|
11989
|
+
const byType = new Map(
|
|
11990
|
+
Object.entries(propsByType).map(
|
|
11991
|
+
([type, props]) => [type, createBindingValidator(type, props, void 0, { unknownProps: "keep" })]
|
|
11992
|
+
)
|
|
11993
|
+
);
|
|
11994
|
+
return createRecordType("binding", {
|
|
11995
|
+
scope: "document",
|
|
11996
|
+
validator: dispatchingValidator("binding", byType, createBaseBindingValidator())
|
|
11997
|
+
}).withDefaultProperties(() => ({ meta: {} }));
|
|
11998
|
+
}
|
|
11999
|
+
var CUSTOM_RECORD_MIGRATION_SEQUENCE_PREFIX = "com.tldraw.record";
|
|
12000
|
+
function customRecordMigrationSequenceId(type) {
|
|
12001
|
+
return `${CUSTOM_RECORD_MIGRATION_SEQUENCE_PREFIX}.${type}`;
|
|
12002
|
+
}
|
|
12003
|
+
function createCustomRecordMigrationIds(recordType, versions) {
|
|
12004
|
+
return createMigrationIds(
|
|
12005
|
+
customRecordMigrationSequenceId(recordType),
|
|
12006
|
+
versions
|
|
12007
|
+
);
|
|
12008
|
+
}
|
|
12009
|
+
function createCustomRecordMigrationSequence(migrations) {
|
|
12010
|
+
return createShapePropsMigrationSequence(migrations);
|
|
12011
|
+
}
|
|
12012
|
+
function isPlainObject3(value) {
|
|
12013
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
12014
|
+
}
|
|
12015
|
+
function toCustomRecordMigrationSequence(type, migrations) {
|
|
12016
|
+
const first = migrations.sequence[0];
|
|
12017
|
+
const sequenceId = first ? parseMigrationId(first.id).sequenceId : customRecordMigrationSequenceId(type);
|
|
12018
|
+
if (!sequenceId.endsWith(`.${type}`)) {
|
|
12019
|
+
throw new Error(
|
|
12020
|
+
`Migration sequence "${sequenceId}" does not name custom record "${type}"; ids must end in ".${type}"`
|
|
12021
|
+
);
|
|
12022
|
+
}
|
|
12023
|
+
const matches2 = (record) => record.typeName === CUSTOM_RECORD_TYPE_NAME && record.type === type;
|
|
12024
|
+
const wrap = (fn) => (record) => {
|
|
12025
|
+
const props = record.props;
|
|
12026
|
+
if (!isPlainObject3(props)) return record;
|
|
12027
|
+
const next = { ...props };
|
|
12028
|
+
const replacement = fn(next);
|
|
12029
|
+
return { ...record, props: replacement ?? next };
|
|
12030
|
+
};
|
|
12031
|
+
return createMigrationSequence({
|
|
12032
|
+
sequenceId,
|
|
12033
|
+
...migrations.retroactive === void 0 ? {} : { retroactive: migrations.retroactive },
|
|
12034
|
+
sequence: migrations.sequence.map((migration) => ({
|
|
12035
|
+
id: migration.id,
|
|
12036
|
+
scope: "record",
|
|
12037
|
+
filter: matches2,
|
|
12038
|
+
up: wrap(migration.up),
|
|
12039
|
+
...migration.down ? { down: wrap(migration.down) } : {}
|
|
12040
|
+
}))
|
|
12041
|
+
});
|
|
12042
|
+
}
|
|
12043
|
+
|
|
11766
12044
|
// src/records/schemaRecords.ts
|
|
11767
12045
|
function createCustomRecordType(info) {
|
|
11768
12046
|
const validator = createCustomRecordValidator(info.type, info.props);
|
|
@@ -11873,17 +12151,23 @@ function createSchema(migrationsOrUtils = []) {
|
|
|
11873
12151
|
...createCustomRecordMigrationSequences(records),
|
|
11874
12152
|
...migrationsOrUtils.migrations ?? []
|
|
11875
12153
|
];
|
|
11876
|
-
return createSchemaWithMigrations(migrations, records
|
|
12154
|
+
return createSchemaWithMigrations(migrations, records, {
|
|
12155
|
+
...migrationsOrUtils.shapeUtils ? { shapeUtils: migrationsOrUtils.shapeUtils } : {},
|
|
12156
|
+
...migrationsOrUtils.bindingUtils ? { bindingUtils: migrationsOrUtils.bindingUtils } : {}
|
|
12157
|
+
});
|
|
11877
12158
|
}
|
|
11878
|
-
function createSchemaWithMigrations(migrations, records) {
|
|
12159
|
+
function createSchemaWithMigrations(migrations, records, utils = {}) {
|
|
11879
12160
|
const customRecords = createCustomRecordTypeMap(records);
|
|
12161
|
+
const shapeRecords = createShapeRecordType(collectProps(utils.shapeUtils, defaultShapeSchemas));
|
|
12162
|
+
const bindingRecords = createBindingRecordType(collectProps(utils.bindingUtils, defaultBindingSchemas));
|
|
12163
|
+
const assetRecords = createAssetRecordType(collectProps(void 0, defaultAssetSchemas));
|
|
11880
12164
|
return StoreSchema.create(
|
|
11881
12165
|
{
|
|
11882
12166
|
document: DocumentRecordType,
|
|
11883
12167
|
page: PageRecordType,
|
|
11884
|
-
shape:
|
|
11885
|
-
binding:
|
|
11886
|
-
asset:
|
|
12168
|
+
shape: shapeRecords,
|
|
12169
|
+
binding: bindingRecords,
|
|
12170
|
+
asset: assetRecords,
|
|
11887
12171
|
camera: CameraRecordType,
|
|
11888
12172
|
instance: InstanceRecordType,
|
|
11889
12173
|
instance_page_state: InstancePageStateRecordType,
|
|
@@ -11909,8 +12193,19 @@ function createStore(options = {}) {
|
|
|
11909
12193
|
props: { defaultName: options.defaultName ?? "", assets: options.assets ?? createInMemoryAssetStore() }
|
|
11910
12194
|
});
|
|
11911
12195
|
if (options.snapshot) store.loadStoreSnapshot(options.snapshot);
|
|
12196
|
+
else if (options.seed ?? true) seedBaseRecords(store);
|
|
11912
12197
|
return store;
|
|
11913
12198
|
}
|
|
12199
|
+
function seedBaseRecords(store) {
|
|
12200
|
+
if (store.has(DOCUMENT_ID)) return;
|
|
12201
|
+
if (store.query.records("page").get().length > 0) return;
|
|
12202
|
+
store.put([
|
|
12203
|
+
DocumentRecordType.create({ id: DOCUMENT_ID, name: store.props.defaultName }),
|
|
12204
|
+
// The same fixed id the editor uses, so two replicas that each seeded
|
|
12205
|
+
// their own store meet on one page rather than diverging into two.
|
|
12206
|
+
PageRecordType.create({ id: DEFAULT_PAGE_ID, name: "Page 1", index: FIRST_PAGE_INDEX })
|
|
12207
|
+
]);
|
|
12208
|
+
}
|
|
11914
12209
|
|
|
11915
12210
|
// src/editor/selectionHandles.ts
|
|
11916
12211
|
var HANDLE_HIT_RADIUS = 12;
|
|
@@ -12344,27 +12639,6 @@ function stringOrUndefined(value) {
|
|
|
12344
12639
|
}
|
|
12345
12640
|
|
|
12346
12641
|
// src/editor/schemaFactories.ts
|
|
12347
|
-
var shapeSchemas = {};
|
|
12348
|
-
var bindingSchemas = {};
|
|
12349
|
-
var assetSchemas = {};
|
|
12350
|
-
var defaultShapeSchemas = shapeSchemas;
|
|
12351
|
-
var defaultBindingSchemas = bindingSchemas;
|
|
12352
|
-
var defaultAssetSchemas = assetSchemas;
|
|
12353
|
-
function registerDefaultShapeSchema(type, info) {
|
|
12354
|
-
return register(shapeSchemas, type, info);
|
|
12355
|
-
}
|
|
12356
|
-
function registerDefaultBindingSchema(type, info) {
|
|
12357
|
-
return register(bindingSchemas, type, info);
|
|
12358
|
-
}
|
|
12359
|
-
function registerDefaultAssetSchema(type, info) {
|
|
12360
|
-
return register(assetSchemas, type, info);
|
|
12361
|
-
}
|
|
12362
|
-
function register(map, type, info) {
|
|
12363
|
-
map[type] = info;
|
|
12364
|
-
return () => {
|
|
12365
|
-
if (map[type] === info) delete map[type];
|
|
12366
|
-
};
|
|
12367
|
-
}
|
|
12368
12642
|
function createTLSchemaFromUtils(options = {}) {
|
|
12369
12643
|
return createSchema({
|
|
12370
12644
|
...options.shapeUtils ? { shapeUtils: options.shapeUtils } : {},
|
|
@@ -13725,6 +13999,12 @@ var BindingUtil = class {
|
|
|
13725
13999
|
}
|
|
13726
14000
|
editor;
|
|
13727
14001
|
static type;
|
|
14002
|
+
/**
|
|
14003
|
+
* One validator per prop of the binding this util describes — the contract
|
|
14004
|
+
* the store checks a record against before it is written, and what
|
|
14005
|
+
* `createSchema()` reads to build the document schema. A binding type that
|
|
14006
|
+
* declares none is not validated: see `createBindingRecordType`.
|
|
14007
|
+
*/
|
|
13728
14008
|
static props;
|
|
13729
14009
|
static migrations;
|
|
13730
14010
|
get type() {
|
|
@@ -14432,6 +14712,10 @@ var BRUSH_FILL = "var(--mocanvas-brush-fill, rgba(47, 111, 228, 0.12))";
|
|
|
14432
14712
|
var SNAP = "var(--mocanvas-snap, #cf3fe0)";
|
|
14433
14713
|
var INDICATOR_STROKE = 1.5;
|
|
14434
14714
|
var HANDLE = { corner: 9, rotate: 5.5, shape: 6, virtual: 4 };
|
|
14715
|
+
var MAX_TICK_MS = 64;
|
|
14716
|
+
function hasFrameWork(editor) {
|
|
14717
|
+
return editor.scribbles.hasPendingWork() || editor.edgeScrollManager.getIsEnabled();
|
|
14718
|
+
}
|
|
14435
14719
|
function Canvas({ editor, className, style, children, components, indicatorOverlayUtil }) {
|
|
14436
14720
|
const containerRef = useRef(null);
|
|
14437
14721
|
const canvasRef = useRef(null);
|
|
@@ -14470,13 +14754,20 @@ function Canvas({ editor, className, style, children, components, indicatorOverl
|
|
|
14470
14754
|
if (!backend) return;
|
|
14471
14755
|
let raf = 0;
|
|
14472
14756
|
let dirty = true;
|
|
14473
|
-
|
|
14757
|
+
let last = null;
|
|
14758
|
+
const draw = (time) => {
|
|
14474
14759
|
raf = 0;
|
|
14475
|
-
|
|
14476
|
-
|
|
14477
|
-
if (editor.
|
|
14478
|
-
|
|
14760
|
+
const elapsed = last === null ? 0 : Math.min(time - last, MAX_TICK_MS);
|
|
14761
|
+
last = time;
|
|
14762
|
+
if (elapsed > 0) editor.emit("tick", elapsed);
|
|
14763
|
+
if (dirty) {
|
|
14764
|
+
dirty = false;
|
|
14765
|
+
if (editor.renderFrame(backend).pending) dirty = true;
|
|
14766
|
+
}
|
|
14767
|
+
if (dirty || hasFrameWork(editor)) {
|
|
14479
14768
|
raf = requestAnimationFrame(draw);
|
|
14769
|
+
} else {
|
|
14770
|
+
last = null;
|
|
14480
14771
|
}
|
|
14481
14772
|
};
|
|
14482
14773
|
const stop = react(
|
|
@@ -15243,7 +15534,7 @@ var arrowBindingVersions = createBuiltInBindingPropsMigrationIds("arrow", {
|
|
|
15243
15534
|
|
|
15244
15535
|
// src/assets/assetValidators.ts
|
|
15245
15536
|
var assetIdValidator = T.idOfType("asset");
|
|
15246
|
-
var
|
|
15537
|
+
var imageAssetProps2 = {
|
|
15247
15538
|
w: T.number,
|
|
15248
15539
|
h: T.number,
|
|
15249
15540
|
name: T.string,
|
|
@@ -15251,14 +15542,16 @@ var imageAssetPropsValidator = T.object({
|
|
|
15251
15542
|
mimeType: T.string.nullable(),
|
|
15252
15543
|
src: T.srcUrl.nullable(),
|
|
15253
15544
|
fileSize: T.number.optional()
|
|
15254
|
-
}
|
|
15255
|
-
var
|
|
15545
|
+
};
|
|
15546
|
+
var bookmarkAssetProps2 = {
|
|
15256
15547
|
title: T.string,
|
|
15257
15548
|
description: T.string,
|
|
15258
15549
|
image: T.srcUrl,
|
|
15259
15550
|
favicon: T.srcUrl,
|
|
15260
15551
|
src: T.linkUrl.nullable()
|
|
15261
|
-
}
|
|
15552
|
+
};
|
|
15553
|
+
var imageAssetPropsValidator = T.object(imageAssetProps2);
|
|
15554
|
+
var bookmarkAssetPropsValidator = T.object(bookmarkAssetProps2);
|
|
15262
15555
|
function assetValidatorFor(type, props) {
|
|
15263
15556
|
return T.model(
|
|
15264
15557
|
`${type}_asset`,
|
|
@@ -15296,6 +15589,9 @@ var assetValidators = {
|
|
|
15296
15589
|
video: videoAssetValidator,
|
|
15297
15590
|
bookmark: bookmarkAssetValidator
|
|
15298
15591
|
};
|
|
15592
|
+
registerDefaultAssetSchema("image", { props: imageAssetProps2 });
|
|
15593
|
+
registerDefaultAssetSchema("video", { props: imageAssetProps2 });
|
|
15594
|
+
registerDefaultAssetSchema("bookmark", { props: bookmarkAssetProps2 });
|
|
15299
15595
|
|
|
15300
15596
|
// src/assets/AssetUtil.ts
|
|
15301
15597
|
var AssetUtil = class {
|
|
@@ -15418,6 +15714,6 @@ function setDefaultCdnBaseUrl(url) {
|
|
|
15418
15714
|
cdnBaseUrl = url.replace(/\/+$/, "");
|
|
15419
15715
|
}
|
|
15420
15716
|
|
|
15421
|
-
export { ARROWHEAD_KINDS, ARROW_SHAPE_KINDS, ASSET_MIGRATION_SEQUENCE_PREFIX, Arc2d, ArrayOfValidator, ArrowShapeArrowheadEndStyle, ArrowShapeArrowheadStartStyle, ArrowShapeKindStyle, AssetRecordType, AssetUrlsProvider, AssetUtil, AssetUtilRegistry, BINDING_MIGRATION_SEQUENCE_PREFIX, BUILTIN_ASSET_MIGRATION_SEQUENCE_PREFIX, BUILTIN_BINDING_MIGRATION_SEQUENCE_PREFIX, BUILTIN_SHAPE_MIGRATION_SEQUENCE_PREFIX, BaseBoxShapeUtil, BaseFrameLikeShapeUtil, BindingRecordType, BindingUtil, BoundsSnaps, Box, CANVAS_THEME_VARS, COLLABORATOR_INACTIVE_TIMEOUT, CURRENT_SESSION_SCHEMA_VERSION, CURSOR_TYPES, CUSTOM_RECORD_MIGRATION_SEQUENCE_PREFIX, CUSTOM_RECORD_TYPE_NAME, CameraRecordType, CameraStateTracker, Canvas, Circle2d, ClickManager, CollaboratorsManager, CommentReactionRecordType, CommentRecordType, CommentThreadRecordType, ContainerProvider, ContentElementManager, CubicBezier2d, CubicSpline2d, DEFAULT_ASSET_CONTEXT, DEFAULT_CAMERA_OPTIONS, DEFAULT_COLORS, DEFAULT_DARK_COLORS, DEFAULT_DASHES, DEFAULT_EDITOR_CONFIG, DEFAULT_FILLS, DEFAULT_FILL_TOKENS, DEFAULT_FONTS, DEFAULT_FONT_FAMILIES, DEFAULT_H_ALIGNS, DEFAULT_LIGHT_COLORS, DEFAULT_LINE_HEIGHT, DEFAULT_MENU_CONTEXT, DEFAULT_SHAPE_INDICATOR_OPTIONS, DEFAULT_SIZES, DEFAULT_TEXT_ALIGNS, DEFAULT_THEME, DEFAULT_TIME_CONTEXT, DEFAULT_V_ALIGNS, DIM_2D, DIM_3D, DOCUMENT_ID, DefaultBackground, DefaultCanvas, DefaultColorStyle, DefaultCursor, DefaultDashStyle, DefaultErrorFallback, DefaultFillStyle, DefaultFontFaces, DefaultFontFamilies, DefaultFontStyle, DefaultGrid, DefaultHorizontalAlignStyle, DefaultLabelColorStyle, DefaultShapeWrapper, DefaultSizeStyle, DefaultSpinner, DefaultSvgDefs, DefaultTextAlignStyle, DefaultVerticalAlignStyle, DictValidator, DocumentRecordType, EASINGS, ELBOW_ARROW_SNAP_MODES, EVENT_NAME_MAP, Edge2d, EdgeScrollManager, Editor, EditorAtom, EditorContext, EditorManager, EditorPortal, EditorProvider, ElbowArrowSnap, Ellipse2d, EnumStyleProp, ErrorBoundary, ErrorScreen, EventEmitter, FONT_SIZES, FontManager, GEO_SHAPE_KINDS, GeoShapeGeoStyle, Geometry2d, Geometry2dFilters, Group2d, HALF_PI, HANDLE_HIT_RADIUS, HTMLContainer, HandleSnaps, HandleTable, HistoryManager, INSTANCE_ID, ImageShapeCrop, InputsManager, InstancePageStateRecordType, InstancePresenceRecordType, InstanceRecordType, LIGHT_THEME, LINE_SPLINE_KINDS, LOCAL_STATE_PREFIX, LineShapeSplineStyle, LoadingScreen, MAX_TEXTURE_RESOLUTION, MAX_TEXTURE_ZOOM, Mat, MenuClickCapture, MenuManager, MocanvasUiProvider, ObjectValidator, OverlayManager, OverlayUtil, PI, PI2, PRESENCE_COLORS, PageRecordType, PerformanceApiAdapter, PerformanceManager, Point2d, PointerRecordType, Polygon2d, Polyline2d, ROTATE_CORNER_TO_SELECTION_CORNER, ROTATE_HANDLE_OFFSET, ReadonlySharedStyleMap, Rectangle2d, RootState, SHAPE_MIGRATION_SEQUENCE_PREFIX, SIDES, SIN, STROKE_SIZES, SVGContainer, ScribbleManager, ShapeIndicatorCompositor, ShapeRecordType, ShapeUtil, SharedStyleMap, SnapManager, Stadium2d, StateNode, StyleProp, SvgExportContextProvider, T, TAB_ID, TLEditorsRegistry, TLPOINTER_ID, TL_CANVAS_UI_COLOR_TYPES, TL_CURSOR_TYPES, TL_HANDLE_TYPES, TL_SCRIBBLE_STATES, TextManager, TextureManager, ThemeManager, Timers, TransformedGeometry2d, UNKNOWN_EDIT_START_INFO, USER_PREFERENCES_DEFAULTS, UnionValidator, UserPreferencesManager, UserRecordType, ValidationError, Validator, Vec, WebGL2Backend, angleDistance, animateShape, animateShapes, applyThemePatch, approximately, areAnglesCompatible, arrowBindingVersions, assetIdValidator, assetMigrations, assetPropsMigrationSequenceId, assetValidator, assetValidators, average, b64Vecs, bindingIdValidator, bindingPropsMigrationSequenceId, bookmarkAssetMigrations, bookmarkAssetProps, bookmarkAssetPropsValidator, bookmarkAssetValidator, boundsIndicatorPath, boxModelValidator, bucketTextureResolution, canBindShapes, canBuildIndicatorPaths, canCreateShape, canCreateShapes, canCropShape, canEditShape, canonicalizeRotation, canvasUiColorTypeValidator, centerOfCircleFromThreePoints, clamp, clampRadians, clockwiseAngleDist, commentAnchorValidator, commentReactionRecordConfig, commentReactionValidator, commentRecordConfig, commentSchemaRecords, commentThreadRecordConfig, commentThreadValidator, commentValidator, compressLegacySegments, coreShapes, counterClockwiseAngleDist, createAssetId, createAssetPropsMigrationIds, createAssetPropsMigrationSequence, createAssetValidator, createBackend, createBindingId, createBindingPropsMigrationIds, createBindingPropsMigrationSequence, createBindingValidator, createBuiltInAssetPropsMigrationIds, createBuiltInBindingPropsMigrationIds, createBuiltInShapePropsMigrationIds, createCachedUserResolve, createComment, createCommentId, createCommentReaction, createCommentReactionId, createCommentThread, createCommentThreadId, createCurrentUser, createCustomRecord, createCustomRecordId, createCustomRecordMigrationIds, createCustomRecordMigrationSequence, createCustomRecordMigrationSequences, createCustomRecordType, createCustomRecordTypeMap, createCustomRecordValidator, createDeepLinkString, createInMemoryAssetStore, createMemoryUserStore, createPresenceStateDerivation, createPropsMigrationSequences, createRootState, createSchema, createSessionStateSnapshotSignal, createShapeId, createShapePropsMigrationIds, createShapePropsMigrationSequence, createShapeValidator, createStore, createTLCurrentUser, createTLSchemaFromUtils, createTheme, createUserId, createUserPreferences, createUserRecordType, cursorTypeValidator, cursorValidator, customRecordMigrationSequenceId, dataUrlToFile, decodeDrawSegmentPath, defaultAssetMigrations, defaultAssetSchemas, defaultBindingSchemas, defaultShapeSchemas, defaultTldrawOptions, defaultUserPreferences, defaultUserStore, degreesToRadians, deselect, drawShapeSegmentValidator, dropShapesOnFrameLike, duplicatePage, easeInOutCubic, fileToBase64DataUrl, fileToDataUrl, findCommonAncestor, findShapeAncestor, fontKey, formatValidationPath, getArcMeasure, getAssetSrc, getBaseZoomForCameraOptions, getColorNamesFromThemes, getColorValue, getCulledShapes, getCurrentPageRenderingShapesSorted, getCurrentPageShapesInReadingOrder, getCursor, getCustomRecordIdType, getDefaultAssetContext, getDefaultCdnBaseUrl, getDefaultCrop, getDefaultDisplayValues, getDefaultUserPresence, getDefaultUserProperties, getDisplayValues, getDroppedShapesToNewParents, getEngineProvider, getExportImplementation, getFocusedGroup, getFocusedGroupId, getFontNamesFromThemes, getFontsFromRichText, getFrameLikeDropTarget, getFreshUserPreferences, getHandleHitRadius, getIncrementedName, getIndicatorSource, getInitialMetaForShape, getLocaleChain, getNearestAdjacentShape, getNotVisibleShapes, getOnlySelectedShapeId, getOverlayDisplayValues, getOwnerDocument, getOwnerWindow, getPageStates, getPaletteEntries, getPerfectDashProps, getPointInArcT, getPointOnCircle, getPointerInfo, getPointsOnArc, getPolygonVertices, getRenderingShapes, getSelectedShapeAtPoint, getSelectionHandlePositions, getSelectionRotatedPageBounds, getSelectionRotatedScreenBounds, getSelectionScreenBounds, getSessionStateSnapshot, getSessionStateSnapshotFromStore, getShapeAndDescendantIds, getShapeClipPath, getShapeHandles, getShapeIdsInsideBounds, getShapeIndicatorNode, getShapeIndicatorPath, getShapeMaskedPageBounds, getShapeStyleIfExists, getShapesPageBounds, getSharedOpacity, getSnapshot, getStylePropsOf, getSvgAsImage, getSvgPathFromPoints, getTextMeasureProvider, getThemeCssVars, getUncroppedSize, getUserPreferences, handleTypeValidator, hardReset, hardResetEditor, hasAncestor, hexToRgba, hitTestSelectionBounds, hitTestSelectionHandles, idValidator, imageAssetMigrations, imageAssetProps, imageAssetPropsValidator, imageAssetValidator, inlineBase64AssetStore, intersectCircleCircle, intersectCirclePolygon, intersectCirclePolyline, intersectLineSegmentCircle, intersectLineSegmentLineSegment, intersectLineSegmentPolygon, intersectLineSegmentPolyline, intersectPolygonBounds, intersectPolygonPolygon, isAncestorSelected, isAsset, isAssetId, isBinding, isBindingId, isCommentId, isCommentReactionId, isCommentThreadId, isCursorInViewport, isCustomRecord, isCustomRecordId, isDocument, isFullCrop, isInstancePresenceId, isOptionalValidator, isPage, isPageId, isPointInShape, isPropsMigrations, isSafeFloat, isShape, isShapeHidden, isShapeId, isShapeInPage, isUserId, isValidProps, kickoutOccludedShapes, lerp, linesIntersect, loadSessionStateSnapshotIntoStore, loadSnapshot, loopToHtmlElement, maybeSnapToGrid, mixHexColors, moveElementInto, moveShapesToPage, normalizeIndicatorPath, normalizeLoadedRecords, noteReactivePointerType, opacityValidator, openWindow, packShapes, pageIdValidator, parentIdValidator, parseDeepLinkString, perimeterOfEllipse, pointInPolygon, pointerValidator, polygonIntersectsPolyline, polygonsIntersect, popFocusedGroupId, precise, prefixError, preventDefault, radiansToDegrees, randomPresenceColor, rangeIntersection, refreshPage, refreshReactiveEnvironment, registerColorsFromThemes, registerCoreShape, registerDefaultAssetSchema, registerDefaultBindingSchema, registerDefaultShapeSchema, registerEngineProvider, registerExportImplementation, registerFontsFromThemes, registerTextMeasureImplementation, releasePointerCapture, resizeBox, resizeScaled, resizeToBounds, resolveAssetUrl, resolveLineHeightPx, resolveShape, resolveThemes, resolveUiMessage, richTextToPlainText, rootBindingMigrations, rootShapeMigrations, rotateSelectionHandle, runtime, sanitizeId, scribbleValidator, selectAdjacentShape, selectFirstChildShape, selectParentShape, setDefaultCdnBaseUrl, setFocusedGroup, setOpacityForNextShapes, setOpacityForSelectedShapes, setPointerCapture, setRuntimeOverrides, setUserPreferences, shapeIdValidator, shapePropsMigrationSequenceId, shortAngleDist, snapAngle, stopEventPropagation, strokeShapeIndicators, suffixSafeId, tleditors, tlenv, tlenvReactive, tlmenus, tltime, toCustomRecordMigrationSequence, toDomPrecision, toFixed, toMigrationSequence, toPrecision, trackPointer, uniq, updatePage, useActions, useAssetUrls, useColorMode, useContainer, useContainerIfExists, useCurrentTheme, useCurrentUser, useDelaySvgExport, useEditor, useEditorComponents, useEditorPortalHost, useGlobalMenuIsOpen, useIsCropping, useIsEditing, useIsToolSelected, useMaybeEditor, useMocanvasUi, usePassThroughWheelEvents, useSharedSafeId, useSvgExportContext, useTLSchemaFromUtils, useTLStore, useThemeColors, useThemeCssVars, useTools, useTransform, useUniqueSafeId, useViewportHeight, userIdValidator, userPreferencesValidator, userTypeValidator, userValidator, validateCustomRecordInfos, validateProps, vecModelValidator, videoAssetMigrations, videoAssetProps, videoAssetValidator, visitDescendants, withCoreShapes };
|
|
15717
|
+
export { ARROWHEAD_KINDS, ARROW_SHAPE_KINDS, ASSET_MIGRATION_SEQUENCE_PREFIX, Arc2d, ArrayOfValidator, ArrowShapeArrowheadEndStyle, ArrowShapeArrowheadStartStyle, ArrowShapeKindStyle, AssetRecordType, AssetUrlsProvider, AssetUtil, AssetUtilRegistry, BINDING_MIGRATION_SEQUENCE_PREFIX, BUILTIN_ASSET_MIGRATION_SEQUENCE_PREFIX, BUILTIN_BINDING_MIGRATION_SEQUENCE_PREFIX, BUILTIN_SHAPE_MIGRATION_SEQUENCE_PREFIX, BaseBoxShapeUtil, BaseFrameLikeShapeUtil, BindingRecordType, BindingUtil, BoundsSnaps, Box, CANVAS_THEME_VARS, COLLABORATOR_INACTIVE_TIMEOUT, CURRENT_SESSION_SCHEMA_VERSION, CURSOR_TYPES, CUSTOM_RECORD_MIGRATION_SEQUENCE_PREFIX, CUSTOM_RECORD_TYPE_NAME, CameraRecordType, CameraStateTracker, Canvas, Circle2d, ClickManager, CollaboratorsManager, CommentReactionRecordType, CommentRecordType, CommentThreadRecordType, ContainerProvider, ContentElementManager, CubicBezier2d, CubicSpline2d, DEFAULT_ASSET_CONTEXT, DEFAULT_CAMERA_OPTIONS, DEFAULT_COLORS, DEFAULT_DARK_COLORS, DEFAULT_DASHES, DEFAULT_EDITOR_CONFIG, DEFAULT_FILLS, DEFAULT_FILL_TOKENS, DEFAULT_FONTS, DEFAULT_FONT_FAMILIES, DEFAULT_H_ALIGNS, DEFAULT_LIGHT_COLORS, DEFAULT_LINE_HEIGHT, DEFAULT_MENU_CONTEXT, DEFAULT_PAGE_ID, DEFAULT_SHAPE_INDICATOR_OPTIONS, DEFAULT_SIZES, DEFAULT_TEXT_ALIGNS, DEFAULT_THEME, DEFAULT_TIME_CONTEXT, DEFAULT_V_ALIGNS, DIM_2D, DIM_3D, DOCUMENT_ID, DefaultBackground, DefaultCanvas, DefaultColorStyle, DefaultCursor, DefaultDashStyle, DefaultErrorFallback, DefaultFillStyle, DefaultFontFaces, DefaultFontFamilies, DefaultFontStyle, DefaultGrid, DefaultHorizontalAlignStyle, DefaultLabelColorStyle, DefaultShapeWrapper, DefaultSizeStyle, DefaultSpinner, DefaultSvgDefs, DefaultTextAlignStyle, DefaultVerticalAlignStyle, DictValidator, DocumentRecordType, EASINGS, ELBOW_ARROW_SNAP_MODES, EVENT_NAME_MAP, Edge2d, EdgeScrollManager, Editor, EditorAtom, EditorContext, EditorManager, EditorPortal, EditorProvider, ElbowArrowSnap, Ellipse2d, EnumStyleProp, ErrorBoundary, ErrorScreen, EventEmitter, FIRST_PAGE_INDEX, FONT_SIZES, FontManager, GEO_SHAPE_KINDS, GeoShapeGeoStyle, Geometry2d, Geometry2dFilters, Group2d, HALF_PI, HANDLE_HIT_RADIUS, HTMLContainer, HandleSnaps, HandleTable, HistoryManager, INSTANCE_ID, ImageShapeCrop, InputsManager, InstancePageStateRecordType, InstancePresenceRecordType, InstanceRecordType, LIGHT_THEME, LINE_SPLINE_KINDS, LOCAL_STATE_PREFIX, LineShapeSplineStyle, LoadingScreen, MAX_TEXTURE_RESOLUTION, MAX_TEXTURE_ZOOM, Mat, MenuClickCapture, MenuManager, MocanvasUiProvider, ObjectValidator, OverlayManager, OverlayUtil, PI, PI2, PRESENCE_COLORS, PageRecordType, PerformanceApiAdapter, PerformanceManager, Point2d, PointerRecordType, Polygon2d, Polyline2d, ROTATE_CORNER_TO_SELECTION_CORNER, ROTATE_HANDLE_OFFSET, ReadonlySharedStyleMap, Rectangle2d, RootState, SHAPE_MIGRATION_SEQUENCE_PREFIX, SIDES, SIN, STROKE_SIZES, SVGContainer, ScribbleManager, ShapeIndicatorCompositor, ShapeRecordType, ShapeUtil, SharedStyleMap, SnapManager, Stadium2d, StateNode, StyleProp, SvgExportContextProvider, T, TAB_ID, TLEditorsRegistry, TLPOINTER_ID, TL_CANVAS_UI_COLOR_TYPES, TL_CURSOR_TYPES, TL_HANDLE_TYPES, TL_SCRIBBLE_STATES, TextManager, TextureManager, ThemeManager, Timers, TransformedGeometry2d, UNKNOWN_EDIT_START_INFO, USER_PREFERENCES_DEFAULTS, UnionValidator, UserPreferencesManager, UserRecordType, ValidationError, Validator, Vec, WebGL2Backend, angleDistance, animateShape, animateShapes, applyThemePatch, approximately, areAnglesCompatible, arrowBindingVersions, assetIdValidator, assetMigrations, assetPropsMigrationSequenceId, assetValidator, assetValidators, average, b64Vecs, bindingIdValidator, bindingPropsMigrationSequenceId, bookmarkAssetMigrations, bookmarkAssetProps, bookmarkAssetPropsValidator, bookmarkAssetValidator, boundsIndicatorPath, boxModelValidator, bucketTextureResolution, canBindShapes, canBuildIndicatorPaths, canCreateShape, canCreateShapes, canCropShape, canEditShape, canonicalizeRotation, canvasUiColorTypeValidator, centerOfCircleFromThreePoints, clamp, clampRadians, clockwiseAngleDist, commentAnchorValidator, commentReactionRecordConfig, commentReactionValidator, commentRecordConfig, commentSchemaRecords, commentThreadRecordConfig, commentThreadValidator, commentValidator, compressLegacySegments, coreShapes, counterClockwiseAngleDist, createAssetId, createAssetPropsMigrationIds, createAssetPropsMigrationSequence, createAssetPropsValidator, createAssetValidator, createBackend, createBaseAssetValidator, createBaseBindingValidator, createBaseShapeValidator, createBindingId, createBindingPropsMigrationIds, createBindingPropsMigrationSequence, createBindingValidator, createBuiltInAssetPropsMigrationIds, createBuiltInBindingPropsMigrationIds, createBuiltInShapePropsMigrationIds, createCachedUserResolve, createComment, createCommentId, createCommentReaction, createCommentReactionId, createCommentThread, createCommentThreadId, createCurrentUser, createCustomRecord, createCustomRecordId, createCustomRecordMigrationIds, createCustomRecordMigrationSequence, createCustomRecordMigrationSequences, createCustomRecordType, createCustomRecordTypeMap, createCustomRecordValidator, createDeepLinkString, createInMemoryAssetStore, createMemoryUserStore, createPresenceStateDerivation, createPropsMigrationSequences, createRootState, createSchema, createSessionStateSnapshotSignal, createShapeId, createShapePropsMigrationIds, createShapePropsMigrationSequence, createShapeValidator, createStore, createTLCurrentUser, createTLSchemaFromUtils, createTheme, createUserId, createUserPreferences, createUserRecordType, cursorTypeValidator, cursorValidator, customRecordMigrationSequenceId, dataUrlToFile, decodeDrawSegmentPath, defaultAssetMigrations, defaultAssetSchemas, defaultBindingSchemas, defaultShapeSchemas, defaultTldrawOptions, defaultUserPreferences, defaultUserStore, degreesToRadians, deselect, drawShapeSegmentValidator, dropShapesOnFrameLike, duplicatePage, easeInOutCubic, fileToBase64DataUrl, fileToDataUrl, findCommonAncestor, findShapeAncestor, fontKey, formatValidationPath, getArcMeasure, getAssetSrc, getBaseZoomForCameraOptions, getColorNamesFromThemes, getColorValue, getCulledShapes, getCurrentPageRenderingShapesSorted, getCurrentPageShapesInReadingOrder, getCursor, getCustomRecordIdType, getDefaultAssetContext, getDefaultCdnBaseUrl, getDefaultCrop, getDefaultDisplayValues, getDefaultUserPresence, getDefaultUserProperties, getDisplayValues, getDroppedShapesToNewParents, getEngineProvider, getExportImplementation, getFocusedGroup, getFocusedGroupId, getFontNamesFromThemes, getFontsFromRichText, getFrameLikeDropTarget, getFreshUserPreferences, getHandleHitRadius, getIncrementedName, getIndicatorSource, getInitialMetaForShape, getLocaleChain, getNearestAdjacentShape, getNotVisibleShapes, getOnlySelectedShapeId, getOverlayDisplayValues, getOwnerDocument, getOwnerWindow, getPageStates, getPaletteEntries, getPerfectDashProps, getPointInArcT, getPointOnCircle, getPointerInfo, getPointsOnArc, getPolygonVertices, getRenderingShapes, getSelectedShapeAtPoint, getSelectionHandlePositions, getSelectionRotatedPageBounds, getSelectionRotatedScreenBounds, getSelectionScreenBounds, getSessionStateSnapshot, getSessionStateSnapshotFromStore, getShapeAndDescendantIds, getShapeClipPath, getShapeHandles, getShapeIdsInsideBounds, getShapeIndicatorNode, getShapeIndicatorPath, getShapeMaskedPageBounds, getShapeStyleIfExists, getShapesPageBounds, getSharedOpacity, getSnapshot, getStylePropsOf, getSvgAsImage, getSvgPathFromPoints, getTextMeasureProvider, getThemeCssVars, getUncroppedSize, getUserPreferences, handleTypeValidator, hardReset, hardResetEditor, hasAncestor, hexToRgba, hitTestSelectionBounds, hitTestSelectionHandles, idValidator, imageAssetMigrations, imageAssetProps, imageAssetPropsValidator, imageAssetValidator, inlineBase64AssetStore, intersectCircleCircle, intersectCirclePolygon, intersectCirclePolyline, intersectLineSegmentCircle, intersectLineSegmentLineSegment, intersectLineSegmentPolygon, intersectLineSegmentPolyline, intersectPolygonBounds, intersectPolygonPolygon, isAncestorSelected, isAsset, isAssetId, isBinding, isBindingId, isCommentId, isCommentReactionId, isCommentThreadId, isCursorInViewport, isCustomRecord, isCustomRecordId, isDocument, isFullCrop, isInstancePresenceId, isOptionalValidator, isPage, isPageId, isPointInShape, isPropsMigrations, isSafeFloat, isShape, isShapeHidden, isShapeId, isShapeInPage, isUserId, isValidProps, kickoutOccludedShapes, lerp, linesIntersect, loadSessionStateSnapshotIntoStore, loadSnapshot, loopToHtmlElement, maybeSnapToGrid, mixHexColors, moveElementInto, moveShapesToPage, normalizeIndicatorPath, normalizeLoadedRecords, noteReactivePointerType, opacityValidator, openWindow, packShapes, pageIdValidator, parentIdValidator, parseDeepLinkString, perimeterOfEllipse, pointInPolygon, pointerValidator, polygonIntersectsPolyline, polygonsIntersect, popFocusedGroupId, precise, prefixError, preventDefault, radiansToDegrees, randomPresenceColor, rangeIntersection, refreshPage, refreshReactiveEnvironment, registerColorsFromThemes, registerCoreShape, registerDefaultAssetSchema, registerDefaultBindingSchema, registerDefaultShapeSchema, registerEngineProvider, registerExportImplementation, registerFontsFromThemes, registerTextMeasureImplementation, releasePointerCapture, resizeBox, resizeScaled, resizeToBounds, resolveAssetUrl, resolveLineHeightPx, resolveShape, resolveThemes, resolveUiMessage, richTextToPlainText, rootBindingMigrations, rootShapeMigrations, rotateSelectionHandle, runtime, sanitizeId, scribbleValidator, selectAdjacentShape, selectFirstChildShape, selectParentShape, setDefaultCdnBaseUrl, setFocusedGroup, setOpacityForNextShapes, setOpacityForSelectedShapes, setPointerCapture, setRuntimeOverrides, setUserPreferences, shapeIdValidator, shapePropsMigrationSequenceId, shortAngleDist, snapAngle, stopEventPropagation, strokeShapeIndicators, suffixSafeId, tleditors, tlenv, tlenvReactive, tlmenus, tltime, toCustomRecordMigrationSequence, toDomPrecision, toFixed, toMigrationSequence, toPrecision, trackPointer, uniq, updatePage, useActions, useAssetUrls, useColorMode, useContainer, useContainerIfExists, useCurrentTheme, useCurrentUser, useDelaySvgExport, useEditor, useEditorComponents, useEditorPortalHost, useGlobalMenuIsOpen, useIsCropping, useIsEditing, useIsToolSelected, useMaybeEditor, useMocanvasUi, usePassThroughWheelEvents, useSharedSafeId, useSvgExportContext, useTLSchemaFromUtils, useTLStore, useThemeColors, useThemeCssVars, useTools, useTransform, useUniqueSafeId, useViewportHeight, userIdValidator, userPreferencesValidator, userTypeValidator, userValidator, validateCustomRecordInfos, validateProps, vecModelValidator, videoAssetMigrations, videoAssetProps, videoAssetValidator, visitDescendants, warnOnce, withCoreShapes };
|
|
15422
15718
|
//# sourceMappingURL=index.js.map
|
|
15423
15719
|
//# sourceMappingURL=index.js.map
|