@paroicms/zoom-plugin 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.
- package/README.md +19 -0
- package/backend/dist/index.js +69 -0
- package/frontend/dist/cross.svg +1 -0
- package/frontend/dist/zoom-plugin.css +1 -0
- package/frontend/dist/zoom-plugin.mjs +35 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @paroicms/zoom-plugin
|
|
2
|
+
|
|
3
|
+
This package is part of [ParoiCMS](https://www.npmjs.com/package/@paroicms/server).
|
|
4
|
+
|
|
5
|
+
Image zoom viewer plugin for ParoiCMS. Provides an overlay zoom viewer for images on public websites.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
Add the `zoomable` filter to any image element to enable zoom functionality:
|
|
10
|
+
|
|
11
|
+
```liquid
|
|
12
|
+
<img src="..." {{ media | zoomable }}>
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Images with `data-zoomable` attributes automatically get click-to-zoom functionality. When clicked, the image opens in a full-screen overlay viewer displaying the high-resolution version.
|
|
16
|
+
|
|
17
|
+
## License
|
|
18
|
+
|
|
19
|
+
Released under the [MIT license](https://gitlab.com/paroi/opensource/paroicms/-/blob/main/LICENSE.md).
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { escapeHtml, makeStylesheetLinkAsyncTag, } from "@paroicms/public-server-lib";
|
|
2
|
+
import { esmDirName, extractPackageNameAndVersionSync } from "@paroicms/script-lib";
|
|
3
|
+
import { type } from "arktype";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
const MediaIdQueryAT = type({
|
|
6
|
+
"mediaId?": "string|undefined",
|
|
7
|
+
"+": "reject",
|
|
8
|
+
});
|
|
9
|
+
const projectDir = dirname(esmDirName(import.meta.url));
|
|
10
|
+
const packageDir = dirname(projectDir);
|
|
11
|
+
const { version } = extractPackageNameAndVersionSync(packageDir);
|
|
12
|
+
const plugin = {
|
|
13
|
+
version,
|
|
14
|
+
siteInit(service) {
|
|
15
|
+
service.setPublicAssetsDirectory(join(packageDir, "frontend", "dist"));
|
|
16
|
+
service.registerLiquidFilter("zoomable", async (service, val) => {
|
|
17
|
+
if (!val)
|
|
18
|
+
return "";
|
|
19
|
+
service.setRenderState("paZoom:enabled", true);
|
|
20
|
+
const mediaId = typeof val === "string"
|
|
21
|
+
? val
|
|
22
|
+
: val && typeof val === "object" && "mediaId" in val && typeof val.mediaId === "string"
|
|
23
|
+
? val.mediaId
|
|
24
|
+
: undefined;
|
|
25
|
+
if (!mediaId)
|
|
26
|
+
return "";
|
|
27
|
+
return `data-zoomable="${encodeURIComponent(mediaId)}"`;
|
|
28
|
+
}, { raw: true });
|
|
29
|
+
service.registerHeadTags(({ state }) => {
|
|
30
|
+
if (!state.get("paZoom:enabled"))
|
|
31
|
+
return;
|
|
32
|
+
return [
|
|
33
|
+
makeStylesheetLinkAsyncTag(`${service.pluginAssetsUrl}/zoom-plugin.css`),
|
|
34
|
+
`<script type="module" src="${escapeHtml(`${service.pluginAssetsUrl}/zoom-plugin.mjs`)}" async></script>`,
|
|
35
|
+
];
|
|
36
|
+
});
|
|
37
|
+
service.setPublicApiHandler(async (service, httpContext, relativePath) => {
|
|
38
|
+
const { req, res } = httpContext;
|
|
39
|
+
if (relativePath === "/zoom-image") {
|
|
40
|
+
const { mediaId } = MediaIdQueryAT.assert(req.query);
|
|
41
|
+
if (!mediaId) {
|
|
42
|
+
res.append("Content-Type", "application/json; charset=utf-8");
|
|
43
|
+
res.status(400).send({ error: "mediaId parameter is required" });
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const renderService = await service.openRenderingService({
|
|
47
|
+
language: service.siteSchema.defaultLanguage,
|
|
48
|
+
urlLike: relativePath,
|
|
49
|
+
});
|
|
50
|
+
try {
|
|
51
|
+
const image = await renderService.useImage(mediaId, "x1900x", { pixelRatio: 1 });
|
|
52
|
+
res.append("Content-Type", "application/json; charset=utf-8");
|
|
53
|
+
res.status(200).send(image);
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
service.logger.warn(`Failed to get zoom image for mediaId '${mediaId}':`, error);
|
|
57
|
+
res.append("Content-Type", "application/json; charset=utf-8");
|
|
58
|
+
res.status(404).send({ error: "Image not found" });
|
|
59
|
+
}
|
|
60
|
+
await renderService.close();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
res.append("Content-Type", "application/json; charset=utf-8");
|
|
64
|
+
res.status(404).send({ status: 404 });
|
|
65
|
+
return;
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
export default plugin;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="p-icon" aria-hidden="true"><path d="M8.01186 7.00933L12.27 2.75116C12.341 2.68501 12.398 2.60524 12.4375 2.51661C12.4769 2.42798 12.4982 2.3323 12.4999 2.23529C12.5016 2.13827 12.4838 2.0419 12.4474 1.95194C12.4111 1.86197 12.357 1.78024 12.2884 1.71163C12.2198 1.64302 12.138 1.58893 12.0481 1.55259C11.9581 1.51625 11.8617 1.4984 11.7647 1.50011C11.6677 1.50182 11.572 1.52306 11.4834 1.56255C11.3948 1.60204 11.315 1.65898 11.2488 1.72997L6.99067 5.98814L2.7325 1.72997C2.59553 1.60234 2.41437 1.53286 2.22718 1.53616C2.03999 1.53946 1.8614 1.61529 1.72901 1.74767C1.59663 1.88006 1.5208 2.05865 1.5175 2.24584C1.5142 2.43303 1.58368 2.61419 1.71131 2.75116L5.96948 7.00933L1.71131 11.2675C1.576 11.403 1.5 11.5866 1.5 11.7781C1.5 11.9696 1.576 12.1532 1.71131 12.2887C1.84679 12.424 2.03043 12.5 2.2219 12.5C2.41338 12.5 2.59702 12.424 2.7325 12.2887L6.99067 8.03052L11.2488 12.2887C11.3843 12.424 11.568 12.5 11.7594 12.5C11.9509 12.5 12.1346 12.424 12.27 12.2887C12.4053 12.1532 12.4813 11.9696 12.4813 11.7781C12.4813 11.5866 12.4053 11.403 12.27 11.2675L8.01186 7.00933Z" fill="#fff"></path></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@charset "UTF-8";.TinyModal{background:transparent;border:none;margin:auto;padding:0;position:fixed;overflow:visible;max-width:100vw;max-height:100vh}.TinyModal::backdrop{background-color:#222b}.TinyModal-body{overflow:scroll}.TinyModal-closeButton{align-items:center;background-color:#bbb;border-radius:50%;cursor:pointer;display:flex;font-size:30px;font-weight:700;height:40px;justify-content:center;line-height:1;position:absolute;right:-30px;top:-30px;width:40px;z-index:2}.TinyModal-closeButton:before{content:"×"}@media (max-width: 400px){.TinyModal-closeButton{right:-18px}}.TinyModalHidden{display:none!important}.PaZoomable{cursor:pointer}.PaZoomable:hover,.PaZoomable:focus{outline:1px solid var(--paInteractiveColor)}.PaZoomContent-img{height:100%;object-fit:contain;width:100%}.PaZoomContent-spinner{animation:spin 1s linear infinite;border:4px solid rgba(255,255,255,.3);border-radius:50%;border-top:4px solid white;height:40px;width:40px}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}._paZoomViewer .TinyModal-closeButton{top:5px;right:5px}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import ot from"https://esm.sh/@paroicms/tiny-modal@0.7.0";
|
|
2
|
+
/**
|
|
3
|
+
* @license
|
|
4
|
+
* Copyright 2019 Google LLC
|
|
5
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
6
|
+
*/const U=globalThis,k=U.ShadowRoot&&(U.ShadyCSS===void 0||U.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,X=Symbol(),j=new WeakMap;let nt=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==X)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o;const e=this.t;if(k&&t===void 0){const s=e!==void 0&&e.length===1;s&&(t=j.get(e)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),s&&j.set(e,t))}return t}toString(){return this.cssText}};const rt=o=>new nt(typeof o=="string"?o:o+"",void 0,X),ht=(o,t)=>{if(k)o.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(const e of t){const s=document.createElement("style"),i=U.litNonce;i!==void 0&&s.setAttribute("nonce",i),s.textContent=e.cssText,o.appendChild(s)}},B=k?o=>o:o=>o instanceof CSSStyleSheet?(t=>{let e="";for(const s of t.cssRules)e+=s.cssText;return rt(e)})(o):o;
|
|
7
|
+
/**
|
|
8
|
+
* @license
|
|
9
|
+
* Copyright 2017 Google LLC
|
|
10
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
11
|
+
*/const{is:at,defineProperty:lt,getOwnPropertyDescriptor:ct,getOwnPropertyNames:dt,getOwnPropertySymbols:pt,getPrototypeOf:ut}=Object,M=globalThis,Z=M.trustedTypes,$t=Z?Z.emptyScript:"",_t=M.reactiveElementPolyfillSupport,S=(o,t)=>o,R={toAttribute(o,t){switch(t){case Boolean:o=o?$t:null;break;case Object:case Array:o=o==null?o:JSON.stringify(o)}return o},fromAttribute(o,t){let e=o;switch(t){case Boolean:e=o!==null;break;case Number:e=o===null?null:Number(o);break;case Object:case Array:try{e=JSON.parse(o)}catch{e=null}}return e}},Y=(o,t)=>!at(o,t),V={attribute:!0,type:String,converter:R,reflect:!1,useDefault:!1,hasChanged:Y};Symbol.metadata??=Symbol("metadata"),M.litPropertyMetadata??=new WeakMap;let g=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=V){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){const s=Symbol(),i=this.getPropertyDescriptor(t,s,e);i!==void 0&<(this.prototype,t,i)}}static getPropertyDescriptor(t,e,s){const{get:i,set:n}=ct(this.prototype,t)??{get(){return this[e]},set(r){this[e]=r}};return{get:i,set(r){const l=i?.call(this);n?.call(this,r),this.requestUpdate(t,l,s)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??V}static _$Ei(){if(this.hasOwnProperty(S("elementProperties")))return;const t=ut(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(S("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(S("properties"))){const e=this.properties,s=[...dt(e),...pt(e)];for(const i of s)this.createProperty(i,e[i])}const t=this[Symbol.metadata];if(t!==null){const e=litPropertyMetadata.get(t);if(e!==void 0)for(const[s,i]of e)this.elementProperties.set(s,i)}this._$Eh=new Map;for(const[e,s]of this.elementProperties){const i=this._$Eu(e,s);i!==void 0&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){const e=[];if(Array.isArray(t)){const s=new Set(t.flat(1/0).reverse());for(const i of s)e.unshift(B(i))}else t!==void 0&&e.push(B(t));return e}static _$Eu(t,e){const s=e.attribute;return s===!1?void 0:typeof s=="string"?s:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),this.renderRoot!==void 0&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){const t=new Map,e=this.constructor.elementProperties;for(const s of e.keys())this.hasOwnProperty(s)&&(t.set(s,this[s]),delete this[s]);t.size>0&&(this._$Ep=t)}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return ht(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,s){this._$AK(t,s)}_$ET(t,e){const s=this.constructor.elementProperties.get(t),i=this.constructor._$Eu(t,s);if(i!==void 0&&s.reflect===!0){const n=(s.converter?.toAttribute!==void 0?s.converter:R).toAttribute(e,s.type);this._$Em=t,n==null?this.removeAttribute(i):this.setAttribute(i,n),this._$Em=null}}_$AK(t,e){const s=this.constructor,i=s._$Eh.get(t);if(i!==void 0&&this._$Em!==i){const n=s.getPropertyOptions(i),r=typeof n.converter=="function"?{fromAttribute:n.converter}:n.converter?.fromAttribute!==void 0?n.converter:R;this._$Em=i;const l=r.fromAttribute(e,n.type);this[i]=l??this._$Ej?.get(i)??l,this._$Em=null}}requestUpdate(t,e,s){if(t!==void 0){const i=this.constructor,n=this[t];if(s??=i.getPropertyOptions(t),!((s.hasChanged??Y)(n,e)||s.useDefault&&s.reflect&&n===this._$Ej?.get(t)&&!this.hasAttribute(i._$Eu(t,s))))return;this.C(t,e,s)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,e,{useDefault:s,reflect:i,wrapped:n},r){s&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??e??this[t]),n!==!0||r!==void 0)||(this._$AL.has(t)||(this.hasUpdated||s||(e=void 0),this._$AL.set(t,e)),i===!0&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}const t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[i,n]of this._$Ep)this[i]=n;this._$Ep=void 0}const s=this.constructor.elementProperties;if(s.size>0)for(const[i,n]of s){const{wrapped:r}=n,l=this[i];r!==!0||this._$AL.has(i)||l===void 0||this.C(i,void 0,n,l)}}let t=!1;const e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(s=>s.hostUpdate?.()),this.update(e)):this._$EM()}catch(s){throw t=!1,this._$EM(),s}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(t){}firstUpdated(t){}};g.elementStyles=[],g.shadowRootOptions={mode:"open"},g[S("elementProperties")]=new Map,g[S("finalized")]=new Map,_t?.({ReactiveElement:g}),(M.reactiveElementVersions??=[]).push("2.1.1");
|
|
12
|
+
/**
|
|
13
|
+
* @license
|
|
14
|
+
* Copyright 2017 Google LLC
|
|
15
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
16
|
+
*/const L=globalThis,O=L.trustedTypes,W=O?O.createPolicy("lit-html",{createHTML:o=>o}):void 0,tt="$lit$",_=`lit$${Math.random().toFixed(9).slice(2)}$`,et="?"+_,ft=`<${et}>`,A=document,b=()=>A.createComment(""),w=o=>o===null||typeof o!="object"&&typeof o!="function",I=Array.isArray,mt=o=>I(o)||typeof o?.[Symbol.iterator]=="function",N=`[ \t\n\f\r]`,E=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,q=/-->/g,F=/>/g,f=RegExp(`>|${N}(?:([^\\s"'>=/]+)(${N}*=${N}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),J=/'/g,K=/"/g,st=/^(?:script|style|textarea|title)$/i,At=o=>(t,...e)=>({_$litType$:o,strings:t,values:e}),G=At(1),y=Symbol.for("lit-noChange"),d=Symbol.for("lit-nothing"),Q=new WeakMap,m=A.createTreeWalker(A,129);function it(o,t){if(!I(o)||!o.hasOwnProperty("raw"))throw Error("invalid template strings array");return W!==void 0?W.createHTML(t):t}const gt=(o,t)=>{const e=o.length-1,s=[];let i,n=t===2?"<svg>":t===3?"<math>":"",r=E;for(let l=0;l<e;l++){const h=o[l];let c,p,a=-1,u=0;for(;u<h.length&&(r.lastIndex=u,p=r.exec(h),p!==null);)u=r.lastIndex,r===E?p[1]==="!--"?r=q:p[1]!==void 0?r=F:p[2]!==void 0?(st.test(p[2])&&(i=RegExp("</"+p[2],"g")),r=f):p[3]!==void 0&&(r=f):r===f?p[0]===">"?(r=i??E,a=-1):p[1]===void 0?a=-2:(a=r.lastIndex-p[2].length,c=p[1],r=p[3]===void 0?f:p[3]==='"'?K:J):r===K||r===J?r=f:r===q||r===F?r=E:(r=f,i=void 0);const $=r===f&&o[l+1].startsWith("/>")?" ":"";n+=r===E?h+ft:a>=0?(s.push(c),h.slice(0,a)+tt+h.slice(a)+_+$):h+_+(a===-2?l:$)}return[it(o,n+(o[e]||"<?>")+(t===2?"</svg>":t===3?"</math>":"")),s]};class C{constructor({strings:t,_$litType$:e},s){let i;this.parts=[];let n=0,r=0;const l=t.length-1,h=this.parts,[c,p]=gt(t,e);if(this.el=C.createElement(c,s),m.currentNode=this.el.content,e===2||e===3){const a=this.el.content.firstChild;a.replaceWith(...a.childNodes)}for(;(i=m.nextNode())!==null&&h.length<l;){if(i.nodeType===1){if(i.hasAttributes())for(const a of i.getAttributeNames())if(a.endsWith(tt)){const u=p[r++],$=i.getAttribute(a).split(_),x=/([.?@])?(.*)/.exec(u);h.push({type:1,index:n,name:x[2],strings:$,ctor:x[1]==="."?vt:x[1]==="?"?Et:x[1]==="@"?St:T}),i.removeAttribute(a)}else a.startsWith(_)&&(h.push({type:6,index:n}),i.removeAttribute(a));if(st.test(i.tagName)){const a=i.textContent.split(_),u=a.length-1;if(u>0){i.textContent=O?O.emptyScript:"";for(let $=0;$<u;$++)i.append(a[$],b()),m.nextNode(),h.push({type:2,index:++n});i.append(a[u],b())}}}else if(i.nodeType===8)if(i.data===et)h.push({type:2,index:n});else{let a=-1;for(;(a=i.data.indexOf(_,a+1))!==-1;)h.push({type:7,index:n}),a+=_.length-1}n++}}static createElement(t,e){const s=A.createElement("template");return s.innerHTML=t,s}}function v(o,t,e=o,s){if(t===y)return t;let i=s!==void 0?e._$Co?.[s]:e._$Cl;const n=w(t)?void 0:t._$litDirective$;return i?.constructor!==n&&(i?._$AO?.(!1),n===void 0?i=void 0:(i=new n(o),i._$AT(o,e,s)),s!==void 0?(e._$Co??=[])[s]=i:e._$Cl=i),i!==void 0&&(t=v(o,i._$AS(o,t.values),i,s)),t}class yt{constructor(t,e){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:e},parts:s}=this._$AD,i=(t?.creationScope??A).importNode(e,!0);m.currentNode=i;let n=m.nextNode(),r=0,l=0,h=s[0];for(;h!==void 0;){if(r===h.index){let c;h.type===2?c=new P(n,n.nextSibling,this,t):h.type===1?c=new h.ctor(n,h.name,h.strings,this,t):h.type===6&&(c=new bt(n,this,t)),this._$AV.push(c),h=s[++l]}r!==h?.index&&(n=m.nextNode(),r++)}return m.currentNode=A,i}p(t){let e=0;for(const s of this._$AV)s!==void 0&&(s.strings!==void 0?(s._$AI(t,s,e),e+=s.strings.length-2):s._$AI(t[e])),e++}}class P{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,s,i){this.type=2,this._$AH=d,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=s,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode;const e=this._$AM;return e!==void 0&&t?.nodeType===11&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=v(this,t,e),w(t)?t===d||t==null||t===""?(this._$AH!==d&&this._$AR(),this._$AH=d):t!==this._$AH&&t!==y&&this._(t):t._$litType$!==void 0?this.$(t):t.nodeType!==void 0?this.T(t):mt(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==d&&w(this._$AH)?this._$AA.nextSibling.data=t:this.T(A.createTextNode(t)),this._$AH=t}$(t){const{values:e,_$litType$:s}=t,i=typeof s=="number"?this._$AC(t):(s.el===void 0&&(s.el=C.createElement(it(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===i)this._$AH.p(e);else{const n=new yt(i,this),r=n.u(this.options);n.p(e),this.T(r),this._$AH=n}}_$AC(t){let e=Q.get(t.strings);return e===void 0&&Q.set(t.strings,e=new C(t)),e}k(t){I(this._$AH)||(this._$AH=[],this._$AR());const e=this._$AH;let s,i=0;for(const n of t)i===e.length?e.push(s=new P(this.O(b()),this.O(b()),this,this.options)):s=e[i],s._$AI(n),i++;i<e.length&&(this._$AR(s&&s._$AB.nextSibling,i),e.length=i)}_$AR(t=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);t!==this._$AB;){const s=t.nextSibling;t.remove(),t=s}}setConnected(t){this._$AM===void 0&&(this._$Cv=t,this._$AP?.(t))}}class T{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,e,s,i,n){this.type=1,this._$AH=d,this._$AN=void 0,this.element=t,this.name=e,this._$AM=i,this.options=n,s.length>2||s[0]!==""||s[1]!==""?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=d}_$AI(t,e=this,s,i){const n=this.strings;let r=!1;if(n===void 0)t=v(this,t,e,0),r=!w(t)||t!==this._$AH&&t!==y,r&&(this._$AH=t);else{const l=t;let h,c;for(t=n[0],h=0;h<n.length-1;h++)c=v(this,l[s+h],e,h),c===y&&(c=this._$AH[h]),r||=!w(c)||c!==this._$AH[h],c===d?t=d:t!==d&&(t+=(c??"")+n[h+1]),this._$AH[h]=c}r&&!i&&this.j(t)}j(t){t===d?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}}class vt extends T{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===d?void 0:t}}class Et extends T{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==d)}}class St extends T{constructor(t,e,s,i,n){super(t,e,s,i,n),this.type=5}_$AI(t,e=this){if((t=v(this,t,e,0)??d)===y)return;const s=this._$AH,i=t===d&&s!==d||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,n=t!==d&&(s===d||i);i&&this.element.removeEventListener(this.name,this,s),n&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}}class bt{constructor(t,e,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=e,this.options=s}get _$AU(){return this._$AM._$AU}_$AI(t){v(this,t)}}const wt=L.litHtmlPolyfillSupport;wt?.(C,P),(L.litHtmlVersions??=[]).push("3.3.1");const z=(o,t,e)=>{const s=e?.renderBefore??t;let i=s._$litPart$;if(i===void 0){const n=e?.renderBefore??null;s._$litPart$=i=new P(t.insertBefore(b(),n),n,void 0,e??{})}return i._$AI(o),i};
|
|
17
|
+
/**
|
|
18
|
+
* @license
|
|
19
|
+
* Copyright 2017 Google LLC
|
|
20
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
21
|
+
*/const D=globalThis;class H extends g{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){const t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){const e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=z(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return y}}H._$litElement$=!0,H.finalized=!0,D.litElementHydrateSupport?.({LitElement:H});const Ct=D.litElementPolyfillSupport;Ct?.({LitElement:H});(D.litElementVersions??=[]).push("4.2.1");const Pt="/api/plugin/zoom-plugin",xt=Pt;function Ut(){const o=document.querySelectorAll("[data-zoomable]");for(const t of o){if(!(t instanceof HTMLElement))continue;const e=t.dataset.zoomable?.trim();e&&Ht(t,{mediaId:e})}}function Ht(o,{mediaId:t}){o.classList.add("PaZoomable"),o.setAttribute("tabindex","0"),o.addEventListener("click",async e=>{e.preventDefault(),await Ot(t)})}async function Ot(o){const t=document.createElement("div"),e=ot({dialogContent:t,modalClass:"_paZoomViewer"});e.open(),z(G`
|
|
22
|
+
<div class="PaZoomContent">
|
|
23
|
+
<div class="PaZoomContent-spinner"></div>
|
|
24
|
+
</div>
|
|
25
|
+
`,t);try{const s=await fetch(`${xt}/zoom-image?mediaId=${encodeURIComponent(o)}`);if(!s.ok){console.error("Failed to fetch zoom image:",s.statusText),e.close();return}const i=await s.json();z(G`
|
|
26
|
+
<div class="PaZoomContent">
|
|
27
|
+
<img
|
|
28
|
+
class="PaZoomContent-img"
|
|
29
|
+
src="${i.url}"
|
|
30
|
+
width="${i.width}"
|
|
31
|
+
height="${i.height}"
|
|
32
|
+
alt=""
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
`,t)}catch(s){console.error("Error fetching zoom image:",s),e.close()}}Ut();
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@paroicms/zoom-plugin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Image zoom viewer plugin for ParoiCMS",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"paroicms",
|
|
7
|
+
"plugin",
|
|
8
|
+
"zoom",
|
|
9
|
+
"image"
|
|
10
|
+
],
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://gitlab.com/paroi/opensource/paroicms.git",
|
|
14
|
+
"directory": "plugins/zoom-plugin"
|
|
15
|
+
},
|
|
16
|
+
"author": "Paroi Team",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "backend/dist/index.js",
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "npm run build:backend && npm run build:frontend",
|
|
22
|
+
"build:backend": "(cd backend && tsc)",
|
|
23
|
+
"build:backend:watch": "(cd backend && tsc --watch --preserveWatchOutput)",
|
|
24
|
+
"build:frontend": "(cd frontend && npm run build)",
|
|
25
|
+
"build:frontend:watch": "(cd frontend && npm run build:watch)",
|
|
26
|
+
"clear": "rimraf backend/dist/* frontend/dist/*"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@paroicms/script-lib": "0.3.2",
|
|
30
|
+
"arktype": "~2.1.20"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"@paroicms/public-anywhere-lib": "0",
|
|
34
|
+
"@paroicms/public-server-lib": "0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@paroicms/public-anywhere-lib": "0.37.0",
|
|
38
|
+
"@paroicms/public-server-lib": "0.47.0",
|
|
39
|
+
"@types/node": "~24.0.1",
|
|
40
|
+
"rimraf": "~6.0.1",
|
|
41
|
+
"typescript": "~5.9.2"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"backend/dist",
|
|
45
|
+
"frontend/dist"
|
|
46
|
+
]
|
|
47
|
+
}
|