kritzel-stencil 0.4.6 → 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.
Files changed (150) hide show
  1. package/dist/cjs/index.cjs.js +1 -1
  2. package/dist/cjs/kritzel-active-users_47.cjs.entry.js +140 -101
  3. package/dist/cjs/loader.cjs.js +1 -1
  4. package/dist/cjs/{schema.constants-C8hqt--r.js → schema.constants-gDeS7USU.js} +75 -7
  5. package/dist/cjs/stencil.cjs.js +1 -1
  6. package/dist/collection/classes/core/core.class.js +4 -5
  7. package/dist/collection/classes/handlers/line-handle.handler.js +1 -1
  8. package/dist/collection/classes/managers/license.manager.js +56 -0
  9. package/dist/collection/classes/objects/line.class.js +1 -1
  10. package/dist/collection/classes/objects/shape.class.js +3 -3
  11. package/dist/collection/classes/objects/text.class.js +1 -1
  12. package/dist/collection/collection-manifest.json +1 -1
  13. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +31 -8
  14. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +59 -18
  15. package/dist/collection/components/core/kritzel-watermark/kritzel-watermark.js +1 -1
  16. package/dist/collection/components/shared/kritzel-avatar/kritzel-avatar.js +3 -3
  17. package/dist/collection/components/shared/kritzel-button/kritzel-button.js +2 -2
  18. package/dist/collection/components/shared/kritzel-color/kritzel-color.js +2 -2
  19. package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js +1 -1
  20. package/dist/collection/components/shared/kritzel-font/kritzel-font.js +1 -1
  21. package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js +1 -1
  22. package/dist/collection/components/shared/kritzel-input/kritzel-input.js +1 -1
  23. package/dist/collection/components/shared/kritzel-master-detail/kritzel-master-detail.js +3 -3
  24. package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js +1 -1
  25. package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js +2 -2
  26. package/dist/collection/components/shared/kritzel-numeric-input/kritzel-numeric-input.js +1 -1
  27. package/dist/collection/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.js +1 -1
  28. package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js +1 -1
  29. package/dist/collection/components/shared/kritzel-slide-toggle/kritzel-slide-toggle.js +1 -1
  30. package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js +1 -1
  31. package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js +1 -1
  32. package/dist/collection/components/shared/kritzel-sync-indicator/kritzel-sync-indicator.js +1 -1
  33. package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js +2 -2
  34. package/dist/collection/components/ui/kritzel-back-to-content/kritzel-back-to-content.js +1 -1
  35. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +6 -6
  36. package/dist/collection/components/ui/kritzel-current-user/kritzel-current-user.js +1 -1
  37. package/dist/collection/components/ui/kritzel-current-user-dialog/kritzel-current-user-dialog.js +1 -1
  38. package/dist/collection/components/ui/kritzel-export/kritzel-export.js +1 -1
  39. package/dist/collection/components/ui/kritzel-loading-overlay/kritzel-loading-overlay.js +1 -1
  40. package/dist/collection/components/ui/kritzel-login-dialog/kritzel-login-dialog.js +1 -1
  41. package/dist/collection/components/ui/kritzel-more-menu/kritzel-more-menu.js +1 -1
  42. package/dist/collection/components/ui/kritzel-settings/kritzel-settings.css +8 -0
  43. package/dist/collection/components/ui/kritzel-settings/kritzel-settings.js +2 -15
  44. package/dist/collection/components/ui/kritzel-share-dialog/kritzel-share-dialog.js +2 -2
  45. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js +1 -1
  46. package/dist/collection/components/ui/kritzel-zoom-panel/kritzel-zoom-panel.js +1 -1
  47. package/dist/collection/constants/license.constants.js +1 -1
  48. package/dist/collection/constants/version.js +1 -1
  49. package/dist/collection/helpers/svg-export.helper.js +19 -9
  50. package/dist/collection/helpers/theme.helper.js +8 -0
  51. package/dist/collection/index.js +1 -0
  52. package/dist/collection/interfaces/context-menu-state.interface.js +1 -0
  53. package/dist/collection/themes/dark-theme.js +2 -0
  54. package/dist/collection/themes/light-theme.js +2 -0
  55. package/dist/components/index.js +3 -3
  56. package/dist/components/kritzel-active-users.js +1 -1
  57. package/dist/components/kritzel-avatar.js +1 -1
  58. package/dist/components/kritzel-awareness-cursors.js +1 -1
  59. package/dist/components/kritzel-back-to-content.js +1 -1
  60. package/dist/components/kritzel-button.js +1 -1
  61. package/dist/components/kritzel-color-palette.js +1 -1
  62. package/dist/components/kritzel-color.js +1 -1
  63. package/dist/components/kritzel-controls.js +1 -1
  64. package/dist/components/kritzel-current-user-dialog.js +1 -1
  65. package/dist/components/kritzel-current-user.js +1 -1
  66. package/dist/components/kritzel-editor.js +67 -44
  67. package/dist/components/kritzel-engine.js +1 -1
  68. package/dist/components/kritzel-export.js +1 -1
  69. package/dist/components/kritzel-font-size.js +1 -1
  70. package/dist/components/kritzel-font.js +1 -1
  71. package/dist/components/kritzel-input.js +1 -1
  72. package/dist/components/kritzel-loading-overlay.js +1 -1
  73. package/dist/components/kritzel-login-dialog.js +1 -1
  74. package/dist/components/kritzel-master-detail.js +1 -1
  75. package/dist/components/kritzel-menu-item.js +1 -1
  76. package/dist/components/kritzel-menu.js +1 -1
  77. package/dist/components/kritzel-more-menu.js +1 -1
  78. package/dist/components/kritzel-numeric-input.js +1 -1
  79. package/dist/components/kritzel-opacity-slider.js +1 -1
  80. package/dist/components/kritzel-portal.js +1 -1
  81. package/dist/components/kritzel-settings.js +1 -1
  82. package/dist/components/kritzel-share-dialog.js +1 -1
  83. package/dist/components/kritzel-slide-toggle.js +1 -1
  84. package/dist/components/kritzel-split-button.js +1 -1
  85. package/dist/components/kritzel-stroke-size.js +1 -1
  86. package/dist/components/kritzel-sync-indicator.js +1 -1
  87. package/dist/components/kritzel-tool-config.js +1 -1
  88. package/dist/components/kritzel-tooltip.js +1 -1
  89. package/dist/components/kritzel-utility-panel.js +1 -1
  90. package/dist/components/kritzel-watermark.js +1 -1
  91. package/dist/components/kritzel-workspace-manager.js +1 -1
  92. package/dist/components/kritzel-zoom-panel.js +1 -1
  93. package/dist/components/{p-Ka7OWbnk.js → p-0H4HOJjy.js} +2 -2
  94. package/dist/components/{p-B5oHmPJb.js → p-7Rt7ml3v.js} +1 -1
  95. package/dist/components/{p-BI2ng9I_.js → p-8xkoVMfO.js} +2 -2
  96. package/dist/components/{p-Cymum41a.js → p-9m1cAVwG.js} +3 -3
  97. package/dist/components/{p-CwJwsRR3.js → p-BKOsmXB5.js} +4 -4
  98. package/dist/components/{p-Ca-igU1f.js → p-BLOPBDUF.js} +1 -1
  99. package/dist/components/{p-DUYmwrWV.js → p-BMRln59F.js} +3 -3
  100. package/dist/components/{p-DIazmg6w.js → p-BO9BvTtK.js} +2 -2
  101. package/dist/components/{p-D3y_Hauo.js → p-BU-FZuj0.js} +3 -3
  102. package/dist/components/{p-DgJ0ufzr.js → p-BVEGQLBD.js} +1 -1
  103. package/dist/components/{p-Dlp84thc.js → p-BYO6pz8T.js} +1 -1
  104. package/dist/components/{p-JYj3Facr.js → p-BknTMcbz.js} +16 -16
  105. package/dist/components/{p-CWRSGYOE.js → p-BzJEwFtn.js} +1 -1
  106. package/dist/components/{p-B6t5q-V4.js → p-BzrxIesp.js} +1 -1
  107. package/dist/components/{p-894OnDQV.js → p-CM1duewg.js} +1 -1
  108. package/dist/components/{p-CqLgB8JK.js → p-CMZ09rB1.js} +3 -3
  109. package/dist/components/{p-e6Zpc9Vp.js → p-COjsYPir.js} +2 -2
  110. package/dist/components/{p-BmyTdQGy.js → p-CURiiQfq.js} +12 -0
  111. package/dist/components/{p-BsANVili.js → p-CVhcOiEA.js} +3 -3
  112. package/dist/components/{p-D82VaHce.js → p-Ckm1Aq0V.js} +2 -2
  113. package/dist/components/{p-C38P-Vd0.js → p-Cr2z2UBL.js} +7 -7
  114. package/dist/components/{p-PSFAfAyd.js → p-CwuGA058.js} +1 -1
  115. package/dist/components/{p-Cr682JI_.js → p-D8TOEhPY.js} +3 -3
  116. package/dist/components/{p-BBmP8lVY.js → p-D8bHNNEm.js} +129 -49
  117. package/dist/components/{p-ClFprFvz.js → p-DDbO5q-e.js} +3 -3
  118. package/dist/components/{p-BDzlx2hB.js → p-DIMNEOTW.js} +1 -1
  119. package/dist/components/{p-C4NrrUfN.js → p-DSOc0eIT.js} +1 -1
  120. package/dist/components/{p-D5jf8wAu.js → p-DXcjIb_a.js} +3 -3
  121. package/dist/components/{p-Ch42cOeY.js → p-DgA865Tp.js} +8 -21
  122. package/dist/components/{p-B8Xi4Clg.js → p-DgnK50xO.js} +1 -1
  123. package/dist/components/{p-D30zs0kA.js → p-DkY7pIg5.js} +3 -3
  124. package/dist/components/{p-BTzlrIxe.js → p-DrQRChp3.js} +2 -2
  125. package/dist/components/{p-CsvMgk_f.js → p-DwY5pghH.js} +1 -1
  126. package/dist/components/{p-DkUb2czk.js → p-OLfoATNk.js} +1 -1
  127. package/dist/components/{p-DEBwmRTC.js → p-oGAPPwAL.js} +2 -2
  128. package/dist/components/{p-DJ88BrIW.js → p-yD_3Z3K1.js} +1 -1
  129. package/dist/esm/index.js +2 -2
  130. package/dist/esm/kritzel-active-users_47.entry.js +140 -101
  131. package/dist/esm/loader.js +1 -1
  132. package/dist/esm/{schema.constants-uC7_X6yr.js → schema.constants-Rpm1NA9u.js} +75 -7
  133. package/dist/esm/stencil.js +1 -1
  134. package/dist/stencil/index.esm.js +2 -2
  135. package/dist/stencil/{p-5b969a42.entry.js → p-8c1b7b08.entry.js} +140 -101
  136. package/dist/stencil/{p-uC7_X6yr.js → p-Rpm1NA9u.js} +75 -7
  137. package/dist/stencil/stencil.esm.js +1 -1
  138. package/dist/types/classes/core/core.class.d.ts +2 -2
  139. package/dist/types/classes/managers/license.manager.d.ts +6 -0
  140. package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +4 -0
  141. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +4 -1
  142. package/dist/types/components.d.ts +7 -0
  143. package/dist/types/constants/license.constants.d.ts +1 -1
  144. package/dist/types/constants/version.d.ts +1 -1
  145. package/dist/types/helpers/theme.helper.d.ts +1 -0
  146. package/dist/types/index.d.ts +1 -0
  147. package/dist/types/interfaces/context-menu-state.interface.d.ts +16 -0
  148. package/dist/types/interfaces/theme.interface.d.ts +2 -0
  149. package/package.json +1 -1
  150. package/readme.md +3 -3
@@ -1,20 +1,19 @@
1
1
  import { p as proxyCustomElement, H, c as createEvent, h, d as Host, t as transformTag } from './p-B43upypT.js';
2
2
  import { a as KritzelMouseButton, d as defineCustomElement$5 } from './p-Cm33td2O.js';
3
- import { K as KritzelBaseObject, e as KritzelMathHelper, f as KritzelGeometryHelper, a as KritzelPath, b as KritzelLine, d as defineCustomElement$7 } from './p-Ka7OWbnk.js';
3
+ import { K as KritzelBaseObject, e as KritzelMathHelper, f as KritzelGeometryHelper, a as KritzelPath, b as KritzelLine, d as defineCustomElement$6 } from './p-0H4HOJjy.js';
4
4
  import { c as commonjsGlobal } from './p-BFTU3MAI.js';
5
- import { a as KritzelColorHelper, D as DEFAULT_COLOR_PALETTE, K as KritzelThemeManager } from './p-BmyTdQGy.js';
5
+ import { a as KritzelColorHelper, D as DEFAULT_COLOR_PALETTE, K as KritzelThemeManager } from './p-CURiiQfq.js';
6
6
  import { K as KritzelDevicesHelper } from './p-jGOpkGDl.js';
7
7
  import { K as KritzelFontRegistry, r as resolveTextToolAvailableFonts } from './p-DJkKlUyZ.js';
8
- import { A as ABSOLUTE_SCALE_MAX, a as ABSOLUTE_SCALE_MIN, d as defineCustomElement$1 } from './p-PSFAfAyd.js';
8
+ import { A as ABSOLUTE_SCALE_MAX, a as ABSOLUTE_SCALE_MIN, d as defineCustomElement$1 } from './p-CwuGA058.js';
9
9
  import { K as KritzelWorkspace, W as WORKSPACE_EXPORT_VERSION } from './p-DAwPPDMS.js';
10
10
  import { K as KritzelHTMLHelper } from './p-WUdQqYnu.js';
11
- import { K as KritzelContextMenu, d as defineCustomElement$6 } from './p-BxpKq94F.js';
12
11
  import { O as ObjectHelper } from './p-Dd-pMvlr.js';
13
12
  import * as Y from 'yjs';
14
13
  import { a as CURRENT_WORKSPACE_SCHEMA_VERSION, C as CURRENT_APP_STATE_SCHEMA_VERSION } from './p-CW-VyJgK.js';
15
14
  import { K as KritzelIconRegistry, d as defineCustomElement$4 } from './p-CdR76C4L.js';
16
- import { d as defineCustomElement$3 } from './p-DgJ0ufzr.js';
17
- import { d as defineCustomElement$2 } from './p-894OnDQV.js';
15
+ import { d as defineCustomElement$3 } from './p-BVEGQLBD.js';
16
+ import { d as defineCustomElement$2 } from './p-CM1duewg.js';
18
17
 
19
18
  class KritzelKeyboardHelper {
20
19
  static forceHideKeyboard() {
@@ -13878,7 +13877,7 @@ class KritzelText extends KritzelBaseObject {
13878
13877
  }
13879
13878
  element.style.fontFamily = KritzelFontRegistry.resolveCssFontFamily(this.fontFamily);
13880
13879
  element.style.fontSize = `${this.fontSize}pt`;
13881
- element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
13880
+ element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
13882
13881
  if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
13883
13882
  if (!this._core.store.state.isScaling && !this._core.store.state.isPanning) {
13884
13883
  requestAnimationFrame(() => this.adjustSizeOnInput());
@@ -16220,7 +16219,7 @@ class KritzelShape extends KritzelBaseObject {
16220
16219
  }
16221
16220
  element.style.fontFamily = this.fontFamily;
16222
16221
  element.style.fontSize = `${this.fontSize}pt`;
16223
- element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
16222
+ element.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
16224
16223
  element.style.whiteSpace = 'pre-wrap';
16225
16224
  element.style.wordWrap = 'break-word';
16226
16225
  if (this.editor.dom.parentElement === element) {
@@ -16536,13 +16535,13 @@ class KritzelShape extends KritzelBaseObject {
16536
16535
  this.fontColor = KritzelColorHelper.determineTextColor(this.fillColor);
16537
16536
  // Update the editor's text color immediately
16538
16537
  if (this.editor?.dom?.parentElement) {
16539
- this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
16538
+ this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
16540
16539
  }
16541
16540
  }
16542
16541
  else if (changedProperties.includes('fontColor')) {
16543
16542
  // Also update editor when fontColor changes directly
16544
16543
  if (this.editor?.dom?.parentElement) {
16545
- this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor);
16544
+ this.editor.dom.parentElement.style.color = KritzelColorHelper.resolveThemeColor(this.fontColor, this._core?.themeManager?.currentTheme);
16546
16545
  }
16547
16546
  }
16548
16547
  }
@@ -21165,7 +21164,7 @@ class KritzelLineHandleHandler extends KritzelBaseHandler {
21165
21164
  t: clipInfo?.t,
21166
21165
  edgeX: clipInfo?.edgeX,
21167
21166
  edgeY: clipInfo?.edgeY,
21168
- lineStroke: KritzelColorHelper.resolveThemeColor(line.stroke),
21167
+ lineStroke: KritzelColorHelper.resolveThemeColor(line.stroke, this._core.themeManager.currentTheme),
21169
21168
  lineStrokeWidth: line.strokeWidth / line.scale,
21170
21169
  arrowOffset: endpoint === 'start'
21171
21170
  ? (line.hasStartArrow ? line.getArrowSize('start') / line.scale : undefined)
@@ -23840,7 +23839,7 @@ const KRITZEL_LICENSE_TOKEN_PREFIX = 'KRTZL1.';
23840
23839
  * printed public key here. Replacing this value invalidates every license
23841
23840
  * signed with the previous key.
23842
23841
  */
23843
- const KRITZEL_LICENSE_PUBLIC_KEY = 'I-pYJlxDEjT94rwSaqhXW5Sv__fMKS-JKKnV3pg0PaM';
23842
+ const KRITZEL_LICENSE_PUBLIC_KEY = '2IwZDin-qV3kOt8SEQCqdaJsGT9S7tAGapUYJVnVGQo';
23844
23843
 
23845
23844
  /** Minimum delay (ms) between periodic license re-validations. */
23846
23845
  const MIN_REVALIDATION_DELAY_MS = 30_000;
@@ -24073,8 +24072,64 @@ class KritzelLicenseManager {
24073
24072
  if (typeof claims.exp === 'number' && claims.exp * 1000 <= Date.now()) {
24074
24073
  return { status: 'rejected' }; // Cleanly expired.
24075
24074
  }
24075
+ const allowedDomains = this.normalizeAllowedDomains(claims.allowedDomains);
24076
+ if (allowedDomains === null || allowedDomains.length === 0) {
24077
+ return { status: 'rejected' };
24078
+ }
24079
+ const currentHostname = this.getCurrentHostname();
24080
+ if (!currentHostname || !allowedDomains.includes(currentHostname)) {
24081
+ return { status: 'rejected' };
24082
+ }
24076
24083
  return { status: 'pass', payloadSegment, signatureSegment, claims };
24077
24084
  }
24085
+ /** Returns the normalized current hostname, or null when unavailable/invalid. */
24086
+ getCurrentHostname() {
24087
+ const hostname = globalThis.location?.hostname;
24088
+ if (typeof hostname !== 'string') {
24089
+ return null;
24090
+ }
24091
+ return this.normalizeDomain(hostname);
24092
+ }
24093
+ /** Normalizes and validates the allowed domains claim. */
24094
+ normalizeAllowedDomains(domains) {
24095
+ if (!Array.isArray(domains)) {
24096
+ return null;
24097
+ }
24098
+ const normalized = new Set();
24099
+ for (const entry of domains) {
24100
+ if (typeof entry !== 'string') {
24101
+ return null;
24102
+ }
24103
+ const domain = this.normalizeDomain(entry);
24104
+ if (!domain) {
24105
+ return null;
24106
+ }
24107
+ normalized.add(domain);
24108
+ }
24109
+ return Array.from(normalized);
24110
+ }
24111
+ /** Normalizes a domain and rejects malformed hostnames. */
24112
+ normalizeDomain(value) {
24113
+ const trimmed = value.trim().toLowerCase();
24114
+ if (trimmed.length === 0) {
24115
+ return null;
24116
+ }
24117
+ const withoutTrailingDot = trimmed.endsWith('.') ? trimmed.slice(0, -1) : trimmed;
24118
+ if (withoutTrailingDot.length === 0) {
24119
+ return null;
24120
+ }
24121
+ try {
24122
+ const parsed = new URL(`https://${withoutTrailingDot}`);
24123
+ const normalizedHostname = parsed.hostname.toLowerCase();
24124
+ if (normalizedHostname !== withoutTrailingDot) {
24125
+ return null;
24126
+ }
24127
+ return normalizedHostname;
24128
+ }
24129
+ catch {
24130
+ return null;
24131
+ }
24132
+ }
24078
24133
  /**
24079
24134
  * Verifies the Ed25519 signature of the token against the embedded public
24080
24135
  * key. Resolves true/false for a definitive valid/invalid signature.
@@ -46669,13 +46724,13 @@ class KritzelCore {
46669
46724
  }
46670
46725
  /**
46671
46726
  * Selects all objects in the workspace.
46672
- * Excludes selection-related and context menu objects.
46727
+ * Excludes selection-related objects.
46673
46728
  * Switches to selection tool.
46674
46729
  */
46675
46730
  selectAllObjects() {
46676
46731
  const allObjects = this._store.objects
46677
46732
  .allObjects()
46678
- .filter(o => !(o instanceof KritzelSelectionGroup) && !(o instanceof KritzelSelectionBox) && !(o instanceof KritzelContextMenu));
46733
+ .filter(o => !(o instanceof KritzelSelectionGroup) && !(o instanceof KritzelSelectionBox));
46679
46734
  if (allObjects.length > 0) {
46680
46735
  const selectionGroup = KritzelSelectionGroup.create(this);
46681
46736
  allObjects.forEach(obj => {
@@ -46694,7 +46749,7 @@ class KritzelCore {
46694
46749
  }
46695
46750
  /**
46696
46751
  * Selects all objects currently visible in the viewport.
46697
- * Excludes selection-related and context menu objects.
46752
+ * Excludes selection-related objects.
46698
46753
  * Switches to selection tool.
46699
46754
  */
46700
46755
  selectAllObjectsInViewport() {
@@ -46709,7 +46764,7 @@ class KritzelCore {
46709
46764
  const objectsInViewport = this._store.objects
46710
46765
  .query(viewportBounds)
46711
46766
  .filter(o => o.isInViewport())
46712
- .filter(o => !(o instanceof KritzelSelectionGroup) && !(o instanceof KritzelSelectionBox) && !(o instanceof KritzelContextMenu));
46767
+ .filter(o => !(o instanceof KritzelSelectionGroup) && !(o instanceof KritzelSelectionBox));
46713
46768
  if (objectsInViewport.length > 0) {
46714
46769
  const selectionGroup = KritzelSelectionGroup.create(this);
46715
46770
  objectsInViewport.forEach(obj => {
@@ -47292,14 +47347,20 @@ class KritzelSvgExportHelper {
47292
47347
  const scale = this.getObjectScale(text);
47293
47348
  // Convert ProseMirror content to HTML
47294
47349
  const htmlContent = this.prosemirrorToHtml(text.content, text, theme);
47295
- // Calculate dimensions accounting for scale
47350
+ // Calculate dimensions in SVG world units (world units = CSS px in a 1:1 SVG).
47296
47351
  const width = text.totalWidth / scale;
47297
47352
  const height = text.totalHeight / scale;
47353
+ // Convert the font size from pt to SVG world units (px equivalent).
47354
+ // text.fontSize is stored in CSS pt; 1 pt = 4/3 px at 96 dpi.
47355
+ // We also bake in scaleFactor (user resize) and divide by the object scale so
47356
+ // that the rendered font aligns with the world-unit dimensions above.
47357
+ // The CSS transform: scale(scaleFactor) is removed from the div because the
47358
+ // adjusted font-size already accounts for it – keeping both would double-scale
47359
+ // the content and overflow the foreignObject.
47360
+ const svgFontSizePx = (text.fontSize * (4 / 3) * (text.scaleFactor || 1) / scale).toFixed(4);
47298
47361
  return `<g transform="${transform}"${opacity}>
47299
- <foreignObject x="0" y="0" width="${width}" height="${height}">
47300
- <div xmlns="http://www.w3.org/1999/xhtml" style="font-family: ${text.fontFamily}; font-size: ${text.fontSize}pt; color: ${fontColor}; background-color: ${bgColor || 'transparent'}; transform: scale(${text.scaleFactor}); transform-origin: top left; white-space: pre-wrap; word-wrap: break-word;">
47301
- ${htmlContent}
47302
- </div>
47362
+ <foreignObject x="0" y="0" width="${width}" height="${height}" overflow="visible">
47363
+ <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>
47303
47364
  </foreignObject>
47304
47365
  </g>`;
47305
47366
  }
@@ -47318,9 +47379,13 @@ class KritzelSvgExportHelper {
47318
47379
  const height = text.totalHeight / scale;
47319
47380
  const lines = this.prosemirrorToPlainTextLines(text.content);
47320
47381
  const resolvedLines = lines.length > 0 ? lines : [''];
47321
- const resolvedFontSize = Math.max(1, text.fontSize * (text.scaleFactor || 1));
47322
- const lineHeight = resolvedFontSize * 1.2;
47323
- const startY = resolvedFontSize;
47382
+ // Convert the font size from pt to SVG world units (px equivalent).
47383
+ // text.fontSize is stored in CSS pt; 1 pt = 4/3 px at 96 dpi.
47384
+ // We also bake in scaleFactor (user resize) and divide by the object scale so
47385
+ // that the rendered lines align with the world-unit bounding box dimensions above.
47386
+ const resolvedFontSizePx = Math.max(1, text.fontSize * (4 / 3) * (text.scaleFactor || 1) / scale);
47387
+ const lineHeight = resolvedFontSizePx * 1.2;
47388
+ const startY = resolvedFontSizePx;
47324
47389
  const bgRect = bgColor && bgColor !== 'transparent'
47325
47390
  ? `<rect x="0" y="0" width="${width}" height="${height}" fill="${bgColor}"/>`
47326
47391
  : '';
@@ -47332,7 +47397,7 @@ class KritzelSvgExportHelper {
47332
47397
  .join('');
47333
47398
  return `<g transform="${transform}"${opacity}>
47334
47399
  ${bgRect}
47335
- <text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSize}" fill="${fontColor}">${tspans}</text>
47400
+ <text font-family="${this.escapeHtml(text.fontFamily)}" font-size="${resolvedFontSizePx}" fill="${fontColor}">${tspans}</text>
47336
47401
  </g>`;
47337
47402
  }
47338
47403
  /**
@@ -48810,6 +48875,8 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
48810
48875
  awarenessChange;
48811
48876
  /** Emitted when notifications change. */
48812
48877
  notificationsChange;
48878
+ /** Emitted when context-menu visibility, items, or position changes. */
48879
+ contextMenuStateChange;
48813
48880
  /** Emitted when the combined loading state (external `isLoading` prop or internal workspace loading) changes. */
48814
48881
  loadingChange;
48815
48882
  /** Emitted when remote workspace synchronization is in progress. */
@@ -49002,6 +49069,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
49002
49069
  }
49003
49070
  handleLongPress(ev) {
49004
49071
  this.contextMenuHandler.handleContextMenu(ev.detail);
49072
+ this.emitContextMenuStateChange();
49005
49073
  }
49006
49074
  handleContextMenu(ev) {
49007
49075
  if (ev.cancelable) {
@@ -49014,6 +49082,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
49014
49082
  return;
49015
49083
  }
49016
49084
  this.contextMenuHandler.handleContextMenu(ev);
49085
+ this.emitContextMenuStateChange();
49017
49086
  }
49018
49087
  handleResize() {
49019
49088
  this.viewport.handleResize();
@@ -49255,6 +49324,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
49255
49324
  this.core.store.objects?.clearLocalSelectionBox();
49256
49325
  this.core.store.state.isSelecting = false;
49257
49326
  this.core.store.state.isEnabled = true;
49327
+ this.emitContextMenuStateChange();
49258
49328
  this.core.rerender();
49259
49329
  }
49260
49330
  /**
@@ -49268,6 +49338,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
49268
49338
  */
49269
49339
  async openContextMenu(options) {
49270
49340
  this.contextMenuHandler.open(options);
49341
+ this.emitContextMenuStateChange();
49271
49342
  }
49272
49343
  /**
49273
49344
  * Retrieves a canvas object by its unique ID.
@@ -50385,7 +50456,6 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
50385
50456
  viewport;
50386
50457
  contextMenuHandler;
50387
50458
  keyHandler;
50388
- contextMenuElement = null;
50389
50459
  _lastHadSelectionGroup = false;
50390
50460
  _isViewportReady = false;
50391
50461
  _isYjsInitialized = false;
@@ -50424,6 +50494,22 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
50424
50494
  this.isSyncing = isSyncing;
50425
50495
  this.syncingChange.emit(isSyncing);
50426
50496
  }
50497
+ emitContextMenuStateChange() {
50498
+ this.contextMenuStateChange.emit({
50499
+ isVisible: this.core.store.state.isContextMenuVisible,
50500
+ isObjectMenu: !!this.core.store.selectionGroup,
50501
+ items: this.core.store.state.contextMenuItems,
50502
+ objects: this.core.store.selectionGroup?.objects || [],
50503
+ position: {
50504
+ x: this.core.store.state.contextMenuX,
50505
+ y: this.core.store.state.contextMenuY,
50506
+ },
50507
+ worldPosition: {
50508
+ x: this.core.store.state.contextMenuWorldX,
50509
+ y: this.core.store.state.contextMenuWorldY,
50510
+ },
50511
+ });
50512
+ }
50427
50513
  applyToolConfig(tool, toolConfig) {
50428
50514
  const normalizedToolConfig = this.normalizeToolConfig(toolConfig);
50429
50515
  Object.entries(normalizedToolConfig).forEach(([key, value]) => {
@@ -50512,6 +50598,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
50512
50598
  this.viewportChange = createEvent(this, "viewportChange");
50513
50599
  this.awarenessChange = createEvent(this, "awarenessChange");
50514
50600
  this.notificationsChange = createEvent(this, "notificationsChange");
50601
+ this.contextMenuStateChange = createEvent(this, "contextMenuStateChange");
50515
50602
  this.loadingChange = createEvent(this, "loadingChange");
50516
50603
  this.syncingChange = createEvent(this, "syncingChange");
50517
50604
  this.core = new KritzelCore(this);
@@ -50566,6 +50653,10 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
50566
50653
  this.core.store.state.viewportBoundaryRight = this.viewportBoundaryRight;
50567
50654
  this.core.store.state.viewportBoundaryTop = this.viewportBoundaryTop;
50568
50655
  this.core.store.state.viewportBoundaryBottom = this.viewportBoundaryBottom;
50656
+ if (this.debugInfo) {
50657
+ this.core.store.state.debugInfo = this.debugInfo;
50658
+ this.core.assetResolver.setShowInfo(this.debugInfo.showAssetResolverInfo);
50659
+ }
50569
50660
  this._isWorkspaceLoading = true;
50570
50661
  this.syncLoadingState();
50571
50662
  }
@@ -50969,7 +51060,9 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
50969
51060
  this.emitObjectsInViewportChange();
50970
51061
  }
50971
51062
  }
50972
- 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" }, 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: {
51063
+ 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: {
51064
+ color: 'var(--kritzel-global-text-primary)',
51065
+ } }, 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: {
50973
51066
  transform: `matrix(${this.core.store.state?.scale}, 0, 0, ${this.core.store.state?.scale}, ${this.core.store.state?.translateX}, ${this.core.store.state?.translateY})`,
50974
51067
  opacity: this._sceneBootstrapOpacity.toString(),
50975
51068
  transition: this._sceneBootstrapTransitionEnabled ? 'opacity 220ms ease-out' : 'none',
@@ -51152,6 +51245,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
51152
51245
  left: `${object.totalWidth}px`,
51153
51246
  top: '0',
51154
51247
  zIndex: (object.zIndex + 2).toString(),
51248
+ color: 'var(--kritzel-global-text-primary)',
51155
51249
  } }, 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)) &&
51156
51250
  (() => {
51157
51251
  const isSelectionGroup = KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup');
@@ -51352,8 +51446,12 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
51352
51446
  strokeDasharray: data.dashArray,
51353
51447
  strokeLinecap: 'round',
51354
51448
  } }))), h("circle", { cx: data.centerX, cy: data.centerY, r: data.indicatorRadius, style: {
51355
- fill: isActiveSnap ? 'var(--kritzel-snap-indicator-fill, rgba(59, 130, 246, 0.3))' : 'rgba(59, 130, 246, 0.18)',
51356
- stroke: isActiveSnap ? 'var(--kritzel-snap-indicator-stroke, #007bff)' : 'rgba(59, 130, 246, 0.5)',
51449
+ fill: isActiveSnap
51450
+ ? 'var(--kritzel-snap-indicator-fill, rgba(59, 130, 246, 0.3))'
51451
+ : 'var(--kritzel-snap-indicator-fill-inactive, var(--kritzel-snap-indicator-fill, rgba(59, 130, 246, 0.18)))',
51452
+ stroke: isActiveSnap
51453
+ ? 'var(--kritzel-snap-indicator-stroke, #007bff)'
51454
+ : 'var(--kritzel-snap-indicator-stroke-inactive, var(--kritzel-snap-indicator-stroke, rgba(59, 130, 246, 0.5)))',
51357
51455
  strokeWidth: data.indicatorStrokeWidth,
51358
51456
  } }))));
51359
51457
  })(), (() => {
@@ -51400,20 +51498,7 @@ const KritzelEngine = /*@__PURE__*/ proxyCustomElement(class KritzelEngine exten
51400
51498
  stroke: 'var(--kritzel-snap-indicator-stroke, #007bff)',
51401
51499
  strokeWidth: data.indicatorStrokeWidth,
51402
51500
  } })))));
51403
- })()), this.core.store.state.isContextMenuVisible && (h("kritzel-context-menu", { class: "context-menu", ref: el => (this.contextMenuElement = el ?? null), items: this.core.store.state.contextMenuItems, objects: this.core.store.selectionGroup?.objects || [], style: {
51404
- position: 'absolute',
51405
- left: `${this.core.store.state.contextMenuX}px`,
51406
- top: `${this.core.store.state.contextMenuY}px`,
51407
- zIndex: '10002',
51408
- }, onActionSelected: event => {
51409
- if (event.detail.action) {
51410
- event.detail.action({
51411
- x: this.core.store.state.contextMenuWorldX,
51412
- y: this.core.store.state.contextMenuWorldY,
51413
- }, this.core.store.selectionGroup?.objects || []);
51414
- }
51415
- this.hideContextMenu();
51416
- }, onClose: () => this.hideContextMenu() })), this.core.store.objects?.hasAwareness && h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool?.toolType === 'eraser' && !this.core.store.state.isScaling && h("kritzel-cursor-trail", { core: this.core }), !this.core.licenseManager.isLicensed && h("kritzel-watermark", { core: this.core, label: this.core.localizationManager.translate('watermark.poweredBy') })));
51501
+ })()), this.core.store.objects?.hasAwareness && h("kritzel-awareness-cursors", { core: this.core }), this.core.store.state?.activeTool?.toolType === 'eraser' && !this.core.store.state.isScaling && h("kritzel-cursor-trail", { core: this.core }), !this.core.licenseManager.isLicensed && h("kritzel-watermark", { core: this.core, label: this.core.localizationManager.translate('watermark.poweredBy') })));
51417
51502
  }
51418
51503
  static get watchers() { return {
51419
51504
  "workspace": [{
@@ -51678,7 +51763,7 @@ function defineCustomElement() {
51678
51763
  if (typeof customElements === "undefined") {
51679
51764
  return;
51680
51765
  }
51681
- const components = ["kritzel-engine", "kritzel-awareness-cursors", "kritzel-context-menu", "kritzel-cursor-trail", "kritzel-icon", "kritzel-loading-overlay", "kritzel-sync-indicator", "kritzel-watermark"];
51766
+ const components = ["kritzel-engine", "kritzel-awareness-cursors", "kritzel-cursor-trail", "kritzel-icon", "kritzel-loading-overlay", "kritzel-sync-indicator", "kritzel-watermark"];
51682
51767
  components.forEach(tagName => { switch (tagName) {
51683
51768
  case "kritzel-engine":
51684
51769
  if (!customElements.get(transformTag(tagName))) {
@@ -51686,11 +51771,6 @@ function defineCustomElement() {
51686
51771
  }
51687
51772
  break;
51688
51773
  case "kritzel-awareness-cursors":
51689
- if (!customElements.get(transformTag(tagName))) {
51690
- defineCustomElement$7();
51691
- }
51692
- break;
51693
- case "kritzel-context-menu":
51694
51774
  if (!customElements.get(transformTag(tagName))) {
51695
51775
  defineCustomElement$6();
51696
51776
  }
@@ -2,9 +2,9 @@ import { p as proxyCustomElement, H, c as createEvent, h, d as Host, t as transf
2
2
  import { K as KritzelWorkspace } from './p-DAwPPDMS.js';
3
3
  import { O as ObjectHelper } from './p-Dd-pMvlr.js';
4
4
  import { d as defineCustomElement$5 } from './p-CdR76C4L.js';
5
- import { d as defineCustomElement$3, a as defineCustomElement$4 } from './p-CwJwsRR3.js';
6
- import { d as defineCustomElement$2 } from './p-Ca-igU1f.js';
7
- import { d as defineCustomElement$1 } from './p-Cr682JI_.js';
5
+ import { d as defineCustomElement$3, a as defineCustomElement$4 } from './p-BKOsmXB5.js';
6
+ import { d as defineCustomElement$2 } from './p-BLOPBDUF.js';
7
+ import { d as defineCustomElement$1 } from './p-D8TOEhPY.js';
8
8
 
9
9
  const kritzelWorkspaceManagerCss = () => `:host{display:flex;flex-direction:column;z-index:1}.manager{opacity:0;pointer-events:none;transition:opacity 0.2s ease-out}.manager.visible{opacity:1;pointer-events:auto}`;
10
10
 
@@ -97,7 +97,7 @@ const KritzelNumericInput = /*@__PURE__*/ proxyCustomElement(class KritzelNumeri
97
97
  this.valueChange.emit(newValue);
98
98
  };
99
99
  render() {
100
- return (h(Host, { key: 'eb766b22717d856d096bd1a4a44279f6ac994892' }, h("div", { key: '2394e2b2af48f560e77e7a37b34d00656b0dd344', class: "input-container" }, this.label && h("label", { key: 'd8889aa93d4a86fa841f4da1f0b97411ab039cb1', class: "input-label" }, this.label), h("div", { key: 'b55ae2edf164cdfcdda356119b148c8bfb8fbd24', class: "input-wrapper" }, h("input", { key: 'ee1f1663f19c5ca66d64b6c5142005da318e03e4', type: "number", class: "numeric-input", title: "", min: this.min === Number.MIN_SAFE_INTEGER ? undefined : this.min, max: this.max === Number.MAX_SAFE_INTEGER ? undefined : this.max, step: this.step, value: this.inputValue, placeholder: this.placeholder, onInput: this.handleInput, onBlur: this.handleBlur, onKeyDown: this.handleKeyDown, onInvalid: this.handleInvalid }), h("div", { key: '82e127b045e631616e6368c437473bbf9732445d', class: "spinner-buttons" }, h("button", { key: 'e7412dffccbdacbb5743ae2e2e7bd33c68e6fceb', type: "button", class: "spinner-button spinner-up", onClick: this.handleIncrement, tabIndex: -1, "aria-label": "Increase value" }, h("svg", { key: '7e471bf2bee5d4d161fea2e838b26e2f28bb84d9', viewBox: "0 0 10 6", class: "spinner-icon" }, h("path", { key: '69e4c80eed03b2ee2a044d07f35420b7618f4e75', d: "M1 5L5 1L9 5", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))), h("button", { key: 'a0c2350d48c398f7396cebd973438c0e390d0aff', type: "button", class: "spinner-button spinner-down", onClick: this.handleDecrement, tabIndex: -1, "aria-label": "Decrease value" }, h("svg", { key: 'c1f6264d187936d5eb0cc43c0275dc2e2c93b854', viewBox: "0 0 10 6", class: "spinner-icon" }, h("path", { key: 'facbdd171b43868ec41b469b0d11d6c9bfcec3aa', d: "M1 1L5 5L9 1", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))))))));
100
+ return (h(Host, { key: '8901e0b56ccbc344420483a4a56663f7cd74d9e8' }, h("div", { key: '5f3d6b5c56007e11383aa69f60f22031b0e8f332', class: "input-container" }, this.label && h("label", { key: '2cb102a5b6c16d068f4f304fbcc6241f79fc0ce8', class: "input-label" }, this.label), h("div", { key: '96441095acc3d9a8e77b6d2bac2ceda683c9c976', class: "input-wrapper" }, h("input", { key: '523a5485111077e20faded235df6362e5ea9cfd4', type: "number", class: "numeric-input", title: "", min: this.min === Number.MIN_SAFE_INTEGER ? undefined : this.min, max: this.max === Number.MAX_SAFE_INTEGER ? undefined : this.max, step: this.step, value: this.inputValue, placeholder: this.placeholder, onInput: this.handleInput, onBlur: this.handleBlur, onKeyDown: this.handleKeyDown, onInvalid: this.handleInvalid }), h("div", { key: '2071e98125a8d014513e93052bd8c1fee17932a5', class: "spinner-buttons" }, h("button", { key: '12422e5285dfb532dbbb6eb1a36dbcb3de50f2bc', type: "button", class: "spinner-button spinner-up", onClick: this.handleIncrement, tabIndex: -1, "aria-label": "Increase value" }, h("svg", { key: '49ad5625c80fae6706ba4ab91f47bd550481ef74', viewBox: "0 0 10 6", class: "spinner-icon" }, h("path", { key: 'ff7d19b61baeb5ba58bb60f2cc629bcec6eb4411', d: "M1 5L5 1L9 5", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))), h("button", { key: 'e4fec28e4fc997e007127f2b30b00cc752433221', type: "button", class: "spinner-button spinner-down", onClick: this.handleDecrement, tabIndex: -1, "aria-label": "Decrease value" }, h("svg", { key: '27bf06cde8de11f4a97090911afd6b8993463112', viewBox: "0 0 10 6", class: "spinner-icon" }, h("path", { key: 'ed7071dd79bfe509ebb319ce43ecb3e982dd4157', d: "M1 1L5 5L9 1", stroke: "currentColor", "stroke-width": "1.5", fill: "none", "stroke-linecap": "round", "stroke-linejoin": "round" }))))))));
101
101
  }
102
102
  static get watchers() { return {
103
103
  "value": [{
@@ -39,7 +39,7 @@ const KritzelInput = /*@__PURE__*/ proxyCustomElement(class KritzelInput extends
39
39
  this.valueChange.emit(input.value);
40
40
  };
41
41
  render() {
42
- return (h(Host, { key: 'a59aa026922a3267ec7e6177973e80edfa97202c' }, h("div", { key: '46b1f191072bfb2a26579a329f8fd6ec86ca3ef9', class: "input-container" }, this.label && h("label", { key: '5409f811792034be56c3269b31ff374d8ed33de2', class: "input-label" }, this.label), h("div", { key: 'f51219b2a6384aeee63a7c8214821abd853a0ea5', class: { 'input-wrapper': true, 'has-suffix': !!this.suffix } }, h("input", { key: '05c93a526aa2f2d757a7c139fa3a47d84a4e2d95', type: this.type, class: "text-input", value: this.inputValue, placeholder: this.placeholder, disabled: this.disabled, onInput: this.handleInput }), this.suffix && h("span", { key: '91b60b25a7ff750720ff1961e224a035a2d86096', class: "input-suffix" }, this.suffix)))));
42
+ return (h(Host, { key: '46a0a48902a06ad85edcbaad3679ce3fe9ba850c' }, h("div", { key: 'a6beaf920614aa959d2fbd68b7268afba8637358', class: "input-container" }, this.label && h("label", { key: 'ca6d3fb3c22f1540795dbb0695ddd9b87cc05eee', class: "input-label" }, this.label), h("div", { key: '78d116e82531a9cca996d594792245449bcaf9c8', class: { 'input-wrapper': true, 'has-suffix': !!this.suffix } }, h("input", { key: '0d10d6356dea3a11338172bbe8c3c878eefcc708', type: this.type, class: "text-input", value: this.inputValue, placeholder: this.placeholder, disabled: this.disabled, onInput: this.handleInput }), this.suffix && h("span", { key: '0e6166ba8728efc1035302d7fb048306efbe5a68', class: "input-suffix" }, this.suffix)))));
43
43
  }
44
44
  static get watchers() { return {
45
45
  "value": [{
@@ -91,16 +91,16 @@ const KritzelAvatar = /*@__PURE__*/ proxyCustomElement(class KritzelAvatar exten
91
91
  height: `${this.size}px`,
92
92
  fontSize: `${Math.round(this.size * 0.4)}px`,
93
93
  };
94
- return (h(Host, { key: 'a25cae3d0597e53606a00855e3175c89ff90d58e', style: containerStyles, class: {
94
+ return (h(Host, { key: '116725d55e4443e80216b3b3251e957d2009b43e', style: containerStyles, class: {
95
95
  'has-image': !!showImage,
96
96
  'has-initials': !!showInitials,
97
97
  'has-default': !!showDefaultIcon,
98
- }, role: "img", "aria-label": this.getDisplayName() || 'User avatar' }, showImage && (h("img", { key: 'c3288f0ba9e0d8876403244fe3942dd91e685a79', src: imageUrl, alt: "", class: "avatar-image", ref: (el) => {
98
+ }, role: "img", "aria-label": this.getDisplayName() || 'User avatar' }, showImage && (h("img", { key: 'd70ad4eb484404b18c13e066e8c10b3c86918ee5', src: imageUrl, alt: "", class: "avatar-image", ref: (el) => {
99
99
  if (el) {
100
100
  el.referrerPolicy = 'no-referrer';
101
101
  el.crossOrigin = 'anonymous';
102
102
  }
103
- }, onError: this.handleImageError })), showInitials && (h("span", { key: 'ae0ca459b87e90a1f67abe747b75d8dd61247ead', class: "avatar-initials", style: { backgroundColor: this.getBackgroundColor() } }, initials)), showDefaultIcon && (h("span", { key: '2a60a0347ae21732828920339f53803330c9c6c6', class: "avatar-default" }, h("svg", { key: 'ee057dc02ae61206164775b35ad1408fe04dfed9', viewBox: "0 0 24 24", fill: "currentColor" }, h("path", { key: '2190046ba2e2c659d47f8a7f4a12bb10ae626f07', d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" }))))));
103
+ }, onError: this.handleImageError })), showInitials && (h("span", { key: '21a9022cffdb69e0c3626e513cb3c036a9d3a16d', class: "avatar-initials", style: { backgroundColor: this.getBackgroundColor() } }, initials)), showDefaultIcon && (h("span", { key: '43e676af007bf254b1921f3efcbc7fff4e204359', class: "avatar-default" }, h("svg", { key: 'a7378795539a902e28ca644a80f1ca00cc9f818a', viewBox: "0 0 24 24", fill: "currentColor" }, h("path", { key: '31548a495a86f033325c98cfcc0ae398b6bb8281', d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" }))))));
104
104
  }
105
105
  static get watchers() { return {
106
106
  "user": [{
@@ -1,20 +1,20 @@
1
1
  import { p as proxyCustomElement, H, c as createEvent, h, d as Host, t as transformTag } from './p-B43upypT.js';
2
- import { a as CURRENT_WORKSPACE_SCHEMA_VERSION, C as CURRENT_APP_STATE_SCHEMA_VERSION } from './p-CW-VyJgK.js';
2
+ import { C as CURRENT_APP_STATE_SCHEMA_VERSION, a as CURRENT_WORKSPACE_SCHEMA_VERSION } from './p-CW-VyJgK.js';
3
3
  import { d as defineCustomElement$6 } from './p-DX2nriaq.js';
4
4
  import { d as defineCustomElement$5 } from './p-Df3BwVGy.js';
5
5
  import { d as defineCustomElement$4 } from './p-CdR76C4L.js';
6
- import { d as defineCustomElement$3 } from './p-BsANVili.js';
7
- import { d as defineCustomElement$2 } from './p-BDzlx2hB.js';
8
- import { d as defineCustomElement$1 } from './p-CWRSGYOE.js';
6
+ import { d as defineCustomElement$3 } from './p-CVhcOiEA.js';
7
+ import { d as defineCustomElement$2 } from './p-DIMNEOTW.js';
8
+ import { d as defineCustomElement$1 } from './p-BzJEwFtn.js';
9
9
 
10
10
  /**
11
11
  * The current version of the Kritzel library.
12
12
  * This file is auto-generated by the version bump scripts.
13
13
  * Do not modify manually.
14
14
  */
15
- const KRITZEL_VERSION = '0.4.6';
15
+ const KRITZEL_VERSION = '0.4.8';
16
16
 
17
- 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)}`;
17
+ 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)}`;
18
18
 
19
19
  const DEFAULT_SCALE_MIN = 0.0001;
20
20
  const DEFAULT_SCALE_MAX = 1000;
@@ -225,23 +225,10 @@ const KritzelSettings = /*@__PURE__*/ proxyCustomElement(class KritzelSettings e
225
225
  }));
226
226
  }
227
227
  renderCategoryContent() {
228
- switch (this.selectedCategoryId) {
229
- case 'general':
230
- return (h("div", { class: "settings-content" }, h("h3", null, this.t('settings.general.title', 'General Settings')), h("div", { class: "settings-group" }, h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.general.theme.label', 'Theme')), h("p", { class: "settings-description" }, this.t('settings.general.theme.description', 'Select a registered color theme for the editor interface.')), h("kritzel-dropdown", { options: this.availableThemes.map(t => ({ value: t, label: t })), value: this.theme, onValueChanged: this.handleThemeChange })), this.availableLocales.length > 0 && (h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.general.language.label', 'Language')), h("p", { class: "settings-description" }, this.t('settings.general.language.description', 'Select the display language for the editor interface.')), h("kritzel-dropdown", { options: this.availableLocales.map(l => ({ value: l.code, label: l.label })), value: this.locale, onValueChanged: this.handleLocaleChange }))), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.general.lockDrawingScale.label', 'Lock Drawing Scale')), h("p", { class: "settings-description" }, this.t('settings.general.lockDrawingScale.description', 'When enabled, drawn objects maintain a fixed visual size regardless of the current zoom level.')), h("kritzel-slide-toggle", { checked: this.lockDrawingScale, label: this.t('settings.general.lockDrawingScale.label', 'Lock Drawing Scale'), onCheckedChange: this.handleLockDrawingScaleChange })))));
231
- case 'viewport':
232
- return (h("div", { class: "settings-content" }, h("h3", null, this.t('settings.viewport.title', 'Viewport Settings')), h("div", { class: "settings-group" }, h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.minZoom.label', 'Minimum Zoom Level')), h("p", { class: "settings-description" }, this.t('settings.viewport.minZoom.description', 'Sets the minimum zoom level. Lower values allow zooming out further to see more of the canvas.')), h("kritzel-numeric-input", { value: this.scaleMin, min: 0.0001, max: 1, step: 0.0001, onValueChange: this.handleScaleMinChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.maxZoom.label', 'Maximum Zoom Level')), h("p", { class: "settings-description" }, this.t('settings.viewport.maxZoom.description', 'Sets the maximum zoom level. Higher values allow zooming in closer for detailed work.')), h("kritzel-numeric-input", { value: this.scaleMax, min: 1, max: 1000, step: 1, onValueChange: this.handleScaleMaxChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryLeft.label', 'Viewport Boundary Left')), h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryLeft.description', 'Left boundary in world coordinates. Set to limit how far left the viewport can pan.')), h("kritzel-numeric-input", { value: this.viewportBoundaryLeft, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryLeftChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryRight.label', 'Viewport Boundary Right')), h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryRight.description', 'Right boundary in world coordinates. Set to limit how far right the viewport can pan.')), h("kritzel-numeric-input", { value: this.viewportBoundaryRight, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryRightChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryTop.label', 'Viewport Boundary Top')), h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryTop.description', 'Top boundary in world coordinates. Set to limit how far up the viewport can pan.')), h("kritzel-numeric-input", { value: this.viewportBoundaryTop, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryTopChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryBottom.label', 'Viewport Boundary Bottom')), h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryBottom.description', 'Bottom boundary in world coordinates. Set to limit how far down the viewport can pan.')), h("kritzel-numeric-input", { value: this.viewportBoundaryBottom, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryBottomChange })))));
233
- case 'shortcuts':
234
- return (h("div", { class: "settings-content" }, h("h3", null, this.t('settings.shortcuts.title', 'Keyboard Shortcuts')), h("div", { class: "shortcuts-list" }, Array.from(this.groupShortcutsByCategory()).map(([category, shortcuts]) => (h("div", { class: "shortcuts-category", key: category }, h("h4", { class: "shortcuts-category-title" }, category), h("div", { class: "shortcuts-group" }, shortcuts.map(shortcut => (h("div", { class: "shortcut-item", key: shortcut.key + shortcut.label }, h("span", { class: "shortcut-label" }, shortcut.label), h("kbd", { class: "shortcut-key" }, this.formatKeyCombo(shortcut))))))))))));
235
- case 'developer':
236
- return (h("div", { class: "settings-content" }, h("h3", null, this.t('settings.developer.title', 'Developer Options')), h("div", { class: "settings-group" }, h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showViewportInfo.label', 'Show Viewport Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showViewportInfo.description', 'Display viewport debug information such as position, zoom level, and boundaries.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showViewportInfo, label: this.t('settings.developer.showViewportInfo.label', 'Show Viewport Info'), onCheckedChange: this.handleDebugInfoChange('showViewportInfo') })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showObjectInfo.label', 'Show Object Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showObjectInfo.description', 'Display debug information about objects on the canvas.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showObjectInfo, label: this.t('settings.developer.showObjectInfo.label', 'Show Object Info'), onCheckedChange: this.handleDebugInfoChange('showObjectInfo') })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showSyncProviderInfo.label', 'Show Sync Provider Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showSyncProviderInfo.description', 'Display debug information about the sync provider connection status.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showSyncProviderInfo, label: this.t('settings.developer.showSyncProviderInfo.label', 'Show Sync Provider Info'), onCheckedChange: this.handleDebugInfoChange('showSyncProviderInfo') })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showMigrationInfo.label', 'Show Migration Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showMigrationInfo.description', 'Display debug information about data migrations.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showMigrationInfo, label: this.t('settings.developer.showMigrationInfo.label', 'Show Migration Info'), onCheckedChange: this.handleDebugInfoChange('showMigrationInfo') })))));
237
- case 'about':
238
- return (h("div", { class: "settings-content" }, h("h3", null, this.t('settings.about.title', 'About')), h("p", null, this.t('settings.about.description', 'Kritzel - A drawing application')), h("p", { class: "version-info" }, "Version ", KRITZEL_VERSION), h("p", { class: "version-info" }, "App-State Schema v", CURRENT_APP_STATE_SCHEMA_VERSION), h("p", { class: "version-info" }, "Workspace Schema v", CURRENT_WORKSPACE_SCHEMA_VERSION)));
239
- default:
240
- return null;
241
- }
228
+ return (h("div", { class: "settings-categories-wrapper" }, h("div", { class: { 'settings-tab-panel': true, 'is-active': this.selectedCategoryId === 'general' } }, h("div", { class: "settings-content" }, h("h3", null, this.t('settings.general.title', 'General Settings')), h("div", { class: "settings-group" }, h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.general.theme.label', 'Theme')), h("p", { class: "settings-description" }, this.t('settings.general.theme.description', 'Select a registered color theme for the editor interface.')), h("kritzel-dropdown", { options: this.availableThemes.map(t => ({ value: t, label: t })), value: this.theme, onValueChanged: this.handleThemeChange })), this.availableLocales.length > 0 && (h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.general.language.label', 'Language')), h("p", { class: "settings-description" }, this.t('settings.general.language.description', 'Select the display language for the editor interface.')), h("kritzel-dropdown", { options: this.availableLocales.map(l => ({ value: l.code, label: l.label })), value: this.locale, onValueChanged: this.handleLocaleChange }))), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.general.lockDrawingScale.label', 'Lock Drawing Scale')), h("p", { class: "settings-description" }, this.t('settings.general.lockDrawingScale.description', 'When enabled, drawn objects maintain a fixed visual size regardless of the current zoom level.')), h("kritzel-slide-toggle", { checked: this.lockDrawingScale, label: this.t('settings.general.lockDrawingScale.label', 'Lock Drawing Scale'), onCheckedChange: this.handleLockDrawingScaleChange }))))), h("div", { class: { 'settings-tab-panel': true, 'is-active': this.selectedCategoryId === 'viewport' } }, h("div", { class: "settings-content" }, h("h3", null, this.t('settings.viewport.title', 'Viewport Settings')), h("div", { class: "settings-group" }, h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.minZoom.label', 'Minimum Zoom Level')), h("p", { class: "settings-description" }, this.t('settings.viewport.minZoom.description', 'Sets the minimum zoom level. Lower values allow zooming out further to see more of the canvas.')), h("kritzel-numeric-input", { value: this.scaleMin, min: 0.0001, max: 1, step: 0.0001, onValueChange: this.handleScaleMinChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.maxZoom.label', 'Maximum Zoom Level')), h("p", { class: "settings-description" }, this.t('settings.viewport.maxZoom.description', 'Sets the maximum zoom level. Higher values allow zooming in closer for detailed work.')), h("kritzel-numeric-input", { value: this.scaleMax, min: 1, max: 1000, step: 1, onValueChange: this.handleScaleMaxChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryLeft.label', 'Viewport Boundary Left')), h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryLeft.description', 'Left boundary in world coordinates. Set to limit how far left the viewport can pan.')), h("kritzel-numeric-input", { value: this.viewportBoundaryLeft, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryLeftChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryRight.label', 'Viewport Boundary Right')), h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryRight.description', 'Right boundary in world coordinates. Set to limit how far right the viewport can pan.')), h("kritzel-numeric-input", { value: this.viewportBoundaryRight, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryRightChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryTop.label', 'Viewport Boundary Top')), h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryTop.description', 'Top boundary in world coordinates. Set to limit how far up the viewport can pan.')), h("kritzel-numeric-input", { value: this.viewportBoundaryTop, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryTopChange })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.viewport.boundaryBottom.label', 'Viewport Boundary Bottom')), h("p", { class: "settings-description" }, this.t('settings.viewport.boundaryBottom.description', 'Bottom boundary in world coordinates. Set to limit how far down the viewport can pan.')), h("kritzel-numeric-input", { value: this.viewportBoundaryBottom, step: 100, placeholder: this.t('settings.viewport.boundaryPlaceholder', 'Infinite'), onValueChange: this.handleViewportBoundaryBottomChange }))))), h("div", { class: { 'settings-tab-panel': true, 'is-active': this.selectedCategoryId === 'shortcuts' } }, h("div", { class: "settings-content" }, h("h3", null, this.t('settings.shortcuts.title', 'Keyboard Shortcuts')), h("div", { class: "shortcuts-list" }, Array.from(this.groupShortcutsByCategory()).map(([category, shortcuts]) => (h("div", { class: "shortcuts-category", key: category }, h("h4", { class: "shortcuts-category-title" }, category), h("div", { class: "shortcuts-group" }, shortcuts.map(shortcut => (h("div", { class: "shortcut-item", key: shortcut.key + shortcut.label }, h("span", { class: "shortcut-label" }, shortcut.label), h("kbd", { class: "shortcut-key" }, this.formatKeyCombo(shortcut)))))))))))), h("div", { class: { 'settings-tab-panel': true, 'is-active': this.selectedCategoryId === 'developer' } }, h("div", { class: "settings-content" }, h("h3", null, this.t('settings.developer.title', 'Developer Options')), h("div", { class: "settings-group" }, h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showViewportInfo.label', 'Show Viewport Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showViewportInfo.description', 'Display viewport debug information such as position, zoom level, and boundaries.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showViewportInfo, label: this.t('settings.developer.showViewportInfo.label', 'Show Viewport Info'), onCheckedChange: this.handleDebugInfoChange('showViewportInfo') })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showObjectInfo.label', 'Show Object Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showObjectInfo.description', 'Display debug information about objects on the canvas.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showObjectInfo, label: this.t('settings.developer.showObjectInfo.label', 'Show Object Info'), onCheckedChange: this.handleDebugInfoChange('showObjectInfo') })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showSyncProviderInfo.label', 'Show Sync Provider Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showSyncProviderInfo.description', 'Display debug information about the sync provider connection status.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showSyncProviderInfo, label: this.t('settings.developer.showSyncProviderInfo.label', 'Show Sync Provider Info'), onCheckedChange: this.handleDebugInfoChange('showSyncProviderInfo') })), h("div", { class: "settings-item" }, h("label", { class: "settings-label" }, this.t('settings.developer.showMigrationInfo.label', 'Show Migration Info')), h("p", { class: "settings-description" }, this.t('settings.developer.showMigrationInfo.description', 'Display debug information about data migrations.')), h("kritzel-slide-toggle", { checked: this.debugInfo.showMigrationInfo, label: this.t('settings.developer.showMigrationInfo.label', 'Show Migration Info'), onCheckedChange: this.handleDebugInfoChange('showMigrationInfo') }))))), h("div", { class: { 'settings-tab-panel': true, 'is-active': this.selectedCategoryId === 'about' } }, h("div", { class: "settings-content" }, h("h3", null, this.t('settings.about.title', 'About')), h("p", null, this.t('settings.about.description', 'Kritzel - A drawing application')), h("p", { class: "version-info" }, "Version ", KRITZEL_VERSION), h("p", { class: "version-info" }, "App-State Schema v", CURRENT_APP_STATE_SCHEMA_VERSION), h("p", { class: "version-info" }, "Workspace Schema v", CURRENT_WORKSPACE_SCHEMA_VERSION)))));
242
229
  }
243
230
  render() {
244
- return (h(Host, { key: '1fb0bca35cb20633f017a927d39e2a66ebfb403b' }, h("kritzel-dialog", { key: '6366a8d8e7f65ef3f715248db3dc7c7e36dd3f4a', isOpen: this.isDialogOpen, dialogTitle: this.t('settings.dialogTitle', 'Settings'), size: "large", contained: true, onDialogClose: this.closeDialog }, h("kritzel-master-detail", { key: '2f4891d1ef0b3f130c591790b2e53e7264a61145', items: this.categories, selectedItemId: this.selectedCategoryId, onItemSelect: this.handleCategorySelect }, this.renderCategoryContent()))));
231
+ return (h(Host, { key: '36bca8be04b34a37630d6aa5394595a8b394d180' }, h("kritzel-dialog", { key: '1e257904178fd9afa2bfbe4a758663fb366c8847', isOpen: this.isDialogOpen, dialogTitle: this.t('settings.dialogTitle', 'Settings'), size: "large", contained: true, onDialogClose: this.closeDialog }, h("kritzel-master-detail", { key: 'b7d9ad97d9b126ccf6e800e6c9032749635eb988', items: this.categories, selectedItemId: this.selectedCategoryId, onItemSelect: this.handleCategorySelect }, this.renderCategoryContent()))));
245
232
  }
246
233
  static get watchers() { return {
247
234
  "settings": [{
@@ -14,7 +14,7 @@ const KritzelFont = /*@__PURE__*/ proxyCustomElement(class KritzelFont extends H
14
14
  size = 24;
15
15
  color = '#000000';
16
16
  render() {
17
- return (h(Host, { key: '57369ac95d0c99a52a8580e7659ec10e0e8ab38e' }, h("div", { key: 'e8f128fd7b8d26debb2c4ad2075b27f969d731bd', class: "font-preview", style: {
17
+ return (h(Host, { key: '054371cac30a2433611139a670406b0a1e3b99ff' }, h("div", { key: 'b4f2142b3cb31d067f39952a38b6f665f28f63bf', class: "font-preview", style: {
18
18
  fontFamily: this.fontFamily,
19
19
  fontSize: `${this.size}px`,
20
20
  color: this.color