@enzedonline/quill-blot-formatter2
Version:
An update for quill-blot-formatter to make quilljs v2 compatible.
6 lines • 76.5 kB
JavaScript
(function(d,y){typeof exports=="object"&&typeof module<"u"?y(exports):typeof define=="function"&&define.amd?define(["exports"],y):(d=typeof globalThis<"u"?globalThis:d||self,y(d.QuillBlotFormatter2={}))})(this,function(d){"use strict";class y{formatter;toolbarButtons=[];debug;constructor(t){this.formatter=t,this.debug=this.formatter.options.debug||!1,this.debug&&console.debug("Action created:",this.constructor.name)}onCreate=()=>{};onDestroy=()=>{};onUpdate=()=>{}}class A extends y{static sendCaretBack=(t=1,e=!1)=>{const i=window.getSelection();if(i&&i.rangeCount>0){const s=i.getRangeAt(0),o=s.startContainer,n=s.startOffset;if(n>0)s.setStart(o,n-t);else if(o.previousSibling){const r=o.previousSibling;r.nodeType===Node.TEXT_NODE&&s.setStart(r,r.textContent?.length||0)}s.collapse(!0),i.removeAllRanges(),i.addRange(s),e&&console.debug("Caret moved back by",t,"characters")}};static placeCaretBeforeBlot=(t,e,i=!1)=>{const s=t.getIndex(e);t.setSelection(s,0,"user"),i&&console.debug("Caret placed before blot at index:",s,e)};static placeCaretAfterBlot=(t,e,i=!1)=>{t.setSelection(null),t.root.focus();const s=t.getIndex(e),o=t.getLength();s+1>=o-1?(t.setSelection(o-1,0,"user"),i&&console.debug("Caret placed at the end of the document after blot:",e)):(i&&console.debug("Caret placed after character following blot at index:",s,e),t.setSelection(s+2,0,"user"),this.sendCaretBack(1,i))};onCreate=()=>{document.addEventListener("keyup",this.onKeyUp),this.formatter.quill.root.addEventListener("input",this.onKeyUp)};onDestroy=()=>{document.removeEventListener("keyup",this.onKeyUp),this.formatter.quill.root.removeEventListener("input",this.onKeyUp)};onKeyUp=t=>{const e=!!document.querySelector("[data-blot-formatter-modal]");if(!this.formatter.currentSpec||e)return;const i=this.formatter.currentSpec.getTargetBlot();i&&(t.code==="ArrowLeft"?(A.placeCaretBeforeBlot(this.formatter.quill,i,this.debug),this.formatter.hide()):t.code==="ArrowRight"&&(A.placeCaretAfterBlot(this.formatter.quill,i,this.debug),this.formatter.hide()))}}function V(h){return h&&h.__esModule&&Object.prototype.hasOwnProperty.call(h,"default")?h.default:h}var S,M;function X(){if(M)return S;M=1;var h=function(c){return t(c)&&!e(c)};function t(a){return!!a&&typeof a=="object"}function e(a){var c=Object.prototype.toString.call(a);return c==="[object RegExp]"||c==="[object Date]"||o(a)}var i=typeof Symbol=="function"&&Symbol.for,s=i?Symbol.for("react.element"):60103;function o(a){return a.$$typeof===s}function n(a){return Array.isArray(a)?[]:{}}function r(a,c){return c.clone!==!1&&c.isMergeableObject(a)?x(n(a),a,c):a}function l(a,c,u){return a.concat(c).map(function(v){return r(v,u)})}function f(a,c){if(!c.customMerge)return x;var u=c.customMerge(a);return typeof u=="function"?u:x}function g(a){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(a).filter(function(c){return Object.propertyIsEnumerable.call(a,c)}):[]}function m(a){return Object.keys(a).concat(g(a))}function p(a,c){try{return c in a}catch{return!1}}function _(a,c){return p(a,c)&&!(Object.hasOwnProperty.call(a,c)&&Object.propertyIsEnumerable.call(a,c))}function J(a,c,u){var v={};return u.isMergeableObject(a)&&m(a).forEach(function(b){v[b]=r(a[b],u)}),m(c).forEach(function(b){_(a,b)||(p(a,b)&&u.isMergeableObject(c[b])?v[b]=f(b,u)(a[b],c[b],u):v[b]=r(c[b],u))}),v}function x(a,c,u){u=u||{},u.arrayMerge=u.arrayMerge||l,u.isMergeableObject=u.isMergeableObject||h,u.cloneUnlessOtherwiseSpecified=r;var v=Array.isArray(c),b=Array.isArray(a),et=v===b;return et?v?u.arrayMerge(a,c,u):J(a,c,u):r(c,u)}x.all=function(c,u){if(!Array.isArray(c))throw new Error("first argument should be an array");return c.reduce(function(v,b){return x(v,b,u)},{})};var tt=x;return S=tt,S}var Y=X();const Q=V(Y);class E{formatter;element;buttons={};constructor(t){this.formatter=t,this.element=document.createElement("div"),this.element.classList.add(this.formatter.options.toolbar.mainClassName),this.element.addEventListener("mousedown",e=>{e.stopPropagation()}),this.formatter.options.toolbar.mainStyle&&Object.assign(this.element.style,this.formatter.options.toolbar.mainStyle)}create=()=>{const t=[];this.formatter.actions.forEach(e=>{e.toolbarButtons.forEach(i=>{this.buttons[i.action]=i,t.push(i.create())})}),this.element.append(...t),this.formatter.overlay.append(this.element),this.formatter.options.debug&&console.debug("Toolbar created with buttons:",Object.keys(this.buttons),t)};destroy=()=>{this.element&&this.formatter.overlay.removeChild(this.element);for(const t of Object.values(this.buttons))t.destroy();this.buttons={},this.element.innerHTML="",this.formatter.options.debug&&console.debug("Toolbar destroyed")}}class k{constructor(t,e=!1){this.quill=t,this.debug=e;const i=t.container.querySelector(".ql-tooltip");console.debug("tooltip:",i),i?(k.watchTooltip(t,e),e&&console.debug("Tooltip watcher initialized for:",i)):console.warn("No tooltip found to watch for adjustments.")}static _repositionTooltip=(t,e,i=!1)=>{const s=t.getBoundingClientRect(),o=e.getBoundingClientRect();let n=s.left-o.left,r=s.top-o.top;const l=s.width,f=s.height,g=e.clientWidth,m=e.clientHeight;let p=!1;const _={};r<0&&(_.top=`${s.height}px`,p=!0),r+f>m&&(_.top=`${m-f}px`,p=!0),n<0&&(_.left="0px",p=!0),n+l>g&&(_.left=`${g-l}px`,p=!0),p?(i&&console.debug("Repositioning tooltip",_),_.top!==void 0&&(t.style.top=_.top),_.left!==void 0&&(t.style.left=_.left),t.classList.contains("ql-flip")&&t.classList.remove("ql-flip")):i&&console.debug("Tooltip position is fine, no changes needed")};static observers=new WeakMap;static watchTooltip(t,e=!1){const i=t.container.querySelector(".ql-tooltip"),s=t.container;if(!i){console.warn("No tooltip found to watch for adjustments.");return}this.removeTooltipWatcher(i,e);let o=!1;const n=new MutationObserver(r=>{if(!o){if(e)for(const l of r)console.debug("Tooltip mutation:",l.attributeName,i.getAttribute(l.attributeName));o=!0,this._repositionTooltip(i,s,e),setTimeout(()=>{o=!1},0)}});n.observe(i,{attributes:!0,attributeFilter:["style","class"]}),this.observers.set(i,n)}static removeTooltipWatcher(t,e=!1){let i=null;t instanceof HTMLDivElement?i=t:i=t.container.querySelector(".ql-tooltip"),i&&this.observers.has(i)&&(this.observers.get(i)?.disconnect(),this.observers.delete(i),e&&console.debug("Tooltip watcher removed for:",i))}destroy=()=>{this.quill.container.querySelector(".ql-tooltip")&&(k.removeTooltipWatcher(this.quill,this.debug),this.debug&&console.debug("Tooltip watcher removed on destroy"))}}const T=h=>{const t=h.import("formats/image"),e=["alt","height","width","title"];return class extends t{static blotName="image";static formats(s){return e.reduce((o,n)=>(s.hasAttribute(n)&&(o[n]=s.getAttribute(n)),o),{})}format(s,o){e.indexOf(s)>-1?o||s==="alt"?this.domNode.setAttribute(s,o):this.domNode.removeAttribute(s):super.format(s,o)}}},z=h=>{const t=h.import("parchment"),{ClassAttributor:e,Scope:i}=t;return class extends e{constructor(o=!1){super("iframeAlign","ql-iframe-align",{scope:i.BLOCK,whitelist:["left","center","right"]}),this.debug=o}static attrName="iframeAlign";add(o,n){if(this.debug&&console.debug("IframeAlignAttributor.add",o,n),o instanceof HTMLElement){typeof n=="object"?(super.add(o,n.align),o.dataset.blotAlign=n.align):(super.add(o,n),o.dataset.blotAlign=n);let r=o.getAttribute("width");return r?(isNaN(Number(r.trim().slice(-1)))||(r=`${r}px`),o.style.setProperty("--resize-width",r),o.dataset.relativeSize=`${r.endsWith("%")}`):(o.style.removeProperty("--resize-width"),o.dataset.relativeSize="false"),this.debug&&console.debug("IframeAlignAttributor.add - node:",o,"aligned with:",n),!0}else return this.debug&&console.debug("IframeAlignAttributor.add - node is not an HTMLElement, skipping alignment"),!1}remove(o){this.debug&&console.debug("IframeAlignAttributor.remove",o),o instanceof HTMLElement&&(super.remove(o),delete o.dataset.blotAlign)}value(o){const n=super.value(o),r=o instanceof HTMLElement&&(o.style.getPropertyValue("--resize-width")||o.getAttribute("width"))||"",l={align:n,width:r,relativeSize:`${r.endsWith("%")}`};return this.debug&&console.debug("IframeAlignAttributor.value",o,l),l}}},R=h=>{const t=h.import("parchment"),{ClassAttributor:e,Scope:i}=t;return class extends e{constructor(o=!1){super("imageAlign","ql-image-align",{scope:i.INLINE,whitelist:["left","center","right"]}),this.debug=o}static tagName="SPAN";static attrName="imageAlign";add(o,n){if(this.debug&&console.debug("ImageAlignAttributor.add",o,n),o instanceof HTMLSpanElement&&n){let r=o.querySelector("img");if(typeof n=="object"&&n.align)super.add(o,n.align),o.setAttribute("contenteditable","false"),n.title?o.setAttribute("data-title",n.title):o.removeAttribute("data-title"),n.align&&(r.dataset.blotAlign=n.align),this.debug&&console.debug("ImageAlignAttributor.add - imageElement:",r,"aligned with:",n.align);else if(typeof n=="string")super.add(o,n),r.dataset.blotAlign=n,this.debug&&console.debug("ImageAlignAttributor.add - imageElement:",r,"aligned with:",n);else return this.debug&&console.debug("ImageAlignAttributor.add - no value provided, skipping alignment"),!1;let l=this.getImageWidth(r);return o.setAttribute("data-relative-size",`${l?.endsWith("%")}`),!0}else{const r=o instanceof HTMLImageElement?o:o.querySelector("img");if(this.debug&&console.debug(`ImageAlignAttributor.add - ${o.tagName} is not a span, checking for image:`,r),r instanceof HTMLImageElement){const l=h.find(r);return this.debug&&console.debug("ImageAlignAttributor.add - found image blot:",l),l&&(o.firstChild instanceof HTMLSpanElement||!r.parentElement?.matches('span[class^="ql-image-align-"]'))&&(l.format("imageAlign",n),this.debug&&console.debug("ImageAlignAttributor.add - reapplying imageAlign format to image blot:",n,l)),!0}return!1}}remove(o){this.debug&&console.debug("ImageAlignAttributor.remove",o),o instanceof HTMLElement&&(super.remove(o),o.firstChild&&o.firstChild instanceof HTMLElement&&delete o.firstChild.dataset.blotAlign)}value(o){const n=o.querySelector("img");if(!n)return null;const r=n.parentElement,l=super.value(r),f=n.getAttribute("title")||"";let g=n.getAttribute("width")||"";parseFloat(g)||(n.complete?g=this.getImageWidth(n):n.onload=p=>{g=this.getImageWidth(p.target)});const m={align:l,title:f,width:g,contenteditable:"false",relativeSize:`${g.endsWith("%")}`};return this.debug&&console.debug("ImageAlignAttributor.value",o,m),m}getImageWidth(o){let n=o.getAttribute("width");return n?isNaN(Number(n.trim().slice(-1)))||(n=`${n}px`,o.setAttribute("width",n)):(n=`${o.naturalWidth}px`,o.setAttribute("width",n)),o.parentElement.style.setProperty("--resize-width",n),n}}},O=h=>{const t=h.import("formats/video");return class extends t{static blotName="video";static aspectRatio="16 / 9 auto";static create(i){const s=super.create(i);return s.setAttribute("width","100%"),s.style.aspectRatio=this.aspectRatio,s}html(){return this.domNode.outerHTML}}};class H{alignments={};options;formatter;debug;Scope;constructor(t){this.formatter=t,this.debug=t.options.debug??!1;const e=t.Quill.import("parchment");this.Scope=e.Scope,this.options=t.options,this.options.align.alignments.forEach(i=>{this.alignments[i]={name:i,apply:s=>{this.setAlignment(s,i)}}}),this.debug&&console.debug("DefaultAligner created with alignments:",this.alignments)}getAlignments=()=>Object.keys(this.alignments).map(t=>this.alignments[t]);clear=t=>{t!=null&&(t.domNode.tagName==="IMG"?t.parent!==null&&t.parent.domNode.tagName==="SPAN"&&(t.parent.format(this.formatter.ImageAlign.attrName,!1),this.debug&&console.debug("Cleared image alignment from parent span:",t.parent)):t.domNode.tagName==="IFRAME"&&(t.format(this.formatter.IframeAlign.attrName,!1),this.debug&&console.debug("Cleared iframe alignment:",t)))};isInlineBlot=t=>(t.statics?.scope&this.Scope.INLINE)===this.Scope.INLINE_BLOT;isBlockBlot=t=>(t.statics?.scope&this.Scope.BLOCK)===this.Scope.BLOCK_BLOT;hasInlineScope=t=>(t.statics.scope&this.Scope.INLINE)===this.Scope.INLINE;hasBlockScope=t=>(t.statics.scope&this.Scope.BLOCK)===this.Scope.BLOCK;isAligned=(t,e)=>{const i=this.getAlignment(t);return e?i===e.name:!!i};getAlignment=t=>t.domNode.dataset.blotAlign;setAlignment=(t,e)=>{if(t===null){this.debug&&console.debug("DefaultAligner.setAlignment called with null blot, no action taken");return}const i=this.isAligned(t,this.alignments[e]);if(this.debug&&console.debug("hasAlignment",i),this.clear(t),!i)if(this.isInlineBlot(t)||this.hasInlineScope(t)){if(this.debug&&console.debug("setting alignment",this.isInlineBlot(t)||this.hasInlineScope(t)),!t.domNode.getAttribute("width")&&this.options.resize.useRelativeSize&&!this.options.resize.allowResizeModeChange)try{const s=getComputedStyle(this.formatter.quill.root),o=this.formatter.quill.root.clientWidth-parseFloat(s.paddingLeft)-parseFloat(s.paddingRight);t.domNode.setAttribute("width",`${Math.min(Math.round(100*t.domNode.naturalWidth/o),100)}%`)}catch{this.debug&&console.debug("DefaultAligner.setAlignment Error setting image width:",t)}this.debug&&console.debug("DefaultAligner.setAlignment formatting image with",this.formatter.ImageAlign.attrName,{align:this.alignments[e].name,title:t.domNode.getAttribute("title")||""}),t.format(this.formatter.ImageAlign.attrName,{align:this.alignments[e].name,title:t.domNode.getAttribute("title")||""});try{const s=this.formatter.quill.getContents().ops;s.length===2&&s[1].insert===`
`&&this.formatter.quill.insertText(this.formatter.quill.getLength(),`
`,"user")}catch{}}else(this.isBlockBlot(t)||this.hasBlockScope(t))&&(this.debug&&console.debug("DefaultAligner.setAlignment formatting iframe with",this.formatter.IframeAlign.attrName,{align:this.alignments[e].name}),t.format(this.formatter.IframeAlign.attrName,this.alignments[e].name))}}class w{action;icon;onClick;options;element=null;initialVisibility=!0;constructor(t,e,i){this.action=t,this.icon=i.icons[t],this.onClick=e,this.options=i}create=()=>(this.element=document.createElement("span"),this.element.innerHTML=this.icon,this.element.className=this.options.buttonClassName,this.element.dataset.action=this.action,this.element.onclick=this.onClick,this.options.tooltips&&this.options.tooltips[this.action]&&(this.element.title=this.options.tooltips[this.action]),this.selected=this.preselect(),this.visible=this.initialVisibility,this._styleButton(),this.element);destroy=()=>{this.element&&(this.element.onclick=null,this.element.remove(),this.element=null)};preselect=()=>!1;get selected(){return this.element?.dataset.selected==="true"}set selected(t){this.element&&(this.element.dataset.selected=t.toString(),t?(this.element.classList.add(this.options.buttonSelectedClassName),this.options.buttonSelectedStyle&&Object.assign(this.element.style,this.options.buttonSelectedStyle)):(this.element.classList.remove(this.options.buttonSelectedClassName),this.options.buttonSelectedStyle&&(this.element.removeAttribute("style"),this.options.buttonStyle&&Object.assign(this.element.style,this.options.buttonStyle))))}get visible(){return this.element?.style.display!=="none"}set visible(t){this.element&&(typeof t=="boolean"&&(t=t?"inline-block":"none"),this.element.style.display=t)}_styleButton=()=>{if(this.element&&(this.options.buttonStyle&&Object.assign(this.element.style,this.options.buttonStyle),this.options.svgStyle)){const t=this.element.children[0];t&&Object.assign(t.style,this.options.svgStyle)}}}class N extends y{aligner;alignButtons={};constructor(t){super(t),this.aligner=new H(t),t.options.debug&&console.debug("AlignAction Aligner created:",this.aligner)}_createAlignmentButtons=()=>{for(const e of Object.values(this.aligner.alignments))this.alignButtons[e.name]=new w(e.name,this.onClickHandler,this.formatter.options.toolbar);const t=this.formatter.currentSpec?.getTargetBlot();if(t){const e=this.aligner.getAlignment(t);e&&this.alignButtons[e]&&(this.alignButtons[e].preselect=()=>!0),this.debug&&(console.debug("AlignAction alignment buttons created:",this.alignButtons),console.debug("Blot alignment on load:",e))}};_clearButtons=()=>{for(const t of Object.values(this.alignButtons))t.selected=!1;this.debug&&console.debug("AlignAction alignment buttons cleared")};onClickHandler=t=>{const e=t.target.closest(`span.${this.formatter.options.toolbar.buttonClassName}`);if(e){const i=e.dataset.action||"",s=this.formatter.currentSpec?.getTargetBlot();if(i&&s){const o=this.aligner.alignments[i];this._clearButtons(),this.aligner.isAligned(s,o)?(this.aligner.clear(s),this.debug&&console.debug("AlignAction clear alignment:",i,s)):(this.aligner.setAlignment(s,i),this.alignButtons[i].selected=!0,this.debug&&console.debug("AlignAction set alignment:",i,s))}}this.formatter.update()};onCreate=()=>{this._createAlignmentButtons(),this.toolbarButtons=Object.values(this.alignButtons),this.formatter.options.debug&&console.debug("AlignAction alignment buttons created:",this.toolbarButtons)};onDestroy=()=>{this.alignButtons={},this.toolbarButtons=[],this.formatter.options.debug&&console.debug("AlignAction alignment buttons destroyed")}}class q extends y{onCreate=()=>{document.addEventListener("keyup",this._onKeyUp),this.formatter.quill.root.addEventListener("input",this._onKeyUp)};onDestroy=()=>{document.removeEventListener("keyup",this._onKeyUp),this.formatter.quill.root.removeEventListener("input",this._onKeyUp)};_onKeyUp=t=>{const e=!!document.querySelector("[data-blot-formatter-modal]");if(!(!this.formatter.currentSpec||e)&&(t.code==="Delete"||t.code==="Backspace")){this.debug&&console.debug("DeleteAction keyup detected:",t.code);const i=this.formatter.currentSpec.getTargetElement();if(i){const s=this.formatter.Quill.find(i);if(s){const o=this.formatter.quill.getIndex(s);this.formatter.quill.deleteText(o,1,"user")}}this.formatter.hide()}}}class D extends y{_topLeftHandle;_topRightHandle;_bottomRightHandle;_bottomLeftHandle;_dragHandle=null;_dragStartX=0;_dragCursorStyle;_preDragWidth=0;_pinchStartDistance=0;_calculatedAspectRatio=0;_computedAspectRatio=void 0;_target;_editorStyle;_editorWidth=0;_useRelativeSize;_resizeModeButton=null;_isUnclickable=!1;_hasResized=!1;_formattedWidth="";_sizeInfoTimerId=null;_isImage=!1;_isSVG=!1;_naturalWidth=void 0;constructor(t){super(t),this._topLeftHandle=this._createHandle("top-left","nwse-resize"),this._topRightHandle=this._createHandle("top-right","nesw-resize"),this._bottomRightHandle=this._createHandle("bottom-right","nwse-resize"),this._bottomLeftHandle=this._createHandle("bottom-left","nesw-resize"),this._dragCursorStyle=document.createElement("style"),this._useRelativeSize=this.formatter.options.resize.useRelativeSize,t.options.resize.allowResizeModeChange&&(this._resizeModeButton=this._createResizeModeButton(),this.toolbarButtons=[this._resizeModeButton])}onCreate=()=>{this._target=this.formatter.currentSpec?.getTargetElement(),this._isUnclickable=this.formatter.currentSpec?.isUnclickable||!1,this._isImage=this._target instanceof HTMLImageElement,this._isImage&&(this._isSVG=this._isSvgImage()),this.formatter.overlay.append(this._topLeftHandle,this._topRightHandle,this._bottomRightHandle,this._bottomLeftHandle),this.formatter.overlay.addEventListener("mousedown",this._onOverlayMouseDown),this.formatter.overlay.addEventListener("mouseup",this._onOverlayMouseUp);const t={passive:!1};this.formatter.overlay.addEventListener("touchstart",this._onOverlayTouchStart,t),this.formatter.overlay.addEventListener("touchmove",this._onOverlayTouchMove,t),this.formatter.overlay.addEventListener("touchend",this._onOverlayTouchEnd,t);const e=this.formatter.options.resize.handleStyle||{};this._repositionHandles(e),this.debug&&console.debug("ResizeAction created with target:",this._target,"isUnclickable:",this._isUnclickable)};onDestroy=()=>{this._target=null,this._isUnclickable=!1,this._isImage=!1,this._naturalWidth=void 0,this._isSVG=!1,this._setCursor(""),[this._topLeftHandle,this._topRightHandle,this._bottomRightHandle,this._bottomLeftHandle].forEach(e=>{e.remove()}),this.formatter.overlay.removeEventListener("mousedown",this._onOverlayMouseDown),this.formatter.overlay.removeEventListener("mouseup",this._onOverlayMouseUp);const t={passive:!1};this.formatter.overlay.removeEventListener("touchstart",this._onOverlayTouchStart,t),this.formatter.overlay.removeEventListener("touchmove",this._onOverlayTouchMove,t),this.formatter.overlay.removeEventListener("touchend",this._onOverlayTouchEnd,t),this.formatter.update()};_createHandle=(t,e)=>{const i=document.createElement("div");return i.classList.add(this.formatter.options.resize.handleClassName),i.setAttribute("data-position",t),i.style.cursor=e,this.formatter.options.resize.handleStyle&&Object.assign(i.style,this.formatter.options.resize.handleStyle),i.addEventListener("pointerdown",this._onHandlePointerDown),i};_repositionHandles=t=>{const e=t?.width?`${-parseFloat(t.width)/2}px`:"0px",i=t?.height?`${-parseFloat(t.height)/2}px`:"0px",{style:s}=this._topLeftHandle;s.left=e,s.top=i;const{style:o}=this._topRightHandle;o.right=e,o.top=i;const{style:n}=this._bottomRightHandle;n.right=e,n.bottom=i;const{style:r}=this._bottomLeftHandle;r.left=e,r.bottom=i};_setCursor=t=>{if(!document.body){console.warn("ResizeAction: Cannot set cursor - document.body is null");return}try{t?(this._dragCursorStyle.innerHTML=`body, body * { cursor: ${t} !important; }`,document.head.contains(this._dragCursorStyle)||document.head.appendChild(this._dragCursorStyle)):document.head.contains(this._dragCursorStyle)&&document.head.removeChild(this._dragCursorStyle)}catch(e){console.error("ResizeAction: Error setting cursor style:",e)}};_resizeMode=t=>{if(t){if(this._hasResized=!1,this._formattedWidth="",this._target){this._useRelativeSize=this.formatter._useRelative(this._target),this._editorStyle=getComputedStyle(this.formatter.quill.root),this._editorWidth=this.formatter.quill.root.clientWidth-parseFloat(this._editorStyle.paddingLeft)-parseFloat(this._editorStyle.paddingRight);const e=this._target.getBoundingClientRect();if((e.height===void 0||e.height===0)&&(e.height=this._target.clientHeight+1),this._preDragWidth=e.width,this._computedAspectRatio=getComputedStyle(this._target).aspectRatio||"auto",this._calculatedAspectRatio=e.width/e.height,this._useRelativeSize)this._isUnclickable&&this._computedAspectRatio==="auto"&&(this._target.style.aspectRatio=this.formatter.options.video.defaultAspectRatio,console.warn(`No iframe aspect-ratio set. Set an aspect ratio either via custom blot or css.
Using temporary aspect ratio "${this.formatter.options.video.defaultAspectRatio}"`));else if(this._isUnclickable&&this._computedAspectRatio!=="auto"){const i=this._computedAspectRatio.match(/(\d+)\s*\/\s*(\d+)/);if(i)try{this._calculatedAspectRatio=parseFloat(i[1])/parseFloat(i[2])}catch{}}this._isImage&&!this._useRelativeSize&&!this._isSVG&&this.formatter.options.resize.imageOversizeProtection&&(this._naturalWidth=this._target.naturalWidth),this._showSizeInfo(!0,e.width,e.height),this.debug&&console.debug("ResizeAction resize mode activated:",{target:this._target,useRelativeSize:this._useRelativeSize,editorWidth:this._editorWidth,preDragWidth:this._preDragWidth,aspectRatio:this._calculatedAspectRatio,computedAspectRatio:this._computedAspectRatio})}}else{if(this._target&&this._hasResized){let e=this._roundDimension(this._formattedWidth);this._target.setAttribute("width",e),this.formatter.toolbar.buttons.resizeMode&&(this.formatter.toolbar.buttons.resizeMode.selected=this.isRelative),this._isUnclickable?(this._target.style.setProperty("--resize-width",`${e}`),this._target.dataset.relativeSize=`${this.isRelative}`):this.isAligned&&this._target.parentElement&&(this._target.parentElement.style.setProperty("--resize-width",`${e}`),this._target.parentElement.dataset.relativeSize=`${this.isRelative}`),this.debug&&console.debug("ResizeAction resize mode deactivated:",{target:this._target,width:e,isRelative:this.isRelative,isAligned:this.isAligned})}this._naturalWidth=void 0,this.formatter.update(),this._showSizeInfo(!1)}};_onHandlePointerDown=t=>{this._resizeMode(!0),t.target instanceof HTMLElement&&this._target&&(this._dragHandle=t.target,this._setCursor(this._dragHandle.style.cursor),this._dragStartX=t.clientX,document.addEventListener("pointermove",this._onHandleDrag),document.addEventListener("pointerup",this._onHandlePointerUp))};_onHandleDrag=t=>{if(!this._target||!this._dragHandle)return;this._hasResized=!0;const e=t.clientX-this._dragStartX,i=this._dragHandle===this._topLeftHandle||this._dragHandle===this._bottomLeftHandle,s=Math.round(i?this._preDragWidth-e:this._preDragWidth+e),o=Math.max(Math.min(s,this._editorWidth),this.formatter.options.resize.minimumWidthPx);this._resizeTarget(o)};_onHandlePointerUp=()=>{this._setCursor(""),this._resizeMode(!1),document.removeEventListener("pointermove",this._onHandleDrag),document.removeEventListener("pointerup",this._onHandlePointerUp)};_onOverlayTouchStart=t=>{t.target===this.formatter.overlay&&(this._resizeMode(!0),this._target&&t.touches.length===2&&(t.preventDefault(),this._pinchStartDistance=this._calculateDistance(t.touches[0],t.touches[1]),this._preDragWidth=this._target.clientWidth))};_onOverlayTouchMove=t=>{if(t.target===this.formatter.overlay&&this._target&&t.touches.length===2&&this._pinchStartDistance!==null&&this._preDragWidth!==null&&(t.preventDefault(),this._target)){this._hasResized=!0;const i=this._calculateDistance(t.touches[0],t.touches[1])/this._pinchStartDistance;let s=Math.round(this._preDragWidth*i);s=Math.max(Math.min(s,this._editorWidth),10),this._resizeTarget(s)}};_onOverlayTouchEnd=t=>{t.target===this.formatter.overlay&&this._resizeMode(!1)};_onOverlayMouseDown=t=>{t.target===this.formatter.overlay&&this._resizeMode(!0)};_onOverlayMouseUp=t=>{t.target===this.formatter.overlay&&this._resizeMode(!1)};_resizeTarget=t=>{if(!this._target){console.warn("ResizeAction: Cannot resize - target element is null");return}try{t=Math.min(this._naturalWidth??1/0,t);const e=t/this._calculatedAspectRatio;this._updateSizeInfo(t,e),this.formatter._useRelative(this._target)?this._formattedWidth=`${100*t/this._editorWidth}%`:this._formattedWidth=`${t}px`,this._target.setAttribute("width",this._formattedWidth),this._target.setAttribute("height","auto"),this._isUnclickable?(!this._useRelativeSize&&this._computedAspectRatio==="auto"&&this._target.setAttribute("height",`${t/this._calculatedAspectRatio|0}px`),this._target.style.setProperty("--resize-width",this._formattedWidth)):!this._isUnclickable&&this.isAligned&&this._target.parentElement&&this._target.parentElement.style.setProperty("--resize-width",this._formattedWidth),this.formatter.update()}catch(e){console.error("ResizeAction: Error resizing target element:",e)}};_showSizeInfo=(t,e=null,i=null)=>{t?(this._cancelSizeInfoTimer(),e!==null&&i!==null&&this._updateSizeInfo(e,i),this.formatter.sizeInfo.style.transition="",this.formatter.sizeInfo.style.opacity="1"):this._closeSizeInfo()};_updateSizeInfo=(t,e)=>{const i=Math.round(t),s=Math.round(e);let o=`${i} x ${s}px`;if(this.isRelative)o=`${Math.round(100*t/this._editorWidth)}% (${o})`;else if(!this._hasResized&&this._target){const n=this._target.getAttribute("width");if(n){const r=parseFloat(n);if(r!==t){const l=t/e,f=Math.round(r/l);o=`${n} x ${f}px (${o})`}}else if(this._target instanceof HTMLImageElement){const{naturalWidth:r,naturalHeight:l}=this._target;r!==t&&(o=`${r} x ${l}px (${o})`)}}this.formatter.sizeInfo.innerText=o};get isRelative(){return this._target?.getAttribute("width")?.endsWith("%")||!1}get isAligned(){return this._target?this._target.hasAttribute("data-blot-align"):!1}_createResizeModeButton=()=>{const t=new w("resizeMode",this._onResizeModeClickHandler,this.formatter.options.toolbar);return t.preselect=()=>this.isRelative,t};_onResizeModeClickHandler=t=>{t.stopImmediatePropagation(),this._swapResizeMode(!0)};_swapResizeMode=(t=!1)=>{if(this._target){const e=this._target.getBoundingClientRect();this._editorStyle=getComputedStyle(this.formatter.quill.root),this._editorWidth=this.formatter.quill.root.clientWidth-parseFloat(this._editorStyle.paddingLeft)-parseFloat(this._editorStyle.paddingRight);let i;this.isRelative?i=`${Math.round(e.width)}px`:i=`${Math.round(100*e.width/this._editorWidth)}%`,this._target.setAttribute("width",`${i}`),this._target.setAttribute("height","auto"),this.formatter.currentSpec?.isUnclickable?(this._target.style.setProperty("--resize-width",`${i}`),this._target.dataset.relativeSize=`${this.isRelative}`):this.isAligned&&this._target.parentElement&&(this._target.parentElement.style.setProperty("--resize-width",`${i}`),this._target.parentElement.dataset.relativeSize=`${this.isRelative}`),this.formatter.toolbar.buttons.resizeMode.selected=this.isRelative,this.formatter.update(),t&&(this._showSizeInfo(!0,e.width,e.height),this._showSizeInfo(!1)),this.debug&&console.debug("ResizeAction resize mode swapped:",{target:this._target,newWidth:i,isRelative:this.isRelative,isAligned:this.isAligned})}};_closeSizeInfo=()=>{this._sizeInfoTimerId=setTimeout(()=>{this.formatter.sizeInfo.style.transition="opacity 1s",this.formatter.sizeInfo.style.opacity="0"},1e3)};_cancelSizeInfoTimer=()=>{this._sizeInfoTimerId!==null&&(clearTimeout(this._sizeInfoTimerId),this._sizeInfoTimerId=null)};_calculateDistance=(t,e)=>{const i=e.clientX-t.clientX,s=e.clientY-t.clientY;return Math.sqrt(i*i+s*s)};_roundDimension=t=>t.replace(/([^0-9.-]*)(-?[\d.]+)(.*)/,(e,i,s,o)=>`${i}${Math.round(Number(s))}${o}`);_isSvgImage=()=>this._target instanceof HTMLImageElement?this._target.src.startsWith("data:image/")?this._target.src.includes("image/svg+xml"):this._target.src.endsWith(".svg"):!1}class I{formatter;isUnclickable=!1;constructor(t){this.formatter=t}init=()=>{};getActions(){const t=[];return this.formatter.options.align.allowAligning&&t.push(new N(this.formatter)),this.formatter.options.resize.allowResizing&&t.push(new D(this.formatter)),this.formatter.options.delete.allowKeyboardDelete&&t.push(new q(this.formatter)),t.push(new A(this.formatter)),t}getTargetElement=()=>null;getTargetBlot=()=>{const t=this.getTargetElement();return t?this.formatter.Quill.find(t):null};getOverlayElement=()=>this.getTargetElement();setSelection=()=>{this.formatter.quill.setSelection(null)};onHide=()=>{}}const K="blot-formatter__proxy-image";class W extends I{selector;unclickable;proxyContainer;unclickableProxies;isUnclickable=!0;constructor(t){super(t),this.selector=t.options.video.selector,this.unclickable=null,this.proxyContainer=this._createProxyContainer(),this.unclickableProxies={}}init=()=>{this.formatter.quill.on("text-change",this._onTextChange),this.formatter.quill.root.addEventListener("scroll",()=>{this._repositionProxyImages()}),this._observeEditorResize()};_observeEditorResize=()=>{let t=null;new ResizeObserver(i=>{for(const s of i)t&&clearTimeout(t),t=window.setTimeout(()=>{this._repositionProxyImages()},200)}).observe(this.formatter.quill.root)};getTargetElement=()=>this.unclickable;getOverlayElement=()=>this.unclickable;_onTextChange=()=>{Object.entries(this.unclickableProxies).forEach(([t,{unclickable:e,proxyImage:i}])=>{try{this.formatter.quill.root.contains(e)||(i.remove(),delete this.unclickableProxies[t])}catch{}}),this.formatter.quill.root.querySelectorAll(`${this.selector}:not([data-blot-formatter-id])`).forEach(t=>{this._createUnclickableProxyImage(t)}),this._repositionProxyImages()};_createUnclickableProxyImage=t=>{const e=Array.from(crypto.getRandomValues(new Uint8Array(5)),r=>String.fromCharCode(97+r%26)).join("");t.dataset.blotFormatterId=e;const i=document.createElement("canvas"),s=i.getContext("2d");s&&(s.globalAlpha=0,s.fillRect(0,0,1,1));const o=document.createElement("img");o.src=i.toDataURL("image/png"),o.classList.add(K),o.dataset.blotFormatterId=e;const n={...this.formatter.options.video.proxyStyle,position:"absolute",margin:"0",userSelect:"none"};Object.assign(o.style,n),o.style.setProperty("-webkit-user-select","none"),o.style.setProperty("-moz-user-select","none"),o.style.setProperty("-ms-user-select","none"),this.formatter.options.debug&&o.style.setProperty("border","3px solid red"),this.proxyContainer.appendChild(o),o.addEventListener("click",this._onProxyImageClick),o.addEventListener("contextmenu",r=>{r.stopPropagation(),r.preventDefault()}),o.addEventListener("wheel",this.formatter._passWheelEventThrough),o.addEventListener("touchstart",this.formatter._onTouchScrollStart,{passive:!1}),o.addEventListener("touchmove",this.formatter._onTouchScrollMove,{passive:!1}),this.unclickableProxies[e]={unclickable:t,proxyImage:o},this.formatter.options.debug&&console.debug("UnclickableBlotSpec created proxy for unclickable:",t,"with ID:",e,"and proxy image:",o)};_repositionProxyImages=()=>{if(Object.keys(this.unclickableProxies).length>0){const t=this.formatter.quill.container.getBoundingClientRect(),e=this.formatter.quill.container.scrollLeft,i=this.formatter.quill.container.scrollTop;Object.entries(this.unclickableProxies).forEach(([s,{unclickable:o,proxyImage:n}])=>{try{const r=o.getBoundingClientRect();Object.assign(n.style,{left:`${r.left-t.left-1+e}px`,top:`${r.top-t.top+i}px`,width:`${r.width}px`,height:`${r.height}px`})}catch(r){const l=`Error positioning proxy image with id ${s}: `;console.error(l,`${r instanceof Error?r.message:r}`)}})}};_onProxyImageClick=t=>{const i=t.target.dataset.blotFormatterId;this.unclickable=this.unclickableProxies[`${i}`].unclickable,this.formatter.show(this)};_createProxyContainer=()=>{const t=document.createElement("div");return t.classList.add("proxy-container"),this.formatter.quill.container.appendChild(t),t}}class j extends W{constructor(t){super(t)}}class P extends y{modal;targetElement=null;currentBlot=null;constructor(t){super(t),this.toolbarButtons=[new w("attribute",this._onClickHandler,this.formatter.options.toolbar)],this.modal=this._createModal()}onCreate=()=>{this.targetElement=this.formatter.currentSpec?.getTargetElement(),this.currentBlot=this.formatter.currentSpec?.getTargetBlot()};onDestroy=()=>{this.targetElement=null,this.modal.form.removeEventListener("submit",this._onSubmitHandler),this.modal.form.removeEventListener("cancel",this._hideAltTitleModal),this.modal.element.removeEventListener("pointerdown",this._onPointerDownHandler),this.modal.cancelButton.removeEventListener("click",this._hideAltTitleModal),this.modal.element.remove()};_onClickHandler=()=>{this._showAltTitleModal()};_showAltTitleModal=()=>{this.targetElement&&(this.modal.altInput.value=this.targetElement.getAttribute("alt")||"",this.modal.titleInput.value=this.targetElement.getAttribute("title")||"",document.body.append(this.modal.element),this.formatter.options.debug&&console.debug("Showing Alt Title modal for:",this.targetElement))};_hideAltTitleModal=()=>{this.modal.element.remove()};_setAltTitle=()=>{if(this.targetElement){const t=typeof this.modal.altInput.value=="string"?this.modal.altInput.value:"",e=this.modal.titleInput.value;this.targetElement.setAttribute("alt",t),e?this.targetElement.setAttribute("title",e):this.targetElement.removeAttribute("title"),this.formatter.options.debug&&console.debug("Setting alt:",t,"title:",e,"on target element:",this.targetElement);const i=this.currentBlot?.parent?.formats()[this.formatter.ImageAlign.attrName]?.align;this.currentBlot&&i&&(this.formatter.options.debug&&console.debug("Updating title of image with alignment:",i),this.currentBlot.parent?.format(this.formatter.ImageAlign.attrName,!1),this.currentBlot.format(this.formatter.ImageAlign.attrName,{align:i,title:e}))}};_createModal=()=>{const t=Array.from(crypto.getRandomValues(new Uint8Array(5)),p=>String.fromCharCode(97+p%26)).join(""),e=document.createElement("div");e.id=`${t}-modal`,e.setAttribute("data-blot-formatter-modal","");const i=document.createElement("div"),s=document.createElement("form");s.id=`${t}-form`;const o=document.createElement("label");o.setAttribute("for","alt"),o.textContent=this.formatter.options.overlay.labels?.alt||this.formatter.options.image.altTitleModalOptions.labels.alt;const n=document.createElement("textarea");n.name="alt",n.rows=3;const r=document.createElement("label");r.setAttribute("for","title"),r.textContent=this.formatter.options.overlay.labels?.title||this.formatter.options.image.altTitleModalOptions.labels.title;const l=document.createElement("textarea");l.name="title",l.rows=3;const f=document.createElement("div"),g=document.createElement("button");g.type="submit",g.innerHTML=this.formatter.options.image.altTitleModalOptions.icons.submitButton,f.appendChild(g),s.appendChild(o),s.appendChild(n),s.appendChild(r),s.appendChild(l),s.appendChild(f);const m=document.createElement("button");return m.id=`${t}-cancel`,m.type="button",m.innerHTML=this.formatter.options.image.altTitleModalOptions.icons.cancelButton,this.formatter.options.image.altTitleModalOptions.styles&&(Object.assign(e.style,this.formatter.options.image.altTitleModalOptions.styles.modalBackground),Object.assign(i.style,this.formatter.options.image.altTitleModalOptions.styles.modalContainer),Object.assign(o.style,this.formatter.options.image.altTitleModalOptions.styles.label),Object.assign(n.style,this.formatter.options.image.altTitleModalOptions.styles.textarea),Object.assign(r.style,this.formatter.options.image.altTitleModalOptions.styles.label),Object.assign(l.style,this.formatter.options.image.altTitleModalOptions.styles.textarea),Object.assign(g.style,this.formatter.options.image.altTitleModalOptions.styles.submitButton),Object.assign(m.style,this.formatter.options.image.altTitleModalOptions.styles.cancelButton)),i.appendChild(s),i.appendChild(m),e.appendChild(i),s.addEventListener("submit",this._onSubmitHandler),s.addEventListener("cancel",this._hideAltTitleModal),e.addEventListener("pointerdown",this._onPointerDownHandler),m.addEventListener("click",this._hideAltTitleModal),{element:e,form:s,altInput:n,titleInput:l,cancelButton:m}};_onSubmitHandler=t=>{t.preventDefault(),this._setAltTitle(),this._hideAltTitleModal()};_onPointerDownHandler=t=>{t.target===this.modal.element&&this._hideAltTitleModal()}}class C extends y{options;modal;targetElement=null;imageDetails=null;static isEligibleForCompression=(t,e=!1)=>{let i=!1;if(t instanceof HTMLImageElement&&t.src.startsWith("data:image/")){const s=t.src.substring(5,t.src.indexOf(";"));i=s!=="svg+xml"&&s!=="gif"}return e&&console.debug("Image eligibility check:",{element:t,isEligible:i}),i};constructor(t){super(t),this.options=this.formatter.options.image.compressorOptions,this.toolbarButtons=[new w("compress",this._onClickHandler,this.formatter.options.toolbar)],this.modal=this._createModal()}onCreate=()=>{this.targetElement=this.formatter.currentSpec?.getTargetElement();const t=C.isEligibleForCompression(this.targetElement,this.debug);this.toolbarButtons[0].initialVisibility=t,this.debug&&console.debug("CompressAction initialized with target element:",this.targetElement,"is eligible:",t)};onDestroy=()=>{this.targetElement=null,this._hideModal(),this.modal.continueButton.removeEventListener("click",this._onContinueClick),this.modal.moreInfoButton.removeEventListener("click",this._onMoreInfoClick),this.modal.cancelButton.removeEventListener("click",this._hideModal),this.modal.element.removeEventListener("pointerdown",this._onBackgroundClick)};_onClickHandler=()=>{this._showModal()};_showModal=()=>{this.targetElement instanceof HTMLImageElement&&(this.imageDetails=this._getImageDetails(this.targetElement),this.imageDetails.canCompress?(this.modal.moreInfoButton.style.visibility="visible",this.modal.moreInfoText.style.display="none",document.body.append(this.modal.element)):this._displayFeedback(this.options.text.nothingToDo))};_hideModal=()=>{this.modal.element.remove()};_parseDimensions=t=>{let e=t.getAttribute("width"),i=t.getAttribute("height"),s=null,o=null;if(e)if(e.toLowerCase().endsWith("px"))s=parseFloat(e);else if(e.endsWith("%"))s=this.options.maxWidth??null;else if(e.toLowerCase().endsWith("em")||e.toLowerCase().endsWith("rem"))s=parseFloat(e)*16;else if(!isNaN(parseFloat(e)))s=parseFloat(e);else return[null,null];if(i)if(!isNaN(parseFloat(i)))o=parseFloat(i);else if(i.toLowerCase().endsWith("px"))o=parseFloat(i);else if(i.toLowerCase().endsWith("em")||i.toLowerCase().endsWith("rem"))o=parseFloat(i)*16;else if(s&&t.naturalWidth>0&&t.naturalHeight>0)o=s/(t.naturalWidth/t.naturalHeight);else return[null,null];return[s,o]};_getImageSize=t=>{const e=t.getAttribute("src");if(!e||!e.startsWith("data:image/"))return null;const i=e.split(",")[1];return i?Math.ceil(i.length*3/4):null};_displayFeedback=t=>{this.formatter.sizeInfo.innerHTML=t,this.formatter.sizeInfo.style.transition="",this.formatter.sizeInfo.style.opacity="1",setTimeout(()=>{this.formatter.sizeInfo.style.transition="opacity 1s",this.formatter.sizeInfo.style.opacity="0"},2500)};_getImageDetails=t=>{let[e,i]=this._parseDimensions(t);!e&&(this.options.maxWidth??1/0)<t.naturalWidth&&(e=this.options.maxWidth,i=e/(t.naturalWidth/t.naturalHeight));const s={naturalWidth:t.naturalWidth,naturalHeight:t.naturalHeight,targetWidth:e,targetHeight:i,size:this._getImageSize(t),canCompress:!!(e&&i&&e<t.naturalWidth&&C.isEligibleForCompression(t,this.debug))};return this.debug&&console.debug("Image details:",{element:t,...s}),s};_compressImage=t=>{if(this.imageDetails?.canCompress){const e=new Image;e.src=t.src,e.onload=()=>{this.debug&&console.debug("Compressing Image Copy loaded:",e);const i=document.createElement("canvas");i.width=this.imageDetails.targetWidth,i.height=this.imageDetails.targetHeight,i.getContext("2d").drawImage(e,0,0,i.width,i.height);const o=i.toDataURL("image/jpeg",this.options.jpegQuality),n=new TextEncoder().encode(t.src).length,r=new TextEncoder().encode(o).length;r<n&&(t.src=o);const l=`${Math.ceil((this.imageDetails.size-this._getImageSize(t))/1024)}kB`,f=`${this.options.text.reducedLabel}: ${l}<br>
${this.imageDetails.naturalWidth} x ${this.imageDetails.naturalHeight}px → ${i.width} x ${Math.round(i.height)}px
`;return this.debug&&console.debug("Image compressed:",{"original size":n,"resized size":r,"size diff":l,"new dimensions":{width:i.width,height:Math.round(i.height)}}),this._displayFeedback(f),!0},e.onerror=i=>(console.error("Image loading failed:",i),this._displayFeedback(`Image loading failed: ${i}`),!1)}else this._displayFeedback(this.options.text.nothingToDo);return!0};_createModal=()=>{const t=document.createElement("div");t.setAttribute("data-blot-formatter-compress-modal","");const e=document.createElement("div"),i=document.createElement("div"),s=document.createElement("div"),o=document.createElement("div"),n=document.createElement("button"),r=document.createElement("button"),l=document.createElement("button");return s.style.display="none",o.append(n,r,l),e.append(i,s,o),t.appendChild(e),i.innerHTML=this.options.text.prompt,s.innerHTML=this.options.text.moreInfo||"",this.options.styles&&(Object.assign(t.style,this.options.styles.modalBackground),Object.assign(e.style,this.options.styles.modalContainer),Object.assign(o.style,this.options.styles.buttonContainer),Object.assign(n.style,{...this.options.styles.buttons,...this.options.buttons.cancel.style}),this.options.text.moreInfo?Object.assign(r.style,{...this.options.styles.buttons,...this.options.buttons.moreInfo.style}):r.style.visibility="hidden",Object.assign(l.style,{...this.options.styles.buttons,...this.options.buttons.continue.style})),n.innerHTML=this.options.icons.cancel,r.innerHTML=this.options.icons.moreInfo,l.innerHTML=this.options.icons.continue,l.addEventListener("click",this._onContinueClick),r.addEventListener("click",this._onMoreInfoClick),n.addEventListener("click",this._hideModal),t.addEventListener("pointerdown",this._onBackgroundClick),{element:t,moreInfoButton:r,cancelButton:n,continueButton:l,moreInfoText:s}};_onContinueClick=()=>{this.targetElement instanceof HTMLImageElement&&this._compressImage(this.targetElement),this._hideModal()};_onMoreInfoClick=()=>{this.modal.moreInfoText.innerHTML=this.options.text.moreInfo||"",this.modal.moreInfoText.style.display="block",this.modal.moreInfoButton.style.visibility="hidden"};_onBackgroundClick=t=>{t.stopImmediatePropagation(),t.target===this.modal.element&&(this.debug&&console.debug("Modal background clicked, hiding modal"),this._hideModal())}}class $ extends y{targetElement=null;currentBlot=null;toolbarButton;linkOptions;modal;constructor(t){super(t),this.linkOptions=this.formatter.options.image.linkOptions,this.toolbarButton=new w("link",this._onClickHandler,this.formatter.options.toolbar),this.toolbarButton.preselect=()=>!!this.getLink(),this.toolbarButtons=[this.toolbarButton],window.LinkAction=this}onCreate=()=>{this.targetElement=this.formatter.currentSpec?.getTargetElement(),this.currentBlot=this.formatter.currentSpec?.getTargetBlot()};onDestroy=()=>{this.targetElement=null,this._removeEventListeners(),this.hideLinkModal()};_addEventListeners=()=>{this.modal&&(this.modal.form.addEventListener("submit",this._formSubmitHandler),this.modal.cancelButton.addEventListener("click",this.hideLinkModal),this.modal.removeButton.addEventListener("click",this.removeLink),this.modal.background.addEventListener("click",this._onBackgroundClick),this.modal.input.addEventListener("contextmenu",this._trapContextEvent))};_removeEventListeners=()=>{this.modal&&(this.modal.form.removeEventListener("submit",this._formSubmitHandler),this.modal.cancelButton.removeEventListener("click",this.hideLinkModal),this.modal.removeButton.removeEventListener("click",this.removeLink),this.modal.background.removeEventListener("click",this._onBackgroundClick),this.modal.input.removeEventListener("contextmenu",this._trapContextEvent))};_trapContextEvent=t=>{t.stopImmediatePropagation()};_onClickHandler=()=>{this.showLinkModal()};_onBackgroundClick=t=>{t.target===this.modal?.background&&(t.stopImmediatePropagation(),t.preventDefault(),this.hideLinkModal(),this.debug&&console.debug("LinkAction modal background clicked, hiding modal"))};showLinkModal=()=>{if(this.targetElement){if(this.modal=this._buildModal(),!this.modal)return;this.formatter.overlay.append(this.modal.dialog,this.modal.background),this._addEventListeners(),this.modal.dialog.style.visibility="hidden",this.modal.dialog.show(),this._positionModal(this.modal.dialog),this.modal.dialog.style.visibility="visible",this.modal.input.focus(),this.modal.input.select()}};_buildModal=()=>{const t=document.createElement("dialog");t.className=this.linkOptions.modal.dialog.className,t.dataset.blotFormatterModal="",Object.assign(t.style,this.linkOptions.modal.dialog.style);const e=document.createElement("form");e.method="dialog",e.className=this.linkOptions.modal.form.className,Object.assign(e.style,this.linkOptions.modal.form.style);const i=document.createElement("label");i.htmlFor="link-url",i.textContent=this.linkOptions.modal.label.text,i.className=this.linkOptions.modal.label.className,Object.assign(i.style,this.linkOptions.modal.label.style);const s=document.createElement("input");s.type="url",s.id="link-url",s.name="url",s.value=this.getLink()||"",s.select(),s.autofocus=!0,s.className=this.linkOptions.modal.input.className,Object.assign(s.style,this.linkOptions.modal.input.style),s.placeholder=this.linkOptions.modal.input.placeholder||"";const o=document.createElement("button");o.type="submit",o.innerHTML=this.linkOptions.modal.buttons.submit.icon,o.className=this.linkOptions.modal.buttons.submit.className,Object.assign(o.style,this.linkOptions.modal.buttons.submit.style);const n=document.createElement("button");n.type="button",n.innerHTML=this.linkOptions.modal.buttons.cancel.icon,n.className=this.linkOptions.modal.buttons.cancel.className,Object.assign(n.style,this.linkOptions.modal.buttons.cancel.style);const r=document.createElement("button");r.type="button",r.innerHTML=this.linkOptions.modal.buttons.remove.icon,r.className=this.linkOptions.modal.buttons.remove.className,Object.assign(r.style,this.linkOptions.modal.buttons.remove.style),e.appendChild(i),e.appendChild(s),e.appendChild(o),e.appendChild(r),e.appendChild(n),t.appendChild(e);const l=document.createElement("div");return l.className=this.linkOptions.modal.background.className||"",Object.assign(l.style,this.linkOptions.modal.background.style),{dialog:t,background:l,form:e,label:i,input:s,okButton:o,cancelButton:n,removeButton:r}};_positionModal=t=>{const e=this.formatter.overlay.getBoundingClientRect(),i=this.formatter.quill.root.getBoundingClientRect(),s=t.offsetParent?.getBoundingClientRect()??{top:0,left:0},o=t.offsetWidth,n=t.offsetHeight;let r=e.left+e.width/2-o/2-s.left,l=e.top+e.height/2-n/2-s.top;const f=i.left-s.left,g=i.right-o-s.left;r=Math.min(Math.max(r,f),g);const m=i.top-s.top,p=i.bottom-n-s.top;l=Math.min(Math.max(l,m),p),t.style.position="absolute",t.style.left=`${r}px`,t.style.top=`${l}px`};hideLinkModal=()=>{this.modal?.dialog?.open&&this.modal.dialog.close(),this.modal?.dialog?.remove(),this.modal?.background&&this.modal.background.remove(),this._removeEventListeners(),this.modal=void 0};_formSubmitHandler=t=>{t.preventDefault();const e=t.target,s=new FormData(e).get("url").trim();this.debug&&console.debug("LinkAction form submitted with URL:",s),this.currentBlot&&(s?this.applyLink(s):this.removeLink())};getLink=()=>{const t=this.currentBlot;if(!t||!t.domNode)return null;const e=this.formatter.quill.getIndex(t),i=this.formatter.quill.getFormat(e,1,this.formatter.Quill.sources.SILENT);return this.debug&&console.debug("LinkAction getLink called, formats:",i),i.link||null};removeLink=()=>{const t=this.currentBlot;if(!t||!t.domNode)return;let e=t.parent;for(;e&&typeof e.formats=="function";){if(e.formats().link){e.format("link",null);break}e=e.parent}this.debug&&console.debug("LinkAction removeLink called, removed link from blot:",e),this.hideLinkModal(),this.toolbarButton.selected=!1};applyLink=t=>{t!==this.getLink()&&(this.removeLink(),this.currentBlot?.format("link",t),this.toolbarButton.selected=!!t),this.hideLinkModal()}}class F extends