kritzel-stencil 0.1.69 → 0.1.71

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 (98) hide show
  1. package/dist/cjs/index.cjs.js +35 -30
  2. package/dist/cjs/kritzel-active-users_41.cjs.entry.js +298 -207
  3. package/dist/cjs/loader.cjs.js +1 -1
  4. package/dist/cjs/stencil.cjs.js +1 -1
  5. package/dist/cjs/{alignment.enum-D0b0c-AK.js → workspace.migrations-Cma2Vh5E.js} +121 -5
  6. package/dist/collection/classes/core/core.class.js +15 -6
  7. package/dist/collection/classes/core/workspace.class.js +4 -4
  8. package/dist/collection/classes/registries/icon-registry.class.js +2 -1
  9. package/dist/collection/classes/structures/app-state-map.structure.js +25 -1
  10. package/dist/collection/classes/structures/object-map.structure.js +13 -0
  11. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +36 -1
  12. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +44 -1
  13. package/dist/collection/components/shared/kritzel-master-detail/kritzel-master-detail.css +1 -0
  14. package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js +3 -1
  15. package/dist/collection/components/ui/kritzel-more-menu/kritzel-more-menu.css +5 -0
  16. package/dist/collection/components/ui/kritzel-more-menu/kritzel-more-menu.js +5 -2
  17. package/dist/collection/components/ui/kritzel-settings/kritzel-settings.js +23 -3
  18. package/dist/collection/configs/default-engine-config.js +2 -1
  19. package/dist/collection/constants/schema.constants.js +4 -0
  20. package/dist/collection/constants/version.js +1 -1
  21. package/dist/collection/helpers/migration.helper.js +45 -0
  22. package/dist/collection/index.js +5 -0
  23. package/dist/collection/interfaces/migration.interface.js +1 -0
  24. package/dist/collection/migrations/app-state.migrations.js +47 -0
  25. package/dist/collection/migrations/workspace.migrations.js +10 -0
  26. package/dist/components/index.js +1 -1
  27. package/dist/components/kritzel-back-to-content.js +1 -1
  28. package/dist/components/kritzel-brush-style.js +1 -1
  29. package/dist/components/kritzel-context-menu.js +1 -1
  30. package/dist/components/kritzel-controls.js +1 -1
  31. package/dist/components/kritzel-editor.js +1 -1
  32. package/dist/components/kritzel-engine.js +1 -1
  33. package/dist/components/kritzel-export.js +1 -1
  34. package/dist/components/kritzel-icon.js +1 -1
  35. package/dist/components/kritzel-login-dialog.js +1 -1
  36. package/dist/components/kritzel-master-detail.js +1 -1
  37. package/dist/components/kritzel-menu-item.js +1 -1
  38. package/dist/components/kritzel-menu.js +1 -1
  39. package/dist/components/kritzel-more-menu.js +1 -1
  40. package/dist/components/kritzel-pill-tabs.js +1 -1
  41. package/dist/components/kritzel-settings.js +1 -1
  42. package/dist/components/kritzel-share-dialog.js +1 -1
  43. package/dist/components/kritzel-split-button.js +1 -1
  44. package/dist/components/kritzel-tool-config.js +1 -1
  45. package/dist/components/kritzel-utility-panel.js +1 -1
  46. package/dist/components/kritzel-workspace-manager.js +1 -1
  47. package/dist/components/{p-D6RNXsYR.js → p-B47JuZiD.js} +1 -1
  48. package/dist/components/{p-B_j7el2b.js → p-B5ouV8EQ.js} +1 -1
  49. package/dist/components/p-BB6jZPvJ.js +1 -0
  50. package/dist/components/{p-BsM1KXx1.js → p-BG1IxseV.js} +1 -1
  51. package/dist/components/p-BvToKcu1.js +1 -0
  52. package/dist/components/{p-A7HszzcA.js → p-C5KuV1pK.js} +1 -1
  53. package/dist/components/{p-BbUblXxe.js → p-CHmi1QWx.js} +1 -1
  54. package/dist/components/p-CHtn5xr6.js +1 -0
  55. package/dist/components/{p-CcR5avNh.js → p-CNro30tB.js} +1 -1
  56. package/dist/components/{p-C2Fpsb5N.js → p-CUkKKbnu.js} +1 -1
  57. package/dist/components/p-D5rvyCKa.js +1 -0
  58. package/dist/components/{p-QkQRIhFK.js → p-DEzfXrGX.js} +1 -1
  59. package/dist/components/{p-CF7GRkAC.js → p-D_Rh1g93.js} +1 -1
  60. package/dist/components/{p-B8t6bOJH.js → p-DiFVw6IQ.js} +1 -1
  61. package/dist/components/{p-CVvPMxWx.js → p-Do0Q5-iC.js} +1 -1
  62. package/dist/components/{p-CmZLak6y.js → p-DsIlDGDO.js} +1 -1
  63. package/dist/components/p-Duv3EM3w.js +1 -0
  64. package/dist/components/p-MrsvScCa.js +9 -0
  65. package/dist/components/{p-D6uQVtzS.js → p-VHyNcODZ.js} +1 -1
  66. package/dist/esm/index.js +2 -2
  67. package/dist/esm/kritzel-active-users_41.entry.js +109 -18
  68. package/dist/esm/loader.js +1 -1
  69. package/dist/esm/stencil.js +1 -1
  70. package/dist/esm/{alignment.enum-DAQizL2y.js → workspace.migrations-BeeAeDP0.js} +117 -6
  71. package/dist/stencil/index.esm.js +1 -1
  72. package/dist/stencil/p-47cfd58a.entry.js +9 -0
  73. package/dist/stencil/{p-DAQizL2y.js → p-BeeAeDP0.js} +1 -1
  74. package/dist/stencil/stencil.esm.js +1 -1
  75. package/dist/types/classes/core/core.class.d.ts +1 -0
  76. package/dist/types/classes/core/workspace.class.d.ts +7 -7
  77. package/dist/types/classes/structures/app-state-map.structure.d.ts +1 -0
  78. package/dist/types/components/core/kritzel-editor/kritzel-editor.d.ts +2 -0
  79. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +4 -0
  80. package/dist/types/components/ui/kritzel-more-menu/kritzel-more-menu.d.ts +1 -0
  81. package/dist/types/components/ui/kritzel-settings/kritzel-settings.d.ts +3 -0
  82. package/dist/types/components.d.ts +18 -0
  83. package/dist/types/constants/schema.constants.d.ts +4 -0
  84. package/dist/types/constants/version.d.ts +1 -1
  85. package/dist/types/helpers/migration.helper.d.ts +30 -0
  86. package/dist/types/index.d.ts +5 -0
  87. package/dist/types/interfaces/debug-info.interface.d.ts +1 -0
  88. package/dist/types/interfaces/migration.interface.d.ts +16 -0
  89. package/dist/types/interfaces/settings.interface.d.ts +3 -0
  90. package/dist/types/migrations/app-state.migrations.d.ts +11 -0
  91. package/dist/types/migrations/workspace.migrations.d.ts +11 -0
  92. package/package.json +1 -1
  93. package/dist/components/p-BFtP25sy.js +0 -1
  94. package/dist/components/p-C8HhteY6.js +0 -1
  95. package/dist/components/p-CKfBxe_j.js +0 -9
  96. package/dist/components/p-C_DXltJs.js +0 -1
  97. package/dist/components/p-_7z0DVvB.js +0 -1
  98. package/dist/stencil/p-459cea5b.entry.js +0 -9
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var index = require('./index-Dc7LOVhs.js');
4
- var alignment_enum = require('./alignment.enum-D0b0c-AK.js');
4
+ var workspace_migrations = require('./workspace.migrations-Cma2Vh5E.js');
5
5
  var Y = require('yjs');
6
6
  require('y-websocket');
7
7
  require('y-indexeddb');
@@ -249,7 +249,7 @@ const KritzelColorComponent = class {
249
249
  return '';
250
250
  if (typeof this.value === 'string')
251
251
  return this.value;
252
- return alignment_enum.KritzelColorHelper.resolveThemeColor(this.value, this.theme);
252
+ return workspace_migrations.KritzelColorHelper.resolveThemeColor(this.value, this.theme);
253
253
  }
254
254
  isLightColor(hexColor) {
255
255
  if (!hexColor)
@@ -349,7 +349,7 @@ const KritzelColorPalette = class {
349
349
  return (index.h("div", { tabIndex: 0, class: {
350
350
  'color-container': true,
351
351
  'selected': this.areColorsEqual(this.selectedColor, color),
352
- }, onClick: () => this.handleColorClick(color), onKeyDown: event => this.handleKeyDown(event, color) }, index.h("kritzel-color", { value: alignment_enum.KritzelColorHelper.applyOpacity(color, this.opacity, this.theme), theme: this.theme })));
352
+ }, onClick: () => this.handleColorClick(color), onKeyDown: event => this.handleKeyDown(event, color) }, index.h("kritzel-color", { value: workspace_migrations.KritzelColorHelper.applyOpacity(color, this.opacity, this.theme), theme: this.theme })));
353
353
  }))));
354
354
  }
355
355
  };
@@ -559,10 +559,10 @@ KritzelContextMenu.style = kritzelContextMenuCss();
559
559
 
560
560
  class KritzelToolConfigHelper {
561
561
  static getToolConfig(tool) {
562
- if (tool instanceof alignment_enum.KritzelSelectionTool) {
562
+ if (tool instanceof workspace_migrations.KritzelSelectionTool) {
563
563
  return tool.getToolConfig();
564
564
  }
565
- if (tool instanceof alignment_enum.KritzelBrushTool) {
565
+ if (tool instanceof workspace_migrations.KritzelBrushTool) {
566
566
  return {
567
567
  type: 'brush',
568
568
  colorProperty: 'color',
@@ -574,7 +574,7 @@ class KritzelToolConfigHelper {
574
574
  ],
575
575
  };
576
576
  }
577
- if (tool instanceof alignment_enum.KritzelLineTool) {
577
+ if (tool instanceof workspace_migrations.KritzelLineTool) {
578
578
  return {
579
579
  type: 'line',
580
580
  colorProperty: 'color',
@@ -587,7 +587,7 @@ class KritzelToolConfigHelper {
587
587
  ],
588
588
  };
589
589
  }
590
- if (tool instanceof alignment_enum.KritzelShapeTool) {
590
+ if (tool instanceof workspace_migrations.KritzelShapeTool) {
591
591
  return {
592
592
  type: 'shape',
593
593
  colorProperty: 'strokeColor',
@@ -600,7 +600,7 @@ class KritzelToolConfigHelper {
600
600
  ],
601
601
  };
602
602
  }
603
- if (tool instanceof alignment_enum.KritzelTextTool) {
603
+ if (tool instanceof workspace_migrations.KritzelTextTool) {
604
604
  return {
605
605
  type: 'text',
606
606
  colorProperty: 'fontColor',
@@ -633,7 +633,7 @@ const KritzelControls = class {
633
633
  theme;
634
634
  isControlsReady;
635
635
  firstConfig = null;
636
- isTouchDevice = alignment_enum.KritzelDevicesHelper.isTouchDevice();
636
+ isTouchDevice = workspace_migrations.KritzelDevicesHelper.isTouchDevice();
637
637
  selectedSubOptions = new Map();
638
638
  canScrollLeft = false;
639
639
  canScrollRight = false;
@@ -654,7 +654,7 @@ const KritzelControls = class {
654
654
  this.closeTooltip();
655
655
  }
656
656
  handleSelectionChange() {
657
- if (this.activeControl?.tool instanceof alignment_enum.KritzelSelectionTool) {
657
+ if (this.activeControl?.tool instanceof workspace_migrations.KritzelSelectionTool) {
658
658
  this.updateDisplayValues(this.activeControl.tool);
659
659
  }
660
660
  }
@@ -701,10 +701,10 @@ const KritzelControls = class {
701
701
  const opacity = tool[config.opacityProperty] ?? 1;
702
702
  const size = tool[config.sizeProperty];
703
703
  const displayValues = {
704
- color: alignment_enum.KritzelColorHelper.applyOpacity(color, opacity, this.theme),
704
+ color: workspace_migrations.KritzelColorHelper.applyOpacity(color, opacity, this.theme),
705
705
  size,
706
706
  };
707
- if (tool instanceof alignment_enum.KritzelTextTool) {
707
+ if (tool instanceof workspace_migrations.KritzelTextTool) {
708
708
  displayValues.fontFamily = tool.fontFamily;
709
709
  }
710
710
  // Check for equality implementation to prevent unnecessary re-renders
@@ -810,11 +810,11 @@ const KritzelControls = class {
810
810
  await this.handleControlClick(control);
811
811
  }
812
812
  render() {
813
- const hasConfigUI = this.activeControl?.tool instanceof alignment_enum.KritzelBrushTool ||
814
- this.activeControl?.tool instanceof alignment_enum.KritzelTextTool ||
815
- this.activeControl?.tool instanceof alignment_enum.KritzelLineTool ||
816
- this.activeControl?.tool instanceof alignment_enum.KritzelShapeTool ||
817
- (this.activeControl?.tool instanceof alignment_enum.KritzelSelectionTool && this.activeControl.tool.hasSelection());
813
+ const hasConfigUI = this.activeControl?.tool instanceof workspace_migrations.KritzelBrushTool ||
814
+ this.activeControl?.tool instanceof workspace_migrations.KritzelTextTool ||
815
+ this.activeControl?.tool instanceof workspace_migrations.KritzelLineTool ||
816
+ this.activeControl?.tool instanceof workspace_migrations.KritzelShapeTool ||
817
+ (this.activeControl?.tool instanceof workspace_migrations.KritzelSelectionTool && this.activeControl.tool.hasSelection());
818
818
  // Separate tool controls from config control
819
819
  const toolControls = this.controls.filter(c => c.type === 'tool' || c.type === 'separator');
820
820
  const configControl = this.controls.find(c => c.type === 'config' && c.name === this.firstConfig?.name);
@@ -866,7 +866,7 @@ const KritzelControls = class {
866
866
  }
867
867
  }, style: {
868
868
  cursor: 'pointer',
869
- } }, this.activeControl.tool instanceof alignment_enum.KritzelTextTool && this.displayValues ? (index.h("div", { class: "font-container" }, index.h("kritzel-font", { fontFamily: this.displayValues.fontFamily, size: this.displayValues.size, color: this.displayValues.color }))) : this.displayValues && (index.h("div", { class: "color-container" }, index.h("kritzel-color", { value: this.displayValues.color, theme: this.theme, size: this.displayValues.size, style: {
869
+ } }, this.activeControl.tool instanceof workspace_migrations.KritzelTextTool && this.displayValues ? (index.h("div", { class: "font-container" }, index.h("kritzel-font", { fontFamily: this.displayValues.fontFamily, size: this.displayValues.size, color: this.displayValues.color }))) : this.displayValues && (index.h("div", { class: "color-container" }, index.h("kritzel-color", { value: this.displayValues.color, theme: this.theme, size: this.displayValues.size, style: {
870
870
  borderRadius: '50%',
871
871
  border: 'none',
872
872
  } })))))))));
@@ -949,7 +949,7 @@ const KritzelCursorTrail = class {
949
949
  isLeftButtonDown = false;
950
950
  handleMouseDown(ev) {
951
951
  if (ev.pointerType === 'mouse') {
952
- if (ev.button === alignment_enum.KritzelMouseButton.Left) {
952
+ if (ev.button === workspace_migrations.KritzelMouseButton.Left) {
953
953
  this.isLeftButtonDown = true;
954
954
  this.cursorTrailPoints = [];
955
955
  }
@@ -976,7 +976,7 @@ const KritzelCursorTrail = class {
976
976
  }
977
977
  handlePointerUp(ev) {
978
978
  if (ev.pointerType === 'mouse') {
979
- if (ev.button === alignment_enum.KritzelMouseButton.Left) {
979
+ if (ev.button === workspace_migrations.KritzelMouseButton.Left) {
980
980
  this.isLeftButtonDown = false;
981
981
  this.cursorTrailPoints = [];
982
982
  }
@@ -1580,14 +1580,14 @@ const KritzelDropdown = class {
1580
1580
  KritzelDropdown.style = kritzelDropdownCss();
1581
1581
 
1582
1582
  const DEFAULT_SHAPE_CONFIG = {
1583
- shapeType: alignment_enum.ShapeType.Rectangle,
1583
+ shapeType: workspace_migrations.ShapeType.Rectangle,
1584
1584
  fillColor: { light: 'transparent', dark: 'transparent' },
1585
- strokeColor: alignment_enum.DEFAULT_COLOR_PALETTE[0],
1585
+ strokeColor: workspace_migrations.DEFAULT_COLOR_PALETTE[0],
1586
1586
  strokeWidth: 4,
1587
- fontColor: alignment_enum.DEFAULT_COLOR_PALETTE[0],
1587
+ fontColor: workspace_migrations.DEFAULT_COLOR_PALETTE[0],
1588
1588
  fontSize: 16,
1589
1589
  fontFamily: 'Arial',
1590
- palette: [...alignment_enum.DEFAULT_COLOR_PALETTE],
1590
+ palette: [...workspace_migrations.DEFAULT_COLOR_PALETTE],
1591
1591
  };
1592
1592
 
1593
1593
  const ABSOLUTE_SCALE_MAX = 1000;
@@ -1621,6 +1621,12 @@ const KritzelEditor = class {
1621
1621
  viewportBoundaryTop = -Infinity;
1622
1622
  viewportBoundaryBottom = Infinity;
1623
1623
  wheelEnabled = true;
1624
+ debugInfo = {
1625
+ showViewportInfo: false,
1626
+ showObjectInfo: false,
1627
+ showSyncProviderInfo: true,
1628
+ showMigrationInfo: true,
1629
+ };
1624
1630
  user;
1625
1631
  activeUsers;
1626
1632
  controls = [
@@ -1628,52 +1634,52 @@ const KritzelEditor = class {
1628
1634
  name: 'selection',
1629
1635
  type: 'tool',
1630
1636
  isDefault: true,
1631
- tool: alignment_enum.KritzelSelectionTool,
1637
+ tool: workspace_migrations.KritzelSelectionTool,
1632
1638
  icon: 'cursor',
1633
1639
  },
1634
1640
  {
1635
1641
  name: 'brush',
1636
1642
  type: 'tool',
1637
- tool: alignment_enum.KritzelBrushTool,
1643
+ tool: workspace_migrations.KritzelBrushTool,
1638
1644
  icon: 'pen',
1639
- config: alignment_enum.DEFAULT_BRUSH_CONFIG,
1645
+ config: workspace_migrations.DEFAULT_BRUSH_CONFIG,
1640
1646
  },
1641
1647
  {
1642
1648
  name: 'eraser',
1643
1649
  type: 'tool',
1644
- tool: alignment_enum.KritzelEraserTool,
1650
+ tool: workspace_migrations.KritzelEraserTool,
1645
1651
  icon: 'eraser',
1646
1652
  },
1647
1653
  {
1648
1654
  name: 'line',
1649
1655
  type: 'tool',
1650
- tool: alignment_enum.KritzelLineTool,
1656
+ tool: workspace_migrations.KritzelLineTool,
1651
1657
  icon: 'arrow',
1652
- config: alignment_enum.DEFAULT_LINE_TOOL_CONFIG,
1658
+ config: workspace_migrations.DEFAULT_LINE_TOOL_CONFIG,
1653
1659
  },
1654
1660
  {
1655
1661
  name: 'shape',
1656
1662
  type: 'tool',
1657
- tool: alignment_enum.KritzelShapeTool,
1663
+ tool: workspace_migrations.KritzelShapeTool,
1658
1664
  icon: 'shape-rectangle',
1659
1665
  config: DEFAULT_SHAPE_CONFIG,
1660
1666
  subOptions: [
1661
- { id: 'rectangle', icon: 'shape-rectangle', label: 'Rectangle', value: alignment_enum.ShapeType.Rectangle, toolProperty: 'shapeType' },
1662
- { id: 'ellipse', icon: 'shape-ellipse', label: 'Ellipse', value: alignment_enum.ShapeType.Ellipse, toolProperty: 'shapeType' },
1663
- { id: 'triangle', icon: 'shape-triangle', label: 'Triangle', value: alignment_enum.ShapeType.Triangle, toolProperty: 'shapeType' },
1667
+ { id: 'rectangle', icon: 'shape-rectangle', label: 'Rectangle', value: workspace_migrations.ShapeType.Rectangle, toolProperty: 'shapeType' },
1668
+ { id: 'ellipse', icon: 'shape-ellipse', label: 'Ellipse', value: workspace_migrations.ShapeType.Ellipse, toolProperty: 'shapeType' },
1669
+ { id: 'triangle', icon: 'shape-triangle', label: 'Triangle', value: workspace_migrations.ShapeType.Triangle, toolProperty: 'shapeType' },
1664
1670
  ],
1665
1671
  },
1666
1672
  {
1667
1673
  name: 'text',
1668
1674
  type: 'tool',
1669
- tool: alignment_enum.KritzelTextTool,
1675
+ tool: workspace_migrations.KritzelTextTool,
1670
1676
  icon: 'type',
1671
- config: alignment_enum.DEFAULT_TEXT_CONFIG,
1677
+ config: workspace_migrations.DEFAULT_TEXT_CONFIG,
1672
1678
  },
1673
1679
  {
1674
1680
  name: 'image',
1675
1681
  type: 'tool',
1676
- tool: alignment_enum.KritzelImageTool,
1682
+ tool: workspace_migrations.KritzelImageTool,
1677
1683
  icon: 'image',
1678
1684
  },
1679
1685
  {
@@ -1721,12 +1727,12 @@ const KritzelEditor = class {
1721
1727
  group: 'other',
1722
1728
  disabled: async () => (await this.engineRef.getSelectedObjects()).length < 2,
1723
1729
  children: [
1724
- { label: 'Align Left', icon: 'align-start-vertical', action: () => this.engineRef.alignObjects(alignment_enum.KritzelAlignment.StartHorizontal) },
1725
- { label: 'Align Center Horizontally', icon: 'align-center-horizontal', action: () => this.engineRef.alignObjects(alignment_enum.KritzelAlignment.CenterHorizontal) },
1726
- { label: 'Align Right', icon: 'align-end-vertical', action: () => this.engineRef.alignObjects(alignment_enum.KritzelAlignment.EndHorizontal) },
1727
- { label: 'Align Top', icon: 'align-start-horizontal', action: () => this.engineRef.alignObjects(alignment_enum.KritzelAlignment.StartVertical) },
1728
- { label: 'Align Center Vertically', icon: 'align-center-vertical', action: () => this.engineRef.alignObjects(alignment_enum.KritzelAlignment.CenterVertical) },
1729
- { label: 'Align Bottom', icon: 'align-end-horizontal', action: () => this.engineRef.alignObjects(alignment_enum.KritzelAlignment.EndVertical) },
1730
+ { label: 'Align Left', icon: 'align-start-vertical', action: () => this.engineRef.alignObjects(workspace_migrations.KritzelAlignment.StartHorizontal) },
1731
+ { label: 'Align Center Horizontally', icon: 'align-center-horizontal', action: () => this.engineRef.alignObjects(workspace_migrations.KritzelAlignment.CenterHorizontal) },
1732
+ { label: 'Align Right', icon: 'align-end-vertical', action: () => this.engineRef.alignObjects(workspace_migrations.KritzelAlignment.EndHorizontal) },
1733
+ { label: 'Align Top', icon: 'align-start-horizontal', action: () => this.engineRef.alignObjects(workspace_migrations.KritzelAlignment.StartVertical) },
1734
+ { label: 'Align Center Vertically', icon: 'align-center-vertical', action: () => this.engineRef.alignObjects(workspace_migrations.KritzelAlignment.CenterVertical) },
1735
+ { label: 'Align Bottom', icon: 'align-end-horizontal', action: () => this.engineRef.alignObjects(workspace_migrations.KritzelAlignment.EndVertical) },
1730
1736
  ],
1731
1737
  },
1732
1738
  {
@@ -1766,7 +1772,7 @@ const KritzelEditor = class {
1766
1772
  isControlsVisible = true;
1767
1773
  isUtilityPanelVisible = true;
1768
1774
  syncConfig = {
1769
- providers: [alignment_enum.IndexedDBSyncProvider],
1775
+ providers: [workspace_migrations.IndexedDBSyncProvider],
1770
1776
  };
1771
1777
  /** Optional login configuration. When provided, a "Sign in" button is shown that opens a login dialog with the configured providers. */
1772
1778
  loginConfig;
@@ -2116,6 +2122,7 @@ const KritzelEditor = class {
2116
2122
  this.viewportBoundaryRight = event.detail.viewportBoundaryRight ?? Infinity;
2117
2123
  this.viewportBoundaryTop = event.detail.viewportBoundaryTop ?? -Infinity;
2118
2124
  this.viewportBoundaryBottom = event.detail.viewportBoundaryBottom ?? Infinity;
2125
+ this.debugInfo = event.detail.debugInfo;
2119
2126
  this.themeChange.emit(event.detail.theme);
2120
2127
  }
2121
2128
  get moreMenuItems() {
@@ -2223,6 +2230,9 @@ const KritzelEditor = class {
2223
2230
  if (typeof parsed.viewportBoundaryBottom === 'number') {
2224
2231
  this.viewportBoundaryBottom = parsed.viewportBoundaryBottom;
2225
2232
  }
2233
+ if (parsed.debugInfo) {
2234
+ this.debugInfo = { ...this.debugInfo, ...parsed.debugInfo };
2235
+ }
2226
2236
  }
2227
2237
  catch {
2228
2238
  // Invalid JSON, use prop defaults
@@ -2233,20 +2243,20 @@ const KritzelEditor = class {
2233
2243
  this.shortcuts = await this.engineRef.getDisplayableShortcuts();
2234
2244
  }
2235
2245
  getContentObjects(objects) {
2236
- return objects.filter(obj => !(obj instanceof alignment_enum.KritzelSelectionGroup) && !(obj instanceof alignment_enum.KritzelSelectionBox));
2246
+ return objects.filter(obj => !(obj instanceof workspace_migrations.KritzelSelectionGroup) && !(obj instanceof workspace_migrations.KritzelSelectionBox));
2237
2247
  }
2238
2248
  registerCustomSvgIcons() {
2239
2249
  for (const [name, svg] of Object.entries(this.customSvgIcons)) {
2240
- alignment_enum.KritzelIconRegistry.register(name, svg);
2250
+ workspace_migrations.KritzelIconRegistry.register(name, svg);
2241
2251
  }
2242
2252
  }
2243
2253
  listenForMobileKeyboard() {
2244
- alignment_enum.KritzelKeyboardHelper.onKeyboardVisibleChanged(isOpen => {
2254
+ workspace_migrations.KritzelKeyboardHelper.onKeyboardVisibleChanged(isOpen => {
2245
2255
  this.isVirtualKeyboardOpen = isOpen;
2246
2256
  });
2247
2257
  }
2248
2258
  setOsSpecificCssVariables() {
2249
- const os = alignment_enum.KritzelDevicesHelper.detectOS();
2259
+ const os = workspace_migrations.KritzelDevicesHelper.detectOS();
2250
2260
  switch (os) {
2251
2261
  case 'iOS':
2252
2262
  // iOS specific adjustments
@@ -2278,7 +2288,7 @@ const KritzelEditor = class {
2278
2288
  const isLoggedIn = this.isLoggedIn;
2279
2289
  const shouldShowCurrentUser = isLoggedIn;
2280
2290
  const shouldShowLoginButton = !!this.loginConfig && !isLoggedIn;
2281
- return (index.h(index.Host, { key: 'ac7aa83139228074f31fe5dc21e9ae87a3ac69dd' }, index.h("div", { key: '41c4d85409a2d119437497d966a8e381f6760fc8', class: "top-left-buttons" }, index.h("kritzel-workspace-manager", { key: '76feeb04f3f2ba5c1786c16462cb1b35b4ae31d2', workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-back-to-content", { key: '2763d5bfff7d7380817e09ee893434e45762cf97', visible: this.isBackToContentButtonVisible, onBackToContent: () => this.backToContent() })), index.h("kritzel-engine", { key: 'b4ac1436bdead364e0c979d9b2c9425e0d1d716f', ref: el => (this.engineRef = el), workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, scaleMin: this.scaleMin, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, wheelEnabled: this.wheelEnabled, theme: this.currentTheme, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onActiveWorkspaceChange: event => this.handleActiveWorkspaceChange(event), onObjectsChange: event => this.handleObjectsChange(event), onObjectsAdded: event => this.handleObjectsAdded(event), onObjectsRemoved: event => this.handleObjectsRemoved(event), onObjectsUpdated: event => this.handleObjectsUpdated(event), onUndoStateChange: event => this.handleUndoStateChange(event), onObjectsInViewportChange: event => this.handleObjectsInViewportChange(event), onViewportChange: event => this.handleViewportChange(event), onAwarenessChange: event => this.handleAwarenessChange(event) }), index.h("kritzel-controls", { key: 'f220efad958bfaefa5e8b1ce564233eee2381ec1', class: { 'keyboard-open': this.isVirtualKeyboardOpen }, style: { display: this.isControlsVisible ? 'flex' : 'none' }, ref: el => (this.controlsRef = el), controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState, theme: this.currentTheme, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: '3a70ba67e3866fc32c1be871407b187d3d0eb9b2', class: "top-right-buttons" }, index.h("kritzel-settings", { key: 'b92d2932a768c1bb2120ed02e76632db7b5b302c', ref: el => (this.settingsRef = el), shortcuts: this.shortcuts, editorId: this.editorId, onSettingsChange: event => this.handleSettingsChange(event) }), index.h("kritzel-export", { key: '48d7221954707a7bb6e8d657a5037de422784ff7', ref: el => (this.exportRef = el), workspaceName: this.activeWorkspace?.name || 'workspace', onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), index.h("kritzel-active-users", { key: '5dff24dab886d9da046ddb1b6476869d7ef96c87', users: this.activeUsers }), shouldShowCurrentUser && (index.h("kritzel-current-user", { key: '41a3b802c8eb7195744e1beb878a6a124f0f32e9', user: this.user })), shouldShowLoginButton && index.h("kritzel-button", { key: '7db44575d89d2b22cf69e15055be74389c6bb615', onButtonClick: () => this.loginDialogRef?.open() }, "Sign in"), index.h("kritzel-more-menu", { key: '8d25b93f9b0e5f4587f65ee2a384e0915b095db9', items: this.moreMenuItems }), index.h("kritzel-share-dialog", { key: '056f2cbc0e41838b22feaa4c819fe9eb580b0b9b', ref: el => (this.shareDialogRef = el), isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: 'cdcd95c3d961499182ddc188756c70c32fbaef55', ref: el => (this.loginDialogRef = el), providers: this.loginConfig.providers, dialogTitle: this.loginConfig.title, subtitle: this.loginConfig.subtitle, onProviderLogin: this.handleProviderLogin })))));
2291
+ return (index.h(index.Host, { key: '0339b3ea217d55c8192efa53ad8059ff2ffdd578' }, index.h("div", { key: '2149a3f5e251a398e0c7815ebb88d251cbc83d9d', class: "top-left-buttons" }, index.h("kritzel-workspace-manager", { key: '727f465560d3a8aa49ebdfba9251df26b748669a', workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), index.h("kritzel-back-to-content", { key: '269748350eef82b390893ed5b8b6516eef85fa1f', visible: this.isBackToContentButtonVisible, onBackToContent: () => this.backToContent() })), index.h("kritzel-engine", { key: 'c8248639b41f4500718d745b55c988b9f63fde27', ref: el => (this.engineRef = el), workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, scaleMin: this.scaleMin, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, wheelEnabled: this.wheelEnabled, theme: this.currentTheme, debugInfo: this.debugInfo, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onActiveWorkspaceChange: event => this.handleActiveWorkspaceChange(event), onObjectsChange: event => this.handleObjectsChange(event), onObjectsAdded: event => this.handleObjectsAdded(event), onObjectsRemoved: event => this.handleObjectsRemoved(event), onObjectsUpdated: event => this.handleObjectsUpdated(event), onUndoStateChange: event => this.handleUndoStateChange(event), onObjectsInViewportChange: event => this.handleObjectsInViewportChange(event), onViewportChange: event => this.handleViewportChange(event), onAwarenessChange: event => this.handleAwarenessChange(event) }), index.h("kritzel-controls", { key: 'fc1be924d9807aba8aad966bf8ea14785064ed45', class: { 'keyboard-open': this.isVirtualKeyboardOpen }, style: { display: this.isControlsVisible ? 'flex' : 'none' }, ref: el => (this.controlsRef = el), controls: this.controls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState, theme: this.currentTheme, onIsControlsReady: () => (this.isControlsReady = true) }), index.h("div", { key: '12800aa2e7833e838b91d194274344a904d5410b', class: "top-right-buttons" }, index.h("kritzel-settings", { key: 'cb540f195a5a56159999c7d33fccbf94a9d25764', ref: el => (this.settingsRef = el), shortcuts: this.shortcuts, editorId: this.editorId, onSettingsChange: event => this.handleSettingsChange(event) }), index.h("kritzel-export", { key: 'fd17ac3acbf352ee2e1ca797bd72b2d9a4183323', ref: el => (this.exportRef = el), workspaceName: this.activeWorkspace?.name || 'workspace', onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), index.h("kritzel-active-users", { key: '74879be875fe6db127f4864f8aad08f39901e053', users: this.activeUsers }), shouldShowCurrentUser && (index.h("kritzel-current-user", { key: 'a4bc322c69f0784c39c043f0089853babbdd1584', user: this.user })), shouldShowLoginButton && index.h("kritzel-button", { key: 'fb89dd330087ee2dd7288285071ee28a97bcec8e', onButtonClick: () => this.loginDialogRef?.open() }, "Sign in"), index.h("kritzel-more-menu", { key: 'bba9421fab99b82143880478329973f33bfb3039', items: this.moreMenuItems }), index.h("kritzel-share-dialog", { key: 'd03c43ce77c16fd3a5cce7aa134d5ef73361d8b3', ref: el => (this.shareDialogRef = el), isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (index.h("kritzel-login-dialog", { key: 'ced23497db2b7abea1f2121085a21ed9208ecba9', ref: el => (this.loginDialogRef = el), providers: this.loginConfig.providers, dialogTitle: this.loginConfig.title, subtitle: this.loginConfig.subtitle, onProviderLogin: this.handleProviderLogin })))));
2282
2292
  }
2283
2293
  static get watchers() { return {
2284
2294
  "isEngineReady": [{
@@ -19692,7 +19702,7 @@ class KritzelViewport {
19692
19702
  if (event.pointerType === 'mouse') {
19693
19703
  const adjustedClientX = event.clientX - this._core.store.offsetX;
19694
19704
  const adjustedClientY = event.clientY - this._core.store.offsetY;
19695
- if (event.button === alignment_enum.KritzelMouseButton.Right) {
19705
+ if (event.button === workspace_migrations.KritzelMouseButton.Right) {
19696
19706
  this._core.store.state.isPanning = true;
19697
19707
  this._core.store.state.startX = adjustedClientX;
19698
19708
  this._core.store.state.startY = adjustedClientY;
@@ -19708,7 +19718,7 @@ class KritzelViewport {
19708
19718
  // Clear selection box when scaling starts to prevent it from remaining on screen
19709
19719
  if (this._core.store.state.isSelecting) {
19710
19720
  this._core.store.state.isSelecting = false;
19711
- this._core.store.state.objects.remove(obj => obj instanceof alignment_enum.KritzelSelectionBox);
19721
+ this._core.store.state.objects.remove(obj => obj instanceof workspace_migrations.KritzelSelectionBox);
19712
19722
  this._core.store.setSelectionBox(null);
19713
19723
  // Clear selection preview state from objects - use selectedObjects for efficiency
19714
19724
  this._core.store.selectedObjects.forEach(object => {
@@ -20153,7 +20163,7 @@ const NUDGE_AMOUNT = 10;
20153
20163
  * Provides functionality for tool switching, clipboard operations, object manipulation,
20154
20164
  * undo/redo, and navigation via keyboard input.
20155
20165
  */
20156
- class KritzelKeyHandler extends alignment_enum.KritzelBaseHandler {
20166
+ class KritzelKeyHandler extends workspace_migrations.KritzelBaseHandler {
20157
20167
  /**
20158
20168
  * Array of registered keyboard shortcuts with their associated actions.
20159
20169
  * Each shortcut defines the key combination, display label, category, optional condition, and action to execute.
@@ -20218,7 +20228,7 @@ class KritzelKeyHandler extends alignment_enum.KritzelBaseHandler {
20218
20228
  * @param index - The zero-based index of the tool to activate from the tool registry.
20219
20229
  */
20220
20230
  switchToolByIndex(index) {
20221
- const toolInstance = alignment_enum.KritzelToolRegistry.getToolByIndex(index);
20231
+ const toolInstance = workspace_migrations.KritzelToolRegistry.getToolByIndex(index);
20222
20232
  if (toolInstance) {
20223
20233
  this._core.store.setState('activeTool', toolInstance);
20224
20234
  this._core.deselectAllObjects();
@@ -20267,7 +20277,7 @@ class KritzelKeyHandler extends alignment_enum.KritzelBaseHandler {
20267
20277
  * Manages the display and positioning of context menus, selecting appropriate menu items
20268
20278
  * based on whether an object is targeted or the canvas background is right-clicked.
20269
20279
  */
20270
- class KritzelContextMenuHandler extends alignment_enum.KritzelBaseHandler {
20280
+ class KritzelContextMenuHandler extends workspace_migrations.KritzelBaseHandler {
20271
20281
  /**
20272
20282
  * Menu items to display when the context menu is opened on the canvas background
20273
20283
  * (i.e., when no object is selected).
@@ -20303,7 +20313,7 @@ class KritzelContextMenuHandler extends alignment_enum.KritzelBaseHandler {
20303
20313
  * @returns void - This method does not return a value; it updates state and triggers a rerender.
20304
20314
  */
20305
20315
  handleContextMenu(event) {
20306
- if (!(this._core.store.state.activeTool instanceof alignment_enum.KritzelSelectionTool)) {
20316
+ if (!(this._core.store.state.activeTool instanceof workspace_migrations.KritzelSelectionTool)) {
20307
20317
  return;
20308
20318
  }
20309
20319
  if (this._core.store.state.skipContextMenu) {
@@ -20313,13 +20323,13 @@ class KritzelContextMenuHandler extends alignment_enum.KritzelBaseHandler {
20313
20323
  const selectionTool = this._core.store.state.activeTool;
20314
20324
  selectionTool?.moveHandler?.cancelPendingDrag();
20315
20325
  if (this._core.store.selectionBox) {
20316
- this._core.store.state.objects.remove(object => object instanceof alignment_enum.KritzelSelectionBox);
20326
+ this._core.store.state.objects.remove(object => object instanceof workspace_migrations.KritzelSelectionBox);
20317
20327
  this._core.store.setSelectionBox(null);
20318
20328
  this._core.store.state.isSelecting = false;
20319
20329
  }
20320
20330
  const selectedObject = this._core.getObjectFromPointerEvent(event, '.object');
20321
- if (selectedObject && !(selectedObject instanceof alignment_enum.KritzelSelectionGroup) && !(selectedObject instanceof alignment_enum.KritzelSelectionBox)) {
20322
- const selectionGroup = alignment_enum.KritzelSelectionGroup.create(this._core);
20331
+ if (selectedObject && !(selectedObject instanceof workspace_migrations.KritzelSelectionGroup) && !(selectedObject instanceof workspace_migrations.KritzelSelectionBox)) {
20332
+ const selectionGroup = workspace_migrations.KritzelSelectionGroup.create(this._core);
20323
20333
  selectionGroup.addOrRemove(selectedObject);
20324
20334
  selectionGroup.isSelected = true;
20325
20335
  selectionGroup.rotation = selectedObject.rotation;
@@ -20358,7 +20368,7 @@ class KritzelContextMenuHandler extends alignment_enum.KritzelBaseHandler {
20358
20368
  * Extends KritzelBaseObject to inherit common object functionality like positioning,
20359
20369
  * scaling, and lifecycle management.
20360
20370
  */
20361
- class KritzelCustomElement extends alignment_enum.KritzelBaseObject {
20371
+ class KritzelCustomElement extends workspace_migrations.KritzelBaseObject {
20362
20372
  __class__ = 'KritzelCustomElement';
20363
20373
  /** The HTML element to be rendered on the canvas. */
20364
20374
  element;
@@ -20502,16 +20512,16 @@ class KritzelReviver {
20502
20512
  let revivedObj;
20503
20513
  switch (obj.__class__) {
20504
20514
  case 'KritzelPath':
20505
- revivedObj = alignment_enum.KritzelPath.create(this._core).deserialize(obj);
20515
+ revivedObj = workspace_migrations.KritzelPath.create(this._core).deserialize(obj);
20506
20516
  break;
20507
20517
  case 'KritzelLine':
20508
- revivedObj = alignment_enum.KritzelLine.create(this._core).deserialize(obj);
20518
+ revivedObj = workspace_migrations.KritzelLine.create(this._core).deserialize(obj);
20509
20519
  break;
20510
20520
  case 'KritzelText':
20511
- revivedObj = alignment_enum.KritzelText.create(this._core, obj.fontSize, obj.fontFamily).deserialize(obj);
20521
+ revivedObj = workspace_migrations.KritzelText.create(this._core, obj.fontSize, obj.fontFamily).deserialize(obj);
20512
20522
  break;
20513
20523
  case 'KritzelShape':
20514
- revivedObj = alignment_enum.KritzelShape.create(this._core, {
20524
+ revivedObj = workspace_migrations.KritzelShape.create(this._core, {
20515
20525
  shapeType: obj.shapeType,
20516
20526
  fillColor: obj.fillColor,
20517
20527
  strokeColor: obj.strokeColor,
@@ -20522,40 +20532,40 @@ class KritzelReviver {
20522
20532
  }).deserialize(obj);
20523
20533
  break;
20524
20534
  case 'KritzelImage':
20525
- revivedObj = alignment_enum.KritzelImage.create(this._core).deserialize(obj);
20535
+ revivedObj = workspace_migrations.KritzelImage.create(this._core).deserialize(obj);
20526
20536
  break;
20527
20537
  case 'KritzelCustomElement':
20528
20538
  revivedObj = KritzelCustomElement.create(this._core).deserialize(obj);
20529
20539
  break;
20530
20540
  case 'KritzelSelectionGroup':
20531
- revivedObj = alignment_enum.KritzelSelectionGroup.create(this._core).deserialize(obj);
20541
+ revivedObj = workspace_migrations.KritzelSelectionGroup.create(this._core).deserialize(obj);
20532
20542
  break;
20533
20543
  case 'KritzelGroup':
20534
- revivedObj = alignment_enum.KritzelGroup.create(this._core).deserialize(obj);
20544
+ revivedObj = workspace_migrations.KritzelGroup.create(this._core).deserialize(obj);
20535
20545
  break;
20536
20546
  case 'KritzelWorkspace':
20537
- revivedObj = alignment_enum.KritzelWorkspace.create(this._core, obj).deserialize(obj);
20547
+ revivedObj = workspace_migrations.KritzelWorkspace.create(this._core, obj).deserialize(obj);
20538
20548
  break;
20539
20549
  case 'KritzelBrushTool':
20540
- revivedObj = new alignment_enum.KritzelBrushTool(this._core);
20550
+ revivedObj = new workspace_migrations.KritzelBrushTool(this._core);
20541
20551
  break;
20542
20552
  case 'KritzelEraserTool':
20543
- revivedObj = new alignment_enum.KritzelEraserTool(this._core);
20553
+ revivedObj = new workspace_migrations.KritzelEraserTool(this._core);
20544
20554
  break;
20545
20555
  case 'KritzelImageTool':
20546
- revivedObj = new alignment_enum.KritzelImageTool(this._core);
20556
+ revivedObj = new workspace_migrations.KritzelImageTool(this._core);
20547
20557
  break;
20548
20558
  case 'KritzelSelectionTool':
20549
- revivedObj = new alignment_enum.KritzelSelectionTool(this._core);
20559
+ revivedObj = new workspace_migrations.KritzelSelectionTool(this._core);
20550
20560
  break;
20551
20561
  case 'KritzelTextTool':
20552
- revivedObj = new alignment_enum.KritzelTextTool(this._core);
20562
+ revivedObj = new workspace_migrations.KritzelTextTool(this._core);
20553
20563
  break;
20554
20564
  case 'KritzelLineTool':
20555
- revivedObj = new alignment_enum.KritzelLineTool(this._core);
20565
+ revivedObj = new workspace_migrations.KritzelLineTool(this._core);
20556
20566
  break;
20557
20567
  case 'KritzelShapeTool':
20558
- revivedObj = new alignment_enum.KritzelShapeTool(this._core);
20568
+ revivedObj = new workspace_migrations.KritzelShapeTool(this._core);
20559
20569
  break;
20560
20570
  default:
20561
20571
  revivedObj = obj;
@@ -20610,7 +20620,8 @@ const DEFAULT_ENGINE_CONFIG = {
20610
20620
  debugInfo: {
20611
20621
  showObjectInfo: false,
20612
20622
  showViewportInfo: false,
20613
- showSyncProviderInfo: true
20623
+ showSyncProviderInfo: true,
20624
+ showMigrationInfo: true
20614
20625
  },
20615
20626
  host: null,
20616
20627
  pointerX: 0,
@@ -20679,32 +20690,32 @@ class AlignmentHelper {
20679
20690
  const offsetX = objBounds.x - obj.translateX;
20680
20691
  const offsetY = objBounds.y - obj.translateY;
20681
20692
  switch (alignment) {
20682
- case alignment_enum.KritzelAlignment.StartHorizontal:
20693
+ case workspace_migrations.KritzelAlignment.StartHorizontal:
20683
20694
  // Align left edges to selection's left edge
20684
20695
  newTranslateX = selectionBounds.minX - offsetX;
20685
20696
  break;
20686
- case alignment_enum.KritzelAlignment.CenterHorizontal:
20697
+ case workspace_migrations.KritzelAlignment.CenterHorizontal:
20687
20698
  // Align centers horizontally
20688
20699
  const selectionCenterX = (selectionBounds.minX + selectionBounds.maxX) / 2;
20689
20700
  const objCenterX = objBounds.x + objBounds.width / 2;
20690
20701
  newTranslateX = obj.translateX + (selectionCenterX - objCenterX);
20691
20702
  break;
20692
- case alignment_enum.KritzelAlignment.EndHorizontal:
20703
+ case workspace_migrations.KritzelAlignment.EndHorizontal:
20693
20704
  // Align right edges to selection's right edge
20694
20705
  const objRightEdge = objBounds.x + objBounds.width;
20695
20706
  newTranslateX = obj.translateX + (selectionBounds.maxX - objRightEdge);
20696
20707
  break;
20697
- case alignment_enum.KritzelAlignment.StartVertical:
20708
+ case workspace_migrations.KritzelAlignment.StartVertical:
20698
20709
  // Align top edges to selection's top edge
20699
20710
  newTranslateY = selectionBounds.minY - offsetY;
20700
20711
  break;
20701
- case alignment_enum.KritzelAlignment.CenterVertical:
20712
+ case workspace_migrations.KritzelAlignment.CenterVertical:
20702
20713
  // Align centers vertically
20703
20714
  const selectionCenterY = (selectionBounds.minY + selectionBounds.maxY) / 2;
20704
20715
  const objCenterY = objBounds.y + objBounds.height / 2;
20705
20716
  newTranslateY = obj.translateY + (selectionCenterY - objCenterY);
20706
20717
  break;
20707
- case alignment_enum.KritzelAlignment.EndVertical:
20718
+ case workspace_migrations.KritzelAlignment.EndVertical:
20708
20719
  // Align bottom edges to selection's bottom edge
20709
20720
  const objBottomEdge = objBounds.y + objBounds.height;
20710
20721
  newTranslateY = obj.translateY + (selectionBounds.maxY - objBottomEdge);
@@ -20721,7 +20732,7 @@ class AlignmentHelper {
20721
20732
  */
20722
20733
  const DEFAULT_SYNC_CONFIG = {
20723
20734
  providers: [
20724
- alignment_enum.IndexedDBSyncProvider
20735
+ workspace_migrations.IndexedDBSyncProvider
20725
20736
  ],
20726
20737
  };
20727
20738
 
@@ -21189,6 +21200,9 @@ class KritzelObjectMap {
21189
21200
  // Initialize document metadata (only if not already set by a previous client)
21190
21201
  const workspaceName = core.store?.state?.activeWorkspace?.name ?? '';
21191
21202
  this.initializeMetadata('workspace', workspaceId, workspaceName);
21203
+ // Run any pending schema migrations before loading data
21204
+ const quietMigrations = !core.store?.state?.debugInfo?.showMigrationInfo;
21205
+ workspace_migrations.runMigrations(this._ydoc, this._metadataMap, { objects: this._objectsMap }, workspace_migrations.WORKSPACE_MIGRATIONS, workspace_migrations.CURRENT_WORKSPACE_SCHEMA_VERSION, { quiet: quietMigrations });
21192
21206
  // Load objects from Yjs
21193
21207
  this.loadFromYjs();
21194
21208
  }
@@ -21206,6 +21220,10 @@ class KritzelObjectMap {
21206
21220
  this._core?.rerender();
21207
21221
  return;
21208
21222
  }
21223
+ // Skip migration transactions — data will be loaded fresh via loadFromYjs()
21224
+ if (event.transaction.origin === 'migration') {
21225
+ return;
21226
+ }
21209
21227
  const changedKeys = Array.from(event.keysChanged);
21210
21228
  const objectsToUpdate = [];
21211
21229
  const selectionGroupsToUpdate = [];
@@ -21220,7 +21238,7 @@ class KritzelObjectMap {
21220
21238
  if (serialized) {
21221
21239
  const object = this._reviver.revive(serialized);
21222
21240
  // Separate SelectionGroups to process them after regular objects
21223
- if (object instanceof alignment_enum.KritzelSelectionGroup) {
21241
+ if (object instanceof workspace_migrations.KritzelSelectionGroup) {
21224
21242
  selectionGroupsToUpdate.push(object);
21225
21243
  }
21226
21244
  else {
@@ -21283,7 +21301,7 @@ class KritzelObjectMap {
21283
21301
  ...objectsToDelete
21284
21302
  ]);
21285
21303
  // Find any existing SelectionGroups that contain changed objects
21286
- const existingSelectionGroups = this.quadtree.filter(o => o instanceof alignment_enum.KritzelSelectionGroup && !updatedSelectionGroupIds.has(o.id));
21304
+ const existingSelectionGroups = this.quadtree.filter(o => o instanceof workspace_migrations.KritzelSelectionGroup && !updatedSelectionGroupIds.has(o.id));
21287
21305
  for (const selectionGroup of existingSelectionGroups) {
21288
21306
  const hasChangedChildren = selectionGroup.objectIds.some(id => changedObjectIds.has(id));
21289
21307
  if (hasChangedChildren) {
@@ -21327,6 +21345,9 @@ class KritzelObjectMap {
21327
21345
  if (this._metadataMap.get('isPublic') === undefined) {
21328
21346
  this._metadataMap.set('isPublic', false);
21329
21347
  }
21348
+ if (this._metadataMap.get('schemaVersion') === undefined) {
21349
+ this._metadataMap.set('schemaVersion', workspace_migrations.CURRENT_WORKSPACE_SCHEMA_VERSION);
21350
+ }
21330
21351
  this._metadataMap.set('workspaceId', workspaceId);
21331
21352
  this._metadataMap.set('workspaceName', workspaceName);
21332
21353
  }, 'metadata');
@@ -21533,7 +21554,7 @@ class KritzelObjectMap {
21533
21554
  * @returns `true` if the object should be persisted, `false` otherwise
21534
21555
  */
21535
21556
  isPersistable(object) {
21536
- if (object instanceof alignment_enum.KritzelSelectionBox) {
21557
+ if (object instanceof workspace_migrations.KritzelSelectionBox) {
21537
21558
  return false;
21538
21559
  }
21539
21560
  return true;
@@ -21744,7 +21765,7 @@ class KritzelStore {
21744
21765
  * @returns The next z-index value to use for new objects
21745
21766
  */
21746
21767
  get currentZIndex() {
21747
- return Math.max(0, ...this._state.objects.filter(o => !(o instanceof alignment_enum.KritzelSelectionGroup) && !(o instanceof alignment_enum.KritzelSelectionBox)).map(o => o.zIndex)) + 1;
21768
+ return Math.max(0, ...this._state.objects.filter(o => !(o instanceof workspace_migrations.KritzelSelectionGroup) && !(o instanceof workspace_migrations.KritzelSelectionBox)).map(o => o.zIndex)) + 1;
21748
21769
  }
21749
21770
  /**
21750
21771
  * Returns true if viewport boundaries are set to finite values (not Infinity).
@@ -21817,14 +21838,14 @@ class KritzelStore {
21817
21838
  * @returns Array of all regular canvas objects
21818
21839
  */
21819
21840
  get allNonSelectionObjects() {
21820
- return this.allObjects.filter(o => !(o instanceof alignment_enum.KritzelSelectionGroup) && !(o instanceof alignment_enum.KritzelSelectionBox));
21841
+ return this.allObjects.filter(o => !(o instanceof workspace_migrations.KritzelSelectionGroup) && !(o instanceof workspace_migrations.KritzelSelectionBox));
21821
21842
  }
21822
21843
  /**
21823
21844
  * Gets all currently selected objects (excluding the selection group itself).
21824
21845
  * @returns Array of selected objects
21825
21846
  */
21826
21847
  get selectedObjects() {
21827
- return this.allObjects.filter(o => !(o instanceof alignment_enum.KritzelSelectionGroup)).filter(o => o.isSelected);
21848
+ return this.allObjects.filter(o => !(o instanceof workspace_migrations.KritzelSelectionGroup)).filter(o => o.isSelected);
21828
21849
  }
21829
21850
  /**
21830
21851
  * Gets the current selection box if one exists.
@@ -21835,7 +21856,7 @@ class KritzelStore {
21835
21856
  if (this._selectionBoxCacheValid) {
21836
21857
  return this._cachedSelectionBox;
21837
21858
  }
21838
- const selectionBoxes = this._state.objects.filter(o => o instanceof alignment_enum.KritzelSelectionBox);
21859
+ const selectionBoxes = this._state.objects.filter(o => o instanceof workspace_migrations.KritzelSelectionBox);
21839
21860
  this._cachedSelectionBox = selectionBoxes.length > 0 ? selectionBoxes[0] : null;
21840
21861
  this._selectionBoxCacheValid = true;
21841
21862
  return this._cachedSelectionBox;
@@ -21849,7 +21870,7 @@ class KritzelStore {
21849
21870
  if (this._selectionGroupCacheValid) {
21850
21871
  return this._cachedSelectionGroup;
21851
21872
  }
21852
- const selectionGroups = this._state.objects.filter(o => o instanceof alignment_enum.KritzelSelectionGroup);
21873
+ const selectionGroups = this._state.objects.filter(o => o instanceof workspace_migrations.KritzelSelectionGroup);
21853
21874
  this._cachedSelectionGroup = selectionGroups.length > 0 ? selectionGroups[0] : null;
21854
21875
  this._selectionGroupCacheValid = true;
21855
21876
  return this._cachedSelectionGroup;
@@ -21884,7 +21905,7 @@ class KritzelStore {
21884
21905
  * @returns The text object in editing mode, or null if none
21885
21906
  */
21886
21907
  get activeText() {
21887
- const activeTexts = this._state.objects.filter(o => o instanceof alignment_enum.KritzelText && o.isEditing);
21908
+ const activeTexts = this._state.objects.filter(o => o instanceof workspace_migrations.KritzelText && o.isEditing);
21888
21909
  return activeTexts.length > 0 ? activeTexts[0] : null;
21889
21910
  }
21890
21911
  /**
@@ -21892,7 +21913,7 @@ class KritzelStore {
21892
21913
  * @returns The shape object in editing mode, or null if none
21893
21914
  */
21894
21915
  get activeShape() {
21895
- const activeShapes = this._state.objects.filter(o => o instanceof alignment_enum.KritzelShape && o.isEditing);
21916
+ const activeShapes = this._state.objects.filter(o => o instanceof workspace_migrations.KritzelShape && o.isEditing);
21896
21917
  return activeShapes.length > 0 ? activeShapes[0] : null;
21897
21918
  }
21898
21919
  /**
@@ -21900,7 +21921,7 @@ class KritzelStore {
21900
21921
  * @returns The incomplete path object, or null if no path is being drawn
21901
21922
  */
21902
21923
  get currentPath() {
21903
- const drawingPaths = this._state.objects.filter(o => o instanceof alignment_enum.KritzelPath && o.isCompleted === false);
21924
+ const drawingPaths = this._state.objects.filter(o => o instanceof workspace_migrations.KritzelPath && o.isCompleted === false);
21904
21925
  return drawingPaths.length > 0 ? drawingPaths[0] : null;
21905
21926
  }
21906
21927
  /**
@@ -21908,7 +21929,7 @@ class KritzelStore {
21908
21929
  * @returns The incomplete line object, or null if no line is being drawn
21909
21930
  */
21910
21931
  get currentLine() {
21911
- const drawingLines = this._state.objects.filter(o => o instanceof alignment_enum.KritzelLine && o.isCompleted === false);
21932
+ const drawingLines = this._state.objects.filter(o => o instanceof workspace_migrations.KritzelLine && o.isCompleted === false);
21912
21933
  return drawingLines.length > 0 ? drawingLines[0] : null;
21913
21934
  }
21914
21935
  /**
@@ -22071,6 +22092,9 @@ class KritzelAppStateMap {
22071
22092
  }
22072
22093
  });
22073
22094
  this._isReady = true;
22095
+ // Run any pending schema migrations before loading data
22096
+ const quietMigrations = !core.store.state.debugInfo.showMigrationInfo;
22097
+ workspace_migrations.runMigrations(this._ydoc, this._metadataMap, { workspaces: this._workspacesMap }, workspace_migrations.APP_STATE_MIGRATIONS, workspace_migrations.CURRENT_APP_STATE_SCHEMA_VERSION, { quiet: quietMigrations });
22074
22098
  // Initialize document metadata (only if not already set by a previous client)
22075
22099
  this.initializeMetadata('state');
22076
22100
  // Load workspaces from Yjs
@@ -22099,7 +22123,7 @@ class KritzelAppStateMap {
22099
22123
  if (instanceId) {
22100
22124
  return instanceId;
22101
22125
  }
22102
- const generatedInstanceId = alignment_enum.ObjectHelper.generateUUID();
22126
+ const generatedInstanceId = workspace_migrations.ObjectHelper.generateUUID();
22103
22127
  try {
22104
22128
  storage.setItem(storageKey, generatedInstanceId);
22105
22129
  }
@@ -22120,6 +22144,10 @@ class KritzelAppStateMap {
22120
22144
  this._core?.rerender();
22121
22145
  return;
22122
22146
  }
22147
+ // Skip migration transactions — data will be loaded fresh via loadFromYjs()
22148
+ if (event.transaction.origin === 'migration') {
22149
+ return;
22150
+ }
22123
22151
  const changedKeys = Array.from(event.keysChanged);
22124
22152
  const workspacesToUpdate = [];
22125
22153
  const workspacesToDelete = [];
@@ -22157,11 +22185,22 @@ class KritzelAppStateMap {
22157
22185
  /**
22158
22186
  * Reconstructs a KritzelWorkspace instance from its serialized form.
22159
22187
  * Restores all properties including id, name, viewport, and timestamps.
22188
+ * Handles both legacy { translateX, translateY } and new { centerWorldX, centerWorldY } viewport formats.
22160
22189
  * @param serialized - The serialized workspace data object.
22161
22190
  * @returns A fully reconstructed KritzelWorkspace instance.
22162
22191
  */
22163
22192
  reviveWorkspace(serialized) {
22164
- const workspace = new alignment_enum.KritzelWorkspace(serialized.id, serialized.name, serialized.viewport);
22193
+ let viewport = serialized.viewport;
22194
+ // Backward compatibility: convert legacy translateX/translateY to centerWorldX/centerWorldY
22195
+ if (viewport && 'translateX' in viewport && !('centerWorldX' in viewport)) {
22196
+ const scale = viewport.scale ?? 1;
22197
+ viewport = {
22198
+ centerWorldX: -(viewport.translateX ?? 0) / scale,
22199
+ centerWorldY: -(viewport.translateY ?? 0) / scale,
22200
+ scale,
22201
+ };
22202
+ }
22203
+ const workspace = new workspace_migrations.KritzelWorkspace(serialized.id, serialized.name, viewport);
22165
22204
  workspace._core = this._core;
22166
22205
  workspace.createdAt = new Date(serialized.createdAt);
22167
22206
  workspace.updatedAt = new Date(serialized.updatedAt);
@@ -22183,6 +22222,9 @@ class KritzelAppStateMap {
22183
22222
  if (this._metadataMap.get('isPublic') === undefined) {
22184
22223
  this._metadataMap.set('isPublic', false);
22185
22224
  }
22225
+ if (this._metadataMap.get('schemaVersion') === undefined) {
22226
+ this._metadataMap.set('schemaVersion', workspace_migrations.CURRENT_APP_STATE_SCHEMA_VERSION);
22227
+ }
22186
22228
  }, 'metadata');
22187
22229
  }
22188
22230
  /**
@@ -22404,7 +22446,7 @@ class KritzelCursorManager {
22404
22446
  this._targetElement = element;
22405
22447
  // Set the pointer cursor CSS variable for child components to use
22406
22448
  if (this._targetElement) {
22407
- this._targetElement.style.setProperty('--kritzel-global-pointer-cursor', alignment_enum.KritzelCursorHelper.getPointerCursor());
22449
+ this._targetElement.style.setProperty('--kritzel-global-pointer-cursor', workspace_migrations.KritzelCursorHelper.getPointerCursor());
22408
22450
  }
22409
22451
  }
22410
22452
  /**
@@ -22490,7 +22532,7 @@ class KritzelCursorManager {
22490
22532
  const icon = state.cursor?.icon;
22491
22533
  const iconActive = state.cursor?.iconActive ?? icon;
22492
22534
  const rotation = state.cursor?.rotation;
22493
- const cursor = alignment_enum.KritzelCursorHelper.getCursor({
22535
+ const cursor = workspace_migrations.KritzelCursorHelper.getCursor({
22494
22536
  iconName: isPointerDown ? iconActive : icon,
22495
22537
  rotation: rotation,
22496
22538
  });
@@ -22620,9 +22662,9 @@ class KritzelCore {
22620
22662
  this._editorId = editorId;
22621
22663
  this._store = new KritzelStore(DEFAULT_ENGINE_CONFIG);
22622
22664
  this._appStateMap = new KritzelAppStateMap();
22623
- this._anchorManager = new alignment_enum.KritzelAnchorManager(this);
22665
+ this._anchorManager = new workspace_migrations.KritzelAnchorManager(this);
22624
22666
  this._cursorManager = new KritzelCursorManager(this);
22625
- this._themeManager = new alignment_enum.KritzelThemeManager(this);
22667
+ this._themeManager = new workspace_migrations.KritzelThemeManager(this);
22626
22668
  }
22627
22669
  /**
22628
22670
  * Sets the synchronization configuration for collaborative features.
@@ -22640,7 +22682,7 @@ class KritzelCore {
22640
22682
  setEditorId(editorId) {
22641
22683
  this._editorId = editorId;
22642
22684
  // Re-create theme manager so it picks up the new storage key
22643
- this._themeManager = new alignment_enum.KritzelThemeManager(this);
22685
+ this._themeManager = new workspace_migrations.KritzelThemeManager(this);
22644
22686
  }
22645
22687
  /**
22646
22688
  * Initializes the Yjs document for collaborative editing.
@@ -22719,7 +22761,7 @@ class KritzelCore {
22719
22761
  }
22720
22762
  else {
22721
22763
  // Create fallback workspace
22722
- activeWorkspace = new alignment_enum.KritzelWorkspace(alignment_enum.ObjectHelper.generateUUID(), 'New Workspace');
22764
+ activeWorkspace = new workspace_migrations.KritzelWorkspace(workspace_migrations.ObjectHelper.generateUUID(), 'New Workspace');
22723
22765
  activeWorkspace._core = this;
22724
22766
  this.saveWorkspaceToAppState(activeWorkspace);
22725
22767
  }
@@ -22737,11 +22779,14 @@ class KritzelCore {
22737
22779
  // Set active workspace
22738
22780
  this._store.state.activeWorkspace = activeWorkspace;
22739
22781
  this._store.state.workspaces = this.loadWorkspacesFromAppState();
22740
- // Set viewport from workspace
22741
- const viewport = activeWorkspace.viewport ?? { translateX: 0, translateY: 0, scale: 1 };
22742
- this._store.state.translateX = viewport.translateX ?? 0;
22743
- this._store.state.translateY = viewport.translateY ?? 0;
22744
- this._store.state.scale = viewport.scale ?? 1;
22782
+ // Set viewport from workspace (convert world-space center to screen-space translate)
22783
+ const viewport = activeWorkspace.viewport ?? { centerWorldX: 0, centerWorldY: 0, scale: 1 };
22784
+ const scale = viewport.scale ?? 1;
22785
+ const viewportWidth = this._store.state.viewportWidth;
22786
+ const viewportHeight = this._store.state.viewportHeight;
22787
+ this._store.state.translateX = viewportWidth / 2 - (viewport.centerWorldX ?? 0) * scale;
22788
+ this._store.state.translateY = viewportHeight / 2 - (viewport.centerWorldY ?? 0) * scale;
22789
+ this._store.state.scale = scale;
22745
22790
  await objectsMap.initialize(this, activeWorkspace.id, this._syncConfig);
22746
22791
  // Set local user in awareness after object map is initialized
22747
22792
  if (this._user) {
@@ -22769,7 +22814,7 @@ class KritzelCore {
22769
22814
  let workspace = this.getWorkspaces().find(w => w.id === workspaceId);
22770
22815
  if (!workspace) {
22771
22816
  // Create it if it doesn't exist locally
22772
- workspace = new alignment_enum.KritzelWorkspace(workspaceId, name);
22817
+ workspace = new workspace_migrations.KritzelWorkspace(workspaceId, name);
22773
22818
  workspace.isPublic = true;
22774
22819
  this.createWorkspace(workspace);
22775
22820
  }
@@ -22796,7 +22841,7 @@ class KritzelCore {
22796
22841
  };
22797
22842
  return this._store.state.objects
22798
22843
  .query(viewportBounds)
22799
- .filter(obj => !(obj instanceof alignment_enum.KritzelSelectionGroup) && !(obj instanceof alignment_enum.KritzelSelectionBox))
22844
+ .filter(obj => !(obj instanceof workspace_migrations.KritzelSelectionGroup) && !(obj instanceof workspace_migrations.KritzelSelectionBox))
22800
22845
  .sort((a, b) => a.zIndex - b.zIndex);
22801
22846
  }
22802
22847
  /**
@@ -22883,6 +22928,7 @@ class KritzelCore {
22883
22928
  }
22884
22929
  /**
22885
22930
  * Persists the current viewport state to the active workspace.
22931
+ * Converts screen-space translate values to device-independent world-space center coordinates.
22886
22932
  * Validates that the workspace still exists before saving.
22887
22933
  * @param translateX - The X translation of the viewport
22888
22934
  * @param translateY - The Y translation of the viewport
@@ -22898,7 +22944,12 @@ class KritzelCore {
22898
22944
  if (!isValid) {
22899
22945
  return;
22900
22946
  }
22901
- activeWorkspace.viewport = { translateX, translateY, scale };
22947
+ // Convert screen-space translate to device-independent world-space center
22948
+ const viewportWidth = this._store.state.viewportWidth;
22949
+ const viewportHeight = this._store.state.viewportHeight;
22950
+ const centerWorldX = (viewportWidth / 2 - translateX) / scale;
22951
+ const centerWorldY = (viewportHeight / 2 - translateY) / scale;
22952
+ activeWorkspace.viewport = { centerWorldX, centerWorldY, scale };
22902
22953
  activeWorkspace.updatedAt = new Date();
22903
22954
  this.saveWorkspaceToAppState(activeWorkspace);
22904
22955
  }
@@ -22928,7 +22979,7 @@ class KritzelCore {
22928
22979
  */
22929
22980
  removeObject(object, preserveChildren = false) {
22930
22981
  // Handle KritzelGroup: recursively delete all children first (unless preserveChildren is true)
22931
- if (alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup') && !preserveChildren) {
22982
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup') && !preserveChildren) {
22932
22983
  // Get children before removing the group
22933
22984
  const children = [...object.children];
22934
22985
  children.forEach(child => {
@@ -22936,7 +22987,7 @@ class KritzelCore {
22936
22987
  });
22937
22988
  }
22938
22989
  // Handle anchor cleanup
22939
- if (alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelLine')) {
22990
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelLine')) {
22940
22991
  // If removing a line, clean up its anchor index entries
22941
22992
  this._anchorManager.handleLineDeleted(object.id);
22942
22993
  }
@@ -23127,7 +23178,7 @@ class KritzelCore {
23127
23178
  this.removeSelectionGroup();
23128
23179
  this.removeSelectionBox();
23129
23180
  // Create a new selection group for the pasted objects
23130
- const selectionGroup = alignment_enum.KritzelSelectionGroup.create(this);
23181
+ const selectionGroup = workspace_migrations.KritzelSelectionGroup.create(this);
23131
23182
  // Build a reverse mapping: originalId -> newCopiedObjectId
23132
23183
  // This is used to remap anchor references from original IDs to the copied object IDs
23133
23184
  const originalToNewIdMap = new Map();
@@ -23152,7 +23203,7 @@ class KritzelCore {
23152
23203
  // Update z-index
23153
23204
  obj.zIndex = baseZIndex + i;
23154
23205
  // Handle KritzelGroup: also add pending children with offset
23155
- if (alignment_enum.KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup')) {
23206
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup')) {
23156
23207
  if (obj._pendingChildren.length > 0) {
23157
23208
  obj._pendingChildren.forEach((child, childIndex) => {
23158
23209
  // Update workspace
@@ -23180,7 +23231,7 @@ class KritzelCore {
23180
23231
  // Update line anchors to point to the newly pasted objects
23181
23232
  // Only remap if the anchor target was also part of the copied selection
23182
23233
  copiedObjects.forEach(obj => {
23183
- if (alignment_enum.KritzelClassHelper.isInstanceOf(obj, 'KritzelLine')) {
23234
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(obj, 'KritzelLine')) {
23184
23235
  let updated = false;
23185
23236
  if (obj.startAnchor && originalToNewIdMap.has(obj.startAnchor.objectId)) {
23186
23237
  obj.startAnchor = { objectId: originalToNewIdMap.get(obj.startAnchor.objectId) };
@@ -23238,7 +23289,7 @@ class KritzelCore {
23238
23289
  this._store.state.copiedObjectIdMapping = newIdMapping;
23239
23290
  }
23240
23291
  });
23241
- this._store.setState('activeTool', alignment_enum.KritzelToolRegistry.getTool('selection'));
23292
+ this._store.setState('activeTool', workspace_migrations.KritzelToolRegistry.getTool('selection'));
23242
23293
  this.engine.emitObjectsChange();
23243
23294
  this.rerender();
23244
23295
  }
@@ -23338,12 +23389,12 @@ class KritzelCore {
23338
23389
  return;
23339
23390
  }
23340
23391
  // Create a group from the selected objects
23341
- const group = alignment_enum.KritzelGroup.createFromObjects(this, selectionGroup.objects);
23392
+ const group = workspace_migrations.KritzelGroup.createFromObjects(this, selectionGroup.objects);
23342
23393
  // Add the group to the object store
23343
23394
  this.addObject(group);
23344
23395
  // Remove the selection group and create a new one with just the group
23345
23396
  this.removeSelectionGroup();
23346
- const newSelectionGroup = alignment_enum.KritzelSelectionGroup.create(this);
23397
+ const newSelectionGroup = workspace_migrations.KritzelSelectionGroup.create(this);
23347
23398
  newSelectionGroup.addOrRemove(group);
23348
23399
  newSelectionGroup.isSelected = true;
23349
23400
  newSelectionGroup.rotation = group.rotation;
@@ -23360,13 +23411,13 @@ class KritzelCore {
23360
23411
  if (!selectionGroup) {
23361
23412
  return;
23362
23413
  }
23363
- const groups = selectionGroup.objects.filter(obj => alignment_enum.KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup'));
23414
+ const groups = selectionGroup.objects.filter(obj => workspace_migrations.KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup'));
23364
23415
  if (groups.length === 0) {
23365
23416
  return;
23366
23417
  }
23367
23418
  // Collect all children from all groups
23368
23419
  const allChildren = [];
23369
- const nonGroupObjects = selectionGroup.objects.filter(obj => !alignment_enum.KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup'));
23420
+ const nonGroupObjects = selectionGroup.objects.filter(obj => !workspace_migrations.KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup'));
23370
23421
  groups.forEach(group => {
23371
23422
  // Get children before removing the group
23372
23423
  const children = group.ungroup();
@@ -23376,7 +23427,7 @@ class KritzelCore {
23376
23427
  });
23377
23428
  // Create a new selection group with all the ungrouped children and non-group objects
23378
23429
  this.removeSelectionGroup();
23379
- const newSelectionGroup = alignment_enum.KritzelSelectionGroup.create(this);
23430
+ const newSelectionGroup = workspace_migrations.KritzelSelectionGroup.create(this);
23380
23431
  [...allChildren, ...nonGroupObjects].forEach(child => {
23381
23432
  newSelectionGroup.addOrRemove(child);
23382
23433
  });
@@ -23394,7 +23445,7 @@ class KritzelCore {
23394
23445
  if (objects.length === 0) {
23395
23446
  return;
23396
23447
  }
23397
- const selectionGroup = alignment_enum.KritzelSelectionGroup.create(this);
23448
+ const selectionGroup = workspace_migrations.KritzelSelectionGroup.create(this);
23398
23449
  objects.forEach(obj => {
23399
23450
  obj.isSelected = false;
23400
23451
  selectionGroup.addOrRemove(obj);
@@ -23414,9 +23465,9 @@ class KritzelCore {
23414
23465
  selectAllObjects() {
23415
23466
  const allObjects = this._store.state.objects
23416
23467
  .allObjects()
23417
- .filter(o => !(o instanceof alignment_enum.KritzelSelectionGroup) && !(o instanceof alignment_enum.KritzelSelectionBox) && !(o instanceof KritzelContextMenu));
23468
+ .filter(o => !(o instanceof workspace_migrations.KritzelSelectionGroup) && !(o instanceof workspace_migrations.KritzelSelectionBox) && !(o instanceof KritzelContextMenu));
23418
23469
  if (allObjects.length > 0) {
23419
- const selectionGroup = alignment_enum.KritzelSelectionGroup.create(this);
23470
+ const selectionGroup = workspace_migrations.KritzelSelectionGroup.create(this);
23420
23471
  allObjects.forEach(obj => {
23421
23472
  obj.isSelected = false;
23422
23473
  selectionGroup.addOrRemove(obj);
@@ -23427,7 +23478,7 @@ class KritzelCore {
23427
23478
  selectionGroup.rotation = selectionGroup.objects[0].rotation;
23428
23479
  }
23429
23480
  this.addSelectionGroup(selectionGroup);
23430
- this._store.setState('activeTool', alignment_enum.KritzelToolRegistry.getTool('selection'));
23481
+ this._store.setState('activeTool', workspace_migrations.KritzelToolRegistry.getTool('selection'));
23431
23482
  this.rerender();
23432
23483
  }
23433
23484
  }
@@ -23448,9 +23499,9 @@ class KritzelCore {
23448
23499
  const objectsInViewport = this._store.state.objects
23449
23500
  .query(viewportBounds)
23450
23501
  .filter(o => o.isInViewport())
23451
- .filter(o => !(o instanceof alignment_enum.KritzelSelectionGroup) && !(o instanceof alignment_enum.KritzelSelectionBox) && !(o instanceof KritzelContextMenu));
23502
+ .filter(o => !(o instanceof workspace_migrations.KritzelSelectionGroup) && !(o instanceof workspace_migrations.KritzelSelectionBox) && !(o instanceof KritzelContextMenu));
23452
23503
  if (objectsInViewport.length > 0) {
23453
- const selectionGroup = alignment_enum.KritzelSelectionGroup.create(this);
23504
+ const selectionGroup = workspace_migrations.KritzelSelectionGroup.create(this);
23454
23505
  objectsInViewport.forEach(obj => {
23455
23506
  obj.isSelected = false;
23456
23507
  selectionGroup.addOrRemove(obj);
@@ -23461,7 +23512,7 @@ class KritzelCore {
23461
23512
  selectionGroup.rotation = selectionGroup.objects[0].rotation;
23462
23513
  }
23463
23514
  this.addSelectionGroup(selectionGroup);
23464
- this._store.setState('activeTool', alignment_enum.KritzelToolRegistry.getTool('selection'));
23515
+ this._store.setState('activeTool', workspace_migrations.KritzelToolRegistry.getTool('selection'));
23465
23516
  this.rerender();
23466
23517
  }
23467
23518
  }
@@ -23471,7 +23522,7 @@ class KritzelCore {
23471
23522
  */
23472
23523
  clearSelection() {
23473
23524
  this.removeSelectionGroup();
23474
- this._store.state.objects.remove(o => o instanceof alignment_enum.KritzelSelectionBox || o instanceof alignment_enum.KritzelSelectionGroup);
23525
+ this._store.state.objects.remove(o => o instanceof workspace_migrations.KritzelSelectionBox || o instanceof workspace_migrations.KritzelSelectionGroup);
23475
23526
  this._store.setSelectionBox(null);
23476
23527
  this._store.setSelectionGroup(null);
23477
23528
  this._store.state.isSelecting = false;
@@ -23613,7 +23664,7 @@ class KritzelCore {
23613
23664
  }
23614
23665
  this.resetActiveText();
23615
23666
  this.clearSelection();
23616
- this._store.setState('activeTool', alignment_enum.KritzelToolRegistry.getTool('selection'));
23667
+ this._store.setState('activeTool', workspace_migrations.KritzelToolRegistry.getTool('selection'));
23617
23668
  }
23618
23669
  /**
23619
23670
  * Determines whether to display the selection group UI for an object.
@@ -23628,7 +23679,7 @@ class KritzelCore {
23628
23679
  const selectionGroup = this._store.selectionGroup;
23629
23680
  if (!selectionGroup) {
23630
23681
  // During selection phase (no group yet), hide UI for KritzelLine objects
23631
- return !(object instanceof alignment_enum.KritzelLine);
23682
+ return !(object instanceof workspace_migrations.KritzelLine);
23632
23683
  }
23633
23684
  // Show UI if selection contains more than one object
23634
23685
  if (selectionGroup.objects.length > 1) {
@@ -23637,7 +23688,7 @@ class KritzelCore {
23637
23688
  // Hide UI if selection contains a single KritzelLine
23638
23689
  if (selectionGroup.objects.length === 1) {
23639
23690
  const selectedObject = selectionGroup.objects[0];
23640
- return !(selectedObject instanceof alignment_enum.KritzelLine);
23691
+ return !(selectedObject instanceof workspace_migrations.KritzelLine);
23641
23692
  }
23642
23693
  return true;
23643
23694
  }
@@ -23649,7 +23700,7 @@ class KritzelCore {
23649
23700
  */
23650
23701
  displaySelectionLineUI(object) {
23651
23702
  // Only show line UI on KritzelLine objects, not on selection groups
23652
- if (!(object instanceof alignment_enum.KritzelLine)) {
23703
+ if (!(object instanceof workspace_migrations.KritzelLine)) {
23653
23704
  return false;
23654
23705
  }
23655
23706
  // During selection phase (no group yet), show line UI if line is selected
@@ -23663,7 +23714,7 @@ class KritzelCore {
23663
23714
  // Show UI only if selection contains exactly one KritzelLine and it's this object
23664
23715
  if (selectionGroup.objects.length === 1) {
23665
23716
  const selectedObject = selectionGroup.objects[0];
23666
- return selectedObject instanceof alignment_enum.KritzelLine && selectedObject.id === object.id;
23717
+ return selectedObject instanceof workspace_migrations.KritzelLine && selectedObject.id === object.id;
23667
23718
  }
23668
23719
  return false;
23669
23720
  }
@@ -23747,7 +23798,7 @@ class KritzelSvgExportHelper {
23747
23798
  static flattenObjects(objects) {
23748
23799
  const result = [];
23749
23800
  for (const obj of objects) {
23750
- if (alignment_enum.KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup')) {
23801
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(obj, 'KritzelGroup')) {
23751
23802
  result.push(...this.flattenObjects(obj.children));
23752
23803
  }
23753
23804
  else {
@@ -23765,7 +23816,7 @@ class KritzelSvgExportHelper {
23765
23816
  static collectDefs(objects, theme) {
23766
23817
  const defs = [];
23767
23818
  for (const obj of objects) {
23768
- if (alignment_enum.KritzelClassHelper.isInstanceOf(obj, 'KritzelLine')) {
23819
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(obj, 'KritzelLine')) {
23769
23820
  if (obj.hasStartArrow) {
23770
23821
  defs.push(this.generateArrowMarker(obj, 'start', theme));
23771
23822
  }
@@ -23803,22 +23854,22 @@ class KritzelSvgExportHelper {
23803
23854
  * @returns SVG element string, or empty string if object type is not supported
23804
23855
  */
23805
23856
  static objectToSvgElement(object, theme) {
23806
- if (alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelPath')) {
23857
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelPath')) {
23807
23858
  return this.pathToSvg(object, theme);
23808
23859
  }
23809
- if (alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelLine')) {
23860
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelLine')) {
23810
23861
  return this.lineToSvg(object, theme);
23811
23862
  }
23812
- if (alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelShape')) {
23863
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelShape')) {
23813
23864
  return this.shapeToSvg(object, theme);
23814
23865
  }
23815
- if (alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelText')) {
23866
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelText')) {
23816
23867
  return this.textToSvg(object, theme);
23817
23868
  }
23818
- if (alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
23869
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelImage')) {
23819
23870
  return this.imageToSvg(object);
23820
23871
  }
23821
- if (alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
23872
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup')) {
23822
23873
  return this.groupToSvg(object, theme);
23823
23874
  }
23824
23875
  return '';
@@ -23831,8 +23882,8 @@ class KritzelSvgExportHelper {
23831
23882
  */
23832
23883
  static pathToSvg(path, theme) {
23833
23884
  const transform = this.buildTransform(path);
23834
- const fill = alignment_enum.KritzelColorHelper.resolveThemeColor(path.fill, theme);
23835
- const stroke = alignment_enum.KritzelColorHelper.resolveThemeColor(path.stroke, theme);
23885
+ const fill = workspace_migrations.KritzelColorHelper.resolveThemeColor(path.fill, theme);
23886
+ const stroke = workspace_migrations.KritzelColorHelper.resolveThemeColor(path.stroke, theme);
23836
23887
  const opacity = path.opacity !== 1 ? ` opacity="${path.opacity}"` : '';
23837
23888
  // Path needs to be wrapped in a g with translation since path.d uses local coordinates
23838
23889
  return `<g transform="${transform}"${opacity}>
@@ -23849,7 +23900,7 @@ class KritzelSvgExportHelper {
23849
23900
  */
23850
23901
  static lineToSvg(line, theme) {
23851
23902
  const transform = this.buildTransform(line);
23852
- const stroke = alignment_enum.KritzelColorHelper.resolveThemeColor(line.stroke, theme);
23903
+ const stroke = workspace_migrations.KritzelColorHelper.resolveThemeColor(line.stroke, theme);
23853
23904
  const opacity = line.opacity !== 1 ? ` opacity="${line.opacity}"` : '';
23854
23905
  const markerStart = line.hasStartArrow ? ` marker-start="url(#${line.startMarkerId})"` : '';
23855
23906
  const markerEnd = line.hasEndArrow ? ` marker-end="url(#${line.endMarkerId})"` : '';
@@ -23867,8 +23918,8 @@ class KritzelSvgExportHelper {
23867
23918
  */
23868
23919
  static shapeToSvg(shape, theme) {
23869
23920
  const transform = this.buildTransform(shape);
23870
- const fill = alignment_enum.KritzelColorHelper.resolveThemeColor(shape.fillColor, theme);
23871
- const stroke = alignment_enum.KritzelColorHelper.resolveThemeColor(shape.strokeColor, theme);
23921
+ const fill = workspace_migrations.KritzelColorHelper.resolveThemeColor(shape.fillColor, theme);
23922
+ const stroke = workspace_migrations.KritzelColorHelper.resolveThemeColor(shape.strokeColor, theme);
23872
23923
  const opacity = shape.opacity !== 1 ? ` opacity="${shape.opacity}"` : '';
23873
23924
  // Get the SVG path for the shape
23874
23925
  const pathD = shape.getSvgPath();
@@ -23878,7 +23929,7 @@ class KritzelSvgExportHelper {
23878
23929
  else if (shape.content) {
23879
23930
  const textHtml = this.prosemirrorToHtml(shape.content, shape, theme);
23880
23931
  if (textHtml) {
23881
- const fontColor = alignment_enum.KritzelColorHelper.resolveThemeColor(shape.fontColor, theme);
23932
+ const fontColor = workspace_migrations.KritzelColorHelper.resolveThemeColor(shape.fontColor, theme);
23882
23933
  textContent = `
23883
23934
  <foreignObject x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}">
23884
23935
  <div xmlns="http://www.w3.org/1999/xhtml" style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; text-align: center; font-family: ${shape.fontFamily}; font-size: ${shape.fontSize}px; color: ${fontColor}; overflow: hidden;">
@@ -23902,8 +23953,8 @@ class KritzelSvgExportHelper {
23902
23953
  static textToSvg(text, theme) {
23903
23954
  const transform = this.buildTransform(text);
23904
23955
  const opacity = text.opacity !== 1 ? ` opacity="${text.opacity}"` : '';
23905
- const fontColor = alignment_enum.KritzelColorHelper.resolveThemeColor(text.fontColor, theme);
23906
- const bgColor = alignment_enum.KritzelColorHelper.resolveThemeColor(text.backgroundColor, theme);
23956
+ const fontColor = workspace_migrations.KritzelColorHelper.resolveThemeColor(text.fontColor, theme);
23957
+ const bgColor = workspace_migrations.KritzelColorHelper.resolveThemeColor(text.backgroundColor, theme);
23907
23958
  // Convert ProseMirror content to HTML
23908
23959
  const htmlContent = this.prosemirrorToHtml(text.content, text, theme);
23909
23960
  // Calculate dimensions accounting for scale
@@ -25055,6 +25106,13 @@ const KritzelEngine = class {
25055
25106
  onViewportBoundaryBottomChange(newValue) {
25056
25107
  this.core.store.state.viewportBoundaryBottom = newValue ?? Infinity;
25057
25108
  }
25109
+ /** Debug info display options controlling which debug overlays are visible */
25110
+ debugInfo;
25111
+ onDebugInfoChange(newValue) {
25112
+ if (newValue) {
25113
+ this.core.store.state.debugInfo = newValue;
25114
+ }
25115
+ }
25058
25116
  /** When false, wheel events will not trigger viewport pan/zoom. The event still propagates to parent elements. */
25059
25117
  wheelEnabled = true;
25060
25118
  /** Emitted when the engine has fully initialized and is ready for interaction. */
@@ -25107,8 +25165,8 @@ const KritzelEngine = class {
25107
25165
  if (this.core.store.isDisabled) {
25108
25166
  return;
25109
25167
  }
25110
- if (alignment_enum.KritzelDevicesHelper.isTouchDevice()) {
25111
- alignment_enum.KritzelEventHelper.onLongPress(ev, (event) => this.longpress.emit(event));
25168
+ if (workspace_migrations.KritzelDevicesHelper.isTouchDevice()) {
25169
+ workspace_migrations.KritzelEventHelper.onLongPress(ev, (event) => this.longpress.emit(event));
25112
25170
  }
25113
25171
  this.host.setPointerCapture(ev.pointerId);
25114
25172
  this.core.store.state.pointers.set(ev.pointerId, ev);
@@ -25242,11 +25300,11 @@ const KritzelEngine = class {
25242
25300
  * @returns The registered tool instance, or `null` if registration failed.
25243
25301
  */
25244
25302
  async registerTool(toolName, toolClass, toolConfig) {
25245
- if (typeof toolClass !== 'function' || !(toolClass.prototype instanceof alignment_enum.KritzelBaseTool)) {
25303
+ if (typeof toolClass !== 'function' || !(toolClass.prototype instanceof workspace_migrations.KritzelBaseTool)) {
25246
25304
  console.error(`Failed to register tool "${toolName}": Tool class must be a constructor function`);
25247
25305
  return null;
25248
25306
  }
25249
- const registeredTool = alignment_enum.KritzelToolRegistry.registerTool(toolName, toolClass, this.core);
25307
+ const registeredTool = workspace_migrations.KritzelToolRegistry.registerTool(toolName, toolClass, this.core);
25250
25308
  if (toolConfig) {
25251
25309
  Object.entries(toolConfig).forEach(([key, value]) => {
25252
25310
  registeredTool[key] = value;
@@ -25348,7 +25406,7 @@ const KritzelEngine = class {
25348
25406
  async hideContextMenu() {
25349
25407
  this.core.store.state.pointers.clear();
25350
25408
  this.core.store.state.isContextMenuVisible = false;
25351
- this.core.store.state.objects.remove(o => o instanceof alignment_enum.KritzelSelectionBox);
25409
+ this.core.store.state.objects.remove(o => o instanceof workspace_migrations.KritzelSelectionBox);
25352
25410
  this.core.store.setSelectionBox(null);
25353
25411
  this.core.store.state.isSelecting = false;
25354
25412
  this.core.store.state.isEnabled = true;
@@ -25406,7 +25464,7 @@ const KritzelEngine = class {
25406
25464
  object.workspaceId = this.core.store.state.activeWorkspace.id;
25407
25465
  // Handle KritzelText: recreate the editor now that _core is available
25408
25466
  // The editor's dispatchTransaction callback needs _core for persisting changes
25409
- if (alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelText')) {
25467
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelText')) {
25410
25468
  const pendingContent = object.content;
25411
25469
  object.editor = object.createEditor();
25412
25470
  if (pendingContent) {
@@ -25414,7 +25472,7 @@ const KritzelEngine = class {
25414
25472
  }
25415
25473
  }
25416
25474
  // Handle KritzelGroup: flush pending children into the store
25417
- if (alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup') && object._pendingChildren.length > 0) {
25475
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelGroup') && object._pendingChildren.length > 0) {
25418
25476
  object.childIds = [];
25419
25477
  // Build a map of old ID → new ID so we can remap anchor references
25420
25478
  const idRemapping = new Map();
@@ -25430,7 +25488,7 @@ const KritzelEngine = class {
25430
25488
  });
25431
25489
  // Remap anchor references in lines before inserting into the store
25432
25490
  object._pendingChildren.forEach(child => {
25433
- if (alignment_enum.KritzelClassHelper.isInstanceOf(child, 'KritzelLine')) {
25491
+ if (workspace_migrations.KritzelClassHelper.isInstanceOf(child, 'KritzelLine')) {
25434
25492
  if (child.startAnchor && idRemapping.has(child.startAnchor.objectId)) {
25435
25493
  child.startAnchor = { objectId: idRemapping.get(child.startAnchor.objectId) };
25436
25494
  }
@@ -25499,14 +25557,14 @@ const KritzelEngine = class {
25499
25557
  */
25500
25558
  async selectObjects(objects) {
25501
25559
  this.core.store.state.activeTool?.onDeactivate();
25502
- this.core.store.setState('activeTool', alignment_enum.KritzelToolRegistry.getTool('selection'));
25560
+ this.core.store.setState('activeTool', workspace_migrations.KritzelToolRegistry.getTool('selection'));
25503
25561
  this.core.deselectAllObjects();
25504
25562
  this.core.selectObjects(objects);
25505
25563
  }
25506
25564
  /** Selects all objects currently visible in the viewport. Switches to the selection tool automatically. */
25507
25565
  async selectAllObjectsInViewport() {
25508
25566
  this.core.store.state.activeTool?.onDeactivate();
25509
- this.core.store.setState('activeTool', alignment_enum.KritzelToolRegistry.getTool('selection'));
25567
+ this.core.store.setState('activeTool', workspace_migrations.KritzelToolRegistry.getTool('selection'));
25510
25568
  this.core.deselectAllObjects();
25511
25569
  this.core.selectAllObjectsInViewport();
25512
25570
  }
@@ -25819,14 +25877,23 @@ const KritzelEngine = class {
25819
25877
  if (!data.__class__ || data.__class__ !== 'KritzelWorkspace') {
25820
25878
  throw new Error('Invalid workspace data: missing or incorrect __class__ identifier');
25821
25879
  }
25822
- if (data.version && data.version !== alignment_enum.WORKSPACE_EXPORT_VERSION) {
25823
- console.warn(`Workspace version mismatch: expected ${alignment_enum.WORKSPACE_EXPORT_VERSION}, got ${data.version}`);
25880
+ if (data.version && data.version !== workspace_migrations.WORKSPACE_EXPORT_VERSION) {
25881
+ console.warn(`Workspace version mismatch: expected ${workspace_migrations.WORKSPACE_EXPORT_VERSION}, got ${data.version}`);
25824
25882
  }
25825
25883
  // Create a new workspace with a fresh ID but use the imported name
25826
- const newWorkspaceId = alignment_enum.ObjectHelper.generateUUID();
25884
+ const newWorkspaceId = workspace_migrations.ObjectHelper.generateUUID();
25827
25885
  const importedName = data.name || 'Imported Workspace';
25828
- const importedViewport = data.viewport || { translateX: 0, translateY: 0, scale: 1 };
25829
- const newWorkspace = new alignment_enum.KritzelWorkspace(newWorkspaceId, importedName, importedViewport);
25886
+ let importedViewport = data.viewport || { centerWorldX: 0, centerWorldY: 0, scale: 1 };
25887
+ // Backward compatibility: convert legacy translateX/translateY to centerWorldX/centerWorldY
25888
+ if ('translateX' in importedViewport && !('centerWorldX' in importedViewport)) {
25889
+ const scale = importedViewport.scale ?? 1;
25890
+ importedViewport = {
25891
+ centerWorldX: -(importedViewport.translateX ?? 0) / scale,
25892
+ centerWorldY: -(importedViewport.translateY ?? 0) / scale,
25893
+ scale,
25894
+ };
25895
+ }
25896
+ const newWorkspace = new workspace_migrations.KritzelWorkspace(newWorkspaceId, importedName, importedViewport);
25830
25897
  // Save the new workspace
25831
25898
  this.core.createWorkspace(newWorkspace);
25832
25899
  this.workspacesChange.emit(this.core.store.state.workspaces);
@@ -25864,8 +25931,8 @@ const KritzelEngine = class {
25864
25931
  if (!data.__class__ || data.__class__ !== 'KritzelWorkspace') {
25865
25932
  throw new Error('Invalid workspace data: missing or incorrect __class__ identifier');
25866
25933
  }
25867
- if (data.version && data.version !== alignment_enum.WORKSPACE_EXPORT_VERSION) {
25868
- console.warn(`Workspace version mismatch: expected ${alignment_enum.WORKSPACE_EXPORT_VERSION}, got ${data.version}`);
25934
+ if (data.version && data.version !== workspace_migrations.WORKSPACE_EXPORT_VERSION) {
25935
+ console.warn(`Workspace version mismatch: expected ${workspace_migrations.WORKSPACE_EXPORT_VERSION}, got ${data.version}`);
25869
25936
  }
25870
25937
  const currentWorkspaceId = this.core.store.state.activeWorkspace.id;
25871
25938
  let loadedCount = 0;
@@ -26022,7 +26089,7 @@ const KritzelEngine = class {
26022
26089
  const workspaceId = token;
26023
26090
  let workspace = this.core.getWorkspaces().find(w => w.id === workspaceId);
26024
26091
  if (!workspace) {
26025
- workspace = new alignment_enum.KritzelWorkspace(workspaceId, 'Shared Workspace');
26092
+ workspace = new workspace_migrations.KritzelWorkspace(workspaceId, 'Shared Workspace');
26026
26093
  workspace.isPublic = true;
26027
26094
  this.core.createWorkspace(workspace);
26028
26095
  }
@@ -26062,10 +26129,10 @@ const KritzelEngine = class {
26062
26129
  _syncInitPromise = null;
26063
26130
  _syncConfigRevision = 0;
26064
26131
  get isSelecting() {
26065
- return this.core.store.state.activeTool instanceof alignment_enum.KritzelSelectionTool && this.core.store.state.isSelecting;
26132
+ return this.core.store.state.activeTool instanceof workspace_migrations.KritzelSelectionTool && this.core.store.state.isSelecting;
26066
26133
  }
26067
26134
  get isSelectionActive() {
26068
- return this.core.store.state.activeTool instanceof alignment_enum.KritzelSelectionTool && this.core.store.selectionGroup !== null;
26135
+ return this.core.store.state.activeTool instanceof workspace_migrations.KritzelSelectionTool && this.core.store.selectionGroup !== null;
26069
26136
  }
26070
26137
  constructor(hostRef) {
26071
26138
  index.registerInstance(this, hostRef);
@@ -26284,9 +26351,9 @@ const KritzelEngine = class {
26284
26351
  this.core.store.onStateChange('activeTool', this._handleActiveToolChange.bind(this));
26285
26352
  }
26286
26353
  _handleActiveToolChange(activeTool) {
26287
- if (!(activeTool instanceof alignment_enum.KritzelSelectionTool)) {
26354
+ if (!(activeTool instanceof workspace_migrations.KritzelSelectionTool)) {
26288
26355
  this.core.clearSelection();
26289
- this.core.store.state.objects.remove(o => o instanceof alignment_enum.KritzelSelectionBox);
26356
+ this.core.store.state.objects.remove(o => o instanceof workspace_migrations.KritzelSelectionBox);
26290
26357
  this.core.store.setSelectionBox(null);
26291
26358
  this.core.store.state.isSelecting = false;
26292
26359
  this.core.store.state.isResizeHandleSelected = false;
@@ -26295,7 +26362,7 @@ const KritzelEngine = class {
26295
26362
  this.core.store.state.skipContextMenu = false;
26296
26363
  this.core.store.state.copiedObjects = null;
26297
26364
  this.activeToolChange.emit(activeTool);
26298
- alignment_enum.KritzelKeyboardHelper.forceHideKeyboard();
26365
+ workspace_migrations.KritzelKeyboardHelper.forceHideKeyboard();
26299
26366
  this.core.rerender();
26300
26367
  }
26301
26368
  render() {
@@ -26326,7 +26393,7 @@ const KritzelEngine = class {
26326
26393
  position: 'absolute',
26327
26394
  zIndex: object.zIndex.toString(),
26328
26395
  pointerEvents: this.core.store.state.isScaling ? 'none' : 'auto',
26329
- } }, alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelPath') && (index.h("svg", { ref: el => object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
26396
+ } }, workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelPath') && (index.h("svg", { ref: el => object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
26330
26397
  height: object?.totalHeight + 'px',
26331
26398
  width: object?.totalWidth + 'px',
26332
26399
  left: '0',
@@ -26337,7 +26404,7 @@ const KritzelEngine = class {
26337
26404
  opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
26338
26405
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
26339
26406
  overflow: 'visible',
26340
- }, viewBox: object?.viewBox }, index.h("path", { d: object?.d, fill: alignment_enum.KritzelColorHelper.resolveThemeColor(object.fill, currentTheme), stroke: alignment_enum.KritzelColorHelper.resolveThemeColor(object?.stroke, currentTheme), "shape-rendering": object.isLowRes() ? 'optimizeSpeed' : 'auto' }))), alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelLine') && (index.h("svg", { ref: el => object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
26407
+ }, viewBox: object?.viewBox }, index.h("path", { d: object?.d, fill: workspace_migrations.KritzelColorHelper.resolveThemeColor(object.fill, currentTheme), stroke: workspace_migrations.KritzelColorHelper.resolveThemeColor(object?.stroke, currentTheme), "shape-rendering": object.isLowRes() ? 'optimizeSpeed' : 'auto' }))), workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelLine') && (index.h("svg", { ref: el => object.mount(el), xmlns: "http://www.w3.org/2000/svg", style: {
26341
26408
  height: object?.totalHeight + 'px',
26342
26409
  width: object?.totalWidth + 'px',
26343
26410
  left: '0',
@@ -26348,7 +26415,7 @@ const KritzelEngine = class {
26348
26415
  opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
26349
26416
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
26350
26417
  overflow: 'visible',
26351
- }, viewBox: object?.viewBox }, (object.hasStartArrow || object.hasEndArrow) && (index.h("defs", null, object.hasStartArrow && (index.h("marker", { id: object.startMarkerId, markerWidth: object.getArrowSize('start'), markerHeight: object.getArrowSize('start'), refX: 0, refY: object.getArrowSize('start') / 2, orient: "auto-start-reverse", markerUnits: "userSpaceOnUse" }, index.h("path", { d: object.getArrowPath(object.arrows?.start?.style), fill: object.getArrowFill('start'), transform: `scale(${object.getArrowSize('start') / 10})` }))), object.hasEndArrow && (index.h("marker", { id: object.endMarkerId, markerWidth: object.getArrowSize('end'), markerHeight: object.getArrowSize('end'), refX: 0, refY: object.getArrowSize('end') / 2, orient: "auto", markerUnits: "userSpaceOnUse" }, index.h("path", { d: object.getArrowPath(object.arrows?.end?.style), fill: object.getArrowFill('end'), transform: `scale(${object.getArrowSize('end') / 10})` }))))), index.h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: "transparent", "stroke-width": Math.max(object?.strokeWidth || 0, 10), "stroke-linecap": "round" }), index.h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: alignment_enum.KritzelColorHelper.resolveThemeColor(object?.stroke, currentTheme), "stroke-width": object?.strokeWidth, "stroke-linecap": "round", "marker-start": object.hasStartArrow ? `url(#${object.startMarkerId})` : undefined, "marker-end": object.hasEndArrow ? `url(#${object.endMarkerId})` : undefined }))), alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && (index.h("img", { ref: el => object.mount(el), src: object.src, style: {
26418
+ }, viewBox: object?.viewBox }, (object.hasStartArrow || object.hasEndArrow) && (index.h("defs", null, object.hasStartArrow && (index.h("marker", { id: object.startMarkerId, markerWidth: object.getArrowSize('start'), markerHeight: object.getArrowSize('start'), refX: 0, refY: object.getArrowSize('start') / 2, orient: "auto-start-reverse", markerUnits: "userSpaceOnUse" }, index.h("path", { d: object.getArrowPath(object.arrows?.start?.style), fill: object.getArrowFill('start'), transform: `scale(${object.getArrowSize('start') / 10})` }))), object.hasEndArrow && (index.h("marker", { id: object.endMarkerId, markerWidth: object.getArrowSize('end'), markerHeight: object.getArrowSize('end'), refX: 0, refY: object.getArrowSize('end') / 2, orient: "auto", markerUnits: "userSpaceOnUse" }, index.h("path", { d: object.getArrowPath(object.arrows?.end?.style), fill: object.getArrowFill('end'), transform: `scale(${object.getArrowSize('end') / 10})` }))))), index.h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: "transparent", "stroke-width": Math.max(object?.strokeWidth || 0, 10), "stroke-linecap": "round" }), index.h("path", { d: this.core.anchorManager.computeClippedLinePath(object), fill: "none", stroke: workspace_migrations.KritzelColorHelper.resolveThemeColor(object?.stroke, currentTheme), "stroke-width": object?.strokeWidth, "stroke-linecap": "round", "marker-start": object.hasStartArrow ? `url(#${object.startMarkerId})` : undefined, "marker-end": object.hasEndArrow ? `url(#${object.endMarkerId})` : undefined }))), workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelImage') && (index.h("img", { ref: el => object.mount(el), src: object.src, style: {
26352
26419
  position: 'absolute',
26353
26420
  left: '0',
26354
26421
  top: '0',
@@ -26358,15 +26425,15 @@ const KritzelEngine = class {
26358
26425
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
26359
26426
  opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
26360
26427
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
26361
- backgroundColor: alignment_enum.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
26362
- borderColor: alignment_enum.KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
26428
+ backgroundColor: workspace_migrations.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
26429
+ borderColor: workspace_migrations.KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
26363
26430
  borderWidth: object.borderWidth + 'px',
26364
26431
  borderStyle: 'solid',
26365
26432
  padding: object.padding + 'px',
26366
26433
  overflow: 'visible',
26367
26434
  userSelect: 'none',
26368
26435
  imageRendering: this.core.store.state.isScaling || this.core.store.state.isPanning ? 'pixelated' : 'auto',
26369
- }, draggable: false, onDragStart: e => e.preventDefault() })), alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelCustomElement') && (index.h("div", { ref: el => object.mount(el), style: {
26436
+ }, draggable: false, onDragStart: e => e.preventDefault() })), workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelCustomElement') && (index.h("div", { ref: el => object.mount(el), style: {
26370
26437
  position: 'absolute',
26371
26438
  left: '0',
26372
26439
  top: '0',
@@ -26376,14 +26443,14 @@ const KritzelEngine = class {
26376
26443
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
26377
26444
  opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
26378
26445
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
26379
- backgroundColor: alignment_enum.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
26380
- borderColor: alignment_enum.KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
26446
+ backgroundColor: workspace_migrations.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
26447
+ borderColor: workspace_migrations.KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
26381
26448
  borderWidth: object.borderWidth + 'px',
26382
26449
  borderStyle: 'solid',
26383
26450
  padding: object.padding + 'px',
26384
26451
  overflow: 'hidden',
26385
26452
  display: 'block',
26386
- } })), alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') && !this.core.displaySelectionLineUI(object) && (index.h("div", { ref: el => object.mount(el), style: {
26453
+ } })), workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionGroup') && !this.core.displaySelectionLineUI(object) && (index.h("div", { ref: el => object.mount(el), style: {
26387
26454
  position: 'absolute',
26388
26455
  left: '0',
26389
26456
  top: '0',
@@ -26393,7 +26460,7 @@ const KritzelEngine = class {
26393
26460
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
26394
26461
  opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
26395
26462
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
26396
- } })), alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionBox') && (index.h("div", { ref: el => object.mount(el), style: {
26463
+ } })), workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelSelectionBox') && (index.h("div", { ref: el => object.mount(el), style: {
26397
26464
  position: 'absolute',
26398
26465
  left: '0',
26399
26466
  top: '0',
@@ -26403,11 +26470,11 @@ const KritzelEngine = class {
26403
26470
  transformOrigin: object.rotationDegrees !== 0 ? `${object.totalWidth / 2}px ${object.totalHeight / 2}px` : undefined,
26404
26471
  opacity: object.markedForRemoval ? '0.5' : object.opacity.toString(),
26405
26472
  pointerEvents: object.markedForRemoval ? 'none' : 'auto',
26406
- backgroundColor: alignment_enum.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
26407
- borderColor: alignment_enum.KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
26473
+ backgroundColor: workspace_migrations.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
26474
+ borderColor: workspace_migrations.KritzelColorHelper.resolveThemeColor(object.borderColor, currentTheme),
26408
26475
  borderWidth: object.borderWidth + 'px',
26409
26476
  borderStyle: 'solid',
26410
- } })), alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelText') && (index.h("div", { style: {
26477
+ } })), workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelText') && (index.h("div", { style: {
26411
26478
  position: 'absolute',
26412
26479
  left: '0',
26413
26480
  top: '0',
@@ -26425,9 +26492,9 @@ const KritzelEngine = class {
26425
26492
  width: 'max-content',
26426
26493
  transformOrigin: 'top left',
26427
26494
  transform: `scale(${object.scaleFactor})`,
26428
- backgroundColor: alignment_enum.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
26495
+ backgroundColor: workspace_migrations.KritzelColorHelper.resolveThemeColor(object.backgroundColor, currentTheme),
26429
26496
  overflow: 'visible',
26430
- } }))), alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelShape') && (index.h("div", { ref: el => object.mount(el), onPointerDown: e => object.handlePointerDown(e), onPointerMove: e => object.handlePointerMove(e), onPointerUp: e => object.handlePointerUp(e), style: {
26497
+ } }))), workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelShape') && (index.h("div", { ref: el => object.mount(el), onPointerDown: e => object.handlePointerDown(e), onPointerMove: e => object.handlePointerMove(e), onPointerUp: e => object.handlePointerUp(e), style: {
26431
26498
  position: 'absolute',
26432
26499
  left: '0',
26433
26500
  top: '0',
@@ -26446,7 +26513,7 @@ const KritzelEngine = class {
26446
26513
  height: '100%',
26447
26514
  overflow: 'visible',
26448
26515
  pointerEvents: 'none',
26449
- }, viewBox: object.viewBox, preserveAspectRatio: "none" }, index.h("path", { d: object.getSvgPath(), fill: alignment_enum.KritzelColorHelper.resolveThemeColor(object.fillColor, currentTheme), stroke: alignment_enum.KritzelColorHelper.resolveThemeColor(object.strokeColor, currentTheme), "stroke-width": object.strokeWidth })), index.h("div", { ref: el => object.mountTextEditor(el), style: {
26516
+ }, viewBox: object.viewBox, preserveAspectRatio: "none" }, index.h("path", { d: object.getSvgPath(), fill: workspace_migrations.KritzelColorHelper.resolveThemeColor(object.fillColor, currentTheme), stroke: workspace_migrations.KritzelColorHelper.resolveThemeColor(object.strokeColor, currentTheme), "stroke-width": object.strokeWidth })), index.h("div", { ref: el => object.mountTextEditor(el), style: {
26450
26517
  position: 'absolute',
26451
26518
  top: '0',
26452
26519
  left: '0',
@@ -26534,7 +26601,7 @@ const KritzelEngine = class {
26534
26601
  } }), index.h("circle", { class: "rotation-handle-overlay", cx: object.totalWidth / 2, cy: -((15 * object.scale) / this.core.store.state?.scale), r: `${(baseHandleTouchSize * object.scale) / this.core.store.state?.scale}`, style: {
26535
26602
  fill: 'transparent',
26536
26603
  paintOrder: 'fill',
26537
- } }))))), this.core.displaySelectionLineUI(object) && alignment_enum.KritzelClassHelper.isInstanceOf(object, 'KritzelLine') && (index.h("g", { class: "selection-line-ui", style: { pointerEvents: 'none' } }, index.h("g", { class: "selection-line-borders" }, index.h("path", { class: "selection-line-border", d: this.core.anchorManager.computeClippedLinePath(object, true), style: {
26604
+ } }))))), this.core.displaySelectionLineUI(object) && workspace_migrations.KritzelClassHelper.isInstanceOf(object, 'KritzelLine') && (index.h("g", { class: "selection-line-ui", style: { pointerEvents: 'none' } }, index.h("g", { class: "selection-line-borders" }, index.h("path", { class: "selection-line-border", d: this.core.anchorManager.computeClippedLinePath(object, true), style: {
26538
26605
  stroke: 'var(--kritzel-selection-border-color, #007AFF)',
26539
26606
  strokeWidth: `calc(var(--kritzel-selection-border-width, 2px) * ${object.scale} / ${this.core.store.state?.scale})`,
26540
26607
  strokeLinecap: 'round',
@@ -26656,7 +26723,7 @@ const KritzelEngine = class {
26656
26723
  y: (-this.core.store.state.translateY + this.core.store.state.contextMenuY) / this.core.store.state.scale,
26657
26724
  }, this.core.store.selectionGroup?.objects);
26658
26725
  this.hideContextMenu();
26659
- }, onClose: () => this.hideContextMenu() })), this.core.store.state?.activeTool instanceof alignment_enum.KritzelEraserTool && !this.core.store.state.isScaling && index.h("kritzel-cursor-trail", { core: this.core })));
26726
+ }, onClose: () => this.hideContextMenu() })), this.core.store.state?.activeTool instanceof workspace_migrations.KritzelEraserTool && !this.core.store.state.isScaling && index.h("kritzel-cursor-trail", { core: this.core })));
26660
26727
  }
26661
26728
  static get watchers() { return {
26662
26729
  "workspace": [{
@@ -26697,6 +26764,9 @@ const KritzelEngine = class {
26697
26764
  }],
26698
26765
  "viewportBoundaryBottom": [{
26699
26766
  "onViewportBoundaryBottomChange": 0
26767
+ }],
26768
+ "debugInfo": [{
26769
+ "onDebugInfoChange": 0
26700
26770
  }]
26701
26771
  }; }
26702
26772
  };
@@ -26884,7 +26954,7 @@ const KritzelIcon = class {
26884
26954
  label;
26885
26955
  size = 24;
26886
26956
  render() {
26887
- const svgContent = alignment_enum.KritzelIconRegistry.get(this.name);
26957
+ const svgContent = workspace_migrations.KritzelIconRegistry.get(this.name);
26888
26958
  if (!svgContent) {
26889
26959
  console.error(`[kritzel-icon] Icon "${this.name}" not found in registry.`);
26890
26960
  return index.h("span", { class: "error-icon", "aria-label": `Error: Icon ${this.name} not found` }, "?");
@@ -27082,7 +27152,7 @@ const KritzelLoginDialog = class {
27082
27152
  };
27083
27153
  KritzelLoginDialog.style = kritzelLoginDialogCss();
27084
27154
 
27085
- const kritzelMasterDetailCss = () => `:host{display:block;width:100%;height:100%}.master-detail-container{display:flex;width:100%;height:100%;min-height:var(--kritzel-master-detail-min-height, 300px);gap:var(--kritzel-master-detail-gap, 0);background-color:var(--kritzel-master-detail-background-color, transparent)}.master-menu{display:flex;flex-direction:column;width:var(--kritzel-master-detail-menu-width, 200px);min-width:var(--kritzel-master-detail-menu-min-width, 160px);padding:var(--kritzel-master-detail-menu-padding, 8px);background-color:var(--kritzel-master-detail-menu-background-color, #ffffff);border-right:var(--kritzel-master-detail-menu-border-right, 1px solid #ebebeb);gap:var(--kritzel-master-detail-menu-gap, 4px);overflow-y:auto}.menu-item{display:flex;align-items:center;gap:var(--kritzel-master-detail-menu-item-gap, 10px);padding:var(--kritzel-master-detail-menu-item-padding, 10px 12px);border:none;border-radius:var(--kritzel-master-detail-menu-item-border-radius, 6px);background-color:var(--kritzel-master-detail-menu-item-background-color, transparent);color:var(--kritzel-master-detail-menu-item-color, #333333);font-family:inherit;font-size:var(--kritzel-master-detail-menu-item-font-size, 14px);font-weight:var(--kritzel-master-detail-menu-item-font-weight, 400);text-align:left;cursor:var(--kritzel-global-pointer-cursor, pointer);transition:background-color 150ms ease, color 150ms ease;-webkit-tap-highlight-color:transparent}.menu-item:hover:not(.is-disabled){background-color:var(--kritzel-master-detail-menu-item-hover-background-color, #ebebeb)}.menu-item:active:not(.is-disabled){background-color:var(--kritzel-master-detail-menu-item-active-background-color, #e0e0e0)}.menu-item.is-selected{background-color:var(--kritzel-master-detail-menu-item-selected-background-color, #0066cc);color:var(--kritzel-master-detail-menu-item-selected-color, #ffffff);font-weight:var(--kritzel-master-detail-menu-item-selected-font-weight, 500)}.menu-item.is-selected:hover{background-color:var(--kritzel-master-detail-menu-item-selected-hover-background-color, #0052a3)}.menu-item.is-disabled{color:var(--kritzel-master-detail-menu-item-disabled-color, #999999);cursor:not-allowed;opacity:0.6}.menu-item:focus-visible{outline:var(--kritzel-master-detail-menu-item-focus-outline, revert);outline-offset:var(--kritzel-master-detail-menu-item-focus-outline-offset, revert)}.menu-item-icon{flex-shrink:0;display:flex;align-items:center;justify-content:center}.menu-item-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.detail-panel{flex:1;min-height:0;padding:var(--kritzel-master-detail-detail-padding, 16px);background-color:var(--kritzel-master-detail-detail-background-color, #ffffff);overflow-y:auto;-webkit-overflow-scrolling:touch;scrollbar-color:var(--kritzel-global-scrollbar-thumb-color, #ebebeb) transparent;scrollbar-width:thin}.detail-panel:focus{outline:none}.detail-panel:focus-visible{outline:var(--kritzel-master-detail-detail-focus-outline, revert);outline-offset:var(--kritzel-master-detail-detail-focus-outline-offset, revert)}.mobile-back-button{display:none;align-items:center;gap:8px;background:none;border:none;padding:0 0 16px 0;cursor:pointer;color:var(--kritzel-master-detail-back-button-color, #333333);font-weight:500;font-size:14px;font-family:inherit}.mobile-back-icon{display:flex;align-items:center;flex-shrink:0}.menu-item-chevron{display:none;flex-shrink:0;margin-left:auto;color:var(--kritzel-master-detail-menu-item-chevron-color, #999999)}.menu-item-chevron svg{width:16px;height:16px;stroke:currentColor}@media (max-width: 768px){.master-menu{width:100%;border-right:none}.detail-panel{display:none;width:100%}.master-detail-container.is-mobile-detail-visible .master-menu{display:none}.master-detail-container.is-mobile-detail-visible .detail-panel{display:block}.mobile-back-button{display:flex}.menu-item.is-selected{background-color:transparent;color:var(--kritzel-master-detail-menu-item-color, #333333);font-weight:var(--kritzel-master-detail-menu-item-font-weight, 400)}.menu-item.is-selected:hover{background-color:var(--kritzel-master-detail-menu-item-hover-background-color, #ebebeb)}.menu-item-chevron{display:flex;align-items:center}}`;
27155
+ const kritzelMasterDetailCss = () => `:host{display:block;width:100%;height:100%}.master-detail-container{display:flex;width:100%;height:100%;min-height:var(--kritzel-master-detail-min-height, 300px);gap:var(--kritzel-master-detail-gap, 0);background-color:var(--kritzel-master-detail-background-color, transparent)}.master-menu{display:flex;flex-direction:column;width:var(--kritzel-master-detail-menu-width, 200px);min-width:var(--kritzel-master-detail-menu-min-width, 160px);padding:var(--kritzel-master-detail-menu-padding, 8px);background-color:var(--kritzel-master-detail-menu-background-color, #ffffff);border-right:var(--kritzel-master-detail-menu-border-right, 1px solid #ebebeb);gap:var(--kritzel-master-detail-menu-gap, 4px);overflow-y:auto}.menu-item{display:flex;align-items:center;gap:var(--kritzel-master-detail-menu-item-gap, 10px);padding:var(--kritzel-master-detail-menu-item-padding, 10px 12px);border:none;border-radius:var(--kritzel-master-detail-menu-item-border-radius, 6px);background-color:var(--kritzel-master-detail-menu-item-background-color, transparent);color:var(--kritzel-master-detail-menu-item-color, #333333);font-family:inherit;font-size:var(--kritzel-master-detail-menu-item-font-size, 14px);font-weight:var(--kritzel-master-detail-menu-item-font-weight, 400);text-align:left;cursor:var(--kritzel-global-pointer-cursor, pointer);transition:background-color 150ms ease, color 150ms ease;-webkit-tap-highlight-color:transparent}.menu-item:hover:not(.is-disabled){background-color:var(--kritzel-master-detail-menu-item-hover-background-color, #ebebeb)}.menu-item:active:not(.is-disabled){background-color:var(--kritzel-master-detail-menu-item-active-background-color, #e0e0e0)}.menu-item.is-selected{background-color:var(--kritzel-master-detail-menu-item-selected-background-color, #0066cc);color:var(--kritzel-master-detail-menu-item-selected-color, #ffffff);font-weight:var(--kritzel-master-detail-menu-item-selected-font-weight, 500)}.menu-item.is-selected:hover{background-color:var(--kritzel-master-detail-menu-item-selected-hover-background-color, #0052a3)}.menu-item.is-disabled{color:var(--kritzel-master-detail-menu-item-disabled-color, #999999);cursor:not-allowed;opacity:0.6}.menu-item:focus-visible{outline:var(--kritzel-master-detail-menu-item-focus-outline, revert);outline-offset:var(--kritzel-master-detail-menu-item-focus-outline-offset, revert)}.menu-item-icon{flex-shrink:0;display:flex;align-items:center;justify-content:center}.menu-item-label{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.detail-panel{flex:1;min-height:0;padding:var(--kritzel-master-detail-detail-padding, 16px);background-color:var(--kritzel-master-detail-detail-background-color, #ffffff);overflow-y:auto;-webkit-overflow-scrolling:touch;scrollbar-color:var(--kritzel-global-scrollbar-thumb-color, #ebebeb) transparent;scrollbar-width:thin}.detail-panel:focus{outline:none}.detail-panel:focus-visible{outline:var(--kritzel-master-detail-detail-focus-outline, revert);outline-offset:var(--kritzel-master-detail-detail-focus-outline-offset, revert)}.mobile-back-button{display:none;align-items:center;gap:8px;background:none;border:none;padding:0 0 16px 0;cursor:pointer;-webkit-tap-highlight-color:transparent;color:var(--kritzel-master-detail-back-button-color, #333333);font-weight:500;font-size:14px;font-family:inherit}.mobile-back-icon{display:flex;align-items:center;flex-shrink:0}.menu-item-chevron{display:none;flex-shrink:0;margin-left:auto;color:var(--kritzel-master-detail-menu-item-chevron-color, #999999)}.menu-item-chevron svg{width:16px;height:16px;stroke:currentColor}@media (max-width: 768px){.master-menu{width:100%;border-right:none}.detail-panel{display:none;width:100%}.master-detail-container.is-mobile-detail-visible .master-menu{display:none}.master-detail-container.is-mobile-detail-visible .detail-panel{display:block}.mobile-back-button{display:flex}.menu-item.is-selected{background-color:transparent;color:var(--kritzel-master-detail-menu-item-color, #333333);font-weight:var(--kritzel-master-detail-menu-item-font-weight, 400)}.menu-item.is-selected:hover{background-color:var(--kritzel-master-detail-menu-item-hover-background-color, #ebebeb)}.menu-item-chevron{display:flex;align-items:center}}`;
27086
27156
 
27087
27157
  const KritzelMasterDetail = class {
27088
27158
  constructor(hostRef) {
@@ -27296,7 +27366,7 @@ const KritzelMenuItem = class {
27296
27366
  requestAnimationFrame(() => {
27297
27367
  if (this.inputRef) {
27298
27368
  this.inputRef.focus();
27299
- if (alignment_enum.KritzelDevicesHelper.isIOS()) {
27369
+ if (workspace_migrations.KritzelDevicesHelper.isIOS()) {
27300
27370
  const length = this.inputRef.value.length;
27301
27371
  this.inputRef.setSelectionRange(length, length);
27302
27372
  }
@@ -27315,7 +27385,7 @@ const KritzelMenuItem = class {
27315
27385
  this.focusInput();
27316
27386
  }
27317
27387
  setDeviceSpecificStyles = () => {
27318
- const isTouchDevice = alignment_enum.KritzelDevicesHelper.isTouchDevice();
27388
+ const isTouchDevice = workspace_migrations.KritzelDevicesHelper.isTouchDevice();
27319
27389
  if (isTouchDevice) {
27320
27390
  this.host.style.setProperty('--kritzel-menu-item-overlay-background-color', 'transparent');
27321
27391
  this.host.style.setProperty('--kritzel-menu-item-button-hover-background-color', 'transparent');
@@ -27380,7 +27450,7 @@ const KritzelMenuItem = class {
27380
27450
  };
27381
27451
  KritzelMenuItem.style = kritzelMenuItemCss();
27382
27452
 
27383
- const kritzelMoreMenuCss = () => `:host{display:inline-flex;padding:var(--kritzel-more-menu-padding, 4px);background-color:var(--kritzel-more-menu-background-color, #ffffff);border-radius:var(--kritzel-more-menu-border-radius, 12px);box-shadow:var(--kritzel-more-menu-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-more-menu-border, 1px solid #ebebeb)}.more-menu-button{display:flex;align-items:center;justify-content:center;width:var(--kritzel-more-menu-button-width, 40px);height:var(--kritzel-more-menu-button-height, 40px);padding:0;border:none;border-radius:var(--kritzel-more-menu-inner-border-radius, 12px);background-color:transparent;cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:none;transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none;color:var(--kritzel-more-menu-button-color, currentColor)}.more-menu-button:hover{background-color:var(--kritzel-more-menu-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.more-menu-button:focus-visible{background-color:var(--kritzel-more-menu-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.more-menu-button:active{background-color:var(--kritzel-more-menu-button-active-background-color, hsl(0, 0%, 0%, 4.3%))}`;
27453
+ const kritzelMoreMenuCss = () => `:host{display:inline-flex;padding:var(--kritzel-more-menu-padding, 4px);background-color:var(--kritzel-more-menu-background-color, #ffffff);border-radius:var(--kritzel-more-menu-border-radius, 12px);box-shadow:var(--kritzel-more-menu-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));border:var(--kritzel-more-menu-border, 1px solid #ebebeb)}:host(.mobile){--kritzel-more-menu-button-hover-background-color:transparent;--kritzel-more-menu-button-active-background-color:transparent}.more-menu-button{display:flex;align-items:center;justify-content:center;width:var(--kritzel-more-menu-button-width, 40px);height:var(--kritzel-more-menu-button-height, 40px);padding:0;border:none;border-radius:var(--kritzel-more-menu-inner-border-radius, 12px);background-color:transparent;cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:none;transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent;-webkit-appearance:none;-moz-appearance:none;appearance:none;color:var(--kritzel-more-menu-button-color, currentColor)}.more-menu-button:hover{background-color:var(--kritzel-more-menu-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.more-menu-button:focus-visible{background-color:var(--kritzel-more-menu-button-hover-background-color, hsl(0, 0%, 0%, 4.3%))}.more-menu-button:active{background-color:var(--kritzel-more-menu-button-active-background-color, hsl(0, 0%, 0%, 4.3%))}`;
27384
27454
 
27385
27455
  const KritzelMoreMenu = class {
27386
27456
  constructor(hostRef) {
@@ -27411,6 +27481,7 @@ const KritzelMoreMenu = class {
27411
27481
  */
27412
27482
  itemSelect;
27413
27483
  menuAnchor = null;
27484
+ isTouchDevice = workspace_migrations.KritzelDevicesHelper.isTouchDevice();
27414
27485
  toggleMenu = (event) => {
27415
27486
  event.stopPropagation();
27416
27487
  if (this.menuAnchor) {
@@ -27436,7 +27507,7 @@ const KritzelMoreMenu = class {
27436
27507
  this.closeMenu();
27437
27508
  };
27438
27509
  render() {
27439
- return (index.h(index.Host, { key: '01e6914520c01bb58af817148b9a013e906209d8' }, index.h("button", { key: '4e38c8b7f82e8fb06872c4cf84e6611d544f3ea8', class: "more-menu-button", onClick: this.toggleMenu }, index.h("kritzel-icon", { key: 'd682c22f8445bb024dd6fa9ee3dde986b18420e5', name: this.icon, size: this.iconSize })), index.h("kritzel-portal", { key: '117e69ab70d77cb612ac4e4eca196b8a0b03326b', anchor: this.menuAnchor, offsetY: this.offsetY, onClose: this.closeMenu }, index.h("kritzel-menu", { key: 'c440f9a68c199dbfdd33d645bb160908b6699b4e', items: this.visibleItems, onItemSelect: this.handleMenuItemSelect }))));
27510
+ return (index.h(index.Host, { key: '02d18106b6a932cd4508bebc6ada3416f38eafc6', class: { mobile: this.isTouchDevice } }, index.h("button", { key: 'dff3f7bd69f8f1eafbff03b9ecc2f96c85784a85', class: "more-menu-button", onClick: this.toggleMenu }, index.h("kritzel-icon", { key: '28586ce5dd15be347cc59555608a2cbbf2978a2b', name: this.icon, size: this.iconSize })), index.h("kritzel-portal", { key: '3ca9260c3602a639687bc1341736c15a1b5c10a7', anchor: this.menuAnchor, offsetY: this.offsetY, onClose: this.closeMenu }, index.h("kritzel-menu", { key: 'e8e88cc9f827d93d9adcc86ad1041774cfc282af', items: this.visibleItems, onItemSelect: this.handleMenuItemSelect }))));
27440
27511
  }
27441
27512
  };
27442
27513
  KritzelMoreMenu.style = kritzelMoreMenuCss();
@@ -27724,7 +27795,7 @@ const KritzelPortal = class {
27724
27795
  this.calculatePosition();
27725
27796
  }
27726
27797
  portal;
27727
- id = `portal-${alignment_enum.ObjectHelper.generateUUID()}`;
27798
+ id = `portal-${workspace_migrations.ObjectHelper.generateUUID()}`;
27728
27799
  defaultOffset = 0;
27729
27800
  minLeft = 0;
27730
27801
  themeObserver;
@@ -27923,7 +27994,7 @@ const KritzelPortal = class {
27923
27994
  * This file is auto-generated by the version bump scripts.
27924
27995
  * Do not modify manually.
27925
27996
  */
27926
- const KRITZEL_VERSION = '0.1.69';
27997
+ const KRITZEL_VERSION = '0.1.71';
27927
27998
 
27928
27999
  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)}`;
27929
28000
 
@@ -27935,10 +28006,17 @@ const DEFAULT_VIEWPORT_BOUNDARY_LEFT = -Infinity;
27935
28006
  const DEFAULT_VIEWPORT_BOUNDARY_RIGHT = Infinity;
27936
28007
  const DEFAULT_VIEWPORT_BOUNDARY_TOP = -Infinity;
27937
28008
  const DEFAULT_VIEWPORT_BOUNDARY_BOTTOM = Infinity;
28009
+ const DEFAULT_DEBUG_INFO = {
28010
+ showViewportInfo: false,
28011
+ showObjectInfo: false,
28012
+ showSyncProviderInfo: true,
28013
+ showMigrationInfo: true,
28014
+ };
27938
28015
  const SETTINGS_CATEGORIES = [
27939
28016
  { id: 'general', label: 'General', icon: 'settings' },
27940
28017
  { id: 'viewport', label: 'Viewport', icon: 'viewport' },
27941
28018
  { id: 'shortcuts', label: 'Keyboard Shortcuts', icon: 'command' },
28019
+ { id: 'developer', label: 'Developer Options', icon: 'braces' },
27942
28020
  { id: 'about', label: 'About', icon: 'info' },
27943
28021
  ];
27944
28022
  const KritzelSettings = class {
@@ -27961,6 +28039,7 @@ const KritzelSettings = class {
27961
28039
  viewportBoundaryRight = DEFAULT_VIEWPORT_BOUNDARY_RIGHT;
27962
28040
  viewportBoundaryTop = DEFAULT_VIEWPORT_BOUNDARY_TOP;
27963
28041
  viewportBoundaryBottom = DEFAULT_VIEWPORT_BOUNDARY_BOTTOM;
28042
+ debugInfo = { ...DEFAULT_DEBUG_INFO };
27964
28043
  /** Emitted when settings change */
27965
28044
  settingsChange;
27966
28045
  componentWillLoad() {
@@ -27998,6 +28077,9 @@ const KritzelSettings = class {
27998
28077
  if (typeof parsed.viewportBoundaryBottom === 'number') {
27999
28078
  this.viewportBoundaryBottom = parsed.viewportBoundaryBottom;
28000
28079
  }
28080
+ if (parsed.debugInfo) {
28081
+ this.debugInfo = { ...DEFAULT_DEBUG_INFO, ...parsed.debugInfo };
28082
+ }
28001
28083
  }
28002
28084
  catch {
28003
28085
  // Invalid JSON, use defaults
@@ -28014,6 +28096,7 @@ const KritzelSettings = class {
28014
28096
  viewportBoundaryRight: this.viewportBoundaryRight,
28015
28097
  viewportBoundaryTop: this.viewportBoundaryTop,
28016
28098
  viewportBoundaryBottom: this.viewportBoundaryBottom,
28099
+ debugInfo: this.debugInfo,
28017
28100
  };
28018
28101
  localStorage.setItem(this.storageKey, JSON.stringify(settings));
28019
28102
  this.settingsChange.emit(settings);
@@ -28050,6 +28133,10 @@ const KritzelSettings = class {
28050
28133
  this.viewportBoundaryBottom = event.detail ?? DEFAULT_VIEWPORT_BOUNDARY_BOTTOM;
28051
28134
  this.saveSettings();
28052
28135
  };
28136
+ handleDebugInfoChange = (key) => (event) => {
28137
+ this.debugInfo = { ...this.debugInfo, [key]: event.detail };
28138
+ this.saveSettings();
28139
+ };
28053
28140
  async open() {
28054
28141
  this.isDialogOpen = true;
28055
28142
  }
@@ -28093,14 +28180,16 @@ const KritzelSettings = class {
28093
28180
  return (index.h("div", { class: "settings-content" }, index.h("h3", null, "Viewport Settings"), index.h("div", { class: "settings-group" }, index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, "Minimum Zoom Level"), index.h("p", { class: "settings-description" }, "Sets the minimum zoom level. Lower values allow zooming out further to see more of the canvas."), index.h("kritzel-numeric-input", { value: this.scaleMin, min: 0.0001, max: 1, step: 0.0001, onValueChange: this.handleScaleMinChange })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, "Maximum Zoom Level"), index.h("p", { class: "settings-description" }, "Sets the maximum zoom level. Higher values allow zooming in closer for detailed work."), index.h("kritzel-numeric-input", { value: this.scaleMax, min: 1, max: 1000, step: 1, onValueChange: this.handleScaleMaxChange })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, "Viewport Boundary Left"), index.h("p", { class: "settings-description" }, "Left boundary in world coordinates. Set to limit how far left the viewport can pan."), index.h("kritzel-numeric-input", { value: this.viewportBoundaryLeft, step: 100, placeholder: "Infinite", onValueChange: this.handleViewportBoundaryLeftChange })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, "Viewport Boundary Right"), index.h("p", { class: "settings-description" }, "Right boundary in world coordinates. Set to limit how far right the viewport can pan."), index.h("kritzel-numeric-input", { value: this.viewportBoundaryRight, step: 100, placeholder: "Infinite", onValueChange: this.handleViewportBoundaryRightChange })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, "Viewport Boundary Top"), index.h("p", { class: "settings-description" }, "Top boundary in world coordinates. Set to limit how far up the viewport can pan."), index.h("kritzel-numeric-input", { value: this.viewportBoundaryTop, step: 100, placeholder: "Infinite", onValueChange: this.handleViewportBoundaryTopChange })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, "Viewport Boundary Bottom"), index.h("p", { class: "settings-description" }, "Bottom boundary in world coordinates. Set to limit how far down the viewport can pan."), index.h("kritzel-numeric-input", { value: this.viewportBoundaryBottom, step: 100, placeholder: "Infinite", onValueChange: this.handleViewportBoundaryBottomChange })))));
28094
28181
  case 'shortcuts':
28095
28182
  return (index.h("div", { class: "settings-content" }, index.h("h3", null, "Keyboard Shortcuts"), index.h("div", { class: "shortcuts-list" }, Array.from(this.groupShortcutsByCategory()).map(([category, shortcuts]) => (index.h("div", { class: "shortcuts-category", key: category }, index.h("h4", { class: "shortcuts-category-title" }, category), index.h("div", { class: "shortcuts-group" }, shortcuts.map(shortcut => (index.h("div", { class: "shortcut-item", key: shortcut.key + shortcut.label }, index.h("span", { class: "shortcut-label" }, shortcut.label), index.h("kbd", { class: "shortcut-key" }, this.formatKeyCombo(shortcut))))))))))));
28183
+ case 'developer':
28184
+ return (index.h("div", { class: "settings-content" }, index.h("h3", null, "Developer Options"), index.h("div", { class: "settings-group" }, index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, "Show Viewport Info"), index.h("p", { class: "settings-description" }, "Display viewport debug information such as position, zoom level, and boundaries."), index.h("kritzel-slide-toggle", { checked: this.debugInfo.showViewportInfo, label: "Show Viewport Info", onCheckedChange: this.handleDebugInfoChange('showViewportInfo') })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, "Show Object Info"), index.h("p", { class: "settings-description" }, "Display debug information about objects on the canvas."), index.h("kritzel-slide-toggle", { checked: this.debugInfo.showObjectInfo, label: "Show Object Info", onCheckedChange: this.handleDebugInfoChange('showObjectInfo') })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, "Show Sync Provider Info"), index.h("p", { class: "settings-description" }, "Display debug information about the sync provider connection status."), index.h("kritzel-slide-toggle", { checked: this.debugInfo.showSyncProviderInfo, label: "Show Sync Provider Info", onCheckedChange: this.handleDebugInfoChange('showSyncProviderInfo') })), index.h("div", { class: "settings-item" }, index.h("label", { class: "settings-label" }, "Show Migration Info"), index.h("p", { class: "settings-description" }, "Display debug information about data migrations."), index.h("kritzel-slide-toggle", { checked: this.debugInfo.showMigrationInfo, label: "Show Migration Info", onCheckedChange: this.handleDebugInfoChange('showMigrationInfo') })))));
28096
28185
  case 'about':
28097
- return (index.h("div", { class: "settings-content" }, index.h("h3", null, "About"), index.h("p", null, "Kritzel - A drawing application"), index.h("p", { class: "version-info" }, "Version ", KRITZEL_VERSION)));
28186
+ return (index.h("div", { class: "settings-content" }, index.h("h3", null, "About"), index.h("p", null, "Kritzel - A drawing application"), index.h("p", { class: "version-info" }, "Version ", KRITZEL_VERSION), index.h("p", { class: "version-info" }, "App-State Schema v", workspace_migrations.CURRENT_APP_STATE_SCHEMA_VERSION), index.h("p", { class: "version-info" }, "Workspace Schema v", workspace_migrations.CURRENT_WORKSPACE_SCHEMA_VERSION)));
28098
28187
  default:
28099
28188
  return null;
28100
28189
  }
28101
28190
  }
28102
28191
  render() {
28103
- return (index.h(index.Host, { key: '358564b01ec3dceb48562a7382b5e6a71f82eb5c' }, index.h("kritzel-dialog", { key: 'ae60c37956c2fae6c16c0c75df94a8210e74cecd', isOpen: this.isDialogOpen, dialogTitle: "Settings", size: "large", onDialogClose: this.closeDialog }, index.h("kritzel-master-detail", { key: '5e26848b125e46e0ddad5f145ffeb380b7321d2e', items: SETTINGS_CATEGORIES, selectedItemId: this.selectedCategoryId, onItemSelect: this.handleCategorySelect }, this.renderCategoryContent()))));
28192
+ return (index.h(index.Host, { key: 'fc940d4154b06378cf13f7cde5238f4a1ac1d2ba' }, index.h("kritzel-dialog", { key: '0c50f5cb3570eba67ce4c04f9f453361e0c9626a', isOpen: this.isDialogOpen, dialogTitle: "Settings", size: "large", onDialogClose: this.closeDialog }, index.h("kritzel-master-detail", { key: '974adda5868d1261784366b59e285a0c45d265ca', items: SETTINGS_CATEGORIES, selectedItemId: this.selectedCategoryId, onItemSelect: this.handleCategorySelect }, this.renderCategoryContent()))));
28104
28193
  }
28105
28194
  };
28106
28195
  KritzelSettings.style = kritzelSettingsCss();
@@ -28300,7 +28389,7 @@ const KritzelSplitButton = class {
28300
28389
  menuOpen;
28301
28390
  menuClose;
28302
28391
  isMenuOpen = false;
28303
- isTouchDevice = alignment_enum.KritzelDevicesHelper.isTouchDevice();
28392
+ isTouchDevice = workspace_migrations.KritzelDevicesHelper.isTouchDevice();
28304
28393
  anchorElement;
28305
28394
  menuScrollTop = 0;
28306
28395
  splitMenuButtonRef;
@@ -28308,6 +28397,7 @@ const KritzelSplitButton = class {
28308
28397
  async open() {
28309
28398
  if (this.isMenuOpen)
28310
28399
  return;
28400
+ window.dispatchEvent(new CustomEvent('kritzel-dismiss-menus'));
28311
28401
  this.isMenuOpen = true;
28312
28402
  this.anchorElement = this.host;
28313
28403
  this.menuOpen.emit();
@@ -28332,6 +28422,7 @@ const KritzelSplitButton = class {
28332
28422
  };
28333
28423
  openMenu = (event) => {
28334
28424
  event.stopPropagation();
28425
+ window.dispatchEvent(new CustomEvent('kritzel-dismiss-menus'));
28335
28426
  this.isMenuOpen = true;
28336
28427
  this.anchorElement = this.host;
28337
28428
  this.menuOpen.emit();
@@ -28364,7 +28455,7 @@ const KritzelSplitButton = class {
28364
28455
  this.menuScrollTop = event.target.scrollTop;
28365
28456
  };
28366
28457
  render() {
28367
- return (index.h(index.Host, { key: '2633a815a27551b87f788c61e6e35a043375d164', class: { mobile: this.isTouchDevice } }, index.h("button", { key: 'd7dcb9c63d5cfa9aea13f3c474bdf612206a0c0d', class: "split-main-button", tabIndex: 0, onClick: this.handleButtonClick, disabled: this.mainButtonDisabled }, this.buttonIcon && index.h("kritzel-icon", { key: '31501575573a05284ad456fee6fa220a2da5cea5', name: this.buttonIcon })), index.h("div", { key: 'a4d4a4d8e12bb9cdea46e224685eecb483cbb638', class: "split-divider" }), index.h("button", { key: 'e762790eeb2c0b7d36b356dcde2a369b66758249', ref: el => (this.splitMenuButtonRef = el), class: "split-menu-button", tabIndex: 0, onClick: this.toggleMenu, disabled: this.menuButtonDisabled }, index.h("kritzel-icon", { key: 'd57f53e4f8a4b535731b2a02455d1e3088d7ab1f', name: this.dropdownIcon })), index.h("kritzel-portal", { key: '4990a1e523b502712422ff1414b657d0f7c5d8a9', anchor: this.anchorElement, offsetY: 4, onClose: this.closeMenu }, index.h("kritzel-menu", { key: 'e28dd4b072b0d13393c6bb350eed67c7d69b985c', ref: el => (this.menuRef = el), items: this.items, onItemSelect: this.handleItemSelect, onItemSave: this.handleItemSave, onItemCancel: this.handleItemCancel, onItemToggleChildMenu: this.handleItemToggleChildMenu, onItemCloseChildMenu: this.handleItemCloseChildMenu, onClose: this.closeMenu, onScroll: this.handleScroll }))));
28458
+ return (index.h(index.Host, { key: '1e85f2b22cde41378d03710bd1332e2eb91ebe5a', class: { mobile: this.isTouchDevice } }, index.h("button", { key: '56573ad5655b2f61e1ebf3c4d85b489375beb62e', class: "split-main-button", tabIndex: 0, onClick: this.handleButtonClick, disabled: this.mainButtonDisabled }, this.buttonIcon && index.h("kritzel-icon", { key: '335c2f5418e305f3e48e3caabc4c48001ddd5ec3', name: this.buttonIcon })), index.h("div", { key: '733e48020f3b21b22de3774323e5a2d024686c2c', class: "split-divider" }), index.h("button", { key: '650cd557b856b5527910cbdeb6d14fe7a88bc0ab', ref: el => (this.splitMenuButtonRef = el), class: "split-menu-button", tabIndex: 0, onClick: this.toggleMenu, disabled: this.menuButtonDisabled }, index.h("kritzel-icon", { key: '3aaacbcdd66583e3884fe44777794209753fe594', name: this.dropdownIcon })), index.h("kritzel-portal", { key: 'd0ca70c21dfbf1684ab84650a31aae77df5cb52e', anchor: this.anchorElement, offsetY: 4, onClose: this.closeMenu }, index.h("kritzel-menu", { key: '9e38d4d6e1c82b6dca3c6d23fb5c0df12bfbefb4', ref: el => (this.menuRef = el), items: this.items, onItemSelect: this.handleItemSelect, onItemSave: this.handleItemSave, onItemCancel: this.handleItemCancel, onItemToggleChildMenu: this.handleItemToggleChildMenu, onItemCloseChildMenu: this.handleItemCloseChildMenu, onClose: this.closeMenu, onScroll: this.handleScroll }))));
28368
28459
  }
28369
28460
  };
28370
28461
  KritzelSplitButton.style = kritzelSplitButtonCss();
@@ -28441,7 +28532,7 @@ const KritzelToolConfig = class {
28441
28532
  currentOpacity = 1;
28442
28533
  updateTrigger = 0;
28443
28534
  handleSelectionChange() {
28444
- if (this.tool instanceof alignment_enum.KritzelSelectionTool) {
28535
+ if (this.tool instanceof workspace_migrations.KritzelSelectionTool) {
28445
28536
  this.config = KritzelToolConfigHelper.getToolConfig(this.tool);
28446
28537
  if (this.config) {
28447
28538
  this.updatePalette();
@@ -28465,10 +28556,10 @@ const KritzelToolConfig = class {
28465
28556
  const opacity = this.currentOpacity;
28466
28557
  const size = this.tool[this.config.sizeProperty];
28467
28558
  const displayValues = {
28468
- color: alignment_enum.KritzelColorHelper.applyOpacity(color, opacity, this.theme),
28559
+ color: workspace_migrations.KritzelColorHelper.applyOpacity(color, opacity, this.theme),
28469
28560
  size,
28470
28561
  };
28471
- if (this.tool instanceof alignment_enum.KritzelTextTool) {
28562
+ if (this.tool instanceof workspace_migrations.KritzelTextTool) {
28472
28563
  displayValues.fontFamily = this.tool.fontFamily;
28473
28564
  }
28474
28565
  this.displayValuesChange.emit(displayValues);
@@ -28831,7 +28922,7 @@ const KritzelWorkspaceManager = class {
28831
28922
  }
28832
28923
  async add() {
28833
28924
  await this.splitButtonRef.open();
28834
- this.newWorkspace = new alignment_enum.KritzelWorkspace(alignment_enum.ObjectHelper.generateUUID(), 'New Workspace');
28925
+ this.newWorkspace = new workspace_migrations.KritzelWorkspace(workspace_migrations.ObjectHelper.generateUUID(), 'New Workspace');
28835
28926
  this.editingItemId = this.newWorkspace.id;
28836
28927
  }
28837
28928
  edit(item) {