@port60/template-kit 0.15.0 → 0.16.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@port60/template-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Build Port60 site templates locally: scaffold, live-preview, validate against the platform contract, and package for studio upload. AI-agent ready \u2014 every scaffold ships AGENTS.md and validate emits machine-readable JSON.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"name": "counter",
|
|
18
18
|
"status": "available",
|
|
19
19
|
"label": "Animated counter",
|
|
20
|
-
"description": "Counts the element's
|
|
20
|
+
"description": "Counts the element's figure up from zero when first revealed. The static text IS the final value, typed exactly as it should read (\"£20\", \"95%\", \"1,200\", \"2.5k\"): the engine animates only the first run of digits and keeps the prefix, suffix, grouping and decimal places as typed, restoring the exact text on the last frame. A numeric attribute value (legacy) overrides the target; the text still sets the format. Reduced motion: the final figure shows immediately.",
|
|
21
21
|
"attributes": [
|
|
22
|
-
{ "attr": "data-p60-count", "value": "the numeric target
|
|
22
|
+
{ "attr": "data-p60-count", "value": "none: the element's own text is the target and the format; or a numeric target (legacy)" },
|
|
23
23
|
{ "attr": "data-p60-count-duration", "value": "optional ms, capped at 4000 (default 1200)" }
|
|
24
24
|
],
|
|
25
25
|
"stateClasses": ["is-revealed"],
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
"name": "nav",
|
|
130
130
|
"status": "available",
|
|
131
131
|
"label": "Navigation",
|
|
132
|
-
"description": "Your menu, made robust. You design the menu (markup, every pixel, the breakpoint); the engine supplies the interaction CSS :hover cannot: data-p60-nav on each nav root (several allowed), data-p60-nav-item on each group holding a data-p60-nav-toggle control and a data-p60-nav-menu panel (nesting allowed). Hover-capable pointers get hover intent (a short delay to open, a grace period to close) so crossing the gap between a toggle and its panel never closes it; keyboard, touch and pen toggle on the control (Enter/click, ArrowDown opens and focuses the first link; a mouse click on an already-hovered parent link navigates); Escape closes and returns focus to the toggle; a click outside or focus moving away closes; one item stays open per level and aria-expanded is kept honest. The burger: data-p60-nav-burger on a button whose aria-controls (or the attribute value) names the stacked panel; the engine toggles is-open on both, closes on Escape (returning focus), on a real navigation inside the panel, on an outside click, and when the burger disappears at a wider viewport. State is is-open on the item, the panel and the burger; under .p60-js show a panel only on is-open and keep your :hover/:focus-within rules scoped to html:not(.p60-js) for the no-JS render.",
|
|
132
|
+
"description": "Your menu, made robust. You design the menu (markup, every pixel, the breakpoint); the engine supplies the interaction CSS :hover cannot: data-p60-nav on each nav root (several allowed), data-p60-nav-item on each group holding a data-p60-nav-toggle control and a data-p60-nav-menu panel (nesting allowed). Hover-capable pointers get hover intent (a short delay to open, a grace period to close) so crossing the gap between a toggle and its panel never closes it; keyboard, touch and pen toggle on the control (Enter/click, ArrowDown opens and focuses the first link; a mouse click on an already-hovered parent link navigates); Escape closes and returns focus to the toggle; a click outside or focus moving away closes; one item stays open per level and aria-expanded is kept honest. The burger: data-p60-nav-burger on a button whose aria-controls (or the attribute value) names the stacked panel; the engine toggles is-open on both, closes on Escape (returning focus), on a real navigation inside the panel, on an outside click, and when the burger disappears at a wider viewport. State is is-open on the item, the panel and the burger; under .p60-js show a panel only on is-open and keep your :hover/:focus-within rules scoped to html:not(.p60-js) for the no-JS render. Fit steps: when the root's row wraps or overflows, the engine steps is-fit-1, is-fit-2, is-fit-3 onto the root until it fits, re-measured on resize and once fonts settle, never on a stacked (column) nav; the platform's defaults shrink the member_menu pill at each step (the Port60 ID wordmark, then the text, leaving the person icon with its accessible label), and a template maps the same classes to anything else it wants to give up before the burger.",
|
|
133
133
|
"attributes": [
|
|
134
134
|
{ "attr": "data-p60-nav", "value": "none; a nav root, several allowed" },
|
|
135
135
|
{ "attr": "data-p60-nav-item", "value": "none; a group holding one toggle and one menu, nestable" },
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
{ "attr": "data-p60-nav-menu", "value": "none; the item's panel" },
|
|
138
138
|
{ "attr": "data-p60-nav-burger", "value": "none, or the id of the panel when aria-controls is absent" }
|
|
139
139
|
],
|
|
140
|
-
"stateClasses": ["is-open"],
|
|
140
|
+
"stateClasses": ["is-open", "is-fit-1", "is-fit-2", "is-fit-3"],
|
|
141
141
|
"cssVars": []
|
|
142
142
|
}
|
|
143
143
|
]
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// GENERATED by scripts/build-behaviors-runtime.mjs — do not edit by hand.
|
|
2
|
-
"use strict";var p60Behaviors=(()=>{var M=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var q=(n,s)=>{for(var e in s)M(n,e,{get:s[e],enumerable:!0})},I=(n,s,e,o)=>{if(s&&typeof s=="object"||typeof s=="function")for(let t of N(s))!P.call(n,t)&&t!==e&&M(n,t,{get:()=>s[t],enumerable:!(o=H(s,t))||o.enumerable});return n};var C=n=>I(M({},"__esModule",{value:!0}),n);var W={};q(W,{initBehaviors:()=>G});var L=()=>window.matchMedia("(prefers-reduced-motion: reduce)").matches;function y(n,s){let e=`data-p60-bound-${s}`;return n.hasAttribute(e)?!0:(n.setAttribute(e,""),!1)}function T(n,s){if(n.length===0)return;if(L()||!("IntersectionObserver"in window)){n.forEach(s);return}let e=new IntersectionObserver(o=>{for(let t of o)t.isIntersecting&&(e.unobserve(t.target),s(t.target))},{rootMargin:"0px 0px -10% 0px",threshold:.15});n.forEach(o=>e.observe(o))}function O(n){let s=Array.from(n.querySelectorAll("[data-p60-reveal-group]")).filter(o=>!y(o,"reveal-group"));for(let o of s)Array.from(o.children).forEach((t,a)=>{t.style.setProperty("--p60-reveal-index",String(a)),t.classList.add("p60-reveal-child")});T(s,o=>o.classList.add("is-revealed"));let e=Array.from(n.querySelectorAll("[data-p60-reveal]")).filter(o=>!y(o,"reveal"));T(e,o=>o.classList.add("is-revealed"))}function D(n){let s=Array.from(n.querySelectorAll("[data-p60-count]")).filter(e=>!y(e,"count"));T(s,e=>{e.classList.add("is-revealed");let o=Number.parseInt(e.getAttribute("data-p60-count")??"",10);if(!Number.isFinite(o)||L())return;let t=Math.min(Number.parseInt(e.getAttribute("data-p60-count-duration")??"1200",10)||1200,4e3),a=new Intl.NumberFormat(document.documentElement.lang||void 0),c=performance.now(),r=i=>{let d=Math.min((i-c)/t,1),l=1-Math.pow(1-d,3);e.textContent=a.format(Math.round(o*l)),d<1&&requestAnimationFrame(r)};requestAnimationFrame(r)})}function B(n){let s=Array.from(n.querySelectorAll("[data-p60-progress]")).filter(e=>!y(e,"progress"));if(!L()){for(let e of s){let o=e.style.width||getComputedStyle(e).width;e.style.transition="none",e.style.width="0px",e.offsetWidth,e.style.transition="width 1.1s cubic-bezier(0.22, 1, 0.36, 1)",e.dataset.p60ProgressTarget=o}T(s,e=>{e.classList.add("is-revealed"),e.style.width=e.dataset.p60ProgressTarget??""})}}function F(n){let s=Array.from(n.querySelectorAll("[data-p60-countdown]")).filter(e=>!y(e,"countdown"));for(let e of s){let o=Date.parse(e.getAttribute("data-p60-until")??"");if(!Number.isFinite(o))continue;let t=e.getAttribute("data-p60-countdown")||"dhm",a=t==="dhms",c=()=>{let i=o-Date.now();if(i<=0){e.classList.add("is-elapsed");let u=e.getAttribute("data-p60-elapsed-text");u&&(e.textContent=u),window.clearInterval(r);return}let d=Math.floor(i/1e3),l=Math.floor(d/86400),f=Math.floor(d%86400/3600),g=Math.floor(d%3600/60),m=d%60,v=[];t.includes("d")&&l>0&&v.push(`${l}d`),v.push(`${f}h`,`${g}m`),a&&v.push(`${m}s`),e.textContent=v.join(" ")},r=window.setInterval(c,a?1e3:15e3);c()}}function _(n){let s=Array.from(n.querySelectorAll("[data-p60-accordion]")).filter(e=>!y(e,"accordion"));for(let e of s){let o=e.getAttribute("data-p60-accordion")!=="multi",t=Array.from(e.querySelectorAll("details"));for(let a of t){a.addEventListener("toggle",()=>{if(a.classList.toggle("is-open",a.open),a.open&&o)for(let i of t)i!==a&&i.open&&(i.open=!1)}),a.open&&a.classList.add("is-open");let r=a.querySelector("summary")?.nextElementSibling;r&&!L()&&a.addEventListener("toggle",()=>{if(!a.open)return;let i=r.scrollHeight;r.style.overflow="hidden",r.animate([{height:"0px",opacity:"0"},{height:`${i}px`,opacity:"1"}],{duration:260,easing:"ease-out"}).addEventListener("finish",()=>{r.style.overflow=""})})}}}function R(n){let s=Array.from(n.querySelectorAll("[data-p60-carousel]")).filter(e=>!y(e,"carousel"));for(let e of s){let o=Array.from(e.querySelectorAll("[data-p60-slide]"));if(o.length<2)continue;let t=Math.max(0,o.findIndex(u=>u.classList.contains("is-active"))),a=!1,c=[],r=document.createElement("nav");r.className="p60-carousel-dots",r.setAttribute("aria-label","Slides"),o.forEach((u,b)=>{let p=document.createElement("button");p.type="button",p.className="p60-carousel-dot",p.setAttribute("aria-label",`Go to slide ${b+1}`),p.addEventListener("click",()=>i(b,!0)),c.push(p),r.appendChild(p)}),e.appendChild(r),e.setAttribute("aria-roledescription","carousel"),e.hasAttribute("tabindex")||e.setAttribute("tabindex","0");let i=(u,b=!1)=>{t=(u+o.length)%o.length,o.forEach((p,h)=>{p.classList.toggle("is-active",h===t),h===t?(p.removeAttribute("aria-hidden"),p.removeAttribute("inert")):(p.setAttribute("aria-hidden","true"),p.setAttribute("inert",""))}),c.forEach((p,h)=>{p.classList.toggle("p60-carousel-dot--active",h===t),p.setAttribute("aria-current",h===t?"true":"false")}),e.style.setProperty("--p60-carousel-index",String(t)),b&&v()};e.querySelectorAll("[data-p60-carousel-prev]").forEach(u=>u.addEventListener("click",()=>i(t-1,!0))),e.querySelectorAll("[data-p60-carousel-next]").forEach(u=>u.addEventListener("click",()=>i(t+1,!0))),e.addEventListener("keydown",u=>{u.key==="ArrowLeft"&&i(t-1,!0),u.key==="ArrowRight"&&i(t+1,!0)});let d=0,l=0;e.addEventListener("pointerdown",u=>{d=u.clientX,l=u.clientY}),e.addEventListener("pointerup",u=>{let b=u.clientX-d,p=u.clientY-l;Math.abs(b)>40&&Math.abs(b)>Math.abs(p)&&i(t+(b<0?1:-1),!0)}),e.addEventListener("mouseenter",()=>{a=!0}),e.addEventListener("mouseleave",()=>{a=!1}),e.addEventListener("focusin",()=>{a=!0}),e.addEventListener("focusout",()=>{a=!1});let f,g=e.getAttribute("data-p60-carousel")==="auto"&&!L(),m=Math.max(Number.parseInt(e.getAttribute("data-p60-interval")??"6000",10)||6e3,3e3),v=()=>{f!==void 0&&window.clearInterval(f),g&&(f=window.setInterval(()=>{!a&&!document.hidden&&i(t+1)},m))};i(t),v()}}function Y(n){let s=Array.from(n.querySelectorAll("[data-p60-sticky-header]")).filter(e=>!y(e,"sticky-header"));for(let e of s){let o=e.getAttribute("data-p60-sticky-header")==="auto-hide",t=window.scrollY,a=!1,c=()=>{let r=window.scrollY;e.classList.toggle("is-condensed",r>24),o&&(r>160&&r>t?e.classList.add("is-hidden"):e.classList.remove("is-hidden")),t=r,a=!1};window.addEventListener("scroll",()=>{a||(a=!0,requestAnimationFrame(c))},{passive:!0}),c()}}function $(n){let s=Array.from(n.querySelectorAll("[data-p60-sticky-cta]")).filter(e=>!y(e,"sticky-cta"));for(let e of s){let o=Number.parseInt(e.getAttribute("data-p60-sticky-cta")??"480",10)||480,t=!1,a=()=>{e.classList.toggle("is-stuck",window.scrollY>o),t=!1};window.addEventListener("scroll",()=>{t||(t=!0,requestAnimationFrame(a))},{passive:!0}),a()}}function K(n){let s=Array.from(n.querySelectorAll("[data-p60-lightbox]")).filter(e=>!y(e,"lightbox"));for(let e of s){let o=Array.from(e.querySelectorAll("a[data-p60-lightbox-item]"));if(o.length===0)continue;let t=null,a=0,c=null,r=()=>{t?.remove(),t=null,e.classList.remove("is-open"),document.removeEventListener("keydown",d),c?.focus()},i=f=>{a=(f+o.length)%o.length;let g=o[a];if(!t)return;let m=t.querySelector(".p60-lightbox-img"),v=t.querySelector(".p60-lightbox-caption");m&&(m.src=g.href);let u=g.getAttribute("data-p60-caption")??g.querySelector("img")?.alt??"";v&&(v.textContent=u),m&&(m.alt=u)},d=f=>{if(f.key==="Escape"&&r(),f.key==="ArrowLeft"&&i(a-1),f.key==="ArrowRight"&&i(a+1),f.key==="Tab"&&t){let g=Array.from(t.querySelectorAll("button")),m=g.indexOf(document.activeElement),v=f.shiftKey?m<=0?g.length-1:m-1:m>=g.length-1?0:m+1;g[v]?.focus(),f.preventDefault()}},l=(f,g)=>{c=g,t=document.createElement("div"),t.className="p60-lightbox",t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),L()&&(t.style.transition="none"),t.innerHTML='<figure><img class="p60-lightbox-img" alt=""><figcaption class="p60-lightbox-caption"></figcaption></figure>';let m=(u,b,p)=>{let h=document.createElement("button");return h.type="button",h.className=u,h.setAttribute("aria-label",b),h.addEventListener("click",p),t.appendChild(h),h};o.length>1&&(m("p60-lightbox-prev","Previous image",()=>i(a-1)),m("p60-lightbox-next","Next image",()=>i(a+1)));let v=m("p60-lightbox-close","Close",r);t.addEventListener("click",u=>{u.target===t&&r()}),document.body.appendChild(t),e.classList.add("is-open"),document.addEventListener("keydown",d),i(f),v.focus()};o.forEach((f,g)=>f.addEventListener("click",m=>{m.preventDefault(),l(g,f)}))}}function V(n){let s=Array.from(n.querySelectorAll("[data-p60-tabs]")).filter(e=>!y(e,"tabs"));for(let e of s){let o=Array.from(e.querySelectorAll("[data-p60-tab]")),t=Array.from(e.querySelectorAll("[data-p60-panel]"));if(o.length===0||t.length===0)continue;let a=r=>t.find(i=>i.getAttribute("data-p60-panel")===r.getAttribute("data-p60-tab"));o[0].closest("[data-p60-tabs] > *")?.setAttribute("role","tablist");let c=(r,i=!1)=>{for(let d of o){let l=d===r;d.classList.toggle("is-active",l),d.setAttribute("aria-selected",l?"true":"false"),d.setAttribute("tabindex",l?"0":"-1")}for(let d of t){let l=d===a(r);d.classList.toggle("is-active",l),d.hidden=!l}i&&r.focus()};o.forEach((r,i)=>{r.setAttribute("role","tab"),r.addEventListener("click",d=>{d.preventDefault(),c(r)}),r.addEventListener("keydown",d=>{let l=d.key;l==="ArrowLeft"&&c(o[(i-1+o.length)%o.length],!0),l==="ArrowRight"&&c(o[(i+1)%o.length],!0),l==="Home"&&c(o[0],!0),l==="End"&&c(o[o.length-1],!0)})}),t.forEach(r=>r.setAttribute("role","tabpanel")),c(o.find(r=>r.classList.contains("is-active"))??o[0])}}var X=60,j=280,x=()=>window.matchMedia("(hover: hover)").matches,z='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',A=new Set,k=!1;function S(n){n.openTimer!==null&&(window.clearTimeout(n.openTimer),n.openTimer=null),n.closeTimer!==null&&(window.clearTimeout(n.closeTimer),n.closeTimer=null)}function E(n,s=!1){S(n);for(let e of Array.from(A))e!==n&&n.item.contains(e.item)&&E(e);n.item.classList.remove("is-open"),n.toggle.setAttribute("aria-expanded","false"),n.openedBy=null,A.delete(n),s&&n.toggle.focus()}function w(n,s){S(n);for(let e of Array.from(A))e!==n&&e.nav===n.nav&&!e.item.contains(n.item)&&E(e);n.item.classList.add("is-open"),n.toggle.setAttribute("aria-expanded","true"),n.openedBy=s,A.add(n)}function U(n){for(let e of Array.from(n.querySelectorAll("[data-p60-nav]"))){let o=Array.from(e.querySelectorAll("[data-p60-nav-item]")).filter(t=>t.closest("[data-p60-nav]")===e&&!y(t,"nav-item"));for(let t of o){let a=l=>l.closest("[data-p60-nav-item]")===t,c=Array.from(t.querySelectorAll("[data-p60-nav-toggle]")).find(a)??null,r=Array.from(t.querySelectorAll("[data-p60-nav-menu]")).find(a)??null;if(!c||!r)continue;let i={nav:e,item:t,toggle:c,menu:r,openedBy:null,lastPointer:"",openTimer:null,closeTimer:null},d=()=>A.has(i);c.setAttribute("aria-expanded","false"),r.id&&!c.hasAttribute("aria-controls")&&c.setAttribute("aria-controls",r.id),t.addEventListener("mouseenter",()=>{x()&&(i.closeTimer!==null&&(window.clearTimeout(i.closeTimer),i.closeTimer=null),!d()&&i.openTimer===null&&(i.openTimer=window.setTimeout(()=>{i.openTimer=null,w(i,"hover")},X)))}),t.addEventListener("mouseleave",()=>{x()&&(i.openTimer!==null&&(window.clearTimeout(i.openTimer),i.openTimer=null),d()&&i.openedBy==="hover"&&i.closeTimer===null&&(i.closeTimer=window.setTimeout(()=>{i.closeTimer=null,E(i)},j)))}),c.addEventListener("pointerdown",l=>{i.lastPointer=l.pointerType??""}),c.addEventListener("click",l=>{let f=l.detail===0||i.lastPointer==="touch"||i.lastPointer==="pen"||!x();if(!d()){l.preventDefault(),l.stopPropagation(),w(i,"toggle");return}!f&&i.openedBy==="hover"||(l.preventDefault(),l.stopPropagation(),E(i))}),c.addEventListener("keydown",l=>{l.key==="ArrowDown"&&(l.preventDefault(),d()||w(i,"toggle"),r.querySelector(z)?.focus())}),t.addEventListener("keydown",l=>{l.key==="Escape"&&d()&&(l.stopPropagation(),E(i,!0))}),t.addEventListener("focusin",l=>{l.target instanceof Node&&r.contains(l.target)&&!d()&&w(i,"focus")}),t.addEventListener("focusout",l=>{let f=l.relatedTarget;f instanceof Node&&!t.contains(f)&&d()&&E(i)})}}let s=Array.from(n.querySelectorAll("[data-p60-nav-burger]")).filter(e=>!y(e,"nav-burger"));for(let e of s){let o=e.getAttribute("aria-controls")||e.getAttribute("data-p60-nav-burger")||"",t=o?document.getElementById(o):null;if(!t)continue;let a=()=>t.classList.contains("is-open"),c=r=>{if(t.classList.toggle("is-open",r),e.classList.toggle("is-open",r),e.setAttribute("aria-expanded",String(r)),!r)for(let i of Array.from(A))t.contains(i.item)&&E(i)};e.setAttribute("aria-expanded","false"),e.addEventListener("click",r=>{r.stopPropagation(),c(!a())}),t.addEventListener("click",r=>{r.target instanceof Element&&r.target.closest("a")&&c(!1)}),document.addEventListener("keydown",r=>{r.key==="Escape"&&a()&&(c(!1),e.focus())}),document.addEventListener("click",r=>{a()&&r.target instanceof Node&&!t.contains(r.target)&&!e.contains(r.target)&&c(!1)}),window.addEventListener("resize",()=>{a()&&e.offsetParent===null&&c(!1)})}k||(k=!0,document.addEventListener("click",e=>{for(let o of Array.from(A))(!(e.target instanceof Node)||!o.item.contains(e.target))&&E(o)}))}function G(n=document){document.documentElement.classList.add("p60-js"),O(n),D(n),B(n),F(n),_(n),R(n),Y(n),$(n),K(n),V(n),U(n)}return C(W);})();
|
|
2
|
+
"use strict";var p60Behaviors=(()=>{var x=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var q=Object.prototype.hasOwnProperty;var I=(n,l)=>{for(var e in l)x(n,e,{get:l[e],enumerable:!0})},C=(n,l,e,o)=>{if(l&&typeof l=="object"||typeof l=="function")for(let t of P(l))!q.call(n,t)&&t!==e&&x(n,t,{get:()=>l[t],enumerable:!(o=H(l,t))||o.enumerable});return n};var F=n=>C(x({},"__esModule",{value:!0}),n);var Q={};I(Q,{initBehaviors:()=>J});var L=()=>window.matchMedia("(prefers-reduced-motion: reduce)").matches;function b(n,l){let e=`data-p60-bound-${l}`;return n.hasAttribute(e)?!0:(n.setAttribute(e,""),!1)}function T(n,l){if(n.length===0)return;if(L()||!("IntersectionObserver"in window)){n.forEach(l);return}let e=new IntersectionObserver(o=>{for(let t of o)t.isIntersecting&&(e.unobserve(t.target),l(t.target))},{rootMargin:"0px 0px -10% 0px",threshold:.15});n.forEach(o=>e.observe(o))}function O(n){let l=Array.from(n.querySelectorAll("[data-p60-reveal-group]")).filter(o=>!b(o,"reveal-group"));for(let o of l)Array.from(o.children).forEach((t,a)=>{t.style.setProperty("--p60-reveal-index",String(a)),t.classList.add("p60-reveal-child")});T(l,o=>o.classList.add("is-revealed"));let e=Array.from(n.querySelectorAll("[data-p60-reveal]")).filter(o=>!b(o,"reveal"));T(e,o=>o.classList.add("is-revealed"))}var B=/\d[\d, ]*(?:\.\d+)?/;function D(n){let l=Array.from(n.querySelectorAll("[data-p60-count]")).filter(e=>!b(e,"count"));T(l,e=>{e.classList.add("is-revealed");let o=e.textContent??"",t=B.exec(o);if(!t)return;let a=t[0].replace(/[, ]+$/,""),c=o.slice(0,t.index),r=o.slice(t.index+a.length),i=/[, ]/.test(a),d=a.includes(".")?a.length-a.indexOf(".")-1:0,s=Number.parseFloat(a.replace(/[, ]/g,"")),f=Number.parseFloat(e.getAttribute("data-p60-count")??""),g=Number.isFinite(f)?f:s;if(!Number.isFinite(g)||L())return;let u=Math.min(Number.parseInt(e.getAttribute("data-p60-count-duration")??"1200",10)||1200,4e3),p=new Intl.NumberFormat(document.documentElement.lang||void 0,{useGrouping:i,minimumFractionDigits:d,maximumFractionDigits:d}),m=performance.now(),h=v=>{let y=Math.min((v-m)/u,1),k=1-Math.pow(1-y,3);e.textContent=y<1?c+p.format(g*k)+r:o,y<1&&requestAnimationFrame(h)};requestAnimationFrame(h)})}function _(n){let l=Array.from(n.querySelectorAll("[data-p60-progress]")).filter(e=>!b(e,"progress"));if(!L()){for(let e of l){let o=e.style.width||getComputedStyle(e).width;e.style.transition="none",e.style.width="0px",e.offsetWidth,e.style.transition="width 1.1s cubic-bezier(0.22, 1, 0.36, 1)",e.dataset.p60ProgressTarget=o}T(l,e=>{e.classList.add("is-revealed"),e.style.width=e.dataset.p60ProgressTarget??""})}}function R(n){let l=Array.from(n.querySelectorAll("[data-p60-countdown]")).filter(e=>!b(e,"countdown"));for(let e of l){let o=Date.parse(e.getAttribute("data-p60-until")??"");if(!Number.isFinite(o))continue;let t=e.getAttribute("data-p60-countdown")||"dhm",a=t==="dhms",c=()=>{let i=o-Date.now();if(i<=0){e.classList.add("is-elapsed");let m=e.getAttribute("data-p60-elapsed-text");m&&(e.textContent=m),window.clearInterval(r);return}let d=Math.floor(i/1e3),s=Math.floor(d/86400),f=Math.floor(d%86400/3600),g=Math.floor(d%3600/60),u=d%60,p=[];t.includes("d")&&s>0&&p.push(`${s}d`),p.push(`${f}h`,`${g}m`),a&&p.push(`${u}s`),e.textContent=p.join(" ")},r=window.setInterval(c,a?1e3:15e3);c()}}function V(n){let l=Array.from(n.querySelectorAll("[data-p60-accordion]")).filter(e=>!b(e,"accordion"));for(let e of l){let o=e.getAttribute("data-p60-accordion")!=="multi",t=Array.from(e.querySelectorAll("details"));for(let a of t){a.addEventListener("toggle",()=>{if(a.classList.toggle("is-open",a.open),a.open&&o)for(let i of t)i!==a&&i.open&&(i.open=!1)}),a.open&&a.classList.add("is-open");let r=a.querySelector("summary")?.nextElementSibling;r&&!L()&&a.addEventListener("toggle",()=>{if(!a.open)return;let i=r.scrollHeight;r.style.overflow="hidden",r.animate([{height:"0px",opacity:"0"},{height:`${i}px`,opacity:"1"}],{duration:260,easing:"ease-out"}).addEventListener("finish",()=>{r.style.overflow=""})})}}}function $(n){let l=Array.from(n.querySelectorAll("[data-p60-carousel]")).filter(e=>!b(e,"carousel"));for(let e of l){let o=Array.from(e.querySelectorAll("[data-p60-slide]"));if(o.length<2)continue;let t=Math.max(0,o.findIndex(m=>m.classList.contains("is-active"))),a=!1,c=[],r=document.createElement("nav");r.className="p60-carousel-dots",r.setAttribute("aria-label","Slides"),o.forEach((m,h)=>{let v=document.createElement("button");v.type="button",v.className="p60-carousel-dot",v.setAttribute("aria-label",`Go to slide ${h+1}`),v.addEventListener("click",()=>i(h,!0)),c.push(v),r.appendChild(v)}),e.appendChild(r),e.setAttribute("aria-roledescription","carousel"),e.hasAttribute("tabindex")||e.setAttribute("tabindex","0");let i=(m,h=!1)=>{t=(m+o.length)%o.length,o.forEach((v,y)=>{v.classList.toggle("is-active",y===t),y===t?(v.removeAttribute("aria-hidden"),v.removeAttribute("inert")):(v.setAttribute("aria-hidden","true"),v.setAttribute("inert",""))}),c.forEach((v,y)=>{v.classList.toggle("p60-carousel-dot--active",y===t),v.setAttribute("aria-current",y===t?"true":"false")}),e.style.setProperty("--p60-carousel-index",String(t)),h&&p()};e.querySelectorAll("[data-p60-carousel-prev]").forEach(m=>m.addEventListener("click",()=>i(t-1,!0))),e.querySelectorAll("[data-p60-carousel-next]").forEach(m=>m.addEventListener("click",()=>i(t+1,!0))),e.addEventListener("keydown",m=>{m.key==="ArrowLeft"&&i(t-1,!0),m.key==="ArrowRight"&&i(t+1,!0)});let d=0,s=0;e.addEventListener("pointerdown",m=>{d=m.clientX,s=m.clientY}),e.addEventListener("pointerup",m=>{let h=m.clientX-d,v=m.clientY-s;Math.abs(h)>40&&Math.abs(h)>Math.abs(v)&&i(t+(h<0?1:-1),!0)}),e.addEventListener("mouseenter",()=>{a=!0}),e.addEventListener("mouseleave",()=>{a=!1}),e.addEventListener("focusin",()=>{a=!0}),e.addEventListener("focusout",()=>{a=!1});let f,g=e.getAttribute("data-p60-carousel")==="auto"&&!L(),u=Math.max(Number.parseInt(e.getAttribute("data-p60-interval")??"6000",10)||6e3,3e3),p=()=>{f!==void 0&&window.clearInterval(f),g&&(f=window.setInterval(()=>{!a&&!document.hidden&&i(t+1)},u))};i(t),p()}}function Y(n){let l=Array.from(n.querySelectorAll("[data-p60-sticky-header]")).filter(e=>!b(e,"sticky-header"));for(let e of l){let o=e.getAttribute("data-p60-sticky-header")==="auto-hide",t=window.scrollY,a=!1,c=()=>{let r=window.scrollY;e.classList.toggle("is-condensed",r>24),o&&(r>160&&r>t?e.classList.add("is-hidden"):e.classList.remove("is-hidden")),t=r,a=!1};window.addEventListener("scroll",()=>{a||(a=!0,requestAnimationFrame(c))},{passive:!0}),c()}}function K(n){let l=Array.from(n.querySelectorAll("[data-p60-sticky-cta]")).filter(e=>!b(e,"sticky-cta"));for(let e of l){let o=Number.parseInt(e.getAttribute("data-p60-sticky-cta")??"480",10)||480,t=!1,a=()=>{e.classList.toggle("is-stuck",window.scrollY>o),t=!1};window.addEventListener("scroll",()=>{t||(t=!0,requestAnimationFrame(a))},{passive:!0}),a()}}function X(n){let l=Array.from(n.querySelectorAll("[data-p60-lightbox]")).filter(e=>!b(e,"lightbox"));for(let e of l){let o=Array.from(e.querySelectorAll("a[data-p60-lightbox-item]"));if(o.length===0)continue;let t=null,a=0,c=null,r=()=>{t?.remove(),t=null,e.classList.remove("is-open"),document.removeEventListener("keydown",d),c?.focus()},i=f=>{a=(f+o.length)%o.length;let g=o[a];if(!t)return;let u=t.querySelector(".p60-lightbox-img"),p=t.querySelector(".p60-lightbox-caption");u&&(u.src=g.href);let m=g.getAttribute("data-p60-caption")??g.querySelector("img")?.alt??"";p&&(p.textContent=m),u&&(u.alt=m)},d=f=>{if(f.key==="Escape"&&r(),f.key==="ArrowLeft"&&i(a-1),f.key==="ArrowRight"&&i(a+1),f.key==="Tab"&&t){let g=Array.from(t.querySelectorAll("button")),u=g.indexOf(document.activeElement),p=f.shiftKey?u<=0?g.length-1:u-1:u>=g.length-1?0:u+1;g[p]?.focus(),f.preventDefault()}},s=(f,g)=>{c=g,t=document.createElement("div"),t.className="p60-lightbox",t.setAttribute("role","dialog"),t.setAttribute("aria-modal","true"),L()&&(t.style.transition="none"),t.innerHTML='<figure><img class="p60-lightbox-img" alt=""><figcaption class="p60-lightbox-caption"></figcaption></figure>';let u=(m,h,v)=>{let y=document.createElement("button");return y.type="button",y.className=m,y.setAttribute("aria-label",h),y.addEventListener("click",v),t.appendChild(y),y};o.length>1&&(u("p60-lightbox-prev","Previous image",()=>i(a-1)),u("p60-lightbox-next","Next image",()=>i(a+1)));let p=u("p60-lightbox-close","Close",r);t.addEventListener("click",m=>{m.target===t&&r()}),document.body.appendChild(t),e.classList.add("is-open"),document.addEventListener("keydown",d),i(f),p.focus()};o.forEach((f,g)=>f.addEventListener("click",u=>{u.preventDefault(),s(g,f)}))}}function z(n){let l=Array.from(n.querySelectorAll("[data-p60-tabs]")).filter(e=>!b(e,"tabs"));for(let e of l){let o=Array.from(e.querySelectorAll("[data-p60-tab]")),t=Array.from(e.querySelectorAll("[data-p60-panel]"));if(o.length===0||t.length===0)continue;let a=r=>t.find(i=>i.getAttribute("data-p60-panel")===r.getAttribute("data-p60-tab"));o[0].closest("[data-p60-tabs] > *")?.setAttribute("role","tablist");let c=(r,i=!1)=>{for(let d of o){let s=d===r;d.classList.toggle("is-active",s),d.setAttribute("aria-selected",s?"true":"false"),d.setAttribute("tabindex",s?"0":"-1")}for(let d of t){let s=d===a(r);d.classList.toggle("is-active",s),d.hidden=!s}i&&r.focus()};o.forEach((r,i)=>{r.setAttribute("role","tab"),r.addEventListener("click",d=>{d.preventDefault(),c(r)}),r.addEventListener("keydown",d=>{let s=d.key;s==="ArrowLeft"&&c(o[(i-1+o.length)%o.length],!0),s==="ArrowRight"&&c(o[(i+1)%o.length],!0),s==="Home"&&c(o[0],!0),s==="End"&&c(o[o.length-1],!0)})}),t.forEach(r=>r.setAttribute("role","tabpanel")),c(o.find(r=>r.classList.contains("is-active"))??o[0])}}var W=60,U=280,M=()=>window.matchMedia("(hover: hover)").matches,j='a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',A=new Set,N=!1;function S(n){n.openTimer!==null&&(window.clearTimeout(n.openTimer),n.openTimer=null),n.closeTimer!==null&&(window.clearTimeout(n.closeTimer),n.closeTimer=null)}function E(n,l=!1){S(n);for(let e of Array.from(A))e!==n&&n.item.contains(e.item)&&E(e);n.item.classList.remove("is-open"),n.toggle.setAttribute("aria-expanded","false"),n.openedBy=null,A.delete(n),l&&n.toggle.focus()}function w(n,l){S(n);for(let e of Array.from(A))e!==n&&e.nav===n.nav&&!e.item.contains(n.item)&&E(e);n.item.classList.add("is-open"),n.toggle.setAttribute("aria-expanded","true"),n.openedBy=l,A.add(n)}function G(n){for(let e of Array.from(n.querySelectorAll("[data-p60-nav]"))){let o=Array.from(e.querySelectorAll("[data-p60-nav-item]")).filter(t=>t.closest("[data-p60-nav]")===e&&!b(t,"nav-item"));for(let t of o){let a=s=>s.closest("[data-p60-nav-item]")===t,c=Array.from(t.querySelectorAll("[data-p60-nav-toggle]")).find(a)??null,r=Array.from(t.querySelectorAll("[data-p60-nav-menu]")).find(a)??null;if(!c||!r)continue;let i={nav:e,item:t,toggle:c,menu:r,openedBy:null,lastPointer:"",openTimer:null,closeTimer:null},d=()=>A.has(i);c.setAttribute("aria-expanded","false"),r.id&&!c.hasAttribute("aria-controls")&&c.setAttribute("aria-controls",r.id),t.addEventListener("mouseenter",()=>{M()&&(i.closeTimer!==null&&(window.clearTimeout(i.closeTimer),i.closeTimer=null),!d()&&i.openTimer===null&&(i.openTimer=window.setTimeout(()=>{i.openTimer=null,w(i,"hover")},W)))}),t.addEventListener("mouseleave",()=>{M()&&(i.openTimer!==null&&(window.clearTimeout(i.openTimer),i.openTimer=null),d()&&i.openedBy==="hover"&&i.closeTimer===null&&(i.closeTimer=window.setTimeout(()=>{i.closeTimer=null,E(i)},U)))}),c.addEventListener("pointerdown",s=>{i.lastPointer=s.pointerType??""}),c.addEventListener("click",s=>{let f=s.detail===0||i.lastPointer==="touch"||i.lastPointer==="pen"||!M();if(!d()){s.preventDefault(),s.stopPropagation(),w(i,"toggle");return}!f&&i.openedBy==="hover"||(s.preventDefault(),s.stopPropagation(),E(i))}),c.addEventListener("keydown",s=>{s.key==="ArrowDown"&&(s.preventDefault(),d()||w(i,"toggle"),r.querySelector(j)?.focus())}),t.addEventListener("keydown",s=>{s.key==="Escape"&&d()&&(s.stopPropagation(),E(i,!0))}),t.addEventListener("focusin",s=>{s.target instanceof Node&&r.contains(s.target)&&!d()&&w(i,"focus")}),t.addEventListener("focusout",s=>{let f=s.relatedTarget;f instanceof Node&&!t.contains(f)&&d()&&E(i)})}if(!b(e,"nav-fit")){let a=u=>{for(let p=1;p<=3;p++)e.classList.toggle(`is-fit-${p}`,p<=u)},c=u=>{let p=u.getBoundingClientRect();return p.width>0||p.height>0?[u]:Array.from(u.children).flatMap(c)},r=u=>{let p=-1/0;for(let m of u.flatMap(c)){let h=m.getBoundingClientRect();if(p!==-1/0&&h.top>=p-2)return!0;p=Math.max(p,h.bottom)}return!1},i=()=>{if(e.scrollWidth>e.clientWidth+1||r(Array.from(e.children)))return!1;let u=e.parentElement;return!(u&&getComputedStyle(u).flexWrap==="wrap"&&r(Array.from(u.children)))},d=0,s=()=>{if(d=performance.now(),e.offsetParent===null||!getComputedStyle(e).flexDirection.startsWith("row")){a(0);return}a(0);let u=0;for(;!i()&&u<3;)a(++u);d=performance.now()},f=!1,g=()=>{f||(f=!0,requestAnimationFrame(()=>{f=!1,s()}))};window.addEventListener("resize",g,{passive:!0}),document.fonts?.ready.then(g).catch(()=>{}),document.fonts?.addEventListener("loadingdone",g),"ResizeObserver"in window&&new ResizeObserver(()=>{performance.now()-d>120&&g()}).observe(e),s()}}let l=Array.from(n.querySelectorAll("[data-p60-nav-burger]")).filter(e=>!b(e,"nav-burger"));for(let e of l){let o=e.getAttribute("aria-controls")||e.getAttribute("data-p60-nav-burger")||"",t=o?document.getElementById(o):null;if(!t)continue;let a=()=>t.classList.contains("is-open"),c=r=>{if(t.classList.toggle("is-open",r),e.classList.toggle("is-open",r),e.setAttribute("aria-expanded",String(r)),!r)for(let i of Array.from(A))t.contains(i.item)&&E(i)};e.setAttribute("aria-expanded","false"),e.addEventListener("click",r=>{r.stopPropagation(),c(!a())}),t.addEventListener("click",r=>{r.target instanceof Element&&r.target.closest("a")&&c(!1)}),document.addEventListener("keydown",r=>{r.key==="Escape"&&a()&&(c(!1),e.focus())}),document.addEventListener("click",r=>{a()&&r.target instanceof Node&&!t.contains(r.target)&&!e.contains(r.target)&&c(!1)}),window.addEventListener("resize",()=>{a()&&e.offsetParent===null&&c(!1)})}N||(N=!0,document.addEventListener("click",e=>{for(let o of Array.from(A))(!(e.target instanceof Node)||!o.item.contains(e.target))&&E(o)}))}function J(n=document){document.documentElement.classList.add("p60-js"),O(n),D(n),_(n),R(n),V(n),$(n),Y(n),K(n),X(n),z(n),G(n)}return F(Q);})();
|
|
@@ -332,6 +332,29 @@ input:focus {
|
|
|
332
332
|
font-weight: 800;
|
|
333
333
|
}
|
|
334
334
|
|
|
335
|
+
/* Compact forms for crowded headers. The `nav` behaviour steps is-fit-1..3 onto a template's nav
|
|
336
|
+
root when its row wraps or overflows (docs/template-behaviours.md); these are the platform's
|
|
337
|
+
defaults for what the island gives up at each step, the way Shopify's Shop button shrinks to
|
|
338
|
+
its mark: first the Port60 ID wordmark, then the text, leaving the person icon with its
|
|
339
|
+
accessible label intact. A template restyles by matching the same classes. */
|
|
340
|
+
[data-p60-nav].is-fit-1 .nav-p60-signin .p60-mark {
|
|
341
|
+
display: none;
|
|
342
|
+
}
|
|
343
|
+
[data-p60-nav].is-fit-2 .nav-p60-signin .nav-p60-signin-label,
|
|
344
|
+
[data-p60-nav].is-fit-2 .nav-account-name,
|
|
345
|
+
[data-p60-nav].is-fit-2 .nav-account-caret {
|
|
346
|
+
display: none;
|
|
347
|
+
}
|
|
348
|
+
[data-p60-nav].is-fit-2 .nav-p60-signin.nav-p60-signin,
|
|
349
|
+
[data-p60-nav].is-fit-2 .nav-account-toggle.nav-account-toggle.nav-account-toggle {
|
|
350
|
+
padding-left: 0.7rem;
|
|
351
|
+
padding-right: 0.7rem;
|
|
352
|
+
}
|
|
353
|
+
[data-p60-nav].is-fit-2 .nav-account-icon {
|
|
354
|
+
width: 1.25rem;
|
|
355
|
+
height: 1.25rem;
|
|
356
|
+
}
|
|
357
|
+
|
|
335
358
|
/* Members account pill (signed in) — a clear "this is your account" affordance, weighted between
|
|
336
359
|
plain nav links and the Donate CTA. The menu anchors right (it's the last nav item).
|
|
337
360
|
`.open` mirrors hover/focus for touch. Unscoped — island chrome, identical in any template's
|