kritzel-stencil 0.4.3 → 0.4.5

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 (117) hide show
  1. package/dist/cjs/kritzel-active-users_47.cjs.entry.js +1 -1
  2. package/dist/collection/constants/version.js +1 -1
  3. package/dist/components/index.js +1226 -1
  4. package/dist/components/kritzel-active-users.js +6 -1
  5. package/dist/components/kritzel-avatar.js +6 -1
  6. package/dist/components/kritzel-awareness-cursors.js +6 -1
  7. package/dist/components/kritzel-back-to-content.js +6 -1
  8. package/dist/components/kritzel-brush-style.js +64 -1
  9. package/dist/components/kritzel-button.js +6 -1
  10. package/dist/components/kritzel-color-palette.js +6 -1
  11. package/dist/components/kritzel-color.js +6 -1
  12. package/dist/components/kritzel-context-menu.js +6 -1
  13. package/dist/components/kritzel-controls.js +6 -1
  14. package/dist/components/kritzel-current-user-dialog.js +6 -1
  15. package/dist/components/kritzel-current-user.js +6 -1
  16. package/dist/components/kritzel-cursor-trail.js +6 -1
  17. package/dist/components/kritzel-dialog.js +6 -1
  18. package/dist/components/kritzel-dropdown.js +6 -1
  19. package/dist/components/kritzel-editor.js +4396 -1
  20. package/dist/components/kritzel-engine.js +6 -1
  21. package/dist/components/kritzel-export.js +6 -1
  22. package/dist/components/kritzel-font-family.js +6 -1
  23. package/dist/components/kritzel-font-size.js +6 -1
  24. package/dist/components/kritzel-font.js +6 -1
  25. package/dist/components/kritzel-icon.js +6 -1
  26. package/dist/components/kritzel-input.js +6 -1
  27. package/dist/components/kritzel-line-endings.js +6 -1
  28. package/dist/components/kritzel-loading-overlay.js +6 -1
  29. package/dist/components/kritzel-login-dialog.js +6 -1
  30. package/dist/components/kritzel-master-detail.js +6 -1
  31. package/dist/components/kritzel-menu-item.js +6 -1
  32. package/dist/components/kritzel-menu.js +6 -1
  33. package/dist/components/kritzel-more-menu.js +6 -1
  34. package/dist/components/kritzel-notification-card.js +6 -1
  35. package/dist/components/kritzel-numeric-input.js +6 -1
  36. package/dist/components/kritzel-opacity-slider.js +6 -1
  37. package/dist/components/kritzel-pill-tabs.js +6 -1
  38. package/dist/components/kritzel-portal.js +6 -1
  39. package/dist/components/kritzel-settings.js +6 -1
  40. package/dist/components/kritzel-shape-fill.js +6 -1
  41. package/dist/components/kritzel-share-dialog.js +6 -1
  42. package/dist/components/kritzel-slide-toggle.js +6 -1
  43. package/dist/components/kritzel-split-button.js +6 -1
  44. package/dist/components/kritzel-stroke-size.js +6 -1
  45. package/dist/components/kritzel-sync-indicator.js +6 -1
  46. package/dist/components/kritzel-tool-config.js +6 -1
  47. package/dist/components/kritzel-tooltip.js +6 -1
  48. package/dist/components/kritzel-utility-panel.js +6 -1
  49. package/dist/components/kritzel-watermark.js +6 -1
  50. package/dist/components/kritzel-workspace-manager.js +6 -1
  51. package/dist/components/kritzel-zoom-panel.js +6 -1
  52. package/dist/components/p--Oazz-BP.js +51657 -2
  53. package/dist/components/p-894OnDQV.js +39 -1
  54. package/dist/components/p-B43upypT.js +1500 -1
  55. package/dist/components/p-B5oHmPJb.js +97 -1
  56. package/dist/components/p-B6t5q-V4.js +63 -1
  57. package/dist/components/p-B8Xi4Clg.js +43 -1
  58. package/dist/components/p-BDzlx2hB.js +135 -1
  59. package/dist/components/p-BFTU3MAI.js +7 -1
  60. package/dist/components/p-BFYtCsZu.js +56 -1
  61. package/dist/components/p-BI2ng9I_.js +62 -1
  62. package/dist/components/p-BTzlrIxe.js +194 -1
  63. package/dist/components/p-BmyTdQGy.js +1090 -1
  64. package/dist/components/p-BsANVili.js +150 -1
  65. package/dist/components/p-BxpKq94F.js +290 -1
  66. package/dist/components/p-C38P-Vd0.js +446 -1
  67. package/dist/components/p-C4NrrUfN.js +77 -1
  68. package/dist/components/p-CW-VyJgK.js +6 -1
  69. package/dist/components/p-CWRSGYOE.js +57 -1
  70. package/dist/components/p-CXpv9Rxe.js +106 -1
  71. package/dist/components/p-Ca-igU1f.js +320 -1
  72. package/dist/components/p-CdR76C4L.js +165 -1
  73. package/dist/components/p-ClFprFvz.js +209 -1
  74. package/dist/components/p-Cm33td2O.js +122 -1
  75. package/dist/components/p-CqLgB8JK.js +91 -1
  76. package/dist/components/p-Cr682JI_.js +156 -1
  77. package/dist/components/p-CsvMgk_f.js +62 -1
  78. package/dist/components/p-CwJwsRR3.js +277 -1
  79. package/dist/components/p-Cymum41a.js +88 -1
  80. package/dist/components/p-D09kgc5Q.js +94 -1
  81. package/dist/components/p-D30zs0kA.js +121 -1
  82. package/dist/components/p-D3y_Hauo.js +85 -1
  83. package/dist/components/p-D5jf8wAu.js +142 -1
  84. package/dist/components/p-D82VaHce.js +53 -1
  85. package/dist/components/p-DAwPPDMS.js +101 -1
  86. package/dist/components/p-DEBwmRTC.js +55 -1
  87. package/dist/components/p-DIazmg6w.js +52 -1
  88. package/dist/components/p-DJ88BrIW.js +70 -1
  89. package/dist/components/p-DJkKlUyZ.js +182 -1
  90. package/dist/components/p-DUYmwrWV.js +3267 -1
  91. package/dist/components/p-DX2nriaq.js +486 -1
  92. package/dist/components/p-Dd-pMvlr.js +20 -1
  93. package/dist/components/p-Df3BwVGy.js +299 -1
  94. package/dist/components/p-DgJ0ufzr.js +43 -1
  95. package/dist/components/p-DkUb2czk.js +70 -1
  96. package/dist/components/p-Dlp84thc.js +57 -1
  97. package/dist/components/p-JYj3Facr.js +431 -1
  98. package/dist/components/p-Ka7OWbnk.js +2304 -1
  99. package/dist/components/p-PSFAfAyd.js +49 -1
  100. package/dist/components/p-U6uE85Qx.js +320 -0
  101. package/dist/components/p-WUdQqYnu.js +118 -1
  102. package/dist/components/p-djJSnjAX.js +84 -1
  103. package/dist/components/p-e6Zpc9Vp.js +143 -1
  104. package/dist/components/p-jGOpkGDl.js +30 -1
  105. package/dist/components/p-pagW8YF7.js +99 -1
  106. package/dist/esm/kritzel-active-users_47.entry.js +1 -1
  107. package/dist/stencil/index.esm.js +1172 -1
  108. package/dist/stencil/p-4463dade.entry.js +36043 -0
  109. package/dist/stencil/p-DQuL1Twl.js +3 -1
  110. package/dist/stencil/p-Dhio9uis.js +1717 -2
  111. package/dist/stencil/p-fb32cd8f.entry.js +29 -1
  112. package/dist/stencil/p-uC7_X6yr.js +30737 -1
  113. package/dist/stencil/stencil.esm.js +21 -1
  114. package/dist/types/constants/version.d.ts +1 -1
  115. package/package.json +1 -1
  116. package/dist/components/p-DPhYXJsM.js +0 -1
  117. package/dist/stencil/p-43a8dcf8.entry.js +0 -9
@@ -1 +1,4396 @@
1
- import{p as t,H as e,c as s,h as i,d as n,t as o}from"./p-B43upypT.js";import{K as r,d as a}from"./p-CdR76C4L.js";import{v as c,w as h,S as l,m as d,f as u,h as p,g as m,k as g,j as f,i as b,s as y,x as k,y as w,z as v,B as z,C}from"./p--Oazz-BP.js";import{D as j,T as A,d as x,l as T}from"./p-BmyTdQGy.js";import{D as S,r as E,K as O}from"./p-DJkKlUyZ.js";import{A as I,a as D,d as M}from"./p-PSFAfAyd.js";import{K as U}from"./p-jGOpkGDl.js";import{O as R}from"./p-Dd-pMvlr.js";import{d as B}from"./p-Ka7OWbnk.js";import*as P from"yjs";import"y-indexeddb";import"y-websocket";import{d as W}from"./p-DJ88BrIW.js";import{d as V}from"./p-D5jf8wAu.js";import{d as F}from"./p-Dlp84thc.js";import{d as L}from"./p-DEBwmRTC.js";import{d as N}from"./p-CqLgB8JK.js";import{d as J}from"./p-Cymum41a.js";import{d as H}from"./p-BxpKq94F.js";import{d as K}from"./p-JYj3Facr.js";import{d as Y}from"./p-DIazmg6w.js";import{d as Z}from"./p-D3y_Hauo.js";import{d as q}from"./p-Cm33td2O.js";import{d as $}from"./p-DX2nriaq.js";import{d as _}from"./p-Df3BwVGy.js";import{d as G}from"./p-e6Zpc9Vp.js";import{d as Q}from"./p-B8Xi4Clg.js";import{d as X}from"./p-djJSnjAX.js";import{d as tt}from"./p-BI2ng9I_.js";import{d as et}from"./p-C4NrrUfN.js";import{d as st}from"./p-CXpv9Rxe.js";import{d as it}from"./p-DgJ0ufzr.js";import{d as nt}from"./p-B5oHmPJb.js";import{d as ot}from"./p-BsANVili.js";import{d as rt,a as at}from"./p-CwJwsRR3.js";import{d as ct}from"./p-D30zs0kA.js";import{d as ht}from"./p-pagW8YF7.js";import{d as lt}from"./p-BDzlx2hB.js";import{d as dt}from"./p-B6t5q-V4.js";import{d as ut}from"./p-D09kgc5Q.js";import{d as pt}from"./p-Ca-igU1f.js";import{d as mt}from"./p-DPhYXJsM.js";import{d as gt}from"./p-BFYtCsZu.js";import{d as ft}from"./p-DUYmwrWV.js";import{d as bt}from"./p-CWRSGYOE.js";import{d as yt}from"./p-Cr682JI_.js";import{d as kt}from"./p-D82VaHce.js";import{d as wt}from"./p-894OnDQV.js";import{d as vt}from"./p-C38P-Vd0.js";import{d as zt}from"./p-BTzlrIxe.js";import{d as Ct}from"./p-CsvMgk_f.js";import{d as jt}from"./p-ClFprFvz.js";import{d as At}from"./p-DkUb2czk.js";const xt=Math.floor,Tt=127,St=Number.MAX_SAFE_INTEGER,Et="undefined"!=typeof TextEncoder?new TextEncoder:null,Ot=Et?t=>Et.encode(t):t=>{const e=unescape(encodeURIComponent(t)),s=e.length,i=new Uint8Array(s);for(let t=0;t<s;t++)i[t]=e.codePointAt(t);return i};let It="undefined"==typeof TextDecoder?null:new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0});It&&1===It.decode(new Uint8Array).length&&(It=null);const Dt=(t,e)=>{const s=t.cbuf.length;t.cpos===s&&(t.bufs.push(t.cbuf),t.cbuf=new Uint8Array(2*s),t.cpos=0),t.cbuf[t.cpos++]=e},Mt=(t,e)=>{for(;e>Tt;)Dt(t,128|Tt&e),e=xt(e/128);Dt(t,Tt&e)},Ut=new Uint8Array(3e4),Rt=Ut.length/3,Bt=Et&&Et.encodeInto?(t,e)=>{if(e.length<Rt){const s=Et.encodeInto(e,Ut).written||0;Mt(t,s);for(let e=0;e<s;e++)Dt(t,Ut[e])}else Pt(t,Ot(e))}:(t,e)=>{const s=unescape(encodeURIComponent(e)),i=s.length;Mt(t,i);for(let e=0;e<i;e++)Dt(t,s.codePointAt(e))},Pt=(t,e)=>{Mt(t,e.byteLength),((t,e)=>{const s=t.cbuf.length,i=t.cpos,n=((t,e)=>t<e?t:e)(s-i,e.length),o=e.length-n;t.cbuf.set(e.subarray(0,n),i),t.cpos+=n,o>0&&(t.bufs.push(t.cbuf),t.cbuf=new Uint8Array(((t,e)=>t>e?t:e)(2*s,o)),t.cbuf.set(e.subarray(n)),t.cpos=o)})(t,e)},Wt=t=>Error(t),Vt=Wt("Unexpected end of array"),Ft=Wt("Integer out of Range"),Lt=t=>t.arr[t.pos++],Nt=t=>{let e=0,s=1;const i=t.arr.length;for(;t.pos<i;){const i=t.arr[t.pos++];if(e+=(i&Tt)*s,s*=128,i<128)return e;if(e>St)throw Ft}throw Vt},Jt=It?t=>It.decode((t=>((t,e)=>{const s=new Uint8Array(t.arr.buffer,t.pos+t.arr.byteOffset,e);return t.pos+=e,s})(t,Nt(t)))(t)):t=>{let e=Nt(t);if(0===e)return"";{let s=String.fromCodePoint(Lt(t));if(--e<100)for(;e--;)s+=String.fromCodePoint(Lt(t));else for(;e>0;){const i=e<1e4?e:1e4,n=t.arr.subarray(t.pos,t.pos+i);t.pos+=i,s+=String.fromCodePoint.apply(null,n),e-=i}return decodeURIComponent(escape(s))}};var Ht;!function(t){t[t.Token=0]="Token",t[t.PermissionDenied=1]="PermissionDenied",t[t.Authenticated=2]="Authenticated"}(Ht||(Ht={}));const Kt=t=>Array.from(t.entries()).map((([t,e])=>({clientId:t,...e})));var Yt;async function Zt(t){return new Promise((e=>setTimeout(e,t)))}function qt(t,e){let s=e.delay;if(0===s)return 0;if(e.factor&&(s*=Math.pow(e.factor,t.attemptNum-1),0!==e.maxDelay&&(s=Math.min(s,e.maxDelay))),e.jitter){const t=Math.ceil(e.minDelay),i=Math.floor(s);s=Math.floor(Math.random()*(i-t+1))+t}return Math.round(s)}!function(t){t[t.Connecting=0]="Connecting",t[t.Open=1]="Open",t[t.Closing=2]="Closing",t[t.Closed=3]="Closed"}(Yt||(Yt={}));const $t=Math.floor,_t=128,Gt=127,Qt=Number.MAX_SAFE_INTEGER,Xt=()=>new Set,te=Array.from,ee="undefined"!=typeof TextEncoder?new TextEncoder:null,se=ee?t=>ee.encode(t):t=>{const e=unescape(encodeURIComponent(t)),s=e.length,i=new Uint8Array(s);for(let t=0;t<s;t++)i[t]=e.codePointAt(t);return i};let ie="undefined"==typeof TextDecoder?null:new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0});ie&&1===ie.decode(new Uint8Array).length&&(ie=null);class ne{constructor(){this.cpos=0,this.cbuf=new Uint8Array(100),this.bufs=[]}}const oe=()=>new ne,re=t=>{let e=t.cpos;for(let s=0;s<t.bufs.length;s++)e+=t.bufs[s].length;return e},ae=t=>{const e=new Uint8Array(re(t));let s=0;for(let i=0;i<t.bufs.length;i++){const n=t.bufs[i];e.set(n,s),s+=n.length}return e.set(new Uint8Array(t.cbuf.buffer,0,t.cpos),s),e},ce=(t,e)=>{const s=t.cbuf.length;t.cpos===s&&(t.bufs.push(t.cbuf),t.cbuf=new Uint8Array(2*s),t.cpos=0),t.cbuf[t.cpos++]=e},he=(t,e)=>{for(;e>Gt;)ce(t,_t|Gt&e),e=$t(e/128);ce(t,Gt&e)},le=new Uint8Array(3e4),de=le.length/3,ue=ee&&ee.encodeInto?(t,e)=>{if(e.length<de){const s=ee.encodeInto(e,le).written||0;he(t,s);for(let e=0;e<s;e++)ce(t,le[e])}else pe(t,se(e))}:(t,e)=>{const s=unescape(encodeURIComponent(e)),i=s.length;he(t,i);for(let e=0;e<i;e++)ce(t,s.codePointAt(e))},pe=(t,e)=>{he(t,e.byteLength),((t,e)=>{const s=t.cbuf.length,i=t.cpos,n=((t,e)=>t<e?t:e)(s-i,e.length),o=e.length-n;t.cbuf.set(e.subarray(0,n),i),t.cpos+=n,o>0&&(t.bufs.push(t.cbuf),t.cbuf=new Uint8Array(((t,e)=>t>e?t:e)(2*s,o)),t.cbuf.set(e.subarray(n)),t.cpos=o)})(t,e)},me=t=>Error(t),ge=me("Unexpected end of array"),fe=me("Integer out of Range");class be{constructor(t){this.arr=t,this.pos=0}}const ye=t=>new be(t),ke=t=>((t,e)=>{const s=new Uint8Array(t.arr.buffer,t.pos+t.arr.byteOffset,e);return t.pos+=e,s})(t,ve(t)),we=t=>t.arr[t.pos++],ve=t=>{let e=0,s=1;const i=t.arr.length;for(;t.pos<i;){const i=t.arr[t.pos++];if(e+=(i&Gt)*s,s*=128,i<_t)return e;if(e>Qt)throw fe}throw ge},ze=ie?t=>ie.decode(ke(t)):t=>{let e=ve(t);if(0===e)return"";{let s=String.fromCodePoint(we(t));if(--e<100)for(;e--;)s+=String.fromCodePoint(we(t));else for(;e>0;){const i=e<1e4?e:1e4,n=t.arr.subarray(t.pos,t.pos+i);t.pos+=i,s+=String.fromCodePoint.apply(null,n),e-=i}return decodeURIComponent(escape(s))}},Ce=Date.now,je=()=>new Map;class Ae{constructor(){this._observers=je()}on(t,e){((t,e,s)=>{let i=t.get(e);return void 0===i&&t.set(e,i=s()),i})(this._observers,t,Xt).add(e)}once(t,e){const s=(...i)=>{this.off(t,s),e(...i)};this.on(t,s)}off(t,e){const s=this._observers.get(t);void 0!==s&&(s.delete(e),0===s.size&&this._observers.delete(t))}emit(t,e){return te((this._observers.get(t)||je()).values()).forEach((t=>t(...e)))}destroy(){this._observers=je()}}const xe=Object.keys,Te=t=>xe(t).length,Se=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),Ee=(t,e)=>{if(null==t||null==e)return((t,e)=>t===e)(t,e);if(t.constructor!==e.constructor)return!1;if(t===e)return!0;switch(t.constructor){case ArrayBuffer:t=new Uint8Array(t),e=new Uint8Array(e);case Uint8Array:if(t.byteLength!==e.byteLength)return!1;for(let s=0;s<t.length;s++)if(t[s]!==e[s])return!1;break;case Set:if(t.size!==e.size)return!1;for(const s of t)if(!e.has(s))return!1;break;case Map:if(t.size!==e.size)return!1;for(const s of t.keys())if(!e.has(s)||!Ee(t.get(s),e.get(s)))return!1;break;case Object:if(Te(t)!==Te(e))return!1;for(const s in t)if(!Se(t,s)||!Ee(t[s],e[s]))return!1;break;case Array:if(t.length!==e.length)return!1;for(let s=0;s<t.length;s++)if(!Ee(t[s],e[s]))return!1;break;default:return!1}return!0};class Oe extends Ae{constructor(t){super(),this.doc=t,this.clientID=t.clientID,this.states=new Map,this.meta=new Map,this._checkInterval=setInterval((()=>{const t=Ce();null!==this.getLocalState()&&15e3<=t-this.meta.get(this.clientID).lastUpdated&&this.setLocalState(this.getLocalState());const e=[];this.meta.forEach(((s,i)=>{i!==this.clientID&&3e4<=t-s.lastUpdated&&this.states.has(i)&&e.push(i)})),e.length>0&&Ie(this,e,"timeout")}),$t(3e3)),t.on("destroy",(()=>{this.destroy()})),this.setLocalState({})}destroy(){this.emit("destroy",[this]),this.setLocalState(null),super.destroy(),clearInterval(this._checkInterval)}getLocalState(){return this.states.get(this.clientID)||null}setLocalState(t){const e=this.clientID,s=this.meta.get(e),i=void 0===s?0:s.clock+1,n=this.states.get(e);null===t?this.states.delete(e):this.states.set(e,t),this.meta.set(e,{clock:i,lastUpdated:Ce()});const o=[],r=[],a=[],c=[];null===t?c.push(e):null==n?null!=t&&o.push(e):(r.push(e),Ee(n,t)||a.push(e)),(o.length>0||a.length>0||c.length>0)&&this.emit("change",[{added:o,updated:a,removed:c},"local"]),this.emit("update",[{added:o,updated:r,removed:c},"local"])}setLocalStateField(t,e){const s=this.getLocalState();null!==s&&this.setLocalState({...s,[t]:e})}getStates(){return this.states}}const Ie=(t,e,s)=>{const i=[];for(let s=0;s<e.length;s++){const n=e[s];if(t.states.has(n)){if(t.states.delete(n),n===t.clientID){const e=t.meta.get(n);t.meta.set(n,{clock:e.clock+1,lastUpdated:Ce()})}i.push(n)}}i.length>0&&(t.emit("change",[{added:[],updated:[],removed:i},s]),t.emit("update",[{added:[],updated:[],removed:i},s]))},De=(t,e,s=t.states)=>{const i=e.length,n=oe();he(n,i);for(let o=0;o<i;o++){const i=e[o],r=s.get(i)||null,a=t.meta.get(i).clock;he(n,i),he(n,a),ue(n,JSON.stringify(r))}return ae(n)};class Me{constructor(){this.callbacks={}}on(t,e){return this.callbacks[t]||(this.callbacks[t]=[]),this.callbacks[t].push(e),this}emit(t,...e){const s=this.callbacks[t];return s&&s.forEach((t=>t.apply(this,e))),this}off(t,e){const s=this.callbacks[t];return s&&(e?this.callbacks[t]=s.filter((t=>t!==e)):delete this.callbacks[t]),this}removeAllListeners(){this.callbacks={}}}class Ue{constructor(t){this.data=t,this.encoder=oe(),this.decoder=ye(new Uint8Array(this.data))}peekVarString(){return(t=>{const e=t.pos,s=ze(t);return t.pos=e,s})(this.decoder)}readVarUint(){return ve(this.decoder)}readVarString(){return ze(this.decoder)}readVarUint8Array(){return ke(this.decoder)}writeVarUint(t){return he(this.encoder,t)}writeVarString(t){return ue(this.encoder,t)}writeVarUint8Array(t){return pe(this.encoder,t)}length(){return re(this.encoder)}}var Re,Be;!function(t){t[t.Sync=0]="Sync",t[t.Awareness=1]="Awareness",t[t.Auth=2]="Auth",t[t.QueryAwareness=3]="QueryAwareness",t[t.Stateless=5]="Stateless",t[t.CLOSE=7]="CLOSE",t[t.SyncStatus=8]="SyncStatus"}(Re||(Re={})),function(t){t.Connecting="connecting",t.Connected="connected",t.Disconnected="disconnected"}(Be||(Be={}));class Pe{constructor(){this.encoder=oe()}get(t){return t.encoder}toUint8Array(){return ae(this.encoder)}}class We extends Pe{constructor(){super(...arguments),this.type=Re.CLOSE,this.description="Ask the server to close the connection"}get(t){return ue(this.encoder,t.documentName),he(this.encoder,this.type),this.encoder}}class Ve extends Me{constructor(t){super(),this.messageQueue=[],this.configuration={url:"",autoConnect:!0,preserveTrailingSlash:!1,document:void 0,WebSocketPolyfill:void 0,messageReconnectTimeout:3e4,delay:1e3,initialDelay:0,factor:2,maxAttempts:0,minDelay:1e3,maxDelay:3e4,jitter:!0,timeout:0,onOpen:()=>null,onConnect:()=>null,onMessage:()=>null,onOutgoingMessage:()=>null,onStatus:()=>null,onDisconnect:()=>null,onClose:()=>null,onDestroy:()=>null,onAwarenessUpdate:()=>null,onAwarenessChange:()=>null,handleTimeout:null,providerMap:new Map},this.webSocket=null,this.webSocketHandlers={},this.shouldConnect=!0,this.status=Be.Disconnected,this.lastMessageReceived=0,this.identifier=0,this.intervals={connectionChecker:null},this.connectionAttempt=null,this.receivedOnOpenPayload=void 0,this.closeTries=0,this.setConfiguration(t),this.configuration.WebSocketPolyfill=t.WebSocketPolyfill?t.WebSocketPolyfill:WebSocket,this.on("open",this.configuration.onOpen),this.on("open",this.onOpen.bind(this)),this.on("connect",this.configuration.onConnect),this.on("message",this.configuration.onMessage),this.on("outgoingMessage",this.configuration.onOutgoingMessage),this.on("status",this.configuration.onStatus),this.on("disconnect",this.configuration.onDisconnect),this.on("close",this.configuration.onClose),this.on("destroy",this.configuration.onDestroy),this.on("awarenessUpdate",this.configuration.onAwarenessUpdate),this.on("awarenessChange",this.configuration.onAwarenessChange),this.on("close",this.onClose.bind(this)),this.on("message",this.onMessage.bind(this)),this.intervals.connectionChecker=setInterval(this.checkConnection.bind(this),this.configuration.messageReconnectTimeout/10),this.shouldConnect&&this.connect()}async onOpen(t){this.status=Be.Connected,this.emit("status",{status:Be.Connected}),this.cancelWebsocketRetry=void 0,this.receivedOnOpenPayload=t}attach(t){this.configuration.providerMap.set(t.configuration.name,t),this.status===Be.Disconnected&&this.shouldConnect&&this.connect(),this.receivedOnOpenPayload&&this.status===Be.Connected&&t.onOpen(this.receivedOnOpenPayload)}detach(t){this.configuration.providerMap.has(t.configuration.name)&&(t.send(We,{documentName:t.configuration.name}),this.configuration.providerMap.delete(t.configuration.name))}setConfiguration(t={}){this.configuration={...this.configuration,...t},this.configuration.autoConnect||(this.shouldConnect=!1)}async connect(){if(this.status===Be.Connected)return;this.cancelWebsocketRetry&&(this.cancelWebsocketRetry(),this.cancelWebsocketRetry=void 0),this.receivedOnOpenPayload=void 0,this.shouldConnect=!0;const{retryPromise:t,cancelFunc:e}=(()=>{let t=!1;return{retryPromise:async function(t,e){const s=function(t){return t||(t={}),{delay:void 0===t.delay?200:t.delay,initialDelay:void 0===t.initialDelay?0:t.initialDelay,minDelay:void 0===t.minDelay?0:t.minDelay,maxDelay:void 0===t.maxDelay?0:t.maxDelay,factor:void 0===t.factor?0:t.factor,maxAttempts:void 0===t.maxAttempts?3:t.maxAttempts,timeout:void 0===t.timeout?0:t.timeout,jitter:!0===t.jitter,initialJitter:!0===t.initialJitter,handleError:void 0===t.handleError?null:t.handleError,handleTimeout:void 0===t.handleTimeout?null:t.handleTimeout,beforeAttempt:void 0===t.beforeAttempt?null:t.beforeAttempt,calculateDelay:void 0===t.calculateDelay?null:t.calculateDelay}}(e);for(const t of["delay","initialDelay","minDelay","maxDelay","maxAttempts","timeout"]){const e=s[t];if(!Number.isInteger(e)||e<0)throw Error(`Value for ${t} must be an integer greater than or equal to 0`)}if(s.factor.constructor!==Number||s.factor<0)throw Error("Value for factor must be a number greater than or equal to 0");if(s.delay<s.minDelay)throw Error(`delay cannot be less than minDelay (delay: ${s.delay}, minDelay: ${s.minDelay}`);const i={attemptNum:0,attemptsRemaining:s.maxAttempts?s.maxAttempts:-1,aborted:!1,abort(){i.aborted=!0}},n=s.calculateDelay||qt,o=s.calculateDelay?s.calculateDelay(i,s):s.initialDelay;if(o&&await Zt(o),i.attemptNum<1&&s.initialJitter){const t=n(i,s);t&&await Zt(t)}return async function e(){if(s.beforeAttempt&&s.beforeAttempt(i,s),i.aborted){const t=Error("Attempt aborted");throw t.code="ATTEMPT_ABORTED",t}const o=async t=>{if(s.handleError&&await s.handleError(t,i,s),i.aborted||0===i.attemptsRemaining)throw t;i.attemptNum++;const o=n(i,s);return o&&await Zt(o),e()};return i.attemptsRemaining>0&&i.attemptsRemaining--,s.timeout?new Promise(((e,n)=>{const r=setTimeout((()=>{if(s.handleTimeout)try{e(s.handleTimeout(i,s))}catch(t){n(t)}else{const t=Error(`Retry timeout (attemptNum: ${i.attemptNum}, timeout: ${s.timeout})`);t.code="ATTEMPT_TIMEOUT",n(t)}}),s.timeout);t(i,s).then((t=>{clearTimeout(r),e(t)})).catch((t=>{clearTimeout(r),o(t).then(e).catch(n)}))})):t(i,s).catch(o)}()}(this.createWebSocketConnection.bind(this),{delay:this.configuration.delay,initialDelay:this.configuration.initialDelay,factor:this.configuration.factor,maxAttempts:this.configuration.maxAttempts,minDelay:this.configuration.minDelay,maxDelay:this.configuration.maxDelay,jitter:this.configuration.jitter,timeout:this.configuration.timeout,handleTimeout:this.configuration.handleTimeout,beforeAttempt:e=>{this.shouldConnect&&!t||e.abort()}}).catch((t=>{if(t&&"ATTEMPT_ABORTED"!==t.code)throw t})),cancelFunc:()=>{t=!0}}})();return this.cancelWebsocketRetry=e,t}attachWebSocketListeners(t,e){const{identifier:s}=t;this.webSocketHandlers[s]={message:t=>this.emit("message",t),close:t=>this.emit("close",{event:t}),open:t=>this.emit("open",t),error:t=>{e(t)}};const i=this.webSocketHandlers[t.identifier];Object.keys(i).forEach((e=>{t.addEventListener(e,i[e])}))}cleanupWebSocket(){if(!this.webSocket)return;const{identifier:t}=this.webSocket,e=this.webSocketHandlers[t];Object.keys(e).forEach((s=>{var i;null===(i=this.webSocket)||void 0===i||i.removeEventListener(s,e[s]),delete this.webSocketHandlers[t]})),this.webSocket.close(),this.webSocket=null}createWebSocketConnection(){return new Promise(((t,e)=>{this.webSocket&&(this.messageQueue=[],this.cleanupWebSocket()),this.lastMessageReceived=0,this.identifier+=1;const s=new this.configuration.WebSocketPolyfill(this.url);s.binaryType="arraybuffer",s.identifier=this.identifier,this.attachWebSocketListeners(s,e),this.webSocket=s,this.status=Be.Connecting,this.emit("status",{status:Be.Connecting}),this.connectionAttempt={resolve:t,reject:e}}))}onMessage(t){var e;this.resolveConnectionAttempt(),this.lastMessageReceived=Ce();const s=new Ue(t.data).peekVarString();null===(e=this.configuration.providerMap.get(s))||void 0===e||e.onMessage(t)}resolveConnectionAttempt(){this.connectionAttempt&&(this.connectionAttempt.resolve(),this.connectionAttempt=null,this.status=Be.Connected,this.emit("status",{status:Be.Connected}),this.emit("connect"),this.messageQueue.forEach((t=>this.send(t))),this.messageQueue=[])}stopConnectionAttempt(){this.connectionAttempt=null}rejectConnectionAttempt(){var t;null===(t=this.connectionAttempt)||void 0===t||t.reject(),this.connectionAttempt=null}checkConnection(){var t;this.status===Be.Connected&&this.lastMessageReceived&&(this.configuration.messageReconnectTimeout>=Ce()-this.lastMessageReceived||(this.closeTries+=1,this.closeTries>2?(this.onClose({event:{code:4408,reason:"forced"}}),this.closeTries=0):(null===(t=this.webSocket)||void 0===t||t.close(),this.messageQueue=[])))}get serverUrl(){if(this.configuration.preserveTrailingSlash)return this.configuration.url;let t=this.configuration.url;for(;"/"===t[t.length-1];)t=t.slice(0,t.length-1);return t}get url(){return this.serverUrl}disconnect(){if(this.shouldConnect=!1,null!==this.webSocket)try{this.webSocket.close(),this.messageQueue=[]}catch(t){console.error(t)}}send(t){var e;(null===(e=this.webSocket)||void 0===e?void 0:e.readyState)===Yt.Open?this.webSocket.send(t):this.messageQueue.push(t)}onClose({event:t}){this.closeTries=0,this.cleanupWebSocket(),this.connectionAttempt&&this.rejectConnectionAttempt(),this.status=Be.Disconnected,this.emit("status",{status:Be.Disconnected}),this.emit("disconnect",{event:t}),!this.cancelWebsocketRetry&&this.shouldConnect&&setTimeout((()=>{this.connect()}),this.configuration.delay)}destroy(){this.emit("destroy"),clearInterval(this.intervals.connectionChecker),this.stopConnectionAttempt(),this.disconnect(),this.removeAllListeners(),this.cleanupWebSocket()}}const Fe=(t,e,s)=>{try{P.applyUpdate(e,ke(t),s)}catch(t){console.error("Caught error while handling a Yjs update",t)}},Le=Fe;class Ne{constructor(t){this.message=t}apply(t,e){const{message:s}=this,i=s.readVarUint(),n=s.length();switch(i){case Re.Sync:this.applySyncMessage(t,e);break;case Re.Awareness:this.applyAwarenessMessage(t);break;case Re.Auth:this.applyAuthMessage(t);break;case Re.QueryAwareness:this.applyQueryAwarenessMessage(t);break;case Re.Stateless:t.receiveStateless(ze(s.decoder));break;case Re.SyncStatus:this.applySyncStatusMessage(t,1===(t=>{let e=t.arr[t.pos++],s=63&e,i=64;const n=(64&e)>0?-1:1;if(!(e&_t))return n*s;const o=t.arr.length;for(;t.pos<o;){if(e=t.arr[t.pos++],s+=(e&Gt)*i,i*=128,e<_t)return n*s;if(s>Qt)throw fe}throw ge})(s.decoder));break;case Re.CLOSE:const n={code:1e3,reason:ze(s.decoder),target:t.configuration.websocketProvider.webSocket,type:"close"};t.onClose(),t.configuration.onClose({event:n}),t.forwardClose({event:n});break;default:throw Error("Can’t apply message of unknown type: "+i)}s.length()>n+1&&t.send(Pe,{encoder:s.encoder})}applySyncMessage(t,e){const{message:s}=this;s.writeVarUint(Re.Sync);const i=((t,e,s,i)=>{const n=ve(t);switch(n){case 0:((t,e,s)=>{((t,e,s)=>{he(t,1),pe(t,P.encodeStateAsUpdate(e,s))})(e,s,ke(t))})(t,e,s);break;case 1:Fe(t,s,i);break;case 2:Le(t,s,i);break;default:throw Error("Unknown message type")}return n})(s.decoder,s.encoder,t.document,t);e&&1===i&&(t.synced=!0)}applySyncStatusMessage(t,e){e&&t.decrementUnsyncedChanges()}applyAwarenessMessage(t){if(!t.awareness)return;const{message:e}=this;((t,e,s)=>{const i=ye(e),n=Ce(),o=[],r=[],a=[],c=[],h=ve(i);for(let e=0;e<h;e++){const e=ve(i);let s=ve(i);const h=JSON.parse(ze(i)),l=t.meta.get(e),d=t.states.get(e),u=void 0===l?0:l.clock;(u<s||u===s&&null===h&&t.states.has(e))&&(null===h?e===t.clientID&&null!=t.getLocalState()?s++:t.states.delete(e):t.states.set(e,h),t.meta.set(e,{clock:s,lastUpdated:n}),void 0===l&&null!==h?o.push(e):void 0!==l&&null===h?c.push(e):null!==h&&(Ee(h,d)||a.push(e),r.push(e)))}(o.length>0||a.length>0||c.length>0)&&t.emit("change",[{added:o,updated:a,removed:c},s]),(o.length>0||r.length>0||c.length>0)&&t.emit("update",[{added:o,updated:r,removed:c},s])})(t.awareness,e.readVarUint8Array(),t)}applyAuthMessage(t){const{message:e}=this;((t,e,s,i)=>{switch(Nt(t)){case Ht.Token:e();break;case Ht.PermissionDenied:s(Jt(t));break;case Ht.Authenticated:i(Jt(t))}})(e.decoder,t.sendToken.bind(t),t.permissionDeniedHandler.bind(t),t.authenticatedHandler.bind(t))}applyQueryAwarenessMessage(t){if(!t.awareness)return;const{message:e}=this;e.writeVarUint(Re.Awareness),e.writeVarUint8Array(De(t.awareness,Array.from(t.awareness.getStates().keys())))}}class Je{constructor(t,e={}){this.message=new t,this.encoder=this.message.get(e)}create(){return ae(this.encoder)}send(t){null==t||t.send(this.create())}}class He extends Pe{constructor(){super(...arguments),this.type=Re.Auth,this.description="Authentication"}get(t){if(void 0===t.token)throw Error("The authentication message requires `token` as an argument.");return ue(this.encoder,t.documentName),he(this.encoder,this.type),((t,e)=>{Mt(t,Ht.Token),Bt(t,e)})(this.encoder,t.token),this.encoder}}class Ke extends Pe{constructor(){super(...arguments),this.type=Re.Awareness,this.description="Awareness states update"}get(t){if(void 0===t.awareness)throw Error("The awareness message requires awareness as an argument");if(void 0===t.clients)throw Error("The awareness message requires clients as an argument");let e;return ue(this.encoder,t.documentName),he(this.encoder,this.type),e=void 0===t.states?De(t.awareness,t.clients):De(t.awareness,t.clients,t.states),pe(this.encoder,e),this.encoder}}class Ye extends Pe{constructor(){super(...arguments),this.type=Re.Stateless,this.description="A stateless message"}get(t){var e;return ue(this.encoder,t.documentName),he(this.encoder,this.type),ue(this.encoder,null!==(e=t.payload)&&void 0!==e?e:""),this.encoder}}class Ze extends Pe{constructor(){super(...arguments),this.type=Re.Sync,this.description="First sync step"}get(t){if(void 0===t.document)throw Error("The sync step one message requires document as an argument");return ue(this.encoder,t.documentName),he(this.encoder,this.type),((t,e)=>{he(t,0);const s=P.encodeStateVector(e);pe(t,s)})(this.encoder,t.document),this.encoder}}class qe extends Pe{constructor(){super(...arguments),this.type=Re.Sync,this.description="A document update"}get(t){return ue(this.encoder,t.documentName),he(this.encoder,this.type),((t,e)=>{he(t,2),pe(t,e)})(this.encoder,t.update),this.encoder}}class $e extends Error{constructor(){super(...arguments),this.code=1001}}class _e extends Me{constructor(t){var e,s,i;super(),this.configuration={name:"",document:void 0,awareness:void 0,token:null,forceSyncInterval:!1,onAuthenticated:()=>null,onAuthenticationFailed:()=>null,onOpen:()=>null,onConnect:()=>null,onMessage:()=>null,onOutgoingMessage:()=>null,onSynced:()=>null,onStatus:()=>null,onDisconnect:()=>null,onClose:()=>null,onDestroy:()=>null,onAwarenessUpdate:()=>null,onAwarenessChange:()=>null,onStateless:()=>null,onUnsyncedChanges:()=>null},this.isSynced=!1,this.unsyncedChanges=0,this.isAuthenticated=!1,this.authorizedScope=void 0,this.manageSocket=!1,this._isAttached=!1,this.intervals={forceSync:null},this.boundDocumentUpdateHandler=this.documentUpdateHandler.bind(this),this.boundAwarenessUpdateHandler=this.awarenessUpdateHandler.bind(this),this.boundPageHide=this.pageHide.bind(this),this.boundOnOpen=this.onOpen.bind(this),this.boundOnClose=this.onClose.bind(this),this.forwardConnect=()=>this.emit("connect"),this.forwardStatus=t=>this.emit("status",t),this.forwardClose=t=>this.emit("close",t),this.forwardDisconnect=t=>this.emit("disconnect",t),this.forwardDestroy=()=>this.emit("destroy"),this.setConfiguration(t),this.configuration.document=t.document?t.document:new P.Doc,this.configuration.awareness=void 0!==t.awareness?t.awareness:new Oe(this.document),this.on("open",this.configuration.onOpen),this.on("message",this.configuration.onMessage),this.on("outgoingMessage",this.configuration.onOutgoingMessage),this.on("synced",this.configuration.onSynced),this.on("destroy",this.configuration.onDestroy),this.on("awarenessUpdate",this.configuration.onAwarenessUpdate),this.on("awarenessChange",this.configuration.onAwarenessChange),this.on("stateless",this.configuration.onStateless),this.on("unsyncedChanges",this.configuration.onUnsyncedChanges),this.on("authenticated",this.configuration.onAuthenticated),this.on("authenticationFailed",this.configuration.onAuthenticationFailed),null===(e=this.awareness)||void 0===e||e.on("update",(()=>{this.emit("awarenessUpdate",{states:Kt(this.awareness.getStates())})})),null===(s=this.awareness)||void 0===s||s.on("change",(()=>{this.emit("awarenessChange",{states:Kt(this.awareness.getStates())})})),this.document.on("update",this.boundDocumentUpdateHandler),null===(i=this.awareness)||void 0===i||i.on("update",this.boundAwarenessUpdateHandler),this.registerEventListeners(),this.configuration.forceSyncInterval&&"number"==typeof this.configuration.forceSyncInterval&&(this.intervals.forceSync=setInterval(this.forceSync.bind(this),this.configuration.forceSyncInterval)),this.manageSocket&&this.attach()}setConfiguration(t={}){t.websocketProvider||(this.manageSocket=!0,this.configuration.websocketProvider=new Ve(t)),this.configuration={...this.configuration,...t}}get document(){return this.configuration.document}get isAttached(){return this._isAttached}get awareness(){return this.configuration.awareness}get hasUnsyncedChanges(){return this.unsyncedChanges>0}resetUnsyncedChanges(){this.unsyncedChanges=1,this.emit("unsyncedChanges",{number:this.unsyncedChanges})}incrementUnsyncedChanges(){this.unsyncedChanges+=1,this.emit("unsyncedChanges",{number:this.unsyncedChanges})}decrementUnsyncedChanges(){this.unsyncedChanges>0&&(this.unsyncedChanges-=1),0===this.unsyncedChanges&&(this.synced=!0),this.emit("unsyncedChanges",{number:this.unsyncedChanges})}forceSync(){this.resetUnsyncedChanges(),this.send(Ze,{document:this.document,documentName:this.configuration.name})}pageHide(){this.awareness&&Ie(this.awareness,[this.document.clientID],"page hide")}registerEventListeners(){"undefined"!=typeof window&&"addEventListener"in window&&window.addEventListener("pagehide",this.boundPageHide)}sendStateless(t){this.send(Ye,{documentName:this.configuration.name,payload:t})}async sendToken(){let t;try{t=await this.getToken()}catch(t){return void this.permissionDeniedHandler("Failed to get token during sendToken(): "+t)}this.send(He,{token:null!=t?t:"",documentName:this.configuration.name})}documentUpdateHandler(t,e){e!==this&&(this.incrementUnsyncedChanges(),this.send(qe,{update:t,documentName:this.configuration.name}))}awarenessUpdateHandler({added:t,updated:e,removed:s},i){const n=t.concat(e).concat(s);this.send(Ke,{awareness:this.awareness,clients:n,documentName:this.configuration.name})}get synced(){return this.isSynced}set synced(t){this.isSynced!==t&&(this.isSynced=t,t&&this.emit("synced",{state:t}))}receiveStateless(t){this.emit("stateless",{payload:t})}async connect(){if(this.manageSocket)return this.configuration.websocketProvider.connect();console.warn("HocuspocusProvider::connect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.")}disconnect(){if(this.manageSocket)return this.configuration.websocketProvider.disconnect();console.warn("HocuspocusProvider::disconnect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.")}async onOpen(t){this.isAuthenticated=!1,this.emit("open",{event:t}),await this.sendToken(),this.startSync()}async getToken(){return"function"==typeof this.configuration.token?await this.configuration.token():this.configuration.token}startSync(){this.resetUnsyncedChanges(),this.send(Ze,{document:this.document,documentName:this.configuration.name}),this.awareness&&null!==this.awareness.getLocalState()&&this.send(Ke,{awareness:this.awareness,clients:[this.document.clientID],documentName:this.configuration.name})}send(t,e){if(!this._isAttached)return;const s=new Je(t,e);this.emit("outgoingMessage",{message:s.message}),s.send(this.configuration.websocketProvider)}onMessage(t){const e=new Ue(t.data),s=e.readVarString();e.writeVarString(s),this.emit("message",{event:t,message:new Ue(t.data)}),new Ne(e).apply(this,!0)}onClose(){this.isAuthenticated=!1,this.synced=!1,this.awareness&&Ie(this.awareness,Array.from(this.awareness.getStates().keys()).filter((t=>t!==this.document.clientID)),this)}destroy(){this.emit("destroy"),this.intervals.forceSync&&clearInterval(this.intervals.forceSync),this.awareness&&(Ie(this.awareness,[this.document.clientID],"provider destroy"),this.awareness.off("update",this.boundAwarenessUpdateHandler),this.awareness.destroy()),this.document.off("update",this.boundDocumentUpdateHandler),this.removeAllListeners(),this.detach(),this.manageSocket&&this.configuration.websocketProvider.destroy(),"undefined"!=typeof window&&"removeEventListener"in window&&window.removeEventListener("pagehide",this.boundPageHide)}detach(){this.configuration.websocketProvider.off("connect",this.configuration.onConnect),this.configuration.websocketProvider.off("connect",this.forwardConnect),this.configuration.websocketProvider.off("status",this.forwardStatus),this.configuration.websocketProvider.off("status",this.configuration.onStatus),this.configuration.websocketProvider.off("open",this.boundOnOpen),this.configuration.websocketProvider.off("close",this.boundOnClose),this.configuration.websocketProvider.off("close",this.configuration.onClose),this.configuration.websocketProvider.off("close",this.forwardClose),this.configuration.websocketProvider.off("disconnect",this.configuration.onDisconnect),this.configuration.websocketProvider.off("disconnect",this.forwardDisconnect),this.configuration.websocketProvider.off("destroy",this.configuration.onDestroy),this.configuration.websocketProvider.off("destroy",this.forwardDestroy),this.configuration.websocketProvider.detach(this),this._isAttached=!1}attach(){this._isAttached||(this.configuration.websocketProvider.on("connect",this.configuration.onConnect),this.configuration.websocketProvider.on("connect",this.forwardConnect),this.configuration.websocketProvider.on("status",this.configuration.onStatus),this.configuration.websocketProvider.on("status",this.forwardStatus),this.configuration.websocketProvider.on("open",this.boundOnOpen),this.configuration.websocketProvider.on("close",this.boundOnClose),this.configuration.websocketProvider.on("close",this.configuration.onClose),this.configuration.websocketProvider.on("close",this.forwardClose),this.configuration.websocketProvider.on("disconnect",this.configuration.onDisconnect),this.configuration.websocketProvider.on("disconnect",this.forwardDisconnect),this.configuration.websocketProvider.on("destroy",this.configuration.onDestroy),this.configuration.websocketProvider.on("destroy",this.forwardDestroy),this.configuration.websocketProvider.attach(this),this._isAttached=!0)}permissionDeniedHandler(t){this.emit("authenticationFailed",{reason:t}),this.isAuthenticated=!1}authenticatedHandler(t){this.isAuthenticated=!0,this.authorizedScope=t,this.emit("authenticated",{scope:t})}setAwarenessField(t,e){if(!this.awareness)throw new $e(`Cannot set awareness field "${t}" to ${JSON.stringify(e)}. You have disabled Awareness for this provider by explicitly passing awareness: null in the provider configuration.`);this.awareness.setLocalStateField(t,e)}}const Ge={type:"pen",color:j[0],size:16,opacity:1,palettes:{pen:[...j]},sizes:{pen:[...c]}},Qe={color:j[0],size:8,opacity:1,fontFamily:"Arial",availableFonts:[...S],palette:[...j],sizes:[...h]},Xe={color:j[0],size:4,opacity:1,palette:[...j],sizes:[...c],arrows:{end:{enabled:!0,style:"triangle"}}},ts={providers:[]},es={shapeType:l.Rectangle,fillColor:{light:"transparent",dark:"transparent"},strokeColor:j[0],strokeWidth:4,opacity:1,fontColor:j[0],fontSize:16,fontFamily:"Arial",palette:[...j],sizes:[...c]},ss=t(class extends e{constructor(t){super(),!1!==t&&this.__registerHost(),this.isReady=s(this,"isReady"),this.activeWorkspaceChange=s(this,"activeWorkspaceChange"),this.objectsChange=s(this,"objectsChange"),this.objectsAdded=s(this,"objectsAdded"),this.objectsRemoved=s(this,"objectsRemoved"),this.objectsUpdated=s(this,"objectsUpdated"),this.undoStateChange=s(this,"undoStateChange"),this.themeChange=s(this,"themeChange"),this.localeChange=s(this,"localeChange"),this.viewportChange=s(this,"viewportChange"),this.logout=s(this,"logout"),this.login=s(this,"login"),this.isPublicChange=s(this,"isPublicChange"),this.awarenessChange=s(this,"awarenessChange")}get host(){return this}scaleMax=I;scaleMin=D;lockDrawingScale=!0;viewportBoundaryLeft=-1/0;viewportBoundaryRight=1/0;viewportBoundaryTop=-1/0;viewportBoundaryBottom=1/0;debugInfo={showViewportInfo:!1,showObjectInfo:!1,showSyncProviderInfo:!0,showMigrationInfo:!0,showAssetResolverInfo:!1};user;activeUsers;controls=[{name:"selection",type:"tool",isDefault:!0,tool:d,icon:"cursor"},{name:"brush",type:"tool",tool:u,icon:"pen",config:Ge},{name:"eraser",type:"tool",tool:p,icon:"eraser"},{name:"line",type:"tool",tool:m,icon:"arrow",config:Xe},{name:"shape",type:"tool",tool:g,icon:"shape-rectangle",config:es,subOptions:[{id:"rectangle",icon:"shape-rectangle",label:"Rectangle",value:l.Rectangle,toolProperty:"shapeType"},{id:"ellipse",icon:"shape-ellipse",label:"Ellipse",value:l.Ellipse,toolProperty:"shapeType"},{id:"triangle",icon:"shape-triangle",label:"Triangle",value:l.Triangle,toolProperty:"shapeType"}]},{name:"text",type:"tool",tool:f,icon:"type",config:Qe},{name:"image",type:"tool",tool:b,icon:"image"},{name:"config",type:"config"}];globalContextMenuItems=[{label:"menu.paste",icon:"paste",action:t=>this.engineRef.paste(t.x,t.y)},{label:"menu.selectAll",icon:"select-all",action:()=>this.selectAllObjectsInViewport()}];objectContextMenuItems=[{label:"menu.copy",icon:"copy",group:"clipboard",action:()=>this.engineRef.copy()},{label:"menu.cut",icon:"cut",group:"clipboard",action:()=>this.engineRef.cut()},{label:"menu.paste",icon:"paste",group:"clipboard",action:t=>this.engineRef.paste(t.x,t.y)},{label:"menu.order",icon:"ordering",group:"other",children:[{label:"menu.bringToFront",icon:"bring-to-front",action:()=>this.engineRef.bringToFront()},{label:"menu.sendToBack",icon:"send-to-back",action:()=>this.engineRef.sendToBack()},{label:"menu.moveUp",icon:"arrow-up-from-dot",action:()=>this.engineRef.bringForward()},{label:"menu.moveDown",icon:"arrow-down-from-dot",action:()=>this.engineRef.sendBackward()}]},{label:"menu.align",icon:"align",group:"other",children:[{label:"menu.alignLeft",icon:"align-start-vertical",action:()=>this.engineRef.alignObjects(y.StartHorizontal)},{label:"menu.alignCenterHorizontal",icon:"align-center-horizontal",action:()=>this.engineRef.alignObjects(y.CenterHorizontal)},{label:"menu.alignRight",icon:"align-end-vertical",action:()=>this.engineRef.alignObjects(y.EndHorizontal)},{label:"menu.alignTop",icon:"align-start-horizontal",action:()=>this.engineRef.alignObjects(y.StartVertical)},{label:"menu.alignCenterVertical",icon:"align-center-vertical",action:()=>this.engineRef.alignObjects(y.CenterVertical)},{label:"menu.alignBottom",icon:"align-end-horizontal",action:()=>this.engineRef.alignObjects(y.EndVertical)}]},{label:"menu.group",icon:"group",group:"other",children:[{label:"menu.group",icon:"group",action:()=>this.engineRef.group()},{label:"menu.ungroup",icon:"ungroup",action:()=>this.engineRef.ungroup()}]},{label:"menu.export",icon:"download",group:"export",children:[{label:"menu.exportAsSvg",icon:"download",action:()=>this.engineRef.exportSelectedObjectsAsSvg()},{label:"menu.exportAsPng",icon:"download",action:()=>this.engineRef.exportSelectedObjectsAsPng()}]},{label:"menu.delete",icon:"delete",group:"edit",action:()=>this.engineRef.delete()}];themes;theme="light";licenseKey;locale="en";locales;fallbackLocale="en";customSvgIcons={};customFonts={};isPanningEnabled=!0;isZoomingEnabled=!0;isControlsVisible=!0;isUtilityPanelVisible=!0;isWorkspaceManagerVisible=!0;isMoreMenuVisible=!0;isZoomPanelVisible=!0;isObjectDistanceFadingActive=!1;syncConfig=k;assetStorageConfig=ts;cursorTarget;loginConfig;isLoading=!1;editorId;activeWorkspaceId;isReady;activeWorkspaceChange;objectsChange;objectsAdded;objectsRemoved;objectsUpdated;undoStateChange;themeChange;localeChange;viewportChange;logout;login;isPublicChange;awarenessChange;isEngineReady=!1;isControlsReady=!1;isWorkspaceManagerReady=!1;workspaces=[];activeWorkspace;isVirtualKeyboardOpen=!1;undoState=null;isBackToContentButtonVisible=!1;resolvedTerms={};availableLocaleOptions=[];currentZoomPercent=100;shortcuts=[];currentIsPublic=!1;isEditorVisible=!1;activeNotification;isNotificationDismissing=!1;normalizedControls=[];notificationDismissTimeout;notificationDismissAnimationTimeout;notificationDisplayDurationMs=5e3;notificationDismissAnimationDurationMs=180;isNotificationHovered=!1;customFontsLoadVersion=0;customFontsReady=Promise.resolve();onIsEngineReady(t){t&&this.isControlsReady&&this.checkIsReady()}onIsControlsReady(t){t&&this.isEngineReady&&this.checkIsReady()}onWorkspacesChange(t){const e=this.activeWorkspace;if(e){const s=t.find((t=>t.id===e.id));s&&s!==e&&(this.activeWorkspace=s)}if(this.activeWorkspaceId){const e=t.find((t=>t.id===this.activeWorkspaceId));e&&e!==this.activeWorkspace&&(this.activeWorkspace=e)}}onActiveWorkspaceChange(){this.updateCurrentIsPublic()}onCustomFontsChange(t){this.registerCustomFonts(t)}onControlsChange(t){this.normalizedControls=this.normalizeControls(t)}onActiveWorkspaceIdChange(t){if(!t)return;if(0===this.workspaces.length)return;const e=this.workspaces.find((e=>e.id===t));e?e!==this.activeWorkspace&&(this.activeWorkspace=e):console.warn("[KritzelEditor] No workspace found with ID: "+t)}onCurrentThemeChange(){this.applyTheme(),setTimeout((()=>this.setOsSpecificCssVariables()),0),this.engineRef&&this.engineRef.saveSettings(this.currentSettingsConfig)}onThemesChange(){this.applyTheme()}onLocaleChange(t){this.engineRef&&(this.engineRef.setLocale(t),this.engineRef.saveSettings(this.currentSettingsConfig),this.refreshLocalizedTerms())}async refreshLocalizedTerms(){this.engineRef&&(this.resolvedTerms=await this.engineRef.getResolvedTerms(),this.availableLocaleOptions=await this.engineRef.getAvailableLocaleOptions())}onTouchStart(t){t.cancelable&&t.preventDefault()}async getObjectById(t){return this.engineRef.getObjectById(t)}async addObject(t){return this.engineRef.addObject(t)}async addObjects(t){return this.engineRef.addObjects(t)}async updateObject(t,e){return this.engineRef.updateObject(t,e)}async removeObject(t){return this.engineRef.removeObject(t)}async removeObjects(t){return this.engineRef.removeObjects(t)}async getSelectedObjects(){return this.engineRef.getSelectedObjects()}async selectObjects(t){return this.engineRef.selectObjects(t)}async selectAllObjectsInViewport(){return this.engineRef.selectAllObjectsInViewport()}async clearSelection(){this.engineRef.clearSelection()}async centerObjectInViewport(t){return this.engineRef.centerObjectInViewport(t)}async panToObject(t){return this.engineRef.panToObject(t)}async backToContent(){return this.engineRef.backToContent()}async centerAllObjects(t=!0){return this.engineRef.centerAllObjects(t)}async centerObjects(t,e=!0){return this.engineRef.centerObjects(t,e)}async setViewport(t,e,s){return this.engineRef.setViewport(t,e,s)}async panTo(t,e){return this.engineRef.panTo(t,e)}async zoomTo(t,e,s){return this.engineRef.zoomTo(t,e,s)}async zoomIn(t=1.6,e=200){return this.engineRef.zoomIn(t,e)}async zoomOut(t=1.6,e=200){return this.engineRef.zoomOut(t,e)}async getViewport(){return this.engineRef.getViewport()}async screenToWorld(t,e){return this.engineRef.screenToWorld(t,e)}async worldToScreen(t,e){return this.engineRef.worldToScreen(t,e)}async createWorkspace(t){return this.engineRef.createWorkspace(t)}async updateWorkspace(t){return this.engineRef.updateWorkspace(t)}async deleteWorkspace(t){return this.engineRef.deleteWorkspace(t)}async getWorkspaces(){return this.engineRef.getWorkspaces()}async getActiveWorkspace(){return this.engineRef.getActiveWorkspace()}async loadSharedWorkspace(t){return this.engineRef.loadSharedWorkspace(t)}async reinitSync(){return this.engineRef.reinitSync()}async registerTool(t,e,s){return this.engineRef.registerTool(t,e,s)}async changeActiveTool(t){return this.engineRef.changeActiveTool(t)}async changeActiveToolByName(t){return this.engineRef.changeActiveToolByName(t)}async disable(){return this.engineRef.disable()}async enable(){return this.engineRef.enable()}async copy(){return this.engineRef.copy()}async cut(){return this.engineRef.cut()}async paste(t,e){return this.engineRef.paste(t,e)}async delete(){return this.engineRef.delete()}async bringForward(t){return this.engineRef.bringForward(t)}async sendBackward(t){return this.engineRef.sendBackward(t)}async bringToFront(t){return this.engineRef.bringToFront(t)}async sendToBack(t){return this.engineRef.sendToBack(t)}async alignObjects(t){return this.engineRef.alignObjects(t)}async group(){return this.engineRef.group()}async ungroup(){return this.engineRef.ungroup()}async undo(){return this.engineRef.undo()}async redo(){return this.engineRef.redo()}async getScreenshot(t="png",e){return this.engineRef.getScreenshot(t,e)}async exportViewportAsPng(t){return this.engineRef.exportViewportAsPng(t)}async exportViewportAsSvg(t){return this.engineRef.exportViewportAsSvg(t)}async exportSelectedObjectsAsPng(){return this.engineRef.exportSelectedObjectsAsPng()}async exportSelectedObjectsAsSvg(){return this.engineRef.exportSelectedObjectsAsSvg()}async downloadAsJson(t){return this.engineRef.downloadAsJson(t)}async importFromFile(){return this.engineRef.importFromFile()}async loadObjectsFromJson(t){return this.engineRef.loadObjectsFromJson(t)}async getObjectsTotalCount(){return this.engineRef.getObjectsTotalCount()}async getAllObjects(){return this.engineRef.getAllObjects()}async findObjects(t){return this.engineRef.findObjects(t)}async getObjectsInViewport(){return this.engineRef.getObjectsInViewport()}async hideContextMenu(){return this.engineRef.hideContextMenu()}async openContextMenu(t){return this.engineRef.openContextMenu(t)}async triggerSelectionChange(){return this.engineRef.triggerSelectionChange()}async getDisplayableShortcuts(){return this.engineRef.getDisplayableShortcuts()}async triggerNotification(t){const e={...t,id:t.id??R.generateUUID(),timestamp:t.timestamp??new Date};this.clearNotificationDismissAnimationTimer(),this.isNotificationDismissing=!1,this.isNotificationHovered=!1,this.activeNotification=e,this.scheduleNotificationDismiss()}engineRef;controlsRef;settingsRef;exportRef;splitButtonRef;shareDialogRef;loginDialogRef;currentUserDialogRef;componentWillLoad(){this.normalizedControls=this.normalizeControls(this.controls),this.loadSettingsFromStorage(),this.applyTheme()}isTextToolConfig(t){return!!t&&"fontFamily"in t&&"size"in t&&"color"in t}normalizeControls(t){return t.map((t=>this.isTextToolConfig(t.config)?{...t,config:{...t.config,availableFonts:E(t.config.availableFonts)}}:t))}applyTheme(){const t=this.resolveThemeObject();A.applyThemeToElement(this.host,t)}resolveThemeObject(){return this.themes?.find((t=>t.name===this.theme))??("dark"===this.theme?x:T)}componentDidLoad(){this.registerCustomSvgIcons(),this.registerCustomFonts(),this.listenForMobileKeyboard(),this.setOsSpecificCssVariables()}disconnectedCallback(){this.clearNotificationDismissTimer(),this.clearNotificationDismissAnimationTimer()}async checkIsReady(){if(await customElements.whenDefined("kritzel-editor"),await customElements.whenDefined("kritzel-workspace-manager"),await customElements.whenDefined("kritzel-controls"),await customElements.whenDefined("kritzel-engine"),await this.waitForCustomFontsReady(),!(this.isEngineReady&&this.isControlsReady&&this.isWorkspaceManagerReady&&this.activeWorkspace))return;this.isEditorVisible=!0;const{id:t,name:e,isPublic:s,createdAt:i,updatedAt:n}=this.activeWorkspace;this.isReady.emit({host:this.host,activeWorkspace:{id:t,name:e,isPublic:s,createdAt:i,updatedAt:n},syncConfig:this.syncConfig,assetStorageConfig:this.assetStorageConfig,loginConfig:this.loginConfig,theme:this.theme})}async onEngineReady(t){if(this.isEngineReady=!0,!t.detail.activeWorkspace)return;this.activeWorkspace=t.detail.activeWorkspace,this.workspaces=t.detail.workspaces,this.currentIsPublic=await this.engineRef.getIsPublic(),await this.refreshLocalizedTerms();const e=await this.engineRef.getViewport();this.currentZoomPercent=this.getZoomPercentFromScale(e.scale),this.loadShortcuts()}handleWorkspacesChange(t){t.stopPropagation(),this.workspaces=t.detail}handleActiveWorkspaceChange(t){if(t.stopPropagation(),this.activeWorkspace=t.detail,!this.isEngineReady)return;const{id:e,name:s,isPublic:i,createdAt:n,updatedAt:o}=this.activeWorkspace;this.activeWorkspaceChange.emit({id:e,name:s,isPublic:i,createdAt:n,updatedAt:o})}handleObjectsChange(t){t.stopPropagation(),this.objectsChange.emit(t.detail)}handleObjectsAdded(t){t.stopPropagation(),this.objectsAdded.emit(t.detail)}handleObjectsRemoved(t){t.stopPropagation(),this.objectsRemoved.emit(t.detail)}handleObjectsUpdated(t){t.stopPropagation(),this.objectsUpdated.emit(t.detail)}handleUndoStateChange(t){t.stopPropagation(),this.undoStateChange.emit(t.detail),this.undoState=t.detail}async handleObjectsInViewportChange(t){t.stopPropagation();const e=this.getContentObjects(t.detail).length>0,s=this.getContentObjects(await this.engineRef.getAllObjects()).length>0;this.isBackToContentButtonVisible=!e&&s}handleViewportChange(t){t.stopPropagation(),this.currentZoomPercent=this.getZoomPercentFromScale(t.detail.scale),this.viewportChange.emit(t.detail)}getZoomPercentFromScale(t){return!Number.isFinite(t)||t<=0?100:Math.round(100*t)}handleAwarenessChange(t){t.stopPropagation(),this.awarenessChange.emit(t.detail)}handleNotificationsChange(t){t.stopPropagation(),this.clearNotificationDismissAnimationTimer(),this.isNotificationDismissing=!1,this.isNotificationHovered=!1,this.activeNotification=t.detail,this.scheduleNotificationDismiss()}handleNotificationHoverChange(t){t.stopPropagation(),this.isNotificationHovered=t.detail,this.isNotificationHovered?this.clearNotificationDismissTimer():this.activeNotification&&!this.isNotificationDismissing&&this.scheduleNotificationDismiss()}scheduleNotificationDismiss(){this.clearNotificationDismissTimer(),this.notificationDismissTimeout=setTimeout((()=>{this.dismissNotification()}),this.notificationDisplayDurationMs)}clearNotificationDismissTimer(){this.notificationDismissTimeout&&(clearTimeout(this.notificationDismissTimeout),this.notificationDismissTimeout=void 0)}clearNotificationDismissAnimationTimer(){this.notificationDismissAnimationTimeout&&(clearTimeout(this.notificationDismissAnimationTimeout),this.notificationDismissAnimationTimeout=void 0)}dismissNotification=()=>{this.clearNotificationDismissTimer(),this.isNotificationHovered=!1,this.activeNotification&&!this.isNotificationDismissing&&(this.isNotificationDismissing=!0,this.clearNotificationDismissAnimationTimer(),this.notificationDismissAnimationTimeout=setTimeout((()=>{this.activeNotification=void 0,this.isNotificationDismissing=!1,this.notificationDismissAnimationTimeout=void 0}),this.notificationDismissAnimationDurationMs))};handleSettingsChange(t){this.scaleMin=t.detail.scaleMin,this.scaleMax=t.detail.scaleMax,this.lockDrawingScale=t.detail.lockDrawingScale,this.theme=t.detail.theme,"string"==typeof t.detail.locale&&t.detail.locale!==this.locale&&(this.locale=t.detail.locale,this.localeChange.emit(t.detail.locale)),this.viewportBoundaryLeft=t.detail.viewportBoundaryLeft??-1/0,this.viewportBoundaryRight=t.detail.viewportBoundaryRight??1/0,this.viewportBoundaryTop=t.detail.viewportBoundaryTop??-1/0,this.viewportBoundaryBottom=t.detail.viewportBoundaryBottom??1/0,this.debugInfo=t.detail.debugInfo,this.engineRef&&this.engineRef.saveSettings(t.detail),this.themeChange.emit(t.detail.theme)}get moreMenuItems(){return[{id:"share",label:this.resolvedTerms["menu.share"]??"Share",icon:"share",action:()=>{this.isLoggedIn||!this.loginConfig?this.shareDialogRef.open():this.openLoginDialog()}},{id:"export",label:this.resolvedTerms["menu.export"]??"Export",icon:"upload",action:async()=>{const t=await this.engineRef.getScreenshot("png");this.exportRef.open(t??void 0)}},{id:"import",label:this.resolvedTerms["menu.import"]??"Import",icon:"download",action:()=>this.engineRef.importFromFile()},{id:"settings",label:this.resolvedTerms["menu.settings"]??"Settings",icon:"settings",action:()=>this.settingsRef.open()}]}handleToggleIsPublic=async t=>{const e=t.detail,s=await this.engineRef.getActiveWorkspace();s.isPublic=e,await this.engineRef.updateWorkspace(s),this.activeWorkspace=s.clone(),this.isPublicChange.emit({isPublic:e,workspaceId:s.id})};updateCurrentIsPublic(){const t=this.activeWorkspace?.isPublic??!1,e=this.activeWorkspace?.id;this.currentIsPublic=t,e&&this.isPublicChange.emit({isPublic:t,workspaceId:e})}handleProviderLogin=t=>{this.login.emit(t.detail)};handleCurrentUserLogout=()=>{this.logout.emit()};get isLoggedIn(){return!!this.user&&!this.user.isGuest}async openLoginDialog(){this.loginDialogRef?.open()}async setLoginLoading(t){this.loginDialogRef?.setLoading(t)}async setLocale(t){this.locale=t,await(this.engineRef?.setLocale(t))}async getLocale(){return this.engineRef?this.engineRef.getLocale():this.locale}async getAvailableLocales(){return this.engineRef?this.engineRef.getAvailableLocales():[]}async registerLocales(t){await(this.engineRef?.registerLocales(t))}async registerFonts(t){await this.registerCustomFonts(t)}async t(t,e){return this.engineRef?this.engineRef.t(t,e):t}getSettingsStorageKey(){return this.editorId?"kritzel-settings-"+this.editorId:"kritzel-settings"}loadSettingsFromStorage(){const t=localStorage.getItem(this.getSettingsStorageKey());if(t)try{const e=JSON.parse(t);"number"==typeof e.scaleMin&&(this.scaleMin=e.scaleMin),"number"==typeof e.scaleMax&&(this.scaleMax=e.scaleMax),"boolean"==typeof e.lockDrawingScale&&(this.lockDrawingScale=e.lockDrawingScale),"string"==typeof e.theme&&(this.theme=e.theme),"string"==typeof e.locale&&(this.locale=e.locale),"number"==typeof e.viewportBoundaryLeft&&(this.viewportBoundaryLeft=e.viewportBoundaryLeft),"number"==typeof e.viewportBoundaryRight&&(this.viewportBoundaryRight=e.viewportBoundaryRight),"number"==typeof e.viewportBoundaryTop&&(this.viewportBoundaryTop=e.viewportBoundaryTop),"number"==typeof e.viewportBoundaryBottom&&(this.viewportBoundaryBottom=e.viewportBoundaryBottom),e.debugInfo&&(this.debugInfo={...this.debugInfo,...e.debugInfo})}catch{}}async loadShortcuts(){this.shortcuts=await this.engineRef.getDisplayableShortcuts()}get currentSettingsConfig(){return{scaleMin:this.scaleMin,scaleMax:this.scaleMax,lockDrawingScale:this.lockDrawingScale,theme:this.theme,locale:this.locale,viewportBoundaryLeft:this.viewportBoundaryLeft,viewportBoundaryRight:this.viewportBoundaryRight,viewportBoundaryTop:this.viewportBoundaryTop,viewportBoundaryBottom:this.viewportBoundaryBottom,debugInfo:this.debugInfo}}getContentObjects(t){return t.filter((t=>!(t instanceof w||t instanceof v)))}registerCustomSvgIcons(){for(const[t,e]of Object.entries(this.customSvgIcons))r.register(t,e)}async registerCustomFonts(t=this.customFonts){O.registerFonts(t);const e=++this.customFontsLoadVersion,s=O.waitForFonts(t);this.customFontsReady=s,await s,e!==this.customFontsLoadVersion&&await this.waitForCustomFontsReady()}async waitForCustomFontsReady(){for(;;){const t=this.customFontsLoadVersion;if(await this.customFontsReady,t===this.customFontsLoadVersion)return}}listenForMobileKeyboard(){z.onKeyboardVisibleChanged((t=>{this.isVirtualKeyboardOpen=t}))}setOsSpecificCssVariables(){switch(U.detectOS()){case"iOS":this.host.style.setProperty("--kritzel-editor-top-left-buttons-top","14px"),this.host.style.setProperty("--kritzel-editor-top-left-buttons-left","14px"),this.host.style.setProperty("--kritzel-editor-controls-bottom","14px"),this.host.style.setProperty("--kritzel-editor-controls-transition","cubic-bezier(0.25, 0.1, 0.25, 1.0)"),this.host.style.setProperty("--kritzel-editor-controls-transform","translateY(200%)"),this.host.style.setProperty("--kritzel-editor-controls-transition-duration","0.25s");break;case"Android":this.host.style.setProperty("--kritzel-editor-top-left-buttons-top","14px"),this.host.style.setProperty("--kritzel-editor-top-left-buttons-left","14px"),this.host.style.setProperty("--kritzel-editor-controls-bottom","24px"),this.host.style.setProperty("--kritzel-editor-controls-transition","cubic-bezier(0.25, 0.1, 0.25, 1.0)"),this.host.style.setProperty("--kritzel-editor-controls-transform","translateY(200%)"),this.host.style.setProperty("--kritzel-editor-controls-transition-duration","0.25s");break;default:this.host.style.setProperty("--kritzel-editor-top-left-buttons-top","14px"),this.host.style.setProperty("--kritzel-editor-top-left-buttons-left","14px"),this.host.style.setProperty("--kritzel-editor-controls-bottom","14px")}}render(){const t=this.isLoggedIn,e=t,s=this.isReady&&!!this.loginConfig&&!t;return i(n,{key:"00d652c74feac7b4917772146368125da6deeb1c"},i("div",{key:"f8fb86b45b0cdabb5e3ad52de6d6ef31a71a09e4",class:"editor-content",style:{opacity:this.isEditorVisible?"1":"0",visibility:this.isEditorVisible?"visible":"hidden",transition:"opacity 0.2s ease-in-out, visibility 0.2s ease-in-out"}},i("div",{key:"2378c776d8eecf2614567bed11c6e93fb338e302",class:"top-left-buttons"},i("kritzel-workspace-manager",{key:"ce41192540169694482d6f8cca60701bc4427438",visible:this.isWorkspaceManagerVisible,workspaces:this.workspaces,activeWorkspace:this.activeWorkspace,terms:this.resolvedTerms,onWorkspaceChange:t=>this.activeWorkspace=t.detail,onIsWorkspaceManagerReady:()=>this.isWorkspaceManagerReady=!0}),i("kritzel-back-to-content",{key:"ec269d3e9f589362d8301370778f0c5e4252eead",visible:this.isBackToContentButtonVisible,text:this.resolvedTerms["backToContent.label"]??"Back to content",onBackToContent:()=>this.backToContent()})),this.activeNotification&&i("div",{key:"847ed8149d556c934090424ff54b17b6721ccc76",class:"top-center-notification-layer",role:"presentation"},i("div",{key:"61d8b8e91cda100ffa6620db26ba6dfb2232946a",class:{"top-center-notification-container":!0,"is-dismissing":this.isNotificationDismissing},role:"presentation"},i("kritzel-notification-card",{key:"b7e132773225ace38e447756110dd39e4661f5fc",notification:this.activeNotification,locale:this.locale,onDismiss:this.dismissNotification,onHoverChange:t=>this.handleNotificationHoverChange(t)}))),i("kritzel-engine",{key:"3e4a6d0dbc015ec675fb21a59990c87e9eaa805f",ref:t=>{t&&(this.engineRef=t)},workspace:this.activeWorkspace,activeWorkspaceId:this.activeWorkspaceId,editorId:this.editorId,syncConfig:this.syncConfig,assetStorageConfig:this.assetStorageConfig,user:this.user,scaleMax:this.scaleMax,lockDrawingScale:this.lockDrawingScale,isObjectDistanceFadingActive:this.isObjectDistanceFadingActive,scaleMin:this.scaleMin,cursorTarget:this.cursorTarget,isLoading:this.isLoading,viewportBoundaryLeft:this.viewportBoundaryLeft,viewportBoundaryRight:this.viewportBoundaryRight,viewportBoundaryTop:this.viewportBoundaryTop,viewportBoundaryBottom:this.viewportBoundaryBottom,isPanningEnabled:this.isPanningEnabled,isZoomingEnabled:this.isZoomingEnabled,theme:this.theme,themes:this.themes,licenseKey:this.licenseKey,locale:this.locale,locales:this.locales,fallbackLocale:this.fallbackLocale,debugInfo:this.debugInfo,globalContextMenuItems:this.globalContextMenuItems,objectContextMenuItems:this.objectContextMenuItems,onIsEngineReady:t=>this.onEngineReady(t),onWorkspacesChange:t=>this.handleWorkspacesChange(t),onActiveWorkspaceChange:t=>this.handleActiveWorkspaceChange(t),onObjectsChange:t=>this.handleObjectsChange(t),onObjectsAdded:t=>this.handleObjectsAdded(t),onObjectsRemoved:t=>this.handleObjectsRemoved(t),onObjectsUpdated:t=>this.handleObjectsUpdated(t),onUndoStateChange:t=>this.handleUndoStateChange(t),onObjectsInViewportChange:t=>this.handleObjectsInViewportChange(t),onViewportChange:t=>this.handleViewportChange(t),onAwarenessChange:t=>this.handleAwarenessChange(t),onNotificationsChange:t=>this.handleNotificationsChange(t)}),i("kritzel-controls",{key:"f84607a0a4d0762c1249400f85b7b8454d672c1e",visible:this.isControlsVisible,class:{"keyboard-open":this.isVirtualKeyboardOpen},ref:t=>{t&&(this.controlsRef=t)},controls:this.normalizedControls,isUtilityPanelVisible:this.isUtilityPanelVisible,undoState:this.undoState??void 0,theme:this.theme,terms:this.resolvedTerms,onIsControlsReady:()=>this.isControlsReady=!0}),i("div",{key:"e2691e7c730195e197511cb1e4d0fe707677b5ff",class:"bottom-left-buttons"},i("kritzel-zoom-panel",{key:"d0ac6624eab49af78d4761c3ad91842834717aad",visible:this.isZoomPanelVisible,disabled:!this.isZoomingEnabled,zoomPercent:this.currentZoomPercent,terms:this.resolvedTerms,onZoomIn:()=>this.zoomIn(),onZoomOut:()=>this.zoomOut()})),i("div",{key:"ad3d386ab7e8ad9fdfbb12754db005bc85fa28ce",class:"top-right-buttons"},i("kritzel-settings",{key:"566024ac6f3d8f7f20238cc1f83882b39dbf698e",ref:t=>{t&&(this.settingsRef=t)},shortcuts:this.shortcuts,availableThemes:this.themes&&this.themes.length>0?this.themes.map((t=>t.name)):["light","dark"],availableLocales:this.availableLocaleOptions,settings:this.currentSettingsConfig,terms:this.resolvedTerms,onSettingsChange:t=>this.handleSettingsChange(t)}),i("kritzel-export",{key:"4a23ea0c6e070d424a90e9fc87de04e11cff7ade",ref:t=>{t&&(this.exportRef=t)},workspaceName:this.activeWorkspace?.name||"workspace",terms:this.resolvedTerms,onExportPng:()=>this.engineRef.exportViewportAsPng(),onExportSvg:()=>this.engineRef.exportViewportAsSvg(),onExportJson:t=>this.engineRef.downloadAsJson(t.detail)}),i("kritzel-active-users",{key:"feef074b52e552fa2ef7e8258002571aca4c5abd",users:this.activeUsers}),e&&i("kritzel-current-user",{key:"844c722545363eaf7eec69037a835eae943afeb9",user:this.user,terms:this.resolvedTerms,onClick:()=>this.currentUserDialogRef?.open()}),e&&i("kritzel-current-user-dialog",{key:"8363c1d3230d111cf1ace0ccf805669e592bb533",ref:t=>{t&&(this.currentUserDialogRef=t,this.currentUserDialogRef.addEventListener("logoutRequest",this.handleCurrentUserLogout))},user:this.user,terms:this.resolvedTerms}),s&&i("kritzel-button",{key:"68ddf8c3aabc7634b4c1d88f3d2d584fa1f1b150",onButtonClick:()=>this.loginDialogRef?.open()},this.resolvedTerms["login.dialogTitle"]??"Sign in"),i("kritzel-more-menu",{key:"39b938f5792f7a36bbf21ed88a1a5c7717a785a6",items:this.moreMenuItems,visible:this.isMoreMenuVisible,terms:this.resolvedTerms}),i("kritzel-share-dialog",{key:"61ed918499760d874d5d2ec140d3cf59ce94520b",ref:t=>{t&&(this.shareDialogRef=t)},isPublic:this.currentIsPublic,workspaceId:this.activeWorkspace?.id,terms:this.resolvedTerms,onToggleIsPublic:this.handleToggleIsPublic}),this.loginConfig&&i("kritzel-login-dialog",{key:"5f6528a57884bd1494e45755609e710f69041a4d",ref:t=>{t&&(this.loginDialogRef=t)},providers:this.loginConfig.providers,dialogTitle:this.loginConfig.title??this.resolvedTerms["login.dialogTitle"]??"Sign in",subtitle:this.loginConfig.subtitle,onProviderLogin:this.handleProviderLogin}))))}static get watchers(){return{isEngineReady:[{onIsEngineReady:0}],isControlsReady:[{onIsControlsReady:0}],workspaces:[{onWorkspacesChange:0}],activeWorkspace:[{onActiveWorkspaceChange:0}],customFonts:[{onCustomFontsChange:0}],controls:[{onControlsChange:0}],activeWorkspaceId:[{onActiveWorkspaceIdChange:0}],theme:[{onCurrentThemeChange:0}],themes:[{onThemesChange:0}],locale:[{onLocaleChange:0}]}}static get style(){return"kritzel-editor{display:flex;margin:0;position:relative;container-type:inline-size;overflow:hidden;width:100%;height:100%;align-items:center;justify-content:center;touch-action:manipulation;user-select:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:start;line-height:normal}.editor-content{position:absolute;inset:0}.editor-content>kritzel-engine{position:absolute;inset:0;z-index:0}kritzel-controls{position:absolute;z-index:1;left:0;right:0;margin-inline:auto;width:max-content;max-width:calc(100% - 16px);bottom:var(--kritzel-editor-controls-bottom, 14px);transition:transform var(--kritzel-editor-controls-transition-duration, 0.1s) var(--kritzel-editor-controls-transition, ease-in-out)}kritzel-controls.keyboard-open{transform:var(--kritzel-editor-controls-transform, translateY(300%))}.top-left-buttons{position:absolute;z-index:1;top:var(--kritzel-editor-top-left-buttons-top, 14px);left:var(--kritzel-editor-top-left-buttons-left, 14px);display:flex;align-items:flex-start;gap:8px}.top-center-notification-layer{position:absolute;top:var(--kritzel-editor-top-center-notification-top, 14px);left:0;right:0;z-index:var(--kritzel-editor-top-center-notification-z-index, 10001);display:flex;justify-content:center;pointer-events:none}.top-center-notification-container{width:min(90vw, 420px);pointer-events:auto;animation:kritzel-notification-slide-in var(--kritzel-editor-notification-animation-duration, 220ms) var(--kritzel-editor-notification-animation-easing, cubic-bezier(0.22, 1, 0.36, 1))}.top-center-notification-container.is-dismissing{animation:kritzel-notification-fade-out var(--kritzel-editor-notification-dismiss-animation-duration, 180ms) var(--kritzel-editor-notification-dismiss-animation-easing, ease-in) forwards}@keyframes kritzel-notification-slide-in{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes kritzel-notification-fade-out{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-6px)}}@media (prefers-reduced-motion: reduce){.top-center-notification-container{animation:none}}.top-right-buttons{position:absolute;z-index:1;top:var(--kritzel-editor-top-right-buttons-top, 14px);right:var(--kritzel-editor-top-right-buttons-right, 14px);display:flex;align-items:center;gap:8px}.bottom-left-buttons{position:absolute;z-index:1;left:var(--kritzel-editor-top-left-buttons-left, 14px);bottom:var(--kritzel-editor-controls-bottom, 14px);display:flex;align-items:flex-end}@container (max-width: 767px){.bottom-left-buttons{display:none}}.top-right-button{display:flex;align-items:center;justify-content:center;width:50px;height:50px;padding:0;border:var(--kritzel-split-button-border, 1px solid #ebebeb);border-radius:var(--kritzel-split-button-border-radius, 12px);background-color:var(--kritzel-split-button-background-color, #ffffff);cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:var(--kritzel-split-button-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent}.top-right-button:hover{background-color:#f5f5f5}.top-right-button:active{background-color:#ebebeb}"}},[512,"kritzel-editor",{scaleMax:[1026,"scale-max"],scaleMin:[1026,"scale-min"],lockDrawingScale:[1028,"lock-drawing-scale"],viewportBoundaryLeft:[1026,"viewport-boundary-left"],viewportBoundaryRight:[1026,"viewport-boundary-right"],viewportBoundaryTop:[1026,"viewport-boundary-top"],viewportBoundaryBottom:[1026,"viewport-boundary-bottom"],debugInfo:[1040],user:[16],activeUsers:[16],controls:[16],globalContextMenuItems:[16],objectContextMenuItems:[16],themes:[16],theme:[1025],licenseKey:[1,"license-key"],locale:[1025],locales:[16],fallbackLocale:[1,"fallback-locale"],customSvgIcons:[16],customFonts:[16],isPanningEnabled:[1028,"is-panning-enabled"],isZoomingEnabled:[1028,"is-zooming-enabled"],isControlsVisible:[4,"is-controls-visible"],isUtilityPanelVisible:[4,"is-utility-panel-visible"],isWorkspaceManagerVisible:[4,"is-workspace-manager-visible"],isMoreMenuVisible:[4,"is-more-menu-visible"],isZoomPanelVisible:[4,"is-zoom-panel-visible"],isObjectDistanceFadingActive:[4,"is-object-distance-fading-active"],syncConfig:[16],assetStorageConfig:[16],cursorTarget:[16],loginConfig:[16],isLoading:[4,"is-loading"],editorId:[1,"editor-id"],activeWorkspaceId:[1,"active-workspace-id"],isEngineReady:[32],isControlsReady:[32],isWorkspaceManagerReady:[32],workspaces:[32],activeWorkspace:[32],isVirtualKeyboardOpen:[32],undoState:[32],isBackToContentButtonVisible:[32],resolvedTerms:[32],availableLocaleOptions:[32],currentZoomPercent:[32],shortcuts:[32],currentIsPublic:[32],isEditorVisible:[32],activeNotification:[32],isNotificationDismissing:[32],normalizedControls:[32],getObjectById:[64],addObject:[64],addObjects:[64],updateObject:[64],removeObject:[64],removeObjects:[64],getSelectedObjects:[64],selectObjects:[64],selectAllObjectsInViewport:[64],clearSelection:[64],centerObjectInViewport:[64],panToObject:[64],backToContent:[64],centerAllObjects:[64],centerObjects:[64],setViewport:[64],panTo:[64],zoomTo:[64],zoomIn:[64],zoomOut:[64],getViewport:[64],screenToWorld:[64],worldToScreen:[64],createWorkspace:[64],updateWorkspace:[64],deleteWorkspace:[64],getWorkspaces:[64],getActiveWorkspace:[64],loadSharedWorkspace:[64],reinitSync:[64],registerTool:[64],changeActiveTool:[64],changeActiveToolByName:[64],disable:[64],enable:[64],copy:[64],cut:[64],paste:[64],delete:[64],bringForward:[64],sendBackward:[64],bringToFront:[64],sendToBack:[64],alignObjects:[64],group:[64],ungroup:[64],undo:[64],redo:[64],getScreenshot:[64],exportViewportAsPng:[64],exportViewportAsSvg:[64],exportSelectedObjectsAsPng:[64],exportSelectedObjectsAsSvg:[64],downloadAsJson:[64],importFromFile:[64],loadObjectsFromJson:[64],getObjectsTotalCount:[64],getAllObjects:[64],findObjects:[64],getObjectsInViewport:[64],hideContextMenu:[64],openContextMenu:[64],triggerSelectionChange:[64],getDisplayableShortcuts:[64],triggerNotification:[64],openLoginDialog:[64],setLoginLoading:[64],setLocale:[64],getLocale:[64],getAvailableLocales:[64],registerLocales:[64],registerFonts:[64],t:[64]},[[0,"dblclick","onTouchStart"]],{isEngineReady:[{onIsEngineReady:0}],isControlsReady:[{onIsControlsReady:0}],workspaces:[{onWorkspacesChange:0}],activeWorkspace:[{onActiveWorkspaceChange:0}],customFonts:[{onCustomFontsChange:0}],controls:[{onControlsChange:0}],activeWorkspaceId:[{onActiveWorkspaceIdChange:0}],theme:[{onCurrentThemeChange:0}],themes:[{onThemesChange:0}],locale:[{onLocaleChange:0}]}]),is=ss,ns=function(){"undefined"!=typeof customElements&&["kritzel-editor","kritzel-active-users","kritzel-avatar","kritzel-awareness-cursors","kritzel-back-to-content","kritzel-button","kritzel-color","kritzel-color-palette","kritzel-context-menu","kritzel-controls","kritzel-current-user","kritzel-current-user-dialog","kritzel-cursor-trail","kritzel-dialog","kritzel-dropdown","kritzel-engine","kritzel-export","kritzel-font","kritzel-font-family","kritzel-font-size","kritzel-icon","kritzel-input","kritzel-line-endings","kritzel-loading-overlay","kritzel-login-dialog","kritzel-master-detail","kritzel-menu","kritzel-menu-item","kritzel-more-menu","kritzel-notification-card","kritzel-numeric-input","kritzel-opacity-slider","kritzel-pill-tabs","kritzel-portal","kritzel-settings","kritzel-shape-fill","kritzel-share-dialog","kritzel-slide-toggle","kritzel-split-button","kritzel-stroke-size","kritzel-sync-indicator","kritzel-tool-config","kritzel-tooltip","kritzel-utility-panel","kritzel-watermark","kritzel-workspace-manager","kritzel-zoom-panel"].forEach((t=>{switch(t){case"kritzel-editor":customElements.get(o(t))||customElements.define(o(t),ss);break;case"kritzel-active-users":customElements.get(o(t))||W();break;case"kritzel-avatar":customElements.get(o(t))||V();break;case"kritzel-awareness-cursors":customElements.get(o(t))||B();break;case"kritzel-back-to-content":customElements.get(o(t))||F();break;case"kritzel-button":customElements.get(o(t))||L();break;case"kritzel-color":customElements.get(o(t))||N();break;case"kritzel-color-palette":customElements.get(o(t))||J();break;case"kritzel-context-menu":customElements.get(o(t))||H();break;case"kritzel-controls":customElements.get(o(t))||K();break;case"kritzel-current-user":customElements.get(o(t))||Y();break;case"kritzel-current-user-dialog":customElements.get(o(t))||Z();break;case"kritzel-cursor-trail":customElements.get(o(t))||q();break;case"kritzel-dialog":customElements.get(o(t))||$();break;case"kritzel-dropdown":customElements.get(o(t))||_();break;case"kritzel-engine":customElements.get(o(t))||C();break;case"kritzel-export":customElements.get(o(t))||G();break;case"kritzel-font":customElements.get(o(t))||Q();break;case"kritzel-font-family":customElements.get(o(t))||X();break;case"kritzel-font-size":customElements.get(o(t))||tt();break;case"kritzel-icon":customElements.get(o(t))||a();break;case"kritzel-input":customElements.get(o(t))||et();break;case"kritzel-line-endings":customElements.get(o(t))||st();break;case"kritzel-loading-overlay":customElements.get(o(t))||it();break;case"kritzel-login-dialog":customElements.get(o(t))||nt();break;case"kritzel-master-detail":customElements.get(o(t))||ot();break;case"kritzel-menu":customElements.get(o(t))||at();break;case"kritzel-menu-item":customElements.get(o(t))||rt();break;case"kritzel-more-menu":customElements.get(o(t))||ct();break;case"kritzel-notification-card":customElements.get(o(t))||ht();break;case"kritzel-numeric-input":customElements.get(o(t))||lt();break;case"kritzel-opacity-slider":customElements.get(o(t))||dt();break;case"kritzel-pill-tabs":customElements.get(o(t))||ut();break;case"kritzel-portal":customElements.get(o(t))||pt();break;case"kritzel-settings":customElements.get(o(t))||mt();break;case"kritzel-shape-fill":customElements.get(o(t))||gt();break;case"kritzel-share-dialog":customElements.get(o(t))||ft();break;case"kritzel-slide-toggle":customElements.get(o(t))||bt();break;case"kritzel-split-button":customElements.get(o(t))||yt();break;case"kritzel-stroke-size":customElements.get(o(t))||kt();break;case"kritzel-sync-indicator":customElements.get(o(t))||wt();break;case"kritzel-tool-config":customElements.get(o(t))||vt();break;case"kritzel-tooltip":customElements.get(o(t))||zt();break;case"kritzel-utility-panel":customElements.get(o(t))||Ct();break;case"kritzel-watermark":customElements.get(o(t))||M();break;case"kritzel-workspace-manager":customElements.get(o(t))||jt();break;case"kritzel-zoom-panel":customElements.get(o(t))||At()}}))};export{Ge as D,_e as H,is as KritzelEditor,Ve as a,Qe as b,Xe as c,ts as d,ns as defineCustomElement}
1
+ import { p as proxyCustomElement, H, c as createEvent, h, d as Host, t as transformTag } from './p-B43upypT.js';
2
+ import { K as KritzelIconRegistry, d as defineCustomElement$s } from './p-CdR76C4L.js';
3
+ import { v as DEFAULT_STROKE_SIZES, w as DEFAULT_FONT_SIZES, S as ShapeType, m as KritzelSelectionTool, f as KritzelBrushTool, h as KritzelEraserTool, g as KritzelLineTool, k as KritzelShapeTool, j as KritzelTextTool, i as KritzelImageTool, s as KritzelAlignment, x as DEFAULT_SYNC_CONFIG, y as KritzelSelectionGroup, z as KritzelSelectionBox, B as KritzelKeyboardHelper, C as defineCustomElement$x } from './p--Oazz-BP.js';
4
+ import { D as DEFAULT_COLOR_PALETTE, T as ThemeHelper, d as darkTheme, l as lightTheme } from './p-BmyTdQGy.js';
5
+ import { D as DEFAULT_TEXT_TOOL_AVAILABLE_FONTS, r as resolveTextToolAvailableFonts, K as KritzelFontRegistry } from './p-DJkKlUyZ.js';
6
+ import { A as ABSOLUTE_SCALE_MAX, a as ABSOLUTE_SCALE_MIN, d as defineCustomElement$4 } from './p-PSFAfAyd.js';
7
+ import { K as KritzelDevicesHelper } from './p-jGOpkGDl.js';
8
+ import { O as ObjectHelper } from './p-Dd-pMvlr.js';
9
+ import { d as defineCustomElement$J } from './p-Ka7OWbnk.js';
10
+ import * as Y from 'yjs';
11
+ import 'y-indexeddb';
12
+ import 'y-websocket';
13
+ import { d as defineCustomElement$L } from './p-DJ88BrIW.js';
14
+ import { d as defineCustomElement$K } from './p-D5jf8wAu.js';
15
+ import { d as defineCustomElement$I } from './p-Dlp84thc.js';
16
+ import { d as defineCustomElement$H } from './p-DEBwmRTC.js';
17
+ import { d as defineCustomElement$G } from './p-CqLgB8JK.js';
18
+ import { d as defineCustomElement$F } from './p-Cymum41a.js';
19
+ import { d as defineCustomElement$E } from './p-BxpKq94F.js';
20
+ import { d as defineCustomElement$D } from './p-JYj3Facr.js';
21
+ import { d as defineCustomElement$C } from './p-DIazmg6w.js';
22
+ import { d as defineCustomElement$B } from './p-D3y_Hauo.js';
23
+ import { d as defineCustomElement$A } from './p-Cm33td2O.js';
24
+ import { d as defineCustomElement$z } from './p-DX2nriaq.js';
25
+ import { d as defineCustomElement$y } from './p-Df3BwVGy.js';
26
+ import { d as defineCustomElement$w } from './p-e6Zpc9Vp.js';
27
+ import { d as defineCustomElement$v } from './p-B8Xi4Clg.js';
28
+ import { d as defineCustomElement$u } from './p-djJSnjAX.js';
29
+ import { d as defineCustomElement$t } from './p-BI2ng9I_.js';
30
+ import { d as defineCustomElement$r } from './p-C4NrrUfN.js';
31
+ import { d as defineCustomElement$q } from './p-CXpv9Rxe.js';
32
+ import { d as defineCustomElement$p } from './p-DgJ0ufzr.js';
33
+ import { d as defineCustomElement$o } from './p-B5oHmPJb.js';
34
+ import { d as defineCustomElement$n } from './p-BsANVili.js';
35
+ import { d as defineCustomElement$l, a as defineCustomElement$m } from './p-CwJwsRR3.js';
36
+ import { d as defineCustomElement$k } from './p-D30zs0kA.js';
37
+ import { d as defineCustomElement$j } from './p-pagW8YF7.js';
38
+ import { d as defineCustomElement$i } from './p-BDzlx2hB.js';
39
+ import { d as defineCustomElement$h } from './p-B6t5q-V4.js';
40
+ import { d as defineCustomElement$g } from './p-D09kgc5Q.js';
41
+ import { d as defineCustomElement$f } from './p-Ca-igU1f.js';
42
+ import { d as defineCustomElement$e } from './p-U6uE85Qx.js';
43
+ import { d as defineCustomElement$d } from './p-BFYtCsZu.js';
44
+ import { d as defineCustomElement$c } from './p-DUYmwrWV.js';
45
+ import { d as defineCustomElement$b } from './p-CWRSGYOE.js';
46
+ import { d as defineCustomElement$a } from './p-Cr682JI_.js';
47
+ import { d as defineCustomElement$9 } from './p-D82VaHce.js';
48
+ import { d as defineCustomElement$8 } from './p-894OnDQV.js';
49
+ import { d as defineCustomElement$7 } from './p-C38P-Vd0.js';
50
+ import { d as defineCustomElement$6 } from './p-BTzlrIxe.js';
51
+ import { d as defineCustomElement$5 } from './p-CsvMgk_f.js';
52
+ import { d as defineCustomElement$3 } from './p-ClFprFvz.js';
53
+ import { d as defineCustomElement$2 } from './p-DkUb2czk.js';
54
+
55
+ /**
56
+ * Common Math expressions.
57
+ *
58
+ * @module math
59
+ */
60
+
61
+ const floor$1 = Math.floor;
62
+
63
+ /**
64
+ * @function
65
+ * @param {number} a
66
+ * @param {number} b
67
+ * @return {number} The smaller element of a and b
68
+ */
69
+ const min$1 = (a, b) => a < b ? a : b;
70
+
71
+ /**
72
+ * @function
73
+ * @param {number} a
74
+ * @param {number} b
75
+ * @return {number} The bigger element of a and b
76
+ */
77
+ const max$1 = (a, b) => a > b ? a : b;
78
+
79
+ /* eslint-env browser */
80
+
81
+ const BIT8$1 = 128;
82
+ const BITS7$1 = 127;
83
+
84
+ /**
85
+ * Utility helpers for working with numbers.
86
+ *
87
+ * @module number
88
+ */
89
+
90
+
91
+ const MAX_SAFE_INTEGER$1 = Number.MAX_SAFE_INTEGER;
92
+
93
+ /**
94
+ * @param {string} str
95
+ * @return {Uint8Array}
96
+ */
97
+ const _encodeUtf8Polyfill$1 = str => {
98
+ const encodedString = unescape(encodeURIComponent(str));
99
+ const len = encodedString.length;
100
+ const buf = new Uint8Array(len);
101
+ for (let i = 0; i < len; i++) {
102
+ buf[i] = /** @type {number} */ (encodedString.codePointAt(i));
103
+ }
104
+ return buf
105
+ };
106
+
107
+ /* c8 ignore next */
108
+ const utf8TextEncoder$1 = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
109
+
110
+ /**
111
+ * @param {string} str
112
+ * @return {Uint8Array}
113
+ */
114
+ const _encodeUtf8Native$1 = str => utf8TextEncoder$1.encode(str);
115
+
116
+ /**
117
+ * @param {string} str
118
+ * @return {Uint8Array}
119
+ */
120
+ /* c8 ignore next */
121
+ const encodeUtf8$1 = utf8TextEncoder$1 ? _encodeUtf8Native$1 : _encodeUtf8Polyfill$1;
122
+
123
+ /* c8 ignore next */
124
+ let utf8TextDecoder$1 = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
125
+
126
+ /* c8 ignore start */
127
+ if (utf8TextDecoder$1 && utf8TextDecoder$1.decode(new Uint8Array()).length === 1) {
128
+ // Safari doesn't handle BOM correctly.
129
+ // This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called.
130
+ // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and
131
+ // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call
132
+ // Another issue is that from then on no BOM chars are recognized anymore
133
+ /* c8 ignore next */
134
+ utf8TextDecoder$1 = null;
135
+ }
136
+
137
+ /**
138
+ * Efficient schema-less binary encoding with support for variable length encoding.
139
+ *
140
+ * Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
141
+ *
142
+ * Encodes numbers in little-endian order (least to most significant byte order)
143
+ * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
144
+ * which is also used in Protocol Buffers.
145
+ *
146
+ * ```js
147
+ * // encoding step
148
+ * const encoder = encoding.createEncoder()
149
+ * encoding.writeVarUint(encoder, 256)
150
+ * encoding.writeVarString(encoder, 'Hello world!')
151
+ * const buf = encoding.toUint8Array(encoder)
152
+ * ```
153
+ *
154
+ * ```js
155
+ * // decoding step
156
+ * const decoder = decoding.createDecoder(buf)
157
+ * decoding.readVarUint(decoder) // => 256
158
+ * decoding.readVarString(decoder) // => 'Hello world!'
159
+ * decoding.hasContent(decoder) // => false - all data is read
160
+ * ```
161
+ *
162
+ * @module encoding
163
+ */
164
+
165
+
166
+ /**
167
+ * Write one byte to the encoder.
168
+ *
169
+ * @function
170
+ * @param {Encoder} encoder
171
+ * @param {number} num The byte that is to be encoded.
172
+ */
173
+ const write$1 = (encoder, num) => {
174
+ const bufferLen = encoder.cbuf.length;
175
+ if (encoder.cpos === bufferLen) {
176
+ encoder.bufs.push(encoder.cbuf);
177
+ encoder.cbuf = new Uint8Array(bufferLen * 2);
178
+ encoder.cpos = 0;
179
+ }
180
+ encoder.cbuf[encoder.cpos++] = num;
181
+ };
182
+
183
+ /**
184
+ * Write a variable length unsigned integer. Max encodable integer is 2^53.
185
+ *
186
+ * @function
187
+ * @param {Encoder} encoder
188
+ * @param {number} num The number that is to be encoded.
189
+ */
190
+ const writeVarUint$1 = (encoder, num) => {
191
+ while (num > BITS7$1) {
192
+ write$1(encoder, BIT8$1 | (BITS7$1 & num));
193
+ num = floor$1(num / 128); // shift >>> 7
194
+ }
195
+ write$1(encoder, BITS7$1 & num);
196
+ };
197
+
198
+ /**
199
+ * A cache to store strings temporarily
200
+ */
201
+ const _strBuffer$1 = new Uint8Array(30000);
202
+ const _maxStrBSize$1 = _strBuffer$1.length / 3;
203
+
204
+ /**
205
+ * Write a variable length string.
206
+ *
207
+ * @function
208
+ * @param {Encoder} encoder
209
+ * @param {String} str The string that is to be encoded.
210
+ */
211
+ const _writeVarStringNative$1 = (encoder, str) => {
212
+ if (str.length < _maxStrBSize$1) {
213
+ // We can encode the string into the existing buffer
214
+ /* c8 ignore next */
215
+ const written = utf8TextEncoder$1.encodeInto(str, _strBuffer$1).written || 0;
216
+ writeVarUint$1(encoder, written);
217
+ for (let i = 0; i < written; i++) {
218
+ write$1(encoder, _strBuffer$1[i]);
219
+ }
220
+ } else {
221
+ writeVarUint8Array$1(encoder, encodeUtf8$1(str));
222
+ }
223
+ };
224
+
225
+ /**
226
+ * Write a variable length string.
227
+ *
228
+ * @function
229
+ * @param {Encoder} encoder
230
+ * @param {String} str The string that is to be encoded.
231
+ */
232
+ const _writeVarStringPolyfill$1 = (encoder, str) => {
233
+ const encodedString = unescape(encodeURIComponent(str));
234
+ const len = encodedString.length;
235
+ writeVarUint$1(encoder, len);
236
+ for (let i = 0; i < len; i++) {
237
+ write$1(encoder, /** @type {number} */ (encodedString.codePointAt(i)));
238
+ }
239
+ };
240
+
241
+ /**
242
+ * Write a variable length string.
243
+ *
244
+ * @function
245
+ * @param {Encoder} encoder
246
+ * @param {String} str The string that is to be encoded.
247
+ */
248
+ /* c8 ignore next */
249
+ const writeVarString$1 = (utf8TextEncoder$1 && /** @type {any} */ (utf8TextEncoder$1).encodeInto) ? _writeVarStringNative$1 : _writeVarStringPolyfill$1;
250
+
251
+ /**
252
+ * Append fixed-length Uint8Array to the encoder.
253
+ *
254
+ * @function
255
+ * @param {Encoder} encoder
256
+ * @param {Uint8Array} uint8Array
257
+ */
258
+ const writeUint8Array$1 = (encoder, uint8Array) => {
259
+ const bufferLen = encoder.cbuf.length;
260
+ const cpos = encoder.cpos;
261
+ const leftCopyLen = min$1(bufferLen - cpos, uint8Array.length);
262
+ const rightCopyLen = uint8Array.length - leftCopyLen;
263
+ encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
264
+ encoder.cpos += leftCopyLen;
265
+ if (rightCopyLen > 0) {
266
+ // Still something to write, write right half..
267
+ // Append new buffer
268
+ encoder.bufs.push(encoder.cbuf);
269
+ // must have at least size of remaining buffer
270
+ encoder.cbuf = new Uint8Array(max$1(bufferLen * 2, rightCopyLen));
271
+ // copy array
272
+ encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
273
+ encoder.cpos = rightCopyLen;
274
+ }
275
+ };
276
+
277
+ /**
278
+ * Append an Uint8Array to Encoder.
279
+ *
280
+ * @function
281
+ * @param {Encoder} encoder
282
+ * @param {Uint8Array} uint8Array
283
+ */
284
+ const writeVarUint8Array$1 = (encoder, uint8Array) => {
285
+ writeVarUint$1(encoder, uint8Array.byteLength);
286
+ writeUint8Array$1(encoder, uint8Array);
287
+ };
288
+
289
+ /**
290
+ * Error helpers.
291
+ *
292
+ * @module error
293
+ */
294
+
295
+ /**
296
+ * @param {string} s
297
+ * @return {Error}
298
+ */
299
+ /* c8 ignore next */
300
+ const create$3 = s => new Error(s);
301
+
302
+ /**
303
+ * Efficient schema-less binary decoding with support for variable length encoding.
304
+ *
305
+ * Use [lib0/decoding] with [lib0/encoding]. Every encoding function has a corresponding decoding function.
306
+ *
307
+ * Encodes numbers in little-endian order (least to most significant byte order)
308
+ * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
309
+ * which is also used in Protocol Buffers.
310
+ *
311
+ * ```js
312
+ * // encoding step
313
+ * const encoder = encoding.createEncoder()
314
+ * encoding.writeVarUint(encoder, 256)
315
+ * encoding.writeVarString(encoder, 'Hello world!')
316
+ * const buf = encoding.toUint8Array(encoder)
317
+ * ```
318
+ *
319
+ * ```js
320
+ * // decoding step
321
+ * const decoder = decoding.createDecoder(buf)
322
+ * decoding.readVarUint(decoder) // => 256
323
+ * decoding.readVarString(decoder) // => 'Hello world!'
324
+ * decoding.hasContent(decoder) // => false - all data is read
325
+ * ```
326
+ *
327
+ * @module decoding
328
+ */
329
+
330
+
331
+ const errorUnexpectedEndOfArray$1 = create$3('Unexpected end of array');
332
+ const errorIntegerOutOfRange$1 = create$3('Integer out of Range');
333
+
334
+ /**
335
+ * Create an Uint8Array view of the next `len` bytes and advance the position by `len`.
336
+ *
337
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
338
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
339
+ *
340
+ * @function
341
+ * @param {Decoder} decoder The decoder instance
342
+ * @param {number} len The length of bytes to read
343
+ * @return {Uint8Array}
344
+ */
345
+ const readUint8Array$1 = (decoder, len) => {
346
+ const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
347
+ decoder.pos += len;
348
+ return view
349
+ };
350
+
351
+ /**
352
+ * Read variable length Uint8Array.
353
+ *
354
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
355
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
356
+ *
357
+ * @function
358
+ * @param {Decoder} decoder
359
+ * @return {Uint8Array}
360
+ */
361
+ const readVarUint8Array$1 = decoder => readUint8Array$1(decoder, readVarUint$1(decoder));
362
+
363
+ /**
364
+ * Read one byte as unsigned integer.
365
+ * @function
366
+ * @param {Decoder} decoder The decoder instance
367
+ * @return {number} Unsigned 8-bit integer
368
+ */
369
+ const readUint8$1 = decoder => decoder.arr[decoder.pos++];
370
+
371
+ /**
372
+ * Read unsigned integer (32bit) with variable length.
373
+ * 1/8th of the storage is used as encoding overhead.
374
+ * * numbers < 2^7 is stored in one bytlength
375
+ * * numbers < 2^14 is stored in two bylength
376
+ *
377
+ * @function
378
+ * @param {Decoder} decoder
379
+ * @return {number} An unsigned integer.length
380
+ */
381
+ const readVarUint$1 = decoder => {
382
+ let num = 0;
383
+ let mult = 1;
384
+ const len = decoder.arr.length;
385
+ while (decoder.pos < len) {
386
+ const r = decoder.arr[decoder.pos++];
387
+ // num = num | ((r & binary.BITS7) << len)
388
+ num = num + (r & BITS7$1) * mult; // shift $r << (7*#iterations) and add it to num
389
+ mult *= 128; // next iteration, shift 7 "more" to the left
390
+ if (r < BIT8$1) {
391
+ return num
392
+ }
393
+ /* c8 ignore start */
394
+ if (num > MAX_SAFE_INTEGER$1) {
395
+ throw errorIntegerOutOfRange$1
396
+ }
397
+ /* c8 ignore stop */
398
+ }
399
+ throw errorUnexpectedEndOfArray$1
400
+ };
401
+
402
+ /**
403
+ * We don't test this function anymore as we use native decoding/encoding by default now.
404
+ * Better not modify this anymore..
405
+ *
406
+ * Transforming utf8 to a string is pretty expensive. The code performs 10x better
407
+ * when String.fromCodePoint is fed with all characters as arguments.
408
+ * But most environments have a maximum number of arguments per functions.
409
+ * For effiency reasons we apply a maximum of 10000 characters at once.
410
+ *
411
+ * @function
412
+ * @param {Decoder} decoder
413
+ * @return {String} The read String.
414
+ */
415
+ /* c8 ignore start */
416
+ const _readVarStringPolyfill$1 = decoder => {
417
+ let remainingLen = readVarUint$1(decoder);
418
+ if (remainingLen === 0) {
419
+ return ''
420
+ } else {
421
+ let encodedString = String.fromCodePoint(readUint8$1(decoder)); // remember to decrease remainingLen
422
+ if (--remainingLen < 100) { // do not create a Uint8Array for small strings
423
+ while (remainingLen--) {
424
+ encodedString += String.fromCodePoint(readUint8$1(decoder));
425
+ }
426
+ } else {
427
+ while (remainingLen > 0) {
428
+ const nextLen = remainingLen < 10000 ? remainingLen : 10000;
429
+ // this is dangerous, we create a fresh array view from the existing buffer
430
+ const bytes = decoder.arr.subarray(decoder.pos, decoder.pos + nextLen);
431
+ decoder.pos += nextLen;
432
+ // Starting with ES5.1 we can supply a generic array-like object as arguments
433
+ encodedString += String.fromCodePoint.apply(null, /** @type {any} */ (bytes));
434
+ remainingLen -= nextLen;
435
+ }
436
+ }
437
+ return decodeURIComponent(escape(encodedString))
438
+ }
439
+ };
440
+ /* c8 ignore stop */
441
+
442
+ /**
443
+ * @function
444
+ * @param {Decoder} decoder
445
+ * @return {String} The read String
446
+ */
447
+ const _readVarStringNative$1 = decoder =>
448
+ /** @type any */ (utf8TextDecoder$1).decode(readVarUint8Array$1(decoder));
449
+
450
+ /**
451
+ * Read string of variable length
452
+ * * varUint is used to store the length of the string
453
+ *
454
+ * @function
455
+ * @param {Decoder} decoder
456
+ * @return {String} The read String
457
+ *
458
+ */
459
+ /* c8 ignore next */
460
+ const readVarString$1 = utf8TextDecoder$1 ? _readVarStringNative$1 : _readVarStringPolyfill$1;
461
+
462
+ var AuthMessageType;
463
+ (function (AuthMessageType) {
464
+ AuthMessageType[AuthMessageType["Token"] = 0] = "Token";
465
+ AuthMessageType[AuthMessageType["PermissionDenied"] = 1] = "PermissionDenied";
466
+ AuthMessageType[AuthMessageType["Authenticated"] = 2] = "Authenticated";
467
+ })(AuthMessageType || (AuthMessageType = {}));
468
+ const writeAuthentication = (encoder, auth) => {
469
+ writeVarUint$1(encoder, AuthMessageType.Token);
470
+ writeVarString$1(encoder, auth);
471
+ };
472
+ const readAuthMessage = (decoder, sendToken, permissionDeniedHandler, authenticatedHandler) => {
473
+ switch (readVarUint$1(decoder)) {
474
+ case AuthMessageType.Token: {
475
+ sendToken();
476
+ break;
477
+ }
478
+ case AuthMessageType.PermissionDenied: {
479
+ permissionDeniedHandler(readVarString$1(decoder));
480
+ break;
481
+ }
482
+ case AuthMessageType.Authenticated: {
483
+ authenticatedHandler(readVarString$1(decoder));
484
+ break;
485
+ }
486
+ }
487
+ };
488
+
489
+ const awarenessStatesToArray = (states) => {
490
+ return Array.from(states.entries()).map(([key, value]) => {
491
+ return {
492
+ clientId: key,
493
+ ...value,
494
+ };
495
+ });
496
+ };
497
+
498
+ /**
499
+ * State of the WebSocket connection.
500
+ * https://developer.mozilla.org/de/docs/Web/API/WebSocket/readyState
501
+ */
502
+ var WsReadyStates;
503
+ (function (WsReadyStates) {
504
+ WsReadyStates[WsReadyStates["Connecting"] = 0] = "Connecting";
505
+ WsReadyStates[WsReadyStates["Open"] = 1] = "Open";
506
+ WsReadyStates[WsReadyStates["Closing"] = 2] = "Closing";
507
+ WsReadyStates[WsReadyStates["Closed"] = 3] = "Closed";
508
+ })(WsReadyStates || (WsReadyStates = {}));
509
+
510
+ function applyDefaults(options) {
511
+ if (!options) {
512
+ options = {};
513
+ }
514
+ return {
515
+ delay: (options.delay === undefined) ? 200 : options.delay,
516
+ initialDelay: (options.initialDelay === undefined) ? 0 : options.initialDelay,
517
+ minDelay: (options.minDelay === undefined) ? 0 : options.minDelay,
518
+ maxDelay: (options.maxDelay === undefined) ? 0 : options.maxDelay,
519
+ factor: (options.factor === undefined) ? 0 : options.factor,
520
+ maxAttempts: (options.maxAttempts === undefined) ? 3 : options.maxAttempts,
521
+ timeout: (options.timeout === undefined) ? 0 : options.timeout,
522
+ jitter: (options.jitter === true),
523
+ initialJitter: (options.initialJitter === true),
524
+ handleError: (options.handleError === undefined) ? null : options.handleError,
525
+ handleTimeout: (options.handleTimeout === undefined) ? null : options.handleTimeout,
526
+ beforeAttempt: (options.beforeAttempt === undefined) ? null : options.beforeAttempt,
527
+ calculateDelay: (options.calculateDelay === undefined) ? null : options.calculateDelay
528
+ };
529
+ }
530
+ async function sleep(delay) {
531
+ return new Promise((resolve) => setTimeout(resolve, delay));
532
+ }
533
+ function defaultCalculateDelay(context, options) {
534
+ let delay = options.delay;
535
+ if (delay === 0) {
536
+ // no delay between attempts
537
+ return 0;
538
+ }
539
+ if (options.factor) {
540
+ delay *= Math.pow(options.factor, context.attemptNum - 1);
541
+ if (options.maxDelay !== 0) {
542
+ delay = Math.min(delay, options.maxDelay);
543
+ }
544
+ }
545
+ if (options.jitter) {
546
+ // Jitter will result in a random value between `minDelay` and
547
+ // calculated delay for a given attempt.
548
+ // See https://www.awsarchitectureblog.com/2015/03/backoff.html
549
+ // We're using the "full jitter" strategy.
550
+ const min = Math.ceil(options.minDelay);
551
+ const max = Math.floor(delay);
552
+ delay = Math.floor(Math.random() * (max - min + 1)) + min;
553
+ }
554
+ return Math.round(delay);
555
+ }
556
+ async function retry(attemptFunc, attemptOptions) {
557
+ const options = applyDefaults(attemptOptions);
558
+ for (const prop of [
559
+ 'delay',
560
+ 'initialDelay',
561
+ 'minDelay',
562
+ 'maxDelay',
563
+ 'maxAttempts',
564
+ 'timeout'
565
+ ]) {
566
+ const value = options[prop];
567
+ if (!Number.isInteger(value) || (value < 0)) {
568
+ throw new Error(`Value for ${prop} must be an integer greater than or equal to 0`);
569
+ }
570
+ }
571
+ if ((options.factor.constructor !== Number) || (options.factor < 0)) {
572
+ throw new Error(`Value for factor must be a number greater than or equal to 0`);
573
+ }
574
+ if (options.delay < options.minDelay) {
575
+ throw new Error(`delay cannot be less than minDelay (delay: ${options.delay}, minDelay: ${options.minDelay}`);
576
+ }
577
+ const context = {
578
+ attemptNum: 0,
579
+ attemptsRemaining: options.maxAttempts ? options.maxAttempts : -1,
580
+ aborted: false,
581
+ abort() {
582
+ context.aborted = true;
583
+ }
584
+ };
585
+ const calculateDelay = options.calculateDelay || defaultCalculateDelay;
586
+ async function makeAttempt() {
587
+ if (options.beforeAttempt) {
588
+ options.beforeAttempt(context, options);
589
+ }
590
+ if (context.aborted) {
591
+ const err = new Error(`Attempt aborted`);
592
+ err.code = 'ATTEMPT_ABORTED';
593
+ throw err;
594
+ }
595
+ const onError = async (err) => {
596
+ if (options.handleError) {
597
+ await options.handleError(err, context, options);
598
+ }
599
+ if (context.aborted || (context.attemptsRemaining === 0)) {
600
+ throw err;
601
+ }
602
+ // We are about to try again so increment attempt number
603
+ context.attemptNum++;
604
+ const delay = calculateDelay(context, options);
605
+ if (delay) {
606
+ await sleep(delay);
607
+ }
608
+ return makeAttempt();
609
+ };
610
+ if (context.attemptsRemaining > 0) {
611
+ context.attemptsRemaining--;
612
+ }
613
+ if (options.timeout) {
614
+ return new Promise((resolve, reject) => {
615
+ const timer = setTimeout(() => {
616
+ if (options.handleTimeout) {
617
+ // If calling handleTimeout throws an error that is not wrapped in a promise
618
+ // we want to catch the error and reject.
619
+ try {
620
+ resolve(options.handleTimeout(context, options));
621
+ }
622
+ catch (e) {
623
+ reject(e);
624
+ }
625
+ }
626
+ else {
627
+ const err = new Error(`Retry timeout (attemptNum: ${context.attemptNum}, timeout: ${options.timeout})`);
628
+ err.code = 'ATTEMPT_TIMEOUT';
629
+ reject(err);
630
+ }
631
+ }, options.timeout);
632
+ attemptFunc(context, options).then((result) => {
633
+ clearTimeout(timer);
634
+ resolve(result);
635
+ }).catch((err) => {
636
+ clearTimeout(timer);
637
+ // Calling resolve with a Promise that rejects here will result
638
+ // in an unhandled rejection. Calling `reject` with errors
639
+ // does not result in an unhandled rejection
640
+ onError(err).then(resolve).catch(reject);
641
+ });
642
+ });
643
+ }
644
+ else {
645
+ // No timeout provided so wait indefinitely for the returned promise
646
+ // to be resolved.
647
+ return attemptFunc(context, options).catch(onError);
648
+ }
649
+ }
650
+ const initialDelay = options.calculateDelay
651
+ ? options.calculateDelay(context, options)
652
+ : options.initialDelay;
653
+ if (initialDelay) {
654
+ await sleep(initialDelay);
655
+ }
656
+ if (context.attemptNum < 1 && options.initialJitter) {
657
+ const delay = calculateDelay(context, options);
658
+ if (delay) {
659
+ await sleep(delay);
660
+ }
661
+ }
662
+ return makeAttempt();
663
+ }
664
+
665
+ /**
666
+ * Common Math expressions.
667
+ *
668
+ * @module math
669
+ */
670
+
671
+ const floor = Math.floor;
672
+
673
+ /**
674
+ * @function
675
+ * @param {number} a
676
+ * @param {number} b
677
+ * @return {number} The smaller element of a and b
678
+ */
679
+ const min = (a, b) => a < b ? a : b;
680
+
681
+ /**
682
+ * @function
683
+ * @param {number} a
684
+ * @param {number} b
685
+ * @return {number} The bigger element of a and b
686
+ */
687
+ const max = (a, b) => a > b ? a : b;
688
+
689
+ /* eslint-env browser */
690
+
691
+ const BIT7 = 64;
692
+ const BIT8 = 128;
693
+ const BITS6 = 63;
694
+ const BITS7 = 127;
695
+
696
+ /**
697
+ * Utility helpers for working with numbers.
698
+ *
699
+ * @module number
700
+ */
701
+
702
+
703
+ const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER;
704
+
705
+ /**
706
+ * Utility module to work with sets.
707
+ *
708
+ * @module set
709
+ */
710
+
711
+ const create$2 = () => new Set();
712
+
713
+ /**
714
+ * Utility module to work with Arrays.
715
+ *
716
+ * @module array
717
+ */
718
+
719
+
720
+ /**
721
+ * Transforms something array-like to an actual Array.
722
+ *
723
+ * @function
724
+ * @template T
725
+ * @param {ArrayLike<T>|Iterable<T>} arraylike
726
+ * @return {T}
727
+ */
728
+ const from = Array.from;
729
+
730
+ /**
731
+ * @param {string} str
732
+ * @return {Uint8Array}
733
+ */
734
+ const _encodeUtf8Polyfill = str => {
735
+ const encodedString = unescape(encodeURIComponent(str));
736
+ const len = encodedString.length;
737
+ const buf = new Uint8Array(len);
738
+ for (let i = 0; i < len; i++) {
739
+ buf[i] = /** @type {number} */ (encodedString.codePointAt(i));
740
+ }
741
+ return buf
742
+ };
743
+
744
+ /* c8 ignore next */
745
+ const utf8TextEncoder = /** @type {TextEncoder} */ (typeof TextEncoder !== 'undefined' ? new TextEncoder() : null);
746
+
747
+ /**
748
+ * @param {string} str
749
+ * @return {Uint8Array}
750
+ */
751
+ const _encodeUtf8Native = str => utf8TextEncoder.encode(str);
752
+
753
+ /**
754
+ * @param {string} str
755
+ * @return {Uint8Array}
756
+ */
757
+ /* c8 ignore next */
758
+ const encodeUtf8 = utf8TextEncoder ? _encodeUtf8Native : _encodeUtf8Polyfill;
759
+
760
+ /* c8 ignore next */
761
+ let utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
762
+
763
+ /* c8 ignore start */
764
+ if (utf8TextDecoder && utf8TextDecoder.decode(new Uint8Array()).length === 1) {
765
+ // Safari doesn't handle BOM correctly.
766
+ // This fixes a bug in Safari 13.0.5 where it produces a BOM the first time it is called.
767
+ // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the first call and
768
+ // utf8TextDecoder.decode(new Uint8Array()).length === 1 on the second call
769
+ // Another issue is that from then on no BOM chars are recognized anymore
770
+ /* c8 ignore next */
771
+ utf8TextDecoder = null;
772
+ }
773
+
774
+ /**
775
+ * Efficient schema-less binary encoding with support for variable length encoding.
776
+ *
777
+ * Use [lib0/encoding] with [lib0/decoding]. Every encoding function has a corresponding decoding function.
778
+ *
779
+ * Encodes numbers in little-endian order (least to most significant byte order)
780
+ * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
781
+ * which is also used in Protocol Buffers.
782
+ *
783
+ * ```js
784
+ * // encoding step
785
+ * const encoder = encoding.createEncoder()
786
+ * encoding.writeVarUint(encoder, 256)
787
+ * encoding.writeVarString(encoder, 'Hello world!')
788
+ * const buf = encoding.toUint8Array(encoder)
789
+ * ```
790
+ *
791
+ * ```js
792
+ * // decoding step
793
+ * const decoder = decoding.createDecoder(buf)
794
+ * decoding.readVarUint(decoder) // => 256
795
+ * decoding.readVarString(decoder) // => 'Hello world!'
796
+ * decoding.hasContent(decoder) // => false - all data is read
797
+ * ```
798
+ *
799
+ * @module encoding
800
+ */
801
+
802
+
803
+ /**
804
+ * A BinaryEncoder handles the encoding to an Uint8Array.
805
+ */
806
+ class Encoder {
807
+ constructor () {
808
+ this.cpos = 0;
809
+ this.cbuf = new Uint8Array(100);
810
+ /**
811
+ * @type {Array<Uint8Array>}
812
+ */
813
+ this.bufs = [];
814
+ }
815
+ }
816
+
817
+ /**
818
+ * @function
819
+ * @return {Encoder}
820
+ */
821
+ const createEncoder = () => new Encoder();
822
+
823
+ /**
824
+ * The current length of the encoded data.
825
+ *
826
+ * @function
827
+ * @param {Encoder} encoder
828
+ * @return {number}
829
+ */
830
+ const length$1 = encoder => {
831
+ let len = encoder.cpos;
832
+ for (let i = 0; i < encoder.bufs.length; i++) {
833
+ len += encoder.bufs[i].length;
834
+ }
835
+ return len
836
+ };
837
+
838
+ /**
839
+ * Transform to Uint8Array.
840
+ *
841
+ * @function
842
+ * @param {Encoder} encoder
843
+ * @return {Uint8Array} The created ArrayBuffer.
844
+ */
845
+ const toUint8Array = encoder => {
846
+ const uint8arr = new Uint8Array(length$1(encoder));
847
+ let curPos = 0;
848
+ for (let i = 0; i < encoder.bufs.length; i++) {
849
+ const d = encoder.bufs[i];
850
+ uint8arr.set(d, curPos);
851
+ curPos += d.length;
852
+ }
853
+ uint8arr.set(new Uint8Array(encoder.cbuf.buffer, 0, encoder.cpos), curPos);
854
+ return uint8arr
855
+ };
856
+
857
+ /**
858
+ * Write one byte to the encoder.
859
+ *
860
+ * @function
861
+ * @param {Encoder} encoder
862
+ * @param {number} num The byte that is to be encoded.
863
+ */
864
+ const write = (encoder, num) => {
865
+ const bufferLen = encoder.cbuf.length;
866
+ if (encoder.cpos === bufferLen) {
867
+ encoder.bufs.push(encoder.cbuf);
868
+ encoder.cbuf = new Uint8Array(bufferLen * 2);
869
+ encoder.cpos = 0;
870
+ }
871
+ encoder.cbuf[encoder.cpos++] = num;
872
+ };
873
+
874
+ /**
875
+ * Write a variable length unsigned integer. Max encodable integer is 2^53.
876
+ *
877
+ * @function
878
+ * @param {Encoder} encoder
879
+ * @param {number} num The number that is to be encoded.
880
+ */
881
+ const writeVarUint = (encoder, num) => {
882
+ while (num > BITS7) {
883
+ write(encoder, BIT8 | (BITS7 & num));
884
+ num = floor(num / 128); // shift >>> 7
885
+ }
886
+ write(encoder, BITS7 & num);
887
+ };
888
+
889
+ /**
890
+ * A cache to store strings temporarily
891
+ */
892
+ const _strBuffer = new Uint8Array(30000);
893
+ const _maxStrBSize = _strBuffer.length / 3;
894
+
895
+ /**
896
+ * Write a variable length string.
897
+ *
898
+ * @function
899
+ * @param {Encoder} encoder
900
+ * @param {String} str The string that is to be encoded.
901
+ */
902
+ const _writeVarStringNative = (encoder, str) => {
903
+ if (str.length < _maxStrBSize) {
904
+ // We can encode the string into the existing buffer
905
+ /* c8 ignore next */
906
+ const written = utf8TextEncoder.encodeInto(str, _strBuffer).written || 0;
907
+ writeVarUint(encoder, written);
908
+ for (let i = 0; i < written; i++) {
909
+ write(encoder, _strBuffer[i]);
910
+ }
911
+ } else {
912
+ writeVarUint8Array(encoder, encodeUtf8(str));
913
+ }
914
+ };
915
+
916
+ /**
917
+ * Write a variable length string.
918
+ *
919
+ * @function
920
+ * @param {Encoder} encoder
921
+ * @param {String} str The string that is to be encoded.
922
+ */
923
+ const _writeVarStringPolyfill = (encoder, str) => {
924
+ const encodedString = unescape(encodeURIComponent(str));
925
+ const len = encodedString.length;
926
+ writeVarUint(encoder, len);
927
+ for (let i = 0; i < len; i++) {
928
+ write(encoder, /** @type {number} */ (encodedString.codePointAt(i)));
929
+ }
930
+ };
931
+
932
+ /**
933
+ * Write a variable length string.
934
+ *
935
+ * @function
936
+ * @param {Encoder} encoder
937
+ * @param {String} str The string that is to be encoded.
938
+ */
939
+ /* c8 ignore next */
940
+ const writeVarString = (utf8TextEncoder && /** @type {any} */ (utf8TextEncoder).encodeInto) ? _writeVarStringNative : _writeVarStringPolyfill;
941
+
942
+ /**
943
+ * Append fixed-length Uint8Array to the encoder.
944
+ *
945
+ * @function
946
+ * @param {Encoder} encoder
947
+ * @param {Uint8Array} uint8Array
948
+ */
949
+ const writeUint8Array = (encoder, uint8Array) => {
950
+ const bufferLen = encoder.cbuf.length;
951
+ const cpos = encoder.cpos;
952
+ const leftCopyLen = min(bufferLen - cpos, uint8Array.length);
953
+ const rightCopyLen = uint8Array.length - leftCopyLen;
954
+ encoder.cbuf.set(uint8Array.subarray(0, leftCopyLen), cpos);
955
+ encoder.cpos += leftCopyLen;
956
+ if (rightCopyLen > 0) {
957
+ // Still something to write, write right half..
958
+ // Append new buffer
959
+ encoder.bufs.push(encoder.cbuf);
960
+ // must have at least size of remaining buffer
961
+ encoder.cbuf = new Uint8Array(max(bufferLen * 2, rightCopyLen));
962
+ // copy array
963
+ encoder.cbuf.set(uint8Array.subarray(leftCopyLen));
964
+ encoder.cpos = rightCopyLen;
965
+ }
966
+ };
967
+
968
+ /**
969
+ * Append an Uint8Array to Encoder.
970
+ *
971
+ * @function
972
+ * @param {Encoder} encoder
973
+ * @param {Uint8Array} uint8Array
974
+ */
975
+ const writeVarUint8Array = (encoder, uint8Array) => {
976
+ writeVarUint(encoder, uint8Array.byteLength);
977
+ writeUint8Array(encoder, uint8Array);
978
+ };
979
+
980
+ /**
981
+ * Error helpers.
982
+ *
983
+ * @module error
984
+ */
985
+
986
+ /**
987
+ * @param {string} s
988
+ * @return {Error}
989
+ */
990
+ /* c8 ignore next */
991
+ const create$1 = s => new Error(s);
992
+
993
+ /**
994
+ * Efficient schema-less binary decoding with support for variable length encoding.
995
+ *
996
+ * Use [lib0/decoding] with [lib0/encoding]. Every encoding function has a corresponding decoding function.
997
+ *
998
+ * Encodes numbers in little-endian order (least to most significant byte order)
999
+ * and is compatible with Golang's binary encoding (https://golang.org/pkg/encoding/binary/)
1000
+ * which is also used in Protocol Buffers.
1001
+ *
1002
+ * ```js
1003
+ * // encoding step
1004
+ * const encoder = encoding.createEncoder()
1005
+ * encoding.writeVarUint(encoder, 256)
1006
+ * encoding.writeVarString(encoder, 'Hello world!')
1007
+ * const buf = encoding.toUint8Array(encoder)
1008
+ * ```
1009
+ *
1010
+ * ```js
1011
+ * // decoding step
1012
+ * const decoder = decoding.createDecoder(buf)
1013
+ * decoding.readVarUint(decoder) // => 256
1014
+ * decoding.readVarString(decoder) // => 'Hello world!'
1015
+ * decoding.hasContent(decoder) // => false - all data is read
1016
+ * ```
1017
+ *
1018
+ * @module decoding
1019
+ */
1020
+
1021
+
1022
+ const errorUnexpectedEndOfArray = create$1('Unexpected end of array');
1023
+ const errorIntegerOutOfRange = create$1('Integer out of Range');
1024
+
1025
+ /**
1026
+ * A Decoder handles the decoding of an Uint8Array.
1027
+ */
1028
+ class Decoder {
1029
+ /**
1030
+ * @param {Uint8Array} uint8Array Binary data to decode
1031
+ */
1032
+ constructor (uint8Array) {
1033
+ /**
1034
+ * Decoding target.
1035
+ *
1036
+ * @type {Uint8Array}
1037
+ */
1038
+ this.arr = uint8Array;
1039
+ /**
1040
+ * Current decoding position.
1041
+ *
1042
+ * @type {number}
1043
+ */
1044
+ this.pos = 0;
1045
+ }
1046
+ }
1047
+
1048
+ /**
1049
+ * @function
1050
+ * @param {Uint8Array} uint8Array
1051
+ * @return {Decoder}
1052
+ */
1053
+ const createDecoder = uint8Array => new Decoder(uint8Array);
1054
+
1055
+ /**
1056
+ * Create an Uint8Array view of the next `len` bytes and advance the position by `len`.
1057
+ *
1058
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
1059
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
1060
+ *
1061
+ * @function
1062
+ * @param {Decoder} decoder The decoder instance
1063
+ * @param {number} len The length of bytes to read
1064
+ * @return {Uint8Array}
1065
+ */
1066
+ const readUint8Array = (decoder, len) => {
1067
+ const view = new Uint8Array(decoder.arr.buffer, decoder.pos + decoder.arr.byteOffset, len);
1068
+ decoder.pos += len;
1069
+ return view
1070
+ };
1071
+
1072
+ /**
1073
+ * Read variable length Uint8Array.
1074
+ *
1075
+ * Important: The Uint8Array still points to the underlying ArrayBuffer. Make sure to discard the result as soon as possible to prevent any memory leaks.
1076
+ * Use `buffer.copyUint8Array` to copy the result into a new Uint8Array.
1077
+ *
1078
+ * @function
1079
+ * @param {Decoder} decoder
1080
+ * @return {Uint8Array}
1081
+ */
1082
+ const readVarUint8Array = decoder => readUint8Array(decoder, readVarUint(decoder));
1083
+
1084
+ /**
1085
+ * Read one byte as unsigned integer.
1086
+ * @function
1087
+ * @param {Decoder} decoder The decoder instance
1088
+ * @return {number} Unsigned 8-bit integer
1089
+ */
1090
+ const readUint8 = decoder => decoder.arr[decoder.pos++];
1091
+
1092
+ /**
1093
+ * Read unsigned integer (32bit) with variable length.
1094
+ * 1/8th of the storage is used as encoding overhead.
1095
+ * * numbers < 2^7 is stored in one bytlength
1096
+ * * numbers < 2^14 is stored in two bylength
1097
+ *
1098
+ * @function
1099
+ * @param {Decoder} decoder
1100
+ * @return {number} An unsigned integer.length
1101
+ */
1102
+ const readVarUint = decoder => {
1103
+ let num = 0;
1104
+ let mult = 1;
1105
+ const len = decoder.arr.length;
1106
+ while (decoder.pos < len) {
1107
+ const r = decoder.arr[decoder.pos++];
1108
+ // num = num | ((r & binary.BITS7) << len)
1109
+ num = num + (r & BITS7) * mult; // shift $r << (7*#iterations) and add it to num
1110
+ mult *= 128; // next iteration, shift 7 "more" to the left
1111
+ if (r < BIT8) {
1112
+ return num
1113
+ }
1114
+ /* c8 ignore start */
1115
+ if (num > MAX_SAFE_INTEGER) {
1116
+ throw errorIntegerOutOfRange
1117
+ }
1118
+ /* c8 ignore stop */
1119
+ }
1120
+ throw errorUnexpectedEndOfArray
1121
+ };
1122
+
1123
+ /**
1124
+ * Read signed integer (32bit) with variable length.
1125
+ * 1/8th of the storage is used as encoding overhead.
1126
+ * * numbers < 2^7 is stored in one bytlength
1127
+ * * numbers < 2^14 is stored in two bylength
1128
+ * @todo This should probably create the inverse ~num if number is negative - but this would be a breaking change.
1129
+ *
1130
+ * @function
1131
+ * @param {Decoder} decoder
1132
+ * @return {number} An unsigned integer.length
1133
+ */
1134
+ const readVarInt = decoder => {
1135
+ let r = decoder.arr[decoder.pos++];
1136
+ let num = r & BITS6;
1137
+ let mult = 64;
1138
+ const sign = (r & BIT7) > 0 ? -1 : 1;
1139
+ if ((r & BIT8) === 0) {
1140
+ // don't continue reading
1141
+ return sign * num
1142
+ }
1143
+ const len = decoder.arr.length;
1144
+ while (decoder.pos < len) {
1145
+ r = decoder.arr[decoder.pos++];
1146
+ // num = num | ((r & binary.BITS7) << len)
1147
+ num = num + (r & BITS7) * mult;
1148
+ mult *= 128;
1149
+ if (r < BIT8) {
1150
+ return sign * num
1151
+ }
1152
+ /* c8 ignore start */
1153
+ if (num > MAX_SAFE_INTEGER) {
1154
+ throw errorIntegerOutOfRange
1155
+ }
1156
+ /* c8 ignore stop */
1157
+ }
1158
+ throw errorUnexpectedEndOfArray
1159
+ };
1160
+
1161
+ /**
1162
+ * We don't test this function anymore as we use native decoding/encoding by default now.
1163
+ * Better not modify this anymore..
1164
+ *
1165
+ * Transforming utf8 to a string is pretty expensive. The code performs 10x better
1166
+ * when String.fromCodePoint is fed with all characters as arguments.
1167
+ * But most environments have a maximum number of arguments per functions.
1168
+ * For effiency reasons we apply a maximum of 10000 characters at once.
1169
+ *
1170
+ * @function
1171
+ * @param {Decoder} decoder
1172
+ * @return {String} The read String.
1173
+ */
1174
+ /* c8 ignore start */
1175
+ const _readVarStringPolyfill = decoder => {
1176
+ let remainingLen = readVarUint(decoder);
1177
+ if (remainingLen === 0) {
1178
+ return ''
1179
+ } else {
1180
+ let encodedString = String.fromCodePoint(readUint8(decoder)); // remember to decrease remainingLen
1181
+ if (--remainingLen < 100) { // do not create a Uint8Array for small strings
1182
+ while (remainingLen--) {
1183
+ encodedString += String.fromCodePoint(readUint8(decoder));
1184
+ }
1185
+ } else {
1186
+ while (remainingLen > 0) {
1187
+ const nextLen = remainingLen < 10000 ? remainingLen : 10000;
1188
+ // this is dangerous, we create a fresh array view from the existing buffer
1189
+ const bytes = decoder.arr.subarray(decoder.pos, decoder.pos + nextLen);
1190
+ decoder.pos += nextLen;
1191
+ // Starting with ES5.1 we can supply a generic array-like object as arguments
1192
+ encodedString += String.fromCodePoint.apply(null, /** @type {any} */ (bytes));
1193
+ remainingLen -= nextLen;
1194
+ }
1195
+ }
1196
+ return decodeURIComponent(escape(encodedString))
1197
+ }
1198
+ };
1199
+ /* c8 ignore stop */
1200
+
1201
+ /**
1202
+ * @function
1203
+ * @param {Decoder} decoder
1204
+ * @return {String} The read String
1205
+ */
1206
+ const _readVarStringNative = decoder =>
1207
+ /** @type any */ (utf8TextDecoder).decode(readVarUint8Array(decoder));
1208
+
1209
+ /**
1210
+ * Read string of variable length
1211
+ * * varUint is used to store the length of the string
1212
+ *
1213
+ * @function
1214
+ * @param {Decoder} decoder
1215
+ * @return {String} The read String
1216
+ *
1217
+ */
1218
+ /* c8 ignore next */
1219
+ const readVarString = utf8TextDecoder ? _readVarStringNative : _readVarStringPolyfill;
1220
+
1221
+ /**
1222
+ * Look ahead and read varString without incrementing position
1223
+ *
1224
+ * @function
1225
+ * @param {Decoder} decoder
1226
+ * @return {string}
1227
+ */
1228
+ const peekVarString = decoder => {
1229
+ const pos = decoder.pos;
1230
+ const s = readVarString(decoder);
1231
+ decoder.pos = pos;
1232
+ return s
1233
+ };
1234
+
1235
+ /**
1236
+ * Utility module to work with time.
1237
+ *
1238
+ * @module time
1239
+ */
1240
+
1241
+
1242
+ /**
1243
+ * Return current unix time.
1244
+ *
1245
+ * @return {number}
1246
+ */
1247
+ const getUnixTime = Date.now;
1248
+
1249
+ /**
1250
+ * Utility module to work with key-value stores.
1251
+ *
1252
+ * @module map
1253
+ */
1254
+
1255
+ /**
1256
+ * Creates a new Map instance.
1257
+ *
1258
+ * @function
1259
+ * @return {Map<any, any>}
1260
+ *
1261
+ * @function
1262
+ */
1263
+ const create = () => new Map();
1264
+
1265
+ /**
1266
+ * Get map property. Create T if property is undefined and set T on map.
1267
+ *
1268
+ * ```js
1269
+ * const listeners = map.setIfUndefined(events, 'eventName', set.create)
1270
+ * listeners.add(listener)
1271
+ * ```
1272
+ *
1273
+ * @function
1274
+ * @template {Map<any, any>} MAP
1275
+ * @template {MAP extends Map<any,infer V> ? function():V : unknown} CF
1276
+ * @param {MAP} map
1277
+ * @param {MAP extends Map<infer K,any> ? K : unknown} key
1278
+ * @param {CF} createT
1279
+ * @return {ReturnType<CF>}
1280
+ */
1281
+ const setIfUndefined = (map, key, createT) => {
1282
+ let set = map.get(key);
1283
+ if (set === undefined) {
1284
+ map.set(key, set = createT());
1285
+ }
1286
+ return set
1287
+ };
1288
+
1289
+ /**
1290
+ * Observable class prototype.
1291
+ *
1292
+ * @module observable
1293
+ */
1294
+
1295
+
1296
+ /* c8 ignore start */
1297
+ /**
1298
+ * Handles named events.
1299
+ *
1300
+ * @deprecated
1301
+ * @template N
1302
+ */
1303
+ class Observable {
1304
+ constructor () {
1305
+ /**
1306
+ * Some desc.
1307
+ * @type {Map<N, any>}
1308
+ */
1309
+ this._observers = create();
1310
+ }
1311
+
1312
+ /**
1313
+ * @param {N} name
1314
+ * @param {function} f
1315
+ */
1316
+ on (name, f) {
1317
+ setIfUndefined(this._observers, name, create$2).add(f);
1318
+ }
1319
+
1320
+ /**
1321
+ * @param {N} name
1322
+ * @param {function} f
1323
+ */
1324
+ once (name, f) {
1325
+ /**
1326
+ * @param {...any} args
1327
+ */
1328
+ const _f = (...args) => {
1329
+ this.off(name, _f);
1330
+ f(...args);
1331
+ };
1332
+ this.on(name, _f);
1333
+ }
1334
+
1335
+ /**
1336
+ * @param {N} name
1337
+ * @param {function} f
1338
+ */
1339
+ off (name, f) {
1340
+ const observers = this._observers.get(name);
1341
+ if (observers !== undefined) {
1342
+ observers.delete(f);
1343
+ if (observers.size === 0) {
1344
+ this._observers.delete(name);
1345
+ }
1346
+ }
1347
+ }
1348
+
1349
+ /**
1350
+ * Emit a named event. All registered event listeners that listen to the
1351
+ * specified name will receive the event.
1352
+ *
1353
+ * @todo This should catch exceptions
1354
+ *
1355
+ * @param {N} name The event name.
1356
+ * @param {Array<any>} args The arguments that are applied to the event listener.
1357
+ */
1358
+ emit (name, args) {
1359
+ // copy all listeners to an array first to make sure that no event is emitted to listeners that are subscribed while the event handler is called.
1360
+ return from((this._observers.get(name) || create()).values()).forEach(f => f(...args))
1361
+ }
1362
+
1363
+ destroy () {
1364
+ this._observers = create();
1365
+ }
1366
+ }
1367
+ /* c8 ignore end */
1368
+
1369
+ /**
1370
+ * Utility functions for working with EcmaScript objects.
1371
+ *
1372
+ * @module object
1373
+ */
1374
+
1375
+
1376
+ /**
1377
+ * @param {Object<string,any>} obj
1378
+ */
1379
+ const keys = Object.keys;
1380
+
1381
+ /**
1382
+ * @deprecated use object.size instead
1383
+ * @param {Object<string,any>} obj
1384
+ * @return {number}
1385
+ */
1386
+ const length = obj => keys(obj).length;
1387
+
1388
+ /**
1389
+ * Calls `Object.prototype.hasOwnProperty`.
1390
+ *
1391
+ * @param {any} obj
1392
+ * @param {string|symbol} key
1393
+ * @return {boolean}
1394
+ */
1395
+ const hasProperty = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
1396
+
1397
+ /**
1398
+ * Common functions and function call helpers.
1399
+ *
1400
+ * @module function
1401
+ */
1402
+
1403
+
1404
+ /**
1405
+ * @template T
1406
+ *
1407
+ * @param {T} a
1408
+ * @param {T} b
1409
+ * @return {boolean}
1410
+ */
1411
+ const equalityStrict = (a, b) => a === b;
1412
+
1413
+ /* c8 ignore start */
1414
+
1415
+ /**
1416
+ * @param {any} a
1417
+ * @param {any} b
1418
+ * @return {boolean}
1419
+ */
1420
+ const equalityDeep = (a, b) => {
1421
+ if (a == null || b == null) {
1422
+ return equalityStrict(a, b)
1423
+ }
1424
+ if (a.constructor !== b.constructor) {
1425
+ return false
1426
+ }
1427
+ if (a === b) {
1428
+ return true
1429
+ }
1430
+ switch (a.constructor) {
1431
+ case ArrayBuffer:
1432
+ a = new Uint8Array(a);
1433
+ b = new Uint8Array(b);
1434
+ // eslint-disable-next-line no-fallthrough
1435
+ case Uint8Array: {
1436
+ if (a.byteLength !== b.byteLength) {
1437
+ return false
1438
+ }
1439
+ for (let i = 0; i < a.length; i++) {
1440
+ if (a[i] !== b[i]) {
1441
+ return false
1442
+ }
1443
+ }
1444
+ break
1445
+ }
1446
+ case Set: {
1447
+ if (a.size !== b.size) {
1448
+ return false
1449
+ }
1450
+ for (const value of a) {
1451
+ if (!b.has(value)) {
1452
+ return false
1453
+ }
1454
+ }
1455
+ break
1456
+ }
1457
+ case Map: {
1458
+ if (a.size !== b.size) {
1459
+ return false
1460
+ }
1461
+ for (const key of a.keys()) {
1462
+ if (!b.has(key) || !equalityDeep(a.get(key), b.get(key))) {
1463
+ return false
1464
+ }
1465
+ }
1466
+ break
1467
+ }
1468
+ case Object:
1469
+ if (length(a) !== length(b)) {
1470
+ return false
1471
+ }
1472
+ for (const key in a) {
1473
+ if (!hasProperty(a, key) || !equalityDeep(a[key], b[key])) {
1474
+ return false
1475
+ }
1476
+ }
1477
+ break
1478
+ case Array:
1479
+ if (a.length !== b.length) {
1480
+ return false
1481
+ }
1482
+ for (let i = 0; i < a.length; i++) {
1483
+ if (!equalityDeep(a[i], b[i])) {
1484
+ return false
1485
+ }
1486
+ }
1487
+ break
1488
+ default:
1489
+ return false
1490
+ }
1491
+ return true
1492
+ };
1493
+
1494
+ /**
1495
+ * @module awareness-protocol
1496
+ */
1497
+
1498
+
1499
+ const outdatedTimeout = 30000;
1500
+
1501
+ /**
1502
+ * @typedef {Object} MetaClientState
1503
+ * @property {number} MetaClientState.clock
1504
+ * @property {number} MetaClientState.lastUpdated unix timestamp
1505
+ */
1506
+
1507
+ /**
1508
+ * The Awareness class implements a simple shared state protocol that can be used for non-persistent data like awareness information
1509
+ * (cursor, username, status, ..). Each client can update its own local state and listen to state changes of
1510
+ * remote clients. Every client may set a state of a remote peer to `null` to mark the client as offline.
1511
+ *
1512
+ * Each client is identified by a unique client id (something we borrow from `doc.clientID`). A client can override
1513
+ * its own state by propagating a message with an increasing timestamp (`clock`). If such a message is received, it is
1514
+ * applied if the known state of that client is older than the new state (`clock < newClock`). If a client thinks that
1515
+ * a remote client is offline, it may propagate a message with
1516
+ * `{ clock: currentClientClock, state: null, client: remoteClient }`. If such a
1517
+ * message is received, and the known clock of that client equals the received clock, it will override the state with `null`.
1518
+ *
1519
+ * Before a client disconnects, it should propagate a `null` state with an updated clock.
1520
+ *
1521
+ * Awareness states must be updated every 30 seconds. Otherwise the Awareness instance will delete the client state.
1522
+ *
1523
+ * @extends {Observable<string>}
1524
+ */
1525
+ class Awareness extends Observable {
1526
+ /**
1527
+ * @param {Y.Doc} doc
1528
+ */
1529
+ constructor (doc) {
1530
+ super();
1531
+ this.doc = doc;
1532
+ /**
1533
+ * @type {number}
1534
+ */
1535
+ this.clientID = doc.clientID;
1536
+ /**
1537
+ * Maps from client id to client state
1538
+ * @type {Map<number, Object<string, any>>}
1539
+ */
1540
+ this.states = new Map();
1541
+ /**
1542
+ * @type {Map<number, MetaClientState>}
1543
+ */
1544
+ this.meta = new Map();
1545
+ this._checkInterval = /** @type {any} */ (setInterval(() => {
1546
+ const now = getUnixTime();
1547
+ if (this.getLocalState() !== null && (outdatedTimeout / 2 <= now - /** @type {{lastUpdated:number}} */ (this.meta.get(this.clientID)).lastUpdated)) {
1548
+ // renew local clock
1549
+ this.setLocalState(this.getLocalState());
1550
+ }
1551
+ /**
1552
+ * @type {Array<number>}
1553
+ */
1554
+ const remove = [];
1555
+ this.meta.forEach((meta, clientid) => {
1556
+ if (clientid !== this.clientID && outdatedTimeout <= now - meta.lastUpdated && this.states.has(clientid)) {
1557
+ remove.push(clientid);
1558
+ }
1559
+ });
1560
+ if (remove.length > 0) {
1561
+ removeAwarenessStates(this, remove, 'timeout');
1562
+ }
1563
+ }, floor(outdatedTimeout / 10)));
1564
+ doc.on('destroy', () => {
1565
+ this.destroy();
1566
+ });
1567
+ this.setLocalState({});
1568
+ }
1569
+
1570
+ destroy () {
1571
+ this.emit('destroy', [this]);
1572
+ this.setLocalState(null);
1573
+ super.destroy();
1574
+ clearInterval(this._checkInterval);
1575
+ }
1576
+
1577
+ /**
1578
+ * @return {Object<string,any>|null}
1579
+ */
1580
+ getLocalState () {
1581
+ return this.states.get(this.clientID) || null
1582
+ }
1583
+
1584
+ /**
1585
+ * @param {Object<string,any>|null} state
1586
+ */
1587
+ setLocalState (state) {
1588
+ const clientID = this.clientID;
1589
+ const currLocalMeta = this.meta.get(clientID);
1590
+ const clock = currLocalMeta === undefined ? 0 : currLocalMeta.clock + 1;
1591
+ const prevState = this.states.get(clientID);
1592
+ if (state === null) {
1593
+ this.states.delete(clientID);
1594
+ } else {
1595
+ this.states.set(clientID, state);
1596
+ }
1597
+ this.meta.set(clientID, {
1598
+ clock,
1599
+ lastUpdated: getUnixTime()
1600
+ });
1601
+ const added = [];
1602
+ const updated = [];
1603
+ const filteredUpdated = [];
1604
+ const removed = [];
1605
+ if (state === null) {
1606
+ removed.push(clientID);
1607
+ } else if (prevState == null) {
1608
+ if (state != null) {
1609
+ added.push(clientID);
1610
+ }
1611
+ } else {
1612
+ updated.push(clientID);
1613
+ if (!equalityDeep(prevState, state)) {
1614
+ filteredUpdated.push(clientID);
1615
+ }
1616
+ }
1617
+ if (added.length > 0 || filteredUpdated.length > 0 || removed.length > 0) {
1618
+ this.emit('change', [{ added, updated: filteredUpdated, removed }, 'local']);
1619
+ }
1620
+ this.emit('update', [{ added, updated, removed }, 'local']);
1621
+ }
1622
+
1623
+ /**
1624
+ * @param {string} field
1625
+ * @param {any} value
1626
+ */
1627
+ setLocalStateField (field, value) {
1628
+ const state = this.getLocalState();
1629
+ if (state !== null) {
1630
+ this.setLocalState({
1631
+ ...state,
1632
+ [field]: value
1633
+ });
1634
+ }
1635
+ }
1636
+
1637
+ /**
1638
+ * @return {Map<number,Object<string,any>>}
1639
+ */
1640
+ getStates () {
1641
+ return this.states
1642
+ }
1643
+ }
1644
+
1645
+ /**
1646
+ * Mark (remote) clients as inactive and remove them from the list of active peers.
1647
+ * This change will be propagated to remote clients.
1648
+ *
1649
+ * @param {Awareness} awareness
1650
+ * @param {Array<number>} clients
1651
+ * @param {any} origin
1652
+ */
1653
+ const removeAwarenessStates = (awareness, clients, origin) => {
1654
+ const removed = [];
1655
+ for (let i = 0; i < clients.length; i++) {
1656
+ const clientID = clients[i];
1657
+ if (awareness.states.has(clientID)) {
1658
+ awareness.states.delete(clientID);
1659
+ if (clientID === awareness.clientID) {
1660
+ const curMeta = /** @type {MetaClientState} */ (awareness.meta.get(clientID));
1661
+ awareness.meta.set(clientID, {
1662
+ clock: curMeta.clock + 1,
1663
+ lastUpdated: getUnixTime()
1664
+ });
1665
+ }
1666
+ removed.push(clientID);
1667
+ }
1668
+ }
1669
+ if (removed.length > 0) {
1670
+ awareness.emit('change', [{ added: [], updated: [], removed }, origin]);
1671
+ awareness.emit('update', [{ added: [], updated: [], removed }, origin]);
1672
+ }
1673
+ };
1674
+
1675
+ /**
1676
+ * @param {Awareness} awareness
1677
+ * @param {Array<number>} clients
1678
+ * @return {Uint8Array}
1679
+ */
1680
+ const encodeAwarenessUpdate = (awareness, clients, states = awareness.states) => {
1681
+ const len = clients.length;
1682
+ const encoder = createEncoder();
1683
+ writeVarUint(encoder, len);
1684
+ for (let i = 0; i < len; i++) {
1685
+ const clientID = clients[i];
1686
+ const state = states.get(clientID) || null;
1687
+ const clock = /** @type {MetaClientState} */ (awareness.meta.get(clientID)).clock;
1688
+ writeVarUint(encoder, clientID);
1689
+ writeVarUint(encoder, clock);
1690
+ writeVarString(encoder, JSON.stringify(state));
1691
+ }
1692
+ return toUint8Array(encoder)
1693
+ };
1694
+
1695
+ /**
1696
+ * @param {Awareness} awareness
1697
+ * @param {Uint8Array} update
1698
+ * @param {any} origin This will be added to the emitted change event
1699
+ */
1700
+ const applyAwarenessUpdate = (awareness, update, origin) => {
1701
+ const decoder = createDecoder(update);
1702
+ const timestamp = getUnixTime();
1703
+ const added = [];
1704
+ const updated = [];
1705
+ const filteredUpdated = [];
1706
+ const removed = [];
1707
+ const len = readVarUint(decoder);
1708
+ for (let i = 0; i < len; i++) {
1709
+ const clientID = readVarUint(decoder);
1710
+ let clock = readVarUint(decoder);
1711
+ const state = JSON.parse(readVarString(decoder));
1712
+ const clientMeta = awareness.meta.get(clientID);
1713
+ const prevState = awareness.states.get(clientID);
1714
+ const currClock = clientMeta === undefined ? 0 : clientMeta.clock;
1715
+ if (currClock < clock || (currClock === clock && state === null && awareness.states.has(clientID))) {
1716
+ if (state === null) {
1717
+ // never let a remote client remove this local state
1718
+ if (clientID === awareness.clientID && awareness.getLocalState() != null) {
1719
+ // remote client removed the local state. Do not remote state. Broadcast a message indicating
1720
+ // that this client still exists by increasing the clock
1721
+ clock++;
1722
+ } else {
1723
+ awareness.states.delete(clientID);
1724
+ }
1725
+ } else {
1726
+ awareness.states.set(clientID, state);
1727
+ }
1728
+ awareness.meta.set(clientID, {
1729
+ clock,
1730
+ lastUpdated: timestamp
1731
+ });
1732
+ if (clientMeta === undefined && state !== null) {
1733
+ added.push(clientID);
1734
+ } else if (clientMeta !== undefined && state === null) {
1735
+ removed.push(clientID);
1736
+ } else if (state !== null) {
1737
+ if (!equalityDeep(state, prevState)) {
1738
+ filteredUpdated.push(clientID);
1739
+ }
1740
+ updated.push(clientID);
1741
+ }
1742
+ }
1743
+ }
1744
+ if (added.length > 0 || filteredUpdated.length > 0 || removed.length > 0) {
1745
+ awareness.emit('change', [{
1746
+ added, updated: filteredUpdated, removed
1747
+ }, origin]);
1748
+ }
1749
+ if (added.length > 0 || updated.length > 0 || removed.length > 0) {
1750
+ awareness.emit('update', [{
1751
+ added, updated, removed
1752
+ }, origin]);
1753
+ }
1754
+ };
1755
+
1756
+ class EventEmitter {
1757
+ constructor() {
1758
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
1759
+ this.callbacks = {};
1760
+ }
1761
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
1762
+ on(event, fn) {
1763
+ if (!this.callbacks[event]) {
1764
+ this.callbacks[event] = [];
1765
+ }
1766
+ this.callbacks[event].push(fn);
1767
+ return this;
1768
+ }
1769
+ emit(event, ...args) {
1770
+ const callbacks = this.callbacks[event];
1771
+ if (callbacks) {
1772
+ callbacks.forEach((callback) => callback.apply(this, args));
1773
+ }
1774
+ return this;
1775
+ }
1776
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
1777
+ off(event, fn) {
1778
+ const callbacks = this.callbacks[event];
1779
+ if (callbacks) {
1780
+ if (fn) {
1781
+ this.callbacks[event] = callbacks.filter((callback) => callback !== fn);
1782
+ }
1783
+ else {
1784
+ delete this.callbacks[event];
1785
+ }
1786
+ }
1787
+ return this;
1788
+ }
1789
+ removeAllListeners() {
1790
+ this.callbacks = {};
1791
+ }
1792
+ }
1793
+
1794
+ class IncomingMessage {
1795
+ constructor(data) {
1796
+ this.data = data;
1797
+ this.encoder = createEncoder();
1798
+ this.decoder = createDecoder(new Uint8Array(this.data));
1799
+ }
1800
+ peekVarString() {
1801
+ return peekVarString(this.decoder);
1802
+ }
1803
+ readVarUint() {
1804
+ return readVarUint(this.decoder);
1805
+ }
1806
+ readVarString() {
1807
+ return readVarString(this.decoder);
1808
+ }
1809
+ readVarUint8Array() {
1810
+ return readVarUint8Array(this.decoder);
1811
+ }
1812
+ writeVarUint(type) {
1813
+ return writeVarUint(this.encoder, type);
1814
+ }
1815
+ writeVarString(string) {
1816
+ return writeVarString(this.encoder, string);
1817
+ }
1818
+ writeVarUint8Array(data) {
1819
+ return writeVarUint8Array(this.encoder, data);
1820
+ }
1821
+ length() {
1822
+ return length$1(this.encoder);
1823
+ }
1824
+ }
1825
+
1826
+ var MessageType;
1827
+ (function (MessageType) {
1828
+ MessageType[MessageType["Sync"] = 0] = "Sync";
1829
+ MessageType[MessageType["Awareness"] = 1] = "Awareness";
1830
+ MessageType[MessageType["Auth"] = 2] = "Auth";
1831
+ MessageType[MessageType["QueryAwareness"] = 3] = "QueryAwareness";
1832
+ MessageType[MessageType["Stateless"] = 5] = "Stateless";
1833
+ MessageType[MessageType["CLOSE"] = 7] = "CLOSE";
1834
+ MessageType[MessageType["SyncStatus"] = 8] = "SyncStatus";
1835
+ })(MessageType || (MessageType = {}));
1836
+ var WebSocketStatus;
1837
+ (function (WebSocketStatus) {
1838
+ WebSocketStatus["Connecting"] = "connecting";
1839
+ WebSocketStatus["Connected"] = "connected";
1840
+ WebSocketStatus["Disconnected"] = "disconnected";
1841
+ })(WebSocketStatus || (WebSocketStatus = {}));
1842
+
1843
+ class OutgoingMessage {
1844
+ constructor() {
1845
+ this.encoder = createEncoder();
1846
+ }
1847
+ get(args) {
1848
+ return args.encoder;
1849
+ }
1850
+ toUint8Array() {
1851
+ return toUint8Array(this.encoder);
1852
+ }
1853
+ }
1854
+
1855
+ class CloseMessage extends OutgoingMessage {
1856
+ constructor() {
1857
+ super(...arguments);
1858
+ this.type = MessageType.CLOSE;
1859
+ this.description = "Ask the server to close the connection";
1860
+ }
1861
+ get(args) {
1862
+ writeVarString(this.encoder, args.documentName);
1863
+ writeVarUint(this.encoder, this.type);
1864
+ return this.encoder;
1865
+ }
1866
+ }
1867
+
1868
+ class HocuspocusProviderWebsocket extends EventEmitter {
1869
+ constructor(configuration) {
1870
+ super();
1871
+ this.messageQueue = [];
1872
+ this.configuration = {
1873
+ url: "",
1874
+ autoConnect: true,
1875
+ preserveTrailingSlash: false,
1876
+ // @ts-ignore
1877
+ document: undefined,
1878
+ WebSocketPolyfill: undefined,
1879
+ // TODO: this should depend on awareness.outdatedTime
1880
+ messageReconnectTimeout: 30000,
1881
+ // 1 second
1882
+ delay: 1000,
1883
+ // instant
1884
+ initialDelay: 0,
1885
+ // double the delay each time
1886
+ factor: 2,
1887
+ // unlimited retries
1888
+ maxAttempts: 0,
1889
+ // wait at least 1 second
1890
+ minDelay: 1000,
1891
+ // at least every 30 seconds
1892
+ maxDelay: 30000,
1893
+ // randomize
1894
+ jitter: true,
1895
+ // retry forever
1896
+ timeout: 0,
1897
+ onOpen: () => null,
1898
+ onConnect: () => null,
1899
+ onMessage: () => null,
1900
+ onOutgoingMessage: () => null,
1901
+ onStatus: () => null,
1902
+ onDisconnect: () => null,
1903
+ onClose: () => null,
1904
+ onDestroy: () => null,
1905
+ onAwarenessUpdate: () => null,
1906
+ onAwarenessChange: () => null,
1907
+ handleTimeout: null,
1908
+ providerMap: new Map(),
1909
+ };
1910
+ this.webSocket = null;
1911
+ this.webSocketHandlers = {};
1912
+ this.shouldConnect = true;
1913
+ this.status = WebSocketStatus.Disconnected;
1914
+ this.lastMessageReceived = 0;
1915
+ this.identifier = 0;
1916
+ this.intervals = {
1917
+ connectionChecker: null,
1918
+ };
1919
+ this.connectionAttempt = null;
1920
+ this.receivedOnOpenPayload = undefined;
1921
+ this.closeTries = 0;
1922
+ this.setConfiguration(configuration);
1923
+ this.configuration.WebSocketPolyfill = configuration.WebSocketPolyfill
1924
+ ? configuration.WebSocketPolyfill
1925
+ : WebSocket;
1926
+ this.on("open", this.configuration.onOpen);
1927
+ this.on("open", this.onOpen.bind(this));
1928
+ this.on("connect", this.configuration.onConnect);
1929
+ this.on("message", this.configuration.onMessage);
1930
+ this.on("outgoingMessage", this.configuration.onOutgoingMessage);
1931
+ this.on("status", this.configuration.onStatus);
1932
+ this.on("disconnect", this.configuration.onDisconnect);
1933
+ this.on("close", this.configuration.onClose);
1934
+ this.on("destroy", this.configuration.onDestroy);
1935
+ this.on("awarenessUpdate", this.configuration.onAwarenessUpdate);
1936
+ this.on("awarenessChange", this.configuration.onAwarenessChange);
1937
+ this.on("close", this.onClose.bind(this));
1938
+ this.on("message", this.onMessage.bind(this));
1939
+ this.intervals.connectionChecker = setInterval(this.checkConnection.bind(this), this.configuration.messageReconnectTimeout / 10);
1940
+ if (this.shouldConnect) {
1941
+ this.connect();
1942
+ }
1943
+ }
1944
+ async onOpen(event) {
1945
+ this.status = WebSocketStatus.Connected;
1946
+ this.emit("status", { status: WebSocketStatus.Connected });
1947
+ this.cancelWebsocketRetry = undefined;
1948
+ this.receivedOnOpenPayload = event;
1949
+ }
1950
+ attach(provider) {
1951
+ this.configuration.providerMap.set(provider.configuration.name, provider);
1952
+ if (this.status === WebSocketStatus.Disconnected && this.shouldConnect) {
1953
+ this.connect();
1954
+ }
1955
+ if (this.receivedOnOpenPayload &&
1956
+ this.status === WebSocketStatus.Connected) {
1957
+ provider.onOpen(this.receivedOnOpenPayload);
1958
+ }
1959
+ }
1960
+ detach(provider) {
1961
+ if (this.configuration.providerMap.has(provider.configuration.name)) {
1962
+ provider.send(CloseMessage, {
1963
+ documentName: provider.configuration.name,
1964
+ });
1965
+ this.configuration.providerMap.delete(provider.configuration.name);
1966
+ }
1967
+ }
1968
+ setConfiguration(configuration = {}) {
1969
+ this.configuration = { ...this.configuration, ...configuration };
1970
+ if (!this.configuration.autoConnect) {
1971
+ this.shouldConnect = false;
1972
+ }
1973
+ }
1974
+ async connect() {
1975
+ if (this.status === WebSocketStatus.Connected) {
1976
+ return;
1977
+ }
1978
+ // Always cancel any previously initiated connection retryer instances
1979
+ if (this.cancelWebsocketRetry) {
1980
+ this.cancelWebsocketRetry();
1981
+ this.cancelWebsocketRetry = undefined;
1982
+ }
1983
+ this.receivedOnOpenPayload = undefined;
1984
+ this.shouldConnect = true;
1985
+ const abortableRetry = () => {
1986
+ let cancelAttempt = false;
1987
+ const retryPromise = retry(this.createWebSocketConnection.bind(this), {
1988
+ delay: this.configuration.delay,
1989
+ initialDelay: this.configuration.initialDelay,
1990
+ factor: this.configuration.factor,
1991
+ maxAttempts: this.configuration.maxAttempts,
1992
+ minDelay: this.configuration.minDelay,
1993
+ maxDelay: this.configuration.maxDelay,
1994
+ jitter: this.configuration.jitter,
1995
+ timeout: this.configuration.timeout,
1996
+ handleTimeout: this.configuration.handleTimeout,
1997
+ beforeAttempt: (context) => {
1998
+ if (!this.shouldConnect || cancelAttempt) {
1999
+ context.abort();
2000
+ }
2001
+ },
2002
+ }).catch((error) => {
2003
+ // If we aborted the connection attempt then don’t throw an error
2004
+ // ref: https://github.com/lifeomic/attempt/blob/master/src/index.ts#L136
2005
+ if (error && error.code !== "ATTEMPT_ABORTED") {
2006
+ throw error;
2007
+ }
2008
+ });
2009
+ return {
2010
+ retryPromise,
2011
+ cancelFunc: () => {
2012
+ cancelAttempt = true;
2013
+ },
2014
+ };
2015
+ };
2016
+ const { retryPromise, cancelFunc } = abortableRetry();
2017
+ this.cancelWebsocketRetry = cancelFunc;
2018
+ return retryPromise;
2019
+ }
2020
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
2021
+ attachWebSocketListeners(ws, reject) {
2022
+ const { identifier } = ws;
2023
+ const onMessageHandler = (payload) => this.emit("message", payload);
2024
+ const onCloseHandler = (payload) => this.emit("close", { event: payload });
2025
+ const onOpenHandler = (payload) => this.emit("open", payload);
2026
+ const onErrorHandler = (err) => {
2027
+ reject(err);
2028
+ };
2029
+ this.webSocketHandlers[identifier] = {
2030
+ message: onMessageHandler,
2031
+ close: onCloseHandler,
2032
+ open: onOpenHandler,
2033
+ error: onErrorHandler,
2034
+ };
2035
+ const handlers = this.webSocketHandlers[ws.identifier];
2036
+ Object.keys(handlers).forEach((name) => {
2037
+ ws.addEventListener(name, handlers[name]);
2038
+ });
2039
+ }
2040
+ cleanupWebSocket() {
2041
+ if (!this.webSocket) {
2042
+ return;
2043
+ }
2044
+ const { identifier } = this.webSocket;
2045
+ const handlers = this.webSocketHandlers[identifier];
2046
+ Object.keys(handlers).forEach((name) => {
2047
+ var _a;
2048
+ (_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.removeEventListener(name, handlers[name]);
2049
+ delete this.webSocketHandlers[identifier];
2050
+ });
2051
+ this.webSocket.close();
2052
+ this.webSocket = null;
2053
+ }
2054
+ createWebSocketConnection() {
2055
+ return new Promise((resolve, reject) => {
2056
+ if (this.webSocket) {
2057
+ this.messageQueue = [];
2058
+ this.cleanupWebSocket();
2059
+ }
2060
+ this.lastMessageReceived = 0;
2061
+ this.identifier += 1;
2062
+ // Init the WebSocket connection
2063
+ const ws = new this.configuration.WebSocketPolyfill(this.url);
2064
+ ws.binaryType = "arraybuffer";
2065
+ ws.identifier = this.identifier;
2066
+ this.attachWebSocketListeners(ws, reject);
2067
+ this.webSocket = ws;
2068
+ // Reset the status
2069
+ this.status = WebSocketStatus.Connecting;
2070
+ this.emit("status", { status: WebSocketStatus.Connecting });
2071
+ // Store resolve/reject for later use
2072
+ this.connectionAttempt = {
2073
+ resolve,
2074
+ reject,
2075
+ };
2076
+ });
2077
+ }
2078
+ onMessage(event) {
2079
+ var _a;
2080
+ this.resolveConnectionAttempt();
2081
+ this.lastMessageReceived = getUnixTime();
2082
+ const message = new IncomingMessage(event.data);
2083
+ const documentName = message.peekVarString();
2084
+ (_a = this.configuration.providerMap.get(documentName)) === null || _a === void 0 ? void 0 : _a.onMessage(event);
2085
+ }
2086
+ resolveConnectionAttempt() {
2087
+ if (this.connectionAttempt) {
2088
+ this.connectionAttempt.resolve();
2089
+ this.connectionAttempt = null;
2090
+ this.status = WebSocketStatus.Connected;
2091
+ this.emit("status", { status: WebSocketStatus.Connected });
2092
+ this.emit("connect");
2093
+ this.messageQueue.forEach((message) => this.send(message));
2094
+ this.messageQueue = [];
2095
+ }
2096
+ }
2097
+ stopConnectionAttempt() {
2098
+ this.connectionAttempt = null;
2099
+ }
2100
+ rejectConnectionAttempt() {
2101
+ var _a;
2102
+ (_a = this.connectionAttempt) === null || _a === void 0 ? void 0 : _a.reject();
2103
+ this.connectionAttempt = null;
2104
+ }
2105
+ checkConnection() {
2106
+ var _a;
2107
+ // Don’t check the connection when it’s not even established
2108
+ if (this.status !== WebSocketStatus.Connected) {
2109
+ return;
2110
+ }
2111
+ // Don’t close the connection while waiting for the first message
2112
+ if (!this.lastMessageReceived) {
2113
+ return;
2114
+ }
2115
+ // Don’t close the connection when a message was received recently
2116
+ if (this.configuration.messageReconnectTimeout >=
2117
+ getUnixTime() - this.lastMessageReceived) {
2118
+ return;
2119
+ }
2120
+ // No message received in a long time, not even your own
2121
+ // Awareness updates, which are updated every 15 seconds
2122
+ // if awareness is enabled.
2123
+ this.closeTries += 1;
2124
+ // https://bugs.webkit.org/show_bug.cgi?id=247943
2125
+ if (this.closeTries > 2) {
2126
+ this.onClose({
2127
+ event: {
2128
+ code: 4408,
2129
+ reason: "forced",
2130
+ },
2131
+ });
2132
+ this.closeTries = 0;
2133
+ }
2134
+ else {
2135
+ (_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.close();
2136
+ this.messageQueue = [];
2137
+ }
2138
+ }
2139
+ get serverUrl() {
2140
+ if (this.configuration.preserveTrailingSlash) {
2141
+ return this.configuration.url;
2142
+ }
2143
+ // By default, ensure that the URL never ends with /
2144
+ let url = this.configuration.url;
2145
+ while (url[url.length - 1] === "/") {
2146
+ url = url.slice(0, url.length - 1);
2147
+ }
2148
+ return url;
2149
+ }
2150
+ get url() {
2151
+ return this.serverUrl;
2152
+ }
2153
+ disconnect() {
2154
+ this.shouldConnect = false;
2155
+ if (this.webSocket === null) {
2156
+ return;
2157
+ }
2158
+ try {
2159
+ this.webSocket.close();
2160
+ this.messageQueue = [];
2161
+ }
2162
+ catch (e) {
2163
+ console.error(e);
2164
+ }
2165
+ }
2166
+ send(message) {
2167
+ var _a;
2168
+ if (((_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.readyState) === WsReadyStates.Open) {
2169
+ this.webSocket.send(message);
2170
+ }
2171
+ else {
2172
+ this.messageQueue.push(message);
2173
+ }
2174
+ }
2175
+ onClose({ event }) {
2176
+ this.closeTries = 0;
2177
+ this.cleanupWebSocket();
2178
+ if (this.connectionAttempt) {
2179
+ // That connection attempt failed.
2180
+ this.rejectConnectionAttempt();
2181
+ }
2182
+ // Let’s update the connection status.
2183
+ this.status = WebSocketStatus.Disconnected;
2184
+ this.emit("status", { status: WebSocketStatus.Disconnected });
2185
+ this.emit("disconnect", { event });
2186
+ // trigger connect if no retry is running and we want to have a connection
2187
+ if (!this.cancelWebsocketRetry && this.shouldConnect) {
2188
+ setTimeout(() => {
2189
+ this.connect();
2190
+ }, this.configuration.delay);
2191
+ }
2192
+ }
2193
+ destroy() {
2194
+ this.emit("destroy");
2195
+ clearInterval(this.intervals.connectionChecker);
2196
+ // If there is still a connection attempt outstanding then we should stop
2197
+ // it before calling disconnect, otherwise it will be rejected in the onClose
2198
+ // handler and trigger a retry
2199
+ this.stopConnectionAttempt();
2200
+ this.disconnect();
2201
+ this.removeAllListeners();
2202
+ this.cleanupWebSocket();
2203
+ }
2204
+ }
2205
+
2206
+ /**
2207
+ * @module sync-protocol
2208
+ */
2209
+
2210
+
2211
+ /**
2212
+ * @typedef {Map<number, number>} StateMap
2213
+ */
2214
+
2215
+ /**
2216
+ * Core Yjs defines two message types:
2217
+ * • YjsSyncStep1: Includes the State Set of the sending client. When received, the client should reply with YjsSyncStep2.
2218
+ * • YjsSyncStep2: Includes all missing structs and the complete delete set. When received, the client is assured that it
2219
+ * received all information from the remote client.
2220
+ *
2221
+ * In a peer-to-peer network, you may want to introduce a SyncDone message type. Both parties should initiate the connection
2222
+ * with SyncStep1. When a client received SyncStep2, it should reply with SyncDone. When the local client received both
2223
+ * SyncStep2 and SyncDone, it is assured that it is synced to the remote client.
2224
+ *
2225
+ * In a client-server model, you want to handle this differently: The client should initiate the connection with SyncStep1.
2226
+ * When the server receives SyncStep1, it should reply with SyncStep2 immediately followed by SyncStep1. The client replies
2227
+ * with SyncStep2 when it receives SyncStep1. Optionally the server may send a SyncDone after it received SyncStep2, so the
2228
+ * client knows that the sync is finished. There are two reasons for this more elaborated sync model: 1. This protocol can
2229
+ * easily be implemented on top of http and websockets. 2. The server should only reply to requests, and not initiate them.
2230
+ * Therefore it is necessary that the client initiates the sync.
2231
+ *
2232
+ * Construction of a message:
2233
+ * [messageType : varUint, message definition..]
2234
+ *
2235
+ * Note: A message does not include information about the room name. This must to be handled by the upper layer protocol!
2236
+ *
2237
+ * stringify[messageType] stringifies a message definition (messageType is already read from the bufffer)
2238
+ */
2239
+
2240
+ const messageYjsSyncStep1 = 0;
2241
+ const messageYjsSyncStep2 = 1;
2242
+ const messageYjsUpdate = 2;
2243
+
2244
+ /**
2245
+ * Create a sync step 1 message based on the state of the current shared document.
2246
+ *
2247
+ * @param {encoding.Encoder} encoder
2248
+ * @param {Y.Doc} doc
2249
+ */
2250
+ const writeSyncStep1 = (encoder, doc) => {
2251
+ writeVarUint(encoder, messageYjsSyncStep1);
2252
+ const sv = Y.encodeStateVector(doc);
2253
+ writeVarUint8Array(encoder, sv);
2254
+ };
2255
+
2256
+ /**
2257
+ * @param {encoding.Encoder} encoder
2258
+ * @param {Y.Doc} doc
2259
+ * @param {Uint8Array} [encodedStateVector]
2260
+ */
2261
+ const writeSyncStep2 = (encoder, doc, encodedStateVector) => {
2262
+ writeVarUint(encoder, messageYjsSyncStep2);
2263
+ writeVarUint8Array(encoder, Y.encodeStateAsUpdate(doc, encodedStateVector));
2264
+ };
2265
+
2266
+ /**
2267
+ * Read SyncStep1 message and reply with SyncStep2.
2268
+ *
2269
+ * @param {decoding.Decoder} decoder The reply to the received message
2270
+ * @param {encoding.Encoder} encoder The received message
2271
+ * @param {Y.Doc} doc
2272
+ */
2273
+ const readSyncStep1 = (decoder, encoder, doc) =>
2274
+ writeSyncStep2(encoder, doc, readVarUint8Array(decoder));
2275
+
2276
+ /**
2277
+ * Read and apply Structs and then DeleteStore to a y instance.
2278
+ *
2279
+ * @param {decoding.Decoder} decoder
2280
+ * @param {Y.Doc} doc
2281
+ * @param {any} transactionOrigin
2282
+ */
2283
+ const readSyncStep2 = (decoder, doc, transactionOrigin) => {
2284
+ try {
2285
+ Y.applyUpdate(doc, readVarUint8Array(decoder), transactionOrigin);
2286
+ } catch (error) {
2287
+ // This catches errors that are thrown by event handlers
2288
+ console.error('Caught error while handling a Yjs update', error);
2289
+ }
2290
+ };
2291
+
2292
+ /**
2293
+ * @param {encoding.Encoder} encoder
2294
+ * @param {Uint8Array} update
2295
+ */
2296
+ const writeUpdate = (encoder, update) => {
2297
+ writeVarUint(encoder, messageYjsUpdate);
2298
+ writeVarUint8Array(encoder, update);
2299
+ };
2300
+
2301
+ /**
2302
+ * Read and apply Structs and then DeleteStore to a y instance.
2303
+ *
2304
+ * @param {decoding.Decoder} decoder
2305
+ * @param {Y.Doc} doc
2306
+ * @param {any} transactionOrigin
2307
+ */
2308
+ const readUpdate = readSyncStep2;
2309
+
2310
+ /**
2311
+ * @param {decoding.Decoder} decoder A message received from another client
2312
+ * @param {encoding.Encoder} encoder The reply message. Does not need to be sent if empty.
2313
+ * @param {Y.Doc} doc
2314
+ * @param {any} transactionOrigin
2315
+ */
2316
+ const readSyncMessage = (decoder, encoder, doc, transactionOrigin) => {
2317
+ const messageType = readVarUint(decoder);
2318
+ switch (messageType) {
2319
+ case messageYjsSyncStep1:
2320
+ readSyncStep1(decoder, encoder, doc);
2321
+ break
2322
+ case messageYjsSyncStep2:
2323
+ readSyncStep2(decoder, doc, transactionOrigin);
2324
+ break
2325
+ case messageYjsUpdate:
2326
+ readUpdate(decoder, doc, transactionOrigin);
2327
+ break
2328
+ default:
2329
+ throw new Error('Unknown message type')
2330
+ }
2331
+ return messageType
2332
+ };
2333
+
2334
+ class MessageReceiver {
2335
+ constructor(message) {
2336
+ this.message = message;
2337
+ }
2338
+ apply(provider, emitSynced) {
2339
+ const { message } = this;
2340
+ const type = message.readVarUint();
2341
+ const emptyMessageLength = message.length();
2342
+ switch (type) {
2343
+ case MessageType.Sync:
2344
+ this.applySyncMessage(provider, emitSynced);
2345
+ break;
2346
+ case MessageType.Awareness:
2347
+ this.applyAwarenessMessage(provider);
2348
+ break;
2349
+ case MessageType.Auth:
2350
+ this.applyAuthMessage(provider);
2351
+ break;
2352
+ case MessageType.QueryAwareness:
2353
+ this.applyQueryAwarenessMessage(provider);
2354
+ break;
2355
+ case MessageType.Stateless:
2356
+ provider.receiveStateless(readVarString(message.decoder));
2357
+ break;
2358
+ case MessageType.SyncStatus:
2359
+ this.applySyncStatusMessage(provider, readVarInt(message.decoder) === 1);
2360
+ break;
2361
+ case MessageType.CLOSE:
2362
+ // eslint-disable-next-line no-case-declarations
2363
+ const event = {
2364
+ code: 1000,
2365
+ reason: readVarString(message.decoder),
2366
+ // @ts-ignore
2367
+ target: provider.configuration.websocketProvider.webSocket,
2368
+ type: "close",
2369
+ };
2370
+ provider.onClose();
2371
+ provider.configuration.onClose({ event });
2372
+ provider.forwardClose({ event });
2373
+ break;
2374
+ default:
2375
+ throw new Error(`Can’t apply message of unknown type: ${type}`);
2376
+ }
2377
+ // Reply
2378
+ if (message.length() > emptyMessageLength + 1) {
2379
+ // length of documentName (considered in emptyMessageLength plus length of yjs sync type, set in applySyncMessage)
2380
+ // @ts-ignore
2381
+ provider.send(OutgoingMessage, { encoder: message.encoder });
2382
+ }
2383
+ }
2384
+ applySyncMessage(provider, emitSynced) {
2385
+ const { message } = this;
2386
+ message.writeVarUint(MessageType.Sync);
2387
+ // Apply update
2388
+ const syncMessageType = readSyncMessage(message.decoder, message.encoder, provider.document, provider);
2389
+ // Synced once we receive Step2
2390
+ if (emitSynced && syncMessageType === messageYjsSyncStep2) {
2391
+ provider.synced = true;
2392
+ }
2393
+ }
2394
+ applySyncStatusMessage(provider, applied) {
2395
+ if (applied) {
2396
+ provider.decrementUnsyncedChanges();
2397
+ }
2398
+ }
2399
+ applyAwarenessMessage(provider) {
2400
+ if (!provider.awareness)
2401
+ return;
2402
+ const { message } = this;
2403
+ applyAwarenessUpdate(provider.awareness, message.readVarUint8Array(), provider);
2404
+ }
2405
+ applyAuthMessage(provider) {
2406
+ const { message } = this;
2407
+ readAuthMessage(message.decoder, provider.sendToken.bind(provider), provider.permissionDeniedHandler.bind(provider), provider.authenticatedHandler.bind(provider));
2408
+ }
2409
+ applyQueryAwarenessMessage(provider) {
2410
+ if (!provider.awareness)
2411
+ return;
2412
+ const { message } = this;
2413
+ message.writeVarUint(MessageType.Awareness);
2414
+ message.writeVarUint8Array(encodeAwarenessUpdate(provider.awareness, Array.from(provider.awareness.getStates().keys())));
2415
+ }
2416
+ }
2417
+
2418
+ class MessageSender {
2419
+ constructor(Message, args = {}) {
2420
+ this.message = new Message();
2421
+ this.encoder = this.message.get(args);
2422
+ }
2423
+ create() {
2424
+ return toUint8Array(this.encoder);
2425
+ }
2426
+ send(webSocket) {
2427
+ webSocket === null || webSocket === void 0 ? void 0 : webSocket.send(this.create());
2428
+ }
2429
+ }
2430
+
2431
+ class AuthenticationMessage extends OutgoingMessage {
2432
+ constructor() {
2433
+ super(...arguments);
2434
+ this.type = MessageType.Auth;
2435
+ this.description = "Authentication";
2436
+ }
2437
+ get(args) {
2438
+ if (typeof args.token === "undefined") {
2439
+ throw new Error("The authentication message requires `token` as an argument.");
2440
+ }
2441
+ writeVarString(this.encoder, args.documentName);
2442
+ writeVarUint(this.encoder, this.type);
2443
+ writeAuthentication(this.encoder, args.token);
2444
+ return this.encoder;
2445
+ }
2446
+ }
2447
+
2448
+ class AwarenessMessage extends OutgoingMessage {
2449
+ constructor() {
2450
+ super(...arguments);
2451
+ this.type = MessageType.Awareness;
2452
+ this.description = "Awareness states update";
2453
+ }
2454
+ get(args) {
2455
+ if (typeof args.awareness === "undefined") {
2456
+ throw new Error("The awareness message requires awareness as an argument");
2457
+ }
2458
+ if (typeof args.clients === "undefined") {
2459
+ throw new Error("The awareness message requires clients as an argument");
2460
+ }
2461
+ writeVarString(this.encoder, args.documentName);
2462
+ writeVarUint(this.encoder, this.type);
2463
+ let awarenessUpdate;
2464
+ if (args.states === undefined) {
2465
+ awarenessUpdate = encodeAwarenessUpdate(args.awareness, args.clients);
2466
+ }
2467
+ else {
2468
+ awarenessUpdate = encodeAwarenessUpdate(args.awareness, args.clients, args.states);
2469
+ }
2470
+ writeVarUint8Array(this.encoder, awarenessUpdate);
2471
+ return this.encoder;
2472
+ }
2473
+ }
2474
+
2475
+ class StatelessMessage extends OutgoingMessage {
2476
+ constructor() {
2477
+ super(...arguments);
2478
+ this.type = MessageType.Stateless;
2479
+ this.description = "A stateless message";
2480
+ }
2481
+ get(args) {
2482
+ var _a;
2483
+ writeVarString(this.encoder, args.documentName);
2484
+ writeVarUint(this.encoder, this.type);
2485
+ writeVarString(this.encoder, (_a = args.payload) !== null && _a !== void 0 ? _a : "");
2486
+ return this.encoder;
2487
+ }
2488
+ }
2489
+
2490
+ class SyncStepOneMessage extends OutgoingMessage {
2491
+ constructor() {
2492
+ super(...arguments);
2493
+ this.type = MessageType.Sync;
2494
+ this.description = "First sync step";
2495
+ }
2496
+ get(args) {
2497
+ if (typeof args.document === "undefined") {
2498
+ throw new Error("The sync step one message requires document as an argument");
2499
+ }
2500
+ writeVarString(this.encoder, args.documentName);
2501
+ writeVarUint(this.encoder, this.type);
2502
+ writeSyncStep1(this.encoder, args.document);
2503
+ return this.encoder;
2504
+ }
2505
+ }
2506
+
2507
+ class UpdateMessage extends OutgoingMessage {
2508
+ constructor() {
2509
+ super(...arguments);
2510
+ this.type = MessageType.Sync;
2511
+ this.description = "A document update";
2512
+ }
2513
+ get(args) {
2514
+ writeVarString(this.encoder, args.documentName);
2515
+ writeVarUint(this.encoder, this.type);
2516
+ writeUpdate(this.encoder, args.update);
2517
+ return this.encoder;
2518
+ }
2519
+ }
2520
+
2521
+ class AwarenessError extends Error {
2522
+ constructor() {
2523
+ super(...arguments);
2524
+ this.code = 1001;
2525
+ }
2526
+ }
2527
+ class HocuspocusProvider extends EventEmitter {
2528
+ constructor(configuration) {
2529
+ var _a, _b, _c;
2530
+ super();
2531
+ this.configuration = {
2532
+ name: "",
2533
+ // @ts-ignore
2534
+ document: undefined,
2535
+ // @ts-ignore
2536
+ awareness: undefined,
2537
+ token: null,
2538
+ forceSyncInterval: false,
2539
+ onAuthenticated: () => null,
2540
+ onAuthenticationFailed: () => null,
2541
+ onOpen: () => null,
2542
+ onConnect: () => null,
2543
+ onMessage: () => null,
2544
+ onOutgoingMessage: () => null,
2545
+ onSynced: () => null,
2546
+ onStatus: () => null,
2547
+ onDisconnect: () => null,
2548
+ onClose: () => null,
2549
+ onDestroy: () => null,
2550
+ onAwarenessUpdate: () => null,
2551
+ onAwarenessChange: () => null,
2552
+ onStateless: () => null,
2553
+ onUnsyncedChanges: () => null,
2554
+ };
2555
+ this.isSynced = false;
2556
+ this.unsyncedChanges = 0;
2557
+ this.isAuthenticated = false;
2558
+ this.authorizedScope = undefined;
2559
+ // @internal
2560
+ this.manageSocket = false;
2561
+ this._isAttached = false;
2562
+ this.intervals = {
2563
+ forceSync: null,
2564
+ };
2565
+ this.boundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);
2566
+ this.boundAwarenessUpdateHandler = this.awarenessUpdateHandler.bind(this);
2567
+ this.boundPageHide = this.pageHide.bind(this);
2568
+ this.boundOnOpen = this.onOpen.bind(this);
2569
+ this.boundOnClose = this.onClose.bind(this);
2570
+ this.forwardConnect = () => this.emit("connect");
2571
+ this.forwardStatus = (e) => this.emit("status", e);
2572
+ this.forwardClose = (e) => this.emit("close", e);
2573
+ this.forwardDisconnect = (e) => this.emit("disconnect", e);
2574
+ this.forwardDestroy = () => this.emit("destroy");
2575
+ this.setConfiguration(configuration);
2576
+ this.configuration.document = configuration.document
2577
+ ? configuration.document
2578
+ : new Y.Doc();
2579
+ this.configuration.awareness =
2580
+ configuration.awareness !== undefined
2581
+ ? configuration.awareness
2582
+ : new Awareness(this.document);
2583
+ this.on("open", this.configuration.onOpen);
2584
+ this.on("message", this.configuration.onMessage);
2585
+ this.on("outgoingMessage", this.configuration.onOutgoingMessage);
2586
+ this.on("synced", this.configuration.onSynced);
2587
+ this.on("destroy", this.configuration.onDestroy);
2588
+ this.on("awarenessUpdate", this.configuration.onAwarenessUpdate);
2589
+ this.on("awarenessChange", this.configuration.onAwarenessChange);
2590
+ this.on("stateless", this.configuration.onStateless);
2591
+ this.on("unsyncedChanges", this.configuration.onUnsyncedChanges);
2592
+ this.on("authenticated", this.configuration.onAuthenticated);
2593
+ this.on("authenticationFailed", this.configuration.onAuthenticationFailed);
2594
+ (_a = this.awareness) === null || _a === void 0 ? void 0 : _a.on("update", () => {
2595
+ this.emit("awarenessUpdate", {
2596
+ states: awarenessStatesToArray(this.awareness.getStates()),
2597
+ });
2598
+ });
2599
+ (_b = this.awareness) === null || _b === void 0 ? void 0 : _b.on("change", () => {
2600
+ this.emit("awarenessChange", {
2601
+ states: awarenessStatesToArray(this.awareness.getStates()),
2602
+ });
2603
+ });
2604
+ this.document.on("update", this.boundDocumentUpdateHandler);
2605
+ (_c = this.awareness) === null || _c === void 0 ? void 0 : _c.on("update", this.boundAwarenessUpdateHandler);
2606
+ this.registerEventListeners();
2607
+ if (this.configuration.forceSyncInterval &&
2608
+ typeof this.configuration.forceSyncInterval === "number") {
2609
+ this.intervals.forceSync = setInterval(this.forceSync.bind(this), this.configuration.forceSyncInterval);
2610
+ }
2611
+ if (this.manageSocket) {
2612
+ this.attach();
2613
+ }
2614
+ }
2615
+ setConfiguration(configuration = {}) {
2616
+ if (!configuration.websocketProvider) {
2617
+ this.manageSocket = true;
2618
+ this.configuration.websocketProvider = new HocuspocusProviderWebsocket(configuration);
2619
+ }
2620
+ this.configuration = { ...this.configuration, ...configuration };
2621
+ }
2622
+ get document() {
2623
+ return this.configuration.document;
2624
+ }
2625
+ get isAttached() {
2626
+ return this._isAttached;
2627
+ }
2628
+ get awareness() {
2629
+ return this.configuration.awareness;
2630
+ }
2631
+ get hasUnsyncedChanges() {
2632
+ return this.unsyncedChanges > 0;
2633
+ }
2634
+ resetUnsyncedChanges() {
2635
+ this.unsyncedChanges = 1;
2636
+ this.emit("unsyncedChanges", { number: this.unsyncedChanges });
2637
+ }
2638
+ incrementUnsyncedChanges() {
2639
+ this.unsyncedChanges += 1;
2640
+ this.emit("unsyncedChanges", { number: this.unsyncedChanges });
2641
+ }
2642
+ decrementUnsyncedChanges() {
2643
+ if (this.unsyncedChanges > 0) {
2644
+ this.unsyncedChanges -= 1;
2645
+ }
2646
+ if (this.unsyncedChanges === 0) {
2647
+ this.synced = true;
2648
+ }
2649
+ this.emit("unsyncedChanges", { number: this.unsyncedChanges });
2650
+ }
2651
+ forceSync() {
2652
+ this.resetUnsyncedChanges();
2653
+ this.send(SyncStepOneMessage, {
2654
+ document: this.document,
2655
+ documentName: this.configuration.name,
2656
+ });
2657
+ }
2658
+ pageHide() {
2659
+ if (this.awareness) {
2660
+ removeAwarenessStates(this.awareness, [this.document.clientID], "page hide");
2661
+ }
2662
+ }
2663
+ registerEventListeners() {
2664
+ if (typeof window === "undefined" || !("addEventListener" in window)) {
2665
+ return;
2666
+ }
2667
+ window.addEventListener("pagehide", this.boundPageHide);
2668
+ }
2669
+ sendStateless(payload) {
2670
+ this.send(StatelessMessage, {
2671
+ documentName: this.configuration.name,
2672
+ payload,
2673
+ });
2674
+ }
2675
+ async sendToken() {
2676
+ let token;
2677
+ try {
2678
+ token = await this.getToken();
2679
+ }
2680
+ catch (error) {
2681
+ this.permissionDeniedHandler(`Failed to get token during sendToken(): ${error}`);
2682
+ return;
2683
+ }
2684
+ this.send(AuthenticationMessage, {
2685
+ token: token !== null && token !== void 0 ? token : "",
2686
+ documentName: this.configuration.name,
2687
+ });
2688
+ }
2689
+ documentUpdateHandler(update, origin) {
2690
+ if (origin === this) {
2691
+ return;
2692
+ }
2693
+ this.incrementUnsyncedChanges();
2694
+ this.send(UpdateMessage, { update, documentName: this.configuration.name });
2695
+ }
2696
+ awarenessUpdateHandler({ added, updated, removed }, origin) {
2697
+ const changedClients = added.concat(updated).concat(removed);
2698
+ this.send(AwarenessMessage, {
2699
+ awareness: this.awareness,
2700
+ clients: changedClients,
2701
+ documentName: this.configuration.name,
2702
+ });
2703
+ }
2704
+ /**
2705
+ * Indicates whether a first handshake with the server has been established
2706
+ *
2707
+ * Note: this does not mean all updates from the client have been persisted to the backend. For this,
2708
+ * use `hasUnsyncedChanges`.
2709
+ */
2710
+ get synced() {
2711
+ return this.isSynced;
2712
+ }
2713
+ set synced(state) {
2714
+ if (this.isSynced === state) {
2715
+ return;
2716
+ }
2717
+ this.isSynced = state;
2718
+ if (state) {
2719
+ this.emit("synced", { state });
2720
+ }
2721
+ }
2722
+ receiveStateless(payload) {
2723
+ this.emit("stateless", { payload });
2724
+ }
2725
+ // not needed, but provides backward compatibility with e.g. lexical/yjs
2726
+ async connect() {
2727
+ if (this.manageSocket) {
2728
+ return this.configuration.websocketProvider.connect();
2729
+ }
2730
+ console.warn("HocuspocusProvider::connect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.");
2731
+ }
2732
+ disconnect() {
2733
+ if (this.manageSocket) {
2734
+ return this.configuration.websocketProvider.disconnect();
2735
+ }
2736
+ console.warn("HocuspocusProvider::disconnect() is deprecated and does not do anything. Please connect/disconnect on the websocketProvider, or attach/deattach providers.");
2737
+ }
2738
+ async onOpen(event) {
2739
+ this.isAuthenticated = false;
2740
+ this.emit("open", { event });
2741
+ await this.sendToken();
2742
+ this.startSync();
2743
+ }
2744
+ async getToken() {
2745
+ if (typeof this.configuration.token === "function") {
2746
+ const token = await this.configuration.token();
2747
+ return token;
2748
+ }
2749
+ return this.configuration.token;
2750
+ }
2751
+ startSync() {
2752
+ this.resetUnsyncedChanges();
2753
+ this.send(SyncStepOneMessage, {
2754
+ document: this.document,
2755
+ documentName: this.configuration.name,
2756
+ });
2757
+ if (this.awareness && this.awareness.getLocalState() !== null) {
2758
+ this.send(AwarenessMessage, {
2759
+ awareness: this.awareness,
2760
+ clients: [this.document.clientID],
2761
+ documentName: this.configuration.name,
2762
+ });
2763
+ }
2764
+ }
2765
+ send(message, args) {
2766
+ if (!this._isAttached)
2767
+ return;
2768
+ const messageSender = new MessageSender(message, args);
2769
+ this.emit("outgoingMessage", { message: messageSender.message });
2770
+ messageSender.send(this.configuration.websocketProvider);
2771
+ }
2772
+ onMessage(event) {
2773
+ const message = new IncomingMessage(event.data);
2774
+ const documentName = message.readVarString();
2775
+ message.writeVarString(documentName);
2776
+ this.emit("message", { event, message: new IncomingMessage(event.data) });
2777
+ new MessageReceiver(message).apply(this, true);
2778
+ }
2779
+ onClose() {
2780
+ this.isAuthenticated = false;
2781
+ this.synced = false;
2782
+ // update awareness (all users except local left)
2783
+ if (this.awareness) {
2784
+ removeAwarenessStates(this.awareness, Array.from(this.awareness.getStates().keys()).filter((client) => client !== this.document.clientID), this);
2785
+ }
2786
+ }
2787
+ destroy() {
2788
+ this.emit("destroy");
2789
+ if (this.intervals.forceSync) {
2790
+ clearInterval(this.intervals.forceSync);
2791
+ }
2792
+ if (this.awareness) {
2793
+ removeAwarenessStates(this.awareness, [this.document.clientID], "provider destroy");
2794
+ this.awareness.off("update", this.boundAwarenessUpdateHandler);
2795
+ this.awareness.destroy();
2796
+ }
2797
+ this.document.off("update", this.boundDocumentUpdateHandler);
2798
+ this.removeAllListeners();
2799
+ this.detach();
2800
+ if (this.manageSocket) {
2801
+ this.configuration.websocketProvider.destroy();
2802
+ }
2803
+ if (typeof window === "undefined" || !("removeEventListener" in window)) {
2804
+ return;
2805
+ }
2806
+ window.removeEventListener("pagehide", this.boundPageHide);
2807
+ }
2808
+ detach() {
2809
+ this.configuration.websocketProvider.off("connect", this.configuration.onConnect);
2810
+ this.configuration.websocketProvider.off("connect", this.forwardConnect);
2811
+ this.configuration.websocketProvider.off("status", this.forwardStatus);
2812
+ this.configuration.websocketProvider.off("status", this.configuration.onStatus);
2813
+ this.configuration.websocketProvider.off("open", this.boundOnOpen);
2814
+ this.configuration.websocketProvider.off("close", this.boundOnClose);
2815
+ this.configuration.websocketProvider.off("close", this.configuration.onClose);
2816
+ this.configuration.websocketProvider.off("close", this.forwardClose);
2817
+ this.configuration.websocketProvider.off("disconnect", this.configuration.onDisconnect);
2818
+ this.configuration.websocketProvider.off("disconnect", this.forwardDisconnect);
2819
+ this.configuration.websocketProvider.off("destroy", this.configuration.onDestroy);
2820
+ this.configuration.websocketProvider.off("destroy", this.forwardDestroy);
2821
+ this.configuration.websocketProvider.detach(this);
2822
+ this._isAttached = false;
2823
+ }
2824
+ attach() {
2825
+ if (this._isAttached)
2826
+ return;
2827
+ this.configuration.websocketProvider.on("connect", this.configuration.onConnect);
2828
+ this.configuration.websocketProvider.on("connect", this.forwardConnect);
2829
+ this.configuration.websocketProvider.on("status", this.configuration.onStatus);
2830
+ this.configuration.websocketProvider.on("status", this.forwardStatus);
2831
+ this.configuration.websocketProvider.on("open", this.boundOnOpen);
2832
+ this.configuration.websocketProvider.on("close", this.boundOnClose);
2833
+ this.configuration.websocketProvider.on("close", this.configuration.onClose);
2834
+ this.configuration.websocketProvider.on("close", this.forwardClose);
2835
+ this.configuration.websocketProvider.on("disconnect", this.configuration.onDisconnect);
2836
+ this.configuration.websocketProvider.on("disconnect", this.forwardDisconnect);
2837
+ this.configuration.websocketProvider.on("destroy", this.configuration.onDestroy);
2838
+ this.configuration.websocketProvider.on("destroy", this.forwardDestroy);
2839
+ this.configuration.websocketProvider.attach(this);
2840
+ this._isAttached = true;
2841
+ }
2842
+ permissionDeniedHandler(reason) {
2843
+ this.emit("authenticationFailed", { reason });
2844
+ this.isAuthenticated = false;
2845
+ }
2846
+ authenticatedHandler(scope) {
2847
+ this.isAuthenticated = true;
2848
+ this.authorizedScope = scope;
2849
+ this.emit("authenticated", { scope });
2850
+ }
2851
+ setAwarenessField(key, value) {
2852
+ if (!this.awareness) {
2853
+ throw new AwarenessError(`Cannot set awareness field "${key}" to ${JSON.stringify(value)}. You have disabled Awareness for this provider by explicitly passing awareness: null in the provider configuration.`);
2854
+ }
2855
+ this.awareness.setLocalStateField(key, value);
2856
+ }
2857
+ }
2858
+
2859
+ const DEFAULT_BRUSH_CONFIG = {
2860
+ type: 'pen',
2861
+ color: DEFAULT_COLOR_PALETTE[0],
2862
+ size: 16,
2863
+ opacity: 1,
2864
+ palettes: {
2865
+ pen: [...DEFAULT_COLOR_PALETTE],
2866
+ },
2867
+ sizes: {
2868
+ pen: [...DEFAULT_STROKE_SIZES],
2869
+ },
2870
+ };
2871
+
2872
+ const DEFAULT_TEXT_CONFIG = {
2873
+ color: DEFAULT_COLOR_PALETTE[0],
2874
+ size: 8,
2875
+ opacity: 1,
2876
+ fontFamily: 'Arial',
2877
+ availableFonts: [...DEFAULT_TEXT_TOOL_AVAILABLE_FONTS],
2878
+ palette: [...DEFAULT_COLOR_PALETTE],
2879
+ sizes: [...DEFAULT_FONT_SIZES],
2880
+ };
2881
+
2882
+ const DEFAULT_LINE_TOOL_CONFIG = {
2883
+ color: DEFAULT_COLOR_PALETTE[0],
2884
+ size: 4,
2885
+ opacity: 1,
2886
+ palette: [...DEFAULT_COLOR_PALETTE],
2887
+ sizes: [...DEFAULT_STROKE_SIZES],
2888
+ arrows: {
2889
+ end: { enabled: true, style: 'triangle' },
2890
+ },
2891
+ };
2892
+
2893
+ /**
2894
+ * Default asset storage configuration. Stores bytes in IndexedDB only,
2895
+ * which provides offline-friendly behavior out of the box. Applications
2896
+ * that sync Yjs over the network should also configure a remote provider
2897
+ * (e.g. HttpAssetProvider) so images are available across devices.
2898
+ */
2899
+ const DEFAULT_ASSET_STORAGE_CONFIG = {
2900
+ providers: [],
2901
+ };
2902
+
2903
+ const DEFAULT_SHAPE_CONFIG = {
2904
+ shapeType: ShapeType.Rectangle,
2905
+ fillColor: { light: 'transparent', dark: 'transparent' },
2906
+ strokeColor: DEFAULT_COLOR_PALETTE[0],
2907
+ strokeWidth: 4,
2908
+ opacity: 1,
2909
+ fontColor: DEFAULT_COLOR_PALETTE[0],
2910
+ fontSize: 16,
2911
+ fontFamily: 'Arial',
2912
+ palette: [...DEFAULT_COLOR_PALETTE],
2913
+ sizes: [...DEFAULT_STROKE_SIZES],
2914
+ };
2915
+
2916
+ const kritzelEditorCss = () => `kritzel-editor{display:flex;margin:0;position:relative;container-type:inline-size;overflow:hidden;width:100%;height:100%;align-items:center;justify-content:center;touch-action:manipulation;user-select:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:start;line-height:normal}.editor-content{position:absolute;inset:0}.editor-content>kritzel-engine{position:absolute;inset:0;z-index:0}kritzel-controls{position:absolute;z-index:1;left:0;right:0;margin-inline:auto;width:max-content;max-width:calc(100% - 16px);bottom:var(--kritzel-editor-controls-bottom, 14px);transition:transform var(--kritzel-editor-controls-transition-duration, 0.1s) var(--kritzel-editor-controls-transition, ease-in-out)}kritzel-controls.keyboard-open{transform:var(--kritzel-editor-controls-transform, translateY(300%))}.top-left-buttons{position:absolute;z-index:1;top:var(--kritzel-editor-top-left-buttons-top, 14px);left:var(--kritzel-editor-top-left-buttons-left, 14px);display:flex;align-items:flex-start;gap:8px}.top-center-notification-layer{position:absolute;top:var(--kritzel-editor-top-center-notification-top, 14px);left:0;right:0;z-index:var(--kritzel-editor-top-center-notification-z-index, 10001);display:flex;justify-content:center;pointer-events:none}.top-center-notification-container{width:min(90vw, 420px);pointer-events:auto;animation:kritzel-notification-slide-in var(--kritzel-editor-notification-animation-duration, 220ms) var(--kritzel-editor-notification-animation-easing, cubic-bezier(0.22, 1, 0.36, 1))}.top-center-notification-container.is-dismissing{animation:kritzel-notification-fade-out var(--kritzel-editor-notification-dismiss-animation-duration, 180ms) var(--kritzel-editor-notification-dismiss-animation-easing, ease-in) forwards}@keyframes kritzel-notification-slide-in{from{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes kritzel-notification-fade-out{from{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-6px)}}@media (prefers-reduced-motion: reduce){.top-center-notification-container{animation:none}}.top-right-buttons{position:absolute;z-index:1;top:var(--kritzel-editor-top-right-buttons-top, 14px);right:var(--kritzel-editor-top-right-buttons-right, 14px);display:flex;align-items:center;gap:8px}.bottom-left-buttons{position:absolute;z-index:1;left:var(--kritzel-editor-top-left-buttons-left, 14px);bottom:var(--kritzel-editor-controls-bottom, 14px);display:flex;align-items:flex-end}@container (max-width: 767px){.bottom-left-buttons{display:none}}.top-right-button{display:flex;align-items:center;justify-content:center;width:50px;height:50px;padding:0;border:var(--kritzel-split-button-border, 1px solid #ebebeb);border-radius:var(--kritzel-split-button-border-radius, 12px);background-color:var(--kritzel-split-button-background-color, #ffffff);cursor:var(--kritzel-global-pointer-cursor, pointer);box-shadow:var(--kritzel-split-button-box-shadow, 0 0 3px rgba(0, 0, 0, 0.08));transition:background-color 150ms ease;-webkit-tap-highlight-color:transparent}.top-right-button:hover{background-color:#f5f5f5}.top-right-button:active{background-color:#ebebeb}`;
2917
+
2918
+ const KritzelEditor$1 = /*@__PURE__*/ proxyCustomElement(class KritzelEditor extends H {
2919
+ constructor(registerHost) {
2920
+ super();
2921
+ if (registerHost !== false) {
2922
+ this.__registerHost();
2923
+ }
2924
+ this.isReady = createEvent(this, "isReady");
2925
+ this.activeWorkspaceChange = createEvent(this, "activeWorkspaceChange");
2926
+ this.objectsChange = createEvent(this, "objectsChange");
2927
+ this.objectsAdded = createEvent(this, "objectsAdded");
2928
+ this.objectsRemoved = createEvent(this, "objectsRemoved");
2929
+ this.objectsUpdated = createEvent(this, "objectsUpdated");
2930
+ this.undoStateChange = createEvent(this, "undoStateChange");
2931
+ this.themeChange = createEvent(this, "themeChange");
2932
+ this.localeChange = createEvent(this, "localeChange");
2933
+ this.viewportChange = createEvent(this, "viewportChange");
2934
+ this.logout = createEvent(this, "logout");
2935
+ this.login = createEvent(this, "login");
2936
+ this.isPublicChange = createEvent(this, "isPublicChange");
2937
+ this.awarenessChange = createEvent(this, "awarenessChange");
2938
+ }
2939
+ get host() { return this; }
2940
+ scaleMax = ABSOLUTE_SCALE_MAX;
2941
+ scaleMin = ABSOLUTE_SCALE_MIN;
2942
+ lockDrawingScale = true;
2943
+ viewportBoundaryLeft = -Infinity;
2944
+ viewportBoundaryRight = Infinity;
2945
+ viewportBoundaryTop = -Infinity;
2946
+ viewportBoundaryBottom = Infinity;
2947
+ debugInfo = {
2948
+ showViewportInfo: false,
2949
+ showObjectInfo: false,
2950
+ showSyncProviderInfo: true,
2951
+ showMigrationInfo: true,
2952
+ showAssetResolverInfo: false,
2953
+ };
2954
+ user;
2955
+ activeUsers;
2956
+ controls = [
2957
+ {
2958
+ name: 'selection',
2959
+ type: 'tool',
2960
+ isDefault: true,
2961
+ tool: KritzelSelectionTool,
2962
+ icon: 'cursor',
2963
+ },
2964
+ {
2965
+ name: 'brush',
2966
+ type: 'tool',
2967
+ tool: KritzelBrushTool,
2968
+ icon: 'pen',
2969
+ config: DEFAULT_BRUSH_CONFIG,
2970
+ },
2971
+ {
2972
+ name: 'eraser',
2973
+ type: 'tool',
2974
+ tool: KritzelEraserTool,
2975
+ icon: 'eraser',
2976
+ },
2977
+ {
2978
+ name: 'line',
2979
+ type: 'tool',
2980
+ tool: KritzelLineTool,
2981
+ icon: 'arrow',
2982
+ config: DEFAULT_LINE_TOOL_CONFIG,
2983
+ },
2984
+ {
2985
+ name: 'shape',
2986
+ type: 'tool',
2987
+ tool: KritzelShapeTool,
2988
+ icon: 'shape-rectangle',
2989
+ config: DEFAULT_SHAPE_CONFIG,
2990
+ subOptions: [
2991
+ { id: 'rectangle', icon: 'shape-rectangle', label: 'Rectangle', value: ShapeType.Rectangle, toolProperty: 'shapeType' },
2992
+ { id: 'ellipse', icon: 'shape-ellipse', label: 'Ellipse', value: ShapeType.Ellipse, toolProperty: 'shapeType' },
2993
+ { id: 'triangle', icon: 'shape-triangle', label: 'Triangle', value: ShapeType.Triangle, toolProperty: 'shapeType' },
2994
+ ],
2995
+ },
2996
+ {
2997
+ name: 'text',
2998
+ type: 'tool',
2999
+ tool: KritzelTextTool,
3000
+ icon: 'type',
3001
+ config: DEFAULT_TEXT_CONFIG,
3002
+ },
3003
+ {
3004
+ name: 'image',
3005
+ type: 'tool',
3006
+ tool: KritzelImageTool,
3007
+ icon: 'image',
3008
+ },
3009
+ {
3010
+ name: 'config',
3011
+ type: 'config',
3012
+ },
3013
+ ];
3014
+ globalContextMenuItems = [
3015
+ {
3016
+ label: 'menu.paste',
3017
+ icon: 'paste',
3018
+ action: menu => this.engineRef.paste(menu.x, menu.y),
3019
+ },
3020
+ {
3021
+ label: 'menu.selectAll',
3022
+ icon: 'select-all',
3023
+ action: () => this.selectAllObjectsInViewport(),
3024
+ },
3025
+ ];
3026
+ objectContextMenuItems = [
3027
+ { label: 'menu.copy', icon: 'copy', group: 'clipboard', action: () => this.engineRef.copy() },
3028
+ { label: 'menu.cut', icon: 'cut', group: 'clipboard', action: () => this.engineRef.cut() },
3029
+ {
3030
+ label: 'menu.paste',
3031
+ icon: 'paste',
3032
+ group: 'clipboard',
3033
+ action: (menu, _) => this.engineRef.paste(menu.x, menu.y),
3034
+ },
3035
+ {
3036
+ label: 'menu.order',
3037
+ icon: 'ordering',
3038
+ group: 'other',
3039
+ children: [
3040
+ { label: 'menu.bringToFront', icon: 'bring-to-front', action: () => this.engineRef.bringToFront() },
3041
+ { label: 'menu.sendToBack', icon: 'send-to-back', action: () => this.engineRef.sendToBack() },
3042
+ { label: 'menu.moveUp', icon: 'arrow-up-from-dot', action: () => this.engineRef.bringForward() },
3043
+ { label: 'menu.moveDown', icon: 'arrow-down-from-dot', action: () => this.engineRef.sendBackward() },
3044
+ ],
3045
+ },
3046
+ {
3047
+ label: 'menu.align',
3048
+ icon: 'align',
3049
+ group: 'other',
3050
+ children: [
3051
+ { label: 'menu.alignLeft', icon: 'align-start-vertical', action: () => this.engineRef.alignObjects(KritzelAlignment.StartHorizontal) },
3052
+ { label: 'menu.alignCenterHorizontal', icon: 'align-center-horizontal', action: () => this.engineRef.alignObjects(KritzelAlignment.CenterHorizontal) },
3053
+ { label: 'menu.alignRight', icon: 'align-end-vertical', action: () => this.engineRef.alignObjects(KritzelAlignment.EndHorizontal) },
3054
+ { label: 'menu.alignTop', icon: 'align-start-horizontal', action: () => this.engineRef.alignObjects(KritzelAlignment.StartVertical) },
3055
+ { label: 'menu.alignCenterVertical', icon: 'align-center-vertical', action: () => this.engineRef.alignObjects(KritzelAlignment.CenterVertical) },
3056
+ { label: 'menu.alignBottom', icon: 'align-end-horizontal', action: () => this.engineRef.alignObjects(KritzelAlignment.EndVertical) },
3057
+ ],
3058
+ },
3059
+ {
3060
+ label: 'menu.group',
3061
+ icon: 'group',
3062
+ group: 'other',
3063
+ children: [
3064
+ {
3065
+ label: 'menu.group',
3066
+ icon: 'group',
3067
+ action: () => this.engineRef.group(),
3068
+ },
3069
+ {
3070
+ label: 'menu.ungroup',
3071
+ icon: 'ungroup',
3072
+ action: () => this.engineRef.ungroup(),
3073
+ },
3074
+ ],
3075
+ },
3076
+ {
3077
+ label: 'menu.export',
3078
+ icon: 'download',
3079
+ group: 'export',
3080
+ children: [
3081
+ { label: 'menu.exportAsSvg', icon: 'download', action: () => this.engineRef.exportSelectedObjectsAsSvg() },
3082
+ { label: 'menu.exportAsPng', icon: 'download', action: () => this.engineRef.exportSelectedObjectsAsPng() },
3083
+ ],
3084
+ },
3085
+ { label: 'menu.delete', icon: 'delete', group: 'edit', action: () => this.engineRef.delete() },
3086
+ ];
3087
+ themes;
3088
+ theme = 'light';
3089
+ /** License key that, when valid, removes the "Powered by Kritzel" watermark. */
3090
+ licenseKey;
3091
+ /** The current locale (language) code applied to the editor, e.g. 'en', 'de', 'fr'. */
3092
+ locale = 'en';
3093
+ /** An array of available locale definitions (with optional partial term overrides). */
3094
+ locales;
3095
+ /** The locale used to resolve terms missing from the active locale. */
3096
+ fallbackLocale = 'en';
3097
+ customSvgIcons = {};
3098
+ /**
3099
+ * Registers fonts for runtime usage (for example custom object rendering).
3100
+ * Text-tool config tooltip options are controlled via controls[].config.availableFonts.
3101
+ */
3102
+ customFonts = {};
3103
+ isPanningEnabled = true;
3104
+ isZoomingEnabled = true;
3105
+ isControlsVisible = true;
3106
+ isUtilityPanelVisible = true;
3107
+ isWorkspaceManagerVisible = true;
3108
+ isMoreMenuVisible = true;
3109
+ isZoomPanelVisible = true;
3110
+ isObjectDistanceFadingActive = false;
3111
+ syncConfig = DEFAULT_SYNC_CONFIG;
3112
+ assetStorageConfig = DEFAULT_ASSET_STORAGE_CONFIG;
3113
+ /** The element to use as the target for the cursor. Defaults to the editor container if not set. */
3114
+ cursorTarget;
3115
+ /** Optional login configuration. When provided, a "Sign in" button is shown that opens a login dialog with the configured providers. */
3116
+ loginConfig;
3117
+ /** Whether the editor is in a loading state. When true, a loading overlay is displayed. */
3118
+ isLoading = false;
3119
+ /** Optional unique identifier for namespacing storage keys across multiple editor instances. */
3120
+ editorId;
3121
+ /** Optional workspace ID to set as active. If provided, the editor will automatically activate the workspace with this ID. */
3122
+ activeWorkspaceId;
3123
+ isReady;
3124
+ activeWorkspaceChange;
3125
+ objectsChange;
3126
+ objectsAdded;
3127
+ objectsRemoved;
3128
+ objectsUpdated;
3129
+ undoStateChange;
3130
+ themeChange;
3131
+ localeChange;
3132
+ viewportChange;
3133
+ logout;
3134
+ login;
3135
+ isPublicChange;
3136
+ awarenessChange;
3137
+ isEngineReady = false;
3138
+ isControlsReady = false;
3139
+ isWorkspaceManagerReady = false;
3140
+ workspaces = [];
3141
+ activeWorkspace;
3142
+ isVirtualKeyboardOpen = false;
3143
+ undoState = null;
3144
+ isBackToContentButtonVisible = false;
3145
+ /** Localized strings for editor-owned UI (e.g. the more menu), resolved from the active locale. */
3146
+ resolvedTerms = {};
3147
+ /** Available locales as `{ code, label }` options for the settings language selector. */
3148
+ availableLocaleOptions = [];
3149
+ currentZoomPercent = 100;
3150
+ shortcuts = [];
3151
+ currentIsPublic = false;
3152
+ isEditorVisible = false;
3153
+ activeNotification;
3154
+ isNotificationDismissing = false;
3155
+ normalizedControls = [];
3156
+ notificationDismissTimeout;
3157
+ notificationDismissAnimationTimeout;
3158
+ notificationDisplayDurationMs = 5000;
3159
+ notificationDismissAnimationDurationMs = 180;
3160
+ isNotificationHovered = false;
3161
+ customFontsLoadVersion = 0;
3162
+ customFontsReady = Promise.resolve();
3163
+ onIsEngineReady(newValue) {
3164
+ if (newValue && this.isControlsReady) {
3165
+ this.checkIsReady();
3166
+ }
3167
+ }
3168
+ onIsControlsReady(newValue) {
3169
+ if (newValue && this.isEngineReady) {
3170
+ this.checkIsReady();
3171
+ }
3172
+ }
3173
+ onWorkspacesChange(newWorkspaces) {
3174
+ const activeWorkspace = this.activeWorkspace;
3175
+ if (activeWorkspace) {
3176
+ const updatedActiveWorkspace = newWorkspaces.find(ws => ws.id === activeWorkspace.id);
3177
+ if (updatedActiveWorkspace && updatedActiveWorkspace !== activeWorkspace) {
3178
+ this.activeWorkspace = updatedActiveWorkspace;
3179
+ }
3180
+ }
3181
+ // If activeWorkspaceId is set, try to keep it in sync with the updated workspaces list
3182
+ if (this.activeWorkspaceId) {
3183
+ const workspaceWithId = newWorkspaces.find(ws => ws.id === this.activeWorkspaceId);
3184
+ if (workspaceWithId && workspaceWithId !== this.activeWorkspace) {
3185
+ this.activeWorkspace = workspaceWithId;
3186
+ }
3187
+ }
3188
+ }
3189
+ onActiveWorkspaceChange() {
3190
+ this.updateCurrentIsPublic();
3191
+ }
3192
+ onCustomFontsChange(newValue) {
3193
+ void this.registerCustomFonts(newValue);
3194
+ }
3195
+ onControlsChange(newValue) {
3196
+ this.normalizedControls = this.normalizeControls(newValue);
3197
+ }
3198
+ onActiveWorkspaceIdChange(newId) {
3199
+ // If no ID is provided, do nothing (allows other logic to control activeWorkspace)
3200
+ if (!newId) {
3201
+ return;
3202
+ }
3203
+ // If workspaces are not loaded yet, the watch will fire again once they are
3204
+ if (this.workspaces.length === 0) {
3205
+ return;
3206
+ }
3207
+ // Find the workspace with the matching ID
3208
+ const workspace = this.workspaces.find(ws => ws.id === newId);
3209
+ if (workspace) {
3210
+ // Only update if it's different from the current activeWorkspace
3211
+ if (workspace !== this.activeWorkspace) {
3212
+ this.activeWorkspace = workspace;
3213
+ }
3214
+ }
3215
+ else {
3216
+ console.warn(`[KritzelEditor] No workspace found with ID: ${newId}`);
3217
+ }
3218
+ }
3219
+ onCurrentThemeChange() {
3220
+ this.applyTheme();
3221
+ setTimeout(() => this.setOsSpecificCssVariables(), 0);
3222
+ if (this.engineRef) {
3223
+ this.engineRef.saveSettings(this.currentSettingsConfig);
3224
+ }
3225
+ }
3226
+ onThemesChange() {
3227
+ this.applyTheme();
3228
+ }
3229
+ onLocaleChange(newValue) {
3230
+ if (this.engineRef) {
3231
+ this.engineRef.setLocale(newValue);
3232
+ this.engineRef.saveSettings(this.currentSettingsConfig);
3233
+ void this.refreshLocalizedTerms();
3234
+ }
3235
+ }
3236
+ /**
3237
+ * Refreshes the editor-owned localized strings (e.g. the more menu and the
3238
+ * strings forwarded to child UI components) from the engine's localization
3239
+ * manager for the active locale.
3240
+ */
3241
+ async refreshLocalizedTerms() {
3242
+ if (!this.engineRef) {
3243
+ return;
3244
+ }
3245
+ this.resolvedTerms = await this.engineRef.getResolvedTerms();
3246
+ this.availableLocaleOptions = await this.engineRef.getAvailableLocaleOptions();
3247
+ }
3248
+ onTouchStart(event) {
3249
+ if (event.cancelable) {
3250
+ event.preventDefault();
3251
+ }
3252
+ }
3253
+ async getObjectById(id) {
3254
+ return this.engineRef.getObjectById(id);
3255
+ }
3256
+ async addObject(object) {
3257
+ return this.engineRef.addObject(object);
3258
+ }
3259
+ async addObjects(objects) {
3260
+ return this.engineRef.addObjects(objects);
3261
+ }
3262
+ async updateObject(object, updatedProperties) {
3263
+ return this.engineRef.updateObject(object, updatedProperties);
3264
+ }
3265
+ async removeObject(object) {
3266
+ return this.engineRef.removeObject(object);
3267
+ }
3268
+ async removeObjects(objects) {
3269
+ return this.engineRef.removeObjects(objects);
3270
+ }
3271
+ async getSelectedObjects() {
3272
+ return this.engineRef.getSelectedObjects();
3273
+ }
3274
+ async selectObjects(objects) {
3275
+ return this.engineRef.selectObjects(objects);
3276
+ }
3277
+ async selectAllObjectsInViewport() {
3278
+ return this.engineRef.selectAllObjectsInViewport();
3279
+ }
3280
+ async clearSelection() {
3281
+ this.engineRef.clearSelection();
3282
+ }
3283
+ async centerObjectInViewport(object) {
3284
+ return this.engineRef.centerObjectInViewport(object);
3285
+ }
3286
+ async panToObject(object) {
3287
+ return this.engineRef.panToObject(object);
3288
+ }
3289
+ async backToContent() {
3290
+ return this.engineRef.backToContent();
3291
+ }
3292
+ async centerAllObjects(animate = true) {
3293
+ return this.engineRef.centerAllObjects(animate);
3294
+ }
3295
+ async centerObjects(objects, animate = true) {
3296
+ return this.engineRef.centerObjects(objects, animate);
3297
+ }
3298
+ async setViewport(x, y, scale) {
3299
+ return this.engineRef.setViewport(x, y, scale);
3300
+ }
3301
+ async panTo(x, y) {
3302
+ return this.engineRef.panTo(x, y);
3303
+ }
3304
+ async zoomTo(scale, worldX, worldY) {
3305
+ return this.engineRef.zoomTo(scale, worldX, worldY);
3306
+ }
3307
+ async zoomIn(factor = 1.6, duration = 200) {
3308
+ return this.engineRef.zoomIn(factor, duration);
3309
+ }
3310
+ async zoomOut(factor = 1.6, duration = 200) {
3311
+ return this.engineRef.zoomOut(factor, duration);
3312
+ }
3313
+ async getViewport() {
3314
+ return this.engineRef.getViewport();
3315
+ }
3316
+ async screenToWorld(x, y) {
3317
+ return this.engineRef.screenToWorld(x, y);
3318
+ }
3319
+ async worldToScreen(x, y) {
3320
+ return this.engineRef.worldToScreen(x, y);
3321
+ }
3322
+ async createWorkspace(workspace) {
3323
+ return this.engineRef.createWorkspace(workspace);
3324
+ }
3325
+ async updateWorkspace(workspace) {
3326
+ return this.engineRef.updateWorkspace(workspace);
3327
+ }
3328
+ async deleteWorkspace(workspace) {
3329
+ return this.engineRef.deleteWorkspace(workspace);
3330
+ }
3331
+ async getWorkspaces() {
3332
+ return this.engineRef.getWorkspaces();
3333
+ }
3334
+ async getActiveWorkspace() {
3335
+ return this.engineRef.getActiveWorkspace();
3336
+ }
3337
+ async loadSharedWorkspace(token) {
3338
+ return this.engineRef.loadSharedWorkspace(token);
3339
+ }
3340
+ async reinitSync() {
3341
+ return this.engineRef.reinitSync();
3342
+ }
3343
+ // ── Tool management ─────────────────────────────────────────────────
3344
+ async registerTool(toolName, toolClass, toolConfig) {
3345
+ return this.engineRef.registerTool(toolName, toolClass, toolConfig);
3346
+ }
3347
+ async changeActiveTool(tool) {
3348
+ return this.engineRef.changeActiveTool(tool);
3349
+ }
3350
+ async changeActiveToolByName(toolName) {
3351
+ return this.engineRef.changeActiveToolByName(toolName);
3352
+ }
3353
+ async disable() {
3354
+ return this.engineRef.disable();
3355
+ }
3356
+ async enable() {
3357
+ return this.engineRef.enable();
3358
+ }
3359
+ async copy() {
3360
+ return this.engineRef.copy();
3361
+ }
3362
+ async cut() {
3363
+ return this.engineRef.cut();
3364
+ }
3365
+ async paste(x, y) {
3366
+ return this.engineRef.paste(x, y);
3367
+ }
3368
+ async delete() {
3369
+ return this.engineRef.delete();
3370
+ }
3371
+ async bringForward(object) {
3372
+ return this.engineRef.bringForward(object);
3373
+ }
3374
+ async sendBackward(object) {
3375
+ return this.engineRef.sendBackward(object);
3376
+ }
3377
+ async bringToFront(object) {
3378
+ return this.engineRef.bringToFront(object);
3379
+ }
3380
+ async sendToBack(object) {
3381
+ return this.engineRef.sendToBack(object);
3382
+ }
3383
+ async alignObjects(alignment) {
3384
+ return this.engineRef.alignObjects(alignment);
3385
+ }
3386
+ async group() {
3387
+ return this.engineRef.group();
3388
+ }
3389
+ async ungroup() {
3390
+ return this.engineRef.ungroup();
3391
+ }
3392
+ async undo() {
3393
+ return this.engineRef.undo();
3394
+ }
3395
+ async redo() {
3396
+ return this.engineRef.redo();
3397
+ }
3398
+ async getScreenshot(format = 'png', options) {
3399
+ return this.engineRef.getScreenshot(format, options);
3400
+ }
3401
+ async exportViewportAsPng(options) {
3402
+ return this.engineRef.exportViewportAsPng(options);
3403
+ }
3404
+ async exportViewportAsSvg(options) {
3405
+ return this.engineRef.exportViewportAsSvg(options);
3406
+ }
3407
+ async exportSelectedObjectsAsPng() {
3408
+ return this.engineRef.exportSelectedObjectsAsPng();
3409
+ }
3410
+ async exportSelectedObjectsAsSvg() {
3411
+ return this.engineRef.exportSelectedObjectsAsSvg();
3412
+ }
3413
+ async downloadAsJson(filename) {
3414
+ return this.engineRef.downloadAsJson(filename);
3415
+ }
3416
+ async importFromFile() {
3417
+ return this.engineRef.importFromFile();
3418
+ }
3419
+ async loadObjectsFromJson(json) {
3420
+ return this.engineRef.loadObjectsFromJson(json);
3421
+ }
3422
+ async getObjectsTotalCount() {
3423
+ return this.engineRef.getObjectsTotalCount();
3424
+ }
3425
+ async getAllObjects() {
3426
+ return this.engineRef.getAllObjects();
3427
+ }
3428
+ async findObjects(predicate) {
3429
+ return this.engineRef.findObjects(predicate);
3430
+ }
3431
+ async getObjectsInViewport() {
3432
+ return this.engineRef.getObjectsInViewport();
3433
+ }
3434
+ async hideContextMenu() {
3435
+ return this.engineRef.hideContextMenu();
3436
+ }
3437
+ async openContextMenu(options) {
3438
+ return this.engineRef.openContextMenu(options);
3439
+ }
3440
+ async triggerSelectionChange() {
3441
+ return this.engineRef.triggerSelectionChange();
3442
+ }
3443
+ async getDisplayableShortcuts() {
3444
+ return this.engineRef.getDisplayableShortcuts();
3445
+ }
3446
+ /**
3447
+ * Triggers a UI notification programmatically.
3448
+ * @param notification - Notification payload. `id` and `timestamp` are optional.
3449
+ */
3450
+ async triggerNotification(notification) {
3451
+ const normalizedNotification = {
3452
+ ...notification,
3453
+ id: notification.id ?? ObjectHelper.generateUUID(),
3454
+ timestamp: notification.timestamp ?? new Date(),
3455
+ };
3456
+ this.clearNotificationDismissAnimationTimer();
3457
+ this.isNotificationDismissing = false;
3458
+ this.isNotificationHovered = false;
3459
+ this.activeNotification = normalizedNotification;
3460
+ this.scheduleNotificationDismiss();
3461
+ }
3462
+ engineRef;
3463
+ controlsRef;
3464
+ settingsRef;
3465
+ exportRef;
3466
+ splitButtonRef;
3467
+ shareDialogRef;
3468
+ loginDialogRef;
3469
+ currentUserDialogRef;
3470
+ componentWillLoad() {
3471
+ this.normalizedControls = this.normalizeControls(this.controls);
3472
+ this.loadSettingsFromStorage();
3473
+ this.applyTheme();
3474
+ }
3475
+ isTextToolConfig(config) {
3476
+ return !!config && 'fontFamily' in config && 'size' in config && 'color' in config;
3477
+ }
3478
+ normalizeControls(controls) {
3479
+ return controls.map(control => {
3480
+ if (!this.isTextToolConfig(control.config)) {
3481
+ return control;
3482
+ }
3483
+ return {
3484
+ ...control,
3485
+ config: {
3486
+ ...control.config,
3487
+ availableFonts: resolveTextToolAvailableFonts(control.config.availableFonts),
3488
+ },
3489
+ };
3490
+ });
3491
+ }
3492
+ applyTheme() {
3493
+ const themeObj = this.resolveThemeObject();
3494
+ ThemeHelper.applyThemeToElement(this.host, themeObj);
3495
+ }
3496
+ resolveThemeObject() {
3497
+ return this.themes?.find(t => t.name === this.theme)
3498
+ ?? (this.theme === 'dark' ? darkTheme : lightTheme);
3499
+ }
3500
+ componentDidLoad() {
3501
+ this.registerCustomSvgIcons();
3502
+ this.registerCustomFonts();
3503
+ this.listenForMobileKeyboard();
3504
+ this.setOsSpecificCssVariables();
3505
+ }
3506
+ disconnectedCallback() {
3507
+ this.clearNotificationDismissTimer();
3508
+ this.clearNotificationDismissAnimationTimer();
3509
+ }
3510
+ async checkIsReady() {
3511
+ await customElements.whenDefined('kritzel-editor');
3512
+ await customElements.whenDefined('kritzel-workspace-manager');
3513
+ await customElements.whenDefined('kritzel-controls');
3514
+ await customElements.whenDefined('kritzel-engine');
3515
+ await this.waitForCustomFontsReady();
3516
+ if (!this.isEngineReady || !this.isControlsReady || !this.isWorkspaceManagerReady || !this.activeWorkspace) {
3517
+ return;
3518
+ }
3519
+ this.isEditorVisible = true;
3520
+ const { id, name, isPublic, createdAt, updatedAt } = this.activeWorkspace;
3521
+ this.isReady.emit({
3522
+ host: this.host,
3523
+ activeWorkspace: {
3524
+ id,
3525
+ name,
3526
+ isPublic,
3527
+ createdAt,
3528
+ updatedAt,
3529
+ },
3530
+ syncConfig: this.syncConfig,
3531
+ assetStorageConfig: this.assetStorageConfig,
3532
+ loginConfig: this.loginConfig,
3533
+ theme: this.theme
3534
+ });
3535
+ }
3536
+ async onEngineReady(event) {
3537
+ this.isEngineReady = true;
3538
+ if (!event.detail.activeWorkspace) {
3539
+ return;
3540
+ }
3541
+ this.activeWorkspace = event.detail.activeWorkspace;
3542
+ this.workspaces = event.detail.workspaces;
3543
+ this.currentIsPublic = await this.engineRef.getIsPublic();
3544
+ await this.refreshLocalizedTerms();
3545
+ const viewport = await this.engineRef.getViewport();
3546
+ this.currentZoomPercent = this.getZoomPercentFromScale(viewport.scale);
3547
+ this.loadShortcuts();
3548
+ }
3549
+ handleWorkspacesChange(event) {
3550
+ event.stopPropagation();
3551
+ this.workspaces = event.detail;
3552
+ }
3553
+ handleActiveWorkspaceChange(event) {
3554
+ event.stopPropagation();
3555
+ this.activeWorkspace = event.detail;
3556
+ if (!this.isEngineReady) {
3557
+ return;
3558
+ }
3559
+ const { id, name, isPublic, createdAt, updatedAt } = this.activeWorkspace;
3560
+ this.activeWorkspaceChange.emit({
3561
+ id,
3562
+ name,
3563
+ isPublic,
3564
+ createdAt,
3565
+ updatedAt,
3566
+ });
3567
+ }
3568
+ handleObjectsChange(event) {
3569
+ event.stopPropagation();
3570
+ this.objectsChange.emit(event.detail);
3571
+ }
3572
+ handleObjectsAdded(event) {
3573
+ event.stopPropagation();
3574
+ this.objectsAdded.emit(event.detail);
3575
+ }
3576
+ handleObjectsRemoved(event) {
3577
+ event.stopPropagation();
3578
+ this.objectsRemoved.emit(event.detail);
3579
+ }
3580
+ handleObjectsUpdated(event) {
3581
+ event.stopPropagation();
3582
+ this.objectsUpdated.emit(event.detail);
3583
+ }
3584
+ handleUndoStateChange(event) {
3585
+ event.stopPropagation();
3586
+ this.undoStateChange.emit(event.detail);
3587
+ this.undoState = event.detail;
3588
+ }
3589
+ async handleObjectsInViewportChange(event) {
3590
+ event.stopPropagation();
3591
+ const hasVisibleObjects = this.getContentObjects(event.detail).length > 0;
3592
+ const hasAnyObjectsAtAll = this.getContentObjects(await this.engineRef.getAllObjects()).length > 0;
3593
+ this.isBackToContentButtonVisible = !hasVisibleObjects && hasAnyObjectsAtAll;
3594
+ }
3595
+ handleViewportChange(event) {
3596
+ event.stopPropagation();
3597
+ this.currentZoomPercent = this.getZoomPercentFromScale(event.detail.scale);
3598
+ this.viewportChange.emit(event.detail);
3599
+ }
3600
+ getZoomPercentFromScale(scale) {
3601
+ if (!Number.isFinite(scale) || scale <= 0) {
3602
+ return 100;
3603
+ }
3604
+ return Math.round(scale * 100);
3605
+ }
3606
+ handleAwarenessChange(event) {
3607
+ event.stopPropagation();
3608
+ this.awarenessChange.emit(event.detail);
3609
+ }
3610
+ handleNotificationsChange(event) {
3611
+ event.stopPropagation();
3612
+ this.clearNotificationDismissAnimationTimer();
3613
+ this.isNotificationDismissing = false;
3614
+ this.isNotificationHovered = false;
3615
+ this.activeNotification = event.detail;
3616
+ this.scheduleNotificationDismiss();
3617
+ }
3618
+ handleNotificationHoverChange(event) {
3619
+ event.stopPropagation();
3620
+ this.isNotificationHovered = event.detail;
3621
+ if (this.isNotificationHovered) {
3622
+ this.clearNotificationDismissTimer();
3623
+ return;
3624
+ }
3625
+ if (this.activeNotification && !this.isNotificationDismissing) {
3626
+ this.scheduleNotificationDismiss();
3627
+ }
3628
+ }
3629
+ scheduleNotificationDismiss() {
3630
+ this.clearNotificationDismissTimer();
3631
+ this.notificationDismissTimeout = setTimeout(() => {
3632
+ this.dismissNotification();
3633
+ }, this.notificationDisplayDurationMs);
3634
+ }
3635
+ clearNotificationDismissTimer() {
3636
+ if (this.notificationDismissTimeout) {
3637
+ clearTimeout(this.notificationDismissTimeout);
3638
+ this.notificationDismissTimeout = undefined;
3639
+ }
3640
+ }
3641
+ clearNotificationDismissAnimationTimer() {
3642
+ if (this.notificationDismissAnimationTimeout) {
3643
+ clearTimeout(this.notificationDismissAnimationTimeout);
3644
+ this.notificationDismissAnimationTimeout = undefined;
3645
+ }
3646
+ }
3647
+ dismissNotification = () => {
3648
+ this.clearNotificationDismissTimer();
3649
+ this.isNotificationHovered = false;
3650
+ if (!this.activeNotification || this.isNotificationDismissing) {
3651
+ return;
3652
+ }
3653
+ this.isNotificationDismissing = true;
3654
+ this.clearNotificationDismissAnimationTimer();
3655
+ this.notificationDismissAnimationTimeout = setTimeout(() => {
3656
+ this.activeNotification = undefined;
3657
+ this.isNotificationDismissing = false;
3658
+ this.notificationDismissAnimationTimeout = undefined;
3659
+ }, this.notificationDismissAnimationDurationMs);
3660
+ };
3661
+ handleSettingsChange(event) {
3662
+ this.scaleMin = event.detail.scaleMin;
3663
+ this.scaleMax = event.detail.scaleMax;
3664
+ this.lockDrawingScale = event.detail.lockDrawingScale;
3665
+ this.theme = event.detail.theme;
3666
+ if (typeof event.detail.locale === 'string' && event.detail.locale !== this.locale) {
3667
+ this.locale = event.detail.locale;
3668
+ this.localeChange.emit(event.detail.locale);
3669
+ }
3670
+ this.viewportBoundaryLeft = event.detail.viewportBoundaryLeft ?? -Infinity;
3671
+ this.viewportBoundaryRight = event.detail.viewportBoundaryRight ?? Infinity;
3672
+ this.viewportBoundaryTop = event.detail.viewportBoundaryTop ?? -Infinity;
3673
+ this.viewportBoundaryBottom = event.detail.viewportBoundaryBottom ?? Infinity;
3674
+ this.debugInfo = event.detail.debugInfo;
3675
+ if (this.engineRef) {
3676
+ this.engineRef.saveSettings(event.detail);
3677
+ }
3678
+ this.themeChange.emit(event.detail.theme);
3679
+ }
3680
+ get moreMenuItems() {
3681
+ return [
3682
+ {
3683
+ id: 'share',
3684
+ label: this.resolvedTerms['menu.share'] ?? 'Share',
3685
+ icon: 'share',
3686
+ action: () => {
3687
+ if (!this.isLoggedIn && this.loginConfig) {
3688
+ this.openLoginDialog();
3689
+ return;
3690
+ }
3691
+ this.shareDialogRef.open();
3692
+ },
3693
+ },
3694
+ {
3695
+ id: 'export',
3696
+ label: this.resolvedTerms['menu.export'] ?? 'Export',
3697
+ icon: 'upload',
3698
+ action: async () => {
3699
+ const preview = await this.engineRef.getScreenshot('png');
3700
+ this.exportRef.open(preview ?? undefined);
3701
+ },
3702
+ },
3703
+ {
3704
+ id: 'import',
3705
+ label: this.resolvedTerms['menu.import'] ?? 'Import',
3706
+ icon: 'download',
3707
+ action: () => this.engineRef.importFromFile(),
3708
+ },
3709
+ {
3710
+ id: 'settings',
3711
+ label: this.resolvedTerms['menu.settings'] ?? 'Settings',
3712
+ icon: 'settings',
3713
+ action: () => this.settingsRef.open(),
3714
+ }
3715
+ ];
3716
+ }
3717
+ handleToggleIsPublic = async (event) => {
3718
+ const isPublic = event.detail;
3719
+ const activeWorkspace = await this.engineRef.getActiveWorkspace();
3720
+ activeWorkspace.isPublic = isPublic;
3721
+ await this.engineRef.updateWorkspace(activeWorkspace);
3722
+ this.activeWorkspace = activeWorkspace.clone();
3723
+ this.isPublicChange.emit({ isPublic, workspaceId: activeWorkspace.id });
3724
+ };
3725
+ /**
3726
+ * Updates the currentIsPublic state from the active workspace and emits the isPublicChange event.
3727
+ */
3728
+ updateCurrentIsPublic() {
3729
+ const isPublic = this.activeWorkspace?.isPublic ?? false;
3730
+ const workspaceId = this.activeWorkspace?.id;
3731
+ this.currentIsPublic = isPublic;
3732
+ if (!workspaceId) {
3733
+ return;
3734
+ }
3735
+ this.isPublicChange.emit({ isPublic, workspaceId });
3736
+ }
3737
+ handleProviderLogin = (event) => {
3738
+ this.login.emit(event.detail);
3739
+ };
3740
+ handleCurrentUserLogout = () => {
3741
+ this.logout.emit();
3742
+ };
3743
+ get isLoggedIn() {
3744
+ return !!this.user && !this.user.isGuest;
3745
+ }
3746
+ async openLoginDialog() {
3747
+ this.loginDialogRef?.open();
3748
+ }
3749
+ async setLoginLoading(provider) {
3750
+ this.loginDialogRef?.setLoading(provider);
3751
+ }
3752
+ /**
3753
+ * Sets the active locale (language) and re-renders the UI.
3754
+ * @param code - The locale code to activate, e.g. 'de'.
3755
+ */
3756
+ async setLocale(code) {
3757
+ this.locale = code;
3758
+ await this.engineRef?.setLocale(code);
3759
+ }
3760
+ /**
3761
+ * Gets the currently active locale code.
3762
+ */
3763
+ async getLocale() {
3764
+ return this.engineRef ? this.engineRef.getLocale() : this.locale;
3765
+ }
3766
+ /**
3767
+ * Gets the list of available locale codes (built-in and registered).
3768
+ */
3769
+ async getAvailableLocales() {
3770
+ return this.engineRef ? this.engineRef.getAvailableLocales() : [];
3771
+ }
3772
+ /**
3773
+ * Registers additional locale definitions (with optional partial term overrides).
3774
+ * @param locales - The locale definitions to register.
3775
+ */
3776
+ async registerLocales(locales) {
3777
+ await this.engineRef?.registerLocales(locales);
3778
+ }
3779
+ /**
3780
+ * Registers custom fonts for the editor runtime.
3781
+ * @param fonts - Mapping from font keys to family names or font definitions.
3782
+ * @remarks This no longer controls the text-tool config tooltip font options.
3783
+ * Configure tooltip fonts via controls[].config.availableFonts.
3784
+ */
3785
+ async registerFonts(fonts) {
3786
+ await this.registerCustomFonts(fonts);
3787
+ }
3788
+ /**
3789
+ * Resolves a term key to its translated string for the active locale.
3790
+ * @param key - The term key to resolve.
3791
+ * @param vars - Optional values for `{placeholder}` interpolation.
3792
+ */
3793
+ async t(key, vars) {
3794
+ return this.engineRef ? this.engineRef.t(key, vars) : key;
3795
+ }
3796
+ getSettingsStorageKey() {
3797
+ return this.editorId ? `kritzel-settings-${this.editorId}` : 'kritzel-settings';
3798
+ }
3799
+ loadSettingsFromStorage() {
3800
+ const stored = localStorage.getItem(this.getSettingsStorageKey());
3801
+ if (stored) {
3802
+ try {
3803
+ const parsed = JSON.parse(stored);
3804
+ if (typeof parsed.scaleMin === 'number') {
3805
+ this.scaleMin = parsed.scaleMin;
3806
+ }
3807
+ if (typeof parsed.scaleMax === 'number') {
3808
+ this.scaleMax = parsed.scaleMax;
3809
+ }
3810
+ if (typeof parsed.lockDrawingScale === 'boolean') {
3811
+ this.lockDrawingScale = parsed.lockDrawingScale;
3812
+ }
3813
+ if (typeof parsed.theme === 'string') {
3814
+ this.theme = parsed.theme;
3815
+ }
3816
+ if (typeof parsed.locale === 'string') {
3817
+ this.locale = parsed.locale;
3818
+ }
3819
+ if (typeof parsed.viewportBoundaryLeft === 'number') {
3820
+ this.viewportBoundaryLeft = parsed.viewportBoundaryLeft;
3821
+ }
3822
+ if (typeof parsed.viewportBoundaryRight === 'number') {
3823
+ this.viewportBoundaryRight = parsed.viewportBoundaryRight;
3824
+ }
3825
+ if (typeof parsed.viewportBoundaryTop === 'number') {
3826
+ this.viewportBoundaryTop = parsed.viewportBoundaryTop;
3827
+ }
3828
+ if (typeof parsed.viewportBoundaryBottom === 'number') {
3829
+ this.viewportBoundaryBottom = parsed.viewportBoundaryBottom;
3830
+ }
3831
+ if (parsed.debugInfo) {
3832
+ this.debugInfo = { ...this.debugInfo, ...parsed.debugInfo };
3833
+ }
3834
+ }
3835
+ catch {
3836
+ // Invalid JSON, use prop defaults
3837
+ }
3838
+ }
3839
+ }
3840
+ async loadShortcuts() {
3841
+ this.shortcuts = await this.engineRef.getDisplayableShortcuts();
3842
+ }
3843
+ get currentSettingsConfig() {
3844
+ return {
3845
+ scaleMin: this.scaleMin,
3846
+ scaleMax: this.scaleMax,
3847
+ lockDrawingScale: this.lockDrawingScale,
3848
+ theme: this.theme,
3849
+ locale: this.locale,
3850
+ viewportBoundaryLeft: this.viewportBoundaryLeft,
3851
+ viewportBoundaryRight: this.viewportBoundaryRight,
3852
+ viewportBoundaryTop: this.viewportBoundaryTop,
3853
+ viewportBoundaryBottom: this.viewportBoundaryBottom,
3854
+ debugInfo: this.debugInfo,
3855
+ };
3856
+ }
3857
+ getContentObjects(objects) {
3858
+ return objects.filter(obj => !(obj instanceof KritzelSelectionGroup) && !(obj instanceof KritzelSelectionBox));
3859
+ }
3860
+ registerCustomSvgIcons() {
3861
+ for (const [name, svg] of Object.entries(this.customSvgIcons)) {
3862
+ KritzelIconRegistry.register(name, svg);
3863
+ }
3864
+ }
3865
+ async registerCustomFonts(fonts = this.customFonts) {
3866
+ KritzelFontRegistry.registerFonts(fonts);
3867
+ const currentVersion = ++this.customFontsLoadVersion;
3868
+ const loadPromise = KritzelFontRegistry.waitForFonts(fonts);
3869
+ this.customFontsReady = loadPromise;
3870
+ await loadPromise;
3871
+ if (currentVersion !== this.customFontsLoadVersion) {
3872
+ await this.waitForCustomFontsReady();
3873
+ }
3874
+ }
3875
+ async waitForCustomFontsReady() {
3876
+ while (true) {
3877
+ const version = this.customFontsLoadVersion;
3878
+ await this.customFontsReady;
3879
+ if (version === this.customFontsLoadVersion) {
3880
+ return;
3881
+ }
3882
+ }
3883
+ }
3884
+ listenForMobileKeyboard() {
3885
+ KritzelKeyboardHelper.onKeyboardVisibleChanged(isOpen => {
3886
+ this.isVirtualKeyboardOpen = isOpen;
3887
+ });
3888
+ }
3889
+ setOsSpecificCssVariables() {
3890
+ const os = KritzelDevicesHelper.detectOS();
3891
+ switch (os) {
3892
+ case 'iOS':
3893
+ // iOS specific adjustments
3894
+ this.host.style.setProperty('--kritzel-editor-top-left-buttons-top', '14px');
3895
+ this.host.style.setProperty('--kritzel-editor-top-left-buttons-left', '14px');
3896
+ this.host.style.setProperty('--kritzel-editor-controls-bottom', '14px');
3897
+ this.host.style.setProperty('--kritzel-editor-controls-transition', 'cubic-bezier(0.25, 0.1, 0.25, 1.0)');
3898
+ this.host.style.setProperty('--kritzel-editor-controls-transform', 'translateY(200%)');
3899
+ this.host.style.setProperty('--kritzel-editor-controls-transition-duration', '0.25s');
3900
+ break;
3901
+ case 'Android':
3902
+ // Android specific adjustments
3903
+ this.host.style.setProperty('--kritzel-editor-top-left-buttons-top', '14px');
3904
+ this.host.style.setProperty('--kritzel-editor-top-left-buttons-left', '14px');
3905
+ this.host.style.setProperty('--kritzel-editor-controls-bottom', '24px');
3906
+ this.host.style.setProperty('--kritzel-editor-controls-transition', 'cubic-bezier(0.25, 0.1, 0.25, 1.0)');
3907
+ this.host.style.setProperty('--kritzel-editor-controls-transform', 'translateY(200%)');
3908
+ this.host.style.setProperty('--kritzel-editor-controls-transition-duration', '0.25s');
3909
+ break;
3910
+ default:
3911
+ // Default for Windows/Linux
3912
+ this.host.style.setProperty('--kritzel-editor-top-left-buttons-top', '14px');
3913
+ this.host.style.setProperty('--kritzel-editor-top-left-buttons-left', '14px');
3914
+ this.host.style.setProperty('--kritzel-editor-controls-bottom', '14px');
3915
+ break;
3916
+ }
3917
+ }
3918
+ render() {
3919
+ const isLoggedIn = this.isLoggedIn;
3920
+ const shouldShowCurrentUser = isLoggedIn;
3921
+ const shouldShowLoginButton = this.isReady && !!this.loginConfig && !isLoggedIn;
3922
+ return (h(Host, { key: '00d652c74feac7b4917772146368125da6deeb1c' }, h("div", { key: 'f8fb86b45b0cdabb5e3ad52de6d6ef31a71a09e4', class: "editor-content", style: {
3923
+ opacity: this.isEditorVisible ? '1' : '0',
3924
+ visibility: this.isEditorVisible ? 'visible' : 'hidden',
3925
+ transition: 'opacity 0.2s ease-in-out, visibility 0.2s ease-in-out',
3926
+ } }, h("div", { key: '2378c776d8eecf2614567bed11c6e93fb338e302', class: "top-left-buttons" }, h("kritzel-workspace-manager", { key: 'ce41192540169694482d6f8cca60701bc4427438', visible: this.isWorkspaceManagerVisible, workspaces: this.workspaces, activeWorkspace: this.activeWorkspace, terms: this.resolvedTerms, onWorkspaceChange: event => (this.activeWorkspace = event.detail), onIsWorkspaceManagerReady: () => (this.isWorkspaceManagerReady = true) }), h("kritzel-back-to-content", { key: 'ec269d3e9f589362d8301370778f0c5e4252eead', visible: this.isBackToContentButtonVisible, text: this.resolvedTerms['backToContent.label'] ?? 'Back to content', onBackToContent: () => this.backToContent() })), this.activeNotification && (h("div", { key: '847ed8149d556c934090424ff54b17b6721ccc76', class: "top-center-notification-layer", role: "presentation" }, h("div", { key: '61d8b8e91cda100ffa6620db26ba6dfb2232946a', class: { 'top-center-notification-container': true, 'is-dismissing': this.isNotificationDismissing }, role: "presentation" }, h("kritzel-notification-card", { key: 'b7e132773225ace38e447756110dd39e4661f5fc', notification: this.activeNotification, locale: this.locale, onDismiss: this.dismissNotification, onHoverChange: event => this.handleNotificationHoverChange(event) })))), h("kritzel-engine", { key: '3e4a6d0dbc015ec675fb21a59990c87e9eaa805f', ref: el => {
3927
+ if (el) {
3928
+ this.engineRef = el;
3929
+ }
3930
+ }, workspace: this.activeWorkspace, activeWorkspaceId: this.activeWorkspaceId, editorId: this.editorId, syncConfig: this.syncConfig, assetStorageConfig: this.assetStorageConfig, user: this.user, scaleMax: this.scaleMax, lockDrawingScale: this.lockDrawingScale, isObjectDistanceFadingActive: this.isObjectDistanceFadingActive, scaleMin: this.scaleMin, cursorTarget: this.cursorTarget, isLoading: this.isLoading, viewportBoundaryLeft: this.viewportBoundaryLeft, viewportBoundaryRight: this.viewportBoundaryRight, viewportBoundaryTop: this.viewportBoundaryTop, viewportBoundaryBottom: this.viewportBoundaryBottom, isPanningEnabled: this.isPanningEnabled, isZoomingEnabled: this.isZoomingEnabled, theme: this.theme, themes: this.themes, licenseKey: this.licenseKey, locale: this.locale, locales: this.locales, fallbackLocale: this.fallbackLocale, debugInfo: this.debugInfo, globalContextMenuItems: this.globalContextMenuItems, objectContextMenuItems: this.objectContextMenuItems, onIsEngineReady: event => this.onEngineReady(event), onWorkspacesChange: event => this.handleWorkspacesChange(event), onActiveWorkspaceChange: event => this.handleActiveWorkspaceChange(event), onObjectsChange: event => this.handleObjectsChange(event), onObjectsAdded: event => this.handleObjectsAdded(event), onObjectsRemoved: event => this.handleObjectsRemoved(event), onObjectsUpdated: event => this.handleObjectsUpdated(event), onUndoStateChange: event => this.handleUndoStateChange(event), onObjectsInViewportChange: event => this.handleObjectsInViewportChange(event), onViewportChange: event => this.handleViewportChange(event), onAwarenessChange: event => this.handleAwarenessChange(event), onNotificationsChange: event => this.handleNotificationsChange(event) }), h("kritzel-controls", { key: 'f84607a0a4d0762c1249400f85b7b8454d672c1e', visible: this.isControlsVisible, class: { 'keyboard-open': this.isVirtualKeyboardOpen }, ref: el => {
3931
+ if (el) {
3932
+ this.controlsRef = el;
3933
+ }
3934
+ }, controls: this.normalizedControls, isUtilityPanelVisible: this.isUtilityPanelVisible, undoState: this.undoState ?? undefined, theme: this.theme, terms: this.resolvedTerms, onIsControlsReady: () => (this.isControlsReady = true) }), h("div", { key: 'e2691e7c730195e197511cb1e4d0fe707677b5ff', class: "bottom-left-buttons" }, h("kritzel-zoom-panel", { key: 'd0ac6624eab49af78d4761c3ad91842834717aad', visible: this.isZoomPanelVisible, disabled: !this.isZoomingEnabled, zoomPercent: this.currentZoomPercent, terms: this.resolvedTerms, onZoomIn: () => this.zoomIn(), onZoomOut: () => this.zoomOut() })), h("div", { key: 'ad3d386ab7e8ad9fdfbb12754db005bc85fa28ce', class: "top-right-buttons" }, h("kritzel-settings", { key: '566024ac6f3d8f7f20238cc1f83882b39dbf698e', ref: el => {
3935
+ if (el) {
3936
+ this.settingsRef = el;
3937
+ }
3938
+ }, shortcuts: this.shortcuts, availableThemes: this.themes && this.themes.length > 0 ? this.themes.map(t => t.name) : ['light', 'dark'], availableLocales: this.availableLocaleOptions, settings: this.currentSettingsConfig, terms: this.resolvedTerms, onSettingsChange: event => this.handleSettingsChange(event) }), h("kritzel-export", { key: '4a23ea0c6e070d424a90e9fc87de04e11cff7ade', ref: el => {
3939
+ if (el) {
3940
+ this.exportRef = el;
3941
+ }
3942
+ }, workspaceName: this.activeWorkspace?.name || 'workspace', terms: this.resolvedTerms, onExportPng: () => this.engineRef.exportViewportAsPng(), onExportSvg: () => this.engineRef.exportViewportAsSvg(), onExportJson: event => this.engineRef.downloadAsJson(event.detail) }), h("kritzel-active-users", { key: 'feef074b52e552fa2ef7e8258002571aca4c5abd', users: this.activeUsers }), shouldShowCurrentUser && h("kritzel-current-user", { key: '844c722545363eaf7eec69037a835eae943afeb9', user: this.user, terms: this.resolvedTerms, onClick: () => this.currentUserDialogRef?.open() }), shouldShowCurrentUser && (h("kritzel-current-user-dialog", { key: '8363c1d3230d111cf1ace0ccf805669e592bb533', ref: el => {
3943
+ if (el) {
3944
+ this.currentUserDialogRef = el;
3945
+ this.currentUserDialogRef.addEventListener('logoutRequest', this.handleCurrentUserLogout);
3946
+ }
3947
+ }, user: this.user, terms: this.resolvedTerms })), shouldShowLoginButton && (h("kritzel-button", { key: '68ddf8c3aabc7634b4c1d88f3d2d584fa1f1b150', onButtonClick: () => this.loginDialogRef?.open() }, this.resolvedTerms['login.dialogTitle'] ?? 'Sign in')), h("kritzel-more-menu", { key: '39b938f5792f7a36bbf21ed88a1a5c7717a785a6', items: this.moreMenuItems, visible: this.isMoreMenuVisible, terms: this.resolvedTerms }), h("kritzel-share-dialog", { key: '61ed918499760d874d5d2ec140d3cf59ce94520b', ref: el => {
3948
+ if (el) {
3949
+ this.shareDialogRef = el;
3950
+ }
3951
+ }, isPublic: this.currentIsPublic, workspaceId: this.activeWorkspace?.id, terms: this.resolvedTerms, onToggleIsPublic: this.handleToggleIsPublic }), this.loginConfig && (h("kritzel-login-dialog", { key: '5f6528a57884bd1494e45755609e710f69041a4d', ref: el => {
3952
+ if (el) {
3953
+ this.loginDialogRef = el;
3954
+ }
3955
+ }, providers: this.loginConfig.providers, dialogTitle: this.loginConfig.title ?? this.resolvedTerms['login.dialogTitle'] ?? 'Sign in', subtitle: this.loginConfig.subtitle, onProviderLogin: this.handleProviderLogin }))))));
3956
+ }
3957
+ static get watchers() { return {
3958
+ "isEngineReady": [{
3959
+ "onIsEngineReady": 0
3960
+ }],
3961
+ "isControlsReady": [{
3962
+ "onIsControlsReady": 0
3963
+ }],
3964
+ "workspaces": [{
3965
+ "onWorkspacesChange": 0
3966
+ }],
3967
+ "activeWorkspace": [{
3968
+ "onActiveWorkspaceChange": 0
3969
+ }],
3970
+ "customFonts": [{
3971
+ "onCustomFontsChange": 0
3972
+ }],
3973
+ "controls": [{
3974
+ "onControlsChange": 0
3975
+ }],
3976
+ "activeWorkspaceId": [{
3977
+ "onActiveWorkspaceIdChange": 0
3978
+ }],
3979
+ "theme": [{
3980
+ "onCurrentThemeChange": 0
3981
+ }],
3982
+ "themes": [{
3983
+ "onThemesChange": 0
3984
+ }],
3985
+ "locale": [{
3986
+ "onLocaleChange": 0
3987
+ }]
3988
+ }; }
3989
+ static get style() { return kritzelEditorCss(); }
3990
+ }, [512, "kritzel-editor", {
3991
+ "scaleMax": [1026, "scale-max"],
3992
+ "scaleMin": [1026, "scale-min"],
3993
+ "lockDrawingScale": [1028, "lock-drawing-scale"],
3994
+ "viewportBoundaryLeft": [1026, "viewport-boundary-left"],
3995
+ "viewportBoundaryRight": [1026, "viewport-boundary-right"],
3996
+ "viewportBoundaryTop": [1026, "viewport-boundary-top"],
3997
+ "viewportBoundaryBottom": [1026, "viewport-boundary-bottom"],
3998
+ "debugInfo": [1040],
3999
+ "user": [16],
4000
+ "activeUsers": [16],
4001
+ "controls": [16],
4002
+ "globalContextMenuItems": [16],
4003
+ "objectContextMenuItems": [16],
4004
+ "themes": [16],
4005
+ "theme": [1025],
4006
+ "licenseKey": [1, "license-key"],
4007
+ "locale": [1025],
4008
+ "locales": [16],
4009
+ "fallbackLocale": [1, "fallback-locale"],
4010
+ "customSvgIcons": [16],
4011
+ "customFonts": [16],
4012
+ "isPanningEnabled": [1028, "is-panning-enabled"],
4013
+ "isZoomingEnabled": [1028, "is-zooming-enabled"],
4014
+ "isControlsVisible": [4, "is-controls-visible"],
4015
+ "isUtilityPanelVisible": [4, "is-utility-panel-visible"],
4016
+ "isWorkspaceManagerVisible": [4, "is-workspace-manager-visible"],
4017
+ "isMoreMenuVisible": [4, "is-more-menu-visible"],
4018
+ "isZoomPanelVisible": [4, "is-zoom-panel-visible"],
4019
+ "isObjectDistanceFadingActive": [4, "is-object-distance-fading-active"],
4020
+ "syncConfig": [16],
4021
+ "assetStorageConfig": [16],
4022
+ "cursorTarget": [16],
4023
+ "loginConfig": [16],
4024
+ "isLoading": [4, "is-loading"],
4025
+ "editorId": [1, "editor-id"],
4026
+ "activeWorkspaceId": [1, "active-workspace-id"],
4027
+ "isEngineReady": [32],
4028
+ "isControlsReady": [32],
4029
+ "isWorkspaceManagerReady": [32],
4030
+ "workspaces": [32],
4031
+ "activeWorkspace": [32],
4032
+ "isVirtualKeyboardOpen": [32],
4033
+ "undoState": [32],
4034
+ "isBackToContentButtonVisible": [32],
4035
+ "resolvedTerms": [32],
4036
+ "availableLocaleOptions": [32],
4037
+ "currentZoomPercent": [32],
4038
+ "shortcuts": [32],
4039
+ "currentIsPublic": [32],
4040
+ "isEditorVisible": [32],
4041
+ "activeNotification": [32],
4042
+ "isNotificationDismissing": [32],
4043
+ "normalizedControls": [32],
4044
+ "getObjectById": [64],
4045
+ "addObject": [64],
4046
+ "addObjects": [64],
4047
+ "updateObject": [64],
4048
+ "removeObject": [64],
4049
+ "removeObjects": [64],
4050
+ "getSelectedObjects": [64],
4051
+ "selectObjects": [64],
4052
+ "selectAllObjectsInViewport": [64],
4053
+ "clearSelection": [64],
4054
+ "centerObjectInViewport": [64],
4055
+ "panToObject": [64],
4056
+ "backToContent": [64],
4057
+ "centerAllObjects": [64],
4058
+ "centerObjects": [64],
4059
+ "setViewport": [64],
4060
+ "panTo": [64],
4061
+ "zoomTo": [64],
4062
+ "zoomIn": [64],
4063
+ "zoomOut": [64],
4064
+ "getViewport": [64],
4065
+ "screenToWorld": [64],
4066
+ "worldToScreen": [64],
4067
+ "createWorkspace": [64],
4068
+ "updateWorkspace": [64],
4069
+ "deleteWorkspace": [64],
4070
+ "getWorkspaces": [64],
4071
+ "getActiveWorkspace": [64],
4072
+ "loadSharedWorkspace": [64],
4073
+ "reinitSync": [64],
4074
+ "registerTool": [64],
4075
+ "changeActiveTool": [64],
4076
+ "changeActiveToolByName": [64],
4077
+ "disable": [64],
4078
+ "enable": [64],
4079
+ "copy": [64],
4080
+ "cut": [64],
4081
+ "paste": [64],
4082
+ "delete": [64],
4083
+ "bringForward": [64],
4084
+ "sendBackward": [64],
4085
+ "bringToFront": [64],
4086
+ "sendToBack": [64],
4087
+ "alignObjects": [64],
4088
+ "group": [64],
4089
+ "ungroup": [64],
4090
+ "undo": [64],
4091
+ "redo": [64],
4092
+ "getScreenshot": [64],
4093
+ "exportViewportAsPng": [64],
4094
+ "exportViewportAsSvg": [64],
4095
+ "exportSelectedObjectsAsPng": [64],
4096
+ "exportSelectedObjectsAsSvg": [64],
4097
+ "downloadAsJson": [64],
4098
+ "importFromFile": [64],
4099
+ "loadObjectsFromJson": [64],
4100
+ "getObjectsTotalCount": [64],
4101
+ "getAllObjects": [64],
4102
+ "findObjects": [64],
4103
+ "getObjectsInViewport": [64],
4104
+ "hideContextMenu": [64],
4105
+ "openContextMenu": [64],
4106
+ "triggerSelectionChange": [64],
4107
+ "getDisplayableShortcuts": [64],
4108
+ "triggerNotification": [64],
4109
+ "openLoginDialog": [64],
4110
+ "setLoginLoading": [64],
4111
+ "setLocale": [64],
4112
+ "getLocale": [64],
4113
+ "getAvailableLocales": [64],
4114
+ "registerLocales": [64],
4115
+ "registerFonts": [64],
4116
+ "t": [64]
4117
+ }, [[0, "dblclick", "onTouchStart"]], {
4118
+ "isEngineReady": [{
4119
+ "onIsEngineReady": 0
4120
+ }],
4121
+ "isControlsReady": [{
4122
+ "onIsControlsReady": 0
4123
+ }],
4124
+ "workspaces": [{
4125
+ "onWorkspacesChange": 0
4126
+ }],
4127
+ "activeWorkspace": [{
4128
+ "onActiveWorkspaceChange": 0
4129
+ }],
4130
+ "customFonts": [{
4131
+ "onCustomFontsChange": 0
4132
+ }],
4133
+ "controls": [{
4134
+ "onControlsChange": 0
4135
+ }],
4136
+ "activeWorkspaceId": [{
4137
+ "onActiveWorkspaceIdChange": 0
4138
+ }],
4139
+ "theme": [{
4140
+ "onCurrentThemeChange": 0
4141
+ }],
4142
+ "themes": [{
4143
+ "onThemesChange": 0
4144
+ }],
4145
+ "locale": [{
4146
+ "onLocaleChange": 0
4147
+ }]
4148
+ }]);
4149
+ function defineCustomElement$1() {
4150
+ if (typeof customElements === "undefined") {
4151
+ return;
4152
+ }
4153
+ const components = ["kritzel-editor", "kritzel-active-users", "kritzel-avatar", "kritzel-awareness-cursors", "kritzel-back-to-content", "kritzel-button", "kritzel-color", "kritzel-color-palette", "kritzel-context-menu", "kritzel-controls", "kritzel-current-user", "kritzel-current-user-dialog", "kritzel-cursor-trail", "kritzel-dialog", "kritzel-dropdown", "kritzel-engine", "kritzel-export", "kritzel-font", "kritzel-font-family", "kritzel-font-size", "kritzel-icon", "kritzel-input", "kritzel-line-endings", "kritzel-loading-overlay", "kritzel-login-dialog", "kritzel-master-detail", "kritzel-menu", "kritzel-menu-item", "kritzel-more-menu", "kritzel-notification-card", "kritzel-numeric-input", "kritzel-opacity-slider", "kritzel-pill-tabs", "kritzel-portal", "kritzel-settings", "kritzel-shape-fill", "kritzel-share-dialog", "kritzel-slide-toggle", "kritzel-split-button", "kritzel-stroke-size", "kritzel-sync-indicator", "kritzel-tool-config", "kritzel-tooltip", "kritzel-utility-panel", "kritzel-watermark", "kritzel-workspace-manager", "kritzel-zoom-panel"];
4154
+ components.forEach(tagName => { switch (tagName) {
4155
+ case "kritzel-editor":
4156
+ if (!customElements.get(transformTag(tagName))) {
4157
+ customElements.define(transformTag(tagName), KritzelEditor$1);
4158
+ }
4159
+ break;
4160
+ case "kritzel-active-users":
4161
+ if (!customElements.get(transformTag(tagName))) {
4162
+ defineCustomElement$L();
4163
+ }
4164
+ break;
4165
+ case "kritzel-avatar":
4166
+ if (!customElements.get(transformTag(tagName))) {
4167
+ defineCustomElement$K();
4168
+ }
4169
+ break;
4170
+ case "kritzel-awareness-cursors":
4171
+ if (!customElements.get(transformTag(tagName))) {
4172
+ defineCustomElement$J();
4173
+ }
4174
+ break;
4175
+ case "kritzel-back-to-content":
4176
+ if (!customElements.get(transformTag(tagName))) {
4177
+ defineCustomElement$I();
4178
+ }
4179
+ break;
4180
+ case "kritzel-button":
4181
+ if (!customElements.get(transformTag(tagName))) {
4182
+ defineCustomElement$H();
4183
+ }
4184
+ break;
4185
+ case "kritzel-color":
4186
+ if (!customElements.get(transformTag(tagName))) {
4187
+ defineCustomElement$G();
4188
+ }
4189
+ break;
4190
+ case "kritzel-color-palette":
4191
+ if (!customElements.get(transformTag(tagName))) {
4192
+ defineCustomElement$F();
4193
+ }
4194
+ break;
4195
+ case "kritzel-context-menu":
4196
+ if (!customElements.get(transformTag(tagName))) {
4197
+ defineCustomElement$E();
4198
+ }
4199
+ break;
4200
+ case "kritzel-controls":
4201
+ if (!customElements.get(transformTag(tagName))) {
4202
+ defineCustomElement$D();
4203
+ }
4204
+ break;
4205
+ case "kritzel-current-user":
4206
+ if (!customElements.get(transformTag(tagName))) {
4207
+ defineCustomElement$C();
4208
+ }
4209
+ break;
4210
+ case "kritzel-current-user-dialog":
4211
+ if (!customElements.get(transformTag(tagName))) {
4212
+ defineCustomElement$B();
4213
+ }
4214
+ break;
4215
+ case "kritzel-cursor-trail":
4216
+ if (!customElements.get(transformTag(tagName))) {
4217
+ defineCustomElement$A();
4218
+ }
4219
+ break;
4220
+ case "kritzel-dialog":
4221
+ if (!customElements.get(transformTag(tagName))) {
4222
+ defineCustomElement$z();
4223
+ }
4224
+ break;
4225
+ case "kritzel-dropdown":
4226
+ if (!customElements.get(transformTag(tagName))) {
4227
+ defineCustomElement$y();
4228
+ }
4229
+ break;
4230
+ case "kritzel-engine":
4231
+ if (!customElements.get(transformTag(tagName))) {
4232
+ defineCustomElement$x();
4233
+ }
4234
+ break;
4235
+ case "kritzel-export":
4236
+ if (!customElements.get(transformTag(tagName))) {
4237
+ defineCustomElement$w();
4238
+ }
4239
+ break;
4240
+ case "kritzel-font":
4241
+ if (!customElements.get(transformTag(tagName))) {
4242
+ defineCustomElement$v();
4243
+ }
4244
+ break;
4245
+ case "kritzel-font-family":
4246
+ if (!customElements.get(transformTag(tagName))) {
4247
+ defineCustomElement$u();
4248
+ }
4249
+ break;
4250
+ case "kritzel-font-size":
4251
+ if (!customElements.get(transformTag(tagName))) {
4252
+ defineCustomElement$t();
4253
+ }
4254
+ break;
4255
+ case "kritzel-icon":
4256
+ if (!customElements.get(transformTag(tagName))) {
4257
+ defineCustomElement$s();
4258
+ }
4259
+ break;
4260
+ case "kritzel-input":
4261
+ if (!customElements.get(transformTag(tagName))) {
4262
+ defineCustomElement$r();
4263
+ }
4264
+ break;
4265
+ case "kritzel-line-endings":
4266
+ if (!customElements.get(transformTag(tagName))) {
4267
+ defineCustomElement$q();
4268
+ }
4269
+ break;
4270
+ case "kritzel-loading-overlay":
4271
+ if (!customElements.get(transformTag(tagName))) {
4272
+ defineCustomElement$p();
4273
+ }
4274
+ break;
4275
+ case "kritzel-login-dialog":
4276
+ if (!customElements.get(transformTag(tagName))) {
4277
+ defineCustomElement$o();
4278
+ }
4279
+ break;
4280
+ case "kritzel-master-detail":
4281
+ if (!customElements.get(transformTag(tagName))) {
4282
+ defineCustomElement$n();
4283
+ }
4284
+ break;
4285
+ case "kritzel-menu":
4286
+ if (!customElements.get(transformTag(tagName))) {
4287
+ defineCustomElement$m();
4288
+ }
4289
+ break;
4290
+ case "kritzel-menu-item":
4291
+ if (!customElements.get(transformTag(tagName))) {
4292
+ defineCustomElement$l();
4293
+ }
4294
+ break;
4295
+ case "kritzel-more-menu":
4296
+ if (!customElements.get(transformTag(tagName))) {
4297
+ defineCustomElement$k();
4298
+ }
4299
+ break;
4300
+ case "kritzel-notification-card":
4301
+ if (!customElements.get(transformTag(tagName))) {
4302
+ defineCustomElement$j();
4303
+ }
4304
+ break;
4305
+ case "kritzel-numeric-input":
4306
+ if (!customElements.get(transformTag(tagName))) {
4307
+ defineCustomElement$i();
4308
+ }
4309
+ break;
4310
+ case "kritzel-opacity-slider":
4311
+ if (!customElements.get(transformTag(tagName))) {
4312
+ defineCustomElement$h();
4313
+ }
4314
+ break;
4315
+ case "kritzel-pill-tabs":
4316
+ if (!customElements.get(transformTag(tagName))) {
4317
+ defineCustomElement$g();
4318
+ }
4319
+ break;
4320
+ case "kritzel-portal":
4321
+ if (!customElements.get(transformTag(tagName))) {
4322
+ defineCustomElement$f();
4323
+ }
4324
+ break;
4325
+ case "kritzel-settings":
4326
+ if (!customElements.get(transformTag(tagName))) {
4327
+ defineCustomElement$e();
4328
+ }
4329
+ break;
4330
+ case "kritzel-shape-fill":
4331
+ if (!customElements.get(transformTag(tagName))) {
4332
+ defineCustomElement$d();
4333
+ }
4334
+ break;
4335
+ case "kritzel-share-dialog":
4336
+ if (!customElements.get(transformTag(tagName))) {
4337
+ defineCustomElement$c();
4338
+ }
4339
+ break;
4340
+ case "kritzel-slide-toggle":
4341
+ if (!customElements.get(transformTag(tagName))) {
4342
+ defineCustomElement$b();
4343
+ }
4344
+ break;
4345
+ case "kritzel-split-button":
4346
+ if (!customElements.get(transformTag(tagName))) {
4347
+ defineCustomElement$a();
4348
+ }
4349
+ break;
4350
+ case "kritzel-stroke-size":
4351
+ if (!customElements.get(transformTag(tagName))) {
4352
+ defineCustomElement$9();
4353
+ }
4354
+ break;
4355
+ case "kritzel-sync-indicator":
4356
+ if (!customElements.get(transformTag(tagName))) {
4357
+ defineCustomElement$8();
4358
+ }
4359
+ break;
4360
+ case "kritzel-tool-config":
4361
+ if (!customElements.get(transformTag(tagName))) {
4362
+ defineCustomElement$7();
4363
+ }
4364
+ break;
4365
+ case "kritzel-tooltip":
4366
+ if (!customElements.get(transformTag(tagName))) {
4367
+ defineCustomElement$6();
4368
+ }
4369
+ break;
4370
+ case "kritzel-utility-panel":
4371
+ if (!customElements.get(transformTag(tagName))) {
4372
+ defineCustomElement$5();
4373
+ }
4374
+ break;
4375
+ case "kritzel-watermark":
4376
+ if (!customElements.get(transformTag(tagName))) {
4377
+ defineCustomElement$4();
4378
+ }
4379
+ break;
4380
+ case "kritzel-workspace-manager":
4381
+ if (!customElements.get(transformTag(tagName))) {
4382
+ defineCustomElement$3();
4383
+ }
4384
+ break;
4385
+ case "kritzel-zoom-panel":
4386
+ if (!customElements.get(transformTag(tagName))) {
4387
+ defineCustomElement$2();
4388
+ }
4389
+ break;
4390
+ } });
4391
+ }
4392
+
4393
+ const KritzelEditor = KritzelEditor$1;
4394
+ const defineCustomElement = defineCustomElement$1;
4395
+
4396
+ export { DEFAULT_BRUSH_CONFIG as D, HocuspocusProvider as H, KritzelEditor, HocuspocusProviderWebsocket as a, DEFAULT_TEXT_CONFIG as b, DEFAULT_LINE_TOOL_CONFIG as c, DEFAULT_ASSET_STORAGE_CONFIG as d, defineCustomElement };