js-cloudimage-hotspot 1.0.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.
- package/LICENSE +21 -0
- package/README.md +294 -0
- package/dist/a11y/aria.d.ts +7 -0
- package/dist/a11y/aria.d.ts.map +1 -0
- package/dist/a11y/focus.d.ts +9 -0
- package/dist/a11y/focus.d.ts.map +1 -0
- package/dist/a11y/keyboard.d.ts +14 -0
- package/dist/a11y/keyboard.d.ts.map +1 -0
- package/dist/core/CIHotspot.d.ts +48 -0
- package/dist/core/CIHotspot.d.ts.map +1 -0
- package/dist/core/ci-hotspot.d.ts +95 -0
- package/dist/core/ci-hotspot.d.ts.map +1 -0
- package/dist/core/config.d.ts +15 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/types.d.ts +227 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/editor/ci-hotspot-editor.d.ts +58 -0
- package/dist/editor/ci-hotspot-editor.d.ts.map +1 -0
- package/dist/editor/drag-manager.d.ts +18 -0
- package/dist/editor/drag-manager.d.ts.map +1 -0
- package/dist/editor/editor-toolbar.d.ts +26 -0
- package/dist/editor/editor-toolbar.d.ts.map +1 -0
- package/dist/editor/index.d.ts +3 -0
- package/dist/editor/index.d.ts.map +1 -0
- package/dist/editor/js-cloudimage-hotspot-editor.cjs.js +4 -0
- package/dist/editor/js-cloudimage-hotspot-editor.cjs.js.map +1 -0
- package/dist/editor/js-cloudimage-hotspot-editor.esm.js +1981 -0
- package/dist/editor/js-cloudimage-hotspot-editor.esm.js.map +1 -0
- package/dist/editor/js-cloudimage-hotspot-editor.min.js +4 -0
- package/dist/editor/js-cloudimage-hotspot-editor.min.js.map +1 -0
- package/dist/editor/property-panel.d.ts +17 -0
- package/dist/editor/property-panel.d.ts.map +1 -0
- package/dist/editor/selection-manager.d.ts +15 -0
- package/dist/editor/selection-manager.d.ts.map +1 -0
- package/dist/editor/types.d.ts +32 -0
- package/dist/editor/types.d.ts.map +1 -0
- package/dist/editor/undo-manager.d.ts +16 -0
- package/dist/editor/undo-manager.d.ts.map +1 -0
- package/dist/fullscreen/fullscreen.d.ts +14 -0
- package/dist/fullscreen/fullscreen.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/js-cloudimage-hotspot.cjs.js +2 -0
- package/dist/js-cloudimage-hotspot.cjs.js.map +1 -0
- package/dist/js-cloudimage-hotspot.esm.js +1408 -0
- package/dist/js-cloudimage-hotspot.esm.js.map +1 -0
- package/dist/js-cloudimage-hotspot.min.js +2 -0
- package/dist/js-cloudimage-hotspot.min.js.map +1 -0
- package/dist/markers/Marker.d.ts +10 -0
- package/dist/markers/Marker.d.ts.map +1 -0
- package/dist/markers/pulse.d.ts +9 -0
- package/dist/markers/pulse.d.ts.map +1 -0
- package/dist/popover/Popover.d.ts +41 -0
- package/dist/popover/Popover.d.ts.map +1 -0
- package/dist/popover/position.d.ts +6 -0
- package/dist/popover/position.d.ts.map +1 -0
- package/dist/popover/sanitize.d.ts +6 -0
- package/dist/popover/sanitize.d.ts.map +1 -0
- package/dist/popover/template.d.ts +9 -0
- package/dist/popover/template.d.ts.map +1 -0
- package/dist/react/index.cjs +2 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.js +1617 -0
- package/dist/react/index.js.map +1 -0
- package/dist/utils/cloudimage.d.ts +16 -0
- package/dist/utils/cloudimage.d.ts.map +1 -0
- package/dist/utils/coordinates.d.ts +17 -0
- package/dist/utils/coordinates.d.ts.map +1 -0
- package/dist/utils/dom.d.ts +13 -0
- package/dist/utils/dom.d.ts.map +1 -0
- package/dist/utils/events.d.ts +15 -0
- package/dist/utils/events.d.ts.map +1 -0
- package/dist/zoom/ScrollHint.d.ts +8 -0
- package/dist/zoom/ScrollHint.d.ts.map +1 -0
- package/dist/zoom/ZoomPan.d.ts +51 -0
- package/dist/zoom/ZoomPan.d.ts.map +1 -0
- package/dist/zoom/controls.d.ts +14 -0
- package/dist/zoom/controls.d.ts.map +1 -0
- package/dist/zoom/gestures.d.ts +28 -0
- package/dist/zoom/gestures.d.ts.map +1 -0
- package/dist/zoom/scroll-hint.d.ts +8 -0
- package/dist/zoom/scroll-hint.d.ts.map +1 -0
- package/dist/zoom/zoom-pan.d.ts +53 -0
- package/dist/zoom/zoom-pan.d.ts.map +1 -0
- package/package.json +97 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { CloudimageConfig, HotspotItem, Placement, Theme, TriggerMode } from '../core/types';
|
|
2
|
+
/** Editor configuration */
|
|
3
|
+
export interface EditorConfig {
|
|
4
|
+
/** Image source URL */
|
|
5
|
+
src: string;
|
|
6
|
+
/** Alt text for the image */
|
|
7
|
+
alt?: string;
|
|
8
|
+
/** Initial hotspots to load into the editor */
|
|
9
|
+
hotspots?: HotspotItem[];
|
|
10
|
+
/** Default trigger mode for new hotspots (default: 'click') */
|
|
11
|
+
defaultTrigger?: TriggerMode;
|
|
12
|
+
/** Default placement for new hotspots (default: 'top') */
|
|
13
|
+
defaultPlacement?: Placement;
|
|
14
|
+
/** Called whenever hotspots change */
|
|
15
|
+
onChange?: (hotspots: HotspotItem[]) => void;
|
|
16
|
+
/** Cloudimage CDN configuration (passed through to the internal viewer) */
|
|
17
|
+
cloudimage?: CloudimageConfig;
|
|
18
|
+
/** Maximum undo history size (default: 50) */
|
|
19
|
+
maxHistory?: number;
|
|
20
|
+
/** Theme — 'light' or 'dark' (default: 'light') */
|
|
21
|
+
theme?: Theme;
|
|
22
|
+
}
|
|
23
|
+
/** Snapshot of editor state for undo/redo */
|
|
24
|
+
export interface EditorSnapshot {
|
|
25
|
+
hotspots: HotspotItem[];
|
|
26
|
+
selectedId: string | null;
|
|
27
|
+
}
|
|
28
|
+
/** Editor mode */
|
|
29
|
+
export type EditorMode = 'select' | 'add';
|
|
30
|
+
/** Editor event names */
|
|
31
|
+
export type EditorEvent = 'hotspot:add' | 'hotspot:remove' | 'hotspot:update' | 'hotspot:select' | 'hotspot:deselect' | 'mode:change' | 'history:change' | 'change';
|
|
32
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/editor/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAElG,2BAA2B;AAC3B,MAAM,WAAW,YAAY;IAC3B,uBAAuB;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,sCAAsC;IACtC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;IAC7C,2EAA2E;IAC3E,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,kBAAkB;AAClB,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE1C,yBAAyB;AACzB,MAAM,MAAM,WAAW,GACnB,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,GAChB,kBAAkB,GAClB,aAAa,GACb,gBAAgB,GAChB,QAAQ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CIHotspotEditor } from './ci-hotspot-editor';
|
|
2
|
+
export declare class UndoManager {
|
|
3
|
+
private editor;
|
|
4
|
+
private undoStack;
|
|
5
|
+
private redoStack;
|
|
6
|
+
private maxHistory;
|
|
7
|
+
constructor(editor: CIHotspotEditor, maxHistory: number);
|
|
8
|
+
saveInitial(): void;
|
|
9
|
+
save(): void;
|
|
10
|
+
undo(): void;
|
|
11
|
+
redo(): void;
|
|
12
|
+
canUndo(): boolean;
|
|
13
|
+
canRedo(): boolean;
|
|
14
|
+
private notifyChange;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=undo-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"undo-manager.d.ts","sourceRoot":"","sources":["../../src/editor/undo-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,qBAAa,WAAW;IAMpB,OAAO,CAAC,MAAM;IALhB,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,SAAS,CAAwB;IACzC,OAAO,CAAC,UAAU,CAAS;gBAGjB,MAAM,EAAE,eAAe,EAC/B,UAAU,EAAE,MAAM;IAKpB,WAAW,IAAI,IAAI;IAMnB,IAAI,IAAI,IAAI;IASZ,IAAI,IAAI,IAAI;IASZ,IAAI,IAAI,IAAI;IAQZ,OAAO,IAAI,OAAO;IAIlB,OAAO,IAAI,OAAO;IAIlB,OAAO,CAAC,YAAY;CAIrB"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface FullscreenControlOptions {
|
|
2
|
+
onChange?: (isFullscreen: boolean) => void;
|
|
3
|
+
}
|
|
4
|
+
export interface FullscreenControl {
|
|
5
|
+
element: HTMLElement;
|
|
6
|
+
isFullscreen: () => boolean;
|
|
7
|
+
toggle: () => void;
|
|
8
|
+
enter: () => void;
|
|
9
|
+
exit: () => void;
|
|
10
|
+
destroy: () => void;
|
|
11
|
+
}
|
|
12
|
+
/** Create a fullscreen toggle button for the container */
|
|
13
|
+
export declare function createFullscreenControl(container: HTMLElement, options?: FullscreenControlOptions): FullscreenControl | null;
|
|
14
|
+
//# sourceMappingURL=fullscreen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fullscreen.d.ts","sourceRoot":"","sources":["../../src/fullscreen/fullscreen.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,CAAC,YAAY,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,WAAW,CAAC;IACrB,YAAY,EAAE,MAAM,OAAO,CAAC;IAC5B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA2CD,0DAA0D;AAC1D,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,WAAW,EACtB,OAAO,GAAE,wBAA6B,GACrC,iBAAiB,GAAG,IAAI,CAoF1B"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CIHotspotConfig, CIHotspotInstance, HotspotItem, CloudimageConfig, PopoverData, Placement, TriggerMode, Theme, Scene, SceneTransition } from './core/types';
|
|
2
|
+
export type { CIHotspotConfig, CIHotspotInstance, HotspotItem, CloudimageConfig, PopoverData, Placement, TriggerMode, Theme, Scene, SceneTransition, };
|
|
3
|
+
export { CIHotspot } from './core/ci-hotspot';
|
|
4
|
+
import { CIHotspot } from './core/ci-hotspot';
|
|
5
|
+
export default CIHotspot;
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,WAAW,EACX,KAAK,EACL,KAAK,EACL,eAAe,EAChB,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,SAAS,EACT,WAAW,EACX,KAAK,EACL,KAAK,EACL,eAAe,GAChB,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const et={alt:"",trigger:"hover",zoom:!1,zoomMax:4,zoomMin:1,theme:"light",pulse:!0,zoomControls:!0,placement:"top",lazyLoad:!0,sceneTransition:"fade",scrollHint:!0,invertMarkerTheme:!1,fullscreenButton:!0,zoomControlsPosition:"bottom-right"},ot={"data-ci-hotspot-src":{key:"src",type:"string"},"data-ci-hotspot-alt":{key:"alt",type:"string"},"data-ci-hotspot-items":{key:"hotspots",type:"json"},"data-ci-hotspot-trigger":{key:"trigger",type:"string"},"data-ci-hotspot-zoom":{key:"zoom",type:"boolean"},"data-ci-hotspot-zoom-max":{key:"zoomMax",type:"number"},"data-ci-hotspot-zoom-min":{key:"zoomMin",type:"number"},"data-ci-hotspot-theme":{key:"theme",type:"string"},"data-ci-hotspot-pulse":{key:"pulse",type:"boolean"},"data-ci-hotspot-placement":{key:"placement",type:"string"},"data-ci-hotspot-lazy-load":{key:"lazyLoad",type:"boolean"},"data-ci-hotspot-zoom-controls":{key:"zoomControls",type:"boolean"},"data-ci-hotspot-scroll-hint":{key:"scrollHint",type:"boolean"},"data-ci-hotspot-ci-token":{key:"token",type:"string",nested:"cloudimage"},"data-ci-hotspot-ci-api-version":{key:"apiVersion",type:"string",nested:"cloudimage"},"data-ci-hotspot-ci-domain":{key:"domain",type:"string",nested:"cloudimage"},"data-ci-hotspot-ci-limit-factor":{key:"limitFactor",type:"number",nested:"cloudimage"},"data-ci-hotspot-ci-params":{key:"params",type:"string",nested:"cloudimage"},"data-ci-hotspot-scenes":{key:"scenes",type:"json"},"data-ci-hotspot-initial-scene":{key:"initialScene",type:"string"},"data-ci-hotspot-scene-transition":{key:"sceneTransition",type:"string"},"data-ci-hotspot-scene-aspect-ratio":{key:"sceneAspectRatio",type:"string"},"data-ci-hotspot-invert-marker-theme":{key:"invertMarkerTheme",type:"boolean"},"data-ci-hotspot-fullscreen-button":{key:"fullscreenButton",type:"boolean"},"data-ci-hotspot-zoom-controls-position":{key:"zoomControlsPosition",type:"string"}};function it(s){const t={},e={};for(const[o,i]of Object.entries(ot)){const a=s.getAttribute(o);if(a===null)continue;const n=st(a,i.type);i.nested==="cloudimage"?e[i.key]=n:t[i.key]=n}return Object.keys(e).length>0&&(t.cloudimage=e),t}function st(s,t){switch(t){case"boolean":return s==="true";case"number":{const e=parseFloat(s);if(isNaN(e)){console.warn(`CIHotspot: invalid number value "${s}"`);return}return e}case"json":try{return JSON.parse(s)}catch{console.warn(`CIHotspot: failed to parse JSON value "${s}"`);return}default:return s}}function O(s){return{...et,...s,src:s.src||"",hotspots:s.hotspots||[]}}function X(s){if(s.scenes&&s.scenes.length>0){const t=new Set;for(const e of s.scenes){if(!e.id)throw new Error('CIHotspot: each scene must have an "id"');if(t.has(e.id))throw new Error(`CIHotspot: duplicate scene ID "${e.id}"`);if(t.add(e.id),!e.src)throw new Error(`CIHotspot: scene "${e.id}" must have a "src"`)}for(const e of s.scenes)for(const o of e.hotspots||[])if(o.navigateTo&&!t.has(o.navigateTo))throw new Error(`CIHotspot: hotspot "${o.id}" navigateTo "${o.navigateTo}" is not a valid scene ID`);if(s.initialScene&&!t.has(s.initialScene))throw new Error(`CIHotspot: initialScene "${s.initialScene}" not found in scenes`)}else if(!s.src)throw new Error('CIHotspot: "src" is required')}const $="ci-hotspot-styles";function K(){return typeof window<"u"&&typeof document<"u"}function nt(s){if(typeof s=="string"){const t=document.querySelector(s);if(!t)throw new Error(`CIHotspot: element "${s}" not found`);return t}return s}function g(s,t,e){const o=document.createElement(s);if(t&&(o.className=t),e)for(const[i,a]of Object.entries(e))o.setAttribute(i,a);return o}function m(s,...t){s.classList.add(...t)}function b(s,...t){s.classList.remove(...t)}function rt(s){if(!K()||document.getElementById($))return;const t=document.createElement("style");t.id=$,t.textContent=s,document.head.appendChild(t)}function W(s){if(typeof s=="string"){const t=s.trim();return t.endsWith("%")?{value:parseFloat(t),isPercent:!0}:{value:parseFloat(t),isPercent:!1}}return{value:s,isPercent:!1}}function N(s,t,e,o){const i=W(s),a=W(t);return{x:i.isPercent?i.value:i.value/e*100,y:a.isPercent?a.value:a.value/o*100}}function f(s,t,e,o){return s.addEventListener(t,e,o),()=>s.removeEventListener(t,e,o)}function at(s,t){const e=g("button","ci-hotspot-marker",{"aria-label":s.label,"aria-expanded":"false","data-hotspot-id":s.id,tabindex:"0"});if(e.style.left=`${s.x}%`,e.style.top=`${s.y}%`,s.className){const o=s.className.trim().split(/\s+/).filter(Boolean);o.length&&m(e,...o)}return s.hidden&&m(e,"ci-hotspot-marker--hidden"),t&&m(e,"ci-hotspot-marker--pulse"),s.icon&&ht(e,s.icon),e}function ct(s){if(typeof DOMParser>"u")return"";const e=new DOMParser().parseFromString(s,"image/svg+xml").documentElement;return e.querySelector("parsererror")?"":(J(e),new XMLSerializer().serializeToString(e))}const lt=new Set(["script","foreignobject","iframe","object","embed","animate","animatetransform","animatemotion","set","style","a","use","image","feimage"]);function J(s){for(const t of Array.from(s.attributes)){const e=t.name.toLowerCase();(e.startsWith("on")||e==="style"||(e==="href"||e==="xlink:href")&&/^\s*javascript\s*:/i.test(t.value))&&s.removeAttribute(t.name)}for(const t of Array.from(s.children)){if(lt.has(t.tagName.toLowerCase())){t.remove();continue}J(t)}}function ht(s,t){const e=t.trim();if(/^<svg[\s>]/i.test(e)||/^<\?xml/i.test(e))s.innerHTML=ct(t);else if(t.match(/\.(png|jpg|jpeg|gif|svg|webp)$/i)||t.startsWith("http")||t.startsWith("/")){const o=g("img",void 0,{src:t,alt:"","aria-hidden":"true"});o.style.width="100%",o.style.height="100%",o.style.objectFit="contain",s.appendChild(o)}else{const o=g("span",t,{"aria-hidden":"true"});s.appendChild(o)}}function u(s,t){t?(m(s,"ci-hotspot-marker--active"),s.setAttribute("aria-expanded","true")):(b(s,"ci-hotspot-marker--active"),s.setAttribute("aria-expanded","false"))}function pt(s,t){t?m(s,"ci-hotspot-marker--hidden"):b(s,"ci-hotspot-marker--hidden")}function H(s){s.remove()}function dt(s,t,e,o){const i=s.getBoundingClientRect(),a=e.getBoundingClientRect(),n=t.offsetWidth,r=t.offsetHeight,c=i.left+i.width/2-a.left,l=i.top+i.height/2-a.top,h=i.top-a.top,d=i.bottom-a.top,p=i.left-a.left,v=i.right-a.left,E=e.offsetWidth,k=e.offsetHeight,w=8,Y={top:h-w,bottom:k-d-w,left:p-w,right:E-v-w};let x=o.placement;x==="auto"&&(x=ut(Y)),x=ft(x,n,r,Y);let T,z,Z=0;switch(x){case"top":T=c-n/2,z=h-w-r;break;case"bottom":T=c-n/2,z=d+w;break;case"left":T=p-w-n,z=l-r/2;break;case"right":T=v+w,z=l-r/2;break;default:T=c-n/2,z=h-w-r}const P=mt(T,z,n,r,E,k);return Z=x==="top"||x==="bottom"?T-P.x:z-P.y,{x:P.x,y:P.y,placement:x,arrowOffset:Z}}function ut(s){const t=Math.max(s.top,s.bottom,s.left,s.right);return t===s.top?"top":t===s.bottom?"bottom":t===s.right?"right":"left"}function ft(s,t,e,o){const i=s;switch(i){case"top":if(o.top<e&&o.bottom>o.top)return"bottom";break;case"bottom":if(o.bottom<e&&o.top>o.bottom)return"top";break;case"left":if(o.left<t&&o.right>o.left)return"right";break;case"right":if(o.right<t&&o.left>o.right)return"left";break}return i}function mt(s,t,e,o,i,a){let r=s,c=t;return e>i-2*4?r=(i-e)/2:(r<4&&(r=4),r+e>i-4&&(r=i-4-e)),o>a-2*4?c=(a-o)/2:(c<4&&(c=4),c+o>a-4&&(c=a-4-o)),{x:r,y:c}}const gt=new Set(["a","b","br","div","em","h1","h2","h3","h4","h5","h6","i","img","li","ol","p","span","strong","ul"]),vt=new Set(["class","href","src","alt","title","target","rel"]),bt=/^(?:https?:|mailto:)/i,yt=/^(?:https?:|data:image\/(?!svg[+%]))/i,wt=new Set(["noopener","noreferrer","nofollow","external","author","help","license","next","prev","search","tag","bookmark"]);function kt(s){const o=new DOMParser().parseFromString(`<body>${s}</body>`,"text/html").body;return Q(o),o.innerHTML}function Q(s){const t=Array.from(s.childNodes);for(const e of t)if(e.nodeType!==Node.TEXT_NODE)if(e.nodeType===Node.ELEMENT_NODE){const o=e,i=o.tagName.toLowerCase();if(!gt.has(i)){o.remove();continue}const a=Array.from(o.attributes);for(const n of a){const r=n.name.toLowerCase();if(r.startsWith("on")){o.removeAttribute(n.name);continue}if(!vt.has(r)){o.removeAttribute(n.name);continue}if(r==="href"&&!bt.test(n.value.trim()))o.removeAttribute(n.name);else if(r==="src"&&!yt.test(n.value.trim()))o.removeAttribute(n.name);else if(r==="rel"){const c=n.value.trim().toLowerCase().split(/\s+/).filter(l=>wt.has(l));c.length===0?o.removeAttribute(n.name):o.setAttribute(n.name,c.join(" "))}}Q(o)}else e.remove()}function xt(s){const t=[];s.image&&t.push(`<img class="ci-hotspot-popover-image" src="${F(s.image)}" alt="${F(s.title||"")}">`);const e=[];if(s.title&&e.push(`<h3 class="ci-hotspot-popover-title">${M(s.title)}</h3>`),s.price&&e.push(`<span class="ci-hotspot-popover-price">${M(s.price)}</span>`),s.description&&e.push(`<p class="ci-hotspot-popover-description">${M(s.description)}</p>`),s.url&&Tt(s.url)){const o=s.ctaText||"View details";e.push(`<a class="ci-hotspot-popover-cta" href="${F(s.url)}">${M(String(o))}</a>`)}return e.length>0&&t.push(`<div class="ci-hotspot-popover-body">${e.join("")}</div>`),t.join("")}function Et(s,t){return t?t(s):s.content?kt(s.content):s.data?xt(s.data):""}function M(s){return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function Tt(s){const t=s.replace(/[\s\x00-\x1f]/g,"");return/^https?:\/\//i.test(t)||/^\/(?!\/)/.test(t)||/^#/.test(t)}function F(s){return s.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}class j{constructor(t,e){this.visible=!1,this.markerEl=null,this.containerEl=null,this.hoverCleanups=[],this.hotspot=t,this.options=e;const o=e.triggerMode==="click"||e.triggerMode==="load";this.element=g("div","ci-hotspot-popover",{role:o?"dialog":"tooltip",id:`ci-hotspot-popover-${t.id}`,"aria-hidden":"true","data-placement":e.placement==="auto"?"top":e.placement,...o&&t.label?{"aria-label":t.label}:{}}),this.arrowEl=g("div","ci-hotspot-popover-arrow"),this.contentEl=g("div","ci-hotspot-popover-content"),this.element.appendChild(this.arrowEl),this.element.appendChild(this.contentEl);const i=Et(t,e.renderFn);if(typeof i=="string"?this.contentEl.innerHTML=i:i instanceof HTMLElement&&this.contentEl.appendChild(i),e.triggerMode==="hover"){const a=()=>this.clearHideTimer(),n=()=>this.scheduleHide();this.element.addEventListener("mouseenter",a),this.element.addEventListener("mouseleave",n),this.hoverCleanups.push(()=>this.element.removeEventListener("mouseenter",a),()=>this.element.removeEventListener("mouseleave",n))}}mount(t,e){this.containerEl=t,this.markerEl=e,t.appendChild(this.element),this.options.triggerMode==="click"||this.options.triggerMode==="load"?(e.setAttribute("aria-haspopup","dialog"),e.setAttribute("aria-controls",this.element.id)):e.setAttribute("aria-describedby",this.element.id)}show(){var t,e;this.clearHideTimer(),!this.visible&&(this.visible=!0,m(this.element,"ci-hotspot-popover--visible"),this.element.setAttribute("aria-hidden","false"),this.updatePosition(),(e=(t=this.options).onOpen)==null||e.call(t,this.hotspot))}scheduleHide(t=200){this.clearHideTimer(),this.hideTimer=setTimeout(()=>{this.hide()},t)}hide(){var t,e;this.clearHideTimer(),this.visible&&(this.visible=!1,b(this.element,"ci-hotspot-popover--visible"),this.element.setAttribute("aria-hidden","true"),(e=(t=this.options).onClose)==null||e.call(t,this.hotspot))}clearHideTimer(){this.hideTimer!==void 0&&(clearTimeout(this.hideTimer),this.hideTimer=void 0)}updatePosition(){if(!this.markerEl||!this.containerEl||!this.visible)return;const t=dt(this.markerEl,this.element,this.containerEl,{placement:this.options.placement});this.element.style.left=`${t.x}px`,this.element.style.top=`${t.y}px`,this.element.setAttribute("data-placement",t.placement),this.positionArrow(t.placement,t.arrowOffset)}positionArrow(t,e){const o=this.arrowEl;o.style.left="",o.style.top="",t==="top"||t==="bottom"?o.style.left=`calc(50% - var(--ci-hotspot-arrow-size) + ${e}px)`:o.style.top=`calc(50% - var(--ci-hotspot-arrow-size) + ${e}px)`}isVisible(){return this.visible}getHotspot(){return this.hotspot}destroy(){var t,e,o;this.clearHideTimer(),this.hoverCleanups.forEach(i=>i()),this.hoverCleanups=[],(t=this.markerEl)==null||t.removeAttribute("aria-describedby"),(e=this.markerEl)==null||e.removeAttribute("aria-controls"),(o=this.markerEl)==null||o.removeAttribute("aria-haspopup"),this.element.remove(),this.markerEl=null,this.containerEl=null}}class zt{constructor(t,e,o){this.lastTouchEnd=0,this.initialPinchDistance=0,this.initialPinchScale=1,this.panStartX=0,this.panStartY=0,this.isPinching=!1,this.isPanning=!1,this.wasPinching=!1,this.cleanups=[],this.el=t,this.callbacks=e,this.initialPinchScale=o();const i=r=>this.handleTouchStart(r,o),a=r=>this.handleTouchMove(r),n=r=>this.handleTouchEnd(r);t.addEventListener("touchstart",i,{passive:!1}),t.addEventListener("touchmove",a,{passive:!1}),t.addEventListener("touchend",n,{passive:!0}),this.cleanups.push(()=>t.removeEventListener("touchstart",i),()=>t.removeEventListener("touchmove",a),()=>t.removeEventListener("touchend",n))}handleTouchStart(t,e){t.touches.length===2?(t.preventDefault(),this.isPinching=!0,this.wasPinching=!1,this.initialPinchDistance=this.getTouchDistance(t.touches),this.initialPinchScale=e()):t.touches.length===1&&(this.panStartX=t.touches[0].clientX,this.panStartY=t.touches[0].clientY,this.wasPinching=!1)}handleTouchMove(t){var e,o,i,a,n,r;if(t.touches.length===2&&this.isPinching){t.preventDefault();const c=this.getTouchDistance(t.touches),l=this.initialPinchScale*(c/this.initialPinchDistance),h=(t.touches[0].clientX+t.touches[1].clientX)/2,d=(t.touches[0].clientY+t.touches[1].clientY)/2;(o=(e=this.callbacks).onPinch)==null||o.call(e,l,h,d)}else if(t.touches.length===1&&!this.isPinching&&!this.wasPinching){this.isPanning||(this.isPanning=!0,(a=(i=this.callbacks).onPanStart)==null||a.call(i));const c=t.touches[0].clientX-this.panStartX,l=t.touches[0].clientY-this.panStartY;(r=(n=this.callbacks).onPan)==null||r.call(n,c,l)}}handleTouchEnd(t){var e,o,i,a;if(this.isPinching&&t.touches.length<2&&(this.isPinching=!1,this.wasPinching=!0,t.touches.length===1&&(this.panStartX=t.touches[0].clientX,this.panStartY=t.touches[0].clientY)),this.isPanning&&(this.isPanning=!1,(o=(e=this.callbacks).onPanEnd)==null||o.call(e)),t.changedTouches.length===1&&t.touches.length===0){if(this.wasPinching){this.wasPinching=!1,this.lastTouchEnd=0;return}const n=Date.now();if(n-this.lastTouchEnd<300){const r=t.changedTouches[0];(a=(i=this.callbacks).onDoubleTap)==null||a.call(i,r.clientX,r.clientY)}this.lastTouchEnd=n}}getTouchDistance(t){const e=t[0].clientX-t[1].clientX,o=t[0].clientY-t[1].clientY;return Math.sqrt(e*e+o*o)}destroy(){this.cleanups.forEach(t=>t()),this.cleanups=[]}}class Ct{constructor(t,e,o){this.zoom=1,this.panX=0,this.panY=0,this.enabled=!0,this.isDragging=!1,this.dragStartX=0,this.dragStartY=0,this.lastPanX=0,this.lastPanY=0,this.gestures=null,this.isGesturing=!1,this.gestureStartZoom=1,this.touchStartPanX=0,this.touchStartPanY=0,this.cleanups=[],this.viewport=t,this.container=e,this.options=o,this.bindEvents()}bindEvents(){const t=n=>{var p,v;if(!this.enabled)return;if(this.isGesturing){n.preventDefault();return}if(!n.ctrlKey){(v=(p=this.options).onScrollWithoutZoom)==null||v.call(p);return}n.preventDefault();const r=this.container.getBoundingClientRect(),c=n.clientX-r.left,l=n.clientY-r.top;let h=n.deltaY;n.deltaMode===1&&(h*=20);const d=-h*.01;this.setZoom(this.zoom+d,c,l)};this.container.addEventListener("wheel",t,{passive:!1}),this.cleanups.push(()=>this.container.removeEventListener("wheel",t)),this.bindSafariGestures();const e=n=>{if(!this.enabled)return;const r=this.container.getBoundingClientRect(),c=n.clientX-r.left,l=n.clientY-r.top;this.zoom>1?this.resetZoom():this.setZoom(2,c,l)};this.container.addEventListener("dblclick",e),this.cleanups.push(()=>this.container.removeEventListener("dblclick",e));const o=n=>{!this.enabled||this.zoom<=1||n.button===0&&(this.isDragging=!0,this.dragStartX=n.clientX,this.dragStartY=n.clientY,this.lastPanX=this.panX,this.lastPanY=this.panY,m(this.viewport,"ci-hotspot-viewport--dragging"),this.container.style.cursor="grabbing",n.preventDefault())},i=n=>{if(!this.isDragging)return;const r=(n.clientX-this.dragStartX)/this.zoom,c=(n.clientY-this.dragStartY)/this.zoom;this.panX=this.lastPanX+r,this.panY=this.lastPanY+c,this.clampPan(),this.applyTransform()},a=()=>{this.isDragging&&(this.isDragging=!1,b(this.viewport,"ci-hotspot-viewport--dragging"),this.container.style.cursor=this.zoom>1?"grab":"")};this.container.addEventListener("mousedown",o),document.addEventListener("mousemove",i),document.addEventListener("mouseup",a),this.cleanups.push(()=>this.container.removeEventListener("mousedown",o),()=>document.removeEventListener("mousemove",i),()=>document.removeEventListener("mouseup",a)),this.gestures=new zt(this.container,{onPinch:(n,r,c)=>{const l=this.container.getBoundingClientRect();this.setZoom(n,r-l.left,c-l.top)},onPanStart:()=>{this.touchStartPanX=this.panX,this.touchStartPanY=this.panY},onPan:(n,r)=>{this.zoom<=1||(this.panX=this.touchStartPanX+n/this.zoom,this.panY=this.touchStartPanY+r/this.zoom,this.clampPan(),this.applyTransform())},onDoubleTap:(n,r)=>{const c=this.container.getBoundingClientRect();this.zoom>1?this.resetZoom():this.setZoom(2,n-c.left,r-c.top)}},()=>this.zoom)}bindSafariGestures(){if(typeof window>"u"||!("GestureEvent"in window))return;const t=i=>{i.preventDefault(),this.isGesturing=!0,this.gestureStartZoom=this.zoom},e=i=>{if(i.preventDefault(),!this.enabled)return;const a=i,n=this.container.getBoundingClientRect(),r=i,c=r.clientX!=null?r.clientX-n.left:n.width/2,l=r.clientY!=null?r.clientY-n.top:n.height/2;this.setZoom(this.gestureStartZoom*a.scale,c,l)},o=i=>{i.preventDefault(),this.isGesturing=!1};this.container.addEventListener("gesturestart",t),this.container.addEventListener("gesturechange",e),this.container.addEventListener("gestureend",o),this.cleanups.push(()=>this.container.removeEventListener("gesturestart",t),()=>this.container.removeEventListener("gesturechange",e),()=>this.container.removeEventListener("gestureend",o))}setZoom(t,e,o){var a,n;const i=this.zoom;if(this.zoom=Math.max(this.options.zoomMin,Math.min(this.options.zoomMax,t)),e!==void 0&&o!==void 0&&i!==this.zoom){const r=this.container.offsetWidth,c=this.container.offsetHeight,l=this.zoom/i,h=e/r,d=o/c;this.panX=this.panX-r*h*(l-1)/this.zoom,this.panY=this.panY-c*d*(l-1)/this.zoom}this.clampPan(),this.applyTransform(),this.updateCursor(),(n=(a=this.options).onZoom)==null||n.call(a,this.zoom)}getZoom(){return this.zoom}resetZoom(){var t,e;this.zoom=1,this.panX=0,this.panY=0,this.applyTransform(),this.updateCursor(),(e=(t=this.options).onZoom)==null||e.call(t,1)}pan(t,e){this.zoom<=1||(this.panX+=t/this.zoom,this.panY+=e/this.zoom,this.clampPan(),this.applyTransform())}enable(){this.enabled=!0}disable(){this.enabled=!1}clampPan(){const t=this.container.offsetWidth,e=this.container.offsetHeight,o=t*(this.zoom-1)/this.zoom,i=e*(this.zoom-1)/this.zoom;this.panX=Math.max(-o,Math.min(0,this.panX)),this.panY=Math.max(-i,Math.min(0,this.panY)),this.zoom<=1&&(this.panX=0,this.panY=0)}applyTransform(){this.viewport.style.transform=`scale(${this.zoom}) translate(${this.panX}px, ${this.panY}px)`,this.viewport.style.setProperty("--zoom",String(this.zoom))}updateCursor(){this.isDragging||(this.container.style.cursor=this.zoom>1?"grab":"")}destroy(){var t;this.cleanups.forEach(e=>e()),this.cleanups=[],(t=this.gestures)==null||t.destroy(),this.gestures=null,this.viewport.style.transform="",this.viewport.style.removeProperty("--zoom"),this.container.style.cursor=""}}function St(s,t,e){const o=e.zoomStep||.5,i=g("div","ci-hotspot-zoom-controls");i.dataset.position=e.position||"bottom-right";const a=g("button","ci-hotspot-zoom-in",{"aria-label":"Zoom in",type:"button"});a.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" x2="16.65" y1="21" y2="16.65"/><line x1="11" x2="11" y1="8" y2="14"/><line x1="8" x2="14" y1="11" y2="11"/></svg>';const n=g("button","ci-hotspot-zoom-out",{"aria-label":"Zoom out",type:"button"});n.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" x2="16.65" y1="21" y2="16.65"/><line x1="8" x2="14" y1="11" y2="11"/></svg>';const r=g("button","ci-hotspot-zoom-reset",{"aria-label":"Reset zoom",type:"button"});r.innerHTML='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>',i.appendChild(a),i.appendChild(n),i.appendChild(r),a.addEventListener("click",l=>{l.stopPropagation(),t.setZoom(t.getZoom()+o),c()}),n.addEventListener("click",l=>{l.stopPropagation(),t.setZoom(t.getZoom()-o),c()}),r.addEventListener("click",l=>{l.stopPropagation(),t.resetZoom(),c()});function c(){const l=t.getZoom();a.disabled=l>=e.zoomMax,n.disabled=l<=e.zoomMin,r.disabled=Math.abs(l-1)<.001}return s.appendChild(i),c(),{element:i,update:c,destroy:()=>i.remove()}}const Pt=typeof navigator<"u"&&/Mac|iPhone|iPad|iPod/i.test(navigator.userAgent),Ht=Pt?"⌘ Scroll or pinch to zoom":"Ctrl + scroll to zoom",Mt=1500;class Lt{constructor(t){this.hideTimer=null,this.el=document.createElement("div"),this.el.className="ci-hotspot-scroll-hint",this.el.textContent=Ht,this.el.setAttribute("aria-hidden","true"),t.appendChild(this.el)}show(){this.hideTimer!==null&&clearTimeout(this.hideTimer),this.el.classList.add("ci-hotspot-scroll-hint--visible"),this.hideTimer=setTimeout(()=>{this.el.classList.remove("ci-hotspot-scroll-hint--visible"),this.hideTimer=null},Mt)}destroy(){this.hideTimer!==null&&(clearTimeout(this.hideTimer),this.hideTimer=null),this.el.remove()}}const At="cloudimg.io",Dt="v7",I=100;function It(s,t=I){return Math.ceil(s/t)*t}function tt(s,t=1,e=1,o=I){const i=s*t*e;return It(i,o)}function C(s,t,e,o=1,i=1){const a=t.domain||At,n=t.apiVersion||Dt,r=t.limitFactor||I,c=tt(e,i,o,r),l=encodeURI(s);let h=`https://${t.token}.${a}/${n}/${l}?width=${c}`;return t.params&&(h+=`&${t.params}`),h}function Ft(s,t,e,o){const i=e.limitFactor||I;let a=0;const n=new ResizeObserver(r=>{for(const c of r){const l=c.contentRect.width;if(l===0)continue;const h=typeof window<"u"&&window.devicePixelRatio||1,d=tt(l,h,o(),i);d!==a&&(a=d,s.src=C(t,e,l,o(),h))}});return{observer:n,destroy:()=>n.disconnect()}}const L=50,V=.5;class Rt{constructor(t){this.cleanups=[];const{container:e,getZoomPan:o,onEscape:i,onFullscreenToggle:a}=t,n=f(e,"keydown",r=>{const c=r.target;if(c.tagName==="INPUT"||c.tagName==="TEXTAREA"||c.tagName==="SELECT")return;const l=o();switch(r.key){case"Escape":i==null||i();break;case"ArrowUp":l&&l.getZoom()>1&&(r.preventDefault(),l.pan(0,L));break;case"ArrowDown":l&&l.getZoom()>1&&(r.preventDefault(),l.pan(0,-L));break;case"ArrowLeft":l&&l.getZoom()>1&&(r.preventDefault(),l.pan(L,0));break;case"ArrowRight":l&&l.getZoom()>1&&(r.preventDefault(),l.pan(-L,0));break;case"+":case"=":l&&(r.preventDefault(),l.setZoom(l.getZoom()+V));break;case"-":l&&(r.preventDefault(),l.setZoom(l.getZoom()-V));break;case"0":l&&(r.preventDefault(),l.resetZoom());break;case"f":a&&(r.preventDefault(),a());break}});this.cleanups.push(n)}destroy(){this.cleanups.forEach(t=>t()),this.cleanups=[]}}const Yt='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';function _(s){return Array.from(s.querySelectorAll(Yt))}function B(s,t){let e=!1,o=null;function i(){if(e)return;e=!0;const r=_(s);r.length!==0&&(r[0].focus(),o=f(s,"keydown",c=>{if(c.key!=="Tab")return;const l=_(s);if(l.length===0)return;const h=l[0],d=l[l.length-1];c.shiftKey&&document.activeElement===h?(c.preventDefault(),d.focus()):!c.shiftKey&&document.activeElement===d&&(c.preventDefault(),h.focus())}))}function a(){e&&(e=!1,o==null||o(),o=null,t.focus())}function n(){a()}return{activate:i,deactivate:a,destroy:n}}let y=null,A=0;function Zt(s){K()&&(y||(y=g("div",void 0,{"aria-live":"polite","aria-atomic":"true",role:"status"}),y.style.cssText="position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0",document.body.appendChild(y)),y.textContent="",requestAnimationFrame(()=>{y&&(y.textContent=s)}))}function G(){A++}function Ot(){A=Math.max(0,A-1),A===0&&y&&(y.remove(),y=null)}const q='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" x2="14" y1="3" y2="10"/><line x1="3" x2="10" y1="21" y2="14"/></svg>',Xt='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="4 14 10 14 10 20"/><polyline points="20 10 14 10 14 4"/><line x1="14" x2="21" y1="10" y2="3"/><line x1="3" x2="10" y1="21" y2="14"/></svg>';function $t(){return!!(document.fullscreenEnabled||document.webkitFullscreenEnabled)}function Wt(){return document.fullscreenElement||document.webkitFullscreenElement||null}function U(s){return s.requestFullscreen?s.requestFullscreen():s.webkitRequestFullscreen?(s.webkitRequestFullscreen(),Promise.resolve()):Promise.reject(new Error("Fullscreen API not supported"))}function R(){return document.exitFullscreen?document.exitFullscreen():document.webkitExitFullscreen?(document.webkitExitFullscreen(),Promise.resolve()):Promise.reject(new Error("Fullscreen API not supported"))}function Nt(s,t={}){if(!$t())return null;const e=g("button","ci-hotspot-fullscreen-btn",{"aria-label":"Enter fullscreen","aria-pressed":"false",type:"button"});e.innerHTML=q;const o=[];function i(){return Wt()===s}function a(){var v;const p=i();e.innerHTML=p?Xt:q,e.setAttribute("aria-label",p?"Exit fullscreen":"Enter fullscreen"),e.setAttribute("aria-pressed",String(p)),p?m(s,"ci-hotspot-container--fullscreen"):b(s,"ci-hotspot-container--fullscreen"),(v=t.onChange)==null||v.call(t,p)}function n(){i()?R().catch(()=>{}):U(s).catch(()=>{})}function r(){i()||U(s).catch(()=>{})}function c(){i()&&R().catch(()=>{})}const l=f(document,"fullscreenchange",a);o.push(l),document.addEventListener("webkitfullscreenchange",a),o.push(()=>document.removeEventListener("webkitfullscreenchange",a));const h=f(e,"click",p=>{p.stopPropagation(),n()});o.push(h),s.appendChild(e);function d(){i()&&R().catch(()=>{}),b(s,"ci-hotspot-container--fullscreen"),o.forEach(p=>p()),o.length=0,e.remove()}return{element:e,isFullscreen:i,toggle:n,enter:r,exit:c,destroy:d}}const jt='.ci-hotspot-container{--ci-hotspot-marker-size: 24px;--ci-hotspot-marker-color: #ffffff;--ci-hotspot-marker-bg: rgba(0, 0, 0, .6);--ci-hotspot-marker-border-width: 2px;--ci-hotspot-marker-border-color: rgba(255, 255, 255, .8);--ci-hotspot-marker-border: var(--ci-hotspot-marker-border-width) solid var(--ci-hotspot-marker-border-color);--ci-hotspot-marker-border-radius: 50%;--ci-hotspot-marker-shadow: 0 2px 8px rgba(0, 0, 0, .3);--ci-hotspot-pulse-color: rgba(0, 0, 0, .2);--ci-hotspot-pulse-size: 40px;--ci-hotspot-pulse-duration: 1.8s;--ci-hotspot-popover-bg: #ffffff;--ci-hotspot-popover-color: #1a1a1a;--ci-hotspot-popover-border: 1px solid rgba(0, 0, 0, .1);--ci-hotspot-popover-border-radius: 12px;--ci-hotspot-popover-shadow: 0 8px 32px rgba(0, 0, 0, .12);--ci-hotspot-popover-padding: 16px;--ci-hotspot-popover-max-width: 320px;--ci-hotspot-popover-max-height: 400px;--ci-hotspot-popover-font-family: inherit;--ci-hotspot-popover-font-size: 14px;--ci-hotspot-popover-line-height: 1.5;--ci-hotspot-popover-z-index: 1000;--ci-hotspot-arrow-size: 8px;--ci-hotspot-arrow-color: var(--ci-hotspot-popover-bg);--ci-hotspot-title-font-size: 16px;--ci-hotspot-title-font-weight: 600;--ci-hotspot-title-color: #1a1a1a;--ci-hotspot-price-color: #2d8c3c;--ci-hotspot-price-font-size: 18px;--ci-hotspot-price-font-weight: 700;--ci-hotspot-description-color: #666666;--ci-hotspot-cta-bg: #0058a3;--ci-hotspot-cta-color: #ffffff;--ci-hotspot-cta-border-radius: 8px;--ci-hotspot-cta-padding: 8px 16px;--ci-hotspot-hover-transition: .2s ease;--ci-hotspot-popover-transition: .3s ease;--ci-hotspot-scene-transition-duration: .4s;--ci-hotspot-zoom-controls-bg: rgba(255, 255, 255, .9);--ci-hotspot-zoom-controls-color: #333333;--ci-hotspot-zoom-controls-border-radius: 8px;--ci-hotspot-zoom-controls-shadow: 0 2px 8px rgba(0, 0, 0, .15)}.ci-hotspot-container *,.ci-hotspot-container *:before,.ci-hotspot-container *:after{box-sizing:border-box}.ci-hotspot-container{position:relative;overflow:hidden;width:100%;line-height:0;user-select:none;-webkit-user-select:none}.ci-hotspot-viewport{position:relative;width:100%;transform-origin:0 0;will-change:transform;transition:transform .3s ease}.ci-hotspot-viewport--dragging{transition:none}.ci-hotspot-image{display:block;width:100%;height:auto;pointer-events:none}.ci-hotspot-markers{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.ci-hotspot-marker{position:absolute;width:var(--ci-hotspot-marker-size);height:var(--ci-hotspot-marker-size);padding:0;border:var(--ci-hotspot-marker-border);border-radius:var(--ci-hotspot-marker-border-radius);background:var(--ci-hotspot-marker-bg);color:var(--ci-hotspot-marker-color);box-shadow:var(--ci-hotspot-marker-shadow);cursor:pointer;pointer-events:auto;transform:translate(-50%,-50%) scale(calc(1 / var(--zoom, 1)));transition:transform var(--ci-hotspot-hover-transition),box-shadow var(--ci-hotspot-hover-transition);z-index:1;display:flex;align-items:center;justify-content:center;font-size:12px;line-height:1;outline:none}.ci-hotspot-marker:hover{transform:translate(-50%,-50%) scale(calc(1.2 / var(--zoom, 1)));box-shadow:0 4px 12px #0006}.ci-hotspot-marker:focus-visible{outline:3px solid var(--ci-hotspot-focus-ring, #4A90D9);outline-offset:2px}.ci-hotspot-marker--active{transform:translate(-50%,-50%) scale(calc(1.2 / var(--zoom, 1)));z-index:2}.ci-hotspot-marker--hidden{display:none}.ci-hotspot-marker--pulse:before{content:"";position:absolute;top:50%;left:50%;width:var(--ci-hotspot-pulse-size);height:var(--ci-hotspot-pulse-size);border-radius:50%;background:var(--ci-hotspot-pulse-color);transform:translate(-50%,-50%) scale(1);animation:ci-hotspot-pulse var(--ci-hotspot-pulse-duration) ease-out infinite;pointer-events:none}@keyframes ci-hotspot-pulse{0%{transform:translate(-50%,-50%) scale(1);opacity:1}to{transform:translate(-50%,-50%) scale(1.8);opacity:0}}.ci-hotspot-marker--pulse{animation:ci-hotspot-breathe 2.4s ease-in-out infinite}.ci-hotspot-marker--pulse:hover,.ci-hotspot-marker--pulse.ci-hotspot-marker--active{animation:none}@keyframes ci-hotspot-breathe{0%,to{transform:translate(-50%,-50%) scale(calc(1 / var(--zoom, 1)))}50%{transform:translate(-50%,-50%) scale(calc(1.15 / var(--zoom, 1)))}}.ci-hotspot-popover{position:absolute;z-index:var(--ci-hotspot-popover-z-index);max-width:var(--ci-hotspot-popover-max-width);background:var(--ci-hotspot-popover-bg);color:var(--ci-hotspot-popover-color);border:var(--ci-hotspot-popover-border);border-radius:var(--ci-hotspot-popover-border-radius);box-shadow:var(--ci-hotspot-popover-shadow);font-family:var(--ci-hotspot-popover-font-family);font-size:var(--ci-hotspot-popover-font-size);line-height:var(--ci-hotspot-popover-line-height);opacity:0;pointer-events:none;transform:translateY(4px);transition:opacity var(--ci-hotspot-popover-transition),transform var(--ci-hotspot-popover-transition)}.ci-hotspot-popover--visible{opacity:1;pointer-events:auto;transform:translateY(0);animation:ci-hotspot-popover-in var(--ci-hotspot-popover-transition) forwards}@keyframes ci-hotspot-popover-in{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.ci-hotspot-popover-arrow{position:absolute;width:calc(var(--ci-hotspot-arrow-size) * 2);height:calc(var(--ci-hotspot-arrow-size) * 2);background:var(--ci-hotspot-arrow-color);transform:rotate(45deg);pointer-events:none}.ci-hotspot-popover[data-placement=top] .ci-hotspot-popover-arrow{bottom:calc(var(--ci-hotspot-arrow-size) * -1)}.ci-hotspot-popover[data-placement=bottom] .ci-hotspot-popover-arrow{top:calc(var(--ci-hotspot-arrow-size) * -1)}.ci-hotspot-popover[data-placement=left] .ci-hotspot-popover-arrow{right:calc(var(--ci-hotspot-arrow-size) * -1)}.ci-hotspot-popover[data-placement=right] .ci-hotspot-popover-arrow{left:calc(var(--ci-hotspot-arrow-size) * -1)}.ci-hotspot-popover-content{padding:var(--ci-hotspot-popover-padding);max-height:var(--ci-hotspot-popover-max-height);overflow-y:auto;overflow-x:hidden;border-radius:var(--ci-hotspot-popover-border-radius)}.ci-hotspot-popover-image{display:block;width:100%;height:auto;border-radius:calc(var(--ci-hotspot-popover-border-radius) - 4px) calc(var(--ci-hotspot-popover-border-radius) - 4px) 0 0;margin:calc(var(--ci-hotspot-popover-padding) * -1);margin-bottom:12px;width:calc(100% + var(--ci-hotspot-popover-padding) * 2)}.ci-hotspot-popover-body{line-height:1.5}.ci-hotspot-popover-title{margin:0 0 4px;font-size:var(--ci-hotspot-title-font-size);font-weight:var(--ci-hotspot-title-font-weight);color:var(--ci-hotspot-title-color)}.ci-hotspot-popover-price{display:inline-block;margin-bottom:8px;font-size:var(--ci-hotspot-price-font-size);font-weight:var(--ci-hotspot-price-font-weight);color:var(--ci-hotspot-price-color)}.ci-hotspot-popover-description{margin:0 0 12px;color:var(--ci-hotspot-description-color)}.ci-hotspot-popover-cta{display:inline-block;padding:var(--ci-hotspot-cta-padding);background:var(--ci-hotspot-cta-bg);color:var(--ci-hotspot-cta-color);border-radius:var(--ci-hotspot-cta-border-radius);text-decoration:none;font-weight:600;font-size:14px;transition:opacity .2s ease}.ci-hotspot-popover-cta:hover{opacity:.9}.ci-hotspot-popover-cta:focus-visible{outline:3px solid var(--ci-hotspot-focus-ring, #4A90D9);outline-offset:2px}.ci-hotspot-zoom-controls{position:absolute;display:flex;gap:2px;background:var(--ci-hotspot-zoom-controls-bg);border-radius:var(--ci-hotspot-zoom-controls-border-radius);box-shadow:var(--ci-hotspot-zoom-controls-shadow);z-index:10;overflow:hidden}.ci-hotspot-zoom-controls button{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:none;background:transparent;color:var(--ci-hotspot-zoom-controls-color);cursor:pointer;font-size:18px;line-height:1;padding:0;transition:background .15s ease}.ci-hotspot-zoom-controls button:hover{background:#0000000d}.ci-hotspot-zoom-controls button:disabled{opacity:.3;cursor:default}.ci-hotspot-zoom-controls button:disabled:hover{background:transparent}.ci-hotspot-zoom-controls button svg{width:18px;height:18px}.ci-hotspot-zoom-controls button:focus-visible{outline:3px solid var(--ci-hotspot-focus-ring, #4A90D9);outline-offset:-3px}.ci-hotspot-zoom-controls[data-position=bottom-right]{bottom:16px;right:16px}.ci-hotspot-zoom-controls[data-position=bottom-left]{bottom:16px;left:16px}.ci-hotspot-zoom-controls[data-position=bottom-center]{bottom:16px;left:50%;transform:translate(-50%)}.ci-hotspot-zoom-controls[data-position=top-right]{top:16px;right:16px}.ci-hotspot-zoom-controls[data-position=top-left]{top:16px;left:16px}.ci-hotspot-zoom-controls[data-position=top-center]{top:16px;left:50%;transform:translate(-50%)}.ci-hotspot-cluster{position:absolute;display:flex;align-items:center;justify-content:center;min-width:32px;height:32px;padding:0 8px;border-radius:16px;border:2px solid rgba(255,255,255,.8);background:var(--ci-hotspot-marker-bg);color:var(--ci-hotspot-marker-color);font-size:13px;font-weight:700;cursor:pointer;pointer-events:auto;transform:translate(-50%,-50%) scale(calc(1 / var(--zoom, 1)));box-shadow:var(--ci-hotspot-marker-shadow)}.ci-hotspot-loading .ci-hotspot-image{opacity:0;transition:opacity .3s ease}.ci-hotspot-loading .ci-hotspot-markers{display:none}.ci-hotspot-theme-dark{--ci-hotspot-marker-bg: rgba(255, 255, 255, .8);--ci-hotspot-marker-color: #1a1a1a;--ci-hotspot-marker-border-color: rgba(255, 255, 255, .4);--ci-hotspot-pulse-color: rgba(255, 255, 255, .2);--ci-hotspot-popover-bg: #1a1a1a;--ci-hotspot-popover-color: #f0f0f0;--ci-hotspot-popover-border: 1px solid rgba(255, 255, 255, .1);--ci-hotspot-popover-shadow: 0 8px 32px rgba(0, 0, 0, .4);--ci-hotspot-title-color: #f0f0f0;--ci-hotspot-description-color: #aaaaaa;--ci-hotspot-zoom-controls-bg: rgba(30, 30, 30, .9);--ci-hotspot-zoom-controls-color: #f0f0f0}.ci-hotspot-marker-inverted{--ci-hotspot-marker-bg: rgba(255, 255, 255, .8);--ci-hotspot-marker-color: #1a1a1a;--ci-hotspot-marker-border-color: rgba(0, 0, 0, .3);--ci-hotspot-marker-shadow: 0 2px 8px rgba(0, 0, 0, .15);--ci-hotspot-pulse-color: rgba(0, 0, 0, .15)}.ci-hotspot-theme-dark.ci-hotspot-marker-inverted{--ci-hotspot-marker-bg: rgba(0, 0, 0, .6);--ci-hotspot-marker-color: #ffffff;--ci-hotspot-marker-border-color: rgba(255, 255, 255, .3);--ci-hotspot-pulse-color: rgba(255, 255, 255, .15)}.ci-hotspot-scroll-hint{position:absolute;bottom:16px;left:50%;transform:translate(-50%) translateY(4px);padding:8px 16px;border-radius:20px;background:#000000b3;color:#fff;font-size:13px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;line-height:1;white-space:nowrap;z-index:100;opacity:0;pointer-events:none;transition:opacity .3s ease,transform .3s ease}.ci-hotspot-scroll-hint--visible{opacity:1;transform:translate(-50%) translateY(0)}.ci-hotspot-container--fixed-ratio .ci-hotspot-viewport{overflow:hidden}.ci-hotspot-container--fixed-ratio .ci-hotspot-image{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain}.ci-hotspot-container--fixed-ratio .ci-hotspot-markers{z-index:1}.ci-hotspot-scene-incoming{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain;pointer-events:none;z-index:0}.ci-hotspot-scene-fade-in{animation:ci-hotspot-scene-fade-in var(--ci-hotspot-scene-transition-duration) ease forwards;z-index:1}.ci-hotspot-scene-fade-out{animation:ci-hotspot-scene-fade-out var(--ci-hotspot-scene-transition-duration) ease forwards}@keyframes ci-hotspot-scene-fade-in{0%{opacity:0}to{opacity:1}}@keyframes ci-hotspot-scene-fade-out{0%{opacity:1}to{opacity:0}}.ci-hotspot-scene-slide-in{animation:ci-hotspot-scene-slide-in var(--ci-hotspot-scene-transition-duration) ease forwards;z-index:1}.ci-hotspot-scene-slide-out{animation:ci-hotspot-scene-slide-out var(--ci-hotspot-scene-transition-duration) ease forwards}@keyframes ci-hotspot-scene-slide-in{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes ci-hotspot-scene-slide-out{0%{transform:translate(0)}to{transform:translate(-100%)}}.ci-hotspot-scene-slide-in-reverse{animation:ci-hotspot-scene-slide-in-reverse var(--ci-hotspot-scene-transition-duration) ease forwards;z-index:1}.ci-hotspot-scene-slide-out-reverse{animation:ci-hotspot-scene-slide-out-reverse var(--ci-hotspot-scene-transition-duration) ease forwards}@keyframes ci-hotspot-scene-slide-in-reverse{0%{transform:translate(-100%)}to{transform:translate(0)}}@keyframes ci-hotspot-scene-slide-out-reverse{0%{transform:translate(0)}to{transform:translate(100%)}}.ci-hotspot-marker--navigate{--ci-hotspot-marker-bg: rgba(0, 88, 163, .7)}.ci-hotspot-navigate-icon{width:75%;height:75%;display:block}.ci-hotspot-scene-transitioning .ci-hotspot-markers{opacity:0;pointer-events:none;transition:opacity .1s ease}.ci-hotspot-scene-loading:after{content:"";position:absolute;top:50%;left:50%;width:32px;height:32px;margin:-16px 0 0 -16px;border:3px solid rgba(0,0,0,.1);border-top-color:#00000080;border-radius:50%;animation:ci-hotspot-spin .6s linear infinite;z-index:10;pointer-events:none}.ci-hotspot-theme-dark .ci-hotspot-scene-loading:after,.ci-hotspot-scene-loading.ci-hotspot-theme-dark:after{border-color:#ffffff1a;border-top-color:#ffffff80}@keyframes ci-hotspot-spin{to{transform:rotate(360deg)}}.ci-hotspot-fullscreen-btn{position:absolute;top:16px;right:16px;display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:none;border-radius:var(--ci-hotspot-zoom-controls-border-radius);background:var(--ci-hotspot-zoom-controls-bg);color:var(--ci-hotspot-zoom-controls-color);box-shadow:var(--ci-hotspot-zoom-controls-shadow);cursor:pointer;padding:0;z-index:10;transition:background .15s ease}.ci-hotspot-fullscreen-btn:hover{background:#0000000d}.ci-hotspot-fullscreen-btn svg{width:18px;height:18px}.ci-hotspot-fullscreen-btn:focus-visible{outline:3px solid var(--ci-hotspot-focus-ring, #4A90D9);outline-offset:2px}.ci-hotspot-container--fullscreen{background:#000;width:100vw;height:100vh;display:flex;align-items:center;justify-content:center}.ci-hotspot-container--fullscreen .ci-hotspot-viewport{width:fit-content;max-width:100%;max-height:100%}.ci-hotspot-container--fullscreen .ci-hotspot-image{max-height:100vh;width:auto;max-width:100%;object-fit:contain}.ci-hotspot-container--fullscreen.ci-hotspot-container--fixed-ratio .ci-hotspot-viewport{width:100%;height:100%}.ci-hotspot-container--fullscreen.ci-hotspot-container--fixed-ratio .ci-hotspot-image{width:100%;height:100%;max-height:none}.ci-hotspot-theme-dark .ci-hotspot-fullscreen-btn,.ci-hotspot-container--fullscreen .ci-hotspot-fullscreen-btn{background:#1e1e1ee6;color:#f0f0f0}.ci-hotspot-theme-dark .ci-hotspot-fullscreen-btn:hover,.ci-hotspot-container--fullscreen .ci-hotspot-fullscreen-btn:hover{background:#ffffff1a}@media (prefers-reduced-motion: reduce){.ci-hotspot-marker,.ci-hotspot-marker:before,.ci-hotspot-popover{animation:none!important;transition-duration:.01ms!important}.ci-hotspot-viewport,.ci-hotspot-scroll-hint{transition-duration:.01ms!important}.ci-hotspot-scene-fade-in,.ci-hotspot-scene-fade-out,.ci-hotspot-scene-slide-in,.ci-hotspot-scene-slide-out,.ci-hotspot-scene-slide-in-reverse,.ci-hotspot-scene-slide-out-reverse{animation-duration:.01ms!important}.ci-hotspot-scene-transitioning .ci-hotspot-markers{transition-duration:.01ms!important}.ci-hotspot-scene-loading:after{animation-duration:.01ms!important}.ci-hotspot-fullscreen-btn{transition-duration:.01ms!important}}',S=class S{constructor(t,e){this.markers=new Map,this.popovers=new Map,this.normalizedHotspots=new Map,this.scrollHint=null,this.zoomPan=null,this.zoomControls=null,this.cloudimageHandler=null,this.resizeObserver=null,this.keyboardHandler=null,this.fullscreenControl=null,this.focusTraps=new Map,this.cleanups=[],this.hotspotCleanups=new Map,this.imageLoaded=!1,this.destroyed=!1,this.scenesMap=new Map,this.isTransitioning=!1,this.activeTimers=new Set,this.sceneHotspotOverrides=new Map,this.preloadedScenes=new Set,this.rootEl=nt(t),this.config=O(e),X(this.config),this.config.scenes&&this.config.scenes.length>0&&this.initScenes(),G(),rt(jt),this.buildDOM(),this.applyTheme(),this.setupImage(),this.initHotspots(),this.config.zoom&&this.initZoom(),this.initKeyboard(),this.initFullscreen(),this.setupResponsive()}static autoInit(t){const o=(t||document).querySelectorAll("[data-ci-hotspot-src], [data-ci-hotspot-scenes]"),i=[];return o.forEach(a=>{const n=it(a);(n.src||n.scenes)&&i.push(new S(a,n))}),i}buildDOM(){this.containerEl=g("div","ci-hotspot-container"),this.viewportEl=g("div","ci-hotspot-viewport"),this.imgEl=g("img","ci-hotspot-image",{alt:this.config.alt||"",draggable:"false"}),this.markersEl=g("div","ci-hotspot-markers"),this.viewportEl.appendChild(this.imgEl),this.viewportEl.appendChild(this.markersEl),this.containerEl.appendChild(this.viewportEl),this.containerEl.setAttribute("role","group"),this.containerEl.setAttribute("aria-label",this.config.alt||"Image with hotspots"),this.config.sceneAspectRatio&&(m(this.containerEl,"ci-hotspot-container--fixed-ratio"),this.viewportEl.style.aspectRatio=this.config.sceneAspectRatio),this.rootEl.innerHTML="",this.rootEl.appendChild(this.containerEl),this.config.lazyLoad&&m(this.containerEl,"ci-hotspot-loading")}applyTheme(){this.config.theme==="dark"&&m(this.containerEl,"ci-hotspot-theme-dark"),this.config.invertMarkerTheme&&m(this.containerEl,"ci-hotspot-marker-inverted")}setupImage(){const t=()=>{b(this.containerEl,"ci-hotspot-loading"),this.imageLoaded=!0,this.renormalizePixelCoordinates(),this.syncMarkersToImage(),this.showLoadTriggerPopovers()};if(this.imgEl.addEventListener("load",t),this.cleanups.push(()=>this.imgEl.removeEventListener("load",t)),this.config.lazyLoad&&typeof IntersectionObserver<"u"){const e=new IntersectionObserver(o=>{var i;(i=o[0])!=null&&i.isIntersecting&&(this.loadImage(),e.disconnect())},{threshold:.1});e.observe(this.containerEl),this.cleanups.push(()=>e.disconnect())}else this.loadImage()}loadImage(){var t,e;if((t=this.config.cloudimage)!=null&&t.token){const o=this.containerEl.offsetWidth||300,i=window.devicePixelRatio||1,a=((e=this.zoomPan)==null?void 0:e.getZoom())||1;this.imgEl.src=C(this.config.src,this.config.cloudimage,o,a,i),this.cloudimageHandler=Ft(this.imgEl,this.config.src,this.config.cloudimage,()=>{var n;return((n=this.zoomPan)==null?void 0:n.getZoom())||1}),this.cloudimageHandler.observer.observe(this.containerEl),this.cleanups.push(()=>{var n;return(n=this.cloudimageHandler)==null?void 0:n.destroy()})}else this.imgEl.src=this.config.src}initHotspots(){for(const t of this.config.hotspots)this.addHotspotInternal(t)}addHotspotInternal(t){var h,d;if(this.markers.has(t.id)){const p=this.markers.get(t.id);H(p),this.markers.delete(t.id),(h=this.popovers.get(t.id))==null||h.destroy(),this.popovers.delete(t.id);const v=this.hotspotCleanups.get(t.id);v&&(v.forEach(k=>k()),this.hotspotCleanups.delete(t.id));const E=this.focusTraps.get(t.id);E&&(E.destroy(),this.focusTraps.delete(t.id))}const{x:e,y:o}=N(t.x,t.y,this.imgEl.naturalWidth||1e3,this.imgEl.naturalHeight||1e3),i={...t,x:e,y:o};this.normalizedHotspots.set(t.id,i);const a=this.config.pulse!==!1,n=at(i,a);this.markers.set(t.id,n),this.markersEl.appendChild(n);const r=t.trigger||this.config.trigger||"hover";if(t.navigateTo){const p=this.enrichNavigateHotspot(t);if(!!(p.data||p.content||this.config.renderPopover)){const E=t.placement||this.config.placement||"top",k=new j(p,{placement:E,triggerMode:"hover",renderFn:this.config.renderPopover,onOpen:this.config.onOpen,onClose:this.config.onClose});this.popovers.set(t.id,k),k.mount(this.containerEl,n),this.bindNavigateTrigger(t,n,k)}else this.bindNavigateTrigger(t,n);return}const c=t.placement||this.config.placement||"top",l=new j(t,{placement:c,triggerMode:r,renderFn:this.config.renderPopover,onOpen:this.config.onOpen,onClose:this.config.onClose});this.popovers.set(t.id,l),l.mount(this.containerEl,n),this.bindTrigger(t,n,l,r),r==="load"&&this.imageLoaded&&(this.closeAll(),l.show(),u(n,!0),this.ensureFocusTrap(t.id,l.element,n),(d=this.focusTraps.get(t.id))==null||d.activate())}enrichNavigateHotspot(t){if(t.data||t.content)return t;const e=this.scenesMap.get(t.navigateTo);return e?{...t,data:{title:t.label||e.alt||e.id}}:t}bindNavigateTrigger(t,e,o){if(m(e,"ci-hotspot-marker--navigate"),e.innerHTML=S.NAVIGATE_ARROW_SVG,t.arrowDirection!=null){const r=e.querySelector("svg");r&&(r.style.transform=`rotate(${t.arrowDirection}deg)`)}const i=t.label||t.navigateTo;if(e.setAttribute("aria-label",`Navigate to ${i}`),e.setAttribute("aria-roledescription","navigation hotspot"),o){const r=f(e,"mouseenter",()=>{this.preloadSceneImage(t.navigateTo),o.clearHideTimer(),o.show(),u(e,!0)}),c=f(e,"mouseleave",()=>{o.scheduleHide(200),this.trackedTimeout(()=>{o.isVisible()||u(e,!1)},250)}),l=f(e,"focus",()=>{this.preloadSceneImage(t.navigateTo),o.clearHideTimer(),o.show(),u(e,!0)}),h=f(e,"blur",()=>{o.scheduleHide(200),this.trackedTimeout(()=>{o.isVisible()||u(e,!1)},250)});this.addHotspotCleanups(t.id,r,c,l,h)}else{const r=f(e,"mouseenter",()=>{this.preloadSceneImage(t.navigateTo)}),c=f(e,"focus",()=>{this.preloadSceneImage(t.navigateTo)});this.addHotspotCleanups(t.id,r,c)}const a=f(e,"click",r=>{var c,l,h;r.stopPropagation(),o==null||o.hide(),u(e,!1),(l=(c=this.config).onClick)==null||l.call(c,r,t),(h=t.onClick)==null||h.call(t,r,t),this.goToScene(t.navigateTo)}),n=f(e,"keydown",r=>{var c,l,h;(r.key==="Enter"||r.key===" ")&&(r.preventDefault(),o==null||o.hide(),u(e,!1),(l=(c=this.config).onClick)==null||l.call(c,r,t),(h=t.onClick)==null||h.call(t,r,t),this.goToScene(t.navigateTo))});this.addHotspotCleanups(t.id,a,n)}bindTrigger(t,e,o,i){i==="hover"?this.bindHoverTrigger(t,e,o):(i==="click"||i==="load")&&this.bindClickTrigger(t,e,o),this.bindKeyboardTrigger(t,e,o,i)}bindHoverTrigger(t,e,o){const i=f(e,"mouseenter",()=>{o.clearHideTimer(),o.show(),u(e,!0)}),a=f(e,"mouseleave",()=>{o.scheduleHide(200),this.trackedTimeout(()=>{o.isVisible()||u(e,!1)},250)});this.addHotspotCleanups(t.id,i,a)}bindClickTrigger(t,e,o){const i=B(o.element,e);this.focusTraps.set(t.id,i);const a=f(e,"click",r=>{var c,l,h;r.stopPropagation(),(l=(c=this.config).onClick)==null||l.call(c,r,t),(h=t.onClick)==null||h.call(t,r,t),o.isVisible()?(o.hide(),u(e,!1),i.deactivate()):(this.closeAll(),o.show(),u(e,!0),i.activate())}),n=f(document,"click",r=>{o.isVisible()&&!t.keepOpen&&!o.element.contains(r.target)&&!e.contains(r.target)&&(o.hide(),u(e,!1),i.deactivate())});this.addHotspotCleanups(t.id,a,n)}bindKeyboardTrigger(t,e,o,i){const a=f(e,"focus",()=>{i==="hover"&&(o.clearHideTimer(),o.show(),u(e,!0))}),n=f(e,"blur",()=>{i==="hover"&&(o.scheduleHide(200),this.trackedTimeout(()=>{o.isVisible()||u(e,!1)},250))}),r=f(e,"keydown",c=>{var l,h,d,p,v;c.key==="Enter"||c.key===" "?(c.preventDefault(),(h=(l=this.config).onClick)==null||h.call(l,c,t),o.isVisible()?(o.hide(),u(e,!1),(d=this.focusTraps.get(t.id))==null||d.deactivate()):(this.closeAll(),o.show(),u(e,!0),this.ensureFocusTrap(t.id,o.element,e),(p=this.focusTraps.get(t.id))==null||p.activate())):c.key==="Escape"&&o.isVisible()&&(o.hide(),u(e,!1),(v=this.focusTraps.get(t.id))==null||v.deactivate(),e.focus())});this.addHotspotCleanups(t.id,a,n,r)}renormalizePixelCoordinates(){const t=this.imgEl.naturalWidth,e=this.imgEl.naturalHeight;if(!(!t||!e)){for(const o of this.config.hotspots)if(typeof o.x=="number"||typeof o.y=="number"){const{x:i,y:a}=N(o.x,o.y,t,e),n=this.markers.get(o.id);n&&(n.style.left=`${i}%`,n.style.top=`${a}%`);const r=this.normalizedHotspots.get(o.id);r&&(r.x=i,r.y=a)}}}showLoadTriggerPopovers(){var t;for(const[e,o]of this.popovers){const i=this.normalizedHotspots.get(e);if(((i==null?void 0:i.trigger)||this.config.trigger||"hover")==="load"&&!o.isVisible()){o.show();const n=this.markers.get(e);n&&(u(n,!0),this.ensureFocusTrap(e,o.element,n),(t=this.focusTraps.get(e))==null||t.activate());break}}}initZoom(){this.config.scrollHint!==!1&&(this.scrollHint=new Lt(this.containerEl)),this.zoomPan=new Ct(this.viewportEl,this.containerEl,{zoomMin:this.config.zoomMin||1,zoomMax:this.config.zoomMax||4,onZoom:t=>{var e,o,i;(o=(e=this.config).onZoom)==null||o.call(e,t),(i=this.zoomControls)==null||i.update();for(const[,a]of this.popovers)a.isVisible()&&a.updatePosition()},onScrollWithoutZoom:()=>{var t;return(t=this.scrollHint)==null?void 0:t.show()}}),this.config.zoomControls!==!1&&(this.zoomControls=St(this.containerEl,this.zoomPan,{zoomMin:this.config.zoomMin||1,zoomMax:this.config.zoomMax||4,position:this.config.zoomControlsPosition}))}setupResponsive(){if(typeof ResizeObserver>"u")return;let t=0;this.resizeObserver=new ResizeObserver(()=>{t||(t=requestAnimationFrame(()=>{if(t=0,this.destroyed)return;this.syncMarkersToImage();const e=this.containerEl.offsetWidth;for(const[o,i]of this.normalizedHotspots)if(i.responsive){const a=this.markers.get(o);if(!a)continue;const n=i.responsive.maxWidth&&e>i.responsive.maxWidth||i.responsive.minWidth&&e<i.responsive.minWidth;pt(a,!!n)}}))}),this.cleanups.push(()=>{t&&cancelAnimationFrame(t)}),this.resizeObserver.observe(this.containerEl),this.cleanups.push(()=>{var e;return(e=this.resizeObserver)==null?void 0:e.disconnect()})}syncMarkersToImage(){if(!this.config.sceneAspectRatio)return;const t=this.viewportEl.offsetWidth,e=this.viewportEl.offsetHeight,o=this.imgEl.naturalWidth,i=this.imgEl.naturalHeight;if(!t||!e||!o||!i)return;const a=t/e,n=o/i;let r,c,l,h;n>a?(r=t,c=t/n,l=0,h=(e-c)/2):(c=e,r=e*n,l=(t-r)/2,h=0),this.markersEl.style.left=`${l}px`,this.markersEl.style.top=`${h}px`,this.markersEl.style.width=`${r}px`,this.markersEl.style.height=`${c}px`,this.markersEl.style.right="auto",this.markersEl.style.bottom="auto"}initScenes(){for(const o of this.config.scenes)this.scenesMap.set(o.id,o);const t=this.config.initialScene||this.config.scenes[0].id,e=this.scenesMap.get(t);this.config.src=e.src,this.config.alt=e.alt||"",this.config.hotspots=[...e.hotspots],this.currentSceneId=t}initKeyboard(){this.keyboardHandler=new Rt({container:this.containerEl,getZoomPan:()=>this.zoomPan,onEscape:()=>{var t;if((t=this.fullscreenControl)!=null&&t.isFullscreen()){this.fullscreenControl.exit();return}this.closeAll()},onFullscreenToggle:()=>{var t;(t=this.fullscreenControl)==null||t.toggle()}})}initFullscreen(){this.config.fullscreenButton!==!1&&(this.fullscreenControl=Nt(this.containerEl,{onChange:t=>{var e,o;requestAnimationFrame(()=>{for(const[,i]of this.popovers)i.isVisible()&&i.updatePosition()}),(o=(e=this.config).onFullscreenChange)==null||o.call(e,t)}}))}preloadSceneImage(t){var i;if(this.preloadedScenes.has(t))return;const e=this.scenesMap.get(t);if(!e)return;this.preloadedScenes.add(t);const o=new Image;if((i=this.config.cloudimage)!=null&&i.token){const a=this.containerEl.offsetWidth||300,n=typeof window<"u"&&window.devicePixelRatio||1;o.src=C(e.src,this.config.cloudimage,a,1,n)}else o.src=e.src}ensureFocusTrap(t,e,o){this.focusTraps.has(t)||this.focusTraps.set(t,B(e,o))}trackedTimeout(t,e){const o=setTimeout(()=>{this.activeTimers.delete(o),t()},e);this.activeTimers.add(o)}syncCurrentSceneHotspots(){!this.currentSceneId||this.isTransitioning||this.sceneHotspotOverrides.set(this.currentSceneId,[...this.config.hotspots])}addHotspotCleanups(t,...e){let o=this.hotspotCleanups.get(t);o||(o=[],this.hotspotCleanups.set(t,o)),o.push(...e)}clearHotspots(){for(const t of this.hotspotCleanups.values())t.forEach(e=>e());this.hotspotCleanups.clear();for(const[,t]of this.popovers)t.destroy();this.popovers.clear();for(const[,t]of this.markers)H(t);this.markers.clear(),this.normalizedHotspots.clear();for(const[,t]of this.focusTraps)t.destroy();this.focusTraps.clear()}getSceneTransitionDuration(){if(typeof getComputedStyle>"u")return 400;const t=getComputedStyle(this.containerEl).getPropertyValue("--ci-hotspot-scene-transition-duration").trim(),e=parseFloat(t);return isNaN(e)?400:t.endsWith("s")&&!t.endsWith("ms")?e*1e3:e}performSceneTransition(t,e,o,i){var c;if(e==="none"){this.clearHotspots(),this.switchToScene(t),i();return}const a=this.getSceneTransitionDuration();m(this.containerEl,"ci-hotspot-scene-transitioning");const n=g("img","ci-hotspot-scene-incoming",{alt:t.alt||"",draggable:"false"});if((c=this.config.cloudimage)!=null&&c.token){const l=this.containerEl.offsetWidth||300,h=typeof window<"u"&&window.devicePixelRatio||1;n.src=C(t.src,this.config.cloudimage,l,1,h)}else n.src=t.src;const r=()=>{if(!this.destroyed){if(e==="fade")m(n,"ci-hotspot-scene-fade-in"),m(this.imgEl,"ci-hotspot-scene-fade-out");else if(e==="slide"){const l=o?"-reverse":"";m(n,`ci-hotspot-scene-slide-in${l}`),m(this.imgEl,`ci-hotspot-scene-slide-out${l}`)}this.viewportEl.insertBefore(n,this.markersEl),this.transitionTimer=setTimeout(()=>{if(this.transitionTimer=void 0,this.destroyed)return;this.clearHotspots(),this.switchToScene(t);const l=()=>{n.remove(),b(this.imgEl,"ci-hotspot-scene-fade-out"),b(this.imgEl,"ci-hotspot-scene-slide-out"),b(this.imgEl,"ci-hotspot-scene-slide-out-reverse"),b(this.containerEl,"ci-hotspot-scene-transitioning"),i()};this.imgEl.complete&&this.imgEl.naturalWidth>0?l():(this.imgEl.addEventListener("load",l,{once:!0}),this.imgEl.addEventListener("error",l,{once:!0}))},a)}};n.complete?r():(m(this.containerEl,"ci-hotspot-scene-loading"),n.onload=()=>{b(this.containerEl,"ci-hotspot-scene-loading"),r()},n.onerror=()=>{this.destroyed||(b(this.containerEl,"ci-hotspot-scene-loading"),n.remove(),b(this.containerEl,"ci-hotspot-scene-transitioning"),this.clearHotspots(),this.switchToScene(t),i())})}switchToScene(t){var o;this.config.src=t.src,this.config.alt=t.alt||"",this.config.hotspots=this.sceneHotspotOverrides.get(t.id)??[...t.hotspots],this.imgEl.alt=t.alt||"",this.containerEl.setAttribute("aria-label",t.alt||"Image with hotspots"),this.imageLoaded=!1;const e=()=>{this.imageLoaded=!0,this.renormalizePixelCoordinates(),this.syncMarkersToImage(),this.showLoadTriggerPopovers()};if(this.imgEl.addEventListener("load",e,{once:!0}),(o=this.config.cloudimage)!=null&&o.token){const i=this.containerEl.offsetWidth||300,a=typeof window<"u"&&window.devicePixelRatio||1;this.imgEl.src=C(t.src,this.config.cloudimage,i,1,a)}else this.imgEl.src=t.src;this.imgEl.complete&&this.imgEl.naturalWidth>0&&!this.imageLoaded&&(this.imgEl.removeEventListener("load",e),e()),this.initHotspots()}getElements(){return{container:this.containerEl,viewport:this.viewportEl,image:this.imgEl,markers:this.markersEl}}open(t){var i;if(this.destroyed)return;const e=this.popovers.get(t),o=this.markers.get(t);!e||!o||e.isVisible()||(this.closeAll(),e.show(),u(o,!0),(i=this.focusTraps.get(t))==null||i.activate())}close(t){var i;if(this.destroyed)return;const e=this.popovers.get(t),o=this.markers.get(t);e&&o&&(e.hide(),u(o,!1),(i=this.focusTraps.get(t))==null||i.deactivate())}closeAll(){var t;if(!this.destroyed){for(const[e,o]of this.popovers)if(o.isVisible()){o.hide();const i=this.markers.get(e);i&&u(i,!1),(t=this.focusTraps.get(e))==null||t.deactivate()}}}setZoom(t){var e;this.destroyed||(e=this.zoomPan)==null||e.setZoom(t)}getZoom(){var t;return((t=this.zoomPan)==null?void 0:t.getZoom())||1}resetZoom(){var t;this.destroyed||(t=this.zoomPan)==null||t.resetZoom()}goToScene(t){if(this.destroyed||this.isTransitioning||!this.scenesMap.size||t===this.currentSceneId)return;const e=this.scenesMap.get(t);if(!e)return;const o=this.config.sceneTransition||"fade";this.isTransitioning=!0,this.zoomPan&&this.zoomPan.getZoom()>1&&this.zoomPan.resetZoom();let i=!1;if(o==="slide"){for(const a of this.config.hotspots)if(a.navigateTo===t){const n=this.normalizedHotspots.get(a.id);n&&n.x<=50&&(i=!0);break}}this.syncCurrentSceneHotspots(),this.currentSceneId=t,this.performSceneTransition(e,o,i,()=>{var n,r;this.isTransitioning=!1,Zt(`Navigated to ${e.alt||t}`),(r=(n=this.config).onSceneChange)==null||r.call(n,t,e);const a=e.hotspots[0];if(a){const c=this.markers.get(a.id);c&&document.activeElement&&this.containerEl.contains(document.activeElement)&&c.focus()}})}getCurrentScene(){return this.currentSceneId}getScenes(){return Array.from(this.scenesMap.keys())}enterFullscreen(){var t;this.destroyed||(t=this.fullscreenControl)==null||t.enter()}exitFullscreen(){var t;this.destroyed||(t=this.fullscreenControl)==null||t.exit()}isFullscreen(){var t;return((t=this.fullscreenControl)==null?void 0:t.isFullscreen())??!1}addHotspot(t){this.destroyed||(this.config.hotspots.push(t),this.addHotspotInternal(t),this.syncCurrentSceneHotspots())}removeHotspot(t){if(this.destroyed)return;const e=this.hotspotCleanups.get(t);e&&(e.forEach(n=>n()),this.hotspotCleanups.delete(t));const o=this.focusTraps.get(t);o&&(o.destroy(),this.focusTraps.delete(t));const i=this.markers.get(t),a=this.popovers.get(t);a&&(a.destroy(),this.popovers.delete(t)),i&&(H(i),this.markers.delete(t)),this.normalizedHotspots.delete(t),this.config.hotspots=this.config.hotspots.filter(n=>n.id!==t),this.syncCurrentSceneHotspots()}updateHotspot(t,e){if(this.destroyed)return;const o=this.config.hotspots.findIndex(l=>l.id===t);if(o===-1)return;const i=this.markers.get(t),a=(i==null?void 0:i.nextElementSibling)||null,r={...this.config.hotspots[o],...e};this.removeHotspot(t),this.config.hotspots.splice(o,0,r),this.addHotspotInternal(r);const c=this.markers.get(t);c&&a&&this.markersEl.contains(a)&&this.markersEl.insertBefore(c,a),this.syncCurrentSceneHotspots()}update(t){this.destroyed||(this.destroyInternal(),G(),this.config=O({...this.config,...t}),X(this.config),this.config.scenes&&this.config.scenes.length>0&&this.initScenes(),this.buildDOM(),this.applyTheme(),this.setupImage(),this.initHotspots(),this.config.zoom&&this.initZoom(),this.initKeyboard(),this.initFullscreen(),this.setupResponsive())}destroy(){this.destroyed||(this.destroyed=!0,this.destroyInternal(),this.rootEl.innerHTML="")}destroyInternal(){var t,e,o,i,a,n,r;this.imageLoaded=!1;for(const c of this.activeTimers)clearTimeout(c);this.activeTimers.clear();for(const c of this.hotspotCleanups.values())c.forEach(l=>l());this.hotspotCleanups.clear(),this.cleanups.forEach(c=>c()),this.cleanups=[];for(const[,c]of this.popovers)c.destroy();this.popovers.clear();for(const[,c]of this.markers)H(c);this.markers.clear(),this.normalizedHotspots.clear();for(const[,c]of this.focusTraps)c.destroy();this.focusTraps.clear(),this.scenesMap.clear(),this.preloadedScenes.clear(),this.sceneHotspotOverrides.clear(),this.currentSceneId=void 0,this.isTransitioning=!1,this.transitionTimer!==void 0&&(clearTimeout(this.transitionTimer),this.transitionTimer=void 0),(t=this.fullscreenControl)==null||t.destroy(),this.fullscreenControl=null,(e=this.keyboardHandler)==null||e.destroy(),this.keyboardHandler=null,(o=this.zoomPan)==null||o.destroy(),this.zoomPan=null,(i=this.zoomControls)==null||i.destroy(),this.zoomControls=null,(a=this.scrollHint)==null||a.destroy(),this.scrollHint=null,(n=this.cloudimageHandler)==null||n.destroy(),this.cloudimageHandler=null,(r=this.resizeObserver)==null||r.disconnect(),this.resizeObserver=null,Ot()}};S.NAVIGATE_ARROW_SVG='<svg class="ci-hotspot-navigate-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>';let D=S;exports.CIHotspot=D;exports.default=D;
|
|
2
|
+
//# sourceMappingURL=js-cloudimage-hotspot.cjs.js.map
|