@kritzel/engine 0.4.31
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/LICENSE.md +50 -0
- package/dist/cjs/app-globals-V2Kpy_OQ.js +5 -0
- package/dist/cjs/engine.constants-CakmdKMW.js +28206 -0
- package/dist/cjs/index-BbbWU2aN.js +1742 -0
- package/dist/cjs/index.cjs.js +4232 -0
- package/dist/cjs/kritzel-awareness-cursors_5.cjs.entry.js +28004 -0
- package/dist/cjs/loader.cjs.js +13 -0
- package/dist/cjs/stencil.cjs.js +25 -0
- package/dist/collection/classes/core/core.class.js +1389 -0
- package/dist/collection/classes/core/reviver.class.js +124 -0
- package/dist/collection/classes/core/store.class.js +337 -0
- package/dist/collection/classes/core/viewport.class.js +794 -0
- package/dist/collection/classes/core/workspace.class.js +112 -0
- package/dist/collection/classes/handlers/base.handler.js +20 -0
- package/dist/collection/classes/handlers/context-menu.handler.js +170 -0
- package/dist/collection/classes/handlers/hover.handler.js +35 -0
- package/dist/collection/classes/handlers/key.handler.js +162 -0
- package/dist/collection/classes/handlers/line-handle.handler.js +475 -0
- package/dist/collection/classes/handlers/move.handler.js +295 -0
- package/dist/collection/classes/handlers/resize.handler.js +327 -0
- package/dist/collection/classes/handlers/rotation.handler.js +174 -0
- package/dist/collection/classes/handlers/selection.handler.js +526 -0
- package/dist/collection/classes/managers/anchor.manager.js +1476 -0
- package/dist/collection/classes/managers/browser-permission.manager.js +64 -0
- package/dist/collection/classes/managers/clipboard.manager.js +346 -0
- package/dist/collection/classes/managers/clipboard.types.js +1 -0
- package/dist/collection/classes/managers/cursor.manager.js +139 -0
- package/dist/collection/classes/managers/license.manager.js +341 -0
- package/dist/collection/classes/managers/localization.manager.js +227 -0
- package/dist/collection/classes/managers/theme.manager.js +206 -0
- package/dist/collection/classes/objects/base-object.class.js +462 -0
- package/dist/collection/classes/objects/dynamic-object.class.js +437 -0
- package/dist/collection/classes/objects/group.class.js +590 -0
- package/dist/collection/classes/objects/image.class.js +500 -0
- package/dist/collection/classes/objects/line.class.js +789 -0
- package/dist/collection/classes/objects/path.class.js +578 -0
- package/dist/collection/classes/objects/selection-box.class.js +32 -0
- package/dist/collection/classes/objects/selection-group.class.js +752 -0
- package/dist/collection/classes/objects/shape.class.js +628 -0
- package/dist/collection/classes/objects/text.class.js +461 -0
- package/dist/collection/classes/providers/assets/asset-resolver.class.js +536 -0
- package/dist/collection/classes/providers/assets/http-asset-provider.class.js +111 -0
- package/dist/collection/classes/providers/assets/indexeddb-asset-provider.class.js +241 -0
- package/dist/collection/classes/providers/assets/presigned-asset-provider.class.js +86 -0
- package/dist/collection/classes/providers/paste-intent/event-paste-intent.provider.js +48 -0
- package/dist/collection/classes/providers/paste-intent/ios-paste-intent.provider.js +16 -0
- package/dist/collection/classes/providers/paste-intent/navigator-paste-intent.provider.js +86 -0
- package/dist/collection/classes/providers/sync/broadcast-sync-provider.class.js +100 -0
- package/dist/collection/classes/providers/sync/hocuspocus-sync-provider.class.js +333 -0
- package/dist/collection/classes/providers/sync/in-memory-sync-provider.class.js +69 -0
- package/dist/collection/classes/providers/sync/indexeddb-sync-provider.class.js +39 -0
- package/dist/collection/classes/providers/sync/websocket-sync-provider.class.js +110 -0
- package/dist/collection/classes/registries/dynamic-object-renderer.registry.js +52 -0
- package/dist/collection/classes/registries/font-registry.class.js +161 -0
- package/dist/collection/classes/registries/icon-registry.class.js +118 -0
- package/dist/collection/classes/registries/paste-intent-provider.registry.js +26 -0
- package/dist/collection/classes/registries/tool.registry.js +69 -0
- package/dist/collection/classes/structures/app-state-map.structure.js +461 -0
- package/dist/collection/classes/structures/object-map.structure.js +1103 -0
- package/dist/collection/classes/structures/quadtree.structure.js +251 -0
- package/dist/collection/classes/tools/base-tool.class.js +88 -0
- package/dist/collection/classes/tools/brush-tool.class.js +236 -0
- package/dist/collection/classes/tools/eraser-tool.class.js +133 -0
- package/dist/collection/classes/tools/image-tool.class.js +152 -0
- package/dist/collection/classes/tools/line-tool.class.js +249 -0
- package/dist/collection/classes/tools/selection-tool.class.js +611 -0
- package/dist/collection/classes/tools/shape-tool.class.js +251 -0
- package/dist/collection/classes/tools/text-tool.class.js +179 -0
- package/dist/collection/collection-manifest.json +17 -0
- package/dist/collection/components/kritzel-awareness-cursors/kritzel-awareness-cursors.css +115 -0
- package/dist/collection/components/kritzel-awareness-cursors/kritzel-awareness-cursors.js +380 -0
- package/dist/collection/components/kritzel-cursor-trail/kritzel-cursor-trail.css +10 -0
- package/dist/collection/components/kritzel-cursor-trail/kritzel-cursor-trail.js +153 -0
- package/dist/collection/components/kritzel-engine/kritzel-engine.css +81 -0
- package/dist/collection/components/kritzel-engine/kritzel-engine.js +6345 -0
- package/dist/collection/components/kritzel-icon/kritzel-icon.css +18 -0
- package/dist/collection/components/kritzel-icon/kritzel-icon.js +93 -0
- package/dist/collection/components/kritzel-watermark/kritzel-watermark.css +29 -0
- package/dist/collection/components/kritzel-watermark/kritzel-watermark.js +83 -0
- package/dist/collection/configs/default-asset-storage.config.js +9 -0
- package/dist/collection/configs/default-brush-tool.config.js +9 -0
- package/dist/collection/configs/default-engine-config.js +73 -0
- package/dist/collection/configs/default-line-tool.config.js +12 -0
- package/dist/collection/configs/default-shape-tool.config.js +15 -0
- package/dist/collection/configs/default-sync.config.js +6 -0
- package/dist/collection/configs/default-text-tool.config.js +12 -0
- package/dist/collection/constants/color-palette.constants.js +40 -0
- package/dist/collection/constants/core.constants.js +1 -0
- package/dist/collection/constants/engine.constants.js +4 -0
- package/dist/collection/constants/license.constants.js +25 -0
- package/dist/collection/constants/schema.constants.js +4 -0
- package/dist/collection/constants/storage.constants.js +1 -0
- package/dist/collection/constants/stroke-size.constants.js +2 -0
- package/dist/collection/constants/text-tool-fonts.constants.js +18 -0
- package/dist/collection/constants/version.js +6 -0
- package/dist/collection/enums/alignment.enum.js +9 -0
- package/dist/collection/enums/event-button.enum.js +6 -0
- package/dist/collection/enums/handle-type.enum.js +7 -0
- package/dist/collection/enums/shape-type.enum.js +6 -0
- package/dist/collection/events/active-workspace-change.event.js +1 -0
- package/dist/collection/events/editor-is-ready.event.js +1 -0
- package/dist/collection/events/login.event.js +1 -0
- package/dist/collection/helpers/alignment.helper.js +73 -0
- package/dist/collection/helpers/class.helper.js +5 -0
- package/dist/collection/helpers/color.helper.js +106 -0
- package/dist/collection/helpers/cursor.helper.js +57 -0
- package/dist/collection/helpers/devices.helper.js +28 -0
- package/dist/collection/helpers/event.helper.js +58 -0
- package/dist/collection/helpers/geometry.helper.js +149 -0
- package/dist/collection/helpers/html.helper.js +116 -0
- package/dist/collection/helpers/image-file.helper.js +6 -0
- package/dist/collection/helpers/keyboard.helper.js +55 -0
- package/dist/collection/helpers/localization.helper.js +25 -0
- package/dist/collection/helpers/math.helper.js +8 -0
- package/dist/collection/helpers/migration.helper.js +45 -0
- package/dist/collection/helpers/object.helper.js +29 -0
- package/dist/collection/helpers/svg-export.helper.js +655 -0
- package/dist/collection/helpers/theme.helper.js +77 -0
- package/dist/collection/helpers/tool-config.helper.js +63 -0
- package/dist/collection/helpers/wheel.helper.js +113 -0
- package/dist/collection/index.js +107 -0
- package/dist/collection/interfaces/anchor.interface.js +1 -0
- package/dist/collection/interfaces/arrow-head.interface.js +1 -0
- package/dist/collection/interfaces/asset-provider.interface.js +1 -0
- package/dist/collection/interfaces/asset-storage-config.interface.js +1 -0
- package/dist/collection/interfaces/asset.interface.js +1 -0
- package/dist/collection/interfaces/bounding-box.interface.js +1 -0
- package/dist/collection/interfaces/clonable.interface.js +1 -0
- package/dist/collection/interfaces/context-menu-item.interface.js +1 -0
- package/dist/collection/interfaces/context-menu-state.interface.js +1 -0
- package/dist/collection/interfaces/debug-info.interface.js +1 -0
- package/dist/collection/interfaces/dialog.interface.js +1 -0
- package/dist/collection/interfaces/document-metadata.interface.js +1 -0
- package/dist/collection/interfaces/dynamic-object-renderer.interface.js +1 -0
- package/dist/collection/interfaces/engine-state.interface.js +1 -0
- package/dist/collection/interfaces/font.interface.js +1 -0
- package/dist/collection/interfaces/localization.interface.js +1 -0
- package/dist/collection/interfaces/login-config.interface.js +1 -0
- package/dist/collection/interfaces/master-detail.interface.js +1 -0
- package/dist/collection/interfaces/menu-item.interface.js +1 -0
- package/dist/collection/interfaces/migration.interface.js +1 -0
- package/dist/collection/interfaces/notification.interface.js +1 -0
- package/dist/collection/interfaces/object-change-event.interface.js +1 -0
- package/dist/collection/interfaces/object-export.interface.js +1 -0
- package/dist/collection/interfaces/object.interface.js +1 -0
- package/dist/collection/interfaces/paste-intent-provider.interface.js +1 -0
- package/dist/collection/interfaces/point.interface.js +1 -0
- package/dist/collection/interfaces/polygon.interface.js +1 -0
- package/dist/collection/interfaces/remote-cursor.interface.js +1 -0
- package/dist/collection/interfaces/selection-state.interface.js +1 -0
- package/dist/collection/interfaces/serializable.interface.js +1 -0
- package/dist/collection/interfaces/settings.interface.js +1 -0
- package/dist/collection/interfaces/share.interface.js +1 -0
- package/dist/collection/interfaces/shortcut.interface.js +1 -0
- package/dist/collection/interfaces/sync-config.interface.js +21 -0
- package/dist/collection/interfaces/sync-provider.interface.js +1 -0
- package/dist/collection/interfaces/theme.interface.js +1 -0
- package/dist/collection/interfaces/tool-config.interface.js +1 -0
- package/dist/collection/interfaces/tool-type.interface.js +1 -0
- package/dist/collection/interfaces/tool.interface.js +1 -0
- package/dist/collection/interfaces/toolbar-item.interface.js +1 -0
- package/dist/collection/interfaces/undo-state.interface.js +1 -0
- package/dist/collection/interfaces/user.interface.js +1 -0
- package/dist/collection/interfaces/viewport-state.interface.js +1 -0
- package/dist/collection/locales/de-locale.js +119 -0
- package/dist/collection/locales/en-locale.js +120 -0
- package/dist/collection/locales/fr-locale.js +119 -0
- package/dist/collection/migrations/app-state.migrations.js +47 -0
- package/dist/collection/migrations/workspace.migrations.js +67 -0
- package/dist/collection/themes/dark-theme.js +340 -0
- package/dist/collection/themes/light-theme.js +346 -0
- package/dist/collection/types/deep-readonly.type.js +1 -0
- package/dist/collection/types/state.types.js +1 -0
- package/dist/components/index.d.ts +47 -0
- package/dist/components/index.js +4143 -0
- package/dist/components/kritzel-awareness-cursors.d.ts +11 -0
- package/dist/components/kritzel-awareness-cursors.js +6 -0
- package/dist/components/kritzel-cursor-trail.d.ts +11 -0
- package/dist/components/kritzel-cursor-trail.js +6 -0
- package/dist/components/kritzel-engine.d.ts +11 -0
- package/dist/components/kritzel-engine.js +52641 -0
- package/dist/components/kritzel-icon.d.ts +11 -0
- package/dist/components/kritzel-icon.js +6 -0
- package/dist/components/kritzel-watermark.d.ts +11 -0
- package/dist/components/kritzel-watermark.js +6 -0
- package/dist/components/p-B2Htv9ou.js +49 -0
- package/dist/components/p-BvRGQvVI.js +3456 -0
- package/dist/components/p-CfSx6HU_.js +1469 -0
- package/dist/components/p-YP8wAcF4.js +122 -0
- package/dist/components/p-fx6msYHJ.js +167 -0
- package/dist/esm/app-globals-DQuL1Twl.js +3 -0
- package/dist/esm/engine.constants-Bl5-pbq-.js +28143 -0
- package/dist/esm/index-BU9Mv7y0.js +1715 -0
- package/dist/esm/index.js +4134 -0
- package/dist/esm/kritzel-awareness-cursors_5.entry.js +27978 -0
- package/dist/esm/loader.js +11 -0
- package/dist/esm/stencil.js +21 -0
- package/dist/index.cjs.js +1 -0
- package/dist/index.js +1 -0
- package/dist/stencil/index.esm.js +4134 -0
- package/dist/stencil/p-BU9Mv7y0.js +1702 -0
- package/dist/stencil/p-Bl5-pbq-.js +28143 -0
- package/dist/stencil/p-DQuL1Twl.js +3 -0
- package/dist/stencil/p-f0a8b7af.entry.js +27978 -0
- package/dist/stencil/stencil.esm.js +21 -0
- package/dist/types/classes/core/core.class.d.ts +532 -0
- package/dist/types/classes/core/reviver.class.d.ts +32 -0
- package/dist/types/classes/core/store.class.d.ts +198 -0
- package/dist/types/classes/core/viewport.class.d.ts +256 -0
- package/dist/types/classes/core/workspace.class.d.ts +95 -0
- package/dist/types/classes/handlers/base.handler.d.ts +18 -0
- package/dist/types/classes/handlers/context-menu.handler.d.ts +67 -0
- package/dist/types/classes/handlers/hover.handler.d.ts +23 -0
- package/dist/types/classes/handlers/key.handler.d.ts +44 -0
- package/dist/types/classes/handlers/line-handle.handler.d.ts +115 -0
- package/dist/types/classes/handlers/move.handler.d.ts +94 -0
- package/dist/types/classes/handlers/resize.handler.d.ts +95 -0
- package/dist/types/classes/handlers/rotation.handler.d.ts +50 -0
- package/dist/types/classes/handlers/selection.handler.d.ts +153 -0
- package/dist/types/classes/managers/anchor.manager.d.ts +513 -0
- package/dist/types/classes/managers/browser-permission.manager.d.ts +41 -0
- package/dist/types/classes/managers/clipboard.manager.d.ts +71 -0
- package/dist/types/classes/managers/clipboard.types.d.ts +23 -0
- package/dist/types/classes/managers/cursor.manager.d.ts +66 -0
- package/dist/types/classes/managers/license.manager.d.ts +147 -0
- package/dist/types/classes/managers/localization.manager.d.ts +145 -0
- package/dist/types/classes/managers/theme.manager.d.ts +112 -0
- package/dist/types/classes/objects/base-object.class.d.ts +266 -0
- package/dist/types/classes/objects/dynamic-object.class.d.ts +148 -0
- package/dist/types/classes/objects/group.class.d.ts +231 -0
- package/dist/types/classes/objects/image.class.d.ts +246 -0
- package/dist/types/classes/objects/line.class.d.ts +285 -0
- package/dist/types/classes/objects/path.class.d.ts +220 -0
- package/dist/types/classes/objects/selection-box.class.d.ts +19 -0
- package/dist/types/classes/objects/selection-group.class.d.ts +267 -0
- package/dist/types/classes/objects/shape.class.d.ts +322 -0
- package/dist/types/classes/objects/text.class.d.ts +197 -0
- package/dist/types/classes/providers/assets/asset-resolver.class.d.ts +141 -0
- package/dist/types/classes/providers/assets/http-asset-provider.class.d.ts +79 -0
- package/dist/types/classes/providers/assets/indexeddb-asset-provider.class.d.ts +69 -0
- package/dist/types/classes/providers/assets/presigned-asset-provider.class.d.ts +69 -0
- package/dist/types/classes/providers/paste-intent/event-paste-intent.provider.d.ts +8 -0
- package/dist/types/classes/providers/paste-intent/ios-paste-intent.provider.d.ts +6 -0
- package/dist/types/classes/providers/paste-intent/navigator-paste-intent.provider.d.ts +9 -0
- package/dist/types/classes/providers/sync/broadcast-sync-provider.class.d.ts +23 -0
- package/dist/types/classes/providers/sync/hocuspocus-sync-provider.class.d.ts +163 -0
- package/dist/types/classes/providers/sync/in-memory-sync-provider.class.d.ts +39 -0
- package/dist/types/classes/providers/sync/indexeddb-sync-provider.class.d.ts +25 -0
- package/dist/types/classes/providers/sync/websocket-sync-provider.class.d.ts +63 -0
- package/dist/types/classes/registries/dynamic-object-renderer.registry.d.ts +32 -0
- package/dist/types/classes/registries/font-registry.class.d.ts +19 -0
- package/dist/types/classes/registries/icon-registry.class.d.ts +39 -0
- package/dist/types/classes/registries/paste-intent-provider.registry.d.ts +10 -0
- package/dist/types/classes/registries/tool.registry.d.ts +53 -0
- package/dist/types/classes/structures/app-state-map.structure.d.ts +171 -0
- package/dist/types/classes/structures/object-map.structure.d.ts +403 -0
- package/dist/types/classes/structures/quadtree.structure.d.ts +128 -0
- package/dist/types/classes/tools/base-tool.class.d.ts +72 -0
- package/dist/types/classes/tools/brush-tool.class.d.ts +68 -0
- package/dist/types/classes/tools/eraser-tool.class.d.ts +38 -0
- package/dist/types/classes/tools/image-tool.class.d.ts +74 -0
- package/dist/types/classes/tools/line-tool.class.d.ts +63 -0
- package/dist/types/classes/tools/selection-tool.class.d.ts +188 -0
- package/dist/types/classes/tools/shape-tool.class.d.ts +90 -0
- package/dist/types/classes/tools/text-tool.class.d.ts +66 -0
- package/dist/types/components/kritzel-awareness-cursors/kritzel-awareness-cursors.d.ts +29 -0
- package/dist/types/components/kritzel-cursor-trail/kritzel-cursor-trail.d.ts +19 -0
- package/dist/types/components/kritzel-engine/kritzel-engine.d.ts +695 -0
- package/dist/types/components/kritzel-icon/kritzel-icon.d.ts +6 -0
- package/dist/types/components/kritzel-watermark/kritzel-watermark.d.ts +20 -0
- package/dist/types/components.d.ts +981 -0
- package/dist/types/configs/default-asset-storage.config.d.ts +8 -0
- package/dist/types/configs/default-brush-tool.config.d.ts +2 -0
- package/dist/types/configs/default-engine-config.d.ts +2 -0
- package/dist/types/configs/default-line-tool.config.d.ts +2 -0
- package/dist/types/configs/default-shape-tool.config.d.ts +2 -0
- package/dist/types/configs/default-sync.config.d.ts +5 -0
- package/dist/types/configs/default-text-tool.config.d.ts +2 -0
- package/dist/types/constants/color-palette.constants.d.ts +31 -0
- package/dist/types/constants/core.constants.d.ts +0 -0
- package/dist/types/constants/engine.constants.d.ts +4 -0
- package/dist/types/constants/license.constants.d.ts +25 -0
- package/dist/types/constants/schema.constants.d.ts +4 -0
- package/dist/types/constants/storage.constants.d.ts +1 -0
- package/dist/types/constants/stroke-size.constants.d.ts +2 -0
- package/dist/types/constants/text-tool-fonts.constants.d.ts +3 -0
- package/dist/types/constants/version.d.ts +6 -0
- package/dist/types/enums/alignment.enum.d.ts +8 -0
- package/dist/types/enums/event-button.enum.d.ts +5 -0
- package/dist/types/enums/handle-type.enum.d.ts +6 -0
- package/dist/types/enums/shape-type.enum.d.ts +5 -0
- package/dist/types/events/active-workspace-change.event.d.ts +7 -0
- package/dist/types/events/editor-is-ready.event.d.ts +18 -0
- package/dist/types/events/login.event.d.ts +3 -0
- package/dist/types/helpers/alignment.helper.d.ts +21 -0
- package/dist/types/helpers/class.helper.d.ts +3 -0
- package/dist/types/helpers/color.helper.d.ts +34 -0
- package/dist/types/helpers/cursor.helper.d.ts +22 -0
- package/dist/types/helpers/devices.helper.d.ts +8 -0
- package/dist/types/helpers/event.helper.d.ts +6 -0
- package/dist/types/helpers/geometry.helper.d.ts +38 -0
- package/dist/types/helpers/html.helper.d.ts +8 -0
- package/dist/types/helpers/image-file.helper.d.ts +3 -0
- package/dist/types/helpers/keyboard.helper.d.ts +6 -0
- package/dist/types/helpers/localization.helper.d.ts +18 -0
- package/dist/types/helpers/math.helper.d.ts +4 -0
- package/dist/types/helpers/migration.helper.d.ts +30 -0
- package/dist/types/helpers/object.helper.d.ts +9 -0
- package/dist/types/helpers/svg-export.helper.d.ts +231 -0
- package/dist/types/helpers/theme.helper.d.ts +42 -0
- package/dist/types/helpers/tool-config.helper.d.ts +4 -0
- package/dist/types/helpers/wheel.helper.d.ts +9 -0
- package/dist/types/index.d.ts +109 -0
- package/dist/types/interfaces/anchor.interface.d.ts +147 -0
- package/dist/types/interfaces/arrow-head.interface.d.ts +27 -0
- package/dist/types/interfaces/asset-provider.interface.d.ts +88 -0
- package/dist/types/interfaces/asset-storage-config.interface.d.ts +40 -0
- package/dist/types/interfaces/asset.interface.d.ts +43 -0
- package/dist/types/interfaces/bounding-box.interface.d.ts +8 -0
- package/dist/types/interfaces/clonable.interface.d.ts +3 -0
- package/dist/types/interfaces/context-menu-item.interface.d.ts +25 -0
- package/dist/types/interfaces/context-menu-state.interface.d.ts +16 -0
- package/dist/types/interfaces/debug-info.interface.d.ts +7 -0
- package/dist/types/interfaces/dialog.interface.d.ts +4 -0
- package/dist/types/interfaces/document-metadata.interface.d.ts +6 -0
- package/dist/types/interfaces/dynamic-object-renderer.interface.d.ts +40 -0
- package/dist/types/interfaces/engine-state.interface.d.ts +82 -0
- package/dist/types/interfaces/font.interface.d.ts +15 -0
- package/dist/types/interfaces/localization.interface.d.ts +143 -0
- package/dist/types/interfaces/login-config.interface.d.ts +24 -0
- package/dist/types/interfaces/master-detail.interface.d.ts +14 -0
- package/dist/types/interfaces/menu-item.interface.d.ts +27 -0
- package/dist/types/interfaces/migration.interface.d.ts +16 -0
- package/dist/types/interfaces/notification.interface.d.ts +10 -0
- package/dist/types/interfaces/object-change-event.interface.d.ts +31 -0
- package/dist/types/interfaces/object-export.interface.d.ts +20 -0
- package/dist/types/interfaces/object.interface.d.ts +53 -0
- package/dist/types/interfaces/paste-intent-provider.interface.d.ts +10 -0
- package/dist/types/interfaces/point.interface.d.ts +4 -0
- package/dist/types/interfaces/polygon.interface.d.ts +7 -0
- package/dist/types/interfaces/remote-cursor.interface.d.ts +18 -0
- package/dist/types/interfaces/selection-state.interface.d.ts +7 -0
- package/dist/types/interfaces/serializable.interface.d.ts +5 -0
- package/dist/types/interfaces/settings.interface.d.ts +25 -0
- package/dist/types/interfaces/share.interface.d.ts +9 -0
- package/dist/types/interfaces/shortcut.interface.d.ts +10 -0
- package/dist/types/interfaces/sync-config.interface.d.ts +41 -0
- package/dist/types/interfaces/sync-provider.interface.d.ts +66 -0
- package/dist/types/interfaces/theme.interface.d.ts +553 -0
- package/dist/types/interfaces/tool-config.interface.d.ts +24 -0
- package/dist/types/interfaces/tool-type.interface.d.ts +1 -0
- package/dist/types/interfaces/tool.interface.d.ts +8 -0
- package/dist/types/interfaces/toolbar-item.interface.d.ts +66 -0
- package/dist/types/interfaces/undo-state.interface.d.ts +6 -0
- package/dist/types/interfaces/user.interface.d.ts +22 -0
- package/dist/types/interfaces/viewport-state.interface.d.ts +7 -0
- package/dist/types/locales/de-locale.d.ts +5 -0
- package/dist/types/locales/en-locale.d.ts +6 -0
- package/dist/types/locales/fr-locale.d.ts +5 -0
- package/dist/types/migrations/app-state.migrations.d.ts +11 -0
- package/dist/types/migrations/workspace.migrations.d.ts +11 -0
- package/dist/types/stencil-public-runtime.d.ts +1873 -0
- package/dist/types/themes/dark-theme.d.ts +5 -0
- package/dist/types/themes/light-theme.d.ts +5 -0
- package/dist/types/types/deep-readonly.type.d.ts +7 -0
- package/dist/types/types/state.types.d.ts +3 -0
- package/loader/cdn.js +1 -0
- package/loader/index.cjs.js +1 -0
- package/loader/index.d.ts +24 -0
- package/loader/index.es2017.js +1 -0
- package/loader/index.js +2 -0
- package/package.json +101 -0
- package/readme.md +11 -0
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
import { KritzelBaseObject } from "./base-object.class";
|
|
2
|
+
import { KritzelClassHelper } from "../../helpers/class.helper";
|
|
3
|
+
import { KritzelMathHelper } from "../../helpers/math.helper";
|
|
4
|
+
/**
|
|
5
|
+
* KritzelGroup represents a permanent grouping of objects that act as a single unit.
|
|
6
|
+
*
|
|
7
|
+
* Unlike KritzelSelectionGroup (which is ephemeral and used for temporary multi-selection),
|
|
8
|
+
* KritzelGroup is persisted and saved with the workspace. Grouped objects move, resize,
|
|
9
|
+
* rotate, copy, and delete together as one unit.
|
|
10
|
+
*
|
|
11
|
+
* Key features:
|
|
12
|
+
* - Supports nested groups (groups can contain other groups)
|
|
13
|
+
* - Clicking any child selects the entire group
|
|
14
|
+
* - Can be ungrouped to restore children to top-level objects
|
|
15
|
+
*/
|
|
16
|
+
export class KritzelGroup extends KritzelBaseObject {
|
|
17
|
+
__class__ = 'KritzelGroup';
|
|
18
|
+
constructor(config) {
|
|
19
|
+
super();
|
|
20
|
+
this.rotation = KritzelMathHelper.degreesToRadians(config?.rotation ?? 0);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* IDs of child objects within this group.
|
|
24
|
+
* Children can be any KritzelBaseObject, including other KritzelGroups for nesting.
|
|
25
|
+
*/
|
|
26
|
+
childIds = [];
|
|
27
|
+
/**
|
|
28
|
+
* Holds child objects that have been added via addChild() before the group
|
|
29
|
+
* is added to the engine. Once the group is added (and _core is set),
|
|
30
|
+
* these are flushed into the store and this array is cleared.
|
|
31
|
+
*/
|
|
32
|
+
_pendingChildren = [];
|
|
33
|
+
/**
|
|
34
|
+
* Snapshots of child states for transformation operations (resize, rotate).
|
|
35
|
+
* Similar pattern to KritzelSelectionGroup.
|
|
36
|
+
*/
|
|
37
|
+
unchangedChildSnapshots = new Map();
|
|
38
|
+
snapshotRotation = 0;
|
|
39
|
+
snapshotTranslateX = 0;
|
|
40
|
+
snapshotTranslateY = 0;
|
|
41
|
+
snapshotTotalWidth = 0;
|
|
42
|
+
snapshotTotalHeight = 0;
|
|
43
|
+
snapshotScale = 1;
|
|
44
|
+
/**
|
|
45
|
+
* Retrieves the actual child objects from the store by their IDs.
|
|
46
|
+
* Filters out any IDs that no longer exist in the store.
|
|
47
|
+
* @returns An array of KritzelBaseObject instances representing the group's children.
|
|
48
|
+
*/
|
|
49
|
+
get children() {
|
|
50
|
+
if (!this._core) {
|
|
51
|
+
return this._pendingChildren;
|
|
52
|
+
}
|
|
53
|
+
return this.childIds
|
|
54
|
+
.map(id => {
|
|
55
|
+
const found = this._core.store.objects.filter(obj => obj.id === id);
|
|
56
|
+
return found.length > 0 ? found[0] : null;
|
|
57
|
+
})
|
|
58
|
+
.filter((obj) => obj !== null);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns the number of children in this group.
|
|
62
|
+
* @returns The count of child IDs stored in this group.
|
|
63
|
+
*/
|
|
64
|
+
get length() {
|
|
65
|
+
return this.childIds.length;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Factory method to create a new empty KritzelGroup with core integration.
|
|
69
|
+
* Initializes the group with default values and links it to the core store.
|
|
70
|
+
* @param core - The KritzelCore instance providing access to store and state management.
|
|
71
|
+
* @returns A new KritzelGroup instance configured with the core context.
|
|
72
|
+
*/
|
|
73
|
+
static create(core, config) {
|
|
74
|
+
const group = new KritzelGroup(config);
|
|
75
|
+
group._core = core;
|
|
76
|
+
group.id = group.generateId();
|
|
77
|
+
group.workspaceId = core.store.state.activeWorkspace.id;
|
|
78
|
+
group.userId = core.user?.id;
|
|
79
|
+
group.scale = core.store.state.scale;
|
|
80
|
+
group.zIndex = core.store.currentZIndex;
|
|
81
|
+
return group;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Creates a KritzelGroup from an array of existing objects.
|
|
85
|
+
* The objects are added as children and the group's bounding box is calculated
|
|
86
|
+
* to encompass all children. Child snapshots are captured for transformation operations.
|
|
87
|
+
* @param core - The KritzelCore instance providing access to store and state management.
|
|
88
|
+
* @param objects - An array of KritzelBaseObject instances to group together.
|
|
89
|
+
* @returns A new KritzelGroup containing the specified objects as children.
|
|
90
|
+
*/
|
|
91
|
+
static createFromObjects(core, objects) {
|
|
92
|
+
const group = KritzelGroup.create(core);
|
|
93
|
+
// Add all objects as children
|
|
94
|
+
objects.forEach(obj => {
|
|
95
|
+
group.childIds.push(obj.id);
|
|
96
|
+
});
|
|
97
|
+
// Calculate bounding box from children
|
|
98
|
+
group.refreshBoundingBox();
|
|
99
|
+
group.captureChildSnapshots();
|
|
100
|
+
return group;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Finds the parent KritzelGroup that contains the given object as a direct child.
|
|
104
|
+
* Searches through all groups in the store to find one containing the specified object ID.
|
|
105
|
+
* @param core - The KritzelCore instance providing access to the object store.
|
|
106
|
+
* @param objectId - The unique identifier of the object to find the parent group for.
|
|
107
|
+
* @returns The parent KritzelGroup if found, or null if the object is not a child of any group.
|
|
108
|
+
*/
|
|
109
|
+
static findParentGroup(core, objectId) {
|
|
110
|
+
const allGroups = core.store.objects
|
|
111
|
+
.filter(obj => obj.__class__ === 'KritzelGroup');
|
|
112
|
+
for (const group of allGroups) {
|
|
113
|
+
if (group.childIds.includes(objectId)) {
|
|
114
|
+
return group;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Recursively collects the IDs of all descendants of the given group (children,
|
|
121
|
+
* grandchildren, etc.). Useful for detecting when a selection contains both an
|
|
122
|
+
* ancestor group and one of its descendants — a configuration that would otherwise
|
|
123
|
+
* cause the descendant to be transformed twice (once via the ancestor, once directly).
|
|
124
|
+
* @param group - The group whose descendants should be collected.
|
|
125
|
+
* @param out - A set that will be populated with all descendant object IDs.
|
|
126
|
+
*/
|
|
127
|
+
static collectDescendantIds(group, out = new Set()) {
|
|
128
|
+
for (const child of group.children) {
|
|
129
|
+
out.add(child.id);
|
|
130
|
+
if (child instanceof KritzelGroup) {
|
|
131
|
+
KritzelGroup.collectDescendantIds(child, out);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return out;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Adds a child object to this group.
|
|
138
|
+
* If the object is already a child, no action is taken.
|
|
139
|
+
* Automatically refreshes the bounding box and captures child snapshots.
|
|
140
|
+
* @param object - The KritzelBaseObject instance to add as a child.
|
|
141
|
+
*/
|
|
142
|
+
addChild(object) {
|
|
143
|
+
if (!this.childIds.includes(object.id)) {
|
|
144
|
+
this.childIds.push(object.id);
|
|
145
|
+
if (!this._core) {
|
|
146
|
+
this._pendingChildren.push(object);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this.refreshBoundingBox();
|
|
150
|
+
this.captureChildSnapshots();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Removes a child object from this group by its ID.
|
|
155
|
+
* If the object is not a child, no action is taken.
|
|
156
|
+
* Automatically refreshes the bounding box and captures child snapshots.
|
|
157
|
+
* @param objectId - The unique identifier of the child object to remove.
|
|
158
|
+
*/
|
|
159
|
+
removeChild(objectId) {
|
|
160
|
+
const index = this.childIds.indexOf(objectId);
|
|
161
|
+
if (index !== -1) {
|
|
162
|
+
this.childIds.splice(index, 1);
|
|
163
|
+
this.refreshBoundingBox();
|
|
164
|
+
this.captureChildSnapshots();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Ungroups this group, returning all children to top-level objects.
|
|
169
|
+
* The group itself should be removed from the store after calling this method.
|
|
170
|
+
* @returns An array of all child objects that were part of this group.
|
|
171
|
+
*/
|
|
172
|
+
ungroup() {
|
|
173
|
+
return this.children;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Finalizes the group after children have been positioned (e.g., after paste).
|
|
177
|
+
* Refreshes the bounding box to encompass all children and captures
|
|
178
|
+
* child snapshots for subsequent transformation operations.
|
|
179
|
+
*
|
|
180
|
+
* Recursively finalizes nested child groups first, so that when a transform
|
|
181
|
+
* (rotate/resize) cascades through nested groups, every group's snapshots are
|
|
182
|
+
* aligned with the current visual state. Without this, a nested group's
|
|
183
|
+
* `snapshotRotation` could be stale, causing the inner group to be offset
|
|
184
|
+
* relative to its parent during rotation.
|
|
185
|
+
*/
|
|
186
|
+
finalize() {
|
|
187
|
+
for (const child of this.children) {
|
|
188
|
+
if (child instanceof KritzelGroup) {
|
|
189
|
+
child.finalize();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
this.refreshBoundingBox();
|
|
193
|
+
this.captureChildSnapshots();
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Moves the group and all its children to the center of the viewport.
|
|
197
|
+
* Overrides the base implementation to ensure children move with the group.
|
|
198
|
+
*/
|
|
199
|
+
centerInViewport() {
|
|
200
|
+
const { viewportWidth, viewportHeight, translateX: viewportTranslateX, translateY: viewportTranslateY, scale: viewportScale } = this._core.store.state;
|
|
201
|
+
const { x, y, width, height } = this.rotatedBoundingBox;
|
|
202
|
+
const objectCenterX = x + width / 2;
|
|
203
|
+
const objectCenterY = y + height / 2;
|
|
204
|
+
const targetCenterX = (viewportWidth / 2 - viewportTranslateX) / viewportScale;
|
|
205
|
+
const targetCenterY = (viewportHeight / 2 - viewportTranslateY) / viewportScale;
|
|
206
|
+
const deltaX = targetCenterX - objectCenterX;
|
|
207
|
+
const deltaY = targetCenterY - objectCenterY;
|
|
208
|
+
this.translateX += deltaX;
|
|
209
|
+
this.translateY += deltaY;
|
|
210
|
+
this.children.forEach(child => {
|
|
211
|
+
child.translateX += deltaX;
|
|
212
|
+
child.translateY += deltaY;
|
|
213
|
+
});
|
|
214
|
+
this.captureChildSnapshots();
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Recalculates the group's bounding box based on its children.
|
|
218
|
+
* Handles three cases: empty group (zero dimensions), single child (inherit its bounds),
|
|
219
|
+
* and multiple children (calculate encompassing bounds with rotation support).
|
|
220
|
+
* Updates translateX, translateY, width, and height properties.
|
|
221
|
+
*/
|
|
222
|
+
refreshBoundingBox() {
|
|
223
|
+
if (this.children.length === 0) {
|
|
224
|
+
this.width = 0;
|
|
225
|
+
this.height = 0;
|
|
226
|
+
this.translateX = 0;
|
|
227
|
+
this.translateY = 0;
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (this.children.length === 1) {
|
|
231
|
+
// Single child: inherit its bounding box
|
|
232
|
+
const child = this.children[0];
|
|
233
|
+
this.translateX = child.boundingBox.x;
|
|
234
|
+
this.translateY = child.boundingBox.y;
|
|
235
|
+
this.width = child.boundingBox.width * this.scale;
|
|
236
|
+
this.height = child.boundingBox.height * this.scale;
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
// Multiple children: calculate encompassing bounding box
|
|
240
|
+
const rotation = this.rotation;
|
|
241
|
+
const cos = Math.cos(-rotation);
|
|
242
|
+
const sin = Math.sin(-rotation);
|
|
243
|
+
let minX = Infinity;
|
|
244
|
+
let maxX = -Infinity;
|
|
245
|
+
let minY = Infinity;
|
|
246
|
+
let maxY = -Infinity;
|
|
247
|
+
this.children.forEach(child => {
|
|
248
|
+
const polygon = child.rotatedPolygon;
|
|
249
|
+
const corners = [polygon.topLeft, polygon.topRight, polygon.bottomRight, polygon.bottomLeft];
|
|
250
|
+
corners.forEach(corner => {
|
|
251
|
+
// Rotate corner into local space (aligned with group rotation)
|
|
252
|
+
const rx = corner.x * cos - corner.y * sin;
|
|
253
|
+
const ry = corner.x * sin + corner.y * cos;
|
|
254
|
+
if (rx < minX)
|
|
255
|
+
minX = rx;
|
|
256
|
+
if (rx > maxX)
|
|
257
|
+
maxX = rx;
|
|
258
|
+
if (ry < minY)
|
|
259
|
+
minY = ry;
|
|
260
|
+
if (ry > maxY)
|
|
261
|
+
maxY = ry;
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
// Dimensions in world units (unrotated)
|
|
265
|
+
const worldWidth = maxX - minX;
|
|
266
|
+
const worldHeight = maxY - minY;
|
|
267
|
+
this.width = (worldWidth - this.padding) * this.scale;
|
|
268
|
+
this.height = (worldHeight - this.padding) * this.scale;
|
|
269
|
+
// Center of the box in rotated space
|
|
270
|
+
const cRx = (minX + maxX) / 2;
|
|
271
|
+
const cRy = (minY + maxY) / 2;
|
|
272
|
+
// Rotate center back to world space
|
|
273
|
+
const cosR = Math.cos(rotation);
|
|
274
|
+
const sinR = Math.sin(rotation);
|
|
275
|
+
const cx = cRx * cosR - cRy * sinR;
|
|
276
|
+
const cy = cRx * sinR + cRy * cosR;
|
|
277
|
+
this.translateX = cx - (this.width / this.scale + 2 * this.padding) / 2;
|
|
278
|
+
this.translateY = cy - (this.height / this.scale + 2 * this.padding) / 2;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Captures snapshots of all child states for transformation operations.
|
|
282
|
+
* Stores position, rotation, dimensions, and scale for each child.
|
|
283
|
+
* Also captures the group's current state for relative calculations.
|
|
284
|
+
*/
|
|
285
|
+
captureChildSnapshots() {
|
|
286
|
+
this.unchangedChildSnapshots.clear();
|
|
287
|
+
this.snapshotRotation = this.rotation;
|
|
288
|
+
this.snapshotTranslateX = this.translateX;
|
|
289
|
+
this.snapshotTranslateY = this.translateY;
|
|
290
|
+
this.snapshotTotalWidth = this.totalWidth;
|
|
291
|
+
this.snapshotTotalHeight = this.totalHeight;
|
|
292
|
+
this.snapshotScale = this.scale || 1;
|
|
293
|
+
this.children.forEach(child => {
|
|
294
|
+
this.unchangedChildSnapshots.set(child.id, {
|
|
295
|
+
id: child.id,
|
|
296
|
+
translateX: child.translateX,
|
|
297
|
+
translateY: child.translateY,
|
|
298
|
+
rotation: child.rotation,
|
|
299
|
+
width: child.width,
|
|
300
|
+
height: child.height,
|
|
301
|
+
totalWidth: child.totalWidth,
|
|
302
|
+
totalHeight: child.totalHeight,
|
|
303
|
+
scale: child.scale,
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
308
|
+
// TRANSFORMATION METHODS
|
|
309
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
310
|
+
/**
|
|
311
|
+
* Moves the group and all its children by the delta between start and end positions.
|
|
312
|
+
* Updates are wrapped in a transaction for atomic persistence.
|
|
313
|
+
* Also updates any lines anchored to child objects.
|
|
314
|
+
* @param startX - The starting x coordinate in screen space.
|
|
315
|
+
* @param startY - The starting y coordinate in screen space.
|
|
316
|
+
* @param endX - The ending x coordinate in screen space.
|
|
317
|
+
* @param endY - The ending y coordinate in screen space.
|
|
318
|
+
*/
|
|
319
|
+
move(startX, startY, endX, endY) {
|
|
320
|
+
const deltaX = (startX - endX) / this._core.store.state.scale;
|
|
321
|
+
const deltaY = (startY - endY) / this._core.store.state.scale;
|
|
322
|
+
this.translateX += deltaX;
|
|
323
|
+
this.translateY += deltaY;
|
|
324
|
+
this._core.store.objects.transaction(() => {
|
|
325
|
+
this._core.store.objects.update(this);
|
|
326
|
+
this.children.forEach(child => {
|
|
327
|
+
child.move(startX, startY, endX, endY);
|
|
328
|
+
// Update any lines anchored to this child
|
|
329
|
+
this._core.anchorManager.updateAnchorsForObject(child.id);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
// Update snapshots
|
|
333
|
+
this.unchangedChildSnapshots.forEach(snapshot => {
|
|
334
|
+
snapshot.translateX += deltaX;
|
|
335
|
+
snapshot.translateY += deltaY;
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Resizes the group and proportionally transforms all children.
|
|
340
|
+
* Children are scaled and repositioned relative to the group's center,
|
|
341
|
+
* accounting for rotation. Updates are wrapped in a transaction.
|
|
342
|
+
* @param x - The new x translation coordinate for the group.
|
|
343
|
+
* @param y - The new y translation coordinate for the group.
|
|
344
|
+
* @param width - The new width of the group's content area.
|
|
345
|
+
* @param height - The new height of the group's content area.
|
|
346
|
+
*/
|
|
347
|
+
resize(x, y, width, height) {
|
|
348
|
+
// Use snapshot dimensions (stable across the gesture) instead of `this.*`,
|
|
349
|
+
// which mutates each frame and gets distorted by descendants like KritzelText
|
|
350
|
+
// that clamp to a uniform scale, causing the cascade factor to drift.
|
|
351
|
+
const baseWidth = this.snapshotTotalWidth > 0
|
|
352
|
+
? this.snapshotTotalWidth - this.padding * 2
|
|
353
|
+
: this.width;
|
|
354
|
+
const baseHeight = this.snapshotTotalHeight > 0
|
|
355
|
+
? this.snapshotTotalHeight - this.padding * 2
|
|
356
|
+
: this.height;
|
|
357
|
+
const baseScale = this.snapshotScale || this.scale || 1;
|
|
358
|
+
const widthScaleFactor = baseWidth !== 0 ? width / baseWidth : 1;
|
|
359
|
+
const heightScaleFactor = baseHeight !== 0 ? height / baseHeight : 1;
|
|
360
|
+
// Calculate old center from snapshot (stable across the gesture)
|
|
361
|
+
const snapshotTotalWidth = this.snapshotTotalWidth || (this.width + this.padding * 2);
|
|
362
|
+
const snapshotTotalHeight = this.snapshotTotalHeight || (this.height + this.padding * 2);
|
|
363
|
+
const oldCenterX = this.snapshotTranslateX + snapshotTotalWidth / 2 / baseScale;
|
|
364
|
+
const oldCenterY = this.snapshotTranslateY + snapshotTotalHeight / 2 / baseScale;
|
|
365
|
+
// Calculate new center
|
|
366
|
+
const newTotalWidth = width + this.padding * 2;
|
|
367
|
+
const newTotalHeight = height + this.padding * 2;
|
|
368
|
+
const newCenterX = x + newTotalWidth / 2 / this.scale;
|
|
369
|
+
const newCenterY = y + newTotalHeight / 2 / this.scale;
|
|
370
|
+
const rotation = this.rotation;
|
|
371
|
+
const cos = Math.cos(-rotation);
|
|
372
|
+
const sin = Math.sin(-rotation);
|
|
373
|
+
const cosR = Math.cos(rotation);
|
|
374
|
+
const sinR = Math.sin(rotation);
|
|
375
|
+
this._core.store.objects.transaction(() => {
|
|
376
|
+
this.children.forEach(child => {
|
|
377
|
+
// Use snapshot values for the child to avoid compounding distortions caused
|
|
378
|
+
// by descendants like text that cannot honour requested aspect ratios.
|
|
379
|
+
const snapshot = this.unchangedChildSnapshots.get(child.id);
|
|
380
|
+
const childTranslateX = snapshot ? snapshot.translateX : child.translateX;
|
|
381
|
+
const childTranslateY = snapshot ? snapshot.translateY : child.translateY;
|
|
382
|
+
const childTotalWidth = snapshot ? snapshot.totalWidth : child.totalWidth;
|
|
383
|
+
const childTotalHeight = snapshot ? snapshot.totalHeight : child.totalHeight;
|
|
384
|
+
const childWidth = snapshot ? snapshot.width : child.width;
|
|
385
|
+
const childHeight = snapshot ? snapshot.height : child.height;
|
|
386
|
+
const childRotation = snapshot ? snapshot.rotation : child.rotation;
|
|
387
|
+
const childScale = (snapshot ? snapshot.scale : child.scale) || 1;
|
|
388
|
+
// Calculate child center from snapshot
|
|
389
|
+
const childCenterX = childTranslateX + childTotalWidth / 2 / childScale;
|
|
390
|
+
const childCenterY = childTranslateY + childTotalHeight / 2 / childScale;
|
|
391
|
+
// Vector from old group center to child center
|
|
392
|
+
const dx = childCenterX - oldCenterX;
|
|
393
|
+
const dy = childCenterY - oldCenterY;
|
|
394
|
+
// Rotate to local space
|
|
395
|
+
const localX = dx * cos - dy * sin;
|
|
396
|
+
const localY = dx * sin + dy * cos;
|
|
397
|
+
// Scale in local space
|
|
398
|
+
const scaledLocalX = localX * widthScaleFactor;
|
|
399
|
+
const scaledLocalY = localY * heightScaleFactor;
|
|
400
|
+
// Rotate back to world space
|
|
401
|
+
const rotatedX = scaledLocalX * cosR - scaledLocalY * sinR;
|
|
402
|
+
const rotatedY = scaledLocalX * sinR + scaledLocalY * cosR;
|
|
403
|
+
// New child center
|
|
404
|
+
const newChildCenterX = newCenterX + rotatedX;
|
|
405
|
+
const newChildCenterY = newCenterY + rotatedY;
|
|
406
|
+
// Calculate relative rotation for scaling
|
|
407
|
+
const relativeRotation = childRotation - rotation;
|
|
408
|
+
const cosRel = Math.cos(relativeRotation);
|
|
409
|
+
const sinRel = Math.sin(relativeRotation);
|
|
410
|
+
const newChildWidthScale = Math.sqrt(Math.pow(widthScaleFactor * cosRel, 2) + Math.pow(heightScaleFactor * sinRel, 2));
|
|
411
|
+
const newChildHeightScale = Math.sqrt(Math.pow(widthScaleFactor * sinRel, 2) + Math.pow(heightScaleFactor * cosRel, 2));
|
|
412
|
+
const updatedWidth = childWidth * newChildWidthScale;
|
|
413
|
+
const updatedHeight = childHeight * newChildHeightScale;
|
|
414
|
+
const updatedTotalWidth = updatedWidth + child.padding * 2;
|
|
415
|
+
const updatedTotalHeight = updatedHeight + child.padding * 2;
|
|
416
|
+
const updatedX = newChildCenterX - updatedTotalWidth / 2 / child.scale;
|
|
417
|
+
const updatedY = newChildCenterY - updatedTotalHeight / 2 / child.scale;
|
|
418
|
+
child.resize(updatedX, updatedY, updatedWidth, updatedHeight);
|
|
419
|
+
// Update anchored lines
|
|
420
|
+
this._core.anchorManager.updateAnchorsForObject(child.id);
|
|
421
|
+
});
|
|
422
|
+
this.refreshBoundingBox();
|
|
423
|
+
// Don't recapture snapshots while an interactive resize is in progress —
|
|
424
|
+
// recapturing each frame would defeat the purpose of using stable snapshots
|
|
425
|
+
// and re-introduce the compounding distortion described above. Snapshots are
|
|
426
|
+
// refreshed at the start of the next gesture via beginTransform/finalize.
|
|
427
|
+
if (!this._core.store.state.isResizing) {
|
|
428
|
+
this.captureChildSnapshots();
|
|
429
|
+
}
|
|
430
|
+
this._core.store.objects.update(this);
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Rotates the group and all its children around the group's center.
|
|
435
|
+
* Children maintain their relative positions and are individually rotated.
|
|
436
|
+
* Uses captured snapshots to calculate rotation deltas.
|
|
437
|
+
* @param value - The new absolute rotation angle in radians.
|
|
438
|
+
*/
|
|
439
|
+
rotate(value) {
|
|
440
|
+
this.rotation = value;
|
|
441
|
+
const centerX = this.translateX + this.totalWidth / 2 / this.scale;
|
|
442
|
+
const centerY = this.translateY + this.totalHeight / 2 / this.scale;
|
|
443
|
+
const angle = value - this.snapshotRotation;
|
|
444
|
+
const cos = Math.cos(angle);
|
|
445
|
+
const sin = Math.sin(angle);
|
|
446
|
+
this._core.store.objects.transaction(() => {
|
|
447
|
+
this._core.store.objects.update(this);
|
|
448
|
+
this.children.forEach(child => {
|
|
449
|
+
const unchangedSnapshot = this.unchangedChildSnapshots.get(child.id);
|
|
450
|
+
if (!unchangedSnapshot)
|
|
451
|
+
return;
|
|
452
|
+
const offsetX = this.getOffsetXToCenterFromSnapshot(unchangedSnapshot);
|
|
453
|
+
const offsetY = this.getOffsetYToCenterFromSnapshot(unchangedSnapshot);
|
|
454
|
+
const rotatedX = cos * offsetX - sin * offsetY;
|
|
455
|
+
const rotatedY = sin * offsetX + cos * offsetY;
|
|
456
|
+
child.translateX = centerX + rotatedX - child.totalWidth / 2 / child.scale;
|
|
457
|
+
child.translateY = centerY + rotatedY - child.totalHeight / 2 / child.scale;
|
|
458
|
+
child.rotate(this.children.length === 1 ? value : unchangedSnapshot.rotation + angle);
|
|
459
|
+
});
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Calculates the horizontal offset from the group's center to a child's center
|
|
464
|
+
* using the captured snapshot values.
|
|
465
|
+
* @param snapshot - The captured state of the child object.
|
|
466
|
+
* @returns The x-axis offset from the group center to the child center.
|
|
467
|
+
*/
|
|
468
|
+
getOffsetXToCenterFromSnapshot(snapshot) {
|
|
469
|
+
const childCenterX = snapshot.translateX + snapshot.totalWidth / snapshot.scale / 2;
|
|
470
|
+
const groupScale = this.snapshotScale || this.scale || 1;
|
|
471
|
+
const groupCenterX = this.snapshotTranslateX + this.snapshotTotalWidth / groupScale / 2;
|
|
472
|
+
return childCenterX - groupCenterX;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Calculates the vertical offset from the group's center to a child's center
|
|
476
|
+
* using the captured snapshot values.
|
|
477
|
+
* @param snapshot - The captured state of the child object.
|
|
478
|
+
* @returns The y-axis offset from the group center to the child center.
|
|
479
|
+
*/
|
|
480
|
+
getOffsetYToCenterFromSnapshot(snapshot) {
|
|
481
|
+
const childCenterY = snapshot.translateY + snapshot.totalHeight / snapshot.scale / 2;
|
|
482
|
+
const groupScale = this.snapshotScale || this.scale || 1;
|
|
483
|
+
const groupCenterY = this.snapshotTranslateY + this.snapshotTotalHeight / groupScale / 2;
|
|
484
|
+
return childCenterY - groupCenterY;
|
|
485
|
+
}
|
|
486
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
487
|
+
// HIT TESTING
|
|
488
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
489
|
+
/**
|
|
490
|
+
* Tests if a point lies within any of the group's children.
|
|
491
|
+
* The group is considered hit if any child passes the hit test.
|
|
492
|
+
* @param x - The x coordinate to test in world space.
|
|
493
|
+
* @param y - The y coordinate to test in world space.
|
|
494
|
+
* @returns True if the point is inside any child, false otherwise.
|
|
495
|
+
*/
|
|
496
|
+
hitTest(x, y) {
|
|
497
|
+
// Check if point is inside any child
|
|
498
|
+
return this.children.some(child => child.hitTest(x, y));
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Tests if a polygon intersects with any of the group's children.
|
|
502
|
+
* Used for lasso selection and area-based hit detection.
|
|
503
|
+
* @param polygon - The polygon to test intersection against.
|
|
504
|
+
* @returns True if the polygon intersects any child, false otherwise.
|
|
505
|
+
*/
|
|
506
|
+
hitTestPolygon(polygon) {
|
|
507
|
+
// Check if polygon intersects with any child
|
|
508
|
+
return this.children.some(child => child.hitTestPolygon(polygon));
|
|
509
|
+
}
|
|
510
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
511
|
+
// COPY & SERIALIZATION
|
|
512
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
513
|
+
/**
|
|
514
|
+
* Creates a deep copy of this group and all its children.
|
|
515
|
+
* Children are copied but not added to the store; they are stored
|
|
516
|
+
* in a temporary _pendingChildren property for paste() to handle.
|
|
517
|
+
* @returns A new KritzelGroup with copied children and properties.
|
|
518
|
+
*/
|
|
519
|
+
copy() {
|
|
520
|
+
const copiedGroup = KritzelGroup.create(this._core);
|
|
521
|
+
// Deep copy all children but DON'T add to store yet
|
|
522
|
+
// Store the copied children temporarily for paste() to handle
|
|
523
|
+
const copiedChildren = [];
|
|
524
|
+
this.children
|
|
525
|
+
.sort((a, b) => a.zIndex - b.zIndex)
|
|
526
|
+
.forEach(child => {
|
|
527
|
+
const copiedChild = child.copy();
|
|
528
|
+
copiedChildren.push(copiedChild);
|
|
529
|
+
copiedGroup.childIds.push(copiedChild.id);
|
|
530
|
+
});
|
|
531
|
+
// Store copied children on the group for paste() to handle
|
|
532
|
+
copiedGroup._pendingChildren = copiedChildren;
|
|
533
|
+
// Copy group properties
|
|
534
|
+
copiedGroup.rotation = this.rotation;
|
|
535
|
+
copiedGroup.translateX = this.translateX;
|
|
536
|
+
copiedGroup.translateY = this.translateY;
|
|
537
|
+
copiedGroup.width = this.width;
|
|
538
|
+
copiedGroup.height = this.height;
|
|
539
|
+
return copiedGroup;
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* Serializes the group to a plain object for persistence.
|
|
543
|
+
* Excludes runtime references (_core, _elementRef, element) and
|
|
544
|
+
* converts the unchangedChildSnapshots Map to a plain object.
|
|
545
|
+
* @returns A serializable plain object representation of this group.
|
|
546
|
+
*/
|
|
547
|
+
serialize() {
|
|
548
|
+
const { _core, _elementRef, element, totalWidth, totalHeight, unchangedChildSnapshots, _pendingChildren, ...remainingProps } = this;
|
|
549
|
+
const clonedProps = structuredClone(remainingProps);
|
|
550
|
+
// Convert Map to plain object for serialization
|
|
551
|
+
clonedProps.unchangedChildSnapshots = Object.fromEntries(this.unchangedChildSnapshots);
|
|
552
|
+
return clonedProps;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Deserializes a plain object back into this KritzelGroup instance.
|
|
556
|
+
* Restores the unchangedChildSnapshots Map from the serialized object format.
|
|
557
|
+
* @param object - The serialized plain object containing group data.
|
|
558
|
+
* @returns This group instance after deserialization, cast to type T.
|
|
559
|
+
*/
|
|
560
|
+
deserialize(object) {
|
|
561
|
+
super.deserialize(object);
|
|
562
|
+
// Restore the Map from serialized object
|
|
563
|
+
if (object.unchangedChildSnapshots) {
|
|
564
|
+
this.unchangedChildSnapshots = new Map(Object.entries(object.unchangedChildSnapshots));
|
|
565
|
+
}
|
|
566
|
+
return this;
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Persists the current state of this group to the store.
|
|
570
|
+
* Triggers synchronization with y.js for collaborative editing.
|
|
571
|
+
*/
|
|
572
|
+
update() {
|
|
573
|
+
this._core.store.objects.update(this);
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Updates the workspace ID for this group and all its children recursively.
|
|
577
|
+
* Handles nested groups by recursively calling this method on child groups.
|
|
578
|
+
* @param workspaceId - The new workspace ID to assign to this group and its children.
|
|
579
|
+
*/
|
|
580
|
+
updateWorkspaceId(workspaceId) {
|
|
581
|
+
this.workspaceId = workspaceId;
|
|
582
|
+
this.children.forEach(child => {
|
|
583
|
+
child.workspaceId = workspaceId;
|
|
584
|
+
// Recursively update nested groups
|
|
585
|
+
if (KritzelClassHelper.isInstanceOf(child, 'KritzelGroup')) {
|
|
586
|
+
child.updateWorkspaceId(workspaceId);
|
|
587
|
+
}
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
}
|