kritzel-stencil 0.4.7 → 0.4.8
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 +1 -1
- package/dist/cjs/kritzel-active-users_47.cjs.entry.js +31 -14
- package/dist/cjs/{schema.constants-C8hqt--r.js → schema.constants-gDeS7USU.js} +75 -7
- package/dist/collection/classes/handlers/line-handle.handler.js +1 -1
- package/dist/collection/classes/managers/license.manager.js +56 -0
- package/dist/collection/classes/objects/line.class.js +1 -1
- package/dist/collection/classes/objects/shape.class.js +3 -3
- package/dist/collection/classes/objects/text.class.js +1 -1
- package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +10 -3
- package/dist/collection/constants/license.constants.js +1 -1
- package/dist/collection/constants/version.js +1 -1
- package/dist/collection/helpers/svg-export.helper.js +19 -9
- package/dist/collection/helpers/theme.helper.js +8 -0
- package/dist/collection/themes/dark-theme.js +2 -0
- package/dist/collection/themes/light-theme.js +2 -0
- package/dist/components/index.js +3 -3
- package/dist/components/kritzel-awareness-cursors.js +1 -1
- package/dist/components/kritzel-color-palette.js +1 -1
- package/dist/components/kritzel-color.js +1 -1
- package/dist/components/kritzel-controls.js +1 -1
- package/dist/components/kritzel-editor.js +9 -9
- package/dist/components/kritzel-engine.js +1 -1
- package/dist/components/kritzel-settings.js +1 -1
- package/dist/components/kritzel-stroke-size.js +1 -1
- package/dist/components/kritzel-tool-config.js +1 -1
- package/dist/components/{p-Ka7OWbnk.js → p-0H4HOJjy.js} +2 -2
- package/dist/components/{p-1nG2hxfJ.js → p-9m1cAVwG.js} +2 -2
- package/dist/components/{p-DkH3hoLz.js → p-BknTMcbz.js} +5 -5
- package/dist/components/{p-zd7zXld8.js → p-CMZ09rB1.js} +1 -1
- package/dist/components/{p-BmyTdQGy.js → p-CURiiQfq.js} +12 -0
- package/dist/components/{p-Bm_BWQa4.js → p-Ckm1Aq0V.js} +1 -1
- package/dist/components/{p-BZxOukfY.js → p-Cr2z2UBL.js} +4 -4
- package/dist/components/{p-C2yi85nc.js → p-D8bHNNEm.js} +93 -20
- package/dist/components/{p-D0oplzU-.js → p-DgA865Tp.js} +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/kritzel-active-users_47.entry.js +31 -14
- package/dist/esm/{schema.constants-uC7_X6yr.js → schema.constants-Rpm1NA9u.js} +75 -7
- package/dist/stencil/index.esm.js +2 -2
- package/dist/stencil/{p-472f2e90.entry.js → p-8c1b7b08.entry.js} +31 -14
- package/dist/stencil/{p-uC7_X6yr.js → p-Rpm1NA9u.js} +75 -7
- package/dist/stencil/stencil.esm.js +1 -1
- package/dist/types/classes/managers/license.manager.d.ts +6 -0
- package/dist/types/constants/license.constants.d.ts +1 -1
- package/dist/types/constants/version.d.ts +1 -1
- package/dist/types/helpers/theme.helper.d.ts +1 -0
- package/dist/types/interfaces/theme.interface.d.ts +2 -0
- package/package.json +1 -1
package/dist/cjs/index.cjs.js
CHANGED
|
@@ -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-gDeS7USU.js');
|
|
5
5
|
var Y = require('yjs');
|
|
6
6
|
require('y-indexeddb');
|
|
7
7
|
require('y-websocket');
|
|
@@ -26284,14 +26284,20 @@ class KritzelSvgExportHelper {
|
|
|
26284
26284
|
const scale = this.getObjectScale(text);
|
|
26285
26285
|
// Convert ProseMirror content to HTML
|
|
26286
26286
|
const htmlContent = this.prosemirrorToHtml(text.content, text, theme);
|
|
26287
|
-
// Calculate dimensions
|
|
26287
|
+
// Calculate dimensions in SVG world units (world units = CSS px in a 1:1 SVG).
|
|
26288
26288
|
const width = text.totalWidth / scale;
|
|
26289
26289
|
const height = text.totalHeight / scale;
|
|
26290
|
+
// Convert the font size from pt to SVG world units (px equivalent).
|
|
26291
|
+
// text.fontSize is stored in CSS pt; 1 pt = 4/3 px at 96 dpi.
|
|
26292
|
+
// We also bake in scaleFactor (user resize) and divide by the object scale so
|
|
26293
|
+
// that the rendered font aligns with the world-unit dimensions above.
|
|
26294
|
+
// The CSS transform: scale(scaleFactor) is removed from the div because the
|
|
26295
|
+
// adjusted font-size already accounts for it – keeping both would double-scale
|
|
26296
|
+
// the content and overflow the foreignObject.
|
|
26297
|
+
const svgFontSizePx = (text.fontSize * (4 / 3) * (text.scaleFactor || 1) / scale).toFixed(4);
|
|
26290
26298
|
return `<g transform="${transform}"${opacity}>
|
|
26291
|
-
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
26292
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: ${text.fontFamily}; font-size: ${
|
|
26293
|
-
${htmlContent}
|
|
26294
|
-
</div>
|
|
26299
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
26300
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: ${text.fontFamily}; font-size: ${svgFontSizePx}px; color: ${fontColor}; background-color: ${bgColor || 'transparent'}; white-space: pre-wrap; word-wrap: break-word; width: 100%; margin: 0; padding: 0; box-sizing: border-box;">${htmlContent.trim()}</div>
|
|
26295
26301
|
</foreignObject>
|
|
26296
26302
|
</g>`;
|
|
26297
26303
|
}
|
|
@@ -26310,9 +26316,13 @@ class KritzelSvgExportHelper {
|
|
|
26310
26316
|
const height = text.totalHeight / scale;
|
|
26311
26317
|
const lines = this.prosemirrorToPlainTextLines(text.content);
|
|
26312
26318
|
const resolvedLines = lines.length > 0 ? lines : [''];
|
|
26313
|
-
|
|
26314
|
-
|
|
26315
|
-
|
|
26319
|
+
// Convert the font size from pt to SVG world units (px equivalent).
|
|
26320
|
+
// text.fontSize is stored in CSS pt; 1 pt = 4/3 px at 96 dpi.
|
|
26321
|
+
// We also bake in scaleFactor (user resize) and divide by the object scale so
|
|
26322
|
+
// that the rendered lines align with the world-unit bounding box dimensions above.
|
|
26323
|
+
const resolvedFontSizePx = Math.max(1, text.fontSize * (4 / 3) * (text.scaleFactor || 1) / scale);
|
|
26324
|
+
const lineHeight = resolvedFontSizePx * 1.2;
|
|
26325
|
+
const startY = resolvedFontSizePx;
|
|
26316
26326
|
const bgRect = bgColor && bgColor !== 'transparent'
|
|
26317
26327
|
? `<rect x="0" y="0" width="${width}" height="${height}" fill="${bgColor}"/>`
|
|
26318
26328
|
: '';
|
|
@@ -26324,7 +26334,7 @@ class KritzelSvgExportHelper {
|
|
|
26324
26334
|
.join('');
|
|
26325
26335
|
return `<g transform="${transform}"${opacity}>
|
|
26326
26336
|
${bgRect}
|
|
26327
|
-
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${
|
|
26337
|
+
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
26328
26338
|
</g>`;
|
|
26329
26339
|
}
|
|
26330
26340
|
/**
|
|
@@ -29983,7 +29993,9 @@ const KritzelEngine = class {
|
|
|
29983
29993
|
this.emitObjectsInViewportChange();
|
|
29984
29994
|
}
|
|
29985
29995
|
}
|
|
29986
|
-
return (index.h(index.Host, null, index.h("kritzel-loading-overlay", { visible: this.core.store.state.isLoading, text: this.core.localizationManager.translate('engine.loading') }), index.h("kritzel-sync-indicator", { visible: this.isSyncing, text: "Syncing..." }), this.core.store.state.debugInfo.showViewportInfo && (index.h("div", { class: "debug-panel"
|
|
29996
|
+
return (index.h(index.Host, null, index.h("kritzel-loading-overlay", { visible: this.core.store.state.isLoading, text: this.core.localizationManager.translate('engine.loading') }), index.h("kritzel-sync-indicator", { visible: this.isSyncing, text: "Syncing..." }), this.core.store.state.debugInfo.showViewportInfo && (index.h("div", { class: "debug-panel", style: {
|
|
29997
|
+
color: 'var(--kritzel-global-text-primary)',
|
|
29998
|
+
} }, index.h("div", null, "ActiveWorkspaceId: ", this.core.store.state?.activeWorkspace?.id), index.h("div", null, "ActiveWorkspaceName: ", this.core.store.state?.activeWorkspace?.name), index.h("div", null, "TranslateX: ", this.core.store.state?.translateX), index.h("div", null, "TranslateY: ", this.core.store.state?.translateY), index.h("div", null, "ViewportWidth: ", this.core.store.state?.viewportWidth), index.h("div", null, "ViewportHeight: ", this.core.store.state?.viewportHeight), index.h("div", null, "PointerCount: ", this.core.store.state.pointers.size), index.h("div", null, "Scale: ", this.core.store.state?.scale), index.h("div", null, "ActiveTool: ", this.core.store.state?.activeTool?.name), index.h("div", null, "HasViewportChanged: ", this.core.store.state?.hasViewportChanged ? 'true' : 'false'), index.h("div", null, "IsEnabled: ", this.core.store.state?.isEnabled ? 'true' : 'false'), index.h("div", null, "IsScaling: ", this.core.store.state?.isScaling ? 'true' : 'false'), index.h("div", null, "IsPanning: ", this.core.store.state?.isPanning ? 'true' : 'false'), index.h("div", null, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), index.h("div", null, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), index.h("div", null, "IsResizeHandleSelected: ", this.core.store.state.isResizeHandleSelected ? 'true' : 'false'), index.h("div", null, "IsRotationHandleSelected: ", this.core.store.state.isRotationHandleSelected ? 'true' : 'false'), index.h("div", null, "IsRotationHandleHovered: ", this.core.store.state.isRotationHandleHovered ? 'true' : 'false'), index.h("div", null, "IsDrawing: ", this.core.store.state.isDrawing ? 'true' : 'false'), index.h("div", null, "IsWriting: ", this.core.store.state.isWriting ? 'true' : 'false'), index.h("div", null, "IsPointerDown: ", this.core.store.isPointerDown ? 'true' : 'false'), index.h("div", null, "PointerX: ", this.core.store.state?.pointerX), index.h("div", null, "PointerY: ", this.core.store.state?.pointerY), index.h("div", null, "TotalObjects: ", this.core.store.totalObjectCount), index.h("div", null, "ObjectsInViewport: ", this.core.store.objectsInViewport.length), index.h("div", null, "SelectedObjects: ", this.core.store.selectionGroup?.objects.length || 0), index.h("div", null, "ViewportCenter: (", viewportCenterX.toFixed(2), ", ", viewportCenterY.toFixed(2), ")"))), index.h("div", { id: "origin", class: "origin", style: {
|
|
29987
29999
|
transform: `matrix(${this.core.store.state?.scale}, 0, 0, ${this.core.store.state?.scale}, ${this.core.store.state?.translateX}, ${this.core.store.state?.translateY})`,
|
|
29988
30000
|
opacity: this._sceneBootstrapOpacity.toString(),
|
|
29989
30001
|
transition: this._sceneBootstrapTransitionEnabled ? 'opacity 220ms ease-out' : 'none',
|
|
@@ -30166,6 +30178,7 @@ const KritzelEngine = class {
|
|
|
30166
30178
|
left: `${object.totalWidth}px`,
|
|
30167
30179
|
top: '0',
|
|
30168
30180
|
zIndex: (object.zIndex + 2).toString(),
|
|
30181
|
+
color: 'var(--kritzel-global-text-primary)',
|
|
30169
30182
|
} }, index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "Id: ", object.id), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "userId: ", object.userId), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "width: ", object.width), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "height: ", object.height), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateX: ", object.translateX), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateY: ", object.translateY), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "scale: ", object.scale), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "rotationDegrees: ", object.rotationDegrees), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "zIndex: ", object.zIndex), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "isSelected: ", object.isSelected ? 'true' : 'false'), schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelCustomElement') && (index.h("div", null, index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "isInteractive: ", object.isInteractive ? 'true' : 'false'))), schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && (index.h("div", null, index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "assetId: ", object.assetId), index.h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "mimeType: ", object.mimeType))))), (this.core.displaySelectionGroupUI(object) || this.core.displaySelectionLineUI(object)) &&
|
|
30170
30183
|
(() => {
|
|
30171
30184
|
const isSelectionGroup = schema_constants.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup');
|
|
@@ -30366,8 +30379,12 @@ const KritzelEngine = class {
|
|
|
30366
30379
|
strokeDasharray: data.dashArray,
|
|
30367
30380
|
strokeLinecap: 'round',
|
|
30368
30381
|
} }))), index.h("circle", { cx: data.centerX, cy: data.centerY, r: data.indicatorRadius, style: {
|
|
30369
|
-
fill: isActiveSnap
|
|
30370
|
-
|
|
30382
|
+
fill: isActiveSnap
|
|
30383
|
+
? 'var(--kritzel-snap-indicator-fill, rgba(59, 130, 246, 0.3))'
|
|
30384
|
+
: 'var(--kritzel-snap-indicator-fill-inactive, var(--kritzel-snap-indicator-fill, rgba(59, 130, 246, 0.18)))',
|
|
30385
|
+
stroke: isActiveSnap
|
|
30386
|
+
? 'var(--kritzel-snap-indicator-stroke, #007bff)'
|
|
30387
|
+
: 'var(--kritzel-snap-indicator-stroke-inactive, var(--kritzel-snap-indicator-stroke, rgba(59, 130, 246, 0.5)))',
|
|
30371
30388
|
strokeWidth: data.indicatorStrokeWidth,
|
|
30372
30389
|
} }))));
|
|
30373
30390
|
})(), (() => {
|
|
@@ -31840,7 +31857,7 @@ const KritzelPortal = class {
|
|
|
31840
31857
|
* This file is auto-generated by the version bump scripts.
|
|
31841
31858
|
* Do not modify manually.
|
|
31842
31859
|
*/
|
|
31843
|
-
const KRITZEL_VERSION = '0.4.
|
|
31860
|
+
const KRITZEL_VERSION = '0.4.8';
|
|
31844
31861
|
|
|
31845
31862
|
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-tab-panel{display:none}.settings-tab-panel.is-active{display:block}.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)}`;
|
|
31846
31863
|
|
|
@@ -14579,7 +14579,9 @@ const lightTheme = {
|
|
|
14579
14579
|
},
|
|
14580
14580
|
snap: {
|
|
14581
14581
|
indicatorFill: 'rgba(59, 130, 246, 0.3)',
|
|
14582
|
+
indicatorFillInactive: 'rgba(59, 130, 246, 0.18)',
|
|
14582
14583
|
indicatorStroke: '#007bff',
|
|
14584
|
+
indicatorStrokeInactive: 'rgba(59, 130, 246, 0.5)',
|
|
14583
14585
|
lineStroke: 'rgba(0, 0, 0, 0.2)',
|
|
14584
14586
|
},
|
|
14585
14587
|
fontSize: {
|
|
@@ -14916,7 +14918,9 @@ const darkTheme = {
|
|
|
14916
14918
|
},
|
|
14917
14919
|
snap: {
|
|
14918
14920
|
indicatorFill: 'rgba(10, 132, 255, 0.35)',
|
|
14921
|
+
indicatorFillInactive: 'rgba(10, 132, 255, 0.2)',
|
|
14919
14922
|
indicatorStroke: '#0A84FF',
|
|
14923
|
+
indicatorStrokeInactive: 'rgba(255, 255, 255, 0.45)',
|
|
14920
14924
|
lineStroke: 'rgba(255, 255, 255, 0.35)',
|
|
14921
14925
|
},
|
|
14922
14926
|
fontSize: {
|
|
@@ -15116,6 +15120,7 @@ const darkTheme = {
|
|
|
15116
15120
|
};
|
|
15117
15121
|
|
|
15118
15122
|
class ThemeHelper {
|
|
15123
|
+
static appliedVariableNames = new WeakMap();
|
|
15119
15124
|
/**
|
|
15120
15125
|
* Converts a camelCase string to kebab-case.
|
|
15121
15126
|
* @example ThemeHelper.camelToKebab('controlHoverBackgroundColor') → 'control-hover-background-color'
|
|
@@ -15181,7 +15186,14 @@ class ThemeHelper {
|
|
|
15181
15186
|
*/
|
|
15182
15187
|
static applyThemeToElement(element, theme) {
|
|
15183
15188
|
const variables = ThemeHelper.flattenThemeToVariables(theme);
|
|
15189
|
+
const previousVariableNames = ThemeHelper.appliedVariableNames.get(element);
|
|
15190
|
+
for (const name of previousVariableNames ?? []) {
|
|
15191
|
+
if (!variables.has(name)) {
|
|
15192
|
+
element.style.removeProperty(name);
|
|
15193
|
+
}
|
|
15194
|
+
}
|
|
15184
15195
|
ThemeHelper.applyVariablesToElement(element, variables);
|
|
15196
|
+
ThemeHelper.appliedVariableNames.set(element, new Set(variables.keys()));
|
|
15185
15197
|
}
|
|
15186
15198
|
}
|
|
15187
15199
|
|
|
@@ -15802,7 +15814,7 @@ class KritzelText extends KritzelBaseObject {
|
|
|
15802
15814
|
}
|
|
15803
15815
|
element.style.fontFamily = KritzelFontRegistry.resolveCssFontFamily(this.fontFamily);
|
|
15804
15816
|
element.style.fontSize = `${this.fontSize}pt`;
|
|
15805
|
-
element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
|
|
15817
|
+
element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
|
|
15806
15818
|
if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
|
|
15807
15819
|
if (!this._core.store.state.isScaling && !this._core.store.state.isPanning) {
|
|
15808
15820
|
requestAnimationFrame(() => this.adjustSizeOnInput());
|
|
@@ -18709,7 +18721,7 @@ class KritzelLine extends KritzelBaseObject {
|
|
|
18709
18721
|
getArrowFill(end) {
|
|
18710
18722
|
const config = end === 'start' ? this.arrows?.start : this.arrows?.end;
|
|
18711
18723
|
const color = config?.fill ?? this.stroke;
|
|
18712
|
-
return KritzelColorHelper.resolveThemeColor(color);
|
|
18724
|
+
return KritzelColorHelper.resolveThemeColor(color, this._core?.themeManager?.currentTheme);
|
|
18713
18725
|
}
|
|
18714
18726
|
/**
|
|
18715
18727
|
* Generates SVG path data for an arrow head based on the given style.
|
|
@@ -19512,7 +19524,7 @@ class KritzelShape extends KritzelBaseObject {
|
|
|
19512
19524
|
}
|
|
19513
19525
|
element.style.fontFamily = this.fontFamily;
|
|
19514
19526
|
element.style.fontSize = `${this.fontSize}pt`;
|
|
19515
|
-
element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
|
|
19527
|
+
element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
|
|
19516
19528
|
element.style.whiteSpace = 'pre-wrap';
|
|
19517
19529
|
element.style.wordWrap = 'break-word';
|
|
19518
19530
|
if (this.editor.dom.parentElement === element) {
|
|
@@ -19828,13 +19840,13 @@ class KritzelShape extends KritzelBaseObject {
|
|
|
19828
19840
|
this.fontColor = KritzelColorHelper.determineTextColor(this.fillColor);
|
|
19829
19841
|
// Update the editor's text color immediately
|
|
19830
19842
|
if (this.editor?.dom?.parentElement) {
|
|
19831
|
-
this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
|
|
19843
|
+
this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
|
|
19832
19844
|
}
|
|
19833
19845
|
}
|
|
19834
19846
|
else if (changedProperties.includes('fontColor')) {
|
|
19835
19847
|
// Also update editor when fontColor changes directly
|
|
19836
19848
|
if (this.editor?.dom?.parentElement) {
|
|
19837
|
-
this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
|
|
19849
|
+
this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
|
|
19838
19850
|
}
|
|
19839
19851
|
}
|
|
19840
19852
|
}
|
|
@@ -24698,7 +24710,7 @@ class KritzelLineHandleHandler extends KritzelBaseHandler {
|
|
|
24698
24710
|
t: clipInfo?.t,
|
|
24699
24711
|
edgeX: clipInfo?.edgeX,
|
|
24700
24712
|
edgeY: clipInfo?.edgeY,
|
|
24701
|
-
lineStroke: KritzelColorHelper.resolveThemeColor(line.stroke),
|
|
24713
|
+
lineStroke: KritzelColorHelper.resolveThemeColor(line.stroke, this._core.themeManager.currentTheme),
|
|
24702
24714
|
lineStrokeWidth: line.strokeWidth / line.scale,
|
|
24703
24715
|
arrowOffset: endpoint === 'start'
|
|
24704
24716
|
? (line.hasStartArrow ? line.getArrowSize('start') / line.scale : undefined)
|
|
@@ -30277,7 +30289,7 @@ const KRITZEL_LICENSE_TOKEN_PREFIX = 'KRTZL1.';
|
|
|
30277
30289
|
* printed public key here. Replacing this value invalidates every license
|
|
30278
30290
|
* signed with the previous key.
|
|
30279
30291
|
*/
|
|
30280
|
-
const KRITZEL_LICENSE_PUBLIC_KEY = '
|
|
30292
|
+
const KRITZEL_LICENSE_PUBLIC_KEY = '2IwZDin-qV3kOt8SEQCqdaJsGT9S7tAGapUYJVnVGQo';
|
|
30281
30293
|
|
|
30282
30294
|
/** Minimum delay (ms) between periodic license re-validations. */
|
|
30283
30295
|
const MIN_REVALIDATION_DELAY_MS = 30_000;
|
|
@@ -30510,8 +30522,64 @@ class KritzelLicenseManager {
|
|
|
30510
30522
|
if (typeof claims.exp === 'number' && claims.exp * 1000 <= Date.now()) {
|
|
30511
30523
|
return { status: 'rejected' }; // Cleanly expired.
|
|
30512
30524
|
}
|
|
30525
|
+
const allowedDomains = this.normalizeAllowedDomains(claims.allowedDomains);
|
|
30526
|
+
if (allowedDomains === null || allowedDomains.length === 0) {
|
|
30527
|
+
return { status: 'rejected' };
|
|
30528
|
+
}
|
|
30529
|
+
const currentHostname = this.getCurrentHostname();
|
|
30530
|
+
if (!currentHostname || !allowedDomains.includes(currentHostname)) {
|
|
30531
|
+
return { status: 'rejected' };
|
|
30532
|
+
}
|
|
30513
30533
|
return { status: 'pass', payloadSegment, signatureSegment, claims };
|
|
30514
30534
|
}
|
|
30535
|
+
/** Returns the normalized current hostname, or null when unavailable/invalid. */
|
|
30536
|
+
getCurrentHostname() {
|
|
30537
|
+
const hostname = globalThis.location?.hostname;
|
|
30538
|
+
if (typeof hostname !== 'string') {
|
|
30539
|
+
return null;
|
|
30540
|
+
}
|
|
30541
|
+
return this.normalizeDomain(hostname);
|
|
30542
|
+
}
|
|
30543
|
+
/** Normalizes and validates the allowed domains claim. */
|
|
30544
|
+
normalizeAllowedDomains(domains) {
|
|
30545
|
+
if (!Array.isArray(domains)) {
|
|
30546
|
+
return null;
|
|
30547
|
+
}
|
|
30548
|
+
const normalized = new Set();
|
|
30549
|
+
for (const entry of domains) {
|
|
30550
|
+
if (typeof entry !== 'string') {
|
|
30551
|
+
return null;
|
|
30552
|
+
}
|
|
30553
|
+
const domain = this.normalizeDomain(entry);
|
|
30554
|
+
if (!domain) {
|
|
30555
|
+
return null;
|
|
30556
|
+
}
|
|
30557
|
+
normalized.add(domain);
|
|
30558
|
+
}
|
|
30559
|
+
return Array.from(normalized);
|
|
30560
|
+
}
|
|
30561
|
+
/** Normalizes a domain and rejects malformed hostnames. */
|
|
30562
|
+
normalizeDomain(value) {
|
|
30563
|
+
const trimmed = value.trim().toLowerCase();
|
|
30564
|
+
if (trimmed.length === 0) {
|
|
30565
|
+
return null;
|
|
30566
|
+
}
|
|
30567
|
+
const withoutTrailingDot = trimmed.endsWith('.') ? trimmed.slice(0, -1) : trimmed;
|
|
30568
|
+
if (withoutTrailingDot.length === 0) {
|
|
30569
|
+
return null;
|
|
30570
|
+
}
|
|
30571
|
+
try {
|
|
30572
|
+
const parsed = new URL(`https://${withoutTrailingDot}`);
|
|
30573
|
+
const normalizedHostname = parsed.hostname.toLowerCase();
|
|
30574
|
+
if (normalizedHostname !== withoutTrailingDot) {
|
|
30575
|
+
return null;
|
|
30576
|
+
}
|
|
30577
|
+
return normalizedHostname;
|
|
30578
|
+
}
|
|
30579
|
+
catch {
|
|
30580
|
+
return null;
|
|
30581
|
+
}
|
|
30582
|
+
}
|
|
30515
30583
|
/**
|
|
30516
30584
|
* Verifies the Ed25519 signature of the token against the embedded public
|
|
30517
30585
|
* key. Resolves true/false for a definitive valid/invalid signature.
|
|
@@ -463,7 +463,7 @@ export class KritzelLineHandleHandler extends KritzelBaseHandler {
|
|
|
463
463
|
t: clipInfo?.t,
|
|
464
464
|
edgeX: clipInfo?.edgeX,
|
|
465
465
|
edgeY: clipInfo?.edgeY,
|
|
466
|
-
lineStroke: KritzelColorHelper.resolveThemeColor(line.stroke),
|
|
466
|
+
lineStroke: KritzelColorHelper.resolveThemeColor(line.stroke, this._core.themeManager.currentTheme),
|
|
467
467
|
lineStrokeWidth: line.strokeWidth / line.scale,
|
|
468
468
|
arrowOffset: endpoint === 'start'
|
|
469
469
|
? (line.hasStartArrow ? line.getArrowSize('start') / line.scale : undefined)
|
|
@@ -230,8 +230,64 @@ export class KritzelLicenseManager {
|
|
|
230
230
|
if (typeof claims.exp === 'number' && claims.exp * 1000 <= Date.now()) {
|
|
231
231
|
return { status: 'rejected' }; // Cleanly expired.
|
|
232
232
|
}
|
|
233
|
+
const allowedDomains = this.normalizeAllowedDomains(claims.allowedDomains);
|
|
234
|
+
if (allowedDomains === null || allowedDomains.length === 0) {
|
|
235
|
+
return { status: 'rejected' };
|
|
236
|
+
}
|
|
237
|
+
const currentHostname = this.getCurrentHostname();
|
|
238
|
+
if (!currentHostname || !allowedDomains.includes(currentHostname)) {
|
|
239
|
+
return { status: 'rejected' };
|
|
240
|
+
}
|
|
233
241
|
return { status: 'pass', payloadSegment, signatureSegment, claims };
|
|
234
242
|
}
|
|
243
|
+
/** Returns the normalized current hostname, or null when unavailable/invalid. */
|
|
244
|
+
getCurrentHostname() {
|
|
245
|
+
const hostname = globalThis.location?.hostname;
|
|
246
|
+
if (typeof hostname !== 'string') {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
return this.normalizeDomain(hostname);
|
|
250
|
+
}
|
|
251
|
+
/** Normalizes and validates the allowed domains claim. */
|
|
252
|
+
normalizeAllowedDomains(domains) {
|
|
253
|
+
if (!Array.isArray(domains)) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
const normalized = new Set();
|
|
257
|
+
for (const entry of domains) {
|
|
258
|
+
if (typeof entry !== 'string') {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
const domain = this.normalizeDomain(entry);
|
|
262
|
+
if (!domain) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
normalized.add(domain);
|
|
266
|
+
}
|
|
267
|
+
return Array.from(normalized);
|
|
268
|
+
}
|
|
269
|
+
/** Normalizes a domain and rejects malformed hostnames. */
|
|
270
|
+
normalizeDomain(value) {
|
|
271
|
+
const trimmed = value.trim().toLowerCase();
|
|
272
|
+
if (trimmed.length === 0) {
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
const withoutTrailingDot = trimmed.endsWith('.') ? trimmed.slice(0, -1) : trimmed;
|
|
276
|
+
if (withoutTrailingDot.length === 0) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
try {
|
|
280
|
+
const parsed = new URL(`https://${withoutTrailingDot}`);
|
|
281
|
+
const normalizedHostname = parsed.hostname.toLowerCase();
|
|
282
|
+
if (normalizedHostname !== withoutTrailingDot) {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
return normalizedHostname;
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
235
291
|
/**
|
|
236
292
|
* Verifies the Ed25519 signature of the token against the embedded public
|
|
237
293
|
* key. Resolves true/false for a definitive valid/invalid signature.
|
|
@@ -749,7 +749,7 @@ export class KritzelLine extends KritzelBaseObject {
|
|
|
749
749
|
getArrowFill(end) {
|
|
750
750
|
const config = end === 'start' ? this.arrows?.start : this.arrows?.end;
|
|
751
751
|
const color = config?.fill ?? this.stroke;
|
|
752
|
-
return KritzelColorHelper.resolveThemeColor(color);
|
|
752
|
+
return KritzelColorHelper.resolveThemeColor(color, this._core?.themeManager?.currentTheme);
|
|
753
753
|
}
|
|
754
754
|
/**
|
|
755
755
|
* Generates SVG path data for an arrow head based on the given style.
|
|
@@ -175,7 +175,7 @@ export class KritzelShape extends KritzelBaseObject {
|
|
|
175
175
|
}
|
|
176
176
|
element.style.fontFamily = this.fontFamily;
|
|
177
177
|
element.style.fontSize = `${this.fontSize}pt`;
|
|
178
|
-
element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
|
|
178
|
+
element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
|
|
179
179
|
element.style.whiteSpace = 'pre-wrap';
|
|
180
180
|
element.style.wordWrap = 'break-word';
|
|
181
181
|
if (this.editor.dom.parentElement === element) {
|
|
@@ -491,13 +491,13 @@ export class KritzelShape extends KritzelBaseObject {
|
|
|
491
491
|
this.fontColor = KritzelColorHelper.determineTextColor(this.fillColor);
|
|
492
492
|
// Update the editor's text color immediately
|
|
493
493
|
if (this.editor?.dom?.parentElement) {
|
|
494
|
-
this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
|
|
494
|
+
this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
|
|
495
495
|
}
|
|
496
496
|
}
|
|
497
497
|
else if (changedProperties.includes('fontColor')) {
|
|
498
498
|
// Also update editor when fontColor changes directly
|
|
499
499
|
if (this.editor?.dom?.parentElement) {
|
|
500
|
-
this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
|
|
500
|
+
this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
|
|
501
501
|
}
|
|
502
502
|
}
|
|
503
503
|
}
|
|
@@ -149,7 +149,7 @@ export class KritzelText extends KritzelBaseObject {
|
|
|
149
149
|
}
|
|
150
150
|
element.style.fontFamily = KritzelFontRegistry.resolveCssFontFamily(this.fontFamily);
|
|
151
151
|
element.style.fontSize = `${this.fontSize}pt`;
|
|
152
|
-
element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
|
|
152
|
+
element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
|
|
153
153
|
if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
|
|
154
154
|
if (!this._core.store.state.isScaling && !this._core.store.state.isPanning) {
|
|
155
155
|
requestAnimationFrame(() => this.adjustSizeOnInput());
|
|
@@ -2416,7 +2416,9 @@ export class KritzelEngine {
|
|
|
2416
2416
|
this.emitObjectsInViewportChange();
|
|
2417
2417
|
}
|
|
2418
2418
|
}
|
|
2419
|
-
return (h(Host, null, h("kritzel-loading-overlay", { visible: this.core.store.state.isLoading, text: this.core.localizationManager.translate('engine.loading') }), h("kritzel-sync-indicator", { visible: this.isSyncing, text: "Syncing..." }), this.core.store.state.debugInfo.showViewportInfo && (h("div", { class: "debug-panel"
|
|
2419
|
+
return (h(Host, null, h("kritzel-loading-overlay", { visible: this.core.store.state.isLoading, text: this.core.localizationManager.translate('engine.loading') }), h("kritzel-sync-indicator", { visible: this.isSyncing, text: "Syncing..." }), this.core.store.state.debugInfo.showViewportInfo && (h("div", { class: "debug-panel", style: {
|
|
2420
|
+
color: 'var(--kritzel-global-text-primary)',
|
|
2421
|
+
} }, h("div", null, "ActiveWorkspaceId: ", this.core.store.state?.activeWorkspace?.id), h("div", null, "ActiveWorkspaceName: ", this.core.store.state?.activeWorkspace?.name), h("div", null, "TranslateX: ", this.core.store.state?.translateX), h("div", null, "TranslateY: ", this.core.store.state?.translateY), h("div", null, "ViewportWidth: ", this.core.store.state?.viewportWidth), h("div", null, "ViewportHeight: ", this.core.store.state?.viewportHeight), h("div", null, "PointerCount: ", this.core.store.state.pointers.size), h("div", null, "Scale: ", this.core.store.state?.scale), h("div", null, "ActiveTool: ", this.core.store.state?.activeTool?.name), h("div", null, "HasViewportChanged: ", this.core.store.state?.hasViewportChanged ? 'true' : 'false'), h("div", null, "IsEnabled: ", this.core.store.state?.isEnabled ? 'true' : 'false'), h("div", null, "IsScaling: ", this.core.store.state?.isScaling ? 'true' : 'false'), h("div", null, "IsPanning: ", this.core.store.state?.isPanning ? 'true' : 'false'), h("div", null, "IsSelecting: ", this.isSelecting ? 'true' : 'false'), h("div", null, "IsSelectionActive: ", this.isSelectionActive ? 'true' : 'false'), h("div", null, "IsResizeHandleSelected: ", this.core.store.state.isResizeHandleSelected ? 'true' : 'false'), h("div", null, "IsRotationHandleSelected: ", this.core.store.state.isRotationHandleSelected ? 'true' : 'false'), h("div", null, "IsRotationHandleHovered: ", this.core.store.state.isRotationHandleHovered ? 'true' : 'false'), h("div", null, "IsDrawing: ", this.core.store.state.isDrawing ? 'true' : 'false'), h("div", null, "IsWriting: ", this.core.store.state.isWriting ? 'true' : 'false'), h("div", null, "IsPointerDown: ", this.core.store.isPointerDown ? 'true' : 'false'), h("div", null, "PointerX: ", this.core.store.state?.pointerX), h("div", null, "PointerY: ", this.core.store.state?.pointerY), h("div", null, "TotalObjects: ", this.core.store.totalObjectCount), h("div", null, "ObjectsInViewport: ", this.core.store.objectsInViewport.length), h("div", null, "SelectedObjects: ", this.core.store.selectionGroup?.objects.length || 0), h("div", null, "ViewportCenter: (", viewportCenterX.toFixed(2), ", ", viewportCenterY.toFixed(2), ")"))), h("div", { id: "origin", class: "origin", style: {
|
|
2420
2422
|
transform: `matrix(${this.core.store.state?.scale}, 0, 0, ${this.core.store.state?.scale}, ${this.core.store.state?.translateX}, ${this.core.store.state?.translateY})`,
|
|
2421
2423
|
opacity: this._sceneBootstrapOpacity.toString(),
|
|
2422
2424
|
transition: this._sceneBootstrapTransitionEnabled ? 'opacity 220ms ease-out' : 'none',
|
|
@@ -2599,6 +2601,7 @@ export class KritzelEngine {
|
|
|
2599
2601
|
left: `${object.totalWidth}px`,
|
|
2600
2602
|
top: '0',
|
|
2601
2603
|
zIndex: (object.zIndex + 2).toString(),
|
|
2604
|
+
color: 'var(--kritzel-global-text-primary)',
|
|
2602
2605
|
} }, h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "Id: ", object.id), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "userId: ", object.userId), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "width: ", object.width), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "height: ", object.height), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateX: ", object.translateX), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "translateY: ", object.translateY), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "scale: ", object.scale), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "rotationDegrees: ", object.rotationDegrees), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "zIndex: ", object.zIndex), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "isSelected: ", object.isSelected ? 'true' : 'false'), KritzelClassHelper.isInstanceOf(object, 'KritzelCustomElement') && (h("div", null, h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "isInteractive: ", object.isInteractive ? 'true' : 'false'))), KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && (h("div", null, h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "assetId: ", object.assetId), h("div", { style: { whiteSpace: 'nowrap', fontSize: '10px' } }, "mimeType: ", object.mimeType))))), (this.core.displaySelectionGroupUI(object) || this.core.displaySelectionLineUI(object)) &&
|
|
2603
2606
|
(() => {
|
|
2604
2607
|
const isSelectionGroup = KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup');
|
|
@@ -2799,8 +2802,12 @@ export class KritzelEngine {
|
|
|
2799
2802
|
strokeDasharray: data.dashArray,
|
|
2800
2803
|
strokeLinecap: 'round',
|
|
2801
2804
|
} }))), h("circle", { cx: data.centerX, cy: data.centerY, r: data.indicatorRadius, style: {
|
|
2802
|
-
fill: isActiveSnap
|
|
2803
|
-
|
|
2805
|
+
fill: isActiveSnap
|
|
2806
|
+
? 'var(--kritzel-snap-indicator-fill, rgba(59, 130, 246, 0.3))'
|
|
2807
|
+
: 'var(--kritzel-snap-indicator-fill-inactive, var(--kritzel-snap-indicator-fill, rgba(59, 130, 246, 0.18)))',
|
|
2808
|
+
stroke: isActiveSnap
|
|
2809
|
+
? 'var(--kritzel-snap-indicator-stroke, #007bff)'
|
|
2810
|
+
: 'var(--kritzel-snap-indicator-stroke-inactive, var(--kritzel-snap-indicator-stroke, rgba(59, 130, 246, 0.5)))',
|
|
2804
2811
|
strokeWidth: data.indicatorStrokeWidth,
|
|
2805
2812
|
} }))));
|
|
2806
2813
|
})(), (() => {
|
|
@@ -22,4 +22,4 @@ export const KRITZEL_LICENSE_TOKEN_PREFIX = 'KRTZL1.';
|
|
|
22
22
|
* printed public key here. Replacing this value invalidates every license
|
|
23
23
|
* signed with the previous key.
|
|
24
24
|
*/
|
|
25
|
-
export const KRITZEL_LICENSE_PUBLIC_KEY = '
|
|
25
|
+
export const KRITZEL_LICENSE_PUBLIC_KEY = '2IwZDin-qV3kOt8SEQCqdaJsGT9S7tAGapUYJVnVGQo';
|
|
@@ -346,14 +346,20 @@ export class KritzelSvgExportHelper {
|
|
|
346
346
|
const scale = this.getObjectScale(text);
|
|
347
347
|
// Convert ProseMirror content to HTML
|
|
348
348
|
const htmlContent = this.prosemirrorToHtml(text.content, text, theme);
|
|
349
|
-
// Calculate dimensions
|
|
349
|
+
// Calculate dimensions in SVG world units (world units = CSS px in a 1:1 SVG).
|
|
350
350
|
const width = text.totalWidth / scale;
|
|
351
351
|
const height = text.totalHeight / scale;
|
|
352
|
+
// Convert the font size from pt to SVG world units (px equivalent).
|
|
353
|
+
// text.fontSize is stored in CSS pt; 1 pt = 4/3 px at 96 dpi.
|
|
354
|
+
// We also bake in scaleFactor (user resize) and divide by the object scale so
|
|
355
|
+
// that the rendered font aligns with the world-unit dimensions above.
|
|
356
|
+
// The CSS transform: scale(scaleFactor) is removed from the div because the
|
|
357
|
+
// adjusted font-size already accounts for it – keeping both would double-scale
|
|
358
|
+
// the content and overflow the foreignObject.
|
|
359
|
+
const svgFontSizePx = (text.fontSize * (4 / 3) * (text.scaleFactor || 1) / scale).toFixed(4);
|
|
352
360
|
return `<g transform="${transform}"${opacity}>
|
|
353
|
-
<foreignObject x="0" y="0" width="${width}" height="${height}">
|
|
354
|
-
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: ${text.fontFamily}; font-size: ${
|
|
355
|
-
${htmlContent}
|
|
356
|
-
</div>
|
|
361
|
+
<foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
|
|
362
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style="font-family: ${text.fontFamily}; font-size: ${svgFontSizePx}px; color: ${fontColor}; background-color: ${bgColor || 'transparent'}; white-space: pre-wrap; word-wrap: break-word; width: 100%; margin: 0; padding: 0; box-sizing: border-box;">${htmlContent.trim()}</div>
|
|
357
363
|
</foreignObject>
|
|
358
364
|
</g>`;
|
|
359
365
|
}
|
|
@@ -372,9 +378,13 @@ export class KritzelSvgExportHelper {
|
|
|
372
378
|
const height = text.totalHeight / scale;
|
|
373
379
|
const lines = this.prosemirrorToPlainTextLines(text.content);
|
|
374
380
|
const resolvedLines = lines.length > 0 ? lines : [''];
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
381
|
+
// Convert the font size from pt to SVG world units (px equivalent).
|
|
382
|
+
// text.fontSize is stored in CSS pt; 1 pt = 4/3 px at 96 dpi.
|
|
383
|
+
// We also bake in scaleFactor (user resize) and divide by the object scale so
|
|
384
|
+
// that the rendered lines align with the world-unit bounding box dimensions above.
|
|
385
|
+
const resolvedFontSizePx = Math.max(1, text.fontSize * (4 / 3) * (text.scaleFactor || 1) / scale);
|
|
386
|
+
const lineHeight = resolvedFontSizePx * 1.2;
|
|
387
|
+
const startY = resolvedFontSizePx;
|
|
378
388
|
const bgRect = bgColor && bgColor !== 'transparent'
|
|
379
389
|
? `<rect x="0" y="0" width="${width}" height="${height}" fill="${bgColor}"/>`
|
|
380
390
|
: '';
|
|
@@ -386,7 +396,7 @@ export class KritzelSvgExportHelper {
|
|
|
386
396
|
.join('');
|
|
387
397
|
return `<g transform="${transform}"${opacity}>
|
|
388
398
|
${bgRect}
|
|
389
|
-
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${
|
|
399
|
+
<text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
|
|
390
400
|
</g>`;
|
|
391
401
|
}
|
|
392
402
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export class ThemeHelper {
|
|
2
|
+
static appliedVariableNames = new WeakMap();
|
|
2
3
|
/**
|
|
3
4
|
* Converts a camelCase string to kebab-case.
|
|
4
5
|
* @example ThemeHelper.camelToKebab('controlHoverBackgroundColor') → 'control-hover-background-color'
|
|
@@ -64,6 +65,13 @@ export class ThemeHelper {
|
|
|
64
65
|
*/
|
|
65
66
|
static applyThemeToElement(element, theme) {
|
|
66
67
|
const variables = ThemeHelper.flattenThemeToVariables(theme);
|
|
68
|
+
const previousVariableNames = ThemeHelper.appliedVariableNames.get(element);
|
|
69
|
+
for (const name of previousVariableNames ?? []) {
|
|
70
|
+
if (!variables.has(name)) {
|
|
71
|
+
element.style.removeProperty(name);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
67
74
|
ThemeHelper.applyVariablesToElement(element, variables);
|
|
75
|
+
ThemeHelper.appliedVariableNames.set(element, new Set(variables.keys()));
|
|
68
76
|
}
|
|
69
77
|
}
|
|
@@ -131,7 +131,9 @@ export const darkTheme = {
|
|
|
131
131
|
},
|
|
132
132
|
snap: {
|
|
133
133
|
indicatorFill: 'rgba(10, 132, 255, 0.35)',
|
|
134
|
+
indicatorFillInactive: 'rgba(10, 132, 255, 0.2)',
|
|
134
135
|
indicatorStroke: '#0A84FF',
|
|
136
|
+
indicatorStrokeInactive: 'rgba(255, 255, 255, 0.45)',
|
|
135
137
|
lineStroke: 'rgba(255, 255, 255, 0.35)',
|
|
136
138
|
},
|
|
137
139
|
fontSize: {
|
|
@@ -132,7 +132,9 @@ export const lightTheme = {
|
|
|
132
132
|
},
|
|
133
133
|
snap: {
|
|
134
134
|
indicatorFill: 'rgba(59, 130, 246, 0.3)',
|
|
135
|
+
indicatorFillInactive: 'rgba(59, 130, 246, 0.18)',
|
|
135
136
|
indicatorStroke: '#007bff',
|
|
137
|
+
indicatorStrokeInactive: 'rgba(59, 130, 246, 0.5)',
|
|
136
138
|
lineStroke: 'rgba(0, 0, 0, 0.2)',
|
|
137
139
|
},
|
|
138
140
|
fontSize: {
|
package/dist/components/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
export { g as getAssetPath, r as render, s as setAssetPath, a as setNonce, b as setPlatformOptions } from './p-B43upypT.js';
|
|
2
|
-
export { K as KritzelBaseObject, b as KritzelLine, a as KritzelPath } from './p-
|
|
3
|
-
export { u as APP_STATE_MIGRATIONS, A as AssetNotFoundError, D as DE_LOCALE, E as EN_LOCALE, F as FR_LOCALE, I as IndexedDBAssetProvider, s as KritzelAlignment, o as KritzelAnchorManager, n as KritzelAssetResolver, e as KritzelBaseTool, f as KritzelBrushTool, l as KritzelCursorHelper, d as KritzelCustomElement, r as KritzelCustomElementRendererRegistry, h as KritzelEraserTool, b as KritzelGroup, a as KritzelImage, i as KritzelImageTool, q as KritzelLicenseManager, g as KritzelLineTool, p as KritzelLocalizationManager, m as KritzelSelectionTool, c as KritzelShape, k as KritzelShapeTool, K as KritzelText, j as KritzelTextTool, S as ShapeType, W as WORKSPACE_MIGRATIONS, t as runMigrations } from './p-
|
|
2
|
+
export { K as KritzelBaseObject, b as KritzelLine, a as KritzelPath } from './p-0H4HOJjy.js';
|
|
3
|
+
export { u as APP_STATE_MIGRATIONS, A as AssetNotFoundError, D as DE_LOCALE, E as EN_LOCALE, F as FR_LOCALE, I as IndexedDBAssetProvider, s as KritzelAlignment, o as KritzelAnchorManager, n as KritzelAssetResolver, e as KritzelBaseTool, f as KritzelBrushTool, l as KritzelCursorHelper, d as KritzelCustomElement, r as KritzelCustomElementRendererRegistry, h as KritzelEraserTool, b as KritzelGroup, a as KritzelImage, i as KritzelImageTool, q as KritzelLicenseManager, g as KritzelLineTool, p as KritzelLocalizationManager, m as KritzelSelectionTool, c as KritzelShape, k as KritzelShapeTool, K as KritzelText, j as KritzelTextTool, S as ShapeType, W as WORKSPACE_MIGRATIONS, t as runMigrations } from './p-D8bHNNEm.js';
|
|
4
4
|
import * as Y from 'yjs';
|
|
5
5
|
import { IndexeddbPersistence } from 'y-indexeddb';
|
|
6
6
|
import { WebsocketProvider } from 'y-websocket';
|
|
7
7
|
import { H as HocuspocusProvider, a as HocuspocusProviderWebsocket } from './kritzel-editor.js';
|
|
8
8
|
export { d as DEFAULT_ASSET_STORAGE_CONFIG, D as DEFAULT_BRUSH_CONFIG, c as DEFAULT_LINE_TOOL_CONFIG, b as DEFAULT_TEXT_CONFIG, KritzelEditor, defineCustomElement as defineCustomElementKritzelEditor } from './kritzel-editor.js';
|
|
9
9
|
export { K as KritzelWorkspace, W as WORKSPACE_EXPORT_VERSION } from './p-DAwPPDMS.js';
|
|
10
|
-
export { K as KritzelThemeManager, d as darkTheme, l as lightTheme } from './p-
|
|
10
|
+
export { K as KritzelThemeManager, d as darkTheme, l as lightTheme } from './p-CURiiQfq.js';
|
|
11
11
|
export { K as KritzelFontRegistry } from './p-DJkKlUyZ.js';
|
|
12
12
|
export { C as CURRENT_APP_STATE_SCHEMA_VERSION, a as CURRENT_WORKSPACE_SCHEMA_VERSION } from './p-CW-VyJgK.js';
|
|
13
13
|
export { KritzelActiveUsers, defineCustomElement as defineCustomElementKritzelActiveUsers } from './kritzel-active-users.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as KritzelAwarenessCursors$1, d as defineCustomElement$1 } from './p-
|
|
1
|
+
import { c as KritzelAwarenessCursors$1, d as defineCustomElement$1 } from './p-0H4HOJjy.js';
|
|
2
2
|
|
|
3
3
|
const KritzelAwarenessCursors = KritzelAwarenessCursors$1;
|
|
4
4
|
const defineCustomElement = defineCustomElement$1;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { K as KritzelColorPalette$1, d as defineCustomElement$1 } from './p-
|
|
1
|
+
import { K as KritzelColorPalette$1, d as defineCustomElement$1 } from './p-9m1cAVwG.js';
|
|
2
2
|
|
|
3
3
|
const KritzelColorPalette = KritzelColorPalette$1;
|
|
4
4
|
const defineCustomElement = defineCustomElement$1;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { K as KritzelColorComponent, d as defineCustomElement$1 } from './p-
|
|
1
|
+
import { K as KritzelColorComponent, d as defineCustomElement$1 } from './p-CMZ09rB1.js';
|
|
2
2
|
|
|
3
3
|
const KritzelColor = KritzelColorComponent;
|
|
4
4
|
const defineCustomElement = defineCustomElement$1;
|