kritzel-stencil 0.3.16 → 0.3.18
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/index-Xav9JFHg.js +2 -2
- package/dist/cjs/index.cjs.js +7 -1
- package/dist/cjs/{kritzel-active-users_42.cjs.entry.js → kritzel-active-users_44.cjs.entry.js} +710 -145
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{schema.constants-DJQTjcy7.js → schema.constants-DrHO_CYF.js} +1169 -171
- package/dist/cjs/stencil.cjs.js +1 -1
- package/dist/collection/classes/core/core.class.js +24 -0
- package/dist/collection/classes/handlers/context-menu.handler.js +24 -2
- package/dist/collection/classes/managers/license.manager.js +285 -0
- package/dist/collection/classes/managers/localization.manager.js +189 -0
- package/dist/collection/classes/objects/custom-element.class.js +2 -0
- package/dist/collection/classes/objects/group.class.js +7 -2
- package/dist/collection/classes/objects/image.class.js +10 -7
- package/dist/collection/classes/objects/line.class.js +3 -0
- package/dist/collection/classes/objects/path.class.js +13 -12
- package/dist/collection/classes/objects/selection-group.class.js +7 -2
- package/dist/collection/classes/objects/shape.class.js +3 -0
- package/dist/collection/classes/objects/text.class.js +4 -1
- package/dist/collection/classes/registries/icon-registry.class.js +1 -0
- package/dist/collection/classes/tools/brush-tool.class.js +1 -1
- package/dist/collection/collection-manifest.json +3 -1
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.css +16 -0
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +462 -60
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +446 -16
- package/dist/collection/components/core/kritzel-watermark/kritzel-watermark.css +29 -0
- package/dist/collection/components/core/kritzel-watermark/kritzel-watermark.js +83 -0
- package/dist/collection/components/shared/kritzel-avatar/kritzel-avatar.js +3 -3
- package/dist/collection/components/shared/kritzel-button/kritzel-button.js +2 -2
- package/dist/collection/components/shared/kritzel-color/kritzel-color.js +2 -2
- package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js +1 -1
- package/dist/collection/components/shared/kritzel-font/kritzel-font.js +1 -1
- package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js +2 -1
- package/dist/collection/components/shared/kritzel-input/kritzel-input.js +1 -1
- package/dist/collection/components/shared/kritzel-master-detail/kritzel-master-detail.js +3 -3
- package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js +1 -1
- package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js +2 -2
- package/dist/collection/components/shared/kritzel-numeric-input/kritzel-numeric-input.js +1 -1
- package/dist/collection/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.js +1 -1
- package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js +1 -1
- package/dist/collection/components/shared/kritzel-slide-toggle/kritzel-slide-toggle.js +1 -1
- package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js +1 -1
- package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js +2 -1
- package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js +2 -2
- package/dist/collection/components/ui/kritzel-back-to-content/kritzel-back-to-content.js +1 -1
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +41 -6
- package/dist/collection/components/ui/kritzel-current-user/kritzel-current-user.js +36 -1
- package/dist/collection/components/ui/kritzel-current-user-dialog/kritzel-current-user-dialog.js +36 -1
- package/dist/collection/components/ui/kritzel-export/kritzel-export.js +44 -7
- package/dist/collection/components/ui/kritzel-login-dialog/kritzel-login-dialog.js +1 -1
- package/dist/collection/components/ui/kritzel-more-menu/kritzel-more-menu.js +36 -1
- package/dist/collection/components/ui/kritzel-settings/kritzel-settings.js +108 -14
- package/dist/collection/components/ui/kritzel-share-dialog/kritzel-share-dialog.js +38 -3
- package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.js +38 -3
- package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js +36 -1
- package/dist/collection/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.js +38 -3
- package/dist/collection/components/ui/kritzel-zoom-panel/kritzel-zoom-panel.css +72 -0
- package/dist/collection/components/ui/kritzel-zoom-panel/kritzel-zoom-panel.js +173 -0
- package/dist/collection/constants/engine.constants.js +2 -0
- package/dist/collection/constants/license.constants.js +25 -0
- package/dist/collection/constants/version.js +1 -1
- package/dist/collection/helpers/localization.helper.js +25 -0
- package/dist/collection/helpers/math.helper.js +3 -0
- package/dist/collection/helpers/svg-export.helper.js +223 -26
- package/dist/collection/index.js +13 -0
- package/dist/collection/interfaces/localization.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/themes/dark-theme.js +18 -0
- package/dist/collection/themes/light-theme.js +18 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +1 -1
- package/dist/components/kritzel-active-users.js +1 -1
- package/dist/components/kritzel-avatar.js +1 -1
- package/dist/components/kritzel-awareness-cursors.js +1 -1
- package/dist/components/kritzel-back-to-content.js +1 -1
- package/dist/components/kritzel-brush-style.js +1 -1
- package/dist/components/kritzel-button.js +1 -1
- package/dist/components/kritzel-color-palette.js +1 -1
- package/dist/components/kritzel-color.js +1 -1
- package/dist/components/kritzel-context-menu.js +1 -1
- package/dist/components/kritzel-controls.js +1 -1
- package/dist/components/kritzel-current-user-dialog.js +1 -1
- package/dist/components/kritzel-current-user.js +1 -1
- package/dist/components/kritzel-editor.js +1 -1
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-export.js +1 -1
- package/dist/components/kritzel-font-size.js +1 -1
- package/dist/components/kritzel-font.js +1 -1
- package/dist/components/kritzel-icon.js +1 -1
- package/dist/components/kritzel-input.js +1 -1
- package/dist/components/kritzel-login-dialog.js +1 -1
- package/dist/components/kritzel-master-detail.js +1 -1
- package/dist/components/kritzel-menu-item.js +1 -1
- package/dist/components/kritzel-menu.js +1 -1
- package/dist/components/kritzel-more-menu.js +1 -1
- package/dist/components/kritzel-numeric-input.js +1 -1
- package/dist/components/kritzel-opacity-slider.js +1 -1
- package/dist/components/kritzel-pill-tabs.js +1 -1
- package/dist/components/kritzel-portal.js +1 -1
- package/dist/components/kritzel-settings.js +1 -1
- package/dist/components/kritzel-share-dialog.js +1 -1
- package/dist/components/kritzel-slide-toggle.js +1 -1
- package/dist/components/kritzel-split-button.js +1 -1
- package/dist/components/kritzel-stroke-size.js +1 -1
- package/dist/components/kritzel-tool-config.js +1 -1
- package/dist/components/kritzel-tooltip.js +1 -1
- package/dist/components/kritzel-utility-panel.js +1 -1
- package/dist/components/kritzel-watermark.d.ts +11 -0
- package/dist/components/kritzel-watermark.js +1 -0
- package/dist/components/kritzel-workspace-manager.js +1 -1
- package/dist/components/kritzel-zoom-panel.d.ts +11 -0
- package/dist/components/kritzel-zoom-panel.js +1 -0
- package/dist/components/{p-B5xxfwKF.js → p-3HxnBrCM.js} +1 -1
- package/dist/components/p-6RjeGuvH.js +1 -0
- package/dist/components/p-7NsK0uHu.js +1 -0
- package/dist/components/{p-dcAernE1.js → p-BCNyR5Sw.js} +1 -1
- package/dist/components/{p-C2SX-XRr.js → p-BG6hOSrm.js} +1 -1
- package/dist/components/p-BKJSh8qQ.js +1 -0
- package/dist/components/{p-SptaSMno.js → p-BKvHg9cv.js} +1 -1
- package/dist/components/p-Bc55X65h.js +1 -0
- package/dist/components/p-BpnIvNvq.js +1 -0
- package/dist/components/p-BvRrA4hN.js +1 -0
- package/dist/components/{p-B2w8X7vn.js → p-BxpKq94F.js} +1 -1
- package/dist/components/{p-BFoK4W--.js → p-Bzv9Px8v.js} +1 -1
- package/dist/components/{p-COLHjboZ.js → p-C9HGoDHE.js} +1 -1
- package/dist/components/p-CEnEDaix.js +1 -0
- package/dist/components/p-CIcLzcfA.js +1 -0
- package/dist/components/p-CPtDfadX.js +1 -0
- package/dist/components/p-C_fKgKHu.js +9 -0
- package/dist/components/p-CdR76C4L.js +1 -0
- package/dist/components/p-Cu9KYyoq.js +1 -0
- package/dist/components/p-CyqRcqsO.js +1 -0
- package/dist/components/{p-UoPj5QjH.js → p-DDkmsPpV.js} +1 -1
- package/dist/components/{p-D-sRVAbQ.js → p-DI4vQRE3.js} +1 -1
- package/dist/components/{p-CJOhfMU5.js → p-DNdXJp8F.js} +1 -1
- package/dist/components/p-DX5K8xnh.js +1 -0
- package/dist/components/{p-DEy7zJCe.js → p-DZdgXCAx.js} +1 -1
- package/dist/components/p-DdH1cKED.js +1 -0
- package/dist/components/p-DgmtCdnL.js +1 -0
- package/dist/components/{p-BzYU3-MJ.js → p-DmWSRsjK.js} +1 -1
- package/dist/components/{p-Bj2laX89.js → p-Dz-Ti24X.js} +1 -1
- package/dist/components/{p-BiG1dxPS.js → p-F5_X4dZG.js} +1 -1
- package/dist/components/{p-x6doYeiI.js → p-IpoC5EEY.js} +1 -1
- package/dist/components/p-Jn6TNdfe.js +1 -0
- package/dist/components/{p-BfNHpqQ8.js → p-NuLP1xHe.js} +1 -1
- package/dist/components/{p-skWUIStn.js → p-SDZNC8GF.js} +1 -1
- package/dist/components/{p-BYmp9Ovv.js → p-U4oawa1x.js} +1 -1
- package/dist/components/{p-DM11KXUT.js → p-f8aW1ye7.js} +1 -1
- package/dist/components/p-mz3pUWW4.js +1 -0
- package/dist/components/p-v7dxxrL5.js +1 -0
- package/dist/components/p-vAeiXe6c.js +1 -0
- package/dist/esm/index-Dhio9uis.js +2 -2
- package/dist/esm/index.js +2 -2
- package/dist/esm/{kritzel-active-users_42.entry.js → kritzel-active-users_44.entry.js} +709 -146
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{schema.constants-DiCnmIYK.js → schema.constants-DchTXG3V.js} +1163 -172
- package/dist/esm/stencil.js +1 -1
- package/dist/stencil/index.esm.js +1 -1
- package/dist/stencil/p-86348986.entry.js +9 -0
- package/dist/stencil/p-DchTXG3V.js +1 -0
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/core/core.class.d.ts +16 -0
- package/dist/types/classes/handlers/context-menu.handler.d.ts +13 -0
- package/dist/types/classes/managers/license.manager.d.ts +141 -0
- package/dist/types/classes/managers/localization.manager.d.ts +121 -0
- package/dist/types/classes/objects/custom-element.class.d.ts +2 -0
- package/dist/types/classes/objects/group.class.d.ts +6 -1
- package/dist/types/classes/objects/image.class.d.ts +1 -1
- package/dist/types/classes/objects/path.class.d.ts +3 -2
- package/dist/types/classes/objects/selection-group.class.d.ts +6 -1
- package/dist/types/classes/objects/shape.class.d.ts +2 -0
- package/dist/types/classes/objects/text.class.d.ts +2 -1
- package/dist/types/classes/tools/brush-tool.class.d.ts +1 -1
- package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +53 -1
- package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +55 -3
- package/dist/types/components/core/kritzel-watermark/kritzel-watermark.d.ts +20 -0
- package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +3 -0
- package/dist/types/components/ui/kritzel-current-user/kritzel-current-user.d.ts +3 -0
- package/dist/types/components/ui/kritzel-current-user-dialog/kritzel-current-user-dialog.d.ts +3 -0
- package/dist/types/components/ui/kritzel-export/kritzel-export.d.ts +4 -1
- package/dist/types/components/ui/kritzel-more-menu/kritzel-more-menu.d.ts +3 -0
- package/dist/types/components/ui/kritzel-settings/kritzel-settings.d.ts +16 -0
- package/dist/types/components/ui/kritzel-share-dialog/kritzel-share-dialog.d.ts +3 -0
- package/dist/types/components/ui/kritzel-tool-config/kritzel-tool-config.d.ts +3 -0
- package/dist/types/components/ui/kritzel-utility-panel/kritzel-utility-panel.d.ts +3 -0
- package/dist/types/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.d.ts +3 -0
- package/dist/types/components/ui/kritzel-zoom-panel/kritzel-zoom-panel.d.ts +20 -0
- package/dist/types/components.d.ts +445 -26
- package/dist/types/constants/engine.constants.d.ts +2 -0
- package/dist/types/constants/license.constants.d.ts +25 -0
- package/dist/types/constants/version.d.ts +1 -1
- package/dist/types/helpers/localization.helper.d.ts +18 -0
- package/dist/types/helpers/math.helper.d.ts +1 -0
- package/dist/types/helpers/svg-export.helper.d.ts +81 -7
- package/dist/types/index.d.ts +13 -0
- package/dist/types/interfaces/context-menu-item.interface.d.ts +7 -1
- package/dist/types/interfaces/line-options.interface.d.ts +2 -0
- package/dist/types/interfaces/localization.interface.d.ts +143 -0
- package/dist/types/interfaces/path-options.interface.d.ts +2 -0
- package/dist/types/interfaces/settings.interface.d.ts +3 -0
- package/dist/types/interfaces/theme.interface.d.ts +27 -2
- 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/package.json +4 -7
- package/dist/components/p-2xYAGd0I.js +0 -1
- package/dist/components/p-B2Os1ya_.js +0 -1
- package/dist/components/p-BTEV1WwT.js +0 -1
- package/dist/components/p-BbactVA0.js +0 -1
- package/dist/components/p-BqwqGFQY.js +0 -1
- package/dist/components/p-C0TN5IAi.js +0 -1
- package/dist/components/p-CFgkUYoO.js +0 -1
- package/dist/components/p-COgo9OWy.js +0 -1
- package/dist/components/p-CUPYGT8c.js +0 -1
- package/dist/components/p-CcyIAi9S.js +0 -1
- package/dist/components/p-Cj78L1Kk.js +0 -1
- package/dist/components/p-CkAVEdDw.js +0 -9
- package/dist/components/p-CmuNn1Tc.js +0 -1
- package/dist/components/p-DDYoDSrm.js +0 -1
- package/dist/components/p-DbB730vO.js +0 -1
- package/dist/components/p-DlwYHzSj.js +0 -1
- package/dist/components/p-FK7b3BGt.js +0 -1
- package/dist/components/p-J9_SwObO.js +0 -1
- package/dist/stencil/p-67775031.entry.js +0 -9
- package/dist/stencil/p-DiCnmIYK.js +0 -1
package/dist/cjs/stencil.cjs.js
CHANGED
|
@@ -19,7 +19,7 @@ var patchBrowser = () => {
|
|
|
19
19
|
|
|
20
20
|
patchBrowser().then(async (options) => {
|
|
21
21
|
await appGlobals.globalScripts();
|
|
22
|
-
return index.bootstrapLazy(JSON.parse("[[\"kritzel-active-users_42.cjs\",[[512,\"kritzel-editor\",{\"scaleMax\":[1026,\"scale-max\"],\"scaleMin\":[1026,\"scale-min\"],\"lockDrawingScale\":[1028,\"lock-drawing-scale\"],\"viewportBoundaryLeft\":[1026,\"viewport-boundary-left\"],\"viewportBoundaryRight\":[1026,\"viewport-boundary-right\"],\"viewportBoundaryTop\":[1026,\"viewport-boundary-top\"],\"viewportBoundaryBottom\":[1026,\"viewport-boundary-bottom\"],\"wheelEnabled\":[1028,\"wheel-enabled\"],\"debugInfo\":[1040],\"user\":[16],\"activeUsers\":[16],\"controls\":[16],\"globalContextMenuItems\":[16],\"objectContextMenuItems\":[16],\"themes\":[16],\"theme\":[1025],\"customSvgIcons\":[16],\"isControlsVisible\":[4,\"is-controls-visible\"],\"isUtilityPanelVisible\":[4,\"is-utility-panel-visible\"],\"isWorkspaceManagerVisible\":[4,\"is-workspace-manager-visible\"],\"isMoreMenuVisible\":[4,\"is-more-menu-visible\"],\"isObjectDistanceFadingActive\":[4,\"is-object-distance-fading-active\"],\"syncConfig\":[16],\"assetStorageConfig\":[16],\"cursorTarget\":[16],\"loginConfig\":[16],\"isLoading\":[4,\"is-loading\"],\"editorId\":[1,\"editor-id\"],\"activeWorkspaceId\":[1,\"active-workspace-id\"],\"isEngineReady\":[32],\"isControlsReady\":[32],\"isWorkspaceManagerReady\":[32],\"workspaces\":[32],\"activeWorkspace\":[32],\"isVirtualKeyboardOpen\":[32],\"undoState\":[32],\"isBackToContentButtonVisible\":[32],\"shortcuts\":[32],\"currentIsPublic\":[32],\"isEditorVisible\":[32],\"getObjectById\":[64],\"addObject\":[64],\"addObjects\":[64],\"updateObject\":[64],\"removeObject\":[64],\"removeObjects\":[64],\"getSelectedObjects\":[64],\"selectObjects\":[64],\"selectAllObjectsInViewport\":[64],\"clearSelection\":[64],\"centerObjectInViewport\":[64],\"panToObject\":[64],\"backToContent\":[64],\"centerAllObjects\":[64],\"centerObjects\":[64],\"setViewport\":[64],\"panTo\":[64],\"zoomTo\":[64],\"zoomIn\":[64],\"zoomOut\":[64],\"getViewport\":[64],\"screenToWorld\":[64],\"worldToScreen\":[64],\"createWorkspace\":[64],\"updateWorkspace\":[64],\"deleteWorkspace\":[64],\"getWorkspaces\":[64],\"getActiveWorkspace\":[64],\"loadSharedWorkspace\":[64],\"reinitSync\":[64],\"registerTool\":[64],\"changeActiveTool\":[64],\"changeActiveToolByName\":[64],\"disable\":[64],\"enable\":[64],\"copy\":[64],\"cut\":[64],\"paste\":[64],\"delete\":[64],\"bringForward\":[64],\"sendBackward\":[64],\"bringToFront\":[64],\"sendToBack\":[64],\"alignObjects\":[64],\"group\":[64],\"ungroup\":[64],\"undo\":[64],\"redo\":[64],\"getScreenshot\":[64],\"exportViewportAsPng\":[64],\"exportViewportAsSvg\":[64],\"exportSelectedObjectsAsPng\":[64],\"exportSelectedObjectsAsSvg\":[64],\"downloadAsJson\":[64],\"importFromFile\":[64],\"loadObjectsFromJson\":[64],\"getObjectsTotalCount\":[64],\"getAllObjects\":[64],\"findObjects\":[64],\"getCopiedObjects\":[64],\"getObjectsInViewport\":[64],\"hideContextMenu\":[64],\"openContextMenu\":[64],\"triggerSelectionChange\":[64],\"getDisplayableShortcuts\":[64],\"openLoginDialog\":[64],\"setLoginLoading\":[64]},[[0,\"dblclick\",\"onTouchStart\"]],{\"isEngineReady\":[{\"onIsEngineReady\":0}],\"isControlsReady\":[{\"onIsControlsReady\":0}],\"workspaces\":[{\"onWorkspacesChange\":0}],\"activeWorkspace\":[{\"onActiveWorkspaceChange\":0}],\"activeWorkspaceId\":[{\"onActiveWorkspaceIdChange\":0}],\"theme\":[{\"onCurrentThemeChange\":0}],\"themes\":[{\"onThemesChange\":0}]}],[513,\"kritzel-controls\",{\"visible\":[4],\"controls\":[16],\"activeControl\":[1040],\"isUtilityPanelVisible\":[4,\"is-utility-panel-visible\"],\"undoState\":[16],\"theme\":[1],\"firstConfig\":[32],\"isTouchDevice\":[32],\"selectedSubOptions\":[32],\"canScrollLeft\":[32],\"canScrollRight\":[32],\"needsScrolling\":[32],\"displayValues\":[32],\"internalControls\":[32],\"closeTooltip\":[64]},[[8,\"keydown\",\"handleKeyDown\"]],{\"controls\":[{\"onControlsChange\":0}],\"theme\":[{\"onThemeChange\":0}]}],[513,\"kritzel-settings\",{\"availableThemes\":[16],\"shortcuts\":[16],\"settings\":[16],\"isDialogOpen\":[32],\"selectedCategoryId\":[32],\"scaleMin\":[32],\"scaleMax\":[32],\"lockDrawingScale\":[32],\"theme\":[32],\"viewportBoundaryLeft\":[32],\"viewportBoundaryRight\":[32],\"viewportBoundaryTop\":[32],\"viewportBoundaryBottom\":[32],\"debugInfo\":[32],\"open\":[64]},null,{\"settings\":[{\"onSettingsPropChange\":0}]}],[513,\"kritzel-export\",{\"workspaceName\":[1,\"workspace-name\"],\"isDialogOpen\":[32],\"previewUrl\":[32],\"isLoading\":[32],\"activeTab\":[32],\"exportFilename\":[32],\"viewportExportFormat\":[32],\"open\":[64]}],[513,\"kritzel-workspace-manager\",{\"visible\":[4],\"activeWorkspace\":[1040],\"workspaces\":[16],\"childMenuAnchor\":[32],\"openChildMenuItem\":[32],\"newWorkspace\":[32],\"editingItemId\":[32]},[[8,\"wheel\",\"handleWheel\"]]],[513,\"kritzel-engine\",{\"workspace\":[16],\"editorId\":[1,\"editor-id\"],\"activeWorkspaceId\":[1,\"active-workspace-id\"],\"syncConfig\":[16],\"assetStorageConfig\":[16],\"user\":[16],\"globalContextMenuItems\":[16],\"objectContextMenuItems\":[16],\"scaleMax\":[1026,\"scale-max\"],\"scaleMin\":[1026,\"scale-min\"],\"cursorTarget\":[16],\"lockDrawingScale\":[4,\"lock-drawing-scale\"],\"isObjectDistanceFadingActive\":[4,\"is-object-distance-fading-active\"],\"theme\":[1],\"themes\":[16],\"viewportBoundaryLeft\":[2,\"viewport-boundary-left\"],\"viewportBoundaryRight\":[2,\"viewport-boundary-right\"],\"viewportBoundaryTop\":[2,\"viewport-boundary-top\"],\"viewportBoundaryBottom\":[2,\"viewport-boundary-bottom\"],\"debugInfo\":[16],\"wheelEnabled\":[4,\"wheel-enabled\"],\"isLoading\":[4,\"is-loading\"],\"forceUpdate\":[32],\"triggerSelectionChange\":[64],\"registerTool\":[64],\"changeActiveTool\":[64],\"changeActiveToolByName\":[64],\"disable\":[64],\"enable\":[64],\"delete\":[64],\"copy\":[64],\"cut\":[64],\"paste\":[64],\"bringForward\":[64],\"sendBackward\":[64],\"bringToFront\":[64],\"sendToBack\":[64],\"alignObjects\":[64],\"group\":[64],\"ungroup\":[64],\"undo\":[64],\"redo\":[64],\"hideContextMenu\":[64],\"openContextMenu\":[64],\"getObjectById\":[64],\"getAllObjects\":[64],\"findObjects\":[64],\"getObjectsTotalCount\":[64],\"addObject\":[64],\"addObjects\":[64],\"updateObject\":[64],\"removeObject\":[64],\"removeObjects\":[64],\"getSelectedObjects\":[64],\"getDisplayableShortcuts\":[64],\"selectObjects\":[64],\"selectAllObjectsInViewport\":[64],\"clearSelection\":[64],\"centerObjectInViewport\":[64],\"panToObject\":[64],\"backToContent\":[64],\"centerAllObjects\":[64],\"centerObjects\":[64],\"setViewport\":[64],\"panTo\":[64],\"zoomTo\":[64],\"zoomIn\":[64],\"zoomOut\":[64],\"getViewport\":[64],\"screenToWorld\":[64],\"worldToScreen\":[64],\"getCopiedObjects\":[64],\"getObjectsInViewport\":[64],\"getScreenshot\":[64],\"exportViewportAsPng\":[64],\"exportViewportAsSvg\":[64],\"getSelectedObjectsAsSvgString\":[64],\"exportSelectedObjectsAsSvg\":[64],\"getSelectedObjectsAsPngDataUrl\":[64],\"exportSelectedObjectsAsPng\":[64],\"exportAsJson\":[64],\"importFromJson\":[64],\"loadObjectsFromJson\":[64],\"downloadAsJson\":[64],\"importFromFile\":[64],\"createWorkspace\":[64],\"updateWorkspace\":[64],\"deleteWorkspace\":[64],\"getWorkspaces\":[64],\"getActiveWorkspace\":[64],\"getIsPublic\":[64],\"loadSharedWorkspace\":[64],\"reinitSync\":[64],\"saveSettings\":[64],\"loadSettings\":[64]},[[1,\"wheel\",\"handleWheel\"],[0,\"pointerdown\",\"handlePointerDown\"],[0,\"pointermove\",\"handlePointerMove\"],[0,\"pointerup\",\"handlePointerUp\"],[0,\"pointercancel\",\"handlePointerCancel\"],[1,\"pointerleave\",\"handlePointerLeave\"],[1,\"longpress\",\"handleLongPress\"],[0,\"contextmenu\",\"handleContextMenu\"],[9,\"resize\",\"handleResize\"],[8,\"keydown\",\"handleKeyDown\"],[8,\"keyup\",\"handleKeyUp\"],[4,\"dblclick\",\"preventDoubleTapZoomOnTouchDevices\"]],{\"workspace\":[{\"onWorkspaceChange\":0}],\"activeWorkspaceId\":[{\"onActiveWorkspaceIdChange\":0}],\"syncConfig\":[{\"onSyncConfigChange\":0}],\"assetStorageConfig\":[{\"onAssetStorageConfigChange\":0}],\"user\":[{\"onUserChange\":0}],\"globalContextMenuItems\":[{\"onGlobalContextMenuItemsChange\":0}],\"objectContextMenuItems\":[{\"onObjectContextMenuItemsChange\":0}],\"scaleMax\":[{\"validateScaleMax\":0}],\"scaleMin\":[{\"validateScaleMin\":0}],\"cursorTarget\":[{\"onCursorTargetChange\":0}],\"lockDrawingScale\":[{\"onLockDrawingScaleChange\":0}],\"isObjectDistanceFadingActive\":[{\"onIsObjectDistanceFadingActiveChange\":0}],\"theme\":[{\"onThemeChange\":0}],\"themes\":[{\"onThemesChange\":0}],\"viewportBoundaryLeft\":[{\"onViewportBoundaryLeftChange\":0}],\"viewportBoundaryRight\":[{\"onViewportBoundaryRightChange\":0}],\"viewportBoundaryTop\":[{\"onViewportBoundaryTopChange\":0}],\"viewportBoundaryBottom\":[{\"onViewportBoundaryBottomChange\":0}],\"debugInfo\":[{\"onDebugInfoChange\":0}],\"isLoading\":[{\"onIsLoadingChange\":0}]}],[513,\"kritzel-more-menu\",{\"visible\":[4],\"items\":[16],\"icon\":[1],\"iconSize\":[2,\"icon-size\"],\"offsetY\":[2,\"offset-y\"],\"menuAnchor\":[32],\"isTouchDevice\":[32]}],[513,\"kritzel-current-user\",{\"user\":[16],\"avatarSize\":[2,\"avatar-size\"]}],[513,\"kritzel-share-dialog\",{\"isPublic\":[4,\"is-public\"],\"workspaceId\":[1,\"workspace-id\"],\"isDialogOpen\":[32],\"internalIsPublic\":[32],\"copySuccess\":[32],\"open\":[64],\"close\":[64]},null,{\"isPublic\":[{\"onIsPublicChange\":0}]}],[513,\"kritzel-login-dialog\",{\"providers\":[16],\"dialogTitle\":[1,\"dialog-title\"],\"subtitle\":[1],\"isDialogOpen\":[32],\"loadingProvider\":[32],\"open\":[64],\"close\":[64],\"setLoading\":[64]}],[513,\"kritzel-active-users\",{\"users\":[16],\"avatarSize\":[2,\"avatar-size\"],\"maxVisible\":[2,\"max-visible\"],\"overlap\":[2]}],[513,\"kritzel-back-to-content\",{\"visible\":[4],\"text\":[1]}],[769,\"kritzel-button\",{\"variant\":[1],\"disabled\":[4],\"type\":[1]}],[513,\"kritzel-tool-config\",{\"tool\":[1040],\"isExpanded\":[1028,\"is-expanded\"],\"theme\":[1],\"engine\":[16],\"config\":[32],\"palette\":[32],\"sizes\":[32],\"currentOpacity\":[32],\"updateTrigger\":[32]},null,{\"tool\":[{\"handleToolChange\":0}],\"theme\":[{\"onThemeChange\":0}],\"engine\":[{\"handleEngineChange\":0}]}],[513,\"kritzel-split-button\",{\"buttonIcon\":[1,\"button-icon\"],\"dropdownIcon\":[1,\"dropdown-icon\"],\"items\":[16],\"mainButtonDisabled\":[4,\"main-button-disabled\"],\"menuButtonDisabled\":[4,\"menu-button-disabled\"],\"isMenuOpen\":[32],\"isTouchDevice\":[32],\"anchorElement\":[32],\"menuScrollTop\":[32],\"open\":[64],\"focusMenu\":[64]}],[513,\"kritzel-current-user-dialog\",{\"user\":[16],\"isDialogOpen\":[32],\"open\":[64],\"close\":[64]}],[513,\"kritzel-context-menu\",{\"items\":[16],\"objects\":[16],\"processedItems\":[32],\"openSubmenuPath\":[32],\"submenuPositions\":[32]},[[9,\"pointerdown\",\"handleOutsideClick\"]],{\"items\":[{\"onItemsChanged\":0}]}],[769,\"kritzel-master-detail\",{\"items\":[16],\"selectedItemId\":[1,\"selected-item-id\"],\"focusedIndex\":[32],\"showMobileDetail\":[32]},null,{\"selectedItemId\":[{\"watchSelectedItemId\":0}]}],[513,\"kritzel-pill-tabs\",{\"tabs\":[16],\"value\":[1025]}],[513,\"kritzel-utility-panel\",{\"undoState\":[16]}],[513,\"kritzel-awareness-cursors\",{\"core\":[16],\"showEdgeIndicators\":[4,\"show-edge-indicators\"],\"edgeIndicatorPadding\":[2,\"edge-indicator-padding\"],\"remoteCursors\":[32],\"objectVersion\":[32]}],[513,\"kritzel-cursor-trail\",{\"core\":[16],\"cursorTrailPoints\":[32],\"isLeftButtonDown\":[32]},[[9,\"pointerdown\",\"handleMouseDown\"],[9,\"pointermove\",\"handlePointerMove\"],[9,\"pointerup\",\"handlePointerUp\"]]],[513,\"kritzel-input\",{\"value\":[1025],\"label\":[1],\"placeholder\":[1],\"suffix\":[1],\"type\":[1],\"disabled\":[4],\"inputValue\":[32]},null,{\"value\":[{\"onValueChange\":0}]}],[513,\"kritzel-numeric-input\",{\"value\":[1026],\"min\":[2],\"max\":[2],\"step\":[2],\"label\":[1],\"placeholder\":[1],\"inputValue\":[32]},null,{\"value\":[{\"onValueChange\":0}]}],[769,\"kritzel-tooltip\",{\"isVisible\":[1028,\"is-visible\"],\"anchorElement\":[16],\"triggerElement\":[16],\"offsetY\":[2,\"offset-y\"],\"positionX\":[32],\"positionY\":[32],\"open\":[64],\"close\":[64],\"toggle\":[64],\"focusContent\":[64]},[[4,\"click\",\"handleOutsideClick\"],[6,\"pointerdown\",\"handleOutsidePointerDown\"],[4,\"kritzelTooltipCloseAll\",\"handleCloseAll\"],[9,\"resize\",\"handleWindowResize\"]],{\"triggerElement\":[{\"handleTriggerElementChange\":0}],\"isVisible\":[{\"handleVisibilityChange\":0}]}],[513,\"kritzel-color-palette\",{\"colors\":[16],\"selectedColor\":[1040],\"isExpanded\":[4,\"is-expanded\"],\"isOpaque\":[4,\"is-opaque\"],\"opacity\":[2],\"theme\":[1]}],[513,\"kritzel-font-family\",{\"fontOptions\":[16],\"selectedFontFamily\":[1025,\"selected-font-family\"]}],[513,\"kritzel-font-size\",{\"sizes\":[16],\"selectedSize\":[1026,\"selected-size\"],\"fontFamily\":[1,\"font-family\"]}],[513,\"kritzel-stroke-size\",{\"sizes\":[16],\"selectedSize\":[1026,\"selected-size\"]}],[513,\"kritzel-line-endings\",{\"styles\":[16],\"value\":[1040]}],[513,\"kritzel-opacity-slider\",{\"value\":[1026],\"min\":[2],\"max\":[2],\"step\":[2],\"previewColor\":[1,\"preview-color\"]}],[513,\"kritzel-shape-fill\",{\"value\":[1025]}],[513,\"kritzel-slide-toggle\",{\"checked\":[1028],\"disabled\":[4],\"label\":[1]}],[513,\"kritzel-avatar\",{\"user\":[16],\"name\":[1],\"size\":[2],\"color\":[1],\"imageError\":[32]},null,{\"user\":[{\"userChanged\":0}],\"profileImageUrl\":[{\"profileImageUrlChanged\":0}]}],[513,\"kritzel-font\",{\"fontFamily\":[1,\"font-family\"],\"size\":[2],\"color\":[1]}],[513,\"kritzel-color\",{\"value\":[1],\"theme\":[1],\"size\":[2]}],[513,\"kritzel-menu\",{\"items\":[16],\"parent\":[16],\"selectedIndex\":[32],\"setScrollTop\":[64],\"setFocus\":[64]}],[513,\"kritzel-menu-item\",{\"item\":[16],\"parent\":[16],\"isDirty\":[32]},null,{\"item\":[{\"onItemChange\":0}]}],[769,\"kritzel-portal\",{\"anchor\":[16],\"offsetX\":[2,\"offset-x\"],\"offsetY\":[2,\"offset-y\"],\"autoFocus\":[4,\"auto-focus\"]},[[8,\"kritzel-dismiss-menus\",\"handleDismissMenus\"],[8,\"click\",\"handleOutsideClick\"],[6,\"pointerdown\",\"handleOutsidePointerDown\"],[8,\"keydown\",\"handleKeyDown\"],[11,\"resize\",\"handleResize\"],[11,\"scroll\",\"handleWindowScroll\"]],{\"anchor\":[{\"anchorChanged\":0}]}],[769,\"kritzel-dialog\",{\"isOpen\":[516,\"is-open\"],\"dialogTitle\":[1,\"dialog-title\"],\"closable\":[4],\"closeOnBackdrop\":[4,\"close-on-backdrop\"],\"closeOnEscape\":[4,\"close-on-escape\"],\"autoFocus\":[4,\"auto-focus\"],\"trapFocus\":[4,\"trap-focus\"],\"size\":[1],\"fullscreenOnMobile\":[4,\"fullscreen-on-mobile\"],\"contained\":[516],\"isAnimating\":[32],\"mobileLockedHeight\":[32],\"containerRect\":[32],\"containerBorderRadius\":[32],\"open\":[64],\"close\":[64],\"focusFirstElement\":[64]},[[8,\"keydown\",\"handleKeyDown\"],[9,\"resize\",\"handleWindowResize\"],[8,\"orientationchange\",\"handleOrientationChange\"]],{\"isOpen\":[{\"handleIsOpenChange\":0}]}],[769,\"kritzel-dropdown\",{\"options\":[16],\"value\":[1],\"width\":[1],\"selectStyles\":[16],\"forceOpenDirection\":[1,\"force-open-direction\"],\"internalValue\":[32],\"hasSuffixContent\":[32],\"hasPrefixContent\":[32],\"isOpen\":[32],\"focusedIndex\":[32],\"openDirection\":[32]},[[4,\"click\",\"handleDocumentClick\"],[4,\"keydown\",\"handleDocumentKeydown\"]],{\"options\":[{\"optionsChanged\":0}],\"value\":[{\"externalValueChanged\":0}]}],[513,\"kritzel-icon\",{\"name\":[1],\"label\":[1],\"size\":[2]}]]],[\"kritzel-brush-style.cjs\",[[513,\"kritzel-brush-style\",{\"type\":[1],\"brushOptions\":[16]}]]]]"), options);
|
|
22
|
+
return index.bootstrapLazy(JSON.parse("[[\"kritzel-active-users_44.cjs\",[[512,\"kritzel-editor\",{\"scaleMax\":[1026,\"scale-max\"],\"scaleMin\":[1026,\"scale-min\"],\"lockDrawingScale\":[1028,\"lock-drawing-scale\"],\"viewportBoundaryLeft\":[1026,\"viewport-boundary-left\"],\"viewportBoundaryRight\":[1026,\"viewport-boundary-right\"],\"viewportBoundaryTop\":[1026,\"viewport-boundary-top\"],\"viewportBoundaryBottom\":[1026,\"viewport-boundary-bottom\"],\"debugInfo\":[1040],\"user\":[16],\"activeUsers\":[16],\"controls\":[16],\"globalContextMenuItems\":[16],\"objectContextMenuItems\":[16],\"themes\":[16],\"theme\":[1025],\"licenseKey\":[1,\"license-key\"],\"locale\":[1025],\"locales\":[16],\"fallbackLocale\":[1,\"fallback-locale\"],\"customSvgIcons\":[16],\"isPanningEnabled\":[1028,\"is-panning-enabled\"],\"isZoomingEnabled\":[1028,\"is-zooming-enabled\"],\"isControlsVisible\":[4,\"is-controls-visible\"],\"isUtilityPanelVisible\":[4,\"is-utility-panel-visible\"],\"isWorkspaceManagerVisible\":[4,\"is-workspace-manager-visible\"],\"isMoreMenuVisible\":[4,\"is-more-menu-visible\"],\"isZoomPanelVisible\":[4,\"is-zoom-panel-visible\"],\"isObjectDistanceFadingActive\":[4,\"is-object-distance-fading-active\"],\"syncConfig\":[16],\"assetStorageConfig\":[16],\"cursorTarget\":[16],\"loginConfig\":[16],\"isLoading\":[4,\"is-loading\"],\"editorId\":[1,\"editor-id\"],\"activeWorkspaceId\":[1,\"active-workspace-id\"],\"isEngineReady\":[32],\"isControlsReady\":[32],\"isWorkspaceManagerReady\":[32],\"workspaces\":[32],\"activeWorkspace\":[32],\"isVirtualKeyboardOpen\":[32],\"undoState\":[32],\"isBackToContentButtonVisible\":[32],\"resolvedTerms\":[32],\"availableLocaleOptions\":[32],\"currentZoomPercent\":[32],\"shortcuts\":[32],\"currentIsPublic\":[32],\"isEditorVisible\":[32],\"getObjectById\":[64],\"addObject\":[64],\"addObjects\":[64],\"updateObject\":[64],\"removeObject\":[64],\"removeObjects\":[64],\"getSelectedObjects\":[64],\"selectObjects\":[64],\"selectAllObjectsInViewport\":[64],\"clearSelection\":[64],\"centerObjectInViewport\":[64],\"panToObject\":[64],\"backToContent\":[64],\"centerAllObjects\":[64],\"centerObjects\":[64],\"setViewport\":[64],\"panTo\":[64],\"zoomTo\":[64],\"zoomIn\":[64],\"zoomOut\":[64],\"getViewport\":[64],\"screenToWorld\":[64],\"worldToScreen\":[64],\"createWorkspace\":[64],\"updateWorkspace\":[64],\"deleteWorkspace\":[64],\"getWorkspaces\":[64],\"getActiveWorkspace\":[64],\"loadSharedWorkspace\":[64],\"reinitSync\":[64],\"registerTool\":[64],\"changeActiveTool\":[64],\"changeActiveToolByName\":[64],\"disable\":[64],\"enable\":[64],\"copy\":[64],\"cut\":[64],\"paste\":[64],\"delete\":[64],\"bringForward\":[64],\"sendBackward\":[64],\"bringToFront\":[64],\"sendToBack\":[64],\"alignObjects\":[64],\"group\":[64],\"ungroup\":[64],\"undo\":[64],\"redo\":[64],\"getScreenshot\":[64],\"exportViewportAsPng\":[64],\"exportViewportAsSvg\":[64],\"exportSelectedObjectsAsPng\":[64],\"exportSelectedObjectsAsSvg\":[64],\"downloadAsJson\":[64],\"importFromFile\":[64],\"loadObjectsFromJson\":[64],\"getObjectsTotalCount\":[64],\"getAllObjects\":[64],\"findObjects\":[64],\"getCopiedObjects\":[64],\"getObjectsInViewport\":[64],\"hideContextMenu\":[64],\"openContextMenu\":[64],\"triggerSelectionChange\":[64],\"getDisplayableShortcuts\":[64],\"openLoginDialog\":[64],\"setLoginLoading\":[64],\"setLocale\":[64],\"getLocale\":[64],\"getAvailableLocales\":[64],\"registerLocales\":[64],\"t\":[64]},[[0,\"dblclick\",\"onTouchStart\"]],{\"isEngineReady\":[{\"onIsEngineReady\":0}],\"isControlsReady\":[{\"onIsControlsReady\":0}],\"workspaces\":[{\"onWorkspacesChange\":0}],\"activeWorkspace\":[{\"onActiveWorkspaceChange\":0}],\"activeWorkspaceId\":[{\"onActiveWorkspaceIdChange\":0}],\"theme\":[{\"onCurrentThemeChange\":0}],\"themes\":[{\"onThemesChange\":0}],\"locale\":[{\"onLocaleChange\":0}]}],[513,\"kritzel-controls\",{\"visible\":[4],\"controls\":[16],\"activeControl\":[1040],\"isUtilityPanelVisible\":[4,\"is-utility-panel-visible\"],\"undoState\":[16],\"theme\":[1],\"terms\":[16],\"firstConfig\":[32],\"isTouchDevice\":[32],\"selectedSubOptions\":[32],\"canScrollLeft\":[32],\"canScrollRight\":[32],\"needsScrolling\":[32],\"displayValues\":[32],\"internalControls\":[32],\"closeTooltip\":[64]},[[8,\"keydown\",\"handleKeyDown\"]],{\"controls\":[{\"onControlsChange\":0}],\"theme\":[{\"onThemeChange\":0}]}],[513,\"kritzel-settings\",{\"availableThemes\":[16],\"availableLocales\":[16],\"shortcuts\":[16],\"terms\":[16],\"settings\":[16],\"isDialogOpen\":[32],\"selectedCategoryId\":[32],\"scaleMin\":[32],\"scaleMax\":[32],\"lockDrawingScale\":[32],\"theme\":[32],\"locale\":[32],\"viewportBoundaryLeft\":[32],\"viewportBoundaryRight\":[32],\"viewportBoundaryTop\":[32],\"viewportBoundaryBottom\":[32],\"debugInfo\":[32],\"open\":[64]},null,{\"settings\":[{\"onSettingsPropChange\":0}]}],[513,\"kritzel-engine\",{\"workspace\":[16],\"editorId\":[1,\"editor-id\"],\"activeWorkspaceId\":[1,\"active-workspace-id\"],\"syncConfig\":[16],\"assetStorageConfig\":[16],\"user\":[16],\"globalContextMenuItems\":[16],\"objectContextMenuItems\":[16],\"scaleMax\":[1026,\"scale-max\"],\"scaleMin\":[1026,\"scale-min\"],\"cursorTarget\":[16],\"lockDrawingScale\":[4,\"lock-drawing-scale\"],\"isObjectDistanceFadingActive\":[4,\"is-object-distance-fading-active\"],\"theme\":[1],\"licenseKey\":[1,\"license-key\"],\"themes\":[16],\"locale\":[1],\"locales\":[16],\"fallbackLocale\":[1,\"fallback-locale\"],\"viewportBoundaryLeft\":[2,\"viewport-boundary-left\"],\"viewportBoundaryRight\":[2,\"viewport-boundary-right\"],\"viewportBoundaryTop\":[2,\"viewport-boundary-top\"],\"viewportBoundaryBottom\":[2,\"viewport-boundary-bottom\"],\"debugInfo\":[16],\"isPanningEnabled\":[4,\"is-panning-enabled\"],\"isZoomingEnabled\":[4,\"is-zooming-enabled\"],\"isLoading\":[4,\"is-loading\"],\"forceUpdate\":[32],\"triggerSelectionChange\":[64],\"registerTool\":[64],\"changeActiveTool\":[64],\"changeActiveToolByName\":[64],\"disable\":[64],\"enable\":[64],\"delete\":[64],\"copy\":[64],\"cut\":[64],\"paste\":[64],\"bringForward\":[64],\"sendBackward\":[64],\"bringToFront\":[64],\"sendToBack\":[64],\"alignObjects\":[64],\"group\":[64],\"ungroup\":[64],\"undo\":[64],\"redo\":[64],\"hideContextMenu\":[64],\"openContextMenu\":[64],\"getObjectById\":[64],\"getAllObjects\":[64],\"findObjects\":[64],\"getObjectsTotalCount\":[64],\"addObject\":[64],\"addObjects\":[64],\"updateObject\":[64],\"removeObject\":[64],\"removeObjects\":[64],\"getSelectedObjects\":[64],\"getDisplayableShortcuts\":[64],\"selectObjects\":[64],\"selectAllObjectsInViewport\":[64],\"clearSelection\":[64],\"centerObjectInViewport\":[64],\"panToObject\":[64],\"backToContent\":[64],\"centerAllObjects\":[64],\"centerObjects\":[64],\"setViewport\":[64],\"panTo\":[64],\"zoomTo\":[64],\"zoomIn\":[64],\"zoomOut\":[64],\"getViewport\":[64],\"screenToWorld\":[64],\"worldToScreen\":[64],\"getCopiedObjects\":[64],\"getObjectsInViewport\":[64],\"getScreenshot\":[64],\"exportViewportAsPng\":[64],\"exportViewportAsSvg\":[64],\"getSelectedObjectsAsSvgString\":[64],\"exportSelectedObjectsAsSvg\":[64],\"getSelectedObjectsAsPngDataUrl\":[64],\"exportSelectedObjectsAsPng\":[64],\"exportAsJson\":[64],\"importFromJson\":[64],\"loadObjectsFromJson\":[64],\"downloadAsJson\":[64],\"importFromFile\":[64],\"createWorkspace\":[64],\"updateWorkspace\":[64],\"deleteWorkspace\":[64],\"getWorkspaces\":[64],\"getActiveWorkspace\":[64],\"getIsPublic\":[64],\"loadSharedWorkspace\":[64],\"reinitSync\":[64],\"saveSettings\":[64],\"loadSettings\":[64],\"registerLocales\":[64],\"setLocale\":[64],\"getLocale\":[64],\"getAvailableLocales\":[64],\"getAvailableLocaleOptions\":[64],\"t\":[64],\"getResolvedTerms\":[64]},[[1,\"wheel\",\"handleWheel\"],[0,\"pointerdown\",\"handlePointerDown\"],[0,\"pointermove\",\"handlePointerMove\"],[0,\"pointerup\",\"handlePointerUp\"],[0,\"pointercancel\",\"handlePointerCancel\"],[1,\"pointerleave\",\"handlePointerLeave\"],[1,\"longpress\",\"handleLongPress\"],[0,\"contextmenu\",\"handleContextMenu\"],[9,\"resize\",\"handleResize\"],[8,\"keydown\",\"handleKeyDown\"],[8,\"keyup\",\"handleKeyUp\"],[4,\"dblclick\",\"preventDoubleTapZoomOnTouchDevices\"]],{\"workspace\":[{\"onWorkspaceChange\":0}],\"activeWorkspaceId\":[{\"onActiveWorkspaceIdChange\":0}],\"syncConfig\":[{\"onSyncConfigChange\":0}],\"assetStorageConfig\":[{\"onAssetStorageConfigChange\":0}],\"user\":[{\"onUserChange\":0}],\"globalContextMenuItems\":[{\"onGlobalContextMenuItemsChange\":0}],\"objectContextMenuItems\":[{\"onObjectContextMenuItemsChange\":0}],\"scaleMax\":[{\"validateScaleMax\":0}],\"scaleMin\":[{\"validateScaleMin\":0}],\"cursorTarget\":[{\"onCursorTargetChange\":0}],\"lockDrawingScale\":[{\"onLockDrawingScaleChange\":0}],\"isObjectDistanceFadingActive\":[{\"onIsObjectDistanceFadingActiveChange\":0}],\"theme\":[{\"onThemeChange\":0}],\"licenseKey\":[{\"onLicenseKeyChange\":0}],\"themes\":[{\"onThemesChange\":0}],\"locale\":[{\"onLocaleChange\":0}],\"locales\":[{\"onLocalesChange\":0}],\"fallbackLocale\":[{\"onFallbackLocaleChange\":0}],\"viewportBoundaryLeft\":[{\"onViewportBoundaryLeftChange\":0}],\"viewportBoundaryRight\":[{\"onViewportBoundaryRightChange\":0}],\"viewportBoundaryTop\":[{\"onViewportBoundaryTopChange\":0}],\"viewportBoundaryBottom\":[{\"onViewportBoundaryBottomChange\":0}],\"debugInfo\":[{\"onDebugInfoChange\":0}],\"isLoading\":[{\"onIsLoadingChange\":0}]}],[513,\"kritzel-export\",{\"workspaceName\":[1,\"workspace-name\"],\"terms\":[16],\"isDialogOpen\":[32],\"previewUrl\":[32],\"isLoading\":[32],\"activeTab\":[32],\"exportFilename\":[32],\"viewportExportFormat\":[32],\"open\":[64]}],[513,\"kritzel-workspace-manager\",{\"visible\":[4],\"activeWorkspace\":[1040],\"workspaces\":[16],\"terms\":[16],\"childMenuAnchor\":[32],\"openChildMenuItem\":[32],\"newWorkspace\":[32],\"editingItemId\":[32]},[[8,\"wheel\",\"handleWheel\"]]],[513,\"kritzel-more-menu\",{\"visible\":[4],\"items\":[16],\"icon\":[1],\"iconSize\":[2,\"icon-size\"],\"offsetY\":[2,\"offset-y\"],\"terms\":[16],\"menuAnchor\":[32],\"isTouchDevice\":[32]}],[513,\"kritzel-current-user\",{\"user\":[16],\"avatarSize\":[2,\"avatar-size\"],\"terms\":[16]}],[513,\"kritzel-share-dialog\",{\"isPublic\":[4,\"is-public\"],\"workspaceId\":[1,\"workspace-id\"],\"terms\":[16],\"isDialogOpen\":[32],\"internalIsPublic\":[32],\"copySuccess\":[32],\"open\":[64],\"close\":[64]},null,{\"isPublic\":[{\"onIsPublicChange\":0}]}],[513,\"kritzel-login-dialog\",{\"providers\":[16],\"dialogTitle\":[1,\"dialog-title\"],\"subtitle\":[1],\"isDialogOpen\":[32],\"loadingProvider\":[32],\"open\":[64],\"close\":[64],\"setLoading\":[64]}],[513,\"kritzel-active-users\",{\"users\":[16],\"avatarSize\":[2,\"avatar-size\"],\"maxVisible\":[2,\"max-visible\"],\"overlap\":[2]}],[513,\"kritzel-back-to-content\",{\"visible\":[4],\"text\":[1]}],[513,\"kritzel-zoom-panel\",{\"visible\":[4],\"disabled\":[4],\"zoomPercent\":[2,\"zoom-percent\"],\"terms\":[16]}],[769,\"kritzel-button\",{\"variant\":[1],\"disabled\":[4],\"type\":[1]}],[513,\"kritzel-tool-config\",{\"tool\":[1040],\"isExpanded\":[1028,\"is-expanded\"],\"theme\":[1],\"engine\":[16],\"terms\":[16],\"config\":[32],\"palette\":[32],\"sizes\":[32],\"currentOpacity\":[32],\"updateTrigger\":[32]},null,{\"tool\":[{\"handleToolChange\":0}],\"theme\":[{\"onThemeChange\":0}],\"engine\":[{\"handleEngineChange\":0}]}],[513,\"kritzel-split-button\",{\"buttonIcon\":[1,\"button-icon\"],\"dropdownIcon\":[1,\"dropdown-icon\"],\"items\":[16],\"mainButtonDisabled\":[4,\"main-button-disabled\"],\"menuButtonDisabled\":[4,\"menu-button-disabled\"],\"isMenuOpen\":[32],\"isTouchDevice\":[32],\"anchorElement\":[32],\"menuScrollTop\":[32],\"open\":[64],\"focusMenu\":[64]}],[513,\"kritzel-current-user-dialog\",{\"user\":[16],\"terms\":[16],\"isDialogOpen\":[32],\"open\":[64],\"close\":[64]}],[513,\"kritzel-context-menu\",{\"items\":[16],\"objects\":[16],\"processedItems\":[32],\"openSubmenuPath\":[32],\"submenuPositions\":[32]},[[9,\"pointerdown\",\"handleOutsideClick\"]],{\"items\":[{\"onItemsChanged\":0}]}],[769,\"kritzel-master-detail\",{\"items\":[16],\"selectedItemId\":[1,\"selected-item-id\"],\"focusedIndex\":[32],\"showMobileDetail\":[32]},null,{\"selectedItemId\":[{\"watchSelectedItemId\":0}]}],[513,\"kritzel-pill-tabs\",{\"tabs\":[16],\"value\":[1025]}],[513,\"kritzel-utility-panel\",{\"undoState\":[16],\"terms\":[16]}],[513,\"kritzel-awareness-cursors\",{\"core\":[16],\"showEdgeIndicators\":[4,\"show-edge-indicators\"],\"edgeIndicatorPadding\":[2,\"edge-indicator-padding\"],\"remoteCursors\":[32],\"objectVersion\":[32]}],[513,\"kritzel-cursor-trail\",{\"core\":[16],\"cursorTrailPoints\":[32],\"isLeftButtonDown\":[32]},[[9,\"pointerdown\",\"handleMouseDown\"],[9,\"pointermove\",\"handlePointerMove\"],[9,\"pointerup\",\"handlePointerUp\"]]],[513,\"kritzel-input\",{\"value\":[1025],\"label\":[1],\"placeholder\":[1],\"suffix\":[1],\"type\":[1],\"disabled\":[4],\"inputValue\":[32]},null,{\"value\":[{\"onValueChange\":0}]}],[513,\"kritzel-numeric-input\",{\"value\":[1026],\"min\":[2],\"max\":[2],\"step\":[2],\"label\":[1],\"placeholder\":[1],\"inputValue\":[32]},null,{\"value\":[{\"onValueChange\":0}]}],[769,\"kritzel-tooltip\",{\"isVisible\":[1028,\"is-visible\"],\"anchorElement\":[16],\"triggerElement\":[16],\"offsetY\":[2,\"offset-y\"],\"positionX\":[32],\"positionY\":[32],\"open\":[64],\"close\":[64],\"toggle\":[64],\"focusContent\":[64]},[[4,\"click\",\"handleOutsideClick\"],[6,\"pointerdown\",\"handleOutsidePointerDown\"],[4,\"kritzelTooltipCloseAll\",\"handleCloseAll\"],[9,\"resize\",\"handleWindowResize\"]],{\"triggerElement\":[{\"handleTriggerElementChange\":0}],\"isVisible\":[{\"handleVisibilityChange\":0}]}],[513,\"kritzel-watermark\",{\"core\":[16],\"label\":[1]}],[513,\"kritzel-color-palette\",{\"colors\":[16],\"selectedColor\":[1040],\"isExpanded\":[4,\"is-expanded\"],\"isOpaque\":[4,\"is-opaque\"],\"opacity\":[2],\"theme\":[1]}],[513,\"kritzel-font-family\",{\"fontOptions\":[16],\"selectedFontFamily\":[1025,\"selected-font-family\"]}],[513,\"kritzel-font-size\",{\"sizes\":[16],\"selectedSize\":[1026,\"selected-size\"],\"fontFamily\":[1,\"font-family\"]}],[513,\"kritzel-stroke-size\",{\"sizes\":[16],\"selectedSize\":[1026,\"selected-size\"]}],[513,\"kritzel-line-endings\",{\"styles\":[16],\"value\":[1040]}],[513,\"kritzel-opacity-slider\",{\"value\":[1026],\"min\":[2],\"max\":[2],\"step\":[2],\"previewColor\":[1,\"preview-color\"]}],[513,\"kritzel-shape-fill\",{\"value\":[1025]}],[513,\"kritzel-slide-toggle\",{\"checked\":[1028],\"disabled\":[4],\"label\":[1]}],[513,\"kritzel-avatar\",{\"user\":[16],\"name\":[1],\"size\":[2],\"color\":[1],\"imageError\":[32]},null,{\"user\":[{\"userChanged\":0}],\"profileImageUrl\":[{\"profileImageUrlChanged\":0}]}],[513,\"kritzel-font\",{\"fontFamily\":[1,\"font-family\"],\"size\":[2],\"color\":[1]}],[513,\"kritzel-color\",{\"value\":[1],\"theme\":[1],\"size\":[2]}],[513,\"kritzel-menu\",{\"items\":[16],\"parent\":[16],\"selectedIndex\":[32],\"setScrollTop\":[64],\"setFocus\":[64]}],[513,\"kritzel-menu-item\",{\"item\":[16],\"parent\":[16],\"isDirty\":[32]},null,{\"item\":[{\"onItemChange\":0}]}],[769,\"kritzel-portal\",{\"anchor\":[16],\"offsetX\":[2,\"offset-x\"],\"offsetY\":[2,\"offset-y\"],\"autoFocus\":[4,\"auto-focus\"]},[[8,\"kritzel-dismiss-menus\",\"handleDismissMenus\"],[8,\"click\",\"handleOutsideClick\"],[6,\"pointerdown\",\"handleOutsidePointerDown\"],[8,\"keydown\",\"handleKeyDown\"],[11,\"resize\",\"handleResize\"],[11,\"scroll\",\"handleWindowScroll\"]],{\"anchor\":[{\"anchorChanged\":0}]}],[769,\"kritzel-dialog\",{\"isOpen\":[516,\"is-open\"],\"dialogTitle\":[1,\"dialog-title\"],\"closable\":[4],\"closeOnBackdrop\":[4,\"close-on-backdrop\"],\"closeOnEscape\":[4,\"close-on-escape\"],\"autoFocus\":[4,\"auto-focus\"],\"trapFocus\":[4,\"trap-focus\"],\"size\":[1],\"fullscreenOnMobile\":[4,\"fullscreen-on-mobile\"],\"contained\":[516],\"isAnimating\":[32],\"mobileLockedHeight\":[32],\"containerRect\":[32],\"containerBorderRadius\":[32],\"open\":[64],\"close\":[64],\"focusFirstElement\":[64]},[[8,\"keydown\",\"handleKeyDown\"],[9,\"resize\",\"handleWindowResize\"],[8,\"orientationchange\",\"handleOrientationChange\"]],{\"isOpen\":[{\"handleIsOpenChange\":0}]}],[769,\"kritzel-dropdown\",{\"options\":[16],\"value\":[1],\"width\":[1],\"selectStyles\":[16],\"forceOpenDirection\":[1,\"force-open-direction\"],\"internalValue\":[32],\"hasSuffixContent\":[32],\"hasPrefixContent\":[32],\"isOpen\":[32],\"focusedIndex\":[32],\"openDirection\":[32]},[[4,\"click\",\"handleDocumentClick\"],[4,\"keydown\",\"handleDocumentKeydown\"]],{\"options\":[{\"optionsChanged\":0}],\"value\":[{\"externalValueChanged\":0}]}],[513,\"kritzel-icon\",{\"name\":[1],\"label\":[1],\"size\":[2]}]]],[\"kritzel-brush-style.cjs\",[[513,\"kritzel-brush-style\",{\"type\":[1],\"brushOptions\":[16]}]]]]"), options);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
exports.setNonce = index.setNonce;
|
|
@@ -15,6 +15,8 @@ import { KritzelAppStateMap } from "../structures/app-state-map.structure";
|
|
|
15
15
|
import { KritzelAnchorManager } from "../managers/anchor.manager";
|
|
16
16
|
import { KritzelCursorManager } from "../managers/cursor.manager";
|
|
17
17
|
import { KritzelThemeManager } from "../managers/theme.manager";
|
|
18
|
+
import { KritzelLocalizationManager } from "../managers/localization.manager";
|
|
19
|
+
import { KritzelLicenseManager } from "../managers/license.manager";
|
|
18
20
|
import { KritzelClassHelper } from "../../helpers/class.helper";
|
|
19
21
|
/**
|
|
20
22
|
* Central orchestrator class for the Kritzel canvas system.
|
|
@@ -40,6 +42,10 @@ export class KritzelCore {
|
|
|
40
42
|
_cursorManager;
|
|
41
43
|
/** Manager for theme styling */
|
|
42
44
|
_themeManager;
|
|
45
|
+
/** Manager for localization / translated UI strings */
|
|
46
|
+
_localizationManager;
|
|
47
|
+
/** Manager for license validation and watermark gating */
|
|
48
|
+
_licenseManager;
|
|
43
49
|
/** Per-core registry of drawing tools (one instance per editor). */
|
|
44
50
|
_toolRegistry;
|
|
45
51
|
/** Optional unique identifier for namespacing storage keys across multiple editor instances */
|
|
@@ -88,6 +94,20 @@ export class KritzelCore {
|
|
|
88
94
|
get themeManager() {
|
|
89
95
|
return this._themeManager;
|
|
90
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* Gets the localization manager.
|
|
99
|
+
* @returns The KritzelLocalizationManager for resolving translated UI strings
|
|
100
|
+
*/
|
|
101
|
+
get localizationManager() {
|
|
102
|
+
return this._localizationManager;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Gets the license manager.
|
|
106
|
+
* @returns The KritzelLicenseManager for validating licenses and gating the watermark
|
|
107
|
+
*/
|
|
108
|
+
get licenseManager() {
|
|
109
|
+
return this._licenseManager;
|
|
110
|
+
}
|
|
91
111
|
/**
|
|
92
112
|
* Gets the tool registry scoped to this core instance.
|
|
93
113
|
* @returns The KritzelToolRegistry owned by this core
|
|
@@ -140,6 +160,8 @@ export class KritzelCore {
|
|
|
140
160
|
this._anchorManager = new KritzelAnchorManager(this);
|
|
141
161
|
this._cursorManager = new KritzelCursorManager(this);
|
|
142
162
|
this._themeManager = new KritzelThemeManager(this);
|
|
163
|
+
this._localizationManager = new KritzelLocalizationManager(this);
|
|
164
|
+
this._licenseManager = new KritzelLicenseManager(this);
|
|
143
165
|
this._toolRegistry = new KritzelToolRegistry(this);
|
|
144
166
|
this._assetResolver = new KritzelAssetResolver();
|
|
145
167
|
}
|
|
@@ -175,6 +197,8 @@ export class KritzelCore {
|
|
|
175
197
|
this._editorId = editorId;
|
|
176
198
|
// Re-create theme manager so it picks up the new storage key
|
|
177
199
|
this._themeManager = new KritzelThemeManager(this);
|
|
200
|
+
// Re-create localization manager so it picks up the new storage key
|
|
201
|
+
this._localizationManager = new KritzelLocalizationManager(this);
|
|
178
202
|
}
|
|
179
203
|
/**
|
|
180
204
|
* Initializes the Yjs document for collaborative editing.
|
|
@@ -28,6 +28,28 @@ export class KritzelContextMenuHandler extends KritzelBaseHandler {
|
|
|
28
28
|
this.globalContextMenuItems = globalContextMenuItems;
|
|
29
29
|
this.objectContextMenuItems = objectContextMenuItems;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolves the active context menu items for display, translating each item's
|
|
33
|
+
* `label` through the current locale. When the label is a known
|
|
34
|
+
* {@link KritzelTermKey} the translation is used; any other string is passed
|
|
35
|
+
* through unchanged. Runs at menu-open time so the labels reflect the locale
|
|
36
|
+
* active at that moment.
|
|
37
|
+
* @returns A new array of items with resolved labels.
|
|
38
|
+
*/
|
|
39
|
+
resolveLabels(items) {
|
|
40
|
+
return items.map(item => ({
|
|
41
|
+
...item,
|
|
42
|
+
label: this._core.localizationManager.translate(item.label),
|
|
43
|
+
children: item.children ? this.resolveLabels(item.children) : undefined,
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Gets the active context menu items (object or global) with localized labels.
|
|
48
|
+
*/
|
|
49
|
+
getResolvedContextMenuItems() {
|
|
50
|
+
const items = this._core.store.selectionGroup ? this.objectContextMenuItems : this.globalContextMenuItems;
|
|
51
|
+
return this.resolveLabels(items);
|
|
52
|
+
}
|
|
31
53
|
/**
|
|
32
54
|
* Handles the context menu event (typically triggered by right-click).
|
|
33
55
|
* This method performs the following operations:
|
|
@@ -71,7 +93,7 @@ export class KritzelContextMenuHandler extends KritzelBaseHandler {
|
|
|
71
93
|
this._core.addSelectionGroup(selectionGroup);
|
|
72
94
|
this._core.rerender();
|
|
73
95
|
}
|
|
74
|
-
this._core.store.state.contextMenuItems = this.
|
|
96
|
+
this._core.store.state.contextMenuItems = this.getResolvedContextMenuItems();
|
|
75
97
|
const clickX = event.clientX - this._core.store.offsetX;
|
|
76
98
|
const clickY = event.clientY - this._core.store.offsetY;
|
|
77
99
|
const { translateX, translateY, scale } = this._core.store.state;
|
|
@@ -127,7 +149,7 @@ export class KritzelContextMenuHandler extends KritzelBaseHandler {
|
|
|
127
149
|
this._core.addSelectionGroup(selectionGroup);
|
|
128
150
|
}
|
|
129
151
|
}
|
|
130
|
-
this._core.store.state.contextMenuItems = this.
|
|
152
|
+
this._core.store.state.contextMenuItems = this.getResolvedContextMenuItems();
|
|
131
153
|
this._core.store.state.contextMenuWorldX = x;
|
|
132
154
|
this._core.store.state.contextMenuWorldY = y;
|
|
133
155
|
const { translateX, translateY, scale } = this._core.store.state;
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { KRITZEL_LICENSE_PUBLIC_KEY, KRITZEL_LICENSE_TOKEN_PREFIX } from "../../constants/license.constants";
|
|
2
|
+
/** Minimum delay (ms) between periodic license re-validations. */
|
|
3
|
+
const MIN_REVALIDATION_DELAY_MS = 30_000;
|
|
4
|
+
/** Maximum delay (ms) between periodic license re-validations. */
|
|
5
|
+
const MAX_REVALIDATION_DELAY_MS = 60_000;
|
|
6
|
+
/**
|
|
7
|
+
* Manages license validation state for the Kritzel editor.
|
|
8
|
+
*
|
|
9
|
+
* The manager is owned per {@link KritzelCore} instance (like the theme and
|
|
10
|
+
* localization managers) so that multiple editors on the same page validate
|
|
11
|
+
* independently.
|
|
12
|
+
*
|
|
13
|
+
* A license key is an offline Ed25519 signed token of the form
|
|
14
|
+
* `KRTZL1.<base64url(payload)>.<base64url(signature)>`. The library verifies it
|
|
15
|
+
* against the embedded {@link KRITZEL_LICENSE_PUBLIC_KEY}; only the owner can
|
|
16
|
+
* mint tokens, with the matching private key (see scripts/license/).
|
|
17
|
+
*
|
|
18
|
+
* Responsibilities:
|
|
19
|
+
* - Cheaply reject absent/malformed/expired keys synchronously so the watermark
|
|
20
|
+
* never flashes off for an obviously invalid key.
|
|
21
|
+
* - Verify the signature asynchronously via WebCrypto, then drive a rerender if
|
|
22
|
+
* the licensed state changed so the watermark is re-asserted on the reactive
|
|
23
|
+
* render path.
|
|
24
|
+
* - Periodically re-check on a randomized interval so the check is harder to
|
|
25
|
+
* stub out programmatically than a fixed `setInterval`. Re-checks reuse the
|
|
26
|
+
* cached verified token and only re-evaluate expiry, so crypto is not re-run
|
|
27
|
+
* on an unchanged key every tick.
|
|
28
|
+
*
|
|
29
|
+
* Failure semantics (fail open):
|
|
30
|
+
* - No key provided -> unlicensed (free tier, watermark shown). The normal
|
|
31
|
+
* default, not an error.
|
|
32
|
+
* - Key present but cleanly invalid (malformed, bad signature, expired) ->
|
|
33
|
+
* unlicensed.
|
|
34
|
+
* - Key present but validation throws an *unexpected* internal error, or the
|
|
35
|
+
* runtime lacks Ed25519 support in WebCrypto -> fail open and treat as
|
|
36
|
+
* licensed so a library defect or old browser never breaks a paying
|
|
37
|
+
* customer's app.
|
|
38
|
+
*/
|
|
39
|
+
export class KritzelLicenseManager {
|
|
40
|
+
_core;
|
|
41
|
+
/** The most recently provided license key, re-checked on each periodic tick. */
|
|
42
|
+
_licenseKey;
|
|
43
|
+
/** Cached result of the latest validation. */
|
|
44
|
+
_isLicensed = false;
|
|
45
|
+
/**
|
|
46
|
+
* The token whose signature most recently verified successfully. Lets the
|
|
47
|
+
* periodic re-check skip crypto and only re-evaluate expiry while the key is
|
|
48
|
+
* unchanged.
|
|
49
|
+
*/
|
|
50
|
+
_verifiedToken;
|
|
51
|
+
/**
|
|
52
|
+
* Monotonic id incremented on every {@link validate} call. An in-flight async
|
|
53
|
+
* verification only commits its result if its id still matches, so a stale
|
|
54
|
+
* verification resolving after a newer call can never clobber fresh state.
|
|
55
|
+
*/
|
|
56
|
+
_validationId = 0;
|
|
57
|
+
/** Cached imported public key, lazily created on first signature check. */
|
|
58
|
+
_publicKeyPromise;
|
|
59
|
+
/** Handle for the self-rescheduling re-validation timer. */
|
|
60
|
+
_timer = null;
|
|
61
|
+
/**
|
|
62
|
+
* Creates a new KritzelLicenseManager instance.
|
|
63
|
+
* @param core - The KritzelCore instance this manager belongs to
|
|
64
|
+
*/
|
|
65
|
+
constructor(core) {
|
|
66
|
+
this._core = core;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Whether the editor is currently considered licensed (watermark hidden).
|
|
70
|
+
*/
|
|
71
|
+
get isLicensed() {
|
|
72
|
+
return this._isLicensed;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Validates the given license key.
|
|
76
|
+
*
|
|
77
|
+
* Runs a synchronous structural pre-check first: an absent, malformed, or
|
|
78
|
+
* already-expired key resolves the state immediately (no async work). A
|
|
79
|
+
* structurally valid key then has its signature verified asynchronously; the
|
|
80
|
+
* licensed state is committed (and a rerender triggered) only if it changed.
|
|
81
|
+
*
|
|
82
|
+
* The return value reflects the state known *synchronously* at call time. The
|
|
83
|
+
* authoritative result for a structurally valid key arrives shortly after via
|
|
84
|
+
* the async verification and the reactive rerender.
|
|
85
|
+
*
|
|
86
|
+
* @param key - The license key to validate, or undefined to clear the license
|
|
87
|
+
* @returns The licensed state known synchronously at call time
|
|
88
|
+
*/
|
|
89
|
+
validate(key) {
|
|
90
|
+
this._licenseKey = key;
|
|
91
|
+
const validationId = ++this._validationId;
|
|
92
|
+
let pre;
|
|
93
|
+
try {
|
|
94
|
+
pre = this.preCheck(key);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Fail open: an unexpected internal error in the cheap pre-check must
|
|
98
|
+
// never break a paying customer's app.
|
|
99
|
+
this.commit(true, validationId);
|
|
100
|
+
return this._isLicensed;
|
|
101
|
+
}
|
|
102
|
+
if (pre.status === 'rejected') {
|
|
103
|
+
this._verifiedToken = undefined;
|
|
104
|
+
this.commit(false, validationId);
|
|
105
|
+
return this._isLicensed;
|
|
106
|
+
}
|
|
107
|
+
// Structurally valid and unexpired. If we already verified this exact token,
|
|
108
|
+
// the signature is still good, so license it without re-running crypto.
|
|
109
|
+
if (this._verifiedToken === key) {
|
|
110
|
+
this.commit(true, validationId);
|
|
111
|
+
return this._isLicensed;
|
|
112
|
+
}
|
|
113
|
+
// Otherwise verify the signature asynchronously. Leave the current state
|
|
114
|
+
// untouched until it settles so a forged token cannot even briefly hide the
|
|
115
|
+
// watermark (default state is unlicensed), and a valid renewal does not flap.
|
|
116
|
+
this.verifySignature(pre.payloadSegment, pre.signatureSegment)
|
|
117
|
+
.then(valid => {
|
|
118
|
+
if (validationId !== this._validationId) {
|
|
119
|
+
return; // A newer validate() superseded this one.
|
|
120
|
+
}
|
|
121
|
+
if (valid) {
|
|
122
|
+
this._verifiedToken = key;
|
|
123
|
+
this.commit(true, validationId);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
this._verifiedToken = undefined;
|
|
127
|
+
this.commit(false, validationId);
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
.catch(() => {
|
|
131
|
+
if (validationId !== this._validationId) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// Fail open on unexpected crypto errors / missing Ed25519 support.
|
|
135
|
+
this.commit(true, validationId);
|
|
136
|
+
});
|
|
137
|
+
return this._isLicensed;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Starts periodic re-validation on a randomized interval between
|
|
141
|
+
* {@link MIN_REVALIDATION_DELAY_MS} and {@link MAX_REVALIDATION_DELAY_MS}.
|
|
142
|
+
*
|
|
143
|
+
* Uses a self-rescheduling `setTimeout` (a fresh random delay each cycle)
|
|
144
|
+
* rather than a fixed `setInterval`, making the check fractionally harder to
|
|
145
|
+
* predict and no-op programmatically. Any existing timer is cleared first so
|
|
146
|
+
* the method is idempotent.
|
|
147
|
+
*/
|
|
148
|
+
startPeriodicValidation() {
|
|
149
|
+
this.stopPeriodicValidation();
|
|
150
|
+
this.scheduleNextValidation();
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Stops periodic re-validation and releases the timer.
|
|
154
|
+
*/
|
|
155
|
+
stopPeriodicValidation() {
|
|
156
|
+
if (this._timer !== null) {
|
|
157
|
+
clearTimeout(this._timer);
|
|
158
|
+
this._timer = null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Cleanup hook called when the editor is torn down.
|
|
163
|
+
*/
|
|
164
|
+
destroy() {
|
|
165
|
+
this.stopPeriodicValidation();
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Commits a new licensed state, triggering a rerender only when it changed.
|
|
169
|
+
* The {@link validationId} guard is checked by async callers; synchronous
|
|
170
|
+
* callers pass the current id.
|
|
171
|
+
*/
|
|
172
|
+
commit(nextLicensed, validationId) {
|
|
173
|
+
if (validationId !== this._validationId) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (nextLicensed !== this._isLicensed) {
|
|
177
|
+
this._isLicensed = nextLicensed;
|
|
178
|
+
this._core.rerender();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Schedules the next re-validation tick at a randomized delay.
|
|
183
|
+
*/
|
|
184
|
+
scheduleNextValidation() {
|
|
185
|
+
const delay = this.getRandomRevalidationDelay();
|
|
186
|
+
this._timer = setTimeout(() => {
|
|
187
|
+
this.validate(this._licenseKey);
|
|
188
|
+
this.scheduleNextValidation();
|
|
189
|
+
}, delay);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Returns a random delay within the configured re-validation window.
|
|
193
|
+
*/
|
|
194
|
+
getRandomRevalidationDelay() {
|
|
195
|
+
const span = MAX_REVALIDATION_DELAY_MS - MIN_REVALIDATION_DELAY_MS;
|
|
196
|
+
return MIN_REVALIDATION_DELAY_MS + Math.floor(Math.random() * (span + 1));
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Synchronous structural pre-check of a license key: verifies the format
|
|
200
|
+
* prefix, three-part structure, JSON payload, and (if present) that the token
|
|
201
|
+
* has not expired. Does not verify the signature.
|
|
202
|
+
*
|
|
203
|
+
* @returns `rejected` for absent/malformed/expired keys, or `pass` with the
|
|
204
|
+
* parsed segments and claims for a structurally valid, unexpired token.
|
|
205
|
+
*/
|
|
206
|
+
preCheck(key) {
|
|
207
|
+
if (key === undefined || key === null) {
|
|
208
|
+
return { status: 'rejected' };
|
|
209
|
+
}
|
|
210
|
+
const token = key.trim();
|
|
211
|
+
if (token.length === 0 || !token.startsWith(KRITZEL_LICENSE_TOKEN_PREFIX)) {
|
|
212
|
+
return { status: 'rejected' };
|
|
213
|
+
}
|
|
214
|
+
const body = token.slice(KRITZEL_LICENSE_TOKEN_PREFIX.length);
|
|
215
|
+
const parts = body.split('.');
|
|
216
|
+
if (parts.length !== 2 || parts[0].length === 0 || parts[1].length === 0) {
|
|
217
|
+
return { status: 'rejected' };
|
|
218
|
+
}
|
|
219
|
+
const [payloadSegment, signatureSegment] = parts;
|
|
220
|
+
let claims;
|
|
221
|
+
try {
|
|
222
|
+
claims = JSON.parse(this.base64UrlToString(payloadSegment));
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return { status: 'rejected' };
|
|
226
|
+
}
|
|
227
|
+
if (claims === null || typeof claims !== 'object') {
|
|
228
|
+
return { status: 'rejected' };
|
|
229
|
+
}
|
|
230
|
+
if (typeof claims.exp === 'number' && claims.exp * 1000 <= Date.now()) {
|
|
231
|
+
return { status: 'rejected' }; // Cleanly expired.
|
|
232
|
+
}
|
|
233
|
+
return { status: 'pass', payloadSegment, signatureSegment, claims };
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Verifies the Ed25519 signature of the token against the embedded public
|
|
237
|
+
* key. Resolves true/false for a definitive valid/invalid signature.
|
|
238
|
+
*
|
|
239
|
+
* Rejects (rather than resolving false) on unexpected crypto failures or when
|
|
240
|
+
* the runtime lacks Ed25519 support, so the caller fails open.
|
|
241
|
+
*/
|
|
242
|
+
async verifySignature(payloadSegment, signatureSegment) {
|
|
243
|
+
const publicKey = await this.getPublicKey();
|
|
244
|
+
const data = this.utf8Bytes(payloadSegment);
|
|
245
|
+
const signature = this.base64UrlToBytes(signatureSegment);
|
|
246
|
+
return crypto.subtle.verify('Ed25519', publicKey, signature, data);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Imports and caches the embedded Ed25519 public key for signature checks.
|
|
250
|
+
*/
|
|
251
|
+
getPublicKey() {
|
|
252
|
+
if (!this._publicKeyPromise) {
|
|
253
|
+
const raw = this.base64UrlToBytes(KRITZEL_LICENSE_PUBLIC_KEY);
|
|
254
|
+
this._publicKeyPromise = Promise.resolve().then(() => crypto.subtle.importKey('raw', raw, { name: 'Ed25519' }, false, ['verify']));
|
|
255
|
+
// If import fails (e.g. no Ed25519 support), drop the cache so a later
|
|
256
|
+
// tick can retry, and let the rejection propagate to fail open.
|
|
257
|
+
this._publicKeyPromise.catch(() => {
|
|
258
|
+
this._publicKeyPromise = undefined;
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
return this._publicKeyPromise;
|
|
262
|
+
}
|
|
263
|
+
/** Decodes a base64url string to its UTF-8 text. */
|
|
264
|
+
base64UrlToString(value) {
|
|
265
|
+
return new TextDecoder().decode(this.base64UrlToBytes(value));
|
|
266
|
+
}
|
|
267
|
+
/** Decodes a base64url string to raw bytes. */
|
|
268
|
+
base64UrlToBytes(value) {
|
|
269
|
+
const base64 = value.replace(/-/g, '+').replace(/_/g, '/');
|
|
270
|
+
const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), '=');
|
|
271
|
+
const binary = atob(padded);
|
|
272
|
+
const bytes = new Uint8Array(new ArrayBuffer(binary.length));
|
|
273
|
+
for (let i = 0; i < binary.length; i++) {
|
|
274
|
+
bytes[i] = binary.charCodeAt(i);
|
|
275
|
+
}
|
|
276
|
+
return bytes;
|
|
277
|
+
}
|
|
278
|
+
/** Encodes a string to its UTF-8 bytes. */
|
|
279
|
+
utf8Bytes(value) {
|
|
280
|
+
const encoded = new TextEncoder().encode(value);
|
|
281
|
+
const bytes = new Uint8Array(new ArrayBuffer(encoded.length));
|
|
282
|
+
bytes.set(encoded);
|
|
283
|
+
return bytes;
|
|
284
|
+
}
|
|
285
|
+
}
|