APP-EXODUS E3 prep: backfill 16 current b/ bodies to sha256 mirror (mirror-first before any CAS exodus)
Browse files- sha256/026c320b1e9de27af7ac42d21d1544035c409fb4c1912507bac0eb28811ca34e +95 -0
- sha256/28186f18edebe4a990c721dc98594d94f74ab02b8eea40d67b04a4b7b777be7f +1 -0
- sha256/2a19268225fab8e102982de6e490c3e3468bedcfe368407aaa3525b78eb7cf34 +1 -0
- sha256/304e4bf228c2aeade13b288617aab175a53d04f8ea3d305dc65a92c8973cc3df +1 -0
- sha256/3fd2a00105ad0e8f01109dce52ff4c7a0cc6c9444532b0453ed9d770cce2d3a4 +35 -0
- sha256/65a4954f079070d79a8687acb55ef9927de74599bbdc0afbc8400cb4b0d75fac +1309 -0
- sha256/6ff8513d484fcf377d948147762b83dafd3cdefd3d48d4333669407808a7653c +0 -0
- sha256/7c0ac719466c48d161fba6b77fdcee5a6c017f9d540da575f23191ddbc97d982 +0 -0
- sha256/929cb2072b4084ca0195c2c0cb65190340c29e62c6b5c50dc1cebf8b788f6eca +1 -0
- sha256/946dd4ca8e36408f3e5da27813cdafad3908e2a3466dc86e82eff442de4b813f +0 -0
- sha256/9ffc94e11c78fbe6b940bc04ac92f0f12238cf7ce82b5092c53d5761146a50df +0 -0
- sha256/ba0a74a49b10960552dd4778d210a152990ee94b69a2847699c630f94f87182d +1 -0
- sha256/bdb559bd0dec93fd70e9c1ed515bbd483ff4cadc8ce38df946983adca29c604e +367 -0
- sha256/bf790f49c2c3366fae494488b1832dac05908e18a37f5b5dd4292c76a6d130f7 +378 -0
- sha256/d76d596376d1203a8c170ddbe9dab02442158671646c630ee1902d5953e63fc5 +551 -0
- sha256/eb343aaebd5beec6186750769cdd48ddde4440b78f92d46c2cb851e893237944 +1 -0
sha256/026c320b1e9de27af7ac42d21d1544035c409fb4c1912507bac0eb28811ca34e
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// messenger-skin.mjs β bakes the SLACK re-tone as the messenger default (aubergine chrome + a floating,
|
| 2 |
+
// inset content pane; see the data-skin="slack" block in messenger-skins) and applies the hi-DPI /
|
| 3 |
+
// high-FPS perf layer. No picker / no toggle. Additive + guarded. Escape hatch: set localStorage
|
| 4 |
+
// "holo.skin" to graphite | warm | contrast | light (or "" to remove) to override the default.
|
| 5 |
+
|
| 6 |
+
(function () {
|
| 7 |
+
if (!document.querySelector("link[data-holo-skins]")) {
|
| 8 |
+
const l = document.createElement("link"); l.rel = "stylesheet"; l.href = new URL("./messenger-skins.css?v=d76d596376d1", import.meta.url); l.setAttribute("data-holo-skins", "1"); document.head.appendChild(l);
|
| 9 |
+
}
|
| 10 |
+
let skin = "whatsapp";
|
| 11 |
+
try { const s = localStorage.getItem("holo.skin"); if (s) skin = s; } catch {}
|
| 12 |
+
// ?skin=aim β the AIM opt-in for THIS visit (session-only; the saved default is untouched)
|
| 13 |
+
try { const q = new URLSearchParams(location.search).get("skin"); if (q) skin = q; } catch {}
|
| 14 |
+
if (skin) document.documentElement.setAttribute("data-skin", skin); else document.documentElement.removeAttribute("data-skin");
|
| 15 |
+
// the AIM experience layer (buddy list Β· sign-on Β· away Β· door sounds, A0-A5) rides ONLY its own skin β
|
| 16 |
+
// every other skin pays nothing. Lazy + fail-soft, the holo-msg-mount idiom.
|
| 17 |
+
if (skin === "aim") { try { import("./holo-aim.mjs?v=aim1").catch(() => {}); } catch {} }
|
| 18 |
+
// remove any lingering picker + its persisted flag from earlier ?skins=1 sessions
|
| 19 |
+
try { localStorage.removeItem("holo.skins"); } catch {}
|
| 20 |
+
try { const p = document.querySelector(".holo-skin-pick"); if (p) p.remove(); } catch {}
|
| 21 |
+
})();
|
| 22 |
+
|
| 23 |
+
// ββ UX ENHANCER (whatsapp-ux-v1) β additive, guarded, DOM-only. Two WhatsApp-desktop niceties the compiled
|
| 24 |
+
// bundle can't get surgically: (1) a DRAG-RESIZE divider between the chat list and the conversation, persisted
|
| 25 |
+
// per device; (2) CLICK-AWAY / tap-outside close for the composer "+" attach sheet and the emoji popover (the
|
| 26 |
+
// message + row menus already close on outside-click via the bundle; these two didn't). Everything here is
|
| 27 |
+
// idempotent and fail-open β if the DOM shape ever changes, it simply does nothing.
|
| 28 |
+
(function () {
|
| 29 |
+
const root = document.documentElement, LS_W = "holo.side.w";
|
| 30 |
+
const MIN = 260, MAXPX = 560, MAXPCT = 0.46;
|
| 31 |
+
const applyWidth = (px) => { if (px == null) root.style.removeProperty("--holo-side-w"); else root.style.setProperty("--holo-side-w", px + "px"); };
|
| 32 |
+
// returning users reopen at their chosen width (set before first paint)
|
| 33 |
+
try { const v = parseFloat(localStorage.getItem(LS_W)); if (v > 0) applyWidth(v); } catch {}
|
| 34 |
+
|
| 35 |
+
const container = () => document.querySelector(".holo-wa-root .cs-main-container");
|
| 36 |
+
const sidebar = () => document.querySelector(".holo-wa-root .cs-sidebar.cs-sidebar--left");
|
| 37 |
+
|
| 38 |
+
function ensureHandle() {
|
| 39 |
+
if (window.innerWidth < 900) return; // desktop only
|
| 40 |
+
const c = container(); if (!c) return;
|
| 41 |
+
if (c.querySelector(":scope > .holo-side-resize")) return; // already mounted
|
| 42 |
+
const h = document.createElement("div");
|
| 43 |
+
h.className = "holo-side-resize"; h.title = "Drag to resize, double-click to reset"; h.setAttribute("aria-hidden", "true");
|
| 44 |
+
c.appendChild(h);
|
| 45 |
+
let startX = 0, startW = 0, raf = 0, pending = 0;
|
| 46 |
+
const maxW = () => Math.min(MAXPX, Math.round((c.clientWidth || window.innerWidth) * MAXPCT));
|
| 47 |
+
const onMove = (e) => {
|
| 48 |
+
pending = Math.max(MIN, Math.min(maxW(), startW + (e.clientX - startX)));
|
| 49 |
+
if (!raf) raf = requestAnimationFrame(() => { raf = 0; applyWidth(pending); });
|
| 50 |
+
};
|
| 51 |
+
const onUp = () => {
|
| 52 |
+
document.removeEventListener("pointermove", onMove);
|
| 53 |
+
document.removeEventListener("pointerup", onUp);
|
| 54 |
+
document.body.classList.remove("holo-side-dragging");
|
| 55 |
+
h.classList.remove("holo-drag");
|
| 56 |
+
if (raf) { cancelAnimationFrame(raf); raf = 0; }
|
| 57 |
+
applyWidth(pending);
|
| 58 |
+
try { localStorage.setItem(LS_W, String(pending)); } catch {}
|
| 59 |
+
};
|
| 60 |
+
h.addEventListener("pointerdown", (e) => {
|
| 61 |
+
if (e.button !== 0) return;
|
| 62 |
+
e.preventDefault();
|
| 63 |
+
const sb = sidebar(); if (!sb) return;
|
| 64 |
+
startX = e.clientX; startW = Math.round(sb.getBoundingClientRect().width); pending = startW;
|
| 65 |
+
document.body.classList.add("holo-side-dragging"); h.classList.add("holo-drag");
|
| 66 |
+
document.addEventListener("pointermove", onMove);
|
| 67 |
+
document.addEventListener("pointerup", onUp);
|
| 68 |
+
});
|
| 69 |
+
h.addEventListener("dblclick", (e) => { e.preventDefault(); applyWidth(null); try { localStorage.removeItem(LS_W); } catch {} }); // reset to default
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
const boot = () => {
|
| 73 |
+
ensureHandle();
|
| 74 |
+
try { new MutationObserver(() => ensureHandle()).observe(document.body, { childList: true, subtree: true }); } catch {}
|
| 75 |
+
window.addEventListener("resize", ensureHandle, { passive: true });
|
| 76 |
+
};
|
| 77 |
+
if (document.body) boot(); else window.addEventListener("DOMContentLoaded", boot, { once: true });
|
| 78 |
+
|
| 79 |
+
// (2) click-away close for the two composer popovers. They close cleanly through the app's OWN Escape handler,
|
| 80 |
+
// so dispatch Escape on an outside pointerdown. pointerdown fires BEFORE React's onClick, and skipping the
|
| 81 |
+
// composer icons (the triggers) avoids the toggle-reopen race.
|
| 82 |
+
document.addEventListener("pointerdown", (e) => {
|
| 83 |
+
const pop = document.querySelector(".holo-attach-menu, .holo-emoji-pop");
|
| 84 |
+
if (!pop) return; // nothing open
|
| 85 |
+
if (pop.contains(e.target)) return; // clicked inside β keep open
|
| 86 |
+
if (e.target.closest && e.target.closest(".holo-c-icon")) return; // a composer trigger β let it toggle
|
| 87 |
+
try { document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", bubbles: true })); } catch {}
|
| 88 |
+
}, true);
|
| 89 |
+
})();
|
| 90 |
+
|
| 91 |
+
// ββ AUDITED E2E STACK (whatsapp-e2e-voz) β activate the additive vodozemac Olm/Megolm engine as an OPT-IN
|
| 92 |
+
// (window.HoloMsg). Importing only DEFINES the door; the 393 KB crypto wasm + the spine load on FIRST USE,
|
| 93 |
+
// so the default holo-seal door pays nothing and is entirely untouched. Nothing calls HoloMsg yet β this
|
| 94 |
+
// just makes the audited Double-Ratchet engine LIVE-CAPABLE; the UI opt-in (?e2e=voz) is the next step.
|
| 95 |
+
try { import("./holo-msg-mount.mjs").catch(() => {}); } catch {}
|
sha256/28186f18edebe4a990c721dc98594d94f74ab02b8eea40d67b04a4b7b777be7f
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
import{$ as I,B as z,Ca as fe,H as te,I as ne,Ib as Le,J as ae,Ja as pe,Ma as Re,Pa as w,Qa as ge,Sa as O,X as oe,aa as m,ab as ve,b as ee,ba as R,bb as A,ca as F,cb as Te,da as x,ea as le,ga as se,ha as ie,ia as re,k as D,kb as Ee,la as ce,nb as B,o as $,rb as Ce,sa as ue,sb as ye,ta as me,ub as H,va as de,wa as he,ya as be}from"./chunk-E6U7U64M.js";import"./chunk-SXSU3V5W.js";import{a as Ve}from"./chunk-EJ2FITLI.js";import{b as Ue}from"./chunk-SQE76S5B.js";var e=Ue(Ve(),1);var T={ref:null,position:"bottom",width:120,height:80,border:1,borderRadius:4,padding:4,gap:16,imageFit:"contain",vignette:!0,hidden:!1,showToggle:!1},Y=t=>({...T,...t});function xe(){let{thumbnails:t}=w();return Y(t)}var E=t=>F($,t),u=t=>E(F("thumbnail",t)),De=A("VideoThumbnail",e.createElement("path",{d:"M10 16.5l6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"})),Fe=A("UnknownThumbnail",e.createElement("path",{d:"M23 18V6c0-1.1-.9-2-2-2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zM8.5 12.5l2.5 3.01L14.5 11l4.5 6H5l3.5-4.5z"}));function Oe({slide:t,render:n,rect:o,imageFit:l}){var r;let d=(r=n.thumbnail)===null||r===void 0?void 0:r.call(n,{slide:t,render:n,rect:o,imageFit:l});if(d)return d;let p={render:n,rect:o,imageFit:l};if(t.thumbnail)return e.createElement(H,{slide:{src:t.thumbnail},...p});if(ce(t))return e.createElement(H,{slide:t,...p});let h=m(u(oe));return t.type==="video"?e.createElement(e.Fragment,null,t.poster&&e.createElement(H,{slide:{src:t.poster},...p}),e.createElement(De,{className:h})):e.createElement(Fe,{className:h})}var Be=x("active"),X=x("fadein"),K=x("fadeout"),Xe=x("placeholder"),Ne="delay",Pe="duration";function Ke({slide:t,index:n,onClick:o,fadeIn:l,fadeOut:r,placeholder:d,onLoseFocus:p}){let h=e.useRef(null),{render:g,styles:C,labels:s}=w(),{slides:b,globalIndex:U}=O(),{getOwnerDocument:M}=pe(),{width:L,height:_,imageFit:N}=xe(),P={width:L,height:_},S=n===U,k=B(p);return e.useEffect(()=>{r&&M().activeElement===h.current&&k()},[r,k,M]),e.createElement("button",{ref:h,type:"button",className:I(m(z),m(u()),S&&m(u(Be())),l&&m(u(X())),r&&m(u(K())),d&&m(u(Xe()))),style:{...l?{[R(u(X(Pe)))]:`${l.duration}ms`,[R(u(X(Ne)))]:`${l.delay}ms`}:null,...r?{[R(u(K(Pe)))]:`${r.duration}ms`,[R(u(K(Ne)))]:`${r.delay}ms`}:null,...C.thumbnail},onClick:o,"aria-current":S?!0:void 0,"aria-label":se(s,b,n)},t&&Oe({slide:t,render:g,rect:P,imageFit:N}))}function Se(t){return["top","bottom"].includes(t)}function ke(t,n){return n+2*(t.border+t.padding)+t.gap}function Ye(t){let{thumbnail:n,poster:o}=t||{thumbnail:"placeholder"};return typeof n=="string"&&n||typeof o=="string"&&o||t&&de(t)||void 0}function Ie({visible:t,containerRef:n}){let o=e.useRef(null),l=Ce(),{publish:r,subscribe:d}=Re(),{carousel:p,styles:h,labels:g}=w(),{slides:C,globalIndex:s,animation:b}=O(),{registerSensors:U,subscribeSensors:M}=ye();Le(M);let L=xe(),{position:_,width:N,height:P,border:S,borderStyle:k,borderColor:j,borderRadius:G,padding:W,gap:q,vignette:_e}=L,i=b?.duration!==void 0&&b?.increment||0,J=b?.duration||0,{prepareAnimation:$e}=Ee(o,a=>({keyframes:Se(_)?[{transform:`translateX(${(l?-1:1)*ke(L,N)*i+a}px)`},{transform:"translateX(0)"}]:[{transform:`translateY(${ke(L,P)*i+a}px)`},{transform:"translateY(0)"}],duration:J,easing:b?.easing})),Q=B(()=>{let a=0;if(n.current&&o.current){let c=n.current.getBoundingClientRect(),v=o.current.getBoundingClientRect();a=Se(_)?v.left-c.left-(c.width-v.width)/2:v.top-c.top-(c.height-v.height)/2}$e(a)});e.useEffect(()=>ie(d(ae,Q)),[d,Q]);let f=be(p,C),Z=[];if(ue(C))for(let a=s-f-Math.abs(i);a<=s+f+Math.abs(i);a+=1){let v=p.finite&&(a<0||a>C.length-1)||i<0&&a<s-f||i>0&&a>s+f?null:me(C,a),y=[`${a}`,Ye(v)].filter(Boolean).join("|");Z.push({key:y,index:a,slide:v})}let ze=a=>()=>{a>s?r(ne,{count:a-s}):a<s&&r(te,{count:s-a})};return e.createElement("div",{className:I(m(E("container")),m(z)),style:{...t?null:{display:"none"},...N!==T.width?{[R(u("width"))]:`${N}px`}:null,...P!==T.height?{[R(u("height"))]:`${P}px`}:null,...S!==T.border?{[R(u("border"))]:`${S}px`}:null,...k?{[R(u("border_style"))]:k}:null,...j?{[R(u("border_color"))]:j}:null,...G!==T.borderRadius?{[R(u("border_radius"))]:`${G}px`}:null,...W!==T.padding?{[R(u("padding"))]:`${W}px`}:null,...q!==T.gap?{[R(u("gap"))]:`${q}px`}:null,...h.thumbnailsContainer}},e.createElement("nav",{ref:o,style:h.thumbnailsTrack,className:I(m(E("track")),m(z)),"aria-label":le(g,"Thumbnails"),tabIndex:-1,...U},Z.map(({key:a,index:c,slide:v})=>{let y=J/Math.abs(i||1),Ae=i>0&&c>s+f-i&&c<=s+f||i<0&&c<s-f-i&&c>=s-f?{duration:y,delay:((i>0?c-(s+f-i):s-f-i-c)-1)*y}:void 0,He=i>0&&c<s-f||i<0&&c>s+f?{duration:y,delay:(i>0?i-(s-f-c):-i-(c-(s+f)))*y}:void 0;return e.createElement(Ke,{key:a,index:c,slide:v,fadeIn:Ae,fadeOut:He,placeholder:!v,onClick:ze(c),onLoseFocus:()=>{var V;return(V=o.current)===null||V===void 0?void 0:V.focus()}})})),_e&&e.createElement("div",{className:m(E("vignette"))}))}var we=e.createContext(null),je=re("useThumbnails","ThumbnailsContext",we);function Ge({children:t,...n}){let{ref:o,position:l,hidden:r}=Y(n.thumbnails),[d,p]=e.useState(!r),h=e.useRef(null),g=e.useMemo(()=>({visible:d,show:()=>p(!0),hide:()=>p(!1)}),[d]);return e.useImperativeHandle(o,()=>g,[g]),e.createElement(ge,{...n},e.createElement(we.Provider,{value:g},e.createElement("div",{ref:h,className:I(m(E()),m(E(`${l}`)))},["start","top"].includes(l)&&e.createElement(Ie,{containerRef:h,visible:d}),e.createElement("div",{className:m(E("wrapper"))},t),["end","bottom"].includes(l)&&e.createElement(Ie,{containerRef:h,visible:d}))))}var Me=()=>e.createElement(e.Fragment,null,e.createElement("path",{strokeWidth:2,stroke:"currentColor",strokeLinejoin:"round",fill:"none",d:"M3 5l18 0l0 14l-18 0l0-14z"}),e.createElement("path",{d:"M5 14h4v3h-4zM10 14h4v3h-4zM15 14h4v3h-4z"})),We=A("ThumbnailsVisible",Me()),qe=Te("ThumbnailsHidden",Me());function Je(){let{visible:t,show:n,hide:o}=je(),{render:l}=w();return l.buttonThumbnails?e.createElement(e.Fragment,null,l.buttonThumbnails({visible:t,show:n,hide:o})):e.createElement(ve,{label:t?"Hide thumbnails":"Show thumbnails",icon:t?We:qe,renderIcon:t?l.iconThumbnailsVisible:l.iconThumbnailsHidden,onClick:t?o:n})}function et({augment:t,contains:n,append:o,addParent:l}){t(({thumbnails:d,toolbar:p,...h})=>{let g=Y(d);return{toolbar:he(p,$,g.showToggle?e.createElement(Je,null):null),thumbnails:g,...h}});let r=fe($,Ge);n(D)?o(D,r):l(ee,r)}export{et as default};
|
sha256/2a19268225fab8e102982de6e490c3e3468bedcfe368407aaa3525b78eb7cf34
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
import"./chunk-SQE76S5B.js";var D=typeof TextEncoder<"u"?new TextEncoder:null;async function b(o){let c=await crypto.subtle.digest("SHA-256",D.encode(o));return[...new Uint8Array(c)].map(y=>y.toString(16).padStart(2,"0")).join("")}var S=o=>b(JSON.stringify([o.v,o.kind,o.text||"",o.bg||"",o.caption||"",o.dataUrl||"",o.at,o.ttl,o.author,o.name||""]));async function O({hd:o=null,now:c=()=>Date.now(),ttlMs:y=864e5}={}){if(o=o||(typeof window<"u"?window.HoloDirect:null),!o||!o.onStory)throw new Error("status needs the HoloDirect story rail");let d=o.mySign?await o.mySign():null,T=()=>{try{return(localStorage.getItem("holo.direct.name")||"").trim()||null}catch{return null}},i=null;try{i=await(await navigator.storage.getDirectory()).getDirectoryHandle("holo-status",{create:!0})}catch{}let a=new Map,g=new Set,l=()=>{for(let t of g)try{t()}catch{}},f=t=>t&&t.at+(t.ttl||y)>c();async function w(t){if(a.set(t.id,t),i)try{let n=await(await i.getFileHandle(t.id,{create:!0})).createWritable();await n.write(JSON.stringify(t)),await n.close()}catch{}}async function h(t){if(a.delete(t),i)try{await i.removeEntry(t)}catch{}}if(i)try{for await(let[t,e]of i.entries())try{let n=JSON.parse(await(await e.getFile()).text());f(n)?a.set(n.id,n):await i.removeEntry(t)}catch{}}catch{}async function A({kind:t,dataUrl:e=null,text:n=null,bg:r=null,caption:u=null}){if(t!=="photo"&&t!=="text")return{ok:!1,error:"kind must be photo|text"};if(t==="photo"&&(!e||String(e).length>2e5))return{ok:!1,error:"photo missing or too large \u2014 downscale to \u22641080px JPEG first"};if(t==="text"&&!(n||"").trim())return{ok:!1,error:"text story needs text"};let s={v:1,kind:t,dataUrl:t==="photo"?e:null,text:n?String(n).slice(0,700):null,bg:r||null,caption:u?String(u).slice(0,700):null,at:c(),ttl:y,author:d,name:T()};s.id=await S(s),await w({...s,mine:!0,seen:!0,viewers:{}}),l();let m={sent:0,contacts:0};try{m=await o.postStory(s)}catch{}return{ok:!0,id:s.id,...m}}async function p({contactId:t,sign:e,frame:n}){if(n.t==="story"){let r=n.story;if(!r||r.v!==1||r.author!==e||!f(r)||String(r.dataUrl||"").length>2e5||String(r.text||"").length>700||await S(r)!==r.id||a.has(r.id))return;await w({...r,authorCid:t||null,mine:!1,seen:!1,viewers:{}}),l()}else if(n.t==="story-ack"){let r=a.get(n.id);r&&r.mine&&e&&(r.viewers[e]=n.ts||c(),await w(r),l())}else if(n.t==="story-revoke"){let r=a.get(n.id);r&&r.author===e&&!r.mine&&(await h(n.id),l())}}o.onStory(t=>{p(t).catch(()=>{})});function x(){let t=new Map;for(let n of a.values()){if(!f(n))continue;let r=n.mine?"me":n.author;(t.get(r)||t.set(r,[]).get(r)).push(n)}for(let n of t.values())n.sort((r,u)=>r.at-u.at);let e=[...t.entries()].sort(([n,r],[u,s])=>n==="me"?-1:u==="me"?1:s[s.length-1].at-r[r.length-1].at);return new Map(e)}let _=()=>{let t=0;for(let e of a.values())f(e)&&!e.mine&&!e.seen&&t++;return t};async function E(t){let e=a.get(t);if(!(!e||e.mine||e.seen)){e.seen=!0,await w(e),l();try{await o.storyCtl(e.authorCid||e.author,{t:"story-ack",id:t,ts:c()})}catch{}}}async function M(t){let e=a.get(t);if(!e||!e.mine)return{ok:!1,error:"not yours"};await h(t),l();try{await o.storyFan({t:"story-revoke",id:t,ts:c()})}catch{}return{ok:!0}}let X=t=>{let e=a.get(t);return e&&e.mine?Object.entries(e.viewers).map(([n,r])=>({sign:n,ts:r})):[]},k=setInterval(()=>{let t=0;for(let[e,n]of a)f(n)||(h(e),t++);t&&l()},6e4);return{post:A,feed:x,unseenCount:_,markSeen:E,revoke:M,viewersOf:X,mySign:d,onChange:t=>(g.add(t),()=>g.delete(t)),_ingest:p,destroy:()=>{clearInterval(k),g.clear()}}}var v=null;function C(o){return v=v||O(o)}export{O as createStatusEngine,C as getStatusEngine};
|
sha256/304e4bf228c2aeade13b288617aab175a53d04f8ea3d305dc65a92c8973cc3df
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
import{Pa as w,Sa as p,ab as m,bb as v,j as s,la as u,wa as f}from"./chunk-E6U7U64M.js";import"./chunk-SXSU3V5W.js";import{a as L}from"./chunk-EJ2FITLI.js";import{b as g}from"./chunk-SQE76S5B.js";var d=g(L(),1);var x={download:void 0},D=e=>({...x,...e});function I(e){if(!e)return;let n=/filename\*\s*=\s*UTF-8''([^;]+)/i.exec(e);if(n)try{let l=decodeURIComponent(n[1].trim());if(l)return l}catch{}let o=/filename\s*=\s*("[^"]*"|[^;]+)/i.exec(e);return o?.[1].trim().replace(/^"(.*)"$/,"$1")||void 0}function U(e){var n,o;return(o=(n=/^content-disposition:(.*)$/im.exec(e.getAllResponseHeaders()))===null||n===void 0?void 0:n[1])!==null&&o!==void 0?o:null}function _(e,n){let o=new XMLHttpRequest;o.open("GET",e),o.responseType="blob",o.onload=()=>{i(o.response,n||I(U(o)))},o.onerror=()=>{console.error("Failed to download file")},o.send()}function y(e){let n=new XMLHttpRequest;n.open("HEAD",e,!1);try{n.send()}catch{}return n.status>=200&&n.status<=299}function r(e){try{e.dispatchEvent(new MouseEvent("click"))}catch{let o=document.createEvent("MouseEvents");o.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),e.dispatchEvent(o)}}function i(e,n){let o=document.createElement("a");o.rel="noopener",o.download=n||"",o.download||(o.target="_blank"),typeof e=="string"?(o.href=e,o.origin!==window.location.origin?y(o.href)?_(e,n):(o.target="_blank",r(o)):r(o)):(o.href=URL.createObjectURL(e),setTimeout(()=>URL.revokeObjectURL(o.href),3e4),setTimeout(()=>r(o),0))}var k=v("DownloadIcon",d.createElement("path",{d:"M18 15v3H6v-3H4v3c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2v-3h-2zm-1-4-1.41-1.41L13 12.17V4h-2v8.17L8.41 9.59 7 11l5 5 5-5z"}));function F(){let{render:e,on:n,download:o}=w(),{download:l}=D(o),{currentSlide:t,currentIndex:b}=p();if(e.buttonDownload)return d.createElement(d.Fragment,null,e.buttonDownload());let c=t&&(t.downloadUrl||typeof t.download=="string"&&t.download||typeof t.download=="object"&&t.download.url||u(t)&&t.src)||void 0,h=l?t?.download!==!1:!!c,E=()=>{if(t&&c){let a=t.downloadFilename||typeof t.download=="object"&&t.download.filename||void 0;i(c,a)}},R=()=>{var a;t&&((l||E)({slide:t,saveAs:i}),(a=n.download)===null||a===void 0||a.call(n,{index:b}))};return d.createElement(m,{label:"Download",icon:k,renderIcon:e.iconDownload,disabled:!h,onClick:R})}function T({augment:e}){e(({toolbar:n,download:o,...l})=>({toolbar:f(n,s,d.createElement(F,null)),download:D(o),...l}))}export{T as default};
|
sha256/3fd2a00105ad0e8f01109dce52ff4c7a0cc6c9444532b0453ed9d770cce2d3a4
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!doctype html><html lang="en"><head><meta charset="utf-8">
|
| 2 |
+
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
| 3 |
+
<title>HOLOGRAM</title>
|
| 4 |
+
<style>html,body{margin:0;height:100%;background:#101010;color:#eee;font:15px/1.5 system-ui,sans-serif}
|
| 5 |
+
.boot{display:grid;place-items:center;height:100%;text-align:center;gap:.6rem}
|
| 6 |
+
.boot small{color:#888}.boot b{font-size:1.1rem;font-weight:700}</style>
|
| 7 |
+
<script>
|
| 8 |
+
// The ΞΊ-Jellyfin wrapper (SHIP D1/D2/D3): register OUR Service Worker at THIS app's scope
|
| 9 |
+
// (/Q/apps/jellyfin/ live Β· / in the harness) β it becomes the media server β then hand off to
|
| 10 |
+
// jellyfin-web. Evict any foreign SW (jellyfin-web ships its own PWA worker at /web/ that would hijack
|
| 11 |
+
// the scope). The built SW is a CLASSIC script (Firefox has no module SWs; evicted imports 404) β so no
|
| 12 |
+
// { type:"module" } here. Same-origin only; degrades to a message if SWs are unavailable.
|
| 13 |
+
(function () {
|
| 14 |
+
var base = location.pathname.replace(/index\.html$/, ""); // this app's root = the SW scope
|
| 15 |
+
var swUrl = base + "holo-jellyfin-sw.js";
|
| 16 |
+
var mine = function (u) { return /holo-jellyfin-sw/.test(u || ""); };
|
| 17 |
+
function fail(m) { document.title = "SW FAILED: " + m; var e = document.getElementById("msg"); if (e) e.textContent = "Couldnβt start the media server: " + m; }
|
| 18 |
+
if (!("serviceWorker" in navigator)) { return fail("this browser has no Service Workers"); }
|
| 19 |
+
var ctl = navigator.serviceWorker.controller;
|
| 20 |
+
if (ctl && mine(ctl.scriptURL)) { location.replace(base + "web/index.html"); return; } // already ours β go
|
| 21 |
+
navigator.serviceWorker.getRegistrations()
|
| 22 |
+
.then(function (rs) { return Promise.all(rs.filter(function (r) { return !mine(r.active && r.active.scriptURL); }).map(function (r) { return r.unregister(); })); })
|
| 23 |
+
.then(function () { return navigator.serviceWorker.register(swUrl, { scope: base }); })
|
| 24 |
+
.then(function (reg) {
|
| 25 |
+
var go = function () { location.replace(base + "web/index.html"); };
|
| 26 |
+
if (reg.active && navigator.serviceWorker.controller) return go();
|
| 27 |
+
navigator.serviceWorker.addEventListener("controllerchange", go);
|
| 28 |
+
var w = reg.installing || reg.waiting || reg.active;
|
| 29 |
+
if (w) w.addEventListener("statechange", function (e) { if (e.target.state === "activated") setTimeout(go, 60); });
|
| 30 |
+
setTimeout(go, 2500); // belt-and-braces: control usually lands < 1s
|
| 31 |
+
})
|
| 32 |
+
.catch(function (e) { fail(e && e.message || String(e)); });
|
| 33 |
+
})();
|
| 34 |
+
</script></head>
|
| 35 |
+
<body><div class="boot"><b>HOLOGRAM</b><small id="msg">Starting your media serverβ¦</small></div></body></html>
|
sha256/65a4954f079070d79a8687acb55ef9927de74599bbdc0afbc8400cb4b0d75fac
ADDED
|
@@ -0,0 +1,1309 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import{a as o}from"./chunk-SQE76S5B.js";var a=o((exports,module)=>{(()=>{"use strict";var __webpack_modules__={"./src/index.ts":((__unused_webpack_module,exports,__webpack_require__)=>{eval(`
|
| 2 |
+
exports.__esModule = true;
|
| 3 |
+
exports.Zuck = void 0;
|
| 4 |
+
var utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
|
| 5 |
+
var options_1 = __webpack_require__(/*! ./options */ "./src/options.ts");
|
| 6 |
+
var modal_1 = __webpack_require__(/*! ./modal */ "./src/modal.ts");
|
| 7 |
+
var Zuck = function (timeline, options) {
|
| 8 |
+
if (!timeline.id) {
|
| 9 |
+
timeline.setAttribute('id', (0, utils_1.generateId)());
|
| 10 |
+
}
|
| 11 |
+
var id = timeline.id;
|
| 12 |
+
var _a = (0, options_1.loadOptions)(options), option = _a.option, callbackOption = _a.callback, templateOption = _a.template, languageOption = _a.language;
|
| 13 |
+
var data = option('stories') || [];
|
| 14 |
+
var internalData = {};
|
| 15 |
+
/* data functions */
|
| 16 |
+
var saveLocalData = function (key, data) {
|
| 17 |
+
try {
|
| 18 |
+
if (option('localStorage') && (0, utils_1.hasWindow)()) {
|
| 19 |
+
var keyName = "zuck-".concat(id, "-").concat(key);
|
| 20 |
+
window.localStorage[keyName] = JSON.stringify(data);
|
| 21 |
+
}
|
| 22 |
+
}
|
| 23 |
+
catch (e) { }
|
| 24 |
+
};
|
| 25 |
+
var getLocalData = function (key) {
|
| 26 |
+
if (option('localStorage') && (0, utils_1.hasWindow)()) {
|
| 27 |
+
var keyName = "zuck-".concat(id, "-").concat(key);
|
| 28 |
+
return window.localStorage[keyName]
|
| 29 |
+
? JSON.parse(window.localStorage[keyName])
|
| 30 |
+
: undefined;
|
| 31 |
+
}
|
| 32 |
+
else {
|
| 33 |
+
return undefined;
|
| 34 |
+
}
|
| 35 |
+
};
|
| 36 |
+
internalData.seenItems = getLocalData('seenItems') || {};
|
| 37 |
+
var playVideoItem = function (storyViewer, elements, unmute) {
|
| 38 |
+
var itemElement = elements === null || elements === void 0 ? void 0 : elements[1];
|
| 39 |
+
var itemPointer = elements === null || elements === void 0 ? void 0 : elements[0];
|
| 40 |
+
if (!itemElement || !itemPointer) {
|
| 41 |
+
return false;
|
| 42 |
+
}
|
| 43 |
+
var cur = internalData.currentVideoElement;
|
| 44 |
+
if (cur) {
|
| 45 |
+
cur.pause();
|
| 46 |
+
}
|
| 47 |
+
if (itemElement.getAttribute('data-type') === 'video') {
|
| 48 |
+
var video_1 = itemElement.querySelector('video');
|
| 49 |
+
if (!video_1) {
|
| 50 |
+
internalData.currentVideoElement = undefined;
|
| 51 |
+
return false;
|
| 52 |
+
}
|
| 53 |
+
var setDuration = function () {
|
| 54 |
+
var duration = video_1.duration;
|
| 55 |
+
var itemPointerProgress = itemPointer.querySelector('.progress');
|
| 56 |
+
if (+video_1.dataset.length) {
|
| 57 |
+
duration = +video_1.dataset.length;
|
| 58 |
+
}
|
| 59 |
+
if (duration && itemPointerProgress) {
|
| 60 |
+
itemPointerProgress.style.animationDuration = "".concat(duration, "s");
|
| 61 |
+
}
|
| 62 |
+
};
|
| 63 |
+
setDuration();
|
| 64 |
+
video_1.addEventListener('loadedmetadata', setDuration);
|
| 65 |
+
internalData.currentVideoElement = video_1;
|
| 66 |
+
video_1.play();
|
| 67 |
+
try {
|
| 68 |
+
unmuteVideoItem(video_1, storyViewer);
|
| 69 |
+
}
|
| 70 |
+
catch (e) {
|
| 71 |
+
console.warn('Could not unmute video', unmute);
|
| 72 |
+
}
|
| 73 |
+
}
|
| 74 |
+
else {
|
| 75 |
+
internalData.currentVideoElement = undefined;
|
| 76 |
+
}
|
| 77 |
+
};
|
| 78 |
+
var findStoryIndex = function (id) {
|
| 79 |
+
return data.findIndex(function (item) { return item.id === id; });
|
| 80 |
+
};
|
| 81 |
+
var pauseVideoItem = function () {
|
| 82 |
+
var video = internalData.currentVideoElement;
|
| 83 |
+
if (video) {
|
| 84 |
+
try {
|
| 85 |
+
video.pause();
|
| 86 |
+
}
|
| 87 |
+
catch (e) { }
|
| 88 |
+
}
|
| 89 |
+
};
|
| 90 |
+
var unmuteVideoItem = function (video, storyViewer) {
|
| 91 |
+
video.muted = false;
|
| 92 |
+
video.volume = 1.0;
|
| 93 |
+
video.removeAttribute('muted');
|
| 94 |
+
video.play();
|
| 95 |
+
if (video.paused) {
|
| 96 |
+
video.muted = true;
|
| 97 |
+
video.play();
|
| 98 |
+
}
|
| 99 |
+
if (storyViewer) {
|
| 100 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('paused');
|
| 101 |
+
}
|
| 102 |
+
};
|
| 103 |
+
var parseItems = function (story, forceUpdate) {
|
| 104 |
+
var storyId = (story === null || story === void 0 ? void 0 : story.getAttribute('data-id')) || '';
|
| 105 |
+
var storyIndex = findStoryIndex(storyId);
|
| 106 |
+
var storyItems = document.querySelectorAll("#".concat(id, " [data-id=\\"").concat(storyId, "\\"] .items > li"));
|
| 107 |
+
var items = [];
|
| 108 |
+
if (!option('reactive') || forceUpdate) {
|
| 109 |
+
storyItems.forEach(function (_a) {
|
| 110 |
+
var firstElementChild = _a.firstElementChild;
|
| 111 |
+
var a = firstElementChild;
|
| 112 |
+
var img = a === null || a === void 0 ? void 0 : a.firstElementChild;
|
| 113 |
+
var li = a === null || a === void 0 ? void 0 : a.parentElement;
|
| 114 |
+
var item = {
|
| 115 |
+
id: (a === null || a === void 0 ? void 0 : a.getAttribute('data-id')) || (li === null || li === void 0 ? void 0 : li.getAttribute('data-id')),
|
| 116 |
+
src: a === null || a === void 0 ? void 0 : a.getAttribute('href'),
|
| 117 |
+
length: (0, utils_1.safeNum)(a === null || a === void 0 ? void 0 : a.getAttribute('data-length')),
|
| 118 |
+
type: a === null || a === void 0 ? void 0 : a.getAttribute('data-type'),
|
| 119 |
+
time: (a === null || a === void 0 ? void 0 : a.getAttribute('data-time')) || (li === null || li === void 0 ? void 0 : li.getAttribute('data-time')),
|
| 120 |
+
link: (a === null || a === void 0 ? void 0 : a.getAttribute('data-link')) || '',
|
| 121 |
+
linkText: a === null || a === void 0 ? void 0 : a.getAttribute('data-linkText'),
|
| 122 |
+
preview: img === null || img === void 0 ? void 0 : img.getAttribute('src'),
|
| 123 |
+
seen: li === null || li === void 0 ? void 0 : li.classList.contains('seen')
|
| 124 |
+
};
|
| 125 |
+
var all = a === null || a === void 0 ? void 0 : a.attributes;
|
| 126 |
+
var reserved = [
|
| 127 |
+
'data-id',
|
| 128 |
+
'href',
|
| 129 |
+
'data-length',
|
| 130 |
+
'data-type',
|
| 131 |
+
'data-time',
|
| 132 |
+
'data-link',
|
| 133 |
+
'data-linkText'
|
| 134 |
+
];
|
| 135 |
+
if (all) {
|
| 136 |
+
for (var z = 0; z < all.length; z++) {
|
| 137 |
+
if (reserved.indexOf(all[z].nodeName) === -1) {
|
| 138 |
+
item[all[z].nodeName.replace('data-', '')] = all === null || all === void 0 ? void 0 : all[z].nodeValue;
|
| 139 |
+
}
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
// destruct the remaining attributes as options
|
| 143 |
+
items.push(item);
|
| 144 |
+
});
|
| 145 |
+
data[storyIndex].items = items;
|
| 146 |
+
var callback = callbackOption('onDataUpdate');
|
| 147 |
+
if (callback) {
|
| 148 |
+
callback(data, function () { });
|
| 149 |
+
}
|
| 150 |
+
}
|
| 151 |
+
};
|
| 152 |
+
var parseStory = function (story) {
|
| 153 |
+
var _a, _b;
|
| 154 |
+
var storyId = (story === null || story === void 0 ? void 0 : story.getAttribute('data-id')) || '';
|
| 155 |
+
var storyIndex = findStoryIndex(storyId);
|
| 156 |
+
var seen = false;
|
| 157 |
+
if (internalData.seenItems[storyId]) {
|
| 158 |
+
seen = true;
|
| 159 |
+
}
|
| 160 |
+
try {
|
| 161 |
+
var storyData = {};
|
| 162 |
+
if (storyIndex !== -1) {
|
| 163 |
+
storyData = data[storyIndex];
|
| 164 |
+
}
|
| 165 |
+
storyData.id = storyId;
|
| 166 |
+
storyData.photo = story === null || story === void 0 ? void 0 : story.getAttribute('data-photo');
|
| 167 |
+
storyData.name = (_a = story === null || story === void 0 ? void 0 : story.querySelector('.name')) === null || _a === void 0 ? void 0 : _a.innerText;
|
| 168 |
+
storyData.link = (_b = story === null || story === void 0 ? void 0 : story.querySelector('.item-link')) === null || _b === void 0 ? void 0 : _b.getAttribute('href');
|
| 169 |
+
storyData.lastUpdated = (0, utils_1.safeNum)((story === null || story === void 0 ? void 0 : story.getAttribute('data-last-updated')) ||
|
| 170 |
+
(story === null || story === void 0 ? void 0 : story.getAttribute('data-time')));
|
| 171 |
+
storyData.seen = seen;
|
| 172 |
+
if (!storyData.items) {
|
| 173 |
+
storyData.items = [];
|
| 174 |
+
}
|
| 175 |
+
if (storyIndex === -1) {
|
| 176 |
+
data.push(storyData);
|
| 177 |
+
}
|
| 178 |
+
else {
|
| 179 |
+
data[storyIndex] = storyData;
|
| 180 |
+
}
|
| 181 |
+
}
|
| 182 |
+
catch (e) {
|
| 183 |
+
data[storyIndex] = {
|
| 184 |
+
items: []
|
| 185 |
+
};
|
| 186 |
+
}
|
| 187 |
+
if (story) {
|
| 188 |
+
story.onclick = function (e) {
|
| 189 |
+
e.preventDefault();
|
| 190 |
+
modal.show(storyId);
|
| 191 |
+
};
|
| 192 |
+
}
|
| 193 |
+
var callback = callbackOption('onDataUpdate');
|
| 194 |
+
if (callback) {
|
| 195 |
+
callback(data, function () { });
|
| 196 |
+
}
|
| 197 |
+
};
|
| 198 |
+
var add = function (data, append) {
|
| 199 |
+
var _a, _b, _c, _d;
|
| 200 |
+
var storyId = data['id'] || '';
|
| 201 |
+
var storyEl = document.querySelector("#".concat(id, " [data-id=\\"").concat(storyId, "\\"]"));
|
| 202 |
+
var items = data['items'];
|
| 203 |
+
var story = null;
|
| 204 |
+
var preview = undefined;
|
| 205 |
+
if (items === null || items === void 0 ? void 0 : items[0]) {
|
| 206 |
+
preview = ((_a = items === null || items === void 0 ? void 0 : items[0]) === null || _a === void 0 ? void 0 : _a.preview) || '';
|
| 207 |
+
}
|
| 208 |
+
if (internalData.seenItems[storyId] === true) {
|
| 209 |
+
data.seen = true;
|
| 210 |
+
}
|
| 211 |
+
if (data) {
|
| 212 |
+
data.currentPreview = preview;
|
| 213 |
+
}
|
| 214 |
+
if (!storyEl) {
|
| 215 |
+
var storyItem = document.createElement('div');
|
| 216 |
+
storyItem.innerHTML = templateOption('timelineItem')(data);
|
| 217 |
+
story = storyItem.firstElementChild;
|
| 218 |
+
}
|
| 219 |
+
else {
|
| 220 |
+
story = storyEl;
|
| 221 |
+
}
|
| 222 |
+
if (data.seen === false) {
|
| 223 |
+
internalData.seenItems[storyId] = false;
|
| 224 |
+
saveLocalData('seenItems', internalData.seenItems);
|
| 225 |
+
}
|
| 226 |
+
story === null || story === void 0 ? void 0 : story.setAttribute('data-id', storyId);
|
| 227 |
+
if (data['photo']) {
|
| 228 |
+
story === null || story === void 0 ? void 0 : story.setAttribute('data-photo', data['photo']);
|
| 229 |
+
}
|
| 230 |
+
story === null || story === void 0 ? void 0 : story.setAttribute('data-time', (_b = data['time']) === null || _b === void 0 ? void 0 : _b.toString());
|
| 231 |
+
if (data['lastUpdated']) {
|
| 232 |
+
story === null || story === void 0 ? void 0 : story.setAttribute('data-last-updated', (_c = data['lastUpdated']) === null || _c === void 0 ? void 0 : _c.toString());
|
| 233 |
+
}
|
| 234 |
+
else {
|
| 235 |
+
story === null || story === void 0 ? void 0 : story.setAttribute('data-last-updated', (_d = data['time']) === null || _d === void 0 ? void 0 : _d.toString());
|
| 236 |
+
}
|
| 237 |
+
parseStory(story);
|
| 238 |
+
if (!storyEl && !option('reactive')) {
|
| 239 |
+
if (append) {
|
| 240 |
+
timeline.appendChild(story);
|
| 241 |
+
}
|
| 242 |
+
else {
|
| 243 |
+
(0, utils_1.prepend)(timeline, story);
|
| 244 |
+
}
|
| 245 |
+
}
|
| 246 |
+
items === null || items === void 0 ? void 0 : items.forEach(function (item) {
|
| 247 |
+
addItem(storyId, item, append);
|
| 248 |
+
});
|
| 249 |
+
if (!append) {
|
| 250 |
+
updateStorySeenPosition();
|
| 251 |
+
}
|
| 252 |
+
};
|
| 253 |
+
var update = add;
|
| 254 |
+
var next = function () {
|
| 255 |
+
modal.next();
|
| 256 |
+
};
|
| 257 |
+
var remove = function (storyId) {
|
| 258 |
+
var _a;
|
| 259 |
+
var story = document.querySelector("#".concat(id, " > [data-id=\\"").concat(storyId, "\\"]"));
|
| 260 |
+
(_a = story === null || story === void 0 ? void 0 : story.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(story);
|
| 261 |
+
};
|
| 262 |
+
var addItem = function (storyId, data, append) {
|
| 263 |
+
var story = document.querySelector("#".concat(id, " > [data-id=\\"").concat(storyId, "\\"]"));
|
| 264 |
+
if (!option('reactive')) {
|
| 265 |
+
var li = document.createElement('li');
|
| 266 |
+
var el = story === null || story === void 0 ? void 0 : story.querySelectorAll('.items')[0];
|
| 267 |
+
if (data['id']) {
|
| 268 |
+
li.className = data['seen'] ? 'seen' : '';
|
| 269 |
+
li.setAttribute('data-id', data['id']);
|
| 270 |
+
}
|
| 271 |
+
li.innerHTML = templateOption('timelineStoryItem')(data);
|
| 272 |
+
if (append) {
|
| 273 |
+
el === null || el === void 0 ? void 0 : el.appendChild(li);
|
| 274 |
+
}
|
| 275 |
+
else {
|
| 276 |
+
(0, utils_1.prepend)(el, li);
|
| 277 |
+
}
|
| 278 |
+
}
|
| 279 |
+
parseItems(story);
|
| 280 |
+
};
|
| 281 |
+
var removeItem = function (storyId, itemId) {
|
| 282 |
+
var _a;
|
| 283 |
+
var item = document.querySelector("#".concat(id, " > [data-id=\\"").concat(storyId, "\\"] [data-id=\\"").concat(itemId, "\\"]"));
|
| 284 |
+
if (!option('reactive')) {
|
| 285 |
+
(_a = item === null || item === void 0 ? void 0 : item.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(item);
|
| 286 |
+
data.forEach(function (story) {
|
| 287 |
+
if (story.id === storyId) {
|
| 288 |
+
story.items = story.items.filter(function (item) { return item.id !== itemId; });
|
| 289 |
+
}
|
| 290 |
+
});
|
| 291 |
+
}
|
| 292 |
+
};
|
| 293 |
+
var nextItem = function (direction, event) {
|
| 294 |
+
var currentStory = internalData.currentStory;
|
| 295 |
+
var currentStoryIndex = findStoryIndex(internalData.currentStory);
|
| 296 |
+
var currentItem = data[currentStoryIndex].currentItem;
|
| 297 |
+
var storyViewer = document.querySelector("#zuck-modal .story-viewer[data-story-id=\\"".concat(currentStory, "\\"]"));
|
| 298 |
+
var directionNumber = direction === 'previous' ? -1 : 1;
|
| 299 |
+
if (!storyViewer) {
|
| 300 |
+
return false;
|
| 301 |
+
}
|
| 302 |
+
var currentItemElements = storyViewer.querySelectorAll("[data-index=\\"".concat(currentItem, "\\"]"));
|
| 303 |
+
var currentPointer = currentItemElements[0];
|
| 304 |
+
var currentItemElement = currentItemElements[1];
|
| 305 |
+
var navigateItem = currentItem + directionNumber;
|
| 306 |
+
var nextItems = storyViewer.querySelectorAll("[data-index=\\"".concat(navigateItem, "\\"]"));
|
| 307 |
+
var nextPointer = nextItems[0];
|
| 308 |
+
var nextItem = nextItems[1];
|
| 309 |
+
if (storyViewer && nextPointer && nextItem) {
|
| 310 |
+
var navigateItemCallback = function () {
|
| 311 |
+
if (direction === 'previous') {
|
| 312 |
+
currentPointer === null || currentPointer === void 0 ? void 0 : currentPointer.classList.remove('seen');
|
| 313 |
+
currentItemElement === null || currentItemElement === void 0 ? void 0 : currentItemElement.classList.remove('seen');
|
| 314 |
+
}
|
| 315 |
+
else {
|
| 316 |
+
currentPointer === null || currentPointer === void 0 ? void 0 : currentPointer.classList.add('seen');
|
| 317 |
+
currentItemElement === null || currentItemElement === void 0 ? void 0 : currentItemElement.classList.add('seen');
|
| 318 |
+
}
|
| 319 |
+
currentPointer === null || currentPointer === void 0 ? void 0 : currentPointer.classList.remove('active');
|
| 320 |
+
currentItemElement === null || currentItemElement === void 0 ? void 0 : currentItemElement.classList.remove('active');
|
| 321 |
+
nextPointer === null || nextPointer === void 0 ? void 0 : nextPointer.classList.remove('seen');
|
| 322 |
+
nextPointer === null || nextPointer === void 0 ? void 0 : nextPointer.classList.add('active');
|
| 323 |
+
nextItem === null || nextItem === void 0 ? void 0 : nextItem.classList.remove('seen');
|
| 324 |
+
nextItem === null || nextItem === void 0 ? void 0 : nextItem.classList.add('active');
|
| 325 |
+
storyViewer
|
| 326 |
+
.querySelectorAll('.time')
|
| 327 |
+
.forEach(function (el) {
|
| 328 |
+
el.innerText = (0, utils_1.timeAgo)(Number(nextItem.getAttribute('data-time')), option('language'));
|
| 329 |
+
});
|
| 330 |
+
data[currentStoryIndex].currentItem =
|
| 331 |
+
data[currentStoryIndex].currentItem + directionNumber;
|
| 332 |
+
var nextVideo = nextItem.querySelector('video');
|
| 333 |
+
if (nextVideo) {
|
| 334 |
+
nextVideo.currentTime = 0;
|
| 335 |
+
}
|
| 336 |
+
playVideoItem(storyViewer, nextItems, event);
|
| 337 |
+
};
|
| 338 |
+
var callback = callbackOption('onNavigateItem');
|
| 339 |
+
callback = !callback
|
| 340 |
+
? callbackOption('onNextItem')
|
| 341 |
+
: callbackOption('onNavigateItem');
|
| 342 |
+
callback(currentStory, nextItem.getAttribute('data-story-id'), navigateItemCallback);
|
| 343 |
+
}
|
| 344 |
+
else if (storyViewer) {
|
| 345 |
+
if (direction !== 'previous') {
|
| 346 |
+
modal.next();
|
| 347 |
+
}
|
| 348 |
+
}
|
| 349 |
+
return true;
|
| 350 |
+
};
|
| 351 |
+
var navigateItem = nextItem;
|
| 352 |
+
var updateStorySeenPosition = function () {
|
| 353 |
+
document
|
| 354 |
+
.querySelectorAll("#".concat(id, " .story.seen"))
|
| 355 |
+
.forEach(function (el) {
|
| 356 |
+
var storyId = el === null || el === void 0 ? void 0 : el.getAttribute('data-id');
|
| 357 |
+
var storyIndex = findStoryIndex(storyId);
|
| 358 |
+
if (storyId) {
|
| 359 |
+
var newData = data[storyIndex];
|
| 360 |
+
var timeline_1 = el === null || el === void 0 ? void 0 : el.parentNode;
|
| 361 |
+
if (!option('reactive') && timeline_1) {
|
| 362 |
+
timeline_1.removeChild(el);
|
| 363 |
+
}
|
| 364 |
+
update(newData, true);
|
| 365 |
+
}
|
| 366 |
+
});
|
| 367 |
+
};
|
| 368 |
+
var init = function () {
|
| 369 |
+
if (timeline && timeline.querySelector('.story')) {
|
| 370 |
+
timeline.querySelectorAll('.story').forEach(function (story) {
|
| 371 |
+
parseStory(story);
|
| 372 |
+
parseItems(story);
|
| 373 |
+
});
|
| 374 |
+
}
|
| 375 |
+
if (option('backNative') && (0, utils_1.hasWindow)()) {
|
| 376 |
+
if (window.location.hash === "#!".concat(id)) {
|
| 377 |
+
window.location.hash = '';
|
| 378 |
+
}
|
| 379 |
+
window.addEventListener('popstate', function () {
|
| 380 |
+
if (window.location.hash !== "#!".concat(id)) {
|
| 381 |
+
window.location.hash = '';
|
| 382 |
+
}
|
| 383 |
+
}, false);
|
| 384 |
+
}
|
| 385 |
+
if (!option('reactive')) {
|
| 386 |
+
var seenItems_1 = getLocalData('seenItems');
|
| 387 |
+
if (seenItems_1) {
|
| 388 |
+
Object.entries(seenItems_1).forEach(function (_a) {
|
| 389 |
+
var key = _a[1];
|
| 390 |
+
if (key && data[key]) {
|
| 391 |
+
data[key].seen = seenItems_1[key] ? true : false;
|
| 392 |
+
}
|
| 393 |
+
});
|
| 394 |
+
}
|
| 395 |
+
}
|
| 396 |
+
option('stories').forEach(function (item) {
|
| 397 |
+
add(item, true);
|
| 398 |
+
});
|
| 399 |
+
updateStorySeenPosition();
|
| 400 |
+
var avatars = option('avatars') ? 'user-icon' : 'story-preview';
|
| 401 |
+
var list = option('list') ? 'list' : 'carousel';
|
| 402 |
+
var rtl = option('rtl') ? 'rtl' : '';
|
| 403 |
+
timeline.className += " stories ".concat(avatars, " ").concat(list, " ").concat("".concat(option('skin')).toLowerCase(), " ").concat(rtl);
|
| 404 |
+
return {
|
| 405 |
+
id: id,
|
| 406 |
+
option: option,
|
| 407 |
+
callback: callbackOption,
|
| 408 |
+
template: templateOption,
|
| 409 |
+
language: languageOption,
|
| 410 |
+
navigateItem: navigateItem,
|
| 411 |
+
saveLocalData: saveLocalData,
|
| 412 |
+
getLocalData: getLocalData,
|
| 413 |
+
data: data,
|
| 414 |
+
internalData: internalData,
|
| 415 |
+
add: add,
|
| 416 |
+
update: update,
|
| 417 |
+
next: next,
|
| 418 |
+
remove: remove,
|
| 419 |
+
addItem: addItem,
|
| 420 |
+
removeItem: removeItem,
|
| 421 |
+
nextItem: nextItem,
|
| 422 |
+
findStoryIndex: findStoryIndex,
|
| 423 |
+
updateStorySeenPosition: updateStorySeenPosition,
|
| 424 |
+
playVideoItem: playVideoItem,
|
| 425 |
+
pauseVideoItem: pauseVideoItem,
|
| 426 |
+
unmuteVideoItem: unmuteVideoItem
|
| 427 |
+
};
|
| 428 |
+
};
|
| 429 |
+
var zuck = init();
|
| 430 |
+
var modal = (0, modal_1.modal)(zuck);
|
| 431 |
+
return zuck;
|
| 432 |
+
};
|
| 433 |
+
exports.Zuck = Zuck;
|
| 434 |
+
exports["default"] = exports.Zuck;
|
| 435 |
+
|
| 436 |
+
|
| 437 |
+
//# sourceURL=webpack://Zuck/./src/index.ts?`)}),"./src/modal.ts":((__unused_webpack_module,exports,__webpack_require__)=>{eval(`
|
| 438 |
+
exports.__esModule = true;
|
| 439 |
+
exports.modal = void 0;
|
| 440 |
+
var utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
|
| 441 |
+
var modal = function (zuck) {
|
| 442 |
+
var id = zuck.id;
|
| 443 |
+
var modalZuckContainer = document.querySelector('#zuck-modal');
|
| 444 |
+
if (!modalZuckContainer && !zuck.hasModal) {
|
| 445 |
+
zuck.hasModal = true;
|
| 446 |
+
modalZuckContainer = document.createElement('div');
|
| 447 |
+
modalZuckContainer.id = 'zuck-modal';
|
| 448 |
+
if (zuck.option('cubeEffect')) {
|
| 449 |
+
modalZuckContainer.className = 'with-cube';
|
| 450 |
+
}
|
| 451 |
+
modalZuckContainer.innerHTML = '<div id="zuck-modal-content"></div>';
|
| 452 |
+
modalZuckContainer.style.display = 'none';
|
| 453 |
+
modalZuckContainer.setAttribute('tabIndex', '1');
|
| 454 |
+
modalZuckContainer.onkeyup = function (_a) {
|
| 455 |
+
var keyCode = _a.keyCode;
|
| 456 |
+
var code = keyCode;
|
| 457 |
+
if (code === 27) {
|
| 458 |
+
modalZuckContainer.modal.close();
|
| 459 |
+
}
|
| 460 |
+
else if (code === 13 || code === 32) {
|
| 461 |
+
modalZuckContainer.modal.next();
|
| 462 |
+
}
|
| 463 |
+
};
|
| 464 |
+
if (zuck.option('openEffect')) {
|
| 465 |
+
modalZuckContainer === null || modalZuckContainer === void 0 ? void 0 : modalZuckContainer.classList.add('with-effects');
|
| 466 |
+
}
|
| 467 |
+
if (zuck.option('rtl')) {
|
| 468 |
+
modalZuckContainer === null || modalZuckContainer === void 0 ? void 0 : modalZuckContainer.classList.add('rtl');
|
| 469 |
+
}
|
| 470 |
+
(0, utils_1.onTransitionEnd)(modalZuckContainer, function () {
|
| 471 |
+
var modalContent = document.querySelector('#zuck-modal-content');
|
| 472 |
+
if (modalZuckContainer === null || modalZuckContainer === void 0 ? void 0 : modalZuckContainer.classList.contains('closed')) {
|
| 473 |
+
if (modalContent) {
|
| 474 |
+
modalContent.innerHTML = '';
|
| 475 |
+
}
|
| 476 |
+
modalZuckContainer.style.display = 'none';
|
| 477 |
+
modalZuckContainer.classList.remove('closed');
|
| 478 |
+
modalZuckContainer.classList.remove('animated');
|
| 479 |
+
}
|
| 480 |
+
});
|
| 481 |
+
document.body.appendChild(modalZuckContainer);
|
| 482 |
+
}
|
| 483 |
+
var translate = function (element, to, duration, ease) {
|
| 484 |
+
var _a;
|
| 485 |
+
if (to === undefined || (to && isNaN(to))) {
|
| 486 |
+
return;
|
| 487 |
+
}
|
| 488 |
+
var direction = to > 0 ? 1 : -1;
|
| 489 |
+
var modalWidth = ((_a = document.querySelector('#zuck-modal')) === null || _a === void 0 ? void 0 : _a.offsetWidth) || 1;
|
| 490 |
+
var to3d = (Math.abs(to) / modalWidth) * 90 * direction;
|
| 491 |
+
if (zuck.option('cubeEffect')) {
|
| 492 |
+
var scaling = to3d === 0 ? 'scale(0.95)' : 'scale(0.930,0.930)';
|
| 493 |
+
var modalContent = document.querySelector('#zuck-modal-content');
|
| 494 |
+
if (modalContent) {
|
| 495 |
+
modalContent.style.transform = scaling;
|
| 496 |
+
}
|
| 497 |
+
if (to3d < -90 || to3d > 90) {
|
| 498 |
+
return false;
|
| 499 |
+
}
|
| 500 |
+
}
|
| 501 |
+
var transform = !zuck.option('cubeEffect')
|
| 502 |
+
? "translate3d(".concat(to, "px, 0, 0)")
|
| 503 |
+
: "rotateY(".concat(to3d, "deg)");
|
| 504 |
+
if (element) {
|
| 505 |
+
if (ease) {
|
| 506 |
+
element.style.transitionTimingFunction = ease;
|
| 507 |
+
}
|
| 508 |
+
element.style.transitionDuration = "".concat(duration, "ms");
|
| 509 |
+
element.style.transform = transform;
|
| 510 |
+
}
|
| 511 |
+
};
|
| 512 |
+
var fullScreen = function (elem, cancel) {
|
| 513 |
+
var anyDocument = document;
|
| 514 |
+
var anyElem = elem;
|
| 515 |
+
try {
|
| 516 |
+
if (cancel) {
|
| 517 |
+
if (anyDocument.fullscreenElement ||
|
| 518 |
+
anyDocument.webkitFullscreenElement ||
|
| 519 |
+
anyDocument.mozFullScreenElement ||
|
| 520 |
+
anyDocument.msFullscreenElement) {
|
| 521 |
+
if (anyDocument.exitFullscreen) {
|
| 522 |
+
anyDocument.exitFullscreen()["catch"](function () { });
|
| 523 |
+
}
|
| 524 |
+
else if (anyDocument.mozCancelFullScreen) {
|
| 525 |
+
anyDocument.mozCancelFullScreen()["catch"](function () { });
|
| 526 |
+
}
|
| 527 |
+
}
|
| 528 |
+
}
|
| 529 |
+
else {
|
| 530 |
+
if (anyElem.requestFullscreen) {
|
| 531 |
+
anyElem.requestFullscreen();
|
| 532 |
+
}
|
| 533 |
+
else if (anyElem.msRequestFullscreen) {
|
| 534 |
+
anyElem.msRequestFullscreen();
|
| 535 |
+
}
|
| 536 |
+
else if (anyElem.mozRequestFullScreen) {
|
| 537 |
+
anyElem.mozRequestFullScreen();
|
| 538 |
+
}
|
| 539 |
+
else if (anyElem.webkitRequestFullscreen) {
|
| 540 |
+
anyElem.webkitRequestFullscreen();
|
| 541 |
+
}
|
| 542 |
+
}
|
| 543 |
+
}
|
| 544 |
+
catch (e) {
|
| 545 |
+
console.warn("[Zuck.js] Can't access fullscreen");
|
| 546 |
+
}
|
| 547 |
+
};
|
| 548 |
+
var moveStoryItem = function (direction) {
|
| 549 |
+
var modalContainer = document.querySelector('#zuck-modal');
|
| 550 |
+
var modalSlider = document.querySelector("#zuck-modal-slider-".concat(id));
|
| 551 |
+
var target = '';
|
| 552 |
+
var useless = '';
|
| 553 |
+
var transform = 0;
|
| 554 |
+
var slideItems = {
|
| 555 |
+
previous: document.querySelector('#zuck-modal .story-viewer.previous'),
|
| 556 |
+
next: document.querySelector('#zuck-modal .story-viewer.next'),
|
| 557 |
+
viewing: document.querySelector('#zuck-modal .story-viewer.viewing')
|
| 558 |
+
};
|
| 559 |
+
if ((!slideItems.previous && !direction) ||
|
| 560 |
+
(!slideItems.next && direction)) {
|
| 561 |
+
if (!zuck.option('rtl')) {
|
| 562 |
+
return false;
|
| 563 |
+
}
|
| 564 |
+
}
|
| 565 |
+
if (!direction) {
|
| 566 |
+
target = 'previous';
|
| 567 |
+
useless = 'next';
|
| 568 |
+
}
|
| 569 |
+
else {
|
| 570 |
+
target = 'next';
|
| 571 |
+
useless = 'previous';
|
| 572 |
+
}
|
| 573 |
+
var transitionTime = 600;
|
| 574 |
+
if (zuck.option('cubeEffect')) {
|
| 575 |
+
if (target === 'previous') {
|
| 576 |
+
transform = (0, utils_1.safeNum)(modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.slideWidth);
|
| 577 |
+
}
|
| 578 |
+
else if (target === 'next') {
|
| 579 |
+
transform = (0, utils_1.safeNum)(modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.slideWidth) * -1;
|
| 580 |
+
}
|
| 581 |
+
}
|
| 582 |
+
else {
|
| 583 |
+
transform = (0, utils_1.findPos)(slideItems[target])[0] * -1;
|
| 584 |
+
}
|
| 585 |
+
translate(modalSlider, transform, transitionTime, null);
|
| 586 |
+
setTimeout(function () {
|
| 587 |
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
| 588 |
+
// set page data when transition complete
|
| 589 |
+
if (zuck.option('rtl')) {
|
| 590 |
+
var tmp = target;
|
| 591 |
+
target = useless;
|
| 592 |
+
useless = tmp;
|
| 593 |
+
}
|
| 594 |
+
if (target !== '' && slideItems[target] && useless !== '') {
|
| 595 |
+
var currentStory = (_a = slideItems[target]) === null || _a === void 0 ? void 0 : _a.getAttribute('data-story-id');
|
| 596 |
+
zuck.internalData.currentStory = currentStory;
|
| 597 |
+
var oldStory = document.querySelector("#zuck-modal .story-viewer.".concat(useless));
|
| 598 |
+
if (oldStory) {
|
| 599 |
+
(_b = oldStory === null || oldStory === void 0 ? void 0 : oldStory.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(oldStory);
|
| 600 |
+
}
|
| 601 |
+
if (slideItems.viewing) {
|
| 602 |
+
(_c = slideItems.viewing) === null || _c === void 0 ? void 0 : _c.classList.add('stopped');
|
| 603 |
+
(_d = slideItems.viewing) === null || _d === void 0 ? void 0 : _d.classList.add(useless);
|
| 604 |
+
(_e = slideItems.viewing) === null || _e === void 0 ? void 0 : _e.classList.remove('viewing');
|
| 605 |
+
}
|
| 606 |
+
if (slideItems[target]) {
|
| 607 |
+
(_f = slideItems[target]) === null || _f === void 0 ? void 0 : _f.classList.remove('stopped');
|
| 608 |
+
(_g = slideItems[target]) === null || _g === void 0 ? void 0 : _g.classList.remove(target);
|
| 609 |
+
(_h = slideItems[target]) === null || _h === void 0 ? void 0 : _h.classList.add('viewing');
|
| 610 |
+
}
|
| 611 |
+
var newTimelineItem = getStoryMorningGlory(target);
|
| 612 |
+
if (newTimelineItem) {
|
| 613 |
+
createStoryViewer(newTimelineItem, target);
|
| 614 |
+
}
|
| 615 |
+
var storyId = zuck.internalData.currentStory;
|
| 616 |
+
var storyIndex = zuck.findStoryIndex(storyId);
|
| 617 |
+
var storyWrap = document.querySelector("#zuck-modal [data-story-id=\\"".concat(storyId, "\\"]"));
|
| 618 |
+
var items = undefined;
|
| 619 |
+
if (storyWrap) {
|
| 620 |
+
items = storyWrap.querySelectorAll('[data-index].active');
|
| 621 |
+
var duration = (_j = items === null || items === void 0 ? void 0 : items[0]) === null || _j === void 0 ? void 0 : _j.firstElementChild;
|
| 622 |
+
zuck.data[storyIndex].currentItem = (0, utils_1.safeNum)((_k = items === null || items === void 0 ? void 0 : items[0]) === null || _k === void 0 ? void 0 : _k.getAttribute('data-index'));
|
| 623 |
+
if (items === null || items === void 0 ? void 0 : items[0]) {
|
| 624 |
+
items[0].innerHTML = zuck.template('viewerItemPointerProgress')(duration.style.cssText);
|
| 625 |
+
(0, utils_1.onAnimationEnd)(duration, function () {
|
| 626 |
+
zuck.nextItem();
|
| 627 |
+
});
|
| 628 |
+
}
|
| 629 |
+
}
|
| 630 |
+
translate(modalSlider, 0, 0, null);
|
| 631 |
+
if (items) {
|
| 632 |
+
var storyViewer = document.querySelector("#zuck-modal .story-viewer[data-story-id=\\"".concat(currentStory, "\\"]"));
|
| 633 |
+
zuck.playVideoItem(storyViewer, items);
|
| 634 |
+
}
|
| 635 |
+
zuck.callback('onView')(zuck.internalData.currentStory);
|
| 636 |
+
}
|
| 637 |
+
}, transitionTime + 50);
|
| 638 |
+
};
|
| 639 |
+
var createStoryViewer = function (storyData, className, forcePlay) {
|
| 640 |
+
var modalSlider = document.querySelector("#zuck-modal-slider-".concat(id));
|
| 641 |
+
var storyItems = storyData['items'];
|
| 642 |
+
storyData.time = storyItems && (storyItems === null || storyItems === void 0 ? void 0 : storyItems[0]['time']);
|
| 643 |
+
var htmlItems = '';
|
| 644 |
+
var pointerItems = '';
|
| 645 |
+
var storyId = storyData['id'];
|
| 646 |
+
var slides = document.createElement('div');
|
| 647 |
+
var currentItem = storyData['currentItem'] || 0;
|
| 648 |
+
var exists = document.querySelector("#zuck-modal .story-viewer[data-story-id=\\"".concat(storyId, "\\"]"));
|
| 649 |
+
if (exists) {
|
| 650 |
+
return false;
|
| 651 |
+
}
|
| 652 |
+
slides.className = 'slides';
|
| 653 |
+
storyItems.forEach(function (item, i) {
|
| 654 |
+
if (currentItem > i) {
|
| 655 |
+
storyData.items[i].seen = true;
|
| 656 |
+
item.seen = true;
|
| 657 |
+
}
|
| 658 |
+
pointerItems += zuck.template('viewerItemPointer')(i, currentItem, item);
|
| 659 |
+
htmlItems += zuck.template('viewerItemBody')(i, currentItem, item);
|
| 660 |
+
});
|
| 661 |
+
slides.innerHTML = htmlItems;
|
| 662 |
+
var video = slides.querySelector('video');
|
| 663 |
+
var addMuted = function (video) {
|
| 664 |
+
if (video.muted) {
|
| 665 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.add('muted');
|
| 666 |
+
}
|
| 667 |
+
else {
|
| 668 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('muted');
|
| 669 |
+
}
|
| 670 |
+
};
|
| 671 |
+
if (video) {
|
| 672 |
+
video.onwaiting = function () {
|
| 673 |
+
if (video.paused) {
|
| 674 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.add('paused');
|
| 675 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.add('loading');
|
| 676 |
+
}
|
| 677 |
+
};
|
| 678 |
+
video.onplay = function () {
|
| 679 |
+
addMuted(video);
|
| 680 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('stopped');
|
| 681 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('paused');
|
| 682 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('loading');
|
| 683 |
+
};
|
| 684 |
+
video.onload =
|
| 685 |
+
video.onplaying =
|
| 686 |
+
video.oncanplay =
|
| 687 |
+
function () {
|
| 688 |
+
addMuted(video);
|
| 689 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('loading');
|
| 690 |
+
};
|
| 691 |
+
video.onvolumechange = function () {
|
| 692 |
+
addMuted(video);
|
| 693 |
+
};
|
| 694 |
+
}
|
| 695 |
+
var storyViewerWrap = document.createElement('div');
|
| 696 |
+
storyViewerWrap.innerHTML = zuck.template('viewerItem')(storyData, storyItems[currentItem]);
|
| 697 |
+
var storyViewer = storyViewerWrap.firstElementChild;
|
| 698 |
+
var storyViewerPointerWrap = storyViewer.querySelector('.slides-pointers .wrap');
|
| 699 |
+
storyViewer.className = "story-viewer muted ".concat(className, " ").concat(!forcePlay ? 'stopped' : '', " ").concat(zuck.option('backButton') ? 'with-back-button' : '');
|
| 700 |
+
if (storyId) {
|
| 701 |
+
storyViewer.setAttribute('data-story-id', storyId);
|
| 702 |
+
}
|
| 703 |
+
if (storyViewerPointerWrap) {
|
| 704 |
+
storyViewerPointerWrap.innerHTML = pointerItems;
|
| 705 |
+
}
|
| 706 |
+
storyViewer
|
| 707 |
+
.querySelectorAll('.close, .back')
|
| 708 |
+
.forEach(function (el) {
|
| 709 |
+
el.onclick = function (e) {
|
| 710 |
+
e.preventDefault();
|
| 711 |
+
modalZuckContainer.modal.close();
|
| 712 |
+
};
|
| 713 |
+
});
|
| 714 |
+
storyViewer.appendChild(slides);
|
| 715 |
+
if (className === 'viewing') {
|
| 716 |
+
zuck.playVideoItem(storyViewer, storyViewer.querySelectorAll("[data-index=\\"".concat(currentItem, "\\"].active")), undefined);
|
| 717 |
+
}
|
| 718 |
+
storyViewer
|
| 719 |
+
.querySelectorAll('.slides-pointers [data-index] > .progress')
|
| 720 |
+
.forEach(function (el) {
|
| 721 |
+
(0, utils_1.onAnimationEnd)(el, function () {
|
| 722 |
+
zuck.nextItem(undefined);
|
| 723 |
+
});
|
| 724 |
+
});
|
| 725 |
+
if (!modalSlider) {
|
| 726 |
+
return;
|
| 727 |
+
}
|
| 728 |
+
if (className === 'previous') {
|
| 729 |
+
(0, utils_1.prepend)(modalSlider, storyViewer);
|
| 730 |
+
}
|
| 731 |
+
else {
|
| 732 |
+
modalSlider.appendChild(storyViewer);
|
| 733 |
+
}
|
| 734 |
+
};
|
| 735 |
+
var createStoryTouchEvents = function (modalSlider) {
|
| 736 |
+
var modalContainer = document.querySelector('#zuck-modal');
|
| 737 |
+
var enableMouseEvents = true;
|
| 738 |
+
var position = null;
|
| 739 |
+
var touchOffset = null;
|
| 740 |
+
var isScrolling = null;
|
| 741 |
+
var delta = null;
|
| 742 |
+
var timer = undefined;
|
| 743 |
+
var nextTimer = undefined;
|
| 744 |
+
var touchStart = function (event) {
|
| 745 |
+
var storyViewer = document.querySelector('#zuck-modal .viewing');
|
| 746 |
+
var storyViewerWrap = document.querySelector('#zuck-modal .story-viewer');
|
| 747 |
+
if (event.target.nodeName === 'A') {
|
| 748 |
+
return;
|
| 749 |
+
}
|
| 750 |
+
var touches = event.touches
|
| 751 |
+
? event.touches[0]
|
| 752 |
+
: event;
|
| 753 |
+
var pos = (0, utils_1.findPos)(document.querySelector('#zuck-modal .story-viewer.viewing'));
|
| 754 |
+
if (modalContainer) {
|
| 755 |
+
modalContainer.slideWidth = storyViewerWrap === null || storyViewerWrap === void 0 ? void 0 : storyViewerWrap.offsetWidth;
|
| 756 |
+
modalContainer.slideHeight = storyViewerWrap === null || storyViewerWrap === void 0 ? void 0 : storyViewerWrap.offsetHeight;
|
| 757 |
+
}
|
| 758 |
+
position = {
|
| 759 |
+
x: pos[0],
|
| 760 |
+
y: pos[1]
|
| 761 |
+
};
|
| 762 |
+
var clientX = touches.clientX;
|
| 763 |
+
var clientY = touches.clientY;
|
| 764 |
+
touchOffset = {
|
| 765 |
+
x: clientX,
|
| 766 |
+
y: clientY,
|
| 767 |
+
time: Date.now(),
|
| 768 |
+
valid: true
|
| 769 |
+
};
|
| 770 |
+
if (clientY < 80 || clientY > (0, utils_1.safeNum)(modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.slideHeight) - 80) {
|
| 771 |
+
touchOffset.valid = false;
|
| 772 |
+
}
|
| 773 |
+
else {
|
| 774 |
+
event.preventDefault();
|
| 775 |
+
isScrolling = undefined;
|
| 776 |
+
delta = {};
|
| 777 |
+
if (enableMouseEvents) {
|
| 778 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('mousemove', touchMove);
|
| 779 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('mouseup', touchEnd);
|
| 780 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('mouseleave', touchEnd);
|
| 781 |
+
}
|
| 782 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('touchmove', touchMove);
|
| 783 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('touchend', touchEnd);
|
| 784 |
+
if (storyViewer) {
|
| 785 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.add('paused');
|
| 786 |
+
}
|
| 787 |
+
zuck.pauseVideoItem();
|
| 788 |
+
timer = setTimeout(function () {
|
| 789 |
+
if (storyViewer) {
|
| 790 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.add('longPress');
|
| 791 |
+
}
|
| 792 |
+
}, 600);
|
| 793 |
+
nextTimer = setTimeout(function () {
|
| 794 |
+
clearInterval(nextTimer);
|
| 795 |
+
nextTimer = undefined;
|
| 796 |
+
}, 250);
|
| 797 |
+
}
|
| 798 |
+
};
|
| 799 |
+
var touchMove = function (event) {
|
| 800 |
+
var touches = event.touches
|
| 801 |
+
? event.touches[0]
|
| 802 |
+
: event;
|
| 803 |
+
var clientX = touches.clientX;
|
| 804 |
+
var clientY = touches.clientY;
|
| 805 |
+
if (touchOffset && touchOffset.valid) {
|
| 806 |
+
delta = {
|
| 807 |
+
x: clientX - touchOffset.x,
|
| 808 |
+
y: clientY - touchOffset.y
|
| 809 |
+
};
|
| 810 |
+
if (typeof isScrolling === 'undefined') {
|
| 811 |
+
isScrolling = !!(isScrolling || Math.abs(delta.x) < Math.abs(delta.y));
|
| 812 |
+
}
|
| 813 |
+
if (!isScrolling && touchOffset) {
|
| 814 |
+
event.preventDefault();
|
| 815 |
+
translate(modalSlider, (0, utils_1.safeNum)(position === null || position === void 0 ? void 0 : position.x) + (0, utils_1.safeNum)(delta === null || delta === void 0 ? void 0 : delta.x), 0, null);
|
| 816 |
+
}
|
| 817 |
+
}
|
| 818 |
+
};
|
| 819 |
+
var touchEnd = function (event) {
|
| 820 |
+
var storyViewer = document.querySelector('#zuck-modal .viewing');
|
| 821 |
+
var lastTouchOffset = touchOffset;
|
| 822 |
+
var duration = touchOffset ? Date.now() - touchOffset.time : undefined;
|
| 823 |
+
var isValid = (Number(duration) < 300 && Math.abs((0, utils_1.safeNum)(delta === null || delta === void 0 ? void 0 : delta.x)) > 25) ||
|
| 824 |
+
Math.abs((0, utils_1.safeNum)(delta === null || delta === void 0 ? void 0 : delta.x)) > (0, utils_1.safeNum)(modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.slideWidth) / 3;
|
| 825 |
+
var direction = (0, utils_1.safeNum)(delta === null || delta === void 0 ? void 0 : delta.x) < 0;
|
| 826 |
+
var index = direction
|
| 827 |
+
? document.querySelector('#zuck-modal .story-viewer.next')
|
| 828 |
+
: document.querySelector('#zuck-modal .story-viewer.previous');
|
| 829 |
+
var isOutOfBounds = (direction && !index) || (!direction && !index);
|
| 830 |
+
if (touchOffset && !touchOffset.valid) {
|
| 831 |
+
}
|
| 832 |
+
else {
|
| 833 |
+
if (delta) {
|
| 834 |
+
if (!isScrolling) {
|
| 835 |
+
if (isValid && !isOutOfBounds) {
|
| 836 |
+
moveStoryItem(direction);
|
| 837 |
+
}
|
| 838 |
+
else {
|
| 839 |
+
translate(modalSlider, (0, utils_1.safeNum)(position === null || position === void 0 ? void 0 : position.x), 300);
|
| 840 |
+
}
|
| 841 |
+
}
|
| 842 |
+
touchOffset = undefined;
|
| 843 |
+
if (enableMouseEvents) {
|
| 844 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.removeEventListener('mousemove', touchMove);
|
| 845 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.removeEventListener('mouseup', touchEnd);
|
| 846 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.removeEventListener('mouseleave', touchEnd);
|
| 847 |
+
}
|
| 848 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.removeEventListener('touchmove', touchMove);
|
| 849 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.removeEventListener('touchend', touchEnd);
|
| 850 |
+
}
|
| 851 |
+
var video = zuck.internalData.currentVideoElement;
|
| 852 |
+
if (timer) {
|
| 853 |
+
clearInterval(timer);
|
| 854 |
+
}
|
| 855 |
+
if (storyViewer) {
|
| 856 |
+
zuck.playVideoItem(storyViewer, storyViewer.querySelectorAll('.active'), undefined);
|
| 857 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('longPress');
|
| 858 |
+
storyViewer === null || storyViewer === void 0 ? void 0 : storyViewer.classList.remove('paused');
|
| 859 |
+
}
|
| 860 |
+
if (nextTimer) {
|
| 861 |
+
clearInterval(nextTimer);
|
| 862 |
+
nextTimer = undefined;
|
| 863 |
+
var navigateItem = function () {
|
| 864 |
+
if (!direction) {
|
| 865 |
+
if ((0, utils_1.safeNum)(lastTouchOffset === null || lastTouchOffset === void 0 ? void 0 : lastTouchOffset.x) > document.body.offsetWidth / 3 ||
|
| 866 |
+
!zuck.option('previousTap')) {
|
| 867 |
+
if (zuck.option('rtl')) {
|
| 868 |
+
zuck.navigateItem('previous', event);
|
| 869 |
+
}
|
| 870 |
+
else {
|
| 871 |
+
zuck.navigateItem('next', event);
|
| 872 |
+
}
|
| 873 |
+
}
|
| 874 |
+
else {
|
| 875 |
+
if (zuck.option('rtl')) {
|
| 876 |
+
zuck.navigateItem('next', event);
|
| 877 |
+
}
|
| 878 |
+
else {
|
| 879 |
+
zuck.navigateItem('previous', event);
|
| 880 |
+
}
|
| 881 |
+
}
|
| 882 |
+
}
|
| 883 |
+
};
|
| 884 |
+
var storyViewerViewing = document.querySelector('#zuck-modal .viewing');
|
| 885 |
+
if (storyViewerViewing && video) {
|
| 886 |
+
if (storyViewerViewing === null || storyViewerViewing === void 0 ? void 0 : storyViewerViewing.classList.contains('muted')) {
|
| 887 |
+
zuck.unmuteVideoItem(video, storyViewerViewing);
|
| 888 |
+
}
|
| 889 |
+
else {
|
| 890 |
+
navigateItem();
|
| 891 |
+
}
|
| 892 |
+
}
|
| 893 |
+
else {
|
| 894 |
+
navigateItem();
|
| 895 |
+
return false;
|
| 896 |
+
}
|
| 897 |
+
}
|
| 898 |
+
}
|
| 899 |
+
};
|
| 900 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('touchstart', touchStart);
|
| 901 |
+
if (enableMouseEvents) {
|
| 902 |
+
modalSlider === null || modalSlider === void 0 ? void 0 : modalSlider.addEventListener('mousedown', touchStart);
|
| 903 |
+
}
|
| 904 |
+
};
|
| 905 |
+
var getStoryMorningGlory = function (what) {
|
| 906 |
+
// my wife told me to stop singing Wonderwall. I SAID MAYBE.
|
| 907 |
+
var currentStory = zuck.internalData.currentStory;
|
| 908 |
+
if (currentStory && what !== '') {
|
| 909 |
+
var element = document.querySelector("#".concat(id, " [data-id=\\"").concat(currentStory, "\\"]"));
|
| 910 |
+
var foundStory = what === 'previous'
|
| 911 |
+
? element.previousElementSibling
|
| 912 |
+
: element.nextElementSibling;
|
| 913 |
+
if (foundStory) {
|
| 914 |
+
var storyId = foundStory.getAttribute('data-id');
|
| 915 |
+
var storyIndex = zuck.findStoryIndex(storyId);
|
| 916 |
+
var data = zuck.data[storyIndex] || false;
|
| 917 |
+
return data;
|
| 918 |
+
}
|
| 919 |
+
}
|
| 920 |
+
return false;
|
| 921 |
+
};
|
| 922 |
+
var show = function (storyId) {
|
| 923 |
+
var modalContainer = document.querySelector('#zuck-modal');
|
| 924 |
+
var callback = function () {
|
| 925 |
+
var modalContent = document.querySelector('#zuck-modal-content');
|
| 926 |
+
modalContent.innerHTML = "<div id=\\"zuck-modal-slider-".concat(id, "\\" class=\\"slider\\"></div>");
|
| 927 |
+
if (!modalContent || !storyId) {
|
| 928 |
+
return;
|
| 929 |
+
}
|
| 930 |
+
var storyIndex = zuck.findStoryIndex(storyId);
|
| 931 |
+
var storyData = zuck.data[storyIndex];
|
| 932 |
+
var currentItem = storyData.currentItem || 0;
|
| 933 |
+
var modalSlider = document.querySelector("#zuck-modal-slider-".concat(id));
|
| 934 |
+
createStoryTouchEvents(modalSlider);
|
| 935 |
+
zuck.internalData.currentStory = storyId;
|
| 936 |
+
storyData.currentItem = currentItem;
|
| 937 |
+
if (zuck.option('backNative') && (0, utils_1.hasWindow)()) {
|
| 938 |
+
window.location.hash = "#!".concat(id);
|
| 939 |
+
}
|
| 940 |
+
var previousItemData = getStoryMorningGlory('previous');
|
| 941 |
+
if (previousItemData) {
|
| 942 |
+
createStoryViewer(previousItemData, 'previous');
|
| 943 |
+
}
|
| 944 |
+
createStoryViewer(storyData, 'viewing', true);
|
| 945 |
+
var nextItemData = getStoryMorningGlory('next');
|
| 946 |
+
if (nextItemData) {
|
| 947 |
+
createStoryViewer(nextItemData, 'next');
|
| 948 |
+
}
|
| 949 |
+
if (zuck.option('autoFullScreen')) {
|
| 950 |
+
modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.classList.add('fullscreen');
|
| 951 |
+
}
|
| 952 |
+
var tryFullScreen = function () {
|
| 953 |
+
if ((modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.classList.contains('fullscreen')) &&
|
| 954 |
+
zuck.option('autoFullScreen') &&
|
| 955 |
+
document.body.offsetWidth <= 1024) {
|
| 956 |
+
fullScreen(modalContainer);
|
| 957 |
+
}
|
| 958 |
+
modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.focus();
|
| 959 |
+
};
|
| 960 |
+
var storyViewerWrap = document.querySelector('#zuck-modal .story-viewer');
|
| 961 |
+
if (zuck.option('openEffect') && modalContainer) {
|
| 962 |
+
var storyEl = document.querySelector("#".concat(id, " [data-id=\\"").concat(storyId, "\\"] .item-preview"));
|
| 963 |
+
var pos = (0, utils_1.findPos)(storyEl);
|
| 964 |
+
modalContainer.style.marginLeft = "".concat(pos[0] + (0, utils_1.safeNum)(storyEl === null || storyEl === void 0 ? void 0 : storyEl.offsetWidth) / 2, "px");
|
| 965 |
+
modalContainer.style.marginTop = "".concat(pos[1] + (0, utils_1.safeNum)(storyEl === null || storyEl === void 0 ? void 0 : storyEl.offsetHeight) / 2, "px");
|
| 966 |
+
modalContainer.style.display = 'block';
|
| 967 |
+
modalContainer.slideWidth = (storyViewerWrap === null || storyViewerWrap === void 0 ? void 0 : storyViewerWrap.offsetWidth) || 0;
|
| 968 |
+
setTimeout(function () {
|
| 969 |
+
modalContainer === null || modalContainer === void 0 ? void 0 : modalContainer.classList.add('animated');
|
| 970 |
+
}, 10);
|
| 971 |
+
setTimeout(function () {
|
| 972 |
+
tryFullScreen();
|
| 973 |
+
}, 300); // because effects
|
| 974 |
+
}
|
| 975 |
+
else {
|
| 976 |
+
if (modalContainer) {
|
| 977 |
+
modalContainer.style.display = 'block';
|
| 978 |
+
modalContainer.slideWidth = (storyViewerWrap === null || storyViewerWrap === void 0 ? void 0 : storyViewerWrap.offsetWidth) || 0;
|
| 979 |
+
}
|
| 980 |
+
tryFullScreen();
|
| 981 |
+
}
|
| 982 |
+
zuck.callback('onView')(storyId);
|
| 983 |
+
};
|
| 984 |
+
zuck.callback('onOpen')(storyId, callback);
|
| 985 |
+
};
|
| 986 |
+
var next = function () {
|
| 987 |
+
var callback = function () {
|
| 988 |
+
var lastStory = zuck.internalData.currentStory;
|
| 989 |
+
var lastStoryIndex = zuck.findStoryIndex(lastStory);
|
| 990 |
+
var lastStoryTimelineElement = document.querySelector("#".concat(id, " [data-id=\\"").concat(lastStory, "\\"]"));
|
| 991 |
+
if (lastStoryTimelineElement) {
|
| 992 |
+
lastStoryTimelineElement === null || lastStoryTimelineElement === void 0 ? void 0 : lastStoryTimelineElement.classList.add('seen');
|
| 993 |
+
zuck.data[lastStoryIndex].seen = true;
|
| 994 |
+
zuck.internalData.seenItems[lastStory] = true;
|
| 995 |
+
zuck.saveLocalData('seenItems', zuck.internalData.seenItems);
|
| 996 |
+
zuck.updateStorySeenPosition();
|
| 997 |
+
}
|
| 998 |
+
var stories = document.querySelector('#zuck-modal .story-viewer.next');
|
| 999 |
+
if (!stories) {
|
| 1000 |
+
modalZuckContainer.modal.close();
|
| 1001 |
+
}
|
| 1002 |
+
else {
|
| 1003 |
+
if (zuck.option('rtl')) {
|
| 1004 |
+
moveStoryItem(false);
|
| 1005 |
+
}
|
| 1006 |
+
else {
|
| 1007 |
+
moveStoryItem(true);
|
| 1008 |
+
}
|
| 1009 |
+
}
|
| 1010 |
+
};
|
| 1011 |
+
zuck.callback('onEnd')(zuck.internalData.currentStory, callback);
|
| 1012 |
+
};
|
| 1013 |
+
var close = function () {
|
| 1014 |
+
var modalContainer = document.querySelector('#zuck-modal');
|
| 1015 |
+
var modalContent = document.querySelector('#zuck-modal-content');
|
| 1016 |
+
var callback = function () {
|
| 1017 |
+
if (zuck.option('backNative') && (0, utils_1.hasWindow)()) {
|
| 1018 |
+
window.location.hash = '';
|
| 1019 |
+
}
|
| 1020 |
+
fullScreen(modalContainer, true);
|
| 1021 |
+
if (modalContainer) {
|
| 1022 |
+
if (zuck.option('openEffect')) {
|
| 1023 |
+
modalContainer.classList.add('closed');
|
| 1024 |
+
}
|
| 1025 |
+
else {
|
| 1026 |
+
if (modalContent) {
|
| 1027 |
+
modalContent.innerHTML = '';
|
| 1028 |
+
}
|
| 1029 |
+
modalContainer.style.display = 'none';
|
| 1030 |
+
}
|
| 1031 |
+
}
|
| 1032 |
+
};
|
| 1033 |
+
zuck.callback('onClose')(zuck.internalData.currentStory, callback);
|
| 1034 |
+
};
|
| 1035 |
+
modalZuckContainer.modal = {
|
| 1036 |
+
show: show,
|
| 1037 |
+
next: next,
|
| 1038 |
+
close: close
|
| 1039 |
+
};
|
| 1040 |
+
return modalZuckContainer.modal;
|
| 1041 |
+
};
|
| 1042 |
+
exports.modal = modal;
|
| 1043 |
+
|
| 1044 |
+
|
| 1045 |
+
//# sourceURL=webpack://Zuck/./src/modal.ts?`)}),"./src/options.ts":((__unused_webpack_module,exports,__webpack_require__)=>{eval(`
|
| 1046 |
+
exports.__esModule = true;
|
| 1047 |
+
exports.loadOptions = exports.option = exports.optionsDefault = void 0;
|
| 1048 |
+
var utils_1 = __webpack_require__(/*! ./utils */ "./src/utils.ts");
|
| 1049 |
+
var optionsDefault = function (option) { return ({
|
| 1050 |
+
rtl: false,
|
| 1051 |
+
skin: 'snapgram',
|
| 1052 |
+
avatars: true,
|
| 1053 |
+
stories: [],
|
| 1054 |
+
backButton: true,
|
| 1055 |
+
backNative: false,
|
| 1056 |
+
paginationArrows: false,
|
| 1057 |
+
previousTap: true,
|
| 1058 |
+
autoFullScreen: false,
|
| 1059 |
+
openEffect: true,
|
| 1060 |
+
cubeEffect: false,
|
| 1061 |
+
list: false,
|
| 1062 |
+
localStorage: true,
|
| 1063 |
+
callbacks: {
|
| 1064 |
+
onOpen: function (storyId, callback) {
|
| 1065 |
+
// on open story viewer
|
| 1066 |
+
callback();
|
| 1067 |
+
},
|
| 1068 |
+
onView: function (storyId, callback) {
|
| 1069 |
+
// on view story
|
| 1070 |
+
callback === null || callback === void 0 ? void 0 : callback();
|
| 1071 |
+
},
|
| 1072 |
+
onEnd: function (storyId, callback) {
|
| 1073 |
+
// on end story
|
| 1074 |
+
callback();
|
| 1075 |
+
},
|
| 1076 |
+
onClose: function (storyId, callback) {
|
| 1077 |
+
// on close story viewer
|
| 1078 |
+
callback();
|
| 1079 |
+
},
|
| 1080 |
+
onNextItem: function (storyId, nextStoryId, callback) {
|
| 1081 |
+
// on navigate item of story
|
| 1082 |
+
callback();
|
| 1083 |
+
},
|
| 1084 |
+
onNavigateItem: function (storyId, nextStoryId, callback) {
|
| 1085 |
+
// use to update state on your reactive framework
|
| 1086 |
+
callback();
|
| 1087 |
+
},
|
| 1088 |
+
onDataUpdate: function (data, callback) {
|
| 1089 |
+
// use to update state on your reactive framework
|
| 1090 |
+
callback();
|
| 1091 |
+
}
|
| 1092 |
+
},
|
| 1093 |
+
template: {
|
| 1094 |
+
timelineItem: function (itemData) {
|
| 1095 |
+
return "\\n <div class=\\"story ".concat(itemData['seen'] === true ? 'seen' : '', "\\">\\n <a class=\\"item-link\\" ").concat(itemData['link'] ? "href=\\"".concat(itemData['link'] || '', "\\"") : '', ">\\n <span class=\\"item-preview\\">\\n <img lazy=\\"eager\\" src=\\"").concat(option('avatars') || !itemData['currentPreview']
|
| 1096 |
+
? itemData['photo']
|
| 1097 |
+
: itemData['currentPreview'], "\\" />\\n </span>\\n <span class=\\"info\\" itemProp=\\"author\\" itemScope itemType=\\"http://schema.org/Person\\">\\n <strong class=\\"name\\" itemProp=\\"name\\">").concat(itemData['name'], "</strong>\\n <span class=\\"time\\">").concat((0, utils_1.timeAgo)(itemData['lastUpdated'] || itemData['time'], option('language')) || '', "</span>\\n </span>\\n </a>\\n\\n <ul class=\\"items\\"></ul>\\n </div>");
|
| 1098 |
+
},
|
| 1099 |
+
timelineStoryItem: function (itemData) {
|
| 1100 |
+
var reserved = [
|
| 1101 |
+
'id',
|
| 1102 |
+
'seen',
|
| 1103 |
+
'src',
|
| 1104 |
+
'link',
|
| 1105 |
+
'linkText',
|
| 1106 |
+
'loop',
|
| 1107 |
+
'time',
|
| 1108 |
+
'type',
|
| 1109 |
+
'length',
|
| 1110 |
+
'preview'
|
| 1111 |
+
];
|
| 1112 |
+
var attributes = "";
|
| 1113 |
+
for (var dataKey in itemData) {
|
| 1114 |
+
if (reserved.indexOf(dataKey) === -1) {
|
| 1115 |
+
if (itemData[dataKey] !== undefined && itemData[dataKey] !== false) {
|
| 1116 |
+
attributes += " data-".concat(dataKey, "=\\"").concat(itemData[dataKey], "\\"");
|
| 1117 |
+
}
|
| 1118 |
+
}
|
| 1119 |
+
}
|
| 1120 |
+
reserved.forEach(function (dataKey) {
|
| 1121 |
+
if (itemData[dataKey] !== undefined && itemData[dataKey] !== false) {
|
| 1122 |
+
attributes += " data-".concat(dataKey, "=\\"").concat(itemData[dataKey], "\\"");
|
| 1123 |
+
}
|
| 1124 |
+
});
|
| 1125 |
+
return "<a href=\\"".concat(itemData['src'], "\\" ").concat(attributes, ">\\n <img loading=\\"auto\\" src=\\"").concat(itemData['preview'], "\\" />\\n </a>");
|
| 1126 |
+
},
|
| 1127 |
+
viewerItem: function (storyData, currentStoryItem) {
|
| 1128 |
+
return "<div class=\\"story-viewer\\">\\n <div class=\\"head\\">\\n <div class=\\"left\\">\\n ".concat(option('backButton') ? '<a class="back">‹</a>' : '', "\\n\\n <span class=\\"item-preview\\">\\n <img lazy=\\"eager\\" class=\\"profilePhoto\\" src=\\"").concat(storyData['photo'], "\\" />\\n </span>\\n\\n <div class=\\"info\\">\\n <strong class=\\"name\\">").concat(storyData['name'], "</strong>\\n <span class=\\"time\\">").concat((0, utils_1.timeAgo)(storyData['time'], option('language')) || '', "</span>\\n </div>\\n </div>\\n\\n <div class=\\"right\\">\\n <span class=\\"time\\">\\n ").concat((0, utils_1.timeAgo)(currentStoryItem['time'], option('language')) ||
|
| 1129 |
+
'', "\\n </span>\\n <span class=\\"loading\\"></span>\\n <a class=\\"close\\" tabIndex=\\"2\\">×</a>\\n </div>\\n </div>\\n\\n <div class=\\"slides-pointers\\">\\n <div class=\\"wrap\\"></div>\\n </div>\\n\\n ").concat(option('paginationArrows')
|
| 1130 |
+
? "\\n <div class=\\"slides-pagination\\">\\n <span class=\\"previous\\">‹</span>\\n <span class=\\"next\\">›</span>\\n </div>"
|
| 1131 |
+
: '', "\\n </div>");
|
| 1132 |
+
},
|
| 1133 |
+
viewerItemPointerProgress: function (style) {
|
| 1134 |
+
return "<span class=\\"progress\\" style=\\"".concat(style, "\\"></span>");
|
| 1135 |
+
},
|
| 1136 |
+
viewerItemPointer: function (index, currentIndex, item) {
|
| 1137 |
+
return "<span\\n class=\\"\\n ".concat(currentIndex === index ? 'active' : '', "\\n ").concat(item['seen'] === true ? 'seen' : '', "\\n \\"\\n data-index=\\"").concat(index, "\\" data-item-id=\\"").concat(item['id'], "\\">\\n ").concat(option('template')['viewerItemPointerProgress']("animation-duration:".concat((0, utils_1.safeNum)(item['length']) ? item['length'] : '3', "s")), "\\n </span>");
|
| 1138 |
+
},
|
| 1139 |
+
viewerItemBody: function (index, currentIndex, item) {
|
| 1140 |
+
return "<div\\n class=\\"\\n item\\n ".concat(item['seen'] === true ? 'seen' : '', "\\n ").concat(currentIndex === index ? 'active' : '', "\\n \\"\\n data-time=\\"").concat(item['time'], "\\"\\n data-type=\\"").concat(item['type'], "\\"\\n data-index=\\"").concat(index, "\\"\\n data-item-id=\\"").concat(item['id'], "\\">\\n ").concat(item['type'] === 'video'
|
| 1141 |
+
? "<video class=\\"media\\" data-length=\\"".concat(item.length, "\\" ").concat(item.loop ? 'loop' : '', " muted webkit-playsinline playsinline preload=\\"auto\\" src=\\"").concat(item['src'], "\\" ").concat(item['type'], "></video>\\n <b class=\\"tip muted\\">").concat(option('language')['unmute'], "</b>")
|
| 1142 |
+
: "<img loading=\\"auto\\" class=\\"media\\" src=\\"".concat(item['src'], "\\" ").concat(item['type'], " />\\n "), "\\n\\n ").concat(item['link']
|
| 1143 |
+
? "<a class=\\"tip link\\" href=\\"".concat(item['link'], "\\" rel=\\"noopener\\" target=\\"_blank\\">\\n ").concat(item['linkText'] || option('language')['visitLink'], "\\n </a>")
|
| 1144 |
+
: '', "\\n </div>");
|
| 1145 |
+
}
|
| 1146 |
+
},
|
| 1147 |
+
language: {
|
| 1148 |
+
unmute: 'Touch to unmute',
|
| 1149 |
+
keyboardTip: 'Press space to see next',
|
| 1150 |
+
visitLink: 'Visit link',
|
| 1151 |
+
time: {
|
| 1152 |
+
ago: 'ago',
|
| 1153 |
+
hour: 'hour ago',
|
| 1154 |
+
hours: 'hours ago',
|
| 1155 |
+
minute: 'minute ago',
|
| 1156 |
+
minutes: 'minutes ago',
|
| 1157 |
+
fromnow: 'from now',
|
| 1158 |
+
seconds: 'seconds ago',
|
| 1159 |
+
yesterday: 'yesterday',
|
| 1160 |
+
tomorrow: 'tomorrow',
|
| 1161 |
+
days: 'days ago'
|
| 1162 |
+
}
|
| 1163 |
+
}
|
| 1164 |
+
}); };
|
| 1165 |
+
exports.optionsDefault = optionsDefault;
|
| 1166 |
+
var option = function (options, _name) {
|
| 1167 |
+
var self = function (name) {
|
| 1168 |
+
return typeof (options === null || options === void 0 ? void 0 : options[name]) !== 'undefined'
|
| 1169 |
+
? options === null || options === void 0 ? void 0 : options[name]
|
| 1170 |
+
: (0, exports.optionsDefault)(self)[name];
|
| 1171 |
+
};
|
| 1172 |
+
return self(_name);
|
| 1173 |
+
};
|
| 1174 |
+
exports.option = option;
|
| 1175 |
+
var loadOptions = function (options) {
|
| 1176 |
+
return {
|
| 1177 |
+
option: function (name) {
|
| 1178 |
+
return (0, exports.option)(options, name);
|
| 1179 |
+
},
|
| 1180 |
+
callback: function (name) {
|
| 1181 |
+
var customOpts = (0, exports.option)(options, 'callbacks');
|
| 1182 |
+
return typeof customOpts[name] !== undefined
|
| 1183 |
+
? customOpts[name]
|
| 1184 |
+
: (0, exports.option)(undefined, 'callbacks')[name];
|
| 1185 |
+
},
|
| 1186 |
+
template: function (name) {
|
| 1187 |
+
var customOpts = (0, exports.option)(options, 'template');
|
| 1188 |
+
return typeof customOpts[name] !== undefined
|
| 1189 |
+
? customOpts[name]
|
| 1190 |
+
: (0, exports.option)(undefined, 'template')[name];
|
| 1191 |
+
},
|
| 1192 |
+
language: function (name) {
|
| 1193 |
+
var customOpts = (0, exports.option)(options, 'language');
|
| 1194 |
+
return typeof customOpts[name] !== undefined
|
| 1195 |
+
? customOpts[name]
|
| 1196 |
+
: (0, exports.option)(undefined, 'language')[name];
|
| 1197 |
+
}
|
| 1198 |
+
};
|
| 1199 |
+
};
|
| 1200 |
+
exports.loadOptions = loadOptions;
|
| 1201 |
+
|
| 1202 |
+
|
| 1203 |
+
//# sourceURL=webpack://Zuck/./src/options.ts?`)}),"./src/utils.ts":((__unused_webpack_module,exports)=>{eval(`
|
| 1204 |
+
exports.__esModule = true;
|
| 1205 |
+
exports.timeAgo = exports.findPos = exports.generateId = exports.prepend = exports.onTransitionEnd = exports.onAnimationEnd = exports.safeNum = exports.hasWindow = void 0;
|
| 1206 |
+
var hasWindow = function () {
|
| 1207 |
+
return typeof window !== 'undefined';
|
| 1208 |
+
};
|
| 1209 |
+
exports.hasWindow = hasWindow;
|
| 1210 |
+
var safeNum = function (num) {
|
| 1211 |
+
return num ? Number(num) : 0;
|
| 1212 |
+
};
|
| 1213 |
+
exports.safeNum = safeNum;
|
| 1214 |
+
var onAnimationEnd = function (el, func) {
|
| 1215 |
+
el.addEventListener('animationend', func);
|
| 1216 |
+
};
|
| 1217 |
+
exports.onAnimationEnd = onAnimationEnd;
|
| 1218 |
+
var onTransitionEnd = function (el, func) {
|
| 1219 |
+
if (!el.transitionEndEvent) {
|
| 1220 |
+
el.transitionEndEvent = true;
|
| 1221 |
+
el.addEventListener('transitionend', func);
|
| 1222 |
+
}
|
| 1223 |
+
};
|
| 1224 |
+
exports.onTransitionEnd = onTransitionEnd;
|
| 1225 |
+
var prepend = function (parent, child) {
|
| 1226 |
+
if (!child || !parent) {
|
| 1227 |
+
return;
|
| 1228 |
+
}
|
| 1229 |
+
if (parent === null || parent === void 0 ? void 0 : parent.firstChild) {
|
| 1230 |
+
parent.insertBefore(child, parent === null || parent === void 0 ? void 0 : parent.firstChild);
|
| 1231 |
+
}
|
| 1232 |
+
else {
|
| 1233 |
+
parent.appendChild(child);
|
| 1234 |
+
}
|
| 1235 |
+
};
|
| 1236 |
+
exports.prepend = prepend;
|
| 1237 |
+
var generateId = function () {
|
| 1238 |
+
return 'stories-' + Math.random().toString(36).substr(2, 9);
|
| 1239 |
+
};
|
| 1240 |
+
exports.generateId = generateId;
|
| 1241 |
+
var findPos = function (obj, offsetY, offsetX, stop) {
|
| 1242 |
+
var curleft = 0;
|
| 1243 |
+
var curtop = 0;
|
| 1244 |
+
if (obj) {
|
| 1245 |
+
if (obj.offsetParent) {
|
| 1246 |
+
do {
|
| 1247 |
+
curleft += obj.offsetLeft;
|
| 1248 |
+
curtop += obj.offsetTop;
|
| 1249 |
+
if (obj === stop) {
|
| 1250 |
+
break;
|
| 1251 |
+
}
|
| 1252 |
+
} while ((obj = obj.offsetParent));
|
| 1253 |
+
}
|
| 1254 |
+
if (offsetY) {
|
| 1255 |
+
curtop = curtop - offsetY;
|
| 1256 |
+
}
|
| 1257 |
+
if (offsetX) {
|
| 1258 |
+
curleft = curleft - offsetX;
|
| 1259 |
+
}
|
| 1260 |
+
}
|
| 1261 |
+
return [curleft, curtop];
|
| 1262 |
+
};
|
| 1263 |
+
exports.findPos = findPos;
|
| 1264 |
+
var timeAgo = function (time, languageObject) {
|
| 1265 |
+
var language = (languageObject === null || languageObject === void 0 ? void 0 : languageObject.time) || undefined;
|
| 1266 |
+
var timeNumber = time instanceof Date ? time.getTime() : (0, exports.safeNum)(time) * 1000;
|
| 1267 |
+
var dateObj = new Date(timeNumber);
|
| 1268 |
+
var dateStr = dateObj.getTime();
|
| 1269 |
+
var seconds = (new Date().getTime() - dateStr) / 1000;
|
| 1270 |
+
var formats = [
|
| 1271 |
+
[60, " ".concat((language === null || language === void 0 ? void 0 : language.seconds) || ''), 1],
|
| 1272 |
+
[120, "1 ".concat((language === null || language === void 0 ? void 0 : language.minute) || ''), ''],
|
| 1273 |
+
[3600, " ".concat((language === null || language === void 0 ? void 0 : language.minutes) || ''), 60],
|
| 1274 |
+
[7200, "1 ".concat((language === null || language === void 0 ? void 0 : language.hour) || ''), ''],
|
| 1275 |
+
[86400, " ".concat((language === null || language === void 0 ? void 0 : language.hours) || ''), 3600],
|
| 1276 |
+
[172800, " ".concat((language === null || language === void 0 ? void 0 : language.yesterday) || ''), ''],
|
| 1277 |
+
[604800, " ".concat((language === null || language === void 0 ? void 0 : language.days) || ''), 86400]
|
| 1278 |
+
];
|
| 1279 |
+
var currentFormat = 1;
|
| 1280 |
+
if (seconds < 0) {
|
| 1281 |
+
seconds = Math.abs(seconds);
|
| 1282 |
+
currentFormat = 2;
|
| 1283 |
+
}
|
| 1284 |
+
var result = false;
|
| 1285 |
+
formats.forEach(function (format) {
|
| 1286 |
+
var formatKey = format[0];
|
| 1287 |
+
if (seconds < formatKey && !result) {
|
| 1288 |
+
if (typeof format[2] === 'string') {
|
| 1289 |
+
result = format[currentFormat];
|
| 1290 |
+
}
|
| 1291 |
+
else if (format !== null) {
|
| 1292 |
+
result = Math.floor(seconds / format[2]) + format[1];
|
| 1293 |
+
}
|
| 1294 |
+
}
|
| 1295 |
+
});
|
| 1296 |
+
if (!result) {
|
| 1297 |
+
var day = dateObj.getDate();
|
| 1298 |
+
var month = dateObj.getMonth();
|
| 1299 |
+
var year = dateObj.getFullYear();
|
| 1300 |
+
return "".concat(day, "/").concat(month + 1, "/").concat(year);
|
| 1301 |
+
}
|
| 1302 |
+
else {
|
| 1303 |
+
return result;
|
| 1304 |
+
}
|
| 1305 |
+
};
|
| 1306 |
+
exports.timeAgo = timeAgo;
|
| 1307 |
+
|
| 1308 |
+
|
| 1309 |
+
//# sourceURL=webpack://Zuck/./src/utils.ts?`)})},__webpack_module_cache__={};function __webpack_require__(n){var t=__webpack_module_cache__[n];if(t!==void 0)return t.exports;var e=__webpack_module_cache__[n]={exports:{}};return __webpack_modules__[n](e,e.exports,__webpack_require__),e.exports}var __webpack_exports__=__webpack_require__("./src/index.ts");exports.Zuck=__webpack_exports__.default})()});export default a();
|
sha256/6ff8513d484fcf377d948147762b83dafd3cdefd3d48d4333669407808a7653c
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
sha256/7c0ac719466c48d161fba6b77fdcee5a6c017f9d540da575f23191ddbc97d982
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
sha256/929cb2072b4084ca0195c2c0cb65190340c29e62c6b5c50dc1cebf8b788f6eca
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
import{$ as lt,A as nt,B as ot,Ca as ft,Cb as K,F as it,G as ct,Ja as gt,Pa as T,Q as at,S as rt,Sa as B,_ as st,aa as W,ab as wt,bb as tt,ha as ut,ia as ht,ib as X,jb as pt,ka as J,la as N,ma as Q,nb as L,p as q,qa as dt,ub as $,wa as mt,xb as vt}from"./chunk-E6U7U64M.js";import"./chunk-SXSU3V5W.js";import{a as Pt}from"./chunk-EJ2FITLI.js";import{b as It}from"./chunk-SQE76S5B.js";var e=It(Pt(),1);var Mt={minZoom:1,maxZoomPixelRatio:1,zoomInMultiplier:2,doubleTapDelay:300,doubleClickDelay:500,doubleClickMaxStops:2,keyboardMoveDistance:50,wheelZoomDistanceFactor:100,pinchZoomDistanceFactor:100,pinchZoomV4:!1,scrollToZoom:!1,maxZoom:8};function _t(t){return Math.min(Math.max(t,Number.EPSILON),1)}function Ct(t){let{minZoom:n,...i}={...Mt,...t};return{minZoom:_t(n),...i}}function kt(t,n,i,o){let c=e.useRef(void 0),l=e.useRef(void 0),{zoom:u}=T().animation,s=pt(),h=L(()=>{var d,g,r;if((d=c.current)===null||d===void 0||d.cancel(),c.current=void 0,l.current&&o?.current){try{c.current=(r=(g=o.current).animate)===null||r===void 0?void 0:r.call(g,[{transform:l.current},{transform:`scale(${t}) translateX(${n}px) translateY(${i}px)`}],{duration:s?0:u??500,easing:c.current?"ease-out":"ease-in-out"})}catch(R){console.error(R)}l.current=void 0,c.current&&(c.current.onfinish=()=>{c.current=void 0})}});return X(h,[t,n,i,h]),e.useCallback(()=>{l.current=o?.current?window.getComputedStyle(o.current).transform:void 0},[o])}function yt(t,n){let{on:i}=T(),o=L(()=>{var c;n||(c=i.zoom)===null||c===void 0||c.call(i,{zoom:t})});e.useEffect(o,[t,o])}function G(){let{zoom:t}=T();return Ct(t)}function Dt(t,n){var i;let o=typeof t=="function"?(i=t(n))!==null&&i!==void 0?i:Mt.maxZoom:t;return Math.max(o,1)}function Ot(t,n){var i,o;let c={width:0,height:0},l={width:0,height:0},{currentSlide:u}=B(),{imageFit:s}=T().carousel,{maxZoomPixelRatio:h,maxZoom:d}=G();if(t&&u){let r={...u,...n};if(N(r)){let R=Q(r,s),m=Math.max(...(((i=r.srcSet)===null||i===void 0?void 0:i.map(v=>v.width))||[]).concat(r.width?[r.width]:[])),w=Math.max(...(((o=r.srcSet)===null||o===void 0?void 0:o.map(v=>v.height))||[]).concat(r.height?[r.height]:[]));m>0&&w>0&&t.width>0&&t.height>0&&(l=R?{width:Math.round(Math.min(m,t.width/t.height*w)),height:Math.round(Math.min(w,t.height/t.width*m))}:{width:m,height:w},l={width:l.width*h,height:l.height*h},c=R?{width:Math.min(t.width,l.width,m),height:Math.min(t.height,l.height,w)}:{width:Math.round(Math.min(t.width,t.height/w*m,m)),height:Math.round(Math.min(t.height,t.width/m*w,w))})}else t.width>0&&t.height>0&&(n&&n.width>0&&n.height>0?c={width:Math.min(t.width,n.width),height:Math.min(t.height,n.height)}:c={width:t.width,height:t.height})}let g=u&&c.width?N(u)?Math.max(J(l.width/c.width,5),1):Dt(d,u):1;return{imageRect:c,maxZoom:g}}function Rt(t,n){return Math.hypot(t.clientX-n.clientX,t.clientY-n.clientY)}function Zt(t,n,i=100,o=2){return t*Math.min(1+Math.abs(n/i),o)**Math.sign(n)}function Lt(t,n,i,o,c,l,u,s,h){let d=e.useRef([]),g=e.useRef(0),r=e.useRef(void 0),{globalIndex:R}=B(),{getOwnerWindow:m}=gt(),{containerRef:w,subscribeSensors:v}=K(),{keyboardMoveDistance:C,zoomInMultiplier:k,wheelZoomDistanceFactor:x,scrollToZoom:M,doubleTapDelay:Z,doubleClickDelay:b,doubleClickMaxStops:S,pinchZoomDistanceFactor:p,pinchZoomV4:I}=G(),Y=e.useCallback(a=>{if(w.current){let{pageX:f,pageY:E}=a,{scrollX:P,scrollY:_}=m(),{left:O,top:F,width:H,height:V}=w.current.getBoundingClientRect();return[f-O-P-H/2,E-F-_-V/2]}return[]},[w,m]),y=L(a=>{let{key:f,metaKey:E,ctrlKey:P}=a,_=E||P,O=()=>{a.preventDefault(),a.stopPropagation()};if(t>1){let F=(H,V)=>{O(),s(H,V)};f==="ArrowDown"?F(0,C):f==="ArrowUp"?F(0,-C):f==="ArrowLeft"?F(-C,0):f==="ArrowRight"&&F(C,0)}f==="+"||_&&f==="="?(O(),c()):f==="-"||_&&f==="_"?(O(),l()):_&&f==="0"&&(O(),u(1))}),D=L(a=>{if((a.ctrlKey||M)&&Math.abs(a.deltaY)>Math.abs(a.deltaX)){a.stopPropagation(),u(Zt(t,-a.deltaY,x),!0,...Y(a));return}t>1&&(a.stopPropagation(),M||s(a.deltaX,a.deltaY))}),A=e.useCallback(a=>{let f=d.current;f.splice(0,f.length,...f.filter(E=>E.pointerId!==a.pointerId))},[]),z=e.useCallback(a=>{A(a),a.persist(),d.current.push(a)},[A]),j=L(a=>{var f;let E=d.current;if(a.pointerType==="mouse"&&a.buttons>1||!(!((f=h?.current)===null||f===void 0)&&f.contains(a.target)))return;t>1&&a.stopPropagation();let{timeStamp:P}=a;if(E.length===0&&P-g.current<(a.pointerType==="touch"?Z:b)){g.current=0;let _=t>=1?t!==i?t*Math.max(i**(1/S),k):1:t!==n?t/Math.max(n**(-1/S),k):1;u(_,!1,...Y(a))}else g.current=P;if(z(a),E.length===2){let _=Rt(E[0],E[1]);r.current={previousDistance:_,initialDistance:Math.max(_,1),initialZoom:t}}}),xt=L(a=>{let f=d.current,E=f.find(P=>P.pointerId===a.pointerId);if(f.length===2&&r.current){a.stopPropagation(),z(a);let P=Rt(f[0],f[1]),_=I?r.current.initialZoom/r.current.initialDistance*P:Zt(t,P-r.current.previousDistance,p);u(_,!0,...f.map(O=>Y(O)).reduce((O,F)=>F.map((H,V)=>O[V]+H/2))),r.current.previousDistance=P;return}t>1&&(a.stopPropagation(),E&&(f.length===1&&s((E.clientX-a.clientX)/t,(E.clientY-a.clientY)/t),z(a)))}),St=e.useCallback(a=>{let f=d.current;f.length===2&&f.find(E=>E.pointerId===a.pointerId)&&(r.current=void 0),A(a)},[A]),U=e.useCallback(()=>{let a=d.current;a.splice(0,a.length),g.current=0,r.current=void 0},[]);vt(v,j,xt,St,o),e.useEffect(U,[R,U]),e.useEffect(()=>o?()=>{}:ut(U,v(at,y),v(rt,D)),[o,v,U,y,D])}function Yt(t,n,i){let[o,c]=e.useState(1),[l,u]=e.useState(0),[s,h]=e.useState(0),d=kt(o,l,s,i),{currentSlide:g,globalIndex:r}=B(),{containerRect:R,slideRect:m}=K(),{minZoom:w,zoomInMultiplier:v}=G(),C=g&&N(g)?g.src:void 0,k=!i?.current;X(()=>{c(1),u(0),h(0)},[r,C]);let x=e.useCallback((p,I,Y)=>{let y=Y||o,D=l-(p||0),A=s-(I||0),z=(t.width*y-m.width)/2/y,j=(t.height*y-m.height)/2/y;u(Math.min(Math.abs(D),Math.max(z,0))*Math.sign(D)),h(Math.min(Math.abs(A),Math.max(j,0))*Math.sign(A))},[o,l,s,m,t.width,t.height]),M=e.useCallback((p,I,Y,y)=>{let D=J(p+.01<n?p-.01>w?p:w:n,5);I||d(),x(Y?Y*(1/o-1/D):0,y?y*(1/o-1/D):0,D),c(D)},[o,w,n,x,d]),Z=L(()=>{o>1&&(o>n&&M(n,!0),x())});X(Z,[R.width,R.height,Z]);let b=e.useCallback(()=>{let p=o*v;M(o<1&&p>1?1:p)},[o,v,M]),S=e.useCallback(()=>{let p=o/v;M(o>1&&p<1?1:p)},[o,v,M]);return{zoom:o,offsetX:l,offsetY:s,disabled:k,changeOffsets:x,changeZoom:M,zoomIn:b,zoomOut:S}}var Et=e.createContext(null),et=ht("useZoom","ZoomControllerContext",Et);function Ft({children:t}){let[n,i]=e.useState(),{slideRect:o}=K(),{ref:c,minZoom:l}=G(),{imageRect:u,maxZoom:s}=Ot(o,n?.imageDimensions),{zoom:h,offsetX:d,offsetY:g,disabled:r,changeZoom:R,changeOffsets:m,zoomIn:w,zoomOut:v}=Yt(u,s,n?.zoomWrapperRef);yt(h,r),Lt(h,l,s,r,w,v,R,m,n?.zoomWrapperRef);let C=e.useMemo(()=>({zoom:h,minZoom:l,maxZoom:s,offsetX:d,offsetY:g,disabled:r,zoomIn:w,zoomOut:v,changeZoom:R}),[h,l,s,d,g,r,w,v,R]);e.useImperativeHandle(c,()=>C,[C]);let k=e.useMemo(()=>({...C,setZoomWrapper:i}),[C,i]);return e.createElement(Et.Provider,{value:k},t)}var Tt=tt("ZoomIn",e.createElement(e.Fragment,null,e.createElement("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"}),e.createElement("path",{d:"M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z"}))),At=tt("ZoomOut",e.createElement("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zM7 9h5v1H7z"})),bt=e.forwardRef(function({zoomIn:n,onLoseFocus:i},o){let c=e.useRef(!1),l=e.useRef(!1),{zoom:u,minZoom:s,maxZoom:h,zoomIn:d,zoomOut:g,disabled:r}=et(),{render:R}=T(),m=r||(n?u>=h:u<=s);return e.useEffect(()=>{m&&c.current&&l.current&&i(),m||(c.current=!0)},[m,i]),e.createElement(wt,{ref:o,disabled:m,label:n?"Zoom in":"Zoom out",icon:n?Tt:At,renderIcon:n?R.iconZoomIn:R.iconZoomOut,onClick:n?d:g,onFocus:()=>{l.current=!0},onBlur:()=>{l.current=!1}})});function Xt(){let t=e.useRef(null),n=e.useRef(null),{focus:i}=K(),o=e.useCallback(u=>{var s,h;!((s=u.current)===null||s===void 0)&&s.disabled?i():(h=u.current)===null||h===void 0||h.focus()},[i]),c=e.useCallback(()=>o(t),[o]),l=e.useCallback(()=>o(n),[o]);return e.createElement(e.Fragment,null,e.createElement(bt,{zoomIn:!0,ref:t,onLoseFocus:l}),e.createElement(bt,{ref:n,onLoseFocus:c}))}function Nt(){let{render:t}=T(),n=et();return t.buttonZoom?e.createElement(e.Fragment,null,t.buttonZoom(n)):e.createElement(Xt,null)}function zt(t){var n;return(((n=t.srcSet)===null||n===void 0?void 0:n.length)||0)>0}function Ht({current:t,preload:n},{type:i,source:o}){switch(i){case"fetch":return t?{current:t,preload:o}:{current:o};case"done":return o===n?{current:o}:{current:t,preload:n};default:throw new Error(st)}}function Vt(t){var n,i;let[{current:o,preload:c},l]=e.useReducer(Ht,{}),{slide:u,rect:s,imageFit:h,render:d,interactive:g}=t,r=u.srcSet.sort((b,S)=>b.width-S.width),R=(n=u.width)!==null&&n!==void 0?n:r[r.length-1].width,m=(i=u.height)!==null&&i!==void 0?i:r[r.length-1].height,w=Q(u,h),v=Math.max(...r.map(b=>b.width)),C=Math.min((w?Math.max:Math.min)(s.width,R*(s.height/m)),v),k=dt(),x=L(()=>{var b;let S=(b=r.find(p=>p.width>=C*k))!==null&&b!==void 0?b:r[r.length-1];(!o||r.findIndex(p=>p.src===o)<r.findIndex(p=>p===S))&&l({type:"fetch",source:S.src})});X(x,[s.width,s.height,k,x]);let M=L(b=>l({type:"done",source:b})),Z={WebkitTransform:g?"initial":"translateZ(0)"};return w||Object.assign(Z,s.width/s.height<R/m?{width:"100%",height:"auto"}:{width:"auto",height:"100%"}),e.createElement(e.Fragment,null,c&&c!==o&&e.createElement($,{key:"preload",...t,offset:void 0,slide:{...u,src:c,srcSet:void 0},style:{position:"absolute",visibility:"hidden",...Z},onLoad:()=>M(c),render:{...d,iconLoading:()=>null,iconError:()=>null}}),o&&e.createElement($,{key:"current",...t,slide:{...u,src:o,srcSet:void 0},style:Z}))}function Wt({render:t,slide:n,offset:i,rect:o}){var c;let[l,u]=e.useState(),s=e.useRef(null),h=N(n),{zoom:d,maxZoom:g,offsetX:r,offsetY:R,setZoomWrapper:m}=et(),w=d>1,{carousel:v,on:C}=T(),{currentIndex:k}=B();X(()=>{if(i!==0||h||!s.current)return()=>{};let M=()=>{let b=s.current;if(!b)return;let S=0,p=0;for(let I of b.children)I instanceof HTMLElement&&(S=Math.max(S,I.offsetWidth),p=Math.max(p,I.offsetHeight));u(I=>I&&I.width===S&&I.height===p?I:{width:S,height:p})};if(M(),typeof ResizeObserver>"u")return()=>{};let Z=new ResizeObserver(M);for(let b of s.current.children)Z.observe(b);return()=>Z.disconnect()},[i,h,o]),X(()=>i===0?(m({zoomWrapperRef:s,imageDimensions:l}),()=>m(void 0)):()=>{},[i,l,m]);let x=(c=t.slide)===null||c===void 0?void 0:c.call(t,{slide:n,offset:i,rect:o,zoom:d,maxZoom:g});if(!x&&h){let M={slide:n,offset:i,rect:o,render:t,imageFit:v.imageFit,imageProps:v.imageProps,onClick:i===0?()=>{var Z;return(Z=C.click)===null||Z===void 0?void 0:Z.call(C,{index:k})}:void 0};x=zt(n)?e.createElement(Vt,{...M,slide:n,interactive:w,rect:i===0?{width:o.width*d,height:o.height*d}:o}):e.createElement($,{onLoad:Z=>u({width:Z.naturalWidth,height:Z.naturalHeight}),...M})}return x?e.createElement("div",{ref:s,className:lt(W(nt),W(ot),W(it),w&&W(ct)),style:i===0?{transform:`scale(${d}) translateX(${r}px) translateY(${R}px)`}:void 0},x):null}var Ut=({augment:t,addModule:n})=>{t(({zoom:i,toolbar:o,render:c,controller:l,...u})=>{let s=Ct(i);return{zoom:s,toolbar:mt(o,q,e.createElement(Nt,null)),render:{...c,slide:h=>{var d,g;return N(h.slide)||h.slide.type!=null&&(!((d=s.supports)===null||d===void 0)&&d.includes(h.slide.type))?e.createElement(Wt,{render:c,...h}):(g=c.slide)===null||g===void 0?void 0:g.call(c,h)}},controller:{...l,preventDefaultWheelY:s.scrollToZoom},...u}}),n(ft(q,Ft))};export{Ut as default};
|
sha256/946dd4ca8e36408f3e5da27813cdafad3908e2a3466dc86e82eff442de4b813f
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
sha256/9ffc94e11c78fbe6b940bc04ac92f0f12238cf7ce82b5092c53d5761146a50df
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
sha256/ba0a74a49b10960552dd4778d210a152990ee94b69a2847699c630f94f87182d
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
import{a as _n}from"./chunk-SXSU3V5W.js";import{a as mn}from"./chunk-EJ2FITLI.js";import{b as _t}from"./chunk-SQE76S5B.js";var n=_t(mn(),1);var Ve="carousel",$e="controller",vt="navigation",Lt="no-scroll",Ie="portal",gt="root",Fe="toolbar",vn="captions",Ln="counter",gn="download",Nn="fullscreen",In="inline",Cn="share",Pn="slideshow",Sn="thumbnails",On="zoom",fe="loading",Nt="playing",Re="error",Ee="complete",It="placeholder",ae=e=>`active-slide-${e}`,Tn=ae(fe),xn=ae(Nt),bn=ae(Re),wn=ae(Ee),An="fullsize",Ge="flex_center",Ct="no_scroll",He="no_scroll_padding",Ce="slide",Pt="slide_wrapper",yn="slide_wrapper_interactive",q="prev",Q="next",Ke="swipe",ee="close",Be="onPointerDown",Xe="onPointerMove",Ye="onPointerUp",ze="onPointerLeave",je="onPointerCancel",Ze="onKeyDown",St="onKeyUp",qe="onWheel",Ot="Escape",Tt="ArrowLeft",xt="ArrowRight",bt="button",Pe="icon",Qe="contain",Je="cover",wt="Unknown action type";var Gt=_t(_n(),1),Ht="yarl__";function z(...e){return e.filter(Boolean).join(" ")}function P(e){return`${Ht}${e}`}function F(e){return`--${Ht}${e}`}function pe(e,t){return`${e}${t?`_${t}`:""}`}function at(e){return t=>pe(e,t)}function ne(e,t){var o;return(o=e?.[t])!==null&&o!==void 0?o:t}function ko(e,t){return ne(e,t)}function Mn(e,t,o){return ne(e,"{index} of {total}").replace(/\{index}/g,`${st(o,t.length)+1}`).replace(/\{total}/g,`${t.length}`)}function Kt(...e){return()=>{e.forEach(t=>{t()})}}function j(e,t,o){return()=>{let r=n.useContext(o);if(!r)throw new Error(`${e} must be used within a ${t}.Provider`);return r}}function it(){return typeof window<"u"}function Dn(e,t=0){let o=10**t;return Math.round((e+Number.EPSILON)*o)/o}function Bt(e){return e.type===void 0||e.type==="image"}function Un(e,t){return e.imageFit===Je||e.imageFit!==Qe&&t===Je}function Te(e){return typeof e=="string"?Number.parseInt(e,10):e}function Oe(e){if(typeof e=="number")return{pixel:e};if(typeof e=="string"){let t=Te(e);return e.endsWith("%")?{percent:t}:{pixel:t}}return{pixel:0}}function Wn(e,t){let o=Oe(t),r=o.percent!==void 0?e.width/100*o.percent:o.pixel;return{width:Math.max(e.width-2*r,0),height:Math.max(e.height-2*r,0)}}function Vo(){return(it()?window?.devicePixelRatio:void 0)||1}function st(e,t){return t>0?(e%t+t)%t:0}function Xt(e){return e.length>0}function Yt(e,t){return e[st(t,e.length)]}function ot(e,t){return Xt(e)?Yt(e,t):void 0}function kn(e){return Bt(e)?e.src:void 0}function $o(e,t,o){if(!o)return e;let{buttons:r,...c}=e,a=r.findIndex(s=>s===t),i=n.isValidElement(o)?n.cloneElement(o,{key:t},null):o;if(a>=0){let s=[...r];return s.splice(a,1,i),{buttons:s,...c}}return{buttons:[i,...r],...c}}function Fo(){let e=t=>{t.stopPropagation()};return{onPointerDown:e,onKeyDown:e,onWheel:e}}function Vn(e,t,o=0){return Math.min(e.preload,Math.max(e.finite?t.length-1:Math.floor(t.length/2),o))}var $n=Number(n.version.split(".")[0])>=19;function Fn(e){return{inert:$n?e:e?"":void 0}}function Gn(e){e.scrollTop}var rt={open:!1,close:()=>{},index:0,slides:[],render:{},plugins:[],toolbar:{buttons:[ee]},labels:{},animation:{fade:250,swipe:500,easing:{fade:"ease",swipe:"ease-out",navigation:"ease-in-out"}},carousel:{finite:!1,preload:2,padding:"16px",spacing:"30%",imageFit:Qe,imageProps:{}},controller:{ref:null,focus:!0,aria:!1,touchAction:"none",closeOnPullUp:!1,closeOnPullDown:!1,closeOnBackdropClick:!1,closeOnEscape:!0,preventDefaultWheelX:!0,preventDefaultWheelY:!1,disableSwipeNavigation:!1},portal:{},noScroll:{disabled:!1},on:{},styles:{},className:""};function oe(e,t){return{name:e,component:t}}function U(e,t){return{module:e,children:t}}function zt(e,t,o){return e.module.name===t?o(e):e.children?[U(e.module,e.children.flatMap(r=>{var c;return(c=zt(r,t,o))!==null&&c!==void 0?c:[]}))]:[e]}function ie(e,t,o){return e.flatMap(r=>{var c;return(c=zt(r,t,o))!==null&&c!==void 0?c:[]})}function Hn(e,t=[],o=[]){let r=e,c=p=>{let E=[...r];for(;E.length>0;){let u=E.pop();if(u?.module.name===p)return!0;u?.children&&E.push(...u.children)}return!1},a=(p,E)=>{if(p===""){r=[U(E,r)];return}r=ie(r,p,u=>[U(E,[u])])},i=(p,E)=>{r=ie(r,p,u=>[U(u.module,[U(E,u.children)])])},s=(p,E,u)=>{r=ie(r,p,N=>{var I;return[U(N.module,[...u?[U(E)]:[],...(I=N.children)!==null&&I!==void 0?I:[],...u?[]:[U(E)]])]})},d=(p,E,u)=>{r=ie(r,p,N=>[...u?[U(E)]:[],N,...u?[]:[U(E)]])},f=p=>{i($e,p)},h=(p,E)=>{r=ie(r,p,u=>[U(E,u.children)])},m=p=>{r=ie(r,p,E=>E.children)},R=p=>{o.push(p)};return t.forEach(p=>{p({contains:c,addParent:a,append:i,addChild:s,addSibling:d,addModule:f,replace:h,remove:m,augment:R})}),{config:r,augmentation:p=>o.reduce((E,u)=>u(E),p)}}var jt=n.createContext(null),Zt=j("useA11yContext","A11yContext",jt);function Kn({children:e}){let[t,o]=n.useState(!1),[r,c]=n.useState(!1),a=n.useMemo(()=>({focusWithin:t,trackFocusWithin:(s,d)=>{let f=h=>m=>{var R;m.currentTarget.contains(m.relatedTarget)||o(h),(R=h?s:d)===null||R===void 0||R(m)};return{onFocus:f(!0),onBlur:f(!1)}},autoPlaying:r,setAutoPlaying:c}),[t,r]);return n.createElement(jt.Provider,{value:a},e)}var qt=n.createContext(null),lt=j("useDocument","DocumentContext",qt);function Bn({nodeRef:e,children:t}){let o=n.useMemo(()=>{let r=a=>{var i;return((i=a||e.current)===null||i===void 0?void 0:i.ownerDocument)||document};return{getOwnerDocument:r,getOwnerWindow:a=>{var i;return((i=r(a))===null||i===void 0?void 0:i.defaultView)||window}}},[e]);return n.createElement(qt.Provider,{value:o},t)}var Qt=n.createContext(null),xe=j("useEvents","EventsContext",Qt);function Xn({children:e}){let[t]=n.useState({});n.useEffect(()=>()=>{Object.keys(t).forEach(r=>delete t[r])},[t]);let o=n.useMemo(()=>{let r=(i,s)=>{var d;(d=t[i])===null||d===void 0||d.splice(0,t[i].length,...t[i].filter(f=>f!==s))};return{publish:(...[i,s])=>{var d;(d=t[i])===null||d===void 0||d.forEach(f=>f(s))},subscribe:(i,s)=>(t[i]||(t[i]=[]),t[i].push(s),()=>r(i,s)),unsubscribe:r}},[t]);return n.createElement(Qt.Provider,{value:o},e)}var Jt=n.createContext(null),he=j("useLightboxProps","LightboxPropsContext",Jt);function Yn({children:e,...t}){return n.createElement(Jt.Provider,{value:t},e)}var en=n.createContext(null),be=j("useLightboxState","LightboxStateContext",en),tn=n.createContext(null),zn=j("useLightboxDispatch","LightboxDispatchContext",tn);function jn(e,t){switch(t.type){case"swipe":{let{slides:o}=e,r=t?.increment||0,c=e.globalIndex+r,a=st(c,o.length),i=ot(o,a),s=r||t.duration!==void 0?{increment:r,duration:t.duration,easing:t.easing}:void 0;return{slides:o,currentIndex:a,globalIndex:c,currentSlide:i,animation:s}}case"update":return t.slides!==e.slides||t.index!==e.currentIndex?{slides:t.slides,currentIndex:t.index,globalIndex:t.index,currentSlide:ot(t.slides,t.index)}:e;default:throw new Error(wt)}}function Zn({slides:e,index:t,children:o}){let[r,c]=n.useReducer(jn,{slides:e,currentIndex:t,globalIndex:t,currentSlide:ot(e,t)}),[a,i]=n.useState(e),[s,d]=n.useState(t);(e!==a||t!==s)&&(i(e),d(t),c({type:"update",slides:e,index:t}));let f=n.useMemo(()=>({...r,state:r,dispatch:c}),[r,c]);return n.createElement(tn.Provider,{value:c},n.createElement(en.Provider,{value:f},o))}var nn=n.createContext(null),qn=j("useRTLContext","RTLContext",nn);function Qn({isRTL:e,children:t}){let o=n.useMemo(()=>({isRTL:e}),[e]);return n.createElement(nn.Provider,{value:o},t)}var on=n.createContext(null),we=j("useTimeouts","TimeoutsContext",on);function Jn({children:e}){let[t]=n.useState([]);n.useEffect(()=>()=>{t.forEach(r=>window.clearTimeout(r)),t.splice(0,t.length)},[t]);let o=n.useMemo(()=>{let r=i=>{t.splice(0,t.length,...t.filter(s=>s!==i))};return{setTimeout:(i,s)=>{let d=window.setTimeout(()=>{r(d),i()},s);return t.push(d),d},clearTimeout:i=>{i!==void 0&&(r(i),window.clearTimeout(i))}}},[t]);return n.createElement(on.Provider,{value:o},e)}var rn=n.forwardRef(function({label:t,className:o,icon:r,renderIcon:c,onClick:a,style:i,...s},d){let{styles:f,labels:h}=he(),m=ne(h,t);return n.createElement("button",{ref:d,type:"button",title:m,"aria-label":m,className:z(P(bt),o),onClick:a,style:{...i,...f.button},...s},c?c():n.createElement(r,{className:P(Pe),style:f.icon}))});function cn(e,t){let o=r=>n.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:"24",height:"24","aria-hidden":"true",focusable:"false",...r},t);return o.displayName=e,o}function me(e,t){return cn(e,n.createElement("g",{fill:"currentColor"},n.createElement("path",{d:"M0 0h24v24H0z",fill:"none"}),t))}function Go(e,t){return cn(e,n.createElement(n.Fragment,null,n.createElement("defs",null,n.createElement("mask",{id:"strike"},n.createElement("path",{d:"M0 0h24v24H0z",fill:"white"}),n.createElement("path",{d:"M0 0L24 24",stroke:"black",strokeWidth:4}))),n.createElement("path",{d:"M0.70707 2.121320L21.878680 23.292883",stroke:"currentColor",strokeWidth:2}),n.createElement("g",{fill:"currentColor",mask:"url(#strike)"},n.createElement("path",{d:"M0 0h24v24H0z",fill:"none"}),t)))}var eo=me("Close",n.createElement("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"})),to=me("Previous",n.createElement("path",{d:"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"})),no=me("Next",n.createElement("path",{d:"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"})),oo=me("Loading",n.createElement(n.Fragment,null,Array.from({length:8}).map((e,t,o)=>n.createElement("line",{key:t,x1:"12",y1:"6.5",x2:"12",y2:"1.8",strokeLinecap:"round",strokeWidth:"2.6",stroke:"currentColor",strokeOpacity:1/o.length*(t+1),transform:`rotate(${360/o.length*t}, 12, 12)`})))),ro=me("Error",n.createElement("path",{d:"M21.9,21.9l-8.49-8.49l0,0L3.59,3.59l0,0L2.1,2.1L0.69,3.51L3,5.83V19c0,1.1,0.9,2,2,2h13.17l2.31,2.31L21.9,21.9z M5,18 l3.5-4.5l2.5,3.01L12.17,15l3,3H5z M21,18.17L5.83,3H19c1.1,0,2,0.9,2,2V18.17z"})),Ae=it()?n.useLayoutEffect:n.useEffect;function an(){let[e,t]=n.useState(!1);return n.useEffect(()=>{var o,r;let c=(o=window.matchMedia)===null||o===void 0?void 0:o.call(window,"(prefers-reduced-motion: reduce)");t(c?.matches);let a=i=>t(i.matches);return(r=c?.addEventListener)===null||r===void 0||r.call(c,"change",a),()=>{var i;return(i=c?.removeEventListener)===null||i===void 0?void 0:i.call(c,"change",a)}},[]),e}function co(e){let t=0,o=0,r=0,a=window.getComputedStyle(e).transform.match(/matrix.*\((.+)\)/);if(a){let i=a[1].split(",").map(Te);i.length===6?(t=i[4],o=i[5]):i.length===16&&(t=i[12],o=i[13],r=i[14])}return{x:t,y:o,z:r}}function At(e,t){let o=n.useRef(void 0),r=n.useRef(void 0),c=an();return Ae(()=>{var a,i,s;if(e.current&&o.current!==void 0&&!c){let{keyframes:d,duration:f,easing:h,onfinish:m}=t(o.current,e.current.getBoundingClientRect(),co(e.current))||{};if(d&&f){(a=r.current)===null||a===void 0||a.cancel(),r.current=void 0;try{r.current=(s=(i=e.current).animate)===null||s===void 0?void 0:s.call(i,d,{duration:f,easing:h})}catch(R){console.error(R)}r.current&&(r.current.onfinish=()=>{r.current=void 0,m?.()})}}o.current=void 0}),{prepareAnimation:a=>{o.current=a},isAnimationPlaying:()=>{var a;return((a=r.current)===null||a===void 0?void 0:a.playState)==="running"}}}function sn(){let e=n.useRef(null),t=n.useRef(void 0),[o,r]=n.useState();return{setContainerRef:n.useCallback(a=>{e.current=a,t.current&&(t.current.disconnect(),t.current=void 0);let i=()=>{if(a){let s=window.getComputedStyle(a),d=f=>parseFloat(f)||0;r({width:Math.round(a.clientWidth-d(s.paddingLeft)-d(s.paddingRight)),height:Math.round(a.clientHeight-d(s.paddingTop)-d(s.paddingBottom))})}else r(void 0)};i(),a&&typeof ResizeObserver<"u"&&(t.current=new ResizeObserver(i),t.current.observe(a))},[]),containerRef:e,containerRect:o}}function Se(){let e=n.useRef(void 0),{setTimeout:t,clearTimeout:o}=we();return n.useCallback((r,c)=>{o(e.current),e.current=t(r,c>0?c:0)},[t,o])}function A(e){let t=n.useRef(e);return Ae(()=>{t.current=e}),n.useCallback((...o)=>{var r;return(r=t.current)===null||r===void 0?void 0:r.call(t,...o)},[])}function yt(e,t){typeof e=="function"?e(t):e&&(e.current=t)}function ct(e,t){return n.useMemo(()=>e==null&&t==null?null:o=>{yt(e,o),yt(t,o)},[e,t])}function ao(e,t=!1){let o=n.useRef(!1);Ae(()=>{t&&o.current&&(o.current=!1,e())},[t,e]);let r=n.useCallback(()=>{o.current=!0},[]),c=n.useCallback(()=>{o.current=!1},[]);return{onFocus:r,onBlur:c}}function ut(){return qn().isRTL}function io(){let[e]=n.useState({}),t=n.useCallback((c,a)=>{var i;(i=e[c])===null||i===void 0||i.forEach(s=>{a.isPropagationStopped()||s(a)})},[e]),o=n.useMemo(()=>({onPointerDown:c=>t(Be,c),onPointerMove:c=>t(Xe,c),onPointerUp:c=>t(Ye,c),onPointerLeave:c=>t(ze,c),onPointerCancel:c=>t(je,c),onKeyDown:c=>t(Ze,c),onKeyUp:c=>t(St,c),onWheel:c=>t(qe,c)}),[t]),r=n.useCallback((c,a)=>(e[c]||(e[c]=[]),e[c].unshift(a),()=>{let i=e[c];i&&i.splice(0,i.length,...i.filter(s=>s!==a))}),[e]);return{registerSensors:o,subscribeSensors:r}}function Mt(e,t){let o=n.useRef(0),r=Se(),c=A((...a)=>{o.current=Date.now(),e(a)});return n.useCallback((...a)=>{r(()=>{c(a)},t-(Date.now()-o.current))},[t,c,r])}var et=at("slide"),tt=at("slide_image");function so({slide:e,offset:t,render:o,rect:r,imageFit:c,imageProps:a,onClick:i,onLoad:s,onError:d,style:f}){var h,m,R,p,E,u,N,I;let[S,b]=n.useState(fe),{publish:w}=xe(),{setTimeout:T}=we(),D=n.useRef(null);n.useEffect(()=>{t===0&&w(ae(S))},[t,S,w]);let O=A(C=>{("decode"in C?C.decode():Promise.resolve()).catch(()=>{}).then(()=>{C.parentNode&&(b(Ee),T(()=>{s?.(C)},0))})}),y=n.useCallback(C=>{D.current=C,C?.complete&&O(C)},[O]),_=n.useCallback(C=>{O(C.currentTarget)},[O]),V=A(()=>{b(Re),d?.()}),H=Un(e,c),B=(C,re)=>Number.isFinite(C)?C:re,v=B(Math.max(...((m=(h=e.srcSet)===null||h===void 0?void 0:h.map(C=>C.width))!==null&&m!==void 0?m:[]).concat(e.width?[e.width]:[]).filter(Boolean)),((R=D.current)===null||R===void 0?void 0:R.naturalWidth)||0),g=B(Math.max(...((E=(p=e.srcSet)===null||p===void 0?void 0:p.map(C=>C.height))!==null&&E!==void 0?E:[]).concat(e.height?[e.height]:[]).filter(Boolean)),((u=D.current)===null||u===void 0?void 0:u.naturalHeight)||0),L=v&&g?{maxWidth:`min(${v}px, 100%)`,maxHeight:`min(${g}px, 100%)`}:{maxWidth:"100%",maxHeight:"100%"},M=(N=e.srcSet)===null||N===void 0?void 0:N.slice().sort((C,re)=>C.width-re.width).map(C=>`${C.src} ${C.width}w`).join(", "),W=()=>r&&!H&&e.width&&e.height?r.height/e.height*e.width:Number.MAX_VALUE,J=M&&r&&it()?`${Math.round(Math.min(W(),r.width))}px`:void 0,{style:se,className:ye,...Z}=(typeof a=="function"?a(e):a)||{};return n.createElement(n.Fragment,null,n.createElement("img",{ref:y,onLoad:_,onError:V,onClick:i,draggable:!1,className:z(P(tt()),H&&P(tt("cover")),S!==Ee&&P(tt("loading")),ye),style:{...L,...f,...se},...Z,alt:(I=e.alt)!==null&&I!==void 0?I:"",sizes:J,srcSet:M,src:e.src}),S!==Ee&&n.createElement("div",{className:P(et(It))},S===fe&&(o?.iconLoading?o.iconLoading():n.createElement(oo,{className:z(P(Pe),P(et(fe)))})),S===Re&&(o?.iconError?o.iconError():n.createElement(ro,{className:z(P(Pe),P(et(Re)))}))))}var lo=n.forwardRef(function({className:t,children:o,onFocus:r,onBlur:c,...a},i){let s=n.useRef(null),[d,f]=n.useState(!1),{trackFocusWithin:h}=Zt(),m=A(()=>{if(s.current){let R=window.getComputedStyle(s.current).direction==="rtl";R!==d&&f(R)}});return n.useEffect(m),n.createElement(Bn,{nodeRef:s},n.createElement(Qn,{isRTL:d},n.createElement("div",{ref:ct(i,s),className:z(P("root"),t),...h(r,c),...a},o)))}),k;(function(e){e[e.NONE=0]="NONE",e[e.SWIPE=1]="SWIPE",e[e.PULL=2]="PULL",e[e.ANIMATION=3]="ANIMATION"})(k||(k={}));function uo(e,t,o,r,c){n.useEffect(()=>c?()=>{}:Kt(e(Be,t),e(Xe,o),e(Ye,r),e(ze,r),e(je,r)),[e,t,o,r,c])}var K;(function(e){e[e.NONE=0]="NONE",e[e.SWIPE=1]="SWIPE",e[e.PULL=2]="PULL"})(K||(K={}));var nt=30;function fo({disableSwipeNavigation:e,closeOnBackdropClick:t},o,r,c,a,i,s,d,f,h,m,R,p,E,u,N){let I=n.useRef(0),S=n.useRef([]),b=n.useRef(void 0),w=n.useRef(0),T=n.useRef(K.NONE),D=n.useCallback(v=>{b.current===v.pointerId&&(b.current=void 0,T.current=K.NONE);let g=S.current;g.splice(0,g.length,...g.filter(L=>L.pointerId!==v.pointerId))},[]),O=n.useCallback(v=>{D(v),v.persist(),S.current.push(v)},[D]),y=n.useCallback(v=>S.current.find(({pointerId:g})=>v.pointerId===g),[]),_=A(v=>{O(v)}),V=(v,g)=>m&&v>g||h&&v<-g,H=A(v=>{let g=y(v);if(g)if(b.current===v.pointerId){let L=Date.now()-w.current,M=I.current;T.current===K.SWIPE?Math.abs(M)>.3*c||Math.abs(M)>5&&L<a?d(M,L):f(M):T.current===K.PULL&&(V(M,2*nt)?E(M,L):u(M)),I.current=0,T.current=K.NONE}else{let{target:L}=v;t&&L instanceof HTMLElement&&L===g.target&&(L.classList.contains(P(Ce))||L.classList.contains(P(Pt)))&&N()}D(v)}),B=A(v=>{let g=y(v);if(g){let L=b.current===v.pointerId;if(v.buttons===0){L&&I.current!==0?H(v):D(g);return}let M=v.clientX-g.clientX,W=v.clientY-g.clientY;if(b.current===void 0){let J=se=>{O(v),b.current=v.pointerId,w.current=Date.now(),T.current=se};Math.abs(M)>Math.abs(W)&&Math.abs(M)>nt&&r(M)?e||(J(K.SWIPE),i()):Math.abs(W)>Math.abs(M)&&V(W,nt)&&(J(K.PULL),R())}else L&&(T.current===K.SWIPE?(I.current=M,s(M)):T.current===K.PULL&&(I.current=W,p(W)))}});uo(o,_,B,H)}function Ro({preventDefaultWheelX:e,preventDefaultWheelY:t}){let o=n.useRef(null),r=A(c=>{let a=Math.abs(c.deltaX)>Math.abs(c.deltaY);(a&&e||!a&&t||c.ctrlKey)&&c.preventDefault()});return n.useCallback(c=>{var a;c?c.addEventListener("wheel",r,{passive:!1}):(a=o.current)===null||a===void 0||a.removeEventListener("wheel",r),o.current=c},[r])}function Eo(e,t,o,r,c,a,i,s,d){let f=n.useRef(0),h=n.useRef(0),m=n.useRef(void 0),R=n.useRef(void 0),p=n.useRef(0),E=n.useRef(void 0),u=n.useRef(0),{setTimeout:N,clearTimeout:I}=we(),S=n.useCallback(()=>{m.current&&(I(m.current),m.current=void 0)},[I]),b=n.useCallback(()=>{R.current&&(I(R.current),R.current=void 0)},[I]),w=A(()=>{e!==k.SWIPE&&(f.current=0,u.current=0,S(),b())});n.useEffect(w,[e,w]);let T=A(O=>{R.current=void 0,f.current===O&&d(f.current)}),D=A(O=>{if(O.ctrlKey||Math.abs(O.deltaY)>Math.abs(O.deltaX))return;let y=_=>{p.current=_,I(E.current),E.current=_>0?N(()=>{p.current=0,E.current=void 0},300):void 0};if(e===k.NONE){if(Math.abs(O.deltaX)<=1.2*Math.abs(p.current)){y(O.deltaX);return}if(!o(-O.deltaX))return;if(h.current+=O.deltaX,S(),Math.abs(h.current)>30)h.current=0,y(0),u.current=Date.now(),a();else{let _=h.current;m.current=N(()=>{m.current=void 0,_===h.current&&(h.current=0)},c)}}else if(e===k.SWIPE){let _=f.current-O.deltaX;if(_=Math.min(Math.abs(_),r)*Math.sign(_),f.current=_,i(_),b(),Math.abs(_)>.2*r){y(O.deltaX),s(_,Date.now()-u.current);return}R.current=N(()=>T(_),2*c)}else y(O.deltaX)});n.useEffect(()=>t(qe,D),[t,D])}var Dt=at("container"),ln=n.createContext(null),_e=j("useController","ControllerContext",ln);function po({children:e,...t}){var o;let{carousel:r,animation:c,controller:a,on:i,styles:s,render:d}=t,{closeOnPullUp:f,closeOnPullDown:h,preventDefaultWheelX:m,preventDefaultWheelY:R}=a,[p,E]=n.useState(),u=be(),N=zn(),[I,S]=n.useState(k.NONE),b=n.useRef(0),w=n.useRef(0),T=n.useRef(1),{registerSensors:D,subscribeSensors:O}=io(),{subscribe:y,publish:_}=xe(),V=Se(),H=Se(),B=Se(),{containerRef:v,setContainerRef:g,containerRect:L}=sn(),M=ct(Ro({preventDefaultWheelX:m,preventDefaultWheelY:R}),g),W=n.useRef(null),J=ct(W,void 0),{getOwnerDocument:se}=lt(),ye=ut(),Z=l=>(ye?-1:1)*(typeof l=="number"?l:1),C=A(()=>{var l;return(l=v.current)===null||l===void 0?void 0:l.focus()}),re=A(()=>t),dt=A(()=>u),ve=n.useCallback(l=>_(q,l),[_]),Le=n.useCallback(l=>_(Q,l),[_]),ce=n.useCallback(()=>_(ee),[_]),Me=l=>!(r.finite&&(Z(l)>0&&u.currentIndex===0||Z(l)<0&&u.currentIndex===u.slides.length-1)),ft=l=>{var x;b.current=l,(x=v.current)===null||x===void 0||x.style.setProperty(F("swipe_offset"),`${Math.round(l)}px`)},De=l=>{var x,$;w.current=l,T.current=(()=>{let ue=h&&l>0?l:f&&l<0?-l:0;return Math.min(Math.max(Dn(1-ue/60*(1-.5),2),.5),1)})(),(x=v.current)===null||x===void 0||x.style.setProperty(F("pull_offset"),`${Math.round(l)}px`),($=v.current)===null||$===void 0||$.style.setProperty(F("pull_opacity"),`${T.current}`)},{prepareAnimation:fn}=At(W,(l,x,$)=>{if(W.current&&L)return{keyframes:[{transform:`translate(0, ${l.rect.y-x.y+$.y}px)`,opacity:l.opacity},{transform:"translate(0, 0)",opacity:1}],duration:l.duration,easing:c.easing.fade}}),Rt=(l,x)=>{if(f||h){De(l);let $=0;W.current&&($=c.fade*(x?2:1),fn({rect:W.current.getBoundingClientRect(),opacity:T.current,duration:$})),B(()=>{De(0),S(k.NONE)},$),S(k.ANIMATION),x||ce()}},{prepareAnimation:Rn,isAnimationPlaying:En}=At(W,(l,x,$)=>{var X;if(W.current&&L&&(!((X=u.animation)===null||X===void 0)&&X.duration)){let G=Oe(r.spacing),ue=(G.percent?G.percent*L.width/100:G.pixel)||0;return{keyframes:[{transform:`translate(${Z(u.globalIndex-l.index)*(L.width+ue)+l.rect.x-x.x+$.x}px, 0)`},{transform:"translate(0, 0)"}],duration:u.animation.duration,easing:u.animation.easing}}}),le=A(l=>{var x,$;let X=l.offset||0,G=X?c.swipe:(x=c.navigation)!==null&&x!==void 0?x:c.swipe,ue=!X&&!En()?c.easing.navigation:c.easing.swipe,{direction:ge}=l,Ne=($=l.count)!==null&&$!==void 0?$:1,Ue=k.ANIMATION,Y=G*Ne;if(!ge){let de=L?.width,mt=l.duration||0,ke=de?G/de*Math.abs(X):G;Ne!==0?(mt<ke?Y=Y/ke*Math.max(mt,ke/5):de&&(Y=G/de*(de-Math.abs(X))),ge=Z(X)>0?q:Q):Y=G/2}let We=0;ge===q?Me(Z(1))?We=-Ne:(Ue=k.NONE,Y=G):ge===Q&&(Me(Z(-1))?We=Ne:(Ue=k.NONE,Y=G)),Y=Math.round(Y),H(()=>{ft(0),S(k.NONE)},Y),W.current&&Rn({rect:W.current.getBoundingClientRect(),index:u.globalIndex}),S(Ue),_(Ke,{type:"swipe",increment:We,duration:Y,easing:ue})});n.useEffect(()=>{var l,x;!((l=u.animation)===null||l===void 0)&&l.increment&&(!((x=u.animation)===null||x===void 0)&&x.duration)&&V(()=>N({type:"swipe",increment:0}),u.animation.duration)},[u.animation,N,V]);let Et=[O,Me,L?.width||0,c.swipe,()=>S(k.SWIPE),l=>ft(l),(l,x)=>le({offset:l,duration:x,count:1}),l=>le({offset:l,count:0})],pn=[()=>{h&&S(k.PULL)},l=>De(l),l=>Rt(l),l=>Rt(l,!0)];fo(a,...Et,f,h,...pn,ce),Eo(I,...Et);let pt=A(()=>{a.focus&&se().querySelector(`.${P(Ie)} .${P(Dt())}`)&&C()});n.useEffect(pt,[pt]);let ht=A(()=>{var l;(l=i.view)===null||l===void 0||l.call(i,{index:u.currentIndex})});n.useEffect(ht,[u.globalIndex,ht]),n.useEffect(()=>Kt(y(q,l=>le({direction:q,...l})),y(Q,l=>le({direction:Q,...l})),y(Ke,l=>N(l))),[y,le,N]);let hn=n.useMemo(()=>({prev:ve,next:Le,close:ce,focus:C,slideRect:L?Wn(L,r.padding):{width:0,height:0},containerRect:L||{width:0,height:0},subscribeSensors:O,containerRef:v,setCarouselRef:J,toolbarWidth:p,setToolbarWidth:E}),[ve,Le,ce,C,O,L,v,J,p,E,r.padding]);return n.useImperativeHandle(a.ref,()=>({prev:ve,next:Le,close:ce,focus:C,getLightboxProps:re,getLightboxState:dt}),[ve,Le,ce,C,re,dt]),n.createElement("div",{ref:M,className:z(P(Dt()),P(Ge)),style:{...I===k.SWIPE?{[F("swipe_offset")]:`${Math.round(b.current)}px`}:null,...I===k.PULL?{[F("pull_offset")]:`${Math.round(w.current)}px`,[F("pull_opacity")]:`${T.current}`}:null,...a.touchAction!=="none"?{[F("controller_touch_action")]:a.touchAction}:null,...s.container},tabIndex:-1,...D},L&&n.createElement(ln.Provider,{value:hn},e,(o=d.controls)===null||o===void 0?void 0:o.call(d)))}var ho=oe($e,po);function te(e){return pe(Ve,e)}function Ut(e){return pe(Ce,e)}function mo({slide:e,offset:t}){let o=n.useRef(null),{currentIndex:r,slides:c}=be(),{slideRect:a,focus:i}=_e(),{render:s,carousel:{imageFit:d,imageProps:f},on:{click:h},styles:{slide:m},labels:R}=he(),{getOwnerDocument:p}=lt(),E=t!==0;n.useEffect(()=>{var N;E&&(!((N=o.current)===null||N===void 0)&&N.contains(p().activeElement))&&i()},[E,i,p]);let u=()=>{var N,I,S,b;let w=(N=s.slide)===null||N===void 0?void 0:N.call(s,{slide:e,offset:t,rect:a});return!w&&Bt(e)&&(w=n.createElement(so,{slide:e,offset:t,render:s,rect:a,imageFit:d,imageProps:f,onClick:E?void 0:()=>h?.({index:r})})),w?n.createElement(n.Fragment,null,(I=s.slideHeader)===null||I===void 0?void 0:I.call(s,{slide:e}),((S=s.slideContainer)!==null&&S!==void 0?S:(({children:T})=>T))({slide:e,children:w}),(b=s.slideFooter)===null||b===void 0?void 0:b.call(s,{slide:e})):null};return n.createElement("div",{ref:o,className:z(P(Ut()),!E&&P(Ut("current")),P(Ge)),...Fn(E),style:m,role:"group","aria-roledescription":ne(R,"Slide"),"aria-label":Mn(R,c,r+t)},u())}function _o(){let e=he().styles.slide;return n.createElement("div",{className:P(Ce),style:e})}function vo({carousel:e,labels:t}){let{slides:o,currentIndex:r,globalIndex:c}=be(),{setCarouselRef:a}=_e(),{autoPlaying:i,focusWithin:s}=Zt(),d=Oe(e.spacing),f=Oe(e.padding),h=Vn(e,o,1),m=[];if(Xt(o))for(let R=r-h;R<=r+h;R+=1){let p=Yt(o,R),E=c-r+R,u=e.finite&&(R<0||R>o.length-1);m.push(u?{key:E}:{key:[`${E}`,kn(p)].filter(Boolean).join("|"),offset:R-r,slide:p})}return n.createElement("div",{ref:a,className:z(P(te()),m.length>0&&P(te("with_slides"))),style:{[`${F(te("slides_count"))}`]:m.length,[`${F(te("spacing_px"))}`]:d.pixel||0,[`${F(te("spacing_percent"))}`]:d.percent||0,[`${F(te("padding_px"))}`]:f.pixel||0,[`${F(te("padding_percent"))}`]:f.percent||0},role:"region","aria-live":i&&!s?"off":"polite","aria-roledescription":ne(t,"Carousel"),"aria-label":ne(t,"Photo gallery")},m.map(({key:R,slide:p,offset:E})=>p?n.createElement(mo,{key:R,slide:p,offset:E}):n.createElement(_o,{key:R})))}var Lo=oe(Ve,vo);function un(){let{carousel:e}=he(),{slides:t,currentIndex:o}=be(),r=t.length===0||e.finite&&o===0,c=t.length===0||e.finite&&o===t.length-1;return{prevDisabled:r,nextDisabled:c}}function go(e){var t;let o=ut(),{publish:r}=xe(),{animation:c,controller:a}=he(),{prevDisabled:i,nextDisabled:s}=un(),d=((t=c.navigation)!==null&&t!==void 0?t:c.swipe)/2,f=Mt(()=>r(q),d),h=Mt(()=>r(Q),d),m=A(R=>{switch(R.key){case Ot:if(!a.closeOnEscape)return;r(ee);break;case Tt:(o?s:i)||(o?h:f)();break;case xt:(o?i:s)||(o?f:h)();break;default:return}R.stopPropagation()});n.useEffect(()=>e(Ze,m),[e,m])}function Wt({label:e,icon:t,renderIcon:o,action:r,onClick:c,disabled:a,style:i}){return n.createElement(rn,{label:e,icon:t,renderIcon:o,className:P(`navigation_${r}`),disabled:a,onClick:c,style:i,...ao(_e().focus,a)})}function No({render:{buttonPrev:e,buttonNext:t,iconPrev:o,iconNext:r},styles:c}){let{prev:a,next:i,subscribeSensors:s}=_e(),{prevDisabled:d,nextDisabled:f}=un();return go(s),n.createElement(n.Fragment,null,e?e():n.createElement(Wt,{label:"Previous",action:q,icon:to,renderIcon:o,style:c.navigationPrev,disabled:d,onClick:a}),t?t():n.createElement(Wt,{label:"Next",action:Q,icon:no,renderIcon:r,style:c.navigationNext,disabled:f,onClick:i}))}var Io=oe(vt,No),kt=P(Ct),Co=P(He);function Po(e){return"style"in e}function Vt(e,t,o){let r=window.getComputedStyle(e),c=o?"padding-left":"padding-right",a=o?r.paddingLeft:r.paddingRight,i=e.style.getPropertyValue(c);return e.style.setProperty(c,`${(Te(a)||0)+t}px`),()=>{i?e.style.setProperty(c,i):e.style.removeProperty(c)}}function So({noScroll:{disabled:e},children:t}){let o=ut(),{getOwnerDocument:r,getOwnerWindow:c}=lt();return n.useEffect(()=>{if(e)return()=>{};let a=[],i=c(),{body:s,documentElement:d}=r(),f=Math.round(i.innerWidth-d.clientWidth);if(f>0){a.push(Vt(s,f,o));let h=s.getElementsByTagName("*");for(let m=0;m<h.length;m+=1){let R=h[m];Po(R)&&i.getComputedStyle(R).getPropertyValue("position")==="fixed"&&!R.classList.contains(Co)&&a.push(Vt(R,f,o))}}return s.classList.add(kt),()=>{s.classList.remove(kt),a.forEach(h=>h())}},[o,e,r,c]),n.createElement(n.Fragment,null,t)}var Oo=oe(Lt,So);function $t(e){return pe(Ie,e)}function Ft(e,t,o){let r=e.getAttribute(t);return e.setAttribute(t,o),()=>{r?e.setAttribute(t,r):e.removeAttribute(t)}}function To({portal:{root:e,container:{className:t,style:o,...r}={}},animation:c,styles:a,className:i,on:s,close:d,labels:f,children:h}){let[m,R]=n.useState(!1),[p,E]=n.useState(!1),u=n.useRef([]),N=n.useRef(null),{setTimeout:I}=we(),{subscribe:S}=xe(),w=an()?0:c.fade;n.useEffect(()=>(R(!0),()=>{R(!1),E(!1)}),[]);let T=A(()=>{u.current.forEach(_=>_()),u.current=[]}),D=A(()=>{var _;E(!1),T(),(_=s.exiting)===null||_===void 0||_.call(s),I(()=>{var V;(V=s.exited)===null||V===void 0||V.call(s),d()},w)});n.useEffect(()=>S(ee,D),[S,D]);let O=A(_=>{var V,H,B;Gn(_),E(!0),(V=s.entering)===null||V===void 0||V.call(s);let v=(B=(H=_.parentNode)===null||H===void 0?void 0:H.children)!==null&&B!==void 0?B:[];for(let g=0;g<v.length;g+=1){let L=v[g];["TEMPLATE","SCRIPT","STYLE"].indexOf(L.tagName)===-1&&L!==_&&(u.current.push(Ft(L,"inert","")),u.current.push(Ft(L,"aria-hidden","true")))}u.current.push(()=>{var g,L;(L=(g=N.current)===null||g===void 0?void 0:g.focus)===null||L===void 0||L.call(g)}),I(()=>{var g;(g=s.entered)===null||g===void 0||g.call(s)},w)}),y=n.useCallback(_=>{_?O(_):T()},[O,T]);return m?(0,Gt.createPortal)(n.createElement(lo,{ref:y,className:z(i,t,P($t()),P(He),p&&P($t("open"))),"aria-modal":!0,role:"dialog","aria-label":ne(f,"Lightbox"),style:{...c.fade!==rt.animation.fade?{[F("fade_animation_duration")]:`${w}ms`}:null,...c.easing.fade!==rt.animation.easing.fade?{[F("fade_animation_timing_function")]:c.easing.fade}:null,...a.root,...o},onFocus:_=>{N.current||(N.current=_.relatedTarget)},...r},h),(typeof e=="function"?e():e)||document.body):null}var xo=oe(Ie,To);function bo({children:e}){return n.createElement(n.Fragment,null,e)}var wo=oe(gt,bo);function Ao(e){return pe(Fe,e)}function yo({toolbar:{buttons:e},render:{buttonClose:t,iconClose:o},styles:r}){let{close:c,setToolbarWidth:a}=_e(),{setContainerRef:i,containerRect:s}=sn();Ae(()=>{a(s?.width)},[a,s?.width]);let d=()=>t?t():n.createElement(rn,{key:ee,label:"Close",icon:eo,renderIcon:o,onClick:c});return n.createElement("div",{ref:i,style:r.toolbar,className:P(Ao())},e?.map(f=>f===ee?d():f))}var Mo=oe(Fe,yo);function dn(e,t){var o;return n.createElement(e.module.component,{key:e.module.name,...t},(o=e.children)===null||o===void 0?void 0:o.map(r=>dn(r,t)))}function Do(e,t={}){let{easing:o,...r}=e,{easing:c,...a}=t;return{easing:{...o,...c},...r,...a}}function Ho({carousel:e,animation:t,render:o,toolbar:r,controller:c,noScroll:a,on:i,plugins:s,slides:d,index:f,...h}){let{animation:m,carousel:R,render:p,toolbar:E,controller:u,noScroll:N,on:I,slides:S,index:b,plugins:w,...T}=rt,{config:D,augmentation:O}=Hn([U(xo,[U(Oo,[U(ho,[U(Lo),U(Mo),U(Io)])])])],s||w),y=O({animation:Do(m,t),carousel:{...R,...e},render:{...p,...o},toolbar:{...E,...r},controller:{...u,...c},noScroll:{...N,...a},on:{...I,...i},...T,...h});return y.open?n.createElement(Yn,{...y},n.createElement(Zn,{slides:d||S,index:Te(f||b)},n.createElement(Jn,null,n.createElement(Xn,null,n.createElement(Kn,null,dn(U(wo,D),y)))))):null}export{Ve as a,$e as b,vt as c,Lt as d,Ie as e,gt as f,Fe as g,vn as h,Ln as i,gn as j,Nn as k,In as l,Cn as m,Pn as n,Sn as o,On as p,fe as q,Nt as r,Re as s,Ee as t,It as u,ae as v,Tn as w,xn as x,bn as y,wn as z,An as A,Ge as B,Ct as C,He as D,Ce as E,Pt as F,yn as G,q as H,Q as I,Ke as J,ee as K,Be as L,Xe as M,Ye as N,ze as O,je as P,Ze as Q,St as R,qe as S,Ot as T,Tt as U,xt as V,bt as W,Pe as X,Qe as Y,Je as Z,wt as _,z as $,P as aa,F as ba,pe as ca,at as da,ne as ea,ko as fa,Mn as ga,Kt as ha,j as ia,it as ja,Dn as ka,Bt as la,Un as ma,Te as na,Oe as oa,Wn as pa,Vo as qa,st as ra,Xt as sa,Yt as ta,ot as ua,kn as va,$o as wa,Fo as xa,Vn as ya,Fn as za,Gn as Aa,rt as Ba,oe as Ca,U as Da,Hn as Ea,jt as Fa,Zt as Ga,Kn as Ha,qt as Ia,lt as Ja,Bn as Ka,Qt as La,xe as Ma,Xn as Na,Jt as Oa,he as Pa,Yn as Qa,en as Ra,be as Sa,tn as Ta,zn as Ua,Zn as Va,nn as Wa,qn as Xa,Qn as Ya,on as Za,we as _a,Jn as $a,rn as ab,me as bb,Go as cb,eo as db,to as eb,no as fb,oo as gb,ro as hb,Ae as ib,an as jb,At as kb,sn as lb,Se as mb,A as nb,yt as ob,ct as pb,ao as qb,ut as rb,io as sb,Mt as tb,so as ub,lo as vb,k as wb,uo as xb,fo as yb,Ro as zb,Eo as Ab,ln as Bb,_e as Cb,po as Db,ho as Eb,vo as Fb,Lo as Gb,un as Hb,go as Ib,Wt as Jb,No as Kb,Io as Lb,So as Mb,Oo as Nb,To as Ob,xo as Pb,bo as Qb,wo as Rb,yo as Sb,Mo as Tb,Ho as Ub};
|
sha256/bdb559bd0dec93fd70e9c1ed515bbd483ff4cadc8ce38df946983adca29c604e
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// holo-orb.js β THE canonical living Q orb (shared by the standalone Q chat and the messenger; the messenger's
|
| 2 |
+
// holo-q-orb-live.mjs re-exports this file). mountOrb(canvas, opts?) β { stop, fallback, mode, ... } β the API is
|
| 3 |
+
// a superset of the original 54-line WebGL orb (opts optional, {stop,fallback} preserved), so existing callers
|
| 4 |
+
// are unaffected while every surface gains the enhanced renderer. Original preserved as holo-orb.js.pre-converge.bak.
|
| 5 |
+
//
|
| 6 |
+
// PRIMARY: a NATIVE-WebGPU raymarched volume rendered on a dedicated Web Worker via OffscreenCanvas. The render
|
| 7 |
+
// loop lives on the worker, PHYSICALLY off the main thread, so the orb stays glass-smooth and NEVER freezes even
|
| 8 |
+
// while the host's main thread is busy (React, Q inference, message churn). It binds the real GPU adapter
|
| 9 |
+
// (powerPreference:"high-performance", no fallback) β 100% native WebGPU, and renders at native DPR Γ SSAA for a
|
| 10 |
+
// crisp, hyper-real look. Fully self-contained: the worker is spawned from a Blob URL with inline WGSL β no deps,
|
| 11 |
+
// no import map, no extra files to serve, so it works in every environment (dev SPA and the real app alike).
|
| 12 |
+
//
|
| 13 |
+
// FALLBACK: the original self-contained WebGL2 wireframe icosphere (kept verbatim below), then a CSS/SVG orb.
|
| 14 |
+
// The gate is fail-closed and probe-before-transfer: the worker confirms a GPU adapter BEFORE the canvas is
|
| 15 |
+
// transferred, so a probe failure leaves the canvas reusable for the WebGL2 floor.
|
| 16 |
+
//
|
| 17 |
+
// mountOrb(canvas) β { stop(), fallback:boolean, mode }
|
| 18 |
+
|
| 19 |
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 20 |
+
// WGSL β fullscreen-triangle vertex + a raymarched, noise-displaced SDF sphere with the OS brand spectrum
|
| 21 |
+
// (OKLAB-interpolated), a triangular lattice shell, thin-film iridescence, an inner living nebula, ACES filmic
|
| 22 |
+
// tonemap and temporal dither. Idle-animated (breath + spin + shimmer) so it's alive at rest with ZERO main-
|
| 23 |
+
// thread involvement. TERM-IDENTICAL to the native OS orb (usr/lib/holo/voice/holo-voice-orb-gpu.mjs): same
|
| 24 |
+
// march (72 steps / 4 octaves / radius 0.82 / freq 1.7 / glow 0.012), same full signal uniforms (level + bands
|
| 25 |
+
// + onset + energy + warm/dim/gold), same spin/swell/iridescence/nebula formulas β so the messenger's corner
|
| 26 |
+
// orb and the CEF home-tab orb are the SAME animation, pixel for pixel (minus the OS-only morph-form library).
|
| 27 |
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 28 |
+
const WGSL = `
|
| 29 |
+
struct U {
|
| 30 |
+
res: vec2f, time: f32, level: f32,
|
| 31 |
+
bass: f32, mid: f32, treble: f32, onset: f32,
|
| 32 |
+
energy: f32, warm: f32, dim: f32, gold: f32,
|
| 33 |
+
};
|
| 34 |
+
@group(0) @binding(0) var<uniform> u: U;
|
| 35 |
+
|
| 36 |
+
const STOPS = array<vec3f, 8>(
|
| 37 |
+
vec3f(1.0, 0.231, 0.42), vec3f(1.0, 0.62, 0.173), vec3f(1.0, 0.886, 0.29), vec3f(0.275, 0.878, 0.541),
|
| 38 |
+
vec3f(0.169, 0.831, 1.0), vec3f(0.357, 0.549, 1.0), vec3f(0.78, 0.482, 1.0), vec3f(1.0, 0.231, 0.42));
|
| 39 |
+
|
| 40 |
+
@vertex fn vs(@builtin(vertex_index) vi: u32) -> @builtin(position) vec4f {
|
| 41 |
+
var p = array<vec2f, 3>(vec2f(-1.0, -1.0), vec2f(3.0, -1.0), vec2f(-1.0, 3.0));
|
| 42 |
+
return vec4f(p[vi], 0.0, 1.0);
|
| 43 |
+
}
|
| 44 |
+
fn hash(p3i: vec3f) -> f32 { var p3 = fract(p3i * 0.1031); p3 = p3 + dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); }
|
| 45 |
+
fn vnoise(x: vec3f) -> f32 {
|
| 46 |
+
let i = floor(x); let f = fract(x); let w = f * f * (3.0 - 2.0 * f);
|
| 47 |
+
let n000 = hash(i + vec3f(0.0,0.0,0.0)); let n100 = hash(i + vec3f(1.0,0.0,0.0));
|
| 48 |
+
let n010 = hash(i + vec3f(0.0,1.0,0.0)); let n110 = hash(i + vec3f(1.0,1.0,0.0));
|
| 49 |
+
let n001 = hash(i + vec3f(0.0,0.0,1.0)); let n101 = hash(i + vec3f(1.0,0.0,1.0));
|
| 50 |
+
let n011 = hash(i + vec3f(0.0,1.0,1.0)); let n111 = hash(i + vec3f(1.0,1.0,1.0));
|
| 51 |
+
let x00 = mix(n000,n100,w.x); let x10 = mix(n010,n110,w.x); let x01 = mix(n001,n101,w.x); let x11 = mix(n011,n111,w.x);
|
| 52 |
+
return mix(mix(x00,x10,w.y), mix(x01,x11,w.y), w.z) * 2.0 - 1.0;
|
| 53 |
+
}
|
| 54 |
+
fn fbm(p0: vec3f) -> f32 { var p = p0; var a = 0.5; var s = 0.0; for (var i = 0; i < 4; i = i + 1) { s = s + a * vnoise(p); p = p * 1.9; a = a * 0.5; } return s; }
|
| 55 |
+
fn srgb2lin(c: vec3f) -> vec3f { return select(c/12.92, pow((c+0.055)/1.055, vec3f(2.4)), c > vec3f(0.04045)); }
|
| 56 |
+
fn lin2srgb(c: vec3f) -> vec3f { let x = max(c, vec3f(0.0)); return select(x*12.92, 1.055*pow(x, vec3f(1.0/2.4))-0.055, x > vec3f(0.0031308)); }
|
| 57 |
+
fn lin2oklab(c: vec3f) -> vec3f {
|
| 58 |
+
let l = 0.4122214708*c.r + 0.5363325363*c.g + 0.0514459929*c.b;
|
| 59 |
+
let m = 0.2119034982*c.r + 0.6806995451*c.g + 0.1073969566*c.b;
|
| 60 |
+
let s = 0.0883024619*c.r + 0.2817188376*c.g + 0.6299787005*c.b;
|
| 61 |
+
let l_ = pow(max(l,0.0),1.0/3.0); let m_ = pow(max(m,0.0),1.0/3.0); let s_ = pow(max(s,0.0),1.0/3.0);
|
| 62 |
+
return vec3f(0.2104542553*l_+0.7936177850*m_-0.0040720468*s_, 1.9779984951*l_-2.4285922050*m_+0.4505937099*s_, 0.0259040371*l_+0.7827717662*m_-0.8086757660*s_);
|
| 63 |
+
}
|
| 64 |
+
fn oklab2srgb(c: vec3f) -> vec3f {
|
| 65 |
+
let l_ = c.x+0.3963377774*c.y+0.2158037573*c.z; let m_ = c.x-0.1055613458*c.y-0.0638541728*c.z; let s_ = c.x-0.0894841775*c.y-1.2914855480*c.z;
|
| 66 |
+
let l = l_*l_*l_; let m = m_*m_*m_; let s = s_*s_*s_;
|
| 67 |
+
let lin = vec3f(4.0767416621*l-3.3077115913*m+0.2309699292*s, -1.2684380046*l+2.6097574011*m-0.3413193965*s, -0.0041960863*l-0.7034186147*m+1.7076147010*s);
|
| 68 |
+
return lin2srgb(lin);
|
| 69 |
+
}
|
| 70 |
+
fn spec(t0: f32) -> vec3f { let t = fract(t0) * 7.0; let k = clamp(i32(floor(t)), 0, 6); let a = lin2oklab(srgb2lin(STOPS[k])); let b = lin2oklab(srgb2lin(STOPS[k+1])); return oklab2srgb(mix(a, b, fract(t))); }
|
| 71 |
+
fn sdf(p: vec3f) -> f32 {
|
| 72 |
+
let R = 0.82 + u.level * 0.05 + u.onset * 0.03 + sin(u.time * 0.6) * 0.012;
|
| 73 |
+
let warp = vec3f(u.time*0.05, u.time*0.06, u.time*0.07);
|
| 74 |
+
let disp = fbm(p * 1.7 + warp) * (0.07 + u.level * 0.20 + u.mid * 0.14 + u.bass * 0.10);
|
| 75 |
+
return length(p) - R - disp;
|
| 76 |
+
}
|
| 77 |
+
fn nrm(p: vec3f) -> vec3f { let e = vec2f(0.0012, 0.0); return normalize(vec3f(sdf(p+e.xyy)-sdf(p-e.xyy), sdf(p+e.yxy)-sdf(p-e.yxy), sdf(p+e.yyx)-sdf(p-e.yyx))); }
|
| 78 |
+
fn gline(x: f32) -> f32 { return smoothstep(0.42, 0.5, abs(fract(x) - 0.5)); }
|
| 79 |
+
fn ign(p: vec2f) -> f32 { return fract(52.9829189 * fract(dot(p, vec2f(0.06711056, 0.00583715)))); }
|
| 80 |
+
fn aces(x: vec3f) -> vec3f { let a=2.51; let b=0.03; let c=2.43; let d=0.59; let e=0.14; return clamp((x*(a*x+b))/(x*(c*x+d)+e), vec3f(0.0), vec3f(1.0)); }
|
| 81 |
+
|
| 82 |
+
@fragment fn fs(@builtin(position) fc: vec4f) -> @location(0) vec4f {
|
| 83 |
+
let uv = (fc.xy - 0.5 * u.res) / u.res.y;
|
| 84 |
+
let ro = vec3f(0.0, 0.0, 3.6);
|
| 85 |
+
let rd = normalize(vec3f(uv.x, -uv.y, -1.5));
|
| 86 |
+
let spin = u.time / 7.0 * (1.0 + u.level * 1.6 + u.treble * 1.4) * (0.4 + 0.6 * u.energy);
|
| 87 |
+
var t = 0.0; var glow = 0.0; var neb = 0.0; var hit = false; var hp = vec3f(0.0);
|
| 88 |
+
var omega = 1.2; var prevD = 1e9; var stepLen = 0.0;
|
| 89 |
+
for (var i = 0; i < 72; i = i + 1) {
|
| 90 |
+
let p = ro + rd * t; let d = sdf(p);
|
| 91 |
+
if (omega > 1.0 && (d + prevD) < stepLen) { t = t - stepLen; omega = 1.0; prevD = 1e9; continue; }
|
| 92 |
+
prevD = d;
|
| 93 |
+
glow = glow + 0.012 / (1.0 + d * d * 42.0);
|
| 94 |
+
if (d < 0.0) { neb = neb + (0.5 + 0.5 * fbm(p * 2.72 + vec3f(u.time * 0.09))) * 0.05; }
|
| 95 |
+
if (d < 0.0015) { hit = true; hp = p; break; }
|
| 96 |
+
stepLen = max(d * omega, 0.004); t = t + stepLen;
|
| 97 |
+
if (t > 6.0) { break; }
|
| 98 |
+
}
|
| 99 |
+
var col = vec3f(0.0); var alpha = 0.0;
|
| 100 |
+
if (hit) {
|
| 101 |
+
let n = nrm(hp);
|
| 102 |
+
let lon = atan2(n.x, n.z) / 6.2831853 + 0.5;
|
| 103 |
+
let lat = acos(clamp(n.y, -1.0, 1.0)) / 3.14159265;
|
| 104 |
+
let hue = lon + spin + 0.18 * n.y;
|
| 105 |
+
let base = spec(hue);
|
| 106 |
+
let fres = pow(1.0 - max(dot(n, -rd), 0.0), 2.5);
|
| 107 |
+
let ld = normalize(vec3f(-0.4, 0.7, 0.5));
|
| 108 |
+
let diff = 0.5 + 0.5 * max(dot(n, ld), 0.0);
|
| 109 |
+
let irid = spec(hue + fres * 0.30 + u.treble * 0.08);
|
| 110 |
+
let bodyHue = mix(base, irid, fres * 0.45);
|
| 111 |
+
let A = lon * 18.0; let B = lat * 11.0; let pf = sin(lat * 3.14159265);
|
| 112 |
+
let g = max(gline(B), max(gline(A + B * 0.5), gline(A - B * 0.5))) * pf;
|
| 113 |
+
let face = bodyHue * (0.28 + 0.30 * diff);
|
| 114 |
+
let dofs = 0.020 * (0.5 + fres);
|
| 115 |
+
let edgeRGB = vec3f(spec(hue - dofs).r, spec(hue).g, spec(hue + dofs).b);
|
| 116 |
+
let edge = (edgeRGB * 1.7 + vec3f(0.22, 0.22, 0.32)) * (0.7 + 0.6 * fres);
|
| 117 |
+
col = mix(face, edge, g) + bodyHue * fres * 0.55;
|
| 118 |
+
col = col * (0.9 + u.level * 0.45 + u.onset * 0.5);
|
| 119 |
+
alpha = max(g, 0.34 + 0.45 * fres);
|
| 120 |
+
}
|
| 121 |
+
let ncol = spec(spin + 0.55 + neb);
|
| 122 |
+
col = col + ncol * neb * (0.7 + u.level * 0.9 + u.bass * 0.8);
|
| 123 |
+
let gcol = spec(spin + 0.25);
|
| 124 |
+
col = col + gcol * glow * (0.6 + u.level * 1.0 + u.treble * 0.7);
|
| 125 |
+
alpha = max(alpha, clamp((glow + neb * 0.6) * 1.2, 0.0, 1.0));
|
| 126 |
+
if (u.gold > 0.0) { col = mix(col, vec3f(1.0, 0.78, 0.20) * (0.4 + 0.9 * length(col)), u.gold); }
|
| 127 |
+
col.r = col.r * (1.0 + u.warm * 0.10);
|
| 128 |
+
col.b = col.b * (1.0 - u.warm * 0.30);
|
| 129 |
+
col = col * (1.0 - u.dim * 0.4);
|
| 130 |
+
col = aces(col * 1.18);
|
| 131 |
+
col = col + (ign(fc.xy + u.time * 60.0) - 0.5) * (1.5 / 255.0);
|
| 132 |
+
col = clamp(col, vec3f(0.0), vec3f(1.0));
|
| 133 |
+
return vec4f(col * alpha, alpha);
|
| 134 |
+
}`;
|
| 135 |
+
|
| 136 |
+
// ββ the worker body (classic worker, spawned from a Blob URL). WGSL is injected as a JS string literal so the
|
| 137 |
+
// whole thing is self-contained β nothing extra is fetched, so it runs in any serve environment. ββ
|
| 138 |
+
const WORKER_BODY = [
|
| 139 |
+
"const WGSL = __WGSL__;",
|
| 140 |
+
"let dev=null, ctx=null, pipeline=null, bind=null, ubuf=null, uf=null, raf=0, running=false, dead=false, canvas=null;",
|
| 141 |
+
"let dpr=1, ssMax=1, scale=1, cssW=64, cssH=64;", // backing = css Γ dpr Γ scale; scale climbs to ssMax (SSAA) with headroom, drops under load β the native orb's ladder
|
| 142 |
+
"let mode=0, extLevel=-1, cur=0.0, gcur=0.0, dbg=false, fc=0, lastT=0, emaDt=0;", // mode: 0 idle Β· 1 listening Β· 2 thinking Β· 3 speaking. cur = eased base level; gcur = eased gold (mind-flare) wash; extLevel = live speech amplitude (0..1) or -1.
|
| 143 |
+
"const NOW=function(){return (typeof performance!=='undefined')?performance.now():Date.now();};",
|
| 144 |
+
"const RAF=(typeof requestAnimationFrame==='function')?requestAnimationFrame:function(f){return setTimeout(function(){f(NOW());},16);};",
|
| 145 |
+
"const CAF=(typeof cancelAnimationFrame==='function')?cancelAnimationFrame:clearTimeout;",
|
| 146 |
+
"function resize(){var s=dpr*scale;var w=Math.max(1,Math.round(cssW*s)),h=Math.max(1,Math.round(cssH*s)); if(canvas.width!==w||canvas.height!==h){canvas.width=w;canvas.height=h;}}",
|
| 147 |
+
// Q-state-reactive level, calibrated to the NATIVE orb's idle: at rest level eases to 0 (energy 1), so the
|
| 148 |
+
// idle animation is exactly the OS home-tab orb β breath sin(tΒ·0.6)Β·0.012, spin t/7, fbm skin 0.07. States
|
| 149 |
+
// modulate on top: listening = alert; thinking = livelier + the OS gold mind-flare wash; speaking = pulse to
|
| 150 |
+
// live amplitude (extLevel) or a synthetic speech cadence. cur/gcur ease so transitions read as intent.",
|
| 151 |
+
"function frame(){ if(!running||dead) return; var t=NOW()/1000; var base, osc, gold=0;",
|
| 152 |
+
" if(mode===2){ base=0.35; osc=0.10*Math.sin(t*3.4); gold=0.30+0.20*Math.sin(t*3.4); }",
|
| 153 |
+
" else if(mode===1){ base=0.22; osc=0.05*Math.sin(t*2.0); }",
|
| 154 |
+
" else if(mode===3){ base=0.32; osc=(extLevel>=0?0.0:0.30*Math.abs(Math.sin(t*6.5))); }",
|
| 155 |
+
" else { base=0.0; osc=0.0; }",
|
| 156 |
+
" var live=(extLevel>=0&&(mode===1||mode===3))?extLevel*0.6:0.0;", // REAL audio amplitude swells the orb (listening to you Β· speaking as Q)
|
| 157 |
+
" cur+=(base-cur)*0.06; gcur+=(gold-gcur)*0.08; var lvl=Math.max(0.0, cur+osc+live);",
|
| 158 |
+
" var now=NOW(); if(lastT){ emaDt=emaDt?emaDt*0.9+(now-lastT)*0.1:(now-lastT); } lastT=now;",
|
| 159 |
+
" if(((++fc)%24)===0&&emaDt>0){ var fps=1000/emaDt;", // frame-time adaptive resolution (the native ladder): drop fast under load, climb slow into SSAA headroom β sharp AND never laggy
|
| 160 |
+
" if(fps<50&&scale>0.5){ scale=Math.max(0.5,scale-0.25); resize(); }",
|
| 161 |
+
" else if(fps>58&&scale<ssMax){ scale=Math.min(ssMax,scale+0.25); resize(); } }",
|
| 162 |
+
" if(dbg&&(fc%15)===0){ try{ self.postMessage({t:'lvl', v:lvl, mode:mode}); }catch(e){} }",
|
| 163 |
+
" uf[0]=canvas.width; uf[1]=canvas.height; uf[2]=t; uf[3]=lvl;",
|
| 164 |
+
" uf[4]=0; uf[5]=0; uf[6]=0; uf[7]=0; uf[8]=1; uf[9]=0; uf[10]=0; uf[11]=gcur;", // bass/mid/treble/onset idle at 0 and energy at 1 β the native orb's values when no live meter feeds it
|
| 165 |
+
" dev.queue.writeBuffer(ubuf,0,uf); var view; try{ view=ctx.getCurrentTexture().createView(); }catch(e){ raf=RAF(frame); return; } var enc=dev.createCommandEncoder(); var pass=enc.beginRenderPass({colorAttachments:[{view:view,clearValue:{r:0,g:0,b:0,a:0},loadOp:'clear',storeOp:'store'}]}); pass.setPipeline(pipeline); pass.setBindGroup(0,bind); pass.draw(3); pass.end(); dev.queue.submit([enc.finish()]); raf=RAF(frame); }",
|
| 166 |
+
"self.onmessage=async function(e){ var m=e.data||{}; try{",
|
| 167 |
+
" if(m.t==='probe'){ try{ if(!navigator.gpu) throw new Error('no gpu'); var a=await navigator.gpu.requestAdapter({powerPreference:'high-performance'}); if(!a) throw new Error('no adapter'); var d=await a.requestDevice(); if(d.destroy) d.destroy(); self.postMessage({t:'probe-ok'}); }catch(err){ self.postMessage({t:'fail',err:'probe: '+String(err&&err.message||err)}); } return; }",
|
| 168 |
+
" if(m.t==='init'){ try{",
|
| 169 |
+
" canvas=m.canvas; dpr=m.dpr||1; ssMax=m.ss||1; scale=1; cssW=m.cssW||64; cssH=m.cssH||64; dbg=!!m.debug;",
|
| 170 |
+
" var a=await navigator.gpu.requestAdapter({powerPreference:'high-performance'}); if(!a) throw new Error('no adapter'); dev=await a.requestDevice(); if(dev.lost) dev.lost.then(function(){dead=true;});",
|
| 171 |
+
" ctx=canvas.getContext('webgpu'); if(!ctx) throw new Error('no webgpu ctx'); var fmt=navigator.gpu.getPreferredCanvasFormat(); ctx.configure({device:dev,format:fmt,alphaMode:'premultiplied'});",
|
| 172 |
+
" uf=new Float32Array(12); ubuf=dev.createBuffer({size:48,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});",
|
| 173 |
+
" dev.pushErrorScope('validation'); var mod=dev.createShaderModule({code:WGSL});",
|
| 174 |
+
" pipeline=dev.createRenderPipeline({layout:'auto',vertex:{module:mod,entryPoint:'vs'},fragment:{module:mod,entryPoint:'fs',targets:[{format:fmt,blend:{color:{srcFactor:'one',dstFactor:'one-minus-src-alpha'},alpha:{srcFactor:'one',dstFactor:'one-minus-src-alpha'}}}]},primitive:{topology:'triangle-list'}});",
|
| 175 |
+
" var perr=await dev.popErrorScope(); if(perr) throw new Error('wgsl: '+perr.message);",
|
| 176 |
+
" bind=dev.createBindGroup({layout:pipeline.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:ubuf}}]});",
|
| 177 |
+
" resize(); running=true; raf=RAF(frame); self.postMessage({t:'ready'});",
|
| 178 |
+
" }catch(err){ self.postMessage({t:'fail',err:String(err&&err.message||err)}); } return; }",
|
| 179 |
+
" if(!canvas) return;",
|
| 180 |
+
" if(m.t==='size'){ cssW=m.cssW||cssW; cssH=m.cssH||cssH; dpr=m.dpr||dpr; resize(); }",
|
| 181 |
+
" else if(m.t==='sig'){ mode=m.mode||0; extLevel=(typeof m.level==='number'?m.level:-1); }",
|
| 182 |
+
" else if(m.t==='pause'){ if(running){ running=false; if(raf){ CAF(raf); raf=0; } } }", // off-screen/backgrounded β halt the loop, KEEP the device (cheap resume)
|
| 183 |
+
" else if(m.t==='resume'){ if(!running && !dead && canvas){ running=true; raf=RAF(frame); } }",
|
| 184 |
+
" else if(m.t==='stop'){ running=false; if(raf){ CAF(raf); raf=0; } try{ if(dev&&dev.destroy) dev.destroy(); }catch(e){} }",
|
| 185 |
+
"}catch(err){ try{ self.postMessage({t:'fail',err:String(err&&err.message||err)}); }catch(e2){} } };",
|
| 186 |
+
].join("\n");
|
| 187 |
+
|
| 188 |
+
const WORKER_SRC = WORKER_BODY.replace("__WGSL__", JSON.stringify(WGSL));
|
| 189 |
+
|
| 190 |
+
// mount the WebGPU worker orb. Returns a handle (sync) that upgrades async; on any failure it falls back to the
|
| 191 |
+
// WebGL2 wireframe on the SAME canvas (probe-before-transfer keeps the canvas reusable). Returns null only when
|
| 192 |
+
// the platform can't do OffscreenCanvas/Worker/WebGPU at all β caller uses WebGL2 directly.
|
| 193 |
+
function mountGpuOrb(canvas, opts) {
|
| 194 |
+
opts = opts || {};
|
| 195 |
+
const ok = typeof navigator !== "undefined" && navigator.gpu &&
|
| 196 |
+
typeof OffscreenCanvas !== "undefined" && typeof Worker !== "undefined" &&
|
| 197 |
+
canvas && canvas.transferControlToOffscreen;
|
| 198 |
+
if (!ok) return null;
|
| 199 |
+
|
| 200 |
+
let worker = null, url = null, stopped = false, transferred = false, fellBack = null, timer = 0, ro = null, pendingSig = null, onQState = null;
|
| 201 |
+
const handle = { fallback: false, mode: "webgpu-worker",
|
| 202 |
+
pause() { // visibility budget: halt the render loop while unseen (keeps the device warm for an instant resume)
|
| 203 |
+
try { if (worker && !stopped) worker.postMessage({ t: "pause" }); } catch (e) {}
|
| 204 |
+
if (fellBack && fellBack.pause) { try { fellBack.pause(); } catch (e) {} }
|
| 205 |
+
},
|
| 206 |
+
resume() {
|
| 207 |
+
try { if (worker && !stopped) worker.postMessage({ t: "resume" }); } catch (e) {}
|
| 208 |
+
if (fellBack && fellBack.resume) { try { fellBack.resume(); } catch (e) {} }
|
| 209 |
+
},
|
| 210 |
+
stop() {
|
| 211 |
+
stopped = true; if (timer) { clearTimeout(timer); timer = 0; }
|
| 212 |
+
try { if (ro) ro.disconnect(); } catch (e) {}
|
| 213 |
+
try { if (typeof window !== "undefined" && onQState) window.removeEventListener("holo-q-state", onQState); } catch (e) {}
|
| 214 |
+
try { if (worker) { worker.postMessage({ t: "stop" }); worker.terminate(); } } catch (e) {}
|
| 215 |
+
try { if (url) URL.revokeObjectURL(url); } catch (e) {}
|
| 216 |
+
if (fellBack && fellBack.stop) { try { fellBack.stop(); } catch (e) {} }
|
| 217 |
+
} };
|
| 218 |
+
|
| 219 |
+
function toWebgl() {
|
| 220 |
+
if (timer) { clearTimeout(timer); timer = 0; }
|
| 221 |
+
try { if (worker) worker.terminate(); } catch (e) {}
|
| 222 |
+
if (stopped || transferred || fellBack) return; // transferred β canvas burned, can't reuse (rare, post-probe only)
|
| 223 |
+
fellBack = mountWebglOrb(canvas); // same untouched canvas β the proven WebGL2 wireframe
|
| 224 |
+
handle.mode = (fellBack && !fellBack.fallback) ? "webgl" : "none";
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
try { url = URL.createObjectURL(new Blob([WORKER_SRC], { type: "text/javascript" })); worker = new Worker(url); }
|
| 228 |
+
catch (e) { return mountWebglOrb(canvas); }
|
| 229 |
+
|
| 230 |
+
const dpr = () => Math.min((typeof window !== "undefined" && window.devicePixelRatio) || 1, 3); // full device DPR (cap 3) β a small corner orb is cheap, so every edge is razor-sharp
|
| 231 |
+
const cw = () => canvas.clientWidth || 64, ch = () => canvas.clientHeight || 64;
|
| 232 |
+
|
| 233 |
+
worker.onmessage = (e) => {
|
| 234 |
+
const m = e.data || {};
|
| 235 |
+
if (m.t === "probe-ok") {
|
| 236 |
+
if (stopped) return;
|
| 237 |
+
let off; try { off = canvas.transferControlToOffscreen(); transferred = true; }
|
| 238 |
+
catch (err) { toWebgl(); return; }
|
| 239 |
+
try { worker.postMessage({ t: "init", canvas: off, dpr: dpr(), ss: 2, cssW: cw(), cssH: ch(), debug: !!opts.debug }, [off]); } // ss = the SSAA ceiling the worker's ladder climbs to with fps headroom (starts at 1Γ β instant first paint)
|
| 240 |
+
catch (err) { toWebgl(); }
|
| 241 |
+
} else if (m.t === "ready") { if (timer) { clearTimeout(timer); timer = 0; } if (pendingSig) { forwardSig(pendingSig.mode, pendingSig.level); pendingSig = null; } } // painting on the worker
|
| 242 |
+
else if (m.t === "lvl") { handle.level = m.v; handle.stateMode = m.mode; if (typeof handle.onLevel === "function") { try { handle.onLevel(m.v, m.mode); } catch (e) {} } } // optional debug readback (opts.debug)
|
| 243 |
+
else if (m.t === "fail") { toWebgl(); }
|
| 244 |
+
};
|
| 245 |
+
worker.onerror = () => toWebgl();
|
| 246 |
+
timer = setTimeout(toWebgl, 4500);
|
| 247 |
+
try { worker.postMessage({ t: "probe" }); } catch (e) { toWebgl(); }
|
| 248 |
+
|
| 249 |
+
if (typeof ResizeObserver !== "undefined") {
|
| 250 |
+
ro = new ResizeObserver(() => { if (transferred && worker && !stopped) { try { worker.postMessage({ t: "size", cssW: cw(), cssH: ch(), dpr: dpr() }); } catch (e) {} } });
|
| 251 |
+
try { ro.observe(canvas); } catch (e) {}
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
// ββ Q-state reactivity: forward the global `holo-q-state` events to the worker (the messenger dispatches them
|
| 255 |
+
// when Q is thinking/listening/speaking), so the orb visibly REACTS instead of only idling. Buffered until the
|
| 256 |
+
// worker is live (pendingSig), and torn down with the orb (stop() removes the listener). ββ
|
| 257 |
+
const MODE_MAP = { idle: 0, listening: 1, thinking: 2, speaking: 3 };
|
| 258 |
+
function forwardSig(modeNum, level) {
|
| 259 |
+
if (worker && transferred && !stopped) { try { worker.postMessage({ t: "sig", mode: modeNum, level: level }); } catch (e) {} }
|
| 260 |
+
else pendingSig = { mode: modeNum, level: level };
|
| 261 |
+
}
|
| 262 |
+
handle.signal = function (s) { s = s || {}; forwardSig(MODE_MAP[s.mode] || 0, (typeof s.level === "number") ? s.level : -1); };
|
| 263 |
+
onQState = (e) => handle.signal((e && e.detail) || {});
|
| 264 |
+
if (typeof window !== "undefined") { try { window.addEventListener("holo-q-state", onQState); } catch (e) {} }
|
| 265 |
+
return handle;
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
// ββ VISIBILITY BUDGET (M5-L1) β the orb is a CONTINUOUS GPU raymarch; on a phone it must cost ~nothing when it
|
| 269 |
+
// can't be seen. The dominant case is the app/tab BACKGROUNDED β halt the loop on `visibilitychange`/document.hidden
|
| 270 |
+
// and resume on return. This is 100% reliable and self-correcting: the orb runs exactly as before whenever the app
|
| 271 |
+
// is foreground-visible, and goes idle (no rAF, no GPU) the moment it's backgrounded β the big battery/thermal win.
|
| 272 |
+
// prefers-reduced-motion β paint one calm frame, then hold static (the base <img> behind the canvas carries the
|
| 273 |
+
// still orb, so it never goes blank). Fail-safe: any error leaves the orb running exactly as before β we never
|
| 274 |
+
// break the orb to save a frame. (Off-screen-while-foreground gating via IntersectionObserver is deferred to a
|
| 275 |
+
// later L1 pass, pending real-device verification β it can't be exercised in a throttled headless tab.)
|
| 276 |
+
function budgetByVisibility(canvas, h) {
|
| 277 |
+
try {
|
| 278 |
+
if (!h || typeof h.pause !== "function" || typeof h.resume !== "function") return h; // mode:"none" β nothing to gate
|
| 279 |
+
if (typeof document === "undefined") return h;
|
| 280 |
+
const reduce = (typeof matchMedia === "function") && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
| 281 |
+
if (reduce) {
|
| 282 |
+
const t = setTimeout(function () { try { h.pause(); } catch (e) {} }, 450); // one frame settles, then the still image holds
|
| 283 |
+
const os = h.stop && h.stop.bind(h);
|
| 284 |
+
h.stop = function () { try { clearTimeout(t); } catch (e) {} if (os) os(); };
|
| 285 |
+
return h;
|
| 286 |
+
}
|
| 287 |
+
let gone = false;
|
| 288 |
+
const onVis = function () { if (gone) return; try { document.hidden ? h.pause() : h.resume(); } catch (e) {} };
|
| 289 |
+
try { document.addEventListener("visibilitychange", onVis); } catch (e) {}
|
| 290 |
+
const os = h.stop && h.stop.bind(h);
|
| 291 |
+
h.stop = function () {
|
| 292 |
+
gone = true;
|
| 293 |
+
try { document.removeEventListener("visibilitychange", onVis); } catch (e) {}
|
| 294 |
+
if (os) os();
|
| 295 |
+
};
|
| 296 |
+
if (document.hidden) onVis(); // mounted while backgrounded β start idle
|
| 297 |
+
return h;
|
| 298 |
+
} catch (e) { return h; }
|
| 299 |
+
}
|
| 300 |
+
|
| 301 |
+
export function mountOrb(canvas, opts) {
|
| 302 |
+
const h = mountGpuOrb(canvas, opts) // native-WebGPU worker orb (off the main thread) β the hero
|
| 303 |
+
|| mountWebglOrb(canvas); // no WebGPU/Worker/OffscreenCanvas β the WebGL2 wireframe floor
|
| 304 |
+
return budgetByVisibility(canvas, h);
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 308 |
+
// FALLBACK β the self-contained WebGL2 wireframe icosphere, restyled QUIET: where WebGPU isn't available
|
| 309 |
+
// (Brave shields, older GPUs) the orb must still look like the OS β a dim violet-ink lattice breathing on
|
| 310 |
+
// dark glass, never the loud rainbow wireframe. Geometry and motion are the proven originals; only the ink
|
| 311 |
+
// changed (single hue family, low alpha) so the fallback reads as a resting state of the hero orb.
|
| 312 |
+
// βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 313 |
+
function hueAt(t){ const k=0.5+0.5*Math.sin(t*2*Math.PI); return [0.42+0.14*k, 0.44+0.06*k, 0.66+0.24*k]; } // ink indigo β soft violet, one quiet family
|
| 314 |
+
function norm(v){ const l=Math.hypot(v[0],v[1],v[2])||1; return [v[0]/l,v[1]/l,v[2]/l]; }
|
| 315 |
+
function icosphere(sub){
|
| 316 |
+
const t=(1+Math.sqrt(5))/2;
|
| 317 |
+
let V=[[-1,t,0],[1,t,0],[-1,-t,0],[1,-t,0],[0,-1,t],[0,1,t],[0,-1,-t],[0,1,-t],[t,0,-1],[t,0,1],[-t,0,-1],[-t,0,1]].map(norm);
|
| 318 |
+
let F=[[0,11,5],[0,5,1],[0,1,7],[0,7,10],[0,10,11],[1,5,9],[5,11,4],[11,10,2],[10,7,6],[7,1,8],[3,9,4],[3,4,2],[3,2,6],[3,6,8],[3,8,9],[4,9,5],[2,4,11],[6,2,10],[8,6,7],[9,8,1]];
|
| 319 |
+
const cache=new Map();
|
| 320 |
+
const mid=(a,b)=>{ const key=a<b?a+"_"+b:b+"_"+a; if(cache.has(key))return cache.get(key); const m=norm([(V[a][0]+V[b][0])/2,(V[a][1]+V[b][1])/2,(V[a][2]+V[b][2])/2]); V.push(m); const i=V.length-1; cache.set(key,i); return i; };
|
| 321 |
+
for(let s=0;s<sub;s++){ const nf=[]; for(const [a,b,c] of F){ const ab=mid(a,b),bc=mid(b,c),ca=mid(c,a); nf.push([a,ab,ca],[b,bc,ab],[c,ca,bc],[ab,bc,ca]); } F=nf; }
|
| 322 |
+
const seen=new Set(), E=[];
|
| 323 |
+
for(const [a,b,c] of F) for(const [x,y] of [[a,b],[b,c],[c,a]]){ const k=x<y?x+"_"+y:y+"_"+x; if(!seen.has(k)){ seen.add(k); E.push(x,y); } }
|
| 324 |
+
return { V, E };
|
| 325 |
+
}
|
| 326 |
+
function mat4Perspective(fovy, aspect, near, far){ const f=1/Math.tan(fovy/2), nf=1/(near-far); return new Float32Array([f/aspect,0,0,0, 0,f,0,0, 0,0,(far+near)*nf,-1, 0,0,2*far*near*nf,0]); }
|
| 327 |
+
|
| 328 |
+
function mountWebglOrb(canvas){
|
| 329 |
+
let gl; try { gl = canvas.getContext("webgl2", { alpha:true, antialias:true, premultipliedAlpha:false }); } catch(e){}
|
| 330 |
+
if(!gl) return { fallback:true, mode:"none", stop(){} };
|
| 331 |
+
const { V, E } = icosphere(3);
|
| 332 |
+
const pos=new Float32Array(E.length*3), col=new Float32Array(E.length*3);
|
| 333 |
+
for(let i=0;i<E.length;i++){ const p=V[E[i]]; pos[i*3]=p[0]; pos[i*3+1]=p[1]; pos[i*3+2]=p[2]; const h=hueAt(Math.atan2(p[2],p[0])/(2*Math.PI)+0.5); col[i*3]=h[0]; col[i*3+1]=h[1]; col[i*3+2]=h[2]; }
|
| 334 |
+
const vs=`#version 300 es
|
| 335 |
+
in vec3 aPos; in vec3 aCol; uniform mat4 uProj; uniform float uT; out vec3 vCol; out float vD;
|
| 336 |
+
void main(){
|
| 337 |
+
float a=uT*0.9, ca=cos(a), sa=sin(a);
|
| 338 |
+
vec3 p=vec3(ca*aPos.x+sa*aPos.z, aPos.y, -sa*aPos.x+ca*aPos.z);
|
| 339 |
+
float ax=uT*0.556, cx=cos(ax), sx=sin(ax);
|
| 340 |
+
p=vec3(p.x, cx*p.y - sx*p.z, sx*p.y + cx*p.z);
|
| 341 |
+
float br=1.0 + 0.05*sin(uT*1.3+p.y*3.0) + 0.035*sin(uT*0.7+p.x*4.0);
|
| 342 |
+
p*=br; vD=p.z; p.z-=3.15;
|
| 343 |
+
gl_Position=uProj*vec4(p,1.0); vCol=aCol;
|
| 344 |
+
}`;
|
| 345 |
+
const fs=`#version 300 es
|
| 346 |
+
precision highp float; in vec3 vCol; in float vD; out vec4 o;
|
| 347 |
+
void main(){ float d=0.40+0.30*smoothstep(-1.0,1.0,vD); o=vec4(vCol*d, 0.45); }`;
|
| 348 |
+
const sh=(t,s)=>{ const o=gl.createShader(t); gl.shaderSource(o,s); gl.compileShader(o); if(!gl.getShaderParameter(o,gl.COMPILE_STATUS)){ console.error("[orb] shader:", gl.getShaderInfoLog(o)); } return o; };
|
| 349 |
+
const prog=gl.createProgram(); gl.attachShader(prog,sh(gl.VERTEX_SHADER,vs)); gl.attachShader(prog,sh(gl.FRAGMENT_SHADER,fs)); gl.linkProgram(prog);
|
| 350 |
+
if(!gl.getProgramParameter(prog,gl.LINK_STATUS)){ console.error("[orb] link:", gl.getProgramInfoLog(prog)); return { fallback:true, mode:"none", stop(){} }; }
|
| 351 |
+
gl.useProgram(prog);
|
| 352 |
+
const mkBuf=(data,loc)=>{ const b=gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER,b); gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW); gl.enableVertexAttribArray(loc); gl.vertexAttribPointer(loc,3,gl.FLOAT,false,0,0); };
|
| 353 |
+
mkBuf(pos, gl.getAttribLocation(prog,"aPos")); mkBuf(col, gl.getAttribLocation(prog,"aCol"));
|
| 354 |
+
const uProj=gl.getUniformLocation(prog,"uProj"), uT=gl.getUniformLocation(prog,"uT");
|
| 355 |
+
gl.enable(gl.BLEND); gl.blendFunc(gl.SRC_ALPHA, gl.ONE); gl.lineWidth(1);
|
| 356 |
+
let raf=0, t0=performance.now(), stopped=false, paused=false;
|
| 357 |
+
function resize(){ const dpr=Math.min(window.devicePixelRatio||1, 2.5); const w=Math.max(2, canvas.clientWidth), h=Math.max(2, canvas.clientHeight); const W=Math.round(w*dpr), H=Math.round(h*dpr); if(canvas.width!==W||canvas.height!==H){ canvas.width=W; canvas.height=H; } gl.viewport(0,0,canvas.width,canvas.height); gl.uniformMatrix4fv(uProj,false, mat4Perspective(45*Math.PI/180, canvas.width/canvas.height, 0.1, 10)); }
|
| 358 |
+
function frame(){ if(stopped||paused) return; resize(); const t=(performance.now()-t0)/1000; gl.clearColor(0,0,0,0); gl.clear(gl.COLOR_BUFFER_BIT); gl.uniform1f(uT,t); gl.drawArrays(gl.LINES,0,E.length); raf=requestAnimationFrame(frame); }
|
| 359 |
+
frame();
|
| 360 |
+
return {
|
| 361 |
+
stop(){ stopped=true; cancelAnimationFrame(raf); raf=0; },
|
| 362 |
+
pause(){ if(paused||stopped) return; paused=true; if(raf){ cancelAnimationFrame(raf); raf=0; } }, // halt while unseen; the last frame stays painted
|
| 363 |
+
resume(){ if(!paused||stopped) return; paused=false; if(!raf) frame(); },
|
| 364 |
+
fallback:false, mode:"webgl" };
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
export default mountOrb;
|
sha256/bf790f49c2c3366fae494488b1832dac05908e18a37f5b5dd4292c76a6d130f7
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// messenger-shadcn-ui.mjs β DROP-IN mount(el, model) rendering the Holo Messenger UX from STREAMING
|
| 2 |
+
// shadcn ΞΊ-components, faithful to the real app (network app-rail Β· Q sidebar Β· triage Β· rich rows Β·
|
| 3 |
+
// Q chat pane Β· earth wallpaper Β· real SVG line icons), same contract as the chatscope bundle.
|
| 4 |
+
//
|
| 5 |
+
// ADDITIVE + SAFE: only takes over window.HoloMessengerUI.mount on opt-in (?ui=shadcn or
|
| 6 |
+
// localStorage["holo.ui.shadcn"]="1"). Default boot stays the untouched chatscope UI.
|
| 7 |
+
//
|
| 8 |
+
// PERF: memoized rows Β· composer owns its draft Β· windowed thread (β€WINDOW rows in DOM; 1M chat stays tiny).
|
| 9 |
+
// PASS 1 = faithful shell. Rich message content + action surface are Pass 2/3.
|
| 10 |
+
|
| 11 |
+
const WANT = (() => {
|
| 12 |
+
try { const u = new URL(location.href);
|
| 13 |
+
if (u.searchParams.get("ui") === "shadcn") return true;
|
| 14 |
+
if (u.searchParams.get("ui") === "chatscope") return false;
|
| 15 |
+
return localStorage.getItem("holo.ui.shadcn") === "1";
|
| 16 |
+
} catch { return false; }
|
| 17 |
+
})();
|
| 18 |
+
|
| 19 |
+
const WINDOW = 80;
|
| 20 |
+
const BRANDS = "/usr/share/brands/";
|
| 21 |
+
const WP = "/apps/holo-messenger/_vendor/wallpaper-default.jpg"; // the earth photo (default)
|
| 22 |
+
const NET_SLUG = { whatsapp: "whatsapp", telegram: "telegram", signal: "signal", imessage: "imessage", instagram: "instagram", messenger: "messenger", discord: "discord", slack: "slack", gmessages: "googlemessages", googlemessages: "googlemessages", x: "x", twitter: "x", linkedin: "linkedin", gmail: "gmail", email: "gmail", internal: null };
|
| 23 |
+
|
| 24 |
+
const CSS = `
|
| 25 |
+
.wa{height:100dvh;display:grid;grid-template-columns:64px minmax(300px,.46fr) minmax(0,1fr);background:#0b141a;color:#e9edef;
|
| 26 |
+
font:14.5px/1.5 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}
|
| 27 |
+
.wa *{box-sizing:border-box}
|
| 28 |
+
.wa svg{display:block}
|
| 29 |
+
.rail{background:#111b21;border-right:1px solid #0a1015;display:flex;flex-direction:column;align-items:center;gap:7px;padding:12px 0}
|
| 30 |
+
.rb{position:relative;width:46px;height:46px;border-radius:15px;display:grid;place-items:center;cursor:pointer;color:#aebac1;transition:background .12s,color .12s;background:transparent;border:0}
|
| 31 |
+
.rb:hover{background:#202c33;color:#e9edef}.rb.on{background:#2a3942;color:#00a884}
|
| 32 |
+
.rb img{width:28px;height:28px;border-radius:8px;object-fit:cover}
|
| 33 |
+
.rb .dot{position:absolute;right:5px;bottom:5px;width:10px;height:10px;border-radius:50%;background:#00d95f;border:2px solid #111b21}
|
| 34 |
+
.rb .bdg{position:absolute;top:-3px;right:-3px;min-width:19px;height:19px;border-radius:10px;background:#00a884;color:#0b141a;font-size:11px;font-weight:700;display:grid;place-items:center;padding:0 4px;border:2px solid #111b21}
|
| 35 |
+
.rsep{width:28px;height:1px;background:#22303a;margin:3px 0}
|
| 36 |
+
.rgrow{flex:1 1 auto}
|
| 37 |
+
.rav{width:40px;height:40px;border-radius:50%;overflow:hidden;cursor:pointer;background:radial-gradient(circle at 35% 30%,#7cf0c8,#2b9e7a 60%,#0b3b2e);margin-top:2px}
|
| 38 |
+
.side{background:#111b21;border-right:1px solid #222d34;display:flex;flex-direction:column;min-width:0}
|
| 39 |
+
.stitle{display:flex;align-items:center;gap:6px;padding:15px 14px 10px}
|
| 40 |
+
.stitle .t{font-size:23px;font-weight:600;letter-spacing:-.4px;flex:1 1 auto}
|
| 41 |
+
.search{padding:4px 12px 8px;position:relative}
|
| 42 |
+
.search .si{position:absolute;left:26px;top:50%;transform:translateY(-50%);color:#8696a0;pointer-events:none;z-index:1;display:grid}
|
| 43 |
+
.filt{display:flex;align-items:center;gap:8px;padding:2px 14px 8px}
|
| 44 |
+
.chip{display:inline-flex;align-items:center;gap:6px;background:#202c33;color:#8696a0;border:0;border-radius:999px;padding:5px 14px;font-size:13px;cursor:pointer}
|
| 45 |
+
.chip.on{background:#0b3b2e;color:#00d95f}
|
| 46 |
+
.caret{background:#202c33;color:#8696a0;border:0;border-radius:999px;width:30px;height:28px;display:grid;place-items:center;cursor:pointer;font-size:11px}
|
| 47 |
+
.triage{margin:2px 12px 8px;display:flex;align-items:center;gap:9px;background:linear-gradient(90deg,#0e2a24,#122a1e);color:#7cf0c8;border:1px solid #123c30;border-radius:14px;padding:9px 14px;font-size:13.5px;cursor:pointer}
|
| 48 |
+
.triage .sk{color:#00d95f;display:grid;flex:0 0 auto}
|
| 49 |
+
.chats{flex:1 1 auto;overflow-y:auto;overflow-x:hidden}
|
| 50 |
+
.chats::-webkit-scrollbar{width:6px}.chats::-webkit-scrollbar-thumb{background:#374248;border-radius:6px}
|
| 51 |
+
.row{display:flex;gap:13px;align-items:center;padding:9px 14px;cursor:pointer;position:relative}
|
| 52 |
+
.row:after{content:"";position:absolute;left:78px;right:0;bottom:0;height:1px;background:#1c262d}
|
| 53 |
+
.row:hover{background:#202c33}.row.on{background:#2a3942}.row.on:after{background:transparent}
|
| 54 |
+
.av{position:relative;flex:0 0 auto;border-radius:50%;overflow:hidden}
|
| 55 |
+
.av img{width:100%;height:100%;object-fit:cover;display:block}
|
| 56 |
+
.row .b{min-width:0;flex:1 1 auto}
|
| 57 |
+
.row .n{color:#e9edef;font-size:16px;font-weight:400;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:6px}
|
| 58 |
+
.row .p{color:#8696a0;font-size:13.5px;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:3px}
|
| 59 |
+
.row .rc{color:#53bdeb}
|
| 60 |
+
.row .m{margin-left:auto;text-align:right;display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex:0 0 auto}
|
| 61 |
+
.row .t{color:#8696a0;font-size:12px}.row.unread .t{color:#00d95f;font-weight:500}
|
| 62 |
+
.row .pin{color:#f15c6d;font-size:13px;transform:rotate(45deg)}
|
| 63 |
+
.netdot{width:16px;height:16px;border-radius:4px;object-fit:cover;flex:0 0 auto}
|
| 64 |
+
.main{position:relative;display:flex;flex-direction:column;min-width:0;background:#0b141a}
|
| 65 |
+
.wp{position:absolute;inset:0;background:#0b141a center/cover no-repeat;z-index:0}
|
| 66 |
+
.wp:after{content:"";position:absolute;inset:0;background:linear-gradient(rgba(11,20,26,.35),rgba(11,20,26,.5))}
|
| 67 |
+
.mh,.thread,.composer,.e2ewrap{position:relative;z-index:1}
|
| 68 |
+
.mh{height:60px;flex:0 0 auto;background:#202c33;display:flex;align-items:center;gap:14px;padding:0 16px}
|
| 69 |
+
.mh .who .n{font-size:16px;color:#e9edef;font-weight:500}
|
| 70 |
+
.mh .who .s{font-size:13px;color:#00a884;margin-top:1px}
|
| 71 |
+
.mh .sp{margin-left:auto}.mh .icons{display:flex;gap:2px}
|
| 72 |
+
.ico{width:40px;height:40px;border-radius:50%;display:grid;place-items:center;color:#aebac1;cursor:pointer;transition:background .12s;background:transparent;border:0}
|
| 73 |
+
.ico:hover{background:#ffffff14;color:#e9edef}
|
| 74 |
+
.ico.sk{color:#00d95f}
|
| 75 |
+
.e2ewrap{display:flex;justify-content:center;padding:14px 0 2px}
|
| 76 |
+
.e2e{background:#182229;color:#ffd279;font-size:12.5px;padding:6px 14px;border-radius:8px;box-shadow:0 1px .5px #0003}
|
| 77 |
+
.thread{flex:1 1 auto;overflow-y:auto;overflow-x:hidden;padding:10px 8% 14px;display:flex;flex-direction:column;gap:3px}
|
| 78 |
+
.thread::-webkit-scrollbar{width:6px}.thread::-webkit-scrollbar-thumb{background:#374248cc;border-radius:6px}
|
| 79 |
+
.more{align-self:center;color:#8696a0;font-size:12px;padding:8px;opacity:.85}
|
| 80 |
+
.day{align-self:center;background:#182229;color:#8696a0;font-size:12.5px;padding:5px 12px;border-radius:8px;margin:8px 0 6px;box-shadow:0 1px .5px #0003}
|
| 81 |
+
.bub{max-width:65%;padding:6px 9px 8px 10px;border-radius:8px;font-size:14.2px;line-height:1.42;box-shadow:0 1px .5px #0003;word-wrap:break-word;white-space:pre-wrap}
|
| 82 |
+
.in{align-self:flex-start;background:#202c33;border-top-left-radius:0}
|
| 83 |
+
.out{align-self:flex-end;background:#005c4b;border-top-right-radius:0}
|
| 84 |
+
.grp{margin-top:8px}
|
| 85 |
+
.bub .tt{font-size:11px;color:#ffffff8a;float:right;margin:6px 0 -3px 12px;position:relative;top:4px}
|
| 86 |
+
.bub .tt .rc{color:#53bdeb}
|
| 87 |
+
.empty{margin:auto;color:#8696a0;text-align:center;background:#182229;padding:8px 16px;border-radius:8px}
|
| 88 |
+
.composer{flex:0 0 auto;background:#202c33;display:flex;align-items:center;gap:6px;padding:8px 14px}
|
| 89 |
+
.composer .grow{flex:1 1 auto}
|
| 90 |
+
.send{width:44px;height:44px;border-radius:50%;background:#00a884;color:#0b141a;border:0;display:grid;place-items:center;cursor:pointer;flex:0 0 auto}
|
| 91 |
+
/* media */
|
| 92 |
+
.m-img{display:block;max-width:320px;max-height:340px;border-radius:6px;cursor:pointer;object-fit:cover}
|
| 93 |
+
.m-vid{position:relative;max-width:320px;border-radius:6px;overflow:hidden;cursor:pointer}
|
| 94 |
+
.m-vid img{display:block;width:100%;border-radius:6px}
|
| 95 |
+
.m-play{position:absolute;inset:0;display:grid;place-items:center}
|
| 96 |
+
.m-play span{width:48px;height:48px;border-radius:50%;background:#0009;color:#fff;display:grid;place-items:center;font-size:20px}
|
| 97 |
+
.m-file{display:flex;align-items:center;gap:10px;background:#ffffff0f;border-radius:8px;padding:9px 11px;min-width:200px;cursor:pointer}
|
| 98 |
+
.m-file .fi{width:38px;height:38px;border-radius:8px;background:#00a88433;color:#7cf0c8;display:grid;place-items:center;font-size:16px;flex:0 0 auto}
|
| 99 |
+
.m-file .fn{font-size:13.5px;color:#e9edef;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
| 100 |
+
.m-file .fs{font-size:12px;color:#8696a0;margin-top:2px}
|
| 101 |
+
.m-aud{display:flex;align-items:center;gap:10px;min-width:220px;padding:2px 0}
|
| 102 |
+
.m-aud audio{height:34px}
|
| 103 |
+
.lb{position:fixed;inset:0;background:#000c;z-index:60;display:grid;place-items:center;cursor:zoom-out}
|
| 104 |
+
.lb img,.lb video{max-width:90vw;max-height:90vh;border-radius:8px}
|
| 105 |
+
.lb .x{position:absolute;top:18px;right:22px;color:#fff;font-size:28px;cursor:pointer;background:0;border:0}
|
| 106 |
+
/* attach tray + pay sheet */
|
| 107 |
+
.tray{position:absolute;bottom:66px;left:14px;background:#233138;border-radius:12px;box-shadow:0 10px 34px #0009;padding:6px;z-index:6;min-width:236px}
|
| 108 |
+
.tray button{display:flex;align-items:center;gap:11px;width:100%;background:0;border:0;color:#e9edef;font-size:14.5px;padding:10px 12px;border-radius:8px;cursor:pointer;text-align:left}
|
| 109 |
+
.tray button:hover{background:#2a3942}.tray button:disabled{opacity:.5}
|
| 110 |
+
.tray .sep{height:1px;background:#2a3942;margin:4px 6px}
|
| 111 |
+
.paywrap{position:fixed;inset:0;background:#000a;z-index:60;display:grid;place-items:center}
|
| 112 |
+
.pay{background:#111b21;border-radius:14px;padding:20px;width:346px;max-width:90vw;box-shadow:0 20px 60px #000a}
|
| 113 |
+
.pay h3{margin:0 0 4px;font-size:17px}.pay .psub{color:#8696a0;font-size:13px;margin-bottom:14px}
|
| 114 |
+
.pay .seg{display:flex;background:#202c33;border-radius:10px;padding:3px;margin-bottom:14px}
|
| 115 |
+
.pay .seg button{flex:1;background:0;border:0;color:#8696a0;padding:8px;border-radius:8px;cursor:pointer;font-size:14px}
|
| 116 |
+
.pay .seg button.on{background:#00a884;color:#0b141a;font-weight:600}
|
| 117 |
+
.pay .amt{width:100%;background:#202c33;border:0;border-radius:10px;color:#e9edef;font-size:26px;text-align:center;padding:12px;margin-bottom:10px;outline:0}
|
| 118 |
+
.pay .chips{display:flex;gap:8px;margin-bottom:12px}
|
| 119 |
+
.pay .chips button{flex:1;background:#202c33;border:0;color:#e9edef;border-radius:8px;padding:9px;cursor:pointer}
|
| 120 |
+
.pay .chips button.on{background:#0b3b2e;color:#00d95f}
|
| 121 |
+
.pay .memo{width:100%;background:#202c33;border:0;border-radius:10px;color:#e9edef;padding:10px 12px;margin-bottom:12px;font-size:14px;outline:0}
|
| 122 |
+
.pay .err{color:#f15c6d;font-size:13px;margin-bottom:8px;text-align:center}
|
| 123 |
+
.pay .go{width:100%;background:#00a884;color:#0b141a;border:0;border-radius:10px;padding:12px;font-weight:600;cursor:pointer;font-size:15px}
|
| 124 |
+
.pay .go:disabled{opacity:.5;cursor:default}
|
| 125 |
+
.pay .cancel{width:100%;background:0;color:#8696a0;border:0;padding:10px;margin-top:6px;cursor:pointer}
|
| 126 |
+
`;
|
| 127 |
+
|
| 128 |
+
async function ensureImportmap() {
|
| 129 |
+
if (document.querySelector('script[type="importmap"][data-holo-ui]')) return;
|
| 130 |
+
const map = await (await fetch("/apps/ui/vendor/importmap.json")).json();
|
| 131 |
+
const imports = {}; for (const [k, v] of Object.entries(map.imports || map)) imports[k] = typeof v === "string" ? v.replace(/^\.\//, "/apps/ui/") : v;
|
| 132 |
+
const s = document.createElement("script"); s.type = "importmap"; s.setAttribute("data-holo-ui", "1"); s.textContent = JSON.stringify({ imports }); document.head.appendChild(s);
|
| 133 |
+
}
|
| 134 |
+
let _deps = null;
|
| 135 |
+
async function deps() {
|
| 136 |
+
if (_deps) return _deps;
|
| 137 |
+
await ensureImportmap();
|
| 138 |
+
const React = await import("react");
|
| 139 |
+
const { createRoot } = await import("react-dom/client");
|
| 140 |
+
const reg = await (await fetch("/apps/ui/registry/index.json")).json();
|
| 141 |
+
const K = Object.fromEntries(reg.components.map((c) => [c.name, c.holo]));
|
| 142 |
+
const [button, badge, avatar, input] = await Promise.all(["button", "badge", "avatar", "input"].map((n) => import(K[n])));
|
| 143 |
+
return (_deps = { React, createRoot, C: { button, badge, avatar, input } });
|
| 144 |
+
}
|
| 145 |
+
if (!document.getElementById("wa-shadcn-css")) { const st = document.createElement("style"); st.id = "wa-shadcn-css"; st.textContent = CSS; document.head.appendChild(st); }
|
| 146 |
+
|
| 147 |
+
const initials = (s) => (String(s || "?").trim().split(/\s+/).map((w) => w[0]).join("").slice(0, 2) || "?").toUpperCase();
|
| 148 |
+
const hue = (s) => { let h = 0; s = String(s || ""); for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) >>> 0; return `hsl(${h % 360} 40% 46%)`; };
|
| 149 |
+
const isOut = (m) => !!(m && (m.mine || m.out || m.fromMe || m.dir === "out" || m.from === "me" || m.self));
|
| 150 |
+
const threadOf = (model, id) => { try { if (id && model.thread) return model.thread(id) || []; } catch {} return (model.threads && model.threads[id]) || []; };
|
| 151 |
+
const rcMark = (m) => m.status === "read" || m.status === "delivered" ? "ββ" : m.status === "sent" ? "β" : "";
|
| 152 |
+
const slugOf = (net) => { const k = String(net || "").toLowerCase(); return NET_SLUG[k] === undefined ? k : NET_SLUG[k]; };
|
| 153 |
+
const mimeKind = (mime, kind) => { const k = String(kind || "").toLowerCase(); if (["image", "video", "audio", "voice"].includes(k)) return k === "voice" ? "audio" : k; const t = String(mime || "").split("/")[0]; if (t === "image" || t === "video" || t === "audio") return t; return "file"; };
|
| 154 |
+
const humanSize = (n) => { n = +n || 0; if (!n) return ""; const u = ["B", "KB", "MB", "GB"]; let i = 0; while (n >= 1024 && i < u.length - 1) { n /= 1024; i++; } return (n < 10 && i ? n.toFixed(1) : Math.round(n)) + " " + u[i]; };
|
| 155 |
+
const fileGlyph = (mime, name) => { const m = String(mime || ""), e = String(name || "").split(".").pop().toLowerCase(); if (m.includes("pdf") || e === "pdf") return "π"; if (["zip", "rar", "7z"].includes(e)) return "π"; if (["doc", "docx"].includes(e)) return "π"; if (["xls", "xlsx", "csv"].includes(e)) return "π"; return "π"; };
|
| 156 |
+
|
| 157 |
+
function buildApp({ React, C }) {
|
| 158 |
+
const { createElement: h, memo, useState, useRef, useEffect, useCallback, useLayoutEffect } = React;
|
| 159 |
+
const Avatar = C.avatar.Avatar, AvatarImage = C.avatar.AvatarImage, AvatarFallback = C.avatar.AvatarFallback;
|
| 160 |
+
const Button = C.button.Button, Input = C.input.Input, Badge = C.badge.Badge;
|
| 161 |
+
|
| 162 |
+
// exact SVG line icons (from the real app's IC set)
|
| 163 |
+
const svg = (kids, s = 22, w = 1.8) => h("svg", { viewBox: "0 0 24 24", width: s, height: s, fill: "none", stroke: "currentColor", strokeWidth: w, strokeLinecap: "round", strokeLinejoin: "round" }, ...kids);
|
| 164 |
+
const P = (d, e) => h("path", { d, ...e });
|
| 165 |
+
const CIR = (cx, cy, r, e) => h("circle", { cx, cy, r, ...e });
|
| 166 |
+
const RC = (x, y, width, height, rx, e) => h("rect", { x, y, width, height, rx, ...e });
|
| 167 |
+
const fillC = { fill: "currentColor", stroke: "none" };
|
| 168 |
+
const IC = {
|
| 169 |
+
chats: () => svg([P("M20 11.4A7.6 7.6 0 0 1 8.9 18.2L4.5 19.4l1.2-4.2A7.6 7.6 0 1 1 20 11.4Z")]),
|
| 170 |
+
search: (s) => svg([CIR(11, 11, 7), P("m20 20-3.6-3.6")], s || 19),
|
| 171 |
+
phone: () => svg([P("M6.6 4H4.5A1.5 1.5 0 0 0 3 5.6 16 16 0 0 0 18.4 21a1.5 1.5 0 0 0 1.6-1.5v-2.1a1.5 1.5 0 0 0-1.2-1.45l-2.2-.45a1.5 1.5 0 0 0-1.5.6l-.5.7a12 12 0 0 1-5.1-5.1l.7-.5a1.5 1.5 0 0 0 .6-1.5l-.45-2.2A1.5 1.5 0 0 0 6.6 4Z")]),
|
| 172 |
+
video: () => svg([RC(3, 6.5, 12, 11, 2.5), P("m15 10.5 5.5-3v9l-5.5-3Z")]),
|
| 173 |
+
menu: () => svg([CIR(12, 5, 1.35, fillC), CIR(12, 12, 1.35, fillC), CIR(12, 19, 1.35, fillC)]),
|
| 174 |
+
newchat: () => svg([P("M13.5 4H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7.5"), P("M18.4 3.6a2 2 0 0 1 2.8 2.8L13 14.6l-3.4.9.9-3.4 7.9-8.5Z")]),
|
| 175 |
+
emoji: () => svg([CIR(12, 12, 8.5), P("M8.8 14.2a4.2 4.2 0 0 0 6.4 0"), CIR(9, 10, 1, fillC), CIR(15, 10, 1, fillC)]),
|
| 176 |
+
plus: () => svg([P("M12 5.5v13M5.5 12h13")]),
|
| 177 |
+
mic: () => svg([RC(9, 3, 6, 11, 3), P("M5.5 11a6.5 6.5 0 0 0 13 0M12 17.5V21M8.5 21h7")]),
|
| 178 |
+
send: () => svg([P("M4.5 12 20.5 4.5 13 20.5l-2.8-6.4L4.5 12Z")]),
|
| 179 |
+
spark: (s) => svg([P("M12 3.2l1.7 4.6 4.6 1.7-4.6 1.7L12 15.8l-1.7-4.6L5.7 9.5l4.6-1.7L12 3.2Z"), P("M5.5 15.5l.8 2 2 .8-2 .8-.8 2-.8-2-2-.8 2-.8.8-2Z")], s || 20),
|
| 180 |
+
sun: () => svg([CIR(12, 12, 4), P("M12 2v2M12 20v2M4 12H2M22 12h-2M5.6 5.6 4.2 4.2M19.8 19.8l-1.4-1.4M18.4 5.6l1.4-1.4M4.2 19.8l1.4-1.4")]),
|
| 181 |
+
plusThin: () => svg([P("M12 5.5v13M5.5 12h13")], 26, 1.6),
|
| 182 |
+
};
|
| 183 |
+
|
| 184 |
+
const Av = (name, size, bg, src) => h("div", { className: "av", style: { height: size + "px", width: size + "px" } },
|
| 185 |
+
h(Avatar, { style: { height: "100%", width: "100%", background: bg || hue(name), display: "grid", placeItems: "center" } },
|
| 186 |
+
src ? h(AvatarImage, { src, alt: "", style: { height: "100%", width: "100%", objectFit: "cover" } }) : null,
|
| 187 |
+
h(AvatarFallback, { style: { background: bg || hue(name), color: "#fff", fontSize: (size * 0.36) + "px", fontWeight: 500, height: "100%", width: "100%", display: "grid", placeItems: "center" } }, initials(name))));
|
| 188 |
+
const Ico = (icon, onClick, title, cls) => h("button", { className: "ico" + (cls ? " " + cls : ""), onClick, title }, icon);
|
| 189 |
+
const netLogo = (net) => { const s = slugOf(net); return s ? h("img", { className: "netdot", src: BRANDS + s + ".svg", alt: "", onError: (e) => { e.currentTarget.style.display = "none"; } }) : null; };
|
| 190 |
+
|
| 191 |
+
// rich media in a bubble β image/video/audio/file, with lazy bridge-media resolution
|
| 192 |
+
function MediaView({ media, model, onMedia }) {
|
| 193 |
+
const [url, setUrl] = useState(media.url || media.thumb || "");
|
| 194 |
+
const bucket = mimeKind(media.mime, media.kind);
|
| 195 |
+
useEffect(() => { let alive = true;
|
| 196 |
+
if (!media.url && (media.lazy || media.pending || media.ref) && model.resolveBridgeMedia) {
|
| 197 |
+
Promise.resolve(model.resolveBridgeMedia(media)).then((u) => { if (alive && u) setUrl(typeof u === "string" ? u : (u.url || u.src || "")); }).catch(() => {});
|
| 198 |
+
} return () => { alive = false; }; }, []);
|
| 199 |
+
if (bucket === "image") return url ? h("img", { className: "m-img", src: url, alt: "", loading: "lazy", onClick: () => onMedia({ kind: "image", url }) }) : h("div", { className: "m-file" }, "πΌ Photo");
|
| 200 |
+
if (bucket === "video") return h("div", { className: "m-vid", onClick: () => onMedia({ kind: "video", url }) }, h("img", { src: media.thumb || url, alt: "" }), h("div", { className: "m-play" }, h("span", {}, "βΆ")));
|
| 201 |
+
if (bucket === "audio") return h("div", { className: "m-aud" }, url ? h("audio", { controls: true, src: url }) : h("span", {}, "π€ Voice message"));
|
| 202 |
+
return h("div", { className: "m-file", onClick: () => url && window.open(url, "_blank") }, h("div", { className: "fi" }, fileGlyph(media.mime, media.filename)), h("div", { style: { minWidth: 0 } }, h("div", { className: "fn" }, media.filename || "File"), media.size ? h("div", { className: "fs" }, humanSize(media.size)) : null));
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
const Rail = memo(function Rail({ nets, active, totalUnread, onPick }) {
|
| 206 |
+
return h("nav", { className: "rail" },
|
| 207 |
+
h("button", { className: "rb" + (active === "All" ? " on" : ""), title: "All chats", onClick: () => onPick("All") }, IC.chats(), totalUnread ? h("span", { className: "bdg" }, totalUnread > 99 ? "99+" : totalUnread) : null),
|
| 208 |
+
nets.length ? h("div", { className: "rsep" }) : null,
|
| 209 |
+
nets.map((n) => h("button", { key: n.id, className: "rb" + (active === n.id ? " on" : ""), title: n.label, onClick: () => onPick(n.id) },
|
| 210 |
+
(() => { const s = slugOf(n.id); return s ? h("img", { src: BRANDS + s + ".svg", alt: n.label, onError: (e) => { const t = document.createTextNode((n.label || "?")[0].toUpperCase()); try { e.currentTarget.replaceWith(t); } catch {} } }) : (n.label || "?")[0].toUpperCase(); })(),
|
| 211 |
+
h("span", { className: "dot" }), n.unread ? h("span", { className: "bdg" }, n.unread > 99 ? "99+" : n.unread) : null)),
|
| 212 |
+
h("button", { className: "rb", title: "Add network", onClick: () => onPick("+") }, IC.plusThin()),
|
| 213 |
+
h("div", { className: "rgrow" }),
|
| 214 |
+
h("div", { className: "rav" }));
|
| 215 |
+
});
|
| 216 |
+
|
| 217 |
+
const Row = memo(function Row({ c, on, preview, receipt, onSelect }) {
|
| 218 |
+
return h("div", { className: "row" + (on ? " on" : "") + (c.unread ? " unread" : ""), onClick: () => onSelect(c.id) },
|
| 219 |
+
Av(c.name, 49, c.isQ ? "#12b886" : hue(c.name), c.avatar),
|
| 220 |
+
h("div", { className: "b" },
|
| 221 |
+
h("div", { className: "n" }, c.name || c.id || "Chat", c.network ? netLogo(c.network) : null),
|
| 222 |
+
h("div", { className: "p" }, receipt ? h("span", { className: "rc" }, receipt + " ") : null, preview)),
|
| 223 |
+
h("div", { className: "m" },
|
| 224 |
+
h("div", { className: "t" }, c.time || c.ts || ""),
|
| 225 |
+
c.pinned ? h("span", { className: "pin" }, "π") : null,
|
| 226 |
+
c.unread ? h(Badge, { style: { background: "#00a884", color: "#0b141a", borderRadius: "999px", height: "20px", minWidth: "20px", justifyContent: "center", padding: "0 6px", fontSize: "12px", fontWeight: 600 } }, String(c.unread)) : null));
|
| 227 |
+
});
|
| 228 |
+
|
| 229 |
+
function Thread({ model, activeId, onMedia }) {
|
| 230 |
+
const all = threadOf(model, activeId);
|
| 231 |
+
const [limit, setLimit] = useState(WINDOW);
|
| 232 |
+
const ref = useRef(null), prevId = useRef(activeId), anchorH = useRef(0), pin = useRef(true);
|
| 233 |
+
const toBottom = (el) => { el.scrollTop = el.scrollHeight; };
|
| 234 |
+
useEffect(() => { setLimit(WINDOW); }, [activeId]);
|
| 235 |
+
// Runs after every render (no deps): a fresh chat, or new messages arriving, both flow through here.
|
| 236 |
+
// While "pinned" we stay glued to the newest message β exactly like WhatsApp.
|
| 237 |
+
useLayoutEffect(() => { const el = ref.current; if (!el) return;
|
| 238 |
+
if (prevId.current !== activeId) { prevId.current = activeId; pin.current = true; anchorH.current = 0; toBottom(el); return; }
|
| 239 |
+
if (anchorH.current) { el.scrollTop = el.scrollHeight - anchorH.current; anchorH.current = 0; return; }
|
| 240 |
+
if (pin.current) toBottom(el); });
|
| 241 |
+
// Media resolves async (placeholder first, <img> swapped in later) and reflows the thread AFTER layout.
|
| 242 |
+
// A ResizeObserver on the scroll container won't catch it (its own box size never changes), and per-image
|
| 243 |
+
// listeners miss images added later β so listen for `load` in the CAPTURE phase on the container, which
|
| 244 |
+
// fires for ANY descendant image whenever it appears/loads. Keeps us glued to the newest message.
|
| 245 |
+
useEffect(() => { const el = ref.current; if (!el) return; pin.current = true; toBottom(el);
|
| 246 |
+
requestAnimationFrame(() => { if (pin.current && ref.current) toBottom(ref.current); });
|
| 247 |
+
const stick = () => { if (pin.current && ref.current) toBottom(ref.current); };
|
| 248 |
+
el.addEventListener("load", stick, true); el.addEventListener("error", stick, true);
|
| 249 |
+
return () => { el.removeEventListener("load", stick, true); el.removeEventListener("error", stick, true); };
|
| 250 |
+
}, [activeId]);
|
| 251 |
+
// Detach when the user scrolls up; re-attach ("jump to latest") once they're back near the bottom.
|
| 252 |
+
const onScroll = useCallback((e) => { const el = e.currentTarget;
|
| 253 |
+
pin.current = el.scrollHeight - el.scrollTop - el.clientHeight < 80;
|
| 254 |
+
if (el.scrollTop < 120 && limit < all.length) { anchorH.current = el.scrollHeight; setLimit((l) => Math.min(all.length, l + WINDOW)); } }, [limit, all.length]);
|
| 255 |
+
const start = Math.max(0, all.length - limit), shown = all.slice(start);
|
| 256 |
+
if (!all.length) return h("div", { className: "thread", ref }, h("div", { className: "empty" }, "No messages yet. Say hello π"));
|
| 257 |
+
const rows = [h("div", { className: "e2ewrap", key: "e2e" }, h("div", { className: "e2e" }, "π Messages are end-to-end encrypted")), h("div", { className: "day", key: "day" }, "Today")];
|
| 258 |
+
if (start > 0) rows.push(h("div", { className: "more", key: "more" }, `β ${start.toLocaleString()} earlier β scroll up`));
|
| 259 |
+
let lastOut = null;
|
| 260 |
+
shown.forEach((m, i) => { const out = isOut(m); const hasMedia = m.media && (m.media.url || m.media.thumb || m.media.ref || m.media.lazy || m.media.kind);
|
| 261 |
+
rows.push(h("div", { key: start + i, className: "bub " + (out ? "out" : "in") + (out !== lastOut ? " grp" : ""), style: hasMedia ? { maxWidth: "min(360px,72%)" } : null },
|
| 262 |
+
hasMedia ? h(MediaView, { media: m.media, model, onMedia }) : null,
|
| 263 |
+
m.text ? h("div", { style: hasMedia ? { marginTop: "5px" } : null }, m.text) : null,
|
| 264 |
+
h("span", { className: "tt" }, (m.time || m.ts || ""), out ? h("span", { className: "rc" }, " " + rcMark(m)) : null)));
|
| 265 |
+
lastOut = out; });
|
| 266 |
+
return h("div", { className: "thread", ref, onScroll }, rows);
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
const Composer = memo(function Composer({ activeId, onSend, onPlus }) {
|
| 270 |
+
const [draft, setDraft] = useState("");
|
| 271 |
+
const send = () => { const t = draft.trim(); if (!t) return; onSend(activeId, t); setDraft(""); };
|
| 272 |
+
return h("div", { className: "composer" },
|
| 273 |
+
Ico(IC.plus(), onPlus, "Attach"),
|
| 274 |
+
h("div", { className: "grow" }, h(Input, { placeholder: "Type a message", value: draft, autoFocus: true,
|
| 275 |
+
onChange: (e) => setDraft(e.target.value), onKeyDown: (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); } },
|
| 276 |
+
style: { background: "#2a3942", border: "0", borderRadius: "10px", height: "44px", color: "#e9edef", paddingLeft: "16px" } })),
|
| 277 |
+
h("button", { className: "send", onClick: send, "aria-label": "Send" }, draft.trim() ? IC.send() : IC.mic()));
|
| 278 |
+
});
|
| 279 |
+
|
| 280 |
+
const TrayBtn = (glyph, label, onClick, disabled) => h("button", { onClick, disabled }, h("span", { style: { fontSize: "17px" } }, glyph), label);
|
| 281 |
+
|
| 282 |
+
function PaySheet({ model, activeId, conv, sheet, setSheet }) {
|
| 283 |
+
const set = (patch) => setSheet((s) => ({ ...s, ...patch, err: null }));
|
| 284 |
+
const amt = parseFloat(sheet.amount);
|
| 285 |
+
const go = async () => { set({ busy: true }); let r;
|
| 286 |
+
try { r = await model.holoPay(sheet.genesis || activeId, { kind: sheet.kind, amount: amt, memo: (sheet.memo || "").trim() }); } catch (e) { r = { ok: false, error: String(e && e.message || e) }; }
|
| 287 |
+
if (r && r.ok) setSheet(null); else setSheet((s) => ({ ...s, busy: false, err: (r && r.error) || "Couldn't create the payment" })); };
|
| 288 |
+
return h("div", { className: "paywrap", onClick: () => setSheet(null) },
|
| 289 |
+
h("div", { className: "pay", onClick: (e) => e.stopPropagation() },
|
| 290 |
+
h("h3", {}, sheet.kind === "send" ? "Send money" : "Request money"), h("div", { className: "psub" }, (sheet.kind === "send" ? "To " : "From ") + (conv.name || "this chat")),
|
| 291 |
+
h("div", { className: "seg" }, h("button", { className: sheet.kind === "send" ? "on" : "", onClick: () => set({ kind: "send" }) }, "Send"), h("button", { className: sheet.kind === "request" ? "on" : "", onClick: () => set({ kind: "request" }) }, "Request")),
|
| 292 |
+
h("input", { className: "amt", inputMode: "decimal", placeholder: "$0", value: sheet.amount, onChange: (e) => set({ amount: e.target.value.replace(/[^0-9.]/g, "") }), autoFocus: true }),
|
| 293 |
+
h("div", { className: "chips" }, [10, 20, 50, 100].map((a) => h("button", { key: a, className: amt === a ? "on" : "", onClick: () => set({ amount: String(a) }) }, "$" + a))),
|
| 294 |
+
h("input", { className: "memo", placeholder: "What's it for? (optional)", maxLength: 120, value: sheet.memo || "", onChange: (e) => set({ memo: e.target.value }) }),
|
| 295 |
+
sheet.err ? h("div", { className: "err" }, sheet.err) : null,
|
| 296 |
+
h("button", { className: "go", disabled: sheet.busy || !(amt > 0), onClick: go }, sheet.busy ? (sheet.kind === "send" ? "Confirm in your walletβ¦" : "Creatingβ¦") : ((sheet.kind === "send" ? "Send" : "Request") + (amt > 0 ? " $" + sheet.amount : " money"))),
|
| 297 |
+
h("button", { className: "cancel", onClick: () => setSheet(null) }, "Cancel")));
|
| 298 |
+
}
|
| 299 |
+
|
| 300 |
+
const previewOf = (model, c) => { if (c.preview) return c.preview; const t = threadOf(model, c.id); const last = t.length ? t[t.length - 1] : null; return (last && (last.text || (last.media ? "π media" : ""))) || ""; };
|
| 301 |
+
|
| 302 |
+
return function App({ model }) {
|
| 303 |
+
const convs = Array.isArray(model.conversations) ? model.conversations : [];
|
| 304 |
+
const [activeId, setActiveId] = useState(null);
|
| 305 |
+
const [filter, setFilter] = useState("All");
|
| 306 |
+
const [q, setQ] = useState("");
|
| 307 |
+
const [lb, setLb] = useState(null);
|
| 308 |
+
const [attachOpen, setAttachOpen] = useState(false);
|
| 309 |
+
const [paySheet, setPaySheet] = useState(null);
|
| 310 |
+
const fileRef = useRef(null);
|
| 311 |
+
const onSelect = useCallback((id) => { setActiveId(id); setAttachOpen(false); }, []);
|
| 312 |
+
const active = (activeId && convs.some((c) => c.id === activeId)) ? activeId : ((convs.find((c) => c.active) || convs[0] || {}).id || null);
|
| 313 |
+
const conv = convs.find((c) => c.id === active) || {};
|
| 314 |
+
const onSend = useCallback((id, text) => { try { model.onSend && model.onSend(id, text); } catch (e) { console.error("[shadcn-ui] onSend", e); } }, [model]);
|
| 315 |
+
const call = useCallback((video) => { try { model.startCall && model.startCall(active, { video }); } catch (e) { console.error("[shadcn-ui] startCall", e); } }, [model, active]);
|
| 316 |
+
const pickFile = (accept) => { if (fileRef.current) { fileRef.current.accept = accept; fileRef.current.click(); } setAttachOpen(false); };
|
| 317 |
+
const onFile = (e) => { const f = e.target.files && e.target.files[0]; if (f) { try { model.onAttach && model.onAttach(active, f); } catch (er) { console.error("[shadcn-ui] onAttach", er); } } e.target.value = ""; };
|
| 318 |
+
const tryM = (fn, ...a) => { setAttachOpen(false); try { const r = model[fn] && model[fn](...a); if (r && r.catch) r.catch(() => {}); } catch (e) { console.error("[shadcn-ui] " + fn, e); } };
|
| 319 |
+
const nets = Array.isArray(model.networks) && model.networks.length ? model.networks
|
| 320 |
+
: Object.values(convs.reduce((a, c) => { const id = (c.network || c.platform); if (id && !a[id]) a[id] = { id, label: id[0].toUpperCase() + id.slice(1), unread: 0 }; if (id) a[id].unread += (c.unread || 0); return a; }, {}));
|
| 321 |
+
const totalUnread = convs.reduce((n, c) => n + (c.unread || 0), 0);
|
| 322 |
+
const signalUnread = model.signalUnread != null ? model.signalUnread : convs.filter((c) => c.unread).length;
|
| 323 |
+
const qs = q.trim().toLowerCase();
|
| 324 |
+
const shown = convs.filter((c) => (filter === "All" || (c.network || c.platform) === filter) && (!qs || (c.name || "").toLowerCase().includes(qs) || (previewOf(model, c) || "").toLowerCase().includes(qs)));
|
| 325 |
+
const sub = conv.presence || (conv.isQ ? "online, on your device" : (conv.status || conv.network || conv.platform || ""));
|
| 326 |
+
const runSearch = () => { const t = q.trim(); if (!t) return; try { if (model.qCommand) model.qCommand(t); else if (model.onNewChat) model.onNewChat(t); } catch {} };
|
| 327 |
+
|
| 328 |
+
return h("div", { className: "wa" },
|
| 329 |
+
h(Rail, { nets, active: filter, totalUnread, onPick: (id) => { if (id === "+") { try { model.openNetworks && model.openNetworks(); } catch {} } else setFilter(id); } }),
|
| 330 |
+
h("div", { className: "side" },
|
| 331 |
+
h("div", { className: "stitle" }, h("span", { className: "t" }, "Messenger"),
|
| 332 |
+
model.askQ ? Ico(IC.spark(), () => { try { model.askQ(); } catch {} }, "Ask Q", "sk") : null, Ico(IC.newchat(), () => { try { model.onNewChat && model.onNewChat(""); } catch {} }, "New chat")),
|
| 333 |
+
h("div", { className: "search" }, h("span", { className: "si" }, IC.search()),
|
| 334 |
+
h(Input, { placeholder: "Search, ask Q, or start a chatβ¦", value: q, onChange: (e) => setQ(e.target.value), onKeyDown: (e) => { if (e.key === "Enter") runSearch(); },
|
| 335 |
+
style: { background: "#202c33", border: "0", borderRadius: "10px", height: "42px", color: "#e9edef", paddingLeft: "40px", fontSize: "14.5px" } })),
|
| 336 |
+
signalUnread ? h("div", { className: "triage" }, h("span", { className: "sk" }, IC.spark(18)), `${signalUnread} need you Β· ~${Math.max(1, Math.round(signalUnread * 0.4))} min`) : null,
|
| 337 |
+
h("div", { className: "chats" }, shown.map((c) => h(Row, { key: c.id, c, on: c.id === active, preview: previewOf(model, c), receipt: c.receipt || "", onSelect })))),
|
| 338 |
+
h("div", { className: "main" },
|
| 339 |
+
h("div", { className: "wp", style: { backgroundImage: `url(${WP})` } }),
|
| 340 |
+
h("div", { className: "mh" }, Av(conv.name, 40, conv.isQ ? "#12b886" : hue(conv.name), conv.avatar),
|
| 341 |
+
h("div", { className: "who" }, h("div", { className: "n" }, conv.name || ""), sub ? h("div", { className: "s" }, sub) : null),
|
| 342 |
+
h("div", { className: "sp" }), h("div", { className: "icons" }, Ico(IC.video(), () => call(true), "Video call"), Ico(IC.phone(), () => call(false), "Voice call"), Ico(IC.menu(), () => { try { model.onFavourite && model.onFavourite(active); } catch {} }, "Menu"))),
|
| 343 |
+
h(Thread, { model, activeId: active, onMedia: setLb }),
|
| 344 |
+
h("input", { ref: fileRef, type: "file", style: { display: "none" }, onChange: onFile }),
|
| 345 |
+
attachOpen ? h("div", { className: "tray" },
|
| 346 |
+
TrayBtn("πΌ", "Photos & videos", () => pickFile("image/*,video/*")),
|
| 347 |
+
TrayBtn("π", "Document", () => pickFile("*/*")),
|
| 348 |
+
(conv.network && !conv.isQ && model.holoPay) ? TrayBtn("πΈ", "Send money", () => { setAttachOpen(false); setPaySheet({ kind: "send", amount: "", memo: "", busy: false, err: null }); }) : null,
|
| 349 |
+
h("div", { className: "sep" }),
|
| 350 |
+
model.startMeet ? TrayBtn("π₯", "Start a meeting", () => tryM("startMeet", active, { video: true })) : null,
|
| 351 |
+
model.startTogether ? TrayBtn("π₯", "Share my screen", () => tryM("startTogether", active, { kind: "tab", title: "" })) : null,
|
| 352 |
+
model.startTogether ? TrayBtn("π", "Co-edit a doc", () => tryM("startTogether", active, { kind: "doc", title: "" })) : null,
|
| 353 |
+
(conv.network && !conv.isQ && model.qDraft) ? [h("div", { className: "sep", key: "s" }), TrayBtn("β¨", "Draft a reply with Q", () => tryM("qDraft", active))] : null) : null,
|
| 354 |
+
h(Composer, { key: active, activeId: active, onSend, onPlus: () => setAttachOpen((v) => !v) })),
|
| 355 |
+
lb ? h("div", { className: "lb", onClick: () => setLb(null) }, h("button", { className: "x", "aria-label": "Close" }, "β"),
|
| 356 |
+
lb.kind === "video" ? h("video", { src: lb.url, controls: true, autoPlay: true, onClick: (e) => e.stopPropagation() }) : h("img", { src: lb.url, alt: "", onClick: (e) => e.stopPropagation() })) : null,
|
| 357 |
+
paySheet ? h(PaySheet, { model, activeId: active, conv, sheet: paySheet, setSheet: setPaySheet }) : null);
|
| 358 |
+
};
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
async function mount(el, model) {
|
| 362 |
+
const d = await deps();
|
| 363 |
+
const App = buildApp(d);
|
| 364 |
+
let cur = model;
|
| 365 |
+
const root = d.createRoot(el);
|
| 366 |
+
const render = (mdl) => { cur = mdl || cur; root.render(d.React.createElement(App, { model: cur })); };
|
| 367 |
+
render(model);
|
| 368 |
+
console.log("[shadcn-ui] Holo Messenger (Pass 1) mounted from ΞΊ-components Β·", (model.conversations || []).length, "chats");
|
| 369 |
+
return { update: render, unmount: () => { try { root.unmount(); } catch {} } };
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
if (WANT && typeof window !== "undefined") {
|
| 373 |
+
const prev = window.HoloMessengerUI;
|
| 374 |
+
window.HoloMessengerUI = { mount, version: ((prev && prev.version) || "m1") + "+shadcn", _chatscope: prev };
|
| 375 |
+
console.log("[shadcn-ui] streaming-ΞΊ shadcn UI ACTIVE (opt out: ?ui=chatscope)");
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
export { mount };
|
sha256/d76d596376d1203a8c170ddbe9dab02442158671646c630ee1902d5953e63fc5
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* messenger-skins.css β OPTIONAL colour re-tones, applied ONLY when <html> carries data-skin="β¦".
|
| 2 |
+
* Default (no attribute) is untouched, so this can never disturb the shipping look. Colours only β no
|
| 3 |
+
* layout β safe and fully reversible.
|
| 4 |
+
*
|
| 5 |
+
* The theme drives ~half its colour from --wa-* vars on .holo-wa-root and hardcodes the other half to the
|
| 6 |
+
* same values. This shared block re-points the major hardcoded surfaces back onto the vars; each skin then
|
| 7 |
+
* only remaps the vars and the whole surface re-tones consistently. */
|
| 8 |
+
|
| 9 |
+
html[data-skin] .holo-wa-root { background: var(--wa-bg) !important; color: var(--wa-ink); }
|
| 10 |
+
html[data-skin] .holo-wa-root .cs-main-container,
|
| 11 |
+
html[data-skin] .holo-wa-root .cs-chat-container,
|
| 12 |
+
html[data-skin] .holo-wa-root .cs-message-list { background: transparent; }
|
| 13 |
+
html[data-skin] .holo-wa-root .cs-sidebar,
|
| 14 |
+
html[data-skin] .holo-wa-root .holo-rail,
|
| 15 |
+
html[data-skin] .holo-wa-root .cs-conversation-list { background: var(--wa-side) !important; }
|
| 16 |
+
html[data-skin] .holo-wa-root .cs-conversation-header,
|
| 17 |
+
html[data-skin] .holo-wa-root .holo-list-title,
|
| 18 |
+
html[data-skin] .holo-wa-root .cs-message-input,
|
| 19 |
+
html[data-skin] .holo-wa-root .holo-composer { background: var(--wa-head) !important; }
|
| 20 |
+
html[data-skin] .holo-wa-root .cs-search,
|
| 21 |
+
html[data-skin] .holo-wa-root .holo-wp-search,
|
| 22 |
+
html[data-skin] .holo-wa-root .cs-message-input__content-editor-wrapper,
|
| 23 |
+
html[data-skin] .holo-wa-root .cs-message-input__content-editor { background: color-mix(in srgb, var(--wa-head) 78%, var(--wa-bg)) !important; color: var(--wa-ink) !important; }
|
| 24 |
+
html[data-skin] .holo-wa-root .cs-conversation:hover,
|
| 25 |
+
html[data-skin] .holo-wa-root .cs-conversation.cs-conversation--active { background: var(--wa-head) !important; }
|
| 26 |
+
html[data-skin] .holo-wa-root .cs-conversation__name,
|
| 27 |
+
html[data-skin] .holo-wa-root .cs-conversation-header__user-name { color: var(--wa-ink) !important; }
|
| 28 |
+
html[data-skin] .holo-wa-root .cs-conversation__info,
|
| 29 |
+
html[data-skin] .holo-wa-root .cs-conversation__last-sender,
|
| 30 |
+
html[data-skin] .holo-wa-root .cs-conversation-header__info { color: var(--wa-dim) !important; }
|
| 31 |
+
html[data-skin] .holo-wa-root .cs-message--incoming .cs-message__content { background: var(--wa-in) !important; color: var(--wa-ink) !important; }
|
| 32 |
+
html[data-skin] .holo-wa-root .cs-message--outgoing .cs-message__content { background: var(--wa-out) !important; }
|
| 33 |
+
html[data-skin] .holo-wa-root .cs-message__content { color: var(--wa-ink); }
|
| 34 |
+
html[data-skin] .holo-wa-root .holo-rail-btn.on,
|
| 35 |
+
html[data-skin] .holo-wa-root .holo-rail-net.on,
|
| 36 |
+
html[data-skin] .holo-wa-root .holo-catchup-pill { color: var(--wa-accent) !important; }
|
| 37 |
+
html[data-skin] .holo-wa-root .holo-c-send,
|
| 38 |
+
html[data-skin] .holo-wa-root .cs-button--send { background: var(--wa-accent) !important; }
|
| 39 |
+
|
| 40 |
+
/* ββ cooler / graphite ββ */
|
| 41 |
+
html[data-skin="graphite"] .holo-wa-root { --wa-bg:#0d1117; --wa-side:#12171e; --wa-head:#1c232c; --wa-in:#1c232c; --wa-out:#1f4a55; --wa-ink:#e6eaf0; --wa-dim:#8b96a3; --wa-accent:#4ab3d4; --wa-line:#222a34; }
|
| 42 |
+
/* ββ warmer ββ */
|
| 43 |
+
html[data-skin="warm"] .holo-wa-root { --wa-bg:#14100c; --wa-side:#1b1611; --wa-head:#271f18; --wa-in:#271f18; --wa-out:#4d3f1f; --wa-ink:#efe8df; --wa-dim:#a89a88; --wa-accent:#e0a53c; --wa-line:#2c241b; }
|
| 44 |
+
/* ββ higher contrast ββ */
|
| 45 |
+
html[data-skin="contrast"] .holo-wa-root { --wa-bg:#000000; --wa-side:#0a0a0a; --wa-head:#181818; --wa-in:#1d1d1d; --wa-out:#00805e; --wa-ink:#ffffff; --wa-dim:#a6adb4; --wa-accent:#00e08a; --wa-line:#2a2a2a; }
|
| 46 |
+
/* ββ light mode (experimental: some deep-hardcoded text may stay dark) ββ */
|
| 47 |
+
html[data-skin="light"] .holo-wa-root { --wa-bg:#d7dce1; --wa-side:#ffffff; --wa-head:#f0f2f5; --wa-in:#ffffff; --wa-out:#d9fdd3; --wa-ink:#111b21; --wa-dim:#54656f; --wa-accent:#008069; --wa-line:#e4e8ec; }
|
| 48 |
+
html[data-skin="light"] .holo-wa-root .cs-message__content { color: #111b21 !important; }
|
| 49 |
+
html[data-skin="light"] .holo-wa-root .cs-message-list { background: var(--wa-bg) !important; background-image: none !important; }
|
| 50 |
+
html[data-skin="light"] .holo-wa-root .holo-wp-tile { background-image: none !important; }
|
| 51 |
+
|
| 52 |
+
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 53 |
+
* HI-DPI + HIGH-FPS layer (always on, colour-independent). The honest "8K/retina" story: a DOM/CSS UI
|
| 54 |
+
* is ALREADY resolution-independent β text and the SVG icons are vectors, so on a retina/4K/8K panel it
|
| 55 |
+
* renders at the display's native device pixels with zero extra work (no bitmaps to upscale). What we
|
| 56 |
+
* actually tune here is smoothness + latency:
|
| 57 |
+
* β’ content-visibility skips rendering/layout of off-screen chat rows β a huge list scrolls at the
|
| 58 |
+
* display's full refresh (60/120Hz) and first paint is near-instant (browser does O(visible) work).
|
| 59 |
+
* β’ the scrollers are promoted to their own GPU layer so scrolling never touches the main thread.
|
| 60 |
+
* β’ crisp text rasterisation + high-quality image scaling for hi-DPI. */
|
| 61 |
+
.holo-wa-root { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; }
|
| 62 |
+
.holo-wa-root .cs-conversation { content-visibility: auto; contain-intrinsic-size: auto 72px; }
|
| 63 |
+
.holo-wa-root .cs-message { content-visibility: auto; contain-intrinsic-size: auto 44px; }
|
| 64 |
+
.holo-wa-root .cs-conversation-list,
|
| 65 |
+
.holo-wa-root .cs-message-list .scrollbar-container,
|
| 66 |
+
.holo-wa-root .cs-message-list__scroll-wrapper { will-change: scroll-position; transform: translateZ(0); backface-visibility: hidden; overflow-anchor: auto; }
|
| 67 |
+
.holo-wa-root .cs-avatar img, .holo-wa-root .holo-av-real, .holo-wa-root .holo-media-el img { image-rendering: auto; }
|
| 68 |
+
.holo-wa-root .holo-media-el img, .holo-wa-root .cs-message img { image-rendering: -webkit-optimize-contrast; }
|
| 69 |
+
@media (min-resolution: 1.5dppx) { .holo-wa-root { text-rendering: geometricPrecision; } }
|
| 70 |
+
|
| 71 |
+
/* floating skin picker */
|
| 72 |
+
.holo-skin-pick { position: fixed; right: 16px; bottom: 86px; z-index: 90; display: flex; gap: 4px; align-items: center; background: #0b141aee; border: 1px solid #2a3942; border-radius: 999px; padding: 5px; backdrop-filter: blur(10px); font: 12.5px ui-sans-serif, system-ui, sans-serif; box-shadow: 0 8px 30px #0007; }
|
| 73 |
+
.holo-skin-pick button { background: transparent; border: 0; color: #aebac1; border-radius: 999px; padding: 5px 11px; cursor: pointer; }
|
| 74 |
+
.holo-skin-pick button:hover { background: #ffffff14; color: #e9edef; }
|
| 75 |
+
.holo-skin-pick button.on { background: #00a884; color: #0b141a; font-weight: 600; }
|
| 76 |
+
|
| 77 |
+
/* instant wallpaper */
|
| 78 |
+
/* An inline low-res earth paints INSTANTLY (zero network β it ships in this CSS) as the chat-pane
|
| 79 |
+
* backdrop; the full 2560px wallpaper is preloaded (see app.html) and covers it the moment it decodes.
|
| 80 |
+
* So the pane is never empty and there is no visible load. */
|
| 81 |
+
html[data-skin] .holo-wa-root .cs-chat-container { background: var(--wa-bg) url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDABQODxIPDRQSERIXFhQYHzMhHxwcHz8tLyUzSkFOTUlBSEZSXHZkUldvWEZIZoxob3p9hIWET2ORm4+AmnaBhH//2wBDARYXFx8bHzwhITx/VEhUf39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f39/f3//wAARCAAgADADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwCAR+1SLHVaPUYm2Zyp/jyOB9KE1AbzgjPXaRgAf41pdisjQSL2/SphDx0/Sq8epW64zknuBV6O+s3XKzJ9CcGk5tFciZGIT6fpT1h+YZx+VTC5tuomT880yTUdNgI8ycF89EXJqPavoP2aW5ya28f8bMT9cVIsVqDyCfq1VPtPIOwgfWpDcKFyvzH8q1ujKzL8bWynAiT8RmpGmTsiAfSs0XR/5aKOem3mnrdkcBGz+FF0Go6aW6ZiEwF/6ZjH61XNvdH/AJZnn3qc3rFdrQMwqP7bcKP3cSj2C0tB3Z//2Q==") center center / cover no-repeat !important; }
|
| 82 |
+
html[data-skin] .holo-wa-root .cs-message-list { transition: background-image .25s ease; }
|
| 83 |
+
|
| 84 |
+
/* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 85 |
+
* SLACK skin β data-skin="slack". Unlike the colour-only re-tones above, this one also does LAYOUT: the
|
| 86 |
+
* Slack "window envelope". An aubergine chrome (far-left rail + channel sidebar) wraps a content pane that
|
| 87 |
+
* floats as a rounded island inset by an EVEN margin on ALL FOUR sides β the darker chrome shows through
|
| 88 |
+
* every gap (top, right, bottom, AND a left gutter between sidebar and pane), with rounded corners + a soft
|
| 89 |
+
* shadow for depth. Placed at end-of-file so source order beats the base skin block AND the wallpaper rule
|
| 90 |
+
* above (equal specificity β later wins); every rule carries `.holo-wa-root` to match the base depth.
|
| 91 |
+
*
|
| 92 |
+
* Two coupling facts make the float robust: (1) the composer is a position:absolute overlay on .holo-main
|
| 93 |
+
* whose `left` is CSS `34%` β the SAME 34% as the sidebar's flex-basis β so re-anchoring it to
|
| 94 |
+
* `calc(34% + gap)` keeps it glued to the gapped pane at every window width, no JS. (2) the bundle gives the
|
| 95 |
+
* pane height:100%, which ignores margin and overflows; `height:auto` + flex:1 1 auto lets the even margin
|
| 96 |
+
* actually shrink it. ALL geometry lives in the β₯900px media query so the narrow/mobile single-column layout
|
| 97 |
+
* (sidebar collapses, composer full-bleed) is left exactly as the bundle intends. Colours + margins only,
|
| 98 |
+
* fully reversible, every feature intact. */
|
| 99 |
+
html[data-skin="slack"] .holo-wa-root {
|
| 100 |
+
--wa-bg:var(--holo-chrome, #150E1A); --wa-side:#2A1530; --wa-head:#1B1B1F; --wa-in:#26262B; --wa-out:#3A2140;
|
| 101 |
+
--wa-ink:#E9E5ED; --wa-dim:#A99DB4; --wa-accent:#C6A6E6; --wa-line:#ffffff12;
|
| 102 |
+
--slk-pane:#1B1B1F; --slk-hi:#5C2D66; --slk-hover:#3A2140; --slk-gap:var(--holo-env-gap, 10px);
|
| 103 |
+
background: var(--wa-bg) !important;
|
| 104 |
+
}
|
| 105 |
+
/* chrome behind the floating pane (the colour seen in the inset margin/gutter) */
|
| 106 |
+
html[data-skin="slack"] .holo-wa-root.holo-wa-root,
|
| 107 |
+
html[data-skin="slack"] .holo-wa-root .cs-main-container { background: var(--wa-bg) !important; }
|
| 108 |
+
/* the WebGPU wallpaper backdrop is off in Slack β the pane is a flat surface */
|
| 109 |
+
html[data-skin="slack"] .holo-wa-root .holo-backdrop { display: none !important; }
|
| 110 |
+
/* far-left workspace rail: flush with the chrome β transparent over the same --wa-bg ground as the menu, no seam,
|
| 111 |
+
so rail + list + gutter are ONE continuous background and only the conversation floats (the Slack move). */
|
| 112 |
+
html[data-skin="slack"] .holo-wa-root .holo-rail { background:var(--holo-chrome, #150E1A) !important; border-right:0 !important; }
|
| 113 |
+
html[data-skin="slack"] .holo-wa-root .holo-rail-btn.on,
|
| 114 |
+
html[data-skin="slack"] .holo-wa-root .holo-rail-net.on { color: var(--wa-accent) !important; }
|
| 115 |
+
/* THE LEFT MENU IS THE BACKGROUND β like Slack, the rail, the channel list and the gutter around the floating
|
| 116 |
+
pane are ONE continuous chrome (the --wa-bg ground), not a separate lighter panel. So every sidebar surface is
|
| 117 |
+
transparent: the menu items sit directly on the background, and the ONLY thing that floats is the conversation
|
| 118 |
+
island. This is what makes the whole shell read as one window with content lifted out of it. */
|
| 119 |
+
html[data-skin="slack"] .holo-wa-root .cs-sidebar.cs-sidebar--left,
|
| 120 |
+
html[data-skin="slack"] .holo-wa-root .cs-conversation-list,
|
| 121 |
+
html[data-skin="slack"] .holo-wa-root .holo-list-head,
|
| 122 |
+
html[data-skin="slack"] .holo-wa-root .holo-list-title,
|
| 123 |
+
html[data-skin="slack"] .holo-wa-root .holo-chips,
|
| 124 |
+
html[data-skin="slack"] .holo-wa-root .holo-catchup { background: transparent !important; }
|
| 125 |
+
html[data-skin="slack"] .holo-wa-root .cs-search { background:#1F0F24 !important; border:1px solid #ffffff12 !important; color:var(--wa-ink) !important; }
|
| 126 |
+
/* conversation rows = inset rounded pills (Slack). Inset applied to EVERY row so hover/active only swap the
|
| 127 |
+
* background β no layout jump. Active carries the highlight + white text. */
|
| 128 |
+
html[data-skin="slack"] .holo-wa-root .cs-conversation { margin:1px 8px !important; border-radius:8px !important; }
|
| 129 |
+
html[data-skin="slack"] .holo-wa-root .cs-conversation:hover { background: var(--slk-hover) !important; }
|
| 130 |
+
html[data-skin="slack"] .holo-wa-root .cs-conversation.cs-conversation--active { background: var(--slk-hi) !important; color:#fff !important; }
|
| 131 |
+
html[data-skin="slack"] .holo-wa-root .cs-conversation.cs-conversation--active * { color:#fff !important; }
|
| 132 |
+
/* pane + its inner surfaces (colours are width-independent; the float geometry is gated below) */
|
| 133 |
+
html[data-skin="slack"] .holo-wa-root .cs-chat-container { background: var(--slk-pane) !important; }
|
| 134 |
+
html[data-skin="slack"] .holo-wa-root .cs-message-list { background: var(--slk-pane) !important; background-image: none !important; }
|
| 135 |
+
html[data-skin="slack"] .holo-wa-root .cs-conversation-header { background: var(--slk-pane) !important; border-bottom: 1px solid #ffffff12; }
|
| 136 |
+
html[data-skin="slack"] .holo-wa-root .holo-composer { background: var(--slk-pane) !important; border-top: 1px solid #ffffff12; }
|
| 137 |
+
html[data-skin="slack"] .holo-wa-root .holo-c-input { background:#26262B !important; border:1px solid #ffffff14 !important; border-radius:8px !important; color:var(--wa-ink) !important; }
|
| 138 |
+
|
| 139 |
+
/* ββ the floating envelope (desktop only; narrow layout keeps the bundle's single-column defaults) ββ */
|
| 140 |
+
@media (min-width: 900px) {
|
| 141 |
+
html[data-skin="slack"] .holo-wa-root .cs-chat-container {
|
| 142 |
+
flex: 1 1 auto !important; min-width: 0; height: auto !important; align-self: stretch;
|
| 143 |
+
margin: var(--slk-gap) !important; /* even inset on all four sides */
|
| 144 |
+
border-radius: 12px; overflow: hidden;
|
| 145 |
+
box-shadow: 0 0 0 1px #00000055, 0 14px 38px #00000085;
|
| 146 |
+
}
|
| 147 |
+
/* glue the composer to the gapped pane: left tracks the sidebar's 34%, plus the gutter */
|
| 148 |
+
html[data-skin="slack"] .holo-wa-root .holo-composer {
|
| 149 |
+
left: calc(34% + var(--slk-gap)) !important; right: var(--slk-gap) !important;
|
| 150 |
+
bottom: var(--slk-gap) !important; width: auto !important; border-radius: 0 0 12px 12px;
|
| 151 |
+
}
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
/* ββ THEATRE MODE β full-screen wallpaper + glass, under the Slack skin ββββββββββββββββββββββββββββ
|
| 155 |
+
* Theatre (`.theater`, toggle β/Ctrl+\) collapses the rail + sidebar and floats ONE conversation over a
|
| 156 |
+
* FULL-BLEED wallpaper as centred glass capsules (see whatsapp-theme.css "Stage 6"). Three things make it
|
| 157 |
+
* immersive + fast here:
|
| 158 |
+
* 1. WALLPAPER edge-to-edge β a static image on the root (the whole viewport), NOT the WebGPU `.holo-backdrop`
|
| 159 |
+
* canvas (which we turn OFF: it was rendering at opacity:0, all cost no pixels). The image is the one
|
| 160 |
+
* app.html already preloads, so it paints with zero extra latency; every layer above it is transparent.
|
| 161 |
+
* 2. LIGHT + CLEAR β the heavy radial vignette + hue-tint is replaced by a soft top/bottom legibility scrim
|
| 162 |
+
* only, so the middle of the wallpaper stays bright and open.
|
| 163 |
+
* 3. STUNNING GLASS, CHEAP β real backdrop-blur is limited to the TWO capsules (header + composer); message
|
| 164 |
+
* bubbles are plain translucent fills (no per-bubble blur) so a long thread never janks input.
|
| 165 |
+
* Selector depth `β¦"slack"] .holo-wa-root.theater .X` = (0,4,1) beats the base slack rules (0,3,1) and
|
| 166 |
+
* theatre's own (0,3,0); transforms are left untouched so theatre's centring + auto-quiet fade keep animating. */
|
| 167 |
+
html[data-skin="slack"] .holo-wa-root.theater {
|
| 168 |
+
/* FOLLOW the operator's chosen wallpaper (--wp-img, set from localStorage holo-messenger/wallpaper-src),
|
| 169 |
+
falling back to the preloaded default when unset. `none` (the "plain" mode) is honoured β dark. */
|
| 170 |
+
background: #0b0f14 var(--wp-img, url("/apps/holo-messenger/_vendor/wallpaper-default.jpg")) center center / cover no-repeat !important;
|
| 171 |
+
}
|
| 172 |
+
html[data-skin="slack"] .holo-wa-root.theater .holo-backdrop { display: none !important; } /* WebGPU canvas off β lower latency */
|
| 173 |
+
html[data-skin="slack"] .holo-wa-root.theater .cs-chat-container {
|
| 174 |
+
background: transparent !important; margin: 0 !important; border-radius: 0 !important;
|
| 175 |
+
overflow: visible !important; box-shadow: none !important; /* full-bleed, no slack box */
|
| 176 |
+
}
|
| 177 |
+
/* transparent reading column, aligned to the SAME 812px as the chrome so bubbles line up with the composer */
|
| 178 |
+
html[data-skin="slack"] .holo-wa-root.theater .cs-message-list {
|
| 179 |
+
background: transparent !important;
|
| 180 |
+
padding-left: max(20px, calc((100% - 812px) / 2)) !important;
|
| 181 |
+
padding-right: max(20px, calc((100% - 812px) / 2)) !important;
|
| 182 |
+
}
|
| 183 |
+
/* clear + light: only a soft top/bottom scrim for legibility; the wallpaper stays bright in the middle */
|
| 184 |
+
html[data-skin="slack"] .holo-wa-root.theater .holo-main::before {
|
| 185 |
+
background: linear-gradient(to bottom, rgba(0,0,0,.30) 0%, transparent 16%, transparent 80%, rgba(0,0,0,.42) 100%) !important;
|
| 186 |
+
}
|
| 187 |
+
/* stunning glass capsules β vivid backdrop-blur, crisp edge, top highlight (only these two get real blur) */
|
| 188 |
+
html[data-skin="slack"] .holo-wa-root.theater .cs-conversation-header,
|
| 189 |
+
html[data-skin="slack"] .holo-wa-root.theater .holo-composer {
|
| 190 |
+
background: rgba(22,24,32,.44) !important;
|
| 191 |
+
-webkit-backdrop-filter: blur(30px) saturate(1.4) brightness(1.06) !important;
|
| 192 |
+
backdrop-filter: blur(30px) saturate(1.4) brightness(1.06) !important;
|
| 193 |
+
border: 1px solid rgba(255,255,255,.16) !important;
|
| 194 |
+
box-shadow: 0 14px 40px rgba(0,0,0,.42), inset 0 1px 0 rgba(255,255,255,.16) !important;
|
| 195 |
+
}
|
| 196 |
+
html[data-skin="slack"] .holo-wa-root.theater .holo-composer {
|
| 197 |
+
left: 50% !important; right: auto !important; width: min(calc(100% - 40px), 812px) !important;
|
| 198 |
+
bottom: 18px !important; border-radius: 18px !important;
|
| 199 |
+
}
|
| 200 |
+
/* bubbles: light translucent fills (no blur = no jank on long threads) */
|
| 201 |
+
html[data-skin="slack"] .holo-wa-root.theater .cs-message--incoming .cs-message__content { background: rgba(28,28,36,.62) !important; }
|
| 202 |
+
html[data-skin="slack"] .holo-wa-root.theater .cs-message--outgoing .cs-message__content { background: rgba(58,33,64,.60) !important; }
|
| 203 |
+
|
| 204 |
+
/* ββ FRAME-COLLAPSED β the immersive focus view (chats folded into the rail) βββββββββββββββββββββββ
|
| 205 |
+
* "Collapse chats into the rail" (`.holo-main.frame-collapsed`) folds the conversation list away and lets
|
| 206 |
+
* ONE conversation take the whole frame. The slack skin otherwise left it broken: the composer stayed pinned
|
| 207 |
+
* to `left:34%` (the vanished sidebar edge) so it floated stranded in the middle. Here we make it the SAME
|
| 208 |
+
* immersive treatment as theatre β full-screen wallpaper + glass capsules β but KEEP the rail as a clean
|
| 209 |
+
* glass nav (that's the whole point of this mode), and centre the header/composer/reading-column in the frame
|
| 210 |
+
* to the RIGHT of the rail so everything lines up.
|
| 211 |
+
* Β· `:has(.holo-main.frame-collapsed)` puts the wallpaper on the ROOT (so it sits behind the rail too).
|
| 212 |
+
* Β· `:not(.theater)` so theatre (which hides the rail) keeps full ownership when both happen to be on.
|
| 213 |
+
* Β· Only 3 blur layers total (rail + header + composer); bubbles are plain translucent β stays responsive. */
|
| 214 |
+
html[data-skin="slack"] .holo-wa-root:has(.holo-main.frame-collapsed):not(.theater) {
|
| 215 |
+
/* same as theatre: follow the operator's --wp-img, fall back to the preloaded default */
|
| 216 |
+
background: #0b0f14 var(--wp-img, url("/apps/holo-messenger/_vendor/wallpaper-default.jpg")) center center / cover no-repeat !important;
|
| 217 |
+
}
|
| 218 |
+
html[data-skin="slack"] .holo-wa-root:has(.holo-main.frame-collapsed):not(.theater) .holo-backdrop { display: none !important; }
|
| 219 |
+
/* the left nav bar stays β a clean SOLID strip; the wallpaper covers the entire screen EXCEPT this rail */
|
| 220 |
+
html[data-skin="slack"] .holo-wa-root:has(.holo-main.frame-collapsed):not(.theater) .holo-rail {
|
| 221 |
+
background: #17111D !important;
|
| 222 |
+
border-right: 1px solid rgba(255,255,255,.08) !important;
|
| 223 |
+
}
|
| 224 |
+
/* transparent full-bleed frame + reading column centred in the space right of the rail */
|
| 225 |
+
html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-chat-container {
|
| 226 |
+
background: transparent !important; margin: 0 !important; border-radius: 0 !important; overflow: visible !important; box-shadow: none !important;
|
| 227 |
+
}
|
| 228 |
+
html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-message-list {
|
| 229 |
+
background: transparent !important;
|
| 230 |
+
padding-left: max(20px, calc((100% - 812px) / 2)) !important;
|
| 231 |
+
padding-right: max(20px, calc((100% - 812px) / 2)) !important;
|
| 232 |
+
}
|
| 233 |
+
html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed::before {
|
| 234 |
+
content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
|
| 235 |
+
background: linear-gradient(to bottom, rgba(0,0,0,.30) 0%, transparent 16%, transparent 80%, rgba(0,0,0,.42) 100%);
|
| 236 |
+
}
|
| 237 |
+
/* glass header + composer, centred in the frame (the rail is the nav, the frame is everything right of it) */
|
| 238 |
+
html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-conversation-header,
|
| 239 |
+
html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .holo-composer {
|
| 240 |
+
background: rgba(22,24,32,.44) !important;
|
| 241 |
+
-webkit-backdrop-filter: blur(30px) saturate(1.4) brightness(1.06) !important;
|
| 242 |
+
backdrop-filter: blur(30px) saturate(1.4) brightness(1.06) !important;
|
| 243 |
+
border: 1px solid rgba(255,255,255,.16) !important;
|
| 244 |
+
box-shadow: 0 14px 40px rgba(0,0,0,.42), inset 0 1px 0 rgba(255,255,255,.16) !important;
|
| 245 |
+
}
|
| 246 |
+
html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-conversation-header {
|
| 247 |
+
margin: 14px auto 0 !important; max-width: 812px !important; width: calc(100% - 40px) !important; border-radius: 16px !important;
|
| 248 |
+
}
|
| 249 |
+
html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .holo-composer {
|
| 250 |
+
left: 50% !important; right: auto !important; transform: translateX(-50%) !important;
|
| 251 |
+
width: min(calc(100% - 40px), 812px) !important; bottom: 18px !important; border-radius: 18px !important;
|
| 252 |
+
}
|
| 253 |
+
html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-message--incoming .cs-message__content { background: rgba(28,28,36,.62) !important; }
|
| 254 |
+
html[data-skin="slack"] .holo-wa-root:not(.theater) .holo-main.frame-collapsed .cs-message--outgoing .cs-message__content { background: rgba(58,33,64,.60) !important; }
|
| 255 |
+
|
| 256 |
+
/* ββ BASE-LAYER fix: composer alignment in frame-collapsed, for ANY skin βββββββββββββββββββββββββββ
|
| 257 |
+
* Skin-agnostic (this file is loaded regardless of the active skin). The bundle pins the composer to
|
| 258 |
+
* `left:34%` β the sidebar's flex-basis β but frame-collapsed folds the sidebar to 0, so on every NON-slack
|
| 259 |
+
* skin (graphite/warm/contrast/light/none) the composer floated stranded in the middle. Align it to the
|
| 260 |
+
* full-bleed chat (left:0 = the rail's right edge; right:0 is already the base). `:not(.theater)` yields to
|
| 261 |
+
* theatre's own centred composer; slack's higher-specificity immersive rule above wins for the slack skin. */
|
| 262 |
+
.holo-wa-root:not(.theater) .holo-main.frame-collapsed .holo-composer { left: 0 !important; }
|
| 263 |
+
|
| 264 |
+
/* ββ WHATSAPP SKIN β the messenger as WhatsApp Desktop ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 265 |
+
* Green/dark bubbles + the doodle chat texture; the whole conversation floats as ONE rounded window over the
|
| 266 |
+
* (dimmed) home wallpaper desktop. Default skin (messenger-skin.mjs). All pane rules carry BOTH .holo-wa-root and
|
| 267 |
+
* .holo-wa-root.wall-on selectors so they beat the wall-on living-wallpaper rules (0,5,1 > 0,4,1) in either state. */
|
| 268 |
+
html[data-skin="whatsapp"] .holo-wa-root {
|
| 269 |
+
--wa-bg:#0b141a; --wa-side:#111b21; --wa-head:#202c33; --wa-in:#202c33; --wa-out:#005c4b;
|
| 270 |
+
--wa-ink:#e9edef; --wa-dim:#8696a0; --wa-accent:#00a884; --wa-line:#ffffff14;
|
| 271 |
+
--wa-doodle:url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20width%3D%27300%27%20height%3D%27300%27%20viewBox%3D%270%200%20300%20300%27%20fill%3D%27none%27%20stroke%3D%27url%28%23hd%29%27%20stroke-opacity%3D%27.12%27%20stroke-width%3D%272.3%27%20stroke-linecap%3D%27round%27%20stroke-linejoin%3D%27round%27%3E%3Cdefs%3E%3ClinearGradient%20id%3D%27hd%27%20x1%3D%270%27%20y1%3D%270%27%20x2%3D%271%27%20y2%3D%271%27%3E%3Cstop%20offset%3D%270%27%20stop-color%3D%27%232ee6c6%27%2F%3E%3Cstop%20offset%3D%27.55%27%20stop-color%3D%27%234d8cff%27%2F%3E%3Cstop%20offset%3D%271%27%20stop-color%3D%27%23d46bff%27%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Cg%20transform%3D%27translate%2840%2044%29%20rotate%28-8%29%27%3E%3Cpath%20d%3D%27M-13-9h26a3%203%200%200%201%203%203v11a3%203%200%200%201-3%203H-2l-7%206v-6h-4a3%203%200%200%201-3-3v-11a3%203%200%200%201%203-3z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28150%2030%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M0%2012C-16%202-14-11-5-11c4%200%205%203%205%203s1-3%205-3c9%200%2011%2013-5%2023z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28255%2048%29%20rotate%286%29%27%3E%3Cpath%20d%3D%27M-15-6h7l3-4h10l3%204h7a2%202%200%200%201%202%202v16a2%202%200%200%201-2%202h-30a2%202%200%200%201-2-2v-16a2%202%200%200%201%202-2z%20M0-1a7%207%200%201%200%20.1%200z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%2892%20120%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M0-14a14%2014%200%201%200%20.1%200z%20M-6-4a1%201%200%201%200%20.1%200z%20M6-4a1%201%200%201%200%20.1%200z%20M-7%204a10%2010%200%200%200%2014%200%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28205%20108%29%20rotate%28-12%29%27%3E%3Cpath%20d%3D%27M0-15l4%2010%2011%200-9%207%204%2011-10-7-10%207%204-11-9-7%2011%200z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%2830%20128%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M-6%2012a5%205%200%201%200%200-.1%20M-6%2012v-22l16-4v18a5%205%200%201%200%200-.1%20M-6-10l16-4%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28150%2096%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M0-6a6%206%200%201%200%20.1%200z%20M0-15v5%20M0%2010v5%20M-15%200h5%20M10%200h5%20M-11-11l3%203%20M8%208l3%203%20M11-11l-3%203%20M-8%208l-3%203%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28268%20150%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M-15%204L15-12-3%2015-6%203-15%204z%20M-6%203L15-12%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%2860%20210%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M-11-8h20v10a10%2010%200%200%201-20%200z%20M9-6h4a4%204%200%200%201%200%208h-4%20M-11%2016h20%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28145%20205%29%20rotate%288%29%27%3E%3Cpath%20d%3D%27M-12-12c0%2016%208%2024%2024%2024l3-7-7-4-4%203c-4-2-8-6-10-10l3-4-4-7z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28235%20205%29%20rotate%28-6%29%27%3E%3Cpath%20d%3D%27M-13-4h26v6h-26z%20M-10%202h20v14h-20z%20M0-4v20%20M0-4c-6-10-14-2%200%200%20M0-4c6-10%2014-2%200%200%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28100%20258%29%20rotate%2810%29%27%3E%3Cpath%20d%3D%27M0-3a3%203%200%201%200%20.1%200z%20M0-3c0-9%2010-9%206-2%20M2%200c8-4%2010%206%202%204%20M-1%202c3%208-7%209-5%201%20M-3-1c-8-3-6-11%201-5%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28195%20258%29%20rotate%28-6%29%27%3E%3Cpath%20d%3D%27M0-14a9%2011%200%201%201-.1%200z%20M0-3v6%20M0%203l-3%204h6z%27%2F%3E%3C%2Fg%3E%3Cg%20transform%3D%27translate%28275%20258%29%20rotate%280%29%27%3E%3Cpath%20d%3D%27M3-14l-11%2015h7l-3%2013%2012-16h-7z%27%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
|
| 272 |
+
--wgap:var(--holo-env-gap, 10px);
|
| 273 |
+
background:var(--holo-chrome, #1f1f1e) !important;
|
| 274 |
+
}
|
| 275 |
+
/* THE DESKTOP behind the window = the home wallpaper (the backdrop canvas), full-bleed + dimmed. No wallpaper set
|
| 276 |
+
β a plain dark desktop. */
|
| 277 |
+
/* SUPERSEDED (user: clean nav-matched frame): the desktop behind the window is now ONE flat surface = the left-nav
|
| 278 |
+
chrome (see the root `background:var(--holo-chrome)` set above). The living-wallpaper canvas AND its scrim are
|
| 279 |
+
hidden outright, so the frame around the floating conversation reads as a single continuous nav ground and the
|
| 280 |
+
window is the only thing that floats (also drops the WebGPU per-frame cost β snappier). The `.wall-on` variants
|
| 281 |
+
(0,4,1) + later source-order beat the bundle's `wall-on .holo-backdrop{display:block}`. */
|
| 282 |
+
html[data-skin="whatsapp"] .holo-wa-root .holo-backdrop { display:none !important; }
|
| 283 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .holo-backdrop { display:none !important; }
|
| 284 |
+
html[data-skin="whatsapp"] .holo-wa-root .holo-wall-scrim { display:none !important; }
|
| 285 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .holo-wall-scrim { display:none !important; }
|
| 286 |
+
/* rail = OS chrome */
|
| 287 |
+
html[data-skin="whatsapp"] .holo-wa-root .holo-rail { background:var(--holo-chrome) !important; border-right:0 !important; }
|
| 288 |
+
/* sidebar + list = solid WhatsApp panel (opaque β the desktop shows only in the frame around the window) */
|
| 289 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-main-container,
|
| 290 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-main-container,
|
| 291 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-sidebar.cs-sidebar--left,
|
| 292 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-sidebar.cs-sidebar--left,
|
| 293 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-conversation-list,
|
| 294 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-conversation-list,
|
| 295 |
+
html[data-skin="whatsapp"] .holo-wa-root .holo-list-head,
|
| 296 |
+
html[data-skin="whatsapp"] .holo-wa-root .holo-chips,
|
| 297 |
+
html[data-skin="whatsapp"] .holo-wa-root .holo-catchup { background:var(--wa-side) !important; backdrop-filter:none !important; -webkit-backdrop-filter:none !important; }
|
| 298 |
+
/* CHAT = the WhatsApp doodle (opaque dark base + the line-art texture), NOT the home photo */
|
| 299 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-chat-container,
|
| 300 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-chat-container { background:#0b141a !important; }
|
| 301 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-message-list,
|
| 302 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-message-list {
|
| 303 |
+
background-color:#0b141a !important;
|
| 304 |
+
background-image:var(--wa-doodle) !important;
|
| 305 |
+
background-repeat:repeat !important; background-size:300px 300px !important; background-position:center center !important; }
|
| 306 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-message-list::before,
|
| 307 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-message-list::before,
|
| 308 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-message-list::after { display:none !important; }
|
| 309 |
+
/* header + composer = solid WhatsApp bar (kills the wall-on glass) */
|
| 310 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-conversation-header,
|
| 311 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-conversation-header { background:var(--wa-head) !important; backdrop-filter:none !important; -webkit-backdrop-filter:none !important; border-bottom:0 !important; }
|
| 312 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .holo-composer,
|
| 313 |
+
html[data-skin="whatsapp"] .holo-wa-root .holo-composer { background:var(--wa-head) !important; backdrop-filter:none !important; -webkit-backdrop-filter:none !important; border-top:0 !important; }
|
| 314 |
+
/* bubbles = WhatsApp green out / dark in; composer + search pills */
|
| 315 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-message--outgoing .cs-message__content { background:var(--wa-out) !important; color:var(--wa-ink) !important; }
|
| 316 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-message--incoming .cs-message__content { background:var(--wa-in) !important; color:var(--wa-ink) !important; }
|
| 317 |
+
/* ββ WHATSAPP TEXT INPUTS β one rounded, immersive pill everywhere (composer, search, chat editor, onboarding).
|
| 318 |
+
WhatsApp's soft ~21px capsule on every field; a subtle lift on focus (deeper fill + a thin accent ring) so the
|
| 319 |
+
field feels alive without a hard border. Single radius token keeps them visually identical. */
|
| 320 |
+
html[data-skin="whatsapp"] .holo-wa-root .holo-c-input {
|
| 321 |
+
background:#2a3942 !important; color:var(--wa-ink) !important; border:0 !important;
|
| 322 |
+
border-radius:21px !important; padding:11px 18px !important; min-height:42px !important; font-size:15px !important;
|
| 323 |
+
transition:background-color .16s ease, box-shadow .16s ease !important; }
|
| 324 |
+
html[data-skin="whatsapp"] .holo-wa-root .holo-c-input:focus {
|
| 325 |
+
background:#33434d !important; box-shadow:0 0 0 1px rgba(0,168,132,.55) !important; }
|
| 326 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-search {
|
| 327 |
+
background:#202c33 !important; color:var(--wa-ink) !important; border:0 !important; border-radius:21px !important; }
|
| 328 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-message-input__content-editor-wrapper,
|
| 329 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-message-input__content-editor { border-radius:21px !important; }
|
| 330 |
+
html[data-skin="whatsapp"] .holo-wa-root .holo-onboard-input { border-radius:21px !important; }
|
| 331 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-conversation.cs-conversation--active,
|
| 332 |
+
html[data-skin="whatsapp"] .holo-wa-root .cs-conversation:hover { background:#202c33 !important; }
|
| 333 |
+
|
| 334 |
+
/* ββ THE FLOATING WINDOW (desktop β₯900px) β inset the whole content pane (.holo-main) so the wallpaper desktop
|
| 335 |
+
frames it. Everything inside (sidebar, chat, composer) rides the inset automatically β the composer stays
|
| 336 |
+
pixel-aligned with zero re-math. The window shrinks from the right when a drawer opens (--holo-aside-w). ββ */
|
| 337 |
+
/* REFINED (user: smooth, no glitches): .holo-main is only the composer's ANCHOR box β the VISIBLE rounded island is
|
| 338 |
+
the base theme's `.cs-main-container` (position:fixed, inset --holo-env-gap, radius --holo-env-radius, shadow
|
| 339 |
+
--holo-env-shadow). The old 18px/14px inset here did NOT match that island, so the composer (a child of .holo-main)
|
| 340 |
+
landed ~8px inside the island's rounded bottom-right corner. Track the env-island EXACTLY (same gap + radius) and
|
| 341 |
+
drop .holo-main's own bg/shadow (the island already draws the frame) β the composer sits flush, one clean window,
|
| 342 |
+
zero double-frame. Still shrinks from the right on drawer open, matching the island's own right:calc(...). */
|
| 343 |
+
@media (min-width:900px) {
|
| 344 |
+
html[data-skin="whatsapp"] .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) {
|
| 345 |
+
margin:var(--holo-env-gap, 10px) !important;
|
| 346 |
+
margin-right:calc(var(--holo-env-gap, 10px) + var(--holo-aside-w, 0px)) !important;
|
| 347 |
+
height:auto !important; align-self:stretch;
|
| 348 |
+
border-radius:var(--holo-env-radius, 10px) !important; overflow:hidden;
|
| 349 |
+
background:transparent !important; box-shadow:none !important; }
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
/* ββ CANVAS WINDOW (canvas-window-crisp-v1) β the messenger renders as ONE clean floating canvas, just like Home.
|
| 353 |
+
Home's island reads clearly only because a bright wallpaper sits behind its 11% env-ring; the messenger is
|
| 354 |
+
dark-on-dark chrome, so that same ring nearly vanishes and the window looked edge-to-edge. Define it with a
|
| 355 |
+
CRISP brighter edge + a soft cast shadow so the whole surface floats as a distinct rounded window on the
|
| 356 |
+
chrome β same 10px env inset + radius as Home (composer stays pixel-aligned), just a readable edge. The
|
| 357 |
+
visible island is the base theme's `.cs-main-container` (fixed, inset env-gap); it escapes .holo-main's
|
| 358 |
+
overflow so its cast shadow shows. Desktop β₯900px only; Home's own island is untouched. Behind it the
|
| 359 |
+
chrome gutter is left flat and empty (no wallpaper backdrop, no second frame) β one window, clean. ββ */
|
| 360 |
+
@media (min-width:900px) {
|
| 361 |
+
html[data-skin="whatsapp"] .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .cs-main-container {
|
| 362 |
+
box-shadow: 0 0 0 1px rgba(255,255,255,.2), 0 18px 46px -14px rgba(0,0,0,.66) !important; }
|
| 363 |
+
/* the rail sits in the chrome gutter; keep that gutter pure chrome so nothing peeks behind the window */
|
| 364 |
+
html[data-skin="whatsapp"] .holo-wa-root { background: var(--holo-chrome, #1f1f1e) !important; }
|
| 365 |
+
}
|
| 366 |
+
|
| 367 |
+
/* ββ WHATSAPP-CLEAN SIDEBAR (whatsapp-clean-netstrip-v1) β the network strip (Telegram/WhatsApp/Gmail/LinkedIn
|
| 368 |
+
platform icons above the filter chips) is NOT connected on the web deploy β tapping only opens an
|
| 369 |
+
explainer sheet β so it reads as unwired chrome, and WhatsApp has no such row. Hide it for the WhatsApp
|
| 370 |
+
skin so the list is clean and familiar: search β chips β conversations, nothing decorative between. The
|
| 371 |
+
"All" filter it also held lives in the chips row, so nothing functional is lost. (Reappears the moment a
|
| 372 |
+
real network is bridged is a later, JS-gated refinement; this is the clean default look the operator asked
|
| 373 |
+
for β "only show wired elements".) ββ */
|
| 374 |
+
html[data-skin="whatsapp"] .holo-netstrip { display: none !important; }
|
| 375 |
+
|
| 376 |
+
/* ββ LIVING WALLPAPER IN THE MESSENGER (whatsapp-living-wallpaper-v1) β the chat wears the operator's OWN home
|
| 377 |
+
wallpaper. It is the SAME dynamic wallpaper plane as Home (--wp-img on .holo-backdrop), so it changes the
|
| 378 |
+
instant they change their home wallpaper, and it MORPHS continuously Homeβchat via the pre-wired shared
|
| 379 |
+
view-transition-name:holo-wall (island β window on the GPU compositor). The WhatsApp skin otherwise
|
| 380 |
+
suppresses this for the doodle; here we un-hide it for the chat pane ONLY when a wallpaper is present
|
| 381 |
+
(.wall-on), and lay a STRONG, near-uniform dark scrim over it so the photo stays SUBTLE and the bubbles
|
| 382 |
+
never fight it β sharp, immersive, familiar. The sidebar/header/composer stay solid WhatsApp (untouched
|
| 383 |
+
above). Appended last = wins the source-order tie over the skin's hide rules. No wallpaper β .wall-on is
|
| 384 |
+
absent β the flat look above still holds. ββ */
|
| 385 |
+
/* The page-level .holo-backdrop canvas + .holo-wall-scrim stay HIDDEN (base skin rules 282-285) β un-hiding them
|
| 386 |
+
painted the photo in the chrome gutter BEHIND the opaque card ("loads in the background"), never in the chat.
|
| 387 |
+
Instead paint the wallpaper DIRECTLY on the chat pane (.cs-chat-container) β the photo lives INSIDE the chat box,
|
| 388 |
+
with the dark scrim layered in the SAME background over it (image is the lower layer). The message list scrolls
|
| 389 |
+
transparent over it, so the photo holds still while messages move β exactly WhatsApp. --wp-img cascades from
|
| 390 |
+
.holo-wa-root (main.jsx sets it from the operator's home wallpaper) β changes live when they change Home. */
|
| 391 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-chat-container {
|
| 392 |
+
background-color:#0b141a !important;
|
| 393 |
+
background-image:
|
| 394 |
+
linear-gradient(180deg, rgba(11,20,26,.80) 0%, rgba(11,20,26,.74) 32%, rgba(11,20,26,.78) 68%, rgba(11,20,26,.86) 100%),
|
| 395 |
+
var(--wp-img) !important;
|
| 396 |
+
background-repeat:no-repeat, no-repeat !important;
|
| 397 |
+
background-size:cover, cover !important;
|
| 398 |
+
background-position:center center, center center !important; }
|
| 399 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .cs-message-list {
|
| 400 |
+
background:transparent !important; background-color:transparent !important; background-image:none !important; }
|
| 401 |
+
|
| 402 |
+
/* ββ COHERENT RUNTIME-SWITCH TRANSITION (whatsapp-runtime-switch-v1) β every switch between holospaces (and Homeβchat)
|
| 403 |
+
is now ONE clean, low-latency crossfade, not several animations fighting. The old build layered THREE systems on
|
| 404 |
+
each switch: (1) the View-Transition root crossfade; (2) a ONE-SIDED `holo-wall` wallpaper morph β the Home wall
|
| 405 |
+
carried view-transition-name:holo-wall but the destination holospace has no matching element (its backdrop is
|
| 406 |
+
hidden), so the wallpaper visibly slid/scaled to nothing ("the background wallpaper feels strange"); (3) a matching
|
| 407 |
+
one-sided `holo-q-orb` morph AND the space layer's OWN opacity fade doubling the root crossfade. Collapse to ONE
|
| 408 |
+
animation: the wall + orb stop morphing (they ride the single root crossfade) and the space layer stops
|
| 409 |
+
self-animating (keep only its drawer-resize `right` glide). Result: identical crisp ~.2s crossfade for ALL apps
|
| 410 |
+
β smooth, robust, coherent. Reduced-motion users still get the instant, no-animation path (unchanged). */
|
| 411 |
+
html[data-skin="whatsapp"] .holo-home-wall,
|
| 412 |
+
html[data-skin="whatsapp"] .holo-wa-root.wall-on .holo-backdrop,
|
| 413 |
+
html[data-skin="whatsapp"] .holo-home-orb,
|
| 414 |
+
html[data-skin="whatsapp"] .holo-global-orb { view-transition-name:none !important; }
|
| 415 |
+
html[data-skin="whatsapp"]::view-transition-old(root),
|
| 416 |
+
html[data-skin="whatsapp"]::view-transition-new(root) {
|
| 417 |
+
animation-duration:.2s !important; animation-timing-function:var(--holo-env-ease, cubic-bezier(.4,0,.2,1)) !important; }
|
| 418 |
+
html[data-skin="whatsapp"] .holo-space-layer {
|
| 419 |
+
transition:right .26s var(--holo-ease, cubic-bezier(.4,0,.2,1)) !important; }
|
| 420 |
+
|
| 421 |
+
/* ββ RESIZABLE SIDEBAR (whatsapp-resize-v1) β the divider between the chat list and the conversation is now a
|
| 422 |
+
draggable handle, WhatsApp-desktop style. Width lives in one var (--holo-side-w) so the sidebar AND the handle
|
| 423 |
+
track it together; the enhancer in messenger-skin.mjs sets it on drag and persists to localStorage (returning
|
| 424 |
+
users reopen at their width). Default 34% when unset. Desktop only; hidden on mobile / home / a live holospace /
|
| 425 |
+
collapsed / expanded so it never floats over the wrong surface. */
|
| 426 |
+
@media (min-width:900px) {
|
| 427 |
+
html[data-skin="whatsapp"] .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .cs-sidebar.cs-sidebar--left {
|
| 428 |
+
flex:0 0 var(--holo-side-w, 34%) !important;
|
| 429 |
+
min-width:var(--holo-side-w, 34%) !important;
|
| 430 |
+
max-width:var(--holo-side-w, 34%) !important; }
|
| 431 |
+
html[data-skin="whatsapp"] .holo-wa-root:not(.theater) .cs-main-container > .holo-side-resize {
|
| 432 |
+
position:absolute; top:0; bottom:0; left:var(--holo-side-w, 34%); width:9px; margin-left:-5px;
|
| 433 |
+
z-index:46; cursor:col-resize; touch-action:none; }
|
| 434 |
+
html[data-skin="whatsapp"] .holo-side-resize::after {
|
| 435 |
+
content:""; position:absolute; top:0; bottom:0; left:50%; width:1px; transform:translateX(-.5px);
|
| 436 |
+
background:transparent; transition:background .15s ease, box-shadow .15s ease; }
|
| 437 |
+
html[data-skin="whatsapp"] .holo-side-resize:hover::after,
|
| 438 |
+
html[data-skin="whatsapp"] .holo-side-resize.holo-drag::after {
|
| 439 |
+
background:var(--holo-accent, #00a884); box-shadow:0 0 0 1px var(--holo-accent, #00a884); }
|
| 440 |
+
}
|
| 441 |
+
html[data-skin="whatsapp"] .holo-wa-root.home-open .holo-side-resize,
|
| 442 |
+
html[data-skin="whatsapp"] .holo-wa-root.space-active .holo-side-resize,
|
| 443 |
+
html[data-skin="whatsapp"] .holo-main.frame-collapsed .holo-side-resize,
|
| 444 |
+
html[data-holo-expanded] .holo-side-resize { display:none !important; }
|
| 445 |
+
@media (max-width:899px) { html[data-skin="whatsapp"] .holo-side-resize { display:none !important; } }
|
| 446 |
+
/* while dragging: kill the sidebar's width easing (so the panel tracks the pointer 1:1, zero lag) and stop the chat
|
| 447 |
+
iframe from swallowing pointermove; the whole document shows the col-resize cursor. */
|
| 448 |
+
body.holo-side-dragging { cursor:col-resize !important; user-select:none !important; }
|
| 449 |
+
body.holo-side-dragging .cs-sidebar { transition:none !important; }
|
| 450 |
+
body.holo-side-dragging iframe { pointer-events:none !important; }
|
| 451 |
+
|
| 452 |
+
/* ββ COMPOSER TRACKS THE DIVIDER (whatsapp-resize-v1) β the bottom entry bar and every chat-area overlay
|
| 453 |
+
(composer, its context + suggested-reply rows, the in-chat find bar, and the attach / emoji / sticker
|
| 454 |
+
popovers) are position:absolute children of the full-width .holo-main, pinned to the OLD fixed 34% list
|
| 455 |
+
edge. When the divider dragged the sidebar to --holo-side-w they stayed stranded at 34%, so the whole
|
| 456 |
+
bottom text field detached from the conversation column β the broken UX. Re-point their left to the SAME
|
| 457 |
+
var the sidebar uses, under the SAME guard as the sidebar-resize rule (desktop β₯900px, whatsapp skin, not
|
| 458 |
+
theater / collapsed / fullscreen-expanded) so the composer and popovers stay flush with the resized column.
|
| 459 |
+
Unset β 34% (identical to before); set β the dragged px width. No drag = zero change. */
|
| 460 |
+
@media (min-width:900px) {
|
| 461 |
+
html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-composer,
|
| 462 |
+
html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-compose-ctx,
|
| 463 |
+
html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-suggest,
|
| 464 |
+
html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-find {
|
| 465 |
+
left:var(--holo-side-w, 34%) !important; }
|
| 466 |
+
html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-emoji-pop,
|
| 467 |
+
html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-attach-menu,
|
| 468 |
+
html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-sticker-pop {
|
| 469 |
+
left:calc(var(--holo-side-w, 34%) + 8px) !important; }
|
| 470 |
+
html[data-skin="whatsapp"]:not([data-holo-expanded]) .holo-wa-root:not(.theater) .holo-main:not(.frame-collapsed) .holo-emoji-btn {
|
| 471 |
+
left:calc(var(--holo-side-w, 34%) + 12px) !important; }
|
| 472 |
+
}
|
| 473 |
+
|
| 474 |
+
/* ββ AIM SKIN β data-skin="aim" (A0). The original 1999 instant-messenger feeling, reborn: warm platinum
|
| 475 |
+
* chrome, raised-bevel edges, sharp small type (Tahoma), the yellow accent, a classic blue title bar on the
|
| 476 |
+
* open conversation. Opt-in only (?skin=aim or localStorage holo.skin=aim); every other skin is untouched.
|
| 477 |
+
* NO AOL property β homage through shape, rhythm and sound character, all marks and sounds are ours.
|
| 478 |
+
* The experience layer (buddy list / sign-on / away / door sounds) is holo-aim.mjs; these are its clothes.
|
| 479 |
+
* Placed at end-of-file so source order beats the base skin block (equal specificity β later wins). ββ */
|
| 480 |
+
html[data-skin="aim"] .holo-wa-root {
|
| 481 |
+
--wa-bg:#d6d2c8; --wa-side:#ffffff; --wa-head:#ece9d8; --wa-in:#ffffff; --wa-out:#fff3b8;
|
| 482 |
+
--wa-ink:#141414; --wa-dim:#5a5950; --wa-accent:#e8b800; --wa-line:#aca899;
|
| 483 |
+
font-family: Tahoma, Verdana, "Segoe UI", system-ui, sans-serif;
|
| 484 |
+
}
|
| 485 |
+
/* light-skin honesty: deep-hardcoded dark-theme text must flip dark-on-light (the "light" skin precedent) */
|
| 486 |
+
html[data-skin="aim"] .holo-wa-root .cs-message__content { color:#141414 !important; }
|
| 487 |
+
html[data-skin="aim"] .holo-wa-root .cs-message-list { background:var(--wa-bg) !important; background-image:none !important; }
|
| 488 |
+
html[data-skin="aim"] .holo-wa-root .holo-wp-tile { background-image:none !important; }
|
| 489 |
+
html[data-skin="aim"] .holo-wa-root .holo-backdrop, html[data-skin="aim"] .holo-wa-root .holo-wall-scrim { display:none !important; }
|
| 490 |
+
/* the classic window: bevel edges, sharp corners, small crisp type */
|
| 491 |
+
html[data-skin="aim"] .holo-wa-root .cs-sidebar.cs-sidebar--left { border-right:1px solid var(--wa-line) !important; }
|
| 492 |
+
html[data-skin="aim"] .holo-wa-root .cs-conversation__name { font-size:12.5px !important; }
|
| 493 |
+
html[data-skin="aim"] .holo-wa-root .cs-message__content { border-radius:4px !important; border:1px solid #c9c5b8; font-size:13px; }
|
| 494 |
+
html[data-skin="aim"] .holo-wa-root .holo-c-input,
|
| 495 |
+
html[data-skin="aim"] .holo-wa-root .cs-search,
|
| 496 |
+
html[data-skin="aim"] .holo-wa-root .cs-message-input__content-editor-wrapper,
|
| 497 |
+
html[data-skin="aim"] .holo-wa-root .cs-message-input__content-editor { border-radius:3px !important; background:#ffffff !important; color:#141414 !important; border:1px solid #7f9db9 !important; }
|
| 498 |
+
/* the conversation header = the classic blue title bar, white text */
|
| 499 |
+
html[data-skin="aim"] .holo-wa-root .cs-conversation-header { background:linear-gradient(180deg,#0a246a,#3a6ea5) !important; border-bottom:1px solid #002050 !important; }
|
| 500 |
+
html[data-skin="aim"] .holo-wa-root .cs-conversation-header__user-name,
|
| 501 |
+
html[data-skin="aim"] .holo-wa-root .cs-conversation-header__info { color:#ffffff !important; }
|
| 502 |
+
html[data-skin="aim"] .holo-wa-root .holo-c-send,
|
| 503 |
+
html[data-skin="aim"] .holo-wa-root .cs-button--send { background:var(--wa-accent) !important; color:#141414 !important; border-radius:3px !important; }
|
| 504 |
+
/* the Buddy List replaces the Direct section β ONE surface (holo-aim.mjs renders it) */
|
| 505 |
+
html[data-skin="aim"] .holo-wa-root .holo-direct-section { display:none !important; }
|
| 506 |
+
/* ββ the Buddy List ββ */
|
| 507 |
+
html[data-skin="aim"] .holo-aim-buddylist { display:flex; flex-direction:column; background:#ffffff; border:1px solid var(--wa-line); border-radius:3px; margin:6px 8px; font:12px Tahoma, Verdana, sans-serif; color:#141414; overflow:hidden; }
|
| 508 |
+
html[data-skin="aim"] .holo-aim-head { display:flex; align-items:center; gap:6px; padding:6px 8px; background:linear-gradient(180deg,#fff3b8,#f7c923); border-bottom:1px solid #cfa900; font-weight:700; }
|
| 509 |
+
html[data-skin="aim"] .holo-aim-mark { font-size:13px; }
|
| 510 |
+
html[data-skin="aim"] .holo-aim-me { flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
| 511 |
+
html[data-skin="aim"] .holo-aim-mystate { font-weight:400; color:#5a5950; font-size:11px; }
|
| 512 |
+
html[data-skin="aim"] .holo-aim-mystate.online { color:#0a7d20; }
|
| 513 |
+
html[data-skin="aim"] .holo-aim-mystate.away { color:#a05a00; }
|
| 514 |
+
html[data-skin="aim"] .holo-aim-away-btn, html[data-skin="aim"] .holo-aim-return { font:11px Tahoma, sans-serif; background:#ece9d8; border:1px solid #aca899; border-radius:3px; padding:2px 8px; cursor:pointer; }
|
| 515 |
+
html[data-skin="aim"] .holo-aim-awaybar { padding:4px 10px; background:#fffbe0; border-bottom:1px solid #e8dfa0; color:#7a6a00; font-style:italic; font-size:11.5px; }
|
| 516 |
+
html[data-skin="aim"] .holo-aim-group { padding:4px 8px; background:#ece9d8; border-top:1px solid #d9d5c8; font-weight:700; font-size:11.5px; cursor:pointer; user-select:none; }
|
| 517 |
+
html[data-skin="aim"] .holo-aim-tri { color:#5a5950; }
|
| 518 |
+
html[data-skin="aim"] .holo-aim-buddy { display:flex; align-items:center; gap:6px; width:100%; text-align:left; background:transparent; border:0; padding:3px 10px 3px 16px; cursor:pointer; font:12px Tahoma, sans-serif; color:#141414; }
|
| 519 |
+
html[data-skin="aim"] .holo-aim-buddy:hover { background:#316ac5; color:#ffffff; }
|
| 520 |
+
html[data-skin="aim"] .holo-aim-buddy:hover .holo-aim-info { color:#ffffff; }
|
| 521 |
+
html[data-skin="aim"] .holo-aim-buddy.online .holo-aim-bname { font-weight:700; }
|
| 522 |
+
html[data-skin="aim"] .holo-aim-buddy.idle .holo-aim-bname { color:#7a7a72; }
|
| 523 |
+
html[data-skin="aim"] .holo-aim-buddy.idle:hover .holo-aim-bname { color:#e6e6e6; }
|
| 524 |
+
html[data-skin="aim"] .holo-aim-bname { flex:1; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
| 525 |
+
html[data-skin="aim"] .holo-aim-dot { width:8px; height:8px; border-radius:50%; flex:0 0 auto; background:#b8b4a6; }
|
| 526 |
+
html[data-skin="aim"] .holo-aim-dot.online { background:#22a834; box-shadow:0 0 2px #22a834; }
|
| 527 |
+
html[data-skin="aim"] .holo-aim-dot.idle { background:#e8b800; }
|
| 528 |
+
html[data-skin="aim"] .holo-aim-dot.away { background:#e07800; }
|
| 529 |
+
html[data-skin="aim"] .holo-aim-note { color:#a05a00; flex:0 0 auto; }
|
| 530 |
+
html[data-skin="aim"] .holo-aim-info { color:#8a887c; flex:0 0 auto; font-size:11px; cursor:pointer; }
|
| 531 |
+
/* ββ sign-on + sheets + toast (spawned only under the aim skin) ββ */
|
| 532 |
+
.holo-aim-signon, .holo-aim-awaysheet { position:fixed; inset:0; z-index:2147483400; background:rgba(30,28,20,.45); display:flex; align-items:center; justify-content:center; font:13px Tahoma, Verdana, sans-serif; }
|
| 533 |
+
.holo-aim-signon-card, .holo-aim-away-card { width:min(300px,92vw); background:#ece9d8; border:1px solid #716f64; border-radius:4px; box-shadow:0 10px 34px rgba(0,0,0,.4), inset 0 1px 0 #fff; padding:14px; display:flex; flex-direction:column; gap:8px; color:#141414; }
|
| 534 |
+
.holo-aim-signon-mark { font-weight:700; font-size:15px; padding-bottom:4px; border-bottom:1px solid #cfcbba; }
|
| 535 |
+
.holo-aim-signon-card label, .holo-aim-info-grouplab { font-size:11px; color:#5a5950; }
|
| 536 |
+
.holo-aim-sn, .holo-aim-away-msg, .holo-aim-info-group { font:13px Tahoma, sans-serif; background:#fff; border:1px solid #7f9db9; border-radius:2px; padding:5px 7px; color:#141414; }
|
| 537 |
+
.holo-aim-away-msg { height:56px; resize:none; }
|
| 538 |
+
.holo-aim-go, .holo-aim-away-go { background:linear-gradient(180deg,#fff3b8,#f7c923); border:1px solid #cfa900; border-radius:3px; padding:6px; font:700 13px Tahoma, sans-serif; cursor:pointer; }
|
| 539 |
+
.holo-aim-skip, .holo-aim-away-x { background:transparent; border:0; color:#5a5950; cursor:pointer; font:11px Tahoma, sans-serif; }
|
| 540 |
+
.holo-aim-away-title { font-weight:700; }
|
| 541 |
+
.holo-aim-away-presets { display:flex; flex-wrap:wrap; gap:4px; }
|
| 542 |
+
.holo-aim-away-presets button { font:11px Tahoma, sans-serif; background:#fff; border:1px solid #aca899; border-radius:3px; padding:2px 6px; cursor:pointer; }
|
| 543 |
+
.holo-aim-away-row { display:flex; gap:8px; align-items:center; justify-content:flex-end; }
|
| 544 |
+
.holo-aim-info-name { font-weight:700; display:flex; align-items:center; gap:6px; }
|
| 545 |
+
.holo-aim-info-name .holo-aim-dot { width:8px; height:8px; border-radius:50%; background:#b8b4a6; display:inline-block; }
|
| 546 |
+
.holo-aim-info-name .holo-aim-dot.online { background:#22a834; } .holo-aim-info-name .holo-aim-dot.idle { background:#e8b800; } .holo-aim-info-name .holo-aim-dot.away { background:#e07800; }
|
| 547 |
+
.holo-aim-info-state { font-weight:400; font-size:11px; color:#5a5950; }
|
| 548 |
+
.holo-aim-info-away { font-style:italic; color:#7a6a00; background:#fffbe0; border:1px solid #e8dfa0; border-radius:3px; padding:4px 7px; }
|
| 549 |
+
.holo-aim-info-verify { font-size:11.5px; color:#3a3a34; }
|
| 550 |
+
.holo-aim-info-profile { background:linear-gradient(180deg,#dce9f7,#a6caf0); border:1px solid #3a6ea5; border-radius:3px; padding:5px 9px; font:700 12px Tahoma, sans-serif; cursor:pointer; }
|
| 551 |
+
.holo-aim-toast { position:fixed; bottom:24px; left:50%; transform:translateX(-50%); z-index:2147483300; background:#ece9d8; border:1px solid #716f64; border-radius:4px; box-shadow:0 8px 24px rgba(0,0,0,.35); padding:7px 14px; font:12px Tahoma, Verdana, sans-serif; color:#141414; }
|
sha256/eb343aaebd5beec6186750769cdd48ddde4440b78f92d46c2cb851e893237944
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"use client";import{$,$a,A,Aa,Ab,B,Ba,Bb,C,Ca,Cb,D,Da,Db,E,Ea,Eb,F,Fa,Fb,G,Ga,Gb,H,Ha,Hb,I,Ia,Ib,J,Ja,Jb,K,Ka,Kb,L,La,Lb,M,Ma,Mb,N,Na,Nb,O,Oa,Ob,P,Pa,Pb,Q,Qa,Qb,R,Ra,Rb,S,Sa,Sb,T,Ta,Tb,U,Ua,Ub,V,Va,W,Wa,X,Xa,Y,Ya,Z,Za,_,_a,a,aa,ab,b,ba,bb,c,ca,cb,d,da,db,e,ea,eb,f,fa,fb,g,ga,gb,h,ha,hb,i,ia,ib,j,ja,jb,k,ka,kb,l,la,lb,m,ma,mb,n,na,nb,o,oa,ob,p,pa,pb,q,qa,qb,r,ra,rb,s,sa,sb,t,ta,tb,u,ua,ub,v,va,vb,w,wa,wb,x,xa,xb,y,ya,yb,z,za,zb}from"./chunk-E6U7U64M.js";import"./chunk-SXSU3V5W.js";import"./chunk-EJ2FITLI.js";import"./chunk-SQE76S5B.js";export{Fa as A11yContext,Ha as A11yContextProvider,K as ACTION_CLOSE,I as ACTION_NEXT,H as ACTION_PREV,J as ACTION_SWIPE,z as ACTIVE_SLIDE_COMPLETE,y as ACTIVE_SLIDE_ERROR,w as ACTIVE_SLIDE_LOADING,x as ACTIVE_SLIDE_PLAYING,B as CLASS_FLEX_CENTER,A as CLASS_FULLSIZE,C as CLASS_NO_SCROLL,D as CLASS_NO_SCROLL_PADDING,E as CLASS_SLIDE,F as CLASS_SLIDE_WRAPPER,G as CLASS_SLIDE_WRAPPER_INTERACTIVE,Fb as Carousel,Gb as CarouselModule,db as CloseIcon,Db as Controller,Bb as ControllerContext,Eb as ControllerModule,Ia as DocumentContext,Ka as DocumentContextProvider,W as ELEMENT_BUTTON,X as ELEMENT_ICON,Q as EVENT_ON_KEY_DOWN,R as EVENT_ON_KEY_UP,P as EVENT_ON_POINTER_CANCEL,L as EVENT_ON_POINTER_DOWN,O as EVENT_ON_POINTER_LEAVE,M as EVENT_ON_POINTER_MOVE,N as EVENT_ON_POINTER_UP,S as EVENT_ON_WHEEL,hb as ErrorIcon,La as EventsContext,Na as EventsProvider,Y as IMAGE_FIT_CONTAIN,Z as IMAGE_FIT_COVER,ab as IconButton,ub as ImageSlide,Ub as Lightbox,Ba as LightboxDefaultProps,Ta as LightboxDispatchContext,Oa as LightboxPropsContext,Qa as LightboxPropsProvider,vb as LightboxRoot,Ra as LightboxStateContext,Va as LightboxStateProvider,gb as LoadingIcon,a as MODULE_CAROUSEL,b as MODULE_CONTROLLER,c as MODULE_NAVIGATION,d as MODULE_NO_SCROLL,e as MODULE_PORTAL,f as MODULE_ROOT,g as MODULE_TOOLBAR,Kb as Navigation,Jb as NavigationButton,Lb as NavigationModule,fb as NextIcon,Mb as NoScroll,Nb as NoScrollModule,h as PLUGIN_CAPTIONS,i as PLUGIN_COUNTER,j as PLUGIN_DOWNLOAD,k as PLUGIN_FULLSCREEN,l as PLUGIN_INLINE,m as PLUGIN_SHARE,n as PLUGIN_SLIDESHOW,o as PLUGIN_THUMBNAILS,p as PLUGIN_ZOOM,Ob as Portal,Pb as PortalModule,eb as PreviousIcon,Wa as RTLContext,Ya as RTLContextProvider,Qb as Root,Rb as RootModule,t as SLIDE_STATUS_COMPLETE,s as SLIDE_STATUS_ERROR,q as SLIDE_STATUS_LOADING,u as SLIDE_STATUS_PLACEHOLDER,r as SLIDE_STATUS_PLAYING,wb as SwipeState,Za as TimeoutsContext,$a as TimeoutsProvider,Sb as Toolbar,Tb as ToolbarModule,_ as UNKNOWN_ACTION_TYPE,U as VK_ARROW_LEFT,V as VK_ARROW_RIGHT,T as VK_ESCAPE,v as activeSlideStatus,wa as addToolbarButton,ya as calculatePreload,ha as cleanup,$ as clsx,ca as composePrefix,pa as computeSlideRect,bb as createIcon,cb as createIconDisabled,Ca as createModule,Da as createNode,aa as cssClass,ba as cssVar,Ub as default,qa as devicePixelRatio,ta as getSlide,ua as getSlideIfPresent,ra as getSlideIndex,va as getSlideKey,sa as hasSlides,ja as hasWindow,ma as isImageFitCover,la as isImageSlide,fa as label,da as makeComposePrefix,za as makeInertWhen,ia as makeUseContext,na as parseInt,oa as parseLengthPercentage,Aa as reflow,ka as round,ob as setRef,xa as stopNavigationEventsPropagation,ea as translateLabel,ga as translateSlideCounter,Ga as useA11yContext,kb as useAnimation,lb as useContainerRect,Cb as useController,mb as useDelay,Ja as useDocumentContext,nb as useEventCallback,Ma as useEvents,pb as useForkRef,Ib as useKeyboardNavigation,ib as useLayoutEffect,Ua as useLightboxDispatch,Pa as useLightboxProps,Sa as useLightboxState,qb as useLoseFocus,jb as useMotionPreference,Hb as useNavigationState,xb as usePointerEvents,yb as usePointerSwipe,zb as usePreventWheelDefaults,rb as useRTL,Xa as useRTLContext,sb as useSensors,tb as useThrottle,_a as useTimeouts,Ab as useWheelSwipe,Ea as withPlugins};
|