kritzel-stencil 0.4.0 → 0.4.2
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/dist/cjs/index.cjs.js +2 -1
- package/dist/cjs/kritzel-active-users_47.cjs.entry.js +365 -80
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{schema.constants-fuAsi56H.js → schema.constants-C8hqt--r.js} +274 -33
- package/dist/cjs/stencil.cjs.js +1 -1
- package/dist/collection/classes/core/workspace.class.js +1 -1
- package/dist/collection/classes/handlers/context-menu.handler.js +2 -3
- package/dist/collection/classes/managers/clipboard.manager.js +9 -3
- package/dist/collection/classes/objects/base-object.class.js +0 -1
- package/dist/collection/classes/objects/text.class.js +2 -1
- package/dist/collection/classes/registries/font-registry.class.js +161 -0
- package/dist/collection/classes/structures/object-map.structure.js +9 -0
- package/dist/collection/classes/tools/image-tool.class.js +19 -3
- package/dist/collection/classes/tools/text-tool.class.js +2 -0
- package/dist/collection/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.js +22 -7
- package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +138 -9
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +186 -25
- package/dist/collection/components/shared/kritzel-font-family/kritzel-font-family.js +31 -22
- package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +10 -11
- package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.js +40 -5
- package/dist/collection/configs/default-text-tool.config.js +2 -0
- package/dist/collection/constants/text-tool-fonts.constants.js +18 -0
- package/dist/collection/constants/version.js +1 -1
- package/dist/collection/helpers/image-file.helper.js +6 -0
- package/dist/collection/index.js +2 -0
- package/dist/collection/interfaces/font.interface.js +1 -0
- package/dist/components/index.js +1 -1
- package/dist/components/kritzel-awareness-cursors.js +1 -1
- package/dist/components/kritzel-controls.js +1 -1
- package/dist/components/kritzel-cursor-trail.js +1 -1
- package/dist/components/kritzel-editor.js +1 -1
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-font-family.js +1 -1
- package/dist/components/kritzel-settings.js +1 -1
- package/dist/components/kritzel-tool-config.js +1 -1
- package/dist/components/kritzel-workspace-manager.js +1 -1
- package/dist/components/p--Oazz-BP.js +9 -0
- package/dist/components/p-C38P-Vd0.js +1 -0
- package/dist/components/{p-zhjb97WN.js → p-C3UQ-Zrg.js} +1 -1
- package/dist/components/{p-9692OaI_.js → p-ClFprFvz.js} +1 -1
- package/dist/components/p-Cm33td2O.js +1 -0
- package/dist/components/{p-DhMlShij.js → p-DAwPPDMS.js} +1 -1
- package/dist/components/p-DJkKlUyZ.js +1 -0
- package/dist/components/p-JYj3Facr.js +1 -0
- package/dist/components/p-Ka7OWbnk.js +1 -0
- package/dist/components/p-djJSnjAX.js +1 -0
- package/dist/esm/index.js +2 -2
- package/dist/esm/kritzel-active-users_47.entry.js +365 -80
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{schema.constants-Cv5-yM39.js → schema.constants-uC7_X6yr.js} +272 -34
- package/dist/esm/stencil.js +1 -1
- package/dist/stencil/index.esm.js +1 -1
- package/dist/stencil/p-b64c3584.entry.js +9 -0
- package/dist/stencil/p-uC7_X6yr.js +1 -0
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/core/workspace.class.d.ts +1 -1
- package/dist/types/classes/managers/clipboard.manager.d.ts +1 -0
- package/dist/types/classes/objects/base-object.class.d.ts +0 -1
- package/dist/types/classes/registries/font-registry.class.d.ts +19 -0
- package/dist/types/classes/structures/object-map.structure.d.ts +2 -2
- package/dist/types/classes/tools/image-tool.class.d.ts +9 -2
- package/dist/types/classes/tools/text-tool.class.d.ts +3 -0
- package/dist/types/components/core/kritzel-awareness-cursors/kritzel-awareness-cursors.d.ts +2 -0
- package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +22 -0
- package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +17 -0
- package/dist/types/components/shared/kritzel-font-family/kritzel-font-family.d.ts +4 -0
- package/dist/types/components/ui/kritzel-tool-config/kritzel-tool-config.d.ts +1 -0
- package/dist/types/components.d.ts +20 -2
- package/dist/types/constants/text-tool-fonts.constants.d.ts +3 -0
- package/dist/types/constants/version.d.ts +1 -1
- package/dist/types/helpers/image-file.helper.d.ts +3 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/interfaces/font.interface.d.ts +15 -0
- package/dist/types/interfaces/toolbar-control.interface.d.ts +2 -0
- package/package.json +1 -1
- package/dist/components/p-B4b6TDxp.js +0 -1
- package/dist/components/p-C2ocjA6D.js +0 -1
- package/dist/components/p-CwbZCXKh.js +0 -1
- package/dist/components/p-D2q_wTyG.js +0 -1
- package/dist/components/p-D8NvNMcU.js +0 -1
- package/dist/components/p-D8W6LE-c.js +0 -1
- package/dist/components/p-G9G9y5VE.js +0 -9
- package/dist/components/p-JhOYwUOj.js +0 -1
- package/dist/components/p-UEf2EN23.js +0 -1
- package/dist/stencil/p-2c489187.entry.js +0 -9
- package/dist/stencil/p-Cv5-yM39.js +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var index = require('./index-Xav9JFHg.js');
|
|
4
|
-
var schema_constants = require('./schema.constants-
|
|
4
|
+
var schema_constants = require('./schema.constants-C8hqt--r.js');
|
|
5
5
|
var Y = require('yjs');
|
|
6
6
|
require('y-indexeddb');
|
|
7
7
|
require('y-websocket');
|
|
@@ -196,23 +196,38 @@ const KritzelAwarenessCursors = class {
|
|
|
196
196
|
objectVersion = 0;
|
|
197
197
|
cleanupIntervalId;
|
|
198
198
|
objectChangeRafId = null;
|
|
199
|
+
removeAwarenessChangeListener;
|
|
200
|
+
removeObjectsChangeListener;
|
|
199
201
|
componentDidLoad() {
|
|
200
|
-
this.core.store.objects?.onAwarenessChange(states => {
|
|
202
|
+
this.removeAwarenessChangeListener = this.core.store.objects?.onAwarenessChange(states => {
|
|
201
203
|
this.handleAwarenessChange(states);
|
|
202
204
|
});
|
|
203
|
-
this.core.store.objects?.onObjectsChange(() => {
|
|
205
|
+
this.removeObjectsChangeListener = this.core.store.objects?.onObjectsChange(() => {
|
|
204
206
|
this.handleRemoteObjectChange();
|
|
205
207
|
});
|
|
206
208
|
this.cleanupIntervalId = setInterval(() => {
|
|
207
209
|
this.cleanupStaleCursors();
|
|
208
210
|
}, CLEANUP_INTERVAL_MS);
|
|
211
|
+
if (this.cleanupIntervalId && typeof this.cleanupIntervalId.unref === 'function') {
|
|
212
|
+
this.cleanupIntervalId.unref();
|
|
213
|
+
}
|
|
209
214
|
}
|
|
210
215
|
disconnectedCallback() {
|
|
211
|
-
if (this.
|
|
212
|
-
|
|
216
|
+
if (this.removeAwarenessChangeListener) {
|
|
217
|
+
this.removeAwarenessChangeListener();
|
|
218
|
+
this.removeAwarenessChangeListener = undefined;
|
|
219
|
+
}
|
|
220
|
+
if (this.removeObjectsChangeListener) {
|
|
221
|
+
this.removeObjectsChangeListener();
|
|
222
|
+
this.removeObjectsChangeListener = undefined;
|
|
213
223
|
}
|
|
214
|
-
if (this.
|
|
215
|
-
|
|
224
|
+
if (this.cleanupIntervalId && typeof globalThis.clearInterval === 'function') {
|
|
225
|
+
globalThis.clearInterval(this.cleanupIntervalId);
|
|
226
|
+
this.cleanupIntervalId = undefined;
|
|
227
|
+
}
|
|
228
|
+
if (this.objectChangeRafId !== null && typeof globalThis.cancelAnimationFrame === 'function') {
|
|
229
|
+
globalThis.cancelAnimationFrame(this.objectChangeRafId);
|
|
230
|
+
this.objectChangeRafId = null;
|
|
216
231
|
}
|
|
217
232
|
}
|
|
218
233
|
handleAwarenessChange(states) {
|
|
@@ -370,7 +385,7 @@ const KritzelAwarenessCursors = class {
|
|
|
370
385
|
}
|
|
371
386
|
render() {
|
|
372
387
|
const cursors = Array.from(this.remoteCursors.values());
|
|
373
|
-
return (index.h(index.Host, { key: '
|
|
388
|
+
return (index.h(index.Host, { key: '9be6694250bafe011be27301d1c7a53fc7957657' }, cursors.map(remoteCursor => {
|
|
374
389
|
if (!remoteCursor.cursor)
|
|
375
390
|
return null;
|
|
376
391
|
// When a remote user is actively drawing, derive cursor position from
|
|
@@ -993,8 +1008,9 @@ const KritzelControls = class {
|
|
|
993
1008
|
this.closeTooltip();
|
|
994
1009
|
}
|
|
995
1010
|
handleSelectionChange() {
|
|
996
|
-
|
|
997
|
-
|
|
1011
|
+
const tool = this.activeControl?.tool;
|
|
1012
|
+
if (tool && typeof tool !== 'function' && tool.toolType === 'selection') {
|
|
1013
|
+
this.updateDisplayValues(tool);
|
|
998
1014
|
}
|
|
999
1015
|
}
|
|
1000
1016
|
async onControlsChange() {
|
|
@@ -1045,7 +1061,7 @@ const KritzelControls = class {
|
|
|
1045
1061
|
color: schema_constants.KritzelColorHelper.applyOpacity(color, opacity, this.theme),
|
|
1046
1062
|
size,
|
|
1047
1063
|
};
|
|
1048
|
-
if (tool
|
|
1064
|
+
if (tool.toolType === 'text') {
|
|
1049
1065
|
displayValues.fontFamily = tool.fontFamily;
|
|
1050
1066
|
}
|
|
1051
1067
|
// Check for equality implementation to prevent unnecessary re-renders
|
|
@@ -1186,13 +1202,13 @@ const KritzelControls = class {
|
|
|
1186
1202
|
// Separate tool controls from config control
|
|
1187
1203
|
const toolControls = this.internalControls.filter(c => c.type === 'tool' || c.type === 'separator');
|
|
1188
1204
|
const configControl = this.internalControls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
|
|
1189
|
-
return (index.h(index.Host, { key: '
|
|
1205
|
+
return (index.h(index.Host, { key: 'a526bd337a6b75933ec4be89c3edded0a9c39e7c', style: { display: this.visible ? '' : 'none' }, class: {
|
|
1190
1206
|
mobile: this.isTouchDevice,
|
|
1191
|
-
} }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '
|
|
1207
|
+
} }, this.isUtilityPanelVisible && (index.h("kritzel-utility-panel", { key: '5314f067c5a22425690e3b6f26c836962ac528a2', style: {
|
|
1192
1208
|
position: 'absolute',
|
|
1193
1209
|
bottom: '56px',
|
|
1194
1210
|
left: '12px',
|
|
1195
|
-
}, undoState: this.undoState, terms: this.terms, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '
|
|
1211
|
+
}, undoState: this.undoState, terms: this.terms, onUndo: () => this.kritzelEngine?.undo(), onRedo: () => this.kritzelEngine?.redo(), onDelete: () => this.kritzelEngine?.delete() })), index.h("div", { key: '7cf0cd164d723b5901f54a6671395f63dd8bad29', class: "kritzel-controls" }, index.h("div", { key: 'b7169122686a0a67c37d96751291fc43f4c45e4a', class: { 'scroll-indicator-left': true, 'visible': this.canScrollLeft } }), index.h("div", { key: '6e3c4f30900e4722abdfaf3cfdc68cf1a07b9292', class: "kritzel-tools-scroll", ref: el => (this.toolsScrollRef = el), onScroll: this.handleToolsScroll }, toolControls.map(control => {
|
|
1196
1212
|
// Check if this control has sub-options (split-button)
|
|
1197
1213
|
if (control.subOptions?.length) {
|
|
1198
1214
|
const selectedSubOption = this.getSelectedSubOption(control);
|
|
@@ -1222,10 +1238,10 @@ const KritzelControls = class {
|
|
|
1222
1238
|
'kritzel-control': true,
|
|
1223
1239
|
'selected': this.activeControl?.name === control?.name,
|
|
1224
1240
|
}, key: control.name, "data-testid": `tool-${control.name}`, onClick: _event => this.handleControlClick?.(control), "aria-label": control.name.charAt(0).toUpperCase() + control.name.slice(1) }, index.h("kritzel-icon", { name: control.icon })));
|
|
1225
|
-
})), index.h("div", { key: '
|
|
1241
|
+
})), index.h("div", { key: 'bc8d79e0512f30fe150c6d2ac7f81206fc47c1a5', class: { 'scroll-indicator-right': true, 'visible': this.canScrollRight && !(configControl && this.activeControl && hasConfigUI) } }), configControl && this.activeControl && (index.h("div", { class: {
|
|
1226
1242
|
'kritzel-config-container': true,
|
|
1227
1243
|
'visible': hasConfigUI,
|
|
1228
|
-
}, key: configControl.name }, index.h("div", { key: '
|
|
1244
|
+
}, key: configControl.name }, index.h("div", { key: '671431a9c388080fb917d4e8c596d17e92eaba08', class: { 'config-gradient-left': true, 'visible': this.needsScrolling } }), index.h("kritzel-tooltip", { key: '394e8e2c07b191b3fb93645d68d7eae67761167a', anchorElement: this.host.shadowRoot?.querySelector('.kritzel-config-container'), triggerElement: this.configTriggerRef }, index.h("kritzel-tool-config", { key: 'b8479fba2afdb51fe0ef965e18b1ae45ba8a7da6', tool: this.activeControl.tool, theme: this.theme, engine: this.kritzelEngine, terms: this.terms, onToolChange: event => this.handleToolChange?.(event), onDisplayValuesChange: this.handleDisplayValuesChange, style: { width: '100%', height: '100%' } })), index.h("div", { key: '8fac81d682dbdec6b5247154fd20d553dfe6f1a7', tabIndex: hasConfigUI ? 0 : -1, class: "kritzel-config", "data-testid": "tool-config", ref: el => {
|
|
1229
1245
|
if (el)
|
|
1230
1246
|
this.configTriggerRef = el;
|
|
1231
1247
|
}, onKeyDown: event => {
|
|
@@ -1234,7 +1250,7 @@ const KritzelControls = class {
|
|
|
1234
1250
|
}
|
|
1235
1251
|
}, style: {
|
|
1236
1252
|
cursor: 'pointer',
|
|
1237
|
-
} }, this.displayValues && (index.h("div", { key: '
|
|
1253
|
+
} }, this.displayValues && (index.h("div", { key: '6aa1daed9425d069c7d0405a04e65b4c4e88291f', class: "color-container" }, index.h("kritzel-color", { key: '7b54461769bf4aec3e39d1fbe21c015b7d7a85bb', value: this.displayValues.color, theme: this.theme, size: 18, style: {
|
|
1238
1254
|
borderRadius: '50%',
|
|
1239
1255
|
border: 'none',
|
|
1240
1256
|
} })))))))));
|
|
@@ -2312,6 +2328,11 @@ const KritzelEditor = class {
|
|
|
2312
2328
|
/** The locale used to resolve terms missing from the active locale. */
|
|
2313
2329
|
fallbackLocale = 'en';
|
|
2314
2330
|
customSvgIcons = {};
|
|
2331
|
+
/**
|
|
2332
|
+
* Registers fonts for runtime usage (for example custom object rendering).
|
|
2333
|
+
* Text-tool config tooltip options are controlled via controls[].config.availableFonts.
|
|
2334
|
+
*/
|
|
2335
|
+
customFonts = {};
|
|
2315
2336
|
isPanningEnabled = true;
|
|
2316
2337
|
isZoomingEnabled = true;
|
|
2317
2338
|
isControlsVisible = true;
|
|
@@ -2364,11 +2385,14 @@ const KritzelEditor = class {
|
|
|
2364
2385
|
isEditorVisible = false;
|
|
2365
2386
|
activeNotification;
|
|
2366
2387
|
isNotificationDismissing = false;
|
|
2388
|
+
normalizedControls = [];
|
|
2367
2389
|
notificationDismissTimeout;
|
|
2368
2390
|
notificationDismissAnimationTimeout;
|
|
2369
2391
|
notificationDisplayDurationMs = 5000;
|
|
2370
2392
|
notificationDismissAnimationDurationMs = 180;
|
|
2371
2393
|
isNotificationHovered = false;
|
|
2394
|
+
customFontsLoadVersion = 0;
|
|
2395
|
+
customFontsReady = Promise.resolve();
|
|
2372
2396
|
onIsEngineReady(newValue) {
|
|
2373
2397
|
if (newValue && this.isControlsReady) {
|
|
2374
2398
|
this.checkIsReady();
|
|
@@ -2398,6 +2422,12 @@ const KritzelEditor = class {
|
|
|
2398
2422
|
onActiveWorkspaceChange() {
|
|
2399
2423
|
this.updateCurrentIsPublic();
|
|
2400
2424
|
}
|
|
2425
|
+
onCustomFontsChange(newValue) {
|
|
2426
|
+
void this.registerCustomFonts(newValue);
|
|
2427
|
+
}
|
|
2428
|
+
onControlsChange(newValue) {
|
|
2429
|
+
this.normalizedControls = this.normalizeControls(newValue);
|
|
2430
|
+
}
|
|
2401
2431
|
onActiveWorkspaceIdChange(newId) {
|
|
2402
2432
|
// If no ID is provided, do nothing (allows other logic to control activeWorkspace)
|
|
2403
2433
|
if (!newId) {
|
|
@@ -2671,9 +2701,27 @@ const KritzelEditor = class {
|
|
|
2671
2701
|
loginDialogRef;
|
|
2672
2702
|
currentUserDialogRef;
|
|
2673
2703
|
componentWillLoad() {
|
|
2704
|
+
this.normalizedControls = this.normalizeControls(this.controls);
|
|
2674
2705
|
this.loadSettingsFromStorage();
|
|
2675
2706
|
this.applyTheme();
|
|
2676
2707
|
}
|
|
2708
|
+
isTextToolConfig(config) {
|
|
2709
|
+
return !!config && 'fontFamily' in config && 'size' in config && 'color' in config;
|
|
2710
|
+
}
|
|
2711
|
+
normalizeControls(controls) {
|
|
2712
|
+
return controls.map(control => {
|
|
2713
|
+
if (!this.isTextToolConfig(control.config)) {
|
|
2714
|
+
return control;
|
|
2715
|
+
}
|
|
2716
|
+
return {
|
|
2717
|
+
...control,
|
|
2718
|
+
config: {
|
|
2719
|
+
...control.config,
|
|
2720
|
+
availableFonts: schema_constants.resolveTextToolAvailableFonts(control.config.availableFonts),
|
|
2721
|
+
},
|
|
2722
|
+
};
|
|
2723
|
+
});
|
|
2724
|
+
}
|
|
2677
2725
|
applyTheme() {
|
|
2678
2726
|
const themeObj = this.resolveThemeObject();
|
|
2679
2727
|
schema_constants.ThemeHelper.applyThemeToElement(this.host, themeObj);
|
|
@@ -2684,6 +2732,7 @@ const KritzelEditor = class {
|
|
|
2684
2732
|
}
|
|
2685
2733
|
componentDidLoad() {
|
|
2686
2734
|
this.registerCustomSvgIcons();
|
|
2735
|
+
this.registerCustomFonts();
|
|
2687
2736
|
this.listenForMobileKeyboard();
|
|
2688
2737
|
this.setOsSpecificCssVariables();
|
|
2689
2738
|
}
|
|
@@ -2696,6 +2745,7 @@ const KritzelEditor = class {
|
|
|
2696
2745
|
await customElements.whenDefined('kritzel-workspace-manager');
|
|
2697
2746
|
await customElements.whenDefined('kritzel-controls');
|
|
2698
2747
|
await customElements.whenDefined('kritzel-engine');
|
|
2748
|
+
await this.waitForCustomFontsReady();
|
|
2699
2749
|
if (!this.isEngineReady || !this.isControlsReady || !this.isWorkspaceManagerReady || !this.activeWorkspace) {
|
|
2700
2750
|
return;
|
|
2701
2751
|
}
|
|
@@ -2959,6 +3009,15 @@ const KritzelEditor = class {
|
|
|
2959
3009
|
async registerLocales(locales) {
|
|
2960
3010
|
await this.engineRef?.registerLocales(locales);
|
|
2961
3011
|
}
|
|
3012
|
+
/**
|
|
3013
|
+
* Registers custom fonts for the editor runtime.
|
|
3014
|
+
* @param fonts - Mapping from font keys to family names or font definitions.
|
|
3015
|
+
* @remarks This no longer controls the text-tool config tooltip font options.
|
|
3016
|
+
* Configure tooltip fonts via controls[].config.availableFonts.
|
|
3017
|
+
*/
|
|
3018
|
+
async registerFonts(fonts) {
|
|
3019
|
+
await this.registerCustomFonts(fonts);
|
|
3020
|
+
}
|
|
2962
3021
|
/**
|
|
2963
3022
|
* Resolves a term key to its translated string for the active locale.
|
|
2964
3023
|
* @param key - The term key to resolve.
|
|
@@ -3036,6 +3095,25 @@ const KritzelEditor = class {
|
|
|
3036
3095
|
schema_constants.KritzelIconRegistry.register(name, svg);
|
|
3037
3096
|
}
|
|
3038
3097
|
}
|
|
3098
|
+
async registerCustomFonts(fonts = this.customFonts) {
|
|
3099
|
+
schema_constants.KritzelFontRegistry.registerFonts(fonts);
|
|
3100
|
+
const currentVersion = ++this.customFontsLoadVersion;
|
|
3101
|
+
const loadPromise = schema_constants.KritzelFontRegistry.waitForFonts(fonts);
|
|
3102
|
+
this.customFontsReady = loadPromise;
|
|
3103
|
+
await loadPromise;
|
|
3104
|
+
if (currentVersion !== this.customFontsLoadVersion) {
|
|
3105
|
+
await this.waitForCustomFontsReady();
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
async waitForCustomFontsReady() {
|
|
3109
|
+
while (true) {
|
|
3110
|
+
const version = this.customFontsLoadVersion;
|
|
3111
|
+
await this.customFontsReady;
|
|
3112
|
+
if (version === this.customFontsLoadVersion) {
|
|
3113
|
+
return;
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3039
3117
|
listenForMobileKeyboard() {
|
|
3040
3118
|
schema_constants.KritzelKeyboardHelper.onKeyboardVisibleChanged(isOpen => {
|
|
3041
3119
|
this.isVirtualKeyboardOpen = isOpen;
|
|
@@ -3074,36 +3152,36 @@ const KritzelEditor = class {
|
|
|
3074
3152
|
const isLoggedIn = this.isLoggedIn;
|
|
3075
3153
|
const shouldShowCurrentUser = isLoggedIn;
|
|
3076
3154
|
const shouldShowLoginButton = this.isReady && !!this.loginConfig && !isLoggedIn;
|
|
3077
|
-
return (index.h(index.Host, { key: '
|
|
3155
|
+
return (index.h(index.Host, { key: '00d652c74feac7b4917772146368125da6deeb1c' }, index.h("div", { key: 'f8fb86b45b0cdabb5e3ad52de6d6ef31a71a09e4', class: "editor-content", style: {
|
|
3078
3156
|
opacity: this.isEditorVisible ? '1' : '0',
|
|
3079
3157
|
visibility: this.isEditorVisible ? 'visible' : 'hidden',
|
|
3080
3158
|
transition: 'opacity 0.2s ease-in-out, visibility 0.2s ease-in-out',
|
|
3081
|
-
} }, index.h("div", { key: '
|
|
3159
|
+
} }, index.h("div", { key: '2378c776d8eecf2614567bed11c6e93fb338e302', class: "top-left-buttons" }, index.h("kritzel-workspace-manager", { key: 'ce41192540169694482d6f8cca60701bc4427438', visible: this.isWorkspaceManagerVisible, workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, terms: this.resolvedTerms, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-back-to-content", { key: 'ec269d3e9f589362d8301370778f0c5e4252eead', visible: this.isBackToContentButtonVisible, text: this.resolvedTerms['backToContent.label'] ?? 'Back to content', onBackToContent: () => this.backToContent() })), this.activeNotification && (index.h("div", { key: '847ed8149d556c934090424ff54b17b6721ccc76', class: "top-center-notification-layer", role: "presentation" }, index.h("div", { key: '61d8b8e91cda100ffa6620db26ba6dfb2232946a', class: { 'top-center-notification-container': true, 'is-dismissing': this.isNotificationDismissing }, role: "presentation" }, index.h("kritzel-notification-card", { key: 'b7e132773225ace38e447756110dd39e4661f5fc', notification: this.activeNotification, locale: this.locale, onDismiss: this.dismissNotification, onHoverChange: event => this.handleNotificationHoverChange(event) })))), index.h("kritzel-engine", { key: '3e4a6d0dbc015ec675fb21a59990c87e9eaa805f', ref: el => {
|
|
3082
3160
|
if (el) {
|
|
3083
3161
|
this.engineRef = el;
|
|
3084
3162
|
}
|
|
3085
|
-
}, 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), onNotificationsChange: event => this.handleNotificationsChange(event) }), index.h("kritzel-controls", { key: '
|
|
3163
|
+
}, 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), onNotificationsChange: event => this.handleNotificationsChange(event) }), index.h("kritzel-controls", { key: 'f84607a0a4d0762c1249400f85b7b8454d672c1e', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
|
|
3086
3164
|
if (el) {
|
|
3087
3165
|
this.controlsRef = el;
|
|
3088
3166
|
}
|
|
3089
|
-
}, controls: this.
|
|
3167
|
+
}, controls: this.normalizedControls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: 'e2691e7c730195e197511cb1e4d0fe707677b5ff', class: "bottom-left-buttons" }, index.h("kritzel-zoom-panel", { key: 'd0ac6624eab49af78d4761c3ad91842834717aad', visible: this.isZoomPanelVisible, disabled: !this.isZoomingEnabled, zoomPercent: this.currentZoomPercent, terms: this.resolvedTerms, onZoomIn: () => this.zoomIn(), onZoomOut: () => this.zoomOut() })), index.h("div", { key: 'ad3d386ab7e8ad9fdfbb12754db005bc85fa28ce', class: "top-right-buttons" }, index.h("kritzel-settings", { key: '566024ac6f3d8f7f20238cc1f83882b39dbf698e', ref: el => {
|
|
3090
3168
|
if (el) {
|
|
3091
3169
|
this.settingsRef = el;
|
|
3092
3170
|
}
|
|
3093
|
-
}, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], availableLocales: this.availableLocaleOptions, settings: this.currentSettingsConfig, terms: this.resolvedTerms, onSettingsChange: event => this.handleSettingsChange(event) }), index.h("kritzel-export", { key: '
|
|
3171
|
+
}, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], availableLocales: this.availableLocaleOptions, settings: this.currentSettingsConfig, terms: this.resolvedTerms, onSettingsChange: event => this.handleSettingsChange(event) }), index.h("kritzel-export", { key: '4a23ea0c6e070d424a90e9fc87de04e11cff7ade', ref: el => {
|
|
3094
3172
|
if (el) {
|
|
3095
3173
|
this.exportRef = el;
|
|
3096
3174
|
}
|
|
3097
|
-
}, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), index.h("kritzel-active-users", { key: '
|
|
3175
|
+
}, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), index.h("kritzel-active-users", { key: 'feef074b52e552fa2ef7e8258002571aca4c5abd', users: this.activeUsers }), shouldShowCurrentUser && index.h("kritzel-current-user", { key: '844c722545363eaf7eec69037a835eae943afeb9', user: this.user, terms: this.resolvedTerms, onClick: () => this.currentUserDialogRef?.open() }), shouldShowCurrentUser && (index.h("kritzel-current-user-dialog", { key: '8363c1d3230d111cf1ace0ccf805669e592bb533', ref: el => {
|
|
3098
3176
|
if (el) {
|
|
3099
3177
|
this.currentUserDialogRef = el;
|
|
3100
3178
|
this.currentUserDialogRef.addEventListener('logoutRequest', this.handleCurrentUserLogout);
|
|
3101
3179
|
}
|
|
3102
|
-
}, user: this.user, terms: this.resolvedTerms })), shouldShowLoginButton && (index.h("kritzel-button", { key: '
|
|
3180
|
+
}, user: this.user, terms: this.resolvedTerms })), shouldShowLoginButton && (index.h("kritzel-button", { key: '68ddf8c3aabc7634b4c1d88f3d2d584fa1f1b150', onButtonClick: () => this.loginDialogRef?.open() }, this.resolvedTerms['login.dialogTitle'] ?? 'Sign in')), index.h("kritzel-more-menu", { key: '39b938f5792f7a36bbf21ed88a1a5c7717a785a6', items: this.moreMenuItems, visible: this.isMoreMenuVisible, terms: this.resolvedTerms }), index.h("kritzel-share-dialog", { key: '61ed918499760d874d5d2ec140d3cf59ce94520b', ref: el => {
|
|
3103
3181
|
if (el) {
|
|
3104
3182
|
this.shareDialogRef = el;
|
|
3105
3183
|
}
|
|
3106
|
-
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: '
|
|
3184
|
+
}, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: '5f6528a57884bd1494e45755609e710f69041a4d', ref: el => {
|
|
3107
3185
|
if (el) {
|
|
3108
3186
|
this.loginDialogRef = el;
|
|
3109
3187
|
}
|
|
@@ -3122,6 +3200,12 @@ const KritzelEditor = class {
|
|
|
3122
3200
|
"activeWorkspace": [{
|
|
3123
3201
|
"onActiveWorkspaceChange": 0
|
|
3124
3202
|
}],
|
|
3203
|
+
"customFonts": [{
|
|
3204
|
+
"onCustomFontsChange": 0
|
|
3205
|
+
}],
|
|
3206
|
+
"controls": [{
|
|
3207
|
+
"onControlsChange": 0
|
|
3208
|
+
}],
|
|
3125
3209
|
"activeWorkspaceId": [{
|
|
3126
3210
|
"onActiveWorkspaceIdChange": 0
|
|
3127
3211
|
}],
|
|
@@ -21403,7 +21487,7 @@ class KritzelContextMenuHandler extends schema_constants.KritzelBaseHandler {
|
|
|
21403
21487
|
* @returns void - This method does not return a value; it updates state and triggers a rerender.
|
|
21404
21488
|
*/
|
|
21405
21489
|
handleContextMenu(event) {
|
|
21406
|
-
if (
|
|
21490
|
+
if (this._core.store.state.activeTool?.toolType !== 'selection') {
|
|
21407
21491
|
return;
|
|
21408
21492
|
}
|
|
21409
21493
|
if (this._core.store.state.skipContextMenu) {
|
|
@@ -21463,7 +21547,7 @@ class KritzelContextMenuHandler extends schema_constants.KritzelBaseHandler {
|
|
|
21463
21547
|
*/
|
|
21464
21548
|
open(options) {
|
|
21465
21549
|
const { x, y, objectId } = options;
|
|
21466
|
-
if (this._core.store.state.activeTool
|
|
21550
|
+
if (this._core.store.state.activeTool?.toolType === 'selection') {
|
|
21467
21551
|
const selectionTool = this._core.store.state.activeTool;
|
|
21468
21552
|
selectionTool?.moveHandler?.cancelPendingDrag();
|
|
21469
21553
|
}
|
|
@@ -22278,6 +22362,9 @@ class KritzelObjectMap {
|
|
|
22278
22362
|
*/
|
|
22279
22363
|
onAwarenessChange(callback) {
|
|
22280
22364
|
this._awarenessChangeCallbacks.push(callback);
|
|
22365
|
+
return () => {
|
|
22366
|
+
this._awarenessChangeCallbacks = this._awarenessChangeCallbacks.filter(existingCallback => existingCallback !== callback);
|
|
22367
|
+
};
|
|
22281
22368
|
}
|
|
22282
22369
|
/**
|
|
22283
22370
|
* Registers a callback to be invoked when remote object changes are received.
|
|
@@ -22286,6 +22373,9 @@ class KritzelObjectMap {
|
|
|
22286
22373
|
*/
|
|
22287
22374
|
onObjectsChange(callback) {
|
|
22288
22375
|
this._objectsChangeCallbacks.push(callback);
|
|
22376
|
+
return () => {
|
|
22377
|
+
this._objectsChangeCallbacks = this._objectsChangeCallbacks.filter(existingCallback => existingCallback !== callback);
|
|
22378
|
+
};
|
|
22289
22379
|
}
|
|
22290
22380
|
/**
|
|
22291
22381
|
* Returns the Yjs UndoManager instance for managing undo/redo operations.
|
|
@@ -22482,6 +22572,9 @@ class KritzelObjectMap {
|
|
|
22482
22572
|
callback(states);
|
|
22483
22573
|
}
|
|
22484
22574
|
}, delayMs);
|
|
22575
|
+
if (typeof this._awarenessEmitTimeout.unref === 'function') {
|
|
22576
|
+
this._awarenessEmitTimeout.unref();
|
|
22577
|
+
}
|
|
22485
22578
|
}
|
|
22486
22579
|
};
|
|
22487
22580
|
this._awareness.on('change', this._awarenessChangeHandler);
|
|
@@ -24472,9 +24565,8 @@ class KritzelClipboardManager {
|
|
|
24472
24565
|
const scale = this._core.store.state.scale;
|
|
24473
24566
|
const offset = 25 / scale;
|
|
24474
24567
|
const preparePromises = intent.files.map(async (file, index) => {
|
|
24475
|
-
|
|
24476
|
-
|
|
24477
|
-
return schema_constants.KritzelImage.fromBlob(this._core, compressed, {
|
|
24568
|
+
const preparedFile = await this.prepareImageFile(file);
|
|
24569
|
+
return schema_constants.KritzelImage.fromBlob(this._core, preparedFile, {
|
|
24478
24570
|
translateX: index * offset,
|
|
24479
24571
|
translateY: index * offset,
|
|
24480
24572
|
});
|
|
@@ -24486,6 +24578,12 @@ class KritzelClipboardManager {
|
|
|
24486
24578
|
return null;
|
|
24487
24579
|
}
|
|
24488
24580
|
}
|
|
24581
|
+
async prepareImageFile(file) {
|
|
24582
|
+
if (schema_constants.KritzelImageFileHelper.isGifFile(file)) {
|
|
24583
|
+
return file;
|
|
24584
|
+
}
|
|
24585
|
+
return schema_constants.imageCompression(file, { maxWidthOrHeight: 1200 });
|
|
24586
|
+
}
|
|
24489
24587
|
async materializePlainText(intent) {
|
|
24490
24588
|
const textObject = schema_constants.KritzelText.create(this._core);
|
|
24491
24589
|
const paragraphs = intent.text.split('\n').map(line => {
|
|
@@ -27953,7 +28051,7 @@ const KritzelEngine = class {
|
|
|
27953
28051
|
}
|
|
27954
28052
|
return existingTool;
|
|
27955
28053
|
}
|
|
27956
|
-
const registeredTool = this.core.toolRegistry.registerTool(toolName, toolClass);
|
|
28054
|
+
const registeredTool = this.core.toolRegistry.registerTool(toolName, this.resolveToolClass(toolClass));
|
|
27957
28055
|
if (toolConfig) {
|
|
27958
28056
|
this.applyToolConfig(registeredTool, toolConfig);
|
|
27959
28057
|
}
|
|
@@ -28755,8 +28853,25 @@ const KritzelEngine = class {
|
|
|
28755
28853
|
if (!workspace) {
|
|
28756
28854
|
throw new Error('Cannot export workspace: no active workspace is loaded');
|
|
28757
28855
|
}
|
|
28856
|
+
await this.core.initializeAssetStorage();
|
|
28758
28857
|
const serialized = workspace.serialize({ includeObjects: true });
|
|
28759
|
-
|
|
28858
|
+
const exportMode = this.getWorkspaceExportMode();
|
|
28859
|
+
const { objects, ...workspaceWithoutObjects } = serialized;
|
|
28860
|
+
const payload = {
|
|
28861
|
+
...workspaceWithoutObjects,
|
|
28862
|
+
exportMode,
|
|
28863
|
+
...(objects !== undefined ? { objects } : {}),
|
|
28864
|
+
};
|
|
28865
|
+
if (exportMode === 'portable') {
|
|
28866
|
+
const portableAssets = await this.collectPortableAssets(payload.objects);
|
|
28867
|
+
if (Object.keys(portableAssets).length > 0) {
|
|
28868
|
+
payload.assets = portableAssets;
|
|
28869
|
+
}
|
|
28870
|
+
}
|
|
28871
|
+
else {
|
|
28872
|
+
delete payload.assets;
|
|
28873
|
+
}
|
|
28874
|
+
return JSON.stringify(payload, null, 2);
|
|
28760
28875
|
}
|
|
28761
28876
|
/**
|
|
28762
28877
|
* Imports a workspace from a JSON string into a new workspace.
|
|
@@ -28770,22 +28885,15 @@ const KritzelEngine = class {
|
|
|
28770
28885
|
if (!data.__class__ || data.__class__ !== 'KritzelWorkspace') {
|
|
28771
28886
|
throw new Error('Invalid workspace data: missing or incorrect __class__ identifier');
|
|
28772
28887
|
}
|
|
28888
|
+
await this.core.initializeAssetStorage();
|
|
28889
|
+
await this.restorePortableAssets(data);
|
|
28773
28890
|
if (data.version && data.version !== schema_constants.WORKSPACE_EXPORT_VERSION) {
|
|
28774
28891
|
console.warn(`Workspace version mismatch: expected ${schema_constants.WORKSPACE_EXPORT_VERSION}, got ${data.version}`);
|
|
28775
28892
|
}
|
|
28776
28893
|
// Create a new workspace with a fresh ID but use the imported name
|
|
28777
28894
|
const newWorkspaceId = schema_constants.ObjectHelper.generateUUID();
|
|
28778
|
-
const importedName = data.name
|
|
28779
|
-
|
|
28780
|
-
// Backward compatibility: convert legacy translateX/translateY to centerWorldX/centerWorldY
|
|
28781
|
-
if ('translateX' in importedViewport && !('centerWorldX' in importedViewport)) {
|
|
28782
|
-
const scale = importedViewport.scale ?? 1;
|
|
28783
|
-
importedViewport = {
|
|
28784
|
-
centerWorldX: -(importedViewport.translateX ?? 0) / scale,
|
|
28785
|
-
centerWorldY: -(importedViewport.translateY ?? 0) / scale,
|
|
28786
|
-
scale,
|
|
28787
|
-
};
|
|
28788
|
-
}
|
|
28895
|
+
const importedName = this.getImportedWorkspaceName(data.name);
|
|
28896
|
+
const importedViewport = this.getImportedWorkspaceViewport(data.viewport);
|
|
28789
28897
|
const newWorkspace = new schema_constants.KritzelWorkspace(newWorkspaceId, importedName, importedViewport);
|
|
28790
28898
|
// Save the new workspace
|
|
28791
28899
|
this.core.createWorkspace(newWorkspace);
|
|
@@ -28824,6 +28932,8 @@ const KritzelEngine = class {
|
|
|
28824
28932
|
if (!data.__class__ || data.__class__ !== 'KritzelWorkspace') {
|
|
28825
28933
|
throw new Error('Invalid workspace data: missing or incorrect __class__ identifier');
|
|
28826
28934
|
}
|
|
28935
|
+
await this.core.initializeAssetStorage();
|
|
28936
|
+
await this.restorePortableAssets(data);
|
|
28827
28937
|
if (data.version && data.version !== schema_constants.WORKSPACE_EXPORT_VERSION) {
|
|
28828
28938
|
console.warn(`Workspace version mismatch: expected ${schema_constants.WORKSPACE_EXPORT_VERSION}, got ${data.version}`);
|
|
28829
28939
|
}
|
|
@@ -28850,6 +28960,98 @@ const KritzelEngine = class {
|
|
|
28850
28960
|
this.core.rerender();
|
|
28851
28961
|
return loadedCount;
|
|
28852
28962
|
}
|
|
28963
|
+
getWorkspaceExportMode() {
|
|
28964
|
+
return this.core.assetResolver.hasRemoteProvider ? 'lightweight' : 'portable';
|
|
28965
|
+
}
|
|
28966
|
+
async collectPortableAssets(serializedObjects) {
|
|
28967
|
+
if (!Array.isArray(serializedObjects) || serializedObjects.length === 0) {
|
|
28968
|
+
return {};
|
|
28969
|
+
}
|
|
28970
|
+
const assetIds = new Set();
|
|
28971
|
+
for (const serializedObject of serializedObjects) {
|
|
28972
|
+
if (!serializedObject || typeof serializedObject !== 'object') {
|
|
28973
|
+
continue;
|
|
28974
|
+
}
|
|
28975
|
+
const maybeImage = serializedObject;
|
|
28976
|
+
if (maybeImage.__class__ === 'KritzelImage' && typeof maybeImage.assetId === 'string' && maybeImage.assetId.length > 0) {
|
|
28977
|
+
assetIds.add(maybeImage.assetId);
|
|
28978
|
+
}
|
|
28979
|
+
}
|
|
28980
|
+
const assets = {};
|
|
28981
|
+
for (const assetId of assetIds) {
|
|
28982
|
+
try {
|
|
28983
|
+
const blob = await this.core.assetResolver.fetchBlob(assetId);
|
|
28984
|
+
assets[assetId] = await this.blobToDataUrl(blob);
|
|
28985
|
+
}
|
|
28986
|
+
catch (error) {
|
|
28987
|
+
console.warn(`[Kritzel] Failed to embed asset ${assetId} in portable workspace export:`, error);
|
|
28988
|
+
}
|
|
28989
|
+
}
|
|
28990
|
+
return assets;
|
|
28991
|
+
}
|
|
28992
|
+
async restorePortableAssets(data) {
|
|
28993
|
+
const assets = data.assets;
|
|
28994
|
+
if (!assets || typeof assets !== 'object') {
|
|
28995
|
+
return;
|
|
28996
|
+
}
|
|
28997
|
+
for (const [assetId, dataUrl] of Object.entries(assets)) {
|
|
28998
|
+
if (!assetId || typeof dataUrl !== 'string' || !dataUrl.startsWith('data:')) {
|
|
28999
|
+
continue;
|
|
29000
|
+
}
|
|
29001
|
+
try {
|
|
29002
|
+
const blob = await this.dataUrlToBlob(dataUrl);
|
|
29003
|
+
await this.core.assetResolver.put(blob, {
|
|
29004
|
+
id: assetId,
|
|
29005
|
+
mimeType: blob.type || 'application/octet-stream',
|
|
29006
|
+
kind: 'image',
|
|
29007
|
+
});
|
|
29008
|
+
}
|
|
29009
|
+
catch (error) {
|
|
29010
|
+
console.warn(`[Kritzel] Failed to restore embedded asset ${assetId} from portable workspace import:`, error);
|
|
29011
|
+
}
|
|
29012
|
+
}
|
|
29013
|
+
}
|
|
29014
|
+
blobToDataUrl(blob) {
|
|
29015
|
+
return new Promise((resolve, reject) => {
|
|
29016
|
+
const reader = new FileReader();
|
|
29017
|
+
reader.onload = () => resolve(reader.result);
|
|
29018
|
+
reader.onerror = () => reject(reader.error ?? new Error('Failed to read blob as data URL'));
|
|
29019
|
+
reader.readAsDataURL(blob);
|
|
29020
|
+
});
|
|
29021
|
+
}
|
|
29022
|
+
async dataUrlToBlob(dataUrl) {
|
|
29023
|
+
const response = await fetch(dataUrl);
|
|
29024
|
+
return response.blob();
|
|
29025
|
+
}
|
|
29026
|
+
getImportedWorkspaceName(rawName) {
|
|
29027
|
+
if (typeof rawName === 'string' && rawName.trim().length > 0) {
|
|
29028
|
+
return rawName;
|
|
29029
|
+
}
|
|
29030
|
+
return 'Imported Workspace';
|
|
29031
|
+
}
|
|
29032
|
+
getImportedWorkspaceViewport(rawViewport) {
|
|
29033
|
+
if (!rawViewport || typeof rawViewport !== 'object') {
|
|
29034
|
+
return { centerWorldX: 0, centerWorldY: 0, scale: 1 };
|
|
29035
|
+
}
|
|
29036
|
+
const viewport = rawViewport;
|
|
29037
|
+
if (typeof viewport.centerWorldX === 'number' && typeof viewport.centerWorldY === 'number') {
|
|
29038
|
+
const scale = typeof viewport.scale === 'number' && viewport.scale > 0 ? viewport.scale : 1;
|
|
29039
|
+
return {
|
|
29040
|
+
centerWorldX: viewport.centerWorldX,
|
|
29041
|
+
centerWorldY: viewport.centerWorldY,
|
|
29042
|
+
scale,
|
|
29043
|
+
};
|
|
29044
|
+
}
|
|
29045
|
+
if (typeof viewport.translateX === 'number' || typeof viewport.translateY === 'number') {
|
|
29046
|
+
const scale = typeof viewport.scale === 'number' && viewport.scale > 0 ? viewport.scale : 1;
|
|
29047
|
+
return {
|
|
29048
|
+
centerWorldX: -(typeof viewport.translateX === 'number' ? viewport.translateX : 0) / scale,
|
|
29049
|
+
centerWorldY: -(typeof viewport.translateY === 'number' ? viewport.translateY : 0) / scale,
|
|
29050
|
+
scale,
|
|
29051
|
+
};
|
|
29052
|
+
}
|
|
29053
|
+
return { centerWorldX: 0, centerWorldY: 0, scale: 1 };
|
|
29054
|
+
}
|
|
28853
29055
|
/**
|
|
28854
29056
|
* Exports the current workspace as a JSON file and triggers a browser download.
|
|
28855
29057
|
* @param filename - Optional custom filename (without extension). Defaults to workspace name with timestamp.
|
|
@@ -29134,31 +29336,71 @@ const KritzelEngine = class {
|
|
|
29134
29336
|
this.syncingChange.emit(isSyncing);
|
|
29135
29337
|
}
|
|
29136
29338
|
applyToolConfig(tool, toolConfig) {
|
|
29137
|
-
|
|
29339
|
+
const normalizedToolConfig = this.normalizeToolConfig(toolConfig);
|
|
29340
|
+
Object.entries(normalizedToolConfig).forEach(([key, value]) => {
|
|
29138
29341
|
tool[key] = value;
|
|
29139
29342
|
});
|
|
29140
29343
|
// Resolve palettes map into the flat palette array the UI reads
|
|
29141
|
-
if ('palettes' in
|
|
29142
|
-
const brushConfig =
|
|
29344
|
+
if ('palettes' in normalizedToolConfig && 'type' in normalizedToolConfig) {
|
|
29345
|
+
const brushConfig = normalizedToolConfig;
|
|
29143
29346
|
const resolvedPalette = brushConfig.palettes[brushConfig.type];
|
|
29144
29347
|
if (resolvedPalette) {
|
|
29145
29348
|
tool['palette'] = resolvedPalette;
|
|
29146
29349
|
}
|
|
29147
29350
|
}
|
|
29148
29351
|
// Resolve sizes map into the flat sizes array the UI reads (brush tool uses a map keyed by type)
|
|
29149
|
-
if ('sizes' in
|
|
29150
|
-
const brushConfig =
|
|
29352
|
+
if ('sizes' in normalizedToolConfig && normalizedToolConfig.sizes != null && 'type' in normalizedToolConfig) {
|
|
29353
|
+
const brushConfig = normalizedToolConfig;
|
|
29151
29354
|
const resolvedSizes = brushConfig.sizes?.[brushConfig.type];
|
|
29152
29355
|
if (resolvedSizes) {
|
|
29153
29356
|
tool['sizes'] = resolvedSizes;
|
|
29154
29357
|
}
|
|
29155
29358
|
}
|
|
29156
29359
|
}
|
|
29360
|
+
normalizeToolConfig(toolConfig) {
|
|
29361
|
+
if (!this.isTextToolConfig(toolConfig)) {
|
|
29362
|
+
return toolConfig;
|
|
29363
|
+
}
|
|
29364
|
+
return {
|
|
29365
|
+
...toolConfig,
|
|
29366
|
+
availableFonts: schema_constants.resolveTextToolAvailableFonts(toolConfig.availableFonts),
|
|
29367
|
+
};
|
|
29368
|
+
}
|
|
29369
|
+
isTextToolConfig(toolConfig) {
|
|
29370
|
+
return 'fontFamily' in toolConfig && 'size' in toolConfig && 'color' in toolConfig;
|
|
29371
|
+
}
|
|
29372
|
+
/** Built-in tool classes of this bundle keyed by their tool type. */
|
|
29373
|
+
static BUILT_IN_TOOL_CLASSES = {
|
|
29374
|
+
selection: schema_constants.KritzelSelectionTool,
|
|
29375
|
+
brush: schema_constants.KritzelBrushTool,
|
|
29376
|
+
eraser: schema_constants.KritzelEraserTool,
|
|
29377
|
+
line: schema_constants.KritzelLineTool,
|
|
29378
|
+
shape: schema_constants.KritzelShapeTool,
|
|
29379
|
+
text: schema_constants.KritzelTextTool,
|
|
29380
|
+
image: schema_constants.KritzelImageTool,
|
|
29381
|
+
};
|
|
29382
|
+
/**
|
|
29383
|
+
* Resolves a tool class to the internal built-in class when a foreign copy is passed.
|
|
29384
|
+
* Classes from another compiled copy of the library (dual-package hazard, e.g. built-ins
|
|
29385
|
+
* re-exported by a framework wrapper) would otherwise break `instanceof` checks.
|
|
29386
|
+
*/
|
|
29387
|
+
resolveToolClass(toolClass) {
|
|
29388
|
+
if (toolClass.prototype instanceof schema_constants.KritzelBaseTool) {
|
|
29389
|
+
return toolClass;
|
|
29390
|
+
}
|
|
29391
|
+
try {
|
|
29392
|
+
const probe = new toolClass(this.core);
|
|
29393
|
+
return KritzelEngine.BUILT_IN_TOOL_CLASSES[probe.toolType] ?? toolClass;
|
|
29394
|
+
}
|
|
29395
|
+
catch {
|
|
29396
|
+
return toolClass;
|
|
29397
|
+
}
|
|
29398
|
+
}
|
|
29157
29399
|
get isSelecting() {
|
|
29158
|
-
return this.core.store.state.activeTool
|
|
29400
|
+
return this.core.store.state.activeTool?.toolType === 'selection' && this.core.store.state.isSelecting;
|
|
29159
29401
|
}
|
|
29160
29402
|
get isSelectionActive() {
|
|
29161
|
-
return this.core.store.state.activeTool
|
|
29403
|
+
return this.core.store.state.activeTool?.toolType === 'selection' && this.core.store.selectionGroup !== null;
|
|
29162
29404
|
}
|
|
29163
29405
|
constructor(hostRef) {
|
|
29164
29406
|
index.registerInstance(this, hostRef);
|
|
@@ -29475,7 +29717,7 @@ const KritzelEngine = class {
|
|
|
29475
29717
|
this.core.store.onStateChange('activeTool', this._handleActiveToolChange.bind(this));
|
|
29476
29718
|
}
|
|
29477
29719
|
_handleActiveToolChange(activeTool) {
|
|
29478
|
-
if (
|
|
29720
|
+
if (activeTool?.toolType !== 'selection') {
|
|
29479
29721
|
this.core.clearSelection();
|
|
29480
29722
|
this.core.store.objects?.remove(o => o instanceof schema_constants.KritzelSelectionBox);
|
|
29481
29723
|
this.core.store.setSelectionBox(null);
|
|
@@ -29484,10 +29726,10 @@ const KritzelEngine = class {
|
|
|
29484
29726
|
this.core.store.state.isResizeHandleSelected = false;
|
|
29485
29727
|
this.core.store.state.isRotationHandleSelected = false;
|
|
29486
29728
|
}
|
|
29487
|
-
if (
|
|
29729
|
+
if (activeTool?.toolType !== 'text') {
|
|
29488
29730
|
this.core.resetActiveText();
|
|
29489
29731
|
}
|
|
29490
|
-
if (
|
|
29732
|
+
if (activeTool?.toolType !== 'shape') {
|
|
29491
29733
|
this.core.resetActiveShape();
|
|
29492
29734
|
}
|
|
29493
29735
|
this.core.store.state.skipContextMenu = false;
|
|
@@ -29721,7 +29963,7 @@ const KritzelEngine = class {
|
|
|
29721
29963
|
borderWidth: object.borderWidth + 'px',
|
|
29722
29964
|
borderStyle: 'solid',
|
|
29723
29965
|
padding: object.padding + 'px',
|
|
29724
|
-
overflow: '
|
|
29966
|
+
overflow: 'visible',
|
|
29725
29967
|
display: 'block',
|
|
29726
29968
|
} })), schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') && !this.core.displaySelectionLineUI(object) && (index.h("div", { ref: el => el && object.mount(el), style: {
|
|
29727
29969
|
position: 'absolute',
|
|
@@ -30071,7 +30313,7 @@ const KritzelEngine = class {
|
|
|
30071
30313
|
}, this.core.store.selectionGroup?.objects || []);
|
|
30072
30314
|
}
|
|
30073
30315
|
this.hideContextMenu();
|
|
30074
|
-
}, onClose: () => this.hideContextMenu() })), this.core.store.objects?.hasAwareness && index.h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool
|
|
30316
|
+
}, onClose: () => this.hideContextMenu() })), this.core.store.objects?.hasAwareness && index.h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool?.toolType === 'eraser' && !this.core.store.state.isScaling && index.h("kritzel-cursor-trail", { core: this.core }), !this.core.licenseManager.isLicensed && index.h("kritzel-watermark", { core: this.core, label: this.core.localizationManager.translate('watermark.poweredBy') })));
|
|
30075
30317
|
}
|
|
30076
30318
|
static get watchers() { return {
|
|
30077
30319
|
"workspace": [{
|
|
@@ -30259,39 +30501,47 @@ const KritzelFontFamily = class {
|
|
|
30259
30501
|
index.registerInstance(this, hostRef);
|
|
30260
30502
|
this.fontFamilyChange = index.createEvent(this, "fontFamilyChange");
|
|
30261
30503
|
}
|
|
30262
|
-
fontOptions = [
|
|
30263
|
-
{ value: 'arial', label: 'Arial' },
|
|
30264
|
-
{ value: 'verdana', label: 'Verdana' },
|
|
30265
|
-
{ value: 'helvetica', label: 'Helvetica' },
|
|
30266
|
-
{ value: 'tahoma', label: 'Tahoma' },
|
|
30267
|
-
{ value: 'trebuchet ms', label: 'Trebuchet MS' },
|
|
30268
|
-
{ value: 'times new roman', label: 'Times New Roman' },
|
|
30269
|
-
{ value: 'georgia', label: 'Georgia' },
|
|
30270
|
-
{ value: 'garamond', label: 'Garamond' },
|
|
30271
|
-
{ value: 'courier new', label: 'Courier New' },
|
|
30272
|
-
{ value: 'brush script mt', label: 'Brush Script MT' },
|
|
30273
|
-
];
|
|
30504
|
+
fontOptions = [];
|
|
30274
30505
|
selectedFontFamily;
|
|
30275
30506
|
fontFamilyChange;
|
|
30507
|
+
handleFontOptionsChange() {
|
|
30508
|
+
this.ensureValidSelectedFont(this.resolveFontOptions());
|
|
30509
|
+
}
|
|
30276
30510
|
componentWillLoad() {
|
|
30277
|
-
|
|
30278
|
-
const isValidCurrentFont = this.fontOptions.some(opt => opt.value === this.selectedFontFamily);
|
|
30279
|
-
if (!this.selectedFontFamily || !isValidCurrentFont) {
|
|
30280
|
-
this.selectedFontFamily = this.fontOptions[0].value;
|
|
30281
|
-
}
|
|
30282
|
-
}
|
|
30511
|
+
this.ensureValidSelectedFont(this.resolveFontOptions());
|
|
30283
30512
|
}
|
|
30284
30513
|
handleDropdownValueChange = (event) => {
|
|
30285
30514
|
this.fontFamilyChange.emit(event.detail);
|
|
30286
30515
|
};
|
|
30516
|
+
ensureValidSelectedFont(options) {
|
|
30517
|
+
if (options.length === 0) {
|
|
30518
|
+
return;
|
|
30519
|
+
}
|
|
30520
|
+
const normalizedSelected = this.selectedFontFamily?.trim().toLocaleLowerCase();
|
|
30521
|
+
const isValidCurrentFont = options.some(opt => opt.value.trim().toLocaleLowerCase() === normalizedSelected);
|
|
30522
|
+
if (!normalizedSelected || !isValidCurrentFont) {
|
|
30523
|
+
this.selectedFontFamily = options[0].value;
|
|
30524
|
+
}
|
|
30525
|
+
}
|
|
30526
|
+
resolveFontOptions() {
|
|
30527
|
+
return this.fontOptions;
|
|
30528
|
+
}
|
|
30287
30529
|
render() {
|
|
30288
|
-
const
|
|
30530
|
+
const fontOptions = this.resolveFontOptions();
|
|
30531
|
+
const selectedOption = fontOptions.find(option => option.value === this.selectedFontFamily);
|
|
30532
|
+
const selectedFontFamily = selectedOption?.cssFontFamily ?? this.selectedFontFamily;
|
|
30533
|
+
const dropdownOptions = fontOptions.map(option => ({
|
|
30289
30534
|
value: option.value,
|
|
30290
30535
|
label: option.label,
|
|
30291
|
-
style: { fontFamily: option.value },
|
|
30536
|
+
style: { fontFamily: option.cssFontFamily ?? option.value },
|
|
30292
30537
|
}));
|
|
30293
|
-
return (index.h(index.Host, { key: '
|
|
30538
|
+
return (index.h(index.Host, { key: '059350f34370f7a291f47a42721ca5d9bb82df49' }, index.h("kritzel-dropdown", { key: 'fbd8cf1ae463c7e9b76d0ac754a41de54397058e', options: dropdownOptions, value: this.selectedFontFamily, onValueChanged: this.handleDropdownValueChange, selectStyles: { fontFamily: selectedFontFamily } })));
|
|
30294
30539
|
}
|
|
30540
|
+
static get watchers() { return {
|
|
30541
|
+
"fontOptions": [{
|
|
30542
|
+
"handleFontOptionsChange": 0
|
|
30543
|
+
}]
|
|
30544
|
+
}; }
|
|
30295
30545
|
};
|
|
30296
30546
|
KritzelFontFamily.style = kritzelFontFamilyCss();
|
|
30297
30547
|
|
|
@@ -31489,7 +31739,7 @@ const KritzelPortal = class {
|
|
|
31489
31739
|
* This file is auto-generated by the version bump scripts.
|
|
31490
31740
|
* Do not modify manually.
|
|
31491
31741
|
*/
|
|
31492
|
-
const KRITZEL_VERSION = '0.4.
|
|
31742
|
+
const KRITZEL_VERSION = '0.4.2';
|
|
31493
31743
|
|
|
31494
31744
|
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)}`;
|
|
31495
31745
|
|
|
@@ -35204,8 +35454,43 @@ const KritzelToolConfig = class {
|
|
|
35204
35454
|
sizes = [];
|
|
35205
35455
|
currentOpacity = 1;
|
|
35206
35456
|
updateTrigger = 0;
|
|
35457
|
+
getFontOptionsFromTool() {
|
|
35458
|
+
const configuredFonts = schema_constants.resolveTextToolAvailableFonts(this.tool.availableFonts).map(font => {
|
|
35459
|
+
const registeredFont = typeof font === 'string'
|
|
35460
|
+
? {
|
|
35461
|
+
family: font,
|
|
35462
|
+
label: font,
|
|
35463
|
+
cssFontFamily: font,
|
|
35464
|
+
}
|
|
35465
|
+
: {
|
|
35466
|
+
family: font.family,
|
|
35467
|
+
label: font.label ?? font.family,
|
|
35468
|
+
cssFontFamily: font.cssFontFamily ?? font.family,
|
|
35469
|
+
};
|
|
35470
|
+
return {
|
|
35471
|
+
value: registeredFont.family,
|
|
35472
|
+
label: registeredFont.label,
|
|
35473
|
+
cssFontFamily: registeredFont.cssFontFamily,
|
|
35474
|
+
};
|
|
35475
|
+
});
|
|
35476
|
+
const mergedFonts = [...configuredFonts];
|
|
35477
|
+
const seenFonts = new Set(mergedFonts.map(font => font.value.trim().toLocaleLowerCase()));
|
|
35478
|
+
for (const font of schema_constants.KritzelFontRegistry.list()) {
|
|
35479
|
+
const normalizedValue = font.family.trim().toLocaleLowerCase();
|
|
35480
|
+
if (seenFonts.has(normalizedValue)) {
|
|
35481
|
+
continue;
|
|
35482
|
+
}
|
|
35483
|
+
seenFonts.add(normalizedValue);
|
|
35484
|
+
mergedFonts.push({
|
|
35485
|
+
value: font.family,
|
|
35486
|
+
label: font.label,
|
|
35487
|
+
cssFontFamily: font.cssFontFamily,
|
|
35488
|
+
});
|
|
35489
|
+
}
|
|
35490
|
+
return mergedFonts;
|
|
35491
|
+
}
|
|
35207
35492
|
handleSelectionChange() {
|
|
35208
|
-
if (this.tool
|
|
35493
|
+
if (this.tool?.toolType === 'selection') {
|
|
35209
35494
|
this.config = KritzelToolConfigHelper.getToolConfig(this.tool);
|
|
35210
35495
|
if (this.config) {
|
|
35211
35496
|
this.updatePalette();
|
|
@@ -35242,7 +35527,7 @@ const KritzelToolConfig = class {
|
|
|
35242
35527
|
color: schema_constants.KritzelColorHelper.applyOpacity(color, opacity, this.theme),
|
|
35243
35528
|
size,
|
|
35244
35529
|
};
|
|
35245
|
-
if (this.tool
|
|
35530
|
+
if (this.tool.toolType === 'text') {
|
|
35246
35531
|
displayValues.fontFamily = this.tool.fontFamily;
|
|
35247
35532
|
}
|
|
35248
35533
|
this.displayValuesChange.emit(displayValues);
|
|
@@ -35335,7 +35620,7 @@ const KritzelToolConfig = class {
|
|
|
35335
35620
|
case 'shape-fill':
|
|
35336
35621
|
return (index.h("kritzel-shape-fill", { key: control.type, value: this.getShapeFillValue(), onValueChange: (event) => this.handlePropertyChange(control.propertyName, event.detail) }));
|
|
35337
35622
|
case 'font-family':
|
|
35338
|
-
return (index.h("kritzel-font-family", { key: control.type, selectedFontFamily: value, onFontFamilyChange: (event) => this.handlePropertyChange(control.propertyName, event.detail) }));
|
|
35623
|
+
return (index.h("kritzel-font-family", { key: control.type, fontOptions: this.getFontOptionsFromTool(), selectedFontFamily: value, onFontFamilyChange: (event) => this.handlePropertyChange(control.propertyName, event.detail) }));
|
|
35339
35624
|
default:
|
|
35340
35625
|
return null;
|
|
35341
35626
|
}
|