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/{kritzel-active-users_42.cjs.entry.js → kritzel-active-users_44.cjs.entry.js}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var index = require('./index-Xav9JFHg.js');
|
|
4
|
-
var schema_constants = require('./schema.constants-
|
|
4
|
+
var schema_constants = require('./schema.constants-DrHO_CYF.js');
|
|
5
5
|
var Y = require('yjs');
|
|
6
6
|
require('y-indexeddb');
|
|
7
7
|
require('y-websocket');
|
|
@@ -154,16 +154,16 @@ const KritzelAvatar = class {
|
|
|
154
154
|
height: `${this.size}px`,
|
|
155
155
|
fontSize: `${Math.round(this.size * 0.4)}px`,
|
|
156
156
|
};
|
|
157
|
-
return (index.h(index.Host, { key: '
|
|
157
|
+
return (index.h(index.Host, { key: '0d372a5443f41835c2e8e5b33b58bcb6c1292e89', style: containerStyles, class: {
|
|
158
158
|
'has-image': !!showImage,
|
|
159
159
|
'has-initials': !!showInitials,
|
|
160
160
|
'has-default': !!showDefaultIcon,
|
|
161
|
-
}, role: "img", "aria-label": this.getDisplayName() || 'User avatar' }, showImage && (index.h("img", { key: '
|
|
161
|
+
}, role: "img", "aria-label": this.getDisplayName() || 'User avatar' }, showImage && (index.h("img", { key: 'deb5f12115dd28b4b4ab2157cb2bbc9e48bb2a3f', src: imageUrl, alt: "", class: "avatar-image", ref: (el) => {
|
|
162
162
|
if (el) {
|
|
163
163
|
el.referrerPolicy = 'no-referrer';
|
|
164
164
|
el.crossOrigin = 'anonymous';
|
|
165
165
|
}
|
|
166
|
-
}, onError: this.handleImageError })), showInitials && (index.h("span", { key: '
|
|
166
|
+
}, onError: this.handleImageError })), showInitials && (index.h("span", { key: '6fc12f2d32923f33df5a8ec743d51434f67e6934', class: "avatar-initials", style: { backgroundColor: this.getBackgroundColor() } }, initials)), showDefaultIcon && (index.h("span", { key: 'd803b385f7eaa0659d7452231bfd46b1634f204d', class: "avatar-default" }, index.h("svg", { key: 'a3275ab33f58440abcd15c296d9c027dfab6495c', viewBox: "0 0 24 24", fill: "currentColor" }, index.h("path", { key: '31ac7e63fe6b1778c3d0cbd71b5c85791b79d084', d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" }))))));
|
|
167
167
|
}
|
|
168
168
|
static get watchers() { return {
|
|
169
169
|
"user": [{
|
|
@@ -473,7 +473,7 @@ const KritzelBackToContent = class {
|
|
|
473
473
|
this.backToContent.emit();
|
|
474
474
|
};
|
|
475
475
|
render() {
|
|
476
|
-
return (index.h(index.Host, { key: '
|
|
476
|
+
return (index.h(index.Host, { key: '5ef034156f28bdd1861d99343d51a237498db46b' }, index.h("button", { key: 'caa1c08d04f1a3a84d694b7df5d318a686d3a1fb', class: { 'back-to-content-button': true, visible: this.visible }, onClick: this.handleClick, "aria-label": this.text }, index.h("kritzel-icon", { key: '0c7cf5e18294ade600be3052ca7c57c8d933a736', name: "chevrons-left" }))));
|
|
477
477
|
}
|
|
478
478
|
};
|
|
479
479
|
KritzelBackToContent.style = kritzelBackToContentCss();
|
|
@@ -500,11 +500,11 @@ const KritzelButton = class {
|
|
|
500
500
|
this.buttonClick.emit();
|
|
501
501
|
};
|
|
502
502
|
render() {
|
|
503
|
-
return (index.h(index.Host, { key: '
|
|
503
|
+
return (index.h(index.Host, { key: 'aa366907b97e648ac73182a43d099baf457e0ba3' }, index.h("button", { key: 'e80875396a791606461b1a20e0f7e1c896f54073', type: this.type, class: {
|
|
504
504
|
'kritzel-button': true,
|
|
505
505
|
[this.variant]: true,
|
|
506
506
|
'disabled': this.disabled,
|
|
507
|
-
}, disabled: this.disabled, onClick: this.handleClick }, index.h("slot", { key: '
|
|
507
|
+
}, disabled: this.disabled, onClick: this.handleClick }, index.h("slot", { key: '8f4e57a73837adfbf91f678c54558fe4c737aa91' }))));
|
|
508
508
|
}
|
|
509
509
|
};
|
|
510
510
|
KritzelButton.style = kritzelButtonCss();
|
|
@@ -552,13 +552,13 @@ const KritzelColorComponent = class {
|
|
|
552
552
|
render() {
|
|
553
553
|
const resolvedColor = this.resolveColor();
|
|
554
554
|
const isColorVeryLight = this.isLightColor(resolvedColor);
|
|
555
|
-
return (index.h(index.Host, { key: '
|
|
555
|
+
return (index.h(index.Host, { key: '21ce0ecb616266ec4953468ae9bbe0b72259c2da' }, index.h("div", { key: '02c8e8684b3b0819755efd1f160bdee662428ddd', class: "checkerboard-bg", style: {
|
|
556
556
|
width: `${this.size}px`,
|
|
557
557
|
height: `${this.size}px`,
|
|
558
558
|
borderRadius: '50%',
|
|
559
559
|
display: 'inline-block',
|
|
560
560
|
position: 'relative',
|
|
561
|
-
} }, index.h("div", { key: '
|
|
561
|
+
} }, index.h("div", { key: '0063e9a701994869adbd3022b5ace542e85dfd95', class: {
|
|
562
562
|
'color-circle': true,
|
|
563
563
|
'white': isColorVeryLight,
|
|
564
564
|
}, style: {
|
|
@@ -614,7 +614,7 @@ const KritzelColorPalette = class {
|
|
|
614
614
|
render() {
|
|
615
615
|
const displayedColors = this.isExpanded ? this.colors : this.colors.slice(0, 6);
|
|
616
616
|
const expandedHeight = this.isExpanded ? this.calculateHeight() : '32px';
|
|
617
|
-
return (index.h(index.Host, { key: '
|
|
617
|
+
return (index.h(index.Host, { key: '9910a765816f45d420ad27c8fc7b02811380783b' }, index.h("div", { key: '91f3dae04338f55ab21831e4cac65f9d855c58c6', class: {
|
|
618
618
|
'color-grid': true,
|
|
619
619
|
'expanded': this.isExpanded,
|
|
620
620
|
}, style: {
|
|
@@ -961,6 +961,8 @@ const KritzelControls = class {
|
|
|
961
961
|
isUtilityPanelVisible = true;
|
|
962
962
|
undoState = null;
|
|
963
963
|
theme = 'light';
|
|
964
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
965
|
+
terms = {};
|
|
964
966
|
isControlsReady;
|
|
965
967
|
firstConfig = null;
|
|
966
968
|
isTouchDevice = schema_constants.KritzelDevicesHelper.isTouchDevice();
|
|
@@ -1180,13 +1182,13 @@ const KritzelControls = class {
|
|
|
1180
1182
|
// Separate tool controls from config control
|
|
1181
1183
|
const toolControls = this.internalControls.filter(c => c.type === 'tool' || c.type === 'separator');
|
|
1182
1184
|
const configControl = this.internalControls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
|
|
1183
|
-
return (index.h(index.Host, { key: '
|
|
1185
|
+
return (index.h(index.Host, { key: '7247a377d1cb75153e35f5308e81b2bd00d98578', style: { display: this.visible ? '' : 'none' }, class: {
|
|
1184
1186
|
mobile: this.isTouchDevice,
|
|
1185
|
-
} }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '
|
|
1187
|
+
} }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '075577cd15f3e577a1a216b5b1f1874e82e0d123', style: {
|
|
1186
1188
|
position: 'absolute',
|
|
1187
1189
|
bottom: '56px',
|
|
1188
1190
|
left: '12px',
|
|
1189
|
-
}, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '
|
|
1191
|
+
}, undoState: this.undoState, terms: this.terms, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '7fb1041763c7b64917e337d68bbb29b36ed86b9a', class: "kritzel-controls" }, index.h("div", { key: '8577ed9c6f43a667aaba7dce1da519456c8ad210', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), index.h("div", { key: '42f8f2b85055705674f9e319056bd48856dbd197', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
|
|
1190
1192
|
// Check if this control has sub-options (split-button)
|
|
1191
1193
|
if (control.subOptions?.length) {
|
|
1192
1194
|
const selectedSubOption = this.getSelectedSubOption(control);
|
|
@@ -1216,10 +1218,10 @@ const KritzelControls = class {
|
|
|
1216
1218
|
'kritzel-control': true,
|
|
1217
1219
|
'selected': this.activeControl?.name === control?.name,
|
|
1218
1220
|
}, key: control.name, "data-testid": `tool-${control.name}`, onClick: _event => this.handleControlClick?.(control), "aria-label": control.name.charAt(0).toUpperCase() + control.name.slice(1) }, index.h("kritzel-icon", { name: control.icon })));
|
|
1219
|
-
})), index.h("div", { key: '
|
|
1221
|
+
})), index.h("div", { key: '20007273e0f701193502320cf58099cbaedb834e', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (index.h("div", { class: {
|
|
1220
1222
|
'kritzel-config-container': true,
|
|
1221
1223
|
'visible': hasConfigUI,
|
|
1222
|
-
}, key: configControl.name }, index.h("div", { key: '
|
|
1224
|
+
}, key: configControl.name }, index.h("div", { key: '2901fc2507e5b02fbd603bd2d2a4e2b07e35c970', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), index.h("kritzel-tooltip", { key: '653e6a9b49146a2f297dbb5b9debe8709efd59ad', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, index.h("kritzel-tool-config", { key: '6fae38444dff1978647e111643ee6e29c9cc1653', tool: this.activeControl.tool, theme: this.theme, engine: this.kritzelEngine, terms: this.terms, onToolChange: event => this.handleToolChange?.(event), onDisplayValuesChange: this.handleDisplayValuesChange, style: { width: '100%', height: '100%' } })), index.h("div", { key: '951a52f625c929634de5102b83a14ad0cf1abc8d', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
|
|
1223
1225
|
if (el)
|
|
1224
1226
|
this.configTriggerRef = el;
|
|
1225
1227
|
}, onKeyDown: event => {
|
|
@@ -1228,7 +1230,7 @@ const KritzelControls = class {
|
|
|
1228
1230
|
}
|
|
1229
1231
|
}, style: {
|
|
1230
1232
|
cursor: 'pointer',
|
|
1231
|
-
} }, this.displayValues && (index.h("div", { key: '
|
|
1233
|
+
} }, this.displayValues && (index.h("div", { key: 'b8fff73b9055e86b312a9f0798fff4177cf85970', class: "color-container" }, index.h("kritzel-color", { key: 'fcd474e557d887f94383b7e583ab1c95a675ce23', value: this.displayValues.color, theme: this.theme, size: 18, style: {
|
|
1232
1234
|
borderRadius: '50%',
|
|
1233
1235
|
border: 'none',
|
|
1234
1236
|
} })))))))));
|
|
@@ -1260,13 +1262,15 @@ const KritzelCurrentUser = class {
|
|
|
1260
1262
|
* Avatar size in pixels
|
|
1261
1263
|
*/
|
|
1262
1264
|
avatarSize = 40;
|
|
1265
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
1266
|
+
terms = {};
|
|
1263
1267
|
dialogRef;
|
|
1264
1268
|
handleAvatarClick = (event) => {
|
|
1265
1269
|
event.stopPropagation();
|
|
1266
1270
|
this.dialogRef?.open();
|
|
1267
1271
|
};
|
|
1268
1272
|
render() {
|
|
1269
|
-
return (index.h(index.Host, { key: '
|
|
1273
|
+
return (index.h(index.Host, { key: '7e45048e532db84347e2531de2df19f5537d62ca' }, index.h("kritzel-avatar", { key: '5a67d1dbae041e16cdaeaf4bc678b6b00c56f442', user: this.user, size: this.avatarSize, onClick: this.handleAvatarClick }), index.h("kritzel-current-user-dialog", { key: '8e35219e282811b8bbafb058c02c8c0474574009', ref: el => (this.dialogRef = el), user: this.user, terms: this.terms })));
|
|
1270
1274
|
}
|
|
1271
1275
|
};
|
|
1272
1276
|
KritzelCurrentUser.style = kritzelCurrentUserCss();
|
|
@@ -1279,6 +1283,8 @@ const KritzelCurrentUserDialog = class {
|
|
|
1279
1283
|
}
|
|
1280
1284
|
get host() { return index.getElement(this); }
|
|
1281
1285
|
user;
|
|
1286
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
1287
|
+
terms = {};
|
|
1282
1288
|
isDialogOpen = false;
|
|
1283
1289
|
async open() {
|
|
1284
1290
|
this.isDialogOpen = true;
|
|
@@ -1298,7 +1304,7 @@ const KritzelCurrentUserDialog = class {
|
|
|
1298
1304
|
}
|
|
1299
1305
|
render() {
|
|
1300
1306
|
const displayName = this.getDisplayName();
|
|
1301
|
-
return (index.h(index.Host, { key: '
|
|
1307
|
+
return (index.h(index.Host, { key: '7c9e5c19249d400e2d670c60f5d6716c742adc62' }, index.h("kritzel-dialog", { key: '811da6bff0ce03914f545dd289878ba04924e85c', dialogTitle: this.terms['currentUser.dialogTitle'] ?? 'Account', isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, size: "small", contained: true }, index.h("div", { key: '03a101b04d61882732547d91e81a2bacb3aa4df8', class: "user-info" }, index.h("kritzel-avatar", { key: '4033d0e2322d7a25231f01115ec33f20e4fb0d4c', user: this.user, size: 80 }), displayName && index.h("div", { key: 'cf3a3aecb84152736c9de119f82a79f1b2b32f6f', class: "user-name" }, displayName), this.user?.email && index.h("div", { key: '5725d71dd80468c64a2b0bb1d9d967232513fb63', class: "user-email" }, this.user.email)))));
|
|
1302
1308
|
}
|
|
1303
1309
|
};
|
|
1304
1310
|
KritzelCurrentUserDialog.style = kritzelCurrentUserDialogCss();
|
|
@@ -2177,6 +2183,8 @@ const DEFAULT_SHAPE_CONFIG = {
|
|
|
2177
2183
|
|
|
2178
2184
|
const ABSOLUTE_SCALE_MAX = 1000;
|
|
2179
2185
|
const ABSOLUTE_SCALE_MIN = 0.0001;
|
|
2186
|
+
/** Destination opened when the "Powered by Kritzel" watermark is clicked. */
|
|
2187
|
+
const KRITZEL_WEBSITE_URL = 'https://kritzel.io';
|
|
2180
2188
|
|
|
2181
2189
|
/**
|
|
2182
2190
|
* Default sync configuration - None
|
|
@@ -2185,7 +2193,7 @@ const DEFAULT_SYNC_CONFIG = {
|
|
|
2185
2193
|
providers: [],
|
|
2186
2194
|
};
|
|
2187
2195
|
|
|
2188
|
-
const kritzelEditorCss = () => `kritzel-editor{display:flex;margin:0;position:relative;overflow:hidden;width:100%;height:100%;align-items:center;justify-content:center;touch-action:manipulation;user-select:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:start;line-height:normal}kritzel-controls{position:absolute;left:0;right:0;margin-inline:auto;width:max-content;max-width:calc(100% - 16px);bottom:var(--kritzel-editor-controls-bottom, 14px);transition:transform var(--kritzel-editor-controls-transition-duration, 0.1s) var(--kritzel-editor-controls-transition, ease-in-out)}kritzel-controls.keyboard-open{transform:var(--kritzel-editor-controls-transform, translateY(300%))}.top-left-buttons{position:absolute;top:var(--kritzel-editor-top-left-buttons-top, 14px);left:var(--kritzel-editor-top-left-buttons-left, 14px);display:flex;align-items:flex-start;gap:8px}.top-right-buttons{position:absolute;top:var(--kritzel-editor-top-right-buttons-top, 14px);right:var(--kritzel-editor-top-right-buttons-right, 14px);display:flex;align-items:center;gap:8px}.top-right-button{display:flex;align-items:center;justify-content:center;width:50px;height:50px;padding:0;border:var(--kritzel-split-button-border, 1px solid #ebebeb);border-radius:var(--kritzel-split-button-border-radius, 12px);background-color:var(--kritzel-split-button-background-color, #ffffff);cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:var(--kritzel-split-button-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent}.top-right-button:hover{background-color:#f5f5f5}.top-right-button:active{background-color:#ebebeb}`;
|
|
2196
|
+
const kritzelEditorCss = () => `kritzel-editor{display:flex;margin:0;position:relative;container-type:inline-size;overflow:hidden;width:100%;height:100%;align-items:center;justify-content:center;touch-action:manipulation;user-select:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:start;line-height:normal}kritzel-controls{position:absolute;left:0;right:0;margin-inline:auto;width:max-content;max-width:calc(100% - 16px);bottom:var(--kritzel-editor-controls-bottom, 14px);transition:transform var(--kritzel-editor-controls-transition-duration, 0.1s) var(--kritzel-editor-controls-transition, ease-in-out)}kritzel-controls.keyboard-open{transform:var(--kritzel-editor-controls-transform, translateY(300%))}.top-left-buttons{position:absolute;top:var(--kritzel-editor-top-left-buttons-top, 14px);left:var(--kritzel-editor-top-left-buttons-left, 14px);display:flex;align-items:flex-start;gap:8px}.top-right-buttons{position:absolute;top:var(--kritzel-editor-top-right-buttons-top, 14px);right:var(--kritzel-editor-top-right-buttons-right, 14px);display:flex;align-items:center;gap:8px}.bottom-left-buttons{position:absolute;left:var(--kritzel-editor-top-left-buttons-left, 14px);bottom:var(--kritzel-editor-controls-bottom, 14px);display:flex;align-items:flex-end}@container (max-width: 767px){.bottom-left-buttons{display:none}}.top-right-button{display:flex;align-items:center;justify-content:center;width:50px;height:50px;padding:0;border:var(--kritzel-split-button-border, 1px solid #ebebeb);border-radius:var(--kritzel-split-button-border-radius, 12px);background-color:var(--kritzel-split-button-background-color, #ffffff);cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:var(--kritzel-split-button-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent}.top-right-button:hover{background-color:#f5f5f5}.top-right-button:active{background-color:#ebebeb}`;
|
|
2189
2197
|
|
|
2190
2198
|
const KritzelEditor = class {
|
|
2191
2199
|
constructor(hostRef) {
|
|
@@ -2198,6 +2206,7 @@ const KritzelEditor = class {
|
|
|
2198
2206
|
this.objectsUpdated = index.createEvent(this, "objectsUpdated");
|
|
2199
2207
|
this.undoStateChange = index.createEvent(this, "undoStateChange");
|
|
2200
2208
|
this.themeChange = index.createEvent(this, "themeChange");
|
|
2209
|
+
this.localeChange = index.createEvent(this, "localeChange");
|
|
2201
2210
|
this.viewportChange = index.createEvent(this, "viewportChange");
|
|
2202
2211
|
this.logout = index.createEvent(this, "logout");
|
|
2203
2212
|
this.login = index.createEvent(this, "login");
|
|
@@ -2212,7 +2221,6 @@ const KritzelEditor = class {
|
|
|
2212
2221
|
viewportBoundaryRight = Infinity;
|
|
2213
2222
|
viewportBoundaryTop = -Infinity;
|
|
2214
2223
|
viewportBoundaryBottom = Infinity;
|
|
2215
|
-
wheelEnabled = true;
|
|
2216
2224
|
debugInfo = {
|
|
2217
2225
|
showViewportInfo: false,
|
|
2218
2226
|
showObjectInfo: false,
|
|
@@ -2281,66 +2289,66 @@ const KritzelEditor = class {
|
|
|
2281
2289
|
];
|
|
2282
2290
|
globalContextMenuItems = [
|
|
2283
2291
|
{
|
|
2284
|
-
label: '
|
|
2292
|
+
label: 'menu.paste',
|
|
2285
2293
|
icon: 'paste',
|
|
2286
2294
|
disabled: async () => (await this.engineRef.getCopiedObjects()).length === 0,
|
|
2287
2295
|
action: menu => this.engineRef.paste(menu.x, menu.y),
|
|
2288
2296
|
},
|
|
2289
2297
|
{
|
|
2290
|
-
label: '
|
|
2298
|
+
label: 'menu.selectAll',
|
|
2291
2299
|
icon: 'select-all',
|
|
2292
2300
|
disabled: async () => (await this.engineRef.getObjectsInViewport()).length === 0,
|
|
2293
2301
|
action: () => this.selectAllObjectsInViewport(),
|
|
2294
2302
|
},
|
|
2295
2303
|
];
|
|
2296
2304
|
objectContextMenuItems = [
|
|
2297
|
-
{ label: '
|
|
2298
|
-
{ label: '
|
|
2305
|
+
{ label: 'menu.copy', icon: 'copy', group: 'clipboard', action: () => this.engineRef.copy() },
|
|
2306
|
+
{ label: 'menu.cut', icon: 'cut', group: 'clipboard', action: () => this.engineRef.cut() },
|
|
2299
2307
|
{
|
|
2300
|
-
label: '
|
|
2308
|
+
label: 'menu.paste',
|
|
2301
2309
|
icon: 'paste',
|
|
2302
2310
|
group: 'clipboard',
|
|
2303
2311
|
disabled: async () => (await this.engineRef.getCopiedObjects()).length === 0,
|
|
2304
2312
|
action: (menu, _) => this.engineRef.paste(menu.x, menu.y),
|
|
2305
2313
|
},
|
|
2306
2314
|
{
|
|
2307
|
-
label: '
|
|
2315
|
+
label: 'menu.order',
|
|
2308
2316
|
icon: 'ordering',
|
|
2309
2317
|
group: 'other',
|
|
2310
2318
|
children: [
|
|
2311
|
-
{ label: '
|
|
2312
|
-
{ label: '
|
|
2313
|
-
{ label: '
|
|
2314
|
-
{ label: '
|
|
2319
|
+
{ label: 'menu.bringToFront', icon: 'bring-to-front', action: () => this.engineRef.bringToFront() },
|
|
2320
|
+
{ label: 'menu.sendToBack', icon: 'send-to-back', action: () => this.engineRef.sendToBack() },
|
|
2321
|
+
{ label: 'menu.moveUp', icon: 'arrow-up-from-dot', action: () => this.engineRef.bringForward() },
|
|
2322
|
+
{ label: 'menu.moveDown', icon: 'arrow-down-from-dot', action: () => this.engineRef.sendBackward() },
|
|
2315
2323
|
],
|
|
2316
2324
|
},
|
|
2317
2325
|
{
|
|
2318
|
-
label: '
|
|
2326
|
+
label: 'menu.align',
|
|
2319
2327
|
icon: 'align',
|
|
2320
2328
|
group: 'other',
|
|
2321
2329
|
disabled: async () => (await this.engineRef.getSelectedObjects()).length < 2,
|
|
2322
2330
|
children: [
|
|
2323
|
-
{ label: '
|
|
2324
|
-
{ label: '
|
|
2325
|
-
{ label: '
|
|
2326
|
-
{ label: '
|
|
2327
|
-
{ label: '
|
|
2328
|
-
{ label: '
|
|
2331
|
+
{ label: 'menu.alignLeft', icon: 'align-start-vertical', action: () => this.engineRef.alignObjects(schema_constants.KritzelAlignment.StartHorizontal) },
|
|
2332
|
+
{ label: 'menu.alignCenterHorizontal', icon: 'align-center-horizontal', action: () => this.engineRef.alignObjects(schema_constants.KritzelAlignment.CenterHorizontal) },
|
|
2333
|
+
{ label: 'menu.alignRight', icon: 'align-end-vertical', action: () => this.engineRef.alignObjects(schema_constants.KritzelAlignment.EndHorizontal) },
|
|
2334
|
+
{ label: 'menu.alignTop', icon: 'align-start-horizontal', action: () => this.engineRef.alignObjects(schema_constants.KritzelAlignment.StartVertical) },
|
|
2335
|
+
{ label: 'menu.alignCenterVertical', icon: 'align-center-vertical', action: () => this.engineRef.alignObjects(schema_constants.KritzelAlignment.CenterVertical) },
|
|
2336
|
+
{ label: 'menu.alignBottom', icon: 'align-end-horizontal', action: () => this.engineRef.alignObjects(schema_constants.KritzelAlignment.EndVertical) },
|
|
2329
2337
|
],
|
|
2330
2338
|
},
|
|
2331
2339
|
{
|
|
2332
|
-
label: '
|
|
2340
|
+
label: 'menu.group',
|
|
2333
2341
|
icon: 'group',
|
|
2334
2342
|
group: 'other',
|
|
2335
2343
|
children: [
|
|
2336
2344
|
{
|
|
2337
|
-
label: '
|
|
2345
|
+
label: 'menu.group',
|
|
2338
2346
|
icon: 'group',
|
|
2339
2347
|
disabled: async () => (await this.engineRef.getSelectedObjects()).length < 2,
|
|
2340
2348
|
action: () => this.engineRef.group(),
|
|
2341
2349
|
},
|
|
2342
2350
|
{
|
|
2343
|
-
label: '
|
|
2351
|
+
label: 'menu.ungroup',
|
|
2344
2352
|
icon: 'ungroup',
|
|
2345
2353
|
disabled: async () => {
|
|
2346
2354
|
const selectedObjects = await this.engineRef.getSelectedObjects();
|
|
@@ -2351,23 +2359,34 @@ const KritzelEditor = class {
|
|
|
2351
2359
|
],
|
|
2352
2360
|
},
|
|
2353
2361
|
{
|
|
2354
|
-
label: '
|
|
2362
|
+
label: 'menu.export',
|
|
2355
2363
|
icon: 'download',
|
|
2356
2364
|
group: 'export',
|
|
2357
2365
|
children: [
|
|
2358
|
-
{ label: '
|
|
2359
|
-
{ label: '
|
|
2366
|
+
{ label: 'menu.exportAsSvg', icon: 'download', action: () => this.engineRef.exportSelectedObjectsAsSvg() },
|
|
2367
|
+
{ label: 'menu.exportAsPng', icon: 'download', action: () => this.engineRef.exportSelectedObjectsAsPng() },
|
|
2360
2368
|
],
|
|
2361
2369
|
},
|
|
2362
|
-
{ label: '
|
|
2370
|
+
{ label: 'menu.delete', icon: 'delete', group: 'edit', action: () => this.engineRef.delete() },
|
|
2363
2371
|
];
|
|
2364
2372
|
themes;
|
|
2365
2373
|
theme = 'light';
|
|
2374
|
+
/** License key that, when valid, removes the "Powered by Kritzel" watermark. */
|
|
2375
|
+
licenseKey;
|
|
2376
|
+
/** The current locale (language) code applied to the editor, e.g. 'en', 'de', 'fr'. */
|
|
2377
|
+
locale = 'en';
|
|
2378
|
+
/** An array of available locale definitions (with optional partial term overrides). */
|
|
2379
|
+
locales;
|
|
2380
|
+
/** The locale used to resolve terms missing from the active locale. */
|
|
2381
|
+
fallbackLocale = 'en';
|
|
2366
2382
|
customSvgIcons = {};
|
|
2383
|
+
isPanningEnabled = true;
|
|
2384
|
+
isZoomingEnabled = true;
|
|
2367
2385
|
isControlsVisible = true;
|
|
2368
2386
|
isUtilityPanelVisible = true;
|
|
2369
2387
|
isWorkspaceManagerVisible = true;
|
|
2370
2388
|
isMoreMenuVisible = true;
|
|
2389
|
+
isZoomPanelVisible = true;
|
|
2371
2390
|
isObjectDistanceFadingActive = false;
|
|
2372
2391
|
syncConfig = DEFAULT_SYNC_CONFIG;
|
|
2373
2392
|
assetStorageConfig = schema_constants.DEFAULT_ASSET_STORAGE_CONFIG;
|
|
@@ -2389,6 +2408,7 @@ const KritzelEditor = class {
|
|
|
2389
2408
|
objectsUpdated;
|
|
2390
2409
|
undoStateChange;
|
|
2391
2410
|
themeChange;
|
|
2411
|
+
localeChange;
|
|
2392
2412
|
viewportChange;
|
|
2393
2413
|
logout;
|
|
2394
2414
|
login;
|
|
@@ -2402,6 +2422,11 @@ const KritzelEditor = class {
|
|
|
2402
2422
|
isVirtualKeyboardOpen = false;
|
|
2403
2423
|
undoState = null;
|
|
2404
2424
|
isBackToContentButtonVisible = false;
|
|
2425
|
+
/** Localized strings for editor-owned UI (e.g. the more menu), resolved from the active locale. */
|
|
2426
|
+
resolvedTerms = {};
|
|
2427
|
+
/** Available locales as `{ code, label }` options for the settings language selector. */
|
|
2428
|
+
availableLocaleOptions = [];
|
|
2429
|
+
currentZoomPercent = 100;
|
|
2405
2430
|
shortcuts = [];
|
|
2406
2431
|
currentIsPublic = false;
|
|
2407
2432
|
isEditorVisible = false;
|
|
@@ -2465,6 +2490,25 @@ const KritzelEditor = class {
|
|
|
2465
2490
|
onThemesChange() {
|
|
2466
2491
|
this.applyTheme();
|
|
2467
2492
|
}
|
|
2493
|
+
onLocaleChange(newValue) {
|
|
2494
|
+
if (this.engineRef) {
|
|
2495
|
+
this.engineRef.setLocale(newValue);
|
|
2496
|
+
this.engineRef.saveSettings(this.currentSettingsConfig);
|
|
2497
|
+
void this.refreshLocalizedTerms();
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
/**
|
|
2501
|
+
* Refreshes the editor-owned localized strings (e.g. the more menu and the
|
|
2502
|
+
* strings forwarded to child UI components) from the engine's localization
|
|
2503
|
+
* manager for the active locale.
|
|
2504
|
+
*/
|
|
2505
|
+
async refreshLocalizedTerms() {
|
|
2506
|
+
if (!this.engineRef) {
|
|
2507
|
+
return;
|
|
2508
|
+
}
|
|
2509
|
+
this.resolvedTerms = await this.engineRef.getResolvedTerms();
|
|
2510
|
+
this.availableLocaleOptions = await this.engineRef.getAvailableLocaleOptions();
|
|
2511
|
+
}
|
|
2468
2512
|
onTouchStart(event) {
|
|
2469
2513
|
if (event.cancelable) {
|
|
2470
2514
|
event.preventDefault();
|
|
@@ -2723,6 +2767,9 @@ const KritzelEditor = class {
|
|
|
2723
2767
|
this.activeWorkspace = event.detail.activeWorkspace;
|
|
2724
2768
|
this.workspaces = event.detail.workspaces;
|
|
2725
2769
|
this.currentIsPublic = await this.engineRef.getIsPublic();
|
|
2770
|
+
await this.refreshLocalizedTerms();
|
|
2771
|
+
const viewport = await this.engineRef.getViewport();
|
|
2772
|
+
this.currentZoomPercent = this.getZoomPercentFromScale(viewport.scale);
|
|
2726
2773
|
this.loadShortcuts();
|
|
2727
2774
|
}
|
|
2728
2775
|
handleWorkspacesChange(event) {
|
|
@@ -2773,8 +2820,15 @@ const KritzelEditor = class {
|
|
|
2773
2820
|
}
|
|
2774
2821
|
handleViewportChange(event) {
|
|
2775
2822
|
event.stopPropagation();
|
|
2823
|
+
this.currentZoomPercent = this.getZoomPercentFromScale(event.detail.scale);
|
|
2776
2824
|
this.viewportChange.emit(event.detail);
|
|
2777
2825
|
}
|
|
2826
|
+
getZoomPercentFromScale(scale) {
|
|
2827
|
+
if (!Number.isFinite(scale) || scale <= 0) {
|
|
2828
|
+
return 100;
|
|
2829
|
+
}
|
|
2830
|
+
return Math.round(scale * 100);
|
|
2831
|
+
}
|
|
2778
2832
|
handleAwarenessChange(event) {
|
|
2779
2833
|
event.stopPropagation();
|
|
2780
2834
|
this.awarenessChange.emit(event.detail);
|
|
@@ -2784,6 +2838,10 @@ const KritzelEditor = class {
|
|
|
2784
2838
|
this.scaleMax = event.detail.scaleMax;
|
|
2785
2839
|
this.lockDrawingScale = event.detail.lockDrawingScale;
|
|
2786
2840
|
this.theme = event.detail.theme;
|
|
2841
|
+
if (typeof event.detail.locale === 'string' && event.detail.locale !== this.locale) {
|
|
2842
|
+
this.locale = event.detail.locale;
|
|
2843
|
+
this.localeChange.emit(event.detail.locale);
|
|
2844
|
+
}
|
|
2787
2845
|
this.viewportBoundaryLeft = event.detail.viewportBoundaryLeft ?? -Infinity;
|
|
2788
2846
|
this.viewportBoundaryRight = event.detail.viewportBoundaryRight ?? Infinity;
|
|
2789
2847
|
this.viewportBoundaryTop = event.detail.viewportBoundaryTop ?? -Infinity;
|
|
@@ -2798,7 +2856,7 @@ const KritzelEditor = class {
|
|
|
2798
2856
|
return [
|
|
2799
2857
|
{
|
|
2800
2858
|
id: 'share',
|
|
2801
|
-
label: 'Share',
|
|
2859
|
+
label: this.resolvedTerms['menu.share'] ?? 'Share',
|
|
2802
2860
|
icon: 'share',
|
|
2803
2861
|
action: () => {
|
|
2804
2862
|
if (!this.isLoggedIn && this.loginConfig) {
|
|
@@ -2810,7 +2868,7 @@ const KritzelEditor = class {
|
|
|
2810
2868
|
},
|
|
2811
2869
|
{
|
|
2812
2870
|
id: 'export',
|
|
2813
|
-
label: 'Export',
|
|
2871
|
+
label: this.resolvedTerms['menu.export'] ?? 'Export',
|
|
2814
2872
|
icon: 'upload',
|
|
2815
2873
|
action: async () => {
|
|
2816
2874
|
const preview = await this.engineRef.getScreenshot('png');
|
|
@@ -2819,19 +2877,19 @@ const KritzelEditor = class {
|
|
|
2819
2877
|
},
|
|
2820
2878
|
{
|
|
2821
2879
|
id: 'import',
|
|
2822
|
-
label: 'Import',
|
|
2880
|
+
label: this.resolvedTerms['menu.import'] ?? 'Import',
|
|
2823
2881
|
icon: 'download',
|
|
2824
2882
|
action: () => this.engineRef.importFromFile(),
|
|
2825
2883
|
},
|
|
2826
2884
|
{
|
|
2827
2885
|
id: 'settings',
|
|
2828
|
-
label: 'Settings',
|
|
2886
|
+
label: this.resolvedTerms['menu.settings'] ?? 'Settings',
|
|
2829
2887
|
icon: 'settings',
|
|
2830
2888
|
action: () => this.settingsRef.open(),
|
|
2831
2889
|
},
|
|
2832
2890
|
{
|
|
2833
2891
|
id: 'logout',
|
|
2834
|
-
label: 'Logout',
|
|
2892
|
+
label: this.resolvedTerms['menu.logout'] ?? 'Logout',
|
|
2835
2893
|
icon: 'log-out',
|
|
2836
2894
|
color: '#ff3b30',
|
|
2837
2895
|
isVisible: this.isLoggedIn,
|
|
@@ -2871,6 +2929,41 @@ const KritzelEditor = class {
|
|
|
2871
2929
|
async setLoginLoading(provider) {
|
|
2872
2930
|
this.loginDialogRef?.setLoading(provider);
|
|
2873
2931
|
}
|
|
2932
|
+
/**
|
|
2933
|
+
* Sets the active locale (language) and re-renders the UI.
|
|
2934
|
+
* @param code - The locale code to activate, e.g. 'de'.
|
|
2935
|
+
*/
|
|
2936
|
+
async setLocale(code) {
|
|
2937
|
+
this.locale = code;
|
|
2938
|
+
await this.engineRef?.setLocale(code);
|
|
2939
|
+
}
|
|
2940
|
+
/**
|
|
2941
|
+
* Gets the currently active locale code.
|
|
2942
|
+
*/
|
|
2943
|
+
async getLocale() {
|
|
2944
|
+
return this.engineRef ? this.engineRef.getLocale() : this.locale;
|
|
2945
|
+
}
|
|
2946
|
+
/**
|
|
2947
|
+
* Gets the list of available locale codes (built-in and registered).
|
|
2948
|
+
*/
|
|
2949
|
+
async getAvailableLocales() {
|
|
2950
|
+
return this.engineRef ? this.engineRef.getAvailableLocales() : [];
|
|
2951
|
+
}
|
|
2952
|
+
/**
|
|
2953
|
+
* Registers additional locale definitions (with optional partial term overrides).
|
|
2954
|
+
* @param locales - The locale definitions to register.
|
|
2955
|
+
*/
|
|
2956
|
+
async registerLocales(locales) {
|
|
2957
|
+
await this.engineRef?.registerLocales(locales);
|
|
2958
|
+
}
|
|
2959
|
+
/**
|
|
2960
|
+
* Resolves a term key to its translated string for the active locale.
|
|
2961
|
+
* @param key - The term key to resolve.
|
|
2962
|
+
* @param vars - Optional values for `{placeholder}` interpolation.
|
|
2963
|
+
*/
|
|
2964
|
+
async t(key, vars) {
|
|
2965
|
+
return this.engineRef ? this.engineRef.t(key, vars) : key;
|
|
2966
|
+
}
|
|
2874
2967
|
getSettingsStorageKey() {
|
|
2875
2968
|
return this.editorId ? `kritzel-settings-${this.editorId}` : 'kritzel-settings';
|
|
2876
2969
|
}
|
|
@@ -2891,6 +2984,9 @@ const KritzelEditor = class {
|
|
|
2891
2984
|
if (typeof parsed.theme === 'string') {
|
|
2892
2985
|
this.theme = parsed.theme;
|
|
2893
2986
|
}
|
|
2987
|
+
if (typeof parsed.locale === 'string') {
|
|
2988
|
+
this.locale = parsed.locale;
|
|
2989
|
+
}
|
|
2894
2990
|
if (typeof parsed.viewportBoundaryLeft === 'number') {
|
|
2895
2991
|
this.viewportBoundaryLeft = parsed.viewportBoundaryLeft;
|
|
2896
2992
|
}
|
|
@@ -2921,6 +3017,7 @@ const KritzelEditor = class {
|
|
|
2921
3017
|
scaleMax: this.scaleMax,
|
|
2922
3018
|
lockDrawingScale: this.lockDrawingScale,
|
|
2923
3019
|
theme: this.theme,
|
|
3020
|
+
locale: this.locale,
|
|
2924
3021
|
viewportBoundaryLeft: this.viewportBoundaryLeft,
|
|
2925
3022
|
viewportBoundaryRight: this.viewportBoundaryRight,
|
|
2926
3023
|
viewportBoundaryTop: this.viewportBoundaryTop,
|
|
@@ -2974,35 +3071,35 @@ const KritzelEditor = class {
|
|
|
2974
3071
|
const isLoggedIn = this.isLoggedIn;
|
|
2975
3072
|
const shouldShowCurrentUser = isLoggedIn;
|
|
2976
3073
|
const shouldShowLoginButton = this.isReady && !!this.loginConfig && !isLoggedIn;
|
|
2977
|
-
return (index.h(index.Host, { key: '
|
|
3074
|
+
return (index.h(index.Host, { key: '72238560a0f0275c506f59220277fdff7ab92c13', style: {
|
|
2978
3075
|
opacity: this.isEditorVisible ? '1' : '0',
|
|
2979
3076
|
visibility: this.isEditorVisible ? 'visible' : 'hidden',
|
|
2980
3077
|
transition: 'opacity 0.2s ease-in-out, visibility 0.2s ease-in-out',
|
|
2981
|
-
} }, index.h("div", { key: '
|
|
3078
|
+
} }, index.h("div", { key: '14fd50ad857199f3b6be708fc4263aa2e69067de', class: "top-left-buttons" }, index.h("kritzel-workspace-manager", { key: '8788631c804770c67110c7e7906fe2034438ef9b', visible: this.isWorkspaceManagerVisible, workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, terms: this.resolvedTerms, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-back-to-content", { key: '1840374d7353af2b050822dcd9c54be46e326278', visible: this.isBackToContentButtonVisible, text: this.resolvedTerms['backToContent.label'] ?? 'Back to content', onBackToContent: () => this.backToContent() })), index.h("kritzel-engine", { key: 'cdde0b65c811ee28fb4266afb96005c1fed24323', ref: el => {
|
|
2982
3079
|
if (el) {
|
|
2983
3080
|
this.engineRef = el;
|
|
2984
3081
|
}
|
|
2985
|
-
}, workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, assetStorageConfig: this.assetStorageConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, isObjectDistanceFadingActive: this.isObjectDistanceFadingActive, scaleMin: this.scaleMin, cursorTarget: this.cursorTarget, isLoading: this.isLoading, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom,
|
|
3082
|
+
}, workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, assetStorageConfig: this.assetStorageConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, isObjectDistanceFadingActive: this.isObjectDistanceFadingActive, scaleMin: this.scaleMin, cursorTarget: this.cursorTarget, isLoading: this.isLoading, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, isPanningEnabled: this.isPanningEnabled, isZoomingEnabled: this.isZoomingEnabled, theme: this.theme, themes: this.themes, licenseKey: this.licenseKey, locale: this.locale, locales: this.locales, fallbackLocale: this.fallbackLocale, debugInfo: this.debugInfo, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onActiveWorkspaceChange: event => this.handleActiveWorkspaceChange(event), onObjectsChange: event => this.handleObjectsChange(event), onObjectsAdded: event => this.handleObjectsAdded(event), onObjectsRemoved: event => this.handleObjectsRemoved(event), onObjectsUpdated: event => this.handleObjectsUpdated(event), onUndoStateChange: event => this.handleUndoStateChange(event), onObjectsInViewportChange: event => this.handleObjectsInViewportChange(event), onViewportChange: event => this.handleViewportChange(event), onAwarenessChange: event => this.handleAwarenessChange(event) }), index.h("kritzel-controls", { key: '9b91d0cc3b3afba8894bd852bac911178c0ca82d', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
|
|
2986
3083
|
if (el) {
|
|
2987
3084
|
this.controlsRef = el;
|
|
2988
3085
|
}
|
|
2989
|
-
}, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: '
|
|
3086
|
+
}, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: '01f63c615eec68696532926b6d1efe2443e2d46a', class: "bottom-left-buttons" }, index.h("kritzel-zoom-panel", { key: '73a1fc5b0892b88d6c0a7c5debb42b7bb3f03a84', visible: this.isZoomPanelVisible, disabled: !this.isZoomingEnabled, zoomPercent: this.currentZoomPercent, terms: this.resolvedTerms, onZoomIn: () => this.zoomIn(), onZoomOut: () => this.zoomOut() })), index.h("div", { key: '94776978ba9dd68b2c5f62b141c074852585a1cd', class: "top-right-buttons" }, index.h("kritzel-settings", { key: '665a74511f8e511602d4d3437927e03af2c3c01c', ref: el => {
|
|
2990
3087
|
if (el) {
|
|
2991
3088
|
this.settingsRef = el;
|
|
2992
3089
|
}
|
|
2993
|
-
}, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], settings: this.currentSettingsConfig, onSettingsChange: event => this.handleSettingsChange(event) }), index.h("kritzel-export", { key: '
|
|
3090
|
+
}, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], availableLocales: this.availableLocaleOptions, settings: this.currentSettingsConfig, terms: this.resolvedTerms, onSettingsChange: event => this.handleSettingsChange(event) }), index.h("kritzel-export", { key: '6b52127d4634d92c3e7410a084f37970bd8c84e7', ref: el => {
|
|
2994
3091
|
if (el) {
|
|
2995
3092
|
this.exportRef = el;
|
|
2996
3093
|
}
|
|
2997
|
-
}, workspaceName: this.activeWorkspace?.name || 'workspace', onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), index.h("kritzel-active-users", { key: '
|
|
3094
|
+
}, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), index.h("kritzel-active-users", { key: '002a01d361137f867efc2a0c91a6c0e9619d4359', users: this.activeUsers }), shouldShowCurrentUser && index.h("kritzel-current-user", { key: '6a9e0ad77997cbb10981d58afb176a7f7f4938aa', user: this.user, terms: this.resolvedTerms }), shouldShowLoginButton && (index.h("kritzel-button", { key: '5ba13725105d0af68c51fec455569ac7bbeaecde', onButtonClick: () => this.loginDialogRef?.open() }, this.resolvedTerms['login.dialogTitle'] ?? 'Sign in')), index.h("kritzel-more-menu", { key: 'f392a518fef108b395eb6d6681af9e06827e3780', items: this.moreMenuItems, visible: this.isMoreMenuVisible, terms: this.resolvedTerms }), index.h("kritzel-share-dialog", { key: '845a3153f5fd9b419f7d0b81be85f5e1ea0051cc', ref: el => {
|
|
2998
3095
|
if (el) {
|
|
2999
3096
|
this.shareDialogRef = el;
|
|
3000
3097
|
}
|
|
3001
|
-
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: '
|
|
3098
|
+
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: '5a7b149d8e2c2acbda3d7818d8576d8ad249ef23', ref: el => {
|
|
3002
3099
|
if (el) {
|
|
3003
3100
|
this.loginDialogRef = el;
|
|
3004
3101
|
}
|
|
3005
|
-
}, providers: this.loginConfig.providers, dialogTitle: this.loginConfig.title, subtitle: this.loginConfig.subtitle, onProviderLogin: this.handleProviderLogin })))));
|
|
3102
|
+
}, providers: this.loginConfig.providers, dialogTitle: this.loginConfig.title ?? this.resolvedTerms['login.dialogTitle'] ?? 'Sign in', subtitle: this.loginConfig.subtitle, onProviderLogin: this.handleProviderLogin })))));
|
|
3006
3103
|
}
|
|
3007
3104
|
static get watchers() { return {
|
|
3008
3105
|
"isEngineReady": [{
|
|
@@ -3025,6 +3122,9 @@ const KritzelEditor = class {
|
|
|
3025
3122
|
}],
|
|
3026
3123
|
"themes": [{
|
|
3027
3124
|
"onThemesChange": 0
|
|
3125
|
+
}],
|
|
3126
|
+
"locale": [{
|
|
3127
|
+
"onLocaleChange": 0
|
|
3028
3128
|
}]
|
|
3029
3129
|
}; }
|
|
3030
3130
|
};
|
|
@@ -21279,6 +21379,28 @@ class KritzelContextMenuHandler extends schema_constants.KritzelBaseHandler {
|
|
|
21279
21379
|
this.globalContextMenuItems = globalContextMenuItems;
|
|
21280
21380
|
this.objectContextMenuItems = objectContextMenuItems;
|
|
21281
21381
|
}
|
|
21382
|
+
/**
|
|
21383
|
+
* Resolves the active context menu items for display, translating each item's
|
|
21384
|
+
* `label` through the current locale. When the label is a known
|
|
21385
|
+
* {@link KritzelTermKey} the translation is used; any other string is passed
|
|
21386
|
+
* through unchanged. Runs at menu-open time so the labels reflect the locale
|
|
21387
|
+
* active at that moment.
|
|
21388
|
+
* @returns A new array of items with resolved labels.
|
|
21389
|
+
*/
|
|
21390
|
+
resolveLabels(items) {
|
|
21391
|
+
return items.map(item => ({
|
|
21392
|
+
...item,
|
|
21393
|
+
label: this._core.localizationManager.translate(item.label),
|
|
21394
|
+
children: item.children ? this.resolveLabels(item.children) : undefined,
|
|
21395
|
+
}));
|
|
21396
|
+
}
|
|
21397
|
+
/**
|
|
21398
|
+
* Gets the active context menu items (object or global) with localized labels.
|
|
21399
|
+
*/
|
|
21400
|
+
getResolvedContextMenuItems() {
|
|
21401
|
+
const items = this._core.store.selectionGroup ? this.objectContextMenuItems : this.globalContextMenuItems;
|
|
21402
|
+
return this.resolveLabels(items);
|
|
21403
|
+
}
|
|
21282
21404
|
/**
|
|
21283
21405
|
* Handles the context menu event (typically triggered by right-click).
|
|
21284
21406
|
* This method performs the following operations:
|
|
@@ -21322,7 +21444,7 @@ class KritzelContextMenuHandler extends schema_constants.KritzelBaseHandler {
|
|
|
21322
21444
|
this._core.addSelectionGroup(selectionGroup);
|
|
21323
21445
|
this._core.rerender();
|
|
21324
21446
|
}
|
|
21325
|
-
this._core.store.state.contextMenuItems = this.
|
|
21447
|
+
this._core.store.state.contextMenuItems = this.getResolvedContextMenuItems();
|
|
21326
21448
|
const clickX = event.clientX - this._core.store.offsetX;
|
|
21327
21449
|
const clickY = event.clientY - this._core.store.offsetY;
|
|
21328
21450
|
const { translateX, translateY, scale } = this._core.store.state;
|
|
@@ -21378,7 +21500,7 @@ class KritzelContextMenuHandler extends schema_constants.KritzelBaseHandler {
|
|
|
21378
21500
|
this._core.addSelectionGroup(selectionGroup);
|
|
21379
21501
|
}
|
|
21380
21502
|
}
|
|
21381
|
-
this._core.store.state.contextMenuItems = this.
|
|
21503
|
+
this._core.store.state.contextMenuItems = this.getResolvedContextMenuItems();
|
|
21382
21504
|
this._core.store.state.contextMenuWorldX = x;
|
|
21383
21505
|
this._core.store.state.contextMenuWorldY = y;
|
|
21384
21506
|
const { translateX, translateY, scale } = this._core.store.state;
|
|
@@ -21425,6 +21547,7 @@ class KritzelCustomElement extends schema_constants.KritzelBaseObject {
|
|
|
21425
21547
|
if (config) {
|
|
21426
21548
|
this.translateX = config.translateX || 0;
|
|
21427
21549
|
this.translateY = config.translateY || 0;
|
|
21550
|
+
this.rotation = schema_constants.KritzelMathHelper.degreesToRadians(config.rotation ?? 0);
|
|
21428
21551
|
this.scale = config.scale || 1;
|
|
21429
21552
|
this.element = config.element;
|
|
21430
21553
|
this.height = config.height || 0;
|
|
@@ -23991,6 +24114,10 @@ class KritzelCore {
|
|
|
23991
24114
|
_cursorManager;
|
|
23992
24115
|
/** Manager for theme styling */
|
|
23993
24116
|
_themeManager;
|
|
24117
|
+
/** Manager for localization / translated UI strings */
|
|
24118
|
+
_localizationManager;
|
|
24119
|
+
/** Manager for license validation and watermark gating */
|
|
24120
|
+
_licenseManager;
|
|
23994
24121
|
/** Per-core registry of drawing tools (one instance per editor). */
|
|
23995
24122
|
_toolRegistry;
|
|
23996
24123
|
/** Optional unique identifier for namespacing storage keys across multiple editor instances */
|
|
@@ -24039,6 +24166,20 @@ class KritzelCore {
|
|
|
24039
24166
|
get themeManager() {
|
|
24040
24167
|
return this._themeManager;
|
|
24041
24168
|
}
|
|
24169
|
+
/**
|
|
24170
|
+
* Gets the localization manager.
|
|
24171
|
+
* @returns The KritzelLocalizationManager for resolving translated UI strings
|
|
24172
|
+
*/
|
|
24173
|
+
get localizationManager() {
|
|
24174
|
+
return this._localizationManager;
|
|
24175
|
+
}
|
|
24176
|
+
/**
|
|
24177
|
+
* Gets the license manager.
|
|
24178
|
+
* @returns The KritzelLicenseManager for validating licenses and gating the watermark
|
|
24179
|
+
*/
|
|
24180
|
+
get licenseManager() {
|
|
24181
|
+
return this._licenseManager;
|
|
24182
|
+
}
|
|
24042
24183
|
/**
|
|
24043
24184
|
* Gets the tool registry scoped to this core instance.
|
|
24044
24185
|
* @returns The KritzelToolRegistry owned by this core
|
|
@@ -24091,6 +24232,8 @@ class KritzelCore {
|
|
|
24091
24232
|
this._anchorManager = new schema_constants.KritzelAnchorManager(this);
|
|
24092
24233
|
this._cursorManager = new KritzelCursorManager(this);
|
|
24093
24234
|
this._themeManager = new schema_constants.KritzelThemeManager(this);
|
|
24235
|
+
this._localizationManager = new schema_constants.KritzelLocalizationManager(this);
|
|
24236
|
+
this._licenseManager = new schema_constants.KritzelLicenseManager(this);
|
|
24094
24237
|
this._toolRegistry = new KritzelToolRegistry(this);
|
|
24095
24238
|
this._assetResolver = new schema_constants.KritzelAssetResolver();
|
|
24096
24239
|
}
|
|
@@ -24126,6 +24269,8 @@ class KritzelCore {
|
|
|
24126
24269
|
this._editorId = editorId;
|
|
24127
24270
|
// Re-create theme manager so it picks up the new storage key
|
|
24128
24271
|
this._themeManager = new schema_constants.KritzelThemeManager(this);
|
|
24272
|
+
// Re-create localization manager so it picks up the new storage key
|
|
24273
|
+
this._localizationManager = new schema_constants.KritzelLocalizationManager(this);
|
|
24129
24274
|
}
|
|
24130
24275
|
/**
|
|
24131
24276
|
* Initializes the Yjs document for collaborative editing.
|
|
@@ -25272,7 +25417,7 @@ class KritzelSvgExportHelper {
|
|
|
25272
25417
|
* @returns SVG document string
|
|
25273
25418
|
*/
|
|
25274
25419
|
static generateSvg(objects, options = {}) {
|
|
25275
|
-
const { theme, padding = 0, includeXmlDeclaration = true } = options;
|
|
25420
|
+
const { theme, padding = 0, includeXmlDeclaration = true, rasterSafeForCanvas = false, imageDataUrls } = options;
|
|
25276
25421
|
if (!objects || objects.length === 0) {
|
|
25277
25422
|
return '';
|
|
25278
25423
|
}
|
|
@@ -25292,7 +25437,7 @@ class KritzelSvgExportHelper {
|
|
|
25292
25437
|
// Generate SVG elements for each object
|
|
25293
25438
|
const elements = objects
|
|
25294
25439
|
.sort((a, b) => a.zIndex - b.zIndex)
|
|
25295
|
-
.map(obj => this.objectToSvgElement(obj, theme))
|
|
25440
|
+
.map(obj => this.objectToSvgElement(obj, theme, imageDataUrls, rasterSafeForCanvas))
|
|
25296
25441
|
.filter(Boolean)
|
|
25297
25442
|
.join('\n ');
|
|
25298
25443
|
const xmlDecl = includeXmlDeclaration ? '<?xml version="1.0" encoding="UTF-8"?>\n' : '';
|
|
@@ -25318,6 +25463,102 @@ class KritzelSvgExportHelper {
|
|
|
25318
25463
|
}
|
|
25319
25464
|
return result;
|
|
25320
25465
|
}
|
|
25466
|
+
/**
|
|
25467
|
+
* Resolves every image referenced by the given objects (including those
|
|
25468
|
+
* nested inside groups) to an inlined `data:` URL, keyed by object id.
|
|
25469
|
+
*
|
|
25470
|
+
* This is required for export flows that rasterize the SVG (e.g. PNG
|
|
25471
|
+
* export): an SVG loaded into an `<img>` element will NOT load external
|
|
25472
|
+
* or `blob:` resources, so a `<image href="blob:...">` renders as a
|
|
25473
|
+
* broken-image placeholder. Embedding the bytes as a base64 `data:` URL
|
|
25474
|
+
* makes the image self-contained and survive rasterization.
|
|
25475
|
+
*
|
|
25476
|
+
* Resolution is best-effort: images that fail to resolve are simply
|
|
25477
|
+
* omitted from the map, and the SVG falls back to whatever `href` the
|
|
25478
|
+
* synchronous path would have produced.
|
|
25479
|
+
* @param objects - Objects to inline images for
|
|
25480
|
+
* @param assetResolver - Resolver used to fetch asset bytes; optional
|
|
25481
|
+
* @returns Map of image object id -> inlined `data:` URL
|
|
25482
|
+
*/
|
|
25483
|
+
static async resolveImageDataUrls(objects, assetResolver) {
|
|
25484
|
+
const dataUrls = new Map();
|
|
25485
|
+
if (!objects || objects.length === 0) {
|
|
25486
|
+
return dataUrls;
|
|
25487
|
+
}
|
|
25488
|
+
const images = this.flattenObjects(objects).filter((obj) => schema_constants.KritzelClassHelper.isInstanceOf(obj, 'KritzelImage'));
|
|
25489
|
+
await Promise.all(images.map(async (image) => {
|
|
25490
|
+
// Legacy inline data URL is already embeddable as-is.
|
|
25491
|
+
if (image.src?.startsWith('data:')) {
|
|
25492
|
+
dataUrls.set(image.id, image.src);
|
|
25493
|
+
return;
|
|
25494
|
+
}
|
|
25495
|
+
// A resolvedSrc that is itself a data URL can be embedded directly.
|
|
25496
|
+
if (image.resolvedSrc?.startsWith('data:')) {
|
|
25497
|
+
dataUrls.set(image.id, image.resolvedSrc);
|
|
25498
|
+
return;
|
|
25499
|
+
}
|
|
25500
|
+
if (!image.assetId || !assetResolver) {
|
|
25501
|
+
return;
|
|
25502
|
+
}
|
|
25503
|
+
try {
|
|
25504
|
+
const blob = await assetResolver.fetchBlob(image.assetId);
|
|
25505
|
+
dataUrls.set(image.id, await this.blobToDataUrl(blob));
|
|
25506
|
+
}
|
|
25507
|
+
catch (err) {
|
|
25508
|
+
console.warn(`[KritzelSvgExportHelper] Failed to inline image asset ${image.assetId} for export:`, err);
|
|
25509
|
+
}
|
|
25510
|
+
}));
|
|
25511
|
+
return dataUrls;
|
|
25512
|
+
}
|
|
25513
|
+
/**
|
|
25514
|
+
* Reads a Blob into a base64 `data:` URL.
|
|
25515
|
+
* @param blob - The blob to encode
|
|
25516
|
+
* @returns Promise resolving to the data URL string
|
|
25517
|
+
*/
|
|
25518
|
+
static async blobToDataUrl(blob) {
|
|
25519
|
+
// Prefer FileReader in browser-like runtimes for efficiency.
|
|
25520
|
+
const hasFileReader = typeof FileReader !== 'undefined';
|
|
25521
|
+
if (hasFileReader) {
|
|
25522
|
+
try {
|
|
25523
|
+
return await new Promise((resolve, reject) => {
|
|
25524
|
+
const reader = new FileReader();
|
|
25525
|
+
reader.onload = () => {
|
|
25526
|
+
if (typeof reader.result === 'string') {
|
|
25527
|
+
resolve(reader.result);
|
|
25528
|
+
return;
|
|
25529
|
+
}
|
|
25530
|
+
reject(new Error('FileReader result is not a string'));
|
|
25531
|
+
};
|
|
25532
|
+
reader.onerror = () => reject(reader.error ?? new Error('Failed to read blob as data URL'));
|
|
25533
|
+
reader.readAsDataURL(blob);
|
|
25534
|
+
});
|
|
25535
|
+
}
|
|
25536
|
+
catch {
|
|
25537
|
+
// Fall through to the ArrayBuffer-based encoder.
|
|
25538
|
+
}
|
|
25539
|
+
}
|
|
25540
|
+
const bytes = new Uint8Array(await blob.arrayBuffer());
|
|
25541
|
+
const mimeType = blob.type || 'application/octet-stream';
|
|
25542
|
+
return `data:${mimeType};base64,${this.uint8ToBase64(bytes)}`;
|
|
25543
|
+
}
|
|
25544
|
+
/**
|
|
25545
|
+
* Encodes a byte array to base64 across browser and Node-like runtimes.
|
|
25546
|
+
*/
|
|
25547
|
+
static uint8ToBase64(bytes) {
|
|
25548
|
+
if (typeof Buffer !== 'undefined') {
|
|
25549
|
+
return Buffer.from(bytes).toString('base64');
|
|
25550
|
+
}
|
|
25551
|
+
let binary = '';
|
|
25552
|
+
const chunkSize = 0x8000;
|
|
25553
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
25554
|
+
const chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.length));
|
|
25555
|
+
binary += String.fromCharCode(...chunk);
|
|
25556
|
+
}
|
|
25557
|
+
if (typeof btoa === 'function') {
|
|
25558
|
+
return btoa(binary);
|
|
25559
|
+
}
|
|
25560
|
+
throw new Error('No base64 encoder available in this runtime');
|
|
25561
|
+
}
|
|
25321
25562
|
/**
|
|
25322
25563
|
* Collects SVG defs (markers, patterns, etc.) needed by the objects.
|
|
25323
25564
|
* @param objects - Objects to collect defs for
|
|
@@ -25362,9 +25603,10 @@ class KritzelSvgExportHelper {
|
|
|
25362
25603
|
* Converts a Kritzel object to its SVG element representation.
|
|
25363
25604
|
* @param object - The object to convert
|
|
25364
25605
|
* @param theme - Theme for color resolution
|
|
25606
|
+
* @param imageDataUrls - Optional map of image id -> inlined data URL
|
|
25365
25607
|
* @returns SVG element string, or empty string if object type is not supported
|
|
25366
25608
|
*/
|
|
25367
|
-
static objectToSvgElement(object, theme) {
|
|
25609
|
+
static objectToSvgElement(object, theme, imageDataUrls, rasterSafeForCanvas = false) {
|
|
25368
25610
|
if (schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelPath')) {
|
|
25369
25611
|
return this.pathToSvg(object, theme);
|
|
25370
25612
|
}
|
|
@@ -25375,13 +25617,13 @@ class KritzelSvgExportHelper {
|
|
|
25375
25617
|
return this.shapeToSvg(object, theme);
|
|
25376
25618
|
}
|
|
25377
25619
|
if (schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelText')) {
|
|
25378
|
-
return this.textToSvg(object, theme);
|
|
25620
|
+
return this.textToSvg(object, theme, rasterSafeForCanvas);
|
|
25379
25621
|
}
|
|
25380
25622
|
if (schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
25381
|
-
return this.imageToSvg(object);
|
|
25623
|
+
return this.imageToSvg(object, imageDataUrls);
|
|
25382
25624
|
}
|
|
25383
25625
|
if (schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
25384
|
-
return this.groupToSvg(object, theme);
|
|
25626
|
+
return this.groupToSvg(object, theme, imageDataUrls, rasterSafeForCanvas);
|
|
25385
25627
|
}
|
|
25386
25628
|
return '';
|
|
25387
25629
|
}
|
|
@@ -25396,9 +25638,10 @@ class KritzelSvgExportHelper {
|
|
|
25396
25638
|
const fill = schema_constants.KritzelColorHelper.resolveThemeColor(path.fill, theme);
|
|
25397
25639
|
const stroke = schema_constants.KritzelColorHelper.resolveThemeColor(path.stroke, theme);
|
|
25398
25640
|
const opacity = path.opacity !== 1 ? ` opacity="${path.opacity}"` : '';
|
|
25641
|
+
const scale = this.getObjectScale(path);
|
|
25399
25642
|
// Path needs to be wrapped in a g with translation since path.d uses local coordinates
|
|
25400
25643
|
return `<g transform="${transform}"${opacity}>
|
|
25401
|
-
<svg viewBox="${path.viewBox}" width="${path.totalWidth /
|
|
25644
|
+
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
25402
25645
|
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
25403
25646
|
</svg>
|
|
25404
25647
|
</g>`;
|
|
@@ -25413,10 +25656,11 @@ class KritzelSvgExportHelper {
|
|
|
25413
25656
|
const transform = this.buildTransform(line);
|
|
25414
25657
|
const stroke = schema_constants.KritzelColorHelper.resolveThemeColor(line.stroke, theme);
|
|
25415
25658
|
const opacity = line.opacity !== 1 ? ` opacity="${line.opacity}"` : '';
|
|
25659
|
+
const scale = this.getObjectScale(line);
|
|
25416
25660
|
const markerStart = line.hasStartArrow ? ` marker-start="url(#${line.startMarkerId})"` : '';
|
|
25417
25661
|
const markerEnd = line.hasEndArrow ? ` marker-end="url(#${line.endMarkerId})"` : '';
|
|
25418
25662
|
return `<g transform="${transform}"${opacity}>
|
|
25419
|
-
<svg viewBox="${line.viewBox}" width="${line.totalWidth /
|
|
25663
|
+
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
25420
25664
|
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
25421
25665
|
</svg>
|
|
25422
25666
|
</g>`;
|
|
@@ -25432,6 +25676,7 @@ class KritzelSvgExportHelper {
|
|
|
25432
25676
|
const fill = schema_constants.KritzelColorHelper.resolveThemeColor(shape.fillColor, theme);
|
|
25433
25677
|
const stroke = schema_constants.KritzelColorHelper.resolveThemeColor(shape.strokeColor, theme);
|
|
25434
25678
|
const opacity = shape.opacity !== 1 ? ` opacity="${shape.opacity}"` : '';
|
|
25679
|
+
const scale = this.getObjectScale(shape);
|
|
25435
25680
|
// Get the SVG path for the shape
|
|
25436
25681
|
const pathD = shape.getSvgPath();
|
|
25437
25682
|
// Handle text content if present
|
|
@@ -25450,7 +25695,7 @@ class KritzelSvgExportHelper {
|
|
|
25450
25695
|
}
|
|
25451
25696
|
}
|
|
25452
25697
|
return `<g transform="${transform}"${opacity}>
|
|
25453
|
-
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth /
|
|
25698
|
+
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
25454
25699
|
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
25455
25700
|
</svg>
|
|
25456
25701
|
</g>`;
|
|
@@ -25461,45 +25706,85 @@ class KritzelSvgExportHelper {
|
|
|
25461
25706
|
* @param theme - Theme for color resolution
|
|
25462
25707
|
* @returns SVG element string
|
|
25463
25708
|
*/
|
|
25464
|
-
static textToSvg(text, theme) {
|
|
25709
|
+
static textToSvg(text, theme, rasterSafeForCanvas = false) {
|
|
25710
|
+
if (rasterSafeForCanvas) {
|
|
25711
|
+
return this.textToSvgRasterSafe(text, theme);
|
|
25712
|
+
}
|
|
25465
25713
|
const transform = this.buildTransform(text);
|
|
25466
25714
|
const opacity = text.opacity !== 1 ? ` opacity="${text.opacity}"` : '';
|
|
25467
25715
|
const fontColor = schema_constants.KritzelColorHelper.resolveThemeColor(text.fontColor, theme);
|
|
25468
25716
|
const bgColor = schema_constants.KritzelColorHelper.resolveThemeColor(text.backgroundColor, theme);
|
|
25717
|
+
const scale = this.getObjectScale(text);
|
|
25469
25718
|
// Convert ProseMirror content to HTML
|
|
25470
25719
|
const htmlContent = this.prosemirrorToHtml(text.content, text, theme);
|
|
25471
25720
|
// Calculate dimensions accounting for scale
|
|
25472
|
-
const width = text.totalWidth /
|
|
25473
|
-
const height = text.totalHeight /
|
|
25721
|
+
const width = text.totalWidth / scale;
|
|
25722
|
+
const height = text.totalHeight / scale;
|
|
25474
25723
|
return `<g transform="${transform}"${opacity}>
|
|
25475
25724
|
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
25476
25725
|
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: ${text.fontFamily}; font-size: ${text.fontSize}pt; color: ${fontColor}; background-color: ${bgColor || 'transparent'}; transform: scale(${text.scaleFactor}); transform-origin: top left; white-space: pre-wrap; word-wrap: break-word;">
|
|
25477
25726
|
${htmlContent}
|
|
25478
25727
|
</div>
|
|
25479
25728
|
</foreignObject>
|
|
25729
|
+
</g>`;
|
|
25730
|
+
}
|
|
25731
|
+
/**
|
|
25732
|
+
* Converts a KritzelText to SVG using pure SVG text primitives.
|
|
25733
|
+
* This path avoids `<foreignObject>`, which taints canvases when the
|
|
25734
|
+
* generated SVG is rasterized through `<img>` and `drawImage`.
|
|
25735
|
+
*/
|
|
25736
|
+
static textToSvgRasterSafe(text, theme) {
|
|
25737
|
+
const transform = this.buildTransform(text);
|
|
25738
|
+
const opacity = text.opacity !== 1 ? ` opacity="${text.opacity}"` : '';
|
|
25739
|
+
const fontColor = schema_constants.KritzelColorHelper.resolveThemeColor(text.fontColor, theme);
|
|
25740
|
+
const bgColor = schema_constants.KritzelColorHelper.resolveThemeColor(text.backgroundColor, theme);
|
|
25741
|
+
const scale = this.getObjectScale(text);
|
|
25742
|
+
const width = text.totalWidth / scale;
|
|
25743
|
+
const height = text.totalHeight / scale;
|
|
25744
|
+
const lines = this.prosemirrorToPlainTextLines(text.content);
|
|
25745
|
+
const resolvedLines = lines.length > 0 ? lines : [''];
|
|
25746
|
+
const resolvedFontSize = Math.max(1, text.fontSize * (text.scaleFactor || 1));
|
|
25747
|
+
const lineHeight = resolvedFontSize * 1.2;
|
|
25748
|
+
const startY = resolvedFontSize;
|
|
25749
|
+
const bgRect = bgColor && bgColor !== 'transparent'
|
|
25750
|
+
? `<rect x="0" y="0" width="${width}" height="${height}" fill="${bgColor}"/>`
|
|
25751
|
+
: '';
|
|
25752
|
+
const tspans = resolvedLines
|
|
25753
|
+
.map((line, index) => {
|
|
25754
|
+
const y = startY + index * lineHeight;
|
|
25755
|
+
return `<tspan x="0" y="${y}" xml:space="preserve">${this.escapeHtml(line)}</tspan>`;
|
|
25756
|
+
})
|
|
25757
|
+
.join('');
|
|
25758
|
+
return `<g transform="${transform}"${opacity}>
|
|
25759
|
+
${bgRect}
|
|
25760
|
+
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSize}" fill="${fontColor}">${tspans}</text>
|
|
25480
25761
|
</g>`;
|
|
25481
25762
|
}
|
|
25482
25763
|
/**
|
|
25483
25764
|
* Converts a KritzelImage to SVG.
|
|
25484
25765
|
*
|
|
25485
|
-
*
|
|
25486
|
-
*
|
|
25766
|
+
* Prefers an inlined `data:` URL from `imageDataUrls` (keyed by object
|
|
25767
|
+
* id) when provided, so the embedded bytes survive rasterization to
|
|
25768
|
+
* PNG. Falls back to `resolvedSrc` (populated by the renderer via the
|
|
25769
|
+
* asset resolver) and finally the legacy inline `src` field for
|
|
25487
25770
|
* documents persisted before the asset layer existed.
|
|
25488
25771
|
*
|
|
25489
|
-
* Note:
|
|
25490
|
-
*
|
|
25491
|
-
*
|
|
25492
|
-
* `
|
|
25772
|
+
* Note: a `blob:` `resolvedSrc` renders correctly on-canvas but becomes
|
|
25773
|
+
* a broken-image placeholder once the SVG is loaded into an `<img>` and
|
|
25774
|
+
* drawn to a canvas. Callers that rasterize the SVG must pass
|
|
25775
|
+
* `imageDataUrls` (see {@link KritzelSvgExportHelper.resolveImageDataUrls}).
|
|
25493
25776
|
* @param image - The image object
|
|
25777
|
+
* @param imageDataUrls - Optional map of image id -> inlined data URL
|
|
25494
25778
|
* @returns SVG element string
|
|
25495
25779
|
*/
|
|
25496
|
-
static imageToSvg(image) {
|
|
25780
|
+
static imageToSvg(image, imageDataUrls) {
|
|
25497
25781
|
const transform = this.buildTransform(image);
|
|
25498
25782
|
const opacity = image.opacity !== 1 ? ` opacity="${image.opacity}"` : '';
|
|
25783
|
+
const scale = this.getObjectScale(image);
|
|
25499
25784
|
// Calculate dimensions
|
|
25500
|
-
const width = image.totalWidth /
|
|
25501
|
-
const height = image.totalHeight /
|
|
25502
|
-
const href = image.resolvedSrc || image.src || '';
|
|
25785
|
+
const width = image.totalWidth / scale;
|
|
25786
|
+
const height = image.totalHeight / scale;
|
|
25787
|
+
const href = imageDataUrls?.get(image.id) || image.resolvedSrc || image.src || '';
|
|
25503
25788
|
return `<g transform="${transform}"${opacity}>
|
|
25504
25789
|
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
25505
25790
|
</g>`;
|
|
@@ -25508,12 +25793,13 @@ class KritzelSvgExportHelper {
|
|
|
25508
25793
|
* Converts a KritzelGroup to SVG by recursively converting children.
|
|
25509
25794
|
* @param group - The group object
|
|
25510
25795
|
* @param theme - Theme for color resolution
|
|
25796
|
+
* @param imageDataUrls - Optional map of image id -> inlined data URL
|
|
25511
25797
|
* @returns SVG element string
|
|
25512
25798
|
*/
|
|
25513
|
-
static groupToSvg(group, theme) {
|
|
25799
|
+
static groupToSvg(group, theme, imageDataUrls, rasterSafeForCanvas = false) {
|
|
25514
25800
|
const children = group.children
|
|
25515
25801
|
.sort((a, b) => a.zIndex - b.zIndex)
|
|
25516
|
-
.map(child => this.objectToSvgElement(child, theme))
|
|
25802
|
+
.map(child => this.objectToSvgElement(child, theme, imageDataUrls, rasterSafeForCanvas))
|
|
25517
25803
|
.filter(Boolean)
|
|
25518
25804
|
.join('\n ');
|
|
25519
25805
|
if (!children) {
|
|
@@ -25532,17 +25818,25 @@ class KritzelSvgExportHelper {
|
|
|
25532
25818
|
*/
|
|
25533
25819
|
static buildTransform(object) {
|
|
25534
25820
|
const transforms = [];
|
|
25821
|
+
const scale = this.getObjectScale(object);
|
|
25535
25822
|
// Translation
|
|
25536
25823
|
transforms.push(`translate(${object.translateX}, ${object.translateY})`);
|
|
25537
25824
|
// Rotation around center
|
|
25538
25825
|
if (object.rotation !== 0) {
|
|
25539
|
-
const centerX = object.totalWidth / 2 /
|
|
25540
|
-
const centerY = object.totalHeight / 2 /
|
|
25826
|
+
const centerX = object.totalWidth / 2 / scale;
|
|
25827
|
+
const centerY = object.totalHeight / 2 / scale;
|
|
25541
25828
|
const degrees = object.rotation * (180 / Math.PI);
|
|
25542
25829
|
transforms.push(`rotate(${degrees}, ${centerX}, ${centerY})`);
|
|
25543
25830
|
}
|
|
25544
25831
|
return transforms.join(' ');
|
|
25545
25832
|
}
|
|
25833
|
+
/**
|
|
25834
|
+
* Returns a safe non-zero scale for export geometry calculations.
|
|
25835
|
+
*/
|
|
25836
|
+
static getObjectScale(object) {
|
|
25837
|
+
const scale = object.scale ?? 1;
|
|
25838
|
+
return scale === 0 ? 1 : scale;
|
|
25839
|
+
}
|
|
25546
25840
|
/**
|
|
25547
25841
|
* Converts ProseMirror JSON content to HTML string.
|
|
25548
25842
|
* @param content - ProseMirror document JSON
|
|
@@ -25598,6 +25892,54 @@ class KritzelSvgExportHelper {
|
|
|
25598
25892
|
return '';
|
|
25599
25893
|
}
|
|
25600
25894
|
}
|
|
25895
|
+
/**
|
|
25896
|
+
* Converts ProseMirror JSON content to plain-text lines.
|
|
25897
|
+
* Used by raster-safe SVG export, which cannot depend on HTML/foreignObject.
|
|
25898
|
+
*/
|
|
25899
|
+
static prosemirrorToPlainTextLines(content) {
|
|
25900
|
+
if (!content || !Array.isArray(content.content)) {
|
|
25901
|
+
return [];
|
|
25902
|
+
}
|
|
25903
|
+
const plainText = content.content
|
|
25904
|
+
.map((node) => this.nodeToPlainText(node))
|
|
25905
|
+
.join('')
|
|
25906
|
+
.replace(/\r\n/g, '\n')
|
|
25907
|
+
.replace(/\n+$/, '');
|
|
25908
|
+
if (!plainText) {
|
|
25909
|
+
return [];
|
|
25910
|
+
}
|
|
25911
|
+
return plainText.split('\n');
|
|
25912
|
+
}
|
|
25913
|
+
/**
|
|
25914
|
+
* Converts a ProseMirror node tree into plain text.
|
|
25915
|
+
*/
|
|
25916
|
+
static nodeToPlainText(node) {
|
|
25917
|
+
if (!node) {
|
|
25918
|
+
return '';
|
|
25919
|
+
}
|
|
25920
|
+
switch (node.type) {
|
|
25921
|
+
case 'text':
|
|
25922
|
+
return node.text || '';
|
|
25923
|
+
case 'hard_break':
|
|
25924
|
+
return '\n';
|
|
25925
|
+
case 'paragraph': {
|
|
25926
|
+
const paragraph = Array.isArray(node.content)
|
|
25927
|
+
? node.content.map((child) => this.nodeToPlainText(child)).join('')
|
|
25928
|
+
: '';
|
|
25929
|
+
return `${paragraph}\n`;
|
|
25930
|
+
}
|
|
25931
|
+
case 'list_item': {
|
|
25932
|
+
const item = Array.isArray(node.content)
|
|
25933
|
+
? node.content.map((child) => this.nodeToPlainText(child)).join('')
|
|
25934
|
+
: '';
|
|
25935
|
+
return `- ${item.trim()}\n`;
|
|
25936
|
+
}
|
|
25937
|
+
default:
|
|
25938
|
+
return Array.isArray(node.content)
|
|
25939
|
+
? node.content.map((child) => this.nodeToPlainText(child)).join('')
|
|
25940
|
+
: '';
|
|
25941
|
+
}
|
|
25942
|
+
}
|
|
25601
25943
|
/**
|
|
25602
25944
|
* Applies a ProseMirror mark to text.
|
|
25603
25945
|
* @param text - The text to wrap
|
|
@@ -26648,6 +26990,11 @@ const KritzelEngine = class {
|
|
|
26648
26990
|
onThemeChange(newValue) {
|
|
26649
26991
|
this.core.themeManager.setTheme(newValue);
|
|
26650
26992
|
}
|
|
26993
|
+
/** License key that, when valid, removes the "Powered by Kritzel" watermark. */
|
|
26994
|
+
licenseKey;
|
|
26995
|
+
onLicenseKeyChange(newValue) {
|
|
26996
|
+
this.core.licenseManager.validate(newValue);
|
|
26997
|
+
}
|
|
26651
26998
|
/** An array of available themes for the editor. */
|
|
26652
26999
|
themes;
|
|
26653
27000
|
onThemesChange(newValue) {
|
|
@@ -26656,6 +27003,25 @@ const KritzelEngine = class {
|
|
|
26656
27003
|
this.core.themeManager.applyTheme(this.core.themeManager.currentTheme);
|
|
26657
27004
|
}
|
|
26658
27005
|
}
|
|
27006
|
+
/** The current locale (language) code to apply to the editor, e.g. 'en', 'de', 'fr'. */
|
|
27007
|
+
locale = 'en';
|
|
27008
|
+
onLocaleChange(newValue) {
|
|
27009
|
+
this.core.localizationManager.setLocale(newValue);
|
|
27010
|
+
}
|
|
27011
|
+
/** An array of available locale definitions (with optional partial term overrides). */
|
|
27012
|
+
locales;
|
|
27013
|
+
onLocalesChange(newValue) {
|
|
27014
|
+
if (newValue && newValue.length > 0) {
|
|
27015
|
+
this.core.localizationManager.registerLocales(newValue);
|
|
27016
|
+
this.core.localizationManager.setLocale(this.locale);
|
|
27017
|
+
}
|
|
27018
|
+
}
|
|
27019
|
+
/** The locale used to resolve terms missing from the active locale. */
|
|
27020
|
+
fallbackLocale = 'en';
|
|
27021
|
+
onFallbackLocaleChange(newValue) {
|
|
27022
|
+
this.core.localizationManager.setFallbackLocale(newValue);
|
|
27023
|
+
this.core.rerender();
|
|
27024
|
+
}
|
|
26659
27025
|
/** Left boundary of the viewport in world coordinates. Objects beyond this X position cannot be panned to. */
|
|
26660
27026
|
viewportBoundaryLeft = -Infinity;
|
|
26661
27027
|
onViewportBoundaryLeftChange(newValue) {
|
|
@@ -26683,8 +27049,10 @@ const KritzelEngine = class {
|
|
|
26683
27049
|
this.core.store.state.debugInfo = newValue;
|
|
26684
27050
|
}
|
|
26685
27051
|
}
|
|
26686
|
-
/** When false, wheel events
|
|
26687
|
-
|
|
27052
|
+
/** When false, non-modified wheel events do not pan the viewport. */
|
|
27053
|
+
isPanningEnabled = true;
|
|
27054
|
+
/** When false, Ctrl+wheel events do not zoom the viewport. */
|
|
27055
|
+
isZoomingEnabled = true;
|
|
26688
27056
|
/** External loading state. Combined with internal workspace-loading state to drive the overlay. */
|
|
26689
27057
|
isLoading = false;
|
|
26690
27058
|
onIsLoadingChange() {
|
|
@@ -26727,13 +27095,19 @@ const KritzelEngine = class {
|
|
|
26727
27095
|
if (this.core.store.isDisabled) {
|
|
26728
27096
|
return;
|
|
26729
27097
|
}
|
|
26730
|
-
if (!this.wheelEnabled) {
|
|
26731
|
-
return;
|
|
26732
|
-
}
|
|
26733
27098
|
if (this.core.store.state.isContextMenuVisible) {
|
|
26734
27099
|
this.hideContextMenu();
|
|
26735
27100
|
}
|
|
26736
|
-
|
|
27101
|
+
if (ev.ctrlKey) {
|
|
27102
|
+
if (this.isZoomingEnabled) {
|
|
27103
|
+
this.viewport.handleWheel(ev);
|
|
27104
|
+
}
|
|
27105
|
+
}
|
|
27106
|
+
else {
|
|
27107
|
+
if (this.isPanningEnabled) {
|
|
27108
|
+
this.viewport.handleWheel(ev);
|
|
27109
|
+
}
|
|
27110
|
+
}
|
|
26737
27111
|
this.core.store.state?.activeTool?.handleWheel(ev);
|
|
26738
27112
|
}
|
|
26739
27113
|
handlePointerDown(ev) {
|
|
@@ -27569,7 +27943,7 @@ const KritzelEngine = class {
|
|
|
27569
27943
|
/**
|
|
27570
27944
|
* Generates an SVG string from the currently selected objects.
|
|
27571
27945
|
* Creates clean, standards-compliant SVG markup by directly serializing object properties.
|
|
27572
|
-
* @param options - Optional export settings (theme, padding).
|
|
27946
|
+
* @param options - Optional export settings (theme, padding, raster-safe mode for canvas export).
|
|
27573
27947
|
* @returns SVG markup string, or null if no objects are selected.
|
|
27574
27948
|
*/
|
|
27575
27949
|
async getSelectedObjectsAsSvgString(options) {
|
|
@@ -27578,10 +27952,16 @@ const KritzelEngine = class {
|
|
|
27578
27952
|
return null;
|
|
27579
27953
|
}
|
|
27580
27954
|
const theme = options?.theme ?? this.core.themeManager.getStoredTheme();
|
|
27955
|
+
// Inline image bytes as data URLs so they survive both standalone SVG
|
|
27956
|
+
// files and rasterization to PNG (a `blob:` href is not loaded when an
|
|
27957
|
+
// SVG is drawn into a canvas, which otherwise yields a broken image).
|
|
27958
|
+
const imageDataUrls = await KritzelSvgExportHelper.resolveImageDataUrls(selectedObjects, this.core.assetResolver);
|
|
27581
27959
|
return KritzelSvgExportHelper.generateSvg(selectedObjects, {
|
|
27582
27960
|
theme,
|
|
27583
27961
|
padding: options?.padding ?? 0,
|
|
27584
27962
|
includeXmlDeclaration: true,
|
|
27963
|
+
rasterSafeForCanvas: options?.rasterSafeForCanvas ?? false,
|
|
27964
|
+
imageDataUrls,
|
|
27585
27965
|
});
|
|
27586
27966
|
}
|
|
27587
27967
|
/**
|
|
@@ -27620,6 +28000,9 @@ const KritzelEngine = class {
|
|
|
27620
28000
|
const svgString = await this.getSelectedObjectsAsSvgString({
|
|
27621
28001
|
theme: options?.theme,
|
|
27622
28002
|
padding: options?.padding,
|
|
28003
|
+
// Avoid foreignObject-based text serialization, which taints the
|
|
28004
|
+
// canvas in SVG->PNG conversion paths.
|
|
28005
|
+
rasterSafeForCanvas: true,
|
|
27623
28006
|
});
|
|
27624
28007
|
if (!svgString) {
|
|
27625
28008
|
return null;
|
|
@@ -27972,6 +28355,55 @@ const KritzelEngine = class {
|
|
|
27972
28355
|
return null;
|
|
27973
28356
|
}
|
|
27974
28357
|
}
|
|
28358
|
+
/**
|
|
28359
|
+
* Registers additional locale definitions (with optional partial term overrides).
|
|
28360
|
+
* @param locales - The locale definitions to register.
|
|
28361
|
+
*/
|
|
28362
|
+
async registerLocales(locales) {
|
|
28363
|
+
this.core.localizationManager.registerLocales(locales);
|
|
28364
|
+
this.core.localizationManager.setLocale(this.core.localizationManager.currentLocale);
|
|
28365
|
+
}
|
|
28366
|
+
/**
|
|
28367
|
+
* Sets the active locale (language) and re-renders the UI.
|
|
28368
|
+
* @param code - The locale code to activate, e.g. 'de'.
|
|
28369
|
+
*/
|
|
28370
|
+
async setLocale(code) {
|
|
28371
|
+
this.locale = code;
|
|
28372
|
+
this.core.localizationManager.setLocale(code);
|
|
28373
|
+
}
|
|
28374
|
+
/**
|
|
28375
|
+
* Gets the currently active locale code.
|
|
28376
|
+
*/
|
|
28377
|
+
async getLocale() {
|
|
28378
|
+
return this.core.localizationManager.currentLocale;
|
|
28379
|
+
}
|
|
28380
|
+
/**
|
|
28381
|
+
* Gets the list of available locale codes (built-in and registered).
|
|
28382
|
+
*/
|
|
28383
|
+
async getAvailableLocales() {
|
|
28384
|
+
return this.core.localizationManager.getAvailableLocales();
|
|
28385
|
+
}
|
|
28386
|
+
/**
|
|
28387
|
+
* Gets the list of available locales as `{ code, label }` options for a selector.
|
|
28388
|
+
*/
|
|
28389
|
+
async getAvailableLocaleOptions() {
|
|
28390
|
+
return this.core.localizationManager.getAvailableLocaleOptions();
|
|
28391
|
+
}
|
|
28392
|
+
/**
|
|
28393
|
+
* Resolves a term key to its translated string for the active locale.
|
|
28394
|
+
* @param key - The term key to resolve.
|
|
28395
|
+
* @param vars - Optional values for `{placeholder}` interpolation.
|
|
28396
|
+
*/
|
|
28397
|
+
async t(key, vars) {
|
|
28398
|
+
return this.core.localizationManager.translate(key, vars);
|
|
28399
|
+
}
|
|
28400
|
+
/**
|
|
28401
|
+
* Resolves every known term key for the active locale into a flat map.
|
|
28402
|
+
* Useful for UI layers that need to localize many strings at once.
|
|
28403
|
+
*/
|
|
28404
|
+
async getResolvedTerms() {
|
|
28405
|
+
return this.core.localizationManager.getAllTerms();
|
|
28406
|
+
}
|
|
27975
28407
|
core;
|
|
27976
28408
|
viewport;
|
|
27977
28409
|
contextMenuHandler;
|
|
@@ -28062,6 +28494,7 @@ const KritzelEngine = class {
|
|
|
28062
28494
|
// Clean up managers
|
|
28063
28495
|
this.core.cursorManager.cleanup();
|
|
28064
28496
|
this.core.themeManager.cleanup();
|
|
28497
|
+
this.core.licenseManager.destroy();
|
|
28065
28498
|
}
|
|
28066
28499
|
componentWillLoad() {
|
|
28067
28500
|
this.core.setEditorId(this.editorId);
|
|
@@ -28070,6 +28503,13 @@ const KritzelEngine = class {
|
|
|
28070
28503
|
}
|
|
28071
28504
|
const editorElement = this.host.closest('kritzel-editor');
|
|
28072
28505
|
this.core.themeManager.injectThemeEarly(editorElement || this.host);
|
|
28506
|
+
if (this.locales && this.locales.length > 0) {
|
|
28507
|
+
this.core.localizationManager.registerLocales(this.locales);
|
|
28508
|
+
}
|
|
28509
|
+
this.core.localizationManager.setFallbackLocale(this.fallbackLocale);
|
|
28510
|
+
this.core.localizationManager.setLocale(this.locale);
|
|
28511
|
+
this.core.licenseManager.validate(this.licenseKey);
|
|
28512
|
+
this.core.licenseManager.startPeriodicValidation();
|
|
28073
28513
|
this.core.setUser(this.user);
|
|
28074
28514
|
this.validateScaleMax(this.scaleMax);
|
|
28075
28515
|
this.validateScaleMin(this.scaleMin);
|
|
@@ -28374,7 +28814,7 @@ const KritzelEngine = class {
|
|
|
28374
28814
|
}
|
|
28375
28815
|
render() {
|
|
28376
28816
|
if (!this.viewport) {
|
|
28377
|
-
return (index.h(index.Host, null, this.core.store.state.isLoading && (index.h("div", { class: "workspace-loading-overlay" }, index.h("span", { class: "workspace-loading-spinner" }),
|
|
28817
|
+
return (index.h(index.Host, null, this.core.store.state.isLoading && (index.h("div", { class: "workspace-loading-overlay" }, index.h("span", { class: "workspace-loading-spinner" }), this.core.localizationManager.translate('engine.loading')))));
|
|
28378
28818
|
}
|
|
28379
28819
|
const currentTheme = this.core.themeManager.getStoredTheme();
|
|
28380
28820
|
const computedStyle = window.getComputedStyle(this.host);
|
|
@@ -28812,7 +29252,7 @@ const KritzelEngine = class {
|
|
|
28812
29252
|
}, this.core.store.selectionGroup?.objects || []);
|
|
28813
29253
|
}
|
|
28814
29254
|
this.hideContextMenu();
|
|
28815
|
-
}, onClose: () => this.hideContextMenu() })), this.core.store.objects?.hasAwareness && index.h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool instanceof schema_constants.KritzelEraserTool && !this.core.store.state.isScaling && index.h("kritzel-cursor-trail", { core: this.core })));
|
|
29255
|
+
}, onClose: () => this.hideContextMenu() })), this.core.store.objects?.hasAwareness && index.h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool instanceof schema_constants.KritzelEraserTool && !this.core.store.state.isScaling && index.h("kritzel-cursor-trail", { core: this.core }), !this.core.licenseManager.isLicensed && (index.h("kritzel-watermark", { core: this.core, label: this.core.localizationManager.translate('watermark.poweredBy') }))));
|
|
28816
29256
|
}
|
|
28817
29257
|
static get watchers() { return {
|
|
28818
29258
|
"workspace": [{
|
|
@@ -28854,9 +29294,21 @@ const KritzelEngine = class {
|
|
|
28854
29294
|
"theme": [{
|
|
28855
29295
|
"onThemeChange": 0
|
|
28856
29296
|
}],
|
|
29297
|
+
"licenseKey": [{
|
|
29298
|
+
"onLicenseKeyChange": 0
|
|
29299
|
+
}],
|
|
28857
29300
|
"themes": [{
|
|
28858
29301
|
"onThemesChange": 0
|
|
28859
29302
|
}],
|
|
29303
|
+
"locale": [{
|
|
29304
|
+
"onLocaleChange": 0
|
|
29305
|
+
}],
|
|
29306
|
+
"locales": [{
|
|
29307
|
+
"onLocalesChange": 0
|
|
29308
|
+
}],
|
|
29309
|
+
"fallbackLocale": [{
|
|
29310
|
+
"onFallbackLocaleChange": 0
|
|
29311
|
+
}],
|
|
28860
29312
|
"viewportBoundaryLeft": [{
|
|
28861
29313
|
"onViewportBoundaryLeftChange": 0
|
|
28862
29314
|
}],
|
|
@@ -28892,6 +29344,8 @@ const KritzelExport = class {
|
|
|
28892
29344
|
* The name of the current workspace, used as default filename
|
|
28893
29345
|
*/
|
|
28894
29346
|
workspaceName = 'workspace';
|
|
29347
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
29348
|
+
terms = {};
|
|
28895
29349
|
isDialogOpen = false;
|
|
28896
29350
|
previewUrl;
|
|
28897
29351
|
isLoading = false;
|
|
@@ -28901,10 +29355,12 @@ const KritzelExport = class {
|
|
|
28901
29355
|
exportPng;
|
|
28902
29356
|
exportSvg;
|
|
28903
29357
|
exportJson;
|
|
28904
|
-
tabs
|
|
28905
|
-
|
|
28906
|
-
|
|
28907
|
-
|
|
29358
|
+
get tabs() {
|
|
29359
|
+
return [
|
|
29360
|
+
{ id: 'viewport', label: this.terms['export.tabs.viewport'] ?? 'Export Viewport' },
|
|
29361
|
+
{ id: 'workspace', label: this.terms['export.tabs.workspace'] ?? 'Export Workspace' },
|
|
29362
|
+
];
|
|
29363
|
+
}
|
|
28908
29364
|
viewportFormatOptions = [
|
|
28909
29365
|
{ value: 'png', label: 'PNG' },
|
|
28910
29366
|
{ value: 'svg', label: 'SVG' },
|
|
@@ -28947,13 +29403,13 @@ const KritzelExport = class {
|
|
|
28947
29403
|
this.closeDialog();
|
|
28948
29404
|
};
|
|
28949
29405
|
renderViewportExport() {
|
|
28950
|
-
return (index.h("div", { class: "export-tab-content" }, this.previewUrl && (index.h("div", { class: "preview-container" }, index.h("img", { src: this.previewUrl, alt: "Viewport Preview" }))), index.h("kritzel-input", { label:
|
|
29406
|
+
return (index.h("div", { class: "export-tab-content" }, this.previewUrl && (index.h("div", { class: "preview-container" }, index.h("img", { src: this.previewUrl, alt: "Viewport Preview" }))), index.h("kritzel-input", { label: this.terms['export.filename.label'] ?? 'Filename', value: this.exportFilename, placeholder: this.terms['export.filename.placeholder'] ?? 'Enter filename', suffix: `.${this.viewportExportFormat}`, onValueChange: this.handleFilenameChange }), index.h("div", { class: "format-selection" }, index.h("label", null, this.terms['export.format.label'] ?? 'Format'), index.h("kritzel-dropdown", { options: this.viewportFormatOptions, value: this.viewportExportFormat, forceOpenDirection: "up", onValueChanged: this.handleViewportFormatChange }))));
|
|
28951
29407
|
}
|
|
28952
29408
|
renderWorkspaceExport() {
|
|
28953
|
-
return (index.h("div", { class: "export-tab-content" }, index.h("kritzel-input", { label:
|
|
29409
|
+
return (index.h("div", { class: "export-tab-content" }, index.h("kritzel-input", { label: this.terms['export.filename.label'] ?? 'Filename', value: this.exportFilename, placeholder: this.terms['export.filename.placeholder'] ?? 'Enter filename', suffix: ".json", onValueChange: this.handleFilenameChange })));
|
|
28954
29410
|
}
|
|
28955
29411
|
render() {
|
|
28956
|
-
return (index.h(index.Host, { key: '
|
|
29412
|
+
return (index.h(index.Host, { key: 'ff6ce7e5d3a0a7a024148529f86bf3ec7ffb0333' }, index.h("kritzel-dialog", { key: '9051d262450af5fbe98959092f6bb0ac25ab43ce', isOpen: this.isDialogOpen, dialogTitle: this.terms['export.dialogTitle'] ?? 'Export', closable: true, contained: true, onDialogClose: this.closeDialog }, index.h("div", { key: '21f404a2101d5cf1d24aeeee663d8fb1854b9574', class: "export-content" }, index.h("kritzel-pill-tabs", { key: '80db6cda288d1b7019387a2f1ade278475ad6e24', tabs: this.tabs, value: this.activeTab, onValueChange: this.handleTabChange }), this.activeTab === 'viewport' && this.renderViewportExport(), this.activeTab === 'workspace' && this.renderWorkspaceExport(), index.h("button", { key: '45809f91ddd63c74f5a4b3a2e266919f244c6109', class: "export-primary-button", onClick: this.handleExport }, this.terms['export.exportButton'] ?? 'Export')))));
|
|
28957
29413
|
}
|
|
28958
29414
|
};
|
|
28959
29415
|
KritzelExport.style = kritzelExportCss();
|
|
@@ -28968,7 +29424,7 @@ const KritzelFont = class {
|
|
|
28968
29424
|
size = 24;
|
|
28969
29425
|
color = '#000000';
|
|
28970
29426
|
render() {
|
|
28971
|
-
return (index.h(index.Host, { key: '
|
|
29427
|
+
return (index.h(index.Host, { key: '49c44f7fef61bd7116e63bbe9522b0a0e22de116' }, index.h("div", { key: '4d130682f67e9c0d758cb6194e6a95f15bceb2ee', class: "font-preview", style: {
|
|
28972
29428
|
fontFamily: this.fontFamily,
|
|
28973
29429
|
fontSize: `${this.size}px`,
|
|
28974
29430
|
color: this.color
|
|
@@ -29043,7 +29499,8 @@ const KritzelFontSize = class {
|
|
|
29043
29499
|
}
|
|
29044
29500
|
render() {
|
|
29045
29501
|
const color = 'var(--kritzel-global-text-primary)';
|
|
29046
|
-
|
|
29502
|
+
const sizes = this.sizes ?? [];
|
|
29503
|
+
return (index.h(index.Host, { key: '2083b05b3fdc9940c26dd90dbf9e097564ee976d' }, sizes.map(size => (index.h("div", { tabIndex: 0, class: {
|
|
29047
29504
|
'size-container': true,
|
|
29048
29505
|
'selected': this.selectedSize === size,
|
|
29049
29506
|
}, onClick: () => this.handleSizeClick(size), onKeyDown: event => this.handleKeyDown(event, size) }, index.h("kritzel-font", { fontFamily: this.fontFamily, size: size, color: color }))))));
|
|
@@ -29110,7 +29567,7 @@ const KritzelInput = class {
|
|
|
29110
29567
|
this.valueChange.emit(input.value);
|
|
29111
29568
|
};
|
|
29112
29569
|
render() {
|
|
29113
|
-
return (index.h(index.Host, { key: '
|
|
29570
|
+
return (index.h(index.Host, { key: '8584ea0fa1a2cf0b9518ea978303837da5bfaf31' }, index.h("div", { key: 'e9f3ac340f17580221d1a86c8eb913fce2acdf49', class: "input-container" }, this.label && index.h("label", { key: 'b0d4c0250b07d83a3cd99e0ab18ed672a29de5f0', class: "input-label" }, this.label), index.h("div", { key: '5044bcff621d6c6850ef3d225608427401b75ebd', class: { 'input-wrapper': true, 'has-suffix': !!this.suffix } }, index.h("input", { key: 'f8d057840e975d900c37a891268f39edb5128d49', type: this.type, class: "text-input", value: this.inputValue, placeholder: this.placeholder, disabled: this.disabled, onInput: this.handleInput }), this.suffix && index.h("span", { key: '4ae299b88798767b13e7126f88d3bd4703c91938', class: "input-suffix" }, this.suffix)))));
|
|
29114
29571
|
}
|
|
29115
29572
|
static get watchers() { return {
|
|
29116
29573
|
"value": [{
|
|
@@ -29250,7 +29707,7 @@ const KritzelLoginDialog = class {
|
|
|
29250
29707
|
this.dialogClosed.emit();
|
|
29251
29708
|
};
|
|
29252
29709
|
render() {
|
|
29253
|
-
return (index.h(index.Host, { key: '
|
|
29710
|
+
return (index.h(index.Host, { key: '443d817d6eba7b9fcd31cab652293d7c01fc5ffa' }, index.h("kritzel-dialog", { key: '55214d78abb10f7e2ba789e10d98bf7f3287ff6a', dialogTitle: this.dialogTitle, isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, size: "small", contained: true }, index.h("div", { key: '31806a7a7c98c2210b7f60d2e0816a8ebc14aff3', class: "login-content" }, this.subtitle && (index.h("p", { key: '7edb2bc7d25cb3c8589594791822e62d035cd3a6', class: "login-subtitle" }, this.subtitle)), index.h("div", { key: '3b7731d9cfb98915ebe07b54a07991e03716ce5c', class: "login-providers" }, this.providers.map(provider => (index.h("button", { key: provider.name, class: {
|
|
29254
29711
|
'provider-button': true,
|
|
29255
29712
|
'is-loading': this.loadingProvider === provider.name,
|
|
29256
29713
|
'is-disabled': this.loadingProvider !== null && this.loadingProvider !== provider.name,
|
|
@@ -29356,15 +29813,15 @@ const KritzelMasterDetail = class {
|
|
|
29356
29813
|
const selectedItem = this.items.find(item => item.id === this.selectedItemId);
|
|
29357
29814
|
const panelId = 'master-detail-panel';
|
|
29358
29815
|
const selectedTabId = selectedItem ? `tab-${selectedItem.id}` : undefined;
|
|
29359
|
-
return (index.h(index.Host, { key: '
|
|
29816
|
+
return (index.h(index.Host, { key: '6429c72aaf47f08ba0bdf5e64829b133339dafab' }, index.h("div", { key: '02e4616c67843632d2291abe347ee6ef7a660b12', class: {
|
|
29360
29817
|
'master-detail-container': true,
|
|
29361
29818
|
'is-mobile-detail-visible': this.showMobileDetail,
|
|
29362
|
-
} }, index.h("nav", { key: '
|
|
29819
|
+
} }, index.h("nav", { key: '35cf3e8f97819a313fa6c57cde0faf05677997eb', class: "master-menu", role: "tablist", "aria-orientation": "vertical", "aria-label": "Settings categories" }, this.items.map((item, index$1) => (index.h("button", { key: item.id, id: `tab-${item.id}`, ref: el => this.setTabRef(el, index$1), class: {
|
|
29363
29820
|
'menu-item': true,
|
|
29364
29821
|
'is-selected': item.id === this.selectedItemId,
|
|
29365
29822
|
'is-disabled': !!item.disabled,
|
|
29366
29823
|
'is-focused': index$1 === this.focusedIndex,
|
|
29367
|
-
}, role: "tab", "aria-selected": item.id === this.selectedItemId ? 'true' : 'false', "aria-controls": panelId, "aria-disabled": item.disabled ? 'true' : undefined, tabIndex: this.getTabIndex(item, index$1), disabled: item.disabled, onClick: () => this.handleItemClick(item), onKeyDown: e => this.handleKeyDown(e, item, index$1), onFocus: () => this.handleFocus(index$1), onBlur: this.handleBlur }, item.icon && (index.h("kritzel-icon", { name: item.icon, size: 20, class: "menu-item-icon" })), index.h("span", { class: "menu-item-label" }, item.label), index.h("span", { class: "menu-item-chevron", "aria-hidden": "true" }, index.h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("path", { d: "m9 18 6-6-6-6" }))))))), index.h("div", { key: '
|
|
29824
|
+
}, role: "tab", "aria-selected": item.id === this.selectedItemId ? 'true' : 'false', "aria-controls": panelId, "aria-disabled": item.disabled ? 'true' : undefined, tabIndex: this.getTabIndex(item, index$1), disabled: item.disabled, onClick: () => this.handleItemClick(item), onKeyDown: e => this.handleKeyDown(e, item, index$1), onFocus: () => this.handleFocus(index$1), onBlur: this.handleBlur }, item.icon && (index.h("kritzel-icon", { name: item.icon, size: 20, class: "menu-item-icon" })), index.h("span", { class: "menu-item-label" }, item.label), index.h("span", { class: "menu-item-chevron", "aria-hidden": "true" }, index.h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }, index.h("path", { d: "m9 18 6-6-6-6" }))))))), index.h("div", { key: 'cc7c69eb7ef02096fb76dbce310740d21019e72f', id: panelId, class: "detail-panel", role: "tabpanel", "aria-labelledby": selectedTabId }, index.h("button", { key: 'd10898c7eb8ec6d993024c7833e1f765a7b93079', class: "mobile-back-button", onClick: this.handleBackClick, "aria-label": "Back to menu" }, index.h("kritzel-icon", { key: '5395af1bce2b91ade970ad68b1bb87b59e771dff', name: "chevron-left", size: 20, class: "mobile-back-icon" }), "Back"), index.h("slot", { key: '7a5a1ef33081c117f1b16f1da887577bd97d3681' })))));
|
|
29368
29825
|
}
|
|
29369
29826
|
static get watchers() { return {
|
|
29370
29827
|
"selectedItemId": [{
|
|
@@ -29437,7 +29894,7 @@ const KritzelMenu = class {
|
|
|
29437
29894
|
this.itemCloseChildMenu.emit(event.detail);
|
|
29438
29895
|
};
|
|
29439
29896
|
render() {
|
|
29440
|
-
return (index.h(index.Host, { key: '
|
|
29897
|
+
return (index.h(index.Host, { key: '4e4e510d2b1b5834ba12739d95e7c33268c005a6', tabIndex: 0, onClick: e => e.stopPropagation() }, this.openChildMenuItem && index.h("div", { key: 'ee60d7f4ceefda5fcdcfb64956b20d42b703c231', class: "has-open-child-overlay", onClick: this.onOverlayClick }), this.items.map(item => (index.h("kritzel-menu-item", { key: item.id, "data-testid": `menu-item-${item.id}`, item: item, parent: this.parent, style: { pointerEvents: this.editingMenuItem && !item.isEditing ? 'none' : 'auto' }, onItemSelect: this.handleItemSelect, onItemSave: this.handleSave, onItemCancel: this.handleCancel, onItemToggleChildMenu: this.handleToggleChildMenu, onItemCloseChildMenu: this.handleCloseChildMenu })))));
|
|
29441
29898
|
}
|
|
29442
29899
|
};
|
|
29443
29900
|
KritzelMenu.style = kritzelMenuCss();
|
|
@@ -29542,12 +29999,12 @@ const KritzelMenuItem = class {
|
|
|
29542
29999
|
];
|
|
29543
30000
|
}
|
|
29544
30001
|
render() {
|
|
29545
|
-
return (index.h(index.Host, { key: '
|
|
30002
|
+
return (index.h(index.Host, { key: 'ac91e3534c71074634ba053adc02f924e3fb5e14', tabIndex: this.item.isDisabled ? -1 : 0, class: {
|
|
29546
30003
|
'selected': this.item.isSelected,
|
|
29547
30004
|
'editing': this.item.isEditing,
|
|
29548
30005
|
'disabled': this.item.isDisabled,
|
|
29549
30006
|
'child-open': this.item.isChildMenuOpen,
|
|
29550
|
-
}, onClick: this.handleItemSelect }, index.h("div", { key: '
|
|
30007
|
+
}, onClick: this.handleItemSelect }, index.h("div", { key: 'f49cf8a96f7394e244ce53d3933137325221d578', class: "menu-item-overlay" }), this.item.isEditing ? this.renderEditMode() : this.renderViewMode()));
|
|
29551
30008
|
}
|
|
29552
30009
|
static get watchers() { return {
|
|
29553
30010
|
"item": [{
|
|
@@ -29587,6 +30044,8 @@ const KritzelMoreMenu = class {
|
|
|
29587
30044
|
* Offset Y for the portal positioning
|
|
29588
30045
|
*/
|
|
29589
30046
|
offsetY = 4;
|
|
30047
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
30048
|
+
terms = {};
|
|
29590
30049
|
/**
|
|
29591
30050
|
* Emitted when a menu item is selected
|
|
29592
30051
|
*/
|
|
@@ -29618,7 +30077,7 @@ const KritzelMoreMenu = class {
|
|
|
29618
30077
|
this.closeMenu();
|
|
29619
30078
|
};
|
|
29620
30079
|
render() {
|
|
29621
|
-
return (index.h(index.Host, { key: '
|
|
30080
|
+
return (index.h(index.Host, { key: '1fe90a065ac35d1c8d2e9159d006b09e104750a3', class: { mobile: this.isTouchDevice }, style: { display: this.visible ? '' : 'none' } }, index.h("div", { key: '734234df7d24f712fa80c3871209142fed2b5ac2', class: { 'more-menu-wrapper': true, visible: this.visible } }, index.h("button", { key: 'a6a56bd5714a8780339390904f0469b395748ba9', class: "more-menu-button", "data-testid": "more-menu-button", onClick: this.toggleMenu, "aria-label": this.terms['moreMenu.ariaLabel'] ?? 'More options' }, index.h("kritzel-icon", { key: 'a4405ef4b8219f28fec095d4a56ac0aa027a9564', name: this.icon, size: this.iconSize })), index.h("kritzel-portal", { key: '99aa8a87844232ec079b48f95afab54cbfe51a0b', anchor: this.menuAnchor, offsetY: this.offsetY, onClose: this.closeMenu }, index.h("kritzel-menu", { key: 'b6861ae2d553ebf5f5af7448c2b053576a380e8c', items: this.visibleItems, onItemSelect: this.handleMenuItemSelect })))));
|
|
29622
30081
|
}
|
|
29623
30082
|
};
|
|
29624
30083
|
KritzelMoreMenu.style = kritzelMoreMenuCss();
|
|
@@ -29716,7 +30175,7 @@ const KritzelNumericInput = class {
|
|
|
29716
30175
|
this.valueChange.emit(newValue);
|
|
29717
30176
|
};
|
|
29718
30177
|
render() {
|
|
29719
|
-
return (index.h(index.Host, { key: '
|
|
30178
|
+
return (index.h(index.Host, { key: '3679786121f22a0aacb1b57701764b0bd0bf02f5' }, index.h("div", { key: 'e88251c356332f29d93f6a3d82f5154188243e4c', class: "input-container" }, this.label && index.h("label", { key: 'cb4d64a5acf94794a5876bc61dc13dd8159ad055', class: "input-label" }, this.label), index.h("div", { key: '9faad300f263e871322b68635feefb08172bd15c', class: "input-wrapper" }, index.h("input", { key: 'dd58ade6fe8454a3e4f67fddbb135d279f1147a8', type: "number", class: "numeric-input", title: "", min: this.min === Number.MIN_SAFE_INTEGER ? undefined : this.min, max: this.max === Number.MAX_SAFE_INTEGER ? undefined : this.max, step: this.step, value: this.inputValue, placeholder: this.placeholder, onInput: this.handleInput, onBlur: this.handleBlur, onKeyDown: this.handleKeyDown, onInvalid: this.handleInvalid }), index.h("div", { key: 'a959beb441fe2143dc9c1c69347194e024362927', class: "spinner-buttons" }, index.h("button", { key: '6e2129f36080317e68b6fe1c05e69ea4e655fd20', type: "button", class: "spinner-button spinner-up", onClick: this.handleIncrement, tabIndex: -1, "aria-label": "Increase value" }, index.h("svg", { key: '47b5e178f82ef4eb6f2c5d888496ed95683c2f6d', viewBox: "0 0 10 6", class: "spinner-icon" }, index.h("path", { key: '6d5eb31ac5829b1e024822786beaafd347081c7e', d: "M1 5L5 1L9 5", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))), index.h("button", { key: '5a897f0b29ce89d5bd94327d2055753d06148c89', type: "button", class: "spinner-button spinner-down", onClick: this.handleDecrement, tabIndex: -1, "aria-label": "Decrease value" }, index.h("svg", { key: '19ff176c07e1c2a18f708debc7c7f3953f2219cb', viewBox: "0 0 10 6", class: "spinner-icon" }, index.h("path", { key: '0c1289eb009b62ea36f7397811f553a4e7e669f6', d: "M1 1L5 5L9 1", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))))))));
|
|
29720
30179
|
}
|
|
29721
30180
|
static get watchers() { return {
|
|
29722
30181
|
"value": [{
|
|
@@ -29755,7 +30214,7 @@ const KritzelOpacitySlider = class {
|
|
|
29755
30214
|
}
|
|
29756
30215
|
render() {
|
|
29757
30216
|
const percentage = this.getPercentage();
|
|
29758
|
-
return (index.h(index.Host, { key: '
|
|
30217
|
+
return (index.h(index.Host, { key: '9b580f61b9113950b7dff5339879374f7882e1bd' }, index.h("div", { key: '80fb336580c49d4d7026993499b9c008ac2a4594', class: "opacity-container" }, index.h("div", { key: 'fcdd8e523d5f2ff4758a4839f2f43cbdabba4c5a', class: "slider-wrapper" }, index.h("input", { key: '914473676adc7cb8974c55b82ba1abf5b2787288', type: "range", class: "opacity-slider", min: this.min, max: this.max, step: this.step, value: this.value, onInput: (e) => this.handleInput(e), style: {
|
|
29759
30218
|
'--slider-progress': `${percentage}%`,
|
|
29760
30219
|
'--kritzel-opacity-slider-thumb-border-color': this.previewColor,
|
|
29761
30220
|
} })))));
|
|
@@ -30108,7 +30567,7 @@ const KritzelPortal = class {
|
|
|
30108
30567
|
this.portal.style.visibility = 'visible';
|
|
30109
30568
|
}
|
|
30110
30569
|
render() {
|
|
30111
|
-
return (index.h(index.Host, { key: '
|
|
30570
|
+
return (index.h(index.Host, { key: 'f4ee3156b094ff1126db417f8396ca6cd0eb9aa4', style: { display: this.anchor ? 'block' : 'none' } }, index.h("slot", { key: '87812f4ddd50a29c8a76938e8778500a4873a30c' })));
|
|
30112
30571
|
}
|
|
30113
30572
|
static get watchers() { return {
|
|
30114
30573
|
"anchor": [{
|
|
@@ -30122,7 +30581,7 @@ const KritzelPortal = class {
|
|
|
30122
30581
|
* This file is auto-generated by the version bump scripts.
|
|
30123
30582
|
* Do not modify manually.
|
|
30124
30583
|
*/
|
|
30125
|
-
const KRITZEL_VERSION = '0.3.
|
|
30584
|
+
const KRITZEL_VERSION = '0.3.18';
|
|
30126
30585
|
|
|
30127
30586
|
const kritzelSettingsCss = () => `:host{display:contents}kritzel-dialog{--kritzel-dialog-body-padding:0;--kritzel-dialog-width-large:800px;--kritzel-dialog-height-large:500px}.footer-button{padding:8px 16px;border-radius:6px;cursor:pointer;font-size:14px}.cancel-button{border:1px solid #ebebeb;background:#fff;color:inherit}.cancel-button:hover{background:#f5f5f5}.settings-content{padding:0}.settings-content h3{margin:0 0 16px 0;font-size:18px;font-weight:600;color:var(--kritzel-settings-content-heading-color, #333333)}.settings-content p{margin:0;font-size:14px;color:var(--kritzel-settings-content-text-color, #666666);line-height:1.5}.settings-group{display:flex;flex-direction:column;gap:24px}.settings-item{display:flex;flex-direction:column;gap:8px}.settings-row{display:flex;align-items:center;justify-content:space-between;gap:16px}.settings-label{font-size:14px;font-weight:600;color:var(--kritzel-settings-label-color, #333333);margin:0 0 4px 0}.settings-description{font-size:12px;color:var(--kritzel-settings-description-color, #888888);margin:0;line-height:1.4}.shortcuts-list{display:flex;flex-direction:column;gap:24px}.shortcuts-category{display:flex;flex-direction:column;gap:8px}.shortcuts-category-title{font-size:14px;font-weight:600;color:var(--kritzel-settings-label-color, #333333);margin:0 0 4px 0}.shortcuts-group{display:flex;flex-direction:column;gap:4px}.shortcut-item{display:flex;justify-content:space-between;align-items:center;padding:6px 8px;border-radius:4px;background:var(--kritzel-settings-shortcut-item-bg, rgba(0, 0, 0, 0.02))}.shortcut-label{font-size:14px;color:var(--kritzel-settings-content-text-color, #666666)}.shortcut-key{font-family:monospace;font-size:12px;padding:2px 8px;border-radius:4px;background:var(--kritzel-settings-shortcut-key-bg, #f0f0f0);color:var(--kritzel-settings-shortcut-key-color, #333333);border:1px solid var(--kritzel-settings-shortcut-key-border, #ddd)}`;
|
|
30128
30587
|
|
|
@@ -30139,13 +30598,7 @@ const DEFAULT_DEBUG_INFO = {
|
|
|
30139
30598
|
showSyncProviderInfo: true,
|
|
30140
30599
|
showMigrationInfo: true,
|
|
30141
30600
|
};
|
|
30142
|
-
const
|
|
30143
|
-
{ id: 'general', label: 'General', icon: 'settings' },
|
|
30144
|
-
{ id: 'viewport', label: 'Viewport', icon: 'viewport' },
|
|
30145
|
-
{ id: 'shortcuts', label: 'Keyboard Shortcuts', icon: 'command' },
|
|
30146
|
-
{ id: 'developer', label: 'Developer Options', icon: 'braces' },
|
|
30147
|
-
{ id: 'about', label: 'About', icon: 'info' },
|
|
30148
|
-
];
|
|
30601
|
+
const SETTINGS_CATEGORY_IDS = ['general', 'viewport', 'shortcuts', 'developer', 'about'];
|
|
30149
30602
|
const KritzelSettings = class {
|
|
30150
30603
|
constructor(hostRef) {
|
|
30151
30604
|
index.registerInstance(this, hostRef);
|
|
@@ -30154,7 +30607,11 @@ const KritzelSettings = class {
|
|
|
30154
30607
|
get host() { return index.getElement(this); }
|
|
30155
30608
|
/** Keyboard shortcuts to display in the settings dialog */
|
|
30156
30609
|
availableThemes = ['light', 'dark'];
|
|
30610
|
+
/** Available locales as `{ code, label }` options for the language selector. */
|
|
30611
|
+
availableLocales = [];
|
|
30157
30612
|
shortcuts = [];
|
|
30613
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
30614
|
+
terms = {};
|
|
30158
30615
|
/** Current settings values. Used to initialize and sync the component's internal state. */
|
|
30159
30616
|
settings;
|
|
30160
30617
|
onSettingsPropChange(newSettings) {
|
|
@@ -30163,11 +30620,12 @@ const KritzelSettings = class {
|
|
|
30163
30620
|
}
|
|
30164
30621
|
}
|
|
30165
30622
|
isDialogOpen = false;
|
|
30166
|
-
selectedCategoryId =
|
|
30623
|
+
selectedCategoryId = SETTINGS_CATEGORY_IDS[0];
|
|
30167
30624
|
scaleMin = DEFAULT_SCALE_MIN;
|
|
30168
30625
|
scaleMax = DEFAULT_SCALE_MAX;
|
|
30169
30626
|
lockDrawingScale = DEFAULT_LOCK_DRAWING_SCALE;
|
|
30170
30627
|
theme = 'light';
|
|
30628
|
+
locale = 'en';
|
|
30171
30629
|
viewportBoundaryLeft = DEFAULT_VIEWPORT_BOUNDARY_LEFT;
|
|
30172
30630
|
viewportBoundaryRight = DEFAULT_VIEWPORT_BOUNDARY_RIGHT;
|
|
30173
30631
|
viewportBoundaryTop = DEFAULT_VIEWPORT_BOUNDARY_TOP;
|
|
@@ -30193,6 +30651,9 @@ const KritzelSettings = class {
|
|
|
30193
30651
|
if (typeof settings.theme === 'string') {
|
|
30194
30652
|
this.theme = settings.theme;
|
|
30195
30653
|
}
|
|
30654
|
+
if (typeof settings.locale === 'string') {
|
|
30655
|
+
this.locale = settings.locale;
|
|
30656
|
+
}
|
|
30196
30657
|
if (typeof settings.viewportBoundaryLeft === 'number') {
|
|
30197
30658
|
this.viewportBoundaryLeft = settings.viewportBoundaryLeft;
|
|
30198
30659
|
}
|
|
@@ -30215,6 +30676,7 @@ const KritzelSettings = class {
|
|
|
30215
30676
|
scaleMax: this.scaleMax,
|
|
30216
30677
|
lockDrawingScale: this.lockDrawingScale,
|
|
30217
30678
|
theme: this.theme,
|
|
30679
|
+
locale: this.locale,
|
|
30218
30680
|
viewportBoundaryLeft: this.viewportBoundaryLeft,
|
|
30219
30681
|
viewportBoundaryRight: this.viewportBoundaryRight,
|
|
30220
30682
|
viewportBoundaryTop: this.viewportBoundaryTop,
|
|
@@ -30239,6 +30701,10 @@ const KritzelSettings = class {
|
|
|
30239
30701
|
this.theme = event.detail;
|
|
30240
30702
|
this.emitSettings();
|
|
30241
30703
|
};
|
|
30704
|
+
handleLocaleChange = (event) => {
|
|
30705
|
+
this.locale = event.detail;
|
|
30706
|
+
this.emitSettings();
|
|
30707
|
+
};
|
|
30242
30708
|
handleViewportBoundaryLeftChange = (event) => {
|
|
30243
30709
|
this.viewportBoundaryLeft = event.detail ?? DEFAULT_VIEWPORT_BOUNDARY_LEFT;
|
|
30244
30710
|
this.emitSettings();
|
|
@@ -30294,24 +30760,52 @@ const KritzelSettings = class {
|
|
|
30294
30760
|
}
|
|
30295
30761
|
return grouped;
|
|
30296
30762
|
}
|
|
30763
|
+
/**
|
|
30764
|
+
* Resolves a localized string from the supplied {@link terms} map, falling
|
|
30765
|
+
* back to the provided English default when the key is missing.
|
|
30766
|
+
*/
|
|
30767
|
+
t(key, fallback) {
|
|
30768
|
+
return this.terms[key] ?? fallback;
|
|
30769
|
+
}
|
|
30770
|
+
get categories() {
|
|
30771
|
+
const icons = {
|
|
30772
|
+
general: 'settings',
|
|
30773
|
+
viewport: 'viewport',
|
|
30774
|
+
shortcuts: 'command',
|
|
30775
|
+
developer: 'braces',
|
|
30776
|
+
about: 'info',
|
|
30777
|
+
};
|
|
30778
|
+
const labels = {
|
|
30779
|
+
general: { key: 'settings.categories.general', fallback: 'General' },
|
|
30780
|
+
viewport: { key: 'settings.categories.viewport', fallback: 'Viewport' },
|
|
30781
|
+
shortcuts: { key: 'settings.categories.shortcuts', fallback: 'Keyboard Shortcuts' },
|
|
30782
|
+
developer: { key: 'settings.categories.developer', fallback: 'Developer Options' },
|
|
30783
|
+
about: { key: 'settings.categories.about', fallback: 'About' },
|
|
30784
|
+
};
|
|
30785
|
+
return SETTINGS_CATEGORY_IDS.map(id => ({
|
|
30786
|
+
id,
|
|
30787
|
+
label: this.t(labels[id].key, labels[id].fallback),
|
|
30788
|
+
icon: icons[id],
|
|
30789
|
+
}));
|
|
30790
|
+
}
|
|
30297
30791
|
renderCategoryContent() {
|
|
30298
30792
|
switch (this.selectedCategoryId) {
|
|
30299
30793
|
case 'general':
|
|
30300
|
-
return (index.h("div", { class: "settings-content" }, index.h("h3", null,
|
|
30794
|
+
return (index.h("div", { class: "settings-content" }, index.h("h3", null, this.t('settings.general.title', 'General Settings')), index.h("div", { class: "settings-group" }, index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.general.theme.label', 'Theme')), index.h("p", { class: "settings-description" }, this.t('settings.general.theme.description', 'Select a registered color theme for the editor interface.')), index.h("kritzel-dropdown", { options: this.availableThemes.map(t => ({ value: t, label: t })), value: this.theme, onValueChanged: this.handleThemeChange })), this.availableLocales.length > 0 && (index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.general.language.label', 'Language')), index.h("p", { class: "settings-description" }, this.t('settings.general.language.description', 'Select the display language for the editor interface.')), index.h("kritzel-dropdown", { options: this.availableLocales.map(l => ({ value: l.code, label: l.label })), value: this.locale, onValueChanged: this.handleLocaleChange }))), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.general.lockDrawingScale.label', 'Lock Drawing Scale')), index.h("p", { class: "settings-description" }, this.t('settings.general.lockDrawingScale.description', 'When enabled, drawn objects maintain a fixed visual size regardless of the current zoom level.')), index.h("kritzel-slide-toggle", { checked: this.lockDrawingScale, label: this.t('settings.general.lockDrawingScale.label', 'Lock Drawing Scale'), onCheckedChange: this.handleLockDrawingScaleChange })))));
|
|
30301
30795
|
case 'viewport':
|
|
30302
|
-
return (index.h("div", { class: "settings-content" }, index.h("h3", null,
|
|
30796
|
+
return (index.h("div", { class: "settings-content" }, index.h("h3", null, this.t('settings.viewport.title', 'Viewport Settings')), index.h("div", { class: "settings-group" }, index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.viewport.minZoom.label', 'Minimum Zoom Level')), index.h("p", { class: "settings-description" }, this.t('settings.viewport.minZoom.description', 'Sets the minimum zoom level. Lower values allow zooming out further to see more of the canvas.')), index.h("kritzel-numeric-input", { value: this.scaleMin, min: 0.0001, max: 1, step: 0.0001, onValueChange: this.handleScaleMinChange })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.viewport.maxZoom.label', 'Maximum Zoom Level')), index.h("p", { class: "settings-description" }, this.t('settings.viewport.maxZoom.description', 'Sets the maximum zoom level. Higher values allow zooming in closer for detailed work.')), index.h("kritzel-numeric-input", { value: this.scaleMax, min: 1, max: 1000, step: 1, onValueChange: this.handleScaleMaxChange })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryLeft.label', 'Viewport Boundary Left')), index.h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryLeft.description', 'Left boundary in world coordinates. Set to limit how far left the viewport can pan.')), index.h("kritzel-numeric-input", { value: this.viewportBoundaryLeft, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryLeftChange })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryRight.label', 'Viewport Boundary Right')), index.h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryRight.description', 'Right boundary in world coordinates. Set to limit how far right the viewport can pan.')), index.h("kritzel-numeric-input", { value: this.viewportBoundaryRight, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryRightChange })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryTop.label', 'Viewport Boundary Top')), index.h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryTop.description', 'Top boundary in world coordinates. Set to limit how far up the viewport can pan.')), index.h("kritzel-numeric-input", { value: this.viewportBoundaryTop, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryTopChange })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryBottom.label', 'Viewport Boundary Bottom')), index.h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryBottom.description', 'Bottom boundary in world coordinates. Set to limit how far down the viewport can pan.')), index.h("kritzel-numeric-input", { value: this.viewportBoundaryBottom, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryBottomChange })))));
|
|
30303
30797
|
case 'shortcuts':
|
|
30304
|
-
return (index.h("div", { class: "settings-content" }, index.h("h3", null,
|
|
30798
|
+
return (index.h("div", { class: "settings-content" }, index.h("h3", null, this.t('settings.shortcuts.title', 'Keyboard Shortcuts')), index.h("div", { class: "shortcuts-list" }, Array.from(this.groupShortcutsByCategory()).map(([category, shortcuts]) => (index.h("div", { class: "shortcuts-category", key: category }, index.h("h4", { class: "shortcuts-category-title" }, category), index.h("div", { class: "shortcuts-group" }, shortcuts.map(shortcut => (index.h("div", { class: "shortcut-item", key: shortcut.key + shortcut.label }, index.h("span", { class: "shortcut-label" }, shortcut.label), index.h("kbd", { class: "shortcut-key" }, this.formatKeyCombo(shortcut))))))))))));
|
|
30305
30799
|
case 'developer':
|
|
30306
|
-
return (index.h("div", { class: "settings-content" }, index.h("h3", null,
|
|
30800
|
+
return (index.h("div", { class: "settings-content" }, index.h("h3", null, this.t('settings.developer.title', 'Developer Options')), index.h("div", { class: "settings-group" }, index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.developer.showViewportInfo.label', 'Show Viewport Info')), index.h("p", { class: "settings-description" }, this.t('settings.developer.showViewportInfo.description', 'Display viewport debug information such as position, zoom level, and boundaries.')), index.h("kritzel-slide-toggle", { checked: this.debugInfo.showViewportInfo, label: this.t('settings.developer.showViewportInfo.label', 'Show Viewport Info'), onCheckedChange: this.handleDebugInfoChange('showViewportInfo') })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.developer.showObjectInfo.label', 'Show Object Info')), index.h("p", { class: "settings-description" }, this.t('settings.developer.showObjectInfo.description', 'Display debug information about objects on the canvas.')), index.h("kritzel-slide-toggle", { checked: this.debugInfo.showObjectInfo, label: this.t('settings.developer.showObjectInfo.label', 'Show Object Info'), onCheckedChange: this.handleDebugInfoChange('showObjectInfo') })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.developer.showSyncProviderInfo.label', 'Show Sync Provider Info')), index.h("p", { class: "settings-description" }, this.t('settings.developer.showSyncProviderInfo.description', 'Display debug information about the sync provider connection status.')), index.h("kritzel-slide-toggle", { checked: this.debugInfo.showSyncProviderInfo, label: this.t('settings.developer.showSyncProviderInfo.label', 'Show Sync Provider Info'), onCheckedChange: this.handleDebugInfoChange('showSyncProviderInfo') })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, this.t('settings.developer.showMigrationInfo.label', 'Show Migration Info')), index.h("p", { class: "settings-description" }, this.t('settings.developer.showMigrationInfo.description', 'Display debug information about data migrations.')), index.h("kritzel-slide-toggle", { checked: this.debugInfo.showMigrationInfo, label: this.t('settings.developer.showMigrationInfo.label', 'Show Migration Info'), onCheckedChange: this.handleDebugInfoChange('showMigrationInfo') })))));
|
|
30307
30801
|
case 'about':
|
|
30308
|
-
return (index.h("div", { class: "settings-content" }, index.h("h3", null,
|
|
30802
|
+
return (index.h("div", { class: "settings-content" }, index.h("h3", null, this.t('settings.about.title', 'About')), index.h("p", null, this.t('settings.about.description', 'Kritzel - A drawing application')), index.h("p", { class: "version-info" }, "Version ", KRITZEL_VERSION), index.h("p", { class: "version-info" }, "App-State Schema v", schema_constants.CURRENT_APP_STATE_SCHEMA_VERSION), index.h("p", { class: "version-info" }, "Workspace Schema v", schema_constants.CURRENT_WORKSPACE_SCHEMA_VERSION)));
|
|
30309
30803
|
default:
|
|
30310
30804
|
return null;
|
|
30311
30805
|
}
|
|
30312
30806
|
}
|
|
30313
30807
|
render() {
|
|
30314
|
-
return (index.h(index.Host, { key: '
|
|
30808
|
+
return (index.h(index.Host, { key: '8dc22abaa2a19a14f3bbef10e34d133b16510498' }, index.h("kritzel-dialog", { key: '54072bf290e2d86bb7ec40d8d3e630be46fa3e1e', isOpen: this.isDialogOpen, dialogTitle: this.t('settings.dialogTitle', 'Settings'), size: "large", contained: true, onDialogClose: this.closeDialog }, index.h("kritzel-master-detail", { key: '5be80411c943ab4b7b90129527c8a0d147306a5f', items: this.categories, selectedItemId: this.selectedCategoryId, onItemSelect: this.handleCategorySelect }, this.renderCategoryContent()))));
|
|
30315
30809
|
}
|
|
30316
30810
|
static get watchers() { return {
|
|
30317
30811
|
"settings": [{
|
|
@@ -30372,6 +30866,8 @@ const KritzelShareDialog = class {
|
|
|
30372
30866
|
* The ID of the workspace being shared. Used to build the share URL.
|
|
30373
30867
|
*/
|
|
30374
30868
|
workspaceId = undefined;
|
|
30869
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
30870
|
+
terms = {};
|
|
30375
30871
|
onIsPublicChange(newValue) {
|
|
30376
30872
|
this.internalIsPublic = newValue;
|
|
30377
30873
|
}
|
|
@@ -30442,9 +30938,9 @@ const KritzelShareDialog = class {
|
|
|
30442
30938
|
this.dialogClosed.emit();
|
|
30443
30939
|
};
|
|
30444
30940
|
render() {
|
|
30445
|
-
return (index.h(index.Host, { key: '
|
|
30446
|
-
? 'Anyone with the link can access this workspace.'
|
|
30447
|
-
: 'Link sharing is disabled. Only you can access this workspace.')), index.h("kritzel-slide-toggle", { key: '
|
|
30941
|
+
return (index.h(index.Host, { key: 'b364f891659d54623b5472fe4cd5a9a85bc2fafa' }, index.h("kritzel-dialog", { key: '7059a3ede84bc67f7661efc8c84eae9b0c401d43', dialogTitle: this.terms['share.dialogTitle'] ?? 'Share Workspace', size: "small", isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, contained: true }, index.h("div", { key: '1b0e7a9b5483a53f91e874075c0edb116b7474d6', class: "share-content" }, index.h("div", { key: '1568dc99224f0f7e2a370c22327dc313515e7d0f', class: "share-section" }, index.h("div", { key: 'a0032f6c870a448e817b013a715aadca1c455bb3', class: "share-row" }, index.h("div", { key: '3bd74cbebc122133354465163f9945dd207245b5', class: "share-label-group" }, index.h("label", { key: '0919fc24e5637c908c53b6914983833b6600e846', class: "share-label" }, this.terms['share.linkSharing.label'] ?? 'Link sharing'), index.h("p", { key: 'f87c9eae7112d284d7d917fae7c9c05fa6feb0ed', class: "share-description" }, this.internalIsPublic
|
|
30942
|
+
? (this.terms['share.linkSharing.enabledDescription'] ?? 'Anyone with the link can access this workspace.')
|
|
30943
|
+
: (this.terms['share.linkSharing.disabledDescription'] ?? 'Link sharing is disabled. Only you can access this workspace.'))), index.h("kritzel-slide-toggle", { key: '81ccfb76255d40da954cfdcbc486bdbb7dc4bff4', checked: this.internalIsPublic, onCheckedChange: this.handleToggleChange, label: this.terms['share.linkSharing.toggleLabel'] ?? 'Enable link sharing' }))), this.internalIsPublic && (index.h("div", { key: 'c72da3550416ebfef5c24690591b212df70cb4db', class: "share-section" }, index.h("div", { key: 'c3dd4bce7d57e60d09989bff6dd1d828a613b425', class: "share-url-container" }, index.h("input", { key: '67aab8a65f54ea67392a9874e949d6d1af519e0f', type: "text", class: "share-url-input", value: this.getShareUrl(), readOnly: true, onClick: (e) => e.target.select() }), index.h("button", { key: 'c31d48fe67cdd12aa517e20bac54ac74c05abd04', class: { 'copy-button': true, 'copy-success': this.copySuccess }, onClick: this.handleCopyUrl, title: this.copySuccess ? (this.terms['share.copyLink.copied'] ?? 'Copied!') : (this.terms['share.copyLink.title'] ?? 'Copy link') }, index.h("kritzel-icon", { key: '08ed01ed081e955e28eaed577438cd0008eaacf4', name: this.copySuccess ? 'check' : 'copy', size: 18 })))))))));
|
|
30448
30944
|
}
|
|
30449
30945
|
static get watchers() { return {
|
|
30450
30946
|
"isPublic": [{
|
|
@@ -30482,7 +30978,7 @@ const KritzelSlideToggle = class {
|
|
|
30482
30978
|
}
|
|
30483
30979
|
};
|
|
30484
30980
|
render() {
|
|
30485
|
-
return (index.h(index.Host, { key: '
|
|
30981
|
+
return (index.h(index.Host, { key: '92aefb30139abd512c02c99f5c532cb69daab8c3', class: { checked: this.checked, disabled: this.disabled }, tabIndex: this.disabled ? -1 : 0, role: "switch", "aria-checked": this.checked ? 'true' : 'false', "aria-disabled": this.disabled ? 'true' : 'false', "aria-label": this.label, onClick: this.handleToggle, onKeyDown: this.handleKeyDown }, index.h("div", { key: '53fc90f3a11055e0b16358be0e3beed2ed25bc48', class: "toggle-track" }, index.h("div", { key: 'e0a0cecb9ede9c8e932cbb6fa7cdc359c07be8db', class: "toggle-thumb" }))));
|
|
30486
30982
|
}
|
|
30487
30983
|
};
|
|
30488
30984
|
KritzelSlideToggle.style = kritzelSlideToggleCss();
|
|
@@ -30582,7 +31078,7 @@ const KritzelSplitButton = class {
|
|
|
30582
31078
|
this.menuScrollTop = event.target.scrollTop;
|
|
30583
31079
|
};
|
|
30584
31080
|
render() {
|
|
30585
|
-
return (index.h(index.Host, { key: '
|
|
31081
|
+
return (index.h(index.Host, { key: '39516b2486a27534273b6bf4def6b11790aa0ed5', class: { mobile: this.isTouchDevice } }, index.h("button", { key: '19c4a58deb3992857b0e42e4a035a15d0980da22', class: "split-main-button", tabIndex: 0, onClick: this.handleButtonClick, disabled: this.mainButtonDisabled, "aria-label": "Main action" }, this.buttonIcon && index.h("kritzel-icon", { key: '4c8e7e09e60717b1653251468c2a25d41c4b1921', name: this.buttonIcon })), index.h("div", { key: '53617db6b630dfb5320e7309dcbc9f7288ff8974', class: "split-divider" }), index.h("button", { key: '5134f88ed43558ff0cb11b8ef29cf2b370aad4ee', ref: el => (this.splitMenuButtonRef = el), class: "split-menu-button", tabIndex: 0, onClick: this.toggleMenu, disabled: this.menuButtonDisabled, "aria-label": "Open menu" }, index.h("kritzel-icon", { key: '41f39a601ae91d4faaf54c1ca39c90e27e084d31', name: this.dropdownIcon })), index.h("kritzel-portal", { key: 'dcfe82f72a53e9346b48d2ff6da236c1f1344f3f', anchor: this.anchorElement, offsetY: 4, onClose: this.closeMenu }, index.h("kritzel-menu", { key: '1208990bff47de642eafa6ca8cfaa76de46ca87c', ref: el => (this.menuRef = el), items: this.items, onItemSelect: this.handleItemSelect, onItemSave: this.handleItemSave, onItemCancel: this.handleItemCancel, onItemToggleChildMenu: this.handleItemToggleChildMenu, onItemCloseChildMenu: this.handleItemCloseChildMenu, onClose: this.closeMenu, onScroll: this.handleScroll }))));
|
|
30586
31082
|
}
|
|
30587
31083
|
};
|
|
30588
31084
|
KritzelSplitButton.style = kritzelSplitButtonCss();
|
|
@@ -30602,7 +31098,8 @@ const KritzelStrokeSize = class {
|
|
|
30602
31098
|
this.sizeChange.emit(size);
|
|
30603
31099
|
}
|
|
30604
31100
|
render() {
|
|
30605
|
-
|
|
31101
|
+
const sizes = this.sizes ?? [];
|
|
31102
|
+
return (index.h(index.Host, { key: '20c11daaf60055262706b8177b1090bddd2d522c' }, index.h("div", { key: '1729e29d836f85fe3be984a5ee78a0debc0e6218', class: "size-grid" }, sizes.map(size => (index.h("div", { tabIndex: 0, class: {
|
|
30606
31103
|
'size-container': true,
|
|
30607
31104
|
'selected': this.selectedSize === size,
|
|
30608
31105
|
}, onClick: () => this.handleSizeClick(size) }, index.h("kritzel-color", { value: 'var(--kritzel-global-text-primary)', size: size })))))));
|
|
@@ -30651,6 +31148,8 @@ const KritzelToolConfig = class {
|
|
|
30651
31148
|
isExpanded = false;
|
|
30652
31149
|
theme;
|
|
30653
31150
|
engine;
|
|
31151
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
31152
|
+
terms = {};
|
|
30654
31153
|
handleSelectionChangeBound = this.handleSelectionChange.bind(this);
|
|
30655
31154
|
onThemeChange() {
|
|
30656
31155
|
this.emitDisplayValues();
|
|
@@ -30793,9 +31292,9 @@ const KritzelToolConfig = class {
|
|
|
30793
31292
|
const value = this.tool[control.propertyName];
|
|
30794
31293
|
switch (control.type) {
|
|
30795
31294
|
case 'stroke-size':
|
|
30796
|
-
return (index.h("kritzel-stroke-size", { key: control.type, sizes: this.sizes
|
|
31295
|
+
return (index.h("kritzel-stroke-size", { key: control.type, sizes: this.sizes, selectedSize: value, onSizeChange: this.handleSizeChange }));
|
|
30797
31296
|
case 'font-size':
|
|
30798
|
-
return (index.h("kritzel-font-size", { key: control.type, sizes: this.sizes
|
|
31297
|
+
return (index.h("kritzel-font-size", { key: control.type, sizes: this.sizes, selectedSize: value, fontFamily: this.tool.fontFamily, onSizeChange: this.handleSizeChange }));
|
|
30799
31298
|
case 'line-endings':
|
|
30800
31299
|
return (index.h("kritzel-line-endings", { key: control.type, value: value, onValueChange: (event) => this.handlePropertyChange(control.propertyName, event.detail) }));
|
|
30801
31300
|
case 'shape-fill':
|
|
@@ -30830,7 +31329,7 @@ const KritzelToolConfig = class {
|
|
|
30830
31329
|
])), shouldShowExpandButton && (index.h("div", { style: {
|
|
30831
31330
|
display: 'flex',
|
|
30832
31331
|
alignItems: 'flex-start',
|
|
30833
|
-
} }, index.h("button", { class: "expand-toggle", onClick: this.handleToggleExpand, title: this.isExpanded ? 'Collapse' : 'Expand' }, index.h("kritzel-icon", { name: this.isExpanded ? 'chevron-up' : 'chevron-down' })))))));
|
|
31332
|
+
} }, index.h("button", { class: "expand-toggle", onClick: this.handleToggleExpand, title: this.isExpanded ? (this.terms['toolConfig.collapse'] ?? 'Collapse') : (this.terms['toolConfig.expand'] ?? 'Expand') }, index.h("kritzel-icon", { name: this.isExpanded ? 'chevron-up' : 'chevron-down' })))))));
|
|
30834
31333
|
}
|
|
30835
31334
|
static get watchers() { return {
|
|
30836
31335
|
"tool": [{
|
|
@@ -30981,14 +31480,14 @@ const KritzelTooltip = class {
|
|
|
30981
31480
|
}
|
|
30982
31481
|
}
|
|
30983
31482
|
render() {
|
|
30984
|
-
return (index.h(index.Host, { key: '
|
|
31483
|
+
return (index.h(index.Host, { key: '57c0c2ddbe3f88815b975b7cf5b02c7da389b7f9', style: {
|
|
30985
31484
|
position: 'fixed',
|
|
30986
31485
|
zIndex: '9999',
|
|
30987
31486
|
transition: 'opacity 0.3s ease-in-out, transform 0.3s ease-in-out',
|
|
30988
31487
|
visibility: this.isVisible ? 'visible' : 'hidden',
|
|
30989
31488
|
left: `${this.positionX}px`,
|
|
30990
31489
|
bottom: `${this.positionY}px`,
|
|
30991
|
-
} }, index.h("div", { key: '
|
|
31490
|
+
} }, index.h("div", { key: '3ab17ef4ba55ed39458814685574b0c00504a07d', class: "tooltip-content", onClick: event => event.stopPropagation(), onPointerDown: event => event.stopPropagation(), onMouseDown: event => event.stopPropagation() }, index.h("slot", { key: 'b0aa1eb2c9363644939bcc59a80d0294787f0946' }))));
|
|
30992
31491
|
}
|
|
30993
31492
|
static get watchers() { return {
|
|
30994
31493
|
"triggerElement": [{
|
|
@@ -31011,6 +31510,8 @@ const KritzelUtilityPanel = class {
|
|
|
31011
31510
|
this.delete = index.createEvent(this, "delete");
|
|
31012
31511
|
}
|
|
31013
31512
|
undoState = null;
|
|
31513
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
31514
|
+
terms = {};
|
|
31014
31515
|
undo;
|
|
31015
31516
|
redo;
|
|
31016
31517
|
delete;
|
|
@@ -31027,11 +31528,32 @@ const KritzelUtilityPanel = class {
|
|
|
31027
31528
|
this.redo.emit();
|
|
31028
31529
|
}
|
|
31029
31530
|
render() {
|
|
31030
|
-
return (index.h(index.Host, { key: '
|
|
31531
|
+
return (index.h(index.Host, { key: '7738c225b6ec936e032770e0a7387b01718e94e0' }, index.h("button", { key: '8bc7346eb02e3c220ca9f9c06f1ae048e83667ee', class: "utility-button", "data-testid": "utility-undo", disabled: !this.undoState?.canUndo, onClick: event => this.handleUndo(event), "aria-label": this.terms['utility.undo'] ?? 'Undo' }, index.h("kritzel-icon", { key: '3c7d87edc047113cac359f4782c7feeb53e18193', name: "undo" })), index.h("button", { key: '960dc7783cfe558f08749b9e71c6583c8d53c167', class: "utility-button", "data-testid": "utility-redo", disabled: !this.undoState?.canRedo, onClick: event => this.handleRedo(event), "aria-label": this.terms['utility.redo'] ?? 'Redo' }, index.h("kritzel-icon", { key: 'b5ac0b631c51b8e6c2762b4887dcdef899327e52', name: "redo" })), index.h("div", { key: '4075c8eb7d8c57d5e93afb18282c7a50ec8e050e', class: "utility-separator" }), index.h("button", { key: '4e7c53a0933c527e84e0ad78519983446f10d23c', class: "utility-button", "data-testid": "utility-delete", onClick: () => this.delete.emit(), "aria-label": this.terms['utility.delete'] ?? 'Delete selected items' }, index.h("kritzel-icon", { key: 'f2d3d9817626c53e2e4c3d4c7c702705b25d7788', name: "delete" }))));
|
|
31031
31532
|
}
|
|
31032
31533
|
};
|
|
31033
31534
|
KritzelUtilityPanel.style = kritzelUtilityPanelCss();
|
|
31034
31535
|
|
|
31536
|
+
const kritzelWatermarkCss = () => `:host{position:absolute;bottom:var(--kritzel-watermark-offset-bottom, 12px);right:var(--kritzel-watermark-offset-right, 12px);z-index:10000;pointer-events:none}.watermark-link{pointer-events:auto;display:inline-flex;align-items:center;padding:4px 8px;border-radius:var(--kritzel-watermark-border-radius, 6px);font-family:var(--kritzel-font-family, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);font-size:var(--kritzel-watermark-font-size, 11px);line-height:1;text-decoration:none;color:var(--kritzel-watermark-color, rgba(60, 60, 60, 0.75));background-color:var(--kritzel-watermark-background, rgba(255, 255, 255, 0.6));box-shadow:var(--kritzel-watermark-box-shadow, 0 1px 2px rgba(0, 0, 0, 0.12));opacity:var(--kritzel-watermark-opacity, 0.85);transition:opacity 150ms ease;user-select:none}.watermark-link:hover{opacity:1}`;
|
|
31537
|
+
|
|
31538
|
+
const KritzelWatermark = class {
|
|
31539
|
+
constructor(hostRef) {
|
|
31540
|
+
index.registerInstance(this, hostRef);
|
|
31541
|
+
}
|
|
31542
|
+
/** The core instance used to resolve localized terms. */
|
|
31543
|
+
core;
|
|
31544
|
+
/**
|
|
31545
|
+
* Resolved "Powered by Kritzel" label. Passed in by the engine so the badge
|
|
31546
|
+
* re-renders when the active locale changes. Falls back to resolving the term
|
|
31547
|
+
* from the core when not provided.
|
|
31548
|
+
*/
|
|
31549
|
+
label;
|
|
31550
|
+
render() {
|
|
31551
|
+
const label = this.label ?? this.core.localizationManager.translate('watermark.poweredBy');
|
|
31552
|
+
return (index.h(index.Host, { key: '7ec2a304ac711a4d2a54edef317eef9f4aad1d47' }, index.h("a", { key: '365d588727bbc360fd47bc9a3fbd66155770d32f', class: "watermark-link", href: KRITZEL_WEBSITE_URL, target: "_blank", rel: "noopener noreferrer", part: "watermark", onPointerDown: (ev) => ev.stopPropagation(), onPointerUp: (ev) => ev.stopPropagation() }, label)));
|
|
31553
|
+
}
|
|
31554
|
+
};
|
|
31555
|
+
KritzelWatermark.style = kritzelWatermarkCss();
|
|
31556
|
+
|
|
31035
31557
|
const kritzelWorkspaceManagerCss = () => `:host{display:flex;flex-direction:column;z-index:1}.manager{opacity:0;pointer-events:none;transition:opacity 0.2s ease-out}.manager.visible{opacity:1;pointer-events:auto}`;
|
|
31036
31558
|
|
|
31037
31559
|
const KritzelWorkspaceManager = class {
|
|
@@ -31047,6 +31569,8 @@ const KritzelWorkspaceManager = class {
|
|
|
31047
31569
|
visible = false;
|
|
31048
31570
|
activeWorkspace;
|
|
31049
31571
|
workspaces = [];
|
|
31572
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
31573
|
+
terms = {};
|
|
31050
31574
|
isWorkspaceManagerReady;
|
|
31051
31575
|
workspaceChange;
|
|
31052
31576
|
childMenuAnchor = null;
|
|
@@ -31150,7 +31674,7 @@ const KritzelWorkspaceManager = class {
|
|
|
31150
31674
|
id: ws.id,
|
|
31151
31675
|
label: ws.name,
|
|
31152
31676
|
icon: ws.isPublic ? 'users-round' : undefined,
|
|
31153
|
-
iconTooltip: ws.isPublic ? 'Shared workspace' : undefined,
|
|
31677
|
+
iconTooltip: ws.isPublic ? (this.terms['workspace.sharedTooltip'] ?? 'Shared workspace') : undefined,
|
|
31154
31678
|
value: ws,
|
|
31155
31679
|
isEditing: this.editingItemId === ws.id,
|
|
31156
31680
|
isSelected: this.activeWorkspace?.id === ws.id,
|
|
@@ -31160,13 +31684,13 @@ const KritzelWorkspaceManager = class {
|
|
|
31160
31684
|
children: [
|
|
31161
31685
|
{
|
|
31162
31686
|
id: `${ws.id}-rename`,
|
|
31163
|
-
label: 'Rename',
|
|
31687
|
+
label: this.terms['workspace.rename'] ?? 'Rename',
|
|
31164
31688
|
value: 'rename',
|
|
31165
31689
|
action: (_item, parent) => this.edit(parent),
|
|
31166
31690
|
},
|
|
31167
31691
|
{
|
|
31168
31692
|
id: `${ws.id}-delete`,
|
|
31169
|
-
label: 'Delete',
|
|
31693
|
+
label: this.terms['workspace.delete'] ?? 'Delete',
|
|
31170
31694
|
value: 'delete',
|
|
31171
31695
|
isDisabled: this.sortedWorkspaces.length <= 1,
|
|
31172
31696
|
action: (_item, parent) => this.delete(parent),
|
|
@@ -31179,6 +31703,45 @@ const KritzelWorkspaceManager = class {
|
|
|
31179
31703
|
};
|
|
31180
31704
|
KritzelWorkspaceManager.style = kritzelWorkspaceManagerCss();
|
|
31181
31705
|
|
|
31706
|
+
const kritzelZoomPanelCss = () => `:host{display:block;z-index:1}.panel{display:flex;flex-direction:row;align-items:center;gap:var(--kritzel-zoom-panel-gap, 4px);padding:var(--kritzel-zoom-panel-padding, 4px);border:var(--kritzel-zoom-panel-border, 1px solid #ebebeb);border-radius:var(--kritzel-zoom-panel-border-radius, 12px);background-color:var(--kritzel-zoom-panel-background-color, #ffffff);box-shadow:var(--kritzel-zoom-panel-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));opacity:0;pointer-events:none;transition:opacity 0.2s ease-out}.panel.visible{opacity:1;pointer-events:auto}.zoom-level{display:inline-flex;align-items:center;justify-content:center;min-width:46px;color:var(--kritzel-zoom-panel-icon-color, #000000);font-family:var(--kritzel-font-family, sans-serif);font-size:12px;font-weight:500;line-height:1;padding:0 4px;user-select:none}.zoom-button{display:flex;align-items:center;justify-content:center;width:var(--kritzel-zoom-panel-button-size, 32px);height:var(--kritzel-zoom-panel-button-size, 32px);padding:0;border:0;border-radius:var(--kritzel-zoom-panel-button-border-radius, 8px);background:transparent;background-color:transparent;color:var(--kritzel-zoom-panel-icon-color, #000000);--kritzel-icon-color:var(--kritzel-zoom-panel-icon-color, #000000);box-shadow:none;appearance:none;cursor:var(--kritzel-global-pointer-cursor, pointer);-webkit-tap-highlight-color:transparent}.zoom-button:hover,.zoom-button:focus-visible{background-color:var(--kritzel-zoom-panel-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.zoom-button:active{background-color:var(--kritzel-zoom-panel-button-active-background-color, hsl(0, 0%, 0%, 8.6%))}.zoom-button:disabled{opacity:0.5;cursor:not-allowed;pointer-events:none}`;
|
|
31707
|
+
|
|
31708
|
+
const KritzelZoomPanel = class {
|
|
31709
|
+
constructor(hostRef) {
|
|
31710
|
+
index.registerInstance(this, hostRef);
|
|
31711
|
+
this.zoomIn = index.createEvent(this, "zoomIn");
|
|
31712
|
+
this.zoomOut = index.createEvent(this, "zoomOut");
|
|
31713
|
+
}
|
|
31714
|
+
/** Whether the zoom panel is visible. */
|
|
31715
|
+
visible = true;
|
|
31716
|
+
/** Whether both zoom buttons are disabled. */
|
|
31717
|
+
disabled = false;
|
|
31718
|
+
/** Current zoom level in percent. */
|
|
31719
|
+
zoomPercent = 100;
|
|
31720
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
31721
|
+
terms = {};
|
|
31722
|
+
/** Emitted when the zoom-in button is clicked. */
|
|
31723
|
+
zoomIn;
|
|
31724
|
+
/** Emitted when the zoom-out button is clicked. */
|
|
31725
|
+
zoomOut;
|
|
31726
|
+
handleZoomIn = () => {
|
|
31727
|
+
if (!this.disabled) {
|
|
31728
|
+
this.zoomIn.emit();
|
|
31729
|
+
}
|
|
31730
|
+
};
|
|
31731
|
+
handleZoomOut = () => {
|
|
31732
|
+
if (!this.disabled) {
|
|
31733
|
+
this.zoomOut.emit();
|
|
31734
|
+
}
|
|
31735
|
+
};
|
|
31736
|
+
get normalizedZoomPercent() {
|
|
31737
|
+
return Number.isFinite(this.zoomPercent) ? Math.max(1, Math.round(this.zoomPercent)) : 100;
|
|
31738
|
+
}
|
|
31739
|
+
render() {
|
|
31740
|
+
return (index.h(index.Host, { key: '6c88ed18f63e1a4cfffef6ba3aa1772404908d59' }, index.h("div", { key: '18fcdf05a6822d2b9cf319059118b4851429283d', class: { panel: true, visible: this.visible } }, index.h("button", { key: 'df2c90912e091e4f2ca025dd246916e9fea6f7fa', class: "zoom-button", type: "button", "aria-label": this.terms['zoom.zoomOut'] ?? 'Zoom out', disabled: this.disabled, onClick: this.handleZoomOut }, index.h("kritzel-icon", { key: '293847a34220520592e74f50c89d57140d7f1cbe', name: "minus" })), index.h("span", { key: '575119b81e6d5d41f5802a29be1b586727968919', class: "zoom-level", "aria-live": "polite" }, this.normalizedZoomPercent, "%"), index.h("button", { key: '8cdd7100aaeb313f2504351204ff512142414815', class: "zoom-button", type: "button", "aria-label": this.terms['zoom.zoomIn'] ?? 'Zoom in', disabled: this.disabled, onClick: this.handleZoomIn }, index.h("kritzel-icon", { key: 'b792164a29dd43ef601a4f469fed440ee1d72510', name: "plus" })))));
|
|
31741
|
+
}
|
|
31742
|
+
};
|
|
31743
|
+
KritzelZoomPanel.style = kritzelZoomPanelCss();
|
|
31744
|
+
|
|
31182
31745
|
exports.kritzel_active_users = KritzelActiveUsers;
|
|
31183
31746
|
exports.kritzel_avatar = KritzelAvatar;
|
|
31184
31747
|
exports.kritzel_awareness_cursors = KritzelAwarenessCursors;
|
|
@@ -31220,4 +31783,6 @@ exports.kritzel_stroke_size = KritzelStrokeSize;
|
|
|
31220
31783
|
exports.kritzel_tool_config = KritzelToolConfig;
|
|
31221
31784
|
exports.kritzel_tooltip = KritzelTooltip;
|
|
31222
31785
|
exports.kritzel_utility_panel = KritzelUtilityPanel;
|
|
31786
|
+
exports.kritzel_watermark = KritzelWatermark;
|
|
31223
31787
|
exports.kritzel_workspace_manager = KritzelWorkspaceManager;
|
|
31788
|
+
exports.kritzel_zoom_panel = KritzelZoomPanel;
|