@tldraw/editor 4.6.0-next.30b99cd52fc8 → 4.6.0-next.35cf541abcf9
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/dist-cjs/index.d.ts +758 -96
- package/dist-cjs/index.js +18 -3
- package/dist-cjs/index.js.map +3 -3
- package/dist-cjs/lib/TldrawEditor.js +55 -12
- package/dist-cjs/lib/TldrawEditor.js.map +3 -3
- package/dist-cjs/lib/components/LiveCollaborators.js +1 -0
- package/dist-cjs/lib/components/LiveCollaborators.js.map +2 -2
- package/dist-cjs/lib/components/MenuClickCapture.js +99 -38
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +10 -3
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +3 -3
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +5 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +1 -0
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js +7 -0
- package/dist-cjs/lib/config/createTLStore.js.map +2 -2
- package/dist-cjs/lib/config/defaultAssets.js +36 -0
- package/dist-cjs/lib/config/defaultAssets.js.map +7 -0
- package/dist-cjs/lib/editor/Editor.js +279 -10
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/assets/AssetUtil.js +67 -0
- package/dist-cjs/lib/editor/assets/AssetUtil.js.map +7 -0
- package/dist-cjs/lib/editor/bindings/BindingUtil.js +1 -0
- package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +1 -1
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -0
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +1 -0
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js +1 -0
- package/dist-cjs/lib/editor/managers/FocusManager/FocusManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js +2 -0
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +2 -0
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +12 -0
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.js +80 -0
- package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.js.map +7 -0
- package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js +466 -0
- package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/PerformanceManager/perf-types.js +17 -0
- package/dist-cjs/lib/editor/managers/PerformanceManager/perf-types.js.map +7 -0
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +1 -0
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +1 -0
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js +1 -0
- package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +2 -1
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +1 -0
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +1 -0
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js +107 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js +586 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js.map +7 -0
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -0
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +8 -4
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +76 -0
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +7 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +22 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +1 -1
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js +6 -0
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +15 -17
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/editor/types/SvgExportContext.js.map +2 -2
- package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
- package/dist-cjs/lib/exports/ExportDelay.js +1 -0
- package/dist-cjs/lib/exports/ExportDelay.js.map +1 -1
- package/dist-cjs/lib/exports/StyleEmbedder.js +1 -0
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js +14 -8
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/globals/environment.js +18 -1
- package/dist-cjs/lib/globals/environment.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +25 -4
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/{useIsDarkMode.js → useColorMode.js} +14 -10
- package/dist-cjs/lib/hooks/useColorMode.js.map +7 -0
- package/dist-cjs/lib/hooks/useCursor.js +3 -7
- package/dist-cjs/lib/hooks/useCursor.js.map +2 -2
- package/dist-cjs/lib/hooks/useDarkMode.js +4 -4
- package/dist-cjs/lib/hooks/useDarkMode.js.map +2 -2
- package/dist-cjs/lib/options.js +2 -0
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +3 -0
- package/dist-cjs/lib/primitives/Vec.js.map +1 -1
- package/dist-cjs/lib/primitives/geometry/Circle2d.js +1 -0
- package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +1 -1
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +1 -0
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +1 -1
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +2 -0
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +1 -1
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js +1 -0
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +1 -1
- package/dist-cjs/lib/utils/EditorAtom.js +2 -0
- package/dist-cjs/lib/utils/EditorAtom.js.map +1 -1
- package/dist-cjs/lib/utils/reparenting.js +2 -1
- package/dist-cjs/lib/utils/reparenting.js.map +2 -2
- package/dist-cjs/lib/utils/richText.js.map +2 -2
- package/dist-cjs/lib/utils/runtime.js +2 -1
- package/dist-cjs/lib/utils/runtime.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +2 -0
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +1 -1
- package/dist-cjs/lib/utils/sync/hardReset.js +0 -8
- package/dist-cjs/lib/utils/sync/hardReset.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +758 -96
- package/dist-esm/index.mjs +19 -6
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +58 -12
- package/dist-esm/lib/TldrawEditor.mjs.map +3 -3
- package/dist-esm/lib/components/LiveCollaborators.mjs +1 -0
- package/dist-esm/lib/components/LiveCollaborators.mjs.map +2 -2
- package/dist-esm/lib/components/MenuClickCapture.mjs +100 -39
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +10 -3
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +3 -3
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +5 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +1 -0
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs +10 -1
- package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
- package/dist-esm/lib/config/defaultAssets.mjs +16 -0
- package/dist-esm/lib/config/defaultAssets.mjs.map +7 -0
- package/dist-esm/lib/editor/Editor.mjs +279 -10
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/assets/AssetUtil.mjs +47 -0
- package/dist-esm/lib/editor/assets/AssetUtil.mjs.map +7 -0
- package/dist-esm/lib/editor/bindings/BindingUtil.mjs +1 -0
- package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/FocusManager/FocusManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs +2 -0
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +2 -0
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +12 -0
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.mjs +60 -0
- package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs +438 -0
- package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/PerformanceManager/perf-types.mjs +1 -0
- package/dist-esm/lib/editor/managers/PerformanceManager/perf-types.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +1 -0
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs +1 -0
- package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +2 -1
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs +89 -0
- package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs +568 -0
- package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -0
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +8 -4
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +56 -0
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +7 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +22 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +1 -1
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs +6 -0
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +15 -17
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/editor/types/SvgExportContext.mjs.map +2 -2
- package/dist-esm/lib/exports/ExportDelay.mjs +1 -0
- package/dist-esm/lib/exports/ExportDelay.mjs.map +1 -1
- package/dist-esm/lib/exports/StyleEmbedder.mjs +1 -0
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +1 -1
- package/dist-esm/lib/exports/getSvgJsx.mjs +14 -11
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/globals/environment.mjs +18 -1
- package/dist-esm/lib/globals/environment.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +25 -4
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useColorMode.mjs +19 -0
- package/dist-esm/lib/hooks/useColorMode.mjs.map +7 -0
- package/dist-esm/lib/hooks/useCursor.mjs +3 -7
- package/dist-esm/lib/hooks/useCursor.mjs.map +2 -2
- package/dist-esm/lib/hooks/useDarkMode.mjs +4 -4
- package/dist-esm/lib/hooks/useDarkMode.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +2 -0
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +3 -0
- package/dist-esm/lib/primitives/Vec.mjs.map +1 -1
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs +1 -0
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +1 -1
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +1 -0
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +1 -1
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +2 -0
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +1 -1
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +1 -0
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +1 -1
- package/dist-esm/lib/utils/EditorAtom.mjs +2 -0
- package/dist-esm/lib/utils/EditorAtom.mjs.map +1 -1
- package/dist-esm/lib/utils/reparenting.mjs +2 -1
- package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
- package/dist-esm/lib/utils/richText.mjs.map +2 -2
- package/dist-esm/lib/utils/runtime.mjs +2 -1
- package/dist-esm/lib/utils/runtime.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +2 -0
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +1 -1
- package/dist-esm/lib/utils/sync/hardReset.mjs +0 -8
- package/dist-esm/lib/utils/sync/hardReset.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +0 -37
- package/package.json +7 -7
- package/src/index.ts +24 -6
- package/src/lib/TldrawEditor.tsx +90 -13
- package/src/lib/components/LiveCollaborators.tsx +8 -2
- package/src/lib/components/MenuClickCapture.tsx +129 -49
- package/src/lib/components/default-components/CanvasShapeIndicators.tsx +14 -3
- package/src/lib/components/default-components/DefaultCanvas.tsx +6 -2
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +2 -2
- package/src/lib/components/default-components/DefaultShapeIndicators.tsx +2 -0
- package/src/lib/config/createTLStore.ts +22 -1
- package/src/lib/config/defaultAssets.ts +19 -0
- package/src/lib/editor/Editor.ts +387 -40
- package/src/lib/editor/assets/AssetUtil.ts +85 -0
- package/src/lib/editor/managers/FontManager/FontManager.test.ts +9 -2
- package/src/lib/editor/managers/FontManager/FontManager.ts +1 -67
- package/src/lib/editor/managers/InputsManager/InputsManager.ts +12 -0
- package/src/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.ts +82 -0
- package/src/lib/editor/managers/PerformanceManager/PerformanceManager.test.ts +522 -0
- package/src/lib/editor/managers/PerformanceManager/PerformanceManager.ts +583 -0
- package/src/lib/editor/managers/PerformanceManager/perf-types.ts +196 -0
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +13 -2
- package/src/lib/editor/managers/SnapManager/SnapManager.ts +1 -1
- package/src/lib/editor/managers/ThemeManager/ThemeManager.ts +116 -0
- package/src/lib/editor/managers/ThemeManager/defaultThemes.ts +605 -0
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +23 -29
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +5 -3
- package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +121 -0
- package/src/lib/editor/shapes/ShapeUtil.ts +39 -3
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -1
- package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +7 -0
- package/src/lib/editor/tools/StateNode.ts +16 -18
- package/src/lib/editor/types/SvgExportContext.tsx +5 -0
- package/src/lib/editor/types/external-content.ts +1 -0
- package/src/lib/exports/getSvgJsx.tsx +23 -16
- package/src/lib/globals/environment.ts +18 -0
- package/src/lib/hooks/useCanvasEvents.ts +40 -3
- package/src/lib/hooks/{useIsDarkMode.ts → useColorMode.ts} +9 -5
- package/src/lib/hooks/useCursor.ts +3 -7
- package/src/lib/hooks/useDarkMode.ts +4 -4
- package/src/lib/options.ts +14 -0
- package/src/lib/utils/reparenting.ts +6 -2
- package/src/lib/utils/richText.ts +1 -1
- package/src/lib/utils/runtime.ts +3 -1
- package/src/lib/utils/sync/hardReset.ts +0 -8
- package/src/version.ts +3 -3
- package/dist-cjs/lib/hooks/useIsDarkMode.js.map +0 -7
- package/dist-esm/lib/hooks/useIsDarkMode.mjs +0 -15
- package/dist-esm/lib/hooks/useIsDarkMode.mjs.map +0 -7
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
import { bind } from "@tldraw/utils";
|
|
12
|
+
import EventEmitter from "eventemitter3";
|
|
13
|
+
function percentile(sorted, p) {
|
|
14
|
+
const idx = Math.ceil(p * sorted.length) - 1;
|
|
15
|
+
return sorted[Math.max(0, idx)];
|
|
16
|
+
}
|
|
17
|
+
function computeFrameTimeStats(frameTimes) {
|
|
18
|
+
if (frameTimes.length === 0) return { avg: 0, median: 0, p95: 0, p99: 0, min: 0, max: 0 };
|
|
19
|
+
const sorted = [...frameTimes].sort((a, b) => a - b);
|
|
20
|
+
const sum = sorted.reduce((a, b) => a + b, 0);
|
|
21
|
+
return {
|
|
22
|
+
avg: sum / sorted.length,
|
|
23
|
+
median: percentile(sorted, 0.5),
|
|
24
|
+
p95: percentile(sorted, 0.95),
|
|
25
|
+
p99: percentile(sorted, 0.99),
|
|
26
|
+
min: sorted[0],
|
|
27
|
+
max: sorted[sorted.length - 1]
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function toLoafEntry(entry) {
|
|
31
|
+
const e = entry;
|
|
32
|
+
if (typeof e.duration !== "number") return null;
|
|
33
|
+
return {
|
|
34
|
+
startTime: e.startTime,
|
|
35
|
+
duration: e.duration,
|
|
36
|
+
blockingDuration: e.blockingDuration ?? 0,
|
|
37
|
+
scripts: (e.scripts ?? []).map((s) => ({
|
|
38
|
+
sourceURL: s.sourceURL ?? "",
|
|
39
|
+
invoker: s.invoker ?? "",
|
|
40
|
+
duration: s.duration ?? 0
|
|
41
|
+
}))
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
class PerformanceManager {
|
|
45
|
+
/** @internal */
|
|
46
|
+
emitter = new EventEmitter();
|
|
47
|
+
editor;
|
|
48
|
+
// Active interaction tracking
|
|
49
|
+
activeInteraction = null;
|
|
50
|
+
// Active camera tracking
|
|
51
|
+
activeCamera = null;
|
|
52
|
+
// Lazy listener cleanup functions
|
|
53
|
+
frameCleanup = null;
|
|
54
|
+
shapeCreatedCleanup = null;
|
|
55
|
+
shapeEditedCleanup = null;
|
|
56
|
+
shapeDeletedCleanup = null;
|
|
57
|
+
// LoAF observer
|
|
58
|
+
loafObserver = null;
|
|
59
|
+
constructor(editor) {
|
|
60
|
+
this.editor = editor;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Subscribe to a performance event. Returns an unsubscribe function.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* const unsub = editor.performance.on('interaction-end', (event) => {
|
|
68
|
+
* sendToAnalytics({ name: event.name, fps: event.fps, p95: event.p95FrameTime })
|
|
69
|
+
* })
|
|
70
|
+
* // later: unsub()
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
on(event, fn) {
|
|
76
|
+
this.emitter.on(event, fn);
|
|
77
|
+
this._maybeAttachLazyListeners(event);
|
|
78
|
+
return () => {
|
|
79
|
+
this.emitter.off(event, fn);
|
|
80
|
+
this._maybeDetachLazyListeners(event);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Subscribe to a performance event once. The listener is removed after the first invocation.
|
|
85
|
+
* Returns an unsubscribe function for early removal.
|
|
86
|
+
*
|
|
87
|
+
* @public
|
|
88
|
+
*/
|
|
89
|
+
once(event, fn) {
|
|
90
|
+
const wrapped = (...args) => {
|
|
91
|
+
;
|
|
92
|
+
fn(...args);
|
|
93
|
+
this._maybeDetachLazyListeners(event);
|
|
94
|
+
};
|
|
95
|
+
this.emitter.once(event, wrapped);
|
|
96
|
+
this._maybeAttachLazyListeners(event);
|
|
97
|
+
return () => {
|
|
98
|
+
this.emitter.off(event, wrapped);
|
|
99
|
+
this._maybeDetachLazyListeners(event);
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/** @internal */
|
|
103
|
+
dispose() {
|
|
104
|
+
if (this.activeCamera?.timeout) clearTimeout(this.activeCamera.timeout);
|
|
105
|
+
this.activeInteraction = null;
|
|
106
|
+
this.activeCamera = null;
|
|
107
|
+
this.frameCleanup?.();
|
|
108
|
+
this.frameCleanup = null;
|
|
109
|
+
this.shapeCreatedCleanup?.();
|
|
110
|
+
this.shapeCreatedCleanup = null;
|
|
111
|
+
this.shapeEditedCleanup?.();
|
|
112
|
+
this.shapeEditedCleanup = null;
|
|
113
|
+
this.shapeDeletedCleanup?.();
|
|
114
|
+
this.shapeDeletedCleanup = null;
|
|
115
|
+
this._stopLoafObserver();
|
|
116
|
+
this.emitter.removeAllListeners();
|
|
117
|
+
}
|
|
118
|
+
// --- Internal notification methods ---
|
|
119
|
+
/** @internal */
|
|
120
|
+
_notifyInteractionStart(name, path) {
|
|
121
|
+
if (this.emitter.listenerCount("interaction-start") === 0 && this.emitter.listenerCount("interaction-end") === 0) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (this.activeInteraction) {
|
|
125
|
+
console.warn(
|
|
126
|
+
`[tldraw] New interaction '${name}' started while '${this.activeInteraction.name}' was still active`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
const selectedShapeTypes = {};
|
|
130
|
+
for (const shape of this.editor.getSelectedShapes()) {
|
|
131
|
+
selectedShapeTypes[shape.type] = (selectedShapeTypes[shape.type] || 0) + 1;
|
|
132
|
+
}
|
|
133
|
+
this.activeInteraction = {
|
|
134
|
+
name,
|
|
135
|
+
path,
|
|
136
|
+
startTime: performance.now(),
|
|
137
|
+
frameTimes: [],
|
|
138
|
+
selectedShapeTypes,
|
|
139
|
+
loafEntries: []
|
|
140
|
+
};
|
|
141
|
+
const event = {
|
|
142
|
+
name,
|
|
143
|
+
path,
|
|
144
|
+
timestamp: performance.now()
|
|
145
|
+
};
|
|
146
|
+
this.emitter.emit("interaction-start", event);
|
|
147
|
+
}
|
|
148
|
+
/** @internal */
|
|
149
|
+
_notifyInteractionEnd() {
|
|
150
|
+
const interaction = this.activeInteraction;
|
|
151
|
+
if (!interaction) return;
|
|
152
|
+
this.activeInteraction = null;
|
|
153
|
+
if (this.emitter.listenerCount("interaction-end") === 0) return;
|
|
154
|
+
const duration = performance.now() - interaction.startTime;
|
|
155
|
+
const stats = computeFrameTimeStats(interaction.frameTimes);
|
|
156
|
+
const event = {
|
|
157
|
+
name: interaction.name,
|
|
158
|
+
path: interaction.path,
|
|
159
|
+
duration,
|
|
160
|
+
fps: interaction.frameTimes.length > 0 ? interaction.frameTimes.length / duration * 1e3 : 0,
|
|
161
|
+
frameCount: interaction.frameTimes.length,
|
|
162
|
+
avgFrameTime: stats.avg,
|
|
163
|
+
medianFrameTime: stats.median,
|
|
164
|
+
p95FrameTime: stats.p95,
|
|
165
|
+
p99FrameTime: stats.p99,
|
|
166
|
+
minFrameTime: stats.min,
|
|
167
|
+
maxFrameTime: stats.max,
|
|
168
|
+
frameTimes: interaction.frameTimes,
|
|
169
|
+
shapeCount: this.editor.getCurrentPageShapeIds().size,
|
|
170
|
+
selectedShapeTypes: interaction.selectedShapeTypes,
|
|
171
|
+
longAnimationFrames: interaction.loafEntries.length > 0 ? interaction.loafEntries : void 0,
|
|
172
|
+
zoomLevel: this.editor.getCamera().z,
|
|
173
|
+
timestamp: performance.now()
|
|
174
|
+
};
|
|
175
|
+
this.emitter.emit("interaction-end", event);
|
|
176
|
+
}
|
|
177
|
+
/** @internal */
|
|
178
|
+
_notifyCameraOperation(type) {
|
|
179
|
+
if (this.emitter.listenerCount("camera-start") === 0 && this.emitter.listenerCount("camera-end") === 0) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (this.activeCamera) {
|
|
183
|
+
if (this.activeCamera.timeout) {
|
|
184
|
+
clearTimeout(this.activeCamera.timeout);
|
|
185
|
+
}
|
|
186
|
+
if (this.activeCamera.type !== type) {
|
|
187
|
+
this._endCameraSession();
|
|
188
|
+
this._startCameraSession(type);
|
|
189
|
+
} else {
|
|
190
|
+
this.activeCamera.timeout = this.editor.timers.setTimeout(
|
|
191
|
+
() => this._endCameraSession(),
|
|
192
|
+
50
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
this._startCameraSession(type);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/** @internal */
|
|
200
|
+
_notifyUndoRedo(type, undoDepth, redoDepth) {
|
|
201
|
+
if (this.emitter.listenerCount(type) === 0) return;
|
|
202
|
+
const event = {
|
|
203
|
+
type,
|
|
204
|
+
undoDepth,
|
|
205
|
+
redoDepth
|
|
206
|
+
};
|
|
207
|
+
this.emitter.emit(type, event);
|
|
208
|
+
}
|
|
209
|
+
// --- Private helpers ---
|
|
210
|
+
_startCameraSession(type) {
|
|
211
|
+
this.activeCamera = {
|
|
212
|
+
type,
|
|
213
|
+
startTime: performance.now(),
|
|
214
|
+
frameTimes: [],
|
|
215
|
+
timeout: this.editor.timers.setTimeout(() => this._endCameraSession(), 50),
|
|
216
|
+
loafEntries: []
|
|
217
|
+
};
|
|
218
|
+
if (this.emitter.listenerCount("camera-start") > 0) {
|
|
219
|
+
const event = {
|
|
220
|
+
type,
|
|
221
|
+
timestamp: performance.now()
|
|
222
|
+
};
|
|
223
|
+
this.emitter.emit("camera-start", event);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
_endCameraSession() {
|
|
227
|
+
const camera = this.activeCamera;
|
|
228
|
+
if (!camera) return;
|
|
229
|
+
this.activeCamera = null;
|
|
230
|
+
if (camera.timeout) clearTimeout(camera.timeout);
|
|
231
|
+
if (this.emitter.listenerCount("camera-end") === 0) return;
|
|
232
|
+
const duration = performance.now() - camera.startTime;
|
|
233
|
+
const stats = computeFrameTimeStats(camera.frameTimes);
|
|
234
|
+
const viewportBounds = this.editor.getViewportScreenBounds();
|
|
235
|
+
const totalShapes = this.editor.getCurrentPageShapeIds().size;
|
|
236
|
+
const culledShapeCount = this.editor.getCulledShapes().size;
|
|
237
|
+
const event = {
|
|
238
|
+
type: camera.type,
|
|
239
|
+
duration,
|
|
240
|
+
fps: camera.frameTimes.length > 0 ? camera.frameTimes.length / duration * 1e3 : 0,
|
|
241
|
+
frameCount: camera.frameTimes.length,
|
|
242
|
+
avgFrameTime: stats.avg,
|
|
243
|
+
medianFrameTime: stats.median,
|
|
244
|
+
p95FrameTime: stats.p95,
|
|
245
|
+
p99FrameTime: stats.p99,
|
|
246
|
+
minFrameTime: stats.min,
|
|
247
|
+
maxFrameTime: stats.max,
|
|
248
|
+
frameTimes: camera.frameTimes,
|
|
249
|
+
shapeCount: totalShapes,
|
|
250
|
+
viewportWidth: viewportBounds.w,
|
|
251
|
+
viewportHeight: viewportBounds.h,
|
|
252
|
+
longAnimationFrames: camera.loafEntries.length > 0 ? camera.loafEntries : void 0,
|
|
253
|
+
visibleShapeCount: totalShapes - culledShapeCount,
|
|
254
|
+
culledShapeCount,
|
|
255
|
+
zoomLevel: this.editor.getCamera().z,
|
|
256
|
+
timestamp: performance.now()
|
|
257
|
+
};
|
|
258
|
+
this.emitter.emit("camera-end", event);
|
|
259
|
+
}
|
|
260
|
+
_onFrame(elapsed) {
|
|
261
|
+
if (this.activeInteraction) {
|
|
262
|
+
this.activeInteraction.frameTimes.push(elapsed);
|
|
263
|
+
}
|
|
264
|
+
if (this.activeCamera) {
|
|
265
|
+
this.activeCamera.frameTimes.push(elapsed);
|
|
266
|
+
}
|
|
267
|
+
if (this.emitter.listenerCount("frame") > 0) {
|
|
268
|
+
const totalShapes = this.editor.getCurrentPageShapeIds().size;
|
|
269
|
+
const culledShapes = this.editor.getCulledShapes();
|
|
270
|
+
const culledCount = culledShapes.size;
|
|
271
|
+
const event = {
|
|
272
|
+
elapsed,
|
|
273
|
+
shapeCount: totalShapes,
|
|
274
|
+
culledShapeCount: culledCount,
|
|
275
|
+
visibleShapeCount: totalShapes - culledCount
|
|
276
|
+
};
|
|
277
|
+
this.emitter.emit("frame", event);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
_onShapesCreated(records) {
|
|
281
|
+
if (this.emitter.listenerCount("shapes-created") === 0) return;
|
|
282
|
+
const shapeTypes = {};
|
|
283
|
+
for (const record of records) {
|
|
284
|
+
if (record.typeName === "shape") {
|
|
285
|
+
shapeTypes[record.type] = (shapeTypes[record.type] || 0) + 1;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
const count = Object.values(shapeTypes).reduce((a, b) => a + b, 0);
|
|
289
|
+
if (count === 0) return;
|
|
290
|
+
const event = {
|
|
291
|
+
operation: "create",
|
|
292
|
+
count,
|
|
293
|
+
shapeTypes,
|
|
294
|
+
timestamp: performance.now()
|
|
295
|
+
};
|
|
296
|
+
this.emitter.emit("shapes-created", event);
|
|
297
|
+
}
|
|
298
|
+
_onShapesEdited(records) {
|
|
299
|
+
if (this.emitter.listenerCount("shapes-updated") === 0) return;
|
|
300
|
+
const shapeTypes = {};
|
|
301
|
+
for (const record of records) {
|
|
302
|
+
if (record.typeName === "shape") {
|
|
303
|
+
shapeTypes[record.type] = (shapeTypes[record.type] || 0) + 1;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const count = Object.values(shapeTypes).reduce((a, b) => a + b, 0);
|
|
307
|
+
if (count === 0) return;
|
|
308
|
+
const event = {
|
|
309
|
+
operation: "update",
|
|
310
|
+
count,
|
|
311
|
+
shapeTypes,
|
|
312
|
+
timestamp: performance.now()
|
|
313
|
+
};
|
|
314
|
+
this.emitter.emit("shapes-updated", event);
|
|
315
|
+
}
|
|
316
|
+
_onShapesDeleted(ids) {
|
|
317
|
+
if (this.emitter.listenerCount("shapes-deleted") === 0) return;
|
|
318
|
+
const shapeTypes = {};
|
|
319
|
+
for (const id of ids) {
|
|
320
|
+
const shape = this.editor.getShape(id);
|
|
321
|
+
if (shape) {
|
|
322
|
+
shapeTypes[shape.type] = (shapeTypes[shape.type] || 0) + 1;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
const event = {
|
|
326
|
+
operation: "delete",
|
|
327
|
+
count: ids.length,
|
|
328
|
+
shapeTypes,
|
|
329
|
+
timestamp: performance.now()
|
|
330
|
+
};
|
|
331
|
+
this.emitter.emit("shapes-deleted", event);
|
|
332
|
+
}
|
|
333
|
+
// --- LoAF observer ---
|
|
334
|
+
_startLoafObserver() {
|
|
335
|
+
if (typeof PerformanceObserver === "undefined") return;
|
|
336
|
+
try {
|
|
337
|
+
const supported = PerformanceObserver.supportedEntryTypes;
|
|
338
|
+
if (!supported?.includes("long-animation-frame")) return;
|
|
339
|
+
} catch {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
this.loafObserver = new PerformanceObserver((list) => {
|
|
343
|
+
const isInteractionActive = this.activeInteraction !== null;
|
|
344
|
+
const isCameraActive = this.activeCamera !== null;
|
|
345
|
+
if (!isInteractionActive && !isCameraActive) return;
|
|
346
|
+
for (const entry of list.getEntries()) {
|
|
347
|
+
const loaf = toLoafEntry(entry);
|
|
348
|
+
if (!loaf) continue;
|
|
349
|
+
if (isInteractionActive) {
|
|
350
|
+
this.activeInteraction.loafEntries.push(loaf);
|
|
351
|
+
}
|
|
352
|
+
if (isCameraActive) {
|
|
353
|
+
this.activeCamera.loafEntries.push(loaf);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
this.loafObserver.observe({ type: "long-animation-frame", buffered: false });
|
|
358
|
+
}
|
|
359
|
+
_stopLoafObserver() {
|
|
360
|
+
if (this.loafObserver) {
|
|
361
|
+
this.loafObserver.disconnect();
|
|
362
|
+
this.loafObserver = null;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
// --- Lazy listener management ---
|
|
366
|
+
_needsFrameListener() {
|
|
367
|
+
return this.emitter.listenerCount("frame") > 0 || this.emitter.listenerCount("interaction-start") > 0 || this.emitter.listenerCount("interaction-end") > 0 || this.emitter.listenerCount("camera-start") > 0 || this.emitter.listenerCount("camera-end") > 0;
|
|
368
|
+
}
|
|
369
|
+
_needsLoafObserver() {
|
|
370
|
+
return this.emitter.listenerCount("interaction-end") > 0 || this.emitter.listenerCount("camera-end") > 0;
|
|
371
|
+
}
|
|
372
|
+
_maybeAttachLazyListeners(event) {
|
|
373
|
+
if (!this.frameCleanup && (event === "frame" || event === "interaction-start" || event === "interaction-end" || event === "camera-start" || event === "camera-end")) {
|
|
374
|
+
if (this._needsFrameListener()) {
|
|
375
|
+
this.editor.on("frame", this._onFrame);
|
|
376
|
+
this.frameCleanup = () => this.editor.off("frame", this._onFrame);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
if (!this.loafObserver && (event === "interaction-end" || event === "camera-end")) {
|
|
380
|
+
if (this._needsLoafObserver()) {
|
|
381
|
+
this._startLoafObserver();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (!this.shapeCreatedCleanup && event === "shapes-created") {
|
|
385
|
+
this.editor.on("created-shapes", this._onShapesCreated);
|
|
386
|
+
this.shapeCreatedCleanup = () => this.editor.off("created-shapes", this._onShapesCreated);
|
|
387
|
+
}
|
|
388
|
+
if (!this.shapeEditedCleanup && event === "shapes-updated") {
|
|
389
|
+
this.editor.on("edited-shapes", this._onShapesEdited);
|
|
390
|
+
this.shapeEditedCleanup = () => this.editor.off("edited-shapes", this._onShapesEdited);
|
|
391
|
+
}
|
|
392
|
+
if (!this.shapeDeletedCleanup && event === "shapes-deleted") {
|
|
393
|
+
this.editor.on("deleted-shapes", this._onShapesDeleted);
|
|
394
|
+
this.shapeDeletedCleanup = () => this.editor.off("deleted-shapes", this._onShapesDeleted);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
_maybeDetachLazyListeners(event) {
|
|
398
|
+
if (this.frameCleanup && (event === "frame" || event === "interaction-start" || event === "interaction-end" || event === "camera-start" || event === "camera-end")) {
|
|
399
|
+
if (!this._needsFrameListener()) {
|
|
400
|
+
this.frameCleanup();
|
|
401
|
+
this.frameCleanup = null;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (this.loafObserver && (event === "interaction-end" || event === "camera-end")) {
|
|
405
|
+
if (!this._needsLoafObserver()) {
|
|
406
|
+
this._stopLoafObserver();
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
if (this.shapeCreatedCleanup && event === "shapes-created" && this.emitter.listenerCount("shapes-created") === 0) {
|
|
410
|
+
this.shapeCreatedCleanup();
|
|
411
|
+
this.shapeCreatedCleanup = null;
|
|
412
|
+
}
|
|
413
|
+
if (this.shapeEditedCleanup && event === "shapes-updated" && this.emitter.listenerCount("shapes-updated") === 0) {
|
|
414
|
+
this.shapeEditedCleanup();
|
|
415
|
+
this.shapeEditedCleanup = null;
|
|
416
|
+
}
|
|
417
|
+
if (this.shapeDeletedCleanup && event === "shapes-deleted" && this.emitter.listenerCount("shapes-deleted") === 0) {
|
|
418
|
+
this.shapeDeletedCleanup();
|
|
419
|
+
this.shapeDeletedCleanup = null;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
__decorateClass([
|
|
424
|
+
bind
|
|
425
|
+
], PerformanceManager.prototype, "_onFrame", 1);
|
|
426
|
+
__decorateClass([
|
|
427
|
+
bind
|
|
428
|
+
], PerformanceManager.prototype, "_onShapesCreated", 1);
|
|
429
|
+
__decorateClass([
|
|
430
|
+
bind
|
|
431
|
+
], PerformanceManager.prototype, "_onShapesEdited", 1);
|
|
432
|
+
__decorateClass([
|
|
433
|
+
bind
|
|
434
|
+
], PerformanceManager.prototype, "_onShapesDeleted", 1);
|
|
435
|
+
export {
|
|
436
|
+
PerformanceManager
|
|
437
|
+
};
|
|
438
|
+
//# sourceMappingURL=PerformanceManager.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/lib/editor/managers/PerformanceManager/PerformanceManager.ts"],
|
|
4
|
+
"sourcesContent": ["import type { TLRecord, TLShapeId } from '@tldraw/tlschema'\nimport { bind } from '@tldraw/utils'\nimport EventEmitter from 'eventemitter3'\nimport type { Editor } from '../../Editor'\nimport type {\n\tTLCameraEndPerfEvent,\n\tTLCameraStartPerfEvent,\n\tTLFramePerfEvent,\n\tTLInteractionEndPerfEvent,\n\tTLInteractionStartPerfEvent,\n\tTLPerfEventMap,\n\tTLPerfLongAnimationFrame,\n\tTLShapeOperationPerfEvent,\n\tTLUndoRedoPerfEvent,\n} from './perf-types'\n\nfunction percentile(sorted: number[], p: number): number {\n\tconst idx = Math.ceil(p * sorted.length) - 1\n\treturn sorted[Math.max(0, idx)]\n}\n\nfunction computeFrameTimeStats(frameTimes: number[]) {\n\tif (frameTimes.length === 0) return { avg: 0, median: 0, p95: 0, p99: 0, min: 0, max: 0 }\n\tconst sorted = [...frameTimes].sort((a, b) => a - b)\n\tconst sum = sorted.reduce((a, b) => a + b, 0)\n\treturn {\n\t\tavg: sum / sorted.length,\n\t\tmedian: percentile(sorted, 0.5),\n\t\tp95: percentile(sorted, 0.95),\n\t\tp99: percentile(sorted, 0.99),\n\t\tmin: sorted[0],\n\t\tmax: sorted[sorted.length - 1],\n\t}\n}\n\nfunction toLoafEntry(entry: PerformanceEntry): TLPerfLongAnimationFrame | null {\n\t// LoAF entries have these properties but TypeScript doesn't know about them yet\n\tconst e = entry as PerformanceEntry & {\n\t\tblockingDuration?: number\n\t\tscripts?: ReadonlyArray<{\n\t\t\tsourceURL?: string\n\t\t\tinvoker?: string\n\t\t\tduration?: number\n\t\t}>\n\t}\n\tif (typeof e.duration !== 'number') return null\n\treturn {\n\t\tstartTime: e.startTime,\n\t\tduration: e.duration,\n\t\tblockingDuration: e.blockingDuration ?? 0,\n\t\tscripts: (e.scripts ?? []).map((s) => ({\n\t\t\tsourceURL: s.sourceURL ?? '',\n\t\t\tinvoker: s.invoker ?? '',\n\t\t\tduration: s.duration ?? 0,\n\t\t})),\n\t}\n}\n\n/**\n * Manages performance event subscriptions for the editor. Available as `editor.performance`.\n *\n * Listeners are lazy \u2014 internal editor hooks (frame, shape events) are only attached while\n * at least one subscriber exists, so there is zero overhead when unused.\n *\n * @example\n * ```ts\n * const unsub = editor.performance.on('interaction-end', (event) => {\n * console.log(`${event.name}: ${event.fps.toFixed(1)} fps, p95=${event.p95FrameTime.toFixed(1)}ms`)\n * })\n * ```\n *\n * @public\n */\nexport class PerformanceManager {\n\t/** @internal */\n\treadonly emitter = new EventEmitter<TLPerfEventMap>()\n\n\tprivate editor: Editor\n\n\t// Active interaction tracking\n\tprivate activeInteraction: {\n\t\tname: string\n\t\tpath: string\n\t\tstartTime: number\n\t\tframeTimes: number[]\n\t\tselectedShapeTypes: Record<string, number>\n\t\tloafEntries: TLPerfLongAnimationFrame[]\n\t} | null = null\n\n\t// Active camera tracking\n\tprivate activeCamera: {\n\t\ttype: 'panning' | 'zooming'\n\t\tstartTime: number\n\t\tframeTimes: number[]\n\t\ttimeout: number | null\n\t\tloafEntries: TLPerfLongAnimationFrame[]\n\t} | null = null\n\n\t// Lazy listener cleanup functions\n\tprivate frameCleanup: (() => void) | null = null\n\tprivate shapeCreatedCleanup: (() => void) | null = null\n\tprivate shapeEditedCleanup: (() => void) | null = null\n\tprivate shapeDeletedCleanup: (() => void) | null = null\n\n\t// LoAF observer\n\tprivate loafObserver: PerformanceObserver | null = null\n\n\tconstructor(editor: Editor) {\n\t\tthis.editor = editor\n\t}\n\n\t/**\n\t * Subscribe to a performance event. Returns an unsubscribe function.\n\t *\n\t * @example\n\t * ```ts\n\t * const unsub = editor.performance.on('interaction-end', (event) => {\n\t * sendToAnalytics({ name: event.name, fps: event.fps, p95: event.p95FrameTime })\n\t * })\n\t * // later: unsub()\n\t * ```\n\t *\n\t * @public\n\t */\n\ton<K extends keyof TLPerfEventMap>(\n\t\tevent: K,\n\t\tfn: (...args: TLPerfEventMap[K]) => void\n\t): () => void {\n\t\tthis.emitter.on(event, fn as any)\n\t\tthis._maybeAttachLazyListeners(event)\n\t\treturn () => {\n\t\t\tthis.emitter.off(event, fn as any)\n\t\t\tthis._maybeDetachLazyListeners(event)\n\t\t}\n\t}\n\n\t/**\n\t * Subscribe to a performance event once. The listener is removed after the first invocation.\n\t * Returns an unsubscribe function for early removal.\n\t *\n\t * @public\n\t */\n\tonce<K extends keyof TLPerfEventMap>(\n\t\tevent: K,\n\t\tfn: (...args: TLPerfEventMap[K]) => void\n\t): () => void {\n\t\tconst wrapped = (...args: TLPerfEventMap[K]) => {\n\t\t\t;(fn as any)(...args)\n\t\t\tthis._maybeDetachLazyListeners(event)\n\t\t}\n\t\tthis.emitter.once(event, wrapped as any)\n\t\tthis._maybeAttachLazyListeners(event)\n\t\treturn () => {\n\t\t\tthis.emitter.off(event, wrapped as any)\n\t\t\tthis._maybeDetachLazyListeners(event)\n\t\t}\n\t}\n\n\t/** @internal */\n\tdispose() {\n\t\tif (this.activeCamera?.timeout) clearTimeout(this.activeCamera.timeout)\n\t\tthis.activeInteraction = null\n\t\tthis.activeCamera = null\n\t\tthis.frameCleanup?.()\n\t\tthis.frameCleanup = null\n\t\tthis.shapeCreatedCleanup?.()\n\t\tthis.shapeCreatedCleanup = null\n\t\tthis.shapeEditedCleanup?.()\n\t\tthis.shapeEditedCleanup = null\n\t\tthis.shapeDeletedCleanup?.()\n\t\tthis.shapeDeletedCleanup = null\n\t\tthis._stopLoafObserver()\n\t\tthis.emitter.removeAllListeners()\n\t}\n\n\t// --- Internal notification methods ---\n\n\t/** @internal */\n\t_notifyInteractionStart(name: string, path: string) {\n\t\tif (\n\t\t\tthis.emitter.listenerCount('interaction-start') === 0 &&\n\t\t\tthis.emitter.listenerCount('interaction-end') === 0\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tif (this.activeInteraction) {\n\t\t\tconsole.warn(\n\t\t\t\t`[tldraw] New interaction '${name}' started while '${this.activeInteraction.name}' was still active`\n\t\t\t)\n\t\t}\n\n\t\t// Capture selected shape types at start\n\t\tconst selectedShapeTypes: Record<string, number> = {}\n\t\tfor (const shape of this.editor.getSelectedShapes()) {\n\t\t\tselectedShapeTypes[shape.type] = (selectedShapeTypes[shape.type] || 0) + 1\n\t\t}\n\n\t\tthis.activeInteraction = {\n\t\t\tname,\n\t\t\tpath,\n\t\t\tstartTime: performance.now(),\n\t\t\tframeTimes: [],\n\t\t\tselectedShapeTypes,\n\t\t\tloafEntries: [],\n\t\t}\n\n\t\tconst event: TLInteractionStartPerfEvent = {\n\t\t\tname,\n\t\t\tpath,\n\t\t\ttimestamp: performance.now(),\n\t\t}\n\t\tthis.emitter.emit('interaction-start', event)\n\t}\n\n\t/** @internal */\n\t_notifyInteractionEnd() {\n\t\tconst interaction = this.activeInteraction\n\t\tif (!interaction) return\n\t\tthis.activeInteraction = null\n\n\t\tif (this.emitter.listenerCount('interaction-end') === 0) return\n\n\t\tconst duration = performance.now() - interaction.startTime\n\t\tconst stats = computeFrameTimeStats(interaction.frameTimes)\n\n\t\tconst event: TLInteractionEndPerfEvent = {\n\t\t\tname: interaction.name,\n\t\t\tpath: interaction.path,\n\t\t\tduration,\n\t\t\tfps:\n\t\t\t\tinteraction.frameTimes.length > 0 ? (interaction.frameTimes.length / duration) * 1000 : 0,\n\t\t\tframeCount: interaction.frameTimes.length,\n\t\t\tavgFrameTime: stats.avg,\n\t\t\tmedianFrameTime: stats.median,\n\t\t\tp95FrameTime: stats.p95,\n\t\t\tp99FrameTime: stats.p99,\n\t\t\tminFrameTime: stats.min,\n\t\t\tmaxFrameTime: stats.max,\n\t\t\tframeTimes: interaction.frameTimes,\n\t\t\tshapeCount: this.editor.getCurrentPageShapeIds().size,\n\t\t\tselectedShapeTypes: interaction.selectedShapeTypes,\n\t\t\tlongAnimationFrames: interaction.loafEntries.length > 0 ? interaction.loafEntries : undefined,\n\t\t\tzoomLevel: this.editor.getCamera().z,\n\t\t\ttimestamp: performance.now(),\n\t\t}\n\t\tthis.emitter.emit('interaction-end', event)\n\t}\n\n\t/** @internal */\n\t_notifyCameraOperation(type: 'panning' | 'zooming') {\n\t\tif (\n\t\t\tthis.emitter.listenerCount('camera-start') === 0 &&\n\t\t\tthis.emitter.listenerCount('camera-end') === 0\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tif (this.activeCamera) {\n\t\t\t// Extend existing camera session\n\t\t\tif (this.activeCamera.timeout) {\n\t\t\t\tclearTimeout(this.activeCamera.timeout)\n\t\t\t}\n\t\t\t// If type changed, end old and start new\n\t\t\tif (this.activeCamera.type !== type) {\n\t\t\t\tthis._endCameraSession()\n\t\t\t\tthis._startCameraSession(type)\n\t\t\t} else {\n\t\t\t\t// Reset timeout\n\t\t\t\tthis.activeCamera.timeout = this.editor.timers.setTimeout(\n\t\t\t\t\t() => this._endCameraSession(),\n\t\t\t\t\t50\n\t\t\t\t)\n\t\t\t}\n\t\t} else {\n\t\t\tthis._startCameraSession(type)\n\t\t}\n\t}\n\n\t/** @internal */\n\t_notifyUndoRedo(type: 'undo' | 'redo', undoDepth: number, redoDepth: number) {\n\t\tif (this.emitter.listenerCount(type) === 0) return\n\n\t\tconst event: TLUndoRedoPerfEvent = {\n\t\t\ttype,\n\t\t\tundoDepth,\n\t\t\tredoDepth,\n\t\t}\n\t\tthis.emitter.emit(type, event)\n\t}\n\n\t// --- Private helpers ---\n\n\tprivate _startCameraSession(type: 'panning' | 'zooming') {\n\t\tthis.activeCamera = {\n\t\t\ttype,\n\t\t\tstartTime: performance.now(),\n\t\t\tframeTimes: [],\n\t\t\ttimeout: this.editor.timers.setTimeout(() => this._endCameraSession(), 50),\n\t\t\tloafEntries: [],\n\t\t}\n\n\t\tif (this.emitter.listenerCount('camera-start') > 0) {\n\t\t\tconst event: TLCameraStartPerfEvent = {\n\t\t\t\ttype,\n\t\t\t\ttimestamp: performance.now(),\n\t\t\t}\n\t\t\tthis.emitter.emit('camera-start', event)\n\t\t}\n\t}\n\n\tprivate _endCameraSession() {\n\t\tconst camera = this.activeCamera\n\t\tif (!camera) return\n\t\tthis.activeCamera = null\n\t\tif (camera.timeout) clearTimeout(camera.timeout)\n\n\t\tif (this.emitter.listenerCount('camera-end') === 0) return\n\n\t\tconst duration = performance.now() - camera.startTime\n\t\tconst stats = computeFrameTimeStats(camera.frameTimes)\n\t\tconst viewportBounds = this.editor.getViewportScreenBounds()\n\t\tconst totalShapes = this.editor.getCurrentPageShapeIds().size\n\t\tconst culledShapeCount = this.editor.getCulledShapes().size\n\n\t\tconst event: TLCameraEndPerfEvent = {\n\t\t\ttype: camera.type,\n\t\t\tduration,\n\t\t\tfps: camera.frameTimes.length > 0 ? (camera.frameTimes.length / duration) * 1000 : 0,\n\t\t\tframeCount: camera.frameTimes.length,\n\t\t\tavgFrameTime: stats.avg,\n\t\t\tmedianFrameTime: stats.median,\n\t\t\tp95FrameTime: stats.p95,\n\t\t\tp99FrameTime: stats.p99,\n\t\t\tminFrameTime: stats.min,\n\t\t\tmaxFrameTime: stats.max,\n\t\t\tframeTimes: camera.frameTimes,\n\t\t\tshapeCount: totalShapes,\n\t\t\tviewportWidth: viewportBounds.w,\n\t\t\tviewportHeight: viewportBounds.h,\n\t\t\tlongAnimationFrames: camera.loafEntries.length > 0 ? camera.loafEntries : undefined,\n\t\t\tvisibleShapeCount: totalShapes - culledShapeCount,\n\t\t\tculledShapeCount,\n\t\t\tzoomLevel: this.editor.getCamera().z,\n\t\t\ttimestamp: performance.now(),\n\t\t}\n\t\tthis.emitter.emit('camera-end', event)\n\t}\n\n\t@bind\n\tprivate _onFrame(elapsed: number) {\n\t\t// Record frame time for active interaction/camera\n\t\tif (this.activeInteraction) {\n\t\t\tthis.activeInteraction.frameTimes.push(elapsed)\n\t\t}\n\t\tif (this.activeCamera) {\n\t\t\tthis.activeCamera.frameTimes.push(elapsed)\n\t\t}\n\n\t\t// Emit standalone frame event if listeners exist\n\t\tif (this.emitter.listenerCount('frame') > 0) {\n\t\t\tconst totalShapes = this.editor.getCurrentPageShapeIds().size\n\t\t\tconst culledShapes = this.editor.getCulledShapes()\n\t\t\tconst culledCount = culledShapes.size\n\t\t\tconst event: TLFramePerfEvent = {\n\t\t\t\telapsed,\n\t\t\t\tshapeCount: totalShapes,\n\t\t\t\tculledShapeCount: culledCount,\n\t\t\t\tvisibleShapeCount: totalShapes - culledCount,\n\t\t\t}\n\t\t\tthis.emitter.emit('frame', event)\n\t\t}\n\t}\n\n\t@bind\n\tprivate _onShapesCreated(records: TLRecord[]) {\n\t\tif (this.emitter.listenerCount('shapes-created') === 0) return\n\t\tconst shapeTypes: Record<string, number> = {}\n\t\tfor (const record of records) {\n\t\t\tif (record.typeName === 'shape') {\n\t\t\t\tshapeTypes[record.type] = (shapeTypes[record.type] || 0) + 1\n\t\t\t}\n\t\t}\n\t\tconst count = Object.values(shapeTypes).reduce((a, b) => a + b, 0)\n\t\tif (count === 0) return\n\t\tconst event: TLShapeOperationPerfEvent = {\n\t\t\toperation: 'create',\n\t\t\tcount,\n\t\t\tshapeTypes,\n\t\t\ttimestamp: performance.now(),\n\t\t}\n\t\tthis.emitter.emit('shapes-created', event)\n\t}\n\n\t@bind\n\tprivate _onShapesEdited(records: TLRecord[]) {\n\t\tif (this.emitter.listenerCount('shapes-updated') === 0) return\n\t\tconst shapeTypes: Record<string, number> = {}\n\t\tfor (const record of records) {\n\t\t\tif (record.typeName === 'shape') {\n\t\t\t\tshapeTypes[record.type] = (shapeTypes[record.type] || 0) + 1\n\t\t\t}\n\t\t}\n\t\tconst count = Object.values(shapeTypes).reduce((a, b) => a + b, 0)\n\t\tif (count === 0) return\n\t\tconst event: TLShapeOperationPerfEvent = {\n\t\t\toperation: 'update',\n\t\t\tcount,\n\t\t\tshapeTypes,\n\t\t\ttimestamp: performance.now(),\n\t\t}\n\t\tthis.emitter.emit('shapes-updated', event)\n\t}\n\n\t@bind\n\tprivate _onShapesDeleted(ids: TLShapeId[]) {\n\t\tif (this.emitter.listenerCount('shapes-deleted') === 0) return\n\t\tconst shapeTypes: Record<string, number> = {}\n\t\tfor (const id of ids) {\n\t\t\t// Works because 'deleted-shapes' fires before store.remove() in Editor.deleteShapes\n\t\t\tconst shape = this.editor.getShape(id)\n\t\t\tif (shape) {\n\t\t\t\tshapeTypes[shape.type] = (shapeTypes[shape.type] || 0) + 1\n\t\t\t}\n\t\t}\n\t\tconst event: TLShapeOperationPerfEvent = {\n\t\t\toperation: 'delete',\n\t\t\tcount: ids.length,\n\t\t\tshapeTypes,\n\t\t\ttimestamp: performance.now(),\n\t\t}\n\t\tthis.emitter.emit('shapes-deleted', event)\n\t}\n\n\t// --- LoAF observer ---\n\n\tprivate _startLoafObserver() {\n\t\tif (typeof PerformanceObserver === 'undefined') return\n\n\t\ttry {\n\t\t\tconst supported = PerformanceObserver.supportedEntryTypes\n\t\t\tif (!supported?.includes('long-animation-frame')) return\n\t\t} catch {\n\t\t\treturn\n\t\t}\n\n\t\tthis.loafObserver = new PerformanceObserver((list) => {\n\t\t\tconst isInteractionActive = this.activeInteraction !== null\n\t\t\tconst isCameraActive = this.activeCamera !== null\n\n\t\t\tif (!isInteractionActive && !isCameraActive) return\n\n\t\t\tfor (const entry of list.getEntries()) {\n\t\t\t\tconst loaf = toLoafEntry(entry)\n\t\t\t\tif (!loaf) continue\n\n\t\t\t\tif (isInteractionActive) {\n\t\t\t\t\tthis.activeInteraction!.loafEntries.push(loaf)\n\t\t\t\t}\n\t\t\t\tif (isCameraActive) {\n\t\t\t\t\tthis.activeCamera!.loafEntries.push(loaf)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tthis.loafObserver.observe({ type: 'long-animation-frame', buffered: false })\n\t}\n\n\tprivate _stopLoafObserver() {\n\t\tif (this.loafObserver) {\n\t\t\tthis.loafObserver.disconnect()\n\t\t\tthis.loafObserver = null\n\t\t}\n\t}\n\n\t// --- Lazy listener management ---\n\n\tprivate _needsFrameListener(): boolean {\n\t\treturn (\n\t\t\tthis.emitter.listenerCount('frame') > 0 ||\n\t\t\tthis.emitter.listenerCount('interaction-start') > 0 ||\n\t\t\tthis.emitter.listenerCount('interaction-end') > 0 ||\n\t\t\tthis.emitter.listenerCount('camera-start') > 0 ||\n\t\t\tthis.emitter.listenerCount('camera-end') > 0\n\t\t)\n\t}\n\n\tprivate _needsLoafObserver(): boolean {\n\t\treturn (\n\t\t\tthis.emitter.listenerCount('interaction-end') > 0 ||\n\t\t\tthis.emitter.listenerCount('camera-end') > 0\n\t\t)\n\t}\n\n\tprivate _maybeAttachLazyListeners(event: keyof TLPerfEventMap) {\n\t\t// Frame listener needed for frame event + interaction/camera frame time tracking\n\t\tif (\n\t\t\t!this.frameCleanup &&\n\t\t\t(event === 'frame' ||\n\t\t\t\tevent === 'interaction-start' ||\n\t\t\t\tevent === 'interaction-end' ||\n\t\t\t\tevent === 'camera-start' ||\n\t\t\t\tevent === 'camera-end')\n\t\t) {\n\t\t\tif (this._needsFrameListener()) {\n\t\t\t\tthis.editor.on('frame', this._onFrame)\n\t\t\t\tthis.frameCleanup = () => this.editor.off('frame', this._onFrame)\n\t\t\t}\n\t\t}\n\n\t\t// LoAF observer needed when interaction-end or camera-end listeners exist\n\t\tif (!this.loafObserver && (event === 'interaction-end' || event === 'camera-end')) {\n\t\t\tif (this._needsLoafObserver()) {\n\t\t\t\tthis._startLoafObserver()\n\t\t\t}\n\t\t}\n\n\t\tif (!this.shapeCreatedCleanup && event === 'shapes-created') {\n\t\t\tthis.editor.on('created-shapes', this._onShapesCreated)\n\t\t\tthis.shapeCreatedCleanup = () => this.editor.off('created-shapes', this._onShapesCreated)\n\t\t}\n\n\t\tif (!this.shapeEditedCleanup && event === 'shapes-updated') {\n\t\t\tthis.editor.on('edited-shapes', this._onShapesEdited)\n\t\t\tthis.shapeEditedCleanup = () => this.editor.off('edited-shapes', this._onShapesEdited)\n\t\t}\n\n\t\tif (!this.shapeDeletedCleanup && event === 'shapes-deleted') {\n\t\t\tthis.editor.on('deleted-shapes', this._onShapesDeleted)\n\t\t\tthis.shapeDeletedCleanup = () => this.editor.off('deleted-shapes', this._onShapesDeleted)\n\t\t}\n\t}\n\n\tprivate _maybeDetachLazyListeners(event: keyof TLPerfEventMap) {\n\t\tif (\n\t\t\tthis.frameCleanup &&\n\t\t\t(event === 'frame' ||\n\t\t\t\tevent === 'interaction-start' ||\n\t\t\t\tevent === 'interaction-end' ||\n\t\t\t\tevent === 'camera-start' ||\n\t\t\t\tevent === 'camera-end')\n\t\t) {\n\t\t\tif (!this._needsFrameListener()) {\n\t\t\t\tthis.frameCleanup()\n\t\t\t\tthis.frameCleanup = null\n\t\t\t}\n\t\t}\n\n\t\t// Stop LoAF observer when no longer needed\n\t\tif (this.loafObserver && (event === 'interaction-end' || event === 'camera-end')) {\n\t\t\tif (!this._needsLoafObserver()) {\n\t\t\t\tthis._stopLoafObserver()\n\t\t\t}\n\t\t}\n\n\t\tif (\n\t\t\tthis.shapeCreatedCleanup &&\n\t\t\tevent === 'shapes-created' &&\n\t\t\tthis.emitter.listenerCount('shapes-created') === 0\n\t\t) {\n\t\t\tthis.shapeCreatedCleanup()\n\t\t\tthis.shapeCreatedCleanup = null\n\t\t}\n\n\t\tif (\n\t\t\tthis.shapeEditedCleanup &&\n\t\t\tevent === 'shapes-updated' &&\n\t\t\tthis.emitter.listenerCount('shapes-updated') === 0\n\t\t) {\n\t\t\tthis.shapeEditedCleanup()\n\t\t\tthis.shapeEditedCleanup = null\n\t\t}\n\n\t\tif (\n\t\t\tthis.shapeDeletedCleanup &&\n\t\t\tevent === 'shapes-deleted' &&\n\t\t\tthis.emitter.listenerCount('shapes-deleted') === 0\n\t\t) {\n\t\t\tthis.shapeDeletedCleanup()\n\t\t\tthis.shapeDeletedCleanup = null\n\t\t}\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=perf-types.mjs.map
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/editor/managers/ScribbleManager/ScribbleManager.ts"],
|
|
4
4
|
"sourcesContent": ["import { TLScribble, VecModel } from '@tldraw/tlschema'\nimport { uniqueId } from '@tldraw/utils'\nimport { Vec } from '../../../primitives/Vec'\nimport type { Editor } from '../../Editor'\n\n/** @public */\nexport interface ScribbleItem {\n\tid: string\n\tscribble: TLScribble\n\ttimeoutMs: number\n\tdelayRemaining: number\n\tprev: null | VecModel\n\tnext: null | VecModel\n}\n\n/** @public */\nexport interface ScribbleSessionOptions {\n\t/** Session id. Auto-generated if not provided. */\n\tid?: string\n\t/**\n\t * Whether scribbles self-consume (shrink from start) while drawing.\n\t * - true: scribbles eat their own tail as you draw (default, used for eraser/select)\n\t * - false: scribbles persist until session stops (used for laser)\n\t */\n\tselfConsume?: boolean\n\t/**\n\t * How long to wait after last activity before auto-stopping the session.\n\t * Only applies when selfConsume is false.\n\t */\n\tidleTimeoutMs?: number\n\t/**\n\t * How scribbles fade when stopping.\n\t * - 'individual': each scribble fades on its own (default)\n\t * - 'grouped': all scribbles fade together as one sequence\n\t */\n\tfadeMode?: 'individual' | 'grouped'\n\t/**\n\t * Easing for grouped fade.\n\t */\n\tfadeEasing?: 'linear' | 'ease-in'\n\t/**\n\t * Duration of the fade in milliseconds.\n\t */\n\tfadeDurationMs?: number\n}\n\n// Internal session state (not exported)\ninterface Session {\n\tid: string\n\titems: ScribbleItem[]\n\tstate: 'active' | 'stopping' | 'complete'\n\toptions: Required<Omit<ScribbleSessionOptions, 'id'>>\n\tidleTimeoutHandle?: number\n\tfadeElapsed: number\n\ttotalPointsAtFadeStart: number\n}\n\n/** @public */\nexport class ScribbleManager {\n\tprivate sessions = new Map<string, Session>()\n\n\tconstructor(private editor: Editor) {}\n\n\t// ==================== SESSION API ====================\n\n\t/**\n\t * Start a new session for grouping scribbles.\n\t * Returns a session ID that can be used with other session methods.\n\t *\n\t * @param options - Session configuration\n\t * @returns Session ID\n\t * @public\n\t */\n\tstartSession(options: ScribbleSessionOptions = {}): string {\n\t\tconst id = options.id ?? uniqueId()\n\t\tconst session: Session = {\n\t\t\tid,\n\t\t\titems: [],\n\t\t\tstate: 'active',\n\t\t\toptions: {\n\t\t\t\tselfConsume: options.selfConsume ?? true,\n\t\t\t\tidleTimeoutMs: options.idleTimeoutMs ?? 0,\n\t\t\t\tfadeMode: options.fadeMode ?? 'individual',\n\t\t\t\tfadeEasing: options.fadeEasing ?? (options.fadeMode === 'grouped' ? 'ease-in' : 'linear'),\n\t\t\t\tfadeDurationMs: options.fadeDurationMs ?? this.editor.options.laserFadeoutMs,\n\t\t\t},\n\t\t\tfadeElapsed: 0,\n\t\t\ttotalPointsAtFadeStart: 0,\n\t\t}\n\n\t\tthis.sessions.set(id, session)\n\n\t\t// Set up idle timeout if configured\n\t\tif (session.options.idleTimeoutMs > 0) {\n\t\t\tthis.resetIdleTimeout(session)\n\t\t}\n\n\t\treturn id\n\t}\n\n\t/**\n\t * Add a scribble to a session.\n\t *\n\t * @param sessionId - The session ID\n\t * @param scribble - Partial scribble properties\n\t * @param scribbleId - Optional scribble ID\n\t * @public\n\t */\n\taddScribbleToSession(\n\t\tsessionId: string,\n\t\tscribble: Partial<TLScribble>,\n\t\tscribbleId = uniqueId()\n\t): ScribbleItem {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session) throw Error(`Session ${sessionId} not found`)\n\n\t\tconst item: ScribbleItem = {\n\t\t\tid: scribbleId,\n\t\t\tscribble: {\n\t\t\t\tid: scribbleId,\n\t\t\t\tsize: 20,\n\t\t\t\tcolor: 'accent',\n\t\t\t\topacity: 0.8,\n\t\t\t\tdelay: 0,\n\t\t\t\tpoints: [],\n\t\t\t\tshrink: 0.1,\n\t\t\t\ttaper: true,\n\t\t\t\t...scribble,\n\t\t\t\tstate: 'starting',\n\t\t\t},\n\t\t\ttimeoutMs: 0,\n\t\t\tdelayRemaining: scribble.delay ?? 0,\n\t\t\tprev: null,\n\t\t\tnext: null,\n\t\t}\n\n\t\tsession.items.push(item)\n\n\t\t// Reset idle timeout on activity\n\t\tif (session.options.idleTimeoutMs > 0) {\n\t\t\tthis.resetIdleTimeout(session)\n\t\t}\n\n\t\treturn item\n\t}\n\n\t/**\n\t * Add a point to a scribble in a session.\n\t *\n\t * @param sessionId - The session ID\n\t * @param scribbleId - The scribble ID\n\t * @param x - X coordinate\n\t * @param y - Y coordinate\n\t * @param z - Z coordinate (pressure)\n\t * @public\n\t */\n\taddPointToSession(\n\t\tsessionId: string,\n\t\tscribbleId: string,\n\t\tx: number,\n\t\ty: number,\n\t\tz = 0.5\n\t): ScribbleItem {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session) throw Error(`Session ${sessionId} not found`)\n\n\t\tconst item = session.items.find((i) => i.id === scribbleId)\n\t\tif (!item) throw Error(`Scribble ${scribbleId} not found in session ${sessionId}`)\n\n\t\tconst point = { x, y, z }\n\t\tif (!item.prev || Vec.Dist(item.prev, point) >= 1) {\n\t\t\titem.next = point\n\t\t}\n\n\t\t// Reset idle timeout on activity\n\t\tif (session.options.idleTimeoutMs > 0) {\n\t\t\tthis.resetIdleTimeout(session)\n\t\t}\n\n\t\treturn item\n\t}\n\n\t/**\n\t * Extend a session, resetting its idle timeout.\n\t *\n\t * @param sessionId - The session ID\n\t * @public\n\t */\n\textendSession(sessionId: string): void {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session) return\n\n\t\tif (session.options.idleTimeoutMs > 0) {\n\t\t\tthis.resetIdleTimeout(session)\n\t\t}\n\t}\n\n\t/**\n\t * Stop a session, triggering fade-out.\n\t *\n\t * @param sessionId - The session ID\n\t * @public\n\t */\n\tstopSession(sessionId: string): void {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session || session.state !== 'active') return\n\n\t\tthis.clearIdleTimeout(session)\n\t\tsession.state = 'stopping'\n\n\t\tif (session.options.fadeMode === 'grouped') {\n\t\t\tsession.totalPointsAtFadeStart = session.items.reduce(\n\t\t\t\t(sum, item) => sum + item.scribble.points.length,\n\t\t\t\t0\n\t\t\t)\n\t\t\tsession.fadeElapsed = 0\n\t\t\tfor (const item of session.items) {\n\t\t\t\titem.scribble.state = 'stopping'\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const item of session.items) {\n\t\t\t\titem.delayRemaining = Math.min(item.delayRemaining, 200)\n\t\t\t\titem.scribble.state = 'stopping'\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clear all scribbles in a session immediately.\n\t *\n\t * @param sessionId - The session ID\n\t * @public\n\t */\n\tclearSession(sessionId: string): void {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session) return\n\n\t\tthis.clearIdleTimeout(session)\n\t\tfor (const item of session.items) {\n\t\t\titem.scribble.points.length = 0\n\t\t}\n\t\tsession.state = 'complete'\n\t}\n\n\t/**\n\t * Check if a session is active.\n\t *\n\t * @param sessionId - The session ID\n\t * @public\n\t */\n\tisSessionActive(sessionId: string): boolean {\n\t\tconst session = this.sessions.get(sessionId)\n\t\treturn session?.state === 'active'\n\t}\n\n\t// ==================== SIMPLE API (for eraser, select, etc.) ====================\n\n\t/**\n\t * Add a scribble using the default self-consuming behavior.\n\t * Creates an implicit session for the scribble.\n\t *\n\t * @param scribble - Partial scribble properties\n\t * @param id - Optional scribble id\n\t * @returns The created scribble item\n\t * @public\n\t */\n\taddScribble(scribble: Partial<TLScribble>, id = uniqueId()): ScribbleItem {\n\t\tconst sessionId = this.startSession()\n\t\treturn this.addScribbleToSession(sessionId, scribble, id)\n\t}\n\n\t/**\n\t * Add a point to a scribble. Searches all sessions.\n\t *\n\t * @param id - The scribble id\n\t * @param x - X coordinate\n\t * @param y - Y coordinate\n\t * @param z - Z coordinate (pressure)\n\t * @public\n\t */\n\taddPoint(id: string, x: number, y: number, z = 0.5): ScribbleItem {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tconst item = session.items.find((i) => i.id === id)\n\t\t\tif (item) {\n\t\t\t\tconst point = { x, y, z }\n\t\t\t\tif (!item.prev || Vec.Dist(item.prev, point) >= 1) {\n\t\t\t\t\titem.next = point\n\t\t\t\t}\n\t\t\t\tif (session.options.idleTimeoutMs > 0) {\n\t\t\t\t\tthis.resetIdleTimeout(session)\n\t\t\t\t}\n\t\t\t\treturn item\n\t\t\t}\n\t\t}\n\t\tthrow Error(`Scribble with id ${id} not found`)\n\t}\n\n\t/**\n\t * Mark a scribble as complete (done being drawn but not yet fading).\n\t * Searches all sessions.\n\t *\n\t * @param id - The scribble id\n\t * @public\n\t */\n\tcomplete(id: string): ScribbleItem {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tconst item = session.items.find((i) => i.id === id)\n\t\t\tif (item) {\n\t\t\t\tif (item.scribble.state === 'starting' || item.scribble.state === 'active') {\n\t\t\t\t\titem.scribble.state = 'complete'\n\t\t\t\t}\n\t\t\t\treturn item\n\t\t\t}\n\t\t}\n\t\tthrow Error(`Scribble with id ${id} not found`)\n\t}\n\n\t/**\n\t * Stop a scribble. Searches all sessions.\n\t *\n\t * @param id - The scribble id\n\t * @public\n\t */\n\tstop(id: string): ScribbleItem {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tconst item = session.items.find((i) => i.id === id)\n\t\t\tif (item) {\n\t\t\t\titem.delayRemaining = Math.min(item.delayRemaining, 200)\n\t\t\t\titem.scribble.state = 'stopping'\n\t\t\t\treturn item\n\t\t\t}\n\t\t}\n\t\tthrow Error(`Scribble with id ${id} not found`)\n\t}\n\n\t/**\n\t * Stop and remove all sessions.\n\t *\n\t * @public\n\t */\n\treset(): void {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tthis.clearIdleTimeout(session)\n\t\t}\n\t\tthis.sessions.clear()\n\t\tthis.editor.updateInstanceState({ scribbles: [] })\n\t}\n\n\t/**\n\t * Update on each animation frame.\n\t *\n\t * @param elapsed - The number of milliseconds since the last tick.\n\t * @public\n\t */\n\ttick(elapsed: number): void {\n\t\tconst currentScribbles = this.editor.getInstanceState().scribbles\n\t\tif (this.sessions.size === 0 && currentScribbles.length === 0) return\n\n\t\tthis.editor.run(() => {\n\t\t\t// Tick all sessions\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tthis.tickSession(session, elapsed)\n\t\t\t}\n\n\t\t\t// Remove completed sessions\n\t\t\tfor (const [id, session] of this.sessions) {\n\t\t\t\tif (session.state === 'complete') {\n\t\t\t\t\tthis.clearIdleTimeout(session)\n\t\t\t\t\tthis.sessions.delete(id)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Collect scribbles from all sessions\n\t\t\tconst scribbles: TLScribble[] = []\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tfor (const item of session.items) {\n\t\t\t\t\tif (item.scribble.points.length > 0) {\n\t\t\t\t\t\tscribbles.push({\n\t\t\t\t\t\t\t...item.scribble,\n\t\t\t\t\t\t\tpoints: [...item.scribble.points],\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.editor.updateInstanceState({ scribbles })\n\t\t})\n\t}\n\n\t// ==================== PRIVATE HELPERS ====================\n\n\tprivate resetIdleTimeout(session: Session): void {\n\t\tthis.clearIdleTimeout(session)\n\t\tsession.idleTimeoutHandle = this.editor.timers.setTimeout(() => {\n\t\t\tthis.stopSession(session.id)\n\t\t}, session.options.idleTimeoutMs)\n\t}\n\n\tprivate clearIdleTimeout(session: Session): void {\n\t\tif (session.idleTimeoutHandle !== undefined) {\n\t\t\tclearTimeout(session.idleTimeoutHandle)\n\t\t\tsession.idleTimeoutHandle = undefined\n\t\t}\n\t}\n\n\tprivate tickSession(session: Session, elapsed: number): void {\n\t\tif (session.state === 'complete') return\n\n\t\tif (session.state === 'stopping' && session.options.fadeMode === 'grouped') {\n\t\t\tthis.tickGroupedFade(session, elapsed)\n\t\t} else {\n\t\t\tthis.tickSessionItems(session, elapsed)\n\t\t}\n\n\t\t// Check if session is complete\n\t\tconst hasContent = session.items.some((item) => item.scribble.points.length > 0)\n\t\tif (!hasContent && (session.state === 'stopping' || session.items.length === 0)) {\n\t\t\tsession.state = 'complete'\n\t\t}\n\t}\n\n\tprivate tickSessionItems(session: Session, elapsed: number): void {\n\t\tfor (const item of session.items) {\n\t\t\tconst shouldSelfConsume =\n\t\t\t\tsession.options.selfConsume ||\n\t\t\t\tsession.state === 'stopping' ||\n\t\t\t\titem.scribble.state === 'stopping'\n\n\t\t\tif (shouldSelfConsume) {\n\t\t\t\tthis.tickSelfConsumingItem(item, elapsed)\n\t\t\t} else {\n\t\t\t\tthis.tickPersistentItem(item)\n\t\t\t}\n\t\t}\n\n\t\t// Remove completed items in individual fade mode\n\t\tif (session.options.fadeMode === 'individual') {\n\t\t\tfor (let i = session.items.length - 1; i >= 0; i--) {\n\t\t\t\tif (session.items[i].scribble.points.length === 0) {\n\t\t\t\t\tsession.items.splice(i, 1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate tickPersistentItem(item: ScribbleItem): void {\n\t\tconst { scribble } = item\n\n\t\tif (scribble.state === 'starting') {\n\t\t\tconst { next, prev } = item\n\t\t\tif (next && next !== prev) {\n\t\t\t\titem.prev = next\n\t\t\t\tscribble.points.push(next)\n\t\t\t}\n\t\t\tif (scribble.points.length > 8) {\n\t\t\t\tscribble.state = 'active'\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tif (scribble.state === 'active') {\n\t\t\tconst { next, prev } = item\n\t\t\tif (next && next !== prev) {\n\t\t\t\titem.prev = next\n\t\t\t\tscribble.points.push(next)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate tickSelfConsumingItem(item: ScribbleItem, elapsed: number): void {\n\t\tconst { scribble } = item\n\n\t\tif (scribble.state === 'starting') {\n\t\t\tconst { next, prev } = item\n\t\t\tif (next && next !== prev) {\n\t\t\t\titem.prev = next\n\t\t\t\tscribble.points.push(next)\n\t\t\t}\n\t\t\tif (scribble.points.length > 8) {\n\t\t\t\tscribble.state = 'active'\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tif (item.delayRemaining > 0) {\n\t\t\titem.delayRemaining = Math.max(0, item.delayRemaining - elapsed)\n\t\t}\n\n\t\titem.timeoutMs += elapsed\n\t\tif (item.timeoutMs >= 16) {\n\t\t\titem.timeoutMs = 0\n\t\t}\n\n\t\tconst { delayRemaining, timeoutMs, prev, next } = item\n\n\t\tswitch (scribble.state) {\n\t\t\tcase 'active': {\n\t\t\t\tif (next && next !== prev) {\n\t\t\t\t\titem.prev = next\n\t\t\t\t\tscribble.points.push(next)\n\t\t\t\t\tif (delayRemaining === 0 && scribble.points.length > 8) {\n\t\t\t\t\t\tscribble.points.shift()\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (timeoutMs === 0) {\n\t\t\t\t\t\tif (scribble.points.length > 1) {\n\t\t\t\t\t\t\tscribble.points.shift()\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\titem.delayRemaining = scribble.delay\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'stopping': {\n\t\t\t\tif (delayRemaining === 0 && timeoutMs === 0) {\n\t\t\t\t\tif (scribble.points.length <= 1) {\n\t\t\t\t\t\tscribble.points.length = 0\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tif (scribble.shrink) {\n\t\t\t\t\t\tscribble.size = Math.max(1, scribble.size * (1 - scribble.shrink))\n\t\t\t\t\t}\n\t\t\t\t\tscribble.points.shift()\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'paused': {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate tickGroupedFade(session: Session, elapsed: number): void {\n\t\tsession.fadeElapsed += elapsed\n\n\t\tlet remainingPoints = 0\n\t\tfor (const item of session.items) {\n\t\t\tremainingPoints += item.scribble.points.length\n\t\t}\n\n\t\tif (remainingPoints === 0) return\n\n\t\tif (session.fadeElapsed >= session.options.fadeDurationMs) {\n\t\t\tfor (const item of session.items) {\n\t\t\t\titem.scribble.points.length = 0\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst progress = session.fadeElapsed / session.options.fadeDurationMs\n\t\tconst easedProgress = session.options.fadeEasing === 'ease-in' ? progress * progress : progress\n\n\t\tconst targetRemoved = Math.floor(easedProgress * session.totalPointsAtFadeStart)\n\t\tconst actuallyRemoved = session.totalPointsAtFadeStart - remainingPoints\n\t\tconst pointsToRemove = Math.max(1, targetRemoved - actuallyRemoved)\n\n\t\tlet removed = 0\n\t\tlet itemIndex = 0\n\t\twhile (removed < pointsToRemove && itemIndex < session.items.length) {\n\t\t\tconst item = session.items[itemIndex]\n\t\t\tif (item.scribble.points.length > 0) {\n\t\t\t\titem.scribble.points.shift()\n\t\t\t\tremoved++\n\t\t\t} else {\n\t\t\t\titemIndex++\n\t\t\t}\n\t\t}\n\t}\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,gBAAgB;AACzB,SAAS,WAAW;AAwDb,MAAM,gBAAgB;AAAA,EAG5B,YAAoB,QAAgB;AAAhB;AAAA,EAAiB;AAAA,
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["next", "prev"]
|
|
7
7
|
}
|