@omniharmonic/openspace-renderer 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 The OpenSpace contributors
4
+
5
+ This license covers everything in this repository except where a directory
6
+ states otherwise: apps/studio and apps/hub are licensed under AGPL-3.0-only
7
+ (see LICENSE-AGPL), and documentation and template designs are licensed under
8
+ CC-BY-4.0.
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,11 @@
1
- # Temporary Holding Version
1
+ # @omniharmonic/openspace-renderer
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ React page/section/block renderer, the base stylesheet (`/os.css`), HTML documents and the vanilla behaviors (`/behaviors/*`).
4
+
5
+ Part of [OpenSpace](https://github.com/omniharmonic/openspace), an open-source website builder. Most sites only depend on `@omniharmonic/openspace-site-kit` (and `@omniharmonic/openspace-cli` as a dev dependency); the other packages come along as its dependencies.
6
+
7
+ Versions of the OpenSpace packages are released in lockstep.
8
+
9
+ ## License
10
+
11
+ MIT
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Behavior manifest (browser-safe). Each behavior is a vanilla ES module with a default export
3
+ * `init(el: HTMLElement)`, attached by `data-os-behavior="<name>"` (several names may be
4
+ * space-separated). The loader `os-behaviors.js` finds those elements and imports only the
5
+ * modules the page uses, from its own directory.
6
+ */
7
+ declare const BEHAVIORS: readonly ["carousel", "lightbox", "accordion", "tabs", "marquee", "reveal", "menu", "popup", "announcement", "form", "newsletter", "video-lite", "search", "cart", "beacon"];
8
+ type BehaviorName = (typeof BEHAVIORS)[number];
9
+ /** File name (without `.js`) of the loader that auto-initialises behaviors. */
10
+ declare const BEHAVIOR_LOADER = "os-behaviors";
11
+ /** Gzipped size budgets in bytes (Global Constraint 4; arch §4.2, §9.3). */
12
+ declare const BEHAVIOR_BUDGETS: Record<BehaviorName | typeof BEHAVIOR_LOADER, number>;
13
+ declare function isBehaviorName(name: string): name is BehaviorName;
14
+ /** Behaviors referenced in rendered HTML, in manifest order (unknown names ignored). */
15
+ declare function behaviorsInHtml(html: string): BehaviorName[];
16
+
17
+ declare const BASE_CSS: string;
18
+
19
+ export { type BehaviorName as B, BASE_CSS as a, BEHAVIORS as b, BEHAVIOR_BUDGETS as c, BEHAVIOR_LOADER as d, behaviorsInHtml as e, isBehaviorName as i };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Behavior manifest (browser-safe). Each behavior is a vanilla ES module with a default export
3
+ * `init(el: HTMLElement)`, attached by `data-os-behavior="<name>"` (several names may be
4
+ * space-separated). The loader `os-behaviors.js` finds those elements and imports only the
5
+ * modules the page uses, from its own directory.
6
+ */
7
+ declare const BEHAVIORS: readonly ["carousel", "lightbox", "accordion", "tabs", "marquee", "reveal", "menu", "popup", "announcement", "form", "newsletter", "video-lite", "search", "cart", "beacon", "before-after", "countdown"];
8
+ type BehaviorName = (typeof BEHAVIORS)[number];
9
+ /** File name (without `.js`) of the loader that auto-initialises behaviors. */
10
+ declare const BEHAVIOR_LOADER = "os-behaviors";
11
+ /** Gzipped size budgets in bytes (Global Constraint 4; arch §4.2, §9.3). */
12
+ declare const BEHAVIOR_BUDGETS: Record<BehaviorName | typeof BEHAVIOR_LOADER, number>;
13
+ declare function isBehaviorName(name: string): name is BehaviorName;
14
+ /** Behaviors referenced in rendered HTML, in manifest order (unknown names ignored). */
15
+ declare function behaviorsInHtml(html: string): BehaviorName[];
16
+
17
+ declare const BASE_CSS: string;
18
+
19
+ export { type BehaviorName as B, BASE_CSS as a, BEHAVIORS as b, BEHAVIOR_BUDGETS as c, BEHAVIOR_LOADER as d, behaviorsInHtml as e, isBehaviorName as i };
@@ -0,0 +1 @@
1
+ var c=()=>typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches;function d(s){let o=[...s.querySelectorAll("details")],u=s.hasAttribute("data-os-exclusive"),i=t=>{if(u)for(let e of o)e!==t&&e.open&&(e.open=!1)};for(let t of o){let e=t.querySelector("summary"),n=e?.nextElementSibling;e?.addEventListener("click",l=>{if(c()||!n||typeof n.animate!="function"){t.open||i(t);return}l.preventDefault();let a={duration:260,easing:"cubic-bezier(0.2, 0, 0, 1)"};t.open?n.animate({height:[`${n.offsetHeight}px`,"0px"],opacity:[1,0]},a).onfinish=()=>{t.open=!1}:(i(t),t.open=!0,n.animate({height:["0px",`${n.offsetHeight}px`],opacity:[0,1]},a))})}let r=location.hash.slice(1);if(r){let t=o.find(e=>e.id===r);t&&(t.open=!0)}}export{d as default};
@@ -0,0 +1 @@
1
+ function o(t,e){try{let n=localStorage.getItem(t);return n===null?e:JSON.parse(n)}catch{return e}}function r(t,e){try{localStorage.setItem(t,JSON.stringify(e))}catch{}}function s(t){let e=`os-announcement:${t.dataset.osKey??""}`;if(o(e,!1)){t.hidden=!0;return}t.querySelector("[data-os-dismiss]")?.addEventListener("click",()=>{t.hidden=!0,r(e,!0)})}export{s as default};
@@ -0,0 +1 @@
1
+ function u(s){let{osHub:e,osSite:t}=s.dataset;if(!e||!t||navigator.webdriver)return;let d=new URLSearchParams(location.search),o={};for(let a of["source","medium","campaign","term","content"]){let i=d.get(`utm_${a}`);i&&(o[a]=i)}let n=innerWidth,r=JSON.stringify({p:location.pathname,r:document.referrer&&new URL(document.referrer).host!==location.host?document.referrer:"",s:n<768?"m":n<1200?"t":"d",u:o}),c=`${e}/a/${t}`;navigator.sendBeacon?.(c,r)||fetch(c,{method:"POST",body:r,keepalive:!0}).catch(()=>{})}export{u as default};
@@ -0,0 +1 @@
1
+ function f(e){let t=e.querySelector("input[type=range]");if(!t)return;let n=e.dataset.osBefore||"Before",r=e.dataset.osAfter||"After",s=()=>{let a=Math.max(0,Math.min(100,Number(t.value)||0));e.style.setProperty("--pos",`${a}%`),t.setAttribute("aria-valuetext",`${a}% ${n}, ${100-a}% ${r}`)};t.addEventListener("input",s),s(),e.classList.add("is-ready")}export{f as default};
@@ -0,0 +1 @@
1
+ function u(n){let e=n.querySelector(".os-carousel__track");if(!e)return;let r=n.querySelector("[data-os-prev]"),l=n.querySelector("[data-os-next]");e.hasAttribute("tabindex")||(e.tabIndex=0);let c=()=>{let t=e.firstElementChild,d=Number.parseFloat(getComputedStyle(e).columnGap)||0,i=t?t.offsetWidth+d:e.clientWidth;return Math.max(i,Math.floor(e.clientWidth/i)*i)},o=t=>e.scrollBy({left:t*c(),behavior:"smooth"}),s=0,a=()=>{s=0;let t=e.scrollWidth-e.clientWidth-2;r&&(r.disabled=e.scrollLeft<=2),l&&(l.disabled=e.scrollLeft>=t)};r?.addEventListener("click",()=>o(-1)),l?.addEventListener("click",()=>o(1)),e.addEventListener("scroll",()=>{s||(s=requestAnimationFrame(a))},{passive:!0}),e.addEventListener("keydown",t=>{(t.key==="ArrowRight"||t.key==="ArrowLeft")&&(t.preventDefault(),o(t.key==="ArrowRight"?1:-1))}),a()}export{u as default};
@@ -0,0 +1 @@
1
+ function L(t,o){try{let s=localStorage.getItem(t);return s===null?o:JSON.parse(s)}catch{return o}}function g(t,o){try{localStorage.setItem(t,JSON.stringify(o))}catch{}}function M(){let t=document.body.dataset;return{site:t.osSite??"",hub:t.osHub??"",base:t.osBase??""}}function a(t,o={},...s){let n=document.createElement(t);for(let[e,r]of Object.entries(o))n.setAttribute(e,r);return n.append(...s),n}function T(t){let o="http://www.w3.org/2000/svg",s=document.createElementNS(o,"svg");s.setAttribute("viewBox","0 0 24 24"),s.setAttribute("width","20"),s.setAttribute("height","20"),s.setAttribute("aria-hidden","true");let n=document.createElementNS(o,"path");return n.setAttribute("d",t),n.setAttribute("fill","none"),n.setAttribute("stroke","currentColor"),n.setAttribute("stroke-width","1.6"),n.setAttribute("stroke-linecap","round"),s.append(n),s}var _="M6 6l12 12M18 6L6 18";var I=()=>M(),m=()=>`os-cart:${I().site}`,N=[],u,O=()=>{if(u===void 0)try{localStorage.setItem("os-probe","1"),localStorage.removeItem("os-probe"),u=!0}catch{u=!1}return u},f=()=>(O()?L(m(),[]):N).filter(t=>t?.sku&&t.qty>0),w=t=>{N=t,g(m(),t),p()},v,k,E,i,l,d,q=!1,x=(t,o)=>{try{return new Intl.NumberFormat(document.documentElement.lang||void 0,{style:"currency",currency:o}).format(t/100)}catch{return`${(t/100).toFixed(2)} ${o}`}};function $(t){d||(d=a("div",{class:"os-visually-hidden",role:"status","aria-live":"polite"}),document.body.append(d)),d.textContent=t}function C(t,o){let s=f(),n=s.find(e=>e.sku===t);n&&(n.qty=Math.max(0,Math.min(99,o))),w(s.filter(e=>e.qty>0))}function p(){let t=f(),o=t.reduce((n,e)=>n+e.qty,0);for(let n of document.querySelectorAll("[data-os-cart-count]"))n.textContent=o?String(o):"";for(let n of document.querySelectorAll("[data-os-cart-toggle]"))n.setAttribute("aria-label",o?`Cart, ${o} item${o===1?"":"s"}`:"Cart");if(!v)return;k.replaceChildren(...t.length?t.map(n=>{let e=a("button",{type:"button","aria-label":`Remove one ${n.name}`},"\u2212"),r=a("button",{type:"button","aria-label":`Add one ${n.name}`},"+");return e.addEventListener("click",()=>C(n.sku,n.qty-1)),r.addEventListener("click",()=>C(n.sku,n.qty+1)),a("div",{class:"os-cart__item"},a("span",{class:"os-cart__name"},n.name),a("span",{class:"os-cart__price"},x(n.price*n.qty,n.currency)),a("span",{class:"os-cart__qty"},e,a("span",{"aria-label":"Quantity"},String(n.qty)),r))}):[a("p",{class:"os-muted"},"Your cart is empty.")]);let s=t[0]?.currency??"USD";E.replaceChildren(a("span",{},"Subtotal"),a("span",{},x(t.reduce((n,e)=>n+e.price*e.qty,0),s))),l.disabled=t.length===0}function P(){k=a("div",{class:"os-cart__items"}),E=a("div",{class:"os-cart__total"}),i=a("p",{class:"os-form__status",role:"alert"}),l=a("button",{type:"button",class:"os-button os-button--primary"},"Check out");let t=a("button",{type:"button",class:"os-menu__close","aria-label":"Close cart"},T(_)),o=a("dialog",{class:"os-cart","aria-labelledby":"os-cart-title"},a("div",{class:"os-cart__inner"},a("div",{class:"os-cart__head"},a("h2",{id:"os-cart-title",class:"os-type-h4"},"Your cart"),t),k,a("div",{class:"os-cart__foot"},E,a("p",{class:"os-muted os-type-small"},"Shipping and taxes are calculated at checkout."),i,l)));return t.addEventListener("click",()=>o.close()),o.addEventListener("click",s=>{s.target===o&&o.close()}),l.addEventListener("click",async()=>{let{hub:s,site:n}=I();l.disabled=!0,i.textContent="",i.dataset.state="";try{let e=await fetch(`${s}/c/${n}/checkout`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({items:f().map(c=>({sku:c.sku,qty:c.qty})),successUrl:`${location.origin}${location.pathname}?os_checkout=success`,cancelUrl:location.href})}),r=await e.json().catch(()=>({}));if(e.ok&&r.url){location.assign(r.url);return}throw new Error(r.message??"Checkout is unavailable right now.")}catch(e){i.dataset.state="error",i.textContent=e instanceof Error&&e.message?e.message:"Checkout is unavailable right now.",l.disabled=!1}}),document.body.append(o),o}function A(){v??(v=P()),p(),v.showModal()}function K(t){if(q||(q=!0,new URLSearchParams(location.search).get("os_checkout")==="success"&&g(m(),[]),addEventListener("storage",o=>{o.key===m()&&p()})),t.hasAttribute("data-os-cart-toggle")&&t.addEventListener("click",A),t.hasAttribute("data-os-add")){let o=t.dataset.osSkuInput,s=t.dataset.osImageTarget,n=o?document.querySelector(o):null;n&&s&&n.addEventListener("change",()=>{let e=n.selectedOptions[0]?.dataset.osImage,r=document.querySelector(s);if(!e||!r)return;for(let b of r.querySelectorAll("source"))b.srcset=e;let c=r.querySelector("img");c&&(c.removeAttribute("srcset"),c.src=e)}),t.addEventListener("click",()=>{let e={...t.dataset},c=(e.osSkuInput?document.querySelector(e.osSkuInput):null)?.selectedOptions[0];if(c?.value&&(e.osSku=c.value,e.osName=c.dataset.osName??e.osName,e.osPrice=c.dataset.osPrice??e.osPrice),!e.osSku)return;let b=e.osQtyInput?document.querySelector(e.osQtyInput):null,S=Math.max(1,Number(b?.value??1)||1),y=f(),h=y.find(H=>H.sku===e.osSku);h?h.qty=Math.min(99,h.qty+S):y.push({sku:e.osSku,name:e.osName??e.osSku,price:Number(e.osPrice??0),currency:e.osCurrency??"USD",qty:S}),w(y),$(`${e.osName??"Item"} added to cart`),t.hasAttribute("data-os-stay")||A()})}p()}export{K as default};
@@ -0,0 +1 @@
1
+ function m(e){let s=Date.parse(e.dataset.osTarget??"");if(Number.isNaN(s))return;let o=e.querySelector(".os-countdown__units"),a=e.querySelector(".os-countdown__done"),t=n=>e.querySelector(`[data-os-unit="${n}"]`),i=[[t("days"),86400,1e9],[t("hours"),3600,24],[t("minutes"),60,60],[t("seconds"),1,60]],r=!!i[3]?.[0],d=0,c=()=>{let n=Math.max(0,Math.floor((s-Date.now())/1e3));for(let[l,u,f]of i)l&&(l.textContent=String(Math.floor(n/u)%f).padStart(2,"0"));n===0&&(clearInterval(d),o&&(o.hidden=!0),a&&(a.hidden=!1),e.classList.add("is-done"))};c(),e.classList.contains("is-done")||(d=window.setInterval(c,r?1e3:15e3)),e.classList.add("is-ready")}export{m as default};
@@ -0,0 +1 @@
1
+ function f(n,e){try{let t=localStorage.getItem(n);return t===null?e:JSON.parse(t)}catch{return e}}function p(n,e){try{localStorage.setItem(n,JSON.stringify(e))}catch{}}function E(n,e={},...t){let s=document.createElement(n);for(let[o,i]of Object.entries(e))s.setAttribute(o,i);return s.append(...t),s}async function v(n,e){try{let t=await fetch(n,{method:"POST",body:e,headers:{Accept:"application/json"}}),s;try{s=await t.json()}catch{s=void 0}return{ok:t.ok,unreachable:t.status>=500,status:t.status,body:s}}catch{return{ok:!1,unreachable:!0,status:0,body:void 0}}}function c(n,e,t=""){let s=n.querySelector(".os-form__status");return s||(s=document.createElement("div"),s.className="os-form__status",n.append(s)),s.setAttribute("role",e==="error"?"alert":"status"),s.dataset.state=e,s.replaceChildren(t),s}function h(n,e){n.setAttribute("aria-busy",String(e));for(let t of n.querySelectorAll("button[type=submit],button:not([type])"))t.disabled=e,t.classList.toggle("is-busy",e)}var m="os-form-queue";function x(n){let e=(n.getAttribute("aria-describedby")??"").split(/\s+/);for(let t of e){let s=t?document.getElementById(t):null;if(s?.classList.contains("os-field__error"))return s}return n.closest(".os-field")?.querySelector(".os-field__error")??null}function L(n,e){n.setAttribute("aria-invalid",e?"true":"false");let t=x(n);t&&(t.textContent=e)}function A(n){let e=[...n.querySelectorAll("input[type=checkbox]")],t=e.length===0||e.some(o=>o.checked);for(let o of e)o.setAttribute("aria-invalid",t?"false":"true");let s=n.querySelector(".os-field__error");return s&&(s.textContent=t?"":n.dataset.osMessage||"Please choose at least one option."),t}function M(n){let e=n.closest("[data-os-required-group]");if(e&&n.type==="checkbox")return A(e);let t=n.checkValidity();return L(n,t?"":n.dataset.osMessage||n.validationMessage),t}async function H(){let n=f(m,[]);if(n.length===0)return;let e=[];for(let t of n){if(t.rejected===void 0){let o=await v(t.action,new URLSearchParams(t.fields));if(o.ok)continue;if(o.unreachable){Date.now()-t.at<7*864e5&&e.push(t);continue}t.rejected=o.body?.message??""}let s=[...document.querySelectorAll("form")].find(o=>o.action===t.action);if(s){let o=t.rejected?` (${t.rejected})`:"";c(s,"error",`A message you sent earlier couldn't be delivered${o}. Please send it again.`)}else Date.now()-t.at<30*864e5&&e.push(t)}p(m,e)}var g="os-form-queue-lease";async function P(n){let e=navigator.locks;if(e?.request){await e.request(m,{ifAvailable:!0},async o=>{o&&await n()});return}let t=Math.random().toString(36).slice(2),s=f(g,null);if(!(s&&s.until>Date.now())&&(p(g,{by:t,until:Date.now()+3e4}),f(g,null)?.by===t))try{await n()}finally{try{localStorage.removeItem(g)}catch{}}}async function q(n,e){let t=e.get("cf-turnstile-response"),s="";for(let o of n.querySelectorAll("input[type=file][name]")){let i=o.files?.[0];if(e.delete(o.name),!i)continue;let u=Number(o.dataset.osMaxBytes)||0,d=u&&i.size>u?`This file is larger than ${u>>20} MB.`:"";if(!d)try{let a=await fetch(`${n.action}/uploads`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({field:o.name,name:i.name,type:i.type,size:i.size,...s?{proof:s}:typeof t=="string"&&t?{token:t}:{}})}),r=await a.json().catch(()=>({}));if(a.ok&&r.id&&r.uploadUrl&&(await fetch(r.uploadUrl,{method:"PUT",body:i,headers:{"Content-Type":r.type||i.type||"application/octet-stream"}})).ok){e.set(o.name,r.id),s||(s=r.id);continue}d=r.message??"We couldn't upload this file. Please try again."}catch{d="We couldn't upload this file. Please check your connection and try again."}return L(o,d),o.focus(),!1}return!0}var T=!1;function w(){T||(T=!0,P(H).finally(()=>{T=!1}))}function I(n){let e=n;e.noValidate=!0;let t=()=>[...e.elements].filter(o=>"checkValidity"in o&&o.name!==""),s=!1;for(let o of t()){let i=o.type==="checkbox"&&!!o.closest("[data-os-required-group]");o.addEventListener("blur",()=>{i&&!s||(o.value!==""||o.getAttribute("aria-invalid")==="true")&&M(o)}),o.addEventListener(o.type==="checkbox"?"change":"input",()=>{o.getAttribute("aria-invalid")==="true"&&M(o)})}w(),addEventListener("online",w),e.addEventListener("submit",async o=>{o.preventDefault(),s=!0;let i=new Set,u=t().filter(r=>{let l=r.type==="checkbox"?r.closest("[data-os-required-group]"):null;if(l){if(i.has(l))return!1;i.add(l)}return!M(r)});if(u.length){u[0]?.focus(),c(e,"error",u.length===1?"Please fix the highlighted field.":`Please fix the ${u.length} highlighted fields.`);return}h(e,!0),c(e,"","");for(let r of e.querySelectorAll(".os-formblock__sent"))r.hidden=!0;let d=new FormData(e);if(!await q(e,d)){h(e,!1),c(e,"error","Please fix the highlighted field.");return}let a=await v(e.action,d);if(h(e,!1),a.ok){let r=a.body?.redirect??e.dataset.osRedirect;if(r){location.assign(r);return}e.reset(),c(e,"success",a.body?.message??e.dataset.osSuccess??"Thanks \u2014 your message was sent.");return}if(a.body?.errors){for(let r of t()){let l=a.body.errors[r.name];l&&L(r,l)}c(e,"error",a.body.message??"Please check the highlighted fields.");return}if(a.unreachable){let r=[];for(let[S,k]of d)typeof k=="string"&&r.push([S,k]);let l=f(m,[]);l.push({action:e.action,fields:r,at:Date.now()}),p(m,l.slice(-20));let b=e.dataset.osOwnerEmail,y=E("span",{},"We couldn't send this right now. It's saved on this device and we'll retry automatically");b?y.append(", or you can email ",E("a",{href:`mailto:${b}`},b)," directly."):y.append("."),c(e,"error",y);return}c(e,"error",a.body?.message??"Something went wrong. Please try again.")})}export{I as default};
@@ -0,0 +1 @@
1
+ function r(o,e={},...t){let n=document.createElement(o);for(let[s,c]of Object.entries(e))n.setAttribute(s,c);return n.append(...t),n}function m(o){let e="http://www.w3.org/2000/svg",t=document.createElementNS(e,"svg");t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("width","20"),t.setAttribute("height","20"),t.setAttribute("aria-hidden","true");let n=document.createElementNS(e,"path");return n.setAttribute("d",o),n.setAttribute("fill","none"),n.setAttribute("stroke","currentColor"),n.setAttribute("stroke-width","1.6"),n.setAttribute("stroke-linecap","round"),t.append(n),t}var b="M6 6l12 12M18 6L6 18",h="M15 5l-7 7 7 7",p="M9 5l7 7-7 7";var d,u=[],i=0,E=null,a,f;function x(){a=r("img",{class:"os-lightbox__img",alt:""}),f=r("figcaption",{class:"os-lightbox__caption"});let o=(t,n,s,c)=>{let g=r("button",{type:"button",class:`os-lightbox__btn ${t}`,"aria-label":n},m(s));return g.addEventListener("click",c),g},e=r("dialog",{class:"os-lightbox os-theme-dark","aria-label":"Image viewer"},r("figure",{class:"os-lightbox__figure"},r("div",{},a,f)),o("os-lightbox__prev","Previous image",h,()=>l(i-1)),o("os-lightbox__next","Next image",p,()=>l(i+1)),o("os-lightbox__close","Close",b,()=>e.close()));return e.addEventListener("keydown",t=>{t.key==="ArrowRight"&&l(i+1),t.key==="ArrowLeft"&&l(i-1)}),e.addEventListener("click",t=>{t.target===e&&e.close()}),e.addEventListener("close",()=>E?.focus()),document.body.append(e),e}function l(o){let e=u.length;i=(o%e+e)%e;let t=u[i];if(!t)return;let n=t.querySelector("img");a.src=t.href,a.alt=n?.alt??"",f.textContent=t.dataset.osCaption??"";for(let s of d?.querySelectorAll(".os-lightbox__prev,.os-lightbox__next")??[])s.hidden=e<2}function v(o){let e=[...o.querySelectorAll("a[data-os-lightbox]")];for(let t of e)t.addEventListener("click",n=>{n.metaKey||n.ctrlKey||n.shiftKey||(n.preventDefault(),d??(d=x()),u=e,E=t,l(e.indexOf(t)),d.showModal())})}export{v as default};
@@ -0,0 +1 @@
1
+ var u=()=>typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches;function c(e,r={},...i){let t=document.createElement(e);for(let[n,s]of Object.entries(r))t.setAttribute(n,s);return t.append(...i),t}function l(e){let r=e.querySelector(".os-marquee__track");if(!r||u())return;for(let a of[...r.children]){let o=a.cloneNode(!0);o.setAttribute("aria-hidden","true"),o.setAttribute("data-os-clone","");for(let d of o.querySelectorAll("a,button,input"))d.setAttribute("tabindex","-1");r.append(o)}let i=Number(e.dataset.osSpeed)||40;e.style.setProperty("--marquee-duration",`${Math.max(8,r.scrollWidth/2/i)}s`),e.classList.add("is-running");let t=!1,n=c("button",{type:"button",class:"os-marquee__toggle","aria-pressed":"false"},"\u2161");n.setAttribute("aria-label","Pause animation");let s=a=>e.classList.toggle("is-paused",a);n.addEventListener("click",()=>{t=!t,n.setAttribute("aria-pressed",String(t)),n.textContent=t?"\u25B6":"\u2161",s(t)}),e.addEventListener("mouseenter",()=>s(!0)),e.addEventListener("mouseleave",()=>s(t)),e.addEventListener("focusin",()=>s(!0)),e.addEventListener("focusout",()=>s(t)),e.append(n)}export{l as default};
@@ -0,0 +1 @@
1
+ var E='a[href],button:not([disabled]),input:not([disabled]):not([type=hidden]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';function u(n){return[...n.querySelectorAll(E)].filter(o=>o.offsetParent!==null||o===document.activeElement)}function m(n){let o=t=>{if(t.key!=="Tab")return;let i=u(n),r=i[0],c=i[i.length-1];!r||!c||(t.shiftKey&&document.activeElement===r?(t.preventDefault(),c.focus()):!t.shiftKey&&document.activeElement===c&&(t.preventDefault(),r.focus()))};return n.addEventListener("keydown",o),o}function b(n){let o=n.querySelector("[data-os-menu-toggle]"),t=n.querySelector("[data-os-menu]"),i=[...n.querySelectorAll("details[data-os-folder]")],r=document.documentElement,c=t&&!t.classList.contains("os-menu--dropdown"),l,d=()=>t?.classList.contains("is-open")??!1,p=()=>{!t||!o||(t.classList.add("is-open"),n.classList.add("is-menu-open"),o.setAttribute("aria-expanded","true"),c&&(t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),t.setAttribute("aria-label","Menu"),r.style.overflow="hidden",l=m(t)),(u(t)[0]??t).focus())},a=(e=!0)=>{!t||!o||!d()||(t.classList.remove("is-open"),n.classList.remove("is-menu-open"),o.setAttribute("aria-expanded","false"),r.style.overflow="",l&&t.removeEventListener("keydown",l),l=void 0,e&&o.focus())};o?.addEventListener("click",()=>d()?a():p()),n.querySelector("[data-os-menu-close]")?.addEventListener("click",()=>a()),t?.addEventListener("click",e=>{e.target.closest("a[href]")&&a(!1)}),n.addEventListener("click",e=>{e.target===n&&a()}),document.addEventListener("keydown",e=>{if(e.key==="Escape"){d()&&a();for(let s of i)s.open&&(s.open=!1,s.querySelector("summary")?.focus())}}),document.addEventListener("click",e=>{for(let s of i)s.open&&!s.contains(e.target)&&(s.open=!1)});for(let e of i)e.addEventListener("toggle",()=>{if(e.open&&!t?.contains(e))for(let s of i)s!==e&&(s.open=!1)});let f=matchMedia("(min-width: 1024px)");if(f.addEventListener?.("change",()=>{f.matches&&!n.classList.contains("is-drawer")&&a(!1)}),n.classList.contains("is-sticky")||n.classList.contains("is-overlay")){let e=0,s=()=>{e=0,n.classList.toggle("is-scrolled",scrollY>8)};addEventListener("scroll",()=>{e||(e=requestAnimationFrame(s))},{passive:!0}),s()}}export{b as default};
@@ -0,0 +1 @@
1
+ async function i(r,e){try{let t=await fetch(r,{method:"POST",body:e,headers:{Accept:"application/json"}}),s;try{s=await t.json()}catch{s=void 0}return{ok:t.ok,unreachable:t.status>=500,status:t.status,body:s}}catch{return{ok:!1,unreachable:!0,status:0,body:void 0}}}function n(r,e,t=""){let s=r.querySelector(".os-form__status");return s||(s=document.createElement("div"),s.className="os-form__status",r.append(s)),s.setAttribute("role",e==="error"?"alert":"status"),s.dataset.state=e,s.replaceChildren(t),s}function o(r,e){r.setAttribute("aria-busy",String(e));for(let t of r.querySelectorAll("button[type=submit],button:not([type])"))t.disabled=e,t.classList.toggle("is-busy",e)}function u(r){let e=r,t=e.querySelector("input[type=email]");e.addEventListener("submit",async s=>{if(s.preventDefault(),t&&!t.checkValidity()){t.setAttribute("aria-invalid","true"),n(e,"error","Please enter a valid email address."),t.focus();return}t?.setAttribute("aria-invalid","false"),o(e,!0);let a=await i(e.action,new FormData(e));o(e,!1),a.ok?(e.reset(),n(e,"success",a.body?.message??e.dataset.osSuccess??"Almost there \u2014 check your inbox to confirm.")):n(e,"error",a.body?.message??(a.unreachable?"We couldn't reach the signup service. Please try again in a moment.":"That didn't work. Please check your email address."))})}export{u as default};
@@ -0,0 +1 @@
1
+ var r=new URL(".",import.meta.url),c=new Map,d=new WeakMap;function l(n=document){let o=[...n.querySelectorAll("[data-os-behavior]")];n instanceof HTMLElement&&n.matches("[data-os-behavior]")&&o.unshift(n);for(let t of o)for(let e of(t.dataset.osBehavior??"").split(/\s+/)){if(!/^[a-z][a-z-]*$/.test(e))continue;let s=d.get(t)??new Set;if(d.set(t,s),s.has(e))continue;s.add(e);let i=c.get(e)??import(new URL(`${e}.js`,r).href);c.set(e,i),i.then(a=>a.default?.(t)).catch(a=>console.warn(`[openspace] ${e} behavior failed`,a))}}window.OpenSpace={scan:l};l();
@@ -0,0 +1 @@
1
+ function d(n,e){try{let o=localStorage.getItem(n);return o===null?e:JSON.parse(o)}catch{return e}}function m(n,e){try{localStorage.setItem(n,JSON.stringify(e))}catch{}}function b(n){let e=n,o=`os-popup:${e.id}`,f=Number(e.dataset.osFrequency??7),i=d(o,0);if(i&&Date.now()-i<f*864e5)return;let a=!1,r=()=>{a||typeof e.showModal!="function"||(a=!0,e.showModal(),m(o,Date.now()),p())},c=()=>{let t=document.documentElement.scrollHeight-innerHeight;t>0&&scrollY/t*100>=Number(e.dataset.osScroll??50)&&r()},l=t=>{t.clientY<=0&&!t.relatedTarget&&r()},u=0,p=()=>{clearTimeout(u),removeEventListener("scroll",c),document.removeEventListener("mouseout",l)},s=e.dataset.osTrigger;s==="time"?u=window.setTimeout(r,Number(e.dataset.osDelay??8)*1e3):s==="scroll"?addEventListener("scroll",c,{passive:!0}):s==="exit"&&document.addEventListener("mouseout",l),e.querySelector("[data-os-close]")?.addEventListener("click",()=>e.close()),e.addEventListener("click",t=>{t.target===e&&e.close()})}export{b as default};
@@ -0,0 +1 @@
1
+ var s=()=>typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches;var r;function i(t){if(s()||typeof IntersectionObserver!="function"){t.classList.add("is-revealed");return}(t.hasAttribute("data-os-stagger")||t.classList.contains("os-section"))&&t.querySelectorAll(".os-block").forEach((n,e)=>{n.style.setProperty("--i",t.hasAttribute("data-os-stagger")?String(e):"0")});let o=t.getBoundingClientRect();o.top<innerHeight&&o.bottom>0&&t.classList.add("is-revealed"),document.documentElement.classList.add("os-reveal-ready"),!t.classList.contains("is-revealed")&&(r??(r=new IntersectionObserver(n=>{for(let e of n)e.isIntersecting&&(e.target.classList.add("is-revealed"),r?.unobserve(e.target))},{rootMargin:"0px 0px -8% 0px",threshold:.12})),r.observe(t))}export{i as default};
@@ -0,0 +1 @@
1
+ function c(){let t=document.body.dataset;return{site:t.osSite??"",hub:t.osHub??"",base:t.osBase??""}}function i(t,r={},...e){let n=document.createElement(t);for(let[s,a]of Object.entries(r))n.setAttribute(s,a);return n.append(...e),n}var o,u,d,l=!1;function f(t,r){return u??(u=new Promise((e,n)=>{document.head.append(i("link",{rel:"stylesheet",href:`${t}/pagefind/pagefind-ui.css`}));let s=i("script",{src:`${t}/pagefind/pagefind-ui.js`});s.onload=()=>{let a=window.PagefindUI;a&&new a({element:r,showSubResults:!0,autofocus:!0}),e()},s.onerror=()=>{r.textContent="Search is not available right now.",n(new Error("pagefind failed to load"))},document.head.append(s)})),u}function p(t){let{base:r}=c();d??(d=()=>{if(!o){let e=i("div",{class:"os-search__mount"});o=i("dialog",{class:"os-search","aria-label":"Search this site"},e),o.addEventListener("click",n=>{n.target===o&&o?.close()}),document.body.append(o),f(r,e).catch(()=>{})}o.showModal(),o.querySelector("input")?.focus()}),t.addEventListener("click",e=>{e.preventDefault(),d?.()}),!l&&(l=!0,document.addEventListener("keydown",e=>{let n=e.target;e.key==="/"&&!/^(INPUT|TEXTAREA|SELECT)$/.test(n.tagName)&&!n.isContentEditable&&(e.preventDefault(),d?.())}))}export{p as default};
@@ -0,0 +1 @@
1
+ function u(f){let o=[...f.querySelectorAll('[role="tab"]')];if(o.length===0)return;let l=t=>{let n=t.getAttribute("aria-controls");return n?document.getElementById(n):null},s=(t,n=!1)=>{for(let r of o){let i=r===t;r.setAttribute("aria-selected",String(i)),r.tabIndex=i?0:-1;let e=l(r);e&&(e.hidden=!i)}n&&t.focus()},c=o.find(t=>t.getAttribute("aria-selected")==="true")??o[0];c&&s(c);for(let[t,n]of o.entries()){let r=l(n);r&&(r.setAttribute("role","tabpanel"),r.tabIndex=0),n.addEventListener("click",()=>s(n)),n.addEventListener("keydown",i=>{let e=o.length,d={ArrowRight:(t+1)%e,ArrowDown:(t+1)%e,ArrowLeft:(t-1+e)%e,ArrowUp:(t-1+e)%e,Home:0,End:e-1}[i.key];if(d===void 0)return;i.preventDefault();let a=o[d];a&&s(a,!0)})}}export{u as default};
@@ -0,0 +1 @@
1
+ var i=()=>typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches;function c(t){if(t instanceof HTMLVideoElement){if(i())return;t.muted=!0,t.playsInline=!0,t.preload="auto";let e=()=>{t.play().catch(()=>{})};typeof IntersectionObserver=="function"?new IntersectionObserver(([r])=>r?.isIntersecting?e():t.pause()).observe(t):e();return}let o=t.querySelector(".os-video__play, [data-os-load]"),s=t.dataset.osEmbed;!o||!s||!/^https:\/\//i.test(s)||o.addEventListener("click",()=>{let e;try{e=new URL(s)}catch{return}if(e.protocol!=="https:")return;let r=o.classList.contains("os-video__play");r&&e.searchParams.set("autoplay","1");let n=document.createElement("iframe");n.src=e.toString(),n.title=t.dataset.osTitle??"Video",r&&(n.allow="autoplay; encrypted-media; picture-in-picture; fullscreen"),n.allowFullscreen=!0,n.setAttribute("referrerpolicy","strict-origin-when-cross-origin"),t.replaceChildren(n),n.focus()},{once:!0})}export{c as default};