kritzel-stencil 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/dist/cjs/{default-line-tool.config-7eJND6Jb.js → default-line-tool.config-MA02HCrH.js} +703 -133
  2. package/dist/cjs/{index-BeKMS-Zt.js → index-Bj0n7fQQ.js} +84 -7
  3. package/dist/cjs/index.cjs.js +1 -1
  4. package/dist/cjs/kritzel-brush-style.cjs.entry.js +1 -1
  5. package/dist/cjs/{kritzel-color_22.cjs.entry.js → kritzel-color_24.cjs.entry.js} +1018 -897
  6. package/dist/cjs/loader.cjs.js +2 -2
  7. package/dist/cjs/stencil.cjs.js +3 -3
  8. package/dist/collection/classes/core/core.class.js +2 -0
  9. package/dist/collection/classes/core/viewport.class.js +43 -3
  10. package/dist/collection/classes/handlers/move.handler.js +6 -0
  11. package/dist/collection/classes/objects/line.class.js +63 -15
  12. package/dist/collection/classes/objects/path.class.js +1 -0
  13. package/dist/collection/classes/objects/shape.class.js +1 -0
  14. package/dist/collection/classes/objects/text.class.js +4 -3
  15. package/dist/collection/classes/providers/indexeddb-sync-provider.class.js +0 -1
  16. package/dist/collection/classes/tools/brush-tool.class.js +5 -0
  17. package/dist/collection/classes/tools/line-tool.class.js +31 -1
  18. package/dist/collection/classes/tools/selection-tool.class.js +193 -0
  19. package/dist/collection/classes/tools/shape-tool.class.js +2 -0
  20. package/dist/collection/classes/tools/text-tool.class.js +3 -0
  21. package/dist/collection/collection-manifest.json +5 -3
  22. package/dist/collection/components/core/kritzel-cursor-trail/kritzel-cursor-trail.js +3 -2
  23. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +37 -19
  24. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +108 -36
  25. package/dist/collection/components/shared/kritzel-color/kritzel-color.js +2 -2
  26. package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.css +1 -1
  27. package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js +24 -2
  28. package/dist/collection/components/shared/kritzel-font/kritzel-font.js +1 -1
  29. package/dist/collection/components/shared/kritzel-font-family/kritzel-font-family.css +1 -1
  30. package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.css +1 -1
  31. package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js +1 -1
  32. package/dist/collection/components/shared/kritzel-line-endings/kritzel-line-endings.css +60 -0
  33. package/dist/collection/components/shared/kritzel-line-endings/kritzel-line-endings.js +187 -0
  34. package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js +15 -8
  35. package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js +16 -9
  36. package/dist/collection/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.css +85 -0
  37. package/dist/collection/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.js +163 -0
  38. package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js +1 -1
  39. package/dist/collection/components/shared/kritzel-shape-fill/kritzel-shape-fill.css +47 -0
  40. package/dist/collection/components/shared/kritzel-shape-fill/kritzel-shape-fill.js +93 -0
  41. package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js +13 -7
  42. package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.css +11 -2
  43. package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js +2 -2
  44. package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.css +1 -1
  45. package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js +6 -4
  46. package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.js +6 -3
  47. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.css +66 -0
  48. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +153 -50
  49. package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.css +38 -0
  50. package/dist/collection/components/ui/kritzel-tool-config/kritzel-tool-config.js +321 -0
  51. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js +3 -2
  52. package/dist/collection/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.js +6 -3
  53. package/dist/collection/configs/default-brush-tool.config.js +2 -52
  54. package/dist/collection/configs/default-line-tool.config.js +2 -26
  55. package/dist/collection/configs/default-shape-tool.config.js +2 -15
  56. package/dist/collection/configs/default-text-tool.config.js +2 -26
  57. package/dist/collection/constants/color-palette.constants.js +30 -0
  58. package/dist/collection/helpers/color.helper.js +31 -0
  59. package/dist/collection/helpers/tool-config.helper.js +65 -0
  60. package/dist/collection/interfaces/tool-config.interface.js +1 -0
  61. package/dist/components/index.d.ts +8 -4
  62. package/dist/components/index.js +1 -1
  63. package/dist/components/kritzel-brush-style.js +1 -1
  64. package/dist/components/kritzel-color-palette.js +1 -1
  65. package/dist/components/kritzel-color.js +1 -1
  66. package/dist/components/kritzel-context-menu.js +1 -1
  67. package/dist/components/kritzel-controls.js +1 -1
  68. package/dist/components/kritzel-cursor-trail.js +1 -1
  69. package/dist/components/kritzel-dropdown.js +1 -1
  70. package/dist/components/kritzel-editor.js +1 -1
  71. package/dist/components/kritzel-engine.js +1 -1
  72. package/dist/components/kritzel-font-family.js +1 -1
  73. package/dist/components/kritzel-font-size.js +1 -1
  74. package/dist/components/kritzel-font.js +1 -1
  75. package/dist/components/kritzel-icon.js +1 -1
  76. package/dist/components/kritzel-line-endings.d.ts +11 -0
  77. package/dist/components/kritzel-line-endings.js +1 -0
  78. package/dist/components/kritzel-menu-item.js +1 -1
  79. package/dist/components/kritzel-menu.js +1 -1
  80. package/dist/components/kritzel-opacity-slider.d.ts +11 -0
  81. package/dist/components/kritzel-opacity-slider.js +1 -0
  82. package/dist/components/kritzel-portal.js +1 -1
  83. package/dist/components/kritzel-shape-fill.d.ts +11 -0
  84. package/dist/components/kritzel-shape-fill.js +1 -0
  85. package/dist/components/kritzel-split-button.js +1 -1
  86. package/dist/components/kritzel-stroke-size.js +1 -1
  87. package/dist/components/kritzel-tool-config.d.ts +11 -0
  88. package/dist/components/kritzel-tool-config.js +1 -0
  89. package/dist/components/kritzel-tooltip.js +1 -1
  90. package/dist/components/kritzel-utility-panel.js +1 -1
  91. package/dist/components/kritzel-workspace-manager.js +1 -1
  92. package/dist/components/p-83YX0-FS.js +1 -0
  93. package/dist/components/p-8iEiCuEN.js +1 -0
  94. package/dist/components/p-9XZbc_qK.js +1 -0
  95. package/dist/components/p-B3P64-gH.js +9 -0
  96. package/dist/components/p-B8QjTqOY.js +1 -0
  97. package/dist/components/p-BF6MdW17.js +1 -0
  98. package/dist/components/p-BVIY50lR.js +1 -0
  99. package/dist/components/p-BbqT9o1F.js +1 -0
  100. package/dist/components/{p-CXzfYQ_u.js → p-BnidlyU0.js} +1 -1
  101. package/dist/components/{p-Bj_Og27M.js → p-BxS4Pdpz.js} +1 -1
  102. package/dist/components/{p-g0N9j_uT.js → p-CCj8nmQH.js} +1 -1
  103. package/dist/components/{p-1z-ds26_.js → p-CLOnpu42.js} +1 -1
  104. package/dist/components/{p-D1tfzpy8.js → p-CSGeDE4f.js} +1 -1
  105. package/dist/components/p-CbuHMNa9.js +1 -0
  106. package/dist/components/p-ClMFs3KI.js +1 -0
  107. package/dist/components/{p-IAqZFssU.js → p-Cnpk2hfo.js} +1 -1
  108. package/dist/components/{p-Cy77SpWt.js → p-Ctv4NAxk.js} +1 -1
  109. package/dist/components/p-CyHZWbkS.js +1 -0
  110. package/dist/components/{p-C4krHoUl.js → p-D8GeJNUv.js} +1 -1
  111. package/dist/components/{p-DB5s1NY4.js → p-DKgqzi2Y.js} +1 -1
  112. package/dist/components/p-DOF5fWDU.js +1 -0
  113. package/dist/components/{p-4FEa4ADy.js → p-DV_h5Jo2.js} +1 -1
  114. package/dist/components/{p-DTezr6w9.js → p-DgCGSL2Q.js} +1 -1
  115. package/dist/components/{p-D5ZsALCP.js → p-wRXL928z.js} +1 -1
  116. package/dist/esm/{default-line-tool.config-CD5sTKH-.js → default-line-tool.config-DLpNl6R9.js} +702 -125
  117. package/dist/esm/{index-BqhmuUH2.js → index-OLdaFN6W.js} +84 -7
  118. package/dist/esm/index.js +2 -2
  119. package/dist/esm/kritzel-brush-style.entry.js +1 -1
  120. package/dist/esm/{kritzel-color_22.entry.js → kritzel-color_24.entry.js} +1009 -890
  121. package/dist/esm/loader.js +3 -3
  122. package/dist/esm/stencil.js +4 -4
  123. package/dist/stencil/index.esm.js +1 -1
  124. package/dist/stencil/{p-09295079.entry.js → p-802bc7cf.entry.js} +1 -1
  125. package/dist/stencil/p-DLpNl6R9.js +1 -0
  126. package/dist/stencil/p-OLdaFN6W.js +2 -0
  127. package/dist/stencil/p-caf30edb.entry.js +9 -0
  128. package/dist/stencil/stencil.esm.js +1 -1
  129. package/dist/types/classes/core/viewport.class.d.ts +6 -0
  130. package/dist/types/classes/managers/anchor.manager.d.ts +1 -1
  131. package/dist/types/classes/objects/line.class.d.ts +2 -0
  132. package/dist/types/classes/objects/shape.class.d.ts +1 -0
  133. package/dist/types/classes/tools/brush-tool.class.d.ts +1 -0
  134. package/dist/types/classes/tools/line-tool.class.d.ts +2 -1
  135. package/dist/types/classes/tools/selection-tool.class.d.ts +22 -0
  136. package/dist/types/classes/tools/shape-tool.class.d.ts +1 -0
  137. package/dist/types/classes/tools/text-tool.class.d.ts +1 -0
  138. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +2 -0
  139. package/dist/types/components/shared/kritzel-color-palette/kritzel-color-palette.d.ts +1 -0
  140. package/dist/types/components/shared/kritzel-line-endings/kritzel-line-endings.d.ts +23 -0
  141. package/dist/types/components/shared/kritzel-opacity-slider/kritzel-opacity-slider.d.ts +17 -0
  142. package/dist/types/components/shared/kritzel-shape-fill/kritzel-shape-fill.d.ts +10 -0
  143. package/dist/types/components/ui/kritzel-controls/kritzel-controls.d.ts +15 -0
  144. package/dist/types/components/ui/kritzel-tool-config/kritzel-tool-config.d.ts +25 -0
  145. package/dist/types/components.d.ts +235 -82
  146. package/dist/types/constants/color-palette.constants.d.ts +5 -0
  147. package/dist/types/helpers/color.helper.d.ts +9 -0
  148. package/dist/types/helpers/tool-config.helper.d.ts +4 -0
  149. package/dist/types/interfaces/line-options.interface.d.ts +1 -0
  150. package/dist/types/interfaces/path-options.interface.d.ts +1 -0
  151. package/dist/types/interfaces/tool-config.interface.d.ts +26 -0
  152. package/dist/types/stencil-public-runtime.d.ts +29 -0
  153. package/package.json +5 -3
  154. package/dist/collection/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.css +0 -19
  155. package/dist/collection/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.js +0 -134
  156. package/dist/collection/components/ui/kritzel-control-text-config/kritzel-control-text-config.css +0 -19
  157. package/dist/collection/components/ui/kritzel-control-text-config/kritzel-control-text-config.js +0 -114
  158. package/dist/components/kritzel-control-brush-config.d.ts +0 -11
  159. package/dist/components/kritzel-control-brush-config.js +0 -1
  160. package/dist/components/kritzel-control-text-config.d.ts +0 -11
  161. package/dist/components/kritzel-control-text-config.js +0 -1
  162. package/dist/components/p-B7Fdo5QJ.js +0 -1
  163. package/dist/components/p-BXaWhpO2.js +0 -1
  164. package/dist/components/p-BtuXeItZ.js +0 -1
  165. package/dist/components/p-C-d2IH4v.js +0 -1
  166. package/dist/components/p-C3UriJh7.js +0 -1
  167. package/dist/components/p-CF5L2Gdl.js +0 -1
  168. package/dist/components/p-CeKT_dTd.js +0 -1
  169. package/dist/components/p-Cp15toXH.js +0 -1
  170. package/dist/components/p-D3LRBk2t.js +0 -9
  171. package/dist/components/p-Du1vxHy8.js +0 -1
  172. package/dist/stencil/p-381c0e9c.entry.js +0 -9
  173. package/dist/stencil/p-BqhmuUH2.js +0 -2
  174. package/dist/stencil/p-CD5sTKH-.js +0 -1
  175. package/dist/types/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.d.ts +0 -15
  176. package/dist/types/components/ui/kritzel-control-text-config/kritzel-control-text-config.d.ts +0 -12
@@ -14043,13 +14043,14 @@ class KritzelText extends KritzelBaseObject {
14043
14043
  if (element === null || this.isInViewport() === false) {
14044
14044
  return;
14045
14045
  }
14046
+ element.style.fontFamily = this.fontFamily;
14047
+ element.style.fontSize = `${this.fontSize}pt`;
14048
+ element.style.color = this.fontColor;
14046
14049
  if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
14050
+ requestAnimationFrame(() => this.adjustSizeOnInput());
14047
14051
  return;
14048
14052
  }
14049
14053
  this.elementRef = element;
14050
- this.elementRef.style.fontFamily = this.fontFamily;
14051
- this.elementRef.style.fontSize = `${this.fontSize}pt`;
14052
- this.elementRef.style.color = this.fontColor;
14053
14054
  this.elementRef.style.whiteSpace = 'pre-wrap';
14054
14055
  this.elementRef.style.wordWrap = 'break-word';
14055
14056
  this.elementRef.innerHTML = '';
@@ -14290,6 +14291,7 @@ class KritzelPath extends KritzelBaseObject {
14290
14291
  object.scale = options?.scale ?? 1;
14291
14292
  object.strokeWidth = options?.strokeWidth ?? 8;
14292
14293
  object.fill = options?.fill ?? '#000000';
14294
+ object.opacity = options?.opacity ?? 1;
14293
14295
  object.zIndex = core.store.currentZIndex;
14294
14296
  object.d = object.generateSvgPath();
14295
14297
  object.updateDimensions();
@@ -14687,6 +14689,7 @@ class KritzelLine extends KritzelBaseObject {
14687
14689
  isDebugInfoVisible = true;
14688
14690
  isCompleted = false;
14689
14691
  _adjustedPoints = null;
14692
+ _clipInfo = null;
14690
14693
  get d() {
14691
14694
  if (this.controlX !== undefined && this.controlY !== undefined) {
14692
14695
  return `M ${this.startX} ${this.startY} Q ${this.controlX} ${this.controlY} ${this.endX} ${this.endY}`;
@@ -14732,6 +14735,7 @@ class KritzelLine extends KritzelBaseObject {
14732
14735
  object.scale = options?.scale ?? 1;
14733
14736
  object.strokeWidth = options?.strokeWidth ?? 4;
14734
14737
  object.stroke = options?.stroke ?? '#000000';
14738
+ object.opacity = options?.opacity ?? 1;
14735
14739
  object.startAnchor = options?.startAnchor;
14736
14740
  object.endAnchor = options?.endAnchor;
14737
14741
  object.arrows = options?.arrows;
@@ -14764,6 +14768,7 @@ class KritzelLine extends KritzelBaseObject {
14764
14768
  this.translateX = x;
14765
14769
  this.translateY = y;
14766
14770
  this._adjustedPoints = null;
14771
+ this._clipInfo = null;
14767
14772
  this._core.store.state.objects.update(this);
14768
14773
  // Update anchors after the line is updated
14769
14774
  this._core.anchorManager.updateAnchorsForObject(this.id);
@@ -14777,6 +14782,7 @@ class KritzelLine extends KritzelBaseObject {
14777
14782
  rotate(value) {
14778
14783
  this.rotation = value;
14779
14784
  this._adjustedPoints = null;
14785
+ this._clipInfo = null;
14780
14786
  this._core.store.state.objects.update(this);
14781
14787
  }
14782
14788
  move(startX, startY, endX, endY) {
@@ -14792,6 +14798,7 @@ class KritzelLine extends KritzelBaseObject {
14792
14798
  this._core.anchorManager.updateAnchorsForObject(this.endAnchor.objectId);
14793
14799
  }
14794
14800
  this._adjustedPoints = null;
14801
+ this._clipInfo = null;
14795
14802
  this._core.store.state.objects.update(this);
14796
14803
  }
14797
14804
  hitTest(x, y) {
@@ -14803,12 +14810,16 @@ class KritzelLine extends KritzelBaseObject {
14803
14810
  }
14804
14811
  // For curved lines, use distance to the Bezier curve
14805
14812
  if (this.controlX !== undefined && this.controlY !== undefined) {
14806
- const distance = this.pointToBezierDistance(x, y);
14813
+ const clip = this.getClipInfo();
14814
+ const startT = clip.start?.t ?? 0;
14815
+ const endT = clip.end?.t ?? 1;
14816
+ const distance = this.pointToBezierDistance(x, y, startT, endT);
14807
14817
  return distance <= halfStroke;
14808
14818
  }
14809
14819
  // For straight lines, use distance to line segment
14810
- const p1 = this._adjustedPoints[0];
14811
- const p2 = this._adjustedPoints[1];
14820
+ const clip = this.getClipInfo();
14821
+ const p1 = clip.start ? [clip.start.x, clip.start.y] : this._adjustedPoints[0];
14822
+ const p2 = clip.end ? [clip.end.x, clip.end.y] : this._adjustedPoints[1];
14812
14823
  const distance = this.pointToLineSegmentDistance(x, y, p1[0], p1[1], p2[0], p2[1]);
14813
14824
  return distance <= halfStroke;
14814
14825
  }
@@ -14817,6 +14828,7 @@ class KritzelLine extends KritzelBaseObject {
14817
14828
  if (this._adjustedPoints === null) {
14818
14829
  this._adjustedPoints = this.computeAdjustedPoints();
14819
14830
  }
14831
+ const clip = this.getClipInfo();
14820
14832
  const polyPoints = [
14821
14833
  { x: polygon.bottomLeft.x, y: polygon.bottomLeft.y },
14822
14834
  { x: polygon.bottomRight.x, y: polygon.bottomRight.y },
@@ -14824,7 +14836,11 @@ class KritzelLine extends KritzelBaseObject {
14824
14836
  { x: polygon.topLeft.x, y: polygon.topLeft.y },
14825
14837
  ];
14826
14838
  // Check if any endpoint is inside the polygon
14827
- for (const [px, py] of this._adjustedPoints) {
14839
+ // Use clipped endpoints
14840
+ const p1 = clip.start ? [clip.start.x, clip.start.y] : this._adjustedPoints[0];
14841
+ const p2 = clip.end ? [clip.end.x, clip.end.y] : this._adjustedPoints[1];
14842
+ const endpoints = [p1, p2];
14843
+ for (const [px, py] of endpoints) {
14828
14844
  if (KritzelGeometryHelper.isPointInPolygon({ x: px, y: py }, polyPoints)) {
14829
14845
  return true;
14830
14846
  }
@@ -14840,9 +14856,12 @@ class KritzelLine extends KritzelBaseObject {
14840
14856
  const p0 = this._adjustedPoints[0];
14841
14857
  const p2 = this._adjustedPoints[1];
14842
14858
  const controlAdjusted = this.computeAdjustedControlPoint();
14859
+ const startT = clip.start?.t ?? 0;
14860
+ const endT = clip.end?.t ?? 1;
14843
14861
  const samples = 20;
14844
- for (let i = 1; i < samples; i++) {
14845
- const t = i / samples;
14862
+ for (let i = 0; i <= samples; i++) {
14863
+ const fraction = i / samples;
14864
+ const t = startT + fraction * (endT - startT);
14846
14865
  const oneMinusT = 1 - t;
14847
14866
  const bx = oneMinusT * oneMinusT * p0[0] + 2 * oneMinusT * t * controlAdjusted[0] + t * t * p2[0];
14848
14867
  const by = oneMinusT * oneMinusT * p0[1] + 2 * oneMinusT * t * controlAdjusted[1] + t * t * p2[1];
@@ -14862,19 +14881,19 @@ class KritzelLine extends KritzelBaseObject {
14862
14881
  return false;
14863
14882
  }
14864
14883
  // For straight lines, check if line intersects any polygon edge
14865
- const p1 = { x: this._adjustedPoints[0][0], y: this._adjustedPoints[0][1] };
14866
- const p2 = { x: this._adjustedPoints[1][0], y: this._adjustedPoints[1][1] };
14884
+ const checkP1 = { x: p1[0], y: p1[1] };
14885
+ const checkP2 = { x: p2[0], y: p2[1] };
14867
14886
  for (let j = 0; j < polyPoints.length; j++) {
14868
14887
  const q1 = polyPoints[j];
14869
14888
  const q2 = polyPoints[(j + 1) % polyPoints.length];
14870
- if (KritzelGeometryHelper.intersectLines(p1, p2, q1, q2)) {
14889
+ if (KritzelGeometryHelper.intersectLines(checkP1, checkP2, q1, q2)) {
14871
14890
  return true;
14872
14891
  }
14873
14892
  // Check distance from polygon edges to line segment
14874
- const d1 = this.pointToLineSegmentDistance(q1.x, q1.y, p1.x, p1.y, p2.x, p2.y);
14875
- const d2 = this.pointToLineSegmentDistance(q2.x, q2.y, p1.x, p1.y, p2.x, p2.y);
14876
- const d3 = this.pointToLineSegmentDistance(p1.x, p1.y, q1.x, q1.y, q2.x, q2.y);
14877
- const d4 = this.pointToLineSegmentDistance(p2.x, p2.y, q1.x, q1.y, q2.x, q2.y);
14893
+ const d1 = this.pointToLineSegmentDistance(q1.x, q1.y, checkP1.x, checkP1.y, checkP2.x, checkP2.y);
14894
+ const d2 = this.pointToLineSegmentDistance(q2.x, q2.y, checkP1.x, checkP1.y, checkP2.x, checkP2.y);
14895
+ const d3 = this.pointToLineSegmentDistance(checkP1.x, checkP1.y, q1.x, q1.y, q2.x, q2.y);
14896
+ const d4 = this.pointToLineSegmentDistance(checkP2.x, checkP2.y, q1.x, q1.y, q2.x, q2.y);
14878
14897
  const minD = Math.min(d1, d2, d3, d4);
14879
14898
  if (minD <= halfStroke) {
14880
14899
  return true;
@@ -14886,6 +14905,7 @@ class KritzelLine extends KritzelBaseObject {
14886
14905
  this.translateX = x;
14887
14906
  this.translateY = y;
14888
14907
  this._adjustedPoints = null;
14908
+ this._clipInfo = null;
14889
14909
  this._core.store.state.objects.update(this);
14890
14910
  }
14891
14911
  /**
@@ -14944,6 +14964,7 @@ class KritzelLine extends KritzelBaseObject {
14944
14964
  this.translateY += correctionY / this.scale;
14945
14965
  // Clear cached adjusted points
14946
14966
  this._adjustedPoints = null;
14967
+ this._clipInfo = null;
14947
14968
  this._core.store.state.objects.update(this);
14948
14969
  }
14949
14970
  updateControlPoint(newX, newY) {
@@ -14986,6 +15007,7 @@ class KritzelLine extends KritzelBaseObject {
14986
15007
  this.translateY += correctionY / this.scale;
14987
15008
  // Clear cached adjusted points
14988
15009
  this._adjustedPoints = null;
15010
+ this._clipInfo = null;
14989
15011
  this._core.store.state.objects.update(this);
14990
15012
  }
14991
15013
  computeAdjustedPoints() {
@@ -15042,7 +15064,7 @@ class KritzelLine extends KritzelBaseObject {
15042
15064
  * Calculates the minimum distance from a point to a quadratic Bezier curve.
15043
15065
  * Uses sampling along the curve to find the closest point.
15044
15066
  */
15045
- pointToBezierDistance(x, y) {
15067
+ pointToBezierDistance(x, y, startT = 0, endT = 1) {
15046
15068
  if (this._adjustedPoints === null) {
15047
15069
  this._adjustedPoints = this.computeAdjustedPoints();
15048
15070
  }
@@ -15053,7 +15075,8 @@ class KritzelLine extends KritzelBaseObject {
15053
15075
  let minDistance = Infinity;
15054
15076
  const samples = 20; // Number of samples along the curve
15055
15077
  for (let i = 0; i <= samples; i++) {
15056
- const t = i / samples;
15078
+ const fraction = i / samples;
15079
+ const t = startT + fraction * (endT - startT);
15057
15080
  const oneMinusT = 1 - t;
15058
15081
  // Quadratic Bezier: B(t) = (1-t)²P₀ + 2(1-t)tP₁ + t²P₂
15059
15082
  const bx = oneMinusT * oneMinusT * p0[0] + 2 * oneMinusT * t * controlAdjusted[0] + t * t * p2[0];
@@ -15067,6 +15090,33 @@ class KritzelLine extends KritzelBaseObject {
15067
15090
  }
15068
15091
  return minDistance;
15069
15092
  }
15093
+ getClipInfo() {
15094
+ if (this._clipInfo)
15095
+ return this._clipInfo;
15096
+ const startAnchor = this.startAnchor;
15097
+ const endAnchor = this.endAnchor;
15098
+ const result = {};
15099
+ if (startAnchor) {
15100
+ const target = this._core.anchorManager.findAnchorTarget(this, 'start');
15101
+ if (target) {
15102
+ const clip = this._core.anchorManager.computeAnchorClipInfo(this, 'start', target);
15103
+ if (clip) {
15104
+ result.start = { x: clip.worldX, y: clip.worldY, t: clip.t };
15105
+ }
15106
+ }
15107
+ }
15108
+ if (endAnchor) {
15109
+ const target = this._core.anchorManager.findAnchorTarget(this, 'end');
15110
+ if (target) {
15111
+ const clip = this._core.anchorManager.computeAnchorClipInfo(this, 'end', target);
15112
+ if (clip) {
15113
+ result.end = { x: clip.worldX, y: clip.worldY, t: clip.t };
15114
+ }
15115
+ }
15116
+ }
15117
+ this._clipInfo = result;
15118
+ return result;
15119
+ }
15070
15120
  /**
15071
15121
  * Computes the adjusted control point in world coordinates, accounting for rotation and translation.
15072
15122
  */
@@ -15728,6 +15778,7 @@ class KritzelBrushTool extends KritzelBaseTool {
15728
15778
  type = 'pen';
15729
15779
  color = '#000000';
15730
15780
  size = 6;
15781
+ opacity = 1;
15731
15782
  palettes = {
15732
15783
  pen: ['#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF', '#808080', '#C0C0C0', '#800000', '#008000', '#000080', '#800080'],
15733
15784
  highlighter: ['#ffff00', '#ffb347', '#b4ffb4'],
@@ -15752,6 +15803,7 @@ class KritzelBrushTool extends KritzelBaseTool {
15752
15803
  scale: this._core.store.state.scale,
15753
15804
  fill: this.color,
15754
15805
  strokeWidth: this.size,
15806
+ opacity: this.opacity,
15755
15807
  });
15756
15808
  path.isCompleted = false;
15757
15809
  this._currentPathId = path.id;
@@ -15771,6 +15823,7 @@ class KritzelBrushTool extends KritzelBaseTool {
15771
15823
  scale: this._core.store.state.scale,
15772
15824
  fill: this.color,
15773
15825
  strokeWidth: this.size,
15826
+ opacity: this.opacity,
15774
15827
  });
15775
15828
  path.isCompleted = false;
15776
15829
  this._currentPathId = path.id;
@@ -15796,6 +15849,7 @@ class KritzelBrushTool extends KritzelBaseTool {
15796
15849
  scale: this._core.store.state.scale,
15797
15850
  fill: this.color,
15798
15851
  strokeWidth: this.size,
15852
+ opacity: this.opacity,
15799
15853
  });
15800
15854
  updatedPath.id = currentPath.id;
15801
15855
  updatedPath.workspaceId = currentPath.workspaceId;
@@ -15821,6 +15875,7 @@ class KritzelBrushTool extends KritzelBaseTool {
15821
15875
  scale: this._core.store.state.scale,
15822
15876
  fill: this.color,
15823
15877
  strokeWidth: this.size,
15878
+ opacity: this.opacity,
15824
15879
  });
15825
15880
  updatedPath.id = currentPath.id;
15826
15881
  updatedPath.workspaceId = currentPath.workspaceId;
@@ -16203,7 +16258,33 @@ class KritzelSelectionGroup extends KritzelBaseObject {
16203
16258
  class KritzelLineTool extends KritzelBaseTool {
16204
16259
  color = '#000000';
16205
16260
  size = 4;
16206
- palettes = ['#000000', '#FFFFFF', '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF', '#808080', '#C0C0C0', '#800000', '#008000', '#000080', '#808000', '#800080'];
16261
+ opacity = 1;
16262
+ palette = [
16263
+ '#000000',
16264
+ '#ff5252',
16265
+ '#ffbc00',
16266
+ '#00c853',
16267
+ '#0000FF',
16268
+ '#d500f9',
16269
+ '#fafafa',
16270
+ '#a52714',
16271
+ '#ee8100',
16272
+ '#558b2f',
16273
+ '#01579b',
16274
+ '#8e24aa',
16275
+ '#90a4ae',
16276
+ '#ff4081',
16277
+ '#ff6e40',
16278
+ '#aeea00',
16279
+ '#304ffe',
16280
+ '#7c4dff',
16281
+ '#cfd8dc',
16282
+ '#f8bbd0',
16283
+ '#ffccbc',
16284
+ '#f0f4c3',
16285
+ '#9fa8da',
16286
+ '#d1c4e9',
16287
+ ];
16207
16288
  /** Arrow head configuration for lines created with this tool */
16208
16289
  arrows;
16209
16290
  _startX = 0;
@@ -16232,6 +16313,7 @@ class KritzelLineTool extends KritzelBaseTool {
16232
16313
  scale: this._core.store.state.scale,
16233
16314
  stroke: this.color,
16234
16315
  strokeWidth: this.size,
16316
+ opacity: this.opacity,
16235
16317
  arrows: this.arrows,
16236
16318
  });
16237
16319
  line.isCompleted = false;
@@ -16256,6 +16338,7 @@ class KritzelLineTool extends KritzelBaseTool {
16256
16338
  scale: this._core.store.state.scale,
16257
16339
  stroke: this.color,
16258
16340
  strokeWidth: this.size,
16341
+ opacity: this.opacity,
16259
16342
  arrows: this.arrows,
16260
16343
  });
16261
16344
  line.isCompleted = false;
@@ -16283,6 +16366,7 @@ class KritzelLineTool extends KritzelBaseTool {
16283
16366
  scale: this._core.store.state.scale,
16284
16367
  stroke: this.color,
16285
16368
  strokeWidth: this.size,
16369
+ opacity: this.opacity,
16286
16370
  arrows: this.arrows,
16287
16371
  });
16288
16372
  updatedLine.id = currentLine.id;
@@ -16310,6 +16394,7 @@ class KritzelLineTool extends KritzelBaseTool {
16310
16394
  scale: this._core.store.state.scale,
16311
16395
  stroke: this.color,
16312
16396
  strokeWidth: this.size,
16397
+ opacity: this.opacity,
16313
16398
  arrows: this.arrows,
16314
16399
  });
16315
16400
  updatedLine.id = currentLine.id;
@@ -16542,6 +16627,7 @@ class KritzelTextTool extends KritzelBaseTool {
16542
16627
  fontFamily = 'Arial';
16543
16628
  fontSize = 16;
16544
16629
  fontColor = '#000000';
16630
+ opacity = 1;
16545
16631
  palette = [
16546
16632
  '#000000',
16547
16633
  '#FFFFFF',
@@ -16592,6 +16678,7 @@ class KritzelTextTool extends KritzelBaseTool {
16592
16678
  const clientY = event.clientY - this._core.store.offsetY;
16593
16679
  const text = KritzelText.create(this._core, this.fontSize, this.fontFamily);
16594
16680
  text.fontColor = this.fontColor;
16681
+ text.opacity = this.opacity;
16595
16682
  text.translateX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
16596
16683
  text.translateY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
16597
16684
  text.zIndex = this._core.store.currentZIndex;
@@ -16626,6 +16713,7 @@ class KritzelTextTool extends KritzelBaseTool {
16626
16713
  const clientY = Math.round(activePointers[0].clientY - this._core.store.offsetY);
16627
16714
  const text = KritzelText.create(this._core, this.fontSize, this.fontFamily);
16628
16715
  text.fontColor = this.fontColor;
16716
+ text.opacity = this.opacity;
16629
16717
  text.translateX = (clientX - this._core.store.state.translateX) / this._core.store.state.scale;
16630
16718
  text.translateY = (clientY - this._core.store.state.translateY) / this._core.store.state.scale;
16631
16719
  text.zIndex = this._core.store.currentZIndex;
@@ -16946,6 +17034,12 @@ class KritzelMoveHandler extends KritzelBaseHandler {
16946
17034
  if (!selectionGroup) {
16947
17035
  return;
16948
17036
  }
17037
+ // Only disconnect lines if the selection group contains ONLY lines.
17038
+ // If moving lines with other objects (e.g. shapes they might be anchored to), prevent auto-disconnect.
17039
+ const onlyLines = selectionGroup.objects.every(obj => obj instanceof KritzelLine);
17040
+ if (!onlyLines) {
17041
+ return;
17042
+ }
16949
17043
  // Find and disconnect anchors from all anchored lines in the selection
16950
17044
  for (const obj of selectionGroup.objects) {
16951
17045
  // Skip if already disconnected in this drag session
@@ -17978,6 +18072,404 @@ class KritzelLineHandleHandler extends KritzelBaseHandler {
17978
18072
  }
17979
18073
  }
17980
18074
 
18075
+ exports.ShapeType = void 0;
18076
+ (function (ShapeType) {
18077
+ ShapeType["Rectangle"] = "rectangle";
18078
+ ShapeType["Ellipse"] = "ellipse";
18079
+ ShapeType["Triangle"] = "triangle";
18080
+ })(exports.ShapeType || (exports.ShapeType = {}));
18081
+
18082
+ class KritzelShape extends KritzelBaseObject {
18083
+ __class__ = 'KritzelShape';
18084
+ shapeType = exports.ShapeType.Rectangle;
18085
+ fillColor = 'transparent';
18086
+ strokeColor = '#000000';
18087
+ strokeWidth = 4;
18088
+ fontFamily = 'Arial';
18089
+ fontSize = 16;
18090
+ fontColor = '#000000';
18091
+ /** Screen-space x coordinate of the shape's top-left corner (like Path.x) */
18092
+ x = 0;
18093
+ /** Screen-space y coordinate of the shape's top-left corner (like Path.y) */
18094
+ y = 0;
18095
+ scale = 1;
18096
+ scaleFactor = 1;
18097
+ isDebugInfoVisible = true;
18098
+ isEditable = true;
18099
+ isEditing = false;
18100
+ editor = null;
18101
+ content = null;
18102
+ _schema = new Schema$1({
18103
+ nodes: addListNodes(schema.spec.nodes, 'paragraph block*', 'block'),
18104
+ marks: schema.spec.marks,
18105
+ });
18106
+ uneditedObject = null;
18107
+ /**
18108
+ * Returns the viewBox for the shape's SVG, using screen-space coordinates.
18109
+ * This follows the same pattern as KritzelPath.viewBox.
18110
+ */
18111
+ get viewBox() {
18112
+ return `${this.x} ${this.y} ${this.width} ${this.height}`;
18113
+ }
18114
+ constructor(config) {
18115
+ super();
18116
+ if (config) {
18117
+ this.x = config.x ?? 0;
18118
+ this.y = config.y ?? 0;
18119
+ this.translateX = config.translateX ?? 0;
18120
+ this.translateY = config.translateY ?? 0;
18121
+ this.width = config.width ?? 100;
18122
+ this.height = config.height ?? 100;
18123
+ this.shapeType = config.shapeType ?? exports.ShapeType.Rectangle;
18124
+ this.fillColor = config.fillColor ?? 'transparent';
18125
+ this.strokeColor = config.strokeColor ?? '#000000';
18126
+ this.strokeWidth = config.strokeWidth ?? 4;
18127
+ this.fontSize = config.fontSize ?? 16;
18128
+ this.fontFamily = config.fontFamily ?? 'Arial';
18129
+ this.fontColor = config.fontColor ?? '#000000';
18130
+ this.scale = config.scale ?? 1;
18131
+ this.scaleFactor = config.scaleX ?? 1;
18132
+ }
18133
+ }
18134
+ /**
18135
+ * Creates a new KritzelShape with screen-space coordinates.
18136
+ * Following the same pattern as KritzelPath.create():
18137
+ * - x, y are screen-space coordinates of the shape's top-left corner
18138
+ * - translateX, translateY should be set to -viewportTranslateX, -viewportTranslateY
18139
+ * - width, height are in screen-space
18140
+ * - scale is the viewport scale at creation time
18141
+ */
18142
+ static create(core, config) {
18143
+ const object = new KritzelShape();
18144
+ object._core = core;
18145
+ object.id = object.generateId();
18146
+ object.workspaceId = core.store.state.activeWorkspace.id;
18147
+ object.x = config?.x ?? 0;
18148
+ object.y = config?.y ?? 0;
18149
+ object.translateX = config?.translateX ?? 0;
18150
+ object.translateY = config?.translateY ?? 0;
18151
+ object.width = config?.width ?? 100;
18152
+ object.height = config?.height ?? 100;
18153
+ object.shapeType = config?.shapeType ?? exports.ShapeType.Rectangle;
18154
+ object.fillColor = config?.fillColor ?? 'transparent';
18155
+ object.strokeColor = config?.strokeColor ?? '#000000';
18156
+ object.strokeWidth = config?.strokeWidth ?? 4;
18157
+ object.opacity = config?.opacity ?? 1;
18158
+ object.fontSize = config?.fontSize ?? 16;
18159
+ object.fontFamily = config?.fontFamily ?? 'Arial';
18160
+ object.fontColor = config?.fontColor ?? '#000000';
18161
+ object.backgroundColor = 'transparent';
18162
+ object.scaleFactor = 1;
18163
+ object.scale = core.store.state.scale;
18164
+ object.zIndex = core.store.currentZIndex;
18165
+ object.editor = object.createEditor();
18166
+ // Compute world-space translateX/Y from screen-space coordinates
18167
+ // This follows the same pattern as KritzelPath.updateDimensions()
18168
+ object.updateDimensions();
18169
+ return object;
18170
+ }
18171
+ /**
18172
+ * Updates the translateX/Y to world coordinates based on screen-space x, y.
18173
+ * This follows the same pattern as KritzelPath.updateDimensions().
18174
+ *
18175
+ * The formula: translateX = (x + initialTranslateX) / scale
18176
+ * where initialTranslateX was -viewportTranslateX
18177
+ *
18178
+ * This converts screen-space position to world coordinates.
18179
+ */
18180
+ updateDimensions() {
18181
+ this.translateX = (this.x + this.translateX) / this.scale;
18182
+ this.translateY = (this.y + this.translateY) / this.scale;
18183
+ }
18184
+ mount(element) {
18185
+ if (element === null || this.isInViewport() === false) {
18186
+ return;
18187
+ }
18188
+ if (this.isMounted && this.elementRef === element && this.editor.dom.parentElement === element) {
18189
+ return;
18190
+ }
18191
+ this.elementRef = element;
18192
+ this.isMounted = true;
18193
+ }
18194
+ mountTextEditor(element) {
18195
+ if (element === null) {
18196
+ return;
18197
+ }
18198
+ if (this.editor.dom.parentElement === element) {
18199
+ return;
18200
+ }
18201
+ element.style.fontFamily = this.fontFamily;
18202
+ element.style.fontSize = `${this.fontSize}pt`;
18203
+ element.style.color = this.fontColor;
18204
+ element.style.whiteSpace = 'pre-wrap';
18205
+ element.style.wordWrap = 'break-word';
18206
+ element.innerHTML = '';
18207
+ element.appendChild(this.editor.dom);
18208
+ }
18209
+ createEditor() {
18210
+ const doc = this._schema.node('doc', null, [this._schema.node('paragraph')]);
18211
+ return new EditorView(null, {
18212
+ state: EditorState.create({
18213
+ doc: doc,
18214
+ plugins: [keymap(baseKeymap)],
18215
+ }),
18216
+ editable: () => false,
18217
+ dispatchTransaction: transaction => {
18218
+ const newState = this.editor.state.apply(transaction);
18219
+ this.editor.updateState(newState);
18220
+ if (transaction.docChanged) {
18221
+ this.content = newState.doc.toJSON();
18222
+ if (!transaction.getMeta('fromRemote')) {
18223
+ this._core.store.state.objects.update(this, { temporary: true });
18224
+ }
18225
+ }
18226
+ },
18227
+ });
18228
+ }
18229
+ setContent(content) {
18230
+ this.content = content;
18231
+ if (this.editor && content) {
18232
+ const newDoc = this.editor.state.schema.nodeFromJSON(content);
18233
+ const tr = this.editor.state.tr.replaceWith(0, this.editor.state.doc.content.size, newDoc.content);
18234
+ tr.setMeta('fromRemote', true);
18235
+ this.editor.dispatch(tr);
18236
+ }
18237
+ }
18238
+ resize(x, y, width, height) {
18239
+ if (width <= 1 || height <= 1) {
18240
+ return;
18241
+ }
18242
+ this.width = width;
18243
+ this.height = height;
18244
+ this.translateX = x;
18245
+ this.translateY = y;
18246
+ this._core.store.state.objects.update(this);
18247
+ }
18248
+ focus(coords) {
18249
+ if (this.editor) {
18250
+ const doc = this.editor.state.doc;
18251
+ if (coords?.x && coords?.y) {
18252
+ const pos = this.editor.posAtCoords({ left: coords.x, top: coords.y });
18253
+ if (pos) {
18254
+ this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, pos.pos)));
18255
+ this.editor.focus();
18256
+ if (KritzelDevicesHelper.isIOS()) {
18257
+ this.scrollIntoViewOnIOS();
18258
+ }
18259
+ return;
18260
+ }
18261
+ }
18262
+ const end = Math.max(1, doc.content.size - 1);
18263
+ this.editor.dispatch(this.editor.state.tr.setSelection(TextSelection.create(doc, end)));
18264
+ this.editor.focus();
18265
+ if (KritzelDevicesHelper.isIOS()) {
18266
+ this.scrollIntoViewOnIOS();
18267
+ }
18268
+ }
18269
+ }
18270
+ scrollIntoViewOnIOS() {
18271
+ setTimeout(() => {
18272
+ if (this.editor && this.editor.dom) {
18273
+ this.editor.dom.scrollIntoView({
18274
+ behavior: 'smooth',
18275
+ block: 'center',
18276
+ inline: 'nearest',
18277
+ });
18278
+ }
18279
+ }, 300);
18280
+ }
18281
+ edit(event) {
18282
+ KritzelKeyboardHelper.disableInteractiveWidget();
18283
+ this.uneditedObject = this.clone();
18284
+ this._core.store.setState('activeTool', KritzelToolRegistry.getTool('shape'));
18285
+ this.editor.setProps({ editable: () => true });
18286
+ this.isEditing = true;
18287
+ this._core.rerender();
18288
+ this.focus({ x: event?.clientX, y: event?.clientY });
18289
+ KritzelKeyboardHelper.enableInteractiveWidget();
18290
+ }
18291
+ save() {
18292
+ this.content = this.editor.state.doc.toJSON();
18293
+ this.editor.setProps({ editable: () => false });
18294
+ this.editor.dom.blur();
18295
+ this.isEditing = false;
18296
+ this._core.store.state.objects.consolidateTemporaryItems();
18297
+ this._core.store.state.objects.update(this);
18298
+ this._core.engine.emitObjectsChange();
18299
+ }
18300
+ handlePointerDown(event) {
18301
+ if (!this.isEditing) {
18302
+ return;
18303
+ }
18304
+ event.stopPropagation();
18305
+ }
18306
+ handlePointerMove(event) {
18307
+ if (!this.isEditing) {
18308
+ return;
18309
+ }
18310
+ event.stopPropagation();
18311
+ }
18312
+ handlePointerUp(event) {
18313
+ if (!this.isEditing) {
18314
+ return;
18315
+ }
18316
+ event.stopPropagation();
18317
+ }
18318
+ copy() {
18319
+ const copiedObject = super.copy();
18320
+ copiedObject.editor = copiedObject.createEditor();
18321
+ if (this.content) {
18322
+ copiedObject.setContent(this.content);
18323
+ }
18324
+ return copiedObject;
18325
+ }
18326
+ serialize() {
18327
+ const { _core, _elementRef, _schema, element, totalWidth, totalHeight, editor, uneditedObject, ...remainingProps } = this;
18328
+ const clonedProps = structuredClone(remainingProps);
18329
+ if (element && typeof element === 'object' && 'nodeType' in element && element.nodeType === 1) {
18330
+ clonedProps.element = element.cloneNode(true);
18331
+ }
18332
+ return clonedProps;
18333
+ }
18334
+ deserialize(object) {
18335
+ super.deserialize(object);
18336
+ if (object.content) {
18337
+ this.setContent(object.content);
18338
+ }
18339
+ return this;
18340
+ }
18341
+ /**
18342
+ * Returns the clipping polygon for arrow intersection.
18343
+ * For ellipse: returns a many-sided polygon approximation
18344
+ * For triangle: returns the 3 corners
18345
+ * For rectangle: returns null (uses default rotatedPolygon)
18346
+ *
18347
+ * Includes padding for half the stroke width so arrow heads don't overlap the stroke.
18348
+ */
18349
+ getClipPolygon() {
18350
+ // Calculate world-space center and dimensions
18351
+ const worldWidth = this.totalWidth / this.scale;
18352
+ const worldHeight = this.totalHeight / this.scale;
18353
+ const centerX = this.translateX + worldWidth / 2;
18354
+ const centerY = this.translateY + worldHeight / 2;
18355
+ // Add padding for stroke width so arrows don't overlap the stroke
18356
+ const strokePadding = (this.strokeWidth / this.scale) / 2;
18357
+ switch (this.shapeType) {
18358
+ case exports.ShapeType.Ellipse:
18359
+ // Return a 32-segment polygon approximation of the ellipse
18360
+ // Add stroke padding to radii
18361
+ return KritzelGeometryHelper.getEllipsePolygonApproximation(centerX, centerY, worldWidth / 2 + strokePadding, worldHeight / 2 + strokePadding, 32, this.rotation);
18362
+ case exports.ShapeType.Triangle:
18363
+ // Return the 3 corners of the triangle in world coordinates
18364
+ // Triangle: top-center, bottom-right, bottom-left
18365
+ // Expand each vertex outward from center by strokePadding
18366
+ const expandVertex = (vx, vy) => {
18367
+ const dx = vx - centerX;
18368
+ const dy = vy - centerY;
18369
+ const dist = Math.sqrt(dx * dx + dy * dy);
18370
+ if (dist === 0)
18371
+ return { x: vx, y: vy };
18372
+ const scale = (dist + strokePadding) / dist;
18373
+ return {
18374
+ x: centerX + dx * scale,
18375
+ y: centerY + dy * scale
18376
+ };
18377
+ };
18378
+ const topX = this.translateX + worldWidth / 2;
18379
+ const topY = this.translateY;
18380
+ const bottomLeftX = this.translateX;
18381
+ const bottomLeftY = this.translateY + worldHeight;
18382
+ const bottomRightX = this.translateX + worldWidth;
18383
+ const bottomRightY = this.translateY + worldHeight;
18384
+ const expandedTop = expandVertex(topX, topY);
18385
+ const expandedBottomRight = expandVertex(bottomRightX, bottomRightY);
18386
+ const expandedBottomLeft = expandVertex(bottomLeftX, bottomLeftY);
18387
+ // Apply rotation around center if rotated
18388
+ if (this.rotation !== 0) {
18389
+ const cos = Math.cos(this.rotation);
18390
+ const sin = Math.sin(this.rotation);
18391
+ const rotate = (p) => {
18392
+ const dx = p.x - centerX;
18393
+ const dy = p.y - centerY;
18394
+ return {
18395
+ x: centerX + dx * cos - dy * sin,
18396
+ y: centerY + dx * sin + dy * cos
18397
+ };
18398
+ };
18399
+ return [
18400
+ rotate(expandedTop),
18401
+ rotate(expandedBottomRight),
18402
+ rotate(expandedBottomLeft)
18403
+ ];
18404
+ }
18405
+ return [expandedTop, expandedBottomRight, expandedBottomLeft];
18406
+ case exports.ShapeType.Rectangle:
18407
+ default:
18408
+ // For rectangles, return null to use the default rotatedPolygon
18409
+ return null;
18410
+ }
18411
+ }
18412
+ /**
18413
+ * Returns the SVG path for rendering the shape.
18414
+ * The path uses screen-space coordinates relative to (x, y).
18415
+ */
18416
+ getSvgPath() {
18417
+ const w = this.width;
18418
+ const h = this.height;
18419
+ switch (this.shapeType) {
18420
+ case exports.ShapeType.Rectangle:
18421
+ return `M ${this.x} ${this.y} L ${this.x + w} ${this.y} L ${this.x + w} ${this.y + h} L ${this.x} ${this.y + h} Z`;
18422
+ case exports.ShapeType.Ellipse:
18423
+ const cx = this.x + w / 2;
18424
+ const cy = this.y + h / 2;
18425
+ const rx = w / 2;
18426
+ const ry = h / 2;
18427
+ return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;
18428
+ case exports.ShapeType.Triangle:
18429
+ const topX = this.x + w / 2;
18430
+ const topY = this.y;
18431
+ const bottomLeftX = this.x;
18432
+ const bottomLeftY = this.y + h;
18433
+ const bottomRightX = this.x + w;
18434
+ const bottomRightY = this.y + h;
18435
+ return `M ${topX} ${topY} L ${bottomRightX} ${bottomRightY} L ${bottomLeftX} ${bottomLeftY} Z`;
18436
+ default:
18437
+ return `M ${this.x} ${this.y} L ${this.x + w} ${this.y} L ${this.x + w} ${this.y + h} L ${this.x} ${this.y + h} Z`;
18438
+ }
18439
+ }
18440
+ }
18441
+
18442
+ /**
18443
+ * Default color palette shared across all tool configurations.
18444
+ * This ensures consistency in color options throughout the application.
18445
+ */
18446
+ const DEFAULT_COLOR_PALETTE = [
18447
+ '#000000',
18448
+ '#ff5252',
18449
+ '#ffbc00',
18450
+ '#00c853',
18451
+ '#0000FF',
18452
+ '#d500f9',
18453
+ '#fafafa',
18454
+ '#a52714',
18455
+ '#ee8100',
18456
+ '#558b2f',
18457
+ '#01579b',
18458
+ '#8e24aa',
18459
+ '#90a4ae',
18460
+ '#ff4081',
18461
+ '#ff6e40',
18462
+ '#aeea00',
18463
+ '#304ffe',
18464
+ '#7c4dff',
18465
+ '#cfd8dc',
18466
+ '#f8bbd0',
18467
+ '#ffccbc',
18468
+ '#f0f4c3',
18469
+ '#9fa8da',
18470
+ '#d1c4e9',
18471
+ ];
18472
+
17981
18473
  class KritzelSelectionTool extends KritzelBaseTool {
17982
18474
  selectionHandler;
17983
18475
  moveHandler;
@@ -17985,6 +18477,193 @@ class KritzelSelectionTool extends KritzelBaseTool {
17985
18477
  resizeHandler;
17986
18478
  rotationHandler;
17987
18479
  lineHandleHandler;
18480
+ palette = [...DEFAULT_COLOR_PALETTE];
18481
+ /** Returns true if there are objects in the selection group */
18482
+ hasSelection() {
18483
+ return !!this._core.store.selectionGroup && this._core.store.selectionGroup.objects.length > 0;
18484
+ }
18485
+ /** Returns the selected objects or empty array */
18486
+ getSelectedObjects() {
18487
+ return this._core.store.selectionGroup?.objects ?? [];
18488
+ }
18489
+ flattenObjects(objects) {
18490
+ let result = [];
18491
+ for (const obj of objects) {
18492
+ if (obj instanceof KritzelGroup) {
18493
+ result = result.concat(this.flattenObjects(obj.children));
18494
+ }
18495
+ else {
18496
+ result.push(obj);
18497
+ }
18498
+ }
18499
+ return result;
18500
+ }
18501
+ get color() {
18502
+ const objects = this.flattenObjects(this.getSelectedObjects());
18503
+ if (objects.length === 0)
18504
+ return '#000000';
18505
+ for (const obj of objects) {
18506
+ if (obj instanceof KritzelPath)
18507
+ return obj.fill;
18508
+ if (obj instanceof KritzelLine)
18509
+ return obj.stroke;
18510
+ if (obj instanceof KritzelText)
18511
+ return obj.fontColor;
18512
+ if (obj instanceof KritzelShape)
18513
+ return obj.strokeColor;
18514
+ }
18515
+ return '#000000';
18516
+ }
18517
+ set color(value) {
18518
+ const objects = this.flattenObjects(this.getSelectedObjects());
18519
+ objects.forEach(obj => {
18520
+ if (obj instanceof KritzelPath)
18521
+ this._core.updateObject(obj, { fill: value });
18522
+ if (obj instanceof KritzelLine)
18523
+ this._core.updateObject(obj, { stroke: value });
18524
+ if (obj instanceof KritzelText)
18525
+ this._core.updateObject(obj, { fontColor: value });
18526
+ if (obj instanceof KritzelShape)
18527
+ this._core.updateObject(obj, { strokeColor: value });
18528
+ });
18529
+ this._core.rerender();
18530
+ }
18531
+ get opacity() {
18532
+ const objects = this.flattenObjects(this.getSelectedObjects());
18533
+ if (objects.length === 0)
18534
+ return 1;
18535
+ return objects[0].opacity;
18536
+ }
18537
+ set opacity(value) {
18538
+ const objects = this.flattenObjects(this.getSelectedObjects());
18539
+ objects.forEach(obj => this._core.updateObject(obj, { opacity: value }));
18540
+ this._core.rerender();
18541
+ }
18542
+ get size() {
18543
+ const objects = this.flattenObjects(this.getSelectedObjects());
18544
+ if (objects.length === 0)
18545
+ return 1;
18546
+ for (const obj of objects) {
18547
+ if (obj instanceof KritzelPath)
18548
+ return obj.strokeWidth;
18549
+ if (obj instanceof KritzelLine)
18550
+ return obj.strokeWidth;
18551
+ if (obj instanceof KritzelText)
18552
+ return obj.fontSize;
18553
+ if (obj instanceof KritzelShape)
18554
+ return obj.strokeWidth;
18555
+ }
18556
+ return 1;
18557
+ }
18558
+ set size(value) {
18559
+ const objects = this.flattenObjects(this.getSelectedObjects());
18560
+ objects.forEach(obj => {
18561
+ if (obj instanceof KritzelPath)
18562
+ this._core.updateObject(obj, { strokeWidth: value });
18563
+ if (obj instanceof KritzelLine)
18564
+ this._core.updateObject(obj, { strokeWidth: value });
18565
+ if (obj instanceof KritzelText)
18566
+ this._core.updateObject(obj, { fontSize: value });
18567
+ if (obj instanceof KritzelShape)
18568
+ this._core.updateObject(obj, { strokeWidth: value });
18569
+ });
18570
+ this._core.rerender();
18571
+ }
18572
+ get fillColor() {
18573
+ const objects = this.flattenObjects(this.getSelectedObjects());
18574
+ for (const obj of objects) {
18575
+ if (obj instanceof KritzelShape)
18576
+ return obj.fillColor;
18577
+ }
18578
+ return 'transparent';
18579
+ }
18580
+ set fillColor(value) {
18581
+ const objects = this.flattenObjects(this.getSelectedObjects());
18582
+ objects.forEach(obj => {
18583
+ if (obj instanceof KritzelShape) {
18584
+ this._core.updateObject(obj, { fillColor: value });
18585
+ // When switching to fill mode, also update stroke color to match
18586
+ if (value !== 'transparent') {
18587
+ this._core.updateObject(obj, { strokeColor: value });
18588
+ }
18589
+ }
18590
+ });
18591
+ this._core.rerender();
18592
+ }
18593
+ get fontFamily() {
18594
+ const objects = this.flattenObjects(this.getSelectedObjects());
18595
+ for (const obj of objects) {
18596
+ if (obj instanceof KritzelText)
18597
+ return obj.fontFamily;
18598
+ if (obj instanceof KritzelShape)
18599
+ return obj.fontFamily;
18600
+ }
18601
+ return 'Arial';
18602
+ }
18603
+ set fontFamily(value) {
18604
+ const objects = this.flattenObjects(this.getSelectedObjects());
18605
+ objects.forEach(obj => {
18606
+ if (obj instanceof KritzelText)
18607
+ this._core.updateObject(obj, { fontFamily: value });
18608
+ if (obj instanceof KritzelShape)
18609
+ this._core.updateObject(obj, { fontFamily: value });
18610
+ });
18611
+ this._core.rerender();
18612
+ }
18613
+ get arrows() {
18614
+ const objects = this.flattenObjects(this.getSelectedObjects());
18615
+ for (const obj of objects) {
18616
+ if (obj instanceof KritzelLine)
18617
+ return obj.arrows;
18618
+ }
18619
+ return { start: { enabled: false }, end: { enabled: false } };
18620
+ }
18621
+ set arrows(value) {
18622
+ const objects = this.flattenObjects(this.getSelectedObjects());
18623
+ objects.forEach(obj => {
18624
+ if (obj instanceof KritzelLine)
18625
+ this._core.updateObject(obj, { arrows: value });
18626
+ });
18627
+ this._core.rerender();
18628
+ }
18629
+ /** Returns the tool config for selected objects, or null if no selection */
18630
+ getToolConfig() {
18631
+ if (!this.hasSelection())
18632
+ return null;
18633
+ const objects = this.flattenObjects(this.getSelectedObjects());
18634
+ const controls = [];
18635
+ const hasShape = objects.some(o => o instanceof KritzelShape);
18636
+ const hasText = objects.some(o => o instanceof KritzelText);
18637
+ const hasLine = objects.some(o => o instanceof KritzelLine);
18638
+ const hasStroke = objects.some(o => o instanceof KritzelPath || o instanceof KritzelLine || o instanceof KritzelShape);
18639
+ if (hasText && !hasStroke) {
18640
+ controls.push({ type: 'font-size', propertyName: 'size' });
18641
+ controls.push({ type: 'font-family', propertyName: 'fontFamily' });
18642
+ }
18643
+ else if (hasStroke && !hasText) {
18644
+ controls.push({ type: 'stroke-size', propertyName: 'size' });
18645
+ }
18646
+ else {
18647
+ if (hasStroke)
18648
+ controls.push({ type: 'stroke-size', propertyName: 'size' });
18649
+ if (hasText)
18650
+ controls.push({ type: 'font-family', propertyName: 'fontFamily' });
18651
+ }
18652
+ if (hasLine) {
18653
+ controls.push({ type: 'line-endings', propertyName: 'arrows' });
18654
+ }
18655
+ if (hasShape) {
18656
+ controls.push({ type: 'shape-fill', propertyName: 'fillColor' });
18657
+ }
18658
+ return {
18659
+ type: 'selection',
18660
+ colorProperty: 'color',
18661
+ sizeProperty: 'size',
18662
+ opacityProperty: 'opacity',
18663
+ paletteSource: 'palette',
18664
+ controls,
18665
+ };
18666
+ }
17988
18667
  constructor(core) {
17989
18668
  super(core);
17990
18669
  this.selectionHandler = new KritzelSelectionHandler(this._core);
@@ -31438,7 +32117,6 @@ class IndexedDBSyncProvider {
31438
32117
  constructor(docName, doc, options) {
31439
32118
  const dbName = options?.name || docName;
31440
32119
  this.provider = new IndexeddbPersistence(dbName, doc);
31441
- console.info(`IndexedDB Persistence initialized: ${dbName}`);
31442
32120
  }
31443
32121
  async connect() {
31444
32122
  if (this.isConnected) {
@@ -35559,58 +36237,7 @@ const DEFAULT_BRUSH_CONFIG = {
35559
36237
  color: '#000000',
35560
36238
  size: 16,
35561
36239
  palettes: {
35562
- pen: [
35563
- '#000000',
35564
- '#ff5252',
35565
- '#ffbc00',
35566
- '#00c853',
35567
- '#0000FF',
35568
- '#d500f9',
35569
- '#fafafa',
35570
- '#a52714',
35571
- '#ee8100',
35572
- '#558b2f',
35573
- '#01579b',
35574
- '#8e24aa',
35575
- '#90a4ae',
35576
- '#ff4081',
35577
- '#ff6e40',
35578
- '#aeea00',
35579
- '#304ffe',
35580
- '#7c4dff',
35581
- '#cfd8dc',
35582
- '#f8bbd0',
35583
- '#ffccbc',
35584
- '#f0f4c3',
35585
- '#9fa8da',
35586
- '#d1c4e9',
35587
- ],
35588
- highlighter: [
35589
- '#0000006e',
35590
- '#ff52526e',
35591
- '#ffbb006e',
35592
- '#00c8536e',
35593
- '#0000FF6e',
35594
- '#d500f96e',
35595
- '#fafafa6e',
35596
- '#a527146e',
35597
- '#ee81006e',
35598
- '#558b2f6e',
35599
- '#01579b6e',
35600
- '#8e24aa6e',
35601
- '#90a4ae6e',
35602
- '#ff40816e',
35603
- '#ff6e406e',
35604
- '#aeea006e',
35605
- '#304ffe6e',
35606
- '#7c4dff6e',
35607
- '#cfd8dc6e',
35608
- '#f8bbd06e',
35609
- '#ffccbc6e',
35610
- '#f0f4c36e',
35611
- '#9fa8da6e',
35612
- '#d1c4e96e',
35613
- ],
36240
+ pen: [...DEFAULT_COLOR_PALETTE],
35614
36241
  },
35615
36242
  };
35616
36243
 
@@ -35618,75 +36245,24 @@ const DEFAULT_TEXT_CONFIG = {
35618
36245
  color: '#000000',
35619
36246
  size: 8,
35620
36247
  fontFamily: 'Arial',
35621
- palette: [
35622
- '#000000',
35623
- '#ff5252',
35624
- '#ffbc00',
35625
- '#00c853',
35626
- '#0000FF',
35627
- '#d500f9',
35628
- '#fafafa',
35629
- '#a52714',
35630
- '#ee8100',
35631
- '#558b2f',
35632
- '#01579b',
35633
- '#8e24aa',
35634
- '#90a4ae',
35635
- '#ff4081',
35636
- '#ff6e40',
35637
- '#aeea00',
35638
- '#304ffe',
35639
- '#7c4dff',
35640
- '#cfd8dc',
35641
- '#f8bbd0',
35642
- '#ffccbc',
35643
- '#f0f4c3',
35644
- '#9fa8da',
35645
- '#d1c4e9',
35646
- ],
36248
+ palette: [...DEFAULT_COLOR_PALETTE],
35647
36249
  };
35648
36250
 
35649
36251
  const DEFAULT_LINE_TOOL_CONFIG = {
35650
36252
  color: '#000000',
35651
36253
  size: 4,
35652
- palette: [
35653
- '#000000',
35654
- '#ff5252',
35655
- '#ffbc00',
35656
- '#00c853',
35657
- '#0000FF',
35658
- '#d500f9',
35659
- '#fafafa',
35660
- '#a52714',
35661
- '#ee8100',
35662
- '#558b2f',
35663
- '#01579b',
35664
- '#8e24aa',
35665
- '#90a4ae',
35666
- '#ff4081',
35667
- '#ff6e40',
35668
- '#aeea00',
35669
- '#304ffe',
35670
- '#7c4dff',
35671
- '#cfd8dc',
35672
- '#f8bbd0',
35673
- '#ffccbc',
35674
- '#f0f4c3',
35675
- '#b3e5fc',
35676
- '#e1bee7',
35677
- ],
36254
+ palette: [...DEFAULT_COLOR_PALETTE],
35678
36255
  arrows: {
35679
36256
  end: { enabled: true, style: 'triangle' },
35680
36257
  },
35681
36258
  };
35682
36259
 
35683
36260
  exports.DEFAULT_BRUSH_CONFIG = DEFAULT_BRUSH_CONFIG;
36261
+ exports.DEFAULT_COLOR_PALETTE = DEFAULT_COLOR_PALETTE;
35684
36262
  exports.DEFAULT_LINE_TOOL_CONFIG = DEFAULT_LINE_TOOL_CONFIG;
35685
36263
  exports.DEFAULT_SYNC_CONFIG = DEFAULT_SYNC_CONFIG;
35686
36264
  exports.DEFAULT_TEXT_CONFIG = DEFAULT_TEXT_CONFIG;
35687
36265
  exports.Doc = Doc;
35688
- exports.EditorState = EditorState;
35689
- exports.EditorView = EditorView;
35690
36266
  exports.HocuspocusProvider = HocuspocusProvider;
35691
36267
  exports.HocuspocusProviderWebsocket = HocuspocusProviderWebsocket;
35692
36268
  exports.IndexedDBSyncProvider = IndexedDBSyncProvider;
@@ -35701,7 +36277,6 @@ exports.KritzelCursorHelper = KritzelCursorHelper;
35701
36277
  exports.KritzelDevicesHelper = KritzelDevicesHelper;
35702
36278
  exports.KritzelEraserTool = KritzelEraserTool;
35703
36279
  exports.KritzelEventHelper = KritzelEventHelper;
35704
- exports.KritzelGeometryHelper = KritzelGeometryHelper;
35705
36280
  exports.KritzelGroup = KritzelGroup;
35706
36281
  exports.KritzelIconRegistry = KritzelIconRegistry;
35707
36282
  exports.KritzelImage = KritzelImage;
@@ -35713,6 +36288,7 @@ exports.KritzelPath = KritzelPath;
35713
36288
  exports.KritzelSelectionBox = KritzelSelectionBox;
35714
36289
  exports.KritzelSelectionGroup = KritzelSelectionGroup;
35715
36290
  exports.KritzelSelectionTool = KritzelSelectionTool;
36291
+ exports.KritzelShape = KritzelShape;
35716
36292
  exports.KritzelText = KritzelText;
35717
36293
  exports.KritzelTextTool = KritzelTextTool;
35718
36294
  exports.KritzelToolRegistry = KritzelToolRegistry;
@@ -35720,12 +36296,8 @@ exports.KritzelWorkspace = KritzelWorkspace;
35720
36296
  exports.ObjectHelper = ObjectHelper;
35721
36297
  exports.Observable = Observable$1;
35722
36298
  exports.ObservableV2 = ObservableV2;
35723
- exports.Schema = Schema$1;
35724
- exports.TextSelection = TextSelection;
35725
36299
  exports.UndoManager = UndoManager;
35726
- exports.addListNodes = addListNodes;
35727
36300
  exports.applyUpdate = applyUpdate;
35728
- exports.baseKeymap = baseKeymap;
35729
36301
  exports.create = create$8;
35730
36302
  exports.createDecoder = createDecoder$1;
35731
36303
  exports.createEncoder = createEncoder$1;
@@ -35737,7 +36309,6 @@ exports.floor = floor$2;
35737
36309
  exports.fromBase64 = fromBase64;
35738
36310
  exports.getUnixTime = getUnixTime$1;
35739
36311
  exports.isNode = isNode;
35740
- exports.keymap = keymap;
35741
36312
  exports.length = length$2;
35742
36313
  exports.map = map;
35743
36314
  exports.min = min$2;
@@ -35747,7 +36318,6 @@ exports.pow = pow;
35747
36318
  exports.readVarString = readVarString$2;
35748
36319
  exports.readVarUint = readVarUint$2;
35749
36320
  exports.readVarUint8Array = readVarUint8Array$2;
35750
- exports.schema = schema;
35751
36321
  exports.setIfUndefined = setIfUndefined$1;
35752
36322
  exports.toBase64 = toBase64;
35753
36323
  exports.toUint8Array = toUint8Array$1;