@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,106 @@
|
|
|
1
|
+
import { resolveColor } from "../constants/color-palette.constants";
|
|
2
|
+
import { KritzelThemeManager } from "../classes/managers/theme.manager";
|
|
3
|
+
export class KritzelColorHelper {
|
|
4
|
+
/**
|
|
5
|
+
* Resolves a color value based on the current theme.
|
|
6
|
+
* Handles both simple string colors and theme-aware color objects.
|
|
7
|
+
* @param color - The color to resolve (string or ThemeAwareColor)
|
|
8
|
+
* @param theme - Optional theme to use. If not provided, uses current theme from ThemeManager
|
|
9
|
+
* @returns The resolved hex color string, or empty string if color is undefined
|
|
10
|
+
*/
|
|
11
|
+
static resolveThemeColor(color, theme) {
|
|
12
|
+
if (!color) {
|
|
13
|
+
return '';
|
|
14
|
+
}
|
|
15
|
+
const currentTheme = theme ?? KritzelThemeManager.getStoredTheme();
|
|
16
|
+
return resolveColor(color, currentTheme);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Applies opacity to a theme-aware color and returns an rgba string.
|
|
20
|
+
* @param color - The theme-aware color object or a hex color string
|
|
21
|
+
* @param opacity - The opacity value between 0 and 1
|
|
22
|
+
* @param theme - Optional theme to use. If not provided, uses current theme from ThemeManager
|
|
23
|
+
* @returns The color as an rgba string, or the resolved hex if opacity is 1
|
|
24
|
+
*/
|
|
25
|
+
static applyOpacity(color, opacity, theme) {
|
|
26
|
+
const hexColor = typeof color === 'string' ? color : this.resolveThemeColor(color, theme);
|
|
27
|
+
if (!hexColor || opacity >= 1)
|
|
28
|
+
return hexColor;
|
|
29
|
+
const sanitizedHex = hexColor.startsWith('#') ? hexColor.slice(1) : hexColor;
|
|
30
|
+
let r, g, b;
|
|
31
|
+
if (sanitizedHex.length === 3) {
|
|
32
|
+
r = parseInt(sanitizedHex[0] + sanitizedHex[0], 16);
|
|
33
|
+
g = parseInt(sanitizedHex[1] + sanitizedHex[1], 16);
|
|
34
|
+
b = parseInt(sanitizedHex[2] + sanitizedHex[2], 16);
|
|
35
|
+
}
|
|
36
|
+
else if (sanitizedHex.length === 6) {
|
|
37
|
+
r = parseInt(sanitizedHex.substring(0, 2), 16);
|
|
38
|
+
g = parseInt(sanitizedHex.substring(2, 4), 16);
|
|
39
|
+
b = parseInt(sanitizedHex.substring(4, 6), 16);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
return hexColor;
|
|
43
|
+
}
|
|
44
|
+
if (isNaN(r) || isNaN(g) || isNaN(b)) {
|
|
45
|
+
return hexColor;
|
|
46
|
+
}
|
|
47
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Determines the appropriate contrast color (black or white) based on the luminance of the given hex color.
|
|
51
|
+
* Uses the relative luminance formula: 0.299*R + 0.587*G + 0.114*B
|
|
52
|
+
* @param hexColor - The hex color string (with or without #)
|
|
53
|
+
* @returns '#000000' for light backgrounds, '#ffffff' for dark backgrounds
|
|
54
|
+
*/
|
|
55
|
+
static getContrastColor(hexColor) {
|
|
56
|
+
const sanitizedHex = hexColor.startsWith('#') ? hexColor.slice(1) : hexColor;
|
|
57
|
+
let r, g, b;
|
|
58
|
+
if (sanitizedHex.length === 3) {
|
|
59
|
+
r = parseInt(sanitizedHex[0] + sanitizedHex[0], 16);
|
|
60
|
+
g = parseInt(sanitizedHex[1] + sanitizedHex[1], 16);
|
|
61
|
+
b = parseInt(sanitizedHex[2] + sanitizedHex[2], 16);
|
|
62
|
+
}
|
|
63
|
+
else if (sanitizedHex.length === 6) {
|
|
64
|
+
r = parseInt(sanitizedHex.substring(0, 2), 16);
|
|
65
|
+
g = parseInt(sanitizedHex.substring(2, 4), 16);
|
|
66
|
+
b = parseInt(sanitizedHex.substring(4, 6), 16);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// Default to black for invalid colors
|
|
70
|
+
return '#000000';
|
|
71
|
+
}
|
|
72
|
+
if (isNaN(r) || isNaN(g) || isNaN(b)) {
|
|
73
|
+
return '#000000';
|
|
74
|
+
}
|
|
75
|
+
// Calculate relative luminance
|
|
76
|
+
const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
|
|
77
|
+
// Use threshold of 150 (midpoint) for balanced contrast
|
|
78
|
+
return luminance > 150 ? '#000000' : '#ffffff';
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Determines the appropriate text color for both light and dark themes based on the fill color.
|
|
82
|
+
* Returns default theme-appropriate colors if the fill is transparent.
|
|
83
|
+
* @param fillColor - The theme-aware fill color
|
|
84
|
+
* @returns A theme-aware color object with appropriate text colors for both themes
|
|
85
|
+
*/
|
|
86
|
+
static determineTextColor(fillColor) {
|
|
87
|
+
// Check if fillColor is transparent for both themes
|
|
88
|
+
const isTransparentLight = fillColor.light === 'transparent';
|
|
89
|
+
const isTransparentDark = fillColor.dark === 'transparent';
|
|
90
|
+
if (isTransparentLight && isTransparentDark) {
|
|
91
|
+
// Return default theme-appropriate colors for transparent fills
|
|
92
|
+
return { light: '#000000', dark: '#ffffff' };
|
|
93
|
+
}
|
|
94
|
+
// Determine text color for each theme based on fill brightness
|
|
95
|
+
const lightThemeTextColor = isTransparentLight
|
|
96
|
+
? '#000000'
|
|
97
|
+
: this.getContrastColor(fillColor.light);
|
|
98
|
+
const darkThemeTextColor = isTransparentDark
|
|
99
|
+
? '#ffffff'
|
|
100
|
+
: this.getContrastColor(fillColor.dark);
|
|
101
|
+
return {
|
|
102
|
+
light: lightThemeTextColor,
|
|
103
|
+
dark: darkThemeTextColor,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { KritzelIconRegistry } from "../classes/registries/icon-registry.class";
|
|
2
|
+
export class KritzelCursorHelper {
|
|
3
|
+
static _pointerCursor = null;
|
|
4
|
+
/**
|
|
5
|
+
* Returns the custom pointer cursor CSS value.
|
|
6
|
+
* This can be used instead of `cursor: pointer` for consistent styling.
|
|
7
|
+
*/
|
|
8
|
+
static getPointerCursor() {
|
|
9
|
+
if (!this._pointerCursor) {
|
|
10
|
+
this._pointerCursor = this.getCursor({ iconName: 'pointer' });
|
|
11
|
+
}
|
|
12
|
+
return this._pointerCursor;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns a custom cursor CSS value with support for rotation.
|
|
16
|
+
* The icon is retrieved from the KritzelIconRegistry.
|
|
17
|
+
*/
|
|
18
|
+
static getCursor(options) {
|
|
19
|
+
const iconName = options.iconName === 'default' ? 'mouse-pointer' : options.iconName;
|
|
20
|
+
const iconSvg = KritzelIconRegistry.get(iconName);
|
|
21
|
+
if (!iconSvg) {
|
|
22
|
+
console.warn(`Icon "${iconName}" not found in registry.`);
|
|
23
|
+
return 'auto';
|
|
24
|
+
}
|
|
25
|
+
const size = options.size || 24;
|
|
26
|
+
const rotation = options.rotation || 0;
|
|
27
|
+
const color = options.color || 'black';
|
|
28
|
+
// Default cursor (mouse-pointer) has hotspot at (4, 4), others at center
|
|
29
|
+
const hotspot = options.hotspot || (options.iconName === 'default' ? { x: 4, y: 4 } : { x: size / 2, y: size / 2 });
|
|
30
|
+
// Modify the SVG string to set size and color
|
|
31
|
+
// We replace width and height to match the requested size
|
|
32
|
+
// We replace currentColor with the requested color
|
|
33
|
+
let content = iconSvg
|
|
34
|
+
.replace(/width="\d+"/, `width="${size}"`)
|
|
35
|
+
.replace(/height="\d+"/, `height="${size}"`)
|
|
36
|
+
.replace(/currentColor/g, color);
|
|
37
|
+
// Create the SVG string
|
|
38
|
+
// We rotate around the center of the SVG canvas
|
|
39
|
+
const center = size / 2;
|
|
40
|
+
// We use a group to apply the rotation
|
|
41
|
+
const svg = `
|
|
42
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 ${size} ${size}">
|
|
43
|
+
<g transform="rotate(${rotation} ${center} ${center})">
|
|
44
|
+
${content}
|
|
45
|
+
</g>
|
|
46
|
+
</svg>
|
|
47
|
+
`;
|
|
48
|
+
// Encode the SVG for use in a data URI
|
|
49
|
+
// We need to be careful with encoding to ensure it works across browsers
|
|
50
|
+
const encodedSvg = encodeURIComponent(svg.replace(/\s+/g, ' ').trim())
|
|
51
|
+
.replace(/'/g, '%27')
|
|
52
|
+
.replace(/"/g, '%22');
|
|
53
|
+
const dataUri = `data:image/svg+xml;charset=utf-8,${encodedSvg}`;
|
|
54
|
+
// Return the cursor style string
|
|
55
|
+
return `url('${dataUri}') ${hotspot.x} ${hotspot.y}, auto`;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export class KritzelDevicesHelper {
|
|
2
|
+
static isTouchDevice() {
|
|
3
|
+
return window.matchMedia('(any-pointer: coarse)').matches;
|
|
4
|
+
}
|
|
5
|
+
static isAndroid() {
|
|
6
|
+
return /android/i.test(navigator.userAgent);
|
|
7
|
+
}
|
|
8
|
+
static isIOS() {
|
|
9
|
+
return /iPad|iPhone|iPod/.test(navigator.userAgent);
|
|
10
|
+
}
|
|
11
|
+
static detectOS() {
|
|
12
|
+
if (this.isIOS()) {
|
|
13
|
+
return 'iOS';
|
|
14
|
+
}
|
|
15
|
+
else if (this.isAndroid()) {
|
|
16
|
+
return 'Android';
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
return 'Other';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
static isMobile() {
|
|
23
|
+
return this.isIOS() || this.isAndroid();
|
|
24
|
+
}
|
|
25
|
+
static isFirefox() {
|
|
26
|
+
return /firefox/i.test(navigator.userAgent);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { KritzelMouseButton } from "../enums/event-button.enum";
|
|
2
|
+
export class KritzelEventHelper {
|
|
3
|
+
static isRightClick(ev) {
|
|
4
|
+
return ev.button === KritzelMouseButton.Right;
|
|
5
|
+
}
|
|
6
|
+
static isLeftClick(ev) {
|
|
7
|
+
return ev.button === KritzelMouseButton.Left;
|
|
8
|
+
}
|
|
9
|
+
static isPointerEventOnContextMenu(event) {
|
|
10
|
+
const path = event.composedPath();
|
|
11
|
+
const contextMenu = path.find(element => element.classList && element.classList.contains('context-menu'));
|
|
12
|
+
return !!contextMenu;
|
|
13
|
+
}
|
|
14
|
+
static onLongPress(event, onSuccess, onCancel) {
|
|
15
|
+
if (event.pointerType !== 'touch') {
|
|
16
|
+
onCancel?.();
|
|
17
|
+
return () => { };
|
|
18
|
+
}
|
|
19
|
+
const startX = event.clientX;
|
|
20
|
+
const startY = event.clientY;
|
|
21
|
+
const target = event.target;
|
|
22
|
+
if (!target) {
|
|
23
|
+
onCancel?.();
|
|
24
|
+
return () => { };
|
|
25
|
+
}
|
|
26
|
+
const longPressTimeout = 400;
|
|
27
|
+
const moveThreshold = 10;
|
|
28
|
+
const timer = setTimeout(() => {
|
|
29
|
+
removeListeners();
|
|
30
|
+
onSuccess(event);
|
|
31
|
+
}, longPressTimeout);
|
|
32
|
+
const cancel = () => {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
removeListeners();
|
|
35
|
+
onCancel?.();
|
|
36
|
+
};
|
|
37
|
+
const onPointerMove = (e) => {
|
|
38
|
+
if (Math.abs(e.clientX - startX) > moveThreshold || Math.abs(e.clientY - startY) > moveThreshold) {
|
|
39
|
+
cancel();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const onPointerUp = () => {
|
|
43
|
+
cancel();
|
|
44
|
+
};
|
|
45
|
+
const onPointerCancel = () => {
|
|
46
|
+
cancel();
|
|
47
|
+
};
|
|
48
|
+
const removeListeners = () => {
|
|
49
|
+
target.removeEventListener('pointermove', onPointerMove);
|
|
50
|
+
target.removeEventListener('pointerup', onPointerUp);
|
|
51
|
+
target.removeEventListener('pointercancel', onPointerCancel);
|
|
52
|
+
};
|
|
53
|
+
target.addEventListener('pointermove', onPointerMove, { passive: true });
|
|
54
|
+
target.addEventListener('pointerup', onPointerUp, { once: true });
|
|
55
|
+
target.addEventListener('pointercancel', onPointerCancel, { once: true });
|
|
56
|
+
return cancel;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
export class KritzelGeometryHelper {
|
|
2
|
+
static doPolygonsIntersect(polygon1, polygon2) {
|
|
3
|
+
// 1. Convert polygons to array of points for easier processing
|
|
4
|
+
const points1 = [polygon1.bottomLeft, polygon1.bottomRight, polygon1.topRight, polygon1.topLeft];
|
|
5
|
+
const points2 = [polygon2.bottomLeft, polygon2.bottomRight, polygon2.topRight, polygon2.topLeft];
|
|
6
|
+
// 2. Check if any point of polygon1 is inside polygon2
|
|
7
|
+
for (const point of points1) {
|
|
8
|
+
if (this.isPointInPolygon(point, points2)) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
// 3. Check if any point of polygon2 is inside polygon1
|
|
13
|
+
for (const point of points2) {
|
|
14
|
+
if (this.isPointInPolygon(point, points1)) {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// 4. Check for edge intersections (more complex)
|
|
19
|
+
for (let i = 0; i < points1.length; i++) {
|
|
20
|
+
const p1a = points1[i];
|
|
21
|
+
const p1b = points1[(i + 1) % points1.length]; // Wrap around to the first point
|
|
22
|
+
for (let j = 0; j < points2.length; j++) {
|
|
23
|
+
const p2a = points2[j];
|
|
24
|
+
const p2b = points2[(j + 1) % points2.length];
|
|
25
|
+
if (this.intersectLines(p1a, p1b, p2a, p2b)) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return false; // No intersection found
|
|
31
|
+
}
|
|
32
|
+
static isPointInPolygon(point, polygon) {
|
|
33
|
+
let inside = false;
|
|
34
|
+
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
|
35
|
+
const xi = polygon[i].x, yi = polygon[i].y;
|
|
36
|
+
const xj = polygon[j].x, yj = polygon[j].y;
|
|
37
|
+
const intersect = yi > point.y !== yj > point.y && point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;
|
|
38
|
+
if (intersect)
|
|
39
|
+
inside = !inside;
|
|
40
|
+
}
|
|
41
|
+
return inside;
|
|
42
|
+
}
|
|
43
|
+
static intersectLines(p1a, p1b, p2a, p2b) {
|
|
44
|
+
const det = (p1b.x - p1a.x) * (p2b.y - p2a.y) - (p1b.y - p1a.y) * (p2b.x - p2a.x);
|
|
45
|
+
if (det === 0) {
|
|
46
|
+
return false; // Lines are parallel
|
|
47
|
+
}
|
|
48
|
+
const t = ((p2a.x - p1a.x) * (p2b.y - p2a.y) - (p2a.y - p1a.y) * (p2b.x - p2a.x)) / det;
|
|
49
|
+
const u = -((p1a.x - p2a.x) * (p1b.y - p1a.y) - (p1a.y - p2a.y) * (p1b.x - p1a.x)) / det;
|
|
50
|
+
return t >= 0 && t <= 1 && u >= 0 && u <= 1;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Finds the intersection point between a line segment and a line segment.
|
|
54
|
+
* Returns the intersection point or null if no intersection.
|
|
55
|
+
*/
|
|
56
|
+
static getLineIntersectionPoint(p1a, p1b, p2a, p2b) {
|
|
57
|
+
const det = (p1b.x - p1a.x) * (p2b.y - p2a.y) - (p1b.y - p1a.y) * (p2b.x - p2a.x);
|
|
58
|
+
if (det === 0) {
|
|
59
|
+
return null; // Lines are parallel
|
|
60
|
+
}
|
|
61
|
+
const t = ((p2a.x - p1a.x) * (p2b.y - p2a.y) - (p2a.y - p1a.y) * (p2b.x - p2a.x)) / det;
|
|
62
|
+
const u = -((p1a.x - p2a.x) * (p1b.y - p1a.y) - (p1a.y - p2a.y) * (p1b.x - p1a.x)) / det;
|
|
63
|
+
if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
|
|
64
|
+
return {
|
|
65
|
+
x: p1a.x + t * (p1b.x - p1a.x),
|
|
66
|
+
y: p1a.y + t * (p1b.y - p1a.y)
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Finds the closest intersection point between a line segment (from lineStart to lineEnd)
|
|
73
|
+
* and a polygon. Returns the intersection point closest to lineStart, or null if no intersection.
|
|
74
|
+
*/
|
|
75
|
+
static getLinePolygonIntersection(lineStart, lineEnd, polygon) {
|
|
76
|
+
const points = [polygon.topLeft, polygon.topRight, polygon.bottomRight, polygon.bottomLeft];
|
|
77
|
+
let closestIntersection = null;
|
|
78
|
+
let closestDistance = Infinity;
|
|
79
|
+
for (let i = 0; i < points.length; i++) {
|
|
80
|
+
const edgeStart = points[i];
|
|
81
|
+
const edgeEnd = points[(i + 1) % points.length];
|
|
82
|
+
const intersection = this.getLineIntersectionPoint(lineStart, lineEnd, edgeStart, edgeEnd);
|
|
83
|
+
if (intersection) {
|
|
84
|
+
const distance = Math.sqrt(Math.pow(intersection.x - lineStart.x, 2) +
|
|
85
|
+
Math.pow(intersection.y - lineStart.y, 2));
|
|
86
|
+
if (distance < closestDistance) {
|
|
87
|
+
closestDistance = distance;
|
|
88
|
+
closestIntersection = intersection;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return closestIntersection;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Generates a polygon approximation of an ellipse.
|
|
96
|
+
* @param centerX - X coordinate of ellipse center
|
|
97
|
+
* @param centerY - Y coordinate of ellipse center
|
|
98
|
+
* @param rx - Horizontal radius
|
|
99
|
+
* @param ry - Vertical radius
|
|
100
|
+
* @param segments - Number of segments (more = smoother approximation)
|
|
101
|
+
* @param rotation - Optional rotation angle in radians
|
|
102
|
+
*/
|
|
103
|
+
static getEllipsePolygonApproximation(centerX, centerY, rx, ry, segments = 32, rotation = 0) {
|
|
104
|
+
const points = [];
|
|
105
|
+
const cos = Math.cos(rotation);
|
|
106
|
+
const sin = Math.sin(rotation);
|
|
107
|
+
for (let i = 0; i < segments; i++) {
|
|
108
|
+
const angle = (2 * Math.PI * i) / segments;
|
|
109
|
+
// Point on unrotated ellipse
|
|
110
|
+
const px = rx * Math.cos(angle);
|
|
111
|
+
const py = ry * Math.sin(angle);
|
|
112
|
+
// Apply rotation around center
|
|
113
|
+
const rotatedX = centerX + px * cos - py * sin;
|
|
114
|
+
const rotatedY = centerY + px * sin + py * cos;
|
|
115
|
+
points.push({ x: rotatedX, y: rotatedY });
|
|
116
|
+
}
|
|
117
|
+
return points;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Finds the closest intersection point between a line segment and a polygon
|
|
121
|
+
* defined as an array of points. Returns the intersection closest to lineStart,
|
|
122
|
+
* or null if no intersection.
|
|
123
|
+
*/
|
|
124
|
+
static getLinePointsArrayIntersection(lineStart, lineEnd, polygonPoints) {
|
|
125
|
+
let closestIntersection = null;
|
|
126
|
+
let closestDistance = Infinity;
|
|
127
|
+
for (let i = 0; i < polygonPoints.length; i++) {
|
|
128
|
+
const edgeStart = polygonPoints[i];
|
|
129
|
+
const edgeEnd = polygonPoints[(i + 1) % polygonPoints.length];
|
|
130
|
+
const intersection = this.getLineIntersectionPoint(lineStart, lineEnd, edgeStart, edgeEnd);
|
|
131
|
+
if (intersection) {
|
|
132
|
+
const distance = Math.sqrt(Math.pow(intersection.x - lineStart.x, 2) +
|
|
133
|
+
Math.pow(intersection.y - lineStart.y, 2));
|
|
134
|
+
if (distance < closestDistance) {
|
|
135
|
+
closestDistance = distance;
|
|
136
|
+
closestIntersection = intersection;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return closestIntersection;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Checks if a point is inside a polygon defined as an array of points.
|
|
144
|
+
* This is a convenience wrapper that works with arbitrary polygon point arrays.
|
|
145
|
+
*/
|
|
146
|
+
static isPointInPolygonPoints(point, polygonPoints) {
|
|
147
|
+
return this.isPointInPolygon(point, polygonPoints);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export class KritzelHTMLHelper {
|
|
2
|
+
static getNumericValueFromStyle(element, property) {
|
|
3
|
+
const value = window.getComputedStyle(element).getPropertyValue(property);
|
|
4
|
+
return parseFloat(value) || 0;
|
|
5
|
+
}
|
|
6
|
+
static isScrollableElement(element) {
|
|
7
|
+
if (!(element instanceof HTMLElement)) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
const style = window.getComputedStyle(element);
|
|
11
|
+
const overflowX = style.overflowX;
|
|
12
|
+
const overflowY = style.overflowY;
|
|
13
|
+
const overflow = style.overflow;
|
|
14
|
+
const canScrollX = (overflowX === 'auto' || overflowX === 'scroll' || overflowX === 'overlay') && element.scrollWidth > element.clientWidth;
|
|
15
|
+
const canScrollY = (overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay') && element.scrollHeight > element.clientHeight;
|
|
16
|
+
const canScroll = overflow === 'auto' || overflow === 'scroll' || overflow === 'overlay';
|
|
17
|
+
return canScrollX || canScrollY || (canScroll && (element.scrollWidth > element.clientWidth || element.scrollHeight > element.clientHeight));
|
|
18
|
+
}
|
|
19
|
+
static findScrollableElement(root) {
|
|
20
|
+
if (!root) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const visited = new Set();
|
|
24
|
+
const walk = (element) => {
|
|
25
|
+
if (visited.has(element)) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
visited.add(element);
|
|
29
|
+
if (this.isScrollableElement(element)) {
|
|
30
|
+
return element;
|
|
31
|
+
}
|
|
32
|
+
if (element.shadowRoot) {
|
|
33
|
+
for (const child of Array.from(element.shadowRoot.children)) {
|
|
34
|
+
const scrollable = walk(child);
|
|
35
|
+
if (scrollable) {
|
|
36
|
+
return scrollable;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (element.tagName === 'SLOT') {
|
|
41
|
+
for (const assignedElement of element.assignedElements({ flatten: true })) {
|
|
42
|
+
const scrollable = walk(assignedElement);
|
|
43
|
+
if (scrollable) {
|
|
44
|
+
return scrollable;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for (const child of Array.from(element.children)) {
|
|
49
|
+
const scrollable = walk(child);
|
|
50
|
+
if (scrollable) {
|
|
51
|
+
return scrollable;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
};
|
|
56
|
+
return walk(root);
|
|
57
|
+
}
|
|
58
|
+
static getScrollableParent(element) {
|
|
59
|
+
if (!element) {
|
|
60
|
+
return window;
|
|
61
|
+
}
|
|
62
|
+
const parent = element.parentNode?.host ?? element.parentElement;
|
|
63
|
+
if (!parent || parent.tagName === 'BODY') {
|
|
64
|
+
return window;
|
|
65
|
+
}
|
|
66
|
+
const style = window.getComputedStyle(parent);
|
|
67
|
+
if (style.overflow === 'auto' || style.overflowY === 'auto' || style.overflow === 'scroll' || style.overflowY === 'scroll') {
|
|
68
|
+
return parent;
|
|
69
|
+
}
|
|
70
|
+
return this.getScrollableParent(parent);
|
|
71
|
+
}
|
|
72
|
+
static isElementInViewport(element) {
|
|
73
|
+
if (!element) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const scrollableParent = this.getScrollableParent(element);
|
|
77
|
+
const rect = element.getBoundingClientRect();
|
|
78
|
+
if (scrollableParent === window) {
|
|
79
|
+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
80
|
+
const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
|
|
81
|
+
return rect.top >= 0 && rect.left >= 0 && rect.bottom <= viewportHeight && rect.right <= viewportWidth;
|
|
82
|
+
}
|
|
83
|
+
const parentRect = scrollableParent.getBoundingClientRect();
|
|
84
|
+
return rect.top >= parentRect.top && rect.left >= parentRect.left && rect.bottom <= parentRect.bottom && rect.right <= parentRect.right;
|
|
85
|
+
}
|
|
86
|
+
static getFocusableElements(root) {
|
|
87
|
+
if (!root)
|
|
88
|
+
return [];
|
|
89
|
+
const focusableElements = [];
|
|
90
|
+
const focusableSelector = 'a[href], button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), details, [tabindex]:not([tabindex="-1"])';
|
|
91
|
+
const isVisible = (el) => {
|
|
92
|
+
const style = window.getComputedStyle(el);
|
|
93
|
+
return style.display !== 'none' && style.visibility !== 'hidden';
|
|
94
|
+
};
|
|
95
|
+
const find = (element) => {
|
|
96
|
+
// Check if the element itself is focusable
|
|
97
|
+
if (element instanceof HTMLElement && element.matches(focusableSelector) && !element.hasAttribute('disabled') && isVisible(element)) {
|
|
98
|
+
focusableElements.push(element);
|
|
99
|
+
}
|
|
100
|
+
// Traverse shadow DOM
|
|
101
|
+
if (element.shadowRoot) {
|
|
102
|
+
Array.from(element.shadowRoot.children).forEach(find);
|
|
103
|
+
}
|
|
104
|
+
// Traverse slotted content
|
|
105
|
+
if (element.tagName === 'SLOT') {
|
|
106
|
+
element.assignedElements({ flatten: true }).forEach(find);
|
|
107
|
+
}
|
|
108
|
+
// Traverse light DOM children if there is no shadow root
|
|
109
|
+
if (!element.shadowRoot) {
|
|
110
|
+
Array.from(element.children).forEach(find);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
find(root);
|
|
114
|
+
return focusableElements;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { KritzelDevicesHelper } from "./devices.helper";
|
|
2
|
+
export class KritzelKeyboardHelper {
|
|
3
|
+
static forceHideKeyboard() {
|
|
4
|
+
if (document.activeElement instanceof HTMLElement) {
|
|
5
|
+
document.activeElement.blur();
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
static enableInteractiveWidget() {
|
|
9
|
+
const meta = document.querySelector('meta[name="viewport"][content*="interactive-widget=resizes-content"]');
|
|
10
|
+
if (meta) {
|
|
11
|
+
let currentContent = meta.getAttribute('content');
|
|
12
|
+
if (!currentContent?.includes('interactive-widget=resizes-content')) {
|
|
13
|
+
currentContent += ', interactive-widget=resizes-content';
|
|
14
|
+
}
|
|
15
|
+
if (currentContent) {
|
|
16
|
+
meta.setAttribute('content', currentContent);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
static disableInteractiveWidget() {
|
|
21
|
+
const meta = document.querySelector('meta[name="viewport"][content*="interactive-widget=resizes-content"]');
|
|
22
|
+
if (meta) {
|
|
23
|
+
let currentContent = meta.getAttribute('content');
|
|
24
|
+
let newContent = currentContent?.replace(/\s*interactive-widget=resizes-content\s*[,;]?/g, '');
|
|
25
|
+
if (newContent !== undefined) {
|
|
26
|
+
newContent = newContent
|
|
27
|
+
.replace(/,(\s*,)+/g, ',')
|
|
28
|
+
.replace(/^,/, '')
|
|
29
|
+
.replace(/,$/, '')
|
|
30
|
+
.trim();
|
|
31
|
+
meta.setAttribute('content', newContent);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
static onKeyboardVisibleChanged(callback) {
|
|
36
|
+
if ('visualViewport' in window) {
|
|
37
|
+
const VIEWPORT_VS_CLIENT_HEIGHT_RATIO = 0.75;
|
|
38
|
+
const onResize = (event) => {
|
|
39
|
+
const target = event.target;
|
|
40
|
+
const isMobileDevice = KritzelDevicesHelper.isMobile();
|
|
41
|
+
const isViewportReduced = (target.height * target.scale) / window.screen.height < VIEWPORT_VS_CLIENT_HEIGHT_RATIO;
|
|
42
|
+
const isOpen = isMobileDevice && isViewportReduced;
|
|
43
|
+
callback(isOpen);
|
|
44
|
+
};
|
|
45
|
+
window.visualViewport?.addEventListener('resize', onResize);
|
|
46
|
+
return () => window.visualViewport?.removeEventListener('resize', onResize);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Fallback for older browsers does not provide a reliable event-based mechanism.
|
|
50
|
+
console.warn('Listening for keyboard visibility changes is not reliably supported in this browser.');
|
|
51
|
+
// Return a no-op cleanup function.
|
|
52
|
+
return () => { };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure static utilities for localization term resolution.
|
|
3
|
+
*/
|
|
4
|
+
export class LocalizationHelper {
|
|
5
|
+
/**
|
|
6
|
+
* Interpolates `{placeholder}` tokens in a term template with the provided
|
|
7
|
+
* variables. Tokens without a matching variable are left untouched.
|
|
8
|
+
*
|
|
9
|
+
* @param template - The raw term string, e.g. `'Expires {date}'`
|
|
10
|
+
* @param vars - Map of placeholder names to replacement values
|
|
11
|
+
* @returns The interpolated string
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* LocalizationHelper.interpolate('Hello {name}', { name: 'Ada' }); // 'Hello Ada'
|
|
15
|
+
*/
|
|
16
|
+
static interpolate(template, vars) {
|
|
17
|
+
if (!vars) {
|
|
18
|
+
return template;
|
|
19
|
+
}
|
|
20
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => {
|
|
21
|
+
const value = vars[key];
|
|
22
|
+
return value === undefined || value === null ? match : String(value);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs pending schema migrations on a Y.Doc.
|
|
3
|
+
*
|
|
4
|
+
* Reads the current `schemaVersion` from the metadata map (defaults to 0 for
|
|
5
|
+
* documents that predate the migration system), filters and sorts pending
|
|
6
|
+
* migrations, and executes them in a single `'migration'`-origin transaction.
|
|
7
|
+
*
|
|
8
|
+
* The `'migration'` origin is:
|
|
9
|
+
* - NOT tracked by the UndoManager (which only tracks `'local'` and `'temporary'`)
|
|
10
|
+
* - Distinguishable in observers so they can skip re-processing migration writes
|
|
11
|
+
*
|
|
12
|
+
* @param ydoc - The Y.Doc to migrate
|
|
13
|
+
* @param metadataMap - The metadata Y.Map that stores the schemaVersion
|
|
14
|
+
* @param maps - Named Y.Maps available for migration logic (e.g. `{ workspaces }` or `{ objects }`)
|
|
15
|
+
* @param migrations - The ordered array of migration definitions
|
|
16
|
+
* @param currentVersion - The target schema version defined in code
|
|
17
|
+
* @param options - Optional configuration (e.g. `{ quiet: true }` to suppress console logs)
|
|
18
|
+
* @returns A result object indicating whether migrations ran and the version range
|
|
19
|
+
*/
|
|
20
|
+
export function runMigrations(ydoc, metadataMap, maps, migrations, currentVersion, options) {
|
|
21
|
+
const quiet = options?.quiet ?? true;
|
|
22
|
+
const docVersion = metadataMap.get('schemaVersion') ?? 0;
|
|
23
|
+
if (docVersion >= currentVersion) {
|
|
24
|
+
return { migrated: false, fromVersion: docVersion, toVersion: docVersion };
|
|
25
|
+
}
|
|
26
|
+
const pending = migrations
|
|
27
|
+
.filter(m => m.fromVersion >= docVersion && m.toVersion <= currentVersion)
|
|
28
|
+
.sort((a, b) => a.fromVersion - b.fromVersion);
|
|
29
|
+
if (!quiet) {
|
|
30
|
+
console.log(`[Kritzel] Running ${pending.length} migration(s) from v${docVersion} to v${currentVersion}`);
|
|
31
|
+
}
|
|
32
|
+
ydoc.transact(() => {
|
|
33
|
+
for (const migration of pending) {
|
|
34
|
+
if (!quiet) {
|
|
35
|
+
console.log(`[Kritzel] Migrating v${migration.fromVersion} → v${migration.toVersion}`);
|
|
36
|
+
}
|
|
37
|
+
migration.migrate(ydoc, maps);
|
|
38
|
+
}
|
|
39
|
+
metadataMap.set('schemaVersion', currentVersion);
|
|
40
|
+
}, 'migration');
|
|
41
|
+
if (!quiet) {
|
|
42
|
+
console.log(`[Kritzel] Migrations complete. Schema now at v${currentVersion}`);
|
|
43
|
+
}
|
|
44
|
+
return { migrated: true, fromVersion: docVersion, toVersion: currentVersion };
|
|
45
|
+
}
|