kritzel-stencil 0.0.156 → 0.0.158

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