@mosaicoo/svg-engine 0.1.0

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.
@@ -0,0 +1,2292 @@
1
+ import*as s from"@angular/core";import{signal as b,computed as m,Injectable as D,inject as f,effect as J,untracked as li,InjectionToken as gt,Injector as Vt,ElementRef as ae,afterEveryRender as pr,ChangeDetectionStrategy as U,Component as W,makeEnvironmentProviders as ci,ENVIRONMENT_INITIALIZER as Fd,viewChild as jd,Directive as pt,input as Gr,DestroyRef as Hr,HostListener as fr}from"@angular/core";import{CommandBus as M,TranslateManyCommand as Ur,toNodeId as Wr,findNodeById as T,isLayer as zt,isPage as $e,parseTransformAttr as di,applyTransform as K,bbox as X,IDENTITY_TRANSFORM as Kr,multiply as ee,EditorStateService as S,invert as Gt,translate as mr,MoveNodeCommand as Vd,composePivotRotation as ui,RotateNodeCommand as hi,bakeScaleIntoNode as zd,composeAnchoredScale as Xr,ResizeNodeCommand as gi,ResizeNodesCommand as Gd,RotateNodesCommand as pi,updateNode as fi,findParent as ft,getPageName as mi,getPageViewBox as Be,getPageBackgroundNode as Hd,createPath as N,InsertNodeCommand as he,AUTO_PARENT as te,isIdentityOrTranslate as Ud,anchorsToPathD as vi,createPolygon as Yr,createEllipse as yi,createRect as qr,createText as Zr,RemoveNodeCommand as vr,SetPropertyCommand as yr,isGroupNode as Fe,RemoveAnchorCommand as Wd,generateNodeId as Ht,ok as Re,createSymbolUse as bi,insertNode as Jr,fail as le,removeNode as Qr,walk as je,SetStylePropertyOnManyCommand as Kd,KnifeCutPathCommand as Xd,parsePathToAnchors as Ut,getPageOptions as wi,PAGE_BACKGROUND_IMAGE_PAR as Yd,readAnimationDoc as qd,emptyAnimationDoc as Zd,AddKeyframeCommand as Jd,RemoveKeyframeCommand as Qd,RemoveTrackCommand as eu,MoveKeyframeCommand as tu,SetKeyframeEasingCommand as nu,SetAnimationDurationCommand as ru,sampleAnimation as ou,animatablePropertiesForNode as iu,readAnimatableValue as su,cloneNodeWithNewIds as Ii,getNodeBBox as br,createGroup as mt,createImage as wr,MakeClipMaskCommand as au,unwrapUrlRef as lu,extractDefById as cu,ReleaseClipMaskCommand as du,ReplaceSmartObjectContentsCommand as uu,ReleaseSmartObjectCommand as hu,HistoryService as Wt,SnapshotsService as Ze,RestoreSnapshotCommand as ki,ReorderNodeCommand as gu,FlipNodeCommand as pu,ConvertNodeToPathCommand as fu,UnionCommand as mu,IntersectCommand as vu,SubtractCommand as yu,DivideCommand as bu,ExcludeCommand as wu,CreateLayerCommand as Iu,MakeLayerCommand as ku,UnmakeLayerCommand as xu,isSmartObject as Du,MakeSmartObjectCommand as Su,GroupSelectionCommand as xi,UngroupCommand as Di,DuplicateNodeCommand as Pu,getNodesWorldBBox as Mu,EnsureDefaultPageCommand as eo,withSmartObjectFlag as _u,RasterizeNodeCommand as Eu,ANIMATION_KEY as Tu,createLine as Ru,isLiveBooleanGroup as Au,MakeCompoundPathCommand as Cu,ReleaseCompoundPathCommand as Ou,MakeLiveBooleanCommand as Nu,RefreshLiveBooleanCommand as Lu,ReleaseLiveBooleanCommand as $u,BatchConvertToPathCommand as Bu,OutlineStrokeCommand as Fu,JoinPathsCommand as ju,SplitPathCommand as Vu,ReversePathCommand as zu,CleanUpPathCommand as Gu,intersectsBBox as Hu,InsertAnchorCommand as Si,MoveAnchorCommand as Pi,ConvertAnchorTypeCommand as Uu,DEFAULT_SNAPSHOT_LIMITS as Wu,INSERT_PARENT_RESOLVER as Ku,createEmptyDocument as ge,MovePageCommand as Xu,ResizePageCommand as Yu}from"@mosaicoo/svg-engine/core";import{ViewportService as A,screenToDoc as Ve,SvgeNodeRenderer as Mi}from"@mosaicoo/svg-engine/render";import{DOCUMENT as re}from"@angular/common";import{svgExporter as vt,collectDefsIds as qu,namespaceCollidingDefs as Zu,mergeDefsFragments as _i,renderPng as to,svgImporter as ze,nodeToSvgMarkup as Ju,gunzipText as Ei,pngExporter as Ti,svgzExporter as Qu,gzipText as eh,ImporterRegistry as th,ExporterRegistry as no}from"@mosaicoo/svg-engine/io";import{ExporterRegistry as um,ImporterRegistry as hm,pngExporter as gm,renderPng as pm,svgExporter as fm,svgImporter as mm}from"@mosaicoo/svg-engine/io";import{OptimizerRegistry as Ri,OptimizeCommand as nh,precisionOptimizer as rh,dropDefaultsOptimizer as oh,pruneEmptyGroupsOptimizer as ih,stripAuthoredTitlesOptimizer as sh}from"@mosaicoo/svg-engine/optimize";import{OptimizeCommand as ym,OptimizerRegistry as bm,dropDefaultsOptimizer as wm,precisionOptimizer as Im,pruneEmptyGroupsOptimizer as km,stripAuthoredTitlesOptimizer as xm}from"@mosaicoo/svg-engine/optimize";import{DomSanitizer as ah}from"@angular/platform-browser";class ne{_hiddenIds=b(new Set,...ngDevMode?[{debugName:"_hiddenIds"}]:[]);_lockedIds=b(new Set,...ngDevMode?[{debugName:"_lockedIds"}]:[]);hiddenIds=this._hiddenIds.asReadonly();lockedIds=this._lockedIds.asReadonly();hasHidden=m(()=>this._hiddenIds().size>0,...ngDevMode?[{debugName:"hasHidden"}]:[]);hasLocked=m(()=>this._lockedIds().size>0,...ngDevMode?[{debugName:"hasLocked"}]:[]);isVisible(e){return!this._hiddenIds().has(e)}isLocked(e){return this._lockedIds().has(e)}setVisible(e,t){const n=this._hiddenIds(),o=n.has(e);if(t&&!o||!t&&o)return;const i=new Set(n);t?i.delete(e):i.add(e),this._hiddenIds.set(i)}toggleVisible(e){this.setVisible(e,!this.isVisible(e))}setLocked(e,t){const n=this._lockedIds(),o=n.has(e);if(t&&o||!t&&!o)return;const i=new Set(n);t?i.add(e):i.delete(e),this._lockedIds.set(i)}toggleLocked(e){this.setLocked(e,!this.isLocked(e))}showAll(){this._hiddenIds().size!==0&&this._hiddenIds.set(new Set)}unlockAll(){this._lockedIds().size!==0&&this._lockedIds.set(new Set)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ne,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ne,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ne,decorators:[{type:D,args:[{providedIn:"root"}]}]});class k{layers=f(ne);_selectedIds=b(new Set,...ngDevMode?[{debugName:"_selectedIds"}]:[]);_focusId=b(null,...ngDevMode?[{debugName:"_focusId"}]:[]);_hoverId=b(null,...ngDevMode?[{debugName:"_hoverId"}]:[]);selectedIds=this._selectedIds.asReadonly();focusId=this._focusId.asReadonly();hoverId=this._hoverId.asReadonly();count=m(()=>this._selectedIds().size,...ngDevMode?[{debugName:"count"}]:[]);hasSelection=m(()=>this._selectedIds().size>0,...ngDevMode?[{debugName:"hasSelection"}]:[]);isSingleSelection=m(()=>this._selectedIds().size===1,...ngDevMode?[{debugName:"isSingleSelection"}]:[]);constructor(){J(()=>{const e=this.layers.lockedIds();e.size!==0&&li(()=>{const t=this._selectedIds();let n=null;for(const i of t)e.has(i)&&(n===null&&(n=new Set(t)),n.delete(i));if(n!==null){this._selectedIds.set(n);const i=this._focusId();i!==null&&e.has(i)&&this._focusId.set(n.size===0?null:Ir(n))}const o=this._hoverId();o!==null&&e.has(o)&&this._hoverId.set(null)})})}select(e){this.layers.isLocked(e)||(this._selectedIds.set(new Set([e])),this._focusId.set(e))}selectMany(e){const t=this.layers.lockedIds(),n=new Set;for(const o of e)t.has(o)||n.add(o);this._selectedIds.set(n),this._focusId.set(n.size===0?null:Ir(n))}addToSelection(e){if(this.layers.isLocked(e))return;const t=this._selectedIds();if(t.has(e)){this._focusId.set(e);return}const n=new Set(t);n.add(e),this._selectedIds.set(n),this._focusId.set(e)}toggle(e){if(this.layers.isLocked(e))return;const t=this._selectedIds(),n=new Set(t);t.has(e)?(n.delete(e),this._selectedIds.set(n),this._focusId.set(n.size===0?null:Ir(n))):(n.add(e),this._selectedIds.set(n),this._focusId.set(e))}deselect(e){const t=this._selectedIds();if(!t.has(e))return;const n=new Set(t);n.delete(e),this._selectedIds.set(n),this._focusId()===e&&this._focusId.set(n.size===0?null:Ir(n))}clear(){this._selectedIds().size===0&&this._focusId()===null||(this._selectedIds.set(new Set),this._focusId.set(null))}isSelected(e){return this._selectedIds().has(e)}setHover(e){if(e!==null&&this.layers.isLocked(e)){this._hoverId.set(null);return}this._hoverId.set(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:k,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:k,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:k,decorators:[{type:D,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});function Ir(r){let e;for(const t of r)e=t;return e}const O="1.0.0";function ro(r,e){return{...r,...e}}function En(r){const e=r.trim();if(e.length===0)throw new Error("parseCombo: combo string is empty");const t=e.split("+").map(h=>h.trim());if(t.some(h=>h.length===0))throw new Error(`parseCombo: invalid combo "${r}" (empty token between '+')`);let n=!1,o=!1,i=!1,a=!1,l=!1;for(let h=0;h<t.length-1;h++)switch(t[h].toLowerCase()){case"ctrl":case"control":n=!0;break;case"shift":o=!0;break;case"alt":case"option":i=!0;break;case"cmd":case"meta":case"win":a=!0;break;case"cmdorctrl":l=!0;break;default:throw new Error(`parseCombo: unknown modifier "${t[h]}" in combo "${r}"`)}const c=t[t.length-1],u=(c.length===1,c.toLowerCase());return{ctrl:l?!1:n,shift:o,alt:i,meta:l?!1:a,...l?{__cmdOrCtrl:!0}:{},key:u}}function oo(r,e){if((e.key.length===1,e.key.toLowerCase())!==r.key)return!1;if(r.__cmdOrCtrl===!0){if(!(e.ctrlKey||e.metaKey))return!1}else if(e.ctrlKey!==r.ctrl||e.metaKey!==r.meta)return!1;return!(e.shiftKey!==r.shift||e.altKey!==r.alt)}function io(r){try{return En(r),{ok:!0}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}const lh=new Set(["control","shift","alt","meta","os","altgraph","dead","capslock","contextmenu"]);function ch(r){const e=r.key;if(typeof e!="string"||e.length===0||lh.has(e.toLowerCase()))return null;const t=[];return r.ctrlKey&&t.push("Ctrl"),r.altKey&&t.push("Alt"),r.shiftKey&&t.push("Shift"),r.metaKey&&t.push("Cmd"),t.push(e.length===1?e.toLowerCase():e),t.join("+")}const dh={arrowup:"\u2191",arrowdown:"\u2193",arrowleft:"\u2190",arrowright:"\u2192",escape:"Esc",enter:"Enter",space:"Space"," ":"Space",delete:"Del",backspace:"\u232B",tab:"Tab"};function uh(r){const e=dh[r];return e!==void 0?e:r.length===1||/^f\d{1,2}$/.test(r)?r.toUpperCase():r.charAt(0).toUpperCase()+r.slice(1)}function hh(r){const e=r.trim();if(e.length===0)return"";const t=e.split("+").map(a=>a.trim()).filter(a=>a.length>0);if(t.length===0)return"";const n=t[t.length-1].toLowerCase(),o=t.slice(0,-1).map(a=>a.toLowerCase()),i=[];return o.includes("cmdorctrl")&&i.push("Ctrl/Cmd"),(o.includes("ctrl")||o.includes("control"))&&i.push("Ctrl"),(o.includes("alt")||o.includes("option"))&&i.push("Alt"),o.includes("shift")&&i.push("Shift"),(o.includes("cmd")||o.includes("meta")||o.includes("win"))&&i.push("Cmd"),i.push(uh(n)),i.join("+")}function Kt(r){let e;try{e=En(r)}catch{return r.trim().toLowerCase()}const t=[];return e.__cmdOrCtrl===!0&&t.push("mod"),e.ctrl&&t.push("ctrl"),e.meta&&t.push("meta"),e.alt&&t.push("alt"),e.shift&&t.push("shift"),t.push(e.key),t.join("+")}class tt{_entries=b([],...ngDevMode?[{debugName:"_entries"}]:[]);shortcuts=b([],...ngDevMode?[{debugName:"shortcuts"}]:[]);register(e){if(typeof e.id!="string"||e.id.length===0)throw new Error("ShortcutRegistry.register: shortcut.id must be non-empty");if(this._entries().some(o=>o.shortcut.id===e.id))throw new Error(`ShortcutRegistry.register: shortcut "${e.id}" is already registered`);const t=En(e.combo),n={shortcut:e,parsed:t};return this._entries.set([...this._entries(),n]),this.shortcuts.set(this._entries().map(o=>o.shortcut)),{dispose:()=>{this._entries.set(this._entries().filter(o=>o.shortcut.id!==e.id)),this.shortcuts.set(this._entries().map(o=>o.shortcut))}}}get(e){return this._entries().find(t=>t.shortcut.id===e)?.shortcut??null}tryMatch(e){for(const t of this._entries()){if(!oo(t.parsed,e))continue;const n=t.shortcut.when;if(!(n!=null&&!n()))return t.shortcut}return null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:tt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:tt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:tt,decorators:[{type:D,args:[{providedIn:"root"}]}]});const kr=1,xr=10,Ai={id:"svge.builtin.selection.nudge",version:"1.0.0",name:"Selection arrow-key nudge",apiVersion:O,install(r){const e=r.injector.get(tt),t=(i,a)=>(i?.injector??r.injector).get(a),n=(i,a,l)=>{const c=t(i,k),u=Array.from(c.selectedIds());if(u.length===0)return;const h={x:a,y:l},g=new Map;for(const v of u)g.set(v,h);t(i,M).dispatch(new Ur(g,`Nudge ${u.length} node(s)`))},o=[{id:"svge.nudge.up",combo:"ArrowUp",dx:0,dy:-kr},{id:"svge.nudge.down",combo:"ArrowDown",dx:0,dy:kr},{id:"svge.nudge.left",combo:"ArrowLeft",dx:-kr,dy:0},{id:"svge.nudge.right",combo:"ArrowRight",dx:kr,dy:0},{id:"svge.nudge.up.large",combo:"Shift+ArrowUp",dx:0,dy:-xr},{id:"svge.nudge.down.large",combo:"Shift+ArrowDown",dx:0,dy:xr},{id:"svge.nudge.left.large",combo:"Shift+ArrowLeft",dx:-xr,dy:0},{id:"svge.nudge.right.large",combo:"Shift+ArrowRight",dx:xr,dy:0}];for(const i of o)r.track(e.register({id:i.id,combo:i.combo,description:`Nudge selection ${i.combo}`,run:(a,l)=>{a.preventDefault(),n(l,i.dx,i.dy)}}))}},Ci="data-node-id";function Dr(r){let e=r;for(;e!==null;){const t=e.getAttribute(Ci);if(t!==null)return Wr(t);e=e.parentElement}return null}function Oi(r){const e=r.target;return e instanceof Element?Dr(e):null}function so(r,e){const t=r.target;return t instanceof Element?ao(t,e):null}function ao(r,e){if(r===null)return null;if(e.mode==="deep")return Dr(r);const t=e.isolationRootId??e.rootId,n=Ni(r);if(n.length===0)return null;const o=n.indexOf(t);if(o===-1)return null;if(o===0)return t;const i=e.isTransparentContainer;if(i===void 0)return n[o-1]??null;for(let a=o-1;a>=0;a--){const l=n[a];if(!i(l))return l}return n[0]??null}function Ni(r){const e=[];let t=r;for(;t!==null;){const n=t.getAttribute(Ci);n!==null&&e.push(Wr(n)),t=t.parentElement}return e}function lo(r){return e=>{const t=T(r,e);return t!==null&&(zt(t)||$e(t))}}const Li=4,gh="path, rect, circle, ellipse, line, polygon, polyline";function ph(r){return typeof r.isPointInFill=="function"&&typeof r.isPointInStroke=="function"&&typeof r.getScreenCTM=="function"}function $i(r,e,t,n=Li){const o=r.querySelectorAll(gh);for(let i=o.length-1;i>=0;i--){const a=o[i];if(ph(a)&&fh(r,a,e,t,n))return a}return null}function fh(r,e,t,n,o){const i=e.getScreenCTM();if(i===null)return!1;const a=i.inverse(),l=(g,v)=>{const p=mh(r,a,g,v);return e.isPointInFill(p)||e.isPointInStroke(p)};if(l(t,n))return!0;if(o<=0)return!1;const c=o,u=c*.70710678,h=[[c,0],[-c,0],[0,c],[0,-c],[u,u],[u,-u],[-u,u],[-u,-u]];for(const[g,v]of h)if(l(t+g,n+v))return!0;return!1}function mh(r,e,t,n){const o=r.createSVGPoint();return o.x=t,o.y=n,o.matrixTransform(e)}const Tn=["tl","tc","tr","ml","mc","mr","bl","bc","br"];function Ie(r,e){const t=r.x,n=r.x+r.width/2,o=r.x+r.width,i=r.y,a=r.y+r.height/2,l=r.y+r.height;switch(e){case"tl":return{x:t,y:i};case"tc":return{x:n,y:i};case"tr":return{x:o,y:i};case"ml":return{x:t,y:a};case"mc":return{x:n,y:a};case"mr":return{x:o,y:a};case"bl":return{x:t,y:l};case"bc":return{x:n,y:l};case"br":return{x:o,y:l}}}function ce(r){return{tl:Ie(r,"tl"),tc:Ie(r,"tc"),tr:Ie(r,"tr"),ml:Ie(r,"ml"),mc:Ie(r,"mc"),mr:Ie(r,"mr"),bl:Ie(r,"bl"),bc:Ie(r,"bc"),br:Ie(r,"br")}}function vh(r,e,t){if(!(t>0))return null;let n=null,o=t*t;for(const i of Tn){const a=Ie(r,i),l=a.x-e.x,c=a.y-e.y,u=l*l+c*c;u<=o&&(o=u,n=i)}return n}function Xt(r,e){return r.querySelector(`[data-node-id="${e}"]`)}function ke(r,e){const t=Xt(r,e);return t===null?null:bh(t,r)}function yh(r,e){const t=Xt(r,e);if(t===null)return null;let n;try{n=t.getBBox()}catch{return null}if(!Number.isFinite(n.x)||!Number.isFinite(n.y)||!Number.isFinite(n.width)||!Number.isFinite(n.height)||n.width===0&&n.height===0)return null;const o=di(t.getAttribute("transform")),i=[{x:n.x,y:n.y},{x:n.x+n.width,y:n.y},{x:n.x+n.width,y:n.y+n.height},{x:n.x,y:n.y+n.height}];let a=1/0,l=1/0,c=-1/0,u=-1/0;for(const h of i){const g=K(o,h.x,h.y);g.x<a&&(a=g.x),g.y<l&&(l=g.y),g.x>c&&(c=g.x),g.y>u&&(u=g.y)}return X(a,l,c-a,u-l)}function Rn(r,e){const t=Xt(r,e);if(t===null)return null;let n;try{n=t.getBBox()}catch{return null}if(!Number.isFinite(n.x)||!Number.isFinite(n.y)||!Number.isFinite(n.width)||!Number.isFinite(n.height)||n.width===0&&n.height===0)return null;const o=co(t,r);return o===null?null:{localBBox:X(n.x,n.y,n.width,n.height),matrix:o}}function Sr(r,e){let t=1/0,n=1/0,o=-1/0,i=-1/0,a=!1;for(const l of e){const c=ke(r,l);c!==null&&(a=!0,t=Math.min(t,c.x),n=Math.min(n,c.y),o=Math.max(o,c.x+c.width),i=Math.max(i,c.y+c.height))}return a?X(t,n,o-t,i-n):null}function bh(r,e){let t;try{t=r.getBBox()}catch{return null}if(!Number.isFinite(t.x)||!Number.isFinite(t.y)||!Number.isFinite(t.width)||!Number.isFinite(t.height)||t.width===0&&t.height===0)return null;const n=co(r,e);if(n===null)return null;const o=[{x:t.x,y:t.y},{x:t.x+t.width,y:t.y},{x:t.x+t.width,y:t.y+t.height},{x:t.x,y:t.y+t.height}];let i=1/0,a=1/0,l=-1/0,c=-1/0;for(const u of o){const h=K(n,u.x,u.y);h.x<i&&(i=h.x),h.y<a&&(a=h.y),h.x>l&&(l=h.x),h.y>c&&(c=h.y)}return X(i,a,l-i,c-a)}function yt(r,e){const t=Xt(r,e);if(t===null)return null;const n=t.parentElement;return n===null||n.isSameNode(r)?null:co(n,r)}function co(r,e){let t=Kr,n=r;for(;n!==null&&n!==e;){const o=n.getAttribute("transform"),i=di(o);t=ee(i,t),n=n.parentElement}return n!==e?null:t}function wh(r){const[e,t,n,o]=r,i=1e-9;return Math.abs(e-1)<i&&Math.abs(t)<i&&Math.abs(n)<i&&Math.abs(o-1)<i}const Ih=.5;class Ue{selection=f(k);state=f(S);bus=f(M);layers=f(ne);viewport=f(A);_customPivots=b(new Map,...ngDevMode?[{debugName:"_customPivots"}]:[]);_multiPivotAbs=b(null,...ngDevMode?[{debugName:"_multiPivotAbs"}]:[]);_lastMultiSignature=b("",...ngDevMode?[{debugName:"_lastMultiSignature"}]:[]);_dragState=b(null,...ngDevMode?[{debugName:"_dragState"}]:[]);customPivots=this._customPivots.asReadonly();dragState=this._dragState.asReadonly();isDragging=m(()=>this._dragState()!==null,...ngDevMode?[{debugName:"isDragging"}]:[]);pivotMode=m(()=>{const e=this.selection.count();return e===0?"none":e===1?"single":"multi"},...ngDevMode?[{debugName:"pivotMode"}]:[]);syncPivotForSelection(){const e=this.selection.selectedIds(),t=kh(e);t!==this._lastMultiSignature()&&(this._lastMultiSignature.set(t),this._multiPivotAbs.set(null))}resolvePivot(e){const t=this.pivotMode();if(t==="none")return{x:e.x+e.width/2,y:e.y+e.height/2};if(t==="single"){const o=this.localPivotForFocus();return o===null?{x:e.x+e.width/2,y:e.y+e.height/2}:Bi(o,e)}const n=this._multiPivotAbs();return n===null?{x:e.x+e.width/2,y:e.y+e.height/2}:this.previewMultiPivot(n)}previewMultiPivot(e){const t=this._dragState();return t===null?e:t.kind==="move"&&t.extraNodes!==void 0?{x:e.x+t.currentDelta.x,y:e.y+t.currentDelta.y}:t.kind==="resize-many"?{x:t.anchor.x+(e.x-t.anchor.x)*t.currentScale.sx,y:t.anchor.y+(e.y-t.anchor.y)*t.currentScale.sy}:e}setPivot(e,t){if(this.pivotMode()==="multi"){this._multiPivotAbs.set({x:e.x,y:e.y});return}this.storeLocalPivot(go(e,t))}setPivotAnchor(e,t){const n=ce(t)[e];this.setPivot(n,t)}setPivotAnchorForNode(e,t,n){const o=ce(n)[t],i=go(o,n),a=new Map(this._customPivots());a.set(e,i),this._customPivots.set(a)}resolvePivotForNode(e,t,n){const o=this._customPivots().get(e)??{x:.5,y:.5},i=Bi(o,t);return K(n,i.x,i.y)}setPivotDocForNode(e,t,n,o){let i;try{i=Gt(o)}catch{return}const a=K(i,t.x,t.y),l=go(a,n),c=new Map(this._customPivots());c.set(e,l),this._customPivots.set(c)}setPivotFractionForNode(e,t){const n=new Map(this._customPivots());n.set(e,t),this._customPivots.set(n)}clearPivotForNode(e){if(!this._customPivots().has(e))return;const t=new Map(this._customPivots());t.delete(e),this._customPivots.set(t)}resetPivot(){const e=this.pivotMode();if(e==="single"){const t=this.selection.focusId();if(t===null)return;const n=new Map(this._customPivots());n.delete(t),this._customPivots.set(n)}else e==="multi"&&this._multiPivotAbs.set(null)}clearAllPivots(){this._customPivots.set(new Map),this._multiPivotAbs.set(null),this._lastMultiSignature.set("")}startMove(e,t){if(this._dragState()!==null||this.layers.isLocked(e))return;const n=T(this.state.document().root,e);n!==null&&this._dragState.set({kind:"move",nodeId:e,startTransform:n.transform,startPoint:t,currentDelta:{x:0,y:0}})}startMoveMany(e,t){if(this._dragState()!==null)return;const n=e.filter(u=>!this.layers.isLocked(u));if(n.length===0)return;if(n.length===1){this.startMove(n[0],t);return}const o=this.state.document().root,i=this.selection.focusId(),a=i!==null&&n.includes(i)?i:n[0],l=T(o,a);if(l===null)return;const c=[];for(const u of n){if(u===a)continue;const h=T(o,u);h!==null&&c.push({id:u,startTransform:h.transform})}this._dragState.set({kind:"move",nodeId:a,startTransform:l.transform,startPoint:t,currentDelta:{x:0,y:0},extraNodes:c})}updateMove(e){const t=this._dragState();if(t===null||t.kind!=="move")return;const n=e.x-t.startPoint.x,o=e.y-t.startPoint.y;if(this.applyPreviewTransform(t.nodeId,ee(mr(n,o),t.startTransform)),t.extraNodes!==void 0)for(const i of t.extraNodes)this.applyPreviewTransform(i.id,ee(mr(n,o),i.startTransform));t.currentDelta={x:n,y:o}}endMove(){const e=this._dragState();if(e===null||e.kind!=="move")return;const{nodeId:t,startTransform:n,currentDelta:o,extraNodes:i}=e;if(this._dragState.set(null),this.applyPreviewTransform(t,n),i!==void 0)for(const l of i)this.applyPreviewTransform(l.id,l.startTransform);const a=Ih/Math.max(this.viewport.displayScale(),1e-6);if(!(Math.abs(o.x)<a&&Math.abs(o.y)<a)){if(i!==void 0&&i.length>0){const l=this._multiPivotAbs();l!==null&&this._multiPivotAbs.set({x:l.x+o.x,y:l.y+o.y})}if(i!==void 0&&i.length>0){const l=new Map;l.set(t,{x:o.x,y:o.y});for(const c of i)l.set(c.id,{x:o.x,y:o.y});this.bus.dispatch(new Ur(l,`Move ${l.size} nodes`))}else this.bus.dispatch(new Vd(t,o.x,o.y))}}startRotate(e,t,n){if(this._dragState()!==null||this.layers.isLocked(e))return;const o=T(this.state.document().root,e);o!==null&&this._dragState.set({kind:"rotate",nodeId:e,startTransform:o.transform,pivot:t,startPoint:n,currentAngleRad:0})}updateRotate(e){const t=this._dragState();if(t===null||t.kind!=="rotate")return;const n=Math.atan2(t.startPoint.y-t.pivot.y,t.startPoint.x-t.pivot.x),i=Math.atan2(e.y-t.pivot.y,e.x-t.pivot.x)-n,a=ui(t.startTransform,i,t.pivot);this.applyPreviewTransform(t.nodeId,a),t.currentAngleRad=i}endRotate(){const e=this._dragState();if(e===null||e.kind!=="rotate")return;const{nodeId:t,startTransform:n,pivot:o,currentAngleRad:i}=e;this._dragState.set(null),this.applyPreviewTransform(t,n),!(Math.abs(i)<1e-4)&&this.bus.dispatch(new hi(t,i,o))}startResize(e,t,n,o=null){if(this._dragState()!==null||this.layers.isLocked(e))return;const i=T(this.state.document().root,e);if(i===null)return;const a=ce(n),l=uo[t];this._dragState.set({kind:"resize",nodeId:e,startTransform:i.transform,startNode:i,anchor:a[l],handleStart:a[t],scaleAxes:ho[t],currentScale:{sx:1,sy:1},parentMatrix:o,bakeLocalAnchor:null})}updateResize(e){const t=this._dragState();if(t===null||t.kind!=="resize")return;const{anchor:n,handleStart:o,scaleAxes:i,startNode:a,parentMatrix:l}=t,c=l!==null&&!wh(l);let u=n,h=o,g=e;if(c&&l!==null){let V;try{V=Gt(l)}catch{return}u=K(V,n.x,n.y),h=K(V,o.x,o.y),g=K(V,e.x,e.y)}const v=h.x-u.x,p=h.y-u.y,x=i.x&&v!==0?(g.x-u.x)/v:1,E=i.y&&p!==0?(g.y-u.y)/p:1;if(!Number.isFinite(x)||!Number.isFinite(E))return;const C=c?u:n,Z=zd(a,x,E,C,c?null:l);if(Z!==null)this.applyPreviewNode(t.nodeId,Z);else{const V=Xr(a.transform,x,E,n);this.applyPreviewTransform(t.nodeId,V)}t.currentScale={sx:x,sy:E},t.bakeLocalAnchor=c?C:null}endResize(){const e=this._dragState();if(e===null||e.kind!=="resize")return;const{nodeId:t,startNode:n,anchor:o,currentScale:i,parentMatrix:a,bakeLocalAnchor:l}=e;if(this._dragState.set(null),this.applyPreviewNode(t,n),Math.abs(i.sx-1)<1e-4&&Math.abs(i.sy-1)<1e-4)return;const c=l??o,u=l!==null?null:a;this.bus.dispatch(new gi(t,c,i.sx,i.sy,u))}startResizeObb(e,t,n,o){if(this._dragState()!==null||this.layers.isLocked(e))return;const i=T(this.state.document().root,e);if(i===null)return;let a;try{a=Gt(o)}catch{return}const l=ce(n);this._dragState.set({kind:"resize-obb",nodeId:e,startTransform:i.transform,invMatrix:a,localAnchor:l[uo[t]],localHandle:l[t],scaleAxes:ho[t],currentScale:{sx:1,sy:1}})}updateResizeObb(e){const t=this._dragState();if(t===null||t.kind!=="resize-obb")return;const{invMatrix:n,localAnchor:o,localHandle:i,scaleAxes:a,startTransform:l,nodeId:c}=t,u=K(n,e.x,e.y),h=i.x-o.x,g=i.y-o.y,v=a.x&&h!==0?(u.x-o.x)/h:1,p=a.y&&g!==0?(u.y-o.y)/g:1;if(!Number.isFinite(v)||!Number.isFinite(p))return;const x=ee(l,Xr(mr(0,0),v,p,o));this.applyPreviewTransform(c,x),t.currentScale={sx:v,sy:p}}endResizeObb(){const e=this._dragState();if(e===null||e.kind!=="resize-obb")return;const{nodeId:t,startTransform:n,localAnchor:o,currentScale:i}=e;this._dragState.set(null),this.applyPreviewTransform(t,n),!(Math.abs(i.sx-1)<1e-4&&Math.abs(i.sy-1)<1e-4)&&this.bus.dispatch(new gi(t,o,i.sx,i.sy,null,!0))}startResizeMany(e,t,n){if(this._dragState()!==null)return;const o=this.state.document().root,i=[];for(const l of e){if(this.layers.isLocked(l.id))continue;const c=T(o,l.id);c!==null&&i.push({id:l.id,startTransform:c.transform,parentMatrix:l.parentMatrix})}if(i.length<2)return;const a=ce(n);this._dragState.set({kind:"resize-many",entries:i,anchor:a[uo[t]],handleStart:a[t],scaleAxes:ho[t],currentScale:{sx:1,sy:1}})}updateResizeMany(e){const t=this._dragState();if(t===null||t.kind!=="resize-many")return;const{anchor:n,handleStart:o,scaleAxes:i,entries:a}=t,l=o.x-n.x,c=o.y-n.y,u=i.x&&l!==0?(e.x-n.x)/l:1,h=i.y&&c!==0?(e.y-n.y)/c:1;if(!Number.isFinite(u)||!Number.isFinite(h))return;const g=Xr([1,0,0,1,0,0],u,h,n);for(const v of a){let p;if(v.parentMatrix===null)p=ee(g,v.startTransform);else try{const x=Gt(v.parentMatrix);p=ee(x,ee(g,ee(v.parentMatrix,v.startTransform)))}catch{p=ee(g,v.startTransform)}this.applyPreviewTransform(v.id,p)}t.currentScale={sx:u,sy:h}}endResizeMany(){const e=this._dragState();if(e===null||e.kind!=="resize-many")return;const{entries:t,anchor:n,currentScale:o}=e;this._dragState.set(null);for(const l of t)this.applyPreviewTransform(l.id,l.startTransform);if(Math.abs(o.sx-1)<1e-4&&Math.abs(o.sy-1)<1e-4)return;const i=this._multiPivotAbs();i!==null&&this._multiPivotAbs.set({x:n.x+(i.x-n.x)*o.sx,y:n.y+(i.y-n.y)*o.sy});const a=t.map(l=>({id:l.id,parentMatrix:l.parentMatrix}));this.bus.dispatch(new Gd(a,n,o.sx,o.sy))}startRotateMany(e,t,n){if(this._dragState()!==null)return;const o=this.state.document().root,i=[];for(const a of e){if(this.layers.isLocked(a.id))continue;const l=T(o,a.id);l!==null&&i.push({id:a.id,startTransform:l.transform,parentMatrix:a.parentMatrix})}i.length<2||(this._multiPivotAbs()===null&&this._multiPivotAbs.set({x:t.x,y:t.y}),this._dragState.set({kind:"rotate-many",entries:i,pivot:t,startPoint:n,currentAngleRad:0}))}updateRotateMany(e){const t=this._dragState();if(t===null||t.kind!=="rotate-many")return;const{pivot:n,startPoint:o,entries:i}=t,a=Math.atan2(o.y-n.y,o.x-n.x),c=Math.atan2(e.y-n.y,e.x-n.x)-a;if(!Number.isFinite(c))return;const u=ui([1,0,0,1,0,0],c,n);for(const h of i){let g;if(h.parentMatrix===null)g=ee(u,h.startTransform);else try{const v=Gt(h.parentMatrix);g=ee(v,ee(u,ee(h.parentMatrix,h.startTransform)))}catch{g=ee(u,h.startTransform)}this.applyPreviewTransform(h.id,g)}t.currentAngleRad=c}endRotateMany(){const e=this._dragState();if(e===null||e.kind!=="rotate-many")return;const{entries:t,pivot:n,currentAngleRad:o}=e;this._dragState.set(null);for(const a of t)this.applyPreviewTransform(a.id,a.startTransform);if(Math.abs(o)<1e-4)return;const i=t.map(a=>({id:a.id,parentMatrix:a.parentMatrix}));this.bus.dispatch(new pi(i,n,o))}cancelGesture(){const e=this._dragState();if(e!==null){if(e.kind==="resize")this.applyPreviewNode(e.nodeId,e.startNode);else if(e.kind==="resize-many"||e.kind==="rotate-many")for(const t of e.entries)this.applyPreviewTransform(t.id,t.startTransform);else if(this.applyPreviewTransform(e.nodeId,e.startTransform),e.kind==="move"&&e.extraNodes!==void 0)for(const t of e.extraNodes)this.applyPreviewTransform(t.id,t.startTransform);this._dragState.set(null)}}applyPreviewNode(e,t){const n=this.state.document(),o=fi(n.root,e,()=>t);o!==n.root&&this.state.setDocument({...n,root:o})}applyPreviewTransform(e,t){const n=this.state.document(),o=fi(n.root,e,i=>({...i,transform:t}));o!==n.root&&this.state.setDocument({...n,root:o})}storeLocalPivot(e){if(this.pivotMode()!=="single")return;const t=this.selection.focusId();if(t===null)return;const n=new Map(this._customPivots());n.set(t,e),this._customPivots.set(n)}localPivotForFocus(){const e=this.selection.focusId();return e===null?null:this._customPivots().get(e)??null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ue,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ue,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ue,decorators:[{type:D,args:[{providedIn:"root"}]}]});const uo={tl:"br",tc:"bc",tr:"bl",ml:"mr",mr:"ml",bl:"tr",bc:"tc",br:"tl"},ho={tl:{x:!0,y:!0},tr:{x:!0,y:!0},bl:{x:!0,y:!0},br:{x:!0,y:!0},tc:{x:!1,y:!0},bc:{x:!1,y:!0},ml:{x:!0,y:!1},mr:{x:!0,y:!1}};function kh(r){return r.size===0?"":Array.from(r).sort().join("|")}function go(r,e){return e.width===0||e.height===0?{x:.5,y:.5}:{x:(r.x-e.x)/e.width,y:(r.y-e.y)/e.height}}function Bi(r,e){return{x:e.x+r.x*e.width,y:e.y+r.y*e.height}}function An(r,e){const t=T(r,e);if(t===null)return Kr;let n=t.transform,o=t.id,i=1e3;for(;i-- >0;){const a=ft(r,o);if(a===null)break;n=ee(a.transform,n),o=a.id}return n}function H(r){const e=r.target;if(!(e instanceof Element))return;const t=e;if(typeof t.setPointerCapture=="function")try{t.setPointerCapture(r.pointerId)}catch{}}function pe(r){const e=r.target;if(!(e instanceof Element))return;const t=e;if(typeof t.releasePointerCapture=="function")try{t.releasePointerCapture(r.pointerId)}catch{}}function po(r){if(r===null||!(r instanceof HTMLElement))return!1;const e=r.tagName;return!!(e==="INPUT"||e==="TEXTAREA"||e==="SELECT"||r.isContentEditable)}class be{selection=f(k);_raw=b(null,...ngDevMode?[{debugName:"_raw"}]:[]);keyObjectId=m(()=>{const e=this._raw();return e===null?null:this.selection.selectedIds().has(e)?e:null},...ngDevMode?[{debugName:"keyObjectId"}]:[]);constructor(){J(()=>{const e=this._raw();e!==null&&!this.selection.selectedIds().has(e)&&this._raw.set(null)})}hasKeyObject=m(()=>this.keyObjectId()!==null,...ngDevMode?[{debugName:"hasKeyObject"}]:[]);setKeyObject(e){this._raw.set(e)}clear(){this._raw.set(null)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:be,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:be,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:be,decorators:[{type:D,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});const fo={small:6,medium:8,large:11},Fi=4,ji=24,bt=fo.medium,Vi="svge:selection:handle-size";class en{_handleSizePx=b(xh(),...ngDevMode?[{debugName:"_handleSizePx"}]:[]);handleSizePx=this._handleSizePx.asReadonly();setHandleSize(e){const t=mo(e);t!==this._handleSizePx()&&(this._handleSizePx.set(t),Dh(t))}setPreset(e){this.setHandleSize(fo[e])}reset(){this.setHandleSize(bt)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:en,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:en,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:en,decorators:[{type:D,args:[{providedIn:"root"}]}]});function mo(r){return Number.isFinite(r)?Math.min(ji,Math.max(Fi,Math.round(r))):bt}function xh(){if(typeof localStorage>"u")return bt;try{const r=localStorage.getItem(Vi);if(r===null)return bt;const e=Number.parseFloat(r);return Number.isFinite(e)?mo(e):bt}catch{return bt}}function Dh(r){if(!(typeof localStorage>"u"))try{localStorage.setItem(Vi,String(r))}catch{}}class Ae{_items=b([],...ngDevMode?[{debugName:"_items"}]:[]);items=this._items.asReadonly();register(e){if(typeof e.id!="string"||e.id.length===0)throw new Error(`${this.constructor.name}.register: item.id must be a non-empty string`);if(this._items().some(t=>t.id===e.id))throw new Error(`${this.constructor.name}.register: item "${e.id}" is already registered`);return this._items.set([...this._items(),e]),{dispose:()=>{this._items.set(this._items().filter(t=>t.id!==e.id))}}}get(e){return this._items().find(t=>t.id===e)??null}update(e,t){if(t.id!==e)throw new Error(`${this.constructor.name}.update: replacement.id "${t.id}" must match target id "${e}"`);const n=this._items(),o=n.findIndex(a=>a.id===e);if(o<0)return!1;const i=n.slice();return i[o]=t,this._items.set(i),!0}byCategory(e){return this._items().filter(t=>t.category===e)}categories(){const e=new Set;for(const t of this._items())t.category!==void 0&&e.add(t.category);return[...e]}}class xt extends Ae{static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:xt,deps:null,target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:xt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:xt,decorators:[{type:D,args:[{providedIn:"root"}]}]});class Dt{_selectedBrushId=b(null,...ngDevMode?[{debugName:"_selectedBrushId"}]:[]);selectedBrushId=this._selectedBrushId.asReadonly();select(e){this._selectedBrushId.set(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Dt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Dt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Dt,decorators:[{type:D,args:[{providedIn:"root"}]}]});function vo(r,e,t){const n=r.length;if(n<2||e<=0)return"";const o=new Array(n).fill(0);for(let g=1;g<n;g++){const v=r[g].x-r[g-1].x,p=r[g].y-r[g-1].y;o[g]=o[g-1]+Math.hypot(v,p)}const i=o[n-1];if(i<1e-9)return"";const a=[];let l={x:1,y:0};for(let g=0;g<n;g++){const v=g>0?r[g].x-r[g-1].x:0,p=g>0?r[g].y-r[g-1].y:0,x=g<n-1?r[g+1].x-r[g].x:0,E=g<n-1?r[g+1].y-r[g].y:0,C=v+x,G=p+E,Z=Math.hypot(C,G);let V;Z<1e-9?V=l:(V={x:C/Z,y:G/Z},l=V),a.push({x:-V.y,y:V.x})}const c=[],u=[];for(let g=0;g<n;g++){const v=i>0?o[g]/i:0,p=zi(t,v),x=e*p/2,E=r[g],C=a[g].x,G=a[g].y;c.push({x:E.x+C*x,y:E.y+G*x}),u.push({x:E.x-C*x,y:E.y-G*x})}const h=[`M${Yt(c[0].x)} ${Yt(c[0].y)}`];for(let g=1;g<n;g++)h.push(`L${Yt(c[g].x)} ${Yt(c[g].y)}`);for(let g=n-1;g>=0;g--)h.push(`L${Yt(u[g].x)} ${Yt(u[g].y)}`);return h.push("Z"),h.join(" ")}function zi(r,e){if(r.length===0)return 1;if(r.length===1)return r[0];const n=Math.max(0,Math.min(1,e))*(r.length-1),o=Math.floor(n),i=Math.min(r.length-1,o+1),a=n-o,l=r[o],c=r[i];return l+(c-l)*a}function Yt(r){const e=Math.round(r*100)/100;return String(Object.is(e,-0)?0:e)}const yo=new gt("ACTIVE_PAGE_STORAGE_KEY",{providedIn:"root",factory:()=>"svge:activePage"});class We{state=f(S);pages=m(()=>this.state.document().root.children.filter(t=>$e(t)),...ngDevMode?[{debugName:"pages"}]:[]);count=m(()=>this.pages().length,...ngDevMode?[{debugName:"count"}]:[]);hasPages=m(()=>this.count()>0,...ngDevMode?[{debugName:"hasPages"}]:[]);byId(e){return this.pages().find(t=>t.id===e)??null}nameOf(e){const t=this.byId(e);return t===null?"":mi(t)}viewBoxOf(e){const t=this.byId(e);return t===null?null:Be(t)??this.state.document().viewBox}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:We,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:We,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:We,decorators:[{type:D,args:[{providedIn:"root"}]}]});class j{pages=f(We);state=f(S);selection=f(k,{optional:!0});storageKey=f(yo);document=f(re);_activePageId=b(null,...ngDevMode?[{debugName:"_activePageId"}]:[]);activePageId=this._activePageId.asReadonly();activePage=m(()=>{const e=this._activePageId();return e===null?null:this.pages.byId(e)},...ngDevMode?[{debugName:"activePage"}]:[]);activePageViewBox=m(()=>{const e=this.activePage();return e===null?null:Be(e)},...ngDevMode?[{debugName:"activePageViewBox"}]:[]);lastActiveSeen=null;constructor(){const e=this.readPersistedId();e!==null&&this._activePageId.set(e),this.lastActiveSeen=this._activePageId(),J(()=>{const t=this.pages.pages(),n=this._activePageId();if(t.length===0){n!==null&&this._activePageId.set(null);return}n!==null&&t.some(i=>i.id===n)||this._activePageId.set(t[0].id)}),J(()=>{const t=this._activePageId(),n=this.lastActiveSeen;this.lastActiveSeen=t,this.persistId(t),n!==null&&t!==n&&this.selection!==null&&this.selection.clear()})}setActive(e){this._activePageId.set(e)}treeForRendering=m(()=>{const e=this.activePage();return e!==null?e:this.state.document().root},...ngDevMode?[{debugName:"treeForRendering"}]:[]);viewBoxForRendering=m(()=>{const e=this.activePageViewBox();return e!==null?e:this.state.document().viewBox},...ngDevMode?[{debugName:"viewBoxForRendering"}]:[]);effectiveDrawTargetId=m(()=>{const e=this.activePage();return e!==null?e.id:this.state.document().root.id},...ngDevMode?[{debugName:"effectiveDrawTargetId"}]:[]);effectiveExportDoc(e){const t=this.activePage();if(t===null)return e;const n=Be(t),o=Hd(t),i=o!==null?[o,...t.children]:t.children;return{...e,viewBox:n??e.viewBox,root:{...e.root,children:i}}}resolveAutoParent(){return this.effectiveDrawTargetId()}readPersistedId(){const e=this.storageKey;if(e===null||e.length===0)return null;const t=this.window();if(t===null)return null;try{const n=t.localStorage.getItem(e);if(n===null)return null;const o=n.trim();return o.length===0?null:Wr(o)}catch{return null}}persistId(e){const t=this.storageKey;if(t===null||t.length===0)return;const n=this.window();if(n!==null)try{e===null?n.localStorage.removeItem(t):n.localStorage.setItem(t,e)}catch{}}window(){const e=this.document.defaultView;return e!==null?e:typeof window<"u"?window:null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:j,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:j,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:j,decorators:[{type:D,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});class we{_points=b([],...ngDevMode?[{debugName:"_points"}]:[]);_drawing=b(!1,...ngDevMode?[{debugName:"_drawing"}]:[]);points=this._points.asReadonly();drawing=this._drawing.asReadonly();hasDraft=m(()=>this._drawing()&&this._points().length>=2,...ngDevMode?[{debugName:"hasDraft"}]:[]);begin(e){this._points.set([e]),this._drawing.set(!0)}append(e){this._drawing()&&this._points.update(t=>[...t,e])}finish(){const e=this._points();return this._drawing.set(!1),this._points.set([]),e}cancel(){this._drawing.set(!1),this._points.set([])}reset(){this.cancel()}_fill=b("none",...ngDevMode?[{debugName:"_fill"}]:[]);_stroke=b("#000000",...ngDevMode?[{debugName:"_stroke"}]:[]);_strokeWidth=b(2,...ngDevMode?[{debugName:"_strokeWidth"}]:[]);_closePath=b(!1,...ngDevMode?[{debugName:"_closePath"}]:[]);fill=this._fill.asReadonly();stroke=this._stroke.asReadonly();strokeWidth=this._strokeWidth.asReadonly();closePath=this._closePath.asReadonly();setFill(e){this._fill.set(e)}setStroke(e){this._stroke.set(e)}setStrokeWidth(e){this._strokeWidth.set(Math.max(.5,Math.min(100,e)))}setClosePath(e){this._closePath.set(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:we,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:we,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:we,decorators:[{type:D,args:[{providedIn:"root"}]}]});class de{_tools=b([],...ngDevMode?[{debugName:"_tools"}]:[]);tools=this._tools.asReadonly();register(e){if(typeof e.id!="string"||e.id.length===0)throw new Error("ToolRegistry.register: tool.id must be a non-empty string");if(this._tools().some(t=>t.id===e.id))throw new Error(`ToolRegistry.register: tool "${e.id}" is already registered`);return this._tools.set([...this._tools(),e]),{dispose:()=>{this._tools.set(this._tools().filter(t=>t.id!==e.id))}}}get(e){return this._tools().find(t=>t.id===e)??null}getByShortcut(e){return this._tools().find(t=>t.shortcut===e)??null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:de,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:de,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:de,decorators:[{type:D,args:[{providedIn:"root"}]}]});const Je="com.svge.tool.select",xe="com.svge.tool.direct-select",Gi="com.svge.tool.pencil",Pr="com.svge.tool.page";class Sh{id=Je;label="Select";icon="near_me";cursor="default";shortcut="v"}class Ph{id=xe;label="Direct Select";icon="ads_click";cursor="default";shortcut="a"}class Mh{id=Gi;label="Pencil";icon="edit";cursor="crosshair";shortcut="p";onActivate(e){e.injector.get(k).clear(),e.injector.get(we).reset()}onDeactivate(e){e.injector.get(we).reset()}onPointerDown(e,t){t.injector.get(we).begin(e.docPoint)}onPointerMove(e,t){t.injector.get(we).append(e.docPoint)}onPointerUp(e,t){const n=t.injector.get(we);if(!n.drawing())return;const o=n.finish();if(o.length<2)return;const a=t.injector.get(Dt).selectedBrushId();if(a!==null){const u=t.injector.get(xt).get(a);if(u!==null){const h=u.baseWidth??8,g=vo(o,h,u.widthProfile);if(g.length>0){const v=N(g,{style:{fill:"#000000",stroke:"none"}});t.injector.get(M).dispatch(new he(te,v));return}}}const l=bo(o)+(n.closePath()?" Z":""),c=N(l,{style:{fill:n.fill(),stroke:n.stroke(),strokeWidth:n.strokeWidth()}});t.injector.get(M).dispatch(new he(te,c))}onPointerCancel(e,t){t.injector.get(we).cancel()}}const Hi={id:"com.svge.tools.select",name:"Select Tools (builtin)",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(de);r.track(e.register(new Sh)),r.track(e.register(new Ph))}};class _h{id=Pr;label="Page";icon="aspect_ratio";cursor="default";shortcut="shift+o";onActivate(e){const n=e.injector.get(j,{optional:!0})?.activePage()??null;n!==null&&e.injector.get(k).select(n.id)}onDeactivate(e){const t=e.injector.get(j,{optional:!0})?.activePage()??null;if(t===null)return;const n=e.injector.get(k);n.focusId()===t.id&&n.clear()}}const Ui={id:"com.svge.tools.page",name:"Page Tool (builtin)",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(de);r.track(e.register(new _h))}},Wi={id:"com.svge.tools.pencil",name:"Pencil Tool (builtin)",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(de);r.track(e.register(new Mh))}};function bo(r){if(r.length===0)return"";const e=[];for(let t=0;t<r.length;t++){const n=r[t];e.push(`${t===0?"M":"L"}${n.x.toFixed(1)} ${n.y.toFixed(1)}`)}return e.join(" ")}class Se{registry=f(de);injector=f(Vt);_activeId=b(null,...ngDevMode?[{debugName:"_activeId"}]:[]);activeId=this._activeId.asReadonly();activeTool=m(()=>{const e=this._activeId();return e===null?null:this.registry.get(e)},...ngDevMode?[{debugName:"activeTool"}]:[]);activate(e){const t=this.registry.get(e);if(t===null)throw new Error(`ToolHostService.activate: no tool registered with id "${e}"`);if(this._activeId()===e)return;const n=this.makeContext(),o=this.activeTool();o?.onDeactivate&&o.onDeactivate(n),this._activeId.set(e),t.onActivate&&t.onActivate(n)}deactivate(){const e=this.activeTool();e!==null&&(e.onDeactivate&&e.onDeactivate(this.makeContext()),this._activeId.set(null))}routePointerDown(e){const t=this.activeTool();t?.onPointerDown&&t.onPointerDown(e,this.makeContext())}routePointerMove(e){const t=this.activeTool();t?.onPointerMove&&t.onPointerMove(e,this.makeContext())}routePointerUp(e){const t=this.activeTool();t?.onPointerUp&&t.onPointerUp(e,this.makeContext())}routePointerCancel(e){const t=this.activeTool();t?.onPointerCancel&&t.onPointerCancel(e,this.makeContext())}routeKeyDown(e){const t=this.activeTool();t?.onKeyDown&&t.onKeyDown(e,this.makeContext())}makeContext(){return{injector:this.injector}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Se,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Se,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Se,decorators:[{type:D,args:[{providedIn:"root"}]}]});const Eh=24,Th="data-svge-handle";class zn{elRef=f(ae);selection=f(k);state=f(S);viewport=f(A);transform=f(Ue);toolHost=f(Se);appearance=f(en);bus=f(M);layers=f(ne);keyObject=f(be);_focusBBox=b(null,...ngDevMode?[{debugName:"_focusBBox"}]:[]);_hoverBBox=b(null,...ngDevMode?[{debugName:"_hoverBBox"}]:[]);_keyBBox=b(null,...ngDevMode?[{debugName:"_keyBBox"}]:[]);_obb=b(null,...ngDevMode?[{debugName:"_obb"}]:[]);keyBBox=this._keyBBox.asReadonly();focusBBox=m(()=>{const e=this.selection.focusId();if(e===null)return this._focusBBox();if(this.layers.hiddenIds().has(e))return null;const t=T(this.state.document().root,e);return t!==null&&t.metadata.visible===!1||t!==null&&$e(t)?null:this._focusBBox()},...ngDevMode?[{debugName:"focusBBox"}]:[]);hoverBBox=m(()=>{const e=this._hoverBBox();if(e===null)return null;const t=this.selection.hoverId();if(t===null)return e;const n=T(this.state.document().root,t);return n!==null&&$e(n)?null:e},...ngDevMode?[{debugName:"hoverBBox"}]:[]);singleSelection=this.selection.isSingleSelection;showsTransformHandles=m(()=>{if(!this.singleSelection())return this.selection.count()>1;if(this.toolHost.activeId()!==xe)return!0;const e=this.selection.focusId();return e===null?!0:Xi(this.state.document().root,e)!=="path"},...ngDevMode?[{debugName:"showsTransformHandles"}]:[]);showsRotationHandle=this.showsTransformHandles;handleSize=m(()=>this.appearance.handleSizePx()/this.viewport.zoom(),...ngDevMode?[{debugName:"handleSize"}]:[]);handleHalf=m(()=>this.handleSize()/2,...ngDevMode?[{debugName:"handleHalf"}]:[]);resizeHandles=m(()=>{const e=this._focusBBox();if(e===null)return[];const t=ce(e);return[{anchor:"tl",...t.tl},{anchor:"tc",...t.tc},{anchor:"tr",...t.tr},{anchor:"ml",...t.ml},{anchor:"mr",...t.mr},{anchor:"bl",...t.bl},{anchor:"bc",...t.bc},{anchor:"br",...t.br}]},...ngDevMode?[{debugName:"resizeHandles"}]:[]);rotationHandlePersistent=m(()=>{if(!this.showsRotationHandle())return null;const e=Eh/this.viewport.zoom(),t=this.obb();if(t!==null){const i=t.matrix,a=ce(t.localBBox).tc,l=K(i,a.x,a.y);let c=-i[2],u=-i[3];const h=Math.hypot(c,u);return h>1e-6&&(c/=h,u/=h),{x:l.x+c*e,y:l.y+u*e,stemX1:l.x,stemY1:l.y}}const n=this.focusBBox();if(n===null)return null;const o=ce(n).tc;return{x:o.x,y:o.y-e,stemX1:o.x,stemY1:o.y}},...ngDevMode?[{debugName:"rotationHandlePersistent"}]:[]);obb=m(()=>{if(!this.singleSelection()||this.focusBBox()===null)return null;const e=this._obb();return e===null||Ud(e.matrix)?null:e},...ngDevMode?[{debugName:"obb"}]:[]);obbTransform=m(()=>{const e=this.obb();if(e===null)return null;const t=e.matrix;return`matrix(${t[0]} ${t[1]} ${t[2]} ${t[3]} ${t[4]} ${t[5]})`},...ngDevMode?[{debugName:"obbTransform"}]:[]);obbAngleDeg=m(()=>{const e=this.obb();return e===null?0:Math.atan2(e.matrix[1],e.matrix[0])*180/Math.PI},...ngDevMode?[{debugName:"obbAngleDeg"}]:[]);obbResizeHandlesDoc=m(()=>{const e=this.obb();if(e===null)return[];const t=ce(e.localBBox);return["tl","tc","tr","ml","mr","bl","bc","br"].map(o=>{const i=K(e.matrix,t[o].x,t[o].y);return{anchor:o,x:i.x,y:i.y}})},...ngDevMode?[{debugName:"obbResizeHandlesDoc"}]:[]);obbHandleTransform(e,t){return`rotate(${this.obbAngleDeg()} ${e} ${t})`}constructor(){pr({read:()=>this.recomputeBBoxes()}),typeof document<"u"&&document.fonts!==void 0&&document.fonts.ready.then(()=>{this.recomputeBBoxes()})}onResizeHandlePointerDown(e,t){const n=this.obb();if(n!==null){const c=this.selection.focusId();if(c===null)return;this.transform.startResizeObb(c,t,n.localBBox,n.matrix),H(e),e.stopPropagation();return}const o=this._focusBBox();if(o===null)return;const i=this.elRef.nativeElement.ownerSVGElement;if(this.selection.count()>1){const c=Array.from(this.selection.selectedIds()).map(u=>({id:u,parentMatrix:i===null?null:yt(i,u)}));this.transform.startResizeMany(c,t,o),H(e),e.stopPropagation();return}const a=this.selection.focusId();if(a===null)return;const l=i===null?null:yt(i,a);this.transform.startResize(a,t,o,l),H(e),e.stopPropagation()}onRotationHandlePointerDown(e){const t=this._focusBBox();if(t===null)return;const n=this.screenToDoc(e.clientX,e.clientY);if(n===null)return;const o=this.elRef.nativeElement.ownerSVGElement;if(this.selection.count()>1){const c=this.transform.resolvePivot(t),u=Array.from(this.selection.selectedIds()).map(h=>({id:h,parentMatrix:o===null?null:yt(o,h)}));this.transform.startRotateMany(u,c,n),H(e),e.stopPropagation();return}const i=this.selection.focusId();if(i===null)return;const a=o===null?null:Rn(o,i),l=a!==null?this.transform.resolvePivotForNode(i,a.localBBox,a.matrix):this.transform.resolvePivot(t);this.transform.startRotate(i,l,n),H(e),e.stopPropagation()}onResizeHandleKeyDown(e,t){const n=e.shiftKey?10:1;let o=0,i=0;switch(e.key){case"ArrowLeft":o=-n;break;case"ArrowRight":o=n;break;case"ArrowUp":i=-n;break;case"ArrowDown":i=n;break;default:return}e.preventDefault(),e.stopPropagation();const a=this.obb();if(a!==null){const x=this.selection.focusId();if(x===null)return;const E=ce(a.localBBox)[t],C=K(a.matrix,E.x+o,E.y+i);this.transform.startResizeObb(x,t,a.localBBox,a.matrix),this.transform.updateResizeObb(C),this.transform.endResizeObb();return}const l=this._focusBBox();if(l===null)return;const c=this.elRef.nativeElement.ownerSVGElement,h=ce(l)[t],g={x:h.x+o,y:h.y+i};if(this.selection.count()>1){const x=Array.from(this.selection.selectedIds()).map(E=>({id:E,parentMatrix:c===null?null:yt(c,E)}));this.transform.startResizeMany(x,t,l),this.transform.updateResizeMany(g),this.transform.endResizeMany();return}const v=this.selection.focusId();if(v===null)return;const p=c===null?null:yt(c,v);this.transform.startResize(v,t,l,p),this.transform.updateResize(g),this.transform.endResize()}onRotationHandleKeyDown(e){const t=e.shiftKey?15:1;let n;switch(e.key){case"ArrowLeft":n=-t;break;case"ArrowRight":n=t;break;default:return}e.preventDefault(),e.stopPropagation();const o=this._focusBBox();if(o===null)return;const i=n*Math.PI/180,a=this.elRef.nativeElement.ownerSVGElement;if(this.selection.count()>1){const h=this.transform.resolvePivot(o),g=Array.from(this.selection.selectedIds()).map(v=>({id:v,parentMatrix:a===null?null:yt(a,v)}));this.bus.dispatch(new pi(g,h,i));return}const l=this.selection.focusId();if(l===null)return;const c=a===null?null:Rn(a,l),u=c!==null?this.transform.resolvePivotForNode(l,c.localBBox,c.matrix):this.transform.resolvePivot(o);this.bus.dispatch(new hi(l,i,u))}anchorLabel(e){return{tl:"top-left corner",tc:"top-center",tr:"top-right corner",ml:"middle-left",mr:"middle-right",bl:"bottom-left corner",bc:"bottom-center",br:"bottom-right corner"}[e]}onHandlePointerMove(e){const t=this.transform.dragState();if(t===null)return;const n=this.screenToDoc(e.clientX,e.clientY);n!==null&&(t.kind==="resize"?this.transform.updateResize(n):t.kind==="resize-obb"?this.transform.updateResizeObb(n):t.kind==="resize-many"?this.transform.updateResizeMany(n):t.kind==="rotate"?this.transform.updateRotate(n):t.kind==="rotate-many"&&this.transform.updateRotateMany(n))}onHandlePointerUp(e){const t=this.transform.dragState();t!==null&&(t.kind==="resize"?this.transform.endResize():t.kind==="resize-obb"?this.transform.endResizeObb():t.kind==="resize-many"?this.transform.endResizeMany():t.kind==="rotate"?this.transform.endRotate():t.kind==="rotate-many"&&this.transform.endRotateMany(),pe(e))}recomputeBBoxes(){const e=this.elRef.nativeElement.ownerSVGElement;if(e===null){this.maybeSet(this._focusBBox,null),this.maybeSet(this._hoverBBox,null);return}const t=this.selection.selectedIds(),n=this.selection.focusId(),o=this.selection.hoverId(),i=this.state.document().root;let a=null;if(this.selection.isSingleSelection()&&n!==null){if(a=ke(e,n),a===null){const g=T(i,n);g!==null&&g.type==="text"&&(a=Ch(i,g,n))}}else t.size>1&&(a=Sr(e,t));this.maybeSet(this._focusBBox,a);const l=this.selection.isSingleSelection()&&n!==null?Rn(e,n):null;this.maybeSetObb(this._obb,l);const c=o!==null&&!t.has(o)?ke(e,o):null;this.maybeSet(this._hoverBBox,c);const u=this.keyObject.keyObjectId(),h=u!==null&&t.size>1&&!this.layers.hiddenIds().has(u)?ke(e,u):null;this.maybeSet(this._keyBBox,h)}screenToDoc(e,t){return Ve(this.elRef.nativeElement.ownerSVGElement,e,t)}maybeSet(e,t){const n=e();n!==t&&(n!==null&&t!==null&&Ki(n,t)||e.set(t))}maybeSetObb(e,t){const n=e();n!==t&&(n!==null&&t!==null&&Ah(n,t)||e.set(t))}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:zn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:zn,isStandalone:!0,selector:"g[svgeSelectionOverlay]",host:{attributes:{role:"group","aria-label":"Selection transform handles"}},ngImport:s,template:`
2
+ @if (hoverBBox(); as h) {
3
+ <svg:rect
4
+ class="hover-outline"
5
+ aria-hidden="true"
6
+ [attr.x]="h.x"
7
+ [attr.y]="h.y"
8
+ [attr.width]="h.width"
9
+ [attr.height]="h.height"
10
+ fill="none"
11
+ ></svg:rect>
12
+ }
13
+
14
+ @if (keyBBox(); as k) {
15
+ <svg:rect
16
+ class="key-object"
17
+ aria-hidden="true"
18
+ [attr.x]="k.x"
19
+ [attr.y]="k.y"
20
+ [attr.width]="k.width"
21
+ [attr.height]="k.height"
22
+ fill="none"
23
+ ></svg:rect>
24
+ }
25
+
26
+ <!--
27
+ **D-141 \u2014 oriented (OBB) chrome.** For a single ROTATED node the box +
28
+ handles + rotation stem are drawn in the node's LOCAL frame inside a
29
+ <g matrix="..."> so the whole transform widget rotates WITH the object
30
+ (Illustrator/Figma/Affinity). Resize handles route to the OBB gesture
31
+ (scale along local axes). Non-rotated single + multi-selection keep the
32
+ axis-aligned chrome in the @else if below.
33
+ -->
34
+ @if (obb(); as o) {
35
+ <svg:g [attr.transform]="obbTransform()">
36
+ <svg:rect
37
+ class="bbox"
38
+ aria-hidden="true"
39
+ [attr.x]="o.localBBox.x"
40
+ [attr.y]="o.localBBox.y"
41
+ [attr.width]="o.localBBox.width"
42
+ [attr.height]="o.localBBox.height"
43
+ fill="none"
44
+ ></svg:rect>
45
+ </svg:g>
46
+
47
+ <!--
48
+ D-142-fix3 \u2014 resize handles for the oriented box are drawn in DOCUMENT
49
+ space (NOT inside the <g matrix>) as fixed-size squares positioned at
50
+ the box corners and rotated by the box ANGLE only. Inside the matrix
51
+ group they inherited its scale/skew, so a non-uniformly scaled object
52
+ stretched the handle squares. Doc-space + angle-only keeps them
53
+ pixel-constant and square under any transform (the box outline above
54
+ still rides the matrix, since it must trace the object's real bounds).
55
+ -->
56
+ @if (showsTransformHandles()) {
57
+ @for (h of obbResizeHandlesDoc(); track h.anchor) {
58
+ <svg:rect
59
+ [class]="'handle resize handle-' + h.anchor"
60
+ [attr.x]="h.x - handleHalf()"
61
+ [attr.y]="h.y - handleHalf()"
62
+ [attr.width]="handleSize()"
63
+ [attr.height]="handleSize()"
64
+ [attr.transform]="obbHandleTransform(h.x, h.y)"
65
+ [attr.data-svge-handle]="h.anchor"
66
+ [attr.aria-label]="
67
+ 'Resize handle, ' +
68
+ anchorLabel(h.anchor) +
69
+ '. Arrow keys to resize 1 unit, Shift+arrow for 10 units.'
70
+ "
71
+ aria-keyshortcuts="ArrowUp ArrowDown ArrowLeft ArrowRight"
72
+ role="button"
73
+ tabindex="0"
74
+ focusable="true"
75
+ (pointerdown)="onResizeHandlePointerDown($event, h.anchor)"
76
+ (pointermove)="onHandlePointerMove($event)"
77
+ (pointerup)="onHandlePointerUp($event)"
78
+ (keydown)="onResizeHandleKeyDown($event, h.anchor)"
79
+ ></svg:rect>
80
+ }
81
+ }
82
+ } @else if (focusBBox(); as b) {
83
+ <svg:rect
84
+ class="bbox"
85
+ aria-hidden="true"
86
+ [attr.x]="b.x"
87
+ [attr.y]="b.y"
88
+ [attr.width]="b.width"
89
+ [attr.height]="b.height"
90
+ fill="none"
91
+ ></svg:rect>
92
+
93
+ @if (showsTransformHandles()) {
94
+ @for (h of resizeHandles(); track h.anchor) {
95
+ <svg:rect
96
+ [class]="'handle resize handle-' + h.anchor"
97
+ [attr.x]="h.x - handleHalf()"
98
+ [attr.y]="h.y - handleHalf()"
99
+ [attr.width]="handleSize()"
100
+ [attr.height]="handleSize()"
101
+ [attr.data-svge-handle]="h.anchor"
102
+ [attr.aria-label]="
103
+ 'Resize handle, ' +
104
+ anchorLabel(h.anchor) +
105
+ '. Arrow keys to resize 1 unit, Shift+arrow for 10 units.'
106
+ "
107
+ aria-keyshortcuts="ArrowUp ArrowDown ArrowLeft ArrowRight"
108
+ role="button"
109
+ tabindex="0"
110
+ focusable="true"
111
+ (pointerdown)="onResizeHandlePointerDown($event, h.anchor)"
112
+ (pointermove)="onHandlePointerMove($event)"
113
+ (pointerup)="onHandlePointerUp($event)"
114
+ (keydown)="onResizeHandleKeyDown($event, h.anchor)"
115
+ ></svg:rect>
116
+ }
117
+ }
118
+ }
119
+
120
+ <!--
121
+ D-141 persistent rotation handle + stem. Rendered ONCE, OUTSIDE the
122
+ AABB/oriented conditional above, in DOCUMENT space (not inside the
123
+ oriented matrix group). This is deliberate: the pointer-capture taken on
124
+ the handle at gesture start would be lost if the element were destroyed
125
+ mid-drag \u2014 and the conditional DOES swap when a rotation crosses the
126
+ identity-to-rotated boundary (a non-rotated node becomes oriented on the
127
+ first move). Keeping the rotation handle persistent preserves capture and
128
+ lets rotationHandlePersistent() recompute its position each frame so the
129
+ stem visually FOLLOWS the mouse during rotation, then settles oriented
130
+ with the element (the user's explicit D-141 requirement). The pivot is the
131
+ bbox centre, invariant under rotation (AABB centre == OBB centre), so the
132
+ rotation gesture itself is unaffected.
133
+ -->
134
+ @if (showsRotationHandle() && rotationHandlePersistent(); as r) {
135
+ <svg:line
136
+ class="rotation-stem"
137
+ aria-hidden="true"
138
+ [attr.x1]="r.stemX1"
139
+ [attr.y1]="r.stemY1"
140
+ [attr.x2]="r.x"
141
+ [attr.y2]="r.y"
142
+ ></svg:line>
143
+ <svg:circle
144
+ class="handle rotation"
145
+ [attr.cx]="r.x"
146
+ [attr.cy]="r.y"
147
+ [attr.r]="handleHalf()"
148
+ [attr.data-svge-handle]="'rotation'"
149
+ aria-label="Rotation handle. Left/right arrows rotate by 1 degree, Shift+arrow rotates by 15 degrees."
150
+ aria-keyshortcuts="ArrowLeft ArrowRight"
151
+ role="button"
152
+ tabindex="0"
153
+ focusable="true"
154
+ (pointerdown)="onRotationHandlePointerDown($event)"
155
+ (pointermove)="onHandlePointerMove($event)"
156
+ (pointerup)="onHandlePointerUp($event)"
157
+ (keydown)="onRotationHandleKeyDown($event)"
158
+ ></svg:circle>
159
+ }
160
+ `,isInline:!0,styles:[`.bbox,.hover-outline{stroke:#1976d2;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.hover-outline{stroke:#90caf9;stroke-dasharray:3 2;vector-effect:non-scaling-stroke}.key-object{stroke:#ff6f00;stroke-width:2;vector-effect:non-scaling-stroke;pointer-events:none}.handle{fill:#fff;stroke:#1976d2;stroke-width:1;vector-effect:non-scaling-stroke;cursor:pointer;touch-action:none;outline:none}.handle:focus-visible{stroke:#ff6f00;stroke-width:2;filter:drop-shadow(0 0 2px rgba(255,111,0,.5))}.handle.resize.handle-tl,.handle.resize.handle-br{cursor:nwse-resize}.handle.resize.handle-tr,.handle.resize.handle-bl{cursor:nesw-resize}.handle.resize.handle-tc,.handle.resize.handle-bc{cursor:ns-resize}.handle.resize.handle-ml,.handle.resize.handle-mr{cursor:ew-resize}.handle.rotation{cursor:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M17.65%206.35A7.96%207.96%200%200%200%2012%204a8%208%200%201%200%207.75%2010h-2.08A6%206%200%201%201%2012%206c1.66%200%203.14.69%204.22%201.78L13%2011h7V4z'%20fill='%23222'%20stroke='%23fff'%20stroke-width='1'/%3E%3C/svg%3E") 12 12,crosshair}.rotation-stem{stroke:#1976d2;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}
161
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:zn,decorators:[{type:W,args:[{selector:"g[svgeSelectionOverlay]",standalone:!0,host:{role:"group","aria-label":"Selection transform handles"},template:`
162
+ @if (hoverBBox(); as h) {
163
+ <svg:rect
164
+ class="hover-outline"
165
+ aria-hidden="true"
166
+ [attr.x]="h.x"
167
+ [attr.y]="h.y"
168
+ [attr.width]="h.width"
169
+ [attr.height]="h.height"
170
+ fill="none"
171
+ ></svg:rect>
172
+ }
173
+
174
+ @if (keyBBox(); as k) {
175
+ <svg:rect
176
+ class="key-object"
177
+ aria-hidden="true"
178
+ [attr.x]="k.x"
179
+ [attr.y]="k.y"
180
+ [attr.width]="k.width"
181
+ [attr.height]="k.height"
182
+ fill="none"
183
+ ></svg:rect>
184
+ }
185
+
186
+ <!--
187
+ **D-141 \u2014 oriented (OBB) chrome.** For a single ROTATED node the box +
188
+ handles + rotation stem are drawn in the node's LOCAL frame inside a
189
+ <g matrix="..."> so the whole transform widget rotates WITH the object
190
+ (Illustrator/Figma/Affinity). Resize handles route to the OBB gesture
191
+ (scale along local axes). Non-rotated single + multi-selection keep the
192
+ axis-aligned chrome in the @else if below.
193
+ -->
194
+ @if (obb(); as o) {
195
+ <svg:g [attr.transform]="obbTransform()">
196
+ <svg:rect
197
+ class="bbox"
198
+ aria-hidden="true"
199
+ [attr.x]="o.localBBox.x"
200
+ [attr.y]="o.localBBox.y"
201
+ [attr.width]="o.localBBox.width"
202
+ [attr.height]="o.localBBox.height"
203
+ fill="none"
204
+ ></svg:rect>
205
+ </svg:g>
206
+
207
+ <!--
208
+ D-142-fix3 \u2014 resize handles for the oriented box are drawn in DOCUMENT
209
+ space (NOT inside the <g matrix>) as fixed-size squares positioned at
210
+ the box corners and rotated by the box ANGLE only. Inside the matrix
211
+ group they inherited its scale/skew, so a non-uniformly scaled object
212
+ stretched the handle squares. Doc-space + angle-only keeps them
213
+ pixel-constant and square under any transform (the box outline above
214
+ still rides the matrix, since it must trace the object's real bounds).
215
+ -->
216
+ @if (showsTransformHandles()) {
217
+ @for (h of obbResizeHandlesDoc(); track h.anchor) {
218
+ <svg:rect
219
+ [class]="'handle resize handle-' + h.anchor"
220
+ [attr.x]="h.x - handleHalf()"
221
+ [attr.y]="h.y - handleHalf()"
222
+ [attr.width]="handleSize()"
223
+ [attr.height]="handleSize()"
224
+ [attr.transform]="obbHandleTransform(h.x, h.y)"
225
+ [attr.data-svge-handle]="h.anchor"
226
+ [attr.aria-label]="
227
+ 'Resize handle, ' +
228
+ anchorLabel(h.anchor) +
229
+ '. Arrow keys to resize 1 unit, Shift+arrow for 10 units.'
230
+ "
231
+ aria-keyshortcuts="ArrowUp ArrowDown ArrowLeft ArrowRight"
232
+ role="button"
233
+ tabindex="0"
234
+ focusable="true"
235
+ (pointerdown)="onResizeHandlePointerDown($event, h.anchor)"
236
+ (pointermove)="onHandlePointerMove($event)"
237
+ (pointerup)="onHandlePointerUp($event)"
238
+ (keydown)="onResizeHandleKeyDown($event, h.anchor)"
239
+ ></svg:rect>
240
+ }
241
+ }
242
+ } @else if (focusBBox(); as b) {
243
+ <svg:rect
244
+ class="bbox"
245
+ aria-hidden="true"
246
+ [attr.x]="b.x"
247
+ [attr.y]="b.y"
248
+ [attr.width]="b.width"
249
+ [attr.height]="b.height"
250
+ fill="none"
251
+ ></svg:rect>
252
+
253
+ @if (showsTransformHandles()) {
254
+ @for (h of resizeHandles(); track h.anchor) {
255
+ <svg:rect
256
+ [class]="'handle resize handle-' + h.anchor"
257
+ [attr.x]="h.x - handleHalf()"
258
+ [attr.y]="h.y - handleHalf()"
259
+ [attr.width]="handleSize()"
260
+ [attr.height]="handleSize()"
261
+ [attr.data-svge-handle]="h.anchor"
262
+ [attr.aria-label]="
263
+ 'Resize handle, ' +
264
+ anchorLabel(h.anchor) +
265
+ '. Arrow keys to resize 1 unit, Shift+arrow for 10 units.'
266
+ "
267
+ aria-keyshortcuts="ArrowUp ArrowDown ArrowLeft ArrowRight"
268
+ role="button"
269
+ tabindex="0"
270
+ focusable="true"
271
+ (pointerdown)="onResizeHandlePointerDown($event, h.anchor)"
272
+ (pointermove)="onHandlePointerMove($event)"
273
+ (pointerup)="onHandlePointerUp($event)"
274
+ (keydown)="onResizeHandleKeyDown($event, h.anchor)"
275
+ ></svg:rect>
276
+ }
277
+ }
278
+ }
279
+
280
+ <!--
281
+ D-141 persistent rotation handle + stem. Rendered ONCE, OUTSIDE the
282
+ AABB/oriented conditional above, in DOCUMENT space (not inside the
283
+ oriented matrix group). This is deliberate: the pointer-capture taken on
284
+ the handle at gesture start would be lost if the element were destroyed
285
+ mid-drag \u2014 and the conditional DOES swap when a rotation crosses the
286
+ identity-to-rotated boundary (a non-rotated node becomes oriented on the
287
+ first move). Keeping the rotation handle persistent preserves capture and
288
+ lets rotationHandlePersistent() recompute its position each frame so the
289
+ stem visually FOLLOWS the mouse during rotation, then settles oriented
290
+ with the element (the user's explicit D-141 requirement). The pivot is the
291
+ bbox centre, invariant under rotation (AABB centre == OBB centre), so the
292
+ rotation gesture itself is unaffected.
293
+ -->
294
+ @if (showsRotationHandle() && rotationHandlePersistent(); as r) {
295
+ <svg:line
296
+ class="rotation-stem"
297
+ aria-hidden="true"
298
+ [attr.x1]="r.stemX1"
299
+ [attr.y1]="r.stemY1"
300
+ [attr.x2]="r.x"
301
+ [attr.y2]="r.y"
302
+ ></svg:line>
303
+ <svg:circle
304
+ class="handle rotation"
305
+ [attr.cx]="r.x"
306
+ [attr.cy]="r.y"
307
+ [attr.r]="handleHalf()"
308
+ [attr.data-svge-handle]="'rotation'"
309
+ aria-label="Rotation handle. Left/right arrows rotate by 1 degree, Shift+arrow rotates by 15 degrees."
310
+ aria-keyshortcuts="ArrowLeft ArrowRight"
311
+ role="button"
312
+ tabindex="0"
313
+ focusable="true"
314
+ (pointerdown)="onRotationHandlePointerDown($event)"
315
+ (pointermove)="onHandlePointerMove($event)"
316
+ (pointerup)="onHandlePointerUp($event)"
317
+ (keydown)="onRotationHandleKeyDown($event)"
318
+ ></svg:circle>
319
+ }
320
+ `,changeDetection:U.OnPush,styles:[`.bbox,.hover-outline{stroke:#1976d2;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.hover-outline{stroke:#90caf9;stroke-dasharray:3 2;vector-effect:non-scaling-stroke}.key-object{stroke:#ff6f00;stroke-width:2;vector-effect:non-scaling-stroke;pointer-events:none}.handle{fill:#fff;stroke:#1976d2;stroke-width:1;vector-effect:non-scaling-stroke;cursor:pointer;touch-action:none;outline:none}.handle:focus-visible{stroke:#ff6f00;stroke-width:2;filter:drop-shadow(0 0 2px rgba(255,111,0,.5))}.handle.resize.handle-tl,.handle.resize.handle-br{cursor:nwse-resize}.handle.resize.handle-tr,.handle.resize.handle-bl{cursor:nesw-resize}.handle.resize.handle-tc,.handle.resize.handle-bc{cursor:ns-resize}.handle.resize.handle-ml,.handle.resize.handle-mr{cursor:ew-resize}.handle.rotation{cursor:url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%3E%3Cpath%20d='M17.65%206.35A7.96%207.96%200%200%200%2012%204a8%208%200%201%200%207.75%2010h-2.08A6%206%200%201%201%2012%206c1.66%200%203.14.69%204.22%201.78L13%2011h7V4z'%20fill='%23222'%20stroke='%23fff'%20stroke-width='1'/%3E%3C/svg%3E") 12 12,crosshair}.rotation-stem{stroke:#1976d2;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}
321
+ `]}]}],ctorParameters:()=>[]});function Ki(r,e){return r.x===e.x&&r.y===e.y&&r.width===e.width&&r.height===e.height}function Rh(r,e){return r[0]===e[0]&&r[1]===e[1]&&r[2]===e[2]&&r[3]===e[3]&&r[4]===e[4]&&r[5]===e[5]}function Ah(r,e){return Ki(r.localBBox,e.localBBox)&&Rh(r.matrix,e.matrix)}function Ch(r,e,t){const n=e.fontSize??16,o=e.content.length===0?[""]:e.content.split(`
322
+ `),i=o.reduce((V,qe)=>Math.max(V,qe.length),0),a=Math.max(20,i*n*.6),l=Math.max(n,o.length*n*1.2),c=e.x,u=e.y-n*.8,h=An(r,t),g=K(h,c,u),v=K(h,c+a,u),p=K(h,c,u+l),x=K(h,c+a,u+l),E=Math.min(g.x,v.x,p.x,x.x),C=Math.min(g.y,v.y,p.y,x.y),G=Math.max(g.x,v.x,p.x,x.x),Z=Math.max(g.y,v.y,p.y,x.y);return X(E,C,G-E,Z-C)}function Xi(r,e){if(r.id===e)return r.type;if(r.type==="group")for(const t of r.children){const n=Xi(t,e);if(n!==null)return n}return null}const Oh=6,Nh=12,Lh=5,$h=10,Yi=3;class Gn{elRef=f(ae);selection=f(k);state=f(S);viewport=f(A);transform=f(Ue);layers=f(ne);_obb=b(null,...ngDevMode?[{debugName:"_obb"}]:[]);_bbox=b(null,...ngDevMode?[{debugName:"_bbox"}]:[]);_popoverOpen=b(!1,...ngDevMode?[{debugName:"_popoverOpen"}]:[]);_drag=b(null,...ngDevMode?[{debugName:"_drag"}]:[]);popoverOpen=this._popoverOpen.asReadonly();frame=m(()=>{const e=this.selection.focusId();if(e!==null){if(this.layers.hiddenIds().has(e))return null;const n=T(this.state.document().root,e);if(n!==null&&n.metadata.visible===!1)return null}if(this.selection.isSingleSelection()&&e!==null){const n=this._obb();return n===null?null:{localBBox:n.localBBox,matrix:n.matrix,single:!0}}const t=this._bbox();return t===null?null:{localBBox:t,matrix:Kr,single:!1}},...ngDevMode?[{debugName:"frame"}]:[]);pivotPos=m(()=>{const e=this.frame();if(e===null)return null;if(e.single){const t=this.selection.focusId();return t===null?null:this.transform.resolvePivotForNode(t,e.localBBox,e.matrix)}return this.transform.resolvePivot(e.localBBox)},...ngDevMode?[{debugName:"pivotPos"}]:[]);hasCustomPivot=m(()=>{const e=this.selection.focusId();return e===null?!1:this.transform.customPivots().has(e)},...ngDevMode?[{debugName:"hasCustomPivot"}]:[]);armLen=m(()=>Nh/this.viewport.zoom(),...ngDevMode?[{debugName:"armLen"}]:[]);dotRadius=m(()=>Oh/2/this.viewport.zoom(),...ngDevMode?[{debugName:"dotRadius"}]:[]);popoverDotRadius=m(()=>$h/2/this.viewport.zoom(),...ngDevMode?[{debugName:"popoverDotRadius"}]:[]);onKeyDown=e=>{e.key==="Escape"&&(this._drag()!==null?(this.cancelDrag(),e.preventDefault()):this._popoverOpen()&&(this._popoverOpen.set(!1),e.preventDefault()))};onWindowPointerDownCapture=e=>{if(!(e instanceof PointerEvent))return;const t=e.target;if(t===null||!t.classList.contains("popover-dot")||!this.elRef.nativeElement.contains(t))return;const o=t.getAttribute("data-svge-anchor"),i=this.frame(),a=this.selection.focusId();if(o===null||!Tn.includes(o)||i===null||a===null){e.stopImmediatePropagation(),e.preventDefault(),this._popoverOpen.set(!1);return}e.stopImmediatePropagation(),e.preventDefault(),this.transform.setPivotAnchorForNode(a,o,i.localBBox),this._popoverOpen.set(!1)};constructor(){pr({read:()=>this.recomputeBBox()}),document.addEventListener("keydown",this.onKeyDown),window.addEventListener("pointerdown",this.onWindowPointerDownCapture,!0)}ngOnDestroy(){document.removeEventListener("keydown",this.onKeyDown),window.removeEventListener("pointerdown",this.onWindowPointerDownCapture,!0)}onPointerDown(e){const t=this.frame(),n=this.pivotPos();if(t===null||n===null)return;const o=t.single?this.selection.focusId():null,i=o!==null&&this.transform.customPivots().has(o);this._drag.set({pointerId:e.pointerId,startScreenX:e.clientX,startScreenY:e.clientY,frame:t,nodeId:o,pivotBeforeDoc:n,hadCustomBefore:i,moved:!1}),H(e),e.stopPropagation()}onPointerMove(e){const t=this._drag();if(t===null||t.pointerId!==e.pointerId)return;const n=e.clientX-t.startScreenX,o=e.clientY-t.startScreenY,i=n*n+o*o;if(!t.moved&&i<Yi*Yi)return;t.moved=!0;const a=this.screenToDoc(e.clientX,e.clientY);if(a===null)return;const l=t.frame,c=e.altKey,u=Lh/this.viewport.zoom(),h=c?null:this.nearestOrientedAnchor(l,a,u);h!==null?t.nodeId!==null?this.transform.setPivotAnchorForNode(t.nodeId,h,l.localBBox):this.transform.setPivotAnchor(h,l.localBBox):t.nodeId!==null?this.transform.setPivotDocForNode(t.nodeId,a,l.localBBox,l.matrix):this.transform.setPivot(a,l.localBBox)}onPointerUp(e){const t=this._drag();t===null||t.pointerId!==e.pointerId||(t.moved||this._popoverOpen.update(n=>!n),this._drag.set(null),pe(e))}onDoubleClick(e){this.transform.resetPivot(),this._popoverOpen.set(!1),e.stopPropagation()}onMainKeyDown(e){(e.key==="Enter"||e.key===" ")&&(e.preventDefault(),e.stopPropagation(),this._popoverOpen.update(t=>!t))}onPopoverDotKeyDown(e,t){if(e.key!=="Enter"&&e.key!==" ")return;e.preventDefault(),e.stopPropagation();const n=this.frame();if(n===null)return;const o=this.selection.focusId();n.single&&o!==null?this.transform.setPivotAnchorForNode(o,t,n.localBBox):this.transform.setPivotAnchor(t,n.localBBox),this._popoverOpen.set(!1)}popoverAnchors(e){return Tn.map(t=>{const n=this.anchorDoc(e,t);return{anchor:t,x:n.x,y:n.y}})}isCurrentAnchor(e){const t=this.frame(),n=this.pivotPos();if(t===null||n===null)return!1;const o=this.anchorDoc(t,e),i=.5/this.viewport.zoom();return Math.abs(n.x-o.x)<i&&Math.abs(n.y-o.y)<i}anchorDoc(e,t){const n=ce(e.localBBox)[t];return K(e.matrix,n.x,n.y)}nearestOrientedAnchor(e,t,n){let o=null,i=n*n;for(const a of Tn){const l=this.anchorDoc(e,a),c=t.x-l.x,u=t.y-l.y,h=c*c+u*u;h<=i&&(i=h,o=a)}return o}cancelDrag(){const e=this._drag();e!==null&&(e.nodeId!==null?e.hadCustomBefore?this.transform.setPivotDocForNode(e.nodeId,e.pivotBeforeDoc,e.frame.localBBox,e.frame.matrix):this.transform.clearPivotForNode(e.nodeId):this.transform.setPivot(e.pivotBeforeDoc,e.frame.localBBox),this._drag.set(null))}recomputeBBox(){this.transform.syncPivotForSelection();const e=this.elRef.nativeElement.ownerSVGElement;if(e===null){this.maybeSetObb(null),this.maybeSet(this._bbox,null);return}const t=this.selection.selectedIds(),n=this.selection.focusId();this.state.document();let o=null,i=null;this.selection.isSingleSelection()&&n!==null?o=Rn(e,n):t.size>1&&(i=Sr(e,t)),this.maybeSetObb(o),this.maybeSet(this._bbox,i)}screenToDoc(e,t){return Ve(this.elRef.nativeElement.ownerSVGElement,e,t)}maybeSet(e,t){const n=e();n!==t&&(n!==null&&t!==null&&n.x===t.x&&n.y===t.y&&n.width===t.width&&n.height===t.height||e.set(t))}maybeSetObb(e){const t=this._obb();t!==e&&(t!==null&&e!==null&&Bh(t,e)||this._obb.set(e))}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Gn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:Gn,isStandalone:!0,selector:"g[svgeRotationPivot]",ngImport:s,template:`
323
+ @if (pivotPos(); as p) {
324
+ <svg:g class="pivot-group">
325
+ <!-- Crosshair arms (axis-aligned: a target symbol, not the box).
326
+ Its POSITION is what tracks the oriented object (D-142). -->
327
+ <svg:line
328
+ class="arm"
329
+ [attr.x1]="p.x - armLen()"
330
+ [attr.y1]="p.y"
331
+ [attr.x2]="p.x + armLen()"
332
+ [attr.y2]="p.y"
333
+ ></svg:line>
334
+ <svg:line
335
+ class="arm"
336
+ [attr.x1]="p.x"
337
+ [attr.y1]="p.y - armLen()"
338
+ [attr.x2]="p.x"
339
+ [attr.y2]="p.y + armLen()"
340
+ ></svg:line>
341
+ <!-- Central handle (pointer target). Keyboard: Enter/Space
342
+ opens the picker popover; double-click resets to center. -->
343
+ <svg:circle
344
+ class="dot"
345
+ [class.custom]="hasCustomPivot()"
346
+ [attr.cx]="p.x"
347
+ [attr.cy]="p.y"
348
+ [attr.r]="dotRadius()"
349
+ role="button"
350
+ tabindex="0"
351
+ focusable="true"
352
+ aria-label="Rotation pivot. Enter to open anchor picker, drag to move, double-click to reset."
353
+ aria-haspopup="menu"
354
+ [attr.aria-expanded]="popoverOpen() ? 'true' : 'false'"
355
+ aria-keyshortcuts="Enter Space Escape"
356
+ (pointerdown)="onPointerDown($event)"
357
+ (pointermove)="onPointerMove($event)"
358
+ (pointerup)="onPointerUp($event)"
359
+ (dblclick)="onDoubleClick($event)"
360
+ (keydown)="onMainKeyDown($event)"
361
+ ></svg:circle>
362
+ </svg:g>
363
+
364
+ @if (popoverOpen() && frame(); as f) {
365
+ <svg:g class="popover" role="menu" aria-label="Pivot anchor picker">
366
+ @for (a of popoverAnchors(f); track a.anchor) {
367
+ <svg:circle
368
+ class="popover-dot"
369
+ [class.active]="isCurrentAnchor(a.anchor)"
370
+ [attr.cx]="a.x"
371
+ [attr.cy]="a.y"
372
+ [attr.r]="popoverDotRadius()"
373
+ [attr.data-svge-anchor]="a.anchor"
374
+ role="menuitemradio"
375
+ tabindex="0"
376
+ focusable="true"
377
+ [attr.aria-checked]="isCurrentAnchor(a.anchor) ? 'true' : 'false'"
378
+ [attr.aria-label]="'Snap pivot to ' + a.anchor"
379
+ (keydown)="onPopoverDotKeyDown($event, a.anchor)"
380
+ ></svg:circle>
381
+ }
382
+ </svg:g>
383
+ }
384
+ }
385
+ `,isInline:!0,styles:[`.arm{stroke:#d32f2f;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.dot{fill:#fff;stroke:#d32f2f;stroke-width:1.5;vector-effect:non-scaling-stroke;cursor:grab;touch-action:none;outline:none}.dot:active{cursor:grabbing}.dot.custom{fill:#d32f2f}.dot:focus-visible{stroke:#ff6f00;stroke-width:2.5;filter:drop-shadow(0 0 2px rgba(255,111,0,.6))}.popover-dot{fill:#fff;stroke:#1976d2;stroke-width:1;vector-effect:non-scaling-stroke;cursor:pointer;outline:none}.popover-dot.active{fill:#1976d2}.popover-dot:focus-visible{stroke:#ff6f00;stroke-width:2;filter:drop-shadow(0 0 2px rgba(255,111,0,.6))}
386
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Gn,decorators:[{type:W,args:[{selector:"g[svgeRotationPivot]",standalone:!0,template:`
387
+ @if (pivotPos(); as p) {
388
+ <svg:g class="pivot-group">
389
+ <!-- Crosshair arms (axis-aligned: a target symbol, not the box).
390
+ Its POSITION is what tracks the oriented object (D-142). -->
391
+ <svg:line
392
+ class="arm"
393
+ [attr.x1]="p.x - armLen()"
394
+ [attr.y1]="p.y"
395
+ [attr.x2]="p.x + armLen()"
396
+ [attr.y2]="p.y"
397
+ ></svg:line>
398
+ <svg:line
399
+ class="arm"
400
+ [attr.x1]="p.x"
401
+ [attr.y1]="p.y - armLen()"
402
+ [attr.x2]="p.x"
403
+ [attr.y2]="p.y + armLen()"
404
+ ></svg:line>
405
+ <!-- Central handle (pointer target). Keyboard: Enter/Space
406
+ opens the picker popover; double-click resets to center. -->
407
+ <svg:circle
408
+ class="dot"
409
+ [class.custom]="hasCustomPivot()"
410
+ [attr.cx]="p.x"
411
+ [attr.cy]="p.y"
412
+ [attr.r]="dotRadius()"
413
+ role="button"
414
+ tabindex="0"
415
+ focusable="true"
416
+ aria-label="Rotation pivot. Enter to open anchor picker, drag to move, double-click to reset."
417
+ aria-haspopup="menu"
418
+ [attr.aria-expanded]="popoverOpen() ? 'true' : 'false'"
419
+ aria-keyshortcuts="Enter Space Escape"
420
+ (pointerdown)="onPointerDown($event)"
421
+ (pointermove)="onPointerMove($event)"
422
+ (pointerup)="onPointerUp($event)"
423
+ (dblclick)="onDoubleClick($event)"
424
+ (keydown)="onMainKeyDown($event)"
425
+ ></svg:circle>
426
+ </svg:g>
427
+
428
+ @if (popoverOpen() && frame(); as f) {
429
+ <svg:g class="popover" role="menu" aria-label="Pivot anchor picker">
430
+ @for (a of popoverAnchors(f); track a.anchor) {
431
+ <svg:circle
432
+ class="popover-dot"
433
+ [class.active]="isCurrentAnchor(a.anchor)"
434
+ [attr.cx]="a.x"
435
+ [attr.cy]="a.y"
436
+ [attr.r]="popoverDotRadius()"
437
+ [attr.data-svge-anchor]="a.anchor"
438
+ role="menuitemradio"
439
+ tabindex="0"
440
+ focusable="true"
441
+ [attr.aria-checked]="isCurrentAnchor(a.anchor) ? 'true' : 'false'"
442
+ [attr.aria-label]="'Snap pivot to ' + a.anchor"
443
+ (keydown)="onPopoverDotKeyDown($event, a.anchor)"
444
+ ></svg:circle>
445
+ }
446
+ </svg:g>
447
+ }
448
+ }
449
+ `,changeDetection:U.OnPush,styles:[`.arm{stroke:#d32f2f;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.dot{fill:#fff;stroke:#d32f2f;stroke-width:1.5;vector-effect:non-scaling-stroke;cursor:grab;touch-action:none;outline:none}.dot:active{cursor:grabbing}.dot.custom{fill:#d32f2f}.dot:focus-visible{stroke:#ff6f00;stroke-width:2.5;filter:drop-shadow(0 0 2px rgba(255,111,0,.6))}.popover-dot{fill:#fff;stroke:#1976d2;stroke-width:1;vector-effect:non-scaling-stroke;cursor:pointer;outline:none}.popover-dot.active{fill:#1976d2}.popover-dot:focus-visible{stroke:#ff6f00;stroke-width:2;filter:drop-shadow(0 0 2px rgba(255,111,0,.6))}
450
+ `]}]}],ctorParameters:()=>[]});function Bh(r,e){return r.localBBox.x===e.localBBox.x&&r.localBBox.y===e.localBBox.y&&r.localBBox.width===e.localBBox.width&&r.localBBox.height===e.localBBox.height&&r.matrix[0]===e.matrix[0]&&r.matrix[1]===e.matrix[1]&&r.matrix[2]===e.matrix[2]&&r.matrix[3]===e.matrix[3]&&r.matrix[4]===e.matrix[4]&&r.matrix[5]===e.matrix[5]}class nt{_state=b(null,...ngDevMode?[{debugName:"_state"}]:[]);state=this._state.asReadonly();isActive=m(()=>this._state()!==null,...ngDevMode?[{debugName:"isActive"}]:[]);rect=m(()=>{const e=this._state();return e===null?null:Fh(e.startPoint,e.currentPoint)},...ngDevMode?[{debugName:"rect"}]:[]);start(e,t,n){this._state()===null&&this._state.set({startPoint:e,currentPoint:e,mode:t,initialSelection:new Set(n)})}update(e){const t=this._state();t!==null&&this._state.set({...t,currentPoint:e})}end(){this._state.set(null)}cancel(){this._state.set(null)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:nt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:nt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:nt,decorators:[{type:D,args:[{providedIn:"root"}]}]});function Fh(r,e){const t=Math.min(r.x,e.x),n=Math.min(r.y,e.y),o=Math.abs(r.x-e.x),i=Math.abs(r.y-e.y);return X(t,n,o,i)}class Hn{rect=f(nt).rect;static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Hn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:Hn,isStandalone:!0,selector:"g[svgeMarquee]",host:{attributes:{"aria-hidden":"true"}},ngImport:s,template:`
451
+ @if (rect(); as r) {
452
+ <svg:rect
453
+ class="marquee"
454
+ [attr.x]="r.x"
455
+ [attr.y]="r.y"
456
+ [attr.width]="r.width"
457
+ [attr.height]="r.height"
458
+ ></svg:rect>
459
+ }
460
+ `,isInline:!0,styles:[`.marquee{fill:#1976d214;stroke:#1976d2;stroke-width:1;stroke-dasharray:4 2;vector-effect:non-scaling-stroke;pointer-events:none}
461
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Hn,decorators:[{type:W,args:[{selector:"g[svgeMarquee]",standalone:!0,host:{"aria-hidden":"true"},template:`
462
+ @if (rect(); as r) {
463
+ <svg:rect
464
+ class="marquee"
465
+ [attr.x]="r.x"
466
+ [attr.y]="r.y"
467
+ [attr.width]="r.width"
468
+ [attr.height]="r.height"
469
+ ></svg:rect>
470
+ }
471
+ `,changeDetection:U.OnPush,styles:[`.marquee{fill:#1976d214;stroke:#1976d2;stroke-width:1;stroke-dasharray:4 2;vector-effect:non-scaling-stroke;pointer-events:none}
472
+ `]}]}]});function qi(r){const e=[];for(const{id:t,bbox:n}of r){const o=n.x+n.width/2,i=n.y+n.height/2;e.push({axis:"x",value:n.x,source:"object",objectId:t},{axis:"x",value:o,source:"object",objectId:t},{axis:"x",value:n.x+n.width,source:"object",objectId:t},{axis:"y",value:n.y,source:"object",objectId:t},{axis:"y",value:i,source:"object",objectId:t},{axis:"y",value:n.y+n.height,source:"object",objectId:t})}return e}function wo(r,e,t,n=0){if(!(e>0))return[];const o=(t==="x"?r.x:r.y)-e,i=(t==="x"?r.x+r.width:r.y+r.height)+e,a=Math.floor((o-n)/e),l=Math.ceil((i-n)/e),c=[];for(let u=a;u<=l;u++)c.push({axis:t,value:n+u*e,source:"grid"});return c}function Zi(r){const e=[];for(const t of r)Number.isFinite(t.position)&&e.push(t.axis==="h"?{axis:"y",value:t.position,source:"guide"}:{axis:"x",value:t.position,source:"guide"});return e}function Ji(r,e,t){if(!(t>0)||e.length===0)return{delta:{x:0,y:0},guides:[]};const n=[r.x,r.x+r.width/2,r.x+r.width],o=[r.y,r.y+r.height/2,r.y+r.height];let i=null,a=null;for(const u of e){const h=u.axis==="x"?n:o;let g=1/0,v=h[0];for(const p of h){const x=Math.abs(p-u.value);x<g&&(g=x,v=p)}g>t||(u.axis==="x"?(i===null||g<i.dist)&&(i={feature:v,target:u,dist:g}):(a===null||g<a.dist)&&(a={feature:v,target:u,dist:g}))}const l={x:i===null?0:i.target.value-i.feature,y:a===null?0:a.target.value-a.feature},c=[];return i!==null&&c.push({axis:"x",value:i.target.value,source:i.target.source}),a!==null&&c.push({axis:"y",value:a.target.value,source:a.target.source}),{delta:l,guides:c}}const jh=10,Vh=8;class ue{_enabled=b(!0,...ngDevMode?[{debugName:"_enabled"}]:[]);_mode=b("both",...ngDevMode?[{debugName:"_mode"}]:[]);_snapToGuides=b(!1,...ngDevMode?[{debugName:"_snapToGuides"}]:[]);_gridSize=b(jh,...ngDevMode?[{debugName:"_gridSize"}]:[]);_gridOrigin=b({x:0,y:0},...ngDevMode?[{debugName:"_gridOrigin"}]:[]);_thresholdPx=b(Vh,...ngDevMode?[{debugName:"_thresholdPx"}]:[]);enabled=this._enabled.asReadonly();mode=this._mode.asReadonly();snapToGuides=this._snapToGuides.asReadonly();gridSize=this._gridSize.asReadonly();gridOrigin=this._gridOrigin.asReadonly();thresholdPx=this._thresholdPx.asReadonly();_activeGuides=b([],...ngDevMode?[{debugName:"_activeGuides"}]:[]);activeGuides=this._activeGuides.asReadonly();hasActiveGuides=m(()=>this._activeGuides().length>0,...ngDevMode?[{debugName:"hasActiveGuides"}]:[]);setEnabled(e){this._enabled.set(e),e||this._activeGuides.set([])}setMode(e){this._mode.set(e)}setSnapToGuides(e){this._snapToGuides.set(e)}toggleSnapToGuides(){this._snapToGuides.update(e=>!e)}setGridSize(e){!Number.isFinite(e)||e<=0||this._gridSize.set(e)}setGridOrigin(e){!Number.isFinite(e.x)||!Number.isFinite(e.y)||this._gridOrigin.set({x:e.x,y:e.y})}setThresholdPx(e){!Number.isFinite(e)||e<0||this._thresholdPx.set(e)}resolveForMove(e,t,n=1,o=[]){if(!this._enabled())return zh;const i=this._mode(),a=this._thresholdPx()/Math.max(n,1e-4),l=[];if((i==="objects"||i==="both")&&l.push(...qi(t)),this._snapToGuides()&&l.push(...Zi(o)),i==="grid"||i==="both"){const c=this._gridSize(),u=this._gridOrigin();l.push(...wo(e,c,"x",u.x),...wo(e,c,"y",u.y))}return Ji(e,l,a)}setActiveGuides(e){this._activeGuides.set(e)}clearActiveGuides(){this._activeGuides.set([])}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ue,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ue,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ue,decorators:[{type:D,args:[{providedIn:"root"}]}]});const zh={delta:{x:0,y:0},guides:[]};class tn{snap=f(ue);viewport=f(A);state=f(S);lines=m(()=>this.snap.activeGuides(),...ngDevMode?[{debugName:"lines"}]:[]);static OVERREACH=3;span=m(()=>{const e=this.viewport.viewBox(),t=this.state.document().viewBox,n=Math.min(e.x,t.x),o=Math.min(e.y,t.y),i=Math.max(e.x+e.width,t.x+t.width),a=Math.max(e.y+e.height,t.y+t.height),l=i-n,c=a-o,u=Math.max(l,c)*tn.OVERREACH;return{x:n-u,y:o-u,width:l+u*2,height:c+u*2}},...ngDevMode?[{debugName:"span"}]:[]);static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:tn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:tn,isStandalone:!0,selector:"g[svgeSnapGuides]",host:{attributes:{"aria-hidden":"true"}},ngImport:s,template:`
473
+ @for (g of lines(); track $index) {
474
+ @if (g.axis === 'x') {
475
+ <svg:line
476
+ class="guide"
477
+ [class.grid]="g.source === 'grid'"
478
+ [class.object]="g.source === 'object'"
479
+ [attr.x1]="g.value"
480
+ [attr.y1]="span().y"
481
+ [attr.x2]="g.value"
482
+ [attr.y2]="span().y + span().height"
483
+ ></svg:line>
484
+ } @else {
485
+ <svg:line
486
+ class="guide"
487
+ [class.grid]="g.source === 'grid'"
488
+ [class.object]="g.source === 'object'"
489
+ [attr.x1]="span().x"
490
+ [attr.y1]="g.value"
491
+ [attr.x2]="span().x + span().width"
492
+ [attr.y2]="g.value"
493
+ ></svg:line>
494
+ }
495
+ }
496
+ `,isInline:!0,styles:[`.guide{stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.guide.grid{stroke:#d81b60;stroke-dasharray:2 2}.guide.object{stroke:#d81b60}
497
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:tn,decorators:[{type:W,args:[{selector:"g[svgeSnapGuides]",standalone:!0,host:{"aria-hidden":"true"},template:`
498
+ @for (g of lines(); track $index) {
499
+ @if (g.axis === 'x') {
500
+ <svg:line
501
+ class="guide"
502
+ [class.grid]="g.source === 'grid'"
503
+ [class.object]="g.source === 'object'"
504
+ [attr.x1]="g.value"
505
+ [attr.y1]="span().y"
506
+ [attr.x2]="g.value"
507
+ [attr.y2]="span().y + span().height"
508
+ ></svg:line>
509
+ } @else {
510
+ <svg:line
511
+ class="guide"
512
+ [class.grid]="g.source === 'grid'"
513
+ [class.object]="g.source === 'object'"
514
+ [attr.x1]="span().x"
515
+ [attr.y1]="g.value"
516
+ [attr.x2]="span().x + span().width"
517
+ [attr.y2]="g.value"
518
+ ></svg:line>
519
+ }
520
+ }
521
+ `,changeDetection:U.OnPush,styles:[`.guide{stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.guide.grid{stroke:#d81b60;stroke-dasharray:2 2}.guide.object{stroke:#d81b60}
522
+ `]}]}]});function Qi(r,e,t="intersect"){if(r.width===0||r.height===0)return[];const n=[];for(const o of e)(t==="contain"?Hh(r,o.bbox):Gh(r,o.bbox))&&n.push(o.id);return n}function Gh(r,e){return r.x<=e.x+e.width&&r.x+r.width>=e.x&&r.y<=e.y+e.height&&r.y+r.height>=e.y}function Hh(r,e){return e.x>=r.x&&e.y>=r.y&&e.x+e.width<=r.x+r.width&&e.y+e.height<=r.y+r.height}function es(r,e){if(r.length<2)return new Map;const t=Wh(r,e),n=new Map;for(const{id:o,bbox:i}of r){const a=as(i,e,t);(a.x!==0||a.y!==0)&&n.set(o,a)}return n}function ts(r,e,t){if(r.length===0)return new Map;const n=ss(t,e),o=new Map;for(const{id:i,bbox:a}of r){const l=as(a,e,n);(l.x!==0||l.y!==0)&&o.set(i,l)}return o}function ns(r,e,t){if(e!==null&&r.length>=2){const n=r.find(o=>o.id===e);if(n!==void 0)return n.bbox}return r.length===1?t:null}function rs(r,e){if(r.length<3)return new Map;const t=e==="horizontal",n=[...r].sort((c,u)=>Cn(c.bbox,t)-Cn(u.bbox,t)),o=Cn(n[0].bbox,t),i=Cn(n[n.length-1].bbox,t);if(i===o)return new Map;const a=(i-o)/(n.length-1),l=new Map;for(let c=1;c<n.length-1;c++){const u=n[c],h=o+c*a,g=Cn(u.bbox,t),v=h-g;v!==0&&l.set(u.id,t?{x:v,y:0}:{x:0,y:v})}return l}function Uh(r,e){if(r.length<3)return null;const t=e==="horizontal",n=h=>t?h.x:h.y,o=h=>t?h.width:h.height,i=[...r].sort((h,g)=>n(h.bbox)-n(g.bbox)),a=i[0].bbox,l=i[i.length-1].bbox,c=n(l)+o(l)-n(a);if(c<=0)return null;let u=0;for(const{bbox:h}of i)u+=o(h);return(c-u)/(i.length-1)}function os(r,e,t){if(r.length<2)return new Map;const n=e==="horizontal",o=u=>n?u.x:u.y,i=u=>n?u.width:u.height,a=[...r].sort((u,h)=>o(u.bbox)-o(h.bbox)),l=new Map;let c=o(a[0].bbox)+i(a[0].bbox);for(let u=1;u<a.length;u++){const h=a[u],g=c+t,v=g-o(h.bbox);v!==0&&l.set(h.id,n?{x:v,y:0}:{x:0,y:v}),c=g+i(h.bbox)}return l}function is(r){if(r.length===0)throw new RangeError("unionBBox: items must be non-empty");let e=1/0,t=1/0,n=-1/0,o=-1/0;for(const{bbox:i}of r)i.x<e&&(e=i.x),i.y<t&&(t=i.y),i.x+i.width>n&&(n=i.x+i.width),i.y+i.height>o&&(o=i.y+i.height);return{x:e,y:t,width:n-e,height:o-t}}function Wh(r,e){return ss(is(r),e)}function ss(r,e){switch(e){case"left":return r.x;case"right":return r.x+r.width;case"center-x":return r.x+r.width/2;case"top":return r.y;case"bottom":return r.y+r.height;case"center-y":return r.y+r.height/2}}function as(r,e,t){switch(e){case"left":return{x:t-r.x,y:0};case"right":return{x:t-(r.x+r.width),y:0};case"center-x":return{x:t-(r.x+r.width/2),y:0};case"top":return{x:0,y:t-r.y};case"bottom":return{x:0,y:t-(r.y+r.height)};case"center-y":return{x:0,y:t-(r.y+r.height/2)}}}function Cn(r,e){return e?r.x+r.width/2:r.y+r.height/2}class rt{bus=f(M);align(e,t){const n=es(e,t);return this.dispatch(n,`Align ${t}`)}alignToReference(e,t,n){const o=ts(e,t,n);return this.dispatch(o,`Align ${t} to page`)}distribute(e,t){const n=rs(e,t);return this.dispatch(n,`Distribute ${t}`)}distributeSpacing(e,t,n){const o=os(e,t,n);return this.dispatch(o,`Distribute ${t} spacing`)}dispatch(e,t){return e.size===0?!1:(this.bus.dispatch(new Ur(e,t)),!0)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:rt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:rt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:rt,decorators:[{type:D,args:[{providedIn:"root"}]}]});const Io={documentation:"/docs/documentation",tutorials:"/docs/tutorials",pluginDevelopment:"/docs/plugin-development",reportIssue:"https://github.com/mosaicoo/svg-engine/issues/new",homepage:"https://github.com/mosaicoo/svg-engine"},ko=new gt("SVGE_HELP_LINKS",{providedIn:"root",factory:()=>Io});function Kh(r){return{provide:ko,useValue:{...Io,...r}}}class St{injector=f(Vt);_installed=b([],...ngDevMode?[{debugName:"_installed"}]:[]);installed=m(()=>this._installed().map(e=>({plugin:e.plugin,installedAt:e.installedAt})),...ngDevMode?[{debugName:"installed"}]:[]);has(e){return this._installed().some(t=>t.plugin.id===e)}get(e){const t=this._installed().find(n=>n.plugin.id===e);return t===void 0?null:{plugin:t.plugin,installedAt:t.installedAt}}list(){return this.installed()}install(e){if(typeof e.id!="string"||e.id.length===0)throw new Error("PluginRegistry.install: plugin.id must be a non-empty string");if(this.has(e.id))throw new Error(`PluginRegistry.install: plugin "${e.id}" is already installed`);if(Xh(e.apiVersion,e.id),e.dependencies){for(const i of e.dependencies)if(!this.has(i))throw new Error(`PluginRegistry.install: plugin "${e.id}" requires "${i}" which is not installed`)}const t=[],n={pluginId:e.id,injector:this.injector,track:i=>(t.push(i),i)};try{e.install(n)}catch(i){throw this.disposeAll(t),new Error(`PluginRegistry.install: plugin "${e.id}" failed during install: ${Yh(i)}`,{cause:i})}const o={plugin:e,installedAt:Date.now(),disposables:t};return this._installed.set([...this._installed(),o]),{plugin:e,installedAt:o.installedAt}}uninstall(e){const t=this._installed(),n=t.find(i=>i.plugin.id===e);if(n===void 0)return!1;const o={pluginId:n.plugin.id,injector:this.injector,track:i=>(n.disposables.push(i),i)};if(n.plugin.uninstall)try{n.plugin.uninstall(o)}catch(i){console.error(`PluginRegistry.uninstall: plugin "${e}" uninstall hook threw \u2014 continuing with cleanup`,i)}return this.disposeAll(n.disposables),this._installed.set(t.filter(i=>i.plugin.id!==e)),!0}disposeAll(e){for(let t=e.length-1;t>=0;t--)try{e[t].dispose()}catch(n){console.error("PluginRegistry: disposable threw during cleanup \u2014 continuing",n)}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:St,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:St,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:St,decorators:[{type:D,args:[{providedIn:"root"}]}]});function Xh(r,e){const t=ls(r),n=ls(O);if(t===null)throw new Error(`PluginRegistry.install: plugin "${e}" has invalid apiVersion "${r}" (expected semver)`);if(t!==n)throw new Error(`PluginRegistry.install: plugin "${e}" targets API v${r} but host is v${O}`)}function ls(r){const e=/^(\d+)\./.exec(r);if(e===null)return null;const t=Number(e[1]);return Number.isFinite(t)?t:null}function Yh(r){if(r instanceof Error)return r.message;try{return JSON.stringify(r)}catch{return String(r)}}class Pt{_entries=b([],...ngDevMode?[{debugName:"_entries"}]:[]);entries=this._entries.asReadonly();has(e){return this._entries().some(t=>t.plugin.id===e)}get(e){return this._entries().find(t=>t.plugin.id===e)??null}register(e,t){return this.has(e.id)?!1:(this._entries.set([...this._entries(),{plugin:e,source:t}]),!0)}unregister(e){return this.has(e)?(this._entries.set(this._entries().filter(t=>t.plugin.id!==e)),!0):!1}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Pt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Pt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Pt,decorators:[{type:D,args:[{providedIn:"root"}]}]});const cs="svge:plugins:state",ds=1;class Mt{document=f(re);_disabled=b(new Set,...ngDevMode?[{debugName:"_disabled"}]:[]);disabled=this._disabled.asReadonly();constructor(){this.hydrate()}isDisabled(e){return this._disabled().has(e)}disabledIds(){return[...this._disabled()]}setDisabled(e,t){const n=new Set(this._disabled());t?n.add(e):n.delete(e),this._disabled.set(n),this.persist()}forget(e){if(!this._disabled().has(e))return;const t=new Set(this._disabled());t.delete(e),this._disabled.set(t),this.persist()}hydrate(){const e=this.window();if(e===null)return;let t;try{t=e.localStorage.getItem(cs)}catch{return}if(t===null||t.length===0)return;let n;try{n=JSON.parse(t)}catch(o){console.warn("PluginStateStore: malformed JSON in storage \u2014 ignoring.",o);return}if(n.v!==ds||!Array.isArray(n.disabled)){console.warn(`PluginStateStore: unexpected payload (v=${n.v}) \u2014 ignoring.`);return}this._disabled.set(new Set(n.disabled.filter(o=>typeof o=="string")))}persist(){const e=this.window();if(e===null)return;const t={v:ds,disabled:[...this._disabled()]};try{e.localStorage.setItem(cs,JSON.stringify(t))}catch(n){console.warn("PluginStateStore: localStorage write failed \u2014",n)}}window(){const e=this.document.defaultView;return e!==null?e:typeof window<"u"?window:null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Mt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Mt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Mt,decorators:[{type:D,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});function us(r){return ci([{provide:Fd,multi:!0,useValue:()=>{f(Pt).register(r,"internal"),!f(Mt).isDisabled(r.id)&&f(St).install(r)}}])}class nn{registry=f(St);catalog=f(Pt);stateStore=f(Mt);_errors=b(new Map,...ngDevMode?[{debugName:"_errors"}]:[]);plugins=m(()=>{const e=new Set(this.registry.installed().map(o=>o.plugin.id)),t=this.stateStore.disabled(),n=this._errors();return this.catalog.entries().map(o=>qh(o,e,t,n))},...ngDevMode?[{debugName:"plugins"}]:[]);internalPlugins=m(()=>this.plugins().filter(e=>e.source==="internal"),...ngDevMode?[{debugName:"internalPlugins"}]:[]);externalPlugins=m(()=>this.plugins().filter(e=>e.source==="external"),...ngDevMode?[{debugName:"externalPlugins"}]:[]);canUninstall(e){return this.catalog.get(e)?.source==="external"}enabledDependentsOf(e){return this.catalog.entries().filter(t=>!this.stateStore.isDisabled(t.plugin.id)&&(t.plugin.dependencies??[]).includes(e)).map(t=>t.plugin.id)}enable(e){const t=this.catalog.get(e);if(t===null)return{ok:!1,error:`Unknown plugin "${e}"`};if(this.stateStore.setDisabled(e,!1),this.registry.has(e))return this.clearError(e),{ok:!0};try{return this.registry.install(t.plugin),this.clearError(e),{ok:!0}}catch(n){const o=n instanceof Error?n.message:String(n);return this.setError(e,o),{ok:!1,error:o}}}disable(e){const t=this.enabledDependentsOf(e);return t.length>0?{ok:!1,error:`In use by: ${t.join(", ")}`}:(this.stateStore.setDisabled(e,!0),this.registry.has(e)&&this.registry.uninstall(e),this.clearError(e),{ok:!0})}uninstall(e){const t=this.catalog.get(e);if(t===null)return{ok:!1,error:`Unknown plugin "${e}"`};if(t.source!=="external")return{ok:!1,error:"Internal plugins cannot be uninstalled \u2014 disable instead."};const n=this.enabledDependentsOf(e);return n.length>0?{ok:!1,error:`In use by: ${n.join(", ")}`}:(this.registry.has(e)&&this.registry.uninstall(e),this.catalog.unregister(e),this.stateStore.forget(e),this.clearError(e),{ok:!0})}installExternal(e){return this.catalog.register(e,"external")?this.enable(e.id):{ok:!1,error:`Plugin "${e.id}" already exists`}}setError(e,t){const n=new Map(this._errors());n.set(e,t),this._errors.set(n)}clearError(e){if(!this._errors().has(e))return;const t=new Map(this._errors());t.delete(e),this._errors.set(t)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:nn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:nn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:nn,decorators:[{type:D,args:[{providedIn:"root"}]}]});function qh(r,e,t,n){const o=r.plugin,i=o.category??"other";return{id:o.id,name:o.name,version:o.version,apiVersion:o.apiVersion,description:o.description,author:o.author,icon:o.icon,category:i,dependencies:o.dependencies??[],source:r.source,enabled:!t.has(o.id),installed:e.has(o.id),error:n.get(o.id)??null}}const Zh=/^sha(256|384|512)-[A-Za-z0-9+/]+={0,2}$/,Jh=/^\d+\.\d+\.\d+/;function hs(r){if(r===null||typeof r!="object")return"manifest must be an object";const e=r,t=n=>{const o=e[n];return typeof o!="string"||o.length===0?`manifest.${n} must be a non-empty string`:null};for(const n of["id","name","version","apiVersion","entry"]){const o=t(n);if(o!==null)return o}if(!Jh.test(e.apiVersion))return`manifest.apiVersion "${String(e.apiVersion)}" is not a valid semver`;try{new URL(e.entry)}catch{return`manifest.entry "${String(e.entry)}" is not an absolute URL`}return e.integrity!==void 0&&(typeof e.integrity!="string"||!Zh.test(e.integrity))?'manifest.integrity must be a valid SRI string (e.g. "sha384-\u2026")':e.dependencies!==void 0&&(!Array.isArray(e.dependencies)||e.dependencies.some(n=>typeof n!="string"))?"manifest.dependencies must be an array of strings":null}const xo=new gt("SVGE_PLUGIN_TRUSTED_ORIGINS",{factory:()=>[]}),Do=new gt("SVGE_PLUGIN_MODULE_LOADER",{factory:()=>null});class Un{manager=f(nn);trustedOrigins=f(xo);moduleLoader=f(Do);get isEnabled(){return this.moduleLoader!==null&&this.trustedOrigins.length>0}isOriginTrusted(e){let t;try{t=new URL(e).origin}catch{return!1}return this.trustedOrigins.includes(t)}async load(e){const t=hs(e);if(t!==null)return De(`Invalid manifest: ${t}`);if(Mr(e.apiVersion)!==Mr(O))return De(`Plugin "${e.id}" targets API v${e.apiVersion} but host is v${O}`);if(!this.isOriginTrusted(e.entry))return De(`Refused: "${e.entry}" is not on the trusted-origins allowlist (${this.trustedOrigins.length===0?"none configured":this.trustedOrigins.join(", ")})`);const n=this.moduleLoader;if(n===null)return De("Runtime plugin loading is not configured (no module loader provided)");let o;try{o=await n(e)}catch(l){return De(`Failed to load module from "${e.entry}": ${So(l)}`)}const i=Qh(o,e);if(typeof i=="string")return De(i);const a=ro(i,{description:i.description??e.description,author:i.author??e.author,icon:i.icon??e.icon,category:i.category??e.category});return this.manager.installExternal(a)}async loadFromManifestUrl(e){if(!this.isEnabled)return De("Runtime plugin loading is not configured by this app");if(!this.isOriginTrusted(e))return De(`Refused: "${e}" is not on the trusted-origins allowlist (${this.trustedOrigins.length===0?"none configured":this.trustedOrigins.join(", ")})`);let t;try{t=await fetch(e,{credentials:"omit"})}catch(o){return De(`Failed to fetch manifest from "${e}": ${So(o)}`)}if(!t.ok)return De(`Failed to fetch manifest from "${e}": HTTP ${t.status}`);let n;try{n=await t.json()}catch(o){return De(`Manifest at "${e}" is not valid JSON: ${So(o)}`)}return this.load(n)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Un,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Un,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Un,decorators:[{type:D,args:[{providedIn:"root"}]}]});function Qh(r,e){if(r===null||typeof r!="object")return"Loaded module is not an object";const t=r.default;if(t===null||typeof t!="object")return"Loaded module has no default export object";const n=t;return typeof n.id!="string"||n.id.length===0?"Default export is not an EditorPlugin (missing id)":typeof n.install!="function"?"Default export is not an EditorPlugin (missing install())":typeof n.apiVersion!="string"?"Loaded plugin is missing apiVersion":n.id!==e.id?`Loaded plugin id "${n.id}" does not match manifest id "${e.id}"`:Mr(n.apiVersion)!==Mr(O)?`Loaded plugin "${n.id}" targets API v${n.apiVersion} but host is v${O}`:t}function Mr(r){const e=/^(\d+)\./.exec(r);if(e===null)return null;const t=Number(e[1]);return Number.isFinite(t)?t:null}function De(r){return{ok:!1,error:r}}function So(r){return r instanceof Error?r.message:String(r)}function eg(r){return ci([{provide:xo,useValue:r.trustedOrigins},{provide:Do,useValue:r.moduleLoader}])}class ie{_anchors=b([],...ngDevMode?[{debugName:"_anchors"}]:[]);_dragState=b(null,...ngDevMode?[{debugName:"_dragState"}]:[]);_previewPoint=b(null,...ngDevMode?[{debugName:"_previewPoint"}]:[]);_snappingToFirst=b(!1,...ngDevMode?[{debugName:"_snappingToFirst"}]:[]);anchors=this._anchors.asReadonly();dragState=this._dragState.asReadonly();previewPoint=this._previewPoint.asReadonly();snappingToFirst=this._snappingToFirst.asReadonly();hasActivePath=m(()=>this._anchors().length>0,...ngDevMode?[{debugName:"hasActivePath"}]:[]);canClose=m(()=>this._anchors().length>=2,...ngDevMode?[{debugName:"canClose"}]:[]);beginPotentialDrag(e){this._dragState.set({start:e,current:e})}updateDrag(e){const t=this._dragState();t!==null&&this._dragState.set({start:t.start,current:e})}commitDrag(){const e=this._dragState();if(e===null)return;const{start:t,current:n}=e,o={x:2*t.x-n.x,y:2*t.y-n.y},a={point:t,handleIn:o,handleOut:n,kind:"symmetric"};this._anchors.update(l=>[...l,a]),this._dragState.set(null)}commitClick(){const e=this._dragState();if(e===null)return;const t=e.start,n={point:t,handleIn:t,handleOut:t,kind:"cusp"};this._anchors.update(o=>[...o,n]),this._dragState.set(null)}cancelDrag(){this._dragState.set(null)}updatePreview(e){this._previewPoint.set(e)}setSnappingToFirst(e){this._snappingToFirst.set(e)}reset(){this._anchors.set([]),this._dragState.set(null),this._previewPoint.set(null),this._snappingToFirst.set(!1)}buildOpenPath(){const e=this._anchors();return e.length<2?null:this.buildPathFromAnchors(e,!1)}buildClosedPath(){const e=this._anchors();return e.length<2?null:this.buildPathFromAnchors(e,!0)}buildPathFromAnchors(e,t){const o=vi([{anchors:e,closed:t}]);return N(o,{style:{fill:t&&this._fill()==="none"?"#000000":this._fill(),stroke:this._stroke(),strokeWidth:this._strokeWidth()}})}_fill=b("none",...ngDevMode?[{debugName:"_fill"}]:[]);_stroke=b("#000000",...ngDevMode?[{debugName:"_stroke"}]:[]);_strokeWidth=b(1,...ngDevMode?[{debugName:"_strokeWidth"}]:[]);_rubberBand=b(!0,...ngDevMode?[{debugName:"_rubberBand"}]:[]);fill=this._fill.asReadonly();stroke=this._stroke.asReadonly();strokeWidth=this._strokeWidth.asReadonly();rubberBand=this._rubberBand.asReadonly();setFill(e){this._fill.set(e)}setStroke(e){this._stroke.set(e)}setStrokeWidth(e){this._strokeWidth.set(Math.max(.5,Math.min(100,e)))}setRubberBand(e){this._rubberBand.set(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ie,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ie,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ie,decorators:[{type:D,args:[{providedIn:"root"}]}]});const gs="com.svge.tool.pen",tg=4,ps=8;class ng{id=gs;label="Pen";icon="draw";cursor="crosshair";shortcut="b";onActivate(e){e.injector.get(k).clear(),e.injector.get(ie).reset()}onDeactivate(e){e.injector.get(ie).reset()}onPointerDown(e,t){const n=t.injector.get(ie),o=n.anchors();if(o.length>=2){const i=o[0];if(Po(e.docPoint,i.point)<=ps){this.finalise(t,!0);return}}n.beginPotentialDrag(e.docPoint)}onPointerMove(e,t){const n=t.injector.get(ie);if(n.dragState()!==null){n.updateDrag(e.docPoint);return}n.updatePreview(e.docPoint);const i=n.anchors();if(i.length>=2){const a=i[0];n.setSnappingToFirst(Po(e.docPoint,a.point)<=ps)}else n.setSnappingToFirst(!1)}onPointerUp(e,t){const n=t.injector.get(ie),o=n.dragState();if(o===null)return;Po(o.start,o.current)<tg?n.commitClick():n.commitDrag()}onPointerCancel(e,t){t.injector.get(ie).cancelDrag()}onKeyDown(e,t){if(e.key==="Escape"){e.preventDefault(),t.injector.get(ie).reset();return}if(e.key==="Enter"){e.preventDefault(),this.finalise(t,!1);return}}finalise(e,t){const n=e.injector.get(ie),o=t?n.buildClosedPath():n.buildOpenPath();o!==null&&(e.injector.get(M).dispatch(new he(te,o)),n.reset())}}const fs={id:"com.svge.tools.pen",name:"Pen Tool (builtin)",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(de);r.track(e.register(new ng))}};function Po(r,e){const t=e.x-r.x,n=e.y-r.y;return Math.hypot(t,n)}const rg=8,og=6;class Wn{pen=f(ie);viewport=f(A);anchorSize=m(()=>rg/this.viewport.zoom(),...ngDevMode?[{debugName:"anchorSize"}]:[]);anchorHalf=m(()=>this.anchorSize()/2,...ngDevMode?[{debugName:"anchorHalf"}]:[]);handleHalf=m(()=>og/this.viewport.zoom()/2,...ngDevMode?[{debugName:"handleHalf"}]:[]);visible=m(()=>this.pen.hasActivePath()||this.pen.dragState()!==null,...ngDevMode?[{debugName:"visible"}]:[]);committedSegments=m(()=>{const e=this.pen.anchors();if(e.length<2)return[];const t=[];for(let n=0;n<e.length-1;n++){const o=e[n],i=e[n+1];t.push({key:`seg-${n}`,d:Mo(o,i)})}return t},...ngDevMode?[{debugName:"committedSegments"}]:[]);rubberBand=m(()=>{if(this.pen.dragState()!==null)return null;const e=this.pen.anchors(),t=this.pen.previewPoint();if(e.length===0||t===null)return null;const n=e[e.length-1];return Mo(n,{point:t,handleIn:t,handleOut:t,kind:"cusp"})},...ngDevMode?[{debugName:"rubberBand"}]:[]);dragHandlePreview=m(()=>{const e=this.pen.dragState();if(e===null)return null;const{start:t,current:n}=e;if(t.x===n.x&&t.y===n.y)return null;const o=n,i={x:2*t.x-n.x,y:2*t.y-n.y};return{start:t,handleIn:i,handleOut:o}},...ngDevMode?[{debugName:"dragHandlePreview"}]:[]);dragCurvePreview=m(()=>{const e=this.dragHandlePreview();if(e===null)return null;const t=this.pen.anchors();if(t.length===0)return null;const n=t[t.length-1],o={point:e.start,handleIn:e.handleIn,handleOut:e.handleOut,kind:"symmetric"};return Mo(n,o)},...ngDevMode?[{debugName:"dragCurvePreview"}]:[]);anchorViews=m(()=>{const e=this.pen.anchors(),t=this.pen.snappingToFirst();return e.map((n,o)=>({key:`anchor-${o}`,point:n.point,isSnapTarget:o===0&&t}))},...ngDevMode?[{debugName:"anchorViews"}]:[]);handleViews=m(()=>{const e=[],t=this.pen.anchors();for(let n=0;n<t.length;n++){const o=t[n];_r(o.handleIn,o.point)||e.push({key:`h-in-${n}`,from:o.point,to:o.handleIn}),_r(o.handleOut,o.point)||e.push({key:`h-out-${n}`,from:o.point,to:o.handleOut})}return e},...ngDevMode?[{debugName:"handleViews"}]:[]);static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Wn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:Wn,isStandalone:!0,selector:"g[svgePenOverlay]",host:{attributes:{"aria-hidden":"true"}},ngImport:s,template:`
523
+ @if (visible()) {
524
+ <!-- Committed segments between consecutive placed anchors. -->
525
+ @for (seg of committedSegments(); track seg.key) {
526
+ <svg:path class="pen-segment" [attr.d]="seg.d"></svg:path>
527
+ }
528
+
529
+ <!-- Rubber band from last anchor to cursor (only when no drag in progress). -->
530
+ @if (rubberBand(); as rb) {
531
+ <svg:path class="pen-rubber" [attr.d]="rb"></svg:path>
532
+ }
533
+
534
+ <!-- In-progress curve segment being formed during a drag \u2014 gives
535
+ real-time feedback of the Bezier the user is creating before
536
+ release, instead of just showing the handle stems. -->
537
+ @if (dragCurvePreview(); as cd) {
538
+ <svg:path class="pen-segment" [attr.d]="cd"></svg:path>
539
+ }
540
+
541
+ <!-- In-progress symmetric handle preview during a drag. -->
542
+ @if (dragHandlePreview(); as h) {
543
+ <svg:line
544
+ class="pen-handle-stem"
545
+ [attr.x1]="h.start.x"
546
+ [attr.y1]="h.start.y"
547
+ [attr.x2]="h.handleOut.x"
548
+ [attr.y2]="h.handleOut.y"
549
+ ></svg:line>
550
+ <svg:line
551
+ class="pen-handle-stem"
552
+ [attr.x1]="h.start.x"
553
+ [attr.y1]="h.start.y"
554
+ [attr.x2]="h.handleIn.x"
555
+ [attr.y2]="h.handleIn.y"
556
+ ></svg:line>
557
+ <svg:circle
558
+ class="pen-handle-knob"
559
+ [attr.cx]="h.handleOut.x"
560
+ [attr.cy]="h.handleOut.y"
561
+ [attr.r]="handleHalf()"
562
+ ></svg:circle>
563
+ <svg:circle
564
+ class="pen-handle-knob"
565
+ [attr.cx]="h.handleIn.x"
566
+ [attr.cy]="h.handleIn.y"
567
+ [attr.r]="handleHalf()"
568
+ ></svg:circle>
569
+ }
570
+
571
+ <!-- Anchor squares (committed). First anchor gets snap-target style. -->
572
+ @for (a of anchorViews(); track a.key) {
573
+ <svg:rect
574
+ class="pen-anchor"
575
+ [class.snap-target]="a.isSnapTarget"
576
+ [attr.x]="a.point.x - anchorHalf()"
577
+ [attr.y]="a.point.y - anchorHalf()"
578
+ [attr.width]="anchorSize()"
579
+ [attr.height]="anchorSize()"
580
+ ></svg:rect>
581
+ }
582
+
583
+ <!-- Handle circles + stems for smooth/symmetric committed anchors. -->
584
+ @for (h of handleViews(); track h.key) {
585
+ <svg:line
586
+ class="pen-handle-stem"
587
+ [attr.x1]="h.from.x"
588
+ [attr.y1]="h.from.y"
589
+ [attr.x2]="h.to.x"
590
+ [attr.y2]="h.to.y"
591
+ ></svg:line>
592
+ <svg:circle
593
+ class="pen-handle-knob"
594
+ [attr.cx]="h.to.x"
595
+ [attr.cy]="h.to.y"
596
+ [attr.r]="handleHalf()"
597
+ ></svg:circle>
598
+ }
599
+ }
600
+ `,isInline:!0,styles:[`.pen-segment{fill:none;stroke:#1976d2;stroke-width:1.5;vector-effect:non-scaling-stroke;pointer-events:none}.pen-rubber{fill:none;stroke:#1976d2;stroke-width:1;stroke-dasharray:4 3;vector-effect:non-scaling-stroke;pointer-events:none;opacity:.7}.pen-anchor{fill:#fff;stroke:#1976d2;stroke-width:1.5;vector-effect:non-scaling-stroke;pointer-events:none}.pen-anchor.snap-target{fill:#ff6f00;stroke:#ff6f00}.pen-handle-knob{fill:#1976d2;stroke:#fff;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.pen-handle-stem{stroke:#90caf9;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}
601
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Wn,decorators:[{type:W,args:[{selector:"g[svgePenOverlay]",standalone:!0,host:{"aria-hidden":"true"},template:`
602
+ @if (visible()) {
603
+ <!-- Committed segments between consecutive placed anchors. -->
604
+ @for (seg of committedSegments(); track seg.key) {
605
+ <svg:path class="pen-segment" [attr.d]="seg.d"></svg:path>
606
+ }
607
+
608
+ <!-- Rubber band from last anchor to cursor (only when no drag in progress). -->
609
+ @if (rubberBand(); as rb) {
610
+ <svg:path class="pen-rubber" [attr.d]="rb"></svg:path>
611
+ }
612
+
613
+ <!-- In-progress curve segment being formed during a drag \u2014 gives
614
+ real-time feedback of the Bezier the user is creating before
615
+ release, instead of just showing the handle stems. -->
616
+ @if (dragCurvePreview(); as cd) {
617
+ <svg:path class="pen-segment" [attr.d]="cd"></svg:path>
618
+ }
619
+
620
+ <!-- In-progress symmetric handle preview during a drag. -->
621
+ @if (dragHandlePreview(); as h) {
622
+ <svg:line
623
+ class="pen-handle-stem"
624
+ [attr.x1]="h.start.x"
625
+ [attr.y1]="h.start.y"
626
+ [attr.x2]="h.handleOut.x"
627
+ [attr.y2]="h.handleOut.y"
628
+ ></svg:line>
629
+ <svg:line
630
+ class="pen-handle-stem"
631
+ [attr.x1]="h.start.x"
632
+ [attr.y1]="h.start.y"
633
+ [attr.x2]="h.handleIn.x"
634
+ [attr.y2]="h.handleIn.y"
635
+ ></svg:line>
636
+ <svg:circle
637
+ class="pen-handle-knob"
638
+ [attr.cx]="h.handleOut.x"
639
+ [attr.cy]="h.handleOut.y"
640
+ [attr.r]="handleHalf()"
641
+ ></svg:circle>
642
+ <svg:circle
643
+ class="pen-handle-knob"
644
+ [attr.cx]="h.handleIn.x"
645
+ [attr.cy]="h.handleIn.y"
646
+ [attr.r]="handleHalf()"
647
+ ></svg:circle>
648
+ }
649
+
650
+ <!-- Anchor squares (committed). First anchor gets snap-target style. -->
651
+ @for (a of anchorViews(); track a.key) {
652
+ <svg:rect
653
+ class="pen-anchor"
654
+ [class.snap-target]="a.isSnapTarget"
655
+ [attr.x]="a.point.x - anchorHalf()"
656
+ [attr.y]="a.point.y - anchorHalf()"
657
+ [attr.width]="anchorSize()"
658
+ [attr.height]="anchorSize()"
659
+ ></svg:rect>
660
+ }
661
+
662
+ <!-- Handle circles + stems for smooth/symmetric committed anchors. -->
663
+ @for (h of handleViews(); track h.key) {
664
+ <svg:line
665
+ class="pen-handle-stem"
666
+ [attr.x1]="h.from.x"
667
+ [attr.y1]="h.from.y"
668
+ [attr.x2]="h.to.x"
669
+ [attr.y2]="h.to.y"
670
+ ></svg:line>
671
+ <svg:circle
672
+ class="pen-handle-knob"
673
+ [attr.cx]="h.to.x"
674
+ [attr.cy]="h.to.y"
675
+ [attr.r]="handleHalf()"
676
+ ></svg:circle>
677
+ }
678
+ }
679
+ `,changeDetection:U.OnPush,styles:[`.pen-segment{fill:none;stroke:#1976d2;stroke-width:1.5;vector-effect:non-scaling-stroke;pointer-events:none}.pen-rubber{fill:none;stroke:#1976d2;stroke-width:1;stroke-dasharray:4 3;vector-effect:non-scaling-stroke;pointer-events:none;opacity:.7}.pen-anchor{fill:#fff;stroke:#1976d2;stroke-width:1.5;vector-effect:non-scaling-stroke;pointer-events:none}.pen-anchor.snap-target{fill:#ff6f00;stroke:#ff6f00}.pen-handle-knob{fill:#1976d2;stroke:#fff;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.pen-handle-stem{stroke:#90caf9;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}
680
+ `]}]}]});function Mo(r,e){const t=_r(r.handleOut,r.point),n=_r(e.handleIn,e.point);return t&&n?`M${fe(r.point.x)} ${fe(r.point.y)} L${fe(e.point.x)} ${fe(e.point.y)}`:`M${fe(r.point.x)} ${fe(r.point.y)} C${fe(r.handleOut.x)} ${fe(r.handleOut.y)} ${fe(e.handleIn.x)} ${fe(e.handleIn.y)} ${fe(e.point.x)} ${fe(e.point.y)}`}function _r(r,e,t=1e-6){return Math.abs(r.x-e.x)<t&&Math.abs(r.y-e.y)<t}function fe(r){return Number.isInteger(r)?`${r}`:Number(r.toFixed(4)).toString()}class Kn{pencil=f(we);previewD=m(()=>this.pencil.hasDraft()?bo(this.pencil.points()):null,...ngDevMode?[{debugName:"previewD"}]:[]);static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Kn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:Kn,isStandalone:!0,selector:"g[svgePencilOverlay]",host:{attributes:{"aria-hidden":"true"}},ngImport:s,template:`
681
+ @if (previewD(); as d) {
682
+ <svg:path class="pencil-draft" [attr.d]="d"></svg:path>
683
+ }
684
+ `,isInline:!0,styles:[`.pencil-draft{fill:none;stroke:#1976d2;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke;pointer-events:none;opacity:.85}
685
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Kn,decorators:[{type:W,args:[{selector:"g[svgePencilOverlay]",standalone:!0,host:{"aria-hidden":"true"},template:`
686
+ @if (previewD(); as d) {
687
+ <svg:path class="pencil-draft" [attr.d]="d"></svg:path>
688
+ }
689
+ `,changeDetection:U.OnPush,styles:[`.pencil-draft{fill:none;stroke:#1976d2;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke;pointer-events:none;opacity:.85}
690
+ `]}]}]});class se{_draft=b(null,...ngDevMode?[{debugName:"_draft"}]:[]);draft=this._draft.asReadonly();isDrafting=m(()=>this._draft()!==null,...ngDevMode?[{debugName:"isDrafting"}]:[]);_fill=b("none",...ngDevMode?[{debugName:"_fill"}]:[]);_stroke=b("#000000",...ngDevMode?[{debugName:"_stroke"}]:[]);_strokeWidth=b(1,...ngDevMode?[{debugName:"_strokeWidth"}]:[]);_cornerRadius=b(0,...ngDevMode?[{debugName:"_cornerRadius"}]:[]);_polygonSides=b(vs,...ngDevMode?[{debugName:"_polygonSides"}]:[]);_starMode=b(!1,...ngDevMode?[{debugName:"_starMode"}]:[]);_starInnerRadius=b(.5,...ngDevMode?[{debugName:"_starInnerRadius"}]:[]);fill=this._fill.asReadonly();stroke=this._stroke.asReadonly();strokeWidth=this._strokeWidth.asReadonly();cornerRadius=this._cornerRadius.asReadonly();polygonSides=this._polygonSides.asReadonly();starMode=this._starMode.asReadonly();starInnerRadius=this._starInnerRadius.asReadonly();setFill(e){this._fill.set(e)}setStroke(e){this._stroke.set(e)}setStrokeWidth(e){this._strokeWidth.set(Math.max(0,Math.min(200,e)))}setCornerRadius(e){this._cornerRadius.set(Math.max(0,Math.min(500,e)))}setPolygonSides(e){this._polygonSides.set(Math.max(3,Math.min(32,Math.round(e))))}setStarMode(e){this._starMode.set(e)}setStarInnerRadius(e){this._starInnerRadius.set(Math.max(.1,Math.min(.95,e)))}begin(e,t,n){this._draft.set({kind:e,start:t,current:t,constrainAspect:n.shift,fromCenter:n.alt})}update(e,t){const n=this._draft();n!==null&&this._draft.set({kind:n.kind,start:n.start,current:e,constrainAspect:t.shift,fromCenter:t.alt})}cancel(){this._draft.set(null)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:se,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:se,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:se,decorators:[{type:D,args:[{providedIn:"root"}]}]});function ms(r){let e=r.current.x-r.start.x,t=r.current.y-r.start.y;if(r.constrainAspect){const i=Math.min(Math.abs(e),Math.abs(t));e=Math.sign(e||1)*i,t=Math.sign(t||1)*i}if(r.fromCenter){const i=Math.abs(e)*2,a=Math.abs(t)*2;return{x:r.start.x-Math.abs(e),y:r.start.y-Math.abs(t),w:i,h:a}}const n=e>=0?r.start.x:r.start.x+e,o=t>=0?r.start.y:r.start.y+t;return{x:n,y:o,w:Math.abs(e),h:Math.abs(t)}}const vs=6;function ys(r,e){const t=Math.max(3,Math.min(32,Math.round(e)));if(r.w===0||r.h===0)return[];const n=r.x+r.w/2,o=r.y+r.h/2,i=r.w/2,a=r.h/2,l=[];for(let c=0;c<t;c++){const u=-Math.PI/2+c/t*Math.PI*2;l.push({x:n+i*Math.cos(u),y:o+a*Math.sin(u)})}return l}function ig(r,e,t){const n=Math.max(3,Math.min(32,Math.round(e)));if(r.w===0||r.h===0)return[];const o=r.x+r.w/2,i=r.y+r.h/2,a=r.w/2,l=r.h/2,c=Math.max(.1,Math.min(.95,t)),u=a*c,h=l*c,g=[];for(let v=0;v<n*2;v++){const p=-Math.PI/2+v/(n*2)*Math.PI*2,x=v%2===0,E=x?a:u,C=x?l:h;g.push({x:o+E*Math.cos(p),y:i+C*Math.sin(p)})}return g}function bs(r,e){return e.star?ig(r,e.sides,e.innerFraction):ys(r,e.sides)}const ws="com.svge.tool.rectangle",Is="com.svge.tool.ellipse",ks="com.svge.tool.polygon",xs=2;class _o{kind;id;label;icon;cursor="crosshair";shortcut;constructor(e,t,n,o){this.kind=o,this.id=e,this.label=t,this.shortcut=n,this.icon=o==="rect"?"crop_square":o==="ellipse"?"radio_button_unchecked":"pentagon"}onActivate(e){e.injector.get(k).clear(),e.injector.get(se).cancel()}onDeactivate(e){e.injector.get(se).cancel()}onPointerDown(e,t){t.injector.get(se).begin(this.kind,e.docPoint,{shift:e.shiftKey,alt:e.altKey})}onPointerMove(e,t){const n=t.injector.get(se);n.isDrafting()&&n.update(e.docPoint,{shift:e.shiftKey,alt:e.altKey})}onPointerUp(e,t){const n=t.injector.get(se),o=n.draft();if(o===null)return;const i=ms(o);if(n.cancel(),i.w<xs||i.h<xs)return;const a=sg(this.kind,i,n);a!==null&&t.injector.get(M).dispatch(new he(te,a))}onPointerCancel(e,t){t.injector.get(se).cancel()}onKeyDown(e,t){e.key==="Escape"&&(e.preventDefault(),t.injector.get(se).cancel())}}function sg(r,e,t){const n={fill:t.fill(),stroke:t.stroke(),strokeWidth:t.strokeWidth()};switch(r){case"rect":{const o=t.cornerRadius(),i={x:e.x,y:e.y,width:e.w,height:e.h};return o>0&&(i.rx=o,i.ry=o),qr(i,{style:n})}case"ellipse":return yi({cx:e.x+e.w/2,cy:e.y+e.h/2,rx:e.w/2,ry:e.h/2},{style:n});case"polygon":{const o=bs(e,{sides:t.polygonSides(),star:t.starMode(),innerFraction:t.starInnerRadius()});return o.length===0?null:Yr(o,{style:n})}}}const Ds={id:"com.svge.tools.shapes",name:"Shape Tools (builtin)",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(de);r.track(e.register(new _o(ws,"Rectangle","r","rect"))),r.track(e.register(new _o(Is,"Ellipse","e","ellipse"))),r.track(e.register(new _o(ks,"Polygon","y","polygon")))}};class Xn{shapes=f(se);visible=m(()=>{const e=this.shapes.draft();if(e===null)return null;const t=ms(e);let n="",o=0;return e.kind==="rect"?o=this.shapes.cornerRadius():e.kind==="polygon"&&(n=bs(t,{sides:this.shapes.polygonSides(),star:this.shapes.starMode(),innerFraction:this.shapes.starInnerRadius()}).map(a=>`${a.x},${a.y}`).join(" ")),{kind:e.kind,bounds:t,cornerRadius:o,pointsAttr:n}},...ngDevMode?[{debugName:"visible"}]:[]);static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Xn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:Xn,isStandalone:!0,selector:"g[svgeShapeOverlay]",host:{attributes:{"aria-hidden":"true"}},ngImport:s,template:`
691
+ @if (visible(); as v) {
692
+ @switch (v.kind) {
693
+ @case ('rect') {
694
+ <svg:rect
695
+ class="shape-draft"
696
+ [attr.x]="v.bounds.x"
697
+ [attr.y]="v.bounds.y"
698
+ [attr.width]="v.bounds.w"
699
+ [attr.height]="v.bounds.h"
700
+ [attr.rx]="v.cornerRadius || null"
701
+ [attr.ry]="v.cornerRadius || null"
702
+ />
703
+ }
704
+ @case ('ellipse') {
705
+ <svg:ellipse
706
+ class="shape-draft"
707
+ [attr.cx]="v.bounds.x + v.bounds.w / 2"
708
+ [attr.cy]="v.bounds.y + v.bounds.h / 2"
709
+ [attr.rx]="v.bounds.w / 2"
710
+ [attr.ry]="v.bounds.h / 2"
711
+ />
712
+ }
713
+ @case ('polygon') {
714
+ <svg:polygon class="shape-draft" [attr.points]="v.pointsAttr" />
715
+ }
716
+ }
717
+ }
718
+ `,isInline:!0,styles:[`.shape-draft{fill:none;stroke:#1976d2;stroke-width:1;stroke-dasharray:4 3;vector-effect:non-scaling-stroke;pointer-events:none;opacity:.8}
719
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Xn,decorators:[{type:W,args:[{selector:"g[svgeShapeOverlay]",standalone:!0,host:{"aria-hidden":"true"},template:`
720
+ @if (visible(); as v) {
721
+ @switch (v.kind) {
722
+ @case ('rect') {
723
+ <svg:rect
724
+ class="shape-draft"
725
+ [attr.x]="v.bounds.x"
726
+ [attr.y]="v.bounds.y"
727
+ [attr.width]="v.bounds.w"
728
+ [attr.height]="v.bounds.h"
729
+ [attr.rx]="v.cornerRadius || null"
730
+ [attr.ry]="v.cornerRadius || null"
731
+ />
732
+ }
733
+ @case ('ellipse') {
734
+ <svg:ellipse
735
+ class="shape-draft"
736
+ [attr.cx]="v.bounds.x + v.bounds.w / 2"
737
+ [attr.cy]="v.bounds.y + v.bounds.h / 2"
738
+ [attr.rx]="v.bounds.w / 2"
739
+ [attr.ry]="v.bounds.h / 2"
740
+ />
741
+ }
742
+ @case ('polygon') {
743
+ <svg:polygon class="shape-draft" [attr.points]="v.pointsAttr" />
744
+ }
745
+ }
746
+ }
747
+ `,changeDetection:U.OnPush,styles:[`.shape-draft{fill:none;stroke:#1976d2;stroke-width:1;stroke-dasharray:4 3;vector-effect:non-scaling-stroke;pointer-events:none;opacity:.8}
748
+ `]}]}]});class ot{_editingId=b(null,...ngDevMode?[{debugName:"_editingId"}]:[]);_isPlaceholder=b(!1,...ngDevMode?[{debugName:"_isPlaceholder"}]:[]);editingId=this._editingId.asReadonly();isPlaceholder=this._isPlaceholder.asReadonly();beginEdit(e,t){this._editingId.set(e),this._isPlaceholder.set(t)}endEdit(){this._editingId.set(null),this._isPlaceholder.set(!1)}_fontFamily=b(null,...ngDevMode?[{debugName:"_fontFamily"}]:[]);_fontSize=b(null,...ngDevMode?[{debugName:"_fontSize"}]:[]);_fontWeight=b(null,...ngDevMode?[{debugName:"_fontWeight"}]:[]);_fontStyle=b(null,...ngDevMode?[{debugName:"_fontStyle"}]:[]);_textAnchor=b("start",...ngDevMode?[{debugName:"_textAnchor"}]:[]);_fill=b("#000000",...ngDevMode?[{debugName:"_fill"}]:[]);fontFamily=this._fontFamily.asReadonly();fontSize=this._fontSize.asReadonly();fontWeight=this._fontWeight.asReadonly();fontStyle=this._fontStyle.asReadonly();textAnchor=this._textAnchor.asReadonly();fill=this._fill.asReadonly();setFontFamily(e){this._fontFamily.set(e)}setFontSize(e){if(e===null){this._fontSize.set(null);return}Number.isFinite(e)&&e>0&&this._fontSize.set(Math.min(400,e))}setFontWeight(e){this._fontWeight.set(e)}setItalic(e){this._fontStyle.set(e?"italic":null)}setTextAnchor(e){this._textAnchor.set(e)}setFill(e){this._fill.set(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ot,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ot,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ot,decorators:[{type:D,args:[{providedIn:"root"}]}]});const Ss="com.svge.tool.text",Er="Type here",ag=16;class lg{id=Ss;label="Text";icon="title";cursor="text";shortcut="t";onActivate(e){e.injector.get(k).clear()}onPointerDown(e,t){if(e.raw.button!==0)return;const n=t.injector.get(S),o=t.injector.get(ot),i=Oi(e.raw);if(i!==null){const v=T(n.document().root,i);if(v!==null&&v.type==="text"){o.beginEdit(i,!1);return}}const a=o.fontSize()??ag,l=Zr({x:e.docPoint.x,y:e.docPoint.y+a*.8,content:Er,fontSize:a},{style:{fill:o.fill()}}),c=o.fontFamily();c!==null&&(l.fontFamily=c);const u=o.fontWeight();u!==null&&(l.fontWeight=u);const h=o.fontStyle();h!==null&&(l.fontStyle=h);const g=o.textAnchor();g!=="start"&&(l.textAnchor=g),t.injector.get(M).dispatch(new he(te,l)),o.beginEdit(l.id,!0)}}const Ps={id:"com.svge.tools.text",name:"Text Tool (builtin)",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(de);r.track(e.register(new lg))}};class Yn{state=f(S);bus=f(M);editorSvc=f(ot);editorEl=jd("editor",...ngDevMode?[{debugName:"editorEl"}]:[]);Math=globalThis.Math;_target=b(null,...ngDevMode?[{debugName:"_target"}]:[]);target=this._target.asReadonly();constructor(){J(()=>{const e=this.editorSvc.editingId();if(e===null){this._target.set(null);return}const t=this.state.document().root,n=T(t,e);if(n===null||n.type!=="text"){this.editorSvc.endEdit();return}const o=n,i=o.fontSize??16,a=An(t,e),l=K(a,o.x,o.y);this._target.set({nodeId:e,initialText:o.content,x:l.x,y:l.y,fontSize:i,color:o.style.fill??"#000000",estimatedWidth:Math.min(800,o.content.length*i*.6+20)})}),pr({read:()=>{const e=this.editorEl(),t=this._target();if(e===void 0||t===null)return;const n=e.nativeElement;if(n.dataset.seededFor===t.nodeId)return;n.dataset.seededFor=t.nodeId,n.textContent=t.initialText,n.focus();const o=window.getSelection?.(),i=document.createRange?.();o!=null&&i!==void 0&&(i.selectNodeContents(n),o.removeAllRanges(),o.addRange(i))}})}onKeyDown(e){if(e.key==="Enter"&&!e.shiftKey){e.preventDefault(),e.stopPropagation(),this.commitAndClose();return}if(e.key==="Enter"&&e.shiftKey){e.preventDefault(),e.stopPropagation(),document.execCommand("insertText",!1,`
749
+ `);return}if(e.key==="Escape"){e.preventDefault(),e.stopPropagation(),this.cancelAndClose();return}}commitAndClose(){const e=this.editorEl(),t=this._target();if(e===void 0||t===null)return;const n=(e.nativeElement.textContent??"").trim(),o=this.editorSvc.isPlaceholder();if(this.editorSvc.endEdit(),n.length===0&&o){this.bus.dispatch(new vr(t.nodeId));return}n!==t.initialText&&this.bus.dispatch(new yr(t.nodeId,"content",n))}cancelAndClose(){const e=this._target(),t=this.editorSvc.isPlaceholder();if(e!==null&&t){const o=(this.editorEl()?.nativeElement.textContent??"").trim(),i=T(this.state.document().root,e.nodeId),l=(i!==null&&i.type==="text"?i.content:"")===Er,c=o.length===0||o===Er;(l||c)&&this.bus.dispatch(new vr(e.nodeId))}this.editorSvc.endEdit()}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Yn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:Yn,isStandalone:!0,selector:"g[svgeInlineTextEditor]",viewQueries:[{propertyName:"editorEl",first:!0,predicate:["editor"],descendants:!0,isSignal:!0}],ngImport:s,template:`
750
+ @if (target(); as t) {
751
+ <svg:foreignObject
752
+ [attr.x]="t.x"
753
+ [attr.y]="t.y - t.fontSize * 0.8"
754
+ [attr.width]="Math.max(200, t.estimatedWidth)"
755
+ [attr.height]="t.fontSize * 1.4"
756
+ >
757
+ <!--
758
+ xmlns is REQUIRED on the root HTML element inside foreignObject
759
+ \u2014 without it, browsers parse the content as SVG-namespace and
760
+ contentEditable / focus / typing all silently fail.
761
+ -->
762
+ <div
763
+ #editor
764
+ xmlns="http://www.w3.org/1999/xhtml"
765
+ class="inline-text-editor"
766
+ contenteditable="true"
767
+ spellcheck="true"
768
+ role="textbox"
769
+ aria-label="Edit text content"
770
+ [style.font-size.px]="t.fontSize"
771
+ [style.color]="t.color"
772
+ (keydown)="onKeyDown($event)"
773
+ (blur)="commitAndClose()"
774
+ ></div>
775
+ </svg:foreignObject>
776
+ }
777
+ `,isInline:!0,styles:[`.inline-text-editor{display:inline-block;min-width:4ch;padding:0 2px;outline:2px solid #1976d2;background:#ffffffd9;font-family:sans-serif;line-height:1.2;white-space:pre-wrap;cursor:text}.inline-text-editor:focus-visible{outline-color:#1976d2;outline-offset:0}
778
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Yn,decorators:[{type:W,args:[{selector:"g[svgeInlineTextEditor]",standalone:!0,template:`
779
+ @if (target(); as t) {
780
+ <svg:foreignObject
781
+ [attr.x]="t.x"
782
+ [attr.y]="t.y - t.fontSize * 0.8"
783
+ [attr.width]="Math.max(200, t.estimatedWidth)"
784
+ [attr.height]="t.fontSize * 1.4"
785
+ >
786
+ <!--
787
+ xmlns is REQUIRED on the root HTML element inside foreignObject
788
+ \u2014 without it, browsers parse the content as SVG-namespace and
789
+ contentEditable / focus / typing all silently fail.
790
+ -->
791
+ <div
792
+ #editor
793
+ xmlns="http://www.w3.org/1999/xhtml"
794
+ class="inline-text-editor"
795
+ contenteditable="true"
796
+ spellcheck="true"
797
+ role="textbox"
798
+ aria-label="Edit text content"
799
+ [style.font-size.px]="t.fontSize"
800
+ [style.color]="t.color"
801
+ (keydown)="onKeyDown($event)"
802
+ (blur)="commitAndClose()"
803
+ ></div>
804
+ </svg:foreignObject>
805
+ }
806
+ `,changeDetection:U.OnPush,styles:[`.inline-text-editor{display:inline-block;min-width:4ch;padding:0 2px;outline:2px solid #1976d2;background:#ffffffd9;font-family:sans-serif;line-height:1.2;white-space:pre-wrap;cursor:text}.inline-text-editor:focus-visible{outline-color:#1976d2;outline-offset:0}
807
+ `]}]}],ctorParameters:()=>[],propDecorators:{editorEl:[{type:s.ViewChild,args:["editor",{isSignal:!0}]}]}});function On(r){return`${r.nodeId}|${r.subpathIndex}|${r.anchorIndex}`}class Ce{_selected=b(new Set,...ngDevMode?[{debugName:"_selected"}]:[]);_refs=b([],...ngDevMode?[{debugName:"_refs"}]:[]);selected=this._refs.asReadonly();count=m(()=>this._refs().length,...ngDevMode?[{debugName:"count"}]:[]);isEmpty=m(()=>this._refs().length===0,...ngDevMode?[{debugName:"isEmpty"}]:[]);isSingle=m(()=>this._refs().length===1,...ngDevMode?[{debugName:"isSingle"}]:[]);selectOne(e){const t=On(e);this._selected.set(new Set([t])),this._refs.set([e])}toggle(e){const t=On(e),n=this._selected();if(n.has(t)){const o=new Set(n);o.delete(t),this._selected.set(o),this._refs.set(this._refs().filter(i=>On(i)!==t))}else this._selected.set(new Set([...n,t])),this._refs.set([...this._refs(),e])}isSelected(e){return this._selected().has(On(e))}clear(){this._selected().size!==0&&(this._selected.set(new Set),this._refs.set([]))}clearForOtherNodes(e){const t=this._refs().filter(n=>n.nodeId===e);t.length!==this._refs().length&&(this._refs.set(t),this._selected.set(new Set(t.map(On))))}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ce,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ce,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ce,decorators:[{type:D,args:[{providedIn:"root"}]}]});class it{state=f(S);_isolationRootId=b(null,...ngDevMode?[{debugName:"_isolationRootId"}]:[]);isolationRootId=this._isolationRootId.asReadonly();isActive=m(()=>this._isolationRootId()!==null,...ngDevMode?[{debugName:"isActive"}]:[]);breadcrumbPath=m(()=>{const e=this._isolationRootId();if(e===null)return[];const t=this.state.document().root,n=[];let o=e,i=1e3;for(;o!==null&&i>0&&(n.push(o),o!==t.id);){const a=ft(t,o);o=a===null?null:a.id,i-=1}return n[n.length-1]!==t.id?[]:n.reverse().filter(a=>a===t.id?!0:Eo(T(t,a)))},...ngDevMode?[{debugName:"breadcrumbPath"}]:[]);enter(e){if(this._isolationRootId()===e)return!1;const t=T(this.state.document().root,e);return Eo(t)?(this._isolationRootId.set(e),!0):!1}exit(){this._isolationRootId()!==null&&this._isolationRootId.set(null)}exitOne(){const e=this._isolationRootId();if(e===null)return;const t=this.state.document().root;let n=ft(t,e);for(;n!==null&&n.id!==t.id&&!Eo(n);)n=ft(t,n.id);if(n===null||n.id===t.id){this.exit();return}this._isolationRootId.set(n.id)}setRoot(e){if(e===null){this.exit();return}this.enter(e)}isInScope(e){const t=this._isolationRootId();if(t===null||e===t)return!0;const n=this.state.document().root,o=T(n,t);return o===null||!Fe(o)?!0:Ms(o,e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:it,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:it,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:it,decorators:[{type:D,args:[{providedIn:"root"}]}]});function Eo(r){return r!==null&&Fe(r)&&!zt(r)&&!$e(r)}function Ms(r,e){if(!Fe(r))return!1;for(const t of r.children)if(t.id===e||Fe(t)&&Ms(t,e))return!0;return!1}const _s="svge:keybindings:v1";class rn{registry=f(tt);document=f(re);_overrides=b({},...ngDevMode?[{debugName:"_overrides"}]:[]);overrides=this._overrides.asReadonly();constructor(){this._overrides.set(this.load())}effectiveEntries=m(()=>{const e=this._overrides(),t=[];for(const n of this.registry.shortcuts()){const o=this.effectiveCombo(n,e);if(o===null||o.length===0)continue;let i;try{i=En(o)}catch{continue}t.push({shortcut:n,parsed:i})}return t},...ngDevMode?[{debugName:"effectiveEntries"}]:[]);bindings=m(()=>{const e=this._overrides(),t=this.registry.shortcuts(),n=new Map;for(const i of t){const a=this.effectiveCombo(i,e);if(a===null||a.length===0)continue;const l=Kt(a);n.set(l,(n.get(l)??0)+1)}return[...t.map(i=>{const a=Object.prototype.hasOwnProperty.call(e,i.id),l=a?e[i.id]:i.combo,c=l===null||l.length===0,u=c?null:l;return{id:i.id,description:i.description??i.id,category:i.category??"Other",defaultCombo:i.combo,combo:u,isCustom:a,isUnbound:c,conflict:u!==null&&(n.get(Kt(u))??0)>1}})].sort((i,a)=>i.category!==a.category?i.category.localeCompare(a.category):i.description.localeCompare(a.description))},...ngDevMode?[{debugName:"bindings"}]:[]);hasCustomizations=m(()=>Object.keys(this._overrides()).length>0,...ngDevMode?[{debugName:"hasCustomizations"}]:[]);tryMatch(e){for(const t of this.effectiveEntries()){if(!oo(t.parsed,e))continue;const n=t.shortcut.when;if(!(n!=null&&!n()))return t.shortcut}return null}setBinding(e,t){const n=io(t);if(!n.ok)return n;const o=this.registry.get(e)?.combo??null;return this._overrides.update(i=>{const a={...i};return o!==null&&Kt(t)===Kt(o)?delete a[e]:a[e]=t,a}),this.save(),{ok:!0}}unbind(e){this._overrides.update(t=>({...t,[e]:null})),this.save()}resetBinding(e){this._overrides.update(t=>{if(!Object.prototype.hasOwnProperty.call(t,e))return t;const n={...t};return delete n[e],n}),this.save()}resetAll(){this._overrides.set({}),this.save()}validate(e){return io(e)}conflictIdsFor(e,t){if(e.length===0)return[];const n=Kt(e),o=this._overrides(),i=[];for(const a of this.registry.shortcuts()){if(a.id===t)continue;const l=this.effectiveCombo(a,o);l===null||l.length===0||Kt(l)===n&&i.push(a.id)}return i}effectiveCombo(e,t){return Object.prototype.hasOwnProperty.call(t,e.id)?t[e.id]:e.combo}load(){const e=this.window();if(e===null)return{};try{const t=e.localStorage.getItem(_s);if(t===null||t.length===0)return{};const n=JSON.parse(t);if(n===null||typeof n!="object"||Array.isArray(n))return{};const o={};for(const[i,a]of Object.entries(n))(typeof a=="string"||a===null)&&(o[i]=a);return o}catch{return{}}}save(){const e=this.window();if(e!==null)try{e.localStorage.setItem(_s,JSON.stringify(this._overrides()))}catch(t){console.warn("KeybindingsService: persist failed \u2014",t)}}window(){const e=this.document.defaultView;if(e!==null)try{if(typeof e.localStorage<"u")return e}catch{return null}return null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:rn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:rn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:rn,decorators:[{type:D,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});class _t{keybindings=f(rn);document=f(re);injector=f(Vt);listening=!1;handler=e=>{if(po(e.target))return;const t=this.keybindings.tryMatch(e);if(t===null)return;const n={injector:this.injector};t.run(e,n)};start(){this.listening||(this.document.addEventListener("keydown",this.handler),this.listening=!0)}stop(){this.listening&&(this.document.removeEventListener("keydown",this.handler),this.listening=!1)}ngOnDestroy(){this.stop()}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:_t,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:_t,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:_t,decorators:[{type:D,args:[{providedIn:"root"}]}]});const Es={kind:"transparent"},cg={top:0,right:0,bottom:0,left:0},Ts={width:800,height:600,orientation:"landscape",margins:cg},Rs={enabled:!1,spacing:20,majorEvery:5,color:"#90a4ae"},dg={enabled:!1},To=1,Ro=10,As={wheelZoomSpeed:5};function ug(r){return 2e-4*Math.max(To,Math.min(Ro,Math.round(r)))}function Cs(r,e){const t=e.width<=e.height,o=e.orientation==="portrait"!==t,i=o?e.height:e.width,a=o?e.width:e.height;return{x:0,y:0,width:i,height:a}}function Ao(r,e,t,n){return e!==null&&e.width>0&&e.height>0?{x:e.x,y:e.y,width:e.width,height:e.height}:r!==null&&r.width>0&&r.height>0?{x:r.x,y:r.y,width:r.width,height:r.height}:t!==null&&t.width>0&&t.height>0?Cs(n,t):null}class L{_background=b(Es,...ngDevMode?[{debugName:"_background"}]:[]);_page=b(Ts,...ngDevMode?[{debugName:"_page"}]:[]);_grid=b(Rs,...ngDevMode?[{debugName:"_grid"}]:[]);_rulers=b(dg,...ngDevMode?[{debugName:"_rulers"}]:[]);_guides=b([],...ngDevMode?[{debugName:"_guides"}]:[]);_guidesLocked=b(!1,...ngDevMode?[{debugName:"_guidesLocked"}]:[]);_interaction=b(As,...ngDevMode?[{debugName:"_interaction"}]:[]);_rulerCursor=b(null,...ngDevMode?[{debugName:"_rulerCursor"}]:[]);guideCounter=0;background=this._background.asReadonly();page=this._page.asReadonly();grid=this._grid.asReadonly();rulers=this._rulers.asReadonly();guides=this._guides.asReadonly();guidesLocked=this._guidesLocked.asReadonly();_selectedGuideId=b(null,...ngDevMode?[{debugName:"_selectedGuideId"}]:[]);selectedGuideId=this._selectedGuideId.asReadonly();_outlineMode=b(!1,...ngDevMode?[{debugName:"_outlineMode"}]:[]);outlineMode=this._outlineMode.asReadonly();setOutlineMode(e){this._outlineMode()!==e&&this._outlineMode.set(e)}toggleOutlineMode(){this.setOutlineMode(!this._outlineMode())}_pixelPreview=b(!1,...ngDevMode?[{debugName:"_pixelPreview"}]:[]);pixelPreview=this._pixelPreview.asReadonly();setPixelPreview(e){this._pixelPreview()!==e&&this._pixelPreview.set(e)}togglePixelPreview(){this.setPixelPreview(!this._pixelPreview())}_pixelPreviewRaster=b(!1,...ngDevMode?[{debugName:"_pixelPreviewRaster"}]:[]);pixelPreviewRaster=this._pixelPreviewRaster.asReadonly();setPixelPreviewRaster(e){this._pixelPreviewRaster()!==e&&this._pixelPreviewRaster.set(e)}togglePixelPreviewRaster(){this.setPixelPreviewRaster(!this._pixelPreviewRaster())}_pixelPreviewRasterReady=b(!1,...ngDevMode?[{debugName:"_pixelPreviewRasterReady"}]:[]);pixelPreviewRasterReady=this._pixelPreviewRasterReady.asReadonly();setPixelPreviewRasterReady(e){this._pixelPreviewRasterReady()!==e&&this._pixelPreviewRasterReady.set(e)}_presentationMode=b(!1,...ngDevMode?[{debugName:"_presentationMode"}]:[]);presentationMode=this._presentationMode.asReadonly();setPresentationMode(e){this._presentationMode()!==e&&this._presentationMode.set(e)}togglePresentationMode(){this.setPresentationMode(!this._presentationMode())}_timeline=b(!1,...ngDevMode?[{debugName:"_timeline"}]:[]);timeline=this._timeline.asReadonly();setTimelineEnabled(e){this._timeline()!==e&&this._timeline.set(e)}toggleTimeline(){this.setTimelineEnabled(!this._timeline())}interaction=this._interaction.asReadonly();rulerCursor=this._rulerCursor.asReadonly();isTransparentBackground=m(()=>this._background().kind==="transparent",...ngDevMode?[{debugName:"isTransparentBackground"}]:[]);setBackground(e){fg(e)&&(mg(this._background(),e)||this._background.set(e))}resetBackground(){this._background.set(Es)}patchPage(e){const t=this._page(),n=Co(e.width)?e.width:t.width,o=Co(e.height)?e.height:t.height,i=e.orientation??t.orientation,a=e.margins?{top:Tr(e.margins.top)?e.margins.top:t.margins.top,right:Tr(e.margins.right)?e.margins.right:t.margins.right,bottom:Tr(e.margins.bottom)?e.margins.bottom:t.margins.bottom,left:Tr(e.margins.left)?e.margins.left:t.margins.left}:t.margins,l={width:n,height:o,orientation:i,margins:a};gg(t,l)||this._page.set(l)}resetPage(){this._page.set(Ts)}patchGrid(e){const t=this._grid(),n=e.enabled??t.enabled,o=Co(e.spacing)?e.spacing:t.spacing,i=hg(e.majorEvery)?e.majorEvery:t.majorEvery,a=typeof e.color=="string"&&e.color.length>0?e.color:t.color,l={enabled:n,spacing:o,majorEvery:i,color:a};pg(t,l)||this._grid.set(l)}toggleGrid(){this.patchGrid({enabled:!this._grid().enabled})}resetGrid(){this._grid.set(Rs)}setRulersEnabled(e){this._rulers().enabled!==e&&this._rulers.set({enabled:e})}toggleRulers(){this.setRulersEnabled(!this._rulers().enabled)}addGuide(e,t){if(!Number.isFinite(t))return null;this.guideCounter+=1;const n=`guide-${this.guideCounter}`;return this._guides.set([...this._guides(),{id:n,axis:e,position:t}]),n}moveGuide(e,t){if(!Number.isFinite(t))return;const n=this._guides().map(o=>o.id===e?{...o,position:t}:o);n!==this._guides()&&this._guides.set(n)}removeGuide(e){const t=this._guides().filter(n=>n.id!==e);t.length!==this._guides().length&&(this._guides.set(t),this._selectedGuideId()===e&&this._selectedGuideId.set(null))}clearGuides(){this.setGuidesLocked(!1),this._guides().length!==0&&(this._guides.set([]),this._selectedGuideId.set(null))}selectGuide(e){if(e===null){if(this._selectedGuideId()===null)return;this._selectedGuideId.set(null);return}if(this._selectedGuideId()!==e){if(!this._guides().some(t=>t.id===e)){this._selectedGuideId.set(null);return}this._selectedGuideId.set(e)}}removeSelectedGuide(){const e=this._selectedGuideId();e!==null&&this.removeGuide(e)}setGuidesLocked(e){this._guidesLocked()!==e&&(this._guidesLocked.set(e),e&&this._selectedGuideId.set(null))}toggleGuidesLocked(){this.setGuidesLocked(!this._guidesLocked())}patchInteraction(e){const t=this._interaction();let n=t.wheelZoomSpeed;typeof e.wheelZoomSpeed=="number"&&Number.isFinite(e.wheelZoomSpeed)&&(n=Math.max(To,Math.min(Ro,Math.round(e.wheelZoomSpeed)))),n!==t.wheelZoomSpeed&&this._interaction.set({wheelZoomSpeed:n})}resetInteraction(){this._interaction.set(As)}setRulerCursor(e){if(e===null){if(this._rulerCursor()===null)return;this._rulerCursor.set(null);return}if(!Number.isFinite(e.x)||!Number.isFinite(e.y)){if(this._rulerCursor()===null)return;this._rulerCursor.set(null);return}const t=this._rulerCursor();t!==null&&t.x===e.x&&t.y===e.y||this._rulerCursor.set({x:e.x,y:e.y})}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:L,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:L,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:L,decorators:[{type:D,args:[{providedIn:"root"}]}]});function Co(r){return typeof r=="number"&&Number.isFinite(r)&&r>0}function Tr(r){return typeof r=="number"&&Number.isFinite(r)&&r>=0}function hg(r){return typeof r=="number"&&Number.isFinite(r)&&r>0&&Number.isInteger(r)}function gg(r,e){return r.width===e.width&&r.height===e.height&&r.orientation===e.orientation&&r.margins.top===e.margins.top&&r.margins.right===e.margins.right&&r.margins.bottom===e.margins.bottom&&r.margins.left===e.margins.left}function pg(r,e){return r.enabled===e.enabled&&r.spacing===e.spacing&&r.majorEvery===e.majorEvery&&r.color===e.color}function fg(r){switch(r.kind){case"transparent":return!0;case"solid":return typeof r.color=="string"&&r.color.length>0;case"image":return typeof r.href=="string"&&r.href.length>0}}function mg(r,e){return r.kind!==e.kind?!1:r.kind==="solid"&&e.kind==="solid"?r.color===e.color:r.kind==="image"&&e.kind==="image"?r.href===e.href:!0}const Os=3,vg=400;class qn{host=f(ae);document=f(re);toolHost=f(Se);selection=f(k);keyObject=f(be);state=f(S);bus=f(M);transform=f(Ue);marquee=f(nt);snap=f(ue);viewport=f(A);isolation=f(it);activePage=f(j);shortcuts=f(_t);workspace=f(L);anchorSelection=f(Ce);_syncSnapGrid=J(()=>{this.snap.setGridSize(this.workspace.grid().spacing);const e=this.activePage.activePage(),t=e!==null?Be(e):null,n=Ao(t,null,this.workspace.page(),this.viewport.contentBox());this.snap.setGridOrigin(n!==null?{x:n.x,y:n.y}:{x:0,y:0})},...ngDevMode?[{debugName:"_syncSnapGrid"}]:[]);potentialDrag=null;moveStartBBox=null;movingIds=null;lastClickTimeMs=0;lastClickTargetId=null;constructor(){this.shortcuts.start(),this.document.addEventListener("keydown",this.onKeyDown)}ngOnDestroy(){this.document.removeEventListener("keydown",this.onKeyDown)}onPointerDown(e){if(e.button!==0)return;this.workspace.selectGuide(null);const t=this.toolHost.activeId();if(t!==null&&t!==Je&&t!==xe){const i=this.buildToolEvent(e);if(i!==null){H(e),this.toolHost.routePointerDown(i);return}}const o=this.resolveSelectionId(e);if(o===null){if(this.isolation.isActive()){this.isolation.exit(),this.potentialDrag=null,H(e);return}const i=this.toDocPoint(e);if(i!==null){const a=e.shiftKey?"add":"replace";this.marquee.start(i,a,this.selection.selectedIds())}this.potentialDrag=null,H(e);return}if(e.shiftKey||e.ctrlKey||e.metaKey?this.selection.toggle(o):this.selection.isSelected(o)||this.selection.select(o),o===this.activePage.activePageId()){const i=this.toDocPoint(e);if(i!==null){const a=e.shiftKey?"add":"replace";this.marquee.start(i,a,this.selection.selectedIds())}this.potentialDrag=null,H(e);return}this.potentialDrag={nodeId:o,startScreenX:e.clientX,startScreenY:e.clientY},H(e)}onPointerMove(e){const t=this.toDocPoint(e);this.workspace.setRulerCursor(t),this.updateHover(e);const n=this.toolHost.activeId();if(n!==null&&n!==Je&&n!==xe){const a=this.buildToolEvent(e);a!==null&&this.toolHost.routePointerMove(a);return}const i=this.transform.dragState();if(i!==null&&i.kind==="move"){const a=this.toDocPoint(e);a!==null&&this.applySnappedMove(i,a);return}if(i===null){if(this.marquee.isActive()){const a=this.toDocPoint(e);a!==null&&(this.marquee.update(a),this.applyMarqueeSelection());return}if(this.potentialDrag!==null){const a=e.clientX-this.potentialDrag.startScreenX,l=e.clientY-this.potentialDrag.startScreenY;if(a*a+l*l<Os*Os)return;const c=this.screenPointToDoc(this.potentialDrag.startScreenX,this.potentialDrag.startScreenY);if(c===null)return;const u=this.findInnerSvg(),h=this.selection.selectedIds();h.size>1&&h.has(this.potentialDrag.nodeId)?(this.movingIds=new Set(h),this.moveStartBBox=u===null?null:Sr(u,h),this.transform.startMoveMany(Array.from(h),c)):(this.movingIds=new Set([this.potentialDrag.nodeId]),this.moveStartBBox=u===null?null:ke(u,this.potentialDrag.nodeId),this.transform.startMove(this.potentialDrag.nodeId,c));const v=this.toDocPoint(e);if(v!==null){const p=this.transform.dragState();p!==null&&p.kind==="move"&&this.applySnappedMove(p,v)}}}}updateHover(e){const t=this.toolHost.activeId();if(t!==null&&t!==Je&&t!==xe||this.transform.dragState()!==null||this.marquee.isActive()||this.potentialDrag!==null){this.selection.setHover(null);return}const o=so(e,{mode:"group",rootId:this.state.document().root.id,isolationRootId:this.isolation.isolationRootId()??this.activePage.activePageId(),isTransparentContainer:lo(this.state.document().root)});this.selection.setHover(o===this.activePage.activePageId()?null:o)}onPointerUp(e){const t=this.toolHost.activeId();if(t!==null&&t!==Je&&t!==xe){const a=this.buildToolEvent(e);a!==null&&this.toolHost.routePointerUp(a),pe(e);return}const o=this.transform.dragState();if(o!==null&&o.kind==="move"&&(this.transform.endMove(),this.snap.clearActiveGuides(),this.moveStartBBox=null,this.movingIds=null),this.marquee.isActive()){const a=this.marquee.state(),l=this.marquee.rect();a!==null&&l!==null&&l.width===0&&l.height===0&&a.mode==="replace"&&this.selection.clear(),this.marquee.end()}if(this.potentialDrag!==null&&(o===null||o.kind!=="move")&&!e.shiftKey&&!e.ctrlKey&&!e.metaKey&&this.keyObject.hasKeyObject()){const a=this.potentialDrag.nodeId;this.selection.isSelected(a)&&this.keyObject.keyObjectId()!==a&&this.keyObject.setKeyObject(a)}this.potentialDrag=null,pe(e)}onPointerCancel(e){const t=this.toolHost.activeId();if(t!==null&&t!==Je&&t!==xe){const o=this.buildToolEvent(e);o!==null&&this.toolHost.routePointerCancel(o)}this.transform.isDragging()&&(this.transform.cancelGesture(),this.snap.clearActiveGuides(),this.moveStartBBox=null,this.movingIds=null),this.marquee.isActive()&&this.marquee.cancel(),this.potentialDrag=null,pe(e)}onPointerLeave(){this.workspace.setRulerCursor(null),this.selection.setHover(null)}onClick(e){if(this.toolHost.activeId()===xe){this.lastClickTimeMs=0,this.lastClickTargetId=null;return}const t=this.state.document().root.id,n=this.resolveSelectionId(e),o=performance.now();if(n!==null&&n===this.lastClickTargetId&&o-this.lastClickTimeMs<=vg){if(this.lastClickTimeMs=0,this.lastClickTargetId=null,n===t)return;const a=T(this.state.document().root,n);if(a===null||a.type!=="group"||$e(a)||zt(a))return;e.preventDefault(),this.isolation.enter(n),this.selection.select(n);return}this.lastClickTimeMs=o,this.lastClickTargetId=n}onKeyDown=e=>{if(!po(e.target)){if(e.key==="Delete"||e.key==="Backspace"){const t=this.anchorSelection.selected();if(t.length>0){const o=[...t].sort((i,a)=>i.subpathIndex!==a.subpathIndex?a.subpathIndex-i.subpathIndex:a.anchorIndex-i.anchorIndex);for(const i of o)this.bus.dispatch(new Wd(i));this.anchorSelection.clear(),e.preventDefault();return}const n=Array.from(this.selection.selectedIds());if(n.length===0)return;e.preventDefault();for(const o of n)this.bus.dispatch(new vr(o));this.selection.clear();return}if(e.key==="Escape"){if(this.transform.isDragging()){this.transform.cancelGesture(),this.snap.clearActiveGuides(),this.moveStartBBox=null,this.movingIds=null,this.potentialDrag=null,e.preventDefault();return}if(this.marquee.isActive()){this.marquee.cancel(),e.preventDefault();return}if(this.isolation.isActive()){this.isolation.exitOne(),e.preventDefault();return}}this.toolHost.routeKeyDown(e)}};applySnappedMove(e,t){if(!this.snap.enabled()||this.moveStartBBox===null){this.transform.updateMove(t);return}const n=t.x-e.startPoint.x,o=t.y-e.startPoint.y,i={x:this.moveStartBBox.x+n,y:this.moveStartBBox.y+o,width:this.moveStartBBox.width,height:this.moveStartBBox.height},a=this.movingIds??new Set([e.nodeId]),l=this.collectStaticBBoxes(a),c=this.snap.resolveForMove(i,l,this.viewport.zoom(),this.workspace.guides()),u={x:t.x+c.delta.x,y:t.y+c.delta.y};this.transform.updateMove(u),this.snap.setActiveGuides(c.guides)}collectStaticBBoxes(e){const t=this.findInnerSvg();if(t===null)return[];const n=this.activePage.activePage(),o=n!==null?n:this.state.document().root,i=[];for(const a of o.children){if(e.has(a.id))continue;const l=ke(t,a.id);l!==null&&i.push({id:a.id,bbox:l})}return i}applyMarqueeSelection(){const e=this.marquee.state(),t=this.marquee.rect();if(e===null||t===null)return;const n=this.findInnerSvg();if(n===null)return;const o=this.activePage.activePage(),i=o!==null?o:this.state.document().root,a=[];for(const c of i.children){if(Xt(n,c.id)===null)continue;const u=ke(n,c.id);u!==null&&a.push({id:c.id,bbox:u})}const l=Qi(t,a,"intersect");if(e.mode==="add"){const c=new Set(e.initialSelection);for(const u of l)c.add(u);this.selection.selectMany(c)}else this.selection.selectMany(l)}selectableOptions(){const e=this.state.document().root;return{mode:"group",rootId:e.id,isolationRootId:this.isolation.isolationRootId()??this.activePage.activePageId(),isTransparentContainer:lo(e)}}resolveSelectionId(e){const t=this.selectableOptions(),n=so(e,t);if(n!==null&&!this.isScopeContainer(n))return n;const o=this.findInnerSvg();if(o!==null){const i=$i(o,e.clientX,e.clientY);if(i!==null){const a=ao(i,t);if(a!==null&&!this.isScopeContainer(a))return a}}return n}isScopeContainer(e){return e===this.state.document().root.id||e===this.activePage.activePageId()||e===this.isolation.isolationRootId()}findInnerSvg(){return this.host.nativeElement.querySelector("svg")}toDocPoint(e){return this.screenPointToDoc(e.clientX,e.clientY)}screenPointToDoc(e,t){return Ve(this.findInnerSvg(),e,t)}buildToolEvent(e){const t=this.toDocPoint(e);return t===null?null:{raw:e,docPoint:t,screenX:e.clientX,screenY:e.clientY,shiftKey:e.shiftKey,altKey:e.altKey,ctrlKey:e.ctrlKey,metaKey:e.metaKey}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:qn,deps:[],target:s.\u0275\u0275FactoryTarget.Directive});static \u0275dir=s.\u0275\u0275ngDeclareDirective({minVersion:"14.0.0",version:"21.2.13",type:qn,isStandalone:!0,selector:"[svgeShellInteractions]",host:{listeners:{pointerdown:"onPointerDown($event)",pointermove:"onPointerMove($event)",pointerup:"onPointerUp($event)",pointercancel:"onPointerCancel($event)",pointerleave:"onPointerLeave()",click:"onClick($event)"}},ngImport:s})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:qn,decorators:[{type:pt,args:[{selector:"[svgeShellInteractions]",standalone:!0,host:{"(pointerdown)":"onPointerDown($event)","(pointermove)":"onPointerMove($event)","(pointerup)":"onPointerUp($event)","(pointercancel)":"onPointerCancel($event)","(pointerleave)":"onPointerLeave()","(click)":"onClick($event)"}}]}],ctorParameters:()=>[]});class Ns{symbolId;drops;parentId;id=Ht();label;insertedIds=[];constructor(e,t,n=te){this.symbolId=e,this.drops=t,this.parentId=n,this.label=`Spray ${t.length} symbol${t.length===1?"":"s"} "${e}"`}getInsertedIds(){return this.insertedIds}execute(e){if(this.drops.length===0)return Re();const t=e.state.document();let n=t.root;const o=[];for(const i of this.drops){const a=bi({symbolId:this.symbolId,x:i.x,y:i.y,width:i.width,height:i.height}),l=this.parentId===te?e.parentResolver?.resolveAutoParent()??t.root.id:this.parentId;try{n=Jr(n,l,a)}catch(c){return le(c instanceof Error?c.message:String(c))}o.push(a.id)}return this.insertedIds=o,e.state.setDocument({...t,root:n}),Re()}undo(e){if(this.insertedIds.length===0)return Re();const t=e.state.document();let n=t.root;for(let o=this.insertedIds.length-1;o>=0;o--){const i=this.insertedIds[o],a=Qr(n,i);if(a===n)return le(`${this.label} undo: instance "${i}" not found`);n=a}return e.state.setDocument({...t,root:n}),Re()}}function qt(r){const e=Ls(r.master),t=r.viewBox!==void 0?` viewBox="${r.viewBox.x} ${r.viewBox.y} ${r.viewBox.width} ${r.viewBox.height}"`:"";return`<symbol id="${r.id}"${t}>${e}</symbol>`}function Ls(r){const e=r.transform,n=e[0]===1&&e[1]===0&&e[2]===0&&e[3]===1&&e[4]===0&&e[5]===0?"":` transform="matrix(${e.join(",")})"`,o=r.style,i=[];o.fill!==void 0&&i.push(`fill="${o.fill}"`),o.stroke!==void 0&&i.push(`stroke="${o.stroke}"`),o.strokeWidth!==void 0&&i.push(`stroke-width="${o.strokeWidth}"`),o.opacity!==void 0&&i.push(`opacity="${o.opacity}"`);const a=i.length>0?" "+i.join(" "):"";switch(r.type){case"rect":return`<rect x="${r.x}" y="${r.y}" width="${r.width}" height="${r.height}"${r.rx!==void 0?` rx="${r.rx}"`:""}${r.ry!==void 0?` ry="${r.ry}"`:""}${a}${n} />`;case"ellipse":return`<ellipse cx="${r.cx}" cy="${r.cy}" rx="${r.rx}" ry="${r.ry}"${a}${n} />`;case"line":return`<line x1="${r.x1}" y1="${r.y1}" x2="${r.x2}" y2="${r.y2}"${a}${n} />`;case"polygon":return`<polygon points="${r.points.map(l=>`${l.x},${l.y}`).join(" ")}"${a}${n} />`;case"polyline":return`<polyline points="${r.points.map(l=>`${l.x},${l.y}`).join(" ")}"${a}${n} />`;case"path":return`<path d="${r.d}"${a}${n} />`;case"text":return`<text x="${r.x}" y="${r.y}"${a}${n}>${r.content}</text>`;case"image":return`<image x="${r.x}" y="${r.y}" width="${r.width}" height="${r.height}" href="${r.href}"${n} />`;case"group":return`<g${a}${n}>${r.children.map(Ls).join("")}</g>`;case"symbol-use":return`<use href="#${r.symbolId}" x="${r.x}" y="${r.y}"${r.width!==void 0?` width="${r.width}"`:""}${r.height!==void 0?` height="${r.height}"`:""}${n} />`}}class Ke extends Ae{static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ke,deps:null,target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ke,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ke,decorators:[{type:D,args:[{providedIn:"root"}]}]});class on{state=f(S);catalog=f(Ke);activeSymbolIds=m(()=>{const e=new Set;return je(this.state.document().root,t=>{t.type==="symbol-use"&&e.add(t.symbolId)}),[...e].filter(t=>this.catalog.get(t)!==null)},...ngDevMode?[{debugName:"activeSymbolIds"}]:[]);buildAllActiveSymbolsMarkup(){const e=this.activeSymbolIds();if(e.length===0)return"";const t=[];for(const n of e){const o=this.catalog.get(n);o!==null&&t.push(o.buildMarkup())}return t.join(`
808
+ `)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:on,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:on,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:on,decorators:[{type:D,args:[{providedIn:"root"}]}]});class Xe{_selectedSymbolId=b(null,...ngDevMode?[{debugName:"_selectedSymbolId"}]:[]);selectedSymbolId=this._selectedSymbolId.asReadonly();select(e){this._selectedSymbolId.set(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Xe,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Xe,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Xe,decorators:[{type:D,args:[{providedIn:"root"}]}]});class Pe{_drops=b([],...ngDevMode?[{debugName:"_drops"}]:[]);_symbolId=b(null,...ngDevMode?[{debugName:"_symbolId"}]:[]);drops=this._drops.asReadonly();symbolId=this._symbolId.asReadonly();hasPreview=m(()=>this._symbolId()!==null&&this._drops().length>0,...ngDevMode?[{debugName:"hasPreview"}]:[]);begin(e){this._symbolId.set(e),this._drops.set([])}append(e){this._drops.update(t=>[...t,e])}clear(){this._drops.set([]),this._symbolId.set(null)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Pe,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Pe,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Pe,decorators:[{type:D,args:[{providedIn:"root"}]}]});const $s="com.svge.tool.eyedropper",Bs="com.svge.tool.knife",Fs="com.svge.tool.smooth",js="com.svge.tool.gradient",Vs="com.svge.tool.width",zs="com.svge.tool.symbol-sprayer";function Rr(r,e,t){const n=r.target;if(!(n instanceof Element))return null;const o=Dr(n);if(o===null)return null;const i=T(e.document().root,o);return i===null||t!==void 0&&i.type!==t?null:i}class sn{_sampleTarget=b("fill",...ngDevMode?[{debugName:"_sampleTarget"}]:[]);_autoApply=b(!0,...ngDevMode?[{debugName:"_autoApply"}]:[]);sampleTarget=this._sampleTarget.asReadonly();autoApply=this._autoApply.asReadonly();setSampleTarget(e){this._sampleTarget.set(e)}setAutoApply(e){this._autoApply.set(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:sn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:sn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:sn,decorators:[{type:D,args:[{providedIn:"root"}]}]});class yg{id=$s;label="Eyedropper";icon="colorize";cursor="crosshair";shortcut="i";onPointerDown(e,t){const n=t.injector.get(S),o=Rr(e.raw,n);if(o===null)return;const i=t.injector.get(sn),a=i.sampleTarget(),l=e.altKey?a==="fill"?"stroke":a==="stroke"?"fill":"both":a,c=l==="both"?["fill","stroke"]:[l],u=t.injector.get(k),h=Array.from(u.selectedIds());if(h.length===0){console.info(`[Eyedropper] sampled ${c.join("+")} (no selection to apply)`);return}if(!i.autoApply()){console.info("[Eyedropper] sample-only mode \u2014 not applying");return}const g=t.injector.get(M);for(const v of c){const p=o.style[v];p!==void 0&&g.dispatch(new Kd(h,v,p))}}}class an{_snapToNodes=b(!0,...ngDevMode?[{debugName:"_snapToNodes"}]:[]);_snapTolerance=b(12,...ngDevMode?[{debugName:"_snapTolerance"}]:[]);snapToNodes=this._snapToNodes.asReadonly();snapTolerance=this._snapTolerance.asReadonly();setSnapToNodes(e){this._snapToNodes.set(e)}setSnapTolerance(e){Number.isFinite(e)&&this._snapTolerance.set(Math.max(2,Math.min(100,e)))}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:an,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:an,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:an,decorators:[{type:D,args:[{providedIn:"root"}]}]});class bg{id=Bs;label="Knife";icon="content_cut";cursor="crosshair";shortcut="c";onPointerDown(e,t){const n=t.injector.get(S),o=Rr(e.raw,n);if(o===null)return;if(o.type!=="path"&&o.type!=="rect"&&o.type!=="ellipse"&&o.type!=="line"&&o.type!=="polygon"&&o.type!=="polyline"){console.info(`[Knife] node type "${o.type}" is not cuttable`);return}const i=t.injector.get(an),a=new Xd(o.id,e.docPoint,i.snapTolerance(),i.snapToNodes()),l=t.injector.get(M).dispatch(a);if(!l.ok){console.info(`[Knife] cut failed: ${l.error}`);return}const c=a.createdIds;c.length>0&&t.injector.get(k).selectMany(c)}}class ln{_tolerance=b(1.5,...ngDevMode?[{debugName:"_tolerance"}]:[]);tolerance=this._tolerance.asReadonly();setTolerance(e){Number.isFinite(e)&&this._tolerance.set(Math.max(.1,Math.min(20,e)))}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ln,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ln,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ln,decorators:[{type:D,args:[{providedIn:"root"}]}]});class wg{id=Fs;label="Smooth";icon="auto_fix_high";cursor="crosshair";shortcut="s";onPointerDown(e,t){const n=t.injector.get(S),o=t.injector.get(k),i=Array.from(o.selectedIds());if(i.length===0){console.info("[Smooth] no selection \u2014 select a path first");return}const a=t.injector.get(ln).tolerance(),l=t.injector.get(M);for(const c of i){const u=T(n.document().root,c);if(u===null||u.type!=="path")continue;const g=Ut(u.d).map(p=>_g(p,a)),v=vi(g);v!==u.d&&l.dispatch(new yr(c,"d",v))}}}class Oe{_focusedNodeId=b(null,...ngDevMode?[{debugName:"_focusedNodeId"}]:[]);focusedNodeId=this._focusedNodeId.asReadonly();_isActive=b(!1,...ngDevMode?[{debugName:"_isActive"}]:[]);isActive=this._isActive.asReadonly();setActive(e){this._isActive.set(e),e||this._focusedNodeId.set(null)}focusNode(e){this._focusedNodeId.set(e)}hasFocus=m(()=>this._focusedNodeId()!==null,...ngDevMode?[{debugName:"hasFocus"}]:[]);static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Oe,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Oe,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Oe,decorators:[{type:D,args:[{providedIn:"root"}]}]});class Ig{id=js;label="Gradient";icon="gradient";cursor="crosshair";shortcut="g";onActivate(e){e.injector.get(Oe).setActive(!0)}onDeactivate(e){e.injector.get(Oe).setActive(!1)}onPointerDown(e,t){const n=t.injector.get(S),o=Rr(e.raw,n);if(o===null){t.injector.get(Oe).focusNode(null);return}const i=o.style.fill;if(typeof i!="string"||!i.trim().startsWith("url(")){console.info("[Gradient] clicked node has no gradient fill \u2014 assign one via Inspector first");return}t.injector.get(Oe).focusNode(o.id),t.injector.get(k).select(o.id)}}const kg=[1],xg=Array.from({length:11},(r,e)=>{const t=e/10;return Math.sin(t*Math.PI)}),Dg=[.2,.6,1,1,.6,.3];class cn{_preset=b("tapered",...ngDevMode?[{debugName:"_preset"}]:[]);_baseWidth=b(12,...ngDevMode?[{debugName:"_baseWidth"}]:[]);preset=this._preset.asReadonly();baseWidth=this._baseWidth.asReadonly();setPreset(e){this._preset.set(e)}setBaseWidth(e){this._baseWidth.set(Math.max(1,Math.min(200,e)))}resolveProfile(){switch(this._preset()){case"uniform":return kg;case"tapered":return xg;case"calligraphic":return Dg}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:cn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:cn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:cn,decorators:[{type:D,args:[{providedIn:"root"}]}]});class Sg{id=Vs;label="Width";icon="line_weight";cursor="crosshair";shortcut="w";onPointerDown(e,t){const n=t.injector.get(S),o=Rr(e.raw,n,"path");if(o===null){console.info("[Width] click missed \u2014 pick a path to apply the width profile");return}const i=Ut(o.d);if(i.length===0)return;const a=t.injector.get(cn),l=a.resolveProfile(),c=a.baseWidth(),u=[];for(const v of i){const p=v.anchors.map(E=>E.point);if(p.length<2)continue;const x=vo(p,c,l);x.length>0&&u.push(x)}if(u.length===0){console.info("[Width] path has no segments to expand");return}const h=t.injector.get(M),g=u.join(" ");h.dispatch(new yr(o.id,"d",g))}}class Et{_spacing=b(40,...ngDevMode?[{debugName:"_spacing"}]:[]);_baseSize=b(48,...ngDevMode?[{debugName:"_baseSize"}]:[]);_scaleJitter=b(.25,...ngDevMode?[{debugName:"_scaleJitter"}]:[]);spacing=this._spacing.asReadonly();baseSize=this._baseSize.asReadonly();scaleJitter=this._scaleJitter.asReadonly();setSpacing(e){this._spacing.set(Math.max(2,Math.min(400,e)))}setBaseSize(e){this._baseSize.set(Math.max(4,Math.min(400,e)))}setScaleJitter(e){this._scaleJitter.set(Math.max(0,Math.min(1,e)))}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Et,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Et,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Et,decorators:[{type:D,args:[{providedIn:"root"}]}]});class Pg{id=zs;label="Symbol Sprayer";icon="auto_awesome";cursor="crosshair";shortcut="o";dragging=!1;lastDropPoint=null;buffer=[];onPointerDown(e,t){const n=t.injector.get(Xe).selectedSymbolId();if(n===null){console.info("[Symbol Sprayer] no symbol selected \u2014 pick one in the Libraries panel \u2192 Symbols tab first.");return}this.dragging=!0,this.buffer=[],this.lastDropPoint=null,t.injector.get(Pe).begin(n),this.emitDropAt(e.docPoint,t,n)}onPointerMove(e,t){if(!this.dragging)return;const n=t.injector.get(Xe).selectedSymbolId();if(n===null)return;const o=this.lastDropPoint;if(o!==null){const i=t.injector.get(Et).spacing();if(Hs(o,e.docPoint)<i)return}this.emitDropAt(e.docPoint,t,n)}onPointerUp(e,t){if(!this.dragging)return;this.dragging=!1;const n=t.injector.get(Pe),o=t.injector.get(Xe).selectedSymbolId();if(o===null||this.buffer.length===0){this.buffer=[],this.lastDropPoint=null,n.clear();return}t.injector.get(M).dispatch(new Ns(o,this.buffer)),this.buffer=[],this.lastDropPoint=null,n.clear()}onPointerCancel(e,t){this.dragging=!1,this.buffer=[],this.lastDropPoint=null,t.injector.get(Pe).clear()}emitDropAt(e,t,n){const i=t.injector.get(Ke).get(n);if(i===null)return;const a=t.injector.get(Et),l=a.baseSize(),c=a.scaleJitter(),u=i.viewBox?.width??l,h=i.viewBox?.height??l,g=u/h,v=1+(Math.random()*2-1)*c,p=l*v*g,x=l*v,E={x:e.x-p/2,y:e.y-x/2,width:p,height:x};this.buffer.push(E),t.injector.get(Pe).append(E),this.lastDropPoint=e}}const Gs={id:"com.svge.tools.extra",name:"Extra Tools (Eyedropper, Knife, Smooth, Gradient, Width, Symbol Sprayer)",version:"2.1.0",apiVersion:O,install(r){const e=r.injector.get(de);r.track(e.register(new yg)),r.track(e.register(new bg)),r.track(e.register(new wg)),r.track(e.register(new Ig)),r.track(e.register(new Sg)),r.track(e.register(new Pg))}};function Hs(r,e){const t=r.x-e.x,n=r.y-e.y;return Math.sqrt(t*t+n*n)}function Mg(r,e,t){const n=t.x-e.x,o=t.y-e.y,i=n*n+o*o;if(i===0)return{point:e,t:0};let a=((r.x-e.x)*n+(r.y-e.y)*o)/i;return a=Math.max(0,Math.min(1,a)),{point:{x:e.x+n*a,y:e.y+o*a},t:a}}function _g(r,e){const t=r.anchors;if(t.length<3)return r;const n=new Array(t.length).fill(!1);n[0]=!0,n[t.length-1]=!0,Oo(t,0,t.length-1,e,n);const o=[];for(let i=0;i<t.length;i++)n[i]&&o.push(t[i]);return{anchors:o,closed:r.closed}}function Oo(r,e,t,n,o){if(t-e<2)return;let i=0,a=e;const l=r[e].point,c=r[t].point;for(let u=e+1;u<t;u++){const h=Mg(r[u].point,l,c),g=Hs(r[u].point,h.point);g>i&&(i=g,a=u)}i>n&&(o[a]=!0,Oo(r,e,a,n,o),Oo(r,a,t,n,o))}class Zn{ws=f(L);solidColor=m(()=>{const e=this.ws.background();return e.kind==="solid"?e.color:null},...ngDevMode?[{debugName:"solidColor"}]:[]);imageUrl=m(()=>{const e=this.ws.background();return e.kind==="image"?`url("${e.href}")`:null},...ngDevMode?[{debugName:"imageUrl"}]:[]);static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Zn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"14.0.0",version:"21.2.13",type:Zn,isStandalone:!0,selector:"svge-workspace-background",ngImport:s,template:`
809
+ <div
810
+ class="bg"
811
+ [class.transparent]="ws.isTransparentBackground()"
812
+ [style.background-color]="solidColor()"
813
+ [style.background-image]="imageUrl()"
814
+ >
815
+ <ng-content />
816
+ </div>
817
+ `,isInline:!0,styles:[`:host{display:block;position:relative;width:100%;height:100%}.bg{position:relative;width:100%;height:100%}.bg.transparent{background-color:#fff;background-image:linear-gradient(45deg,#e0e0e0 25%,transparent 25%),linear-gradient(-45deg,#e0e0e0 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#e0e0e0 75%),linear-gradient(-45deg,transparent 75%,#e0e0e0 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0}.bg:not(.transparent){background-repeat:no-repeat;background-size:cover;background-position:center}
818
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Zn,decorators:[{type:W,args:[{selector:"svge-workspace-background",standalone:!0,template:`
819
+ <div
820
+ class="bg"
821
+ [class.transparent]="ws.isTransparentBackground()"
822
+ [style.background-color]="solidColor()"
823
+ [style.background-image]="imageUrl()"
824
+ >
825
+ <ng-content />
826
+ </div>
827
+ `,changeDetection:U.OnPush,styles:[`:host{display:block;position:relative;width:100%;height:100%}.bg{position:relative;width:100%;height:100%}.bg.transparent{background-color:#fff;background-image:linear-gradient(45deg,#e0e0e0 25%,transparent 25%),linear-gradient(-45deg,#e0e0e0 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#e0e0e0 75%),linear-gradient(-45deg,transparent 75%,#e0e0e0 75%);background-size:16px 16px;background-position:0 0,0 8px,8px -8px,-8px 0}.bg:not(.transparent){background-repeat:no-repeat;background-size:cover;background-position:center}
828
+ `]}]}]});class st{_preview=b(null,...ngDevMode?[{debugName:"_preview"}]:[]);preview=this._preview.asReadonly();previewFor(e){const t=this._preview();return t===null||t.pageId!==e?null:t.viewBox}setPreview(e,t){this._preview.set({pageId:e,viewBox:t})}clearPreview(){this._preview.set(null)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:st,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:st,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:st,decorators:[{type:D,args:[{providedIn:"root"}]}]});class Jn{ws=f(L);viewport=f(A);activePage=f(j,{optional:!0});pageDrag=f(st,{optional:!0});visible=m(()=>this.ws.grid().enabled,...ngDevMode?[{debugName:"visible"}]:[]);lineColor=m(()=>this.ws.grid().color,...ngDevMode?[{debugName:"lineColor"}]:[]);pageBounds=m(()=>{const e=this.activePage?.activePage()??null,t=e!==null?Be(e):null,n=e!==null?this.pageDrag?.previewFor(e.id)??null:null;return Ao(t,n,this.ws.page(),this.viewport.contentBox())},...ngDevMode?[{debugName:"pageBounds"}]:[]);lines=m(()=>{const e=this.ws.grid();if(!e.enabled)return[];const t=this.pageBounds();return t===null?[]:Eg(t,e.spacing,e.majorEvery)},...ngDevMode?[{debugName:"lines"}]:[]);static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Jn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:Jn,isStandalone:!0,selector:"g[svgeGridOverlay]",host:{attributes:{"aria-hidden":"true"}},ngImport:s,template:`
829
+ @if (visible()) {
830
+ @for (line of lines(); track line.key) {
831
+ <svg:line
832
+ [class.major]="line.major"
833
+ class="grid-line"
834
+ [attr.x1]="line.x1"
835
+ [attr.y1]="line.y1"
836
+ [attr.x2]="line.x2"
837
+ [attr.y2]="line.y2"
838
+ [attr.stroke]="lineColor()"
839
+ />
840
+ }
841
+ }
842
+ `,isInline:!0,styles:[`.grid-line{stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none;opacity:.35;shape-rendering:crispEdges}.grid-line.major{opacity:.65}
843
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Jn,decorators:[{type:W,args:[{selector:"g[svgeGridOverlay]",standalone:!0,host:{"aria-hidden":"true"},template:`
844
+ @if (visible()) {
845
+ @for (line of lines(); track line.key) {
846
+ <svg:line
847
+ [class.major]="line.major"
848
+ class="grid-line"
849
+ [attr.x1]="line.x1"
850
+ [attr.y1]="line.y1"
851
+ [attr.x2]="line.x2"
852
+ [attr.y2]="line.y2"
853
+ [attr.stroke]="lineColor()"
854
+ />
855
+ }
856
+ }
857
+ `,changeDetection:U.OnPush,styles:[`.grid-line{stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none;opacity:.35;shape-rendering:crispEdges}.grid-line.major{opacity:.65}
858
+ `]}]}]});function Eg(r,e,t){if(e<=0||r.width<=0||r.height<=0)return[];const n=Math.round(r.width/e),o=Math.round(r.height/e);if(n+o>8e3)return[];const i=t>0?t:1,a=r.x,l=r.y,c=r.x+r.width,u=r.y+r.height,h=[];for(let g=0;g<=n;g++){const v=a+g*e;h.push({key:`v${g}`,x1:v,y1:l,x2:v,y2:u,major:g%i===0})}for(let g=0;g<=o;g++){const v=l+g*e;h.push({key:`h${g}`,x1:a,y1:v,x2:c,y2:v,major:g%i===0})}return h}class Qn{ws=f(L);viewport=f(A);elRef=f(ae);document=f(re);constructor(){this.document.addEventListener("keydown",this.onDocumentKeyDown)}layoutVersion=b(0,...ngDevMode?[{debugName:"layoutVersion"}]:[]);resizeObserver=null;ngAfterViewInit(){const e=this.elRef.nativeElement.ownerSVGElement;e!==null&&typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(()=>{this.layoutVersion.update(t=>t+1)}),this.resizeObserver.observe(e)),this.layoutVersion.update(t=>t+1)}ngOnDestroy(){this.document.removeEventListener("keydown",this.onDocumentKeyDown),this.resizeObserver?.disconnect(),this.resizeObserver=null}onDocumentKeyDown=e=>{e.key==="Escape"&&this.dragState!==null&&(this.ws.moveGuide(this.dragState.guideId,this.dragState.startPosition),this.dragState=null)};guides=this.ws.guides;selectedGuideId=this.ws.selectedGuideId;guidesLocked=this.ws.guidesLocked;clipBounds=m(()=>{this.layoutVersion(),this.viewport.viewBox();const e=this.computeClipBoundsFromCtm();if(e!==null)return e;const t=this.viewport.viewBox();return{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height}},...ngDevMode?[{debugName:"clipBounds"}]:[]);computeClipBoundsFromCtm(){const e=this.elRef.nativeElement.ownerSVGElement;if(e===null||typeof e.getScreenCTM!="function"||typeof e.createSVGPoint!="function")return null;const t=e.getScreenCTM();if(t===null)return null;const n=e.getBoundingClientRect();if(n.width<=0||n.height<=0)return null;const o=t.inverse(),i=e.createSVGPoint();i.x=n.left,i.y=n.top;const a=i.matrixTransform(o),l=e.createSVGPoint();l.x=n.right,l.y=n.bottom;const c=l.matrixTransform(o);return!Number.isFinite(a.x)||!Number.isFinite(c.x)||!Number.isFinite(a.y)||!Number.isFinite(c.y)?null:{left:Math.min(a.x,c.x),top:Math.min(a.y,c.y),right:Math.max(a.x,c.x),bottom:Math.max(a.y,c.y)}}viewBoxLeft=m(()=>this.clipBounds().left,...ngDevMode?[{debugName:"viewBoxLeft"}]:[]);viewBoxTop=m(()=>this.clipBounds().top,...ngDevMode?[{debugName:"viewBoxTop"}]:[]);viewBoxRight=m(()=>this.clipBounds().right,...ngDevMode?[{debugName:"viewBoxRight"}]:[]);viewBoxBottom=m(()=>this.clipBounds().bottom,...ngDevMode?[{debugName:"viewBoxBottom"}]:[]);hitZoneDocUnits=m(()=>{const e=this.viewport.zoom();return e>0?12/e:12},...ngDevMode?[{debugName:"hitZoneDocUnits"}]:[]);dragState=null;onPointerDown(e,t,n,o){if(this.guidesLocked())return;const i=this.screenToDoc(e.clientX,e.clientY);i!==null&&(this.ws.selectGuide(t),this.dragState={guideId:t,axis:n,startPosition:o,startCursor:n==="h"?i.y:i.x},H(e),e.stopPropagation())}onPointerMove(e){if(this.dragState===null)return;const t=this.screenToDoc(e.clientX,e.clientY);if(t===null)return;const o=(this.dragState.axis==="h"?t.y:t.x)-this.dragState.startCursor;this.ws.moveGuide(this.dragState.guideId,this.dragState.startPosition+o)}onPointerUp(e){this.dragState!==null&&(pe(e),this.dragState=null,e.stopPropagation())}onDoubleClick(e,t){this.guidesLocked()||(e.stopPropagation(),this.ws.removeGuide(t))}onGuideFocus(e){this.guidesLocked()||this.ws.selectGuide(e)}onGuideKeyDown(e,t,n,o){if(this.guidesLocked())return;if(e.key==="Delete"||e.key==="Backspace"){e.preventDefault(),e.stopPropagation(),this.ws.removeGuide(t);return}const i=e.shiftKey?10:1;let a;if(n==="h"&&e.key==="ArrowUp")a=-i;else if(n==="h"&&e.key==="ArrowDown")a=i;else if(n==="v"&&e.key==="ArrowLeft")a=-i;else if(n==="v"&&e.key==="ArrowRight")a=i;else return;e.preventDefault(),e.stopPropagation(),this.ws.moveGuide(t,o+a)}screenToDoc(e,t){return Ve(this.elRef.nativeElement.ownerSVGElement,e,t)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Qn,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:Qn,isStandalone:!0,selector:"g[svgeGuidesOverlay]",ngImport:s,template:`
859
+ @for (g of guides(); track g.id) {
860
+ @if (g.axis === 'h') {
861
+ <svg:line
862
+ class="guide-hit ns"
863
+ [class.locked]="guidesLocked()"
864
+ [attr.x1]="viewBoxLeft()"
865
+ [attr.y1]="g.position"
866
+ [attr.x2]="viewBoxRight()"
867
+ [attr.y2]="g.position"
868
+ [attr.stroke-width]="hitZoneDocUnits()"
869
+ role="slider"
870
+ [attr.tabindex]="guidesLocked() ? -1 : 0"
871
+ focusable="true"
872
+ [attr.aria-label]="
873
+ 'Horizontal guide at y=' +
874
+ g.position +
875
+ '. Arrow keys move 1 unit, Shift for 10, Delete removes.'
876
+ "
877
+ [attr.aria-valuenow]="g.position"
878
+ [attr.aria-valuemin]="viewBoxTop()"
879
+ [attr.aria-valuemax]="viewBoxBottom()"
880
+ aria-orientation="horizontal"
881
+ aria-keyshortcuts="ArrowUp ArrowDown Delete"
882
+ (pointerdown)="onPointerDown($event, g.id, g.axis, g.position)"
883
+ (pointermove)="onPointerMove($event)"
884
+ (pointerup)="onPointerUp($event)"
885
+ (dblclick)="onDoubleClick($event, g.id)"
886
+ (focus)="onGuideFocus(g.id)"
887
+ (keydown)="onGuideKeyDown($event, g.id, g.axis, g.position)"
888
+ />
889
+ <svg:line
890
+ class="guide horizontal"
891
+ [class.selected]="selectedGuideId() === g.id"
892
+ [attr.x1]="viewBoxLeft()"
893
+ [attr.y1]="g.position"
894
+ [attr.x2]="viewBoxRight()"
895
+ [attr.y2]="g.position"
896
+ />
897
+ } @else {
898
+ <svg:line
899
+ class="guide-hit ew"
900
+ [class.locked]="guidesLocked()"
901
+ [attr.x1]="g.position"
902
+ [attr.y1]="viewBoxTop()"
903
+ [attr.x2]="g.position"
904
+ [attr.y2]="viewBoxBottom()"
905
+ [attr.stroke-width]="hitZoneDocUnits()"
906
+ role="slider"
907
+ [attr.tabindex]="guidesLocked() ? -1 : 0"
908
+ focusable="true"
909
+ [attr.aria-label]="
910
+ 'Vertical guide at x=' +
911
+ g.position +
912
+ '. Arrow keys move 1 unit, Shift for 10, Delete removes.'
913
+ "
914
+ [attr.aria-valuenow]="g.position"
915
+ [attr.aria-valuemin]="viewBoxLeft()"
916
+ [attr.aria-valuemax]="viewBoxRight()"
917
+ aria-orientation="vertical"
918
+ aria-keyshortcuts="ArrowLeft ArrowRight Delete"
919
+ (pointerdown)="onPointerDown($event, g.id, g.axis, g.position)"
920
+ (pointermove)="onPointerMove($event)"
921
+ (pointerup)="onPointerUp($event)"
922
+ (dblclick)="onDoubleClick($event, g.id)"
923
+ (focus)="onGuideFocus(g.id)"
924
+ (keydown)="onGuideKeyDown($event, g.id, g.axis, g.position)"
925
+ />
926
+ <svg:line
927
+ class="guide vertical"
928
+ [class.selected]="selectedGuideId() === g.id"
929
+ [attr.x1]="g.position"
930
+ [attr.y1]="viewBoxTop()"
931
+ [attr.x2]="g.position"
932
+ [attr.y2]="viewBoxBottom()"
933
+ />
934
+ }
935
+ }
936
+ `,isInline:!0,styles:[`.guide{stroke:#00bcd4;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.guide.selected{stroke:#ff6f00;stroke-width:2}.guide-hit{stroke:transparent;fill:none}.guide-hit.ns{cursor:ns-resize}.guide-hit.ew{cursor:ew-resize}.guide-hit.locked{pointer-events:none;cursor:default}.guide-hit:focus,.guide-hit:focus-visible{outline:none}
937
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Qn,decorators:[{type:W,args:[{selector:"g[svgeGuidesOverlay]",standalone:!0,template:`
938
+ @for (g of guides(); track g.id) {
939
+ @if (g.axis === 'h') {
940
+ <svg:line
941
+ class="guide-hit ns"
942
+ [class.locked]="guidesLocked()"
943
+ [attr.x1]="viewBoxLeft()"
944
+ [attr.y1]="g.position"
945
+ [attr.x2]="viewBoxRight()"
946
+ [attr.y2]="g.position"
947
+ [attr.stroke-width]="hitZoneDocUnits()"
948
+ role="slider"
949
+ [attr.tabindex]="guidesLocked() ? -1 : 0"
950
+ focusable="true"
951
+ [attr.aria-label]="
952
+ 'Horizontal guide at y=' +
953
+ g.position +
954
+ '. Arrow keys move 1 unit, Shift for 10, Delete removes.'
955
+ "
956
+ [attr.aria-valuenow]="g.position"
957
+ [attr.aria-valuemin]="viewBoxTop()"
958
+ [attr.aria-valuemax]="viewBoxBottom()"
959
+ aria-orientation="horizontal"
960
+ aria-keyshortcuts="ArrowUp ArrowDown Delete"
961
+ (pointerdown)="onPointerDown($event, g.id, g.axis, g.position)"
962
+ (pointermove)="onPointerMove($event)"
963
+ (pointerup)="onPointerUp($event)"
964
+ (dblclick)="onDoubleClick($event, g.id)"
965
+ (focus)="onGuideFocus(g.id)"
966
+ (keydown)="onGuideKeyDown($event, g.id, g.axis, g.position)"
967
+ />
968
+ <svg:line
969
+ class="guide horizontal"
970
+ [class.selected]="selectedGuideId() === g.id"
971
+ [attr.x1]="viewBoxLeft()"
972
+ [attr.y1]="g.position"
973
+ [attr.x2]="viewBoxRight()"
974
+ [attr.y2]="g.position"
975
+ />
976
+ } @else {
977
+ <svg:line
978
+ class="guide-hit ew"
979
+ [class.locked]="guidesLocked()"
980
+ [attr.x1]="g.position"
981
+ [attr.y1]="viewBoxTop()"
982
+ [attr.x2]="g.position"
983
+ [attr.y2]="viewBoxBottom()"
984
+ [attr.stroke-width]="hitZoneDocUnits()"
985
+ role="slider"
986
+ [attr.tabindex]="guidesLocked() ? -1 : 0"
987
+ focusable="true"
988
+ [attr.aria-label]="
989
+ 'Vertical guide at x=' +
990
+ g.position +
991
+ '. Arrow keys move 1 unit, Shift for 10, Delete removes.'
992
+ "
993
+ [attr.aria-valuenow]="g.position"
994
+ [attr.aria-valuemin]="viewBoxLeft()"
995
+ [attr.aria-valuemax]="viewBoxRight()"
996
+ aria-orientation="vertical"
997
+ aria-keyshortcuts="ArrowLeft ArrowRight Delete"
998
+ (pointerdown)="onPointerDown($event, g.id, g.axis, g.position)"
999
+ (pointermove)="onPointerMove($event)"
1000
+ (pointerup)="onPointerUp($event)"
1001
+ (dblclick)="onDoubleClick($event, g.id)"
1002
+ (focus)="onGuideFocus(g.id)"
1003
+ (keydown)="onGuideKeyDown($event, g.id, g.axis, g.position)"
1004
+ />
1005
+ <svg:line
1006
+ class="guide vertical"
1007
+ [class.selected]="selectedGuideId() === g.id"
1008
+ [attr.x1]="g.position"
1009
+ [attr.y1]="viewBoxTop()"
1010
+ [attr.x2]="g.position"
1011
+ [attr.y2]="viewBoxBottom()"
1012
+ />
1013
+ }
1014
+ }
1015
+ `,changeDetection:U.OnPush,styles:[`.guide{stroke:#00bcd4;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.guide.selected{stroke:#ff6f00;stroke-width:2}.guide-hit{stroke:transparent;fill:none}.guide-hit.ns{cursor:ns-resize}.guide-hit.ew{cursor:ew-resize}.guide-hit.locked{pointer-events:none;cursor:default}.guide-hit:focus,.guide-hit:focus-visible{outline:none}
1016
+ `]}]}],ctorParameters:()=>[]});class er{ws=f(L);viewport=f(A);activePage=f(j,{optional:!0});toolHost=f(Se,{optional:!0});pageDrag=f(st,{optional:!0});pageBounds=m(()=>{const e=this.activePage?.activePage()??null,t=e!==null?Be(e):null,n=e!==null?this.pageDrag?.previewFor(e.id)??null:null;return Ao(t,n,this.ws.page(),this.viewport.contentBox())},...ngDevMode?[{debugName:"pageBounds"}]:[]);pageBackground=m(()=>{const e=this.activePage?.activePage()??null;return e!==null?wi(e).background:{kind:"transparent"}},...ngDevMode?[{debugName:"pageBackground"}]:[]);backgroundImageHref=m(()=>{const e=this.pageBackground();return e.kind==="image"?e.href:null},...ngDevMode?[{debugName:"backgroundImageHref"}]:[]);rectFill=m(()=>{const e=this.pageBackground();return e.kind==="solid"?e.color:e.kind==="image"?"none":null},...ngDevMode?[{debugName:"rectFill"}]:[]);imagePar=Yd;pageNodeId=m(()=>this.toolHost!==null&&this.toolHost.activeId()!==Pr?null:(this.activePage?.activePage()??null)?.id??null,...ngDevMode?[{debugName:"pageNodeId"}]:[]);marginsRect=m(()=>{const e=this.activePage?.activePage()??null,t=e!==null?wi(e).margins:this.ws.page().margins,n=this.pageBounds();if(n===null||t.top===0&&t.right===0&&t.bottom===0&&t.left===0)return null;const o=n.width-t.left-t.right,i=n.height-t.top-t.bottom;return o<=0||i<=0?null:{x:n.x+t.left,y:n.y+t.top,width:o,height:i}},...ngDevMode?[{debugName:"marginsRect"}]:[]);static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:er,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:er,isStandalone:!0,selector:"g[svgePageOverlay]",host:{attributes:{"aria-hidden":"true"}},ngImport:s,template:`
1017
+ @if (pageBounds(); as p) {
1018
+ <!--
1019
+ Outer page rectangle \u2014 the visible "paper" of the canvas AND
1020
+ (PAGES-REFACTOR Fase 4) the persistent hit-target for the
1021
+ active D-079 page. The rect carries data-node-id with the
1022
+ page id whenever a D-079 page is active so that
1023
+ findOwningNodeId resolves clicks on the empty page interior
1024
+ to the page node \u2014 replacing the PAGES-FIX-4 hit-target rect
1025
+ that lived inside the page's wrapper g and re-mounted on
1026
+ every selection change (the flicker source). Because
1027
+ PageOverlay is mounted in the svgeBehind slot, the rect
1028
+ renders UNDER the document content \u2014 so clicks on shapes
1029
+ still hit the shapes first (their geometry is on top in the
1030
+ paint order and intercepts the pointer), and clicks on empty
1031
+ page area fall through to this rect.
1032
+
1033
+ pointer-events flips between 'all' (when there's an active
1034
+ page id worth resolving to) and 'none' (legacy single-root
1035
+ documents) so the legacy click-through behavior is preserved
1036
+ for pre-D-079 docs.
1037
+
1038
+ Anchored at the page's origin (top-left at 0,0 in document
1039
+ coordinates via the pageBoundsIn helper \u2014 reverted from the
1040
+ earlier "centered in viewport" behaviour in 2026-05-18). Grid
1041
+ and guides overlays use the same helper so they stay aligned
1042
+ to the same rectangle.
1043
+ -->
1044
+ @if (backgroundImageHref(); as href) {
1045
+ <!--
1046
+ Page background IMAGE (PageOptions.background.kind === 'image').
1047
+ Painted UNDER the page-rect (which then uses fill:none so the
1048
+ image shows through). Same href + preserveAspectRatio the
1049
+ exporter emits via getPageBackgroundNode \u2192 parity with export.
1050
+ pointer-events:none so the rect stays the hit-target.
1051
+ -->
1052
+ <svg:image
1053
+ class="page-bg-image"
1054
+ [attr.x]="p.x"
1055
+ [attr.y]="p.y"
1056
+ [attr.width]="p.width"
1057
+ [attr.height]="p.height"
1058
+ [attr.href]="href"
1059
+ [attr.preserveAspectRatio]="imagePar"
1060
+ />
1061
+ }
1062
+ <svg:rect
1063
+ class="page-rect"
1064
+ [attr.x]="p.x"
1065
+ [attr.y]="p.y"
1066
+ [attr.width]="p.width"
1067
+ [attr.height]="p.height"
1068
+ [style.fill]="rectFill()"
1069
+ [attr.data-node-id]="pageNodeId()"
1070
+ [attr.pointer-events]="pageNodeId() === null ? 'none' : 'all'"
1071
+ />
1072
+ @if (marginsRect(); as m) {
1073
+ <!--
1074
+ Inner safe-area rectangle (dashed) \u2014 only emitted when any
1075
+ margin > 0 so default zero-margin pages don't pay for an
1076
+ extra DOM node.
1077
+ -->
1078
+ <svg:rect
1079
+ class="margin-rect"
1080
+ [attr.x]="m.x"
1081
+ [attr.y]="m.y"
1082
+ [attr.width]="m.width"
1083
+ [attr.height]="m.height"
1084
+ />
1085
+ }
1086
+ }
1087
+ `,isInline:!0,styles:[`.page-rect{fill:var(--svge-page-fill, rgba(255, 255, 255, .5));stroke:var(--svge-page-stroke, #1976d2);stroke-width:1;vector-effect:non-scaling-stroke}.page-bg-image{pointer-events:none}.margin-rect{fill:none;stroke:var(--svge-page-margin-stroke, #1976d2);stroke-width:1;stroke-dasharray:4 3;vector-effect:non-scaling-stroke;opacity:.6;pointer-events:none}
1088
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:er,decorators:[{type:W,args:[{selector:"g[svgePageOverlay]",standalone:!0,host:{"aria-hidden":"true"},template:`
1089
+ @if (pageBounds(); as p) {
1090
+ <!--
1091
+ Outer page rectangle \u2014 the visible "paper" of the canvas AND
1092
+ (PAGES-REFACTOR Fase 4) the persistent hit-target for the
1093
+ active D-079 page. The rect carries data-node-id with the
1094
+ page id whenever a D-079 page is active so that
1095
+ findOwningNodeId resolves clicks on the empty page interior
1096
+ to the page node \u2014 replacing the PAGES-FIX-4 hit-target rect
1097
+ that lived inside the page's wrapper g and re-mounted on
1098
+ every selection change (the flicker source). Because
1099
+ PageOverlay is mounted in the svgeBehind slot, the rect
1100
+ renders UNDER the document content \u2014 so clicks on shapes
1101
+ still hit the shapes first (their geometry is on top in the
1102
+ paint order and intercepts the pointer), and clicks on empty
1103
+ page area fall through to this rect.
1104
+
1105
+ pointer-events flips between 'all' (when there's an active
1106
+ page id worth resolving to) and 'none' (legacy single-root
1107
+ documents) so the legacy click-through behavior is preserved
1108
+ for pre-D-079 docs.
1109
+
1110
+ Anchored at the page's origin (top-left at 0,0 in document
1111
+ coordinates via the pageBoundsIn helper \u2014 reverted from the
1112
+ earlier "centered in viewport" behaviour in 2026-05-18). Grid
1113
+ and guides overlays use the same helper so they stay aligned
1114
+ to the same rectangle.
1115
+ -->
1116
+ @if (backgroundImageHref(); as href) {
1117
+ <!--
1118
+ Page background IMAGE (PageOptions.background.kind === 'image').
1119
+ Painted UNDER the page-rect (which then uses fill:none so the
1120
+ image shows through). Same href + preserveAspectRatio the
1121
+ exporter emits via getPageBackgroundNode \u2192 parity with export.
1122
+ pointer-events:none so the rect stays the hit-target.
1123
+ -->
1124
+ <svg:image
1125
+ class="page-bg-image"
1126
+ [attr.x]="p.x"
1127
+ [attr.y]="p.y"
1128
+ [attr.width]="p.width"
1129
+ [attr.height]="p.height"
1130
+ [attr.href]="href"
1131
+ [attr.preserveAspectRatio]="imagePar"
1132
+ />
1133
+ }
1134
+ <svg:rect
1135
+ class="page-rect"
1136
+ [attr.x]="p.x"
1137
+ [attr.y]="p.y"
1138
+ [attr.width]="p.width"
1139
+ [attr.height]="p.height"
1140
+ [style.fill]="rectFill()"
1141
+ [attr.data-node-id]="pageNodeId()"
1142
+ [attr.pointer-events]="pageNodeId() === null ? 'none' : 'all'"
1143
+ />
1144
+ @if (marginsRect(); as m) {
1145
+ <!--
1146
+ Inner safe-area rectangle (dashed) \u2014 only emitted when any
1147
+ margin > 0 so default zero-margin pages don't pay for an
1148
+ extra DOM node.
1149
+ -->
1150
+ <svg:rect
1151
+ class="margin-rect"
1152
+ [attr.x]="m.x"
1153
+ [attr.y]="m.y"
1154
+ [attr.width]="m.width"
1155
+ [attr.height]="m.height"
1156
+ />
1157
+ }
1158
+ }
1159
+ `,changeDetection:U.OnPush,styles:[`.page-rect{fill:var(--svge-page-fill, rgba(255, 255, 255, .5));stroke:var(--svge-page-stroke, #1976d2);stroke-width:1;vector-effect:non-scaling-stroke}.page-bg-image{pointer-events:none}.margin-rect{fill:none;stroke:var(--svge-page-margin-stroke, #1976d2);stroke-width:1;stroke-dasharray:4 3;vector-effect:non-scaling-stroke;opacity:.6;pointer-events:none}
1160
+ `]}]}]});const Ar="data-svge-outline-mode";class tr{elRef=f(ae);ws=f(L);currentlyOn=!1;constructor(){J(()=>{const e=this.ws.outlineMode();e!==this.currentlyOn&&(this.currentlyOn=e,e?this.applyOn():this.restore())})}ngOnDestroy(){this.currentlyOn&&(this.restore(),this.currentlyOn=!1)}applyOn(){const t=this.elRef.nativeElement.querySelectorAll("[data-node-id] > rect, [data-node-id] > ellipse, [data-node-id] > path, [data-node-id] > polygon, [data-node-id] > polyline, [data-node-id] > line, [data-node-id] > text, [data-node-id] > image");for(const n of t){const o=n.style.fill,i=n.style.stroke,a=n.style.strokeWidth;n.setAttribute(Ar,JSON.stringify({fill:o,stroke:i,strokeWidth:a})),n.style.fill="none";const l=window.getComputedStyle(n);l.stroke!=="none"&&l.stroke!=="rgba(0, 0, 0, 0)"||(n.style.stroke="#1976d2",n.style.strokeWidth="1")}}restore(){const t=this.elRef.nativeElement.querySelectorAll(`[${Ar}]`);for(const n of t){const o=n.getAttribute(Ar);if(n.removeAttribute(Ar),o===null)continue;let i={};try{i=JSON.parse(o)}catch{}n.style.fill=i.fill??"",n.style.stroke=i.stroke??"",n.style.strokeWidth=i.strokeWidth??"",n.style.fill===""&&n.style.removeProperty("fill"),n.style.stroke===""&&n.style.removeProperty("stroke"),n.style.strokeWidth===""&&n.style.removeProperty("stroke-width")}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:tr,deps:[],target:s.\u0275\u0275FactoryTarget.Directive});static \u0275dir=s.\u0275\u0275ngDeclareDirective({minVersion:"14.0.0",version:"21.2.13",type:tr,isStandalone:!0,selector:"[svgeOutlineFilter]",ngImport:s})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:tr,decorators:[{type:pt,args:[{selector:"[svgeOutlineFilter]",standalone:!0}]}],ctorParameters:()=>[]});class nr{elRef=f(ae);ws=f(L);currentlyOn=!1;prevShapeRendering="";prevImageRendering="";constructor(){J(()=>{const e=this.ws.pixelPreview();e!==this.currentlyOn&&(this.currentlyOn=e,e?this.applyOn():this.restore())})}ngOnDestroy(){this.currentlyOn&&(this.restore(),this.currentlyOn=!1)}rootSvg(){const e=this.elRef.nativeElement;return e instanceof SVGSVGElement?e:e.querySelector("svg")}applyOn(){const e=this.rootSvg();e!==null&&(this.prevShapeRendering=e.style.getPropertyValue("shape-rendering"),this.prevImageRendering=e.style.getPropertyValue("image-rendering"),e.style.setProperty("shape-rendering","crispEdges"),e.style.setProperty("image-rendering","pixelated"))}restore(){const e=this.rootSvg();e!==null&&(this.prevShapeRendering?e.style.setProperty("shape-rendering",this.prevShapeRendering):e.style.removeProperty("shape-rendering"),this.prevImageRendering?e.style.setProperty("image-rendering",this.prevImageRendering):e.style.removeProperty("image-rendering"),this.prevShapeRendering="",this.prevImageRendering="")}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:nr,deps:[],target:s.\u0275\u0275FactoryTarget.Directive});static \u0275dir=s.\u0275\u0275ngDeclareDirective({minVersion:"14.0.0",version:"21.2.13",type:nr,isStandalone:!0,selector:"[svgePixelPreviewFilter]",ngImport:s})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:nr,decorators:[{type:pt,args:[{selector:"[svgePixelPreviewFilter]",standalone:!0}]}],ctorParameters:()=>[]});const Tg=4096;class rr{ws=f(L);document=f(re);tree=Gr.required(...ngDevMode?[{debugName:"tree"}]:[]);viewBox=Gr(null,...ngDevMode?[{debugName:"viewBox"}]:[]);defs=Gr(null,...ngDevMode?[{debugName:"defs"}]:[]);_bitmap=b(null,...ngDevMode?[{debugName:"_bitmap"}]:[]);bitmap=this._bitmap.asReadonly();box=m(()=>this.viewBox(),...ngDevMode?[{debugName:"box"}]:[]);rasterToken=0;constructor(){J(()=>{const e=this.ws.pixelPreviewRaster(),t=this.tree(),n=this.viewBox(),o=this.defs();li(()=>{this.reset(),e&&this.rasterize(t,n,o)})}),f(Hr).onDestroy(()=>this.reset())}reset(){this.rasterToken++,this._bitmap.set(null),this.ws.setPixelPreviewRasterReady(!1)}rasterize(e,t,n){if(t===null||!Fe(e))return;const o=t.width,i=t.height;if(!(o>0)||!(i>0))return;const a=this.makeContext(o,i);if(a===null)return;const{canvas:l,context:c}=a;let u;try{const v=vt.export({root:e,viewBox:t,defs:n});if(typeof v!="string")return;u=v}catch{return}const h=this.rasterToken,g=new Image;g.onload=()=>{if(h===this.rasterToken)try{c.clearRect(0,0,l.width,l.height),c.drawImage(g,0,0,l.width,l.height),this._bitmap.set(l.toDataURL("image/png")),this.ws.setPixelPreviewRasterReady(!0)}catch{}},g.onerror=()=>{},g.src=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(u)}`}makeContext(e,t){const n=this.document.createElement("canvas"),o=n.getContext?.("2d")??null;if(o===null)return null;const i=Math.min(1,Tg/Math.max(e,t));return n.width=Math.max(1,Math.round(e*i)),n.height=Math.max(1,Math.round(t*i)),{canvas:n,context:o}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:rr,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:rr,isStandalone:!0,selector:"g[svgePixelPreviewRaster]",inputs:{tree:{classPropertyName:"tree",publicName:"tree",isSignal:!0,isRequired:!0,transformFunction:null},viewBox:{classPropertyName:"viewBox",publicName:"viewBox",isSignal:!0,isRequired:!1,transformFunction:null},defs:{classPropertyName:"defs",publicName:"defs",isSignal:!0,isRequired:!1,transformFunction:null}},ngImport:s,template:`
1161
+ @if (bitmap(); as href) {
1162
+ @if (box(); as b) {
1163
+ <svg:image
1164
+ [attr.x]="b.x"
1165
+ [attr.y]="b.y"
1166
+ [attr.width]="b.width"
1167
+ [attr.height]="b.height"
1168
+ [attr.href]="href"
1169
+ preserveAspectRatio="none"
1170
+ style="image-rendering: pixelated"
1171
+ aria-hidden="true"
1172
+ />
1173
+ }
1174
+ }
1175
+ `,isInline:!0,changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:rr,decorators:[{type:W,args:[{selector:"g[svgePixelPreviewRaster]",standalone:!0,template:`
1176
+ @if (bitmap(); as href) {
1177
+ @if (box(); as b) {
1178
+ <svg:image
1179
+ [attr.x]="b.x"
1180
+ [attr.y]="b.y"
1181
+ [attr.width]="b.width"
1182
+ [attr.height]="b.height"
1183
+ [attr.href]="href"
1184
+ preserveAspectRatio="none"
1185
+ style="image-rendering: pixelated"
1186
+ aria-hidden="true"
1187
+ />
1188
+ }
1189
+ }
1190
+ `,changeDetection:U.OnPush}]}],ctorParameters:()=>[],propDecorators:{tree:[{type:s.Input,args:[{isSignal:!0,alias:"tree",required:!0}]}],viewBox:[{type:s.Input,args:[{isSignal:!0,alias:"viewBox",required:!1}]}],defs:[{type:s.Input,args:[{isSignal:!0,alias:"defs",required:!1}]}]}});const No="svge-workspace",Cr=1;function Us(r,e,t="SVGEngine"){return JSON.stringify({format:No,schemaVersion:Cr,app:t,document:r,editor:e},null,2)}function Ws(r){let e;try{e=JSON.parse(r)}catch{return{ok:!1,error:"Not a valid workspace file (invalid JSON)."}}if(!wt(e))return{ok:!1,error:"Not a valid workspace file (expected a JSON object)."};if(e.format!==No)return{ok:!1,error:"Not an SVGEngine workspace file."};const t=e.schemaVersion;if(typeof t!="number"||t>Cr)return{ok:!1,error:`Unsupported workspace version (${String(t)}); this build reads up to v${Cr}.`};const n=e.document;return typeof n!="string"||n.length===0?{ok:!1,error:"Workspace file has no document payload."}:{ok:!0,document:n,editor:Rg(e.editor)}}function Rg(r){if(!wt(r))return{activePageIndex:null};const e=r.activePageIndex;return{activePageIndex:typeof e=="number"&&Number.isInteger(e)&&e>=0?e:null,viewport:Ag(r.viewport),workspace:Og(r.workspace)}}function Ag(r){if(!wt(r))return;const e=r.zoom,t=r.panX,n=r.panY,o=Cg(r.contentBox);if(!(!Qe(e)||!Qe(t)||!Qe(n)||o===null))return{zoom:e,panX:t,panY:n,contentBox:o}}function Cg(r){if(!wt(r))return null;const e=r.x,t=r.y,n=r.width,o=r.height;return!Qe(e)||!Qe(t)||!Qe(n)||!Qe(o)?null:{x:e,y:t,width:n,height:o}}function Og(r){if(wt(r))return{background:Nn(r.background),page:Nn(r.page),grid:Nn(r.grid),rulers:Nn(r.rulers),guides:Ng(r.guides),guidesLocked:typeof r.guidesLocked=="boolean"?r.guidesLocked:void 0,interaction:Nn(r.interaction)}}function Nn(r){return wt(r)?r:void 0}function Ng(r){if(!Array.isArray(r))return;const e=[];return r.forEach((t,n)=>{if(!wt(t))return;const o=t.axis,i=t.position,a=t.id;(o==="h"||o==="v")&&Qe(i)&&e.push({id:typeof a=="string"&&a.length>0?a:`guide-${n+1}`,axis:o,position:i})}),e}function wt(r){return typeof r=="object"&&r!==null}function Qe(r){return typeof r=="number"&&Number.isFinite(r)}class Tt{document=f(re);target=null;_active=b(this.readActive(),...ngDevMode?[{debugName:"_active"}]:[]);active=this._active.asReadonly();constructor(){const e=()=>this._active.set(this.readActive());this.document.addEventListener("fullscreenchange",e),f(Hr).onDestroy(()=>this.document.removeEventListener("fullscreenchange",e))}isSupported(){return typeof this.document.documentElement.requestFullscreen=="function"&&this.document.fullscreenEnabled!==!1}setTarget(e){this.target=e}clearTarget(e){this.target===e&&(this.target=null)}enter(){if(!this.isSupported()||this.readActive())return;(this.target??this.document.documentElement).requestFullscreen?.().catch(()=>{})}exit(){this.readActive()&&this.document.exitFullscreen?.().catch(()=>{})}toggle(){this.readActive()?this.exit():this.enter()}readActive(){return this.document.fullscreenElement!=null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Tt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Tt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Tt,decorators:[{type:D,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});const Or="data-svge-prev-display";class or{elRef=f(ae);layers=f(ne);currentlyHidden=new Set;constructor(){J(()=>{this.applyVisibility()})}ngOnDestroy(){for(const e of this.currentlyHidden)this.restoreOne(e);this.currentlyHidden.clear()}applyVisibility(){const e=this.layers.hiddenIds(),t=this.elRef.nativeElement;for(const n of e)this.currentlyHidden.has(n)||this.hideOne(n,t);for(const n of this.currentlyHidden)e.has(n)||(this.restoreOne(n),this.currentlyHidden.delete(n))}hideOne(e,t){const n=t.querySelectorAll(`[data-node-id="${e}"]`);for(const o of n)o.hasAttribute(Or)||o.setAttribute(Or,o.style.display??""),o.style.display="none";this.currentlyHidden.add(e)}restoreOne(e){const n=this.elRef.nativeElement.querySelectorAll(`[data-node-id="${e}"]`);for(const o of n){const i=o.getAttribute(Or);i!==null?(o.style.display=i,o.removeAttribute(Or)):o.style.removeProperty("display")}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:or,deps:[],target:s.\u0275\u0275FactoryTarget.Directive});static \u0275dir=s.\u0275\u0275ngDeclareDirective({minVersion:"14.0.0",version:"21.2.13",type:or,isStandalone:!0,selector:"[svgeLayersFilter]",ngImport:s})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:or,decorators:[{type:pt,args:[{selector:"[svgeLayersFilter]",standalone:!0}]}],ctorParameters:()=>[]});class Rt{_palettes=b([],...ngDevMode?[{debugName:"_palettes"}]:[]);palettes=this._palettes.asReadonly();register(e){if(typeof e.id!="string"||e.id.length===0)throw new Error("PaletteRegistry.register: palette.id must be a non-empty string");if(e.swatches.length===0)throw new Error(`PaletteRegistry.register: palette "${e.id}" must have at least one swatch`);if(this._palettes().some(t=>t.id===e.id))throw new Error(`PaletteRegistry.register: palette "${e.id}" is already registered`);return this._palettes.set([...this._palettes(),e]),{dispose:()=>{this._palettes.set(this._palettes().filter(t=>t.id!==e.id))}}}get(e){return this._palettes().find(t=>t.id===e)??null}byCategory(e){return this._palettes().filter(t=>t.category===e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Rt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Rt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Rt,decorators:[{type:D,args:[{providedIn:"root"}]}]});const Ks={id:"svge.builtin.palettes",version:"1.0.0",name:"Built-in color palettes",apiVersion:O,install(r){const e=r.injector.get(Rt);r.track(e.register({id:"default-greys",name:"Greys",category:"utility",swatches:["transparent","#ffffff","#f5f5f5","#e0e0e0","#bdbdbd","#9e9e9e","#616161","#424242","#000000"]})),r.track(e.register({id:"material-primary",name:"Material 500",category:"brand",swatches:["#f44336","#e91e63","#9c27b0","#3f51b5","#2196f3","#009688","#4caf50","#ffc107","#ff9800","#795548"]})),r.track(e.register({id:"tailwind-pastels",name:"Pastels",category:"brand",swatches:["#fecaca","#fed7aa","#fde68a","#bbf7d0","#a7f3d0","#bfdbfe","#c7d2fe","#ddd6fe","#fbcfe8"]}))}},Lg=m(()=>!1,...ngDevMode?[{debugName:"ALWAYS_ENABLED"}]:[]);function Xs(r,e){const t=r.disabled;return t==null?Lg:typeof t=="function"&&t.length>0?t(e):t}function $g(r){const e=new Map;return t=>{const n=e.get(t.id);if(n!==void 0)return n;const o=Xs(t,r);return e.set(t.id,o),o}}function Lo(r,e){if(r.divider===!0)return;const t={injector:e};r.run(t)}class Me{_contributions=b([],...ngDevMode?[{debugName:"_contributions"}]:[]);contributions=this._contributions.asReadonly();register(e){if(typeof e.id!="string"||e.id.length===0)throw new Error("MenuContributionRegistry.register: contribution.id must be non-empty");if(typeof e.slot!="string"||e.slot.length===0)throw new Error("MenuContributionRegistry.register: contribution.slot must be non-empty");if(this._contributions().some(t=>t.id===e.id))throw new Error(`MenuContributionRegistry.register: contribution "${e.id}" is already registered`);return this._contributions.set([...this._contributions(),e]),{dispose:()=>{this._contributions.set(this._contributions().filter(t=>t.id!==e.id))}}}bySlot(e){return m(()=>[...this._contributions().filter(n=>n.slot!==e?!1:n.visible==null?!0:n.visible())].sort((n,o)=>(n.order??100)-(o.order??100)))}get(e){return this._contributions().find(t=>t.id===e)??null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Me,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Me,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Me,decorators:[{type:D,args:[{providedIn:"root"}]}]});const y={FILE:"menu.file",EDIT:"menu.edit",VIEW:"menu.view",INSERT:"menu.insert",OBJECT:"menu.object",PATH:"menu.path",TOOLS:"menu.tools",WINDOW:"menu.window",HELP:"menu.help"},me={MAIN:"toolbar.main"},Q={CANVAS:"context.canvas",NODE:"context.node",LAYER:"context.layer",ANCHOR:"context.anchor",GUIDE:"context.guide"};class at{state=f(S);bus=f(M);activePage=f(j,{optional:!0});containerId=m(()=>{const e=this.activePage?.effectiveDrawTargetId()??null;return e!==null?e:this.state.document().root.id},...ngDevMode?[{debugName:"containerId"}]:[]);doc=m(()=>{const e=this.state.document(),t=T(e.root,this.containerId());return qd(t)??Zd()},...ngDevMode?[{debugName:"doc"}]:[]);tracks=m(()=>this.doc().tracks,...ngDevMode?[{debugName:"tracks"}]:[]);durationMs=m(()=>this.doc().durationMs,...ngDevMode?[{debugName:"durationMs"}]:[]);addKeyframe(e,t,n){return this.bus.dispatch(new Jd(this.containerId(),e,t,n))}removeKeyframe(e,t,n){return this.bus.dispatch(new Qd(this.containerId(),e,t,n))}removeTrack(e,t){return this.bus.dispatch(new eu(this.containerId(),e,t))}moveKeyframe(e,t,n,o,i){return this.bus.dispatch(new tu(this.containerId(),e,t,n,o,i))}setKeyframeEasing(e,t,n,o){return this.bus.dispatch(new nu(this.containerId(),e,t,n,o))}setDuration(e){return this.bus.dispatch(new ru(this.containerId(),e))}sample(e){return ou(this.doc(),e)}animatablePropertiesFor(e){const t=T(this.state.document().root,e);return t===null?[]:iu(t)}currentValue(e,t){const n=T(this.state.document().root,e);return n===null?null:su(n,t)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:at,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:at,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:at,decorators:[{type:D,args:[{providedIn:"root"}]}]});class _e{_items=b([],...ngDevMode?[{debugName:"_items"}]:[]);_externalStamp=b(null,...ngDevMode?[{debugName:"_externalStamp"}]:[]);items=this._items.asReadonly();externalStamp=this._externalStamp.asReadonly();hasContent=m(()=>this._items().length>0,...ngDevMode?[{debugName:"hasContent"}]:[]);size=m(()=>this._items().length,...ngDevMode?[{debugName:"size"}]:[]);copy(e){if(e.length===0)return;const t=e.map(n=>Ii(n));this._items.set(t),this._externalStamp.set(null)}setExternalStamp(e){this._externalStamp.set(e)}paste(){const e=this._items();return e.length===0?[]:e.map(t=>Ii(t))}clear(){this._externalStamp.set(null),this._items().length!==0&&this._items.set([])}peekIds(){return this._items().map(e=>e.id)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:_e,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:_e,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:_e,decorators:[{type:D,args:[{providedIn:"root"}]}]});let Bg=0;function Fg(){return`svgi${++Bg}-`}const Zt=3;function $o(r,e){const t=br(r);return t.width>0&&t.height>0?t:e}function Ys(r,e){const t=Math.abs(e.width)<Zt&&Math.abs(e.height)<Zt,n=r.width||1,o=r.height||1,i=t?1:Math.max(1e-4,Math.min(Math.abs(e.width)/n,Math.abs(e.height)/o)),a=e.x+e.width/2,l=e.y+e.height/2,c=a-i*(r.x+r.width/2),u=l-i*(r.y+r.height/2);return[i,0,0,i,c,u]}function qs(r,e){if(Math.abs(e.width)<Zt&&Math.abs(e.height)<Zt){const l=e.x+e.width/2,c=e.y+e.height/2;return[1,0,0,1,l-(r.x+r.width/2),c-(r.y+r.height/2)]}const n=Math.max(1e-4,Math.abs(e.width)/(r.width||1)),o=Math.max(1e-4,Math.abs(e.height)/(r.height||1)),i=e.x-n*r.x,a=e.y-o*r.y;return[n,0,0,o,i,a]}function Zs(r,e){return{x:Math.min(r.x,e.x),y:Math.min(r.y,e.y),width:Math.abs(e.x-r.x),height:Math.abs(e.y-r.y)}}class Ee{bus=f(M);state=f(S);selection=f(k);activePage=f(j);viewport=f(A);_pending=b(null,...ngDevMode?[{debugName:"_pending"}]:[]);pending=this._pending.asReadonly();dragStart=null;_rect=b(null,...ngDevMode?[{debugName:"_rect"}]:[]);rect=this._rect.asReadonly();_stretch=b(!1,...ngDevMode?[{debugName:"_stretch"}]:[]);stretch=this._stretch.asReadonly();hasDragRect=m(()=>{const e=this._rect();return e===null?!1:Math.abs(e.width)>=Zt||Math.abs(e.height)>=Zt},...ngDevMode?[{debugName:"hasDragRect"}]:[]);placedTransform=m(()=>{const e=this._pending(),t=this._rect();return e===null||t===null?null:this._stretch()?qs(e.src,t):Ys(e.src,t)},...ngDevMode?[{debugName:"placedTransform"}]:[]);get isActive(){return this._pending()!==null}begin(e){this._pending.set(e),this.dragStart=null,this._rect.set(null),this._stretch.set(!1)}setStretch(e){this._stretch.set(e)}beginDrag(e){this._pending()!==null&&(this.dragStart=e,this._rect.set({x:e.x,y:e.y,width:0,height:0}))}updateDrag(e){this.dragStart!==null&&this._rect.set(Zs(this.dragStart,e))}commitDrag(){const e=this._pending(),t=this.placedTransform();if(e===null||this.dragStart===null||t===null){this.cancel();return}const{group:n,defs:o}=this.namespaceIncoming(e.group,e.defs),i={...n,transform:t};this.mergeDefs(o),this.bus.dispatch(new he(te,i)),this.selection.select(i.id),this.cancel()}cancel(){this._pending.set(null),this.dragStart=null,this._rect.set(null),this._stretch.set(!1)}placeDocumentCentered(e){const t=e.root;if(t.type!=="group"||t.children.length===0)return null;const{group:n,defs:o}=this.namespaceIncoming(t,e.defs),i=$o(n,e.viewBox),a=i.x+i.width/2,l=i.y+i.height/2,{cx:c,cy:u}=this.insertionCenter(),h={...n,transform:[1,0,0,1,c-a,u-l]};return this.mergeDefs(o),this.bus.dispatch(new he(te,h)),this.selection.select(h.id),h.id}namespaceIncoming(e,t){if(t===void 0||t.length===0)return{group:e,defs:""};const n=qu(this.state.document().defs),o=Zu(e,t,n,Fg());return{group:o.root,defs:o.defs}}mergeDefs(e){if(e.length===0)return;const t=this.state.document();this.state.setDocument({...t,defs:_i(t.defs??"",e)})}insertionCenter(){const e=this.activePage.activePageViewBox();if(e!==null)return{cx:e.x+e.width/2,cy:e.y+e.height/2};const t=this.viewport.viewBox();return{cx:t.x+t.width/2,cy:t.y+t.height/2}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ee,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ee,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ee,decorators:[{type:D,args:[{providedIn:"root"}]}]});const jg=/<svg[\s>]/i;function Vg(r,e){const t=br(mt(e));return{id:"clip",viewBox:t.width>0&&t.height>0?t:{x:0,y:0,width:100,height:100},defs:r.get(S).document().defs,root:mt(e,{id:"clip-root"})}}async function zg(r,e){if(e.length===0)return;const t=Vg(r,e),n=vt.export(t);if(typeof n!="string"||(r.get(_e).setExternalStamp(n),typeof navigator>"u"||navigator.clipboard===void 0))return;const o=new Blob([n],{type:"text/plain"});try{if(typeof ClipboardItem<"u"&&navigator.clipboard.write!==void 0){const i=new ClipboardItem({"text/plain":o,"image/png":to(t)});await navigator.clipboard.write([i]);return}}catch{}try{await navigator.clipboard.writeText?.(n)}catch{}}async function Gg(r){if(typeof navigator>"u"||navigator.clipboard===void 0||navigator.clipboard.read===void 0)return!1;let e;try{e=await navigator.clipboard.read()}catch{return!1}const t=r.get(_e);for(const n of e){const o=n.types.find(a=>a.startsWith("image/"));if(o!==void 0)try{const a=await n.getType(o);if(await Hg(r,a))return!0}catch{}const i=n.types.includes("text/plain")?"text/plain":n.types.includes("text/html")?"text/html":void 0;if(i!==void 0){let a;try{a=(await(await n.getType(i)).text()).trim()}catch{continue}if(a.length===0)continue;if(t.hasContent()&&a===t.externalStamp())return!1;if(jg.test(a)){if(Ug(r,a))return!0}else return Wg(r,a),!0}}return!1}async function Hg(r,e){const t=await Kg(e),n=await Xg(t);if(n===null)return!1;const o=wr({x:0,y:0,width:n.width,height:n.height,href:t},{style:{}}),i={id:"clip",viewBox:{x:0,y:0,width:n.width,height:n.height},root:mt([o],{id:"clip-root"})};return r.get(Ee).placeDocumentCentered(i)!==null}function Ug(r,e){const t=ze.import(e);return t.ok?r.get(Ee).placeDocumentCentered(t.document)!==null:!1}function Wg(r,e){const t=e.length>2e3?e.slice(0,2e3):e,n=Zr({x:0,y:16,content:t,fontSize:16,fontFamily:"system-ui, sans-serif"},{style:{fill:"#000000"}}),o={id:"clip",viewBox:{x:0,y:0,width:240,height:32},root:mt([n],{id:"clip-root"})};r.get(Ee).placeDocumentCentered(o)}function Kg(r){return new Promise((e,t)=>{const n=new FileReader;n.onload=()=>e(n.result),n.onerror=()=>t(new Error("FileReader failed to read clipboard image")),n.readAsDataURL(r)})}function Xg(r){return new Promise(e=>{if(typeof Image>"u"){e(null);return}const t=new Image;t.onload=()=>e({width:t.naturalWidth||1,height:t.naturalHeight||1}),t.onerror=()=>e(null),t.src=r})}const Js=new gt("RECENT_FILES_STORAGE_KEY",{providedIn:"root",factory:()=>"svge:recent-files"}),Qs=10,ea=256*1024;class lt{document=f(re);storageKey=f(Js);_files=b(this.load(),...ngDevMode?[{debugName:"_files"}]:[]);files=this._files.asReadonly();isEmpty=m(()=>this._files().length===0,...ngDevMode?[{debugName:"isEmpty"}]:[]);listeners=new Set;onChange(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notify(){for(const e of this.listeners)e()}record(e,t){const n=e.trim()===""?"Untitled.svg":e.trim();if(t.length>ea){typeof console<"u"&&console.warn(`RecentFilesService: "${n}" (${t.length} B) exceeds the ${ea} B per-entry cap \u2014 not added to recent files.`);return}const o={name:n,svg:t,openedAt:new Date().toISOString()},i=n.toLowerCase(),a=[o,...this._files().filter(l=>l.name.toLowerCase()!==i)].slice(0,Qs);this._files.set(a),this.persist(a),this.notify()}clear(){this._files().length!==0&&(this._files.set([]),this.persist([]),this.notify())}load(){const e=this.window(),t=this.key();if(e===null||t===null)return[];let n;try{n=e.localStorage.getItem(t)}catch{return[]}if(n===null||n.length===0)return[];try{const o=JSON.parse(n);return Array.isArray(o)?o.filter(i=>typeof i=="object"&&i!==null&&typeof i.name=="string"&&typeof i.svg=="string"&&typeof i.openedAt=="string").slice(0,Qs):[]}catch{return[]}}persist(e){const t=this.window(),n=this.key();if(t===null||n===null)return;if(e.length===0){try{t.localStorage.removeItem(n)}catch{}return}let o=[...e];for(;o.length>0;)try{t.localStorage.setItem(n,JSON.stringify(o));return}catch{o=o.slice(0,o.length-1)}typeof console<"u"&&console.warn("RecentFilesService: localStorage write failed (quota / private mode).")}key(){const e=this.storageKey;return e===null||e.length===0?null:e}window(){const e=this.document.defaultView;return e!==null?e:typeof window<"u"?window:null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:lt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:lt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:lt,decorators:[{type:D,args:[{providedIn:"root"}]}]});function Yg(r){const e=[];return je(r,t=>{e.push(t.id)}),e}function ta(r,e){if(e.length===0)return null;const t=Yg(r),n=[...e].sort((o,i)=>t.indexOf(o)-t.indexOf(i));return T(r,n[n.length-1])}function na(r,e){const t=r.get(k),n=r.get(S),o=Array.from(t.selectedIds());if(o.length<2)return;const i=n.document().root,a=ta(i,o);if(a===null||e==="clipPath"&&a.type==="image")return;const l=a.id,c=o.filter(x=>x!==l),u=Ju(a);if(u.trim().length===0)return;const h=e==="clipPath"?"clipPath":"mask",g=e==="clipPath"?"clipPathUnits":"maskUnits",v=`svge-${e==="clipPath"?"clip":"mask"}-${Ht()}`,p=`<${h} id="${v}" ${g}="userSpaceOnUse">
1191
+ ${u}
1192
+ </${h}>`;r.get(M).dispatch(new au(c,l,v,p,e)),t.selectMany(c)}function qg(r,e,t){const n=r.get(S),o=T(n.document().root,e);if(o===null)return;const i=lu(o.style[t]);let a=null;if(i!==null){const l=cu(n.document().defs,i);if(l!==null){const c=l.replace(/^\s*<(clipPath|mask)\b[^>]*>/i,"").replace(/<\/(clipPath|mask)>\s*$/i,"").trim(),u=ze.import(`<svg xmlns="http://www.w3.org/2000/svg">${c}</svg>`);u.ok&&u.document.root.children.length>0&&(a=u.document.root.children[0])}}r.get(M).dispatch(new du(e,t,a))}class dn{findAll(e,t){const n=[];return je(e,o=>{const i=Zg(o,t);i!==null&&n.push(i)}),n}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:dn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:dn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:dn,decorators:[{type:D,args:[{providedIn:"root"}]}]});function Zg(r,e){switch(e.kind){case"fill":{const t=r.style.fill;return typeof t!="string"||Nr(t)!==Nr(e.value)?null:{id:r.id,bucket:"style",field:"fill",currentValue:t}}case"stroke":{const t=r.style.stroke;return typeof t!="string"||Nr(t)!==Nr(e.value)?null:{id:r.id,bucket:"style",field:"stroke",currentValue:t}}case"fontFamily":{if(r.type!=="text")return null;const t=r.fontFamily;if(typeof t!="string")return null;const n=e.value;if((e.match??"contains")==="exact"){if(t!==n)return null}else if(!t.toLowerCase().includes(n.toLowerCase()))return null;return{id:r.id,bucket:"top",field:"fontFamily",currentValue:t}}case"attribute":{const t=r[e.key];if(t==null)return null;const n=String(t);return n!==e.value?null:{id:r.id,bucket:"top",field:e.key,currentValue:n}}}}function Nr(r){return r.trim().toLowerCase()}class Ye{state=f(S);selection=f(k);findSvc=f(dn);selectSameFill(){const e=this.getFocusedNode();if(e===null)return 0;const t=e.style.fill;return typeof t!="string"||t.length===0?0:this.applyMatches({kind:"fill",value:t})}selectSameStroke(){const e=this.getFocusedNode();if(e===null)return 0;const t=e.style.stroke;return typeof t!="string"||t.length===0?0:this.applyMatches({kind:"stroke",value:t})}selectSameFontFamily(){const e=this.getFocusedNode();if(e===null||e.type!=="text")return 0;const t=e.fontFamily;return typeof t!="string"||t.length===0?0:this.applyMatches({kind:"fontFamily",value:t,match:"exact"})}getFocusedNode(){const e=this.selection.focusId();return e===null?null:T(this.state.document().root,e)}applyMatches(e){const t=this.findSvc.findAll(this.state.document().root,e);if(t.length===0)return 0;const n=t.map(o=>o.id);return this.selection.selectMany(n),n.length}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ye,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ye})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ye,decorators:[{type:D}]});function Jg(r){const e=r.get(j).activePageViewBox();if(e!==null)return{cx:e.x+e.width/2,cy:e.y+e.height/2};const t=r.get(A).viewBox();return{cx:t.x+t.width/2,cy:t.y+t.height/2}}function Qg(r,e,t,n){return wr({x:r.cx-e/2,y:r.cy-t/2,width:e,height:t,href:n,preserveAspectRatio:"xMidYMid meet"})}function Lr(r,e){if(r===void 0||typeof Image>"u")return;const t=new Image;t.onload=()=>{const n=t.naturalWidth||200,o=t.naturalHeight||200,i=Qg(Jg(r),n,o,e);r.get(M).dispatch(new he(te,i)),r.get(k).select(i.id)},t.onerror=()=>{typeof window<"u"&&window.alert("Could not load the image.")},t.src=e}function ra(r){if(r===void 0||typeof document>"u")return;const e=document.createElement("input");e.type="file",e.accept="image/*",e.style.display="none",e.addEventListener("change",()=>{const t=e.files?.[0];if(e.remove(),t==null)return;const n=new FileReader;n.onload=()=>{typeof n.result=="string"&&Lr(r,n.result)},n.readAsDataURL(t)},{once:!0}),document.body.appendChild(e),e.click()}const oa="svge:import:placement-mode";class un{_placementMode=b(ep(),...ngDevMode?[{debugName:"_placementMode"}]:[]);placementMode=this._placementMode.asReadonly();setPlacementMode(e){e!==this._placementMode()&&(this._placementMode.set(e),tp(e))}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:un,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:un,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:un,decorators:[{type:D,args:[{providedIn:"root"}]}]});function ep(){if(typeof localStorage>"u")return"centered";try{return localStorage.getItem(oa)==="place"?"place":"centered"}catch{return"centered"}}function tp(r){if(!(typeof localStorage>"u"))try{localStorage.setItem(oa,r)}catch{}}class ct{_effects=b([],...ngDevMode?[{debugName:"_effects"}]:[]);effects=this._effects.asReadonly();register(e){if(typeof e.id!="string"||e.id.length===0)throw new Error("EffectRegistry.register: effect.id must be a non-empty string");if(this._effects().some(t=>t.id===e.id))throw new Error(`EffectRegistry.register: effect "${e.id}" is already registered`);return this._effects.set([...this._effects(),e]),{dispose:()=>{this._effects.set(this._effects().filter(t=>t.id!==e.id))}}}get(e){return this._effects().find(t=>t.id===e)??null}byCategory(e){return this._effects().filter(t=>t.category===e)}buildAllFiltersMarkup(){const e=this._effects();return e.length===0?"":e.map(t=>t.buildFilterMarkup()).join(`
1193
+ `)}buildUsedFiltersMarkup(e){const t=this._effects();if(t.length===0)return"";const n=rp(e);return n.size===0?"":t.filter(o=>n.has(o.id)).map(o=>o.buildFilterMarkup()).join(`
1194
+ `)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ct,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ct,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ct,decorators:[{type:D,args:[{providedIn:"root"}]}]});const np=/url\(\s*#([^)\s]+)\s*\)/g;function rp(r){const e=new Set;return je(r,t=>{const n=t.style?.filter;if(!(typeof n!="string"||n.length===0))for(const o of n.matchAll(np))e.add(o[1])}),e}const Ln="svge-chain-",Bo="__";function op(r){return Ln+r.join(Bo)}function Fo(r){if(!r.startsWith(Ln))return null;const e=r.slice(Ln.length);return e===""?[]:e.split(Bo)}function ia(r){if(r===void 0)return null;const e=/^url\(#(.+?)\)$/.exec(r.trim());if(e===null)return null;const t=e[1];return t.startsWith(Ln)?t:null}function ip(r,e){if(r.length===0)return`<filter id="${e}"></filter>`;const t=[];for(let n=0;n<r.length;n++){const o=sp(r[n].buildFilterMarkup()),i=n===0?null:`step${n-1}-out`,a=n===0?null:`step${n-1}-out-alpha`;t.push(ap(o,n,i,a))}return`<filter id="${e}" x="-50%" y="-50%" width="200%" height="200%">
1195
+ ${t.join(`
1196
+ `)}
1197
+ </filter>`}function sp(r){const e=/<filter\b[^>]*>([\s\S]*)<\/filter>/.exec(r);return e===null?r:e[1].trim()}function ap(r,e,t,n){const o=`step${e}-`;let i=r;const a=new Set,l=/result="([^"]+)"/g;let c;for(;(c=l.exec(r))!==null;)a.add(c[1]);i=i.replace(/result="([^"]+)"/g,(u,h)=>`result="${o}${h}"`);for(const u of a){const h=u.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");i=i.replace(new RegExp(`(in2?)="${h}"`,"g"),(g,v)=>`${v}="${o}${u}"`)}return t!==null&&(i=i.replace(/(in2?)="SourceGraphic"/g,`$1="${t}"`)),n!==null&&(i=i.replace(/(in2?)="SourceAlpha"/g,`$1="${n}"`)),i+=`
1198
+ <feOffset dx="0" dy="0" result="${o}out" />
1199
+ <feColorMatrix in="${o}out" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0" result="${o}out-alpha" />`,i}class At{state=f(S);effects=f(ct);activeChains=m(()=>{const e=new Set;return je(this.state.document().root,t=>{const n=ia(t.style.filter);if(n===null)return;const o=Fo(n);o!==null&&o.every(i=>this.effects.get(i)!==null)&&e.add(n)}),[...e]},...ngDevMode?[{debugName:"activeChains"}]:[]);buildAllChainsMarkup(){const e=this.activeChains();if(e.length===0)return"";const t=[];for(const n of e){const o=Fo(n);if(o===null)continue;const i=o.map(a=>this.effects.get(a)).filter(a=>a!==null);i.length===o.length&&t.push(ip(i,n))}return t.join(`
1200
+ `)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:At,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:At,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:At,decorators:[{type:D,args:[{providedIn:"root"}]}]});class Ct extends Ae{static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ct,deps:null,target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ct,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ct,decorators:[{type:D,args:[{providedIn:"root"}]}]});class hn{state=f(S);catalog=f(Ct);activeClipPathIds=m(()=>{const e=new Set;return je(this.state.document().root,t=>{lp(t.style.clipPath,e)}),[...e].filter(t=>this.catalog.get(t)!==null)},...ngDevMode?[{debugName:"activeClipPathIds"}]:[]);buildAllActiveClipPathsMarkup(){const e=this.activeClipPathIds();return e.length===0?"":e.map(t=>this.catalog.get(t)?.buildMarkup()??"").filter(t=>t.length>0).join(`
1201
+ `)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:hn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:hn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:hn,decorators:[{type:D,args:[{providedIn:"root"}]}]});function lp(r,e){if(r===void 0)return;const t=/^url\(\s*['"]?#([^'"\s)]+)['"]?\s*\)$/.exec(r.trim());t!==null&&e.add(t[1])}function jo(r){const e=r.stops.map(cp).join(`
1202
+ `);if(r.kind==="linear"){const c=r.geometry??{},u=Ge(c.x1??0),h=Ge(c.y1??0),g=Ge(c.x2??1),v=Ge(c.y2??0);return`<linearGradient id="${r.id}" x1="${u}" y1="${h}" x2="${g}" y2="${v}">
1203
+ ${e}
1204
+ </linearGradient>`}const t=r.geometry??{},n=Ge(t.cx??.5),o=Ge(t.cy??.5),i=Ge(t.r??.5),a=t.fx!==void 0?` fx="${Ge(t.fx)}"`:"",l=t.fy!==void 0?` fy="${Ge(t.fy)}"`:"";return`<radialGradient id="${r.id}" cx="${n}" cy="${o}" r="${i}"${a}${l}>
1205
+ ${e}
1206
+ </radialGradient>`}function Ge(r){return`${(r*100).toFixed(2).replace(/\.?0+$/,"")}%`}function cp(r){const e=r.opacity??1,t=e!==1?` stop-opacity="${e}"`:"";return`<stop offset="${(r.offset*100).toFixed(2).replace(/\.?0+$/,"")}%" stop-color="${r.color}"${t} />`}class Ne extends Ae{static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ne,deps:null,target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ne,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ne,decorators:[{type:D,args:[{providedIn:"root"}]}]});class gn{state=f(S);catalog=f(Ne);activeGradientIds=m(()=>{const e=new Set;return je(this.state.document().root,t=>{sa(t.style.fill,e),sa(t.style.stroke,e)}),[...e].filter(t=>this.catalog.get(t)!==null)},...ngDevMode?[{debugName:"activeGradientIds"}]:[]);buildAllActiveGradientsMarkup(){const e=this.activeGradientIds();if(e.length===0)return"";const t=[];for(const n of e){const o=this.catalog.get(n);o!==null&&t.push(o.buildMarkup())}return t.join(`
1207
+ `)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:gn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:gn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:gn,decorators:[{type:D,args:[{providedIn:"root"}]}]});function sa(r,e){if(r===void 0)return;const t=/^url\(\s*['"]?#([^'"\s)]+)['"]?\s*\)$/.exec(r.trim());t!==null&&e.add(t[1])}class Ot extends Ae{static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ot,deps:null,target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ot,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Ot,decorators:[{type:D,args:[{providedIn:"root"}]}]});class pn{state=f(S);catalog=f(Ot);activeMaskIds=m(()=>{const e=new Set;return je(this.state.document().root,t=>{dp(t.style.mask,e)}),[...e].filter(t=>this.catalog.get(t)!==null)},...ngDevMode?[{debugName:"activeMaskIds"}]:[]);buildAllActiveMasksMarkup(){const e=this.activeMaskIds();return e.length===0?"":e.map(t=>this.catalog.get(t)?.buildMarkup()??"").filter(t=>t.length>0).join(`
1208
+ `)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:pn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:pn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:pn,decorators:[{type:D,args:[{providedIn:"root"}]}]});function dp(r,e){if(r===void 0)return;const t=/^url\(\s*['"]?#([^'"\s)]+)['"]?\s*\)$/.exec(r.trim());t!==null&&e.add(t[1])}class Nt extends Ae{static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Nt,deps:null,target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Nt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Nt,decorators:[{type:D,args:[{providedIn:"root"}]}]});class fn{state=f(S);catalog=f(Nt);activePatternIds=m(()=>{const e=new Set;return je(this.state.document().root,t=>{aa(t.style.fill,e),aa(t.style.stroke,e)}),[...e].filter(t=>this.catalog.get(t)!==null)},...ngDevMode?[{debugName:"activePatternIds"}]:[]);buildAllActivePatternsMarkup(){const e=this.activePatternIds();return e.length===0?"":e.map(t=>this.catalog.get(t)?.buildMarkup()??"").filter(t=>t.length>0).join(`
1209
+ `)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:fn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:fn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:fn,decorators:[{type:D,args:[{providedIn:"root"}]}]});function aa(r,e){if(r===void 0)return;const t=/^url\(\s*['"]?#([^'"\s)]+)['"]?\s*\)$/.exec(r.trim());t!==null&&e.add(t[1])}class Le{state=f(S);effects=f(ct);chains=f(At);gradients=f(gn);patterns=f(fn);clipPaths=f(hn);masks=f(pn);symbols=f(on);composed=m(()=>{const e=[this.effects.buildAllFiltersMarkup(),this.chains.buildAllChainsMarkup(),this.gradients.buildAllActiveGradientsMarkup(),this.patterns.buildAllActivePatternsMarkup(),this.clipPaths.buildAllActiveClipPathsMarkup(),this.masks.buildAllActiveMasksMarkup(),this.symbols.buildAllActiveSymbolsMarkup()].filter(t=>t.length>0);return e.length>0?e.join(`
1210
+ `):null},...ngDevMode?[{debugName:"composed"}]:[]);buildExportDefs(e){const t=e??"",n=this.state.document().root,o=[this.effects.buildUsedFiltersMarkup(n),this.chains.buildAllChainsMarkup(),this.gradients.buildAllActiveGradientsMarkup(),this.patterns.buildAllActivePatternsMarkup(),this.clipPaths.buildAllActiveClipPathsMarkup(),this.masks.buildAllActiveMasksMarkup(),this.symbols.buildAllActiveSymbolsMarkup()].filter(i=>i.length>0).join(`
1211
+ `);return t.length===0?o:o.length===0?t:`${t}
1212
+ ${o}`}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Le,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Le,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Le,decorators:[{type:D,args:[{providedIn:"root"}]}]});const It={LAYERS:"layers",HISTORY:"history",PROPERTIES:"properties",APPEARANCE:"appearance",EXPORT:"export",GRADIENT:"gradient"};class Lt{nonce=0;_revealRequest=b(null,...ngDevMode?[{debugName:"_revealRequest"}]:[]);revealRequest=this._revealRequest.asReadonly();_activePanelId=b(null,...ngDevMode?[{debugName:"_activePanelId"}]:[]);activePanelId=this._activePanelId.asReadonly();reveal(e){this._revealRequest.set({panelId:e,nonce:++this.nonce})}setActivePanel(e){this._activePanelId.set(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Lt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Lt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Lt,decorators:[{type:D,args:[{providedIn:"root"}]}]});class dt{bus=f(M);state=f(S);document=f(re);replaceContents(e){if(typeof this.document>"u")return;const t=this.document.createElement("input");t.type="file",t.accept=".svg,image/svg+xml",t.style.display="none",t.addEventListener("change",()=>{const n=t.files?.[0];t.remove(),n?.text().then(o=>{const i=this.applyReplaceText(e,o);!i.ok&&i.error!==void 0&&this.alert(`Replace failed: ${i.error}`),i.warnings.length>0&&typeof console<"u"&&console.warn(`[SVGEngine] Replace warnings:
1213
+ ${i.warnings.join(`
1214
+ `)}`)})},{once:!0}),this.document.body.appendChild(t),t.click()}applyReplaceText(e,t){const n=ze.import(t);if(!n.ok)return{ok:!1,error:n.error,warnings:[]};const o=n.document.root.children;return o.length===0?{ok:!1,error:"imported SVG has no shapes",warnings:n.warnings}:(this.mergeImportedDefs(n.document.defs),this.bus.dispatch(new uu(e,o)),{ok:!0,warnings:n.warnings})}mergeImportedDefs(e){if(e===void 0||e.length===0)return;const t=this.state.document(),n=_i(t.defs,e);n!==t.defs&&this.state.setDocument({...t,defs:n})}release(e){this.bus.dispatch(new hu(e))}rasterize(e){this.release(e)}alert(e){typeof window<"u"&&typeof window.alert=="function"&&window.alert(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:dt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:dt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:dt,decorators:[{type:D,args:[{providedIn:"root"}]}]});const la={id:"svge.builtin.menu-contributions",name:"Built-in editor menu / toolbar / context items (D-043)",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(Me),t=d=>{const w=d.get(Wt);return m(()=>!w.canUndo())},n=d=>{const w=d.get(Wt);return m(()=>!w.canRedo())},o=d=>{const w=d.get(k);return m(()=>!w.hasSelection())},i=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=w.selectedIds();if(P.size<2)return!0;const _=I.document().root;for(const R of P){const $=T(_,R);if($!==null&&(zt($)||$e($)))return!0}return!1})},a=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=w.focusId();if(P===null)return!0;const _=T(I.document().root,P);return _===null||_.type!=="group"})},l=d=>{const w=d.get(_e);return m(()=>!w.hasContent())},c=d=>{const w=d.get(k);return m(()=>w.selectedIds().size<1)},u=d=>{const w=d.get(k);return m(()=>{const I=w.selectedIds();if(I.size<2)return!0;const P=w.focusId();return P===null||!I.has(P)})},h=d=>{const w=d.get(be);return m(()=>!w.hasKeyObject())},g=d=>{const w=d.get(k);return m(()=>w.selectedIds().size<3)},v=d=>{const w=d.get(k);return m(()=>w.selectedIds().size<2)},p=(d,w)=>(w?.injector??r.injector).get(d);r.track(e.register({id:"svge.builtin.file.new",slot:y.FILE,label:"New",icon:"insert_drive_file",shortcut:"Ctrl+N",order:10,run(d){fp(d,p)}})),r.track(e.register({id:"svge.builtin.file.open",slot:y.FILE,label:"Open\u2026",icon:"file_open",shortcut:"Ctrl+O",order:12,run(d){mp(d,p)}})),r.track(e.register({id:"svge.builtin.file.open-recent",slot:y.FILE,label:"Open Recent",icon:"history",order:14,run(){}}));{const d=r.injector.get(lt),w=b(!0,...ngDevMode?[{debugName:"emptyRowDisabled"}]:[]);let I=[];const P=()=>{for(const R of I)R.dispose();I=[];const _=d.files();if(_.length===0){I.push(e.register({id:"svge.builtin.file.open-recent.empty",parentId:"svge.builtin.file.open-recent",slot:y.FILE,label:"No recent files",order:0,disabled:w,run(){}}));return}_.forEach((R,$)=>{I.push(e.register({id:`svge.builtin.file.open-recent.item-${$}`,parentId:"svge.builtin.file.open-recent",slot:y.FILE,label:R.name,tooltip:R.name,icon:"description",order:$,run(F){ga(F,p,R.svg,R.name)}}))}),I.push(e.register({id:"svge.builtin.file.open-recent.divider",parentId:"svge.builtin.file.open-recent",slot:y.FILE,label:"",order:9e3,divider:!0,run(){}})),I.push(e.register({id:"svge.builtin.file.open-recent.clear",parentId:"svge.builtin.file.open-recent",slot:y.FILE,label:"Clear Recent Files",icon:"delete_sweep",order:9001,run(R){p(lt,R).clear()}}))};P(),r.track({dispose:d.onChange(P)}),r.track({dispose:()=>{for(const _ of I)_.dispose()}})}r.track(e.register({id:"svge.builtin.file.divider1",slot:y.FILE,label:"",order:18,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.file.import-menu",slot:y.FILE,label:"Import",icon:"folder_open",order:20,run(){}})),r.track(e.register({id:"svge.builtin.file.import",parentId:"svge.builtin.file.import-menu",slot:y.FILE,label:"SVG\u2026",icon:"description",order:10,run(d){pa(d,p)}})),r.track(e.register({id:"svge.builtin.file.import-image",parentId:"svge.builtin.file.import-menu",slot:y.FILE,label:"Image\u2026",icon:"image",order:15,run(d){ra(d?.injector)}})),r.track(e.register({id:"svge.builtin.file.import-url",parentId:"svge.builtin.file.import-menu",slot:y.FILE,label:"From URL\u2026",icon:"link",order:20,run(d){wp(d,p)}})),r.track(e.register({id:"svge.builtin.file.import-smart-object",parentId:"svge.builtin.file.import-menu",slot:y.FILE,label:"Smart Object\u2026",icon:"inventory_2",order:30,run(d){pa(d,p,yp)}})),r.track(e.register({id:"svge.builtin.file.divider2",slot:y.FILE,label:"",order:38,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.file.save",slot:y.FILE,label:"Save",icon:"save",tooltip:"Save workspace (.svge \u2014 readable JSON)",shortcut:"Ctrl+S",order:30,run(d){wa(d,p,!1)}})),r.track(e.register({id:"svge.builtin.file.save-as",slot:y.FILE,label:"Save As\u2026 (Compressed)",icon:"save_as",tooltip:"Save compressed workspace (.svgez \u2014 gzipped)",order:32,run(d){wa(d,p,!0)}})),r.track(e.register({id:"svge.builtin.file.export-menu",slot:y.FILE,label:"Export",icon:"download",order:40,run(){}})),r.track(e.register({id:"svge.builtin.file.export-svg",parentId:"svge.builtin.file.export-menu",slot:y.FILE,label:"SVG\u2026",icon:"download",order:10,run(d){Fr(d,p,"svg")}})),r.track(e.register({id:"svge.builtin.file.export-svgz",parentId:"svge.builtin.file.export-menu",slot:y.FILE,label:"SVG (Compressed)\u2026",icon:"folder_zip",order:15,run(d){Fr(d,p,"svgz")}})),r.track(e.register({id:"svge.builtin.file.export-svg-animated",parentId:"svge.builtin.file.export-menu",slot:y.FILE,label:"Animated SVG (SMIL)\u2026",icon:"animation",order:20,run(d){Fr(d,p,"svg",!0)}})),r.track(e.register({id:"svge.builtin.file.export-png",parentId:"svge.builtin.file.export-menu",slot:y.FILE,label:"PNG\u2026",icon:"image",order:30,run(d){Fr(d,p,"png")}})),r.track(e.register({id:"svge.builtin.file.optimize",slot:y.FILE,label:"Optimize\u2026",icon:"auto_fix_high",order:60,run(d){const w=p(M,d),I=p(Ri,d);w.dispatch(new nh(I))}})),r.track(e.register({id:"svge.builtin.file.divider3",slot:y.FILE,label:"",order:70,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.edit.undo",slot:y.EDIT,label:"Undo",icon:"undo",shortcut:"Ctrl+Z",order:10,disabled:t,run(d){p(M,d).undo()}})),r.track(e.register({id:"svge.builtin.edit.redo",slot:y.EDIT,label:"Redo",icon:"redo",shortcut:"Ctrl+Shift+Z",order:20,disabled:n,run(d){p(M,d).redo()}})),r.track(e.register({id:"svge.builtin.edit.divider1",slot:y.EDIT,label:"",order:30,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.edit.delete",slot:y.EDIT,label:"Delete",icon:"delete",shortcut:"Delete",order:50,disabled:o,run(d){$r(d,p)}})),r.track(e.register({id:"svge.builtin.edit.select-menu",slot:y.EDIT,label:"Select",icon:"select_all",order:60,run(){}})),r.track(e.register({id:"svge.builtin.edit.select-all",parentId:"svge.builtin.edit.select-menu",slot:y.EDIT,label:"Select All",icon:"select_all",shortcut:"Ctrl+A",order:10,run(d){ca(d,p)}}));const x=d=>{const w=d.get(j);return m(()=>{const I=w.treeForRendering();return I.type!=="group"||I.children.length===0})};r.track(e.register({id:"svge.builtin.edit.invert-selection",parentId:"svge.builtin.edit.select-menu",slot:y.EDIT,label:"Invert Selection",icon:"flip",order:50,disabled:x,run(d){up(d,p)}}));const E=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=w.focusId();return P===null?!0:T(I.document().root,P)===null})},C=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=w.focusId();if(P===null)return!0;const _=T(I.document().root,P);return _===null||_.type!=="text"?!0:typeof _.fontFamily!="string"})};r.track(e.register({id:"svge.builtin.edit.select-same-fill",parentId:"svge.builtin.edit.select-menu",slot:y.EDIT,label:"Select Same Fill",icon:"palette",order:20,disabled:E,run(d){p(Ye,d).selectSameFill()}})),r.track(e.register({id:"svge.builtin.edit.select-same-stroke",parentId:"svge.builtin.edit.select-menu",slot:y.EDIT,label:"Select Same Stroke",icon:"border_color",order:30,disabled:E,run(d){p(Ye,d).selectSameStroke()}})),r.track(e.register({id:"svge.builtin.edit.select-same-font-family",parentId:"svge.builtin.edit.select-menu",slot:y.EDIT,label:"Select Same Font Family",icon:"text_format",order:40,disabled:C,run(d){p(Ye,d).selectSameFontFamily()}})),r.track(e.register({id:"svge.builtin.edit.cut",slot:y.EDIT,label:"Cut",icon:"content_cut",shortcut:"Ctrl+X",order:40,disabled:o,run(d){da(d,p)}})),r.track(e.register({id:"svge.builtin.edit.copy",slot:y.EDIT,label:"Copy",icon:"content_copy",shortcut:"Ctrl+C",order:42,disabled:o,run(d){Br(d,p)}})),r.track(e.register({id:"svge.builtin.edit.paste",slot:y.EDIT,label:"Paste",icon:"content_paste",shortcut:"Ctrl+V",order:44,run(d){Go(d,p,ua)}})),r.track(e.register({id:"svge.builtin.edit.paste-in-place",slot:y.EDIT,label:"Paste In Place",icon:"content_paste_go",shortcut:"Ctrl+Shift+V",order:46,run(d){Go(d,p,{x:0,y:0})}})),r.track(e.register({id:"svge.builtin.edit.duplicate",slot:y.EDIT,label:"Duplicate",icon:"control_point_duplicate",shortcut:"Ctrl+D",order:48,disabled:o,run(d){Ho(d,p)}}));const G=d=>{const w=d.get(Ze,null,{optional:!0});return w===null?m(()=>!0):m(()=>w.count()===0)};r.track(e.register({id:"svge.builtin.edit.history",slot:y.EDIT,label:"History",icon:"history",order:70,run(){}})),r.track(e.register({id:"svge.builtin.edit.history.take",parentId:"svge.builtin.edit.history",slot:y.EDIT,label:"Take Snapshot",icon:"photo_camera",shortcut:"Ctrl+Shift+S",order:10,run(d){const w=p(Ze,d),I=p(S,d);w.take(I.document(),{source:"manual"})}})),r.track(e.register({id:"svge.builtin.edit.history.restore-last",parentId:"svge.builtin.edit.history",slot:y.EDIT,label:"Restore Last Snapshot",icon:"restore",shortcut:"Ctrl+Alt+Z",order:20,disabled:G,run(d){const w=p(Ze,d),I=w.snapshots();if(I.length===0)return;const P=I.find(_=>_.source!=="auto-restore")??I[0];p(M,d).dispatch(new ki(P.id,w))}})),r.track(e.register({id:"svge.builtin.edit.history.divider1",parentId:"svge.builtin.edit.history",slot:y.EDIT,label:"",order:30,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.edit.history.clear",parentId:"svge.builtin.edit.history",slot:y.EDIT,label:"Clear All Snapshots",icon:"delete_sweep",order:40,disabled:G,run(d){typeof window<"u"&&!window.confirm("Delete all snapshots? This cannot be undone.")||p(Ze,d).clear()}})),r.track(e.register({id:"svge.builtin.view.zoom-menu",slot:y.VIEW,label:"Zoom",icon:"zoom_in",order:10,run(){}})),r.track(e.register({id:"svge.builtin.view.zoom-in",parentId:"svge.builtin.view.zoom-menu",slot:y.VIEW,label:"Zoom In",icon:"zoom_in",order:10,run(d){p(A,d).zoomIn()}})),r.track(e.register({id:"svge.builtin.view.zoom-out",parentId:"svge.builtin.view.zoom-menu",slot:y.VIEW,label:"Zoom Out",icon:"zoom_out",order:20,run(d){p(A,d).zoomOut()}})),r.track(e.register({id:"svge.builtin.view.zoom-reset",parentId:"svge.builtin.view.zoom-menu",slot:y.VIEW,label:"Reset Zoom",icon:"fit_screen",order:30,run(d){p(A,d).reset()}})),r.track(e.register({id:"svge.builtin.view.zoom-fit-canvas",parentId:"svge.builtin.view.zoom-menu",slot:y.VIEW,label:"Fit Canvas",icon:"crop_free",order:40,run(d){pp(d,p)}})),r.track(e.register({id:"svge.builtin.view.zoom-fit-selection",parentId:"svge.builtin.view.zoom-menu",slot:y.VIEW,label:"Fit Selection",icon:"center_focus_strong",order:50,disabled:o,run(d){gp(d,p)}})),r.track(e.register({id:"svge.builtin.view.zoom-actual-size",parentId:"svge.builtin.view.zoom-menu",slot:y.VIEW,label:"Actual Size (100%)",icon:"aspect_ratio",order:60,run(d){p(A,d).actualSize()}})),r.track(e.register({id:"svge.builtin.view.divider1",slot:y.VIEW,label:"",order:20,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.view.display-menu",slot:y.VIEW,label:"Display",icon:"visibility",order:30,run(){}})),r.track(e.register({id:"svge.builtin.view.display.presentation",parentId:"svge.builtin.view.display-menu",slot:y.VIEW,label:"Presentation Mode",icon:"slideshow",order:10,tooltip:"Hide all panels and chrome \u2014 show only the artwork. Press Esc to exit.",run(d){p(L,d).togglePresentationMode()}})),r.track(e.register({id:"svge.builtin.view.toggle-outline",parentId:"svge.builtin.view.display-menu",slot:y.VIEW,label:"Outline Mode",icon:"gesture",order:20,run(d){p(L,d).toggleOutlineMode()}})),r.track(e.register({id:"svge.builtin.view.display.pixel-preview",parentId:"svge.builtin.view.display-menu",slot:y.VIEW,label:"Pixel Preview",icon:"grid_4x4",order:30,tooltip:"Preview the artwork rasterized to the pixel grid (hard, anti-alias-free edges).",run(d){p(L,d).togglePixelPreview()}})),r.track(e.register({id:"svge.builtin.view.display.pixel-preview-raster",parentId:"svge.builtin.view.display-menu",slot:y.VIEW,label:"Pixel Preview (Rasterized)",icon:"apps",order:35,tooltip:"Pixel-accurate preview: rasterizes the page to real device pixels (slower; web fonts / embedded HTML may not appear).",run(d){p(L,d).togglePixelPreviewRaster()}})),r.track(e.register({id:"svge.builtin.view.display.full-screen",parentId:"svge.builtin.view.display-menu",slot:y.VIEW,label:"Full Screen",icon:"fullscreen",order:40,tooltip:"Fill the entire screen (browser fullscreen). Press Esc to exit.",disabled:d=>m(()=>!d.get(Tt).isSupported()),run(d){p(Tt,d).toggle()}})),r.track(e.register({id:"svge.builtin.view.show-menu",slot:y.VIEW,label:"Show",icon:"visibility",order:40,run(){}})),r.track(e.register({id:"svge.builtin.view.toggle-grid",parentId:"svge.builtin.view.show-menu",slot:y.VIEW,label:"Grid",icon:"grid_on",order:10,run(d){p(L,d).toggleGrid()}})),r.track(e.register({id:"svge.builtin.view.toggle-rulers",parentId:"svge.builtin.view.show-menu",slot:y.VIEW,label:"Rulers",icon:"straighten",order:20,run(d){p(L,d).toggleRulers()}})),r.track(e.register({id:"svge.builtin.view.toggle-timeline",parentId:"svge.builtin.view.show-menu",slot:y.VIEW,label:"Timeline",icon:"timeline",order:30,run(d){p(L,d).toggleTimeline()}})),r.track(e.register({id:"svge.builtin.view.divider2",slot:y.VIEW,label:"",order:75,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.view.snap",slot:y.VIEW,label:"Snap",icon:"grid_3x3",order:80,run(){}})),r.track(e.register({id:"svge.builtin.view.snap.enabled",parentId:"svge.builtin.view.snap",slot:y.VIEW,label:"Enabled",icon:"power_settings_new",order:10,run(d){const w=p(ue,d);w.setEnabled(!w.enabled())}})),r.track(e.register({id:"svge.builtin.view.snap.divider1",parentId:"svge.builtin.view.snap",slot:y.VIEW,label:"",order:20,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.view.snap.mode-grid",parentId:"svge.builtin.view.snap",slot:y.VIEW,label:"Grid only",icon:"grid_4x4",order:30,run(d){const w=p(ue,d);w.setMode("grid"),w.enabled()||w.setEnabled(!0)}})),r.track(e.register({id:"svge.builtin.view.snap.mode-objects",parentId:"svge.builtin.view.snap",slot:y.VIEW,label:"Objects only",icon:"category",order:40,run(d){const w=p(ue,d);w.setMode("objects"),w.enabled()||w.setEnabled(!0)}})),r.track(e.register({id:"svge.builtin.view.snap.mode-both",parentId:"svge.builtin.view.snap",slot:y.VIEW,label:"Both",icon:"apps",order:50,run(d){const w=p(ue,d);w.setMode("both"),w.enabled()||w.setEnabled(!0)}})),r.track(e.register({id:"svge.builtin.view.snap.divider2",parentId:"svge.builtin.view.snap",slot:y.VIEW,label:"",order:55,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.view.snap.guides",parentId:"svge.builtin.view.snap",slot:y.VIEW,label:"Snap to Guides",icon:"straighten",tooltip:"Also snap to your guide lines. Independent toggle layered on top of the active Grid / Objects / Both mode \u2014 it adds guides, it does not replace the mode.",order:60,run(d){const w=p(ue,d);w.toggleSnapToGuides(),w.snapToGuides()&&!w.enabled()&&w.setEnabled(!0)}}));const Z=d=>{const w=d.get(L);return m(()=>w.guides().length===0)},V=(d,w)=>{const I=p(L,w),_=p(A,w).viewBox(),R=d==="h"?_.y+_.height/2:_.x+_.width/2;I.addGuide(d,R)};r.track(e.register({id:"svge.builtin.view.guides",slot:y.VIEW,label:"Guides",icon:"straighten",order:85,run(){}})),r.track(e.register({id:"svge.builtin.view.guides.add-h",parentId:"svge.builtin.view.guides",slot:y.VIEW,label:"Add Horizontal Guide",icon:"horizontal_rule",order:10,run(d){V("h",d)}})),r.track(e.register({id:"svge.builtin.view.guides.add-v",parentId:"svge.builtin.view.guides",slot:y.VIEW,label:"Add Vertical Guide",icon:"vertical_align_center",order:20,run(d){V("v",d)}}));const qe=d=>{const w=d.get(L);return m(()=>w.guidesLocked())},Pn=d=>{const w=d.get(L);return m(()=>!w.guidesLocked())};r.track(e.register({id:"svge.builtin.view.guides.lock",parentId:"svge.builtin.view.guides",slot:y.VIEW,label:"Lock Guides",icon:"lock",order:25,disabled:qe,run(d){p(L,d).setGuidesLocked(!0)}})),r.track(e.register({id:"svge.builtin.view.guides.unlock",parentId:"svge.builtin.view.guides",slot:y.VIEW,label:"Unlock Guides",icon:"lock_open",order:26,disabled:Pn,run(d){p(L,d).setGuidesLocked(!1)}})),r.track(e.register({id:"svge.builtin.view.guides.divider1",parentId:"svge.builtin.view.guides",slot:y.VIEW,label:"",order:30,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.view.guides.clear",parentId:"svge.builtin.view.guides",slot:y.VIEW,label:"Clear All Guides",icon:"clear_all",order:40,disabled:Z,run(d){p(L,d).clearGuides()}})),r.track(e.register({id:"svge.builtin.edit.group",slot:y.OBJECT,label:"Group",icon:"group_work",shortcut:"Ctrl+G",order:5,disabled:i,run(d){Vo(d,p)}})),r.track(e.register({id:"svge.builtin.edit.ungroup",slot:y.OBJECT,label:"Ungroup",icon:"call_split",shortcut:"Ctrl+Shift+G",order:7,disabled:a,run(d){zo(d,p)}})),r.track(e.register({id:"svge.builtin.object.divider-arrange",slot:y.OBJECT,label:"",order:8,divider:!0,run(){}}));const Te=(d,w)=>{const I=p(k,w),P=Array.from(I.selectedIds());if(P.length===0)return;const _=p(M,w);for(const R of P)_.dispatch(new gu(R,d))};r.track(e.register({id:"svge.builtin.object.arrange",slot:y.OBJECT,label:"Arrange",icon:"layers",order:20,disabled:o,run(){}})),r.track(e.register({id:"svge.builtin.object.bring-to-front",parentId:"svge.builtin.object.arrange",slot:y.OBJECT,label:"Bring to Front",icon:"flip_to_front",shortcut:"Ctrl+Shift+]",order:10,disabled:o,run(d){Te("toFront",d)}})),r.track(e.register({id:"svge.builtin.object.bring-forward",parentId:"svge.builtin.object.arrange",slot:y.OBJECT,label:"Bring Forward",icon:"arrow_upward",shortcut:"Ctrl+]",order:20,disabled:o,run(d){Te("forward",d)}})),r.track(e.register({id:"svge.builtin.object.send-backward",parentId:"svge.builtin.object.arrange",slot:y.OBJECT,label:"Send Backward",icon:"arrow_downward",shortcut:"Ctrl+[",order:30,disabled:o,run(d){Te("backward",d)}})),r.track(e.register({id:"svge.builtin.object.send-to-back",parentId:"svge.builtin.object.arrange",slot:y.OBJECT,label:"Send to Back",icon:"flip_to_back",shortcut:"Ctrl+Shift+[",order:40,disabled:o,run(d){Te("toBack",d)}})),r.track(e.register({id:"svge.builtin.object.flip",slot:y.OBJECT,label:"Transform",icon:"transform",order:30,disabled:o,run(){}}));const ht=(d,w)=>{const I=document.querySelector("svge-renderer svg");if(I===null)return;const P=p(k,d),_=p(ne,d),R=p(M,d);for(const $ of P.selectedIds()){if(_.isLocked($))continue;const F=ke(I,$);if(F===null)continue;const _n={x:F.x+F.width/2,y:F.y+F.height/2};R.dispatch(new pu($,w,_n))}};r.track(e.register({id:"svge.builtin.object.flip.horizontal",parentId:"svge.builtin.object.flip",slot:y.OBJECT,label:"Flip Horizontal",icon:"flip",tooltip:"Mirror left \u2194 right around each shape\u2019s centre",order:10,disabled:o,run(d){ht(d,"horizontal")}})),r.track(e.register({id:"svge.builtin.object.flip.vertical",parentId:"svge.builtin.object.flip",slot:y.OBJECT,label:"Flip Vertical",icon:"flip",tooltip:"Mirror top \u2195 bottom around each shape\u2019s centre",order:20,disabled:o,run(d){ht(d,"vertical")}})),r.track(e.register({id:"svge.builtin.object.rasterize",slot:y.OBJECT,label:"Rasterize",icon:"image",order:35,disabled:o,run(){}}));const Ft=[{label:"1\xD7",scale:1,order:10},{label:"2\xD7 (recommended)",scale:2,order:20},{label:"3\xD7",scale:3,order:30}];for(const d of Ft)r.track(e.register({id:`svge.builtin.object.rasterize.${d.scale}x`,parentId:"svge.builtin.object.rasterize",slot:y.OBJECT,label:d.label,icon:"image",order:d.order,disabled:o,run(w){xp(w,p,d.scale)}}));const zr=d=>{const w=p(k,d),I=p(ne,d),P=p(S,d),_=p(M,d);for(const R of w.selectedIds()){if(I.isLocked(R))continue;const $=T(P.document().root,R);if($===null)continue;const F=$.transform;if(F[0]===1&&F[1]===0&&F[2]===0&&F[3]===1)continue;const _n=[1,0,0,1,F[4],F[5]];_.dispatch(new yr(R,"transform",_n))}};r.track(e.register({id:"svge.builtin.object.transform.reset",parentId:"svge.builtin.object.flip",slot:y.OBJECT,label:"Reset Transform",icon:"restart_alt",tooltip:"Clear rotation, scale and skew (keep position)",order:60,disabled:o,run(d){zr(d)}}));const gr=d=>{const w=document.querySelector("svge-renderer svg");if(w===null)return[];const I=p(k,d),P=[];for(const _ of I.selectedIds()){const R=ke(w,_);R!==null&&P.push({id:_,bbox:R})}return P};r.track(e.register({id:"svge.builtin.object.align",slot:y.OBJECT,label:"Align",icon:"align_horizontal_center",order:50,disabled:c,run(){}}));const jt=(d,w,I,P,_)=>{r.track(e.register({id:d,parentId:"svge.builtin.object.align",slot:y.OBJECT,label:w,icon:I,order:P,disabled:c,run(R){const $=gr(R);if($.length===0)return;const F=p(j,R).activePageViewBox()??p(S,R).document().viewBox,_n=p(be,R).keyObjectId(),si=ns($,_n,F),ai=p(rt,R);si!==null?ai.alignToReference($,_,si):ai.align($,_)}}))};jt("svge.builtin.object.align.left","Align Left","align_horizontal_left",10,"left"),jt("svge.builtin.object.align.center-h","Center Horizontal","align_horizontal_center",20,"center-x"),jt("svge.builtin.object.align.right","Align Right","align_horizontal_right",30,"right"),r.track(e.register({id:"svge.builtin.object.align.divider1",parentId:"svge.builtin.object.align",slot:y.OBJECT,label:"",order:40,divider:!0,run(){}})),jt("svge.builtin.object.align.top","Align Top","align_vertical_top",50,"top"),jt("svge.builtin.object.align.center-v","Center Vertical","align_vertical_center",60,"center-y"),jt("svge.builtin.object.align.bottom","Align Bottom","align_vertical_bottom",70,"bottom"),r.track(e.register({id:"svge.builtin.object.align.divider-key",parentId:"svge.builtin.object.align",slot:y.OBJECT,label:"",order:80,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.object.align.make-key",parentId:"svge.builtin.object.align",slot:y.OBJECT,label:"Make Key Object",icon:"center_focus_strong",tooltip:"Align the rest of the selection to the focused object (it stays put)",order:90,disabled:u,run(d){const w=p(k,d),I=w.focusId();I===null||!w.selectedIds().has(I)||p(be,d).setKeyObject(I)}})),r.track(e.register({id:"svge.builtin.object.align.clear-key",parentId:"svge.builtin.object.align",slot:y.OBJECT,label:"Clear Key Object",icon:"center_focus_weak",tooltip:"Stop aligning to the key object (back to selection / page)",order:100,disabled:h,run(d){p(be,d).clear()}})),r.track(e.register({id:"svge.builtin.object.distribute",slot:y.OBJECT,label:"Distribute",icon:"horizontal_distribute",order:60,disabled:g,run(){}}));const ri=(d,w,I,P,_)=>{r.track(e.register({id:d,parentId:"svge.builtin.object.distribute",slot:y.OBJECT,label:w,icon:I,order:P,disabled:g,run(R){const $=gr(R);$.length<3||p(rt,R).distribute($,_)}}))};ri("svge.builtin.object.distribute.h","Horizontally","horizontal_distribute",10,"horizontal"),ri("svge.builtin.object.distribute.v","Vertically","vertical_distribute",20,"vertical"),r.track(e.register({id:"svge.builtin.object.pathfinder",slot:y.OBJECT,label:"Boolean (Pathfinder)",icon:"join_inner",order:70,disabled:v,run(){}}));const Mn=(d,w)=>{const I=p(k,d),P=Array.from(I.selectedIds());if(P.length<2)return;const _=p(S,d),R=p(M,d);for(const $ of P){const F=T(_.document().root,$);F!==null&&(F.type==="rect"||F.type==="ellipse"||F.type==="line"||F.type==="polygon"||F.type==="polyline")&&R.dispatch(new fu($))}R.dispatch(new w(P)),I.select(P[0])};r.track(e.register({id:"svge.builtin.object.pathfinder.union",parentId:"svge.builtin.object.pathfinder",slot:y.OBJECT,label:"Union",icon:"join_inner",tooltip:"Merge overlapping shapes into one (A \u222A B)",order:10,disabled:v,run(d){Mn(d,mu)}})),r.track(e.register({id:"svge.builtin.object.pathfinder.intersect",parentId:"svge.builtin.object.pathfinder",slot:y.OBJECT,label:"Intersect",icon:"join_full",tooltip:"Keep only the overlapping area (A \u2229 B)",order:20,disabled:v,run(d){Mn(d,vu)}})),r.track(e.register({id:"svge.builtin.object.pathfinder.subtract",parentId:"svge.builtin.object.pathfinder",slot:y.OBJECT,label:"Subtract",icon:"join_left",tooltip:"Remove the others from the first shape (A \\ B)",order:30,disabled:v,run(d){Mn(d,yu)}})),r.track(e.register({id:"svge.builtin.object.pathfinder.divide",parentId:"svge.builtin.object.pathfinder",slot:y.OBJECT,label:"Divide",icon:"call_split",tooltip:"Split into non-overlapping regions",order:40,disabled:v,run(d){Mn(d,bu)}})),r.track(e.register({id:"svge.builtin.object.pathfinder.exclude",parentId:"svge.builtin.object.pathfinder",slot:y.OBJECT,label:"Exclude",icon:"join_right",tooltip:"Keep non-overlapping areas (symmetric difference)",order:50,disabled:v,run(d){Mn(d,wu)}}));const Ed=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=w.focusId();if(P===null)return!0;const _=I.document().root,R=T(_,P);if(R===null||R.type!=="group"||zt(R)||$e(R))return!0;const $=ft(_,P);return $===null||$.id!==_.id&&!$e($)})},Td=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=w.focusId();if(P===null)return!0;const _=T(I.document().root,P);return _===null||!zt(_)})};r.track(e.register({id:"svge.builtin.object.new-layer",slot:y.INSERT,label:"Layer",icon:"layers",order:50,run(d){const w=p(M,d),I=p(k,d),P=new Iu;w.dispatch(P);const _=P.getCreatedLayerId();_!==null&&I.select(_)}}));const Rd=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=w.focusId();if(P===null)return!0;const _=T(I.document().root,P);return _===null||_.style.clipPath===void 0})},Ad=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=w.focusId();if(P===null)return!0;const _=T(I.document().root,P);return _===null||_.style.mask===void 0})},Cd=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=Array.from(w.selectedIds());if(P.length<2)return!0;const _=ta(I.document().root,P);return _===null||_.type==="image"})},oi=(d,w)=>{const I=d?.injector??r.injector,P=I.get(k).focusId();P!==null&&qg(I,P,w)};r.track(e.register({id:"svge.builtin.object.mask",slot:y.OBJECT,label:"Mask",icon:"masks",order:75,disabled:o,run(){}})),r.track(e.register({id:"svge.builtin.object.mask.make-clip",parentId:"svge.builtin.object.mask",slot:y.OBJECT,label:"Make Clipping Path",icon:"crop",shortcut:"Ctrl+7",order:10,tooltip:"O objeto de cima recorta os de baixo. Requer 2+ objetos, e o de cima n\xE3o pode ser uma imagem \u2014 para mascarar com imagem use Make Opacity Mask, ou vetorize antes com Trace Image.",disabled:Cd,run(d){na(d?.injector??r.injector,"clipPath")}})),r.track(e.register({id:"svge.builtin.object.mask.release-clip",parentId:"svge.builtin.object.mask",slot:y.OBJECT,label:"Release Clipping Path",icon:"crop_free",order:20,disabled:Rd,run(d){oi(d,"clipPath")}})),r.track(e.register({id:"svge.builtin.object.mask.divider",parentId:"svge.builtin.object.mask",slot:y.OBJECT,label:"",order:25,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.object.mask.make-opacity",parentId:"svge.builtin.object.mask",slot:y.OBJECT,label:"Make Opacity Mask",icon:"opacity",order:30,disabled:i,run(d){na(d?.injector??r.injector,"mask")}})),r.track(e.register({id:"svge.builtin.object.mask.release-mask",parentId:"svge.builtin.object.mask",slot:y.OBJECT,label:"Release Mask",icon:"layers_clear",order:40,disabled:Ad,run(d){oi(d,"mask")}})),r.track(e.register({id:"svge.builtin.object.convert",slot:y.OBJECT,label:"Convert",icon:"transform",order:80,run(){}})),r.track(e.register({id:"svge.builtin.object.convert-to-layer",parentId:"svge.builtin.object.convert",slot:y.OBJECT,label:"Convert to Layer",icon:"folder_special",order:20,disabled:Ed,run(d){const I=p(k,d).focusId();I!==null&&p(M,d).dispatch(new ku(I))}})),r.track(e.register({id:"svge.builtin.object.convert-to-group",parentId:"svge.builtin.object.convert",slot:y.OBJECT,label:"Convert Layer to Group",icon:"folder",order:30,disabled:Td,run(d){const w=p(k,d),I=w.focusId();if(I===null)return;const P=new xu(I);p(M,d).dispatch(P);const _=P.getResultNodeId();_!==null&&w.select(_)}}));const Od=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=w.selectedIds();if(P.size===0)return!0;const _=I.document().root;let R=null;for(const $ of P){const F=ft(_,$);if(F===null)return!0;if(R===null)R=F.id;else if(F.id!==R)return!0}return!1})},ii=d=>{const w=d.get(k),I=d.get(S);return m(()=>{const P=w.focusId();if(P===null)return!0;const _=T(I.document().root,P);return _===null||!Du(_)})};r.track(e.register({id:"svge.builtin.object.smart-object",slot:y.OBJECT,label:"Smart Object",icon:"inventory_2",order:85,run(){}})),r.track(e.register({id:"svge.builtin.object.smart-object.convert",parentId:"svge.builtin.object.smart-object",slot:y.OBJECT,label:"Convert to Smart Object",icon:"inventory_2",order:10,disabled:Od,run(d){const w=p(k,d),I=Array.from(w.selectedIds());if(I.length===0)return;const P=p(M,d),_=new Su(I);P.dispatch(_);const R=_.getCreatedWrapperId();R!==null&&w.select(R)}})),r.track(e.register({id:"svge.builtin.object.smart-object.divider1",parentId:"svge.builtin.object.smart-object",slot:y.OBJECT,label:"",order:20,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.object.smart-object.replace",parentId:"svge.builtin.object.smart-object",slot:y.OBJECT,label:"Replace Contents\u2026",icon:"sync_alt",order:30,disabled:ii,run(d){const I=p(k,d).focusId();I!==null&&p(dt,d).replaceContents(I)}})),r.track(e.register({id:"svge.builtin.object.smart-object.release",parentId:"svge.builtin.object.smart-object",slot:y.OBJECT,label:"Release Smart Object",icon:"view_module",order:40,disabled:ii,run(d){const I=p(k,d).focusId();I!==null&&p(dt,d).release(I)}})),r.track(e.register({id:"svge.builtin.toolbar.undo",slot:me.MAIN,label:"Undo",icon:"undo",tooltip:"Undo (Ctrl+Z)",order:10,disabled:t,run(d){p(M,d).undo()}})),r.track(e.register({id:"svge.builtin.toolbar.redo",slot:me.MAIN,label:"Redo",icon:"redo",tooltip:"Redo (Ctrl+Shift+Z)",order:20,disabled:n,run(d){p(M,d).redo()}})),r.track(e.register({id:"svge.builtin.toolbar.delete",slot:me.MAIN,label:"Delete",icon:"delete",tooltip:"Delete selection (Delete)",order:30,disabled:o,run(d){$r(d,p)}})),r.track(e.register({id:"svge.builtin.toolbar.copy",slot:me.MAIN,label:"Copy",icon:"content_copy",tooltip:"Copy selection (Ctrl+C)",order:31,disabled:o,run(d){Br(d,p)}})),r.track(e.register({id:"svge.builtin.toolbar.paste",slot:me.MAIN,label:"Paste",icon:"content_paste",tooltip:"Paste from clipboard (Ctrl+V)",order:32,disabled:l,run(d){Go(d,p,ua)}})),r.track(e.register({id:"svge.builtin.toolbar.duplicate",slot:me.MAIN,label:"Duplicate",icon:"control_point_duplicate",tooltip:"Duplicate selection (Ctrl+D)",order:33,disabled:o,run(d){Ho(d,p)}})),r.track(e.register({id:"svge.builtin.toolbar.group",slot:me.MAIN,label:"Group",icon:"group_work",tooltip:"Group selection (Ctrl+G)",order:40,disabled:i,run(d){Vo(d,p)}})),r.track(e.register({id:"svge.builtin.toolbar.ungroup",slot:me.MAIN,label:"Ungroup",icon:"call_split",tooltip:"Ungroup focus (Ctrl+Shift+G)",order:50,disabled:a,run(d){zo(d,p)}})),r.track(e.register({id:"svge.builtin.toolbar.zoom-out",slot:me.MAIN,label:"Zoom Out",icon:"zoom_out",tooltip:"Zoom out",order:60,run(d){p(A,d).zoomOut()}})),r.track(e.register({id:"svge.builtin.toolbar.zoom-in",slot:me.MAIN,label:"Zoom In",icon:"zoom_in",tooltip:"Zoom in",order:70,run(d){p(A,d).zoomIn()}})),r.track(e.register({id:"svge.builtin.toolbar.zoom-reset",slot:me.MAIN,label:"Reset View",icon:"fit_screen",tooltip:"Reset zoom + pan to fit",order:80,run(d){p(A,d).reset()}})),r.track(e.register({id:"svge.builtin.context.canvas.select-all",slot:Q.CANVAS,label:"Select All",icon:"select_all",shortcut:"Ctrl+A",order:10,run(d){ca(d,p)}})),r.track(e.register({id:"svge.builtin.context.canvas.divider1",slot:Q.CANVAS,label:"",order:20,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.context.canvas.zoom-in",slot:Q.CANVAS,label:"Zoom In",icon:"zoom_in",order:30,run(d){p(A,d).zoomIn()}})),r.track(e.register({id:"svge.builtin.context.canvas.zoom-out",slot:Q.CANVAS,label:"Zoom Out",icon:"zoom_out",order:40,run(d){p(A,d).zoomOut()}})),r.track(e.register({id:"svge.builtin.context.canvas.zoom-reset",slot:Q.CANVAS,label:"Reset Zoom",icon:"fit_screen",order:50,run(d){p(A,d).reset()}})),r.track(e.register({id:"svge.builtin.context.node.cut",slot:Q.NODE,label:"Cut",icon:"content_cut",shortcut:"Ctrl+X",order:5,disabled:o,run(d){da(d,p)}})),r.track(e.register({id:"svge.builtin.context.node.copy",slot:Q.NODE,label:"Copy",icon:"content_copy",shortcut:"Ctrl+C",order:6,disabled:o,run(d){Br(d,p)}})),r.track(e.register({id:"svge.builtin.context.node.duplicate",slot:Q.NODE,label:"Duplicate",icon:"control_point_duplicate",shortcut:"Ctrl+D",order:7,disabled:o,run(d){Ho(d,p)}})),r.track(e.register({id:"svge.builtin.context.node.divider0",slot:Q.NODE,label:"",order:9,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.context.node.delete",slot:Q.NODE,label:"Delete",icon:"delete",shortcut:"Delete",order:10,disabled:o,run(d){$r(d,p)}})),r.track(e.register({id:"svge.builtin.context.node.divider1",slot:Q.NODE,label:"",order:20,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.context.node.group",slot:Q.NODE,label:"Group",icon:"group_work",shortcut:"Ctrl+G",order:30,disabled:i,run(d){Vo(d,p)}})),r.track(e.register({id:"svge.builtin.context.node.ungroup",slot:Q.NODE,label:"Ungroup",icon:"call_split",shortcut:"Ctrl+Shift+G",order:40,disabled:a,run(d){zo(d,p)}})),r.track(e.register({id:"svge.builtin.context.node.divider2",slot:Q.NODE,label:"",order:50,divider:!0,run(){}})),r.track(e.register({id:"svge.builtin.context.node.bring-forward",slot:Q.NODE,label:"Bring Forward",icon:"arrow_upward",shortcut:"Ctrl+]",order:60,disabled:o,run(d){Te("forward",d)}})),r.track(e.register({id:"svge.builtin.context.node.send-backward",slot:Q.NODE,label:"Send Backward",icon:"arrow_downward",shortcut:"Ctrl+[",order:70,disabled:o,run(d){Te("backward",d)}}));const Nd=d=>{typeof window>"u"||window.open(d,"_blank","noopener,noreferrer")},Ld=d=>{if(typeof window>"u")return d;try{const w=new URL(d,window.location.href);if((w.protocol==="http:"||w.protocol==="https:")&&!w.searchParams.has("body")){const I=typeof navigator<"u"?navigator.userAgent:"unknown";return w.searchParams.set("body",`
1215
+
1216
+ ---
1217
+ Page: ${window.location.href}
1218
+ User-Agent: ${I}`),w.toString()}}catch{}return d},$d=[{id:"svge.builtin.help.documentation",label:"Documentation",icon:"menu_book",order:20,key:"documentation"},{id:"svge.builtin.help.tutorials",label:"Tutorials",icon:"school",order:30,key:"tutorials"},{id:"svge.builtin.help.plugin-development",label:"Plugin Development",icon:"code",order:50,key:"pluginDevelopment"},{id:"svge.builtin.help.report-issue",label:"Report Issue",icon:"bug_report",order:60,key:"reportIssue",report:!0}];for(const d of $d)r.track(e.register({id:d.id,slot:y.HELP,label:d.label,icon:d.icon,order:d.order,run(w){const I=p(ko,w),P=d.report?Ld(I[d.key]):I[d.key];Nd(P)}}));const Bd=[{id:"svge.window.panels.layers",label:"Layers",icon:"layers",order:10,panelId:It.LAYERS},{id:"svge.window.panels.history",label:"History",icon:"history",order:20,panelId:It.HISTORY},{id:"svge.window.panels.properties",label:"Properties",icon:"tune",order:30,panelId:It.PROPERTIES},{id:"svge.window.panels.appearance",label:"Appearance",icon:"auto_awesome",order:40,panelId:It.APPEARANCE},{id:"svge.window.panels.export",label:"Export",icon:"download",order:50,panelId:It.EXPORT},{id:"svge.window.panels.gradient",label:"Gradient",icon:"gradient",order:60,panelId:It.GRADIENT}];for(const d of Bd)r.track(e.register({id:d.id,parentId:"svge.window.panels",slot:y.WINDOW,label:d.label,icon:d.icon,order:d.order,run(w){p(Lt,w).reveal(d.panelId)}}))}};function $r(r,e){const t=e(k,r),n=Array.from(t.selectedIds());if(n.length===0)return;const o=e(M,r);for(const i of n)o.dispatch(new vr(i))}function ca(r,e){const t=e(j,r).treeForRendering();t.type!=="group"||t.children.length===0||e(k,r).selectMany(t.children.map(n=>n.id))}function up(r,e){const t=e(j,r).treeForRendering();if(t.type!=="group"||t.children.length===0)return;const n=e(k,r).selectedIds(),o=t.children.filter(i=>!n.has(i.id)).map(i=>i.id);e(k,r).selectMany(o)}function Vo(r,e){const t=e(k,r),n=Array.from(t.selectedIds());n.length<2||e(M,r).dispatch(new xi(n))}function zo(r,e){const n=e(k,r).focusId();if(n===null)return;const o=e(S,r),i=T(o.document().root,n);i===null||i.type!=="group"||e(M,r).dispatch(new Di(n))}function hp(r,e){const t=e(k,r),n=e(S,r),o=t.selectedIds();if(o.size===0)return[];const i=[];for(const a of o){const l=T(n.document().root,a);l!==null&&i.push(l)}return i}function Br(r,e){const t=hp(r,e);t.length!==0&&(e(_e,r).copy(t),zg(e(Vt,r),t))}function da(r,e){Br(r,e),$r(r,e)}const ua={x:10,y:10};async function Go(r,e,t){if(await Gg(e(Vt,r)))return;const o=e(_e,r).paste();if(o.length===0)return;const i=e(M,r),a=t.x===0&&t.y===0;for(const c of o){const u=a?c:{...c,transform:ee(mr(t.x,t.y),c.transform)};i.dispatch(new he(te,u))}e(k,r).selectMany(o.map(c=>c.id))}function Ho(r,e){const t=e(k,r),n=Array.from(t.selectedIds());if(n.length===0)return;const o=e(M,r),i=new Pu(n);o.dispatch(i);const a=i.getInsertedIds();a.length>0&&t.selectMany(a)}function gp(r,e){const t=e(k,r).selectedIds();if(t.size===0)return;const n=e(S,r).document().root,o=Mu(n,t);o!==null&&e(A,r).fitBox(o)}function pp(r,e){const t=e(j,r),n=e(S,r),o=t.activePage(),i=o!==null?o:n.document().root,a=br(i),l=e(A,r);if(a.width>0&&a.height>0)l.fitBox(a);else{const c=t.activePageViewBox()??n.document().viewBox;l.fitBox(c,0)}}function fp(r,e){if(typeof window<"u"){const n=e(S,r).document().root;if(n.type==="group"&&n.children.length>0&&!window.confirm("Discard the current document and start fresh?"))return}e(S,r).resetDocument(),e(M,r).dispatch(new eo),e(Wt,r).clear();{const t=e(A,r);t.setContentBox(e(S,r).document().viewBox),t.frameNewDocument()}e(k,r).clear()}function mp(r,e){if(typeof document>"u")return;const t=document.createElement("input");t.type="file",t.accept=".svg,.svgz,.svge,.svgez,image/svg+xml",t.style.display="none",t.addEventListener("change",()=>{const n=t.files?.[0];if(t.remove(),n==null)return;const o=n.name.lastIndexOf("."),i=o>=0?n.name.slice(o+1).toLowerCase():"",a=l=>{typeof window<"u"&&window.alert(`Could not read "${n.name}": ${l instanceof Error?l.message:String(l)}`)};if(i==="svge"||i==="svgez"){Mp(n).then(l=>Pp(r,e,l)).catch(a);return}if(i!=="svg"&&i!=="svgz"){typeof window<"u"&&window.alert(`Opening ".${i}" files is not supported yet.`);return}ha(n).then(l=>ga(r,e,l,n.name)).catch(a)},{once:!0}),document.body.appendChild(t),t.click()}function ha(r){const e=r.name.lastIndexOf(".");return(e>=0?r.name.slice(e+1).toLowerCase():"")==="svgz"?r.arrayBuffer().then(n=>Ei(n)):r.text()}function ga(r,e,t,n){const o=ze.import(t);if(!o.ok){typeof window<"u"&&window.alert(`Open failed: ${o.error}`);return}if(typeof window<"u"){const i=e(S,r).document().root;if(i.type==="group"&&i.children.length>0&&!window.confirm("Discard the current document and open this file?"))return}vp(r,e,o.document),n!==void 0&&e(lt,r).record(n,t),o.warnings.length>0&&typeof console<"u"&&console.warn(`[SVGEngine] Open warnings:
1219
+ ${o.warnings.join(`
1220
+ `)}`)}function vp(r,e,t){e(S,r).resetDocument(t),e(M,r).dispatch(new eo),e(Wt,r).clear(),e(A,r).fit(),e(k,r).clear()}function pa(r,e,t=fa){if(typeof document>"u")return;const n=document.createElement("input");n.type="file",n.accept=".svg,.svgz,image/svg+xml",n.style.display="none",n.addEventListener("change",()=>{const o=n.files?.[0];n.remove(),o!=null&&ha(o).then(i=>t(r,e,i)).catch(i=>{typeof window<"u"&&window.alert(`Could not read "${o.name}": ${i instanceof Error?i.message:String(i)}`)})},{once:!0}),document.body.appendChild(n),n.click()}function fa(r,e,t){const n=ze.import(t);if(!n.ok){typeof window<"u"&&window.alert(`Import failed: ${n.error}`);return}bp(r,e,n.document),n.warnings.length>0&&typeof console<"u"&&console.warn(`[SVGEngine] Import warnings:
1221
+ ${n.warnings.join(`
1222
+ `)}`)}function yp(r,e,t){const n=ze.import(t);if(!n.ok){typeof window<"u"&&window.alert(`Import failed: ${n.error}`);return}va(r,e,n.document,!0),n.warnings.length>0&&typeof console<"u"&&console.warn(`[SVGEngine] Import (Smart Object) warnings:
1223
+ ${n.warnings.join(`
1224
+ `)}`)}function bp(r,e,t){e(un,r).placementMode()==="place"?kp(r,e,t):va(r,e,t)}function wp(r,e){if(typeof window>"u")return;const t=window.prompt("Paste an image URL (SVG or raster):");if(t===null)return;const n=t.trim();if(n.length===0)return;let o;try{o=new URL(n)}catch{window.alert("That does not look like a valid URL.");return}if(o.protocol!=="http:"&&o.protocol!=="https:"){window.alert("Only http(s) image URLs are supported.");return}if(typeof fetch>"u"){window.alert("Importing from a URL is not available in this environment.");return}fetch(n).then(i=>{if(!i.ok)throw new Error(`HTTP ${i.status}`);const a=(i.headers.get("content-type")??"").toLowerCase(),l=ma(a,o.pathname);return l==="raster"?i.blob().then(c=>ya(c)).then(c=>Lr(r?.injector,c)):i.text().then(c=>{l==="svg"||/^\s*(?:<\?xml[^>]*>\s*)?(?:<!--[\s\S]*?-->\s*)*<svg[\s>]/i.test(c)?fa(r,e,c):Lr(r?.injector,n)})}).catch(()=>{ma("",o.pathname)==="svg"?window.alert("Could not fetch that SVG \u2014 the server may block cross-origin requests. Download the file and use File \u25B8 Import \u25B8 SVG\u2026 instead."):Lr(r?.injector,n)})}function ma(r,e){if(r.includes("svg"))return"svg";if(r.startsWith("image/"))return"raster";const t=e.slice(e.lastIndexOf(".")+1).toLowerCase();return t==="svg"?"svg":["png","jpg","jpeg","gif","webp","bmp","avif","ico"].includes(t)?"raster":"unknown"}function Ip(r,e){const t=e(j,r).activePageViewBox();if(t!==null)return{cx:t.x+t.width/2,cy:t.y+t.height/2};const n=e(A,r).viewBox();return{cx:n.x+n.width/2,cy:n.y+n.height/2}}function va(r,e,t,n=!1){const o=t.root;if(o.type!=="group"||o.children.length===0)return;const i=$o(o,t.viewBox),a=i.x+i.width/2,l=i.y+i.height/2,{cx:c,cy:u}=Ip(r,e),h={...o,transform:[1,0,0,1,c-a,u-l]},g=n?_u(h):h,v=e(S,r),p=t.defs;if(p!==void 0&&p.length>0){const x=v.document();v.setDocument({...x,defs:`${x.defs??""}
1225
+ ${p}`})}e(M,r).dispatch(new he(te,g)),e(k,r).select(g.id)}function kp(r,e,t){const n=t.root;n.type!=="group"||n.children.length===0||e(Ee,r).begin({group:n,src:$o(n,t.viewBox),defs:t.defs})}async function xp(r,e,t){if(typeof document>"u"||typeof URL>"u")return;const n=document.querySelector("svge-renderer svg");if(n===null)return;const o=e(k,r),i=e(ne,r),a=e(S,r),l=e(Le,r),c=e(M,r),u=a.document(),h=[];for(const v of o.selectedIds()){if(i.isLocked(v))continue;const p=T(u.root,v);if(p===null)continue;const x=yh(n,v);x!==null&&h.push({id:v,node:p,box:x})}if(h.length===0)return;const g=l.buildExportDefs(u.defs);for(const v of h){const p={id:Ht(),viewBox:v.box,root:mt([v.node]),defs:g};let x;try{const C=await to(p,t);x=await ya(C)}catch(C){typeof console<"u"&&console.warn("[SVGEngine] Rasterize failed:",C);continue}const E=wr({x:v.box.x,y:v.box.y,width:v.box.width,height:v.box.height,href:x},{metadata:v.node.metadata});c.dispatch(new Eu(v.id,E))}}function ya(r){return new Promise((e,t)=>{const n=new FileReader;n.onload=()=>e(n.result),n.onerror=()=>t(n.error??new Error("FileReader failed")),n.readAsDataURL(r)})}async function Fr(r,e,t,n=!1){if(typeof document>"u"||typeof URL>"u")return;const i=e(S,r).document(),a=e(Le,r),l=e(j,r),c={...i,defs:a.buildExportDefs(i.defs)};let u=l.effectiveExportDoc(c);if(n&&t==="svg"){const E=e(at,r).doc();E.tracks.length>0&&(u={...u,root:{...u.root,metadata:{...u.root.metadata,customData:{...u.root.metadata.customData,[Tu]:E}}},exportPreferences:{...u.exportPreferences,emitSmilAnimation:!0}})}const h=t==="png"?Ti:t==="svgz"?Qu:vt;let g;try{const E=h.export(u);g=typeof E=="string"?E:await E}catch(E){typeof window<"u"&&window.alert(`Export failed: ${E instanceof Error?E.message:String(E)}`);return}const v=g instanceof Blob?g:new Blob([g],{type:h.mediaType}),p=URL.createObjectURL(v),x=document.createElement("a");x.href=p,x.download=`untitled${n?"-animated":""}.${h.extension}`,document.body.appendChild(x),x.click(),x.remove(),setTimeout(()=>URL.revokeObjectURL(p),1e3)}function Dp(r,e){const t=e(We,r).pages(),n=e(j,r).activePageId(),o=n===null?-1:t.findIndex(l=>l.id===n),i=e(A,r),a=e(L,r);return{activePageIndex:o>=0?o:null,viewport:{zoom:i.zoom(),panX:i.panX(),panY:i.panY(),contentBox:i.contentBox()},workspace:{background:a.background(),page:a.page(),grid:a.grid(),rulers:a.rulers(),guides:a.guides(),guidesLocked:a.guidesLocked(),interaction:a.interaction()}}}function Sp(r,e){if(e!==void 0){if(e.background!==void 0&&r.setBackground(e.background),e.page!==void 0&&r.patchPage(e.page),e.grid!==void 0&&r.patchGrid(e.grid),e.rulers!==void 0&&r.setRulersEnabled(e.rulers.enabled),e.interaction!==void 0&&r.patchInteraction(e.interaction),r.clearGuides(),e.guides!==void 0)for(const t of e.guides)r.addGuide(t.axis,t.position);e.guidesLocked!==void 0&&r.setGuidesLocked(e.guidesLocked)}}function ba(r,e){if(typeof document>"u"||typeof URL>"u")return;const t=URL.createObjectURL(r),n=document.createElement("a");n.href=t,n.download=e,document.body.appendChild(n),n.click(),n.remove(),setTimeout(()=>URL.revokeObjectURL(t),1e3)}async function wa(r,e,t){if(typeof document>"u"||typeof URL>"u")return;const n=e(S,r).document(),o=e(Le,r),i={...n,defs:o.buildExportDefs(n.defs)},a=vt.export(i);if(typeof a!="string"){typeof window<"u"&&window.alert("Save failed: exporter returned non-string.");return}const l=Us(a,Dp(r,e));try{if(t){const c=await eh(l);ba(new Blob([c],{type:"application/gzip"}),"untitled.svgez")}else ba(new Blob([l],{type:"application/json"}),"untitled.svge")}catch(c){typeof window<"u"&&window.alert(`Save failed: ${c instanceof Error?c.message:String(c)}`)}}function Pp(r,e,t){const n=Ws(t);if(!n.ok){typeof window<"u"&&window.alert(`Open failed: ${n.error}`);return}const o=ze.import(n.document);if(!o.ok){typeof window<"u"&&window.alert(`Open failed: ${o.error}`);return}if(typeof window<"u"){const u=e(S,r).document().root;if(u.type==="group"&&u.children.length>0&&!window.confirm("Discard the current document and open this workspace?"))return}e(S,r).resetDocument(o.document),e(M,r).dispatch(new eo),e(Wt,r).clear(),e(k,r).clear(),Sp(e(L,r),n.editor.workspace);const i=e(We,r).pages(),a=n.editor.activePageIndex;a!==null&&a>=0&&a<i.length&&e(j,r).setActive(i[a].id);const l=n.editor.viewport,c=e(A,r);l!==void 0?(c.setContentBox(l.contentBox),c.setZoom(l.zoom),c.setPan(l.panX,l.panY)):c.fit(),o.warnings.length>0&&typeof console<"u"&&console.warn(`[SVGEngine] Open workspace warnings:
1226
+ ${o.warnings.join(`
1227
+ `)}`)}function Mp(r){const e=r.name.lastIndexOf(".");return(e>=0?r.name.slice(e+1).toLowerCase():"")==="svgez"?r.arrayBuffer().then(n=>Ei(n)):r.text()}const Ia={id:"svge.builtin.insert-menu",name:"Built-in Insert menu (shapes/text/image) \u2014 D-052",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(Me);r.track(e.register({id:"svge.insert.shape",slot:y.INSERT,label:"Shape",icon:"category",order:10,run(){}})),r.track(e.register({id:"svge.insert.shape.rect",parentId:"svge.insert.shape",slot:y.INSERT,label:"Rectangle",icon:"rectangle",order:10,run(t){et(t,(n,o,i)=>qr({x:n-i/2,y:o-i/2,width:i,height:i}))}})),r.track(e.register({id:"svge.insert.shape.rounded-rect",parentId:"svge.insert.shape",slot:y.INSERT,label:"Rounded rectangle",icon:"crop_5_4",order:20,run(t){et(t,(n,o,i)=>qr({x:n-i/2,y:o-i/2,width:i,height:i,rx:i*.12,ry:i*.12}))}})),r.track(e.register({id:"svge.insert.shape.ellipse",parentId:"svge.insert.shape",slot:y.INSERT,label:"Ellipse / Circle",icon:"circle",order:30,run(t){et(t,(n,o,i)=>yi({cx:n,cy:o,rx:i/2,ry:i/2}))}})),r.track(e.register({id:"svge.insert.shape.line",parentId:"svge.insert.shape",slot:y.INSERT,label:"Line",icon:"horizontal_rule",order:40,run(t){et(t,(n,o,i)=>Ru({x1:n-i/2,y1:o,x2:n+i/2,y2:o}))}})),r.track(e.register({id:"svge.insert.shape.triangle",parentId:"svge.insert.shape",slot:y.INSERT,label:"Triangle",icon:"change_history",order:50,run(t){et(t,(n,o,i)=>Yr(ka(n,o,i/2,3,-Math.PI/2)))}})),r.track(e.register({id:"svge.insert.shape.polygon",parentId:"svge.insert.shape",slot:y.INSERT,label:"Polygon (5 sides)",icon:"pentagon",order:60,run(t){et(t,(n,o,i)=>Yr(ka(n,o,i/2,5,-Math.PI/2)))}})),r.track(e.register({id:"svge.insert.shape.star",parentId:"svge.insert.shape",slot:y.INSERT,label:"Star (5 points)",icon:"star",order:70,run(t){et(t,(n,o,i)=>N(Ep(n,o,i/2,5)))}})),r.track(e.register({id:"svge.insert.divider1",slot:y.INSERT,label:"",order:20,divider:!0,run(){}})),r.track(e.register({id:"svge.insert.text",slot:y.INSERT,label:"Text",icon:"text_fields",order:30,run(t){et(t,(n,o,i)=>Zr({x:n,y:o,content:"Text",fontSize:Math.max(12,Math.round(i*.3)),textAnchor:"middle"}))}})),r.track(e.register({id:"svge.insert.image",slot:y.INSERT,label:"Image\u2026",icon:"image",order:40,run(t){ra(t?.injector)}}))}};function et(r,e){const t=r?.injector;if(t===void 0)return;const{centerX:n,centerY:o,size:i}=_p(t),a=e(n,o,i);t.get(M).dispatch(new he(te,a)),t.get(k).select(a.id)}function _p(r){const t=r.get(A).viewBox(),n=t.x+t.width/2,o=t.y+t.height/2,i=Math.min(t.width,t.height)*.25,a=Math.max(40,Math.min(400,i));return{centerX:n,centerY:o,size:a}}function ka(r,e,t,n,o){const i=[];for(let a=0;a<n;a++){const l=o+a*2*Math.PI/n;i.push({x:r+t*Math.cos(l),y:e+t*Math.sin(l)})}return i}function Ep(r,e,t,n){const o=t*.4,i=-Math.PI/2,a=[];for(let l=0;l<n*2;l++){const c=l%2===0?t:o,u=i+l*Math.PI/n,h=r+c*Math.cos(u),g=e+c*Math.sin(u);a.push(`${l===0?"M":"L"}${h.toFixed(1)} ${g.toFixed(1)}`)}return a.push("Z"),a.join(" ")}const xa={id:"svge.builtin.advanced-edit-menu",name:"Built-in advanced edit menu items (compound paths + live boolean) \u2014 D-054/D-056",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(Me),t=l=>{const c=l.get(k);return m(()=>c.selectedIds().size<2)},n=l=>{const c=l.get(k),u=l.get(S);return m(()=>{const h=Array.from(c.selectedIds());if(h.length!==1)return!0;const g=T(u.document().root,h[0]);return g===null||g.type!=="path"})},o=l=>{const c=l.get(k),u=l.get(S);return m(()=>{const h=Array.from(c.selectedIds());if(h.length!==1)return!0;const g=T(u.document().root,h[0]);return g===null||!Au(g)})};r.track(e.register({id:"svge.advanced.compound",slot:y.OBJECT,label:"Compound Path",icon:"merge",order:90,run(){}})),r.track(e.register({id:"svge.advanced.compound.make",parentId:"svge.advanced.compound",slot:y.OBJECT,label:"Make Compound Path",icon:"merge",shortcut:"Ctrl+8",order:10,disabled:t,run(l){Tp(l)}})),r.track(e.register({id:"svge.advanced.compound.release",parentId:"svge.advanced.compound",slot:y.OBJECT,label:"Release Compound Path",icon:"call_split",shortcut:"Ctrl+Alt+8",order:20,disabled:n,run(l){Rp(l)}}));const i="svge.builtin.object.pathfinder";r.track(e.register({id:"svge.advanced.live-boolean.head-divider",parentId:i,slot:y.OBJECT,label:"",order:60,divider:!0,run(){}}));const a=[{id:"union",label:"Make Live Union",icon:"join_full",op:"union"},{id:"intersect",label:"Make Live Intersect",icon:"join_inner",op:"intersect"},{id:"subtract",label:"Make Live Subtract",icon:"remove_circle",op:"subtract"},{id:"exclude",label:"Make Live Exclude",icon:"join_left",op:"exclude"}];for(let l=0;l<a.length;l++){const c=a[l];r.track(e.register({id:`svge.advanced.live-boolean.make.${c.id}`,parentId:i,slot:y.OBJECT,label:c.label,icon:c.icon,order:70+l*10,disabled:t,run(u){Ap(u,c.op)}}))}r.track(e.register({id:"svge.advanced.live-boolean.refresh-divider",parentId:i,slot:y.OBJECT,label:"",order:115,divider:!0,run(){}})),r.track(e.register({id:"svge.advanced.live-boolean.refresh",parentId:i,slot:y.OBJECT,label:"Refresh Live Boolean",icon:"refresh",order:120,disabled:o,run(l){Cp(l)}})),r.track(e.register({id:"svge.advanced.live-boolean.release",parentId:i,slot:y.OBJECT,label:"Release Live Boolean",icon:"lock_open",order:130,disabled:o,run(l){Op(l)}}))}};function Tp(r){const e=r?.injector;if(e===void 0)return;const t=e.get(k),n=Array.from(t.selectedIds());n.length<2||e.get(M).dispatch(new Cu(n))}function Rp(r){const e=r?.injector;if(e===void 0)return;const t=e.get(k),n=Array.from(t.selectedIds());n.length===1&&e.get(M).dispatch(new Ou(n[0]))}function Ap(r,e){const t=r?.injector;if(t===void 0)return;const n=t.get(k),o=Array.from(n.selectedIds());o.length<2||t.get(M).dispatch(new Nu(o,e))}function Cp(r){const e=r?.injector;if(e===void 0)return;const t=e.get(k),n=Array.from(t.selectedIds());n.length===1&&e.get(M).dispatch(new Lu(n[0]))}function Op(r){const e=r?.injector;if(e===void 0)return;const t=e.get(k),n=Array.from(t.selectedIds());n.length===1&&e.get(M).dispatch(new $u(n[0]))}const Np=m(()=>!0,...ngDevMode?[{debugName:"ROADMAP_DISABLED"}]:[]);function Uo(r){return{id:r.id,slot:r.slot,label:r.label,icon:r.icon,order:r.order,parentId:r.parentId,shortcut:r.shortcut,comingSoon:!0,disabled:Np,run(){}}}function Wo(r){return{id:r.id,slot:r.slot,label:r.label,icon:r.icon,order:r.order,run(){}}}const Lp=new Set(["rect","ellipse","line","polygon","polyline"]);function Da(r){const e=r.get(k),n=r.get(S).document().root,o=[];for(const i of e.selectedIds()){const a=T(n,i);a!==null&&Lp.has(a.type)&&o.push(i)}return o}function kt(r){const e=r.get(k),t=r.get(S).document().root,n=[];for(const o of e.selectedIds()){const i=T(t,o);i!==null&&i.type==="path"&&n.push(o)}return n}function Sa(r){const e=r.get(S).document().root;return kt(r).filter(t=>{const n=T(e,t);if(n===null)return!1;const o=n.style.stroke,i=n.style.strokeWidth??1;return typeof o=="string"&&o!=="none"&&o.trim()!==""&&i>0})}function $p(r){const e=r.get(Ce).selected();if(e.length===0)return null;const t=new Map;for(const a of e){const l=t.get(a.nodeId)??[];l.push(a),t.set(a.nodeId,l)}let n=null,o=0;for(const[a,l]of t)l.length>o&&(o=l.length,n=a);if(n===null)return null;const i=t.get(n).map(a=>({subpathIndex:a.subpathIndex,anchorIndex:a.anchorIndex}));return{nodeId:n,cuts:i}}const Pa={id:"svge.builtin.roadmap-menu",name:"Menubar Option B \u2014 Path/Tools/Window menus, Mask + roadmap items (D-085)",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(Me),t=n=>{r.track(e.register(n))};t(Uo({id:"svge.roadmap.file.export.selection",parentId:"svge.builtin.file.export-menu",slot:y.FILE,label:"Export Selection\u2026",icon:"crop",order:40})),t(Uo({id:"svge.roadmap.file.export.artboard",parentId:"svge.builtin.file.export-menu",slot:y.FILE,label:"Export Artboard\u2026",icon:"crop_portrait",order:50})),t(Uo({id:"svge.roadmap.file.export.batch",parentId:"svge.builtin.file.export-menu",slot:y.FILE,label:"Batch Export\u2026",icon:"dynamic_feed",order:60})),t({id:"svge.builtin.path.convert-to-path",slot:y.PATH,label:"Convert to Path",icon:"timeline",order:10,disabled:n=>m(()=>Da(n).length===0),run(n){const o=n?.injector??r.injector,i=Da(o);i.length!==0&&o.get(M).dispatch(new Bu(i))}}),t({id:"svge.builtin.path.outline-stroke",slot:y.PATH,label:"Outline Stroke",icon:"border_style",order:20,disabled:n=>m(()=>Sa(n).length===0),run(n){const o=n?.injector??r.injector,i=Sa(o);i.length!==0&&o.get(M).dispatch(new Fu(i))}}),t({id:"svge.builtin.path.join",slot:y.PATH,label:"Join",icon:"call_merge",order:30,disabled:n=>m(()=>kt(n).length===0),run(n){const o=n?.injector??r.injector,i=kt(o);i.length!==0&&o.get(M).dispatch(new ju(i))}}),t({id:"svge.builtin.path.split",slot:y.PATH,label:"Split",icon:"call_split",order:40,disabled:n=>m(()=>n.get(Ce).count()===0),run(n){const o=n?.injector??r.injector,i=$p(o);i!==null&&o.get(M).dispatch(new Vu(i.nodeId,i.cuts))}}),t({id:"svge.builtin.path.reverse",slot:y.PATH,label:"Reverse Direction",icon:"swap_horiz",order:50,disabled:n=>m(()=>kt(n).length===0),run(n){const o=n?.injector??r.injector,i=kt(o);i.length!==0&&o.get(M).dispatch(new zu(i))}}),t({id:"svge.builtin.path.clean-up",slot:y.PATH,label:"Clean Up",icon:"cleaning_services",order:90,disabled:n=>m(()=>kt(n).length===0),run(n){const o=n?.injector??r.injector,i=kt(o);i.length!==0&&o.get(M).dispatch(new Gu(i))}}),t(Wo({id:"svge.tools.plugins",slot:y.TOOLS,label:"Plugins",icon:"extension",order:30})),t(Wo({id:"svge.window.workspace",slot:y.WINDOW,label:"Workspace",icon:"tune",order:10})),t(Wo({id:"svge.window.panels",slot:y.WINDOW,label:"Panels",icon:"view_sidebar",order:20}))}},Ma="data-svge-import-ghost-defs";class ir{placement=f(Ee);viewport=f(A);hostRef=f(ae);pending=this.placement.pending;rect=this.placement.rect;capture=m(()=>this.viewport.viewBox(),...ngDevMode?[{debugName:"capture"}]:[]);ghostNode=m(()=>{const e=this.placement.pending(),t=this.placement.placedTransform();return e===null||t===null||!this.placement.hasDragRect()?null:{...e.group,transform:t}},...ngDevMode?[{debugName:"ghostNode"}]:[]);constructor(){J(()=>{this.syncGhostDefs(this.placement.pending()?.defs??null)})}onDown(e){const t=this.toDoc(e);t!==null&&(e.preventDefault(),e.stopPropagation(),H(e),this.placement.setStretch(e.shiftKey),this.placement.beginDrag(t))}onMove(e){const t=this.toDoc(e);t!==null&&(this.placement.setStretch(e.shiftKey),this.placement.updateDrag(t))}onUp(e){e.preventDefault(),e.stopPropagation(),pe(e),this.placement.setStretch(e.shiftKey),this.placement.commitDrag()}onEscape(){this.placement.isActive&&this.placement.cancel()}onShiftKey(e){this.placement.isActive&&e.key==="Shift"&&this.placement.setStretch(e.shiftKey)}toDoc(e){const t=e.target.ownerSVGElement;return Ve(t,e.clientX,e.clientY)}syncGhostDefs(e){const t=this.hostRef.nativeElement,n=t.querySelector(`defs[${Ma}="1"]`);if(n!==null&&n.remove(),e===null||e.length===0)return;const o=t.ownerDocument.createElementNS("http://www.w3.org/2000/svg","defs");o.setAttribute(Ma,"1"),o.insertAdjacentHTML("afterbegin",e),t.insertBefore(o,t.firstChild)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ir,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:ir,isStandalone:!0,selector:"g[svgeImportPlacementOverlay]",host:{attributes:{"aria-hidden":"true"},listeners:{"document:keydown.escape":"onEscape()","document:keydown":"onShiftKey($event)","document:keyup":"onShiftKey($event)"}},ngImport:s,template:`
1228
+ @if (pending()) {
1229
+ <svg:rect
1230
+ class="ip-capture"
1231
+ [attr.x]="capture().x"
1232
+ [attr.y]="capture().y"
1233
+ [attr.width]="capture().width"
1234
+ [attr.height]="capture().height"
1235
+ (pointerdown)="onDown($event)"
1236
+ (pointermove)="onMove($event)"
1237
+ (pointerup)="onUp($event)"
1238
+ />
1239
+ @if (rect(); as r) {
1240
+ @if (ghostNode(); as gn) {
1241
+ <!-- Faithful half-opacity preview of the art at its commit transform. -->
1242
+ <svg:g class="ip-ghost">
1243
+ <svg:g svgeNode [node]="gn"></svg:g>
1244
+ </svg:g>
1245
+ }
1246
+ <svg:rect
1247
+ class="ip-band"
1248
+ [attr.x]="r.x"
1249
+ [attr.y]="r.y"
1250
+ [attr.width]="r.width"
1251
+ [attr.height]="r.height"
1252
+ />
1253
+ }
1254
+ }
1255
+ `,isInline:!0,styles:[`.ip-capture{fill:transparent;pointer-events:all;cursor:crosshair}.ip-ghost{opacity:.5;pointer-events:none}.ip-band{fill:color-mix(in srgb,#1976d2 8%,transparent);stroke:#1976d2;stroke-width:1;stroke-dasharray:4 3;vector-effect:non-scaling-stroke;pointer-events:none}
1256
+ `],dependencies:[{kind:"component",type:Mi,selector:"g[svgeNode]",inputs:["node"]}],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ir,decorators:[{type:W,args:[{selector:"g[svgeImportPlacementOverlay]",standalone:!0,imports:[Mi],host:{"aria-hidden":"true"},template:`
1257
+ @if (pending()) {
1258
+ <svg:rect
1259
+ class="ip-capture"
1260
+ [attr.x]="capture().x"
1261
+ [attr.y]="capture().y"
1262
+ [attr.width]="capture().width"
1263
+ [attr.height]="capture().height"
1264
+ (pointerdown)="onDown($event)"
1265
+ (pointermove)="onMove($event)"
1266
+ (pointerup)="onUp($event)"
1267
+ />
1268
+ @if (rect(); as r) {
1269
+ @if (ghostNode(); as gn) {
1270
+ <!-- Faithful half-opacity preview of the art at its commit transform. -->
1271
+ <svg:g class="ip-ghost">
1272
+ <svg:g svgeNode [node]="gn"></svg:g>
1273
+ </svg:g>
1274
+ }
1275
+ <svg:rect
1276
+ class="ip-band"
1277
+ [attr.x]="r.x"
1278
+ [attr.y]="r.y"
1279
+ [attr.width]="r.width"
1280
+ [attr.height]="r.height"
1281
+ />
1282
+ }
1283
+ }
1284
+ `,changeDetection:U.OnPush,styles:[`.ip-capture{fill:transparent;pointer-events:all;cursor:crosshair}.ip-ghost{opacity:.5;pointer-events:none}.ip-band{fill:color-mix(in srgb,#1976d2 8%,transparent);stroke:#1976d2;stroke-width:1;stroke-dasharray:4 3;vector-effect:non-scaling-stroke;pointer-events:none}
1285
+ `]}]}],ctorParameters:()=>[],propDecorators:{onEscape:[{type:fr,args:["document:keydown.escape"]}],onShiftKey:[{type:fr,args:["document:keydown",["$event"]]},{type:fr,args:["document:keyup",["$event"]]}]}});const _a={id:"svge.builtin.editor-shortcuts",name:"Built-in editor shortcuts (D-040)",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(tt),t=(o,i)=>(o?.injector??r.injector).get(i);r.track(e.register({id:"svge.builtin.shortcut.undo",combo:"Ctrl+Z",description:"Undo last command",category:"Edit",run(o,i){o.preventDefault(),t(i,M).undo()}})),r.track(e.register({id:"svge.builtin.shortcut.redo-y",combo:"Ctrl+Y",description:"Redo (Windows idiom)",category:"Edit",run(o,i){o.preventDefault(),t(i,M).redo()}})),r.track(e.register({id:"svge.builtin.shortcut.redo-shift-z",combo:"Ctrl+Shift+Z",description:"Redo (Mac/Linux idiom)",category:"Edit",run(o,i){o.preventDefault(),t(i,M).redo()}})),r.track(e.register({id:"svge.builtin.shortcut.group",combo:"Ctrl+G",description:"Group selection",category:"Object",run(o,i){const a=t(i,k),l=Array.from(a.selectedIds());l.length<2||(o.preventDefault(),t(i,M).dispatch(new xi(l)))}})),r.track(e.register({id:"svge.builtin.shortcut.ungroup",combo:"Ctrl+Shift+G",description:"Ungroup focused selection",category:"Object",run(o,i){const l=t(i,k).focusId();if(l===null)return;const c=t(i,S),u=T(c.document().root,l);u===null||u.type!=="group"||(o.preventDefault(),t(i,M).dispatch(new Di(l)))}})),r.track(e.register({id:"svge.builtin.shortcut.select-all",combo:"Ctrl+A",description:"Select all objects on the active page",category:"Selection",run(o,i){const a=t(i,j).treeForRendering();a.type!=="group"||a.children.length===0||(o.preventDefault(),t(i,k).selectMany(a.children.map(l=>l.id)))}}));const n=(o,i,a,l,c)=>{r.track(e.register({id:o,combo:i,description:a,category:l,run(u,h){const g=h?.injector??r.injector,v=g.get(Me).get(c);v!==null&&(u.preventDefault(),Lo(v,g))}}))};n("svge.builtin.shortcut.cut","Ctrl+X","Cut selection","Edit","svge.builtin.edit.cut"),n("svge.builtin.shortcut.copy","Ctrl+C","Copy selection","Edit","svge.builtin.edit.copy"),n("svge.builtin.shortcut.paste","Ctrl+V","Paste","Edit","svge.builtin.edit.paste"),n("svge.builtin.shortcut.paste-in-place","Ctrl+Shift+V","Paste in place","Edit","svge.builtin.edit.paste-in-place"),n("svge.builtin.shortcut.duplicate","Ctrl+D","Duplicate selection","Edit","svge.builtin.edit.duplicate"),r.track(e.register({id:"svge.builtin.shortcut.take-snapshot",combo:"Ctrl+Shift+S",description:"Take a snapshot of the current document",category:"Snapshots",run(o,i){const l=(i?.injector??r.injector).get(Ze,null,{optional:!0});l!==null&&(o.preventDefault(),l.take(t(i,S).document(),{source:"manual"}))}})),r.track(e.register({id:"svge.builtin.shortcut.restore-last-snapshot",combo:"Ctrl+Alt+Z",description:"Restore the most recent snapshot",category:"Snapshots",run(o,i){const l=(i?.injector??r.injector).get(Ze,null,{optional:!0});if(l===null)return;const c=l.snapshots();if(c.length===0)return;const u=c.find(h=>h.source!=="auto-restore")??c[0];o.preventDefault(),t(i,M).dispatch(new ki(u.id,l))}})),r.track(e.register({id:"svge.builtin.shortcut.save-workspace",combo:"Ctrl+S",description:"Save workspace (.svge)",category:"File",run(o,i){const a=i?.injector??r.injector,l=a.get(Me).get("svge.builtin.file.save");l!==null&&(o.preventDefault(),Lo(l,a))}}))}},Ea={id:"svge.builtin.io",version:"1.0.0",name:"Built-in SVG IO (import + export)",apiVersion:O,install(r){r.track(r.injector.get(th).register(ze)),r.track(r.injector.get(no).register(vt))}},Ta={id:"svge.builtin.exporter.png.plugin",version:"1.0.0",name:"PNG exporter (canvas-based)",apiVersion:O,install(r){r.track(r.injector.get(no).register(Ti))}},Ra={id:"svge.builtin.optimizers",version:"1.0.0",name:"Built-in SVG optimizers",apiVersion:O,install(r){const e=r.injector.get(Ri);r.track(e.register(rh)),r.track(e.register(oh)),r.track(e.register(ih)),r.track(e.register(sh))}},Aa="svge-viewport-culling-style";class $t{state=f(S);viewport=f(A);bboxCache=new WeakMap;culledIds=m(()=>{const e=this.state.document(),t=this.viewport.viewBox(),n=new Set;for(const o of e.root.children)this.cullSubtree(o,t,n);return n},...ngDevMode?[{debugName:"culledIds"}]:[]);cullSubtree(e,t,n){const o=this.getCachedBBox(e);if(!Hu(o,t)){n.add(e.id);return}if(Fe(e))for(const i of e.children)this.cullSubtree(i,t,n)}constructor(){this.ensureStylesheetInjected()}getCachedBBox(e){let t=this.bboxCache.get(e);return t===void 0&&(t=br(e),this.bboxCache.set(e,t)),t}ensureStylesheetInjected(){if(typeof document>"u"||document.getElementById(Aa)!==null)return;const e=document.createElement("style");e.id=Aa,e.textContent='[data-svge-culled="1"]{display:none}',document.head.appendChild(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:$t,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:$t,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:$t,decorators:[{type:D,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});const $n="data-svge-culled";class sr{elRef=f(ae);culling=f($t);rafId=null;constructor(){J(()=>{this.culling.culledIds(),this.scheduleCullingPass()})}ngOnDestroy(){this.rafId!==null&&typeof cancelAnimationFrame=="function"&&(cancelAnimationFrame(this.rafId),this.rafId=null);const t=this.elRef.nativeElement.querySelectorAll(`[${$n}="1"]`);for(const n of t)n.removeAttribute($n)}scheduleCullingPass(){if(this.rafId===null){if(typeof requestAnimationFrame!="function"){this.applyCulling();return}this.rafId=requestAnimationFrame(()=>{this.rafId=null,this.applyCulling()})}}applyCulling(){const e=this.culling.culledIds(),n=this.elRef.nativeElement.querySelectorAll("[data-node-id]");for(const o of n){const i=o.getAttribute("data-node-id");if(i===null)continue;const a=e.has(i),l=o.getAttribute($n)==="1";a&&!l?o.setAttribute($n,"1"):!a&&l&&o.removeAttribute($n)}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:sr,deps:[],target:s.\u0275\u0275FactoryTarget.Directive});static \u0275dir=s.\u0275\u0275ngDeclareDirective({minVersion:"14.0.0",version:"21.2.13",type:sr,isStandalone:!0,selector:"[svgeViewportCulling]",ngImport:s})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:sr,decorators:[{type:pt,args:[{selector:"[svgeViewportCulling]",standalone:!0}]}],ctorParameters:()=>[]});const Ca={id:"svge.builtin.effect.blur",name:"Blur",category:"blur",buildFilterMarkup(){return`<filter id="${this.id}" x="-50%" y="-50%" width="200%" height="200%">
1286
+ <feGaussianBlur in="SourceGraphic" stdDeviation="3" />
1287
+ </filter>`}},Oa={id:"svge.builtin.effect.drop-shadow",name:"Drop shadow",category:"shadow",buildFilterMarkup(){return`<filter id="${this.id}" x="-25%" y="-25%" width="150%" height="150%">
1288
+ <feGaussianBlur in="SourceAlpha" stdDeviation="4" />
1289
+ <feOffset dx="4" dy="4" result="offsetblur" />
1290
+ <feComponentTransfer><feFuncA type="linear" slope="0.5" /></feComponentTransfer>
1291
+ <feMerge>
1292
+ <feMergeNode />
1293
+ <feMergeNode in="SourceGraphic" />
1294
+ </feMerge>
1295
+ </filter>`}},Na={id:"svge.builtin.effect.inner-shadow",name:"Inner shadow",category:"shadow",buildFilterMarkup(){return`<filter id="${this.id}" x="-10%" y="-10%" width="120%" height="120%">
1296
+ <feGaussianBlur in="SourceAlpha" stdDeviation="3" />
1297
+ <feOffset dx="3" dy="3" />
1298
+ <feComposite in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowDiff" />
1299
+ <feFlood flood-color="black" flood-opacity="0.6" />
1300
+ <feComposite in2="shadowDiff" operator="in" />
1301
+ <feComposite in2="SourceGraphic" operator="over" />
1302
+ </filter>`}},La={id:"svge.builtin.effect.outer-glow",name:"Outer glow",category:"glow",buildFilterMarkup(){return`<filter id="${this.id}" x="-50%" y="-50%" width="200%" height="200%">
1303
+ <feGaussianBlur in="SourceAlpha" stdDeviation="5" result="blur" />
1304
+ <feFlood flood-color="white" flood-opacity="0.9" />
1305
+ <feComposite in2="blur" operator="in" result="glow" />
1306
+ <feMerge>
1307
+ <feMergeNode in="glow" />
1308
+ <feMergeNode in="SourceGraphic" />
1309
+ </feMerge>
1310
+ </filter>`}},$a={id:"svge.builtin.effect.inner-glow",name:"Inner glow",category:"glow",buildFilterMarkup(){return`<filter id="${this.id}" x="-10%" y="-10%" width="120%" height="120%">
1311
+ <feGaussianBlur in="SourceAlpha" stdDeviation="4" />
1312
+ <feComposite in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="glowDiff" />
1313
+ <feFlood flood-color="white" flood-opacity="0.8" />
1314
+ <feComposite in2="glowDiff" operator="in" />
1315
+ <feComposite in2="SourceGraphic" operator="over" />
1316
+ </filter>`}},Ba={id:"svge.builtin.effect.bevel",name:"Bevel",category:"stylize",buildFilterMarkup(){return`<filter id="${this.id}" x="-10%" y="-10%" width="120%" height="120%">
1317
+ <feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blur" />
1318
+ <feSpecularLighting in="blur" surfaceScale="3" specularConstant="1" specularExponent="20"
1319
+ lighting-color="white" result="spec">
1320
+ <feDistantLight azimuth="225" elevation="45" />
1321
+ </feSpecularLighting>
1322
+ <feComposite in="spec" in2="SourceAlpha" operator="in" result="specCut" />
1323
+ <feComposite in="SourceGraphic" in2="specCut" operator="arithmetic"
1324
+ k1="0" k2="1" k3="1" k4="0" />
1325
+ </filter>`}},Fa={id:"svge.builtin.effect.emboss",name:"Emboss",category:"stylize",buildFilterMarkup(){return`<filter id="${this.id}">
1326
+ <feConvolveMatrix order="3" preserveAlpha="true"
1327
+ kernelMatrix="-2 -1 0
1328
+ -1 1 1
1329
+ 0 1 2" />
1330
+ </filter>`}},ja={id:"svge.builtin.effect.grayscale",name:"Grayscale",category:"color",buildFilterMarkup(){return`<filter id="${this.id}">
1331
+ <feColorMatrix type="matrix" values="0.2126 0.7152 0.0722 0 0
1332
+ 0.2126 0.7152 0.0722 0 0
1333
+ 0.2126 0.7152 0.0722 0 0
1334
+ 0 0 0 1 0" />
1335
+ </filter>`}},Va={id:"svge.builtin.effect.sepia",name:"Sepia",category:"color",buildFilterMarkup(){return`<filter id="${this.id}">
1336
+ <feColorMatrix type="matrix" values="0.393 0.769 0.189 0 0
1337
+ 0.349 0.686 0.168 0 0
1338
+ 0.272 0.534 0.131 0 0
1339
+ 0 0 0 1 0" />
1340
+ </filter>`}},za={id:"svge.builtin.effect.invert",name:"Invert",category:"color",buildFilterMarkup(){return`<filter id="${this.id}">
1341
+ <feComponentTransfer>
1342
+ <feFuncR type="table" tableValues="1 0" />
1343
+ <feFuncG type="table" tableValues="1 0" />
1344
+ <feFuncB type="table" tableValues="1 0" />
1345
+ </feComponentTransfer>
1346
+ </filter>`}},Ga={id:"svge.builtin.effect.brightness",name:"Brightness +30%",category:"adjustment",buildFilterMarkup(){return`<filter id="${this.id}">
1347
+ <feComponentTransfer>
1348
+ <feFuncR type="linear" slope="1" intercept="0.3" />
1349
+ <feFuncG type="linear" slope="1" intercept="0.3" />
1350
+ <feFuncB type="linear" slope="1" intercept="0.3" />
1351
+ </feComponentTransfer>
1352
+ </filter>`}},Ha={id:"svge.builtin.effect.contrast",name:"Contrast +50%",category:"adjustment",buildFilterMarkup(){return`<filter id="${this.id}">
1353
+ <feComponentTransfer>
1354
+ <feFuncR type="linear" slope="1.5" intercept="-0.25" />
1355
+ <feFuncG type="linear" slope="1.5" intercept="-0.25" />
1356
+ <feFuncB type="linear" slope="1.5" intercept="-0.25" />
1357
+ </feComponentTransfer>
1358
+ </filter>`}},Ua={id:"svge.builtin.effect.saturate",name:"Saturate 200%",category:"adjustment",buildFilterMarkup(){return`<filter id="${this.id}">
1359
+ <feColorMatrix type="saturate" values="2" />
1360
+ </filter>`}},Wa={id:"svge.builtin.effect.hue-rotate",name:"Hue rotate 90\xB0",category:"adjustment",buildFilterMarkup(){return`<filter id="${this.id}">
1361
+ <feColorMatrix type="hueRotate" values="90" />
1362
+ </filter>`}},Ka={id:"svge.builtin.effect.noise",name:"Noise",category:"distortion",buildFilterMarkup(){return`<filter id="${this.id}">
1363
+ <feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2" seed="5"
1364
+ stitchTiles="stitch" result="noise" />
1365
+ <feColorMatrix in="noise" type="matrix"
1366
+ values="0 0 0 0 0
1367
+ 0 0 0 0 0
1368
+ 0 0 0 0 0
1369
+ 0 0 0 0.4 0" result="noiseAlpha" />
1370
+ <feComposite in="noiseAlpha" in2="SourceAlpha" operator="in" result="grain" />
1371
+ <feMerge>
1372
+ <feMergeNode in="SourceGraphic" />
1373
+ <feMergeNode in="grain" />
1374
+ </feMerge>
1375
+ </filter>`}},Xa={id:"svge.builtin.effect.displacement-map",name:"Displacement map",category:"distortion",buildFilterMarkup(){return`<filter id="${this.id}" x="-10%" y="-10%" width="120%" height="120%">
1376
+ <feTurbulence type="turbulence" baseFrequency="0.05" numOctaves="2" seed="2"
1377
+ result="turb" />
1378
+ <feDisplacementMap in="SourceGraphic" in2="turb" scale="10"
1379
+ xChannelSelector="R" yChannelSelector="G" />
1380
+ </filter>`}},Ya={id:"svge.builtin.effect.chromatic-aberration",name:"Chromatic aberration",category:"distortion",buildFilterMarkup(){return`<filter id="${this.id}" x="-10%" y="-10%" width="120%" height="120%">
1381
+ <feColorMatrix in="SourceGraphic" type="matrix"
1382
+ values="1 0 0 0 0
1383
+ 0 0 0 0 0
1384
+ 0 0 0 0 0
1385
+ 0 0 0 1 0" result="r" />
1386
+ <feOffset in="r" dx="-2" dy="0" result="rShift" />
1387
+ <feColorMatrix in="SourceGraphic" type="matrix"
1388
+ values="0 0 0 0 0
1389
+ 0 1 0 0 0
1390
+ 0 0 0 0 0
1391
+ 0 0 0 1 0" result="g" />
1392
+ <feColorMatrix in="SourceGraphic" type="matrix"
1393
+ values="0 0 0 0 0
1394
+ 0 0 0 0 0
1395
+ 0 0 1 0 0
1396
+ 0 0 0 1 0" result="b" />
1397
+ <feOffset in="b" dx="2" dy="0" result="bShift" />
1398
+ <feBlend in="rShift" in2="g" mode="screen" result="rg" />
1399
+ <feBlend in="rg" in2="bShift" mode="screen" />
1400
+ </filter>`}},qa={id:"svge.builtin.effect.pixelate",name:"Pixelate",category:"stylize",buildFilterMarkup(){return`<filter id="${this.id}">
1401
+ <feGaussianBlur stdDeviation="1.5" />
1402
+ <feComponentTransfer>
1403
+ <feFuncR type="discrete" tableValues="0 0.25 0.5 0.75 1" />
1404
+ <feFuncG type="discrete" tableValues="0 0.25 0.5 0.75 1" />
1405
+ <feFuncB type="discrete" tableValues="0 0.25 0.5 0.75 1" />
1406
+ </feComponentTransfer>
1407
+ </filter>`}},Za={id:"svge.builtin.effect.posterize",name:"Posterize",category:"stylize",buildFilterMarkup(){return`<filter id="${this.id}">
1408
+ <feComponentTransfer>
1409
+ <feFuncR type="discrete" tableValues="0 0.33 0.66 1" />
1410
+ <feFuncG type="discrete" tableValues="0 0.33 0.66 1" />
1411
+ <feFuncB type="discrete" tableValues="0 0.33 0.66 1" />
1412
+ </feComponentTransfer>
1413
+ </filter>`}},Ja=[Ca,Oa,Na,La,$a,Ba,Fa,ja,Va,za,Ga,Ha,Ua,Wa,Ka,Xa,Ya,qa,Za],Qa={id:"svge.builtin.effects",version:"2.0.0",name:"Built-in effects (19 presets \u2014 blur, shadows, glows, color, distortion, pixel art)",apiVersion:O,install(r){const e=r.injector.get(ct);for(const t of Ja)r.track(e.register(t))}},Bp=.5,Fp=2,jp=1,Vp=16,zp=800;class ar{host=f(ae);viewport=f(A);workspace=f(L);boundOnWheel=e=>this.onWheel(e);boundOnPointerDown=e=>this.onPointerDown(e);resizeObserver=null;panState=null;constructor(){const e=this.host.nativeElement;e.addEventListener("wheel",this.boundOnWheel,{passive:!1}),e.addEventListener("pointerdown",this.boundOnPointerDown),typeof ResizeObserver<"u"&&(this.resizeObserver=new ResizeObserver(t=>{const n=t[t.length-1];if(n===void 0)return;const o=n.contentRect;this.viewport.setViewportSize(o.width,o.height)}),this.resizeObserver.observe(e))}ngOnDestroy(){const e=this.host.nativeElement;e.removeEventListener("wheel",this.boundOnWheel),e.removeEventListener("pointerdown",this.boundOnPointerDown),this.resizeObserver?.disconnect(),this.resizeObserver=null,this.cleanupPanIfActive()}onWheel(e){e.preventDefault();const t=this.screenToDoc(e.clientX,e.clientY);if(t===null)return;const n=e.deltaMode===WheelEvent.DOM_DELTA_LINE?Vp:e.deltaMode===WheelEvent.DOM_DELTA_PAGE?zp:jp,o=e.deltaY*n,i=ug(this.workspace.interaction().wheelZoomSpeed),a=Math.exp(-o*i),l=Math.max(Bp,Math.min(Fp,a));this.viewport.zoomAt(l,t)}onPointerDown(e){if(e.button!==1)return;e.preventDefault();const t=e.target;H(e),this.panState={pointerId:e.pointerId,startScreenX:e.clientX,startScreenY:e.clientY,startPanX:this.viewport.panX(),startPanY:this.viewport.panY(),target:t},t.addEventListener("pointermove",this.onPanMove),t.addEventListener("pointerup",this.onPanEnd),t.addEventListener("pointercancel",this.onPanEnd)}onPanMove=e=>{const t=this.panState;if(t===null||e.pointerId!==t.pointerId)return;const n=e.clientX-t.startScreenX,o=e.clientY-t.startScreenY,i=this.host.nativeElement.getBoundingClientRect();if(i.width<=0||i.height<=0)return;const a=this.viewport.viewBox(),l=a.width/i.width,c=a.height/i.height;this.viewport.setPan(t.startPanX-n*l,t.startPanY-o*c)};onPanEnd=e=>{const t=this.panState;t===null||e.pointerId!==t.pointerId||this.cleanupPanIfActive()};cleanupPanIfActive(){const e=this.panState;e!==null&&(e.target.removeEventListener("pointermove",this.onPanMove),e.target.removeEventListener("pointerup",this.onPanEnd),e.target.removeEventListener("pointercancel",this.onPanEnd),pe({target:e.target,pointerId:e.pointerId}),this.panState=null)}screenToDoc(e,t){const n=this.host.nativeElement.querySelector("svg");return Ve(n,e,t)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ar,deps:[],target:s.\u0275\u0275FactoryTarget.Directive});static \u0275dir=s.\u0275\u0275ngDeclareDirective({minVersion:"14.0.0",version:"21.2.13",type:ar,isStandalone:!0,selector:"[svgeCanvasGestures]",ngImport:s})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ar,decorators:[{type:pt,args:[{selector:"[svgeCanvasGestures]",standalone:!0}]}],ctorParameters:()=>[]});const Ko="data-svge-isolation-dimmed",Gp="0.35";class lr{elRef=f(ae);isolation=f(it);state=f(S);currentlyDimmed=new Set;constructor(){J(()=>{this.isolation.isolationRootId(),this.state.document(),this.apply()})}ngOnDestroy(){for(const e of this.currentlyDimmed)this.restoreOne(e);this.currentlyDimmed.clear()}apply(){const e=this.isolation.isolationRootId(),t=this.elRef.nativeElement;if(e===null){for(const u of this.currentlyDimmed)this.restoreOne(u);this.currentlyDimmed.clear();return}const n=new Set;n.add(e);const o=this.state.document().root,i=T(o,e);i!==null&&Fe(i)&&el(i,n);const a=Hp(o,e),l=t.querySelectorAll("[data-node-id]"),c=new Set;for(const u of l){const h=u.getAttribute("data-node-id");if(h===null)continue;c.add(h),n.has(h)||a.has(h)?this.currentlyDimmed.has(h)&&(this.restoreOne(h),this.currentlyDimmed.delete(h)):this.currentlyDimmed.has(h)||(this.dimOne(h,u),this.currentlyDimmed.add(h))}for(const u of[...this.currentlyDimmed])c.has(u)||this.currentlyDimmed.delete(u)}dimOne(e,t){const o=this.elRef.nativeElement.querySelectorAll(`[data-node-id="${tl(e)}"]`);for(const i of o.length>0?o:[t])i.setAttribute(Ko,"1"),i.style.opacity=Gp,i.style.pointerEvents="none"}restoreOne(e){const n=this.elRef.nativeElement.querySelectorAll(`[data-node-id="${tl(e)}"]`);for(const o of n)o.hasAttribute(Ko)&&(o.removeAttribute(Ko),o.style.removeProperty("opacity"),o.style.removeProperty("pointer-events"))}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:lr,deps:[],target:s.\u0275\u0275FactoryTarget.Directive});static \u0275dir=s.\u0275\u0275ngDeclareDirective({minVersion:"14.0.0",version:"21.2.13",type:lr,isStandalone:!0,selector:"[svgeIsolationFilter]",ngImport:s})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:lr,decorators:[{type:pt,args:[{selector:"[svgeIsolationFilter]",standalone:!0}]}],ctorParameters:()=>[]});function el(r,e){if(Fe(r))for(const t of r.children)e.add(t.id),Fe(t)&&el(t,e)}function Hp(r,e){const t=new Set;let n=e,o=1e3;for(;n!==null&&o>0;){if(n===r.id)return t.add(r.id),t;const i=ft(r,n);if(i===null)return t;t.add(i.id),n=i.id,o-=1}return t}function tl(r){const e=globalThis.CSS;return e?.escape?e.escape(r):r.replace(/["\\]/g,"\\$&")}function Xo(r,e,t,n,o){const i=1-o,a=i*i*i,l=3*i*i*o,c=3*i*o*o,u=o*o*o;return{x:a*r.x+l*e.x+c*t.x+u*n.x,y:a*r.y+l*e.y+c*t.y+u*n.y}}function Up(r,e,t,n,o,i=24,a=24){let l=0,c=1/0;for(let g=0;g<=i;g++){const v=g/i,p=Yo(Xo(r,e,t,n,v),o);p<c&&(c=p,l=v)}let u=Math.max(0,l-1/i),h=Math.min(1,l+1/i);for(let g=0;g<a;g++){const v=u+(h-u)/3,p=h-(h-u)/3,x=Yo(Xo(r,e,t,n,v),o),E=Yo(Xo(r,e,t,n,p),o);x<E?h=p:u=v}return(u+h)/2}function Yo(r,e){const t=r.x-e.x,n=r.y-e.y;return t*t+n*n}const Wp=8,Kp=6,Xp={cusp:"smooth",smooth:"symmetric",symmetric:"cusp"};class cr{elRef=f(ae);selection=f(k);anchorSelection=f(Ce);state=f(S);viewport=f(A);bus=f(M);toolHost=f(Se);layers=f(ne);pointSize=m(()=>Wp/this.viewport.zoom(),...ngDevMode?[{debugName:"pointSize"}]:[]);pointHalf=m(()=>this.pointSize()/2,...ngDevMode?[{debugName:"pointHalf"}]:[]);handleHalf=m(()=>Kp/this.viewport.zoom()/2,...ngDevMode?[{debugName:"handleHalf"}]:[]);hitZoneSize=m(()=>10/this.viewport.zoom(),...ngDevMode?[{debugName:"hitZoneSize"}]:[]);anchors=m(()=>{if(this.toolHost.activeId()!==xe||this.selection.count()!==1)return null;const e=this.selection.focusId();if(e===null||this.layers.hiddenIds().has(e))return null;const t=this.state.document(),n=Qt(t.root,e);if(n===null||n.type!=="path"||n.metadata.visible===!1)return null;const o=Ut(n.d),i=An(t.root,e),a=[];let l=0;for(const u of o)l+=u.anchors.length;let c=0;for(let u=0;u<o.length;u++){const h=o[u];for(let g=0;g<h.anchors.length;g++){const v=h.anchors[g],p={nodeId:e,subpathIndex:u,anchorIndex:g},x=!Jt(v.handleIn,v.point),E=!Jt(v.handleOut,v.point),C={point:He(i,v.point),handleIn:He(i,v.handleIn),handleOut:He(i,v.handleOut),kind:v.kind};a.push({key:`${u}:${g}`,ref:p,anchor:C,hasHandleIn:x,hasHandleOut:E,isSelected:this.anchorSelection.isSelected(p),index:c,total:l}),c++}}return a},...ngDevMode?[{debugName:"anchors"}]:[]);segments=m(()=>{if(this.toolHost.activeId()!==xe||this.selection.count()!==1)return null;const e=this.selection.focusId();if(e===null||this.layers.hiddenIds().has(e))return null;const t=this.state.document(),n=Qt(t.root,e);if(n===null||n.type!=="path"||n.metadata.visible===!1)return null;const o=Ut(n.d),i=An(t.root,e),a=[];for(let l=0;l<o.length;l++){const c=o[l],u=c.anchors.length,h=c.closed?u:u-1;for(let g=0;g<h;g++){const v=c.anchors[g],p=c.anchors[(g+1)%u],x=He(i,v.point),E=He(i,v.handleOut),C=He(i,p.handleIn),G=He(i,p.point);a.push({key:`seg:${l}:${g}`,d:`M${Y(x.x)} ${Y(x.y)} C${Y(E.x)} ${Y(E.y)} ${Y(C.x)} ${Y(C.y)} ${Y(G.x)} ${Y(G.y)}`,ref:{nodeId:e,subpathIndex:l,anchorIndex:g},p0:x,p1:E,p2:C,p3:G})}}return a},...ngDevMode?[{debugName:"segments"}]:[]);onSegmentPointerDown(e,t){if(e.button===0){if(e.altKey){e.stopPropagation(),e.preventDefault(),this.bus.dispatch(new Si(t,.5));return}e.stopPropagation()}}onSegmentDoubleClick(e,t){e.stopPropagation(),e.preventDefault();const n=this.screenToDoc(e.clientX,e.clientY),o=n===null?.5:Up(t.p0,t.p1,t.p2,t.p3,n),i=Math.min(.999,Math.max(.001,o));this.bus.dispatch(new Si(t.ref,i))}dragState=null;onPointerDown(e,t,n){if(e.button!==0)return;e.stopPropagation(),n==="point"&&(e.shiftKey||e.ctrlKey||e.metaKey?this.anchorSelection.toggle(t):this.anchorSelection.selectOne(t));const o=this.screenToDoc(e.clientX,e.clientY);if(o===null)return;const i=this.anchorAt(t);if(i===null)return;const a=n==="point"?i.point:n==="handleIn"?i.handleIn:i.handleOut,l=this.state.document();if(Qt(l.root,t.nodeId)===null)return;const u=An(l.root,t.nodeId);let h;try{h=Jp(u)}catch{return}this.dragState={ref:t,which:n,startDocPoint:o,originalPos:a,nodeTransform:u,inverseNodeTransform:h},H(e)}resolveLocalPos(e){if(this.dragState===null)return null;const t=He(this.dragState.inverseNodeTransform,this.dragState.startDocPoint),n=He(this.dragState.inverseNodeTransform,e);return{x:this.dragState.originalPos.x+(n.x-t.x),y:this.dragState.originalPos.y+(n.y-t.y)}}onPointerMove(e){if(this.dragState===null)return;e.stopPropagation();const t=this.screenToDoc(e.clientX,e.clientY);if(t===null)return;const n=this.resolveLocalPos(t);n!==null&&this.applyPreview(n)}onPointerUp(e){if(this.dragState===null)return;e.stopPropagation(),pe(e);const t=this.screenToDoc(e.clientX,e.clientY);if(t===null){this.dragState=null;return}const n=this.resolveLocalPos(t);if(n===null){this.dragState=null;return}if(Math.abs(n.x-this.dragState.originalPos.x)<1e-4&&Math.abs(n.y-this.dragState.originalPos.y)<1e-4){this.dragState=null;return}this.revertPreview(),this.bus.dispatch(new Pi(this.dragState.ref,n,this.dragState.which)),this.dragState=null}onDoubleClick(e,t){e.stopPropagation(),this.cycleKind(t)}onKeyDown(e,t,n){if(e.key==="Enter"&&n==="point"){e.preventDefault(),this.cycleKind(t);return}const o=e.shiftKey?10:1;let i=0,a=0;switch(e.key){case"ArrowLeft":i=-o;break;case"ArrowRight":i=o;break;case"ArrowUp":a=-o;break;case"ArrowDown":a=o;break;default:return}e.preventDefault(),e.stopPropagation();const l=this.anchorAt(t);if(l===null)return;const c=n==="point"?l.point:n==="handleIn"?l.handleIn:l.handleOut,u={x:c.x+i,y:c.y+a};this.bus.dispatch(new Pi(t,u,n))}cycleKind(e){const t=this.anchorAt(e);if(t===null)return;const n=Xp[t.kind];n!==t.kind&&this.bus.dispatch(new Uu(e,n))}previewSnapshot=null;applyPreview(e){if(this.dragState===null)return;const t=this.dragState.ref.nodeId,n=this.state.document(),o=Qt(n.root,t);if(o===null||o.type!=="path")return;this.previewSnapshot===null&&(this.previewSnapshot=o.d);const i=Ut(this.previewSnapshot).map(h=>({anchors:[...h.anchors],closed:h.closed})),a=i[this.dragState.ref.subpathIndex];if(a===void 0)return;const l=a.anchors[this.dragState.ref.anchorIndex];if(l===void 0)return;a.anchors[this.dragState.ref.anchorIndex]=Yp(l,e,this.dragState.which);const c=qp(i);if(c===o.d)return;const u=nl(n.root,t,c);this.state.setDocument({...n,root:u})}revertPreview(){if(this.dragState===null||this.previewSnapshot===null)return;const e=this.state.document(),t=nl(e.root,this.dragState.ref.nodeId,this.previewSnapshot);this.state.setDocument({...e,root:t}),this.previewSnapshot=null}screenToDoc(e,t){return Ve(this.elRef.nativeElement.ownerSVGElement,e,t)}anchorAt(e){const t=this.state.document(),n=Qt(t.root,e.nodeId);if(n===null||n.type!=="path")return null;const i=Ut(n.d)[e.subpathIndex];return i===void 0?null:i.anchors[e.anchorIndex]??null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:cr,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:cr,isStandalone:!0,selector:"g[svgeAnchorOverlay]",host:{attributes:{role:"application","aria-label":"Path anchor editor \u2014 use arrow keys to nudge selected anchor or handle, Enter to cycle anchor type, Delete to remove anchor"}},ngImport:s,template:`
1414
+ @if (anchors(); as anchors) {
1415
+ <!--
1416
+ Handle stems first (rendered behind squares so a drag on the
1417
+ square wins hit-testing). Each stem is two short lines from
1418
+ the anchor point to its in/out tangent control. Decorative \u2014
1419
+ aria-hidden so SR users don't hear "graphic" noise for every
1420
+ tangent line.
1421
+ -->
1422
+ @for (a of anchors; track a.key) {
1423
+ @if (a.hasHandleIn) {
1424
+ <svg:line
1425
+ class="handle-stem"
1426
+ aria-hidden="true"
1427
+ [attr.x1]="a.anchor.point.x"
1428
+ [attr.y1]="a.anchor.point.y"
1429
+ [attr.x2]="a.anchor.handleIn.x"
1430
+ [attr.y2]="a.anchor.handleIn.y"
1431
+ />
1432
+ }
1433
+ @if (a.hasHandleOut) {
1434
+ <svg:line
1435
+ class="handle-stem"
1436
+ aria-hidden="true"
1437
+ [attr.x1]="a.anchor.point.x"
1438
+ [attr.y1]="a.anchor.point.y"
1439
+ [attr.x2]="a.anchor.handleOut.x"
1440
+ [attr.y2]="a.anchor.handleOut.y"
1441
+ />
1442
+ }
1443
+ }
1444
+
1445
+ <!-- Handle circles (interactive \u2014 tangent control points). -->
1446
+ @for (a of anchors; track a.key) {
1447
+ @if (a.hasHandleIn) {
1448
+ <svg:circle
1449
+ class="handle-knob"
1450
+ role="button"
1451
+ tabindex="0"
1452
+ focusable="true"
1453
+ [attr.aria-label]="
1454
+ 'Incoming tangent handle, anchor ' + (a.index + 1) + ' of ' + a.total
1455
+ "
1456
+ [attr.cx]="a.anchor.handleIn.x"
1457
+ [attr.cy]="a.anchor.handleIn.y"
1458
+ [attr.r]="handleHalf()"
1459
+ (pointerdown)="onPointerDown($event, a.ref, 'handleIn')"
1460
+ (pointermove)="onPointerMove($event)"
1461
+ (pointerup)="onPointerUp($event)"
1462
+ (keydown)="onKeyDown($event, a.ref, 'handleIn')"
1463
+ />
1464
+ }
1465
+ @if (a.hasHandleOut) {
1466
+ <svg:circle
1467
+ class="handle-knob"
1468
+ role="button"
1469
+ tabindex="0"
1470
+ focusable="true"
1471
+ [attr.aria-label]="
1472
+ 'Outgoing tangent handle, anchor ' + (a.index + 1) + ' of ' + a.total
1473
+ "
1474
+ [attr.cx]="a.anchor.handleOut.x"
1475
+ [attr.cy]="a.anchor.handleOut.y"
1476
+ [attr.r]="handleHalf()"
1477
+ (pointerdown)="onPointerDown($event, a.ref, 'handleOut')"
1478
+ (pointermove)="onPointerMove($event)"
1479
+ (pointerup)="onPointerUp($event)"
1480
+ (keydown)="onKeyDown($event, a.ref, 'handleOut')"
1481
+ />
1482
+ }
1483
+ }
1484
+
1485
+ <!--
1486
+ Invisible segment hit-zones for inserting anchors. Renders BELOW
1487
+ the anchor squares so a click on the anchor itself wins.
1488
+ 'stroke: transparent' + 'stroke-width' ~10px (in CSS px via
1489
+ 1/zoom) makes the target generous enough to hit without a precise
1490
+ stylus.
1491
+
1492
+ Gestures (see handlers):
1493
+ - **Double-click** \u2192 insert a new anchor AT THE CLICK LOCATION
1494
+ (projected onto the curve; market convention \u2014 Inkscape /
1495
+ Affinity / Figma). Primary gesture.
1496
+ - **Alt+click** \u2192 insert at the segment midpoint (t=0.5). Kept
1497
+ for back-compat with the original D-038 gesture.
1498
+ A plain single click is swallowed (stopPropagation) so it neither
1499
+ deselects the path nor starts a marquee from the curve \u2014 and so
1500
+ the overlay survives until the dblclick fires.
1501
+
1502
+ aria-hidden because click-on-curve has no comparable keyboard
1503
+ surface (continuous along the curve); the keyboard alternative is
1504
+ to focus an anchor and use Enter to cycle kind / arrow keys.
1505
+ -->
1506
+ @for (seg of segments(); track seg.key) {
1507
+ <svg:path
1508
+ class="segment-hit"
1509
+ aria-hidden="true"
1510
+ [attr.d]="seg.d"
1511
+ [attr.stroke-width]="hitZoneSize()"
1512
+ (pointerdown)="onSegmentPointerDown($event, seg.ref)"
1513
+ (dblclick)="onSegmentDoubleClick($event, seg)"
1514
+ />
1515
+ }
1516
+
1517
+ <!-- Anchor squares (interactive, on top). -->
1518
+ @for (a of anchors; track a.key) {
1519
+ <svg:rect
1520
+ class="anchor-point"
1521
+ role="button"
1522
+ tabindex="0"
1523
+ focusable="true"
1524
+ [class.selected]="a.isSelected"
1525
+ [attr.aria-pressed]="a.isSelected ? 'true' : 'false'"
1526
+ [attr.aria-label]="
1527
+ 'Anchor ' +
1528
+ (a.index + 1) +
1529
+ ' of ' +
1530
+ a.total +
1531
+ ', ' +
1532
+ a.anchor.kind +
1533
+ ' point. Enter to cycle type, arrow keys to nudge, Shift+arrow for 10 units.'
1534
+ "
1535
+ [attr.x]="a.anchor.point.x - pointHalf()"
1536
+ [attr.y]="a.anchor.point.y - pointHalf()"
1537
+ [attr.width]="pointSize()"
1538
+ [attr.height]="pointSize()"
1539
+ (pointerdown)="onPointerDown($event, a.ref, 'point')"
1540
+ (pointermove)="onPointerMove($event)"
1541
+ (pointerup)="onPointerUp($event)"
1542
+ (dblclick)="onDoubleClick($event, a.ref)"
1543
+ (keydown)="onKeyDown($event, a.ref, 'point')"
1544
+ />
1545
+ }
1546
+ }
1547
+ `,isInline:!0,styles:[`.anchor-point{fill:#fff;stroke:#1976d2;stroke-width:1;vector-effect:non-scaling-stroke;cursor:move;touch-action:none;outline:none}.anchor-point.selected{fill:#ff6f00;stroke:#ff6f00}.anchor-point:focus-visible{stroke:#ff6f00;stroke-width:2;filter:drop-shadow(0 0 2px rgba(255,111,0,.6))}.handle-knob{fill:#1976d2;stroke:#fff;stroke-width:1;vector-effect:non-scaling-stroke;cursor:move;touch-action:none;outline:none}.handle-knob:focus-visible{stroke:#ff6f00;stroke-width:2;filter:drop-shadow(0 0 2px rgba(255,111,0,.6))}.handle-stem{stroke:#90caf9;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.segment-hit{stroke:transparent;fill:none;cursor:crosshair;touch-action:none}
1548
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:cr,decorators:[{type:W,args:[{selector:"g[svgeAnchorOverlay]",standalone:!0,host:{role:"application","aria-label":"Path anchor editor \u2014 use arrow keys to nudge selected anchor or handle, Enter to cycle anchor type, Delete to remove anchor"},template:`
1549
+ @if (anchors(); as anchors) {
1550
+ <!--
1551
+ Handle stems first (rendered behind squares so a drag on the
1552
+ square wins hit-testing). Each stem is two short lines from
1553
+ the anchor point to its in/out tangent control. Decorative \u2014
1554
+ aria-hidden so SR users don't hear "graphic" noise for every
1555
+ tangent line.
1556
+ -->
1557
+ @for (a of anchors; track a.key) {
1558
+ @if (a.hasHandleIn) {
1559
+ <svg:line
1560
+ class="handle-stem"
1561
+ aria-hidden="true"
1562
+ [attr.x1]="a.anchor.point.x"
1563
+ [attr.y1]="a.anchor.point.y"
1564
+ [attr.x2]="a.anchor.handleIn.x"
1565
+ [attr.y2]="a.anchor.handleIn.y"
1566
+ />
1567
+ }
1568
+ @if (a.hasHandleOut) {
1569
+ <svg:line
1570
+ class="handle-stem"
1571
+ aria-hidden="true"
1572
+ [attr.x1]="a.anchor.point.x"
1573
+ [attr.y1]="a.anchor.point.y"
1574
+ [attr.x2]="a.anchor.handleOut.x"
1575
+ [attr.y2]="a.anchor.handleOut.y"
1576
+ />
1577
+ }
1578
+ }
1579
+
1580
+ <!-- Handle circles (interactive \u2014 tangent control points). -->
1581
+ @for (a of anchors; track a.key) {
1582
+ @if (a.hasHandleIn) {
1583
+ <svg:circle
1584
+ class="handle-knob"
1585
+ role="button"
1586
+ tabindex="0"
1587
+ focusable="true"
1588
+ [attr.aria-label]="
1589
+ 'Incoming tangent handle, anchor ' + (a.index + 1) + ' of ' + a.total
1590
+ "
1591
+ [attr.cx]="a.anchor.handleIn.x"
1592
+ [attr.cy]="a.anchor.handleIn.y"
1593
+ [attr.r]="handleHalf()"
1594
+ (pointerdown)="onPointerDown($event, a.ref, 'handleIn')"
1595
+ (pointermove)="onPointerMove($event)"
1596
+ (pointerup)="onPointerUp($event)"
1597
+ (keydown)="onKeyDown($event, a.ref, 'handleIn')"
1598
+ />
1599
+ }
1600
+ @if (a.hasHandleOut) {
1601
+ <svg:circle
1602
+ class="handle-knob"
1603
+ role="button"
1604
+ tabindex="0"
1605
+ focusable="true"
1606
+ [attr.aria-label]="
1607
+ 'Outgoing tangent handle, anchor ' + (a.index + 1) + ' of ' + a.total
1608
+ "
1609
+ [attr.cx]="a.anchor.handleOut.x"
1610
+ [attr.cy]="a.anchor.handleOut.y"
1611
+ [attr.r]="handleHalf()"
1612
+ (pointerdown)="onPointerDown($event, a.ref, 'handleOut')"
1613
+ (pointermove)="onPointerMove($event)"
1614
+ (pointerup)="onPointerUp($event)"
1615
+ (keydown)="onKeyDown($event, a.ref, 'handleOut')"
1616
+ />
1617
+ }
1618
+ }
1619
+
1620
+ <!--
1621
+ Invisible segment hit-zones for inserting anchors. Renders BELOW
1622
+ the anchor squares so a click on the anchor itself wins.
1623
+ 'stroke: transparent' + 'stroke-width' ~10px (in CSS px via
1624
+ 1/zoom) makes the target generous enough to hit without a precise
1625
+ stylus.
1626
+
1627
+ Gestures (see handlers):
1628
+ - **Double-click** \u2192 insert a new anchor AT THE CLICK LOCATION
1629
+ (projected onto the curve; market convention \u2014 Inkscape /
1630
+ Affinity / Figma). Primary gesture.
1631
+ - **Alt+click** \u2192 insert at the segment midpoint (t=0.5). Kept
1632
+ for back-compat with the original D-038 gesture.
1633
+ A plain single click is swallowed (stopPropagation) so it neither
1634
+ deselects the path nor starts a marquee from the curve \u2014 and so
1635
+ the overlay survives until the dblclick fires.
1636
+
1637
+ aria-hidden because click-on-curve has no comparable keyboard
1638
+ surface (continuous along the curve); the keyboard alternative is
1639
+ to focus an anchor and use Enter to cycle kind / arrow keys.
1640
+ -->
1641
+ @for (seg of segments(); track seg.key) {
1642
+ <svg:path
1643
+ class="segment-hit"
1644
+ aria-hidden="true"
1645
+ [attr.d]="seg.d"
1646
+ [attr.stroke-width]="hitZoneSize()"
1647
+ (pointerdown)="onSegmentPointerDown($event, seg.ref)"
1648
+ (dblclick)="onSegmentDoubleClick($event, seg)"
1649
+ />
1650
+ }
1651
+
1652
+ <!-- Anchor squares (interactive, on top). -->
1653
+ @for (a of anchors; track a.key) {
1654
+ <svg:rect
1655
+ class="anchor-point"
1656
+ role="button"
1657
+ tabindex="0"
1658
+ focusable="true"
1659
+ [class.selected]="a.isSelected"
1660
+ [attr.aria-pressed]="a.isSelected ? 'true' : 'false'"
1661
+ [attr.aria-label]="
1662
+ 'Anchor ' +
1663
+ (a.index + 1) +
1664
+ ' of ' +
1665
+ a.total +
1666
+ ', ' +
1667
+ a.anchor.kind +
1668
+ ' point. Enter to cycle type, arrow keys to nudge, Shift+arrow for 10 units.'
1669
+ "
1670
+ [attr.x]="a.anchor.point.x - pointHalf()"
1671
+ [attr.y]="a.anchor.point.y - pointHalf()"
1672
+ [attr.width]="pointSize()"
1673
+ [attr.height]="pointSize()"
1674
+ (pointerdown)="onPointerDown($event, a.ref, 'point')"
1675
+ (pointermove)="onPointerMove($event)"
1676
+ (pointerup)="onPointerUp($event)"
1677
+ (dblclick)="onDoubleClick($event, a.ref)"
1678
+ (keydown)="onKeyDown($event, a.ref, 'point')"
1679
+ />
1680
+ }
1681
+ }
1682
+ `,changeDetection:U.OnPush,styles:[`.anchor-point{fill:#fff;stroke:#1976d2;stroke-width:1;vector-effect:non-scaling-stroke;cursor:move;touch-action:none;outline:none}.anchor-point.selected{fill:#ff6f00;stroke:#ff6f00}.anchor-point:focus-visible{stroke:#ff6f00;stroke-width:2;filter:drop-shadow(0 0 2px rgba(255,111,0,.6))}.handle-knob{fill:#1976d2;stroke:#fff;stroke-width:1;vector-effect:non-scaling-stroke;cursor:move;touch-action:none;outline:none}.handle-knob:focus-visible{stroke:#ff6f00;stroke-width:2;filter:drop-shadow(0 0 2px rgba(255,111,0,.6))}.handle-stem{stroke:#90caf9;stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}.segment-hit{stroke:transparent;fill:none;cursor:crosshair;touch-action:none}
1683
+ `]}]}]});function Jt(r,e,t=1e-6){return Math.abs(r.x-e.x)<t&&Math.abs(r.y-e.y)<t}function Qt(r,e){if(r.id===e)return r;if(r.type==="group")for(const t of r.children){const n=Qt(t,e);if(n!==null)return n}return null}function nl(r,e,t){function n(o){if(o.id===e&&o.type==="path")return{...o,d:t};if(o.type==="group"){let i=!1;const a=o.children.map(l=>{const c=n(l);return c!==l&&(i=!0),c});if(i)return{...o,children:a}}return o}return n(r)}function Yp(r,e,t){if(t==="point"){const c=e.x-r.point.x,u=e.y-r.point.y;return{...r,point:e,handleIn:{x:r.handleIn.x+c,y:r.handleIn.y+u},handleOut:{x:r.handleOut.x+c,y:r.handleOut.y+u}}}if(t==="handleIn"){if(r.kind==="cusp")return{...r,handleIn:e};const c=e.x-r.point.x,u=e.y-r.point.y,h=Math.hypot(c,u);let g=-c,v=-u;if(r.kind==="smooth"&&h>1e-6){const x=Math.hypot(r.handleOut.x-r.point.x,r.handleOut.y-r.point.y)/h;g=-c*x,v=-u*x}return{...r,handleIn:e,handleOut:{x:r.point.x+g,y:r.point.y+v}}}if(r.kind==="cusp")return{...r,handleOut:e};const n=e.x-r.point.x,o=e.y-r.point.y,i=Math.hypot(n,o);let a=-n,l=-o;if(r.kind==="smooth"&&i>1e-6){const u=Math.hypot(r.handleIn.x-r.point.x,r.handleIn.y-r.point.y)/i;a=-n*u,l=-o*u}return{...r,handleOut:e,handleIn:{x:r.point.x+a,y:r.point.y+l}}}function qp(r){return Zp(r)}function Zp(r){const e=[];for(const t of r){if(t.anchors.length===0)continue;const n=t.anchors[0];e.push(`M${Y(n.point.x)} ${Y(n.point.y)}`);for(let o=1;o<t.anchors.length;o++){const i=t.anchors[o-1],a=t.anchors[o];e.push(rl(i,a))}if(t.closed){const o=t.anchors[0],i=t.anchors[t.anchors.length-1];Jt(i.handleOut,i.point)&&Jt(o.handleIn,o.point)||e.push(rl(i,o)),e.push("Z")}}return e.join(" ")}function rl(r,e){const t=Jt(r.handleOut,r.point),n=Jt(e.handleIn,e.point);return t&&n?`L${Y(e.point.x)} ${Y(e.point.y)}`:`C${Y(r.handleOut.x)} ${Y(r.handleOut.y)} ${Y(e.handleIn.x)} ${Y(e.handleIn.y)} ${Y(e.point.x)} ${Y(e.point.y)}`}function Y(r){return Number.isInteger(r)?`${r}`:Number(r.toFixed(4)).toString()}function He(r,e){const t=K(r,e.x,e.y);return{x:t.x,y:t.y}}function Jp(r){return Gt(r)}const qo=new gt("AUTOSAVE_STORAGE_KEY",{providedIn:"root",factory:()=>"svge:autosave"}),Qp=2e3,ol=4*1024*1024;class mn{state=f(S);document=f(re);storageKey=f(qo);debounceHandle=null;constructor(){J(()=>{this.state.document(),this.scheduleSave()})}snapshotNow(){if(!this.hasStorage())return;const e=this.keys();if(e===null)return;const t=this.state.document();let n;try{const o=vt.export(t);n=typeof o=="string"?o:""}catch(o){console.warn("AutoSaveService: serialization failed \u2014",o);return}if(n.length!==0){if(n.length>ol){console.warn(`AutoSaveService: payload (${n.length} B) exceeds limit (${ol} B) \u2014 skipping save.`);return}try{const o=this.window();if(o===null)return;o.localStorage.setItem(e.storage,n),o.localStorage.setItem(e.timestamp,new Date().toISOString())}catch(o){console.warn("AutoSaveService: localStorage write failed \u2014",o)}}}readRecovery(){if(!this.hasStorage())return null;const e=this.keys();if(e===null)return null;const t=this.window();if(t===null)return null;const n=t.localStorage.getItem(e.storage);if(n===null||n.length===0)return null;const o=t.localStorage.getItem(e.timestamp),i=o!==null?new Date(o):new Date(0);return Number.isFinite(i.getTime())?{svg:n,savedAt:i}:{svg:n,savedAt:new Date(0)}}clearRecovery(){if(!this.hasStorage())return;const e=this.keys();if(e===null)return;const t=this.window();t!==null&&(t.localStorage.removeItem(e.storage),t.localStorage.removeItem(e.timestamp))}scheduleSave(){this.hasStorage()&&this.keys()!==null&&(this.debounceHandle!==null&&clearTimeout(this.debounceHandle),this.debounceHandle=setTimeout(()=>{this.debounceHandle=null,this.snapshotNow()},Qp))}keys(){const e=this.storageKey;return e===null||e.length===0?null:{storage:e,timestamp:`${e}:ts`}}window(){const e=this.document.defaultView;return e!==null?e:typeof window<"u"?window:null}hasStorage(){const e=this.window();if(e===null)return!1;try{return typeof e.localStorage<"u"}catch{return!1}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:mn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:mn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:mn,decorators:[{type:D,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});const Zo="svge:snapshots",Jo=1,ef=1500,Qo=4*1024*1024;class vn{snapshots=f(Ze);document=f(re);debounceHandle=null;constructor(){J(()=>{this.snapshots.snapshots(),this.snapshots.limits(),this.scheduleSave()})}saveNow(){if(!this.hasStorage())return;let e;try{const t=this.serialize();e=JSON.stringify(t)}catch(t){console.warn("SnapshotsPersistenceService: serialization failed \u2014",t);return}if(e.length>Qo)try{const t=JSON.stringify(this.serialize({dropThumbnails:!0}));if(t.length<=Qo)e=t;else{console.warn(`SnapshotsPersistenceService: payload (${e.length} B) exceeds limit (${Qo} B) even after stripping thumbnails \u2014 skipping save.`);return}}catch(t){console.warn("SnapshotsPersistenceService: thumbnail-stripped serialization failed \u2014",t);return}try{const t=this.window();if(t===null)return;t.localStorage.setItem(Zo,e)}catch(t){console.warn("SnapshotsPersistenceService: localStorage write failed \u2014",t)}}hydrate(){if(!this.hasStorage())return!1;const e=this.window();if(e===null)return!1;const t=e.localStorage.getItem(Zo);if(t===null||t.length===0)return!1;let n;try{n=JSON.parse(t)}catch(i){return console.warn("SnapshotsPersistenceService: malformed JSON in storage \u2014",i),!1}if(n.v!==Jo)return console.warn(`SnapshotsPersistenceService: unknown schema version ${n.v} (expected ${Jo}) \u2014 ignoring.`),!1;const o=[];for(const i of n.snapshots){const a=ze.import(i.svg);if(!a.ok){console.warn(`SnapshotsPersistenceService: snapshot "${i.name}" failed to import (${a.error}) \u2014 skipping.`);continue}o.push({id:i.id,name:i.name,createdAt:i.createdAt,document:a.document,thumbnail:i.thumbnail,source:i.source})}return n.limits!==void 0&&n.limits!==null&&this.snapshots.setLimits(n.limits),this.snapshots.hydrate(o),!0}clearStorage(){if(!this.hasStorage())return;const e=this.window();e!==null&&e.localStorage.removeItem(Zo)}scheduleSave(){this.hasStorage()&&(this.debounceHandle!==null&&clearTimeout(this.debounceHandle),this.debounceHandle=setTimeout(()=>{this.debounceHandle=null,this.saveNow()},ef))}serialize(e={}){const t=e.dropThumbnails===!0,n=[];for(const o of this.snapshots.snapshots()){const i=vt.export(o.document),a=typeof i=="string"?i:"";a.length!==0&&n.push({id:o.id,name:o.name,createdAt:o.createdAt,svg:a,thumbnail:t?null:o.thumbnail,source:o.source})}return{v:Jo,limits:this.snapshots.limits()??Wu,snapshots:n}}window(){const e=this.document.defaultView;return e!==null?e:typeof window<"u"?window:null}hasStorage(){const e=this.window();if(e===null)return!1;try{return typeof e.localStorage<"u"}catch{return!1}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:vn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:vn})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:vn,decorators:[{type:D}],ctorParameters:()=>[]});const ei=1e3/60;class yn{anim=f(at,{optional:!0});document=f(re);destroyRef=f(Hr);_playhead=b(0,...ngDevMode?[{debugName:"_playhead"}]:[]);_isPlaying=b(!1,...ngDevMode?[{debugName:"_isPlaying"}]:[]);_loop=b(!1,...ngDevMode?[{debugName:"_loop"}]:[]);_speed=b(1,...ngDevMode?[{debugName:"_speed"}]:[]);_fallbackDurationMs=b(1e3,...ngDevMode?[{debugName:"_fallbackDurationMs"}]:[]);playhead=this._playhead.asReadonly();isPlaying=this._isPlaying.asReadonly();loop=this._loop.asReadonly();speed=this._speed.asReadonly();durationMs=m(()=>this.anim?.durationMs()??this._fallbackDurationMs(),...ngDevMode?[{debugName:"durationMs"}]:[]);rafId=null;lastTs=0;constructor(){this.destroyRef.onDestroy(()=>this.pause())}play(){if(this._isPlaying())return;this._playhead()>=this.durationMs()&&this._playhead.set(0),this._isPlaying.set(!0),this.lastTs=0;const e=t=>{if(!this._isPlaying())return;this.lastTs===0&&(this.lastTs=t);const n=t-this.lastTs;this.lastTs=t,this.advance(n),this._isPlaying()&&(this.rafId=this.schedule(e))};this.rafId=this.schedule(e)}pause(){this._isPlaying.set(!1),this.rafId!==null&&this.cancel(this.rafId),this.rafId=null,this.lastTs=0}toggle(){this._isPlaying()?this.pause():this.play()}seek(e){this._playhead.set(this.clamp(e))}step(e){this.seek(this._playhead()+e)}stepForward(e=ei){this.step(Math.abs(e))}stepBackward(e=ei){this.step(-Math.abs(e))}goToStart(){this.seek(0)}goToEnd(){this.seek(this.durationMs())}setLoop(e){this._loop.set(e)}setSpeed(e){this._speed.set(e>0?e:1)}setFallbackDuration(e){this._fallbackDurationMs.set(e<0?0:e)}tick(e){this.advance(e)}advance(e){const t=this.durationMs(),n=this._playhead()+e*this._speed();if(n>=t){this._loop()&&t>0?this._playhead.set(n%t):(this._playhead.set(t),this.pause());return}this._playhead.set(n<0?0:n)}clamp(e){const t=this.durationMs();return e<0?0:e>t?t:e}schedule(e){const t=this.window();return t===null||typeof t.requestAnimationFrame!="function"?null:t.requestAnimationFrame(e)}cancel(e){const t=this.window();t!==null&&typeof t.cancelAnimationFrame=="function"&&t.cancelAnimationFrame(e)}window(){const e=this.document.defaultView;return e!==null?e:typeof window<"u"?window:null}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:yn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:yn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:yn,decorators:[{type:D,args:[{providedIn:"root"}]}],ctorParameters:()=>[]});const il=new gt("ASSET_EXPORT_STORAGE_KEY",{providedIn:"root",factory:()=>"svge:assetExport"});class ut{_slots=b([],...ngDevMode?[{debugName:"_slots"}]:[]);slots=this._slots.asReadonly();count=m(()=>this._slots().length,...ngDevMode?[{debugName:"count"}]:[]);add(e){if(typeof e.exporterId!="string"||e.exporterId.length===0)return null;const t={id:e.id??tf(),target:e.target,exporterId:e.exporterId,scale:Number.isFinite(e.scale)&&e.scale>0?e.scale:1,filename:e.filename};return this._slots.set([...this._slots(),t]),t}update(e,t){const n=this._slots(),o=n.findIndex(a=>a.id===e);if(o<0)return!1;const i=n.slice();return i[o]={...n[o],...t},this._slots.set(i),!0}remove(e){const t=this._slots().filter(n=>n.id!==e);t.length!==this._slots().length&&this._slots.set(t)}clear(){this._slots().length!==0&&this._slots.set([])}setAll(e){const t=new Set;for(const n of e){if(t.has(n.id))return;t.add(n.id)}this._slots.set(e.slice())}resolveUniqueName(e,t,n){const o=nf(e),i=t.startsWith(".")?t:`.${t}`,a=`${o}${i}`;if(!sl(n,a))return a;for(let l=1;l<1e3;l++){const c=`${o} (${l})${i}`;if(!sl(n,c))return c}return`${o}-${Date.now()}${i}`}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ut,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ut,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ut,decorators:[{type:D,args:[{providedIn:"root"}]}]});function tf(){return`slot-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`}function nf(r){const e=(r??"").trim();return e.length===0?"untitled":e}function sl(r,e){const t=e.toLowerCase();for(const n of r)if(n.toLowerCase()===t)return!0;return!1}const ti=1,rf=500;class bn{registry=f(ut);document=f(re);storageKey=f(il);debounceHandle=null;constructor(){this.hydrate(),J(()=>{this.registry.slots(),this.scheduleSave()})}saveNow(){if(!this.hasStorage())return;const e=this.window();if(e===null)return;const t=this.storageKey;if(t===null||t.length===0)return;let n;try{const o={v:ti,slots:this.registry.slots()};n=JSON.stringify(o)}catch(o){console.warn("AssetExportPersistenceService: serialization failed \u2014",o);return}try{e.localStorage.setItem(t,n)}catch(o){console.warn("AssetExportPersistenceService: localStorage write failed \u2014",o)}}hydrate(){if(!this.hasStorage())return!1;const e=this.window();if(e===null)return!1;const t=this.storageKey;if(t===null||t.length===0)return!1;const n=e.localStorage.getItem(t);if(n===null||n.length===0)return!1;let o;try{o=JSON.parse(n)}catch(a){return console.warn("AssetExportPersistenceService: malformed JSON in storage \u2014",a),!1}if(o.v!==ti)return console.warn(`AssetExportPersistenceService: unknown schema version ${o.v} (expected ${ti}) \u2014 ignoring.`),!1;if(!Array.isArray(o.slots))return console.warn("AssetExportPersistenceService: payload.slots is not an array \u2014 ignoring."),!1;const i=[];for(const a of o.slots)typeof a.id=="string"&&a.id.length>0&&typeof a.exporterId=="string"&&a.exporterId.length>0&&typeof a.scale=="number"&&Number.isFinite(a.scale)&&a.scale>0&&typeof a.filename=="string"&&(a.target==="document"||typeof a.target=="object"&&a.target!==null&&"nodeId"in a.target)&&i.push(a);return this.registry.setAll(i),!0}clearStorage(){if(!this.hasStorage())return;const e=this.window();if(e===null)return;const t=this.storageKey;t===null||t.length===0||e.localStorage.removeItem(t)}scheduleSave(){this.hasStorage()&&(this.debounceHandle!==null&&clearTimeout(this.debounceHandle),this.debounceHandle=setTimeout(()=>{this.debounceHandle=null,this.saveNow()},rf))}window(){const e=this.document.defaultView;return e!==null?e:typeof window<"u"?window:null}hasStorage(){const e=this.window();if(e===null)return!1;try{return typeof e.localStorage<"u"}catch{return!1}}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:bn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:bn})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:bn,decorators:[{type:D}],ctorParameters:()=>[]});class wn{state=f(S);exporters=f(no);registry=f(ut);document=f(re);activePage=f(j);activeDefs=f(Le);async exportSlot(e,t){const n=this.exporters.get(e.exporterId);if(n===null)return{ok:!1,slotId:e.id,error:`Exporter "${e.exporterId}" not registered`};const o=this.state.document(),i={...o,defs:this.activeDefs.buildExportDefs(o.defs)},a=this.activePage.effectiveExportDoc(i),l=this.registry.resolveUniqueName(e.filename,n.extension,t);let c;try{if(n.extension==="png"&&e.scale!==2)c=await to(a,e.scale);else{const u=n.export(a);c=await Promise.resolve(u)}}catch(u){return{ok:!1,slotId:e.id,error:al(u)}}try{this.download(c,l,n.mediaType)}catch(u){return{ok:!1,slotId:e.id,error:al(u)}}return t.add(l),{ok:!0,slotId:e.id,filename:l}}async exportAll(){const e=this.registry.slots(),t=new Set,n=[];for(const o of e)n.push(await this.exportSlot(o,t));return n}download(e,t,n){if(typeof URL>"u"||typeof this.document>"u")return;const o=e instanceof Blob?e:new Blob([e],{type:n}),i=URL.createObjectURL(o),a=this.document.createElement("a");a.href=i,a.download=t,this.document.body.appendChild(a),a.click(),a.remove(),setTimeout(()=>URL.revokeObjectURL(i),1e3)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:wn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:wn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:wn,decorators:[{type:D,args:[{providedIn:"root"}]}]});function al(r){return r instanceof Error?r.message:String(r)}class In{state=f(S);bus=f(M);_catalog=b([],...ngDevMode?[{debugName:"_catalog"}]:[]);catalog=this._catalog.asReadonly();hasAssets=m(()=>this._catalog().length>0,...ngDevMode?[{debugName:"hasAssets"}]:[]);add(e){if(this._catalog().some(t=>t.id===e.id))throw new Error(`AssetManagerService.add: duplicate asset id "${e.id}"`);this._catalog.set([...this._catalog(),e])}remove(e){this._catalog.set(this._catalog().filter(t=>t.id!==e))}async addFromFile(e,t=5*1024*1024){if(e.size>t)return null;const n=await of(e);if(n===null)return null;const o={id:`asset.${Date.now()}.${sf(e.name)}`,name:e.name,href:n};return this.add(o),o}insertIntoDocument(e,t={}){const n=t.width??e.width??200,o=t.height??e.height??200,i=wr({x:t.x??50,y:t.y??50,width:n,height:o,href:e.href});return this.bus.dispatch(new he(te,i)),i}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:In,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:In,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:In,decorators:[{type:D,args:[{providedIn:"root"}]}]});function of(r){return new Promise(e=>{const t=new FileReader;t.onload=()=>{const n=t.result;e(typeof n=="string"?n:null)},t.onerror=()=>e(null),t.readAsDataURL(r)})}function sf(r){return r.toLowerCase().replace(/\.[^.]+$/,"").replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)/g,"").slice(0,40)}class Bt{selection=f(k);state=f(S);catalog=f(Ne);_selectedStop=b(null,...ngDevMode?[{debugName:"_selectedStop"}]:[]);activeGradientId=m(()=>{const e=Array.from(this.selection.selectedIds());if(e.length!==1)return null;const t=T(this.state.document().root,e[0]);if(t===null)return null;const n=ll(t.style.fill),o=ll(t.style.stroke),i=n??o;return i===null?null:this.catalog.get(i)!==null?i:null},...ngDevMode?[{debugName:"activeGradientId"}]:[]);targetNodeId=m(()=>{if(this.activeGradientId()===null)return null;const e=Array.from(this.selection.selectedIds());return e.length===1?e[0]:null},...ngDevMode?[{debugName:"targetNodeId"}]:[]);selectedStopIndex=this._selectedStop.asReadonly();selectStop(e){this._selectedStop.set(e)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Bt,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Bt,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Bt,decorators:[{type:D,args:[{providedIn:"root"}]}]});function ll(r){if(r===void 0)return null;const e=/^url\(\s*['"]?#([^'"\s)]+)['"]?\s*\)$/.exec(r.trim());return e===null?null:e[1]}class kn{_count=b(0,...ngDevMode?[{debugName:"_count"}]:[]);count=this._count.asReadonly();running=m(()=>this._count()>0,...ngDevMode?[{debugName:"running"}]:[]);start(){this._count.update(e=>e+1)}stop(){this._count.update(e=>Math.max(0,e-1))}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:kn,deps:[],target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:kn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:kn,decorators:[{type:D,args:[{providedIn:"root"}]}]});function af(r){const e=r!==void 0&&"autoSaveKey"in r?[{provide:qo,useValue:r.autoSaveKey??null}]:[],t=r!==void 0&&"activePageStorageKey"in r?[{provide:yo,useValue:r.activePageStorageKey??null}]:[];return[...e,...t,S,M,Wt,Ze,vn,A,k,it,ne,L,Lt,ue,Ue,nt,rt,be,mn,_e,dt,We,j,{provide:Ku,useExisting:j},ut,wn,bn,Se,Ce,ie,se,ot,Ee,Oe,$t,_t,At,In,gn,fn,Bt,Le,hn,pn,on,Dt,Xe,Pe,kn,Ye,at,yn]}class xn extends Ae{static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:xn,deps:null,target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:xn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:xn,decorators:[{type:D,args:[{providedIn:"root"}]}]});const z={fill:"#90caf9",stroke:"#1565c0",strokeWidth:1},cl={id:"svge.builtin.shape.star",name:"Star",category:"symbols",build(){return N("M50 2 L60 38 L98 38 L67 60 L78 96 L50 74 L22 96 L33 60 L2 38 L40 38 Z",{style:{...z}})}},dl={id:"svge.builtin.shape.arrow",name:"Arrow",category:"arrows",build(){return N("M10 35 L60 35 L60 15 L95 50 L60 85 L60 65 L10 65 Z",{style:{...z}})}},ul={id:"svge.builtin.shape.heart",name:"Heart",category:"symbols",build(){return N("M50 88 C20 70 8 50 8 32 C8 18 18 8 30 8 C40 8 47 14 50 22 C53 14 60 8 70 8 C82 8 92 18 92 32 C92 50 80 70 50 88 Z",{style:{...z}})}},hl={id:"svge.builtin.shape.balloon",name:"Speech balloon",category:"callouts",build(){return N("M15 8 L85 8 C90 8 92 10 92 15 L92 60 C92 65 90 67 85 67 L40 67 L25 92 L28 67 L15 67 C10 67 8 65 8 60 L8 15 C8 10 10 8 15 8 Z",{style:{...z}})}},gl={id:"svge.builtin.shape.lightning",name:"Lightning",category:"symbols",build(){return N("M55 2 L20 52 L42 52 L30 98 L78 40 L52 40 L70 2 Z",{style:{...z}})}},pl={id:"svge.builtin.shape.cloud",name:"Cloud",category:"symbols",build(){return N("M22 70 C8 70 2 62 2 52 C2 42 10 35 22 35 C22 22 32 12 46 12 C58 12 68 20 70 32 C82 32 92 42 92 54 C92 66 80 70 70 70 Z",{style:{...z}})}},fl={id:"svge.builtin.shape.gear",name:"Gear",category:"symbols",build(){return N("M45 2 L55 2 L57 14 L70 18 L80 10 L86 20 L78 30 L82 42 L94 45 L94 55 L82 58 L78 70 L86 80 L80 86 L70 78 L57 82 L55 94 L45 94 L43 82 L30 78 L20 86 L14 80 L22 70 L18 58 L6 55 L6 45 L18 42 L22 30 L14 20 L20 10 L30 18 L43 14 Z",{style:{...z}})}},ml={id:"svge.builtin.shape.diamond",name:"Diamond",category:"geometric",build(){return N("M50 5 L95 50 L50 95 L5 50 Z",{style:{...z}})}},vl={id:"svge.builtin.shape.hexagon",name:"Hexagon",category:"geometric",build(){return N("M25 8 L75 8 L97 50 L75 92 L25 92 L3 50 Z",{style:{...z}})}},yl={id:"svge.builtin.shape.cross",name:"Plus",category:"geometric",build(){return N("M35 5 L65 5 L65 35 L95 35 L95 65 L65 65 L65 95 L35 95 L35 65 L5 65 L5 35 L35 35 Z",{style:{...z}})}},bl={id:"svge.builtin.shape.checkmark",name:"Checkmark",category:"symbols",build(){return N("M10 50 L20 40 L40 60 L80 20 L90 30 L40 80 Z",{style:{...z,fill:"#4caf50",stroke:"#2e7d32"}})}},wl={id:"svge.builtin.shape.triangle",name:"Triangle",category:"geometric",build(){return N("M50 5 L95 90 L5 90 Z",{style:{...z}})}},Il={id:"svge.builtin.shape.pentagon",name:"Pentagon",category:"geometric",build(){return N("M50 4 L94 36 L77 87 L23 87 L6 36 Z",{style:{...z}})}},kl={id:"svge.builtin.shape.octagon",name:"Octagon",category:"geometric",build(){return N("M30 4 L70 4 L96 30 L96 70 L70 96 L30 96 L4 70 L4 30 Z",{style:{...z}})}},xl={id:"svge.builtin.shape.parallelogram",name:"Parallelogram",category:"geometric",build(){return N("M25 20 L95 20 L75 80 L5 80 Z",{style:{...z}})}},Dl={id:"svge.builtin.shape.trapezoid",name:"Trapezoid",category:"geometric",build(){return N("M25 20 L75 20 L95 80 L5 80 Z",{style:{...z}})}},Sl={id:"svge.builtin.shape.right-triangle",name:"Right triangle",category:"geometric",build(){return N("M10 10 L10 90 L90 90 Z",{style:{...z}})}},Pl={id:"svge.builtin.shape.rounded-rect",name:"Rounded rectangle",category:"geometric",build(){return N("M22 20 L78 20 Q90 20 90 32 L90 68 Q90 80 78 80 L22 80 Q10 80 10 68 L10 32 Q10 20 22 20 Z",{style:{...z}})}},Ml={id:"svge.builtin.shape.double-arrow",name:"Double arrow",category:"arrows",build(){return N("M5 50 L25 30 L25 42 L75 42 L75 30 L95 50 L75 70 L75 58 L25 58 L25 70 Z",{style:{...z}})}},_l={id:"svge.builtin.shape.up-arrow",name:"Up arrow",category:"arrows",build(){return N("M50 5 L85 40 L65 40 L65 95 L35 95 L35 40 L15 40 Z",{style:{...z}})}},El={id:"svge.builtin.shape.chevron",name:"Chevron",category:"arrows",build(){return N("M20 15 L50 15 L80 50 L50 85 L20 85 L50 50 Z",{style:{...z}})}},Tl={id:"svge.builtin.shape.crescent-moon",name:"Crescent moon",category:"symbols",build(){return N("M50 5 A45 45 0 1 0 50 95 A35 45 0 1 1 50 5 Z",{style:{...z}})}},Rl={id:"svge.builtin.shape.sparkle",name:"Sparkle",category:"symbols",build(){return N("M50 5 L58 42 L95 50 L58 58 L50 95 L42 58 L5 50 L42 42 Z",{style:{...z}})}},Al={id:"svge.builtin.shape.hexagram",name:"Hexagram",category:"symbols",build(){return N("M50 4 L62 30 L90 27 L73 50 L90 73 L62 70 L50 96 L38 70 L10 73 L27 50 L10 27 L38 30 Z",{style:{...z}})}},Cl=[wl,ml,vl,yl,Il,kl,xl,Dl,Sl,Pl,dl,Ml,_l,El,hl,cl,ul,gl,pl,fl,bl,Tl,Rl,Al],Ol={id:"svge.builtin.shapes",version:"1.0.0",name:"Built-in shapes library (24 shapes: star, arrow, heart, etc.)",apiVersion:O,install(r){const e=r.injector.get(xn);for(const t of Cl)r.track(e.register(t))}},Nl={id:"svge.builtin.palettes.extra",version:"1.0.0",name:"Extra palettes library (IBM, warm, cool, neon)",apiVersion:O,install(r){const e=r.injector.get(Rt);r.track(e.register({id:"ibm-design",name:"IBM Design",category:"brand",swatches:["#0f62fe","#393939","#8a3ffc","#007d79","#fa4d56","#ff832b","#f1c21b","#198038","#161616"]})),r.track(e.register({id:"brand-warm",name:"Warm",category:"brand",swatches:["#b71c1c","#d32f2f","#e64a19","#f57c00","#fbc02d","#ffa000","#8d6e63","#5d4037"]})),r.track(e.register({id:"brand-cool",name:"Cool",category:"brand",swatches:["#0d47a1","#1976d2","#0097a7","#00796b","#388e3c","#7b1fa2","#512da8","#283593"]})),r.track(e.register({id:"neon",name:"Neon",category:"utility",swatches:["#ff006e","#fb5607","#ffbe0b","#8338ec","#3a86ff","#06ffa5","#ffffff","#000000"]}))}};class Dn extends Ae{static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Dn,deps:null,target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Dn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Dn,decorators:[{type:D,args:[{providedIn:"root"}]}]});const Ll={id:"svge.builtin.graphic-style.sketch",name:"Sketch",category:"flat",style:{fill:"#a5d6a7",stroke:"#2e7d32",strokeWidth:2,opacity:1,filter:void 0}},$l={id:"svge.builtin.graphic-style.neon",name:"Neon",category:"effects",style:{fill:"#ff006e",stroke:"#ffbe0b",strokeWidth:2,opacity:.95,filter:"url(#svge.builtin.effect.outer-glow)"}},Bl={id:"svge.builtin.graphic-style.glass",name:"Glass",category:"effects",style:{fill:"#ffffff",stroke:"#ffffff",strokeWidth:1,opacity:.45,filter:"url(#svge.builtin.effect.blur)"}},Fl={id:"svge.builtin.graphic-style.embossed",name:"Embossed",category:"effects",style:{fill:"#e0c9a6",stroke:"#a68a64",strokeWidth:1,opacity:1,filter:"url(#svge.builtin.effect.bevel)"}},jl={id:"svge.builtin.graphic-style.outline",name:"Outline",category:"outline",style:{fill:"none",stroke:"#212121",strokeWidth:3,opacity:1,filter:void 0}},Vl={id:"svge.builtin.graphic-style.filled-3d",name:"Filled 3D",category:"effects",style:{fill:"#2196f3",stroke:"#0d47a1",strokeWidth:1,opacity:1,filter:"url(#svge.builtin.effect.drop-shadow)"}},zl=[Ll,jl,Vl,Fl,Bl,$l],Gl={id:"svge.builtin.graphic-styles",version:"1.0.0",name:"Built-in graphic styles library (6 presets)",apiVersion:O,install(r){const e=r.injector.get(Dn);for(const t of zl)r.track(e.register(t))}};function jr(r,e,t="100%",n="0%"){return`<linearGradient id="${r}" x1="0%" y1="0%" x2="${t}" y2="${n}">
1684
+ ${e.map(Ul).join(`
1685
+ `)}
1686
+ </linearGradient>`}function Hl(r,e){return`<radialGradient id="${r}" cx="50%" cy="50%" r="50%">
1687
+ ${e.map(Ul).join(`
1688
+ `)}
1689
+ </radialGradient>`}function Ul(r){const e=r.opacity??1,t=e!==1?` stop-opacity="${e}"`:"";return`<stop offset="${(r.offset*100).toFixed(0)}%" stop-color="${r.color}"${t} />`}const Wl={id:"svge.builtin.gradient.linear-grey",name:"Grey (horizontal)",category:"linear",kind:"linear",stops:[{offset:0,color:"#f5f5f5"},{offset:1,color:"#424242"}],buildMarkup(){return jr(this.id,this.stops)}},Kl={id:"svge.builtin.gradient.linear-blue-sky",name:"Blue sky (vertical)",category:"linear",kind:"linear",stops:[{offset:0,color:"#90caf9"},{offset:1,color:"#0d47a1"}],buildMarkup(){return jr(this.id,this.stops,"0%","100%")}},Xl={id:"svge.builtin.gradient.linear-sunset",name:"Sunset",category:"linear",kind:"linear",stops:[{offset:0,color:"#fff176"},{offset:.5,color:"#ff8a65"},{offset:1,color:"#c2185b"}],buildMarkup(){return jr(this.id,this.stops)}},Yl={id:"svge.builtin.gradient.linear-ocean",name:"Ocean",category:"linear",kind:"linear",stops:[{offset:0,color:"#80deea"},{offset:.5,color:"#00897b"},{offset:1,color:"#1a237e"}],buildMarkup(){return jr(this.id,this.stops)}},ql={id:"svge.builtin.gradient.radial-spotlight",name:"Spotlight",category:"radial",kind:"radial",stops:[{offset:0,color:"#ffffff",opacity:1},{offset:1,color:"#ffffff",opacity:0}],buildMarkup(){return Hl(this.id,this.stops)}},Zl={id:"svge.builtin.gradient.radial-neon",name:"Neon glow",category:"radial",kind:"radial",stops:[{offset:0,color:"#ff4081"},{offset:.6,color:"#8e24aa"},{offset:1,color:"#311b92"}],buildMarkup(){return Hl(this.id,this.stops)}},Bn={x1:0,y1:0,x2:1,y2:0},Fn={x1:0,y1:0,x2:0,y2:1},jn={x1:0,y1:0,x2:1,y2:1};function oe(r,e,t,n){return{id:`svge.builtin.gradient.linear-${r}`,name:e,category:"linear",kind:"linear",geometry:t,stops:n,buildMarkup(){return jo(this)}}}const Jl=oe("sunrise","Sunrise (horizontal)",Bn,[{offset:0,color:"#ffd194"},{offset:1,color:"#d1913c"}]),Ql=oe("mint","Mint (horizontal)",Bn,[{offset:0,color:"#a8e6cf"},{offset:1,color:"#00897b"}]),ec=oe("grape","Grape (horizontal)",Bn,[{offset:0,color:"#c5a3ff"},{offset:1,color:"#4a148c"}]),tc=oe("ember","Ember (horizontal)",Bn,[{offset:0,color:"#ff5252"},{offset:.5,color:"#ff7043"},{offset:1,color:"#ffab40"}]),nc=oe("steel","Steel (horizontal)",Bn,[{offset:0,color:"#cfd8dc"},{offset:1,color:"#455a64"}]),rc=oe("dusk","Dusk (vertical)",Fn,[{offset:0,color:"#ff9e57"},{offset:.5,color:"#a64f9c"},{offset:1,color:"#1a237e"}]),oc=oe("forest","Forest (vertical)",Fn,[{offset:0,color:"#aed581"},{offset:1,color:"#1b5e20"}]),ic=oe("sky-fade","Sky fade (vertical)",Fn,[{offset:0,color:"#ffffff"},{offset:1,color:"#64b5f6"}]),sc=oe("rose","Rose (vertical)",Fn,[{offset:0,color:"#f8bbd0"},{offset:1,color:"#ad1457"}]),ac=oe("graphite","Graphite (vertical)",Fn,[{offset:0,color:"#9e9e9e"},{offset:1,color:"#212121"}]),lc=oe("aurora","Aurora (diagonal)",jn,[{offset:0,color:"#1de9b6"},{offset:1,color:"#6a1b9a"}]),cc=oe("peachy","Peachy (diagonal)",jn,[{offset:0,color:"#fff59d"},{offset:1,color:"#ec407a"}]),dc=oe("deep-sea","Deep sea (diagonal)",jn,[{offset:0,color:"#26c6da"},{offset:.5,color:"#1565c0"},{offset:1,color:"#0d1b4c"}]),uc=oe("lava","Lava (diagonal)",jn,[{offset:0,color:"#ffee58"},{offset:.5,color:"#f4511e"},{offset:1,color:"#b71c1c"}]),hc=oe("twilight","Twilight (diagonal)",jn,[{offset:0,color:"#3949ab"},{offset:1,color:"#d500f9"}]),gc=[Wl,Kl,Xl,Yl,ql,Zl,Jl,Ql,ec,tc,nc,rc,oc,ic,sc,ac,lc,cc,dc,uc,hc],pc={id:"svge.builtin.gradients",version:"1.0.0",name:"Built-in gradients library (linear + radial, 6 presets)",apiVersion:O,install(r){const e=r.injector.get(Ne);for(const t of gc)r.track(e.register(t))}};class Vn{gradientId;patch;registry;id=Ht();label="Edit gradient";previousItem=null;constructor(e,t,n){this.gradientId=e,this.patch=t,this.registry=n}static for(e,t,n){return new Vn(t,n,e.get(Ne))}execute(){const e=this.registry.get(this.gradientId);if(e===null)return le(`${this.label}: gradient "${this.gradientId}" not found`);this.previousItem=e;const t={...e,...this.patch,buildMarkup(){return jo(this)}};return this.registry.update(this.gradientId,t)?Re():le(`${this.label}: update failed for "${this.gradientId}"`)}undo(){return this.previousItem===null?le(`${this.label} undo: nothing captured`):this.registry.update(this.gradientId,this.previousItem)?Re():le(`${this.label} undo: gradient "${this.gradientId}" no longer in registry`)}}const lf=7,cf=3;class dr{elRef=f(ae);editing=f(Bt);catalog=f(Ne);state=f(S);viewport=f(A);bus=f(M);layers=f(ne);injector=f(Vt);_bbox=b(null,...ngDevMode?[{debugName:"_bbox"}]:[]);dragState=null;selectedIndex=this.editing.selectedStopIndex;stopRadius=m(()=>lf/this.viewport.zoom(),...ngDevMode?[{debugName:"stopRadius"}]:[]);geometry=m(()=>{const e=this.editing.activeGradientId();if(e===null)return null;const t=this.editing.targetNodeId();if(t===null||this.layers.hiddenIds().has(t))return null;const n=T(this.state.document().root,t);if(n!==null&&n.metadata.visible===!1)return null;const o=this._bbox();if(o===null)return null;const i=this.catalog.get(e);return i===null?null:df(i,o)},...ngDevMode?[{debugName:"geometry"}]:[]);stopDots=m(()=>{const e=this.geometry();if(e===null)return[];const t=this.editing.activeGradientId();if(t===null)return[];const n=this.catalog.get(t);return n===null?[]:n.stops.map((o,i)=>{const a=uf(e,o.offset);return{index:i,x:a.x,y:a.y,color:o.color,offsetPct:Math.round(o.offset*100)}})},...ngDevMode?[{debugName:"stopDots"}]:[]);constructor(){pr({read:()=>this.measure()})}measure(){const e=this.editing.targetNodeId();if(e===null){this._bbox()!==null&&this._bbox.set(null);return}const t=this.elRef.nativeElement.ownerSVGElement;if(t===null)return;const n=ke(t,e),o=this._bbox();if(n===null){o!==null&&this._bbox.set(null);return}(o===null||o.x!==n.x||o.y!==n.y||o.width!==n.width||o.height!==n.height)&&this._bbox.set(n)}onStopPointerDown(e,t){const n=this.editing.activeGradientId();if(n===null)return;const o=this.catalog.get(n);o!==null&&(this.dragState={pointerId:e.pointerId,stopIndex:t,startScreenX:e.clientX,startScreenY:e.clientY,stopsBefore:o.stops,moved:!1},H(e),e.stopPropagation())}onStopPointerMove(e){if(this.dragState===null||e.pointerId!==this.dragState.pointerId)return;const t=e.clientX-this.dragState.startScreenX,n=e.clientY-this.dragState.startScreenY;if(!this.dragState.moved&&Math.hypot(t,n)>=cf&&(this.dragState={...this.dragState,moved:!0}),!this.dragState.moved)return;const o=this.geometry();if(o===null)return;const i=this.screenToDoc(e.clientX,e.clientY);if(i===null)return;const a=fc(o,i),l=Math.max(0,Math.min(1,a)),c=this.editing.activeGradientId();if(c===null)return;const u=this.catalog.get(c);if(u===null)return;const h=u.stops.map((g,v)=>v===this.dragState.stopIndex?{...g,offset:l}:g);this.catalog.update(c,{...u,stops:h})}onStopPointerUp(e){if(this.dragState===null||e.pointerId!==this.dragState.pointerId)return;const t=this.dragState.moved,n=this.dragState.stopIndex,o=this.dragState.stopsBefore;if(this.dragState=null,pe(e),t){const i=this.editing.activeGradientId();if(i===null)return;const a=this.catalog.get(i);if(a===null)return;this.catalog.update(i,{...a,stops:o}),this.bus.dispatch(Vn.for(this.injector,i,{stops:a.stops}))}else this.editing.selectStop(n)}onAxisPointerDown(e){const t=this.editing.activeGradientId();if(t===null)return;const n=this.catalog.get(t);if(n===null)return;const o=this.geometry();if(o===null)return;const i=this.screenToDoc(e.clientX,e.clientY);if(i===null)return;const a=Math.max(0,Math.min(1,fc(o,i))),l=hf(n.stops,a),c=gf(n.stops,{offset:a,color:l}),u=c.findIndex(h=>h===c.find(g=>g.offset===a));this.bus.dispatch(Vn.for(this.injector,t,{stops:c})),this.editing.selectStop(u),e.stopPropagation()}screenToDoc(e,t){const n=this.elRef.nativeElement.ownerSVGElement;return n===null?null:Ve(n,e,t)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:dr,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:dr,isStandalone:!0,selector:"g[svgeGradientOverlay]",ngImport:s,template:`
1690
+ @if (geometry(); as g) {
1691
+ <!-- Direction line (linear) or radius circle (radial). The
1692
+ dashed style signals "guide, not content"; pointer-events
1693
+ on the line catch click-to-insert-stop. -->
1694
+ @if (g.kind === 'linear') {
1695
+ <svg:line
1696
+ class="gradient-axis"
1697
+ [attr.x1]="g.startX"
1698
+ [attr.y1]="g.startY"
1699
+ [attr.x2]="g.endX"
1700
+ [attr.y2]="g.endY"
1701
+ (pointerdown)="onAxisPointerDown($event)"
1702
+ ></svg:line>
1703
+ } @else {
1704
+ <svg:circle
1705
+ class="gradient-axis"
1706
+ [attr.cx]="g.centerX"
1707
+ [attr.cy]="g.centerY"
1708
+ [attr.r]="g.radius"
1709
+ fill="none"
1710
+ (pointerdown)="onAxisPointerDown($event)"
1711
+ ></svg:circle>
1712
+ }
1713
+
1714
+ <!-- Stop dots \u2014 colored by stop, position interpolated along
1715
+ the axis. Drag changes offset, click selects for color edit. -->
1716
+ @for (s of stopDots(); track s.index) {
1717
+ <svg:circle
1718
+ class="stop-dot"
1719
+ [class.selected]="s.index === selectedIndex()"
1720
+ [attr.cx]="s.x"
1721
+ [attr.cy]="s.y"
1722
+ [attr.r]="stopRadius()"
1723
+ [attr.fill]="s.color"
1724
+ [attr.data-svge-stop-index]="s.index"
1725
+ role="button"
1726
+ tabindex="0"
1727
+ [attr.aria-label]="'Gradient stop ' + (s.index + 1) + ' at ' + s.offsetPct + ' percent'"
1728
+ (pointerdown)="onStopPointerDown($event, s.index)"
1729
+ (pointermove)="onStopPointerMove($event)"
1730
+ (pointerup)="onStopPointerUp($event)"
1731
+ ></svg:circle>
1732
+ }
1733
+ }
1734
+ `,isInline:!0,styles:[`.gradient-axis{stroke:#1976d2;stroke-width:1.5;stroke-dasharray:4 3;vector-effect:non-scaling-stroke;cursor:copy}.stop-dot{stroke:#1976d2;stroke-width:2;vector-effect:non-scaling-stroke;cursor:grab;touch-action:none}.stop-dot:active{cursor:grabbing}.stop-dot.selected{stroke:#ff6f00;stroke-width:3;filter:drop-shadow(0 0 2px rgba(255,111,0,.7))}.stop-dot:focus-visible{stroke:#ff6f00;outline:none}
1735
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:dr,decorators:[{type:W,args:[{selector:"g[svgeGradientOverlay]",standalone:!0,template:`
1736
+ @if (geometry(); as g) {
1737
+ <!-- Direction line (linear) or radius circle (radial). The
1738
+ dashed style signals "guide, not content"; pointer-events
1739
+ on the line catch click-to-insert-stop. -->
1740
+ @if (g.kind === 'linear') {
1741
+ <svg:line
1742
+ class="gradient-axis"
1743
+ [attr.x1]="g.startX"
1744
+ [attr.y1]="g.startY"
1745
+ [attr.x2]="g.endX"
1746
+ [attr.y2]="g.endY"
1747
+ (pointerdown)="onAxisPointerDown($event)"
1748
+ ></svg:line>
1749
+ } @else {
1750
+ <svg:circle
1751
+ class="gradient-axis"
1752
+ [attr.cx]="g.centerX"
1753
+ [attr.cy]="g.centerY"
1754
+ [attr.r]="g.radius"
1755
+ fill="none"
1756
+ (pointerdown)="onAxisPointerDown($event)"
1757
+ ></svg:circle>
1758
+ }
1759
+
1760
+ <!-- Stop dots \u2014 colored by stop, position interpolated along
1761
+ the axis. Drag changes offset, click selects for color edit. -->
1762
+ @for (s of stopDots(); track s.index) {
1763
+ <svg:circle
1764
+ class="stop-dot"
1765
+ [class.selected]="s.index === selectedIndex()"
1766
+ [attr.cx]="s.x"
1767
+ [attr.cy]="s.y"
1768
+ [attr.r]="stopRadius()"
1769
+ [attr.fill]="s.color"
1770
+ [attr.data-svge-stop-index]="s.index"
1771
+ role="button"
1772
+ tabindex="0"
1773
+ [attr.aria-label]="'Gradient stop ' + (s.index + 1) + ' at ' + s.offsetPct + ' percent'"
1774
+ (pointerdown)="onStopPointerDown($event, s.index)"
1775
+ (pointermove)="onStopPointerMove($event)"
1776
+ (pointerup)="onStopPointerUp($event)"
1777
+ ></svg:circle>
1778
+ }
1779
+ }
1780
+ `,changeDetection:U.OnPush,styles:[`.gradient-axis{stroke:#1976d2;stroke-width:1.5;stroke-dasharray:4 3;vector-effect:non-scaling-stroke;cursor:copy}.stop-dot{stroke:#1976d2;stroke-width:2;vector-effect:non-scaling-stroke;cursor:grab;touch-action:none}.stop-dot:active{cursor:grabbing}.stop-dot.selected{stroke:#ff6f00;stroke-width:3;filter:drop-shadow(0 0 2px rgba(255,111,0,.7))}.stop-dot:focus-visible{stroke:#ff6f00;outline:none}
1781
+ `]}]}],ctorParameters:()=>[]});function df(r,e){const t=r.geometry??{};if(r.kind==="linear"){const l=t.x1??0,c=t.y1??0,u=t.x2??1,h=t.y2??0;return{kind:"linear",startX:e.x+l*e.width,startY:e.y+c*e.height,endX:e.x+u*e.width,endY:e.y+h*e.height,centerX:0,centerY:0,radius:0}}const n=t.cx??.5,o=t.cy??.5,a=(t.r??.5)*Math.sqrt((e.width*e.width+e.height*e.height)/2);return{kind:"radial",startX:0,startY:0,endX:0,endY:0,centerX:e.x+n*e.width,centerY:e.y+o*e.height,radius:a}}function uf(r,e){return r.kind==="linear"?{x:r.startX+(r.endX-r.startX)*e,y:r.startY+(r.endY-r.startY)*e}:{x:r.centerX+r.radius*e,y:r.centerY}}function fc(r,e){if(r.kind==="linear"){const n=r.endX-r.startX,o=r.endY-r.startY,i=n*n+o*o;if(i<1e-9)return 0;const a=e.x-r.startX,l=e.y-r.startY;return(a*n+l*o)/i}const t=Math.hypot(e.x-r.centerX,e.y-r.centerY);return r.radius<1e-9?0:t/r.radius}function hf(r,e){if(r.length===0)return"#808080";const t=[...r].sort((n,o)=>n.offset-o.offset);if(e<=t[0].offset)return t[0].color;if(e>=t.at(-1).offset)return t.at(-1).color;for(let n=0;n<t.length-1;n++){const o=t[n],i=t[n+1];if(e>=o.offset&&e<=i.offset){const a=(e-o.offset)/(i.offset-o.offset);return pf(o.color,i.color,a)}}return t[0].color}function gf(r,e){return[...r,e].sort((t,n)=>t.offset-n.offset)}function pf(r,e,t){const n=mc(r),o=mc(e);if(n===null||o===null)return r;const i=Math.round(n.r*(1-t)+o.r*t),a=Math.round(n.g*(1-t)+o.g*t),l=Math.round(n.b*(1-t)+o.b*t);return`#${[i,a,l].map(c=>c.toString(16).padStart(2,"0")).join("")}`}function mc(r){const e=r.startsWith("#")?r.slice(1):r;if(e.length===3){const n=parseInt(e[0].repeat(2),16),o=parseInt(e[1].repeat(2),16),i=parseInt(e[2].repeat(2),16);if([n,o,i].every(a=>!Number.isNaN(a)))return{r:n,g:o,b:i}}if(e.length===6){const n=parseInt(e.slice(0,2),16),o=parseInt(e.slice(2,4),16),i=parseInt(e.slice(4,6),16);if([n,o,i].every(a=>!Number.isNaN(a)))return{r:n,g:o,b:i}}const t=/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(r);return t!==null?{r:Number(t[1]),g:Number(t[2]),b:Number(t[3])}:null}const ve=10,vc={id:"svge.builtin.pattern.dots",name:"Dots",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="${ve}" height="${ve}">
1782
+ <circle cx="5" cy="5" r="1.5" fill="#212121" />
1783
+ </pattern>`}},yc={id:"svge.builtin.pattern.lines-horizontal",name:"Lines (horizontal)",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="${ve}" height="4">
1784
+ <line x1="0" y1="2" x2="${ve}" y2="2" stroke="#212121" stroke-width="1" />
1785
+ </pattern>`}},bc={id:"svge.builtin.pattern.lines-diagonal",name:"Lines (diagonal)",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="6" height="6"
1786
+ patternTransform="rotate(45)">
1787
+ <line x1="0" y1="0" x2="0" y2="6" stroke="#212121" stroke-width="1" />
1788
+ </pattern>`}},wc={id:"svge.builtin.pattern.grid",name:"Grid",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="${ve}" height="${ve}">
1789
+ <path d="M${ve} 0 L0 0 0 ${ve}" fill="none" stroke="#9e9e9e" stroke-width="0.5" />
1790
+ </pattern>`}},Ic={id:"svge.builtin.pattern.checkerboard",name:"Checkerboard",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="${ve}" height="${ve}">
1791
+ <rect x="0" y="0" width="5" height="5" fill="#212121" />
1792
+ <rect x="5" y="5" width="5" height="5" fill="#212121" />
1793
+ </pattern>`}},kc={id:"svge.builtin.pattern.lines-vertical",name:"Lines (vertical)",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="4" height="${ve}">
1794
+ <line x1="2" y1="0" x2="2" y2="${ve}" stroke="#212121" stroke-width="1" />
1795
+ </pattern>`}},xc={id:"svge.builtin.pattern.cross-hatch",name:"Cross-hatch",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="8" height="8">
1796
+ <path d="M0 8 L8 0 M0 0 L8 8" fill="none" stroke="#212121" stroke-width="0.8" />
1797
+ </pattern>`}},Dc={id:"svge.builtin.pattern.grid-fine",name:"Grid (fine)",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="5" height="5">
1798
+ <path d="M5 0 L0 0 0 5" fill="none" stroke="#9e9e9e" stroke-width="0.4" />
1799
+ </pattern>`}},Sc={id:"svge.builtin.pattern.graph-paper",name:"Graph paper",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="25" height="25">
1800
+ <path d="M5 0 V25 M10 0 V25 M15 0 V25 M20 0 V25 M0 5 H25 M0 10 H25 M0 15 H25 M0 20 H25"
1801
+ fill="none" stroke="#e0e0e0" stroke-width="0.5" />
1802
+ <path d="M25 0 L0 0 0 25" fill="none" stroke="#9e9e9e" stroke-width="1" />
1803
+ </pattern>`}},Pc={id:"svge.builtin.pattern.dots-large",name:"Dots (large)",category:"dots",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="16" height="16">
1804
+ <circle cx="8" cy="8" r="3" fill="#212121" />
1805
+ </pattern>`}},Mc={id:"svge.builtin.pattern.dots-dense",name:"Dots (dense)",category:"dots",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="6" height="6">
1806
+ <circle cx="3" cy="3" r="1" fill="#212121" />
1807
+ </pattern>`}},_c={id:"svge.builtin.pattern.dots-offset",name:"Dots (offset)",category:"dots",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="20">
1808
+ <circle cx="5" cy="5" r="2" fill="#212121" />
1809
+ <circle cx="15" cy="15" r="2" fill="#212121" />
1810
+ </pattern>`}},Ec={id:"svge.builtin.pattern.circles",name:"Circles",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="16" height="16">
1811
+ <circle cx="8" cy="8" r="6" fill="none" stroke="#212121" stroke-width="1" />
1812
+ </pattern>`}},Tc={id:"svge.builtin.pattern.zigzag",name:"Zigzag",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="16" height="8">
1813
+ <path d="M0 8 L4 0 L8 8 L12 0 L16 8" fill="none" stroke="#212121" stroke-width="1" />
1814
+ </pattern>`}},Rc={id:"svge.builtin.pattern.chevron",name:"Chevron",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="10">
1815
+ <path d="M0 8 L10 0 L20 8" fill="none" stroke="#212121" stroke-width="3" />
1816
+ </pattern>`}},Ac={id:"svge.builtin.pattern.waves",name:"Waves",category:"organic",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="10">
1817
+ <path d="M0 5 C5 0 5 0 10 5 C15 10 15 10 20 5" fill="none" stroke="#212121" stroke-width="1" />
1818
+ </pattern>`}},Cc={id:"svge.builtin.pattern.scales",name:"Fish scales",category:"organic",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="20">
1819
+ <path d="M0 0 A10 10 0 0 0 20 0" fill="none" stroke="#212121" stroke-width="1" />
1820
+ <path d="M-10 10 A10 10 0 0 0 10 10" fill="none" stroke="#212121" stroke-width="1" />
1821
+ <path d="M10 10 A10 10 0 0 0 30 10" fill="none" stroke="#212121" stroke-width="1" />
1822
+ </pattern>`}},Oc={id:"svge.builtin.pattern.bricks",name:"Bricks",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="16">
1823
+ <path d="M0 0 H20 M0 8 H20 M0 16 H20" fill="none" stroke="#9e9e9e" stroke-width="1" />
1824
+ <path d="M0 0 V8 M10 8 V16" fill="none" stroke="#9e9e9e" stroke-width="1" />
1825
+ </pattern>`}},Nc={id:"svge.builtin.pattern.triangles",name:"Triangles",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="20">
1826
+ <path d="M0 20 L10 0 L20 20 Z" fill="#212121" />
1827
+ </pattern>`}},Lc={id:"svge.builtin.pattern.diamonds",name:"Diamonds",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="20">
1828
+ <path d="M10 0 L20 10 L10 20 L0 10 Z" fill="none" stroke="#212121" stroke-width="1" />
1829
+ </pattern>`}},$c={id:"svge.builtin.pattern.octagons",name:"Octagons",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="20">
1830
+ <polygon points="6,0 14,0 20,6 20,14 14,20 6,20 0,14 0,6"
1831
+ fill="none" stroke="#212121" stroke-width="1" />
1832
+ </pattern>`}},Bc={id:"svge.builtin.pattern.crosses",name:"Crosses",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="12" height="12">
1833
+ <path d="M5 2 H7 V5 H10 V7 H7 V10 H5 V7 H2 V5 H5 Z" fill="#212121" />
1834
+ </pattern>`}},Fc={id:"svge.builtin.pattern.stars",name:"Stars",category:"decorative",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="20">
1835
+ <path d="M10 2 L11.9 7.4 L17.6 7.5 L13 11 L14.7 16.5 L10 13.2 L5.3 16.5 L7 11 L2.4 7.5 L8.1 7.4 Z"
1836
+ fill="#212121" />
1837
+ </pattern>`}},jc={id:"svge.builtin.pattern.hearts",name:"Hearts",category:"decorative",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="20">
1838
+ <path d="M10 17 C4 12 1 9 1 6 C1 3 3 1 5.5 1 C7.5 1 9 2.5 10 4.5 C11 2.5 12.5 1 14.5 1 C17 1 19 3 19 6 C19 9 16 12 10 17 Z"
1839
+ fill="#212121" />
1840
+ </pattern>`}},Vc={id:"svge.builtin.pattern.stripes-vertical",name:"Stripes (vertical)",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="10">
1841
+ <rect x="0" y="0" width="10" height="10" fill="#212121" />
1842
+ </pattern>`}},zc={id:"svge.builtin.pattern.stripes-diagonal",name:"Stripes (diagonal)",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="14" height="14"
1843
+ patternTransform="rotate(45)">
1844
+ <rect x="0" y="0" width="7" height="14" fill="#212121" />
1845
+ </pattern>`}},Gc={id:"svge.builtin.pattern.checkerboard-small",name:"Checkerboard (small)",category:"geometric",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="6" height="6">
1846
+ <rect x="0" y="0" width="3" height="3" fill="#212121" />
1847
+ <rect x="3" y="3" width="3" height="3" fill="#212121" />
1848
+ </pattern>`}},Hc={id:"svge.builtin.pattern.confetti",name:"Confetti",category:"decorative",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="30" height="30">
1849
+ <rect x="4" y="6" width="5" height="2" rx="1" fill="#212121" transform="rotate(30 6.5 7)" />
1850
+ <rect x="20" y="4" width="5" height="2" rx="1" fill="#9e9e9e" transform="rotate(-20 22.5 5)" />
1851
+ <rect x="10" y="18" width="5" height="2" rx="1" fill="#212121" transform="rotate(60 12.5 19)" />
1852
+ <rect x="22" y="22" width="5" height="2" rx="1" fill="#9e9e9e" transform="rotate(-45 24.5 23)" />
1853
+ <rect x="2" y="24" width="5" height="2" rx="1" fill="#212121" transform="rotate(10 4.5 25)" />
1854
+ </pattern>`}},Uc={id:"svge.builtin.pattern.basketweave",name:"Basket weave",category:"decorative",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="16" height="16">
1855
+ <g fill="#212121">
1856
+ <rect x="0" y="1" width="7" height="1.5" /><rect x="0" y="4" width="7" height="1.5" /><rect x="0" y="6.5" width="7" height="1.5" />
1857
+ <rect x="9" y="9" width="7" height="1.5" /><rect x="9" y="12" width="7" height="1.5" /><rect x="9" y="14.5" width="7" height="1.5" />
1858
+ <rect x="9" y="1" width="1.5" height="7" /><rect x="12" y="1" width="1.5" height="7" /><rect x="14.5" y="1" width="1.5" height="7" />
1859
+ <rect x="1" y="9" width="1.5" height="7" /><rect x="4" y="9" width="1.5" height="7" /><rect x="6.5" y="9" width="1.5" height="7" />
1860
+ </g>
1861
+ </pattern>`}},Wc={id:"svge.builtin.pattern.plaid",name:"Plaid",category:"decorative",buildMarkup(){return`<pattern id="${this.id}" patternUnits="userSpaceOnUse" width="20" height="20">
1862
+ <rect x="0" y="0" width="20" height="6" fill="#212121" opacity="0.25" />
1863
+ <rect x="0" y="0" width="6" height="20" fill="#212121" opacity="0.25" />
1864
+ <rect x="12" y="0" width="2" height="20" fill="#212121" opacity="0.4" />
1865
+ <rect x="0" y="12" width="20" height="2" fill="#212121" opacity="0.4" />
1866
+ </pattern>`}},Kc=[vc,yc,bc,wc,Ic,kc,xc,Dc,Sc,Pc,Mc,_c,Ec,Tc,Rc,Ac,Cc,Oc,Nc,Lc,$c,Bc,Fc,jc,Vc,zc,Gc,Hc,Uc,Wc],Xc={id:"svge.builtin.patterns",version:"1.0.0",name:"Built-in patterns library (30 presets)",apiVersion:O,install(r){const e=r.injector.get(Nt);for(const t of Kc)r.track(e.register(t))}};class Sn extends Ae{static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Sn,deps:null,target:s.\u0275\u0275FactoryTarget.Injectable});static \u0275prov=s.\u0275\u0275ngDeclareInjectable({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Sn,providedIn:"root"})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:Sn,decorators:[{type:D,args:[{providedIn:"root"}]}]});const Yc={id:"svge.builtin.template.a4-portrait",name:"A4 (portrait)",category:"print",dimensions:"595\xD7842",build(){return ge({viewBox:X(0,0,595,842),width:595,height:842})}},qc={id:"svge.builtin.template.instagram-square",name:"Instagram square",category:"social",dimensions:"1080\xD71080",build(){return ge({viewBox:X(0,0,1080,1080),width:1080,height:1080})}},Zc={id:"svge.builtin.template.twitter-card",name:"Twitter / X card",category:"social",dimensions:"1200\xD7675",build(){return ge({viewBox:X(0,0,1200,675),width:1200,height:675})}},Jc={id:"svge.builtin.template.business-card",name:"Business card",category:"print",dimensions:"350\xD7200",build(){return ge({viewBox:X(0,0,350,200),width:350,height:200})}},Qc={id:"svge.builtin.template.a4-landscape",name:"A4 (landscape)",category:"print",dimensions:"842\xD7595",build(){return ge({viewBox:X(0,0,842,595),width:842,height:595})}},ed={id:"svge.builtin.template.letter-portrait",name:"Letter (portrait)",category:"print",dimensions:"612\xD7792",build(){return ge({viewBox:X(0,0,612,792),width:612,height:792})}},td={id:"svge.builtin.template.instagram-story",name:"Instagram story",category:"social",dimensions:"1080\xD71920",build(){return ge({viewBox:X(0,0,1080,1920),width:1080,height:1920})}},nd={id:"svge.builtin.template.instagram-portrait",name:"Instagram portrait",category:"social",dimensions:"1080\xD71350",build(){return ge({viewBox:X(0,0,1080,1350),width:1080,height:1350})}},rd={id:"svge.builtin.template.youtube-thumbnail",name:"YouTube thumbnail",category:"video",dimensions:"1280\xD7720",build(){return ge({viewBox:X(0,0,1280,720),width:1280,height:720})}},od={id:"svge.builtin.template.presentation-16-9",name:"Presentation 16:9",category:"presentation",dimensions:"1920\xD71080",build(){return ge({viewBox:X(0,0,1920,1080),width:1920,height:1080})}},id={id:"svge.builtin.template.pinterest-pin",name:"Pinterest pin",category:"social",dimensions:"1000\xD71500",build(){return ge({viewBox:X(0,0,1e3,1500),width:1e3,height:1500})}},sd={id:"svge.builtin.template.facebook-cover",name:"Facebook cover",category:"social",dimensions:"820\xD7312",build(){return ge({viewBox:X(0,0,820,312),width:820,height:312})}},ad=[Yc,Qc,ed,Jc,qc,nd,td,id,sd,Zc,rd,od],ld={id:"svge.builtin.templates",version:"1.0.0",name:"Built-in document templates (12 print / social / video formats)",apiVersion:O,install(r){const e=r.injector.get(Sn);for(const t of ad)r.track(e.register(t))}},Vr={x:0,y:0,width:64,height:64},ff=N(xf(32,32,28,12,5),{style:{fill:"currentColor"}}),mf=N("M4 24 L40 24 L40 12 L60 32 L40 52 L40 40 L4 40 Z",{style:{fill:"currentColor"}}),vf=N("M32 56 C12 40 4 28 4 20 C4 12 10 8 16 8 C22 8 28 12 32 18 C36 12 42 8 48 8 C54 8 60 12 60 20 C60 28 52 40 32 56 Z",{style:{fill:"currentColor"}}),yf=mt([N(Df(32,32,24,18,8,4),{style:{fill:"currentColor"}}),N("M32 22 A10 10 0 1 0 32 42 A10 10 0 1 0 32 22 Z",{style:{fill:"#ffffff"}})],{style:{fill:"currentColor"}}),bf={id:"svge.builtin.symbol.star",name:"Star",category:"basic",master:ff,viewBox:Vr,buildMarkup(){return qt(this)}},wf={id:"svge.builtin.symbol.arrow",name:"Arrow",category:"basic",master:mf,viewBox:Vr,buildMarkup(){return qt(this)}},If={id:"svge.builtin.symbol.heart",name:"Heart",category:"basic",master:vf,viewBox:Vr,buildMarkup(){return qt(this)}},kf={id:"svge.builtin.symbol.gear",name:"Gear",category:"basic",master:yf,viewBox:Vr,buildMarkup(){return qt(this)}},cd=[bf,wf,If,kf],dd={id:"svge.builtin.symbols",name:"Built-in symbols (4 items) \u2014 D-059",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(Ke);for(const t of cd)r.track(e.register(t))}};function xf(r,e,t,n,o){const i=-Math.PI/2,a=[];for(let l=0;l<o*2;l++){const c=l%2===0?t:n,u=i+l*Math.PI/o,h=r+c*Math.cos(u),g=e+c*Math.sin(u);a.push(`${l===0?"M":"L"}${h.toFixed(2)} ${g.toFixed(2)}`)}return a.push("Z"),a.join(" ")}function Df(r,e,t,n,o,i){const a=[],l=2*Math.PI/o,c=l/2,u=i/360*Math.PI;for(let h=0;h<o;h++){const g=h*l-Math.PI/2,v=g-c,p=g+c-u,x=g-u/2,E=g+u/2,C=g+c;if(h===0){const zr=r+n*Math.cos(v),gr=e+n*Math.sin(v);a.push(`M${zr.toFixed(2)} ${gr.toFixed(2)}`)}const G=r+n*Math.cos(p),Z=e+n*Math.sin(p);a.push(`A${n} ${n} 0 0 1 ${G.toFixed(2)} ${Z.toFixed(2)}`);const V=r+t*Math.cos(x),qe=e+t*Math.sin(x);a.push(`L${V.toFixed(2)} ${qe.toFixed(2)}`);const Pn=r+t*Math.cos(E),Te=e+t*Math.sin(E);a.push(`A${t} ${t} 0 0 1 ${Pn.toFixed(2)} ${Te.toFixed(2)}`);const ht=r+n*Math.cos(C),Ft=e+n*Math.sin(C);a.push(`L${ht.toFixed(2)} ${Ft.toFixed(2)}`)}return a.push("Z"),a.join(" ")}class Sf{symbolId;x;y;width;height;parentId;id=Ht();label;insertedId=null;constructor(e,t,n,o,i,a=te){this.symbolId=e,this.x=t,this.y=n,this.width=o,this.height=i,this.parentId=a,this.label=`Insert symbol "${e}"`}getInsertedId(){return this.insertedId}execute(e){const t=e.state.document(),n=bi({symbolId:this.symbolId,x:this.x,y:this.y,width:this.width,height:this.height}),o=this.parentId===te?e.parentResolver?.resolveAutoParent()??t.root.id:this.parentId;let i;try{i=Jr(t.root,o,n)}catch(a){return le(a instanceof Error?a.message:String(a))}return this.insertedId=n.id,e.state.setDocument({...t,root:i}),Re()}undo(e){if(this.insertedId===null)return le(`${this.label}: nothing to undo`);const t=e.state.document(),n=Qr(t.root,this.insertedId);return n===t.root?le(`${this.label} undo: instance "${this.insertedId}" not found`):(e.state.setDocument({...t,root:n}),Re())}}class ur{preview=f(Pe);catalog=f(Ke);sanitizer=f(ah);previewOpacity=.65;drops=this.preview.drops;useHref=m(()=>{const e=this.preview.symbolId();return e!==null?`#${e}`:null},...ngDevMode?[{debugName:"useHref"}]:[]);previewMarkup=m(()=>{const e=this.preview.symbolId();if(e===null||this.preview.drops().length===0)return null;const t=this.catalog.get(e);return t===null?null:this.sanitizer.bypassSecurityTrustHtml(qt(t))},...ngDevMode?[{debugName:"previewMarkup"}]:[]);static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ur,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:ur,isStandalone:!0,selector:"g[svgeSymbolSprayerOverlay]",host:{attributes:{"aria-hidden":"true"}},ngImport:s,template:`
1867
+ @if (previewMarkup(); as inner) {
1868
+ <svg:g [attr.opacity]="previewOpacity">
1869
+ <!--
1870
+ Inline the symbol master so the <use> elements resolve
1871
+ even before the doc has any committed instances. Use
1872
+ [innerHTML] so Angular parses the SVG markup as a tree
1873
+ (not text). DomSanitizer.bypassSecurityTrustHtml is
1874
+ required because the markup contains <symbol> which the
1875
+ default sanitizer would strip.
1876
+ -->
1877
+ <svg:defs [innerHTML]="inner"></svg:defs>
1878
+ @for (drop of drops(); track $index) {
1879
+ <svg:use
1880
+ [attr.href]="useHref()"
1881
+ [attr.x]="drop.x"
1882
+ [attr.y]="drop.y"
1883
+ [attr.width]="drop.width"
1884
+ [attr.height]="drop.height"
1885
+ ></svg:use>
1886
+ }
1887
+ </svg:g>
1888
+ }
1889
+ `,isInline:!0,styles:[`:host{pointer-events:none}
1890
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:ur,decorators:[{type:W,args:[{selector:"g[svgeSymbolSprayerOverlay]",standalone:!0,host:{"aria-hidden":"true"},template:`
1891
+ @if (previewMarkup(); as inner) {
1892
+ <svg:g [attr.opacity]="previewOpacity">
1893
+ <!--
1894
+ Inline the symbol master so the <use> elements resolve
1895
+ even before the doc has any committed instances. Use
1896
+ [innerHTML] so Angular parses the SVG markup as a tree
1897
+ (not text). DomSanitizer.bypassSecurityTrustHtml is
1898
+ required because the markup contains <symbol> which the
1899
+ default sanitizer would strip.
1900
+ -->
1901
+ <svg:defs [innerHTML]="inner"></svg:defs>
1902
+ @for (drop of drops(); track $index) {
1903
+ <svg:use
1904
+ [attr.href]="useHref()"
1905
+ [attr.x]="drop.x"
1906
+ [attr.y]="drop.y"
1907
+ [attr.width]="drop.width"
1908
+ [attr.height]="drop.height"
1909
+ ></svg:use>
1910
+ }
1911
+ </svg:g>
1912
+ }
1913
+ `,changeDetection:U.OnPush,styles:[`:host{pointer-events:none}
1914
+ `]}]}]});const ud=16;function q(r){const e=[];for(let t=0;t<ud;t++)e.push(r(t/(ud-1)));return e}const Pf={id:"svge.builtin.brush.uniform",name:"Uniform",category:"calligraphic",baseWidth:6,widthProfile:q(()=>1)},Mf={id:"svge.builtin.brush.tapered",name:"Tapered",category:"calligraphic",baseWidth:12,widthProfile:q(r=>Math.sin(r*Math.PI))},_f={id:"svge.builtin.brush.calligraphic",name:"Calligraphic",category:"calligraphic",baseWidth:10,widthProfile:q(r=>r<.15?.2+r/.15*.8:r<.7?1:1-(r-.7)/.3*.7)},Ef={id:"svge.builtin.brush.brush-pen",name:"Brush Pen",category:"calligraphic",baseWidth:10,widthProfile:q(r=>r<.18?.25+r/.18*.75:Math.max(0,1-(r-.18)/.82))},Tf={id:"svge.builtin.brush.wedge",name:"Wedge",category:"calligraphic",baseWidth:12,widthProfile:q(r=>1-r*.85)},Rf={id:"svge.builtin.brush.spindle",name:"Spindle",category:"calligraphic",baseWidth:12,widthProfile:q(r=>1-Math.abs(2*r-1))},Af={id:"svge.builtin.brush.ribbon",name:"Ribbon",category:"calligraphic",baseWidth:10,widthProfile:q(r=>.55+.45*Math.sin(r*Math.PI*6))},Cf={id:"svge.builtin.brush.comet",name:"Comet",category:"calligraphic",baseWidth:14,widthProfile:q(r=>Math.pow(1-r,1.7))},Of={id:"svge.builtin.brush.bulge",name:"Bulge",category:"calligraphic",baseWidth:9,widthProfile:q(r=>.25+Math.sin(r*Math.PI))},Nf={id:"svge.builtin.brush.ramp",name:"Ramp",category:"calligraphic",baseWidth:13,widthProfile:q(r=>.15+r*.85)},Lf={id:"svge.builtin.brush.swell",name:"Swell",category:"calligraphic",baseWidth:14,widthProfile:q(r=>Math.pow(r,1.7))},$f={id:"svge.builtin.brush.marker",name:"Marker",category:"calligraphic",baseWidth:11,widthProfile:q(r=>r<.12?.55+r/.12*.45:r>1-.12?.55+(1-r)/.12*.45:1)},Bf={id:"svge.builtin.brush.flared",name:"Flared",category:"calligraphic",baseWidth:12,widthProfile:q(r=>1-.75*Math.sin(r*Math.PI))},Ff={id:"svge.builtin.brush.swash",name:"Swash",category:"calligraphic",baseWidth:13,widthProfile:q(r=>Math.sin(r*r*Math.PI))},jf={id:"svge.builtin.brush.beads",name:"Beads",category:"calligraphic",baseWidth:11,widthProfile:q(r=>.2+.8*Math.sin(r*Math.PI*5)**2)},Vf={id:"svge.builtin.brush.bamboo",name:"Bamboo",category:"calligraphic",baseWidth:11,widthProfile:q(r=>1-.7*Math.abs(Math.sin(r*Math.PI*4))**6)},zf={id:"svge.builtin.brush.twin",name:"Twin",category:"calligraphic",baseWidth:12,widthProfile:q(r=>.25+.75*Math.sin(r*Math.PI*2)**2)},Gf={id:"svge.builtin.brush.rough",name:"Rough",category:"calligraphic",baseWidth:12,widthProfile:q(r=>Math.max(.12,.62+.22*Math.sin(r*Math.PI*7)+.13*Math.sin(r*Math.PI*17+1)+.08*Math.sin(r*Math.PI*29+2)))},hd=[Pf,Mf,_f,Ef,Tf,Rf,Af,Cf,Of,Nf,Lf,$f,Bf,Ff,jf,Vf,zf,Gf],gd={id:"svge.builtin.brushes",name:"Built-in brushes (18 calligraphic) \u2014 D-060",version:"1.0.0",apiVersion:O,install(r){const e=r.injector.get(xt);for(const t of hd)r.track(e.register(t))}},pd={id:"svge.builtin.clip-path.circle-200",name:"Circle (200px)",category:"shapes",buildMarkup(){return`<clipPath id="${this.id}" clipPathUnits="userSpaceOnUse">
1915
+ <circle cx="200" cy="150" r="100" />
1916
+ </clipPath>`}},fd={id:"svge.builtin.clip-path.ellipse-wide",name:"Ellipse (wide)",category:"shapes",buildMarkup(){return`<clipPath id="${this.id}" clipPathUnits="userSpaceOnUse">
1917
+ <ellipse cx="200" cy="150" rx="180" ry="100" />
1918
+ </clipPath>`}},md={id:"svge.builtin.clip-path.rounded-rect",name:"Rounded rectangle",category:"shapes",buildMarkup(){return`<clipPath id="${this.id}" clipPathUnits="userSpaceOnUse">
1919
+ <rect x="20" y="20" width="360" height="260" rx="24" ry="24" />
1920
+ </clipPath>`}},vd={id:"svge.builtin.clip-path.star",name:"Star",category:"shapes",buildMarkup(){return`<clipPath id="${this.id}" clipPathUnits="userSpaceOnUse">
1921
+ <polygon points="200,30 240,120 340,130 265,200 285,295 200,250 115,295 135,200 60,130 160,120" />
1922
+ </clipPath>`}},yd={id:"svge.builtin.clip-path.heart",name:"Heart",category:"shapes",buildMarkup(){return`<clipPath id="${this.id}" clipPathUnits="userSpaceOnUse">
1923
+ <path d="M200,250 C90,180 90,80 160,80 C185,80 200,100 200,120 C200,100 215,80 240,80 C310,80 310,180 200,250 Z" />
1924
+ </clipPath>`}},bd=[pd,fd,md,vd,yd],wd={id:"svge.builtin.clip-paths",version:"1.0.0",name:"Built-in clipPath library (5 presets)",apiVersion:O,install(r){const e=r.injector.get(Ct);for(const t of bd)r.track(e.register(t))}},Id={id:"svge.builtin.mask.fade-left",name:"Fade from left",category:"gradient",buildMarkup(){return`<mask id="${this.id}" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse">
1925
+ <linearGradient id="svge-mask-grad-fade-left" x1="0" y1="0" x2="400" y2="0" gradientUnits="userSpaceOnUse">
1926
+ <stop offset="0" stop-color="#000" />
1927
+ <stop offset="1" stop-color="#fff" />
1928
+ </linearGradient>
1929
+ <rect x="0" y="0" width="400" height="300" fill="url(#svge-mask-grad-fade-left)" />
1930
+ </mask>`}},kd={id:"svge.builtin.mask.fade-bottom",name:"Fade to bottom",category:"gradient",buildMarkup(){return`<mask id="${this.id}" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse">
1931
+ <linearGradient id="svge-mask-grad-fade-bottom" x1="0" y1="0" x2="0" y2="300" gradientUnits="userSpaceOnUse">
1932
+ <stop offset="0" stop-color="#fff" />
1933
+ <stop offset="1" stop-color="#000" />
1934
+ </linearGradient>
1935
+ <rect x="0" y="0" width="400" height="300" fill="url(#svge-mask-grad-fade-bottom)" />
1936
+ </mask>`}},xd={id:"svge.builtin.mask.spotlight",name:"Spotlight (vignette)",category:"radial",buildMarkup(){return`<mask id="${this.id}" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse">
1937
+ <radialGradient id="svge-mask-grad-spotlight" cx="200" cy="150" r="180" gradientUnits="userSpaceOnUse">
1938
+ <stop offset="0" stop-color="#fff" />
1939
+ <stop offset="0.7" stop-color="#aaa" />
1940
+ <stop offset="1" stop-color="#000" />
1941
+ </radialGradient>
1942
+ <rect x="0" y="0" width="400" height="300" fill="url(#svge-mask-grad-spotlight)" />
1943
+ </mask>`}},Dd={id:"svge.builtin.mask.soft-circle",name:"Soft circle",category:"radial",buildMarkup(){return`<mask id="${this.id}" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse">
1944
+ <radialGradient id="svge-mask-grad-soft-circle" cx="200" cy="150" r="120" gradientUnits="userSpaceOnUse">
1945
+ <stop offset="0" stop-color="#fff" />
1946
+ <stop offset="0.9" stop-color="#fff" />
1947
+ <stop offset="1" stop-color="#000" />
1948
+ </radialGradient>
1949
+ <rect x="0" y="0" width="400" height="300" fill="url(#svge-mask-grad-soft-circle)" />
1950
+ </mask>`}},Sd=[Id,kd,xd,Dd],Pd={id:"svge.builtin.masks",version:"1.0.0",name:"Built-in mask library (4 presets)",apiVersion:O,install(r){const e=r.injector.get(Ot);for(const t of Sd)r.track(e.register(t))}};function Md(r,e={}){const t=e.threshold??128,n=e.tolerance??1,o=e.minPoints??4,i=e.destX??0,a=e.destY??0,l=e.destWidth??r.width,c=e.destHeight??r.height,u=Hf(r,t),g=Uf(u,r.width,r.height).map(x=>({points:Kf(x.points,n)})).filter(x=>x.points.length>=o),v=l/r.width,p=c/r.height;return g.map(x=>`${x.points.map((C,G)=>{const Z=i+C.x*v,V=a+C.y*p;return`${G===0?"M":"L"}${Z.toFixed(2)} ${V.toFixed(2)}`}).join(" ")} Z`)}function Hf(r,e){const{width:t,height:n,data:o}=r,i=new Uint8Array(t*n);for(let a=0;a<t*n;a++){const l=o[a*4],c=o[a*4+1],u=o[a*4+2];if(o[a*4+3]<128){i[a]=0;continue}const g=.299*l+.587*c+.114*u;i[a]=g<=e?1:0}return i}function Uf(r,e,t){const n=[],o=new Uint8Array(e*t),i=(l,c)=>l<0||l>=e||c<0||c>=t?!1:r[c*e+l]===1,a=(l,c)=>i(l,c)?!i(l-1,c)||!i(l+1,c)||!i(l,c-1)||!i(l,c+1):!1;for(let l=0;l<t;l++)for(let c=0;c<e;c++){const u=l*e+c;if(o[u]===1||!a(c,l))continue;const h=[];let g=c,v=l,p=0;const x=c,E=l,C=e*t*4;let G=0;do{o[v*e+g]===0&&(h.push({x:g+.5,y:v+.5}),o[v*e+g]=1);let Z=!1;for(let V=-1;V<=2;V++){const qe=(p+V+4)%4,[Pn,Te]=Wf[qe],ht=g+Pn,Ft=v+Te;if(a(ht,Ft)){g=ht,v=Ft,p=qe,Z=!0;break}}if(!Z)break;G++}while((g!==x||v!==E)&&G<C);h.length>0&&n.push({points:h})}return n}const Wf=[[1,0],[0,1],[-1,0],[0,-1]];function Kf(r,e){if(r.length<=2)return[...r];const t=new Array(r.length).fill(!1);t[0]=!0,t[r.length-1]=!0,ni(r,0,r.length-1,e,t);const n=[];for(let o=0;o<r.length;o++)t[o]&&n.push(r[o]);return n}function ni(r,e,t,n,o){if(t<=e+1)return;let i=0,a=e;const l=r[e],c=r[t];for(let u=e+1;u<t;u++){const h=Xf(r[u],l,c);h>i&&(i=h,a=u)}i>n&&(o[a]=!0,ni(r,e,a,n,o),ni(r,a,t,n,o))}function Xf(r,e,t){const n=t.x-e.x,o=t.y-e.y,i=n*n+o*o;if(i<1e-9)return Math.hypot(r.x-e.x,r.y-e.y);const a=((r.x-e.x)*n+(r.y-e.y)*o)/i,l=e.x+a*n,c=e.y+a*o;return Math.hypot(r.x-l,r.y-c)}class Yf{imageNodeId;opts;id=Ht();label;insertedGroupId=null;tracedPathDs=[];constructor(e,t={}){this.imageNodeId=e,this.opts=t,this.label=`Trace image "${e}"`}async prepare(e){const t=e.state.document(),n=T(t.root,this.imageNodeId);if(n===null||n.type!=="image")throw new Error(`TraceImageCommand: node "${this.imageNodeId}" not found or not an image`);const o=n,i=await qf(o.href),a={destX:o.x,destY:o.y,destWidth:o.width,destHeight:o.height,...this.opts};this.tracedPathDs=Md(i,a)}execute(e){if(this.tracedPathDs.length===0)return le(`${this.label}: no contours traced \u2014 call prepare() first, or adjust threshold/tolerance.`);const t=e.state.document(),n=this.tracedPathDs.map(l=>N(l,{style:{fill:"#000000",stroke:"none"}})),o=mt(n,{metadata:{name:`Traced ${this.imageNodeId}`}}),i=e.parentResolver?.resolveAutoParent()??t.root.id;let a;try{a=Jr(t.root,i,o)}catch(l){return le(l instanceof Error?l.message:String(l))}return this.insertedGroupId=o.id,e.state.setDocument({...t,root:a}),Re()}undo(e){if(this.insertedGroupId===null)return le(`${this.label}: nothing to undo`);const t=e.state.document(),n=Qr(t.root,this.insertedGroupId);return n===t.root?le(`${this.label} undo: group "${this.insertedGroupId}" not found`):(e.state.setDocument({...t,root:n}),Re())}getInsertedGroupId(){return this.insertedGroupId}}async function qf(r){const e=new Image;e.crossOrigin="anonymous",await new Promise((o,i)=>{e.onload=()=>o(),e.onerror=()=>i(new Error(`autotrace: failed to load image "${r}"`)),e.src=r});const t=document.createElement("canvas");t.width=e.naturalWidth,t.height=e.naturalHeight;const n=t.getContext("2d");if(n===null)throw new Error("autotrace: 2D canvas context unavailable");return n.drawImage(e,0,0),n.getImageData(0,0,t.width,t.height)}const _d=16,Zf=_d*2,Jf=6,Qf=11,ye=10;class hr{activePage=f(j);selection=f(k);viewport=f(A);bus=f(M);toolHost=f(Se);pageDrag=f(st);_drag=b(null,...ngDevMode?[{debugName:"_drag"}]:[]);constructor(){J(()=>{const e=this._drag();if(e===null){this.pageDrag.clearPreview();return}this.pageDrag.setPreview(e.pageId,this.computeFinalViewBox(e))})}onEscape(e){this._drag()!==null&&(e.stopPropagation(),e.preventDefault(),this._drag.set(null))}labelOffsetDoc=m(()=>Jf/this.viewport.zoom(),...ngDevMode?[{debugName:"labelOffsetDoc"}]:[]);labelFontSizeDoc=m(()=>Qf/this.viewport.zoom(),...ngDevMode?[{debugName:"labelFontSizeDoc"}]:[]);bracketArmDoc=m(()=>_d/this.viewport.zoom(),...ngDevMode?[{debugName:"bracketArmDoc"}]:[]);midBracketLenDoc=m(()=>Zf/this.viewport.zoom(),...ngDevMode?[{debugName:"midBracketLenDoc"}]:[]);overlay=m(()=>{if(this.toolHost.activeId()!==Pr)return null;const e=this.activePage.activePage();if(e===null||!this.selection.isSelected(e.id))return null;const t=Be(e);if(t===null)return null;const n=this.previewViewBox(t),i=`${mi(e)} \u2014 ${this.formatDim(n.width)}\xD7${this.formatDim(n.height)}`;return{x:n.x,y:n.y,width:n.width,height:n.height,label:i}},...ngDevMode?[{debugName:"overlay"}]:[]);formatDim(e){return Number.isInteger(e)?e.toString():e.toFixed(1)}bracketTL(e){const t=this.bracketArmDoc();return`M${e.x},${e.y+t} L${e.x},${e.y} L${e.x+t},${e.y}`}bracketTR(e){const t=this.bracketArmDoc(),n=e.x+e.width;return`M${n-t},${e.y} L${n},${e.y} L${n},${e.y+t}`}bracketBL(e){const t=this.bracketArmDoc(),n=e.y+e.height;return`M${e.x},${n-t} L${e.x},${n} L${e.x+t},${n}`}bracketBR(e){const t=this.bracketArmDoc(),n=e.x+e.width,o=e.y+e.height;return`M${n-t},${o} L${n},${o} L${n},${o-t}`}bracketT(e){const t=this.midBracketLenDoc()/2,n=e.x+e.width/2;return`M${n-t},${e.y} L${n+t},${e.y}`}bracketB(e){const t=this.midBracketLenDoc()/2,n=e.x+e.width/2,o=e.y+e.height;return`M${n-t},${o} L${n+t},${o}`}bracketL(e){const t=this.midBracketLenDoc()/2,n=e.y+e.height/2;return`M${e.x},${n-t} L${e.x},${n+t}`}bracketR(e){const t=this.midBracketLenDoc()/2,n=e.y+e.height/2,o=e.x+e.width;return`M${o},${n-t} L${o},${n+t}`}onMoveHandlePointerDown(e){if(e.altKey){e.stopPropagation(),e.preventDefault(),this.toolHost.activate(Je);return}const t=this.activePage.activePage();if(t===null)return;const n=Be(t);if(n===null)return;const o=this.screenToDoc(e);o!==null&&(e.stopPropagation(),H(e),this._drag.set({kind:"move",anchor:null,pageId:t.id,startViewBox:{x:n.x,y:n.y,width:n.width,height:n.height},startPoint:o,currentPoint:o}))}onResizeHandlePointerDown(e,t){const n=this.activePage.activePage();if(n===null)return;const o=Be(n);if(o===null)return;const i=this.screenToDoc(e);i!==null&&(e.stopPropagation(),H(e),this._drag.set({kind:"resize",anchor:t,pageId:n.id,startViewBox:{x:o.x,y:o.y,width:o.width,height:o.height},startPoint:i,currentPoint:i}))}onHandlePointerMove(e){const t=this._drag();if(t===null)return;const n=this.screenToDoc(e);n!==null&&this._drag.set({...t,currentPoint:n})}onHandlePointerUp(e){const t=this._drag();if(t===null)return;const n=this.computeFinalViewBox(t);this._drag.set(null),pe(e),t.kind==="move"?this.bus.dispatch(new Xu(t.pageId,{x:n.x,y:n.y})):this.bus.dispatch(new Yu(t.pageId,n))}previewViewBox(e){const t=this._drag();return t===null?e:this.computeFinalViewBox(t)}computeFinalViewBox(e){const t=e.currentPoint.x-e.startPoint.x,n=e.currentPoint.y-e.startPoint.y,o=e.startViewBox;if(e.kind==="move")return{x:o.x+t,y:o.y+n,width:o.width,height:o.height};let i=o.x,a=o.y,l=o.width,c=o.height;const u=o.x+o.width,h=o.y+o.height;switch(e.anchor){case"tl":{i=Math.min(o.x+t,u-ye),a=Math.min(o.y+n,h-ye),l=u-i,c=h-a;break}case"tr":{a=Math.min(o.y+n,h-ye),c=h-a,l=Math.max(o.width+t,ye);break}case"br":{l=Math.max(o.width+t,ye),c=Math.max(o.height+n,ye);break}case"bl":{i=Math.min(o.x+t,u-ye),l=u-i,c=Math.max(o.height+n,ye);break}case"t":{a=Math.min(o.y+n,h-ye),c=h-a;break}case"b":{c=Math.max(o.height+n,ye);break}case"l":{i=Math.min(o.x+t,u-ye),l=u-i;break}case"r":{l=Math.max(o.width+t,ye);break}case null:break}return{x:i,y:a,width:l,height:c}}screenToDoc(e){const t=e.target;return!(t instanceof Element)||!(t instanceof SVGElement)?null:Ve(t.ownerSVGElement,e.clientX,e.clientY)}static \u0275fac=s.\u0275\u0275ngDeclareFactory({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:hr,deps:[],target:s.\u0275\u0275FactoryTarget.Component});static \u0275cmp=s.\u0275\u0275ngDeclareComponent({minVersion:"17.0.0",version:"21.2.13",type:hr,isStandalone:!0,selector:"g[svgePageSelectionOverlay]",host:{attributes:{"aria-hidden":"true"},listeners:{"document:keydown.escape":"onEscape($event)"}},ngImport:s,template:`
1951
+ @if (overlay(); as o) {
1952
+ <!--
1953
+ Floating label above the page's top-left corner. Format:
1954
+ "Page 1 \u2014 800\xD7600" (per the answered user preference).
1955
+ text-anchor=start so the label aligns with the bracket TL.
1956
+ Font size and y-offset compensate for zoom so the label stays
1957
+ at constant CSS-pixel size across the zoom range.
1958
+ -->
1959
+ <svg:text
1960
+ class="page-label"
1961
+ [attr.x]="o.x"
1962
+ [attr.y]="o.y - labelOffsetDoc()"
1963
+ [attr.font-size]="labelFontSizeDoc() + 'px'"
1964
+ text-anchor="start"
1965
+ >
1966
+ {{ o.label }}
1967
+ </svg:text>
1968
+
1969
+ <!--
1970
+ **PAGES-REFACTOR follow-up #3** \u2014 invisible MOVE area covering
1971
+ the page interior. Replaces the dedicated move-handle square
1972
+ (top-center) \u2014 the user asked for "brackets only" visually but
1973
+ we still need a drag affordance, so we use the page interior
1974
+ itself (Illustrator/Affinity convention: with Artboard Tool
1975
+ active, dragging anywhere on the artboard moves it).
1976
+
1977
+ 'fill: transparent' + 'pointer-events: all' makes the entire
1978
+ rect clickable while staying visually invisible. Cursor: move
1979
+ gives the affordance hint. Rendered BEFORE the brackets so the
1980
+ bracket hit-areas (rendered LATER \u2192 on top) intercept clicks
1981
+ near the corners \u2192 start a resize drag instead of a move drag.
1982
+
1983
+ Because PageSelectionOverlay is mounted in the FRONT slot of
1984
+ SvgeRenderer, this rect sits ABOVE shape content. That's
1985
+ intentional: Page tool isn't for editing shapes, so click-
1986
+ through to shapes is undesirable \u2014 we want clicks on the page
1987
+ interior to move the page, not select a shape underneath.
1988
+ -->
1989
+ <svg:rect
1990
+ class="page-move-area"
1991
+ [attr.x]="o.x"
1992
+ [attr.y]="o.y"
1993
+ [attr.width]="o.width"
1994
+ [attr.height]="o.height"
1995
+ aria-label="Page move area \u2014 drag to reposition the page"
1996
+ role="button"
1997
+ (pointerdown)="onMoveHandlePointerDown($event)"
1998
+ (pointermove)="onHandlePointerMove($event)"
1999
+ (pointerup)="onHandlePointerUp($event)"
2000
+ ></svg:rect>
2001
+
2002
+ <!--
2003
+ Mid-edge brackets follow-up \u2014 4 single-line brackets centered
2004
+ on the midpoint of each edge, each wrapping an svg:g that
2005
+ owns a single-axis resize gesture. Visual style is identical
2006
+ to the corner Ls (same .page-bracket + .bracket-hit pair) \u2014
2007
+ only the shape differs (straight line aligned with the edge,
2008
+ not an L).
2009
+
2010
+ Rendered BEFORE the corner brackets so that when their hit
2011
+ areas overlap near a corner, SVG hit-testing picks the corner
2012
+ bracket (rendered later, on top) \u2192 2-axis resize wins over
2013
+ 1-axis at the actual corner pixels.
2014
+ -->
2015
+ <svg:g
2016
+ class="bracket-group bracket-t"
2017
+ aria-label="Page resize handle, top edge"
2018
+ role="button"
2019
+ (pointerdown)="onResizeHandlePointerDown($event, 't')"
2020
+ (pointermove)="onHandlePointerMove($event)"
2021
+ (pointerup)="onHandlePointerUp($event)"
2022
+ >
2023
+ <svg:path class="bracket-hit" [attr.d]="bracketT(o)"></svg:path>
2024
+ <svg:path class="page-bracket" [attr.d]="bracketT(o)"></svg:path>
2025
+ </svg:g>
2026
+ <svg:g
2027
+ class="bracket-group bracket-b"
2028
+ aria-label="Page resize handle, bottom edge"
2029
+ role="button"
2030
+ (pointerdown)="onResizeHandlePointerDown($event, 'b')"
2031
+ (pointermove)="onHandlePointerMove($event)"
2032
+ (pointerup)="onHandlePointerUp($event)"
2033
+ >
2034
+ <svg:path class="bracket-hit" [attr.d]="bracketB(o)"></svg:path>
2035
+ <svg:path class="page-bracket" [attr.d]="bracketB(o)"></svg:path>
2036
+ </svg:g>
2037
+ <svg:g
2038
+ class="bracket-group bracket-l"
2039
+ aria-label="Page resize handle, left edge"
2040
+ role="button"
2041
+ (pointerdown)="onResizeHandlePointerDown($event, 'l')"
2042
+ (pointermove)="onHandlePointerMove($event)"
2043
+ (pointerup)="onHandlePointerUp($event)"
2044
+ >
2045
+ <svg:path class="bracket-hit" [attr.d]="bracketL(o)"></svg:path>
2046
+ <svg:path class="page-bracket" [attr.d]="bracketL(o)"></svg:path>
2047
+ </svg:g>
2048
+ <svg:g
2049
+ class="bracket-group bracket-r"
2050
+ aria-label="Page resize handle, right edge"
2051
+ role="button"
2052
+ (pointerdown)="onResizeHandlePointerDown($event, 'r')"
2053
+ (pointermove)="onHandlePointerMove($event)"
2054
+ (pointerup)="onHandlePointerUp($event)"
2055
+ >
2056
+ <svg:path class="bracket-hit" [attr.d]="bracketR(o)"></svg:path>
2057
+ <svg:path class="page-bracket" [attr.d]="bracketR(o)"></svg:path>
2058
+ </svg:g>
2059
+
2060
+ <!--
2061
+ **PAGES-REFACTOR follow-up #3** \u2014 4 corner L-brackets, each
2062
+ wrapped in an svg:g that owns the resize drag gesture. The
2063
+ bracket-hit path under each visible bracket gives a wider
2064
+ invisible stroke for comfortable click targeting (visible
2065
+ stroke is only ~3 CSS px wide). Cursor + anchor are corner-
2066
+ specific (nwse-resize for tl/br diagonal, nesw-resize for
2067
+ tr/bl anti-diagonal \u2014 Illustrator/Figma convention).
2068
+
2069
+ Rendered AFTER the move-area AND the mid-edge brackets so SVG
2070
+ hit-testing picks the corner bracket first when the pointer
2071
+ is near a corner \u2192 2-axis resize fires; mid-edge drag fires
2072
+ on the rest of each edge; everywhere else in the page interior
2073
+ \u2192 move drag.
2074
+ -->
2075
+ <svg:g
2076
+ class="bracket-group bracket-tl"
2077
+ aria-label="Page resize handle, top-left corner"
2078
+ role="button"
2079
+ (pointerdown)="onResizeHandlePointerDown($event, 'tl')"
2080
+ (pointermove)="onHandlePointerMove($event)"
2081
+ (pointerup)="onHandlePointerUp($event)"
2082
+ >
2083
+ <svg:path class="bracket-hit" [attr.d]="bracketTL(o)"></svg:path>
2084
+ <svg:path class="page-bracket" [attr.d]="bracketTL(o)"></svg:path>
2085
+ </svg:g>
2086
+ <svg:g
2087
+ class="bracket-group bracket-tr"
2088
+ aria-label="Page resize handle, top-right corner"
2089
+ role="button"
2090
+ (pointerdown)="onResizeHandlePointerDown($event, 'tr')"
2091
+ (pointermove)="onHandlePointerMove($event)"
2092
+ (pointerup)="onHandlePointerUp($event)"
2093
+ >
2094
+ <svg:path class="bracket-hit" [attr.d]="bracketTR(o)"></svg:path>
2095
+ <svg:path class="page-bracket" [attr.d]="bracketTR(o)"></svg:path>
2096
+ </svg:g>
2097
+ <svg:g
2098
+ class="bracket-group bracket-bl"
2099
+ aria-label="Page resize handle, bottom-left corner"
2100
+ role="button"
2101
+ (pointerdown)="onResizeHandlePointerDown($event, 'bl')"
2102
+ (pointermove)="onHandlePointerMove($event)"
2103
+ (pointerup)="onHandlePointerUp($event)"
2104
+ >
2105
+ <svg:path class="bracket-hit" [attr.d]="bracketBL(o)"></svg:path>
2106
+ <svg:path class="page-bracket" [attr.d]="bracketBL(o)"></svg:path>
2107
+ </svg:g>
2108
+ <svg:g
2109
+ class="bracket-group bracket-br"
2110
+ aria-label="Page resize handle, bottom-right corner"
2111
+ role="button"
2112
+ (pointerdown)="onResizeHandlePointerDown($event, 'br')"
2113
+ (pointermove)="onHandlePointerMove($event)"
2114
+ (pointerup)="onHandlePointerUp($event)"
2115
+ >
2116
+ <svg:path class="bracket-hit" [attr.d]="bracketBR(o)"></svg:path>
2117
+ <svg:path class="page-bracket" [attr.d]="bracketBR(o)"></svg:path>
2118
+ </svg:g>
2119
+ }
2120
+ `,isInline:!0,styles:[`.page-label{fill:var(--svge-page-overlay-stroke, #1976d2);font-family:system-ui,-apple-system,sans-serif;font-weight:500;pointer-events:none;-webkit-user-select:none;user-select:none}.page-bracket{fill:none;stroke:var(--svge-page-overlay-stroke, #1976d2);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke;pointer-events:none}.bracket-hit{fill:none;stroke:transparent;stroke-width:14;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke;pointer-events:stroke}.bracket-group{touch-action:none}.bracket-group.bracket-tl,.bracket-group.bracket-br{cursor:nwse-resize}.bracket-group.bracket-tr,.bracket-group.bracket-bl{cursor:nesw-resize}.bracket-group.bracket-t,.bracket-group.bracket-b{cursor:ns-resize}.bracket-group.bracket-l,.bracket-group.bracket-r{cursor:ew-resize}.page-move-area{fill:transparent;cursor:move;pointer-events:all;touch-action:none}
2121
+ `],changeDetection:s.ChangeDetectionStrategy.OnPush})}s.\u0275\u0275ngDeclareClassMetadata({minVersion:"12.0.0",version:"21.2.13",ngImport:s,type:hr,decorators:[{type:W,args:[{selector:"g[svgePageSelectionOverlay]",standalone:!0,host:{"aria-hidden":"true"},template:`
2122
+ @if (overlay(); as o) {
2123
+ <!--
2124
+ Floating label above the page's top-left corner. Format:
2125
+ "Page 1 \u2014 800\xD7600" (per the answered user preference).
2126
+ text-anchor=start so the label aligns with the bracket TL.
2127
+ Font size and y-offset compensate for zoom so the label stays
2128
+ at constant CSS-pixel size across the zoom range.
2129
+ -->
2130
+ <svg:text
2131
+ class="page-label"
2132
+ [attr.x]="o.x"
2133
+ [attr.y]="o.y - labelOffsetDoc()"
2134
+ [attr.font-size]="labelFontSizeDoc() + 'px'"
2135
+ text-anchor="start"
2136
+ >
2137
+ {{ o.label }}
2138
+ </svg:text>
2139
+
2140
+ <!--
2141
+ **PAGES-REFACTOR follow-up #3** \u2014 invisible MOVE area covering
2142
+ the page interior. Replaces the dedicated move-handle square
2143
+ (top-center) \u2014 the user asked for "brackets only" visually but
2144
+ we still need a drag affordance, so we use the page interior
2145
+ itself (Illustrator/Affinity convention: with Artboard Tool
2146
+ active, dragging anywhere on the artboard moves it).
2147
+
2148
+ 'fill: transparent' + 'pointer-events: all' makes the entire
2149
+ rect clickable while staying visually invisible. Cursor: move
2150
+ gives the affordance hint. Rendered BEFORE the brackets so the
2151
+ bracket hit-areas (rendered LATER \u2192 on top) intercept clicks
2152
+ near the corners \u2192 start a resize drag instead of a move drag.
2153
+
2154
+ Because PageSelectionOverlay is mounted in the FRONT slot of
2155
+ SvgeRenderer, this rect sits ABOVE shape content. That's
2156
+ intentional: Page tool isn't for editing shapes, so click-
2157
+ through to shapes is undesirable \u2014 we want clicks on the page
2158
+ interior to move the page, not select a shape underneath.
2159
+ -->
2160
+ <svg:rect
2161
+ class="page-move-area"
2162
+ [attr.x]="o.x"
2163
+ [attr.y]="o.y"
2164
+ [attr.width]="o.width"
2165
+ [attr.height]="o.height"
2166
+ aria-label="Page move area \u2014 drag to reposition the page"
2167
+ role="button"
2168
+ (pointerdown)="onMoveHandlePointerDown($event)"
2169
+ (pointermove)="onHandlePointerMove($event)"
2170
+ (pointerup)="onHandlePointerUp($event)"
2171
+ ></svg:rect>
2172
+
2173
+ <!--
2174
+ Mid-edge brackets follow-up \u2014 4 single-line brackets centered
2175
+ on the midpoint of each edge, each wrapping an svg:g that
2176
+ owns a single-axis resize gesture. Visual style is identical
2177
+ to the corner Ls (same .page-bracket + .bracket-hit pair) \u2014
2178
+ only the shape differs (straight line aligned with the edge,
2179
+ not an L).
2180
+
2181
+ Rendered BEFORE the corner brackets so that when their hit
2182
+ areas overlap near a corner, SVG hit-testing picks the corner
2183
+ bracket (rendered later, on top) \u2192 2-axis resize wins over
2184
+ 1-axis at the actual corner pixels.
2185
+ -->
2186
+ <svg:g
2187
+ class="bracket-group bracket-t"
2188
+ aria-label="Page resize handle, top edge"
2189
+ role="button"
2190
+ (pointerdown)="onResizeHandlePointerDown($event, 't')"
2191
+ (pointermove)="onHandlePointerMove($event)"
2192
+ (pointerup)="onHandlePointerUp($event)"
2193
+ >
2194
+ <svg:path class="bracket-hit" [attr.d]="bracketT(o)"></svg:path>
2195
+ <svg:path class="page-bracket" [attr.d]="bracketT(o)"></svg:path>
2196
+ </svg:g>
2197
+ <svg:g
2198
+ class="bracket-group bracket-b"
2199
+ aria-label="Page resize handle, bottom edge"
2200
+ role="button"
2201
+ (pointerdown)="onResizeHandlePointerDown($event, 'b')"
2202
+ (pointermove)="onHandlePointerMove($event)"
2203
+ (pointerup)="onHandlePointerUp($event)"
2204
+ >
2205
+ <svg:path class="bracket-hit" [attr.d]="bracketB(o)"></svg:path>
2206
+ <svg:path class="page-bracket" [attr.d]="bracketB(o)"></svg:path>
2207
+ </svg:g>
2208
+ <svg:g
2209
+ class="bracket-group bracket-l"
2210
+ aria-label="Page resize handle, left edge"
2211
+ role="button"
2212
+ (pointerdown)="onResizeHandlePointerDown($event, 'l')"
2213
+ (pointermove)="onHandlePointerMove($event)"
2214
+ (pointerup)="onHandlePointerUp($event)"
2215
+ >
2216
+ <svg:path class="bracket-hit" [attr.d]="bracketL(o)"></svg:path>
2217
+ <svg:path class="page-bracket" [attr.d]="bracketL(o)"></svg:path>
2218
+ </svg:g>
2219
+ <svg:g
2220
+ class="bracket-group bracket-r"
2221
+ aria-label="Page resize handle, right edge"
2222
+ role="button"
2223
+ (pointerdown)="onResizeHandlePointerDown($event, 'r')"
2224
+ (pointermove)="onHandlePointerMove($event)"
2225
+ (pointerup)="onHandlePointerUp($event)"
2226
+ >
2227
+ <svg:path class="bracket-hit" [attr.d]="bracketR(o)"></svg:path>
2228
+ <svg:path class="page-bracket" [attr.d]="bracketR(o)"></svg:path>
2229
+ </svg:g>
2230
+
2231
+ <!--
2232
+ **PAGES-REFACTOR follow-up #3** \u2014 4 corner L-brackets, each
2233
+ wrapped in an svg:g that owns the resize drag gesture. The
2234
+ bracket-hit path under each visible bracket gives a wider
2235
+ invisible stroke for comfortable click targeting (visible
2236
+ stroke is only ~3 CSS px wide). Cursor + anchor are corner-
2237
+ specific (nwse-resize for tl/br diagonal, nesw-resize for
2238
+ tr/bl anti-diagonal \u2014 Illustrator/Figma convention).
2239
+
2240
+ Rendered AFTER the move-area AND the mid-edge brackets so SVG
2241
+ hit-testing picks the corner bracket first when the pointer
2242
+ is near a corner \u2192 2-axis resize fires; mid-edge drag fires
2243
+ on the rest of each edge; everywhere else in the page interior
2244
+ \u2192 move drag.
2245
+ -->
2246
+ <svg:g
2247
+ class="bracket-group bracket-tl"
2248
+ aria-label="Page resize handle, top-left corner"
2249
+ role="button"
2250
+ (pointerdown)="onResizeHandlePointerDown($event, 'tl')"
2251
+ (pointermove)="onHandlePointerMove($event)"
2252
+ (pointerup)="onHandlePointerUp($event)"
2253
+ >
2254
+ <svg:path class="bracket-hit" [attr.d]="bracketTL(o)"></svg:path>
2255
+ <svg:path class="page-bracket" [attr.d]="bracketTL(o)"></svg:path>
2256
+ </svg:g>
2257
+ <svg:g
2258
+ class="bracket-group bracket-tr"
2259
+ aria-label="Page resize handle, top-right corner"
2260
+ role="button"
2261
+ (pointerdown)="onResizeHandlePointerDown($event, 'tr')"
2262
+ (pointermove)="onHandlePointerMove($event)"
2263
+ (pointerup)="onHandlePointerUp($event)"
2264
+ >
2265
+ <svg:path class="bracket-hit" [attr.d]="bracketTR(o)"></svg:path>
2266
+ <svg:path class="page-bracket" [attr.d]="bracketTR(o)"></svg:path>
2267
+ </svg:g>
2268
+ <svg:g
2269
+ class="bracket-group bracket-bl"
2270
+ aria-label="Page resize handle, bottom-left corner"
2271
+ role="button"
2272
+ (pointerdown)="onResizeHandlePointerDown($event, 'bl')"
2273
+ (pointermove)="onHandlePointerMove($event)"
2274
+ (pointerup)="onHandlePointerUp($event)"
2275
+ >
2276
+ <svg:path class="bracket-hit" [attr.d]="bracketBL(o)"></svg:path>
2277
+ <svg:path class="page-bracket" [attr.d]="bracketBL(o)"></svg:path>
2278
+ </svg:g>
2279
+ <svg:g
2280
+ class="bracket-group bracket-br"
2281
+ aria-label="Page resize handle, bottom-right corner"
2282
+ role="button"
2283
+ (pointerdown)="onResizeHandlePointerDown($event, 'br')"
2284
+ (pointermove)="onHandlePointerMove($event)"
2285
+ (pointerup)="onHandlePointerUp($event)"
2286
+ >
2287
+ <svg:path class="bracket-hit" [attr.d]="bracketBR(o)"></svg:path>
2288
+ <svg:path class="page-bracket" [attr.d]="bracketBR(o)"></svg:path>
2289
+ </svg:g>
2290
+ }
2291
+ `,changeDetection:U.OnPush,styles:[`.page-label{fill:var(--svge-page-overlay-stroke, #1976d2);font-family:system-ui,-apple-system,sans-serif;font-weight:500;pointer-events:none;-webkit-user-select:none;user-select:none}.page-bracket{fill:none;stroke:var(--svge-page-overlay-stroke, #1976d2);stroke-width:3;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke;pointer-events:none}.bracket-hit{fill:none;stroke:transparent;stroke-width:14;stroke-linecap:round;stroke-linejoin:round;vector-effect:non-scaling-stroke;pointer-events:stroke}.bracket-group{touch-action:none}.bracket-group.bracket-tl,.bracket-group.bracket-br{cursor:nwse-resize}.bracket-group.bracket-tr,.bracket-group.bracket-bl{cursor:nesw-resize}.bracket-group.bracket-t,.bracket-group.bracket-b{cursor:ns-resize}.bracket-group.bracket-l,.bracket-group.bracket-r{cursor:ew-resize}.page-move-area{fill:transparent;cursor:move;pointer-events:all;touch-action:none}
2292
+ `]}]}],ctorParameters:()=>[],propDecorators:{onEscape:[{type:fr,args:["document:keydown.escape",["$event"]]}]}});const em="SVGEngine";function B(r,e,t,n){return us(ro(r,{description:e,author:em,icon:t,category:n}))}function tm(){return[B(Hi,"Select, move and marquee shapes \u2014 the default tool.","near_me","tool"),B(Ui,"Create, resize and arrange pages (artboards).","crop_portrait","tool"),B(Wi,"Freehand pencil drawing.","gesture","tool"),B(fs,"B\xE9zier pen \u2014 place anchors, drag for curves.","draw","tool"),B(Ds,"Rectangle, ellipse and polygon tools.","category","tool"),B(Ps,"Add and edit text on the canvas.","title","tool"),B(Gs,"Eyedropper, knife, smooth, gradient, width and symbol sprayer.","build","tool"),B(Ai,"Arrow-key nudge for the current selection.","open_with","shortcut"),B(_a,"Canonical editor shortcuts (Undo/Redo, Group, Select All\u2026).","keyboard","shortcut"),B(Ks,"Built-in color palettes (greys, Material, Tailwind).","palette","palette"),B(Nl,"Extra color palettes (IBM, warm, cool, neon).","palette","palette"),B(Ol,"Starter shape library (star, arrow, heart\u2026).","category","library"),B(dd,"Reusable symbol library (master/instance).","widgets","library"),B(gd,"Calligraphic brush library for the Pencil tool.","brush","library"),B(ld,"Document templates (print, social, video formats).","dashboard","library"),B(pc,"Linear and radial gradient presets.","gradient","library"),B(Xc,"Tileable pattern library.","texture","library"),B(Gl,"One-click appearance presets (graphic styles).","style","library"),B(wd,"Clip-path shape library.","crop","library"),B(Pd,"Mask preset library.","masks","library"),B(Ea,"SVG import and export.","import_export","io"),B(Ta,"Export the document as a PNG image.","image","io"),B(Ra,"SVG optimization passes (precision, drop-defaults, prune-empty).","compress","optimizer"),B(Qa,"19 SVG filter effects (blur, shadows, glows, color, distortion).","auto_awesome","effect"),B(la,"Core File/Edit/Object menu, toolbar and context items.","menu","menu"),B(Ia,"Insert menu \u2014 shapes, text and image submenu.","add_box","menu"),B(xa,"Advanced Edit menu (compound paths, live boolean).","account_tree","menu"),B(Pa,"Option B menubar: Path/Tools/Window menus, Mask, and roadmap items.","schedule","menu")]}export{yo as ACTIVE_PAGE_STORAGE_KEY,il as ASSET_EXPORT_STORAGE_KEY,qo as AUTOSAVE_STORAGE_KEY,Le as ActiveDefsService,j as ActivePageService,rt as AlignmentService,cr as AnchorOverlay,Ce as AnchorSelectionService,at as AnimationService,bn as AssetExportPersistenceService,ut as AssetExportRegistry,wn as AssetExportRunner,In as AssetManagerService,mn as AutoSaveService,Tn as BBOX_ANCHORS,hd as BUILTIN_BRUSHES,bd as BUILTIN_CLIP_PATHS,Ja as BUILTIN_EFFECTS,gc as BUILTIN_GRADIENTS,zl as BUILTIN_GRAPHIC_STYLES,Sd as BUILTIN_MASKS,Kc as BUILTIN_PATTERNS,Cl as BUILTIN_SHAPES,cd as BUILTIN_SYMBOLS,ad as BUILTIN_TEMPLATES,xt as BrushLibraryService,Dt as BrushSelectionService,Ln as CHAIN_FILTER_ID_PREFIX,Bo as CHAIN_FILTER_SEPARATOR,Q as CONTEXT_MENU_SLOT,At as ChainFilterRegistry,Ct as ClipPathLibraryService,_e as ClipboardService,Io as DEFAULT_HELP_LINKS,Li as DEFAULT_HIT_TOLERANCE_PX,vs as DEFAULT_POLYGON_SIDES,ei as DEFAULT_STEP_MS,xe as DIRECT_SELECT_TOOL_ID,Is as ELLIPSE_TOOL_ID,$s as EYEDROPPER_TOOL_ID,ct as EffectRegistry,um as ExporterRegistry,sn as EyedropperToolService,dn as FindReplaceService,Tt as FullscreenService,js as GRADIENT_TOOL_ID,Bt as GradientEditingService,Ne as GradientLibraryService,dr as GradientOverlay,Oe as GradientToolService,Dn as GraphicStyleLibraryService,Jn as GridOverlay,Qn as GuidesOverlay,Th as HANDLE_DATA_ATTR,bt as HANDLE_SIZE_DEFAULT,ji as HANDLE_SIZE_MAX,Fi as HANDLE_SIZE_MIN,fo as HANDLE_SIZE_PRESETS,Ee as ImportPlacementService,un as ImportSettingsService,hm as ImporterRegistry,Yn as InlineTextEditor,ot as InlineTextEditorService,Sf as InsertSymbolInstanceCommand,Ns as InsertSymbolInstancesBatchCommand,lr as IsolationFilter,it as IsolationService,Bs as KNIFE_TOOL_ID,be as KeyObjectService,rn as KeybindingsService,an as KnifeToolService,or as LayersFilter,ne as LayersService,Ae as LibraryRegistry,y as MENU_SLOT,Hn as Marquee,nt as MarqueeService,Ot as MaskLibraryService,Me as MenuContributionRegistry,ym as OptimizeCommand,bm as OptimizerRegistry,tr as OutlineFilter,Pr as PAGE_TOOL_ID,It as PANEL_ID,Gi as PENCIL_TOOL_ID,gs as PEN_TOOL_ID,Er as PLACEHOLDER_TEXT,O as PLUGIN_API_VERSION,ks as POLYGON_TOOL_ID,st as PageDragService,er as PageOverlay,We as PagesService,Rt as PaletteRegistry,Lt as PanelHostService,Nt as PatternLibraryService,Wn as PenOverlay,ie as PenToolService,Kn as PencilOverlay,we as PencilToolService,nr as PixelPreviewFilter,yn as PlaybackService,Pt as PluginCatalog,Un as PluginLoader,nn as PluginManagerService,St as PluginRegistry,Mt as PluginStateStore,Js as RECENT_FILES_STORAGE_KEY,ws as RECTANGLE_TOOL_ID,lt as RecentFilesService,Gn as RotationPivot,Je as SELECT_TOOL_ID,Fs as SMOOTH_TOOL_ID,ko as SVGE_HELP_LINKS,Do as SVGE_PLUGIN_MODULE_LOADER,xo as SVGE_PLUGIN_TRUSTED_ORIGINS,zs as SYMBOL_SPRAYER_TOOL_ID,Ye as SelectSameService,en as SelectionAppearanceService,zn as SelectionOverlay,k as SelectionService,Vn as SetGradientCommand,xn as ShapeLibraryService,Xn as ShapeOverlay,se as ShapeToolService,tt as ShortcutRegistry,_t as ShortcutService,dt as SmartObjectActionsService,ln as SmoothToolService,tn as SnapGuides,ue as SnapService,vn as SnapshotsPersistenceService,ar as SvgeCanvasGestures,ir as SvgeImportPlacementOverlay,hr as SvgePageSelectionOverlay,rr as SvgePixelPreviewRaster,qn as SvgeShellInteractions,sr as SvgeViewportCullingDirective,Ke as SymbolLibraryService,Xe as SymbolSelectionService,ur as SymbolSprayerOverlay,Pe as SymbolSprayerPreviewService,Et as SymbolSprayerService,Ss as TEXT_TOOL_ID,me as TOOLBAR_SLOT,Sn as TemplateLibraryService,Se as ToolHostService,de as ToolRegistry,Yf as TraceImageCommand,kn as TraceProgressService,Ue as TransformService,$t as ViewportCullingService,Ro as WHEEL_ZOOM_SPEED_MAX,To as WHEEL_ZOOM_SPEED_MIN,Vs as WIDTH_TOOL_ID,No as WORKSPACE_FORMAT,Cr as WORKSPACE_SCHEMA_VERSION,cn as WidthToolService,Zn as WorkspaceBackground,L as WorkspaceService,Qc as a4LandscapeTemplate,Yc as a4PortraitTemplate,ce as allAnchors,Ie as anchorPoint,dl as arrowShape,hl as balloonShape,Uc as basketweavePattern,Ba as bevelEffect,Ca as blurEffect,Oc as bricksPattern,Ga as brightnessEffect,jo as buildGradientMarkup,qt as buildSymbolMarkup,xa as builtinAdvancedEditMenuPlugin,gd as builtinBrushesPlugin,wd as builtinClipPathsPlugin,_a as builtinEditorShortcutsPlugin,Qa as builtinEffectsPlugin,pc as builtinGradientsPlugin,Gl as builtinGraphicStylesPlugin,Ia as builtinInsertMenuPlugin,Ea as builtinIoPlugin,Pd as builtinMasksPlugin,la as builtinMenuContributionsPlugin,Ra as builtinOptimizersPlugin,Ks as builtinPalettesPlugin,Xc as builtinPatternsPlugin,Pa as builtinRoadmapMenuPlugin,Ol as builtinShapesPlugin,dd as builtinSymbolsPlugin,ld as builtinTemplatesPlugin,Jc as businessCardTemplate,H as capturePointer,Ic as checkerboardPattern,Gc as checkerboardSmallPattern,bl as checkmarkShape,Rc as chevronPattern,El as chevronShape,Ya as chromaticAberrationEffect,pd as circleClipPath,Ec as circlesPattern,mo as clampHandleSize,pl as cloudShape,Ni as collectNodeAncestorIds,ch as comboFromEvent,oo as comboMatches,es as computeAlignDeltas,ts as computeAlignToReferenceDeltas,Uh as computeAverageGap,rs as computeDistributeDeltas,os as computeDistributeSpacingDeltas,Hc as confettiPattern,Ha as contrastEffect,Tl as crescentMoonShape,xc as crossHatchPattern,yl as crossShape,Bc as crossesPattern,ml as diamondShape,Lc as diamondsPattern,Xa as displacementMapEffect,Mc as dotsDensePattern,Pc as dotsLargePattern,_c as dotsOffsetPattern,vc as dotsPattern,Ml as doubleArrowShape,wm as dropDefaultsOptimizer,Oa as dropShadowEffect,fd as ellipseClipPath,Fa as embossEffect,Fl as embossedStyle,vo as expandStrokeWithProfile,Nl as extraPalettesPlugin,Gs as extraToolsPlugin,ia as extractChainFilterId,sd as facebookCoverTemplate,kd as fadeBottomMask,Id as fadeLeftMask,Vl as filled3DStyle,vh as findNearestAnchor,Dr as findOwningNodeId,Xt as findRenderedNode,Ys as fitImportTransform,hh as formatCombo,fl as gearShape,$i as geometricHitTestElement,Sr as getCombinedBBox,ke as getRenderedNodeBBox,Rn as getRenderedNodeOBB,yt as getRenderedParentMatrix,Bl as glassStyle,Sc as graphPaperPattern,ja as grayscaleEffect,Dc as gridFinePattern,wc as gridPattern,wo as gridTargetsNear,Zi as guidesToSnapTargets,yd as heartClipPath,ul as heartShape,jc as heartsPattern,vl as hexagonShape,Al as hexagramShape,Wa as hueRotateEffect,$a as innerGlowEffect,Na as innerShadowEffect,nd as instagramPortraitTemplate,qc as instagramSquareTemplate,td as instagramStoryTemplate,za as invertEffect,po as isEditableTarget,ed as letterPortraitTemplate,gl as lightningShape,lc as linearAuroraGradient,Kl as linearBlueSkyGradient,dc as linearDeepSeaGradient,rc as linearDuskGradient,tc as linearEmberGradient,oc as linearForestGradient,ec as linearGrapeGradient,ac as linearGraphiteGradient,Wl as linearGreyGradient,uc as linearLavaGradient,Ql as linearMintGradient,Yl as linearOceanGradient,cc as linearPeachyGradient,sc as linearRoseGradient,ic as linearSkyFadeGradient,nc as linearSteelGradient,Jl as linearSunriseGradient,Xl as linearSunsetGradient,hc as linearTwilightGradient,bc as linesDiagonalPattern,yc as linesHorizontalPattern,kc as linesVerticalPattern,op as makeChainFilterId,$g as makeDisabledResolver,$l as neonStyle,Qi as nodesInsideMarquee,Ka as noiseEffect,kl as octagonShape,$c as octagonsPattern,lo as organizationalContainerPredicate,La as outerGlowEffect,jl as outlineStyle,Cs as pageBoundsIn,Ui as pageToolPlugin,xl as parallelogramShape,Fo as parseChainFilterId,En as parseCombo,Ws as parseWorkspace,fs as penToolPlugin,Wi as pencilToolPlugin,Il as pentagonShape,id as pinterestPinTemplate,qa as pixelateEffect,Wc as plaidPattern,gm as pngExporter,Ta as pngExporterPlugin,bo as pointsToPathD,Za as posterizeEffect,Im as precisionOptimizer,od as presentation169Template,eg as providePluginLoader,tm as provideSvgEngineEditorBuiltins,af as provideSvgEngineEditorScope,us as provideSvgEnginePlugin,Kh as provideSvgeHelpLinks,km as pruneEmptyGroupsOptimizer,Zl as radialNeonGradient,ql as radialSpotlightGradient,Zs as rectFromPoints,qi as rectsToSnapTargets,ys as regularPolygonPoints,pe as releasePointer,pm as renderPng,ns as resolveAlignReference,Xs as resolveDisabledSignal,Oi as resolveNodeIdFromEvent,so as resolveSelectableNodeId,ao as resolveSelectableNodeIdFromElement,Ji as resolveSnap,Sl as rightTriangleShape,md as roundedRectClipPath,Pl as roundedRectShape,Lo as runContribution,zi as sampleProfile,Ua as saturateEffect,Cc as scalesPattern,Hi as selectToolPlugin,Ai as selectionNudgePlugin,Va as sepiaEffect,Us as serializeWorkspace,Ds as shapeToolsPlugin,Ll as sketchStyle,Dd as softCircleMask,Rl as sparkleShape,xd as spotlightMask,vd as starClipPath,cl as starShape,Fc as starsPattern,qs as stretchImportTransform,xm as stripAuthoredTitlesOptimizer,zc as stripesDiagonalPattern,Vc as stripesVerticalPattern,fm as svgExporter,mm as svgImporter,Ps as textToolPlugin,Md as traceImageToPaths,Dl as trapezoidShape,wl as triangleShape,Nc as trianglesPattern,Zc as twitterCardTemplate,is as unionBBox,_l as upArrowShape,io as validateCombo,hs as validateExternalPluginManifest,Ac as wavesPattern,ro as withPluginMeta,rd as youtubeThumbnailTemplate,Tc as zigzagPattern};