kritzel-stencil 0.0.157 → 0.0.159

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 (411) hide show
  1. package/dist/cjs/app-globals-V2Kpy_OQ.js +8 -0
  2. package/dist/cjs/app-globals-V2Kpy_OQ.js.map +1 -0
  3. package/dist/cjs/default-text-tool.config-BySzvIox.js +31267 -0
  4. package/dist/cjs/default-text-tool.config-BySzvIox.js.map +1 -0
  5. package/dist/cjs/index-Cj__YTlG.js +1650 -0
  6. package/dist/cjs/index-Cj__YTlG.js.map +1 -0
  7. package/dist/cjs/index.cjs.js +1465 -0
  8. package/dist/cjs/index.cjs.js.map +1 -0
  9. package/dist/cjs/kritzel-brush-style.cjs.entry.js +32 -0
  10. package/dist/cjs/kritzel-brush-style.entry.cjs.js.map +1 -0
  11. package/dist/cjs/kritzel-color_22.cjs.entry.js +20957 -0
  12. package/dist/cjs/loader.cjs.js +14 -0
  13. package/dist/cjs/loader.cjs.js.map +1 -0
  14. package/dist/cjs/stencil.cjs.js +26 -0
  15. package/dist/cjs/stencil.cjs.js.map +1 -0
  16. package/dist/collection/classes/core/core.class.js +470 -0
  17. package/dist/collection/classes/core/core.class.js.map +1 -0
  18. package/dist/collection/classes/core/reviver.class.js +71 -0
  19. package/dist/collection/classes/core/reviver.class.js.map +1 -0
  20. package/dist/collection/classes/core/store.class.js +72 -0
  21. package/dist/collection/classes/core/store.class.js.map +1 -0
  22. package/dist/collection/classes/core/viewport.class.js +190 -0
  23. package/dist/collection/classes/core/viewport.class.js.map +1 -0
  24. package/dist/collection/classes/core/workspace.class.js +41 -0
  25. package/dist/collection/classes/core/workspace.class.js.map +1 -0
  26. package/dist/collection/classes/handlers/base.handler.js +8 -0
  27. package/dist/collection/classes/handlers/base.handler.js.map +1 -0
  28. package/dist/collection/classes/handlers/context-menu.handler.js +62 -0
  29. package/dist/collection/classes/handlers/context-menu.handler.js.map +1 -0
  30. package/dist/collection/classes/handlers/hover.handler.js +19 -0
  31. package/dist/collection/classes/handlers/hover.handler.js.map +1 -0
  32. package/dist/collection/classes/handlers/key.handler.js +58 -0
  33. package/dist/collection/classes/handlers/key.handler.js.map +1 -0
  34. package/dist/collection/classes/handlers/move.handler.js +149 -0
  35. package/dist/collection/classes/handlers/move.handler.js.map +1 -0
  36. package/dist/collection/classes/handlers/resize.handler.js +184 -0
  37. package/dist/collection/classes/handlers/resize.handler.js.map +1 -0
  38. package/dist/collection/classes/handlers/rotation.handler.js +116 -0
  39. package/dist/collection/classes/handlers/rotation.handler.js.map +1 -0
  40. package/dist/collection/classes/handlers/selection.handler.js +246 -0
  41. package/dist/collection/classes/handlers/selection.handler.js.map +1 -0
  42. package/dist/collection/classes/objects/base-object.class.js +232 -0
  43. package/dist/collection/classes/objects/base-object.class.js.map +1 -0
  44. package/dist/collection/classes/objects/custom-element.class.js +62 -0
  45. package/dist/collection/classes/objects/custom-element.class.js.map +1 -0
  46. package/dist/collection/classes/objects/image.class.js +56 -0
  47. package/dist/collection/classes/objects/image.class.js.map +1 -0
  48. package/dist/collection/classes/objects/path.class.js +284 -0
  49. package/dist/collection/classes/objects/path.class.js.map +1 -0
  50. package/dist/collection/classes/objects/selection-box.class.js +19 -0
  51. package/dist/collection/classes/objects/selection-box.class.js.map +1 -0
  52. package/dist/collection/classes/objects/selection-group.class.js +226 -0
  53. package/dist/collection/classes/objects/selection-group.class.js.map +1 -0
  54. package/dist/collection/classes/objects/text.class.js +261 -0
  55. package/dist/collection/classes/objects/text.class.js.map +1 -0
  56. package/dist/collection/classes/providers/broadcast-sync-provider.class.js +93 -0
  57. package/dist/collection/classes/providers/broadcast-sync-provider.class.js.map +1 -0
  58. package/dist/collection/classes/providers/hocuspocus-sync-provider.class.js +232 -0
  59. package/dist/collection/classes/providers/hocuspocus-sync-provider.class.js.map +1 -0
  60. package/dist/collection/classes/providers/indexeddb-sync-provider.class.js +35 -0
  61. package/dist/collection/classes/providers/indexeddb-sync-provider.class.js.map +1 -0
  62. package/dist/collection/classes/providers/websocket-sync-provider.class.js +89 -0
  63. package/dist/collection/classes/providers/websocket-sync-provider.class.js.map +1 -0
  64. package/dist/{stencil/icon-registry.class-BtT8riKh.js → collection/classes/registries/icon-registry.class.js} +2 -6
  65. package/dist/collection/classes/registries/icon-registry.class.js.map +1 -0
  66. package/dist/collection/classes/registries/tool.registry.js +18 -0
  67. package/dist/collection/classes/registries/tool.registry.js.map +1 -0
  68. package/dist/collection/classes/structures/app-state-map.structure.js +189 -0
  69. package/dist/collection/classes/structures/app-state-map.structure.js.map +1 -0
  70. package/dist/collection/classes/structures/object-map.structure.js +328 -0
  71. package/dist/collection/classes/structures/object-map.structure.js.map +1 -0
  72. package/dist/collection/classes/structures/quadtree.structure.js +113 -0
  73. package/dist/collection/classes/structures/quadtree.structure.js.map +1 -0
  74. package/dist/collection/classes/tools/base-tool.class.js +38 -0
  75. package/dist/collection/classes/tools/base-tool.class.js.map +1 -0
  76. package/dist/collection/classes/tools/brush-tool.class.js +133 -0
  77. package/dist/collection/classes/tools/brush-tool.class.js.map +1 -0
  78. package/dist/collection/classes/tools/eraser-tool.class.js +85 -0
  79. package/dist/collection/classes/tools/eraser-tool.class.js.map +1 -0
  80. package/dist/collection/classes/tools/image-tool.class.js +83 -0
  81. package/dist/collection/classes/tools/image-tool.class.js.map +1 -0
  82. package/dist/collection/classes/tools/selection-tool.class.js +164 -0
  83. package/dist/collection/classes/tools/selection-tool.class.js.map +1 -0
  84. package/dist/collection/classes/tools/text-tool.class.js +108 -0
  85. package/dist/collection/classes/tools/text-tool.class.js.map +1 -0
  86. package/dist/collection/collection-manifest.json +34 -0
  87. package/dist/collection/components/core/kritzel-cursor-trail/kritzel-cursor-trail.css +10 -0
  88. package/dist/collection/components/core/kritzel-cursor-trail/kritzel-cursor-trail.js +153 -0
  89. package/dist/collection/components/core/kritzel-cursor-trail/kritzel-cursor-trail.js.map +1 -0
  90. package/dist/collection/components/core/kritzel-editor/kritzel-editor.css +34 -0
  91. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js +928 -0
  92. package/dist/collection/components/core/kritzel-editor/kritzel-editor.js.map +1 -0
  93. package/dist/collection/components/core/kritzel-engine/kritzel-engine.css +73 -0
  94. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js +1613 -0
  95. package/dist/collection/components/core/kritzel-engine/kritzel-engine.js.map +1 -0
  96. package/dist/collection/components/shared/kritzel-brush-style/kritzel-brush-style.css +44 -0
  97. package/dist/collection/components/shared/kritzel-brush-style/kritzel-brush-style.js +98 -0
  98. package/dist/collection/components/shared/kritzel-brush-style/kritzel-brush-style.js.map +1 -0
  99. package/dist/collection/components/shared/kritzel-color/kritzel-color.css +21 -0
  100. package/dist/collection/components/shared/kritzel-color/kritzel-color.js +107 -0
  101. package/dist/collection/components/shared/kritzel-color/kritzel-color.js.map +1 -0
  102. package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.css +46 -0
  103. package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js +145 -0
  104. package/dist/collection/components/shared/kritzel-color-palette/kritzel-color-palette.js.map +1 -0
  105. package/dist/collection/components/shared/kritzel-dropdown/kritzel-dropdown.css +53 -0
  106. package/dist/collection/components/shared/kritzel-dropdown/kritzel-dropdown.js +218 -0
  107. package/dist/collection/components/shared/kritzel-dropdown/kritzel-dropdown.js.map +1 -0
  108. package/dist/collection/components/shared/kritzel-font/kritzel-font.css +10 -0
  109. package/dist/collection/components/shared/kritzel-font/kritzel-font.js +90 -0
  110. package/dist/collection/components/shared/kritzel-font/kritzel-font.js.map +1 -0
  111. package/dist/collection/components/shared/kritzel-font-family/kritzel-font-family.css +48 -0
  112. package/dist/collection/components/shared/kritzel-font-family/kritzel-font-family.js +114 -0
  113. package/dist/collection/components/shared/kritzel-font-family/kritzel-font-family.js.map +1 -0
  114. package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.css +30 -0
  115. package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js +110 -0
  116. package/dist/collection/components/shared/kritzel-font-size/kritzel-font-size.js.map +1 -0
  117. package/dist/collection/components/shared/kritzel-icon/kritzel-icon.css +18 -0
  118. package/dist/collection/components/shared/kritzel-icon/kritzel-icon.js +94 -0
  119. package/dist/collection/components/shared/kritzel-icon/kritzel-icon.js.map +1 -0
  120. package/dist/collection/components/shared/kritzel-menu/kritzel-menu.css +27 -0
  121. package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js +291 -0
  122. package/dist/collection/components/shared/kritzel-menu/kritzel-menu.js.map +1 -0
  123. package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.css +145 -0
  124. package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js +280 -0
  125. package/dist/collection/components/shared/kritzel-menu-item/kritzel-menu-item.js.map +1 -0
  126. package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js +310 -0
  127. package/dist/collection/components/shared/kritzel-portal/kritzel-portal.js.map +1 -0
  128. package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.css +78 -0
  129. package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js +406 -0
  130. package/dist/collection/components/shared/kritzel-split-button/kritzel-split-button.js.map +1 -0
  131. package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.css +28 -0
  132. package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js +89 -0
  133. package/dist/collection/components/shared/kritzel-stroke-size/kritzel-stroke-size.js.map +1 -0
  134. package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.css +17 -0
  135. package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js +251 -0
  136. package/dist/collection/components/shared/kritzel-tooltip/kritzel-tooltip.js.map +1 -0
  137. package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.css +55 -0
  138. package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.js +172 -0
  139. package/dist/collection/components/ui/kritzel-context-menu/kritzel-context-menu.js.map +1 -0
  140. package/dist/collection/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.css +19 -0
  141. package/dist/collection/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.js +135 -0
  142. package/dist/collection/components/ui/kritzel-control-brush-config/kritzel-control-brush-config.js.map +1 -0
  143. package/dist/collection/components/ui/kritzel-control-text-config/kritzel-control-text-config.css +19 -0
  144. package/dist/collection/components/ui/kritzel-control-text-config/kritzel-control-text-config.js +115 -0
  145. package/dist/collection/components/ui/kritzel-control-text-config/kritzel-control-text-config.js.map +1 -0
  146. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.css +127 -0
  147. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js +312 -0
  148. package/dist/collection/components/ui/kritzel-controls/kritzel-controls.js.map +1 -0
  149. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.css +44 -0
  150. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js +111 -0
  151. package/dist/collection/components/ui/kritzel-utility-panel/kritzel-utility-panel.js.map +1 -0
  152. package/dist/collection/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.css +5 -0
  153. package/dist/collection/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.js +255 -0
  154. package/dist/collection/components/ui/kritzel-workspace-manager/kritzel-workspace-manager.js.map +1 -0
  155. package/dist/collection/configs/default-brush-tool.config.js +60 -0
  156. package/dist/collection/configs/default-brush-tool.config.js.map +1 -0
  157. package/dist/collection/configs/default-engine-config.js +53 -0
  158. package/dist/collection/configs/default-engine-config.js.map +1 -0
  159. package/dist/collection/configs/default-sync.config.js +10 -0
  160. package/dist/collection/configs/default-sync.config.js.map +1 -0
  161. package/dist/collection/configs/default-text-tool.config.js +32 -0
  162. package/dist/collection/configs/default-text-tool.config.js.map +1 -0
  163. package/dist/collection/constants/core.constants.js +2 -0
  164. package/dist/collection/constants/core.constants.js.map +1 -0
  165. package/dist/collection/constants/engine.constants.js +3 -0
  166. package/dist/collection/constants/engine.constants.js.map +1 -0
  167. package/dist/collection/enums/event-button.enum.js +7 -0
  168. package/dist/collection/enums/event-button.enum.js.map +1 -0
  169. package/dist/collection/enums/handle-type.enum.js +8 -0
  170. package/dist/collection/enums/handle-type.enum.js.map +1 -0
  171. package/dist/collection/helpers/class.helper.js +6 -0
  172. package/dist/collection/helpers/class.helper.js.map +1 -0
  173. package/dist/collection/helpers/devices.helper.js +26 -0
  174. package/dist/collection/helpers/devices.helper.js.map +1 -0
  175. package/dist/collection/helpers/event.helper.js +51 -0
  176. package/dist/collection/helpers/event.helper.js.map +1 -0
  177. package/dist/collection/helpers/geometry.helper.js +53 -0
  178. package/dist/collection/helpers/geometry.helper.js.map +1 -0
  179. package/dist/collection/helpers/html.helper.js +64 -0
  180. package/dist/{stencil/html.helper-C6qB08BS.js.map → collection/helpers/html.helper.js.map} +1 -1
  181. package/dist/collection/helpers/keyboard.helper.js +49 -0
  182. package/dist/collection/helpers/keyboard.helper.js.map +1 -0
  183. package/dist/collection/helpers/math.helper.js +6 -0
  184. package/dist/collection/helpers/math.helper.js.map +1 -0
  185. package/dist/collection/helpers/object.helper.js +12 -0
  186. package/dist/collection/helpers/object.helper.js.map +1 -0
  187. package/dist/collection/index.js +30 -0
  188. package/dist/collection/index.js.map +1 -0
  189. package/dist/collection/interfaces/bounding-box.interface.js +2 -0
  190. package/dist/collection/interfaces/bounding-box.interface.js.map +1 -0
  191. package/dist/collection/interfaces/clonable.interface.js +2 -0
  192. package/dist/collection/interfaces/clonable.interface.js.map +1 -0
  193. package/dist/collection/interfaces/context-menu-item.interface.js +2 -0
  194. package/dist/collection/interfaces/context-menu-item.interface.js.map +1 -0
  195. package/dist/collection/interfaces/debug-info.interface.js +2 -0
  196. package/dist/collection/interfaces/debug-info.interface.js.map +1 -0
  197. package/dist/collection/interfaces/engine-state.interface.js +2 -0
  198. package/dist/collection/interfaces/engine-state.interface.js.map +1 -0
  199. package/dist/collection/interfaces/menu-item.interface.js +2 -0
  200. package/dist/collection/interfaces/menu-item.interface.js.map +1 -0
  201. package/dist/collection/interfaces/object.interface.js +2 -0
  202. package/dist/collection/interfaces/object.interface.js.map +1 -0
  203. package/dist/collection/interfaces/path-options.interface.js +2 -0
  204. package/dist/collection/interfaces/path-options.interface.js.map +1 -0
  205. package/dist/collection/interfaces/point.interface.js +2 -0
  206. package/dist/collection/interfaces/point.interface.js.map +1 -0
  207. package/dist/collection/interfaces/polygon.interface.js +2 -0
  208. package/dist/collection/interfaces/polygon.interface.js.map +1 -0
  209. package/dist/collection/interfaces/selection-state.interface.js +2 -0
  210. package/dist/collection/interfaces/selection-state.interface.js.map +1 -0
  211. package/dist/collection/interfaces/serializable.interface.js +2 -0
  212. package/dist/collection/interfaces/serializable.interface.js.map +1 -0
  213. package/dist/collection/interfaces/shortcut.interface.js +2 -0
  214. package/dist/collection/interfaces/shortcut.interface.js.map +1 -0
  215. package/dist/collection/interfaces/sync-config.interface.js +2 -0
  216. package/dist/collection/interfaces/sync-config.interface.js.map +1 -0
  217. package/dist/collection/interfaces/sync-provider.interface.js +2 -0
  218. package/dist/collection/interfaces/sync-provider.interface.js.map +1 -0
  219. package/dist/collection/interfaces/tool.interface.js +2 -0
  220. package/dist/collection/interfaces/tool.interface.js.map +1 -0
  221. package/dist/collection/interfaces/toolbar-control.interface.js +2 -0
  222. package/dist/collection/interfaces/toolbar-control.interface.js.map +1 -0
  223. package/dist/collection/interfaces/undo-state.interface.js +2 -0
  224. package/dist/collection/interfaces/undo-state.interface.js.map +1 -0
  225. package/dist/collection/types/deep-readonly.type.js +2 -0
  226. package/dist/collection/types/deep-readonly.type.js.map +1 -0
  227. package/dist/collection/types/state.types.js +2 -0
  228. package/dist/collection/types/state.types.js.map +1 -0
  229. package/dist/components/index.js +1477 -0
  230. package/dist/components/index.js.map +1 -0
  231. package/dist/components/kritzel-brush-style.js +67 -0
  232. package/dist/components/kritzel-brush-style.js.map +1 -0
  233. package/dist/components/kritzel-color-palette.js +9 -0
  234. package/dist/components/kritzel-color-palette.js.map +1 -0
  235. package/dist/components/kritzel-color.js +9 -0
  236. package/dist/components/kritzel-color.js.map +1 -0
  237. package/dist/components/kritzel-context-menu.js +9 -0
  238. package/dist/components/kritzel-context-menu.js.map +1 -0
  239. package/dist/components/kritzel-control-brush-config.js +9 -0
  240. package/dist/components/kritzel-control-brush-config.js.map +1 -0
  241. package/dist/components/kritzel-control-text-config.js +9 -0
  242. package/dist/components/kritzel-control-text-config.js.map +1 -0
  243. package/dist/components/kritzel-controls.js +9 -0
  244. package/dist/components/kritzel-controls.js.map +1 -0
  245. package/dist/components/kritzel-cursor-trail.js +9 -0
  246. package/dist/components/kritzel-cursor-trail.js.map +1 -0
  247. package/dist/components/kritzel-dropdown.js +9 -0
  248. package/dist/components/kritzel-dropdown.js.map +1 -0
  249. package/dist/components/kritzel-editor.js +516 -0
  250. package/dist/components/kritzel-editor.js.map +1 -0
  251. package/dist/components/kritzel-engine.js +9 -0
  252. package/dist/components/kritzel-engine.js.map +1 -0
  253. package/dist/components/kritzel-font-family.js +9 -0
  254. package/dist/components/kritzel-font-family.js.map +1 -0
  255. package/dist/components/kritzel-font-size.js +9 -0
  256. package/dist/components/kritzel-font-size.js.map +1 -0
  257. package/dist/components/kritzel-font.js +9 -0
  258. package/dist/components/kritzel-font.js.map +1 -0
  259. package/dist/components/kritzel-icon.js +9 -0
  260. package/dist/components/kritzel-icon.js.map +1 -0
  261. package/dist/components/kritzel-menu-item.js +9 -0
  262. package/dist/components/kritzel-menu-item.js.map +1 -0
  263. package/dist/components/kritzel-menu.js +9 -0
  264. package/dist/components/kritzel-menu.js.map +1 -0
  265. package/dist/components/kritzel-portal.js +9 -0
  266. package/dist/components/kritzel-portal.js.map +1 -0
  267. package/dist/components/kritzel-split-button.js +9 -0
  268. package/dist/components/kritzel-split-button.js.map +1 -0
  269. package/dist/components/kritzel-stroke-size.js +9 -0
  270. package/dist/components/kritzel-stroke-size.js.map +1 -0
  271. package/dist/components/kritzel-tooltip.js +9 -0
  272. package/dist/components/kritzel-tooltip.js.map +1 -0
  273. package/dist/components/kritzel-utility-panel.js +9 -0
  274. package/dist/components/kritzel-utility-panel.js.map +1 -0
  275. package/dist/components/kritzel-workspace-manager.js +9 -0
  276. package/dist/components/kritzel-workspace-manager.js.map +1 -0
  277. package/dist/{stencil/kritzel-controls.entry.js → components/p-1lIHoOlH.js} +115 -17
  278. package/dist/components/p-1lIHoOlH.js.map +1 -0
  279. package/dist/{stencil/object.helper-B0kd2rUI.js → components/p-B0kd2rUI.js} +2 -2
  280. package/dist/components/p-B0kd2rUI.js.map +1 -0
  281. package/dist/components/p-B4kxkVe-.js +55 -0
  282. package/dist/components/p-B4kxkVe-.js.map +1 -0
  283. package/dist/components/p-BAplhrRJ.js +35593 -0
  284. package/dist/components/p-BAplhrRJ.js.map +1 -0
  285. package/dist/components/p-BQg4YML7.js +106 -0
  286. package/dist/components/p-BQg4YML7.js.map +1 -0
  287. package/dist/{stencil/kritzel-font-family.entry.js → components/p-BgznZoBH.js} +37 -9
  288. package/dist/components/p-BgznZoBH.js.map +1 -0
  289. package/dist/components/p-Bhtn9qay.js +98 -0
  290. package/dist/components/p-Bhtn9qay.js.map +1 -0
  291. package/dist/{stencil/kritzel-context-menu-GdU9xEKC.js → components/p-C2sWlNsJ.js} +41 -12
  292. package/dist/components/p-C2sWlNsJ.js.map +1 -0
  293. package/dist/{stencil/html.helper-C6qB08BS.js → components/p-C6qB08BS.js} +2 -2
  294. package/dist/components/p-C6qB08BS.js.map +1 -0
  295. package/dist/{stencil/text-tool.class-C0GbC5zQ.js → components/p-CBYBurdY.js} +25 -729
  296. package/dist/components/p-CBYBurdY.js.map +1 -0
  297. package/dist/{stencil/kritzel-dropdown.entry.js → components/p-CIXPLjCu.js} +39 -9
  298. package/dist/components/p-CIXPLjCu.js.map +1 -0
  299. package/dist/{stencil/kritzel-workspace-manager.entry.js → components/p-CK6no3mi.js} +68 -13
  300. package/dist/components/p-CK6no3mi.js.map +1 -0
  301. package/dist/{stencil/kritzel-cursor-trail.entry.js → components/p-CLt3HMl6.js} +33 -10
  302. package/dist/components/p-CLt3HMl6.js.map +1 -0
  303. package/dist/{stencil/kritzel-tooltip.entry.js → components/p-CTP479Lf.js} +39 -11
  304. package/dist/components/p-CTP479Lf.js.map +1 -0
  305. package/dist/{stencil/kritzel-menu-item.entry.js → components/p-CsA9M6me.js} +174 -16
  306. package/dist/components/p-CsA9M6me.js.map +1 -0
  307. package/dist/components/p-CwkUrTy1.js +1367 -0
  308. package/dist/components/p-CwkUrTy1.js.map +1 -0
  309. package/dist/{stencil/kritzel-color-palette.entry.js → components/p-D1uj4A4F.js} +39 -9
  310. package/dist/components/p-D1uj4A4F.js.map +1 -0
  311. package/dist/{stencil/kritzel-color.entry.js → components/p-D4yvhd1d.js} +30 -8
  312. package/dist/components/p-D4yvhd1d.js.map +1 -0
  313. package/dist/{stencil/kritzel-portal.entry.js → components/p-D5Wq4x4r.js} +37 -11
  314. package/dist/components/p-D5Wq4x4r.js.map +1 -0
  315. package/dist/{stencil/event-button.enum-D8W6LE-c.js → components/p-D8W6LE-c.js} +2 -2
  316. package/dist/components/p-D8W6LE-c.js.map +1 -0
  317. package/dist/{stencil/kritzel-utility-panel.entry.js → components/p-DAfkuR8U.js} +38 -11
  318. package/dist/components/p-DAfkuR8U.js.map +1 -0
  319. package/dist/components/p-DDmSxM5f.js +57 -0
  320. package/dist/{stencil/kritzel-font-size.entry.esm.js.map → components/p-DDmSxM5f.js.map} +1 -1
  321. package/dist/components/p-Ddh40W3x.js +103 -0
  322. package/dist/components/p-Ddh40W3x.js.map +1 -0
  323. package/dist/{stencil/kritzel-split-button.entry.js → components/p-TdCTkEu0.js} +72 -18
  324. package/dist/components/p-TdCTkEu0.js.map +1 -0
  325. package/dist/{stencil/devices.helper-l10It7Nm.js → components/p-l10It7Nm.js} +2 -2
  326. package/dist/components/p-l10It7Nm.js.map +1 -0
  327. package/dist/{stencil/workspace.class-n789Y3S-.js → components/p-n789Y3S-.js} +2 -2
  328. package/dist/components/p-n789Y3S-.js.map +1 -0
  329. package/dist/components/p-uuRJU2R1.js +46 -0
  330. package/dist/components/p-uuRJU2R1.js.map +1 -0
  331. package/dist/esm/app-globals-DQuL1Twl.js +6 -0
  332. package/dist/esm/app-globals-DQuL1Twl.js.map +1 -0
  333. package/dist/esm/default-text-tool.config-2YFQA3SF.js +31208 -0
  334. package/dist/esm/default-text-tool.config-2YFQA3SF.js.map +1 -0
  335. package/dist/esm/index-SGde3HXB.js +1623 -0
  336. package/dist/esm/index-SGde3HXB.js.map +1 -0
  337. package/dist/esm/index.js +1449 -0
  338. package/dist/esm/index.js.map +1 -0
  339. package/dist/{stencil → esm}/kritzel-brush-style.entry.js +3 -3
  340. package/dist/esm/kritzel-brush-style.entry.js.map +1 -0
  341. package/dist/{stencil/kritzel-engine.entry.js → esm/kritzel-color_22.entry.js} +1806 -90
  342. package/dist/esm/loader.js +12 -0
  343. package/dist/esm/loader.js.map +1 -0
  344. package/dist/esm/stencil.js +22 -0
  345. package/dist/esm/stencil.js.map +1 -0
  346. package/dist/index.cjs.js +1 -0
  347. package/dist/index.js +1 -0
  348. package/dist/stencil/index.esm.js +2 -18
  349. package/dist/stencil/index.esm.js.map +1 -1
  350. package/dist/stencil/loader.esm.js.map +1 -1
  351. package/dist/stencil/p-2YFQA3SF.js +2 -0
  352. package/dist/stencil/p-2YFQA3SF.js.map +1 -0
  353. package/dist/stencil/p-2e85a4af.entry.js +10 -0
  354. package/dist/stencil/p-2e85a4af.entry.js.map +1 -0
  355. package/dist/stencil/p-DQuL1Twl.js +2 -0
  356. package/dist/stencil/p-DQuL1Twl.js.map +1 -0
  357. package/dist/stencil/p-SGde3HXB.js +3 -0
  358. package/dist/stencil/p-SGde3HXB.js.map +1 -0
  359. package/dist/stencil/p-d702c5af.entry.js +2 -0
  360. package/dist/stencil/p-d702c5af.entry.js.map +1 -0
  361. package/dist/stencil/stencil.esm.js +2 -48
  362. package/dist/stencil/stencil.esm.js.map +1 -1
  363. package/dist/types/components/core/kritzel-engine/kritzel-engine.d.ts +0 -1
  364. package/package.json +1 -1
  365. package/dist/stencil/default-text-tool.config-DKpRP4XR.js +0 -1441
  366. package/dist/stencil/default-text-tool.config-DKpRP4XR.js.map +0 -1
  367. package/dist/stencil/devices.helper-l10It7Nm.js.map +0 -1
  368. package/dist/stencil/engine.constants-DsjjAmnl.js +0 -7
  369. package/dist/stencil/engine.constants-DsjjAmnl.js.map +0 -1
  370. package/dist/stencil/event-button.enum-D8W6LE-c.js.map +0 -1
  371. package/dist/stencil/icon-registry.class-BtT8riKh.js.map +0 -1
  372. package/dist/stencil/index-DniO_INI.js +0 -4395
  373. package/dist/stencil/index-DniO_INI.js.map +0 -1
  374. package/dist/stencil/kritzel-color-palette.entry.esm.js.map +0 -1
  375. package/dist/stencil/kritzel-color.entry.esm.js.map +0 -1
  376. package/dist/stencil/kritzel-context-menu-BYgOEy-i.js +0 -66
  377. package/dist/stencil/kritzel-context-menu-BYgOEy-i.js.map +0 -1
  378. package/dist/stencil/kritzel-context-menu-GdU9xEKC.js.map +0 -1
  379. package/dist/stencil/kritzel-context-menu.entry.esm.js.map +0 -1
  380. package/dist/stencil/kritzel-context-menu.entry.js +0 -3
  381. package/dist/stencil/kritzel-control-brush-config.entry.esm.js.map +0 -1
  382. package/dist/stencil/kritzel-control-brush-config.entry.js +0 -54
  383. package/dist/stencil/kritzel-control-text-config.entry.esm.js.map +0 -1
  384. package/dist/stencil/kritzel-control-text-config.entry.js +0 -42
  385. package/dist/stencil/kritzel-controls.entry.esm.js.map +0 -1
  386. package/dist/stencil/kritzel-cursor-trail.entry.esm.js.map +0 -1
  387. package/dist/stencil/kritzel-dropdown.entry.esm.js.map +0 -1
  388. package/dist/stencil/kritzel-editor.entry.esm.js.map +0 -1
  389. package/dist/stencil/kritzel-editor.entry.js +0 -248
  390. package/dist/stencil/kritzel-engine.entry.esm.js.map +0 -1
  391. package/dist/stencil/kritzel-font-family.entry.esm.js.map +0 -1
  392. package/dist/stencil/kritzel-font-size.entry.js +0 -28
  393. package/dist/stencil/kritzel-font.entry.esm.js.map +0 -1
  394. package/dist/stencil/kritzel-font.entry.js +0 -23
  395. package/dist/stencil/kritzel-icon.entry.esm.js.map +0 -1
  396. package/dist/stencil/kritzel-icon.entry.js +0 -29
  397. package/dist/stencil/kritzel-menu-item.entry.esm.js.map +0 -1
  398. package/dist/stencil/kritzel-menu.entry.esm.js.map +0 -1
  399. package/dist/stencil/kritzel-menu.entry.js +0 -72
  400. package/dist/stencil/kritzel-portal.entry.esm.js.map +0 -1
  401. package/dist/stencil/kritzel-split-button.entry.esm.js.map +0 -1
  402. package/dist/stencil/kritzel-stroke-size.entry.esm.js.map +0 -1
  403. package/dist/stencil/kritzel-stroke-size.entry.js +0 -27
  404. package/dist/stencil/kritzel-tooltip.entry.esm.js.map +0 -1
  405. package/dist/stencil/kritzel-utility-panel.entry.esm.js.map +0 -1
  406. package/dist/stencil/kritzel-workspace-manager.entry.esm.js.map +0 -1
  407. package/dist/stencil/object.helper-B0kd2rUI.js.map +0 -1
  408. package/dist/stencil/sync-config.interface-lKfyG1EN.js +0 -19839
  409. package/dist/stencil/sync-config.interface-lKfyG1EN.js.map +0 -1
  410. package/dist/stencil/text-tool.class-C0GbC5zQ.js.map +0 -1
  411. package/dist/stencil/workspace.class-n789Y3S-.js.map +0 -1
@@ -0,0 +1,1465 @@
1
+ 'use strict';
2
+
3
+ var defaultTextTool_config = require('./default-text-tool.config-BySzvIox.js');
4
+
5
+ /**
6
+ * BroadcastChannel sync provider for cross-tab synchronization
7
+ * This is a lightweight alternative to y-webrtc for browser-tab-only sync
8
+ */
9
+ class BroadcastSyncProvider {
10
+ doc;
11
+ channel;
12
+ _synced = false;
13
+ constructor(docName, doc, _options) {
14
+ this.doc = doc;
15
+ this.channel = new BroadcastChannel(docName);
16
+ // Handle incoming messages from other tabs
17
+ this.channel.onmessage = (event) => {
18
+ this.handleMessage(event.data);
19
+ };
20
+ // Listen to document updates and broadcast them
21
+ this.doc.on('update', this.handleDocUpdate);
22
+ // Send initial sync request
23
+ this.broadcastSync();
24
+ // Mark as synced after a short delay (to receive any pending updates)
25
+ setTimeout(() => {
26
+ this._synced = true;
27
+ }, 100);
28
+ console.info(`BroadcastChannel Provider initialized: ${docName}`);
29
+ }
30
+ handleDocUpdate = (update, origin) => {
31
+ // Don't broadcast updates that came from other tabs (to prevent loops)
32
+ if (origin !== this) {
33
+ const encoder = defaultTextTool_config.createEncoder();
34
+ defaultTextTool_config.writeVarUint(encoder, 0); // Message type: sync update
35
+ defaultTextTool_config.writeVarUint8Array(encoder, update);
36
+ this.channel.postMessage(defaultTextTool_config.toUint8Array(encoder));
37
+ }
38
+ };
39
+ handleMessage(message) {
40
+ const decoder = defaultTextTool_config.createDecoder(new Uint8Array(message));
41
+ const messageType = defaultTextTool_config.readVarUint(decoder);
42
+ switch (messageType) {
43
+ case 0: // Sync update
44
+ const update = defaultTextTool_config.readVarUint8Array(decoder);
45
+ defaultTextTool_config.applyUpdate(this.doc, update, this);
46
+ break;
47
+ case 1: // Sync request
48
+ this.broadcastSync();
49
+ break;
50
+ case 2: // Sync response
51
+ const stateVector = defaultTextTool_config.readVarUint8Array(decoder);
52
+ const updateResponse = defaultTextTool_config.encodeStateAsUpdate(this.doc, stateVector);
53
+ if (updateResponse.length > 0) {
54
+ const encoder = defaultTextTool_config.createEncoder();
55
+ defaultTextTool_config.writeVarUint(encoder, 0); // Send as regular update
56
+ defaultTextTool_config.writeVarUint8Array(encoder, updateResponse);
57
+ this.channel.postMessage(defaultTextTool_config.toUint8Array(encoder));
58
+ }
59
+ break;
60
+ }
61
+ }
62
+ broadcastSync() {
63
+ // Broadcast our current state vector to request missing updates
64
+ const encoder = defaultTextTool_config.createEncoder();
65
+ defaultTextTool_config.writeVarUint(encoder, 2); // Message type: sync response
66
+ defaultTextTool_config.writeVarUint8Array(encoder, defaultTextTool_config.encodeStateVector(this.doc));
67
+ this.channel.postMessage(defaultTextTool_config.toUint8Array(encoder));
68
+ }
69
+ async connect() {
70
+ // Wait for initial sync to complete
71
+ if (this._synced) {
72
+ return;
73
+ }
74
+ return new Promise((resolve) => {
75
+ const checkSync = () => {
76
+ if (this._synced) {
77
+ resolve();
78
+ }
79
+ else {
80
+ setTimeout(checkSync, 50);
81
+ }
82
+ };
83
+ checkSync();
84
+ });
85
+ }
86
+ disconnect() {
87
+ // BroadcastChannel doesn't have explicit disconnect
88
+ }
89
+ destroy() {
90
+ this.doc.off('update', this.handleDocUpdate);
91
+ this.channel.close();
92
+ }
93
+ }
94
+
95
+ /* eslint-env browser */
96
+
97
+
98
+ /**
99
+ * @typedef {Object} Channel
100
+ * @property {Set<function(any, any):any>} Channel.subs
101
+ * @property {any} Channel.bc
102
+ */
103
+
104
+ /**
105
+ * @type {Map<string, Channel>}
106
+ */
107
+ const channels = new Map();
108
+
109
+ /* c8 ignore start */
110
+ class LocalStoragePolyfill {
111
+ /**
112
+ * @param {string} room
113
+ */
114
+ constructor (room) {
115
+ this.room = room;
116
+ /**
117
+ * @type {null|function({data:ArrayBuffer}):void}
118
+ */
119
+ this.onmessage = null;
120
+ /**
121
+ * @param {any} e
122
+ */
123
+ this._onChange = e => e.key === room && this.onmessage !== null && this.onmessage({ data: defaultTextTool_config.fromBase64(e.newValue || '') });
124
+ defaultTextTool_config.onChange(this._onChange);
125
+ }
126
+
127
+ /**
128
+ * @param {ArrayBuffer} buf
129
+ */
130
+ postMessage (buf) {
131
+ defaultTextTool_config.varStorage.setItem(this.room, defaultTextTool_config.toBase64(defaultTextTool_config.createUint8ArrayFromArrayBuffer(buf)));
132
+ }
133
+
134
+ close () {
135
+ defaultTextTool_config.offChange(this._onChange);
136
+ }
137
+ }
138
+ /* c8 ignore stop */
139
+
140
+ // Use BroadcastChannel or Polyfill
141
+ /* c8 ignore next */
142
+ const BC = typeof BroadcastChannel === 'undefined' ? LocalStoragePolyfill : BroadcastChannel;
143
+
144
+ /**
145
+ * @param {string} room
146
+ * @return {Channel}
147
+ */
148
+ const getChannel = room =>
149
+ defaultTextTool_config.setIfUndefined(channels, room, () => {
150
+ const subs = defaultTextTool_config.create();
151
+ const bc = new BC(room);
152
+ /**
153
+ * @param {{data:ArrayBuffer}} e
154
+ */
155
+ /* c8 ignore next */
156
+ bc.onmessage = e => subs.forEach(sub => sub(e.data, 'broadcastchannel'));
157
+ return {
158
+ bc, subs
159
+ }
160
+ });
161
+
162
+ /**
163
+ * Subscribe to global `publish` events.
164
+ *
165
+ * @function
166
+ * @param {string} room
167
+ * @param {function(any, any):any} f
168
+ */
169
+ const subscribe = (room, f) => {
170
+ getChannel(room).subs.add(f);
171
+ return f
172
+ };
173
+
174
+ /**
175
+ * Unsubscribe from `publish` global events.
176
+ *
177
+ * @function
178
+ * @param {string} room
179
+ * @param {function(any, any):any} f
180
+ */
181
+ const unsubscribe = (room, f) => {
182
+ const channel = getChannel(room);
183
+ const unsubscribed = channel.subs.delete(f);
184
+ if (unsubscribed && channel.subs.size === 0) {
185
+ channel.bc.close();
186
+ channels.delete(room);
187
+ }
188
+ return unsubscribed
189
+ };
190
+
191
+ /**
192
+ * Publish data to all subscribers (including subscribers on this tab)
193
+ *
194
+ * @function
195
+ * @param {string} room
196
+ * @param {any} data
197
+ * @param {any} [origin]
198
+ */
199
+ const publish = (room, data, origin = null) => {
200
+ const c = getChannel(room);
201
+ c.bc.postMessage(data);
202
+ c.subs.forEach(sub => sub(data, origin));
203
+ };
204
+
205
+ /**
206
+ * @module sync-protocol
207
+ */
208
+
209
+
210
+ /**
211
+ * @typedef {Map<number, number>} StateMap
212
+ */
213
+
214
+ /**
215
+ * Core Yjs defines two message types:
216
+ * • YjsSyncStep1: Includes the State Set of the sending client. When received, the client should reply with YjsSyncStep2.
217
+ * • YjsSyncStep2: Includes all missing structs and the complete delete set. When received, the client is assured that it
218
+ * received all information from the remote client.
219
+ *
220
+ * In a peer-to-peer network, you may want to introduce a SyncDone message type. Both parties should initiate the connection
221
+ * with SyncStep1. When a client received SyncStep2, it should reply with SyncDone. When the local client received both
222
+ * SyncStep2 and SyncDone, it is assured that it is synced to the remote client.
223
+ *
224
+ * In a client-server model, you want to handle this differently: The client should initiate the connection with SyncStep1.
225
+ * When the server receives SyncStep1, it should reply with SyncStep2 immediately followed by SyncStep1. The client replies
226
+ * with SyncStep2 when it receives SyncStep1. Optionally the server may send a SyncDone after it received SyncStep2, so the
227
+ * client knows that the sync is finished. There are two reasons for this more elaborated sync model: 1. This protocol can
228
+ * easily be implemented on top of http and websockets. 2. The server should only reply to requests, and not initiate them.
229
+ * Therefore it is necessary that the client initiates the sync.
230
+ *
231
+ * Construction of a message:
232
+ * [messageType : varUint, message definition..]
233
+ *
234
+ * Note: A message does not include information about the room name. This must to be handled by the upper layer protocol!
235
+ *
236
+ * stringify[messageType] stringifies a message definition (messageType is already read from the bufffer)
237
+ */
238
+
239
+ const messageYjsSyncStep1 = 0;
240
+ const messageYjsSyncStep2 = 1;
241
+ const messageYjsUpdate = 2;
242
+
243
+ /**
244
+ * Create a sync step 1 message based on the state of the current shared document.
245
+ *
246
+ * @param {encoding.Encoder} encoder
247
+ * @param {Y.Doc} doc
248
+ */
249
+ const writeSyncStep1 = (encoder, doc) => {
250
+ defaultTextTool_config.writeVarUint(encoder, messageYjsSyncStep1);
251
+ const sv = defaultTextTool_config.encodeStateVector(doc);
252
+ defaultTextTool_config.writeVarUint8Array(encoder, sv);
253
+ };
254
+
255
+ /**
256
+ * @param {encoding.Encoder} encoder
257
+ * @param {Y.Doc} doc
258
+ * @param {Uint8Array} [encodedStateVector]
259
+ */
260
+ const writeSyncStep2 = (encoder, doc, encodedStateVector) => {
261
+ defaultTextTool_config.writeVarUint(encoder, messageYjsSyncStep2);
262
+ defaultTextTool_config.writeVarUint8Array(encoder, defaultTextTool_config.encodeStateAsUpdate(doc, encodedStateVector));
263
+ };
264
+
265
+ /**
266
+ * Read SyncStep1 message and reply with SyncStep2.
267
+ *
268
+ * @param {decoding.Decoder} decoder The reply to the received message
269
+ * @param {encoding.Encoder} encoder The received message
270
+ * @param {Y.Doc} doc
271
+ */
272
+ const readSyncStep1 = (decoder, encoder, doc) =>
273
+ writeSyncStep2(encoder, doc, defaultTextTool_config.readVarUint8Array(decoder));
274
+
275
+ /**
276
+ * Read and apply Structs and then DeleteStore to a y instance.
277
+ *
278
+ * @param {decoding.Decoder} decoder
279
+ * @param {Y.Doc} doc
280
+ * @param {any} transactionOrigin
281
+ */
282
+ const readSyncStep2 = (decoder, doc, transactionOrigin) => {
283
+ try {
284
+ defaultTextTool_config.applyUpdate(doc, defaultTextTool_config.readVarUint8Array(decoder), transactionOrigin);
285
+ } catch (error) {
286
+ // This catches errors that are thrown by event handlers
287
+ console.error('Caught error while handling a Yjs update', error);
288
+ }
289
+ };
290
+
291
+ /**
292
+ * @param {encoding.Encoder} encoder
293
+ * @param {Uint8Array} update
294
+ */
295
+ const writeUpdate = (encoder, update) => {
296
+ defaultTextTool_config.writeVarUint(encoder, messageYjsUpdate);
297
+ defaultTextTool_config.writeVarUint8Array(encoder, update);
298
+ };
299
+
300
+ /**
301
+ * Read and apply Structs and then DeleteStore to a y instance.
302
+ *
303
+ * @param {decoding.Decoder} decoder
304
+ * @param {Y.Doc} doc
305
+ * @param {any} transactionOrigin
306
+ */
307
+ const readUpdate = readSyncStep2;
308
+
309
+ /**
310
+ * @param {decoding.Decoder} decoder A message received from another client
311
+ * @param {encoding.Encoder} encoder The reply message. Does not need to be sent if empty.
312
+ * @param {Y.Doc} doc
313
+ * @param {any} transactionOrigin
314
+ */
315
+ const readSyncMessage = (decoder, encoder, doc, transactionOrigin) => {
316
+ const messageType = defaultTextTool_config.readVarUint(decoder);
317
+ switch (messageType) {
318
+ case messageYjsSyncStep1:
319
+ readSyncStep1(decoder, encoder, doc);
320
+ break
321
+ case messageYjsSyncStep2:
322
+ readSyncStep2(decoder, doc, transactionOrigin);
323
+ break
324
+ case messageYjsUpdate:
325
+ readUpdate(decoder, doc, transactionOrigin);
326
+ break
327
+ default:
328
+ throw new Error('Unknown message type')
329
+ }
330
+ return messageType
331
+ };
332
+
333
+ const messagePermissionDenied = 0;
334
+
335
+ /**
336
+ * @callback PermissionDeniedHandler
337
+ * @param {any} y
338
+ * @param {string} reason
339
+ */
340
+
341
+ /**
342
+ *
343
+ * @param {decoding.Decoder} decoder
344
+ * @param {Y.Doc} y
345
+ * @param {PermissionDeniedHandler} permissionDeniedHandler
346
+ */
347
+ const readAuthMessage = (decoder, y, permissionDeniedHandler) => {
348
+ switch (defaultTextTool_config.readVarUint(decoder)) {
349
+ case messagePermissionDenied: permissionDeniedHandler(y, defaultTextTool_config.readVarString(decoder));
350
+ }
351
+ };
352
+
353
+ /**
354
+ * @module awareness-protocol
355
+ */
356
+
357
+
358
+ const outdatedTimeout = 30000;
359
+
360
+ /**
361
+ * @typedef {Object} MetaClientState
362
+ * @property {number} MetaClientState.clock
363
+ * @property {number} MetaClientState.lastUpdated unix timestamp
364
+ */
365
+
366
+ /**
367
+ * The Awareness class implements a simple shared state protocol that can be used for non-persistent data like awareness information
368
+ * (cursor, username, status, ..). Each client can update its own local state and listen to state changes of
369
+ * remote clients. Every client may set a state of a remote peer to `null` to mark the client as offline.
370
+ *
371
+ * Each client is identified by a unique client id (something we borrow from `doc.clientID`). A client can override
372
+ * its own state by propagating a message with an increasing timestamp (`clock`). If such a message is received, it is
373
+ * applied if the known state of that client is older than the new state (`clock < newClock`). If a client thinks that
374
+ * a remote client is offline, it may propagate a message with
375
+ * `{ clock: currentClientClock, state: null, client: remoteClient }`. If such a
376
+ * message is received, and the known clock of that client equals the received clock, it will override the state with `null`.
377
+ *
378
+ * Before a client disconnects, it should propagate a `null` state with an updated clock.
379
+ *
380
+ * Awareness states must be updated every 30 seconds. Otherwise the Awareness instance will delete the client state.
381
+ *
382
+ * @extends {Observable<string>}
383
+ */
384
+ class Awareness extends defaultTextTool_config.Observable {
385
+ /**
386
+ * @param {Y.Doc} doc
387
+ */
388
+ constructor (doc) {
389
+ super();
390
+ this.doc = doc;
391
+ /**
392
+ * @type {number}
393
+ */
394
+ this.clientID = doc.clientID;
395
+ /**
396
+ * Maps from client id to client state
397
+ * @type {Map<number, Object<string, any>>}
398
+ */
399
+ this.states = new Map();
400
+ /**
401
+ * @type {Map<number, MetaClientState>}
402
+ */
403
+ this.meta = new Map();
404
+ this._checkInterval = /** @type {any} */ (setInterval(() => {
405
+ const now = defaultTextTool_config.getUnixTime();
406
+ if (this.getLocalState() !== null && (outdatedTimeout / 2 <= now - /** @type {{lastUpdated:number}} */ (this.meta.get(this.clientID)).lastUpdated)) {
407
+ // renew local clock
408
+ this.setLocalState(this.getLocalState());
409
+ }
410
+ /**
411
+ * @type {Array<number>}
412
+ */
413
+ const remove = [];
414
+ this.meta.forEach((meta, clientid) => {
415
+ if (clientid !== this.clientID && outdatedTimeout <= now - meta.lastUpdated && this.states.has(clientid)) {
416
+ remove.push(clientid);
417
+ }
418
+ });
419
+ if (remove.length > 0) {
420
+ removeAwarenessStates(this, remove, 'timeout');
421
+ }
422
+ }, defaultTextTool_config.floor(outdatedTimeout / 10)));
423
+ doc.on('destroy', () => {
424
+ this.destroy();
425
+ });
426
+ this.setLocalState({});
427
+ }
428
+
429
+ destroy () {
430
+ this.emit('destroy', [this]);
431
+ this.setLocalState(null);
432
+ super.destroy();
433
+ clearInterval(this._checkInterval);
434
+ }
435
+
436
+ /**
437
+ * @return {Object<string,any>|null}
438
+ */
439
+ getLocalState () {
440
+ return this.states.get(this.clientID) || null
441
+ }
442
+
443
+ /**
444
+ * @param {Object<string,any>|null} state
445
+ */
446
+ setLocalState (state) {
447
+ const clientID = this.clientID;
448
+ const currLocalMeta = this.meta.get(clientID);
449
+ const clock = currLocalMeta === undefined ? 0 : currLocalMeta.clock + 1;
450
+ const prevState = this.states.get(clientID);
451
+ if (state === null) {
452
+ this.states.delete(clientID);
453
+ } else {
454
+ this.states.set(clientID, state);
455
+ }
456
+ this.meta.set(clientID, {
457
+ clock,
458
+ lastUpdated: defaultTextTool_config.getUnixTime()
459
+ });
460
+ const added = [];
461
+ const updated = [];
462
+ const filteredUpdated = [];
463
+ const removed = [];
464
+ if (state === null) {
465
+ removed.push(clientID);
466
+ } else if (prevState == null) {
467
+ if (state != null) {
468
+ added.push(clientID);
469
+ }
470
+ } else {
471
+ updated.push(clientID);
472
+ if (!defaultTextTool_config.equalityDeep(prevState, state)) {
473
+ filteredUpdated.push(clientID);
474
+ }
475
+ }
476
+ if (added.length > 0 || filteredUpdated.length > 0 || removed.length > 0) {
477
+ this.emit('change', [{ added, updated: filteredUpdated, removed }, 'local']);
478
+ }
479
+ this.emit('update', [{ added, updated, removed }, 'local']);
480
+ }
481
+
482
+ /**
483
+ * @param {string} field
484
+ * @param {any} value
485
+ */
486
+ setLocalStateField (field, value) {
487
+ const state = this.getLocalState();
488
+ if (state !== null) {
489
+ this.setLocalState({
490
+ ...state,
491
+ [field]: value
492
+ });
493
+ }
494
+ }
495
+
496
+ /**
497
+ * @return {Map<number,Object<string,any>>}
498
+ */
499
+ getStates () {
500
+ return this.states
501
+ }
502
+ }
503
+
504
+ /**
505
+ * Mark (remote) clients as inactive and remove them from the list of active peers.
506
+ * This change will be propagated to remote clients.
507
+ *
508
+ * @param {Awareness} awareness
509
+ * @param {Array<number>} clients
510
+ * @param {any} origin
511
+ */
512
+ const removeAwarenessStates = (awareness, clients, origin) => {
513
+ const removed = [];
514
+ for (let i = 0; i < clients.length; i++) {
515
+ const clientID = clients[i];
516
+ if (awareness.states.has(clientID)) {
517
+ awareness.states.delete(clientID);
518
+ if (clientID === awareness.clientID) {
519
+ const curMeta = /** @type {MetaClientState} */ (awareness.meta.get(clientID));
520
+ awareness.meta.set(clientID, {
521
+ clock: curMeta.clock + 1,
522
+ lastUpdated: defaultTextTool_config.getUnixTime()
523
+ });
524
+ }
525
+ removed.push(clientID);
526
+ }
527
+ }
528
+ if (removed.length > 0) {
529
+ awareness.emit('change', [{ added: [], updated: [], removed }, origin]);
530
+ awareness.emit('update', [{ added: [], updated: [], removed }, origin]);
531
+ }
532
+ };
533
+
534
+ /**
535
+ * @param {Awareness} awareness
536
+ * @param {Array<number>} clients
537
+ * @return {Uint8Array}
538
+ */
539
+ const encodeAwarenessUpdate = (awareness, clients, states = awareness.states) => {
540
+ const len = clients.length;
541
+ const encoder = defaultTextTool_config.createEncoder();
542
+ defaultTextTool_config.writeVarUint(encoder, len);
543
+ for (let i = 0; i < len; i++) {
544
+ const clientID = clients[i];
545
+ const state = states.get(clientID) || null;
546
+ const clock = /** @type {MetaClientState} */ (awareness.meta.get(clientID)).clock;
547
+ defaultTextTool_config.writeVarUint(encoder, clientID);
548
+ defaultTextTool_config.writeVarUint(encoder, clock);
549
+ defaultTextTool_config.writeVarString(encoder, JSON.stringify(state));
550
+ }
551
+ return defaultTextTool_config.toUint8Array(encoder)
552
+ };
553
+
554
+ /**
555
+ * @param {Awareness} awareness
556
+ * @param {Uint8Array} update
557
+ * @param {any} origin This will be added to the emitted change event
558
+ */
559
+ const applyAwarenessUpdate = (awareness, update, origin) => {
560
+ const decoder = defaultTextTool_config.createDecoder(update);
561
+ const timestamp = defaultTextTool_config.getUnixTime();
562
+ const added = [];
563
+ const updated = [];
564
+ const filteredUpdated = [];
565
+ const removed = [];
566
+ const len = defaultTextTool_config.readVarUint(decoder);
567
+ for (let i = 0; i < len; i++) {
568
+ const clientID = defaultTextTool_config.readVarUint(decoder);
569
+ let clock = defaultTextTool_config.readVarUint(decoder);
570
+ const state = JSON.parse(defaultTextTool_config.readVarString(decoder));
571
+ const clientMeta = awareness.meta.get(clientID);
572
+ const prevState = awareness.states.get(clientID);
573
+ const currClock = clientMeta === undefined ? 0 : clientMeta.clock;
574
+ if (currClock < clock || (currClock === clock && state === null && awareness.states.has(clientID))) {
575
+ if (state === null) {
576
+ // never let a remote client remove this local state
577
+ if (clientID === awareness.clientID && awareness.getLocalState() != null) {
578
+ // remote client removed the local state. Do not remote state. Broadcast a message indicating
579
+ // that this client still exists by increasing the clock
580
+ clock++;
581
+ } else {
582
+ awareness.states.delete(clientID);
583
+ }
584
+ } else {
585
+ awareness.states.set(clientID, state);
586
+ }
587
+ awareness.meta.set(clientID, {
588
+ clock,
589
+ lastUpdated: timestamp
590
+ });
591
+ if (clientMeta === undefined && state !== null) {
592
+ added.push(clientID);
593
+ } else if (clientMeta !== undefined && state === null) {
594
+ removed.push(clientID);
595
+ } else if (state !== null) {
596
+ if (!defaultTextTool_config.equalityDeep(state, prevState)) {
597
+ filteredUpdated.push(clientID);
598
+ }
599
+ updated.push(clientID);
600
+ }
601
+ }
602
+ }
603
+ if (added.length > 0 || filteredUpdated.length > 0 || removed.length > 0) {
604
+ awareness.emit('change', [{
605
+ added, updated: filteredUpdated, removed
606
+ }, origin]);
607
+ }
608
+ if (added.length > 0 || updated.length > 0 || removed.length > 0) {
609
+ awareness.emit('update', [{
610
+ added, updated, removed
611
+ }, origin]);
612
+ }
613
+ };
614
+
615
+ /**
616
+ * Utility module to work with urls.
617
+ *
618
+ * @module url
619
+ */
620
+
621
+
622
+ /**
623
+ * @param {Object<string,string>} params
624
+ * @return {string}
625
+ */
626
+ const encodeQueryParams = params =>
627
+ defaultTextTool_config.map(params, (val, key) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&');
628
+
629
+ /**
630
+ * @module provider/websocket
631
+ */
632
+
633
+
634
+ const messageSync = 0;
635
+ const messageQueryAwareness = 3;
636
+ const messageAwareness = 1;
637
+ const messageAuth = 2;
638
+
639
+ /**
640
+ * encoder, decoder, provider, emitSynced, messageType
641
+ * @type {Array<function(encoding.Encoder, decoding.Decoder, WebsocketProvider, boolean, number):void>}
642
+ */
643
+ const messageHandlers = [];
644
+
645
+ messageHandlers[messageSync] = (
646
+ encoder,
647
+ decoder,
648
+ provider,
649
+ emitSynced,
650
+ _messageType
651
+ ) => {
652
+ defaultTextTool_config.writeVarUint(encoder, messageSync);
653
+ const syncMessageType = readSyncMessage(
654
+ decoder,
655
+ encoder,
656
+ provider.doc,
657
+ provider
658
+ );
659
+ if (
660
+ emitSynced && syncMessageType === messageYjsSyncStep2 &&
661
+ !provider.synced
662
+ ) {
663
+ provider.synced = true;
664
+ }
665
+ };
666
+
667
+ messageHandlers[messageQueryAwareness] = (
668
+ encoder,
669
+ _decoder,
670
+ provider,
671
+ _emitSynced,
672
+ _messageType
673
+ ) => {
674
+ defaultTextTool_config.writeVarUint(encoder, messageAwareness);
675
+ defaultTextTool_config.writeVarUint8Array(
676
+ encoder,
677
+ encodeAwarenessUpdate(
678
+ provider.awareness,
679
+ Array.from(provider.awareness.getStates().keys())
680
+ )
681
+ );
682
+ };
683
+
684
+ messageHandlers[messageAwareness] = (
685
+ _encoder,
686
+ decoder,
687
+ provider,
688
+ _emitSynced,
689
+ _messageType
690
+ ) => {
691
+ applyAwarenessUpdate(
692
+ provider.awareness,
693
+ defaultTextTool_config.readVarUint8Array(decoder),
694
+ provider
695
+ );
696
+ };
697
+
698
+ messageHandlers[messageAuth] = (
699
+ _encoder,
700
+ decoder,
701
+ provider,
702
+ _emitSynced,
703
+ _messageType
704
+ ) => {
705
+ readAuthMessage(
706
+ decoder,
707
+ provider.doc,
708
+ (_ydoc, reason) => permissionDeniedHandler(provider, reason)
709
+ );
710
+ };
711
+
712
+ // @todo - this should depend on awareness.outdatedTime
713
+ const messageReconnectTimeout = 30000;
714
+
715
+ /**
716
+ * @param {WebsocketProvider} provider
717
+ * @param {string} reason
718
+ */
719
+ const permissionDeniedHandler = (provider, reason) =>
720
+ console.warn(`Permission denied to access ${provider.url}.\n${reason}`);
721
+
722
+ /**
723
+ * @param {WebsocketProvider} provider
724
+ * @param {Uint8Array} buf
725
+ * @param {boolean} emitSynced
726
+ * @return {encoding.Encoder}
727
+ */
728
+ const readMessage = (provider, buf, emitSynced) => {
729
+ const decoder = defaultTextTool_config.createDecoder(buf);
730
+ const encoder = defaultTextTool_config.createEncoder();
731
+ const messageType = defaultTextTool_config.readVarUint(decoder);
732
+ const messageHandler = provider.messageHandlers[messageType];
733
+ if (/** @type {any} */ (messageHandler)) {
734
+ messageHandler(encoder, decoder, provider, emitSynced, messageType);
735
+ } else {
736
+ console.error('Unable to compute message');
737
+ }
738
+ return encoder
739
+ };
740
+
741
+ /**
742
+ * Outsource this function so that a new websocket connection is created immediately.
743
+ * I suspect that the `ws.onclose` event is not always fired if there are network issues.
744
+ *
745
+ * @param {WebsocketProvider} provider
746
+ * @param {WebSocket} ws
747
+ * @param {CloseEvent | null} event
748
+ */
749
+ const closeWebsocketConnection = (provider, ws, event) => {
750
+ if (ws === provider.ws) {
751
+ provider.emit('connection-close', [event, provider]);
752
+ provider.ws = null;
753
+ ws.close();
754
+ provider.wsconnecting = false;
755
+ if (provider.wsconnected) {
756
+ provider.wsconnected = false;
757
+ provider.synced = false;
758
+ // update awareness (all users except local left)
759
+ removeAwarenessStates(
760
+ provider.awareness,
761
+ Array.from(provider.awareness.getStates().keys()).filter((client) =>
762
+ client !== provider.doc.clientID
763
+ ),
764
+ provider
765
+ );
766
+ provider.emit('status', [{
767
+ status: 'disconnected'
768
+ }]);
769
+ } else {
770
+ provider.wsUnsuccessfulReconnects++;
771
+ }
772
+ // Start with no reconnect timeout and increase timeout by
773
+ // using exponential backoff starting with 100ms
774
+ setTimeout(
775
+ setupWS,
776
+ defaultTextTool_config.min(
777
+ defaultTextTool_config.pow(2, provider.wsUnsuccessfulReconnects) * 100,
778
+ provider.maxBackoffTime
779
+ ),
780
+ provider
781
+ );
782
+ }
783
+ };
784
+
785
+ /**
786
+ * @param {WebsocketProvider} provider
787
+ */
788
+ const setupWS = (provider) => {
789
+ if (provider.shouldConnect && provider.ws === null) {
790
+ const websocket = new provider._WS(provider.url, provider.protocols);
791
+ websocket.binaryType = 'arraybuffer';
792
+ provider.ws = websocket;
793
+ provider.wsconnecting = true;
794
+ provider.wsconnected = false;
795
+ provider.synced = false;
796
+
797
+ websocket.onmessage = (event) => {
798
+ provider.wsLastMessageReceived = defaultTextTool_config.getUnixTime();
799
+ const encoder = readMessage(provider, new Uint8Array(event.data), true);
800
+ if (defaultTextTool_config.length(encoder) > 1) {
801
+ websocket.send(defaultTextTool_config.toUint8Array(encoder));
802
+ }
803
+ };
804
+ websocket.onerror = (event) => {
805
+ provider.emit('connection-error', [event, provider]);
806
+ };
807
+ websocket.onclose = (event) => {
808
+ closeWebsocketConnection(provider, websocket, event);
809
+ };
810
+ websocket.onopen = () => {
811
+ provider.wsLastMessageReceived = defaultTextTool_config.getUnixTime();
812
+ provider.wsconnecting = false;
813
+ provider.wsconnected = true;
814
+ provider.wsUnsuccessfulReconnects = 0;
815
+ provider.emit('status', [{
816
+ status: 'connected'
817
+ }]);
818
+ // always send sync step 1 when connected
819
+ const encoder = defaultTextTool_config.createEncoder();
820
+ defaultTextTool_config.writeVarUint(encoder, messageSync);
821
+ writeSyncStep1(encoder, provider.doc);
822
+ websocket.send(defaultTextTool_config.toUint8Array(encoder));
823
+ // broadcast local awareness state
824
+ if (provider.awareness.getLocalState() !== null) {
825
+ const encoderAwarenessState = defaultTextTool_config.createEncoder();
826
+ defaultTextTool_config.writeVarUint(encoderAwarenessState, messageAwareness);
827
+ defaultTextTool_config.writeVarUint8Array(
828
+ encoderAwarenessState,
829
+ encodeAwarenessUpdate(provider.awareness, [
830
+ provider.doc.clientID
831
+ ])
832
+ );
833
+ websocket.send(defaultTextTool_config.toUint8Array(encoderAwarenessState));
834
+ }
835
+ };
836
+ provider.emit('status', [{
837
+ status: 'connecting'
838
+ }]);
839
+ }
840
+ };
841
+
842
+ /**
843
+ * @param {WebsocketProvider} provider
844
+ * @param {ArrayBuffer} buf
845
+ */
846
+ const broadcastMessage = (provider, buf) => {
847
+ const ws = provider.ws;
848
+ if (provider.wsconnected && ws && ws.readyState === ws.OPEN) {
849
+ ws.send(buf);
850
+ }
851
+ if (provider.bcconnected) {
852
+ publish(provider.bcChannel, buf, provider);
853
+ }
854
+ };
855
+
856
+ /**
857
+ * Websocket Provider for Yjs. Creates a websocket connection to sync the shared document.
858
+ * The document name is attached to the provided url. I.e. the following example
859
+ * creates a websocket connection to http://localhost:1234/my-document-name
860
+ *
861
+ * @example
862
+ * import * as Y from 'yjs'
863
+ * import { WebsocketProvider } from 'y-websocket'
864
+ * const doc = new Y.Doc()
865
+ * const provider = new WebsocketProvider('http://localhost:1234', 'my-document-name', doc)
866
+ *
867
+ * @extends {ObservableV2<{ 'connection-close': (event: CloseEvent | null, provider: WebsocketProvider) => any, 'status': (event: { status: 'connected' | 'disconnected' | 'connecting' }) => any, 'connection-error': (event: Event, provider: WebsocketProvider) => any, 'sync': (state: boolean) => any }>}
868
+ */
869
+ class WebsocketProvider extends defaultTextTool_config.ObservableV2 {
870
+ /**
871
+ * @param {string} serverUrl
872
+ * @param {string} roomname
873
+ * @param {Y.Doc} doc
874
+ * @param {object} opts
875
+ * @param {boolean} [opts.connect]
876
+ * @param {awarenessProtocol.Awareness} [opts.awareness]
877
+ * @param {Object<string,string>} [opts.params] specify url parameters
878
+ * @param {Array<string>} [opts.protocols] specify websocket protocols
879
+ * @param {typeof WebSocket} [opts.WebSocketPolyfill] Optionall provide a WebSocket polyfill
880
+ * @param {number} [opts.resyncInterval] Request server state every `resyncInterval` milliseconds
881
+ * @param {number} [opts.maxBackoffTime] Maximum amount of time to wait before trying to reconnect (we try to reconnect using exponential backoff)
882
+ * @param {boolean} [opts.disableBc] Disable cross-tab BroadcastChannel communication
883
+ */
884
+ constructor (serverUrl, roomname, doc, {
885
+ connect = true,
886
+ awareness = new Awareness(doc),
887
+ params = {},
888
+ protocols = [],
889
+ WebSocketPolyfill = WebSocket,
890
+ resyncInterval = -1,
891
+ maxBackoffTime = 2500,
892
+ disableBc = false
893
+ } = {}) {
894
+ super();
895
+ // ensure that serverUrl does not end with /
896
+ while (serverUrl[serverUrl.length - 1] === '/') {
897
+ serverUrl = serverUrl.slice(0, serverUrl.length - 1);
898
+ }
899
+ this.serverUrl = serverUrl;
900
+ this.bcChannel = serverUrl + '/' + roomname;
901
+ this.maxBackoffTime = maxBackoffTime;
902
+ /**
903
+ * The specified url parameters. This can be safely updated. The changed parameters will be used
904
+ * when a new connection is established.
905
+ * @type {Object<string,string>}
906
+ */
907
+ this.params = params;
908
+ this.protocols = protocols;
909
+ this.roomname = roomname;
910
+ this.doc = doc;
911
+ this._WS = WebSocketPolyfill;
912
+ this.awareness = awareness;
913
+ this.wsconnected = false;
914
+ this.wsconnecting = false;
915
+ this.bcconnected = false;
916
+ this.disableBc = disableBc;
917
+ this.wsUnsuccessfulReconnects = 0;
918
+ this.messageHandlers = messageHandlers.slice();
919
+ /**
920
+ * @type {boolean}
921
+ */
922
+ this._synced = false;
923
+ /**
924
+ * @type {WebSocket?}
925
+ */
926
+ this.ws = null;
927
+ this.wsLastMessageReceived = 0;
928
+ /**
929
+ * Whether to connect to other peers or not
930
+ * @type {boolean}
931
+ */
932
+ this.shouldConnect = connect;
933
+
934
+ /**
935
+ * @type {number}
936
+ */
937
+ this._resyncInterval = 0;
938
+ if (resyncInterval > 0) {
939
+ this._resyncInterval = /** @type {any} */ (setInterval(() => {
940
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
941
+ // resend sync step 1
942
+ const encoder = defaultTextTool_config.createEncoder();
943
+ defaultTextTool_config.writeVarUint(encoder, messageSync);
944
+ writeSyncStep1(encoder, doc);
945
+ this.ws.send(defaultTextTool_config.toUint8Array(encoder));
946
+ }
947
+ }, resyncInterval));
948
+ }
949
+
950
+ /**
951
+ * @param {ArrayBuffer} data
952
+ * @param {any} origin
953
+ */
954
+ this._bcSubscriber = (data, origin) => {
955
+ if (origin !== this) {
956
+ const encoder = readMessage(this, new Uint8Array(data), false);
957
+ if (defaultTextTool_config.length(encoder) > 1) {
958
+ publish(this.bcChannel, defaultTextTool_config.toUint8Array(encoder), this);
959
+ }
960
+ }
961
+ };
962
+ /**
963
+ * Listens to Yjs updates and sends them to remote peers (ws and broadcastchannel)
964
+ * @param {Uint8Array} update
965
+ * @param {any} origin
966
+ */
967
+ this._updateHandler = (update, origin) => {
968
+ if (origin !== this) {
969
+ const encoder = defaultTextTool_config.createEncoder();
970
+ defaultTextTool_config.writeVarUint(encoder, messageSync);
971
+ writeUpdate(encoder, update);
972
+ broadcastMessage(this, defaultTextTool_config.toUint8Array(encoder));
973
+ }
974
+ };
975
+ this.doc.on('update', this._updateHandler);
976
+ /**
977
+ * @param {any} changed
978
+ * @param {any} _origin
979
+ */
980
+ this._awarenessUpdateHandler = ({ added, updated, removed }, _origin) => {
981
+ const changedClients = added.concat(updated).concat(removed);
982
+ const encoder = defaultTextTool_config.createEncoder();
983
+ defaultTextTool_config.writeVarUint(encoder, messageAwareness);
984
+ defaultTextTool_config.writeVarUint8Array(
985
+ encoder,
986
+ encodeAwarenessUpdate(awareness, changedClients)
987
+ );
988
+ broadcastMessage(this, defaultTextTool_config.toUint8Array(encoder));
989
+ };
990
+ this._exitHandler = () => {
991
+ removeAwarenessStates(
992
+ this.awareness,
993
+ [doc.clientID],
994
+ 'app closed'
995
+ );
996
+ };
997
+ if (defaultTextTool_config.isNode && typeof process !== 'undefined') {
998
+ process.on('exit', this._exitHandler);
999
+ }
1000
+ awareness.on('update', this._awarenessUpdateHandler);
1001
+ this._checkInterval = /** @type {any} */ (setInterval(() => {
1002
+ if (
1003
+ this.wsconnected &&
1004
+ messageReconnectTimeout <
1005
+ defaultTextTool_config.getUnixTime() - this.wsLastMessageReceived
1006
+ ) {
1007
+ // no message received in a long time - not even your own awareness
1008
+ // updates (which are updated every 15 seconds)
1009
+ closeWebsocketConnection(this, /** @type {WebSocket} */ (this.ws), null);
1010
+ }
1011
+ }, messageReconnectTimeout / 10));
1012
+ if (connect) {
1013
+ this.connect();
1014
+ }
1015
+ }
1016
+
1017
+ get url () {
1018
+ const encodedParams = encodeQueryParams(this.params);
1019
+ return this.serverUrl + '/' + this.roomname +
1020
+ (encodedParams.length === 0 ? '' : '?' + encodedParams)
1021
+ }
1022
+
1023
+ /**
1024
+ * @type {boolean}
1025
+ */
1026
+ get synced () {
1027
+ return this._synced
1028
+ }
1029
+
1030
+ set synced (state) {
1031
+ if (this._synced !== state) {
1032
+ this._synced = state;
1033
+ // @ts-ignore
1034
+ this.emit('synced', [state]);
1035
+ this.emit('sync', [state]);
1036
+ }
1037
+ }
1038
+
1039
+ destroy () {
1040
+ if (this._resyncInterval !== 0) {
1041
+ clearInterval(this._resyncInterval);
1042
+ }
1043
+ clearInterval(this._checkInterval);
1044
+ this.disconnect();
1045
+ if (defaultTextTool_config.isNode && typeof process !== 'undefined') {
1046
+ process.off('exit', this._exitHandler);
1047
+ }
1048
+ this.awareness.off('update', this._awarenessUpdateHandler);
1049
+ this.doc.off('update', this._updateHandler);
1050
+ super.destroy();
1051
+ }
1052
+
1053
+ connectBc () {
1054
+ if (this.disableBc) {
1055
+ return
1056
+ }
1057
+ if (!this.bcconnected) {
1058
+ subscribe(this.bcChannel, this._bcSubscriber);
1059
+ this.bcconnected = true;
1060
+ }
1061
+ // send sync step1 to bc
1062
+ // write sync step 1
1063
+ const encoderSync = defaultTextTool_config.createEncoder();
1064
+ defaultTextTool_config.writeVarUint(encoderSync, messageSync);
1065
+ writeSyncStep1(encoderSync, this.doc);
1066
+ publish(this.bcChannel, defaultTextTool_config.toUint8Array(encoderSync), this);
1067
+ // broadcast local state
1068
+ const encoderState = defaultTextTool_config.createEncoder();
1069
+ defaultTextTool_config.writeVarUint(encoderState, messageSync);
1070
+ writeSyncStep2(encoderState, this.doc);
1071
+ publish(this.bcChannel, defaultTextTool_config.toUint8Array(encoderState), this);
1072
+ // write queryAwareness
1073
+ const encoderAwarenessQuery = defaultTextTool_config.createEncoder();
1074
+ defaultTextTool_config.writeVarUint(encoderAwarenessQuery, messageQueryAwareness);
1075
+ publish(
1076
+ this.bcChannel,
1077
+ defaultTextTool_config.toUint8Array(encoderAwarenessQuery),
1078
+ this
1079
+ );
1080
+ // broadcast local awareness state
1081
+ const encoderAwarenessState = defaultTextTool_config.createEncoder();
1082
+ defaultTextTool_config.writeVarUint(encoderAwarenessState, messageAwareness);
1083
+ defaultTextTool_config.writeVarUint8Array(
1084
+ encoderAwarenessState,
1085
+ encodeAwarenessUpdate(this.awareness, [
1086
+ this.doc.clientID
1087
+ ])
1088
+ );
1089
+ publish(
1090
+ this.bcChannel,
1091
+ defaultTextTool_config.toUint8Array(encoderAwarenessState),
1092
+ this
1093
+ );
1094
+ }
1095
+
1096
+ disconnectBc () {
1097
+ // broadcast message with local awareness state set to null (indicating disconnect)
1098
+ const encoder = defaultTextTool_config.createEncoder();
1099
+ defaultTextTool_config.writeVarUint(encoder, messageAwareness);
1100
+ defaultTextTool_config.writeVarUint8Array(
1101
+ encoder,
1102
+ encodeAwarenessUpdate(this.awareness, [
1103
+ this.doc.clientID
1104
+ ], new Map())
1105
+ );
1106
+ broadcastMessage(this, defaultTextTool_config.toUint8Array(encoder));
1107
+ if (this.bcconnected) {
1108
+ unsubscribe(this.bcChannel, this._bcSubscriber);
1109
+ this.bcconnected = false;
1110
+ }
1111
+ }
1112
+
1113
+ disconnect () {
1114
+ this.shouldConnect = false;
1115
+ this.disconnectBc();
1116
+ if (this.ws !== null) {
1117
+ closeWebsocketConnection(this, this.ws, null);
1118
+ }
1119
+ }
1120
+
1121
+ connect () {
1122
+ this.shouldConnect = true;
1123
+ if (!this.wsconnected && this.ws === null) {
1124
+ setupWS(this);
1125
+ this.connectBc();
1126
+ }
1127
+ }
1128
+ }
1129
+
1130
+ /**
1131
+ * WebSocket sync provider for real-time collaboration
1132
+ */
1133
+ class WebSocketSyncProvider {
1134
+ provider;
1135
+ isConnected = false;
1136
+ constructor(docName, doc, options) {
1137
+ const url = options?.url || 'ws://localhost:1234';
1138
+ const roomName = options?.roomName || docName;
1139
+ this.provider = new WebsocketProvider(url, roomName, doc, {
1140
+ params: options?.params,
1141
+ protocols: options?.protocols,
1142
+ WebSocketPolyfill: options?.WebSocketPolyfill,
1143
+ awareness: options?.awareness,
1144
+ maxBackoffTime: options?.maxBackoffTime,
1145
+ disableBc: true,
1146
+ });
1147
+ this.setupEventListeners();
1148
+ console.info(`WebSocket Provider initialized: ${url}/${roomName}`);
1149
+ }
1150
+ /**
1151
+ * Static factory method for creating WebSocketSyncProvider with configuration options
1152
+ * Returns a ProviderFactory that can be used in sync configuration
1153
+ */
1154
+ static with(options) {
1155
+ return {
1156
+ create: (docName, doc) => {
1157
+ return new WebSocketSyncProvider(docName, doc, options);
1158
+ },
1159
+ };
1160
+ }
1161
+ setupEventListeners() {
1162
+ this.provider.on('status', ({ status }) => {
1163
+ if (status === 'connected') {
1164
+ this.isConnected = true;
1165
+ console.info('WebSocket connected');
1166
+ }
1167
+ else if (status === 'disconnected') {
1168
+ this.isConnected = false;
1169
+ console.info('WebSocket disconnected');
1170
+ }
1171
+ });
1172
+ this.provider.on('sync', (synced) => {
1173
+ if (synced) {
1174
+ console.info('WebSocket synced');
1175
+ }
1176
+ });
1177
+ }
1178
+ async connect() {
1179
+ if (this.isConnected) {
1180
+ return;
1181
+ }
1182
+ return new Promise((resolve, reject) => {
1183
+ const timeout = setTimeout(() => {
1184
+ reject(new Error('WebSocket connection timeout'));
1185
+ }, 10000); // 10 second timeout
1186
+ const statusHandler = ({ status }) => {
1187
+ if (status === 'connected') {
1188
+ clearTimeout(timeout);
1189
+ this.provider.off('status', statusHandler);
1190
+ this.isConnected = true;
1191
+ resolve();
1192
+ }
1193
+ };
1194
+ this.provider.on('status', statusHandler);
1195
+ // If already connected, resolve immediately
1196
+ if (this.provider.wsconnected) {
1197
+ clearTimeout(timeout);
1198
+ this.provider.off('status', statusHandler);
1199
+ this.isConnected = true;
1200
+ resolve();
1201
+ }
1202
+ });
1203
+ }
1204
+ disconnect() {
1205
+ if (this.provider) {
1206
+ this.provider.disconnect();
1207
+ }
1208
+ this.isConnected = false;
1209
+ }
1210
+ destroy() {
1211
+ if (this.provider) {
1212
+ this.provider.destroy();
1213
+ }
1214
+ this.isConnected = false;
1215
+ }
1216
+ }
1217
+
1218
+ /**
1219
+ * Hocuspocus sync provider for real-time collaboration
1220
+ * Supports multiplexing - multiple documents can share the same WebSocket connection
1221
+ */
1222
+ class HocuspocusSyncProvider {
1223
+ provider;
1224
+ isConnected = false;
1225
+ isSynced = false;
1226
+ usesSharedSocket = false;
1227
+ // Static shared WebSocket instance for multiplexing
1228
+ static sharedWebSocketProvider = null;
1229
+ constructor(docName, doc, options) {
1230
+ const name = options?.name || docName;
1231
+ const url = options?.url || 'ws://localhost:1234';
1232
+ // Use provided websocketProvider or the static shared one
1233
+ const websocketProvider = options?.websocketProvider || HocuspocusSyncProvider.sharedWebSocketProvider;
1234
+ if (websocketProvider) {
1235
+ // Multiplexing mode - use shared WebSocket connection
1236
+ this.usesSharedSocket = true;
1237
+ const config = {
1238
+ websocketProvider,
1239
+ name,
1240
+ document: doc,
1241
+ token: options?.token || null,
1242
+ onConnect: () => {
1243
+ this.isConnected = true;
1244
+ if (!options?.quiet) {
1245
+ console.info(`Hocuspocus connected: ${name}`);
1246
+ }
1247
+ if (options?.onConnect) {
1248
+ options.onConnect();
1249
+ }
1250
+ },
1251
+ onDisconnect: () => {
1252
+ this.isConnected = false;
1253
+ this.isSynced = false;
1254
+ if (!options?.quiet) {
1255
+ console.info(`Hocuspocus disconnected: ${name}`);
1256
+ }
1257
+ if (options?.onDisconnect) {
1258
+ options.onDisconnect();
1259
+ }
1260
+ },
1261
+ onSynced: () => {
1262
+ this.isSynced = true;
1263
+ if (!options?.quiet) {
1264
+ console.info(`Hocuspocus synced: ${name}`);
1265
+ }
1266
+ if (options?.onSynced) {
1267
+ options.onSynced();
1268
+ }
1269
+ },
1270
+ };
1271
+ // Add optional settings
1272
+ if (options?.forceSyncInterval !== undefined) {
1273
+ config.forceSyncInterval = options.forceSyncInterval;
1274
+ }
1275
+ if (options?.onAuthenticationFailed) {
1276
+ config.onAuthenticationFailed = options.onAuthenticationFailed;
1277
+ }
1278
+ if (options?.onStatus) {
1279
+ config.onStatus = options.onStatus;
1280
+ }
1281
+ this.provider = new defaultTextTool_config.HocuspocusProvider(config);
1282
+ // Must call attach() explicitly when using shared socket
1283
+ this.provider.attach();
1284
+ if (!options?.quiet) {
1285
+ console.info(`Hocuspocus Provider initialized (multiplexed): ${name}`);
1286
+ }
1287
+ }
1288
+ else {
1289
+ // Standalone mode - create own WebSocket connection
1290
+ this.usesSharedSocket = false;
1291
+ const config = {
1292
+ url,
1293
+ name,
1294
+ document: doc,
1295
+ token: options?.token || null,
1296
+ onConnect: () => {
1297
+ this.isConnected = true;
1298
+ if (!options?.quiet) {
1299
+ console.info(`Hocuspocus connected: ${name}`);
1300
+ }
1301
+ if (options?.onConnect) {
1302
+ options.onConnect();
1303
+ }
1304
+ },
1305
+ onDisconnect: () => {
1306
+ this.isConnected = false;
1307
+ this.isSynced = false;
1308
+ if (!options?.quiet) {
1309
+ console.info(`Hocuspocus disconnected: ${name}`);
1310
+ }
1311
+ if (options?.onDisconnect) {
1312
+ options.onDisconnect();
1313
+ }
1314
+ },
1315
+ onSynced: () => {
1316
+ this.isSynced = true;
1317
+ if (!options?.quiet) {
1318
+ console.info(`Hocuspocus synced: ${name}`);
1319
+ }
1320
+ if (options?.onSynced) {
1321
+ options.onSynced();
1322
+ }
1323
+ },
1324
+ };
1325
+ // Add optional settings
1326
+ if (options?.forceSyncInterval !== undefined) {
1327
+ config.forceSyncInterval = options.forceSyncInterval;
1328
+ }
1329
+ if (options?.onAuthenticationFailed) {
1330
+ config.onAuthenticationFailed = options.onAuthenticationFailed;
1331
+ }
1332
+ if (options?.onStatus) {
1333
+ config.onStatus = options.onStatus;
1334
+ }
1335
+ if (options?.WebSocketPolyfill) {
1336
+ config.WebSocketPolyfill = options.WebSocketPolyfill;
1337
+ }
1338
+ this.provider = new defaultTextTool_config.HocuspocusProvider(config);
1339
+ if (!options?.quiet) {
1340
+ console.info(`Hocuspocus Provider initialized: ${url}/${name}`);
1341
+ }
1342
+ }
1343
+ }
1344
+ /**
1345
+ * Create a shared WebSocket connection for multiplexing
1346
+ * Call this once to create a shared connection that multiple providers can use
1347
+ */
1348
+ static createSharedWebSocket(options) {
1349
+ if (HocuspocusSyncProvider.sharedWebSocketProvider) {
1350
+ console.warn('Shared WebSocket already exists. Returning existing instance.');
1351
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
1352
+ }
1353
+ const config = {
1354
+ url: options.url,
1355
+ };
1356
+ if (options.WebSocketPolyfill) {
1357
+ config.WebSocketPolyfill = options.WebSocketPolyfill;
1358
+ }
1359
+ if (options.onConnect) {
1360
+ config.onConnect = options.onConnect;
1361
+ }
1362
+ if (options.onDisconnect) {
1363
+ config.onDisconnect = options.onDisconnect;
1364
+ }
1365
+ if (options.onStatus) {
1366
+ config.onStatus = options.onStatus;
1367
+ }
1368
+ HocuspocusSyncProvider.sharedWebSocketProvider = new defaultTextTool_config.HocuspocusProviderWebsocket(config);
1369
+ console.info(`Shared Hocuspocus WebSocket created: ${options.url}`);
1370
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
1371
+ }
1372
+ /**
1373
+ * Destroy the shared WebSocket connection
1374
+ * Call this when you're done with all multiplexed providers
1375
+ */
1376
+ static destroySharedWebSocket() {
1377
+ if (HocuspocusSyncProvider.sharedWebSocketProvider) {
1378
+ HocuspocusSyncProvider.sharedWebSocketProvider.destroy();
1379
+ HocuspocusSyncProvider.sharedWebSocketProvider = null;
1380
+ console.info('Shared Hocuspocus WebSocket destroyed');
1381
+ }
1382
+ }
1383
+ /**
1384
+ * Get the shared WebSocket provider instance (if it exists)
1385
+ */
1386
+ static getSharedWebSocket() {
1387
+ return HocuspocusSyncProvider.sharedWebSocketProvider;
1388
+ }
1389
+ /**
1390
+ * Static factory method for creating HocuspocusSyncProvider with configuration options
1391
+ * Returns a ProviderFactory that can be used in sync configuration
1392
+ */
1393
+ static with(options) {
1394
+ return {
1395
+ create: (docName, doc) => {
1396
+ return new HocuspocusSyncProvider(docName, doc, options);
1397
+ },
1398
+ };
1399
+ }
1400
+ async connect() {
1401
+ if (this.isSynced) {
1402
+ return;
1403
+ }
1404
+ return new Promise((resolve, reject) => {
1405
+ const timeout = setTimeout(() => {
1406
+ reject(new Error('Hocuspocus connection timeout'));
1407
+ }, 10000); // 10 second timeout
1408
+ const syncHandler = () => {
1409
+ clearTimeout(timeout);
1410
+ this.provider.off('synced', syncHandler);
1411
+ resolve();
1412
+ };
1413
+ this.provider.on('synced', syncHandler);
1414
+ // If already synced, resolve immediately
1415
+ if (this.provider.isSynced) {
1416
+ clearTimeout(timeout);
1417
+ this.provider.off('synced', syncHandler);
1418
+ resolve();
1419
+ return;
1420
+ }
1421
+ // Connect if not already connected (standalone mode only)
1422
+ if (!this.isConnected && !this.usesSharedSocket) {
1423
+ this.provider.connect();
1424
+ }
1425
+ });
1426
+ }
1427
+ disconnect() {
1428
+ if (this.provider) {
1429
+ if (this.usesSharedSocket) {
1430
+ // Detach from shared socket instead of disconnecting
1431
+ this.provider.detach();
1432
+ }
1433
+ else {
1434
+ this.provider.disconnect();
1435
+ }
1436
+ }
1437
+ this.isConnected = false;
1438
+ this.isSynced = false;
1439
+ }
1440
+ destroy() {
1441
+ if (this.provider) {
1442
+ this.provider.destroy();
1443
+ }
1444
+ this.isConnected = false;
1445
+ this.isSynced = false;
1446
+ }
1447
+ }
1448
+
1449
+ exports.DEFAULT_BRUSH_CONFIG = defaultTextTool_config.DEFAULT_BRUSH_CONFIG;
1450
+ exports.DEFAULT_TEXT_CONFIG = defaultTextTool_config.DEFAULT_TEXT_CONFIG;
1451
+ exports.IndexedDBSyncProvider = defaultTextTool_config.IndexedDBSyncProvider;
1452
+ exports.KritzelAppStateMap = defaultTextTool_config.KritzelAppStateMap;
1453
+ exports.KritzelBrushTool = defaultTextTool_config.KritzelBrushTool;
1454
+ exports.KritzelEraserTool = defaultTextTool_config.KritzelEraserTool;
1455
+ exports.KritzelImage = defaultTextTool_config.KritzelImage;
1456
+ exports.KritzelImageTool = defaultTextTool_config.KritzelImageTool;
1457
+ exports.KritzelPath = defaultTextTool_config.KritzelPath;
1458
+ exports.KritzelSelectionTool = defaultTextTool_config.KritzelSelectionTool;
1459
+ exports.KritzelText = defaultTextTool_config.KritzelText;
1460
+ exports.KritzelTextTool = defaultTextTool_config.KritzelTextTool;
1461
+ exports.KritzelWorkspace = defaultTextTool_config.KritzelWorkspace;
1462
+ exports.BroadcastSyncProvider = BroadcastSyncProvider;
1463
+ exports.HocuspocusSyncProvider = HocuspocusSyncProvider;
1464
+ exports.WebSocketSyncProvider = WebSocketSyncProvider;
1465
+ //# sourceMappingURL=index.cjs.js.map