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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { r as registerInstance, h, H as Host, c as createEvent, g as getElement } from './index-Dhio9uis.js';
|
|
2
|
-
import { c as KritzelPath, e as KritzelLine,
|
|
2
|
+
import { c as KritzelPath, e as KritzelLine, P as KritzelColorHelper, Q as KritzelDevicesHelper, p as KritzelSelectionTool, m as KritzelTextTool, R as KritzelMouseButton, T as DEFAULT_STROKE_SIZES, U as DEFAULT_COLOR_PALETTE, S as ShapeType, D as DEFAULT_BRUSH_CONFIG, i as KritzelBrushTool, k as KritzelEraserTool, x as DEFAULT_LINE_TOOL_CONFIG, j as KritzelLineTool, n as KritzelShapeTool, w as DEFAULT_TEXT_CONFIG, l as KritzelImageTool, G as KritzelAlignment, y as DEFAULT_ASSET_STORAGE_CONFIG, V as ThemeHelper, B as darkTheme, z as lightTheme, X as KritzelSelectionGroup, Y as KritzelSelectionBox, Z as KritzelIconRegistry, _ as KritzelKeyboardHelper, $ as KritzelBaseHandler, K as KritzelBaseObject, a0 as KritzelMathHelper, r as KritzelWorkspace, f as KritzelGroup, d as KritzelImage, g as KritzelShape, b as KritzelText, J as runMigrations, O as CURRENT_WORKSPACE_SCHEMA_VERSION, M as WORKSPACE_MIGRATIONS, N as CURRENT_APP_STATE_SCHEMA_VERSION, L as APP_STATE_MIGRATIONS, a1 as ObjectHelper, o as KritzelCursorHelper, s as KritzelAnchorManager, t as KritzelThemeManager, u as KritzelLocalizationManager, v as KritzelLicenseManager, q as KritzelAssetResolver, a2 as KritzelClassHelper, a3 as KritzelEventHelper, W as WORKSPACE_EXPORT_VERSION } from './schema.constants-DchTXG3V.js';
|
|
3
3
|
import * as Y from 'yjs';
|
|
4
4
|
import 'y-indexeddb';
|
|
5
5
|
import 'y-websocket';
|
|
@@ -132,16 +132,16 @@ const KritzelAvatar = class {
|
|
|
132
132
|
height: `${this.size}px`,
|
|
133
133
|
fontSize: `${Math.round(this.size * 0.4)}px`,
|
|
134
134
|
};
|
|
135
|
-
return (h(Host, { key: '
|
|
135
|
+
return (h(Host, { key: '0d372a5443f41835c2e8e5b33b58bcb6c1292e89', style: containerStyles, class: {
|
|
136
136
|
'has-image': !!showImage,
|
|
137
137
|
'has-initials': !!showInitials,
|
|
138
138
|
'has-default': !!showDefaultIcon,
|
|
139
|
-
}, role: "img", "aria-label": this.getDisplayName() || 'User avatar' }, showImage && (h("img", { key: '
|
|
139
|
+
}, role: "img", "aria-label": this.getDisplayName() || 'User avatar' }, showImage && (h("img", { key: 'deb5f12115dd28b4b4ab2157cb2bbc9e48bb2a3f', src: imageUrl, alt: "", class: "avatar-image", ref: (el) => {
|
|
140
140
|
if (el) {
|
|
141
141
|
el.referrerPolicy = 'no-referrer';
|
|
142
142
|
el.crossOrigin = 'anonymous';
|
|
143
143
|
}
|
|
144
|
-
}, onError: this.handleImageError })), showInitials && (h("span", { key: '
|
|
144
|
+
}, onError: this.handleImageError })), showInitials && (h("span", { key: '6fc12f2d32923f33df5a8ec743d51434f67e6934', class: "avatar-initials", style: { backgroundColor: this.getBackgroundColor() } }, initials)), showDefaultIcon && (h("span", { key: 'd803b385f7eaa0659d7452231bfd46b1634f204d', class: "avatar-default" }, h("svg", { key: 'a3275ab33f58440abcd15c296d9c027dfab6495c', viewBox: "0 0 24 24", fill: "currentColor" }, 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" }))))));
|
|
145
145
|
}
|
|
146
146
|
static get watchers() { return {
|
|
147
147
|
"user": [{
|
|
@@ -451,7 +451,7 @@ const KritzelBackToContent = class {
|
|
|
451
451
|
this.backToContent.emit();
|
|
452
452
|
};
|
|
453
453
|
render() {
|
|
454
|
-
return (h(Host, { key: '
|
|
454
|
+
return (h(Host, { key: '5ef034156f28bdd1861d99343d51a237498db46b' }, h("button", { key: 'caa1c08d04f1a3a84d694b7df5d318a686d3a1fb', class: { 'back-to-content-button': true, visible: this.visible }, onClick: this.handleClick, "aria-label": this.text }, h("kritzel-icon", { key: '0c7cf5e18294ade600be3052ca7c57c8d933a736', name: "chevrons-left" }))));
|
|
455
455
|
}
|
|
456
456
|
};
|
|
457
457
|
KritzelBackToContent.style = kritzelBackToContentCss();
|
|
@@ -478,11 +478,11 @@ const KritzelButton = class {
|
|
|
478
478
|
this.buttonClick.emit();
|
|
479
479
|
};
|
|
480
480
|
render() {
|
|
481
|
-
return (h(Host, { key: '
|
|
481
|
+
return (h(Host, { key: 'aa366907b97e648ac73182a43d099baf457e0ba3' }, h("button", { key: 'e80875396a791606461b1a20e0f7e1c896f54073', type: this.type, class: {
|
|
482
482
|
'kritzel-button': true,
|
|
483
483
|
[this.variant]: true,
|
|
484
484
|
'disabled': this.disabled,
|
|
485
|
-
}, disabled: this.disabled, onClick: this.handleClick }, h("slot", { key: '
|
|
485
|
+
}, disabled: this.disabled, onClick: this.handleClick }, h("slot", { key: '8f4e57a73837adfbf91f678c54558fe4c737aa91' }))));
|
|
486
486
|
}
|
|
487
487
|
};
|
|
488
488
|
KritzelButton.style = kritzelButtonCss();
|
|
@@ -530,13 +530,13 @@ const KritzelColorComponent = class {
|
|
|
530
530
|
render() {
|
|
531
531
|
const resolvedColor = this.resolveColor();
|
|
532
532
|
const isColorVeryLight = this.isLightColor(resolvedColor);
|
|
533
|
-
return (h(Host, { key: '
|
|
533
|
+
return (h(Host, { key: '21ce0ecb616266ec4953468ae9bbe0b72259c2da' }, h("div", { key: '02c8e8684b3b0819755efd1f160bdee662428ddd', class: "checkerboard-bg", style: {
|
|
534
534
|
width: `${this.size}px`,
|
|
535
535
|
height: `${this.size}px`,
|
|
536
536
|
borderRadius: '50%',
|
|
537
537
|
display: 'inline-block',
|
|
538
538
|
position: 'relative',
|
|
539
|
-
} }, h("div", { key: '
|
|
539
|
+
} }, h("div", { key: '0063e9a701994869adbd3022b5ace542e85dfd95', class: {
|
|
540
540
|
'color-circle': true,
|
|
541
541
|
'white': isColorVeryLight,
|
|
542
542
|
}, style: {
|
|
@@ -592,7 +592,7 @@ const KritzelColorPalette = class {
|
|
|
592
592
|
render() {
|
|
593
593
|
const displayedColors = this.isExpanded ? this.colors : this.colors.slice(0, 6);
|
|
594
594
|
const expandedHeight = this.isExpanded ? this.calculateHeight() : '32px';
|
|
595
|
-
return (h(Host, { key: '
|
|
595
|
+
return (h(Host, { key: '9910a765816f45d420ad27c8fc7b02811380783b' }, h("div", { key: '91f3dae04338f55ab21831e4cac65f9d855c58c6', class: {
|
|
596
596
|
'color-grid': true,
|
|
597
597
|
'expanded': this.isExpanded,
|
|
598
598
|
}, style: {
|
|
@@ -939,6 +939,8 @@ const KritzelControls = class {
|
|
|
939
939
|
isUtilityPanelVisible = true;
|
|
940
940
|
undoState = null;
|
|
941
941
|
theme = 'light';
|
|
942
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
943
|
+
terms = {};
|
|
942
944
|
isControlsReady;
|
|
943
945
|
firstConfig = null;
|
|
944
946
|
isTouchDevice = KritzelDevicesHelper.isTouchDevice();
|
|
@@ -1158,13 +1160,13 @@ const KritzelControls = class {
|
|
|
1158
1160
|
// Separate tool controls from config control
|
|
1159
1161
|
const toolControls = this.internalControls.filter(c => c.type === 'tool' || c.type === 'separator');
|
|
1160
1162
|
const configControl = this.internalControls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
|
|
1161
|
-
return (h(Host, { key: '
|
|
1163
|
+
return (h(Host, { key: '7247a377d1cb75153e35f5308e81b2bd00d98578', style: { display: this.visible ? '' : 'none' }, class: {
|
|
1162
1164
|
mobile: this.isTouchDevice,
|
|
1163
|
-
} }, this.isUtilityPanelVisible && (h("kritzel-utility-panel", { key: '
|
|
1165
|
+
} }, this.isUtilityPanelVisible && (h("kritzel-utility-panel", { key: '075577cd15f3e577a1a216b5b1f1874e82e0d123', style: {
|
|
1164
1166
|
position: 'absolute',
|
|
1165
1167
|
bottom: '56px',
|
|
1166
1168
|
left: '12px',
|
|
1167
|
-
}, undoState: this.undoState, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), h("div", { key: '
|
|
1169
|
+
}, undoState: this.undoState, terms: this.terms, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), h("div", { key: '7fb1041763c7b64917e337d68bbb29b36ed86b9a', class: "kritzel-controls" }, h("div", { key: '8577ed9c6f43a667aaba7dce1da519456c8ad210', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), h("div", { key: '42f8f2b85055705674f9e319056bd48856dbd197', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
|
|
1168
1170
|
// Check if this control has sub-options (split-button)
|
|
1169
1171
|
if (control.subOptions?.length) {
|
|
1170
1172
|
const selectedSubOption = this.getSelectedSubOption(control);
|
|
@@ -1194,10 +1196,10 @@ const KritzelControls = class {
|
|
|
1194
1196
|
'kritzel-control': true,
|
|
1195
1197
|
'selected': this.activeControl?.name === control?.name,
|
|
1196
1198
|
}, key: control.name, "data-testid": `tool-${control.name}`, onClick: _event => this.handleControlClick?.(control), "aria-label": control.name.charAt(0).toUpperCase() + control.name.slice(1) }, h("kritzel-icon", { name: control.icon })));
|
|
1197
|
-
})), h("div", { key: '
|
|
1199
|
+
})), h("div", { key: '20007273e0f701193502320cf58099cbaedb834e', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (h("div", { class: {
|
|
1198
1200
|
'kritzel-config-container': true,
|
|
1199
1201
|
'visible': hasConfigUI,
|
|
1200
|
-
}, key: configControl.name }, h("div", { key: '
|
|
1202
|
+
}, key: configControl.name }, h("div", { key: '2901fc2507e5b02fbd603bd2d2a4e2b07e35c970', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), h("kritzel-tooltip", { key: '653e6a9b49146a2f297dbb5b9debe8709efd59ad', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, 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%' } })), h("div", { key: '951a52f625c929634de5102b83a14ad0cf1abc8d', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
|
|
1201
1203
|
if (el)
|
|
1202
1204
|
this.configTriggerRef = el;
|
|
1203
1205
|
}, onKeyDown: event => {
|
|
@@ -1206,7 +1208,7 @@ const KritzelControls = class {
|
|
|
1206
1208
|
}
|
|
1207
1209
|
}, style: {
|
|
1208
1210
|
cursor: 'pointer',
|
|
1209
|
-
} }, this.displayValues && (h("div", { key: '
|
|
1211
|
+
} }, this.displayValues && (h("div", { key: 'b8fff73b9055e86b312a9f0798fff4177cf85970', class: "color-container" }, h("kritzel-color", { key: 'fcd474e557d887f94383b7e583ab1c95a675ce23', value: this.displayValues.color, theme: this.theme, size: 18, style: {
|
|
1210
1212
|
borderRadius: '50%',
|
|
1211
1213
|
border: 'none',
|
|
1212
1214
|
} })))))))));
|
|
@@ -1238,13 +1240,15 @@ const KritzelCurrentUser = class {
|
|
|
1238
1240
|
* Avatar size in pixels
|
|
1239
1241
|
*/
|
|
1240
1242
|
avatarSize = 40;
|
|
1243
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
1244
|
+
terms = {};
|
|
1241
1245
|
dialogRef;
|
|
1242
1246
|
handleAvatarClick = (event) => {
|
|
1243
1247
|
event.stopPropagation();
|
|
1244
1248
|
this.dialogRef?.open();
|
|
1245
1249
|
};
|
|
1246
1250
|
render() {
|
|
1247
|
-
return (h(Host, { key: '
|
|
1251
|
+
return (h(Host, { key: '7e45048e532db84347e2531de2df19f5537d62ca' }, h("kritzel-avatar", { key: '5a67d1dbae041e16cdaeaf4bc678b6b00c56f442', user: this.user, size: this.avatarSize, onClick: this.handleAvatarClick }), h("kritzel-current-user-dialog", { key: '8e35219e282811b8bbafb058c02c8c0474574009', ref: el => (this.dialogRef = el), user: this.user, terms: this.terms })));
|
|
1248
1252
|
}
|
|
1249
1253
|
};
|
|
1250
1254
|
KritzelCurrentUser.style = kritzelCurrentUserCss();
|
|
@@ -1257,6 +1261,8 @@ const KritzelCurrentUserDialog = class {
|
|
|
1257
1261
|
}
|
|
1258
1262
|
get host() { return getElement(this); }
|
|
1259
1263
|
user;
|
|
1264
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
1265
|
+
terms = {};
|
|
1260
1266
|
isDialogOpen = false;
|
|
1261
1267
|
async open() {
|
|
1262
1268
|
this.isDialogOpen = true;
|
|
@@ -1276,7 +1282,7 @@ const KritzelCurrentUserDialog = class {
|
|
|
1276
1282
|
}
|
|
1277
1283
|
render() {
|
|
1278
1284
|
const displayName = this.getDisplayName();
|
|
1279
|
-
return (h(Host, { key: '
|
|
1285
|
+
return (h(Host, { key: '7c9e5c19249d400e2d670c60f5d6716c742adc62' }, h("kritzel-dialog", { key: '811da6bff0ce03914f545dd289878ba04924e85c', dialogTitle: this.terms['currentUser.dialogTitle'] ?? 'Account', isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, size: "small", contained: true }, h("div", { key: '03a101b04d61882732547d91e81a2bacb3aa4df8', class: "user-info" }, h("kritzel-avatar", { key: '4033d0e2322d7a25231f01115ec33f20e4fb0d4c', user: this.user, size: 80 }), displayName && h("div", { key: 'cf3a3aecb84152736c9de119f82a79f1b2b32f6f', class: "user-name" }, displayName), this.user?.email && h("div", { key: '5725d71dd80468c64a2b0bb1d9d967232513fb63', class: "user-email" }, this.user.email)))));
|
|
1280
1286
|
}
|
|
1281
1287
|
};
|
|
1282
1288
|
KritzelCurrentUserDialog.style = kritzelCurrentUserDialogCss();
|
|
@@ -2155,6 +2161,8 @@ const DEFAULT_SHAPE_CONFIG = {
|
|
|
2155
2161
|
|
|
2156
2162
|
const ABSOLUTE_SCALE_MAX = 1000;
|
|
2157
2163
|
const ABSOLUTE_SCALE_MIN = 0.0001;
|
|
2164
|
+
/** Destination opened when the "Powered by Kritzel" watermark is clicked. */
|
|
2165
|
+
const KRITZEL_WEBSITE_URL = 'https://kritzel.io';
|
|
2158
2166
|
|
|
2159
2167
|
/**
|
|
2160
2168
|
* Default sync configuration - None
|
|
@@ -2163,7 +2171,7 @@ const DEFAULT_SYNC_CONFIG = {
|
|
|
2163
2171
|
providers: [],
|
|
2164
2172
|
};
|
|
2165
2173
|
|
|
2166
|
-
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}`;
|
|
2174
|
+
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}`;
|
|
2167
2175
|
|
|
2168
2176
|
const KritzelEditor = class {
|
|
2169
2177
|
constructor(hostRef) {
|
|
@@ -2176,6 +2184,7 @@ const KritzelEditor = class {
|
|
|
2176
2184
|
this.objectsUpdated = createEvent(this, "objectsUpdated");
|
|
2177
2185
|
this.undoStateChange = createEvent(this, "undoStateChange");
|
|
2178
2186
|
this.themeChange = createEvent(this, "themeChange");
|
|
2187
|
+
this.localeChange = createEvent(this, "localeChange");
|
|
2179
2188
|
this.viewportChange = createEvent(this, "viewportChange");
|
|
2180
2189
|
this.logout = createEvent(this, "logout");
|
|
2181
2190
|
this.login = createEvent(this, "login");
|
|
@@ -2190,7 +2199,6 @@ const KritzelEditor = class {
|
|
|
2190
2199
|
viewportBoundaryRight = Infinity;
|
|
2191
2200
|
viewportBoundaryTop = -Infinity;
|
|
2192
2201
|
viewportBoundaryBottom = Infinity;
|
|
2193
|
-
wheelEnabled = true;
|
|
2194
2202
|
debugInfo = {
|
|
2195
2203
|
showViewportInfo: false,
|
|
2196
2204
|
showObjectInfo: false,
|
|
@@ -2259,66 +2267,66 @@ const KritzelEditor = class {
|
|
|
2259
2267
|
];
|
|
2260
2268
|
globalContextMenuItems = [
|
|
2261
2269
|
{
|
|
2262
|
-
label: '
|
|
2270
|
+
label: 'menu.paste',
|
|
2263
2271
|
icon: 'paste',
|
|
2264
2272
|
disabled: async () => (await this.engineRef.getCopiedObjects()).length === 0,
|
|
2265
2273
|
action: menu => this.engineRef.paste(menu.x, menu.y),
|
|
2266
2274
|
},
|
|
2267
2275
|
{
|
|
2268
|
-
label: '
|
|
2276
|
+
label: 'menu.selectAll',
|
|
2269
2277
|
icon: 'select-all',
|
|
2270
2278
|
disabled: async () => (await this.engineRef.getObjectsInViewport()).length === 0,
|
|
2271
2279
|
action: () => this.selectAllObjectsInViewport(),
|
|
2272
2280
|
},
|
|
2273
2281
|
];
|
|
2274
2282
|
objectContextMenuItems = [
|
|
2275
|
-
{ label: '
|
|
2276
|
-
{ label: '
|
|
2283
|
+
{ label: 'menu.copy', icon: 'copy', group: 'clipboard', action: () => this.engineRef.copy() },
|
|
2284
|
+
{ label: 'menu.cut', icon: 'cut', group: 'clipboard', action: () => this.engineRef.cut() },
|
|
2277
2285
|
{
|
|
2278
|
-
label: '
|
|
2286
|
+
label: 'menu.paste',
|
|
2279
2287
|
icon: 'paste',
|
|
2280
2288
|
group: 'clipboard',
|
|
2281
2289
|
disabled: async () => (await this.engineRef.getCopiedObjects()).length === 0,
|
|
2282
2290
|
action: (menu, _) => this.engineRef.paste(menu.x, menu.y),
|
|
2283
2291
|
},
|
|
2284
2292
|
{
|
|
2285
|
-
label: '
|
|
2293
|
+
label: 'menu.order',
|
|
2286
2294
|
icon: 'ordering',
|
|
2287
2295
|
group: 'other',
|
|
2288
2296
|
children: [
|
|
2289
|
-
{ label: '
|
|
2290
|
-
{ label: '
|
|
2291
|
-
{ label: '
|
|
2292
|
-
{ label: '
|
|
2297
|
+
{ label: 'menu.bringToFront', icon: 'bring-to-front', action: () => this.engineRef.bringToFront() },
|
|
2298
|
+
{ label: 'menu.sendToBack', icon: 'send-to-back', action: () => this.engineRef.sendToBack() },
|
|
2299
|
+
{ label: 'menu.moveUp', icon: 'arrow-up-from-dot', action: () => this.engineRef.bringForward() },
|
|
2300
|
+
{ label: 'menu.moveDown', icon: 'arrow-down-from-dot', action: () => this.engineRef.sendBackward() },
|
|
2293
2301
|
],
|
|
2294
2302
|
},
|
|
2295
2303
|
{
|
|
2296
|
-
label: '
|
|
2304
|
+
label: 'menu.align',
|
|
2297
2305
|
icon: 'align',
|
|
2298
2306
|
group: 'other',
|
|
2299
2307
|
disabled: async () => (await this.engineRef.getSelectedObjects()).length < 2,
|
|
2300
2308
|
children: [
|
|
2301
|
-
{ label: '
|
|
2302
|
-
{ label: '
|
|
2303
|
-
{ label: '
|
|
2304
|
-
{ label: '
|
|
2305
|
-
{ label: '
|
|
2306
|
-
{ label: '
|
|
2309
|
+
{ label: 'menu.alignLeft', icon: 'align-start-vertical', action: () => this.engineRef.alignObjects(KritzelAlignment.StartHorizontal) },
|
|
2310
|
+
{ label: 'menu.alignCenterHorizontal', icon: 'align-center-horizontal', action: () => this.engineRef.alignObjects(KritzelAlignment.CenterHorizontal) },
|
|
2311
|
+
{ label: 'menu.alignRight', icon: 'align-end-vertical', action: () => this.engineRef.alignObjects(KritzelAlignment.EndHorizontal) },
|
|
2312
|
+
{ label: 'menu.alignTop', icon: 'align-start-horizontal', action: () => this.engineRef.alignObjects(KritzelAlignment.StartVertical) },
|
|
2313
|
+
{ label: 'menu.alignCenterVertical', icon: 'align-center-vertical', action: () => this.engineRef.alignObjects(KritzelAlignment.CenterVertical) },
|
|
2314
|
+
{ label: 'menu.alignBottom', icon: 'align-end-horizontal', action: () => this.engineRef.alignObjects(KritzelAlignment.EndVertical) },
|
|
2307
2315
|
],
|
|
2308
2316
|
},
|
|
2309
2317
|
{
|
|
2310
|
-
label: '
|
|
2318
|
+
label: 'menu.group',
|
|
2311
2319
|
icon: 'group',
|
|
2312
2320
|
group: 'other',
|
|
2313
2321
|
children: [
|
|
2314
2322
|
{
|
|
2315
|
-
label: '
|
|
2323
|
+
label: 'menu.group',
|
|
2316
2324
|
icon: 'group',
|
|
2317
2325
|
disabled: async () => (await this.engineRef.getSelectedObjects()).length < 2,
|
|
2318
2326
|
action: () => this.engineRef.group(),
|
|
2319
2327
|
},
|
|
2320
2328
|
{
|
|
2321
|
-
label: '
|
|
2329
|
+
label: 'menu.ungroup',
|
|
2322
2330
|
icon: 'ungroup',
|
|
2323
2331
|
disabled: async () => {
|
|
2324
2332
|
const selectedObjects = await this.engineRef.getSelectedObjects();
|
|
@@ -2329,23 +2337,34 @@ const KritzelEditor = class {
|
|
|
2329
2337
|
],
|
|
2330
2338
|
},
|
|
2331
2339
|
{
|
|
2332
|
-
label: '
|
|
2340
|
+
label: 'menu.export',
|
|
2333
2341
|
icon: 'download',
|
|
2334
2342
|
group: 'export',
|
|
2335
2343
|
children: [
|
|
2336
|
-
{ label: '
|
|
2337
|
-
{ label: '
|
|
2344
|
+
{ label: 'menu.exportAsSvg', icon: 'download', action: () => this.engineRef.exportSelectedObjectsAsSvg() },
|
|
2345
|
+
{ label: 'menu.exportAsPng', icon: 'download', action: () => this.engineRef.exportSelectedObjectsAsPng() },
|
|
2338
2346
|
],
|
|
2339
2347
|
},
|
|
2340
|
-
{ label: '
|
|
2348
|
+
{ label: 'menu.delete', icon: 'delete', group: 'edit', action: () => this.engineRef.delete() },
|
|
2341
2349
|
];
|
|
2342
2350
|
themes;
|
|
2343
2351
|
theme = 'light';
|
|
2352
|
+
/** License key that, when valid, removes the "Powered by Kritzel" watermark. */
|
|
2353
|
+
licenseKey;
|
|
2354
|
+
/** The current locale (language) code applied to the editor, e.g. 'en', 'de', 'fr'. */
|
|
2355
|
+
locale = 'en';
|
|
2356
|
+
/** An array of available locale definitions (with optional partial term overrides). */
|
|
2357
|
+
locales;
|
|
2358
|
+
/** The locale used to resolve terms missing from the active locale. */
|
|
2359
|
+
fallbackLocale = 'en';
|
|
2344
2360
|
customSvgIcons = {};
|
|
2361
|
+
isPanningEnabled = true;
|
|
2362
|
+
isZoomingEnabled = true;
|
|
2345
2363
|
isControlsVisible = true;
|
|
2346
2364
|
isUtilityPanelVisible = true;
|
|
2347
2365
|
isWorkspaceManagerVisible = true;
|
|
2348
2366
|
isMoreMenuVisible = true;
|
|
2367
|
+
isZoomPanelVisible = true;
|
|
2349
2368
|
isObjectDistanceFadingActive = false;
|
|
2350
2369
|
syncConfig = DEFAULT_SYNC_CONFIG;
|
|
2351
2370
|
assetStorageConfig = DEFAULT_ASSET_STORAGE_CONFIG;
|
|
@@ -2367,6 +2386,7 @@ const KritzelEditor = class {
|
|
|
2367
2386
|
objectsUpdated;
|
|
2368
2387
|
undoStateChange;
|
|
2369
2388
|
themeChange;
|
|
2389
|
+
localeChange;
|
|
2370
2390
|
viewportChange;
|
|
2371
2391
|
logout;
|
|
2372
2392
|
login;
|
|
@@ -2380,6 +2400,11 @@ const KritzelEditor = class {
|
|
|
2380
2400
|
isVirtualKeyboardOpen = false;
|
|
2381
2401
|
undoState = null;
|
|
2382
2402
|
isBackToContentButtonVisible = false;
|
|
2403
|
+
/** Localized strings for editor-owned UI (e.g. the more menu), resolved from the active locale. */
|
|
2404
|
+
resolvedTerms = {};
|
|
2405
|
+
/** Available locales as `{ code, label }` options for the settings language selector. */
|
|
2406
|
+
availableLocaleOptions = [];
|
|
2407
|
+
currentZoomPercent = 100;
|
|
2383
2408
|
shortcuts = [];
|
|
2384
2409
|
currentIsPublic = false;
|
|
2385
2410
|
isEditorVisible = false;
|
|
@@ -2443,6 +2468,25 @@ const KritzelEditor = class {
|
|
|
2443
2468
|
onThemesChange() {
|
|
2444
2469
|
this.applyTheme();
|
|
2445
2470
|
}
|
|
2471
|
+
onLocaleChange(newValue) {
|
|
2472
|
+
if (this.engineRef) {
|
|
2473
|
+
this.engineRef.setLocale(newValue);
|
|
2474
|
+
this.engineRef.saveSettings(this.currentSettingsConfig);
|
|
2475
|
+
void this.refreshLocalizedTerms();
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
/**
|
|
2479
|
+
* Refreshes the editor-owned localized strings (e.g. the more menu and the
|
|
2480
|
+
* strings forwarded to child UI components) from the engine's localization
|
|
2481
|
+
* manager for the active locale.
|
|
2482
|
+
*/
|
|
2483
|
+
async refreshLocalizedTerms() {
|
|
2484
|
+
if (!this.engineRef) {
|
|
2485
|
+
return;
|
|
2486
|
+
}
|
|
2487
|
+
this.resolvedTerms = await this.engineRef.getResolvedTerms();
|
|
2488
|
+
this.availableLocaleOptions = await this.engineRef.getAvailableLocaleOptions();
|
|
2489
|
+
}
|
|
2446
2490
|
onTouchStart(event) {
|
|
2447
2491
|
if (event.cancelable) {
|
|
2448
2492
|
event.preventDefault();
|
|
@@ -2701,6 +2745,9 @@ const KritzelEditor = class {
|
|
|
2701
2745
|
this.activeWorkspace = event.detail.activeWorkspace;
|
|
2702
2746
|
this.workspaces = event.detail.workspaces;
|
|
2703
2747
|
this.currentIsPublic = await this.engineRef.getIsPublic();
|
|
2748
|
+
await this.refreshLocalizedTerms();
|
|
2749
|
+
const viewport = await this.engineRef.getViewport();
|
|
2750
|
+
this.currentZoomPercent = this.getZoomPercentFromScale(viewport.scale);
|
|
2704
2751
|
this.loadShortcuts();
|
|
2705
2752
|
}
|
|
2706
2753
|
handleWorkspacesChange(event) {
|
|
@@ -2751,8 +2798,15 @@ const KritzelEditor = class {
|
|
|
2751
2798
|
}
|
|
2752
2799
|
handleViewportChange(event) {
|
|
2753
2800
|
event.stopPropagation();
|
|
2801
|
+
this.currentZoomPercent = this.getZoomPercentFromScale(event.detail.scale);
|
|
2754
2802
|
this.viewportChange.emit(event.detail);
|
|
2755
2803
|
}
|
|
2804
|
+
getZoomPercentFromScale(scale) {
|
|
2805
|
+
if (!Number.isFinite(scale) || scale <= 0) {
|
|
2806
|
+
return 100;
|
|
2807
|
+
}
|
|
2808
|
+
return Math.round(scale * 100);
|
|
2809
|
+
}
|
|
2756
2810
|
handleAwarenessChange(event) {
|
|
2757
2811
|
event.stopPropagation();
|
|
2758
2812
|
this.awarenessChange.emit(event.detail);
|
|
@@ -2762,6 +2816,10 @@ const KritzelEditor = class {
|
|
|
2762
2816
|
this.scaleMax = event.detail.scaleMax;
|
|
2763
2817
|
this.lockDrawingScale = event.detail.lockDrawingScale;
|
|
2764
2818
|
this.theme = event.detail.theme;
|
|
2819
|
+
if (typeof event.detail.locale === 'string' && event.detail.locale !== this.locale) {
|
|
2820
|
+
this.locale = event.detail.locale;
|
|
2821
|
+
this.localeChange.emit(event.detail.locale);
|
|
2822
|
+
}
|
|
2765
2823
|
this.viewportBoundaryLeft = event.detail.viewportBoundaryLeft ?? -Infinity;
|
|
2766
2824
|
this.viewportBoundaryRight = event.detail.viewportBoundaryRight ?? Infinity;
|
|
2767
2825
|
this.viewportBoundaryTop = event.detail.viewportBoundaryTop ?? -Infinity;
|
|
@@ -2776,7 +2834,7 @@ const KritzelEditor = class {
|
|
|
2776
2834
|
return [
|
|
2777
2835
|
{
|
|
2778
2836
|
id: 'share',
|
|
2779
|
-
label: 'Share',
|
|
2837
|
+
label: this.resolvedTerms['menu.share'] ?? 'Share',
|
|
2780
2838
|
icon: 'share',
|
|
2781
2839
|
action: () => {
|
|
2782
2840
|
if (!this.isLoggedIn && this.loginConfig) {
|
|
@@ -2788,7 +2846,7 @@ const KritzelEditor = class {
|
|
|
2788
2846
|
},
|
|
2789
2847
|
{
|
|
2790
2848
|
id: 'export',
|
|
2791
|
-
label: 'Export',
|
|
2849
|
+
label: this.resolvedTerms['menu.export'] ?? 'Export',
|
|
2792
2850
|
icon: 'upload',
|
|
2793
2851
|
action: async () => {
|
|
2794
2852
|
const preview = await this.engineRef.getScreenshot('png');
|
|
@@ -2797,19 +2855,19 @@ const KritzelEditor = class {
|
|
|
2797
2855
|
},
|
|
2798
2856
|
{
|
|
2799
2857
|
id: 'import',
|
|
2800
|
-
label: 'Import',
|
|
2858
|
+
label: this.resolvedTerms['menu.import'] ?? 'Import',
|
|
2801
2859
|
icon: 'download',
|
|
2802
2860
|
action: () => this.engineRef.importFromFile(),
|
|
2803
2861
|
},
|
|
2804
2862
|
{
|
|
2805
2863
|
id: 'settings',
|
|
2806
|
-
label: 'Settings',
|
|
2864
|
+
label: this.resolvedTerms['menu.settings'] ?? 'Settings',
|
|
2807
2865
|
icon: 'settings',
|
|
2808
2866
|
action: () => this.settingsRef.open(),
|
|
2809
2867
|
},
|
|
2810
2868
|
{
|
|
2811
2869
|
id: 'logout',
|
|
2812
|
-
label: 'Logout',
|
|
2870
|
+
label: this.resolvedTerms['menu.logout'] ?? 'Logout',
|
|
2813
2871
|
icon: 'log-out',
|
|
2814
2872
|
color: '#ff3b30',
|
|
2815
2873
|
isVisible: this.isLoggedIn,
|
|
@@ -2849,6 +2907,41 @@ const KritzelEditor = class {
|
|
|
2849
2907
|
async setLoginLoading(provider) {
|
|
2850
2908
|
this.loginDialogRef?.setLoading(provider);
|
|
2851
2909
|
}
|
|
2910
|
+
/**
|
|
2911
|
+
* Sets the active locale (language) and re-renders the UI.
|
|
2912
|
+
* @param code - The locale code to activate, e.g. 'de'.
|
|
2913
|
+
*/
|
|
2914
|
+
async setLocale(code) {
|
|
2915
|
+
this.locale = code;
|
|
2916
|
+
await this.engineRef?.setLocale(code);
|
|
2917
|
+
}
|
|
2918
|
+
/**
|
|
2919
|
+
* Gets the currently active locale code.
|
|
2920
|
+
*/
|
|
2921
|
+
async getLocale() {
|
|
2922
|
+
return this.engineRef ? this.engineRef.getLocale() : this.locale;
|
|
2923
|
+
}
|
|
2924
|
+
/**
|
|
2925
|
+
* Gets the list of available locale codes (built-in and registered).
|
|
2926
|
+
*/
|
|
2927
|
+
async getAvailableLocales() {
|
|
2928
|
+
return this.engineRef ? this.engineRef.getAvailableLocales() : [];
|
|
2929
|
+
}
|
|
2930
|
+
/**
|
|
2931
|
+
* Registers additional locale definitions (with optional partial term overrides).
|
|
2932
|
+
* @param locales - The locale definitions to register.
|
|
2933
|
+
*/
|
|
2934
|
+
async registerLocales(locales) {
|
|
2935
|
+
await this.engineRef?.registerLocales(locales);
|
|
2936
|
+
}
|
|
2937
|
+
/**
|
|
2938
|
+
* Resolves a term key to its translated string for the active locale.
|
|
2939
|
+
* @param key - The term key to resolve.
|
|
2940
|
+
* @param vars - Optional values for `{placeholder}` interpolation.
|
|
2941
|
+
*/
|
|
2942
|
+
async t(key, vars) {
|
|
2943
|
+
return this.engineRef ? this.engineRef.t(key, vars) : key;
|
|
2944
|
+
}
|
|
2852
2945
|
getSettingsStorageKey() {
|
|
2853
2946
|
return this.editorId ? `kritzel-settings-${this.editorId}` : 'kritzel-settings';
|
|
2854
2947
|
}
|
|
@@ -2869,6 +2962,9 @@ const KritzelEditor = class {
|
|
|
2869
2962
|
if (typeof parsed.theme === 'string') {
|
|
2870
2963
|
this.theme = parsed.theme;
|
|
2871
2964
|
}
|
|
2965
|
+
if (typeof parsed.locale === 'string') {
|
|
2966
|
+
this.locale = parsed.locale;
|
|
2967
|
+
}
|
|
2872
2968
|
if (typeof parsed.viewportBoundaryLeft === 'number') {
|
|
2873
2969
|
this.viewportBoundaryLeft = parsed.viewportBoundaryLeft;
|
|
2874
2970
|
}
|
|
@@ -2899,6 +2995,7 @@ const KritzelEditor = class {
|
|
|
2899
2995
|
scaleMax: this.scaleMax,
|
|
2900
2996
|
lockDrawingScale: this.lockDrawingScale,
|
|
2901
2997
|
theme: this.theme,
|
|
2998
|
+
locale: this.locale,
|
|
2902
2999
|
viewportBoundaryLeft: this.viewportBoundaryLeft,
|
|
2903
3000
|
viewportBoundaryRight: this.viewportBoundaryRight,
|
|
2904
3001
|
viewportBoundaryTop: this.viewportBoundaryTop,
|
|
@@ -2952,35 +3049,35 @@ const KritzelEditor = class {
|
|
|
2952
3049
|
const isLoggedIn = this.isLoggedIn;
|
|
2953
3050
|
const shouldShowCurrentUser = isLoggedIn;
|
|
2954
3051
|
const shouldShowLoginButton = this.isReady && !!this.loginConfig && !isLoggedIn;
|
|
2955
|
-
return (h(Host, { key: '
|
|
3052
|
+
return (h(Host, { key: '72238560a0f0275c506f59220277fdff7ab92c13', style: {
|
|
2956
3053
|
opacity: this.isEditorVisible ? '1' : '0',
|
|
2957
3054
|
visibility: this.isEditorVisible ? 'visible' : 'hidden',
|
|
2958
3055
|
transition: 'opacity 0.2s ease-in-out, visibility 0.2s ease-in-out',
|
|
2959
|
-
} }, h("div", { key: '
|
|
3056
|
+
} }, h("div", { key: '14fd50ad857199f3b6be708fc4263aa2e69067de', class: "top-left-buttons" }, 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) }), h("kritzel-back-to-content", { key: '1840374d7353af2b050822dcd9c54be46e326278', visible: this.isBackToContentButtonVisible, text: this.resolvedTerms['backToContent.label'] ?? 'Back to content', onBackToContent: () => this.backToContent() })), h("kritzel-engine", { key: 'cdde0b65c811ee28fb4266afb96005c1fed24323', ref: el => {
|
|
2960
3057
|
if (el) {
|
|
2961
3058
|
this.engineRef = el;
|
|
2962
3059
|
}
|
|
2963
|
-
}, 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,
|
|
3060
|
+
}, 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) }), h("kritzel-controls", { key: '9b91d0cc3b3afba8894bd852bac911178c0ca82d', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
|
|
2964
3061
|
if (el) {
|
|
2965
3062
|
this.controlsRef = el;
|
|
2966
3063
|
}
|
|
2967
|
-
}, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: '
|
|
3064
|
+
}, controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: '01f63c615eec68696532926b6d1efe2443e2d46a', class: "bottom-left-buttons" }, h("kritzel-zoom-panel", { key: '73a1fc5b0892b88d6c0a7c5debb42b7bb3f03a84', visible: this.isZoomPanelVisible, disabled: !this.isZoomingEnabled, zoomPercent: this.currentZoomPercent, terms: this.resolvedTerms, onZoomIn: () => this.zoomIn(), onZoomOut: () => this.zoomOut() })), h("div", { key: '94776978ba9dd68b2c5f62b141c074852585a1cd', class: "top-right-buttons" }, h("kritzel-settings", { key: '665a74511f8e511602d4d3437927e03af2c3c01c', ref: el => {
|
|
2968
3065
|
if (el) {
|
|
2969
3066
|
this.settingsRef = el;
|
|
2970
3067
|
}
|
|
2971
|
-
}, 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) }), h("kritzel-export", { key: '
|
|
3068
|
+
}, 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) }), h("kritzel-export", { key: '6b52127d4634d92c3e7410a084f37970bd8c84e7', ref: el => {
|
|
2972
3069
|
if (el) {
|
|
2973
3070
|
this.exportRef = el;
|
|
2974
3071
|
}
|
|
2975
|
-
}, workspaceName: this.activeWorkspace?.name || 'workspace', onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: '
|
|
3072
|
+
}, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: '002a01d361137f867efc2a0c91a6c0e9619d4359', users: this.activeUsers }), shouldShowCurrentUser && h("kritzel-current-user", { key: '6a9e0ad77997cbb10981d58afb176a7f7f4938aa', user: this.user, terms: this.resolvedTerms }), shouldShowLoginButton && (h("kritzel-button", { key: '5ba13725105d0af68c51fec455569ac7bbeaecde', onButtonClick: () => this.loginDialogRef?.open() }, this.resolvedTerms['login.dialogTitle'] ?? 'Sign in')), h("kritzel-more-menu", { key: 'f392a518fef108b395eb6d6681af9e06827e3780', items: this.moreMenuItems, visible: this.isMoreMenuVisible, terms: this.resolvedTerms }), h("kritzel-share-dialog", { key: '845a3153f5fd9b419f7d0b81be85f5e1ea0051cc', ref: el => {
|
|
2976
3073
|
if (el) {
|
|
2977
3074
|
this.shareDialogRef = el;
|
|
2978
3075
|
}
|
|
2979
|
-
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: '
|
|
3076
|
+
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: '5a7b149d8e2c2acbda3d7818d8576d8ad249ef23', ref: el => {
|
|
2980
3077
|
if (el) {
|
|
2981
3078
|
this.loginDialogRef = el;
|
|
2982
3079
|
}
|
|
2983
|
-
}, providers: this.loginConfig.providers, dialogTitle: this.loginConfig.title, subtitle: this.loginConfig.subtitle, onProviderLogin: this.handleProviderLogin })))));
|
|
3080
|
+
}, providers: this.loginConfig.providers, dialogTitle: this.loginConfig.title ?? this.resolvedTerms['login.dialogTitle'] ?? 'Sign in', subtitle: this.loginConfig.subtitle, onProviderLogin: this.handleProviderLogin })))));
|
|
2984
3081
|
}
|
|
2985
3082
|
static get watchers() { return {
|
|
2986
3083
|
"isEngineReady": [{
|
|
@@ -3003,6 +3100,9 @@ const KritzelEditor = class {
|
|
|
3003
3100
|
}],
|
|
3004
3101
|
"themes": [{
|
|
3005
3102
|
"onThemesChange": 0
|
|
3103
|
+
}],
|
|
3104
|
+
"locale": [{
|
|
3105
|
+
"onLocaleChange": 0
|
|
3006
3106
|
}]
|
|
3007
3107
|
}; }
|
|
3008
3108
|
};
|
|
@@ -21257,6 +21357,28 @@ class KritzelContextMenuHandler extends KritzelBaseHandler {
|
|
|
21257
21357
|
this.globalContextMenuItems = globalContextMenuItems;
|
|
21258
21358
|
this.objectContextMenuItems = objectContextMenuItems;
|
|
21259
21359
|
}
|
|
21360
|
+
/**
|
|
21361
|
+
* Resolves the active context menu items for display, translating each item's
|
|
21362
|
+
* `label` through the current locale. When the label is a known
|
|
21363
|
+
* {@link KritzelTermKey} the translation is used; any other string is passed
|
|
21364
|
+
* through unchanged. Runs at menu-open time so the labels reflect the locale
|
|
21365
|
+
* active at that moment.
|
|
21366
|
+
* @returns A new array of items with resolved labels.
|
|
21367
|
+
*/
|
|
21368
|
+
resolveLabels(items) {
|
|
21369
|
+
return items.map(item => ({
|
|
21370
|
+
...item,
|
|
21371
|
+
label: this._core.localizationManager.translate(item.label),
|
|
21372
|
+
children: item.children ? this.resolveLabels(item.children) : undefined,
|
|
21373
|
+
}));
|
|
21374
|
+
}
|
|
21375
|
+
/**
|
|
21376
|
+
* Gets the active context menu items (object or global) with localized labels.
|
|
21377
|
+
*/
|
|
21378
|
+
getResolvedContextMenuItems() {
|
|
21379
|
+
const items = this._core.store.selectionGroup ? this.objectContextMenuItems : this.globalContextMenuItems;
|
|
21380
|
+
return this.resolveLabels(items);
|
|
21381
|
+
}
|
|
21260
21382
|
/**
|
|
21261
21383
|
* Handles the context menu event (typically triggered by right-click).
|
|
21262
21384
|
* This method performs the following operations:
|
|
@@ -21300,7 +21422,7 @@ class KritzelContextMenuHandler extends KritzelBaseHandler {
|
|
|
21300
21422
|
this._core.addSelectionGroup(selectionGroup);
|
|
21301
21423
|
this._core.rerender();
|
|
21302
21424
|
}
|
|
21303
|
-
this._core.store.state.contextMenuItems = this.
|
|
21425
|
+
this._core.store.state.contextMenuItems = this.getResolvedContextMenuItems();
|
|
21304
21426
|
const clickX = event.clientX - this._core.store.offsetX;
|
|
21305
21427
|
const clickY = event.clientY - this._core.store.offsetY;
|
|
21306
21428
|
const { translateX, translateY, scale } = this._core.store.state;
|
|
@@ -21356,7 +21478,7 @@ class KritzelContextMenuHandler extends KritzelBaseHandler {
|
|
|
21356
21478
|
this._core.addSelectionGroup(selectionGroup);
|
|
21357
21479
|
}
|
|
21358
21480
|
}
|
|
21359
|
-
this._core.store.state.contextMenuItems = this.
|
|
21481
|
+
this._core.store.state.contextMenuItems = this.getResolvedContextMenuItems();
|
|
21360
21482
|
this._core.store.state.contextMenuWorldX = x;
|
|
21361
21483
|
this._core.store.state.contextMenuWorldY = y;
|
|
21362
21484
|
const { translateX, translateY, scale } = this._core.store.state;
|
|
@@ -21403,6 +21525,7 @@ class KritzelCustomElement extends KritzelBaseObject {
|
|
|
21403
21525
|
if (config) {
|
|
21404
21526
|
this.translateX = config.translateX || 0;
|
|
21405
21527
|
this.translateY = config.translateY || 0;
|
|
21528
|
+
this.rotation = KritzelMathHelper.degreesToRadians(config.rotation ?? 0);
|
|
21406
21529
|
this.scale = config.scale || 1;
|
|
21407
21530
|
this.element = config.element;
|
|
21408
21531
|
this.height = config.height || 0;
|
|
@@ -23969,6 +24092,10 @@ class KritzelCore {
|
|
|
23969
24092
|
_cursorManager;
|
|
23970
24093
|
/** Manager for theme styling */
|
|
23971
24094
|
_themeManager;
|
|
24095
|
+
/** Manager for localization / translated UI strings */
|
|
24096
|
+
_localizationManager;
|
|
24097
|
+
/** Manager for license validation and watermark gating */
|
|
24098
|
+
_licenseManager;
|
|
23972
24099
|
/** Per-core registry of drawing tools (one instance per editor). */
|
|
23973
24100
|
_toolRegistry;
|
|
23974
24101
|
/** Optional unique identifier for namespacing storage keys across multiple editor instances */
|
|
@@ -24017,6 +24144,20 @@ class KritzelCore {
|
|
|
24017
24144
|
get themeManager() {
|
|
24018
24145
|
return this._themeManager;
|
|
24019
24146
|
}
|
|
24147
|
+
/**
|
|
24148
|
+
* Gets the localization manager.
|
|
24149
|
+
* @returns The KritzelLocalizationManager for resolving translated UI strings
|
|
24150
|
+
*/
|
|
24151
|
+
get localizationManager() {
|
|
24152
|
+
return this._localizationManager;
|
|
24153
|
+
}
|
|
24154
|
+
/**
|
|
24155
|
+
* Gets the license manager.
|
|
24156
|
+
* @returns The KritzelLicenseManager for validating licenses and gating the watermark
|
|
24157
|
+
*/
|
|
24158
|
+
get licenseManager() {
|
|
24159
|
+
return this._licenseManager;
|
|
24160
|
+
}
|
|
24020
24161
|
/**
|
|
24021
24162
|
* Gets the tool registry scoped to this core instance.
|
|
24022
24163
|
* @returns The KritzelToolRegistry owned by this core
|
|
@@ -24069,6 +24210,8 @@ class KritzelCore {
|
|
|
24069
24210
|
this._anchorManager = new KritzelAnchorManager(this);
|
|
24070
24211
|
this._cursorManager = new KritzelCursorManager(this);
|
|
24071
24212
|
this._themeManager = new KritzelThemeManager(this);
|
|
24213
|
+
this._localizationManager = new KritzelLocalizationManager(this);
|
|
24214
|
+
this._licenseManager = new KritzelLicenseManager(this);
|
|
24072
24215
|
this._toolRegistry = new KritzelToolRegistry(this);
|
|
24073
24216
|
this._assetResolver = new KritzelAssetResolver();
|
|
24074
24217
|
}
|
|
@@ -24104,6 +24247,8 @@ class KritzelCore {
|
|
|
24104
24247
|
this._editorId = editorId;
|
|
24105
24248
|
// Re-create theme manager so it picks up the new storage key
|
|
24106
24249
|
this._themeManager = new KritzelThemeManager(this);
|
|
24250
|
+
// Re-create localization manager so it picks up the new storage key
|
|
24251
|
+
this._localizationManager = new KritzelLocalizationManager(this);
|
|
24107
24252
|
}
|
|
24108
24253
|
/**
|
|
24109
24254
|
* Initializes the Yjs document for collaborative editing.
|
|
@@ -25250,7 +25395,7 @@ class KritzelSvgExportHelper {
|
|
|
25250
25395
|
* @returns SVG document string
|
|
25251
25396
|
*/
|
|
25252
25397
|
static generateSvg(objects, options = {}) {
|
|
25253
|
-
const { theme, padding = 0, includeXmlDeclaration = true } = options;
|
|
25398
|
+
const { theme, padding = 0, includeXmlDeclaration = true, rasterSafeForCanvas = false, imageDataUrls } = options;
|
|
25254
25399
|
if (!objects || objects.length === 0) {
|
|
25255
25400
|
return '';
|
|
25256
25401
|
}
|
|
@@ -25270,7 +25415,7 @@ class KritzelSvgExportHelper {
|
|
|
25270
25415
|
// Generate SVG elements for each object
|
|
25271
25416
|
const elements = objects
|
|
25272
25417
|
.sort((a, b) => a.zIndex - b.zIndex)
|
|
25273
|
-
.map(obj => this.objectToSvgElement(obj, theme))
|
|
25418
|
+
.map(obj => this.objectToSvgElement(obj, theme, imageDataUrls, rasterSafeForCanvas))
|
|
25274
25419
|
.filter(Boolean)
|
|
25275
25420
|
.join('\n ');
|
|
25276
25421
|
const xmlDecl = includeXmlDeclaration ? '<?xml version="1.0" encoding="UTF-8"?>\n' : '';
|
|
@@ -25296,6 +25441,102 @@ class KritzelSvgExportHelper {
|
|
|
25296
25441
|
}
|
|
25297
25442
|
return result;
|
|
25298
25443
|
}
|
|
25444
|
+
/**
|
|
25445
|
+
* Resolves every image referenced by the given objects (including those
|
|
25446
|
+
* nested inside groups) to an inlined `data:` URL, keyed by object id.
|
|
25447
|
+
*
|
|
25448
|
+
* This is required for export flows that rasterize the SVG (e.g. PNG
|
|
25449
|
+
* export): an SVG loaded into an `<img>` element will NOT load external
|
|
25450
|
+
* or `blob:` resources, so a `<image href="blob:...">` renders as a
|
|
25451
|
+
* broken-image placeholder. Embedding the bytes as a base64 `data:` URL
|
|
25452
|
+
* makes the image self-contained and survive rasterization.
|
|
25453
|
+
*
|
|
25454
|
+
* Resolution is best-effort: images that fail to resolve are simply
|
|
25455
|
+
* omitted from the map, and the SVG falls back to whatever `href` the
|
|
25456
|
+
* synchronous path would have produced.
|
|
25457
|
+
* @param objects - Objects to inline images for
|
|
25458
|
+
* @param assetResolver - Resolver used to fetch asset bytes; optional
|
|
25459
|
+
* @returns Map of image object id -> inlined `data:` URL
|
|
25460
|
+
*/
|
|
25461
|
+
static async resolveImageDataUrls(objects, assetResolver) {
|
|
25462
|
+
const dataUrls = new Map();
|
|
25463
|
+
if (!objects || objects.length === 0) {
|
|
25464
|
+
return dataUrls;
|
|
25465
|
+
}
|
|
25466
|
+
const images = this.flattenObjects(objects).filter((obj) => KritzelClassHelper.isInstanceOf(obj, 'KritzelImage'));
|
|
25467
|
+
await Promise.all(images.map(async (image) => {
|
|
25468
|
+
// Legacy inline data URL is already embeddable as-is.
|
|
25469
|
+
if (image.src?.startsWith('data:')) {
|
|
25470
|
+
dataUrls.set(image.id, image.src);
|
|
25471
|
+
return;
|
|
25472
|
+
}
|
|
25473
|
+
// A resolvedSrc that is itself a data URL can be embedded directly.
|
|
25474
|
+
if (image.resolvedSrc?.startsWith('data:')) {
|
|
25475
|
+
dataUrls.set(image.id, image.resolvedSrc);
|
|
25476
|
+
return;
|
|
25477
|
+
}
|
|
25478
|
+
if (!image.assetId || !assetResolver) {
|
|
25479
|
+
return;
|
|
25480
|
+
}
|
|
25481
|
+
try {
|
|
25482
|
+
const blob = await assetResolver.fetchBlob(image.assetId);
|
|
25483
|
+
dataUrls.set(image.id, await this.blobToDataUrl(blob));
|
|
25484
|
+
}
|
|
25485
|
+
catch (err) {
|
|
25486
|
+
console.warn(`[KritzelSvgExportHelper] Failed to inline image asset ${image.assetId} for export:`, err);
|
|
25487
|
+
}
|
|
25488
|
+
}));
|
|
25489
|
+
return dataUrls;
|
|
25490
|
+
}
|
|
25491
|
+
/**
|
|
25492
|
+
* Reads a Blob into a base64 `data:` URL.
|
|
25493
|
+
* @param blob - The blob to encode
|
|
25494
|
+
* @returns Promise resolving to the data URL string
|
|
25495
|
+
*/
|
|
25496
|
+
static async blobToDataUrl(blob) {
|
|
25497
|
+
// Prefer FileReader in browser-like runtimes for efficiency.
|
|
25498
|
+
const hasFileReader = typeof FileReader !== 'undefined';
|
|
25499
|
+
if (hasFileReader) {
|
|
25500
|
+
try {
|
|
25501
|
+
return await new Promise((resolve, reject) => {
|
|
25502
|
+
const reader = new FileReader();
|
|
25503
|
+
reader.onload = () => {
|
|
25504
|
+
if (typeof reader.result === 'string') {
|
|
25505
|
+
resolve(reader.result);
|
|
25506
|
+
return;
|
|
25507
|
+
}
|
|
25508
|
+
reject(new Error('FileReader result is not a string'));
|
|
25509
|
+
};
|
|
25510
|
+
reader.onerror = () => reject(reader.error ?? new Error('Failed to read blob as data URL'));
|
|
25511
|
+
reader.readAsDataURL(blob);
|
|
25512
|
+
});
|
|
25513
|
+
}
|
|
25514
|
+
catch {
|
|
25515
|
+
// Fall through to the ArrayBuffer-based encoder.
|
|
25516
|
+
}
|
|
25517
|
+
}
|
|
25518
|
+
const bytes = new Uint8Array(await blob.arrayBuffer());
|
|
25519
|
+
const mimeType = blob.type || 'application/octet-stream';
|
|
25520
|
+
return `data:${mimeType};base64,${this.uint8ToBase64(bytes)}`;
|
|
25521
|
+
}
|
|
25522
|
+
/**
|
|
25523
|
+
* Encodes a byte array to base64 across browser and Node-like runtimes.
|
|
25524
|
+
*/
|
|
25525
|
+
static uint8ToBase64(bytes) {
|
|
25526
|
+
if (typeof Buffer !== 'undefined') {
|
|
25527
|
+
return Buffer.from(bytes).toString('base64');
|
|
25528
|
+
}
|
|
25529
|
+
let binary = '';
|
|
25530
|
+
const chunkSize = 0x8000;
|
|
25531
|
+
for (let i = 0; i < bytes.length; i += chunkSize) {
|
|
25532
|
+
const chunk = bytes.subarray(i, Math.min(i + chunkSize, bytes.length));
|
|
25533
|
+
binary += String.fromCharCode(...chunk);
|
|
25534
|
+
}
|
|
25535
|
+
if (typeof btoa === 'function') {
|
|
25536
|
+
return btoa(binary);
|
|
25537
|
+
}
|
|
25538
|
+
throw new Error('No base64 encoder available in this runtime');
|
|
25539
|
+
}
|
|
25299
25540
|
/**
|
|
25300
25541
|
* Collects SVG defs (markers, patterns, etc.) needed by the objects.
|
|
25301
25542
|
* @param objects - Objects to collect defs for
|
|
@@ -25340,9 +25581,10 @@ class KritzelSvgExportHelper {
|
|
|
25340
25581
|
* Converts a Kritzel object to its SVG element representation.
|
|
25341
25582
|
* @param object - The object to convert
|
|
25342
25583
|
* @param theme - Theme for color resolution
|
|
25584
|
+
* @param imageDataUrls - Optional map of image id -> inlined data URL
|
|
25343
25585
|
* @returns SVG element string, or empty string if object type is not supported
|
|
25344
25586
|
*/
|
|
25345
|
-
static objectToSvgElement(object, theme) {
|
|
25587
|
+
static objectToSvgElement(object, theme, imageDataUrls, rasterSafeForCanvas = false) {
|
|
25346
25588
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelPath')) {
|
|
25347
25589
|
return this.pathToSvg(object, theme);
|
|
25348
25590
|
}
|
|
@@ -25353,13 +25595,13 @@ class KritzelSvgExportHelper {
|
|
|
25353
25595
|
return this.shapeToSvg(object, theme);
|
|
25354
25596
|
}
|
|
25355
25597
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelText')) {
|
|
25356
|
-
return this.textToSvg(object, theme);
|
|
25598
|
+
return this.textToSvg(object, theme, rasterSafeForCanvas);
|
|
25357
25599
|
}
|
|
25358
25600
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
|
|
25359
|
-
return this.imageToSvg(object);
|
|
25601
|
+
return this.imageToSvg(object, imageDataUrls);
|
|
25360
25602
|
}
|
|
25361
25603
|
if (KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
|
|
25362
|
-
return this.groupToSvg(object, theme);
|
|
25604
|
+
return this.groupToSvg(object, theme, imageDataUrls, rasterSafeForCanvas);
|
|
25363
25605
|
}
|
|
25364
25606
|
return '';
|
|
25365
25607
|
}
|
|
@@ -25374,9 +25616,10 @@ class KritzelSvgExportHelper {
|
|
|
25374
25616
|
const fill = KritzelColorHelper.resolveThemeColor(path.fill, theme);
|
|
25375
25617
|
const stroke = KritzelColorHelper.resolveThemeColor(path.stroke, theme);
|
|
25376
25618
|
const opacity = path.opacity !== 1 ? ` opacity="${path.opacity}"` : '';
|
|
25619
|
+
const scale = this.getObjectScale(path);
|
|
25377
25620
|
// Path needs to be wrapped in a g with translation since path.d uses local coordinates
|
|
25378
25621
|
return `<g transform="${transform}"${opacity}>
|
|
25379
|
-
<svg viewBox="${path.viewBox}" width="${path.totalWidth /
|
|
25622
|
+
<svg viewBox="${path.viewBox}" width="${path.totalWidth / scale}" height="${path.totalHeight / scale}" overflow="visible">
|
|
25380
25623
|
<path d="${path.d}" fill="${fill || 'none'}" stroke="${stroke || 'none'}"${path.strokeWidth ? ` stroke-width="${path.strokeWidth}"` : ''}/>
|
|
25381
25624
|
</svg>
|
|
25382
25625
|
</g>`;
|
|
@@ -25391,10 +25634,11 @@ class KritzelSvgExportHelper {
|
|
|
25391
25634
|
const transform = this.buildTransform(line);
|
|
25392
25635
|
const stroke = KritzelColorHelper.resolveThemeColor(line.stroke, theme);
|
|
25393
25636
|
const opacity = line.opacity !== 1 ? ` opacity="${line.opacity}"` : '';
|
|
25637
|
+
const scale = this.getObjectScale(line);
|
|
25394
25638
|
const markerStart = line.hasStartArrow ? ` marker-start="url(#${line.startMarkerId})"` : '';
|
|
25395
25639
|
const markerEnd = line.hasEndArrow ? ` marker-end="url(#${line.endMarkerId})"` : '';
|
|
25396
25640
|
return `<g transform="${transform}"${opacity}>
|
|
25397
|
-
<svg viewBox="${line.viewBox}" width="${line.totalWidth /
|
|
25641
|
+
<svg viewBox="${line.viewBox}" width="${line.totalWidth / scale}" height="${line.totalHeight / scale}" overflow="visible">
|
|
25398
25642
|
<path d="${line.d}" fill="none" stroke="${stroke}" stroke-width="${line.strokeWidth}" stroke-linecap="round"${markerStart}${markerEnd}/>
|
|
25399
25643
|
</svg>
|
|
25400
25644
|
</g>`;
|
|
@@ -25410,6 +25654,7 @@ class KritzelSvgExportHelper {
|
|
|
25410
25654
|
const fill = KritzelColorHelper.resolveThemeColor(shape.fillColor, theme);
|
|
25411
25655
|
const stroke = KritzelColorHelper.resolveThemeColor(shape.strokeColor, theme);
|
|
25412
25656
|
const opacity = shape.opacity !== 1 ? ` opacity="${shape.opacity}"` : '';
|
|
25657
|
+
const scale = this.getObjectScale(shape);
|
|
25413
25658
|
// Get the SVG path for the shape
|
|
25414
25659
|
const pathD = shape.getSvgPath();
|
|
25415
25660
|
// Handle text content if present
|
|
@@ -25428,7 +25673,7 @@ class KritzelSvgExportHelper {
|
|
|
25428
25673
|
}
|
|
25429
25674
|
}
|
|
25430
25675
|
return `<g transform="${transform}"${opacity}>
|
|
25431
|
-
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth /
|
|
25676
|
+
<svg viewBox="${shape.viewBox}" width="${shape.totalWidth / scale}" height="${shape.totalHeight / scale}" overflow="visible" preserveAspectRatio="none">
|
|
25432
25677
|
<path d="${pathD}" fill="${fill || 'transparent'}" stroke="${stroke}" stroke-width="${shape.strokeWidth}"/>${textContent}
|
|
25433
25678
|
</svg>
|
|
25434
25679
|
</g>`;
|
|
@@ -25439,45 +25684,85 @@ class KritzelSvgExportHelper {
|
|
|
25439
25684
|
* @param theme - Theme for color resolution
|
|
25440
25685
|
* @returns SVG element string
|
|
25441
25686
|
*/
|
|
25442
|
-
static textToSvg(text, theme) {
|
|
25687
|
+
static textToSvg(text, theme, rasterSafeForCanvas = false) {
|
|
25688
|
+
if (rasterSafeForCanvas) {
|
|
25689
|
+
return this.textToSvgRasterSafe(text, theme);
|
|
25690
|
+
}
|
|
25443
25691
|
const transform = this.buildTransform(text);
|
|
25444
25692
|
const opacity = text.opacity !== 1 ? ` opacity="${text.opacity}"` : '';
|
|
25445
25693
|
const fontColor = KritzelColorHelper.resolveThemeColor(text.fontColor, theme);
|
|
25446
25694
|
const bgColor = KritzelColorHelper.resolveThemeColor(text.backgroundColor, theme);
|
|
25695
|
+
const scale = this.getObjectScale(text);
|
|
25447
25696
|
// Convert ProseMirror content to HTML
|
|
25448
25697
|
const htmlContent = this.prosemirrorToHtml(text.content, text, theme);
|
|
25449
25698
|
// Calculate dimensions accounting for scale
|
|
25450
|
-
const width = text.totalWidth /
|
|
25451
|
-
const height = text.totalHeight /
|
|
25699
|
+
const width = text.totalWidth / scale;
|
|
25700
|
+
const height = text.totalHeight / scale;
|
|
25452
25701
|
return `<g transform="${transform}"${opacity}>
|
|
25453
25702
|
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
25454
25703
|
<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;">
|
|
25455
25704
|
${htmlContent}
|
|
25456
25705
|
</div>
|
|
25457
25706
|
</foreignObject>
|
|
25707
|
+
</g>`;
|
|
25708
|
+
}
|
|
25709
|
+
/**
|
|
25710
|
+
* Converts a KritzelText to SVG using pure SVG text primitives.
|
|
25711
|
+
* This path avoids `<foreignObject>`, which taints canvases when the
|
|
25712
|
+
* generated SVG is rasterized through `<img>` and `drawImage`.
|
|
25713
|
+
*/
|
|
25714
|
+
static textToSvgRasterSafe(text, theme) {
|
|
25715
|
+
const transform = this.buildTransform(text);
|
|
25716
|
+
const opacity = text.opacity !== 1 ? ` opacity="${text.opacity}"` : '';
|
|
25717
|
+
const fontColor = KritzelColorHelper.resolveThemeColor(text.fontColor, theme);
|
|
25718
|
+
const bgColor = KritzelColorHelper.resolveThemeColor(text.backgroundColor, theme);
|
|
25719
|
+
const scale = this.getObjectScale(text);
|
|
25720
|
+
const width = text.totalWidth / scale;
|
|
25721
|
+
const height = text.totalHeight / scale;
|
|
25722
|
+
const lines = this.prosemirrorToPlainTextLines(text.content);
|
|
25723
|
+
const resolvedLines = lines.length > 0 ? lines : [''];
|
|
25724
|
+
const resolvedFontSize = Math.max(1, text.fontSize * (text.scaleFactor || 1));
|
|
25725
|
+
const lineHeight = resolvedFontSize * 1.2;
|
|
25726
|
+
const startY = resolvedFontSize;
|
|
25727
|
+
const bgRect = bgColor && bgColor !== 'transparent'
|
|
25728
|
+
? `<rect x="0" y="0" width="${width}" height="${height}" fill="${bgColor}"/>`
|
|
25729
|
+
: '';
|
|
25730
|
+
const tspans = resolvedLines
|
|
25731
|
+
.map((line, index) => {
|
|
25732
|
+
const y = startY + index * lineHeight;
|
|
25733
|
+
return `<tspan x="0" y="${y}" xml:space="preserve">${this.escapeHtml(line)}</tspan>`;
|
|
25734
|
+
})
|
|
25735
|
+
.join('');
|
|
25736
|
+
return `<g transform="${transform}"${opacity}>
|
|
25737
|
+
${bgRect}
|
|
25738
|
+
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSize}" fill="${fontColor}">${tspans}</text>
|
|
25458
25739
|
</g>`;
|
|
25459
25740
|
}
|
|
25460
25741
|
/**
|
|
25461
25742
|
* Converts a KritzelImage to SVG.
|
|
25462
25743
|
*
|
|
25463
|
-
*
|
|
25464
|
-
*
|
|
25744
|
+
* Prefers an inlined `data:` URL from `imageDataUrls` (keyed by object
|
|
25745
|
+
* id) when provided, so the embedded bytes survive rasterization to
|
|
25746
|
+
* PNG. Falls back to `resolvedSrc` (populated by the renderer via the
|
|
25747
|
+
* asset resolver) and finally the legacy inline `src` field for
|
|
25465
25748
|
* documents persisted before the asset layer existed.
|
|
25466
25749
|
*
|
|
25467
|
-
* Note:
|
|
25468
|
-
*
|
|
25469
|
-
*
|
|
25470
|
-
* `
|
|
25750
|
+
* Note: a `blob:` `resolvedSrc` renders correctly on-canvas but becomes
|
|
25751
|
+
* a broken-image placeholder once the SVG is loaded into an `<img>` and
|
|
25752
|
+
* drawn to a canvas. Callers that rasterize the SVG must pass
|
|
25753
|
+
* `imageDataUrls` (see {@link KritzelSvgExportHelper.resolveImageDataUrls}).
|
|
25471
25754
|
* @param image - The image object
|
|
25755
|
+
* @param imageDataUrls - Optional map of image id -> inlined data URL
|
|
25472
25756
|
* @returns SVG element string
|
|
25473
25757
|
*/
|
|
25474
|
-
static imageToSvg(image) {
|
|
25758
|
+
static imageToSvg(image, imageDataUrls) {
|
|
25475
25759
|
const transform = this.buildTransform(image);
|
|
25476
25760
|
const opacity = image.opacity !== 1 ? ` opacity="${image.opacity}"` : '';
|
|
25761
|
+
const scale = this.getObjectScale(image);
|
|
25477
25762
|
// Calculate dimensions
|
|
25478
|
-
const width = image.totalWidth /
|
|
25479
|
-
const height = image.totalHeight /
|
|
25480
|
-
const href = image.resolvedSrc || image.src || '';
|
|
25763
|
+
const width = image.totalWidth / scale;
|
|
25764
|
+
const height = image.totalHeight / scale;
|
|
25765
|
+
const href = imageDataUrls?.get(image.id) || image.resolvedSrc || image.src || '';
|
|
25481
25766
|
return `<g transform="${transform}"${opacity}>
|
|
25482
25767
|
<image href="${href}" x="0" y="0" width="${width}" height="${height}" preserveAspectRatio="xMidYMid meet"/>
|
|
25483
25768
|
</g>`;
|
|
@@ -25486,12 +25771,13 @@ class KritzelSvgExportHelper {
|
|
|
25486
25771
|
* Converts a KritzelGroup to SVG by recursively converting children.
|
|
25487
25772
|
* @param group - The group object
|
|
25488
25773
|
* @param theme - Theme for color resolution
|
|
25774
|
+
* @param imageDataUrls - Optional map of image id -> inlined data URL
|
|
25489
25775
|
* @returns SVG element string
|
|
25490
25776
|
*/
|
|
25491
|
-
static groupToSvg(group, theme) {
|
|
25777
|
+
static groupToSvg(group, theme, imageDataUrls, rasterSafeForCanvas = false) {
|
|
25492
25778
|
const children = group.children
|
|
25493
25779
|
.sort((a, b) => a.zIndex - b.zIndex)
|
|
25494
|
-
.map(child => this.objectToSvgElement(child, theme))
|
|
25780
|
+
.map(child => this.objectToSvgElement(child, theme, imageDataUrls, rasterSafeForCanvas))
|
|
25495
25781
|
.filter(Boolean)
|
|
25496
25782
|
.join('\n ');
|
|
25497
25783
|
if (!children) {
|
|
@@ -25510,17 +25796,25 @@ class KritzelSvgExportHelper {
|
|
|
25510
25796
|
*/
|
|
25511
25797
|
static buildTransform(object) {
|
|
25512
25798
|
const transforms = [];
|
|
25799
|
+
const scale = this.getObjectScale(object);
|
|
25513
25800
|
// Translation
|
|
25514
25801
|
transforms.push(`translate(${object.translateX}, ${object.translateY})`);
|
|
25515
25802
|
// Rotation around center
|
|
25516
25803
|
if (object.rotation !== 0) {
|
|
25517
|
-
const centerX = object.totalWidth / 2 /
|
|
25518
|
-
const centerY = object.totalHeight / 2 /
|
|
25804
|
+
const centerX = object.totalWidth / 2 / scale;
|
|
25805
|
+
const centerY = object.totalHeight / 2 / scale;
|
|
25519
25806
|
const degrees = object.rotation * (180 / Math.PI);
|
|
25520
25807
|
transforms.push(`rotate(${degrees}, ${centerX}, ${centerY})`);
|
|
25521
25808
|
}
|
|
25522
25809
|
return transforms.join(' ');
|
|
25523
25810
|
}
|
|
25811
|
+
/**
|
|
25812
|
+
* Returns a safe non-zero scale for export geometry calculations.
|
|
25813
|
+
*/
|
|
25814
|
+
static getObjectScale(object) {
|
|
25815
|
+
const scale = object.scale ?? 1;
|
|
25816
|
+
return scale === 0 ? 1 : scale;
|
|
25817
|
+
}
|
|
25524
25818
|
/**
|
|
25525
25819
|
* Converts ProseMirror JSON content to HTML string.
|
|
25526
25820
|
* @param content - ProseMirror document JSON
|
|
@@ -25576,6 +25870,54 @@ class KritzelSvgExportHelper {
|
|
|
25576
25870
|
return '';
|
|
25577
25871
|
}
|
|
25578
25872
|
}
|
|
25873
|
+
/**
|
|
25874
|
+
* Converts ProseMirror JSON content to plain-text lines.
|
|
25875
|
+
* Used by raster-safe SVG export, which cannot depend on HTML/foreignObject.
|
|
25876
|
+
*/
|
|
25877
|
+
static prosemirrorToPlainTextLines(content) {
|
|
25878
|
+
if (!content || !Array.isArray(content.content)) {
|
|
25879
|
+
return [];
|
|
25880
|
+
}
|
|
25881
|
+
const plainText = content.content
|
|
25882
|
+
.map((node) => this.nodeToPlainText(node))
|
|
25883
|
+
.join('')
|
|
25884
|
+
.replace(/\r\n/g, '\n')
|
|
25885
|
+
.replace(/\n+$/, '');
|
|
25886
|
+
if (!plainText) {
|
|
25887
|
+
return [];
|
|
25888
|
+
}
|
|
25889
|
+
return plainText.split('\n');
|
|
25890
|
+
}
|
|
25891
|
+
/**
|
|
25892
|
+
* Converts a ProseMirror node tree into plain text.
|
|
25893
|
+
*/
|
|
25894
|
+
static nodeToPlainText(node) {
|
|
25895
|
+
if (!node) {
|
|
25896
|
+
return '';
|
|
25897
|
+
}
|
|
25898
|
+
switch (node.type) {
|
|
25899
|
+
case 'text':
|
|
25900
|
+
return node.text || '';
|
|
25901
|
+
case 'hard_break':
|
|
25902
|
+
return '\n';
|
|
25903
|
+
case 'paragraph': {
|
|
25904
|
+
const paragraph = Array.isArray(node.content)
|
|
25905
|
+
? node.content.map((child) => this.nodeToPlainText(child)).join('')
|
|
25906
|
+
: '';
|
|
25907
|
+
return `${paragraph}\n`;
|
|
25908
|
+
}
|
|
25909
|
+
case 'list_item': {
|
|
25910
|
+
const item = Array.isArray(node.content)
|
|
25911
|
+
? node.content.map((child) => this.nodeToPlainText(child)).join('')
|
|
25912
|
+
: '';
|
|
25913
|
+
return `- ${item.trim()}\n`;
|
|
25914
|
+
}
|
|
25915
|
+
default:
|
|
25916
|
+
return Array.isArray(node.content)
|
|
25917
|
+
? node.content.map((child) => this.nodeToPlainText(child)).join('')
|
|
25918
|
+
: '';
|
|
25919
|
+
}
|
|
25920
|
+
}
|
|
25579
25921
|
/**
|
|
25580
25922
|
* Applies a ProseMirror mark to text.
|
|
25581
25923
|
* @param text - The text to wrap
|
|
@@ -26626,6 +26968,11 @@ const KritzelEngine = class {
|
|
|
26626
26968
|
onThemeChange(newValue) {
|
|
26627
26969
|
this.core.themeManager.setTheme(newValue);
|
|
26628
26970
|
}
|
|
26971
|
+
/** License key that, when valid, removes the "Powered by Kritzel" watermark. */
|
|
26972
|
+
licenseKey;
|
|
26973
|
+
onLicenseKeyChange(newValue) {
|
|
26974
|
+
this.core.licenseManager.validate(newValue);
|
|
26975
|
+
}
|
|
26629
26976
|
/** An array of available themes for the editor. */
|
|
26630
26977
|
themes;
|
|
26631
26978
|
onThemesChange(newValue) {
|
|
@@ -26634,6 +26981,25 @@ const KritzelEngine = class {
|
|
|
26634
26981
|
this.core.themeManager.applyTheme(this.core.themeManager.currentTheme);
|
|
26635
26982
|
}
|
|
26636
26983
|
}
|
|
26984
|
+
/** The current locale (language) code to apply to the editor, e.g. 'en', 'de', 'fr'. */
|
|
26985
|
+
locale = 'en';
|
|
26986
|
+
onLocaleChange(newValue) {
|
|
26987
|
+
this.core.localizationManager.setLocale(newValue);
|
|
26988
|
+
}
|
|
26989
|
+
/** An array of available locale definitions (with optional partial term overrides). */
|
|
26990
|
+
locales;
|
|
26991
|
+
onLocalesChange(newValue) {
|
|
26992
|
+
if (newValue && newValue.length > 0) {
|
|
26993
|
+
this.core.localizationManager.registerLocales(newValue);
|
|
26994
|
+
this.core.localizationManager.setLocale(this.locale);
|
|
26995
|
+
}
|
|
26996
|
+
}
|
|
26997
|
+
/** The locale used to resolve terms missing from the active locale. */
|
|
26998
|
+
fallbackLocale = 'en';
|
|
26999
|
+
onFallbackLocaleChange(newValue) {
|
|
27000
|
+
this.core.localizationManager.setFallbackLocale(newValue);
|
|
27001
|
+
this.core.rerender();
|
|
27002
|
+
}
|
|
26637
27003
|
/** Left boundary of the viewport in world coordinates. Objects beyond this X position cannot be panned to. */
|
|
26638
27004
|
viewportBoundaryLeft = -Infinity;
|
|
26639
27005
|
onViewportBoundaryLeftChange(newValue) {
|
|
@@ -26661,8 +27027,10 @@ const KritzelEngine = class {
|
|
|
26661
27027
|
this.core.store.state.debugInfo = newValue;
|
|
26662
27028
|
}
|
|
26663
27029
|
}
|
|
26664
|
-
/** When false, wheel events
|
|
26665
|
-
|
|
27030
|
+
/** When false, non-modified wheel events do not pan the viewport. */
|
|
27031
|
+
isPanningEnabled = true;
|
|
27032
|
+
/** When false, Ctrl+wheel events do not zoom the viewport. */
|
|
27033
|
+
isZoomingEnabled = true;
|
|
26666
27034
|
/** External loading state. Combined with internal workspace-loading state to drive the overlay. */
|
|
26667
27035
|
isLoading = false;
|
|
26668
27036
|
onIsLoadingChange() {
|
|
@@ -26705,13 +27073,19 @@ const KritzelEngine = class {
|
|
|
26705
27073
|
if (this.core.store.isDisabled) {
|
|
26706
27074
|
return;
|
|
26707
27075
|
}
|
|
26708
|
-
if (!this.wheelEnabled) {
|
|
26709
|
-
return;
|
|
26710
|
-
}
|
|
26711
27076
|
if (this.core.store.state.isContextMenuVisible) {
|
|
26712
27077
|
this.hideContextMenu();
|
|
26713
27078
|
}
|
|
26714
|
-
|
|
27079
|
+
if (ev.ctrlKey) {
|
|
27080
|
+
if (this.isZoomingEnabled) {
|
|
27081
|
+
this.viewport.handleWheel(ev);
|
|
27082
|
+
}
|
|
27083
|
+
}
|
|
27084
|
+
else {
|
|
27085
|
+
if (this.isPanningEnabled) {
|
|
27086
|
+
this.viewport.handleWheel(ev);
|
|
27087
|
+
}
|
|
27088
|
+
}
|
|
26715
27089
|
this.core.store.state?.activeTool?.handleWheel(ev);
|
|
26716
27090
|
}
|
|
26717
27091
|
handlePointerDown(ev) {
|
|
@@ -27547,7 +27921,7 @@ const KritzelEngine = class {
|
|
|
27547
27921
|
/**
|
|
27548
27922
|
* Generates an SVG string from the currently selected objects.
|
|
27549
27923
|
* Creates clean, standards-compliant SVG markup by directly serializing object properties.
|
|
27550
|
-
* @param options - Optional export settings (theme, padding).
|
|
27924
|
+
* @param options - Optional export settings (theme, padding, raster-safe mode for canvas export).
|
|
27551
27925
|
* @returns SVG markup string, or null if no objects are selected.
|
|
27552
27926
|
*/
|
|
27553
27927
|
async getSelectedObjectsAsSvgString(options) {
|
|
@@ -27556,10 +27930,16 @@ const KritzelEngine = class {
|
|
|
27556
27930
|
return null;
|
|
27557
27931
|
}
|
|
27558
27932
|
const theme = options?.theme ?? this.core.themeManager.getStoredTheme();
|
|
27933
|
+
// Inline image bytes as data URLs so they survive both standalone SVG
|
|
27934
|
+
// files and rasterization to PNG (a `blob:` href is not loaded when an
|
|
27935
|
+
// SVG is drawn into a canvas, which otherwise yields a broken image).
|
|
27936
|
+
const imageDataUrls = await KritzelSvgExportHelper.resolveImageDataUrls(selectedObjects, this.core.assetResolver);
|
|
27559
27937
|
return KritzelSvgExportHelper.generateSvg(selectedObjects, {
|
|
27560
27938
|
theme,
|
|
27561
27939
|
padding: options?.padding ?? 0,
|
|
27562
27940
|
includeXmlDeclaration: true,
|
|
27941
|
+
rasterSafeForCanvas: options?.rasterSafeForCanvas ?? false,
|
|
27942
|
+
imageDataUrls,
|
|
27563
27943
|
});
|
|
27564
27944
|
}
|
|
27565
27945
|
/**
|
|
@@ -27598,6 +27978,9 @@ const KritzelEngine = class {
|
|
|
27598
27978
|
const svgString = await this.getSelectedObjectsAsSvgString({
|
|
27599
27979
|
theme: options?.theme,
|
|
27600
27980
|
padding: options?.padding,
|
|
27981
|
+
// Avoid foreignObject-based text serialization, which taints the
|
|
27982
|
+
// canvas in SVG->PNG conversion paths.
|
|
27983
|
+
rasterSafeForCanvas: true,
|
|
27601
27984
|
});
|
|
27602
27985
|
if (!svgString) {
|
|
27603
27986
|
return null;
|
|
@@ -27950,6 +28333,55 @@ const KritzelEngine = class {
|
|
|
27950
28333
|
return null;
|
|
27951
28334
|
}
|
|
27952
28335
|
}
|
|
28336
|
+
/**
|
|
28337
|
+
* Registers additional locale definitions (with optional partial term overrides).
|
|
28338
|
+
* @param locales - The locale definitions to register.
|
|
28339
|
+
*/
|
|
28340
|
+
async registerLocales(locales) {
|
|
28341
|
+
this.core.localizationManager.registerLocales(locales);
|
|
28342
|
+
this.core.localizationManager.setLocale(this.core.localizationManager.currentLocale);
|
|
28343
|
+
}
|
|
28344
|
+
/**
|
|
28345
|
+
* Sets the active locale (language) and re-renders the UI.
|
|
28346
|
+
* @param code - The locale code to activate, e.g. 'de'.
|
|
28347
|
+
*/
|
|
28348
|
+
async setLocale(code) {
|
|
28349
|
+
this.locale = code;
|
|
28350
|
+
this.core.localizationManager.setLocale(code);
|
|
28351
|
+
}
|
|
28352
|
+
/**
|
|
28353
|
+
* Gets the currently active locale code.
|
|
28354
|
+
*/
|
|
28355
|
+
async getLocale() {
|
|
28356
|
+
return this.core.localizationManager.currentLocale;
|
|
28357
|
+
}
|
|
28358
|
+
/**
|
|
28359
|
+
* Gets the list of available locale codes (built-in and registered).
|
|
28360
|
+
*/
|
|
28361
|
+
async getAvailableLocales() {
|
|
28362
|
+
return this.core.localizationManager.getAvailableLocales();
|
|
28363
|
+
}
|
|
28364
|
+
/**
|
|
28365
|
+
* Gets the list of available locales as `{ code, label }` options for a selector.
|
|
28366
|
+
*/
|
|
28367
|
+
async getAvailableLocaleOptions() {
|
|
28368
|
+
return this.core.localizationManager.getAvailableLocaleOptions();
|
|
28369
|
+
}
|
|
28370
|
+
/**
|
|
28371
|
+
* Resolves a term key to its translated string for the active locale.
|
|
28372
|
+
* @param key - The term key to resolve.
|
|
28373
|
+
* @param vars - Optional values for `{placeholder}` interpolation.
|
|
28374
|
+
*/
|
|
28375
|
+
async t(key, vars) {
|
|
28376
|
+
return this.core.localizationManager.translate(key, vars);
|
|
28377
|
+
}
|
|
28378
|
+
/**
|
|
28379
|
+
* Resolves every known term key for the active locale into a flat map.
|
|
28380
|
+
* Useful for UI layers that need to localize many strings at once.
|
|
28381
|
+
*/
|
|
28382
|
+
async getResolvedTerms() {
|
|
28383
|
+
return this.core.localizationManager.getAllTerms();
|
|
28384
|
+
}
|
|
27953
28385
|
core;
|
|
27954
28386
|
viewport;
|
|
27955
28387
|
contextMenuHandler;
|
|
@@ -28040,6 +28472,7 @@ const KritzelEngine = class {
|
|
|
28040
28472
|
// Clean up managers
|
|
28041
28473
|
this.core.cursorManager.cleanup();
|
|
28042
28474
|
this.core.themeManager.cleanup();
|
|
28475
|
+
this.core.licenseManager.destroy();
|
|
28043
28476
|
}
|
|
28044
28477
|
componentWillLoad() {
|
|
28045
28478
|
this.core.setEditorId(this.editorId);
|
|
@@ -28048,6 +28481,13 @@ const KritzelEngine = class {
|
|
|
28048
28481
|
}
|
|
28049
28482
|
const editorElement = this.host.closest('kritzel-editor');
|
|
28050
28483
|
this.core.themeManager.injectThemeEarly(editorElement || this.host);
|
|
28484
|
+
if (this.locales && this.locales.length > 0) {
|
|
28485
|
+
this.core.localizationManager.registerLocales(this.locales);
|
|
28486
|
+
}
|
|
28487
|
+
this.core.localizationManager.setFallbackLocale(this.fallbackLocale);
|
|
28488
|
+
this.core.localizationManager.setLocale(this.locale);
|
|
28489
|
+
this.core.licenseManager.validate(this.licenseKey);
|
|
28490
|
+
this.core.licenseManager.startPeriodicValidation();
|
|
28051
28491
|
this.core.setUser(this.user);
|
|
28052
28492
|
this.validateScaleMax(this.scaleMax);
|
|
28053
28493
|
this.validateScaleMin(this.scaleMin);
|
|
@@ -28352,7 +28792,7 @@ const KritzelEngine = class {
|
|
|
28352
28792
|
}
|
|
28353
28793
|
render() {
|
|
28354
28794
|
if (!this.viewport) {
|
|
28355
|
-
return (h(Host, null, this.core.store.state.isLoading && (h("div", { class: "workspace-loading-overlay" }, h("span", { class: "workspace-loading-spinner" }),
|
|
28795
|
+
return (h(Host, null, this.core.store.state.isLoading && (h("div", { class: "workspace-loading-overlay" }, h("span", { class: "workspace-loading-spinner" }), this.core.localizationManager.translate('engine.loading')))));
|
|
28356
28796
|
}
|
|
28357
28797
|
const currentTheme = this.core.themeManager.getStoredTheme();
|
|
28358
28798
|
const computedStyle = window.getComputedStyle(this.host);
|
|
@@ -28790,7 +29230,7 @@ const KritzelEngine = class {
|
|
|
28790
29230
|
}, this.core.store.selectionGroup?.objects || []);
|
|
28791
29231
|
}
|
|
28792
29232
|
this.hideContextMenu();
|
|
28793
|
-
}, onClose: () => this.hideContextMenu() })), this.core.store.objects?.hasAwareness && h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool instanceof KritzelEraserTool && !this.core.store.state.isScaling && h("kritzel-cursor-trail", { core: this.core })));
|
|
29233
|
+
}, onClose: () => this.hideContextMenu() })), this.core.store.objects?.hasAwareness && h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool instanceof KritzelEraserTool && !this.core.store.state.isScaling && h("kritzel-cursor-trail", { core: this.core }), !this.core.licenseManager.isLicensed && (h("kritzel-watermark", { core: this.core, label: this.core.localizationManager.translate('watermark.poweredBy') }))));
|
|
28794
29234
|
}
|
|
28795
29235
|
static get watchers() { return {
|
|
28796
29236
|
"workspace": [{
|
|
@@ -28832,9 +29272,21 @@ const KritzelEngine = class {
|
|
|
28832
29272
|
"theme": [{
|
|
28833
29273
|
"onThemeChange": 0
|
|
28834
29274
|
}],
|
|
29275
|
+
"licenseKey": [{
|
|
29276
|
+
"onLicenseKeyChange": 0
|
|
29277
|
+
}],
|
|
28835
29278
|
"themes": [{
|
|
28836
29279
|
"onThemesChange": 0
|
|
28837
29280
|
}],
|
|
29281
|
+
"locale": [{
|
|
29282
|
+
"onLocaleChange": 0
|
|
29283
|
+
}],
|
|
29284
|
+
"locales": [{
|
|
29285
|
+
"onLocalesChange": 0
|
|
29286
|
+
}],
|
|
29287
|
+
"fallbackLocale": [{
|
|
29288
|
+
"onFallbackLocaleChange": 0
|
|
29289
|
+
}],
|
|
28838
29290
|
"viewportBoundaryLeft": [{
|
|
28839
29291
|
"onViewportBoundaryLeftChange": 0
|
|
28840
29292
|
}],
|
|
@@ -28870,6 +29322,8 @@ const KritzelExport = class {
|
|
|
28870
29322
|
* The name of the current workspace, used as default filename
|
|
28871
29323
|
*/
|
|
28872
29324
|
workspaceName = 'workspace';
|
|
29325
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
29326
|
+
terms = {};
|
|
28873
29327
|
isDialogOpen = false;
|
|
28874
29328
|
previewUrl;
|
|
28875
29329
|
isLoading = false;
|
|
@@ -28879,10 +29333,12 @@ const KritzelExport = class {
|
|
|
28879
29333
|
exportPng;
|
|
28880
29334
|
exportSvg;
|
|
28881
29335
|
exportJson;
|
|
28882
|
-
tabs
|
|
28883
|
-
|
|
28884
|
-
|
|
28885
|
-
|
|
29336
|
+
get tabs() {
|
|
29337
|
+
return [
|
|
29338
|
+
{ id: 'viewport', label: this.terms['export.tabs.viewport'] ?? 'Export Viewport' },
|
|
29339
|
+
{ id: 'workspace', label: this.terms['export.tabs.workspace'] ?? 'Export Workspace' },
|
|
29340
|
+
];
|
|
29341
|
+
}
|
|
28886
29342
|
viewportFormatOptions = [
|
|
28887
29343
|
{ value: 'png', label: 'PNG' },
|
|
28888
29344
|
{ value: 'svg', label: 'SVG' },
|
|
@@ -28925,13 +29381,13 @@ const KritzelExport = class {
|
|
|
28925
29381
|
this.closeDialog();
|
|
28926
29382
|
};
|
|
28927
29383
|
renderViewportExport() {
|
|
28928
|
-
return (h("div", { class: "export-tab-content" }, this.previewUrl && (h("div", { class: "preview-container" }, h("img", { src: this.previewUrl, alt: "Viewport Preview" }))), h("kritzel-input", { label:
|
|
29384
|
+
return (h("div", { class: "export-tab-content" }, this.previewUrl && (h("div", { class: "preview-container" }, h("img", { src: this.previewUrl, alt: "Viewport Preview" }))), 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 }), h("div", { class: "format-selection" }, h("label", null, this.terms['export.format.label'] ?? 'Format'), h("kritzel-dropdown", { options: this.viewportFormatOptions, value: this.viewportExportFormat, forceOpenDirection: "up", onValueChanged: this.handleViewportFormatChange }))));
|
|
28929
29385
|
}
|
|
28930
29386
|
renderWorkspaceExport() {
|
|
28931
|
-
return (h("div", { class: "export-tab-content" }, h("kritzel-input", { label:
|
|
29387
|
+
return (h("div", { class: "export-tab-content" }, 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 })));
|
|
28932
29388
|
}
|
|
28933
29389
|
render() {
|
|
28934
|
-
return (h(Host, { key: '
|
|
29390
|
+
return (h(Host, { key: 'ff6ce7e5d3a0a7a024148529f86bf3ec7ffb0333' }, h("kritzel-dialog", { key: '9051d262450af5fbe98959092f6bb0ac25ab43ce', isOpen: this.isDialogOpen, dialogTitle: this.terms['export.dialogTitle'] ?? 'Export', closable: true, contained: true, onDialogClose: this.closeDialog }, h("div", { key: '21f404a2101d5cf1d24aeeee663d8fb1854b9574', class: "export-content" }, 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(), h("button", { key: '45809f91ddd63c74f5a4b3a2e266919f244c6109', class: "export-primary-button", onClick: this.handleExport }, this.terms['export.exportButton'] ?? 'Export')))));
|
|
28935
29391
|
}
|
|
28936
29392
|
};
|
|
28937
29393
|
KritzelExport.style = kritzelExportCss();
|
|
@@ -28946,7 +29402,7 @@ const KritzelFont = class {
|
|
|
28946
29402
|
size = 24;
|
|
28947
29403
|
color = '#000000';
|
|
28948
29404
|
render() {
|
|
28949
|
-
return (h(Host, { key: '
|
|
29405
|
+
return (h(Host, { key: '49c44f7fef61bd7116e63bbe9522b0a0e22de116' }, h("div", { key: '4d130682f67e9c0d758cb6194e6a95f15bceb2ee', class: "font-preview", style: {
|
|
28950
29406
|
fontFamily: this.fontFamily,
|
|
28951
29407
|
fontSize: `${this.size}px`,
|
|
28952
29408
|
color: this.color
|
|
@@ -29021,7 +29477,8 @@ const KritzelFontSize = class {
|
|
|
29021
29477
|
}
|
|
29022
29478
|
render() {
|
|
29023
29479
|
const color = 'var(--kritzel-global-text-primary)';
|
|
29024
|
-
|
|
29480
|
+
const sizes = this.sizes ?? [];
|
|
29481
|
+
return (h(Host, { key: '2083b05b3fdc9940c26dd90dbf9e097564ee976d' }, sizes.map(size => (h("div", { tabIndex: 0, class: {
|
|
29025
29482
|
'size-container': true,
|
|
29026
29483
|
'selected': this.selectedSize === size,
|
|
29027
29484
|
}, onClick: () => this.handleSizeClick(size), onKeyDown: event => this.handleKeyDown(event, size) }, h("kritzel-font", { fontFamily: this.fontFamily, size: size, color: color }))))));
|
|
@@ -29088,7 +29545,7 @@ const KritzelInput = class {
|
|
|
29088
29545
|
this.valueChange.emit(input.value);
|
|
29089
29546
|
};
|
|
29090
29547
|
render() {
|
|
29091
|
-
return (h(Host, { key: '
|
|
29548
|
+
return (h(Host, { key: '8584ea0fa1a2cf0b9518ea978303837da5bfaf31' }, h("div", { key: 'e9f3ac340f17580221d1a86c8eb913fce2acdf49', class: "input-container" }, this.label && h("label", { key: 'b0d4c0250b07d83a3cd99e0ab18ed672a29de5f0', class: "input-label" }, this.label), h("div", { key: '5044bcff621d6c6850ef3d225608427401b75ebd', class: { 'input-wrapper': true, 'has-suffix': !!this.suffix } }, h("input", { key: 'f8d057840e975d900c37a891268f39edb5128d49', type: this.type, class: "text-input", value: this.inputValue, placeholder: this.placeholder, disabled: this.disabled, onInput: this.handleInput }), this.suffix && h("span", { key: '4ae299b88798767b13e7126f88d3bd4703c91938', class: "input-suffix" }, this.suffix)))));
|
|
29092
29549
|
}
|
|
29093
29550
|
static get watchers() { return {
|
|
29094
29551
|
"value": [{
|
|
@@ -29228,7 +29685,7 @@ const KritzelLoginDialog = class {
|
|
|
29228
29685
|
this.dialogClosed.emit();
|
|
29229
29686
|
};
|
|
29230
29687
|
render() {
|
|
29231
|
-
return (h(Host, { key: '
|
|
29688
|
+
return (h(Host, { key: '443d817d6eba7b9fcd31cab652293d7c01fc5ffa' }, h("kritzel-dialog", { key: '55214d78abb10f7e2ba789e10d98bf7f3287ff6a', dialogTitle: this.dialogTitle, isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, size: "small", contained: true }, h("div", { key: '31806a7a7c98c2210b7f60d2e0816a8ebc14aff3', class: "login-content" }, this.subtitle && (h("p", { key: '7edb2bc7d25cb3c8589594791822e62d035cd3a6', class: "login-subtitle" }, this.subtitle)), h("div", { key: '3b7731d9cfb98915ebe07b54a07991e03716ce5c', class: "login-providers" }, this.providers.map(provider => (h("button", { key: provider.name, class: {
|
|
29232
29689
|
'provider-button': true,
|
|
29233
29690
|
'is-loading': this.loadingProvider === provider.name,
|
|
29234
29691
|
'is-disabled': this.loadingProvider !== null && this.loadingProvider !== provider.name,
|
|
@@ -29334,15 +29791,15 @@ const KritzelMasterDetail = class {
|
|
|
29334
29791
|
const selectedItem = this.items.find(item => item.id === this.selectedItemId);
|
|
29335
29792
|
const panelId = 'master-detail-panel';
|
|
29336
29793
|
const selectedTabId = selectedItem ? `tab-${selectedItem.id}` : undefined;
|
|
29337
|
-
return (h(Host, { key: '
|
|
29794
|
+
return (h(Host, { key: '6429c72aaf47f08ba0bdf5e64829b133339dafab' }, h("div", { key: '02e4616c67843632d2291abe347ee6ef7a660b12', class: {
|
|
29338
29795
|
'master-detail-container': true,
|
|
29339
29796
|
'is-mobile-detail-visible': this.showMobileDetail,
|
|
29340
|
-
} }, h("nav", { key: '
|
|
29797
|
+
} }, h("nav", { key: '35cf3e8f97819a313fa6c57cde0faf05677997eb', class: "master-menu", role: "tablist", "aria-orientation": "vertical", "aria-label": "Settings categories" }, this.items.map((item, index) => (h("button", { key: item.id, id: `tab-${item.id}`, ref: el => this.setTabRef(el, index), class: {
|
|
29341
29798
|
'menu-item': true,
|
|
29342
29799
|
'is-selected': item.id === this.selectedItemId,
|
|
29343
29800
|
'is-disabled': !!item.disabled,
|
|
29344
29801
|
'is-focused': index === this.focusedIndex,
|
|
29345
|
-
}, role: "tab", "aria-selected": item.id === this.selectedItemId ? 'true' : 'false', "aria-controls": panelId, "aria-disabled": item.disabled ? 'true' : undefined, tabIndex: this.getTabIndex(item, index), disabled: item.disabled, onClick: () => this.handleItemClick(item), onKeyDown: e => this.handleKeyDown(e, item, index), onFocus: () => this.handleFocus(index), onBlur: this.handleBlur }, item.icon && (h("kritzel-icon", { name: item.icon, size: 20, class: "menu-item-icon" })), h("span", { class: "menu-item-label" }, item.label), h("span", { class: "menu-item-chevron", "aria-hidden": "true" }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "m9 18 6-6-6-6" }))))))), h("div", { key: '
|
|
29802
|
+
}, role: "tab", "aria-selected": item.id === this.selectedItemId ? 'true' : 'false', "aria-controls": panelId, "aria-disabled": item.disabled ? 'true' : undefined, tabIndex: this.getTabIndex(item, index), disabled: item.disabled, onClick: () => this.handleItemClick(item), onKeyDown: e => this.handleKeyDown(e, item, index), onFocus: () => this.handleFocus(index), onBlur: this.handleBlur }, item.icon && (h("kritzel-icon", { name: item.icon, size: 20, class: "menu-item-icon" })), h("span", { class: "menu-item-label" }, item.label), h("span", { class: "menu-item-chevron", "aria-hidden": "true" }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "m9 18 6-6-6-6" }))))))), h("div", { key: 'cc7c69eb7ef02096fb76dbce310740d21019e72f', id: panelId, class: "detail-panel", role: "tabpanel", "aria-labelledby": selectedTabId }, h("button", { key: 'd10898c7eb8ec6d993024c7833e1f765a7b93079', class: "mobile-back-button", onClick: this.handleBackClick, "aria-label": "Back to menu" }, h("kritzel-icon", { key: '5395af1bce2b91ade970ad68b1bb87b59e771dff', name: "chevron-left", size: 20, class: "mobile-back-icon" }), "Back"), h("slot", { key: '7a5a1ef33081c117f1b16f1da887577bd97d3681' })))));
|
|
29346
29803
|
}
|
|
29347
29804
|
static get watchers() { return {
|
|
29348
29805
|
"selectedItemId": [{
|
|
@@ -29415,7 +29872,7 @@ const KritzelMenu = class {
|
|
|
29415
29872
|
this.itemCloseChildMenu.emit(event.detail);
|
|
29416
29873
|
};
|
|
29417
29874
|
render() {
|
|
29418
|
-
return (h(Host, { key: '
|
|
29875
|
+
return (h(Host, { key: '4e4e510d2b1b5834ba12739d95e7c33268c005a6', tabIndex: 0, onClick: e => e.stopPropagation() }, this.openChildMenuItem && h("div", { key: 'ee60d7f4ceefda5fcdcfb64956b20d42b703c231', class: "has-open-child-overlay", onClick: this.onOverlayClick }), this.items.map(item => (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 })))));
|
|
29419
29876
|
}
|
|
29420
29877
|
};
|
|
29421
29878
|
KritzelMenu.style = kritzelMenuCss();
|
|
@@ -29520,12 +29977,12 @@ const KritzelMenuItem = class {
|
|
|
29520
29977
|
];
|
|
29521
29978
|
}
|
|
29522
29979
|
render() {
|
|
29523
|
-
return (h(Host, { key: '
|
|
29980
|
+
return (h(Host, { key: 'ac91e3534c71074634ba053adc02f924e3fb5e14', tabIndex: this.item.isDisabled ? -1 : 0, class: {
|
|
29524
29981
|
'selected': this.item.isSelected,
|
|
29525
29982
|
'editing': this.item.isEditing,
|
|
29526
29983
|
'disabled': this.item.isDisabled,
|
|
29527
29984
|
'child-open': this.item.isChildMenuOpen,
|
|
29528
|
-
}, onClick: this.handleItemSelect }, h("div", { key: '
|
|
29985
|
+
}, onClick: this.handleItemSelect }, h("div", { key: 'f49cf8a96f7394e244ce53d3933137325221d578', class: "menu-item-overlay" }), this.item.isEditing ? this.renderEditMode() : this.renderViewMode()));
|
|
29529
29986
|
}
|
|
29530
29987
|
static get watchers() { return {
|
|
29531
29988
|
"item": [{
|
|
@@ -29565,6 +30022,8 @@ const KritzelMoreMenu = class {
|
|
|
29565
30022
|
* Offset Y for the portal positioning
|
|
29566
30023
|
*/
|
|
29567
30024
|
offsetY = 4;
|
|
30025
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
30026
|
+
terms = {};
|
|
29568
30027
|
/**
|
|
29569
30028
|
* Emitted when a menu item is selected
|
|
29570
30029
|
*/
|
|
@@ -29596,7 +30055,7 @@ const KritzelMoreMenu = class {
|
|
|
29596
30055
|
this.closeMenu();
|
|
29597
30056
|
};
|
|
29598
30057
|
render() {
|
|
29599
|
-
return (h(Host, { key: '
|
|
30058
|
+
return (h(Host, { key: '1fe90a065ac35d1c8d2e9159d006b09e104750a3', class: { mobile: this.isTouchDevice }, style: { display: this.visible ? '' : 'none' } }, h("div", { key: '734234df7d24f712fa80c3871209142fed2b5ac2', class: { 'more-menu-wrapper': true, visible: this.visible } }, h("button", { key: 'a6a56bd5714a8780339390904f0469b395748ba9', class: "more-menu-button", "data-testid": "more-menu-button", onClick: this.toggleMenu, "aria-label": this.terms['moreMenu.ariaLabel'] ?? 'More options' }, h("kritzel-icon", { key: 'a4405ef4b8219f28fec095d4a56ac0aa027a9564', name: this.icon, size: this.iconSize })), h("kritzel-portal", { key: '99aa8a87844232ec079b48f95afab54cbfe51a0b', anchor: this.menuAnchor, offsetY: this.offsetY, onClose: this.closeMenu }, h("kritzel-menu", { key: 'b6861ae2d553ebf5f5af7448c2b053576a380e8c', items: this.visibleItems, onItemSelect: this.handleMenuItemSelect })))));
|
|
29600
30059
|
}
|
|
29601
30060
|
};
|
|
29602
30061
|
KritzelMoreMenu.style = kritzelMoreMenuCss();
|
|
@@ -29694,7 +30153,7 @@ const KritzelNumericInput = class {
|
|
|
29694
30153
|
this.valueChange.emit(newValue);
|
|
29695
30154
|
};
|
|
29696
30155
|
render() {
|
|
29697
|
-
return (h(Host, { key: '
|
|
30156
|
+
return (h(Host, { key: '3679786121f22a0aacb1b57701764b0bd0bf02f5' }, h("div", { key: 'e88251c356332f29d93f6a3d82f5154188243e4c', class: "input-container" }, this.label && h("label", { key: 'cb4d64a5acf94794a5876bc61dc13dd8159ad055', class: "input-label" }, this.label), h("div", { key: '9faad300f263e871322b68635feefb08172bd15c', class: "input-wrapper" }, 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 }), h("div", { key: 'a959beb441fe2143dc9c1c69347194e024362927', class: "spinner-buttons" }, h("button", { key: '6e2129f36080317e68b6fe1c05e69ea4e655fd20', type: "button", class: "spinner-button spinner-up", onClick: this.handleIncrement, tabIndex: -1, "aria-label": "Increase value" }, h("svg", { key: '47b5e178f82ef4eb6f2c5d888496ed95683c2f6d', viewBox: "0 0 10 6", class: "spinner-icon" }, h("path", { key: '6d5eb31ac5829b1e024822786beaafd347081c7e', d: "M1 5L5 1L9 5", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))), h("button", { key: '5a897f0b29ce89d5bd94327d2055753d06148c89', type: "button", class: "spinner-button spinner-down", onClick: this.handleDecrement, tabIndex: -1, "aria-label": "Decrease value" }, h("svg", { key: '19ff176c07e1c2a18f708debc7c7f3953f2219cb', viewBox: "0 0 10 6", class: "spinner-icon" }, h("path", { key: '0c1289eb009b62ea36f7397811f553a4e7e669f6', d: "M1 1L5 5L9 1", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))))))));
|
|
29698
30157
|
}
|
|
29699
30158
|
static get watchers() { return {
|
|
29700
30159
|
"value": [{
|
|
@@ -29733,7 +30192,7 @@ const KritzelOpacitySlider = class {
|
|
|
29733
30192
|
}
|
|
29734
30193
|
render() {
|
|
29735
30194
|
const percentage = this.getPercentage();
|
|
29736
|
-
return (h(Host, { key: '
|
|
30195
|
+
return (h(Host, { key: '9b580f61b9113950b7dff5339879374f7882e1bd' }, h("div", { key: '80fb336580c49d4d7026993499b9c008ac2a4594', class: "opacity-container" }, h("div", { key: 'fcdd8e523d5f2ff4758a4839f2f43cbdabba4c5a', class: "slider-wrapper" }, 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: {
|
|
29737
30196
|
'--slider-progress': `${percentage}%`,
|
|
29738
30197
|
'--kritzel-opacity-slider-thumb-border-color': this.previewColor,
|
|
29739
30198
|
} })))));
|
|
@@ -30086,7 +30545,7 @@ const KritzelPortal = class {
|
|
|
30086
30545
|
this.portal.style.visibility = 'visible';
|
|
30087
30546
|
}
|
|
30088
30547
|
render() {
|
|
30089
|
-
return (h(Host, { key: '
|
|
30548
|
+
return (h(Host, { key: 'f4ee3156b094ff1126db417f8396ca6cd0eb9aa4', style: { display: this.anchor ? 'block' : 'none' } }, h("slot", { key: '87812f4ddd50a29c8a76938e8778500a4873a30c' })));
|
|
30090
30549
|
}
|
|
30091
30550
|
static get watchers() { return {
|
|
30092
30551
|
"anchor": [{
|
|
@@ -30100,7 +30559,7 @@ const KritzelPortal = class {
|
|
|
30100
30559
|
* This file is auto-generated by the version bump scripts.
|
|
30101
30560
|
* Do not modify manually.
|
|
30102
30561
|
*/
|
|
30103
|
-
const KRITZEL_VERSION = '0.3.
|
|
30562
|
+
const KRITZEL_VERSION = '0.3.18';
|
|
30104
30563
|
|
|
30105
30564
|
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)}`;
|
|
30106
30565
|
|
|
@@ -30117,13 +30576,7 @@ const DEFAULT_DEBUG_INFO = {
|
|
|
30117
30576
|
showSyncProviderInfo: true,
|
|
30118
30577
|
showMigrationInfo: true,
|
|
30119
30578
|
};
|
|
30120
|
-
const
|
|
30121
|
-
{ id: 'general', label: 'General', icon: 'settings' },
|
|
30122
|
-
{ id: 'viewport', label: 'Viewport', icon: 'viewport' },
|
|
30123
|
-
{ id: 'shortcuts', label: 'Keyboard Shortcuts', icon: 'command' },
|
|
30124
|
-
{ id: 'developer', label: 'Developer Options', icon: 'braces' },
|
|
30125
|
-
{ id: 'about', label: 'About', icon: 'info' },
|
|
30126
|
-
];
|
|
30579
|
+
const SETTINGS_CATEGORY_IDS = ['general', 'viewport', 'shortcuts', 'developer', 'about'];
|
|
30127
30580
|
const KritzelSettings = class {
|
|
30128
30581
|
constructor(hostRef) {
|
|
30129
30582
|
registerInstance(this, hostRef);
|
|
@@ -30132,7 +30585,11 @@ const KritzelSettings = class {
|
|
|
30132
30585
|
get host() { return getElement(this); }
|
|
30133
30586
|
/** Keyboard shortcuts to display in the settings dialog */
|
|
30134
30587
|
availableThemes = ['light', 'dark'];
|
|
30588
|
+
/** Available locales as `{ code, label }` options for the language selector. */
|
|
30589
|
+
availableLocales = [];
|
|
30135
30590
|
shortcuts = [];
|
|
30591
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
30592
|
+
terms = {};
|
|
30136
30593
|
/** Current settings values. Used to initialize and sync the component's internal state. */
|
|
30137
30594
|
settings;
|
|
30138
30595
|
onSettingsPropChange(newSettings) {
|
|
@@ -30141,11 +30598,12 @@ const KritzelSettings = class {
|
|
|
30141
30598
|
}
|
|
30142
30599
|
}
|
|
30143
30600
|
isDialogOpen = false;
|
|
30144
|
-
selectedCategoryId =
|
|
30601
|
+
selectedCategoryId = SETTINGS_CATEGORY_IDS[0];
|
|
30145
30602
|
scaleMin = DEFAULT_SCALE_MIN;
|
|
30146
30603
|
scaleMax = DEFAULT_SCALE_MAX;
|
|
30147
30604
|
lockDrawingScale = DEFAULT_LOCK_DRAWING_SCALE;
|
|
30148
30605
|
theme = 'light';
|
|
30606
|
+
locale = 'en';
|
|
30149
30607
|
viewportBoundaryLeft = DEFAULT_VIEWPORT_BOUNDARY_LEFT;
|
|
30150
30608
|
viewportBoundaryRight = DEFAULT_VIEWPORT_BOUNDARY_RIGHT;
|
|
30151
30609
|
viewportBoundaryTop = DEFAULT_VIEWPORT_BOUNDARY_TOP;
|
|
@@ -30171,6 +30629,9 @@ const KritzelSettings = class {
|
|
|
30171
30629
|
if (typeof settings.theme === 'string') {
|
|
30172
30630
|
this.theme = settings.theme;
|
|
30173
30631
|
}
|
|
30632
|
+
if (typeof settings.locale === 'string') {
|
|
30633
|
+
this.locale = settings.locale;
|
|
30634
|
+
}
|
|
30174
30635
|
if (typeof settings.viewportBoundaryLeft === 'number') {
|
|
30175
30636
|
this.viewportBoundaryLeft = settings.viewportBoundaryLeft;
|
|
30176
30637
|
}
|
|
@@ -30193,6 +30654,7 @@ const KritzelSettings = class {
|
|
|
30193
30654
|
scaleMax: this.scaleMax,
|
|
30194
30655
|
lockDrawingScale: this.lockDrawingScale,
|
|
30195
30656
|
theme: this.theme,
|
|
30657
|
+
locale: this.locale,
|
|
30196
30658
|
viewportBoundaryLeft: this.viewportBoundaryLeft,
|
|
30197
30659
|
viewportBoundaryRight: this.viewportBoundaryRight,
|
|
30198
30660
|
viewportBoundaryTop: this.viewportBoundaryTop,
|
|
@@ -30217,6 +30679,10 @@ const KritzelSettings = class {
|
|
|
30217
30679
|
this.theme = event.detail;
|
|
30218
30680
|
this.emitSettings();
|
|
30219
30681
|
};
|
|
30682
|
+
handleLocaleChange = (event) => {
|
|
30683
|
+
this.locale = event.detail;
|
|
30684
|
+
this.emitSettings();
|
|
30685
|
+
};
|
|
30220
30686
|
handleViewportBoundaryLeftChange = (event) => {
|
|
30221
30687
|
this.viewportBoundaryLeft = event.detail ?? DEFAULT_VIEWPORT_BOUNDARY_LEFT;
|
|
30222
30688
|
this.emitSettings();
|
|
@@ -30272,24 +30738,52 @@ const KritzelSettings = class {
|
|
|
30272
30738
|
}
|
|
30273
30739
|
return grouped;
|
|
30274
30740
|
}
|
|
30741
|
+
/**
|
|
30742
|
+
* Resolves a localized string from the supplied {@link terms} map, falling
|
|
30743
|
+
* back to the provided English default when the key is missing.
|
|
30744
|
+
*/
|
|
30745
|
+
t(key, fallback) {
|
|
30746
|
+
return this.terms[key] ?? fallback;
|
|
30747
|
+
}
|
|
30748
|
+
get categories() {
|
|
30749
|
+
const icons = {
|
|
30750
|
+
general: 'settings',
|
|
30751
|
+
viewport: 'viewport',
|
|
30752
|
+
shortcuts: 'command',
|
|
30753
|
+
developer: 'braces',
|
|
30754
|
+
about: 'info',
|
|
30755
|
+
};
|
|
30756
|
+
const labels = {
|
|
30757
|
+
general: { key: 'settings.categories.general', fallback: 'General' },
|
|
30758
|
+
viewport: { key: 'settings.categories.viewport', fallback: 'Viewport' },
|
|
30759
|
+
shortcuts: { key: 'settings.categories.shortcuts', fallback: 'Keyboard Shortcuts' },
|
|
30760
|
+
developer: { key: 'settings.categories.developer', fallback: 'Developer Options' },
|
|
30761
|
+
about: { key: 'settings.categories.about', fallback: 'About' },
|
|
30762
|
+
};
|
|
30763
|
+
return SETTINGS_CATEGORY_IDS.map(id => ({
|
|
30764
|
+
id,
|
|
30765
|
+
label: this.t(labels[id].key, labels[id].fallback),
|
|
30766
|
+
icon: icons[id],
|
|
30767
|
+
}));
|
|
30768
|
+
}
|
|
30275
30769
|
renderCategoryContent() {
|
|
30276
30770
|
switch (this.selectedCategoryId) {
|
|
30277
30771
|
case 'general':
|
|
30278
|
-
return (h("div", { class: "settings-content" }, h("h3", null,
|
|
30772
|
+
return (h("div", { class: "settings-content" }, h("h3", null, this.t('settings.general.title', 'General Settings')), h("div", { class: "settings-group" }, h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.general.theme.label', 'Theme')), h("p", { class: "settings-description" }, this.t('settings.general.theme.description', 'Select a registered color theme for the editor interface.')), h("kritzel-dropdown", { options: this.availableThemes.map(t => ({ value: t, label: t })), value: this.theme, onValueChanged: this.handleThemeChange })), this.availableLocales.length > 0 && (h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.general.language.label', 'Language')), h("p", { class: "settings-description" }, this.t('settings.general.language.description', 'Select the display language for the editor interface.')), h("kritzel-dropdown", { options: this.availableLocales.map(l => ({ value: l.code, label: l.label })), value: this.locale, onValueChanged: this.handleLocaleChange }))), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.general.lockDrawingScale.label', 'Lock Drawing Scale')), 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.')), h("kritzel-slide-toggle", { checked: this.lockDrawingScale, label: this.t('settings.general.lockDrawingScale.label', 'Lock Drawing Scale'), onCheckedChange: this.handleLockDrawingScaleChange })))));
|
|
30279
30773
|
case 'viewport':
|
|
30280
|
-
return (h("div", { class: "settings-content" }, h("h3", null,
|
|
30774
|
+
return (h("div", { class: "settings-content" }, h("h3", null, this.t('settings.viewport.title', 'Viewport Settings')), h("div", { class: "settings-group" }, h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.minZoom.label', 'Minimum Zoom Level')), 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.')), h("kritzel-numeric-input", { value: this.scaleMin, min: 0.0001, max: 1, step: 0.0001, onValueChange: this.handleScaleMinChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.maxZoom.label', 'Maximum Zoom Level')), 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.')), h("kritzel-numeric-input", { value: this.scaleMax, min: 1, max: 1000, step: 1, onValueChange: this.handleScaleMaxChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryLeft.label', 'Viewport Boundary Left')), 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.')), h("kritzel-numeric-input", { value: this.viewportBoundaryLeft, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryLeftChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryRight.label', 'Viewport Boundary Right')), 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.')), h("kritzel-numeric-input", { value: this.viewportBoundaryRight, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryRightChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryTop.label', 'Viewport Boundary Top')), 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.')), h("kritzel-numeric-input", { value: this.viewportBoundaryTop, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryTopChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryBottom.label', 'Viewport Boundary Bottom')), 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.')), h("kritzel-numeric-input", { value: this.viewportBoundaryBottom, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryBottomChange })))));
|
|
30281
30775
|
case 'shortcuts':
|
|
30282
|
-
return (h("div", { class: "settings-content" }, h("h3", null,
|
|
30776
|
+
return (h("div", { class: "settings-content" }, h("h3", null, this.t('settings.shortcuts.title', 'Keyboard Shortcuts')), h("div", { class: "shortcuts-list" }, Array.from(this.groupShortcutsByCategory()).map(([category, shortcuts]) => (h("div", { class: "shortcuts-category", key: category }, h("h4", { class: "shortcuts-category-title" }, category), h("div", { class: "shortcuts-group" }, shortcuts.map(shortcut => (h("div", { class: "shortcut-item", key: shortcut.key + shortcut.label }, h("span", { class: "shortcut-label" }, shortcut.label), h("kbd", { class: "shortcut-key" }, this.formatKeyCombo(shortcut))))))))))));
|
|
30283
30777
|
case 'developer':
|
|
30284
|
-
return (h("div", { class: "settings-content" }, h("h3", null,
|
|
30778
|
+
return (h("div", { class: "settings-content" }, h("h3", null, this.t('settings.developer.title', 'Developer Options')), h("div", { class: "settings-group" }, h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showViewportInfo.label', 'Show Viewport Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showViewportInfo.description', 'Display viewport debug information such as position, zoom level, and boundaries.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showViewportInfo, label: this.t('settings.developer.showViewportInfo.label', 'Show Viewport Info'), onCheckedChange: this.handleDebugInfoChange('showViewportInfo') })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showObjectInfo.label', 'Show Object Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showObjectInfo.description', 'Display debug information about objects on the canvas.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showObjectInfo, label: this.t('settings.developer.showObjectInfo.label', 'Show Object Info'), onCheckedChange: this.handleDebugInfoChange('showObjectInfo') })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showSyncProviderInfo.label', 'Show Sync Provider Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showSyncProviderInfo.description', 'Display debug information about the sync provider connection status.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showSyncProviderInfo, label: this.t('settings.developer.showSyncProviderInfo.label', 'Show Sync Provider Info'), onCheckedChange: this.handleDebugInfoChange('showSyncProviderInfo') })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showMigrationInfo.label', 'Show Migration Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showMigrationInfo.description', 'Display debug information about data migrations.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showMigrationInfo, label: this.t('settings.developer.showMigrationInfo.label', 'Show Migration Info'), onCheckedChange: this.handleDebugInfoChange('showMigrationInfo') })))));
|
|
30285
30779
|
case 'about':
|
|
30286
|
-
return (h("div", { class: "settings-content" }, h("h3", null,
|
|
30780
|
+
return (h("div", { class: "settings-content" }, h("h3", null, this.t('settings.about.title', 'About')), h("p", null, this.t('settings.about.description', 'Kritzel - A drawing application')), h("p", { class: "version-info" }, "Version ", KRITZEL_VERSION), h("p", { class: "version-info" }, "App-State Schema v", CURRENT_APP_STATE_SCHEMA_VERSION), h("p", { class: "version-info" }, "Workspace Schema v", CURRENT_WORKSPACE_SCHEMA_VERSION)));
|
|
30287
30781
|
default:
|
|
30288
30782
|
return null;
|
|
30289
30783
|
}
|
|
30290
30784
|
}
|
|
30291
30785
|
render() {
|
|
30292
|
-
return (h(Host, { key: '
|
|
30786
|
+
return (h(Host, { key: '8dc22abaa2a19a14f3bbef10e34d133b16510498' }, h("kritzel-dialog", { key: '54072bf290e2d86bb7ec40d8d3e630be46fa3e1e', isOpen: this.isDialogOpen, dialogTitle: this.t('settings.dialogTitle', 'Settings'), size: "large", contained: true, onDialogClose: this.closeDialog }, h("kritzel-master-detail", { key: '5be80411c943ab4b7b90129527c8a0d147306a5f', items: this.categories, selectedItemId: this.selectedCategoryId, onItemSelect: this.handleCategorySelect }, this.renderCategoryContent()))));
|
|
30293
30787
|
}
|
|
30294
30788
|
static get watchers() { return {
|
|
30295
30789
|
"settings": [{
|
|
@@ -30350,6 +30844,8 @@ const KritzelShareDialog = class {
|
|
|
30350
30844
|
* The ID of the workspace being shared. Used to build the share URL.
|
|
30351
30845
|
*/
|
|
30352
30846
|
workspaceId = undefined;
|
|
30847
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
30848
|
+
terms = {};
|
|
30353
30849
|
onIsPublicChange(newValue) {
|
|
30354
30850
|
this.internalIsPublic = newValue;
|
|
30355
30851
|
}
|
|
@@ -30420,9 +30916,9 @@ const KritzelShareDialog = class {
|
|
|
30420
30916
|
this.dialogClosed.emit();
|
|
30421
30917
|
};
|
|
30422
30918
|
render() {
|
|
30423
|
-
return (h(Host, { key: '
|
|
30424
|
-
? 'Anyone with the link can access this workspace.'
|
|
30425
|
-
: 'Link sharing is disabled. Only you can access this workspace.')), h("kritzel-slide-toggle", { key: '
|
|
30919
|
+
return (h(Host, { key: 'b364f891659d54623b5472fe4cd5a9a85bc2fafa' }, h("kritzel-dialog", { key: '7059a3ede84bc67f7661efc8c84eae9b0c401d43', dialogTitle: this.terms['share.dialogTitle'] ?? 'Share Workspace', size: "small", isOpen: this.isDialogOpen, onDialogClose: this.closeDialog, contained: true }, h("div", { key: '1b0e7a9b5483a53f91e874075c0edb116b7474d6', class: "share-content" }, h("div", { key: '1568dc99224f0f7e2a370c22327dc313515e7d0f', class: "share-section" }, h("div", { key: 'a0032f6c870a448e817b013a715aadca1c455bb3', class: "share-row" }, h("div", { key: '3bd74cbebc122133354465163f9945dd207245b5', class: "share-label-group" }, h("label", { key: '0919fc24e5637c908c53b6914983833b6600e846', class: "share-label" }, this.terms['share.linkSharing.label'] ?? 'Link sharing'), h("p", { key: 'f87c9eae7112d284d7d917fae7c9c05fa6feb0ed', class: "share-description" }, this.internalIsPublic
|
|
30920
|
+
? (this.terms['share.linkSharing.enabledDescription'] ?? 'Anyone with the link can access this workspace.')
|
|
30921
|
+
: (this.terms['share.linkSharing.disabledDescription'] ?? 'Link sharing is disabled. Only you can access this workspace.'))), h("kritzel-slide-toggle", { key: '81ccfb76255d40da954cfdcbc486bdbb7dc4bff4', checked: this.internalIsPublic, onCheckedChange: this.handleToggleChange, label: this.terms['share.linkSharing.toggleLabel'] ?? 'Enable link sharing' }))), this.internalIsPublic && (h("div", { key: 'c72da3550416ebfef5c24690591b212df70cb4db', class: "share-section" }, h("div", { key: 'c3dd4bce7d57e60d09989bff6dd1d828a613b425', class: "share-url-container" }, h("input", { key: '67aab8a65f54ea67392a9874e949d6d1af519e0f', type: "text", class: "share-url-input", value: this.getShareUrl(), readOnly: true, onClick: (e) => e.target.select() }), 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') }, h("kritzel-icon", { key: '08ed01ed081e955e28eaed577438cd0008eaacf4', name: this.copySuccess ? 'check' : 'copy', size: 18 })))))))));
|
|
30426
30922
|
}
|
|
30427
30923
|
static get watchers() { return {
|
|
30428
30924
|
"isPublic": [{
|
|
@@ -30460,7 +30956,7 @@ const KritzelSlideToggle = class {
|
|
|
30460
30956
|
}
|
|
30461
30957
|
};
|
|
30462
30958
|
render() {
|
|
30463
|
-
return (h(Host, { key: '
|
|
30959
|
+
return (h(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 }, h("div", { key: '53fc90f3a11055e0b16358be0e3beed2ed25bc48', class: "toggle-track" }, h("div", { key: 'e0a0cecb9ede9c8e932cbb6fa7cdc359c07be8db', class: "toggle-thumb" }))));
|
|
30464
30960
|
}
|
|
30465
30961
|
};
|
|
30466
30962
|
KritzelSlideToggle.style = kritzelSlideToggleCss();
|
|
@@ -30560,7 +31056,7 @@ const KritzelSplitButton = class {
|
|
|
30560
31056
|
this.menuScrollTop = event.target.scrollTop;
|
|
30561
31057
|
};
|
|
30562
31058
|
render() {
|
|
30563
|
-
return (h(Host, { key: '
|
|
31059
|
+
return (h(Host, { key: '39516b2486a27534273b6bf4def6b11790aa0ed5', class: { mobile: this.isTouchDevice } }, h("button", { key: '19c4a58deb3992857b0e42e4a035a15d0980da22', class: "split-main-button", tabIndex: 0, onClick: this.handleButtonClick, disabled: this.mainButtonDisabled, "aria-label": "Main action" }, this.buttonIcon && h("kritzel-icon", { key: '4c8e7e09e60717b1653251468c2a25d41c4b1921', name: this.buttonIcon })), h("div", { key: '53617db6b630dfb5320e7309dcbc9f7288ff8974', class: "split-divider" }), 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" }, h("kritzel-icon", { key: '41f39a601ae91d4faaf54c1ca39c90e27e084d31', name: this.dropdownIcon })), h("kritzel-portal", { key: 'dcfe82f72a53e9346b48d2ff6da236c1f1344f3f', anchor: this.anchorElement, offsetY: 4, onClose: this.closeMenu }, 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 }))));
|
|
30564
31060
|
}
|
|
30565
31061
|
};
|
|
30566
31062
|
KritzelSplitButton.style = kritzelSplitButtonCss();
|
|
@@ -30580,7 +31076,8 @@ const KritzelStrokeSize = class {
|
|
|
30580
31076
|
this.sizeChange.emit(size);
|
|
30581
31077
|
}
|
|
30582
31078
|
render() {
|
|
30583
|
-
|
|
31079
|
+
const sizes = this.sizes ?? [];
|
|
31080
|
+
return (h(Host, { key: '20c11daaf60055262706b8177b1090bddd2d522c' }, h("div", { key: '1729e29d836f85fe3be984a5ee78a0debc0e6218', class: "size-grid" }, sizes.map(size => (h("div", { tabIndex: 0, class: {
|
|
30584
31081
|
'size-container': true,
|
|
30585
31082
|
'selected': this.selectedSize === size,
|
|
30586
31083
|
}, onClick: () => this.handleSizeClick(size) }, h("kritzel-color", { value: 'var(--kritzel-global-text-primary)', size: size })))))));
|
|
@@ -30629,6 +31126,8 @@ const KritzelToolConfig = class {
|
|
|
30629
31126
|
isExpanded = false;
|
|
30630
31127
|
theme;
|
|
30631
31128
|
engine;
|
|
31129
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
31130
|
+
terms = {};
|
|
30632
31131
|
handleSelectionChangeBound = this.handleSelectionChange.bind(this);
|
|
30633
31132
|
onThemeChange() {
|
|
30634
31133
|
this.emitDisplayValues();
|
|
@@ -30771,9 +31270,9 @@ const KritzelToolConfig = class {
|
|
|
30771
31270
|
const value = this.tool[control.propertyName];
|
|
30772
31271
|
switch (control.type) {
|
|
30773
31272
|
case 'stroke-size':
|
|
30774
|
-
return (h("kritzel-stroke-size", { key: control.type, sizes: this.sizes
|
|
31273
|
+
return (h("kritzel-stroke-size", { key: control.type, sizes: this.sizes, selectedSize: value, onSizeChange: this.handleSizeChange }));
|
|
30775
31274
|
case 'font-size':
|
|
30776
|
-
return (h("kritzel-font-size", { key: control.type, sizes: this.sizes
|
|
31275
|
+
return (h("kritzel-font-size", { key: control.type, sizes: this.sizes, selectedSize: value, fontFamily: this.tool.fontFamily, onSizeChange: this.handleSizeChange }));
|
|
30777
31276
|
case 'line-endings':
|
|
30778
31277
|
return (h("kritzel-line-endings", { key: control.type, value: value, onValueChange: (event) => this.handlePropertyChange(control.propertyName, event.detail) }));
|
|
30779
31278
|
case 'shape-fill':
|
|
@@ -30808,7 +31307,7 @@ const KritzelToolConfig = class {
|
|
|
30808
31307
|
])), shouldShowExpandButton && (h("div", { style: {
|
|
30809
31308
|
display: 'flex',
|
|
30810
31309
|
alignItems: 'flex-start',
|
|
30811
|
-
} }, h("button", { class: "expand-toggle", onClick: this.handleToggleExpand, title: this.isExpanded ? 'Collapse' : 'Expand' }, h("kritzel-icon", { name: this.isExpanded ? 'chevron-up' : 'chevron-down' })))))));
|
|
31310
|
+
} }, h("button", { class: "expand-toggle", onClick: this.handleToggleExpand, title: this.isExpanded ? (this.terms['toolConfig.collapse'] ?? 'Collapse') : (this.terms['toolConfig.expand'] ?? 'Expand') }, h("kritzel-icon", { name: this.isExpanded ? 'chevron-up' : 'chevron-down' })))))));
|
|
30812
31311
|
}
|
|
30813
31312
|
static get watchers() { return {
|
|
30814
31313
|
"tool": [{
|
|
@@ -30959,14 +31458,14 @@ const KritzelTooltip = class {
|
|
|
30959
31458
|
}
|
|
30960
31459
|
}
|
|
30961
31460
|
render() {
|
|
30962
|
-
return (h(Host, { key: '
|
|
31461
|
+
return (h(Host, { key: '57c0c2ddbe3f88815b975b7cf5b02c7da389b7f9', style: {
|
|
30963
31462
|
position: 'fixed',
|
|
30964
31463
|
zIndex: '9999',
|
|
30965
31464
|
transition: 'opacity 0.3s ease-in-out, transform 0.3s ease-in-out',
|
|
30966
31465
|
visibility: this.isVisible ? 'visible' : 'hidden',
|
|
30967
31466
|
left: `${this.positionX}px`,
|
|
30968
31467
|
bottom: `${this.positionY}px`,
|
|
30969
|
-
} }, h("div", { key: '
|
|
31468
|
+
} }, h("div", { key: '3ab17ef4ba55ed39458814685574b0c00504a07d', class: "tooltip-content", onClick: event => event.stopPropagation(), onPointerDown: event => event.stopPropagation(), onMouseDown: event => event.stopPropagation() }, h("slot", { key: 'b0aa1eb2c9363644939bcc59a80d0294787f0946' }))));
|
|
30970
31469
|
}
|
|
30971
31470
|
static get watchers() { return {
|
|
30972
31471
|
"triggerElement": [{
|
|
@@ -30989,6 +31488,8 @@ const KritzelUtilityPanel = class {
|
|
|
30989
31488
|
this.delete = createEvent(this, "delete");
|
|
30990
31489
|
}
|
|
30991
31490
|
undoState = null;
|
|
31491
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
31492
|
+
terms = {};
|
|
30992
31493
|
undo;
|
|
30993
31494
|
redo;
|
|
30994
31495
|
delete;
|
|
@@ -31005,11 +31506,32 @@ const KritzelUtilityPanel = class {
|
|
|
31005
31506
|
this.redo.emit();
|
|
31006
31507
|
}
|
|
31007
31508
|
render() {
|
|
31008
|
-
return (h(Host, { key: '
|
|
31509
|
+
return (h(Host, { key: '7738c225b6ec936e032770e0a7387b01718e94e0' }, 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' }, h("kritzel-icon", { key: '3c7d87edc047113cac359f4782c7feeb53e18193', name: "undo" })), 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' }, h("kritzel-icon", { key: 'b5ac0b631c51b8e6c2762b4887dcdef899327e52', name: "redo" })), h("div", { key: '4075c8eb7d8c57d5e93afb18282c7a50ec8e050e', class: "utility-separator" }), h("button", { key: '4e7c53a0933c527e84e0ad78519983446f10d23c', class: "utility-button", "data-testid": "utility-delete", onClick: () => this.delete.emit(), "aria-label": this.terms['utility.delete'] ?? 'Delete selected items' }, h("kritzel-icon", { key: 'f2d3d9817626c53e2e4c3d4c7c702705b25d7788', name: "delete" }))));
|
|
31009
31510
|
}
|
|
31010
31511
|
};
|
|
31011
31512
|
KritzelUtilityPanel.style = kritzelUtilityPanelCss();
|
|
31012
31513
|
|
|
31514
|
+
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}`;
|
|
31515
|
+
|
|
31516
|
+
const KritzelWatermark = class {
|
|
31517
|
+
constructor(hostRef) {
|
|
31518
|
+
registerInstance(this, hostRef);
|
|
31519
|
+
}
|
|
31520
|
+
/** The core instance used to resolve localized terms. */
|
|
31521
|
+
core;
|
|
31522
|
+
/**
|
|
31523
|
+
* Resolved "Powered by Kritzel" label. Passed in by the engine so the badge
|
|
31524
|
+
* re-renders when the active locale changes. Falls back to resolving the term
|
|
31525
|
+
* from the core when not provided.
|
|
31526
|
+
*/
|
|
31527
|
+
label;
|
|
31528
|
+
render() {
|
|
31529
|
+
const label = this.label ?? this.core.localizationManager.translate('watermark.poweredBy');
|
|
31530
|
+
return (h(Host, { key: '7ec2a304ac711a4d2a54edef317eef9f4aad1d47' }, 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)));
|
|
31531
|
+
}
|
|
31532
|
+
};
|
|
31533
|
+
KritzelWatermark.style = kritzelWatermarkCss();
|
|
31534
|
+
|
|
31013
31535
|
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}`;
|
|
31014
31536
|
|
|
31015
31537
|
const KritzelWorkspaceManager = class {
|
|
@@ -31025,6 +31547,8 @@ const KritzelWorkspaceManager = class {
|
|
|
31025
31547
|
visible = false;
|
|
31026
31548
|
activeWorkspace;
|
|
31027
31549
|
workspaces = [];
|
|
31550
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
31551
|
+
terms = {};
|
|
31028
31552
|
isWorkspaceManagerReady;
|
|
31029
31553
|
workspaceChange;
|
|
31030
31554
|
childMenuAnchor = null;
|
|
@@ -31128,7 +31652,7 @@ const KritzelWorkspaceManager = class {
|
|
|
31128
31652
|
id: ws.id,
|
|
31129
31653
|
label: ws.name,
|
|
31130
31654
|
icon: ws.isPublic ? 'users-round' : undefined,
|
|
31131
|
-
iconTooltip: ws.isPublic ? 'Shared workspace' : undefined,
|
|
31655
|
+
iconTooltip: ws.isPublic ? (this.terms['workspace.sharedTooltip'] ?? 'Shared workspace') : undefined,
|
|
31132
31656
|
value: ws,
|
|
31133
31657
|
isEditing: this.editingItemId === ws.id,
|
|
31134
31658
|
isSelected: this.activeWorkspace?.id === ws.id,
|
|
@@ -31138,13 +31662,13 @@ const KritzelWorkspaceManager = class {
|
|
|
31138
31662
|
children: [
|
|
31139
31663
|
{
|
|
31140
31664
|
id: `${ws.id}-rename`,
|
|
31141
|
-
label: 'Rename',
|
|
31665
|
+
label: this.terms['workspace.rename'] ?? 'Rename',
|
|
31142
31666
|
value: 'rename',
|
|
31143
31667
|
action: (_item, parent) => this.edit(parent),
|
|
31144
31668
|
},
|
|
31145
31669
|
{
|
|
31146
31670
|
id: `${ws.id}-delete`,
|
|
31147
|
-
label: 'Delete',
|
|
31671
|
+
label: this.terms['workspace.delete'] ?? 'Delete',
|
|
31148
31672
|
value: 'delete',
|
|
31149
31673
|
isDisabled: this.sortedWorkspaces.length <= 1,
|
|
31150
31674
|
action: (_item, parent) => this.delete(parent),
|
|
@@ -31157,4 +31681,43 @@ const KritzelWorkspaceManager = class {
|
|
|
31157
31681
|
};
|
|
31158
31682
|
KritzelWorkspaceManager.style = kritzelWorkspaceManagerCss();
|
|
31159
31683
|
|
|
31160
|
-
|
|
31684
|
+
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}`;
|
|
31685
|
+
|
|
31686
|
+
const KritzelZoomPanel = class {
|
|
31687
|
+
constructor(hostRef) {
|
|
31688
|
+
registerInstance(this, hostRef);
|
|
31689
|
+
this.zoomIn = createEvent(this, "zoomIn");
|
|
31690
|
+
this.zoomOut = createEvent(this, "zoomOut");
|
|
31691
|
+
}
|
|
31692
|
+
/** Whether the zoom panel is visible. */
|
|
31693
|
+
visible = true;
|
|
31694
|
+
/** Whether both zoom buttons are disabled. */
|
|
31695
|
+
disabled = false;
|
|
31696
|
+
/** Current zoom level in percent. */
|
|
31697
|
+
zoomPercent = 100;
|
|
31698
|
+
/** Resolved localized strings keyed by term key, supplied by the editor. */
|
|
31699
|
+
terms = {};
|
|
31700
|
+
/** Emitted when the zoom-in button is clicked. */
|
|
31701
|
+
zoomIn;
|
|
31702
|
+
/** Emitted when the zoom-out button is clicked. */
|
|
31703
|
+
zoomOut;
|
|
31704
|
+
handleZoomIn = () => {
|
|
31705
|
+
if (!this.disabled) {
|
|
31706
|
+
this.zoomIn.emit();
|
|
31707
|
+
}
|
|
31708
|
+
};
|
|
31709
|
+
handleZoomOut = () => {
|
|
31710
|
+
if (!this.disabled) {
|
|
31711
|
+
this.zoomOut.emit();
|
|
31712
|
+
}
|
|
31713
|
+
};
|
|
31714
|
+
get normalizedZoomPercent() {
|
|
31715
|
+
return Number.isFinite(this.zoomPercent) ? Math.max(1, Math.round(this.zoomPercent)) : 100;
|
|
31716
|
+
}
|
|
31717
|
+
render() {
|
|
31718
|
+
return (h(Host, { key: '6c88ed18f63e1a4cfffef6ba3aa1772404908d59' }, h("div", { key: '18fcdf05a6822d2b9cf319059118b4851429283d', class: { panel: true, visible: this.visible } }, h("button", { key: 'df2c90912e091e4f2ca025dd246916e9fea6f7fa', class: "zoom-button", type: "button", "aria-label": this.terms['zoom.zoomOut'] ?? 'Zoom out', disabled: this.disabled, onClick: this.handleZoomOut }, h("kritzel-icon", { key: '293847a34220520592e74f50c89d57140d7f1cbe', name: "minus" })), h("span", { key: '575119b81e6d5d41f5802a29be1b586727968919', class: "zoom-level", "aria-live": "polite" }, this.normalizedZoomPercent, "%"), h("button", { key: '8cdd7100aaeb313f2504351204ff512142414815', class: "zoom-button", type: "button", "aria-label": this.terms['zoom.zoomIn'] ?? 'Zoom in', disabled: this.disabled, onClick: this.handleZoomIn }, h("kritzel-icon", { key: 'b792164a29dd43ef601a4f469fed440ee1d72510', name: "plus" })))));
|
|
31719
|
+
}
|
|
31720
|
+
};
|
|
31721
|
+
KritzelZoomPanel.style = kritzelZoomPanelCss();
|
|
31722
|
+
|
|
31723
|
+
export { KritzelActiveUsers as kritzel_active_users, KritzelAvatar as kritzel_avatar, KritzelAwarenessCursors as kritzel_awareness_cursors, KritzelBackToContent as kritzel_back_to_content, KritzelButton as kritzel_button, KritzelColorComponent as kritzel_color, KritzelColorPalette as kritzel_color_palette, KritzelContextMenu as kritzel_context_menu, KritzelControls as kritzel_controls, KritzelCurrentUser as kritzel_current_user, KritzelCurrentUserDialog as kritzel_current_user_dialog, KritzelCursorTrail as kritzel_cursor_trail, KritzelDialog as kritzel_dialog, KritzelDropdown as kritzel_dropdown, KritzelEditor as kritzel_editor, KritzelEngine as kritzel_engine, KritzelExport as kritzel_export, KritzelFont as kritzel_font, KritzelFontFamily as kritzel_font_family, KritzelFontSize as kritzel_font_size, KritzelIcon as kritzel_icon, KritzelInput as kritzel_input, KritzelLineEndings as kritzel_line_endings, KritzelLoginDialog as kritzel_login_dialog, KritzelMasterDetail as kritzel_master_detail, KritzelMenu as kritzel_menu, KritzelMenuItem as kritzel_menu_item, KritzelMoreMenu as kritzel_more_menu, KritzelNumericInput as kritzel_numeric_input, KritzelOpacitySlider as kritzel_opacity_slider, KritzelPillTabs as kritzel_pill_tabs, KritzelPortal as kritzel_portal, KritzelSettings as kritzel_settings, KritzelShapeFill as kritzel_shape_fill, KritzelShareDialog as kritzel_share_dialog, KritzelSlideToggle as kritzel_slide_toggle, KritzelSplitButton as kritzel_split_button, KritzelStrokeSize as kritzel_stroke_size, KritzelToolConfig as kritzel_tool_config, KritzelTooltip as kritzel_tooltip, KritzelUtilityPanel as kritzel_utility_panel, KritzelWatermark as kritzel_watermark, KritzelWorkspaceManager as kritzel_workspace_manager, KritzelZoomPanel as kritzel_zoom_panel };
|