basecoat-cli 0.3.10 → 0.3.11
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/dist/assets/js/all.js +1 -35
- package/dist/assets/js/all.min.js +1 -1
- package/dist/assets/js/sidebar.js +1 -36
- package/dist/assets/js/sidebar.min.js +1 -1
- package/package.json +1 -1
- package/dist/assets/jinja/carousel.html.jinja +0 -111
- package/dist/assets/js/carousel.js +0 -192
- package/dist/assets/js/carousel.min.js +0 -1
- package/dist/assets/nunjucks/carousel.njk +0 -111
package/dist/assets/js/all.js
CHANGED
|
@@ -945,23 +945,6 @@
|
|
|
945
945
|
})();
|
|
946
946
|
|
|
947
947
|
(() => {
|
|
948
|
-
// Monkey patching the history API to detect client-side navigation
|
|
949
|
-
if (!window.history.__basecoatPatched) {
|
|
950
|
-
const originalPushState = window.history.pushState;
|
|
951
|
-
window.history.pushState = function(...args) {
|
|
952
|
-
originalPushState.apply(this, args);
|
|
953
|
-
window.dispatchEvent(new Event('basecoat:locationchange'));
|
|
954
|
-
};
|
|
955
|
-
|
|
956
|
-
const originalReplaceState = window.history.replaceState;
|
|
957
|
-
window.history.replaceState = function(...args) {
|
|
958
|
-
originalReplaceState.apply(this, args);
|
|
959
|
-
window.dispatchEvent(new Event('basecoat:locationchange'));
|
|
960
|
-
};
|
|
961
|
-
|
|
962
|
-
window.history.__basecoatPatched = true;
|
|
963
|
-
}
|
|
964
|
-
|
|
965
948
|
const initSidebar = (sidebarComponent) => {
|
|
966
949
|
const initialOpen = sidebarComponent.dataset.initialOpen !== 'false';
|
|
967
950
|
const initialMobileOpen = sidebarComponent.dataset.initialMobileOpen === 'true';
|
|
@@ -971,20 +954,6 @@
|
|
|
971
954
|
? (window.innerWidth >= breakpoint ? initialOpen : initialMobileOpen)
|
|
972
955
|
: initialOpen;
|
|
973
956
|
|
|
974
|
-
const updateCurrentPageLinks = () => {
|
|
975
|
-
const currentPath = window.location.pathname.replace(/\/$/, '');
|
|
976
|
-
sidebarComponent.querySelectorAll('a').forEach(link => {
|
|
977
|
-
if (link.hasAttribute('data-ignore-current')) return;
|
|
978
|
-
|
|
979
|
-
const linkPath = new URL(link.href).pathname.replace(/\/$/, '');
|
|
980
|
-
if (linkPath === currentPath) {
|
|
981
|
-
link.setAttribute('aria-current', 'page');
|
|
982
|
-
} else {
|
|
983
|
-
link.removeAttribute('aria-current');
|
|
984
|
-
}
|
|
985
|
-
});
|
|
986
|
-
};
|
|
987
|
-
|
|
988
957
|
const updateState = () => {
|
|
989
958
|
sidebarComponent.setAttribute('aria-hidden', !open);
|
|
990
959
|
if (open) {
|
|
@@ -1035,11 +1004,7 @@
|
|
|
1035
1004
|
}
|
|
1036
1005
|
});
|
|
1037
1006
|
|
|
1038
|
-
window.addEventListener('popstate', updateCurrentPageLinks);
|
|
1039
|
-
window.addEventListener('basecoat:locationchange', updateCurrentPageLinks);
|
|
1040
|
-
|
|
1041
1007
|
updateState();
|
|
1042
|
-
updateCurrentPageLinks();
|
|
1043
1008
|
sidebarComponent.dataset.sidebarInitialized = true;
|
|
1044
1009
|
sidebarComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
|
|
1045
1010
|
};
|
|
@@ -1048,6 +1013,7 @@
|
|
|
1048
1013
|
window.basecoat.register('sidebar', '.sidebar:not([data-sidebar-initialized])', initSidebar);
|
|
1049
1014
|
}
|
|
1050
1015
|
})();
|
|
1016
|
+
|
|
1051
1017
|
(() => {
|
|
1052
1018
|
const initTabs = (tabsComponent) => {
|
|
1053
1019
|
const tablist = tabsComponent.querySelector('[role="tablist"]');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{const e={};let t=null;const n=()=>{Object.entries(e).forEach((([e,{selector:t,init:n}])=>{document.querySelectorAll(t).forEach(n)}))},i=t=>{t.nodeType===Node.ELEMENT_NODE&&Object.entries(e).forEach((([e,{selector:n,init:i}])=>{t.matches(n)&&i(t),t.querySelectorAll(n).forEach(i)}))},a=()=>{t||(t=new MutationObserver((e=>{e.forEach((e=>{e.addedNodes.forEach(i)}))})),t.observe(document.body,{childList:!0,subtree:!0}))};window.basecoat={register:(t,n,i)=>{e[t]={selector:n,init:i}},init:t=>{const n=e[t];if(!n)return void console.warn(`Component '${t}' not found in registry`);const i=`data-${t}-initialized`;document.querySelectorAll(`[${i}]`).forEach((e=>{e.removeAttribute(i)})),document.querySelectorAll(n.selector).forEach(n.init)},initAll:()=>{Object.entries(e).forEach((([e,{selector:t}])=>{const n=`data-${e}-initialized`;document.querySelectorAll(`[${n}]`).forEach((e=>{e.removeAttribute(n)}))})),n()},start:a,stop:()=>{t&&(t.disconnect(),t=null)}},document.addEventListener("DOMContentLoaded",(()=>{n(),a()}))})(),(()=>{const e=e=>{const t=e.querySelector("header input"),n=e.querySelector('[role="menu"]');if(!t||!n){const i=[];return t||i.push("input"),n||i.push("menu"),void console.error(`Command component initialization failed. Missing element(s): ${i.join(", ")}`,e)}const i=Array.from(n.querySelectorAll('[role="menuitem"]')),a=i.filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled")));let r=[...a],o=-1;const s=e=>{if(o>-1&&a[o]&&a[o].classList.remove("active"),o=e,o>-1){const e=a[o];e.classList.add("active"),e.id?t.setAttribute("aria-activedescendant",e.id):t.removeAttribute("aria-activedescendant")}else t.removeAttribute("aria-activedescendant")};t.addEventListener("input",(()=>{const e=t.value.trim().toLowerCase();s(-1),r=[],i.forEach((t=>{if(t.hasAttribute("data-force"))return t.setAttribute("aria-hidden","false"),void(a.includes(t)&&r.push(t));const n=(t.dataset.filter||t.textContent).trim().toLowerCase(),i=(t.dataset.keywords||"").toLowerCase().split(/[\s,]+/).filter(Boolean).some((t=>t.includes(e))),o=n.includes(e)||i;t.setAttribute("aria-hidden",String(!o)),o&&a.includes(t)&&r.push(t)})),r.length>0&&(s(a.indexOf(r[0])),r[0].scrollIntoView({block:"nearest"}))}));n.addEventListener("mousemove",(e=>{const t=e.target.closest('[role="menuitem"]');if(t&&r.includes(t)){const e=a.indexOf(t);e!==o&&s(e)}})),n.addEventListener("click",(t=>{const n=t.target.closest('[role="menuitem"]');if(n&&r.includes(n)){const t=e.closest("dialog.command-dialog");t&&!n.hasAttribute("data-keep-command-open")&&t.close()}})),t.addEventListener("keydown",(e=>{if(!["ArrowDown","ArrowUp","Enter","Home","End"].includes(e.key))return;if("Enter"===e.key)return e.preventDefault(),void(o>-1&&a[o]?.click());if(0===r.length)return;e.preventDefault();const t=o>-1?r.indexOf(a[o]):-1;let n=t;switch(e.key){case"ArrowDown":t<r.length-1&&(n=t+1);break;case"ArrowUp":t>0?n=t-1:-1===t&&(n=0);break;case"Home":n=0;break;case"End":n=r.length-1}if(n!==t){const e=r[n];s(a.indexOf(e)),e.scrollIntoView({block:"nearest",behavior:"smooth"})}})),r.length>0&&(s(a.indexOf(r[0])),r[0].scrollIntoView({block:"nearest"})),e.dataset.commandInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("command",".command:not([data-command-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=e.querySelector(":scope > [data-popover]"),i=n.querySelector('[role="menu"]');if(!t||!i||!n){const a=[];return t||a.push("trigger"),i||a.push("menu"),n||a.push("popover"),void console.error(`Dropdown menu initialisation failed. Missing element(s): ${a.join(", ")}`,e)}let a=[],r=-1;const o=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),t.removeAttribute("aria-activedescendant"),n.setAttribute("aria-hidden","true"),e&&t.focus(),d(-1))},s=(r=!1)=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),t.setAttribute("aria-expanded","true"),n.setAttribute("aria-hidden","false"),a=Array.from(i.querySelectorAll('[role^="menuitem"]')).filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled"))),a.length>0&&r&&("first"===r?d(0):"last"===r&&d(a.length-1))},d=e=>{if(r>-1&&a[r]&&a[r].classList.remove("active"),r=e,r>-1&&a[r]){const e=a[r];e.classList.add("active"),t.setAttribute("aria-activedescendant",e.id)}else t.removeAttribute("aria-activedescendant")};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?o():s(!1)})),e.addEventListener("keydown",(e=>{const n="true"===t.getAttribute("aria-expanded");if("Escape"===e.key)return void(n&&o());if(!n)return void(["Enter"," "].includes(e.key)?(e.preventDefault(),s(!1)):"ArrowDown"===e.key?(e.preventDefault(),s("first")):"ArrowUp"===e.key&&(e.preventDefault(),s("last")));if(0===a.length)return;let i=r;switch(e.key){case"ArrowDown":e.preventDefault(),i=-1===r?0:Math.min(r+1,a.length-1);break;case"ArrowUp":e.preventDefault(),i=-1===r?a.length-1:Math.max(r-1,0);break;case"Home":e.preventDefault(),i=0;break;case"End":e.preventDefault(),i=a.length-1;break;case"Enter":case" ":return e.preventDefault(),a[r]?.click(),void o()}i!==r&&d(i)})),i.addEventListener("mousemove",(e=>{const t=e.target.closest('[role^="menuitem"]');if(t&&a.includes(t)){const e=a.indexOf(t);e!==r&&d(e)}})),i.addEventListener("mouseleave",(()=>{d(-1)})),i.addEventListener("click",(e=>{e.target.closest('[role^="menuitem"]')&&o()})),document.addEventListener("click",(t=>{e.contains(t.target)||o()})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&o(!1)})),e.dataset.dropdownMenuInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("dropdown-menu",".dropdown-menu:not([data-dropdown-menu-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=e.querySelector(":scope > [data-popover]");if(!t||!n){const i=[];return t||i.push("trigger"),n||i.push("content"),void console.error(`Popover initialisation failed. Missing element(s): ${i.join(", ")}`,e)}const i=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),n.setAttribute("aria-hidden","true"),e&&t.focus())};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?i():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}}));const i=n.querySelector("[autofocus]");i&&n.addEventListener("transitionend",(()=>{i.focus()}),{once:!0}),t.setAttribute("aria-expanded","true"),n.setAttribute("aria-hidden","false")})()})),e.addEventListener("keydown",(e=>{"Escape"===e.key&&i()})),document.addEventListener("click",(t=>{e.contains(t.target)||i()})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&i(!1)})),e.dataset.popoverInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("popover",".popover:not([data-popover-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=t.querySelector(":scope > span"),i=e.querySelector(":scope > [data-popover]"),a=i?i.querySelector('[role="listbox"]'):null,r=e.querySelector(':scope > input[type="hidden"]'),o=e.querySelector('header input[type="text"]');if(!(t&&i&&a&&r)){const n=[];return t||n.push("trigger"),i||n.push("popover"),a||n.push("listbox"),r||n.push("input"),void console.error(`Select component initialisation failed. Missing element(s): ${n.join(", ")}`,e)}const s=Array.from(a.querySelectorAll('[role="option"]')),d=s.filter((e=>"true"!==e.getAttribute("aria-disabled")));let c=[...d],l=-1;const u="true"===a.getAttribute("aria-multiselectable"),p=u?new Set:null,v=u?e.dataset.placeholder||"":null,h="true"===e.dataset.closeOnSelect,f=e=>e.dataset.value??e.textContent.trim(),m=e=>{if(l>-1&&d[l]&&d[l].classList.remove("active"),l=e,l>-1){const e=d[l];e.classList.add("active"),e.id?t.setAttribute("aria-activedescendant",e.id):t.removeAttribute("aria-activedescendant")}else t.removeAttribute("aria-activedescendant")},b=()=>{const e=getComputedStyle(i);return parseFloat(e.transitionDuration)>0||parseFloat(e.transitionDelay)>0},w=(t,i=!0)=>{let a;if(u){const e=Array.isArray(t)?t:[];p.clear(),e.forEach((e=>p.add(e)));const i=d.filter((e=>p.has(e)));0===i.length?(n.textContent=v,n.classList.add("text-muted-foreground")):(n.textContent=i.map((e=>e.dataset.label||e.textContent.trim())).join(", "),n.classList.remove("text-muted-foreground")),a=i.map(f),r.value=JSON.stringify(a)}else{const e=t;if(!e)return;n.innerHTML=e.innerHTML,a=f(e),r.value=a}d.forEach((e=>{(u?p.has(e):e===t)?e.setAttribute("aria-selected","true"):e.removeAttribute("aria-selected")})),i&&e.dispatchEvent(new CustomEvent("change",{detail:{value:a},bubbles:!0}))},g=(e=!0)=>{if("true"!==i.getAttribute("aria-hidden")){if(o){const e=()=>{o.value="",c=[...d],s.forEach((e=>e.setAttribute("aria-hidden","false")))};b()?i.addEventListener("transitionend",e,{once:!0}):e()}e&&t.focus(),i.setAttribute("aria-hidden","true"),t.setAttribute("aria-expanded","false"),m(-1)}},E=e=>{p.has(e)?p.delete(e):p.add(e),w(d.filter((e=>p.has(e))))},A=e=>{if(u){const t=d.find((t=>f(t)===e&&!p.has(t)));if(!t)return;p.add(t),w(d.filter((e=>p.has(e))))}else{const t=d.find((t=>f(t)===e));if(!t)return;r.value!==e&&w(t),g()}},y=e=>{if(!u)return;const t=d.find((t=>f(t)===e&&p.has(t)));t&&(p.delete(t),w(d.filter((e=>p.has(e)))))},k=e=>{if(!u)return;const t=d.find((t=>f(t)===e));t&&E(t)};if(o){const e=()=>{const e=o.value.trim().toLowerCase();m(-1),c=[],s.forEach((t=>{if(t.hasAttribute("data-force"))return t.setAttribute("aria-hidden","false"),void(d.includes(t)&&c.push(t));const n=(t.dataset.filter||t.textContent).trim().toLowerCase(),i=(t.dataset.keywords||"").toLowerCase().split(/[\s,]+/).filter(Boolean).some((t=>t.includes(e))),a=n.includes(e)||i;t.setAttribute("aria-hidden",String(!a)),a&&d.includes(t)&&c.push(t)}))};o.addEventListener("input",e)}if(u){const e=d.filter((e=>"true"===e.getAttribute("aria-selected")));try{const t=JSON.parse(r.value||"[]"),n=new Set(d.map(f)),i=Array.isArray(t)?t.filter((e=>n.has(e))):[],a=[];i.length>0?i.forEach((e=>{const t=d.find((t=>f(t)===e&&!a.includes(t)));t&&a.push(t)})):a.push(...e),w(a,!1)}catch(t){w(e,!1)}}else{const e=d.find((e=>f(e)===r.value))||d[0];e&&w(e,!1)}const L=e=>{const n="false"===i.getAttribute("aria-hidden");if(!["ArrowDown","ArrowUp","Enter","Home","End","Escape"].includes(e.key))return;if(!n)return void("Enter"!==e.key&&"Escape"!==e.key&&(e.preventDefault(),t.click()));if(e.preventDefault(),"Escape"===e.key)return void g();if("Enter"===e.key){if(l>-1){const e=d[l];u?(E(e),h&&g()):(r.value!==f(e)&&w(e),g())}return}if(0===c.length)return;const a=l>-1?c.indexOf(d[l]):-1;let o=a;switch(e.key){case"ArrowDown":a<c.length-1&&(o=a+1);break;case"ArrowUp":a>0?o=a-1:-1===a&&(o=0);break;case"Home":o=0;break;case"End":o=c.length-1}if(o!==a){const e=c[o];m(d.indexOf(e)),e.scrollIntoView({block:"nearest",behavior:"smooth"})}};a.addEventListener("mousemove",(e=>{const t=e.target.closest('[role="option"]');if(t&&c.includes(t)){const e=d.indexOf(t);e!==l&&m(e)}})),a.addEventListener("mouseleave",(()=>{const e=a.querySelector('[role="option"][aria-selected="true"]');m(e?d.indexOf(e):-1)})),t.addEventListener("keydown",L),o&&o.addEventListener("keydown",L);t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?g():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),o&&(b()?i.addEventListener("transitionend",(()=>{o.focus()}),{once:!0}):o.focus()),i.setAttribute("aria-hidden","false"),t.setAttribute("aria-expanded","true");const n=a.querySelector('[role="option"][aria-selected="true"]');n&&(m(d.indexOf(n)),n.scrollIntoView({block:"nearest"}))})()})),a.addEventListener("click",(e=>{const n=e.target.closest('[role="option"]');if(!n)return;const i=d.find((e=>e===n));i&&(u?(E(i),h?g():(m(d.indexOf(i)),o?o.focus():t.focus())):(r.value!==f(i)&&w(i),g()))})),document.addEventListener("click",(t=>{e.contains(t.target)||g(!1)})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&g(!1)})),i.setAttribute("aria-hidden","true"),Object.defineProperty(e,"value",{get:()=>u?d.filter((e=>p.has(e))).map(f):r.value,set:e=>{if(u){const t=Array.isArray(e)?e:null!=e?[e]:[],n=[];t.forEach((e=>{const t=d.find((t=>f(t)===e&&!n.includes(t)));t&&n.push(t)})),w(n)}else{const t=d.find((t=>f(t)===e));t&&(w(t),g())}}}),e.select=A,e.selectByValue=A,u&&(e.deselect=y,e.toggle=k,e.selectAll=()=>w(d),e.selectNone=()=>w([])),e.dataset.selectInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("select","div.select:not([data-select-initialized])",e)})(),(()=>{if(!window.history.__basecoatPatched){const e=window.history.pushState;window.history.pushState=function(...t){e.apply(this,t),window.dispatchEvent(new Event("basecoat:locationchange"))};const t=window.history.replaceState;window.history.replaceState=function(...e){t.apply(this,e),window.dispatchEvent(new Event("basecoat:locationchange"))},window.history.__basecoatPatched=!0}const e=e=>{const t="false"!==e.dataset.initialOpen,n="true"===e.dataset.initialMobileOpen,i=parseInt(e.dataset.breakpoint)||768;let a=i>0?window.innerWidth>=i?t:n:t;const r=()=>{const t=window.location.pathname.replace(/\/$/,"");e.querySelectorAll("a").forEach((e=>{if(e.hasAttribute("data-ignore-current"))return;new URL(e.href).pathname.replace(/\/$/,"")===t?e.setAttribute("aria-current","page"):e.removeAttribute("aria-current")}))},o=()=>{e.setAttribute("aria-hidden",!a),a?e.removeAttribute("inert"):e.setAttribute("inert","")},s=e=>{a=e,o()},d=e.id;document.addEventListener("basecoat:sidebar",(e=>{if(!e.detail?.id||e.detail.id===d)switch(e.detail?.action){case"open":s(!0);break;case"close":s(!1);break;default:s(!a)}})),e.addEventListener("click",(t=>{const n=t.target,a=e.querySelector("nav");if(window.innerWidth<i&&n.closest("a, button")&&!n.closest("[data-keep-mobile-sidebar-open]"))return document.activeElement&&document.activeElement.blur(),void s(!1);(n===e||a&&!a.contains(n))&&(document.activeElement&&document.activeElement.blur(),s(!1))})),window.addEventListener("popstate",r),window.addEventListener("basecoat:locationchange",r),o(),r(),e.dataset.sidebarInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("sidebar",".sidebar:not([data-sidebar-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector('[role="tablist"]');if(!t)return;const n=Array.from(t.querySelectorAll('[role="tab"]')),i=n.map((e=>document.getElementById(e.getAttribute("aria-controls")))).filter(Boolean),a=e=>{n.forEach(((e,t)=>{e.setAttribute("aria-selected","false"),e.setAttribute("tabindex","-1"),i[t]&&(i[t].hidden=!0)})),e.setAttribute("aria-selected","true"),e.setAttribute("tabindex","0");const t=document.getElementById(e.getAttribute("aria-controls"));t&&(t.hidden=!1)};t.addEventListener("click",(e=>{const t=e.target.closest('[role="tab"]');t&&a(t)})),t.addEventListener("keydown",(e=>{const t=e.target;if(!n.includes(t))return;let i;const r=n.indexOf(t);switch(e.key){case"ArrowRight":i=n[(r+1)%n.length];break;case"ArrowLeft":i=n[(r-1+n.length)%n.length];break;case"Home":i=n[0];break;case"End":i=n[n.length-1];break;default:return}e.preventDefault(),a(i),i.focus()})),e.dataset.tabsInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("tabs",".tabs:not([data-tabs-initialized])",e)})(),(()=>{let e;const t=new WeakMap;let n=!1;const i={success:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>',error:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>',info:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>',warning:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>'};function a(e){if(e.dataset.toastInitialized)return;const i=parseInt(e.dataset.duration),a=-1!==i?i||("error"===e.dataset.category?5e3:3e3):-1,r={remainingTime:a,timeoutId:null,startTime:null};-1!==a&&(n?r.timeoutId=null:(r.startTime=Date.now(),r.timeoutId=setTimeout((()=>s(e)),a))),t.set(e,r),e.dataset.toastInitialized="true"}function r(){n||(n=!0,e.querySelectorAll('.toast:not([aria-hidden="true"])').forEach((e=>{if(!t.has(e))return;const n=t.get(e);n.timeoutId&&(clearTimeout(n.timeoutId),n.timeoutId=null,n.remainingTime-=Date.now()-n.startTime)})))}function o(){n&&(n=!1,e.querySelectorAll('.toast:not([aria-hidden="true"])').forEach((e=>{if(!t.has(e))return;const n=t.get(e);-1===n.remainingTime||n.timeoutId||(n.remainingTime>0?(n.startTime=Date.now(),n.timeoutId=setTimeout((()=>s(e)),n.remainingTime)):s(e))})))}function s(e){if(!t.has(e))return;const n=t.get(e);clearTimeout(n.timeoutId),t.delete(e),e.contains(document.activeElement)&&document.activeElement.blur(),e.setAttribute("aria-hidden","true"),e.addEventListener("transitionend",(()=>e.remove()),{once:!0})}document.addEventListener("basecoat:toast",(t=>{if(!e)return void console.error("Cannot create toast: toaster container not found on page.");const n=function(e){const{category:t="info",title:n,description:a,action:r,cancel:o,duration:s,icon:d}=e,c=d||t&&i[t]||"",l=n?`<h2>${n}</h2>`:"",u=a?`<p>${a}</p>`:"",p=r?.href?`<a href="${r.href}" class="btn" data-toast-action>${r.label}</a>`:r?.onclick?`<button type="button" class="btn" data-toast-action onclick="${r.onclick}">${r.label}</button>`:"",v=o?`<button type="button" class="btn-outline h-6 text-xs px-2.5 rounded-sm" data-toast-cancel onclick="${o?.onclick}">${o.label}</button>`:"",h=`\n <div\n class="toast"\n role="${"error"===t?"alert":"status"}"\n aria-atomic="true"\n ${t?`data-category="${t}"`:""}\n ${void 0!==s?`data-duration="${s}"`:""}\n >\n <div class="toast-content">\n ${c}\n <section>\n ${l}\n ${u}\n </section>\n ${p||v?`<footer>${p}${v}</footer>`:""}\n </div>\n </div>\n </div>\n `,f=document.createElement("template");return f.innerHTML=h.trim(),f.content.firstChild}(t.detail?.config||{});e.appendChild(n)})),window.basecoat&&(window.basecoat.register("toaster","#toaster:not([data-toaster-initialized])",(function(t){t.dataset.toasterInitialized||(e=t,e.addEventListener("mouseenter",r),e.addEventListener("mouseleave",o),e.addEventListener("click",(e=>{const t=e.target.closest(".toast footer a"),n=e.target.closest(".toast footer button");(t||n)&&s(e.target.closest(".toast"))})),e.querySelectorAll(".toast:not([data-toast-initialized])").forEach(a),e.dataset.toasterInitialized="true",e.dispatchEvent(new CustomEvent("basecoat:initialized")))})),window.basecoat.register("toast",".toast:not([data-toast-initialized])",a))})();
|
|
1
|
+
(()=>{const e={};let t=null;const n=()=>{Object.entries(e).forEach((([e,{selector:t,init:n}])=>{document.querySelectorAll(t).forEach(n)}))},i=t=>{t.nodeType===Node.ELEMENT_NODE&&Object.entries(e).forEach((([e,{selector:n,init:i}])=>{t.matches(n)&&i(t),t.querySelectorAll(n).forEach(i)}))},a=()=>{t||(t=new MutationObserver((e=>{e.forEach((e=>{e.addedNodes.forEach(i)}))})),t.observe(document.body,{childList:!0,subtree:!0}))};window.basecoat={register:(t,n,i)=>{e[t]={selector:n,init:i}},init:t=>{const n=e[t];if(!n)return void console.warn(`Component '${t}' not found in registry`);const i=`data-${t}-initialized`;document.querySelectorAll(`[${i}]`).forEach((e=>{e.removeAttribute(i)})),document.querySelectorAll(n.selector).forEach(n.init)},initAll:()=>{Object.entries(e).forEach((([e,{selector:t}])=>{const n=`data-${e}-initialized`;document.querySelectorAll(`[${n}]`).forEach((e=>{e.removeAttribute(n)}))})),n()},start:a,stop:()=>{t&&(t.disconnect(),t=null)}},document.addEventListener("DOMContentLoaded",(()=>{n(),a()}))})(),(()=>{const e=e=>{const t=e.querySelector("header input"),n=e.querySelector('[role="menu"]');if(!t||!n){const i=[];return t||i.push("input"),n||i.push("menu"),void console.error(`Command component initialization failed. Missing element(s): ${i.join(", ")}`,e)}const i=Array.from(n.querySelectorAll('[role="menuitem"]')),a=i.filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled")));let r=[...a],o=-1;const s=e=>{if(o>-1&&a[o]&&a[o].classList.remove("active"),o=e,o>-1){const e=a[o];e.classList.add("active"),e.id?t.setAttribute("aria-activedescendant",e.id):t.removeAttribute("aria-activedescendant")}else t.removeAttribute("aria-activedescendant")};t.addEventListener("input",(()=>{const e=t.value.trim().toLowerCase();s(-1),r=[],i.forEach((t=>{if(t.hasAttribute("data-force"))return t.setAttribute("aria-hidden","false"),void(a.includes(t)&&r.push(t));const n=(t.dataset.filter||t.textContent).trim().toLowerCase(),i=(t.dataset.keywords||"").toLowerCase().split(/[\s,]+/).filter(Boolean).some((t=>t.includes(e))),o=n.includes(e)||i;t.setAttribute("aria-hidden",String(!o)),o&&a.includes(t)&&r.push(t)})),r.length>0&&(s(a.indexOf(r[0])),r[0].scrollIntoView({block:"nearest"}))}));n.addEventListener("mousemove",(e=>{const t=e.target.closest('[role="menuitem"]');if(t&&r.includes(t)){const e=a.indexOf(t);e!==o&&s(e)}})),n.addEventListener("click",(t=>{const n=t.target.closest('[role="menuitem"]');if(n&&r.includes(n)){const t=e.closest("dialog.command-dialog");t&&!n.hasAttribute("data-keep-command-open")&&t.close()}})),t.addEventListener("keydown",(e=>{if(!["ArrowDown","ArrowUp","Enter","Home","End"].includes(e.key))return;if("Enter"===e.key)return e.preventDefault(),void(o>-1&&a[o]?.click());if(0===r.length)return;e.preventDefault();const t=o>-1?r.indexOf(a[o]):-1;let n=t;switch(e.key){case"ArrowDown":t<r.length-1&&(n=t+1);break;case"ArrowUp":t>0?n=t-1:-1===t&&(n=0);break;case"Home":n=0;break;case"End":n=r.length-1}if(n!==t){const e=r[n];s(a.indexOf(e)),e.scrollIntoView({block:"nearest",behavior:"smooth"})}})),r.length>0&&(s(a.indexOf(r[0])),r[0].scrollIntoView({block:"nearest"})),e.dataset.commandInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("command",".command:not([data-command-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=e.querySelector(":scope > [data-popover]"),i=n.querySelector('[role="menu"]');if(!t||!i||!n){const a=[];return t||a.push("trigger"),i||a.push("menu"),n||a.push("popover"),void console.error(`Dropdown menu initialisation failed. Missing element(s): ${a.join(", ")}`,e)}let a=[],r=-1;const o=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),t.removeAttribute("aria-activedescendant"),n.setAttribute("aria-hidden","true"),e&&t.focus(),d(-1))},s=(r=!1)=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),t.setAttribute("aria-expanded","true"),n.setAttribute("aria-hidden","false"),a=Array.from(i.querySelectorAll('[role^="menuitem"]')).filter((e=>!e.hasAttribute("disabled")&&"true"!==e.getAttribute("aria-disabled"))),a.length>0&&r&&("first"===r?d(0):"last"===r&&d(a.length-1))},d=e=>{if(r>-1&&a[r]&&a[r].classList.remove("active"),r=e,r>-1&&a[r]){const e=a[r];e.classList.add("active"),t.setAttribute("aria-activedescendant",e.id)}else t.removeAttribute("aria-activedescendant")};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?o():s(!1)})),e.addEventListener("keydown",(e=>{const n="true"===t.getAttribute("aria-expanded");if("Escape"===e.key)return void(n&&o());if(!n)return void(["Enter"," "].includes(e.key)?(e.preventDefault(),s(!1)):"ArrowDown"===e.key?(e.preventDefault(),s("first")):"ArrowUp"===e.key&&(e.preventDefault(),s("last")));if(0===a.length)return;let i=r;switch(e.key){case"ArrowDown":e.preventDefault(),i=-1===r?0:Math.min(r+1,a.length-1);break;case"ArrowUp":e.preventDefault(),i=-1===r?a.length-1:Math.max(r-1,0);break;case"Home":e.preventDefault(),i=0;break;case"End":e.preventDefault(),i=a.length-1;break;case"Enter":case" ":return e.preventDefault(),a[r]?.click(),void o()}i!==r&&d(i)})),i.addEventListener("mousemove",(e=>{const t=e.target.closest('[role^="menuitem"]');if(t&&a.includes(t)){const e=a.indexOf(t);e!==r&&d(e)}})),i.addEventListener("mouseleave",(()=>{d(-1)})),i.addEventListener("click",(e=>{e.target.closest('[role^="menuitem"]')&&o()})),document.addEventListener("click",(t=>{e.contains(t.target)||o()})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&o(!1)})),e.dataset.dropdownMenuInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("dropdown-menu",".dropdown-menu:not([data-dropdown-menu-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=e.querySelector(":scope > [data-popover]");if(!t||!n){const i=[];return t||i.push("trigger"),n||i.push("content"),void console.error(`Popover initialisation failed. Missing element(s): ${i.join(", ")}`,e)}const i=(e=!0)=>{"false"!==t.getAttribute("aria-expanded")&&(t.setAttribute("aria-expanded","false"),n.setAttribute("aria-hidden","true"),e&&t.focus())};t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?i():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}}));const i=n.querySelector("[autofocus]");i&&n.addEventListener("transitionend",(()=>{i.focus()}),{once:!0}),t.setAttribute("aria-expanded","true"),n.setAttribute("aria-hidden","false")})()})),e.addEventListener("keydown",(e=>{"Escape"===e.key&&i()})),document.addEventListener("click",(t=>{e.contains(t.target)||i()})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&i(!1)})),e.dataset.popoverInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("popover",".popover:not([data-popover-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector(":scope > button"),n=t.querySelector(":scope > span"),i=e.querySelector(":scope > [data-popover]"),a=i?i.querySelector('[role="listbox"]'):null,r=e.querySelector(':scope > input[type="hidden"]'),o=e.querySelector('header input[type="text"]');if(!(t&&i&&a&&r)){const n=[];return t||n.push("trigger"),i||n.push("popover"),a||n.push("listbox"),r||n.push("input"),void console.error(`Select component initialisation failed. Missing element(s): ${n.join(", ")}`,e)}const s=Array.from(a.querySelectorAll('[role="option"]')),d=s.filter((e=>"true"!==e.getAttribute("aria-disabled")));let c=[...d],l=-1;const u="true"===a.getAttribute("aria-multiselectable"),v=u?new Set:null,f=u?e.dataset.placeholder||"":null,m="true"===e.dataset.closeOnSelect,p=e=>e.dataset.value??e.textContent.trim(),h=e=>{if(l>-1&&d[l]&&d[l].classList.remove("active"),l=e,l>-1){const e=d[l];e.classList.add("active"),e.id?t.setAttribute("aria-activedescendant",e.id):t.removeAttribute("aria-activedescendant")}else t.removeAttribute("aria-activedescendant")},b=()=>{const e=getComputedStyle(i);return parseFloat(e.transitionDuration)>0||parseFloat(e.transitionDelay)>0},w=(t,i=!0)=>{let a;if(u){const e=Array.isArray(t)?t:[];v.clear(),e.forEach((e=>v.add(e)));const i=d.filter((e=>v.has(e)));0===i.length?(n.textContent=f,n.classList.add("text-muted-foreground")):(n.textContent=i.map((e=>e.dataset.label||e.textContent.trim())).join(", "),n.classList.remove("text-muted-foreground")),a=i.map(p),r.value=JSON.stringify(a)}else{const e=t;if(!e)return;n.innerHTML=e.innerHTML,a=p(e),r.value=a}d.forEach((e=>{(u?v.has(e):e===t)?e.setAttribute("aria-selected","true"):e.removeAttribute("aria-selected")})),i&&e.dispatchEvent(new CustomEvent("change",{detail:{value:a},bubbles:!0}))},g=(e=!0)=>{if("true"!==i.getAttribute("aria-hidden")){if(o){const e=()=>{o.value="",c=[...d],s.forEach((e=>e.setAttribute("aria-hidden","false")))};b()?i.addEventListener("transitionend",e,{once:!0}):e()}e&&t.focus(),i.setAttribute("aria-hidden","true"),t.setAttribute("aria-expanded","false"),h(-1)}},E=e=>{v.has(e)?v.delete(e):v.add(e),w(d.filter((e=>v.has(e))))},A=e=>{if(u){const t=d.find((t=>p(t)===e&&!v.has(t)));if(!t)return;v.add(t),w(d.filter((e=>v.has(e))))}else{const t=d.find((t=>p(t)===e));if(!t)return;r.value!==e&&w(t),g()}},k=e=>{if(!u)return;const t=d.find((t=>p(t)===e&&v.has(t)));t&&(v.delete(t),w(d.filter((e=>v.has(e)))))},y=e=>{if(!u)return;const t=d.find((t=>p(t)===e));t&&E(t)};if(o){const e=()=>{const e=o.value.trim().toLowerCase();h(-1),c=[],s.forEach((t=>{if(t.hasAttribute("data-force"))return t.setAttribute("aria-hidden","false"),void(d.includes(t)&&c.push(t));const n=(t.dataset.filter||t.textContent).trim().toLowerCase(),i=(t.dataset.keywords||"").toLowerCase().split(/[\s,]+/).filter(Boolean).some((t=>t.includes(e))),a=n.includes(e)||i;t.setAttribute("aria-hidden",String(!a)),a&&d.includes(t)&&c.push(t)}))};o.addEventListener("input",e)}if(u){const e=d.filter((e=>"true"===e.getAttribute("aria-selected")));try{const t=JSON.parse(r.value||"[]"),n=new Set(d.map(p)),i=Array.isArray(t)?t.filter((e=>n.has(e))):[],a=[];i.length>0?i.forEach((e=>{const t=d.find((t=>p(t)===e&&!a.includes(t)));t&&a.push(t)})):a.push(...e),w(a,!1)}catch(t){w(e,!1)}}else{const e=d.find((e=>p(e)===r.value))||d[0];e&&w(e,!1)}const L=e=>{const n="false"===i.getAttribute("aria-hidden");if(!["ArrowDown","ArrowUp","Enter","Home","End","Escape"].includes(e.key))return;if(!n)return void("Enter"!==e.key&&"Escape"!==e.key&&(e.preventDefault(),t.click()));if(e.preventDefault(),"Escape"===e.key)return void g();if("Enter"===e.key){if(l>-1){const e=d[l];u?(E(e),m&&g()):(r.value!==p(e)&&w(e),g())}return}if(0===c.length)return;const a=l>-1?c.indexOf(d[l]):-1;let o=a;switch(e.key){case"ArrowDown":a<c.length-1&&(o=a+1);break;case"ArrowUp":a>0?o=a-1:-1===a&&(o=0);break;case"Home":o=0;break;case"End":o=c.length-1}if(o!==a){const e=c[o];h(d.indexOf(e)),e.scrollIntoView({block:"nearest",behavior:"smooth"})}};a.addEventListener("mousemove",(e=>{const t=e.target.closest('[role="option"]');if(t&&c.includes(t)){const e=d.indexOf(t);e!==l&&h(e)}})),a.addEventListener("mouseleave",(()=>{const e=a.querySelector('[role="option"][aria-selected="true"]');h(e?d.indexOf(e):-1)})),t.addEventListener("keydown",L),o&&o.addEventListener("keydown",L);t.addEventListener("click",(()=>{"true"===t.getAttribute("aria-expanded")?g():(()=>{document.dispatchEvent(new CustomEvent("basecoat:popover",{detail:{source:e}})),o&&(b()?i.addEventListener("transitionend",(()=>{o.focus()}),{once:!0}):o.focus()),i.setAttribute("aria-hidden","false"),t.setAttribute("aria-expanded","true");const n=a.querySelector('[role="option"][aria-selected="true"]');n&&(h(d.indexOf(n)),n.scrollIntoView({block:"nearest"}))})()})),a.addEventListener("click",(e=>{const n=e.target.closest('[role="option"]');if(!n)return;const i=d.find((e=>e===n));i&&(u?(E(i),m?g():(h(d.indexOf(i)),o?o.focus():t.focus())):(r.value!==p(i)&&w(i),g()))})),document.addEventListener("click",(t=>{e.contains(t.target)||g(!1)})),document.addEventListener("basecoat:popover",(t=>{t.detail.source!==e&&g(!1)})),i.setAttribute("aria-hidden","true"),Object.defineProperty(e,"value",{get:()=>u?d.filter((e=>v.has(e))).map(p):r.value,set:e=>{if(u){const t=Array.isArray(e)?e:null!=e?[e]:[],n=[];t.forEach((e=>{const t=d.find((t=>p(t)===e&&!n.includes(t)));t&&n.push(t)})),w(n)}else{const t=d.find((t=>p(t)===e));t&&(w(t),g())}}}),e.select=A,e.selectByValue=A,u&&(e.deselect=k,e.toggle=y,e.selectAll=()=>w(d),e.selectNone=()=>w([])),e.dataset.selectInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("select","div.select:not([data-select-initialized])",e)})(),(()=>{const e=e=>{const t="false"!==e.dataset.initialOpen,n="true"===e.dataset.initialMobileOpen,i=parseInt(e.dataset.breakpoint)||768;let a=i>0?window.innerWidth>=i?t:n:t;const r=()=>{e.setAttribute("aria-hidden",!a),a?e.removeAttribute("inert"):e.setAttribute("inert","")},o=e=>{a=e,r()},s=e.id;document.addEventListener("basecoat:sidebar",(e=>{if(!e.detail?.id||e.detail.id===s)switch(e.detail?.action){case"open":o(!0);break;case"close":o(!1);break;default:o(!a)}})),e.addEventListener("click",(t=>{const n=t.target,a=e.querySelector("nav");if(window.innerWidth<i&&n.closest("a, button")&&!n.closest("[data-keep-mobile-sidebar-open]"))return document.activeElement&&document.activeElement.blur(),void o(!1);(n===e||a&&!a.contains(n))&&(document.activeElement&&document.activeElement.blur(),o(!1))})),r(),e.dataset.sidebarInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("sidebar",".sidebar:not([data-sidebar-initialized])",e)})(),(()=>{const e=e=>{const t=e.querySelector('[role="tablist"]');if(!t)return;const n=Array.from(t.querySelectorAll('[role="tab"]')),i=n.map((e=>document.getElementById(e.getAttribute("aria-controls")))).filter(Boolean),a=e=>{n.forEach(((e,t)=>{e.setAttribute("aria-selected","false"),e.setAttribute("tabindex","-1"),i[t]&&(i[t].hidden=!0)})),e.setAttribute("aria-selected","true"),e.setAttribute("tabindex","0");const t=document.getElementById(e.getAttribute("aria-controls"));t&&(t.hidden=!1)};t.addEventListener("click",(e=>{const t=e.target.closest('[role="tab"]');t&&a(t)})),t.addEventListener("keydown",(e=>{const t=e.target;if(!n.includes(t))return;let i;const r=n.indexOf(t);switch(e.key){case"ArrowRight":i=n[(r+1)%n.length];break;case"ArrowLeft":i=n[(r-1+n.length)%n.length];break;case"Home":i=n[0];break;case"End":i=n[n.length-1];break;default:return}e.preventDefault(),a(i),i.focus()})),e.dataset.tabsInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("tabs",".tabs:not([data-tabs-initialized])",e)})(),(()=>{let e;const t=new WeakMap;let n=!1;const i={success:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>',error:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>',info:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>',warning:'<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>'};function a(e){if(e.dataset.toastInitialized)return;const i=parseInt(e.dataset.duration),a=-1!==i?i||("error"===e.dataset.category?5e3:3e3):-1,r={remainingTime:a,timeoutId:null,startTime:null};-1!==a&&(n?r.timeoutId=null:(r.startTime=Date.now(),r.timeoutId=setTimeout((()=>s(e)),a))),t.set(e,r),e.dataset.toastInitialized="true"}function r(){n||(n=!0,e.querySelectorAll('.toast:not([aria-hidden="true"])').forEach((e=>{if(!t.has(e))return;const n=t.get(e);n.timeoutId&&(clearTimeout(n.timeoutId),n.timeoutId=null,n.remainingTime-=Date.now()-n.startTime)})))}function o(){n&&(n=!1,e.querySelectorAll('.toast:not([aria-hidden="true"])').forEach((e=>{if(!t.has(e))return;const n=t.get(e);-1===n.remainingTime||n.timeoutId||(n.remainingTime>0?(n.startTime=Date.now(),n.timeoutId=setTimeout((()=>s(e)),n.remainingTime)):s(e))})))}function s(e){if(!t.has(e))return;const n=t.get(e);clearTimeout(n.timeoutId),t.delete(e),e.contains(document.activeElement)&&document.activeElement.blur(),e.setAttribute("aria-hidden","true"),e.addEventListener("transitionend",(()=>e.remove()),{once:!0})}document.addEventListener("basecoat:toast",(t=>{if(!e)return void console.error("Cannot create toast: toaster container not found on page.");const n=function(e){const{category:t="info",title:n,description:a,action:r,cancel:o,duration:s,icon:d}=e,c=d||t&&i[t]||"",l=n?`<h2>${n}</h2>`:"",u=a?`<p>${a}</p>`:"",v=r?.href?`<a href="${r.href}" class="btn" data-toast-action>${r.label}</a>`:r?.onclick?`<button type="button" class="btn" data-toast-action onclick="${r.onclick}">${r.label}</button>`:"",f=o?`<button type="button" class="btn-outline h-6 text-xs px-2.5 rounded-sm" data-toast-cancel onclick="${o?.onclick}">${o.label}</button>`:"",m=`\n <div\n class="toast"\n role="${"error"===t?"alert":"status"}"\n aria-atomic="true"\n ${t?`data-category="${t}"`:""}\n ${void 0!==s?`data-duration="${s}"`:""}\n >\n <div class="toast-content">\n ${c}\n <section>\n ${l}\n ${u}\n </section>\n ${v||f?`<footer>${v}${f}</footer>`:""}\n </div>\n </div>\n </div>\n `,p=document.createElement("template");return p.innerHTML=m.trim(),p.content.firstChild}(t.detail?.config||{});e.appendChild(n)})),window.basecoat&&(window.basecoat.register("toaster","#toaster:not([data-toaster-initialized])",(function(t){t.dataset.toasterInitialized||(e=t,e.addEventListener("mouseenter",r),e.addEventListener("mouseleave",o),e.addEventListener("click",(e=>{const t=e.target.closest(".toast footer a"),n=e.target.closest(".toast footer button");(t||n)&&s(e.target.closest(".toast"))})),e.querySelectorAll(".toast:not([data-toast-initialized])").forEach(a),e.dataset.toasterInitialized="true",e.dispatchEvent(new CustomEvent("basecoat:initialized")))})),window.basecoat.register("toast",".toast:not([data-toast-initialized])",a))})();
|
|
@@ -1,21 +1,4 @@
|
|
|
1
1
|
(() => {
|
|
2
|
-
// Monkey patching the history API to detect client-side navigation
|
|
3
|
-
if (!window.history.__basecoatPatched) {
|
|
4
|
-
const originalPushState = window.history.pushState;
|
|
5
|
-
window.history.pushState = function(...args) {
|
|
6
|
-
originalPushState.apply(this, args);
|
|
7
|
-
window.dispatchEvent(new Event('basecoat:locationchange'));
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const originalReplaceState = window.history.replaceState;
|
|
11
|
-
window.history.replaceState = function(...args) {
|
|
12
|
-
originalReplaceState.apply(this, args);
|
|
13
|
-
window.dispatchEvent(new Event('basecoat:locationchange'));
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
window.history.__basecoatPatched = true;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
2
|
const initSidebar = (sidebarComponent) => {
|
|
20
3
|
const initialOpen = sidebarComponent.dataset.initialOpen !== 'false';
|
|
21
4
|
const initialMobileOpen = sidebarComponent.dataset.initialMobileOpen === 'true';
|
|
@@ -25,20 +8,6 @@
|
|
|
25
8
|
? (window.innerWidth >= breakpoint ? initialOpen : initialMobileOpen)
|
|
26
9
|
: initialOpen;
|
|
27
10
|
|
|
28
|
-
const updateCurrentPageLinks = () => {
|
|
29
|
-
const currentPath = window.location.pathname.replace(/\/$/, '');
|
|
30
|
-
sidebarComponent.querySelectorAll('a').forEach(link => {
|
|
31
|
-
if (link.hasAttribute('data-ignore-current')) return;
|
|
32
|
-
|
|
33
|
-
const linkPath = new URL(link.href).pathname.replace(/\/$/, '');
|
|
34
|
-
if (linkPath === currentPath) {
|
|
35
|
-
link.setAttribute('aria-current', 'page');
|
|
36
|
-
} else {
|
|
37
|
-
link.removeAttribute('aria-current');
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
};
|
|
41
|
-
|
|
42
11
|
const updateState = () => {
|
|
43
12
|
sidebarComponent.setAttribute('aria-hidden', !open);
|
|
44
13
|
if (open) {
|
|
@@ -89,11 +58,7 @@
|
|
|
89
58
|
}
|
|
90
59
|
});
|
|
91
60
|
|
|
92
|
-
window.addEventListener('popstate', updateCurrentPageLinks);
|
|
93
|
-
window.addEventListener('basecoat:locationchange', updateCurrentPageLinks);
|
|
94
|
-
|
|
95
61
|
updateState();
|
|
96
|
-
updateCurrentPageLinks();
|
|
97
62
|
sidebarComponent.dataset.sidebarInitialized = true;
|
|
98
63
|
sidebarComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
|
|
99
64
|
};
|
|
@@ -101,4 +66,4 @@
|
|
|
101
66
|
if (window.basecoat) {
|
|
102
67
|
window.basecoat.register('sidebar', '.sidebar:not([data-sidebar-initialized])', initSidebar);
|
|
103
68
|
}
|
|
104
|
-
})();
|
|
69
|
+
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{
|
|
1
|
+
(()=>{const e=e=>{const t="false"!==e.dataset.initialOpen,i="true"===e.dataset.initialMobileOpen,a=parseInt(e.dataset.breakpoint)||768;let n=a>0?window.innerWidth>=a?t:i:t;const d=()=>{e.setAttribute("aria-hidden",!n),n?e.removeAttribute("inert"):e.setAttribute("inert","")},s=e=>{n=e,d()},o=e.id;document.addEventListener("basecoat:sidebar",(e=>{if(!e.detail?.id||e.detail.id===o)switch(e.detail?.action){case"open":s(!0);break;case"close":s(!1);break;default:s(!n)}})),e.addEventListener("click",(t=>{const i=t.target,n=e.querySelector("nav");if(window.innerWidth<a&&i.closest("a, button")&&!i.closest("[data-keep-mobile-sidebar-open]"))return document.activeElement&&document.activeElement.blur(),void s(!1);(i===e||n&&!n.contains(i))&&(document.activeElement&&document.activeElement.blur(),s(!1))})),d(),e.dataset.sidebarInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("sidebar",".sidebar:not([data-sidebar-initialized])",e)})();
|
package/package.json
CHANGED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
{#
|
|
2
|
-
Renders a carousel component with navigation controls and optional indicators.
|
|
3
|
-
|
|
4
|
-
@param id {string} [optional] - Unique identifier for the carousel component. Auto-generated if not provided.
|
|
5
|
-
@param slides {array} - An array of objects representing carousel slides.
|
|
6
|
-
Each object should have:
|
|
7
|
-
- content {string}: HTML content for the slide.
|
|
8
|
-
- attrs {object} [optional]: Additional HTML attributes for the slide item.
|
|
9
|
-
@param loop {boolean} [optional] [default=false] - Enable continuous looping.
|
|
10
|
-
@param autoplay {number} [optional] [default=0] - Auto-advance delay in milliseconds (0 = disabled).
|
|
11
|
-
@param align {string} [optional] [default='start'] - Slide alignment ('start' or 'center').
|
|
12
|
-
@param orientation {string} [optional] [default='horizontal'] - Carousel orientation ('horizontal' or 'vertical').
|
|
13
|
-
@param show_controls {boolean} [optional] [default=true] - Show previous/next navigation buttons.
|
|
14
|
-
@param show_indicators {boolean} [optional] [default=true] - Show slide indicator dots.
|
|
15
|
-
@param main_attrs {object} [optional] - Additional HTML attributes for the main container.
|
|
16
|
-
@param viewport_attrs {object} [optional] - Additional HTML attributes for the viewport container.
|
|
17
|
-
#}
|
|
18
|
-
{% macro carousel(
|
|
19
|
-
id=None,
|
|
20
|
-
slides=[],
|
|
21
|
-
loop=false,
|
|
22
|
-
autoplay=0,
|
|
23
|
-
align='start',
|
|
24
|
-
orientation='horizontal',
|
|
25
|
-
show_controls=true,
|
|
26
|
-
show_indicators=true,
|
|
27
|
-
main_attrs={},
|
|
28
|
-
viewport_attrs={}
|
|
29
|
-
)
|
|
30
|
-
%}
|
|
31
|
-
{% set id = id or ("carousel-" + (range(100000, 999999) | random | string)) %}
|
|
32
|
-
<div
|
|
33
|
-
class="carousel {{ main_attrs.class }}"
|
|
34
|
-
id="{{ id }}"
|
|
35
|
-
data-carousel-loop="{{ 'true' if loop else 'false' }}"
|
|
36
|
-
{% if autoplay > 0 %}data-carousel-autoplay="{{ autoplay }}"{% endif %}
|
|
37
|
-
data-orientation="{{ orientation }}"
|
|
38
|
-
role="region"
|
|
39
|
-
aria-roledescription="carousel"
|
|
40
|
-
aria-label="Carousel"
|
|
41
|
-
tabindex="0"
|
|
42
|
-
{% for key, value in main_attrs.items() %}
|
|
43
|
-
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
|
|
44
|
-
{% endfor %}
|
|
45
|
-
>
|
|
46
|
-
<div
|
|
47
|
-
class="carousel-viewport {{ viewport_attrs.class }}"
|
|
48
|
-
{% for key, value in viewport_attrs.items() %}
|
|
49
|
-
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
|
|
50
|
-
{% endfor %}
|
|
51
|
-
>
|
|
52
|
-
<div
|
|
53
|
-
class="carousel-slides"
|
|
54
|
-
data-orientation="{{ orientation }}"
|
|
55
|
-
>
|
|
56
|
-
{% for slide in slides %}
|
|
57
|
-
<div
|
|
58
|
-
class="carousel-item"
|
|
59
|
-
role="group"
|
|
60
|
-
aria-roledescription="slide"
|
|
61
|
-
aria-label="{{ loop.index }} of {{ slides | length }}"
|
|
62
|
-
{% if align == 'center' %}data-align="center"{% endif %}
|
|
63
|
-
{% if slide.attrs %}
|
|
64
|
-
{% for key, value in slide.attrs.items() %}
|
|
65
|
-
{{ key }}="{{ value }}"
|
|
66
|
-
{% endfor %}
|
|
67
|
-
{% endif %}
|
|
68
|
-
>
|
|
69
|
-
{{ slide.content | safe }}
|
|
70
|
-
</div>
|
|
71
|
-
{% endfor %}
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
{% if show_controls %}
|
|
76
|
-
<div class="carousel-controls">
|
|
77
|
-
<button
|
|
78
|
-
type="button"
|
|
79
|
-
class="carousel-prev"
|
|
80
|
-
aria-label="Previous slide"
|
|
81
|
-
>
|
|
82
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
83
|
-
<path d="m15 18-6-6 6-6"/>
|
|
84
|
-
</svg>
|
|
85
|
-
</button>
|
|
86
|
-
<button
|
|
87
|
-
type="button"
|
|
88
|
-
class="carousel-next"
|
|
89
|
-
aria-label="Next slide"
|
|
90
|
-
>
|
|
91
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
92
|
-
<path d="m9 18 6-6-6-6"/>
|
|
93
|
-
</svg>
|
|
94
|
-
</button>
|
|
95
|
-
</div>
|
|
96
|
-
{% endif %}
|
|
97
|
-
|
|
98
|
-
{% if show_indicators %}
|
|
99
|
-
<div class="carousel-indicators" role="tablist" aria-label="Slides">
|
|
100
|
-
{% for slide in slides %}
|
|
101
|
-
<button
|
|
102
|
-
type="button"
|
|
103
|
-
role="tab"
|
|
104
|
-
aria-label="Slide {{ loop.index }}"
|
|
105
|
-
{% if loop.index == 1 %}aria-current="true"{% else %}aria-current="false"{% endif %}
|
|
106
|
-
></button>
|
|
107
|
-
{% endfor %}
|
|
108
|
-
</div>
|
|
109
|
-
{% endif %}
|
|
110
|
-
</div>
|
|
111
|
-
{% endmacro %}
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
(() => {
|
|
2
|
-
const initCarousel = (carouselComponent) => {
|
|
3
|
-
const slidesContainer = carouselComponent.querySelector('.carousel-slides');
|
|
4
|
-
if (!slidesContainer) return;
|
|
5
|
-
|
|
6
|
-
const slides = Array.from(carouselComponent.querySelectorAll('.carousel-item'));
|
|
7
|
-
const prevButton = carouselComponent.querySelector('.carousel-prev');
|
|
8
|
-
const nextButton = carouselComponent.querySelector('.carousel-next');
|
|
9
|
-
const indicators = Array.from(carouselComponent.querySelectorAll('.carousel-indicators button'));
|
|
10
|
-
|
|
11
|
-
const loop = carouselComponent.dataset.carouselLoop === 'true';
|
|
12
|
-
const autoplayDelay = parseInt(carouselComponent.dataset.carouselAutoplay, 10);
|
|
13
|
-
const orientation = carouselComponent.dataset.orientation || 'horizontal';
|
|
14
|
-
|
|
15
|
-
let currentIndex = 0;
|
|
16
|
-
let autoplayInterval = null;
|
|
17
|
-
|
|
18
|
-
const getScrollAmount = () => {
|
|
19
|
-
if (slides.length === 0) return 0;
|
|
20
|
-
const firstSlide = slides[0];
|
|
21
|
-
return orientation === 'vertical'
|
|
22
|
-
? firstSlide.offsetHeight + parseInt(getComputedStyle(slidesContainer).gap || 0)
|
|
23
|
-
: firstSlide.offsetWidth + parseInt(getComputedStyle(slidesContainer).gap || 0);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const scrollToIndex = (index) => {
|
|
27
|
-
const scrollAmount = getScrollAmount();
|
|
28
|
-
if (orientation === 'vertical') {
|
|
29
|
-
slidesContainer.scrollTo({ top: scrollAmount * index, behavior: 'smooth' });
|
|
30
|
-
} else {
|
|
31
|
-
slidesContainer.scrollTo({ left: scrollAmount * index, behavior: 'smooth' });
|
|
32
|
-
}
|
|
33
|
-
currentIndex = index;
|
|
34
|
-
updateIndicators();
|
|
35
|
-
updateButtonStates();
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const updateIndicators = () => {
|
|
39
|
-
indicators.forEach((indicator, index) => {
|
|
40
|
-
const isActive = index === currentIndex;
|
|
41
|
-
indicator.setAttribute('aria-current', isActive ? 'true' : 'false');
|
|
42
|
-
indicator.setAttribute('aria-label', `Slide ${index + 1}${isActive ? ' (current)' : ''}`);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
slides.forEach((slide, index) => {
|
|
46
|
-
slide.setAttribute('aria-hidden', index === currentIndex ? 'false' : 'true');
|
|
47
|
-
});
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
const updateButtonStates = () => {
|
|
51
|
-
if (!prevButton || !nextButton) return;
|
|
52
|
-
|
|
53
|
-
if (loop) {
|
|
54
|
-
prevButton.disabled = false;
|
|
55
|
-
nextButton.disabled = false;
|
|
56
|
-
} else {
|
|
57
|
-
prevButton.disabled = currentIndex === 0;
|
|
58
|
-
nextButton.disabled = currentIndex === slides.length - 1;
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const goToPrevious = () => {
|
|
63
|
-
if (currentIndex > 0) {
|
|
64
|
-
scrollToIndex(currentIndex - 1);
|
|
65
|
-
} else if (loop) {
|
|
66
|
-
scrollToIndex(slides.length - 1);
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const goToNext = () => {
|
|
71
|
-
if (currentIndex < slides.length - 1) {
|
|
72
|
-
scrollToIndex(currentIndex + 1);
|
|
73
|
-
} else if (loop) {
|
|
74
|
-
scrollToIndex(0);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const startAutoplay = () => {
|
|
79
|
-
if (!autoplayDelay || autoplayDelay <= 0) return;
|
|
80
|
-
|
|
81
|
-
autoplayInterval = setInterval(() => {
|
|
82
|
-
goToNext();
|
|
83
|
-
}, autoplayDelay);
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const stopAutoplay = () => {
|
|
87
|
-
if (autoplayInterval) {
|
|
88
|
-
clearInterval(autoplayInterval);
|
|
89
|
-
autoplayInterval = null;
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const detectCurrentSlide = () => {
|
|
94
|
-
const scrollPosition = orientation === 'vertical'
|
|
95
|
-
? slidesContainer.scrollTop
|
|
96
|
-
: slidesContainer.scrollLeft;
|
|
97
|
-
const scrollAmount = getScrollAmount();
|
|
98
|
-
const newIndex = Math.round(scrollPosition / scrollAmount);
|
|
99
|
-
|
|
100
|
-
if (newIndex !== currentIndex && newIndex >= 0 && newIndex < slides.length) {
|
|
101
|
-
currentIndex = newIndex;
|
|
102
|
-
updateIndicators();
|
|
103
|
-
updateButtonStates();
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
// Previous/Next button handlers
|
|
108
|
-
if (prevButton) {
|
|
109
|
-
prevButton.addEventListener('click', () => {
|
|
110
|
-
stopAutoplay();
|
|
111
|
-
goToPrevious();
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (nextButton) {
|
|
116
|
-
nextButton.addEventListener('click', () => {
|
|
117
|
-
stopAutoplay();
|
|
118
|
-
goToNext();
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Indicator click handlers
|
|
123
|
-
indicators.forEach((indicator, index) => {
|
|
124
|
-
indicator.addEventListener('click', () => {
|
|
125
|
-
stopAutoplay();
|
|
126
|
-
scrollToIndex(index);
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
// Keyboard navigation
|
|
131
|
-
carouselComponent.addEventListener('keydown', (event) => {
|
|
132
|
-
const isVertical = orientation === 'vertical';
|
|
133
|
-
const prevKey = isVertical ? 'ArrowUp' : 'ArrowLeft';
|
|
134
|
-
const nextKey = isVertical ? 'ArrowDown' : 'ArrowRight';
|
|
135
|
-
|
|
136
|
-
switch (event.key) {
|
|
137
|
-
case prevKey:
|
|
138
|
-
event.preventDefault();
|
|
139
|
-
stopAutoplay();
|
|
140
|
-
goToPrevious();
|
|
141
|
-
break;
|
|
142
|
-
case nextKey:
|
|
143
|
-
event.preventDefault();
|
|
144
|
-
stopAutoplay();
|
|
145
|
-
goToNext();
|
|
146
|
-
break;
|
|
147
|
-
case 'Home':
|
|
148
|
-
event.preventDefault();
|
|
149
|
-
stopAutoplay();
|
|
150
|
-
scrollToIndex(0);
|
|
151
|
-
break;
|
|
152
|
-
case 'End':
|
|
153
|
-
event.preventDefault();
|
|
154
|
-
stopAutoplay();
|
|
155
|
-
scrollToIndex(slides.length - 1);
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
// Detect scroll position changes (for touch/manual scrolling)
|
|
161
|
-
let scrollTimeout;
|
|
162
|
-
slidesContainer.addEventListener('scroll', () => {
|
|
163
|
-
clearTimeout(scrollTimeout);
|
|
164
|
-
scrollTimeout = setTimeout(() => {
|
|
165
|
-
detectCurrentSlide();
|
|
166
|
-
}, 100);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// Pause autoplay on hover or focus
|
|
170
|
-
if (autoplayDelay) {
|
|
171
|
-
carouselComponent.addEventListener('mouseenter', stopAutoplay);
|
|
172
|
-
carouselComponent.addEventListener('mouseleave', startAutoplay);
|
|
173
|
-
carouselComponent.addEventListener('focusin', stopAutoplay);
|
|
174
|
-
carouselComponent.addEventListener('focusout', startAutoplay);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Initialize
|
|
178
|
-
updateIndicators();
|
|
179
|
-
updateButtonStates();
|
|
180
|
-
|
|
181
|
-
if (autoplayDelay) {
|
|
182
|
-
startAutoplay();
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
carouselComponent.dataset.carouselInitialized = true;
|
|
186
|
-
carouselComponent.dispatchEvent(new CustomEvent('basecoat:initialized'));
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
if (window.basecoat) {
|
|
190
|
-
window.basecoat.register('carousel', '.carousel:not([data-carousel-initialized])', initCarousel);
|
|
191
|
-
}
|
|
192
|
-
})();
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(()=>{const e=e=>{const t=e.querySelector(".carousel-slides");if(!t)return;const r=Array.from(e.querySelectorAll(".carousel-item")),a=e.querySelector(".carousel-prev"),o=e.querySelector(".carousel-next"),l=Array.from(e.querySelectorAll(".carousel-indicators button")),s="true"===e.dataset.carouselLoop,n=parseInt(e.dataset.carouselAutoplay,10),i=e.dataset.orientation||"horizontal";let c=0,d=null;const u=()=>{if(0===r.length)return 0;const e=r[0];return"vertical"===i?e.offsetHeight+parseInt(getComputedStyle(t).gap||0):e.offsetWidth+parseInt(getComputedStyle(t).gap||0)},v=e=>{const r=u();"vertical"===i?t.scrollTo({top:r*e,behavior:"smooth"}):t.scrollTo({left:r*e,behavior:"smooth"}),c=e,f(),h()},f=()=>{l.forEach(((e,t)=>{const r=t===c;e.setAttribute("aria-current",r?"true":"false"),e.setAttribute("aria-label",`Slide ${t+1}${r?" (current)":""}`)})),r.forEach(((e,t)=>{e.setAttribute("aria-hidden",t===c?"false":"true")}))},h=()=>{a&&o&&(s?(a.disabled=!1,o.disabled=!1):(a.disabled=0===c,o.disabled=c===r.length-1))},p=()=>{c>0?v(c-1):s&&v(r.length-1)},b=()=>{c<r.length-1?v(c+1):s&&v(0)},E=()=>{!n||n<=0||(d=setInterval((()=>{b()}),n))},g=()=>{d&&(clearInterval(d),d=null)};let m;a&&a.addEventListener("click",(()=>{g(),p()})),o&&o.addEventListener("click",(()=>{g(),b()})),l.forEach(((e,t)=>{e.addEventListener("click",(()=>{g(),v(t)}))})),e.addEventListener("keydown",(e=>{const t="vertical"===i,a=t?"ArrowUp":"ArrowLeft",o=t?"ArrowDown":"ArrowRight";switch(e.key){case a:e.preventDefault(),g(),p();break;case o:e.preventDefault(),g(),b();break;case"Home":e.preventDefault(),g(),v(0);break;case"End":e.preventDefault(),g(),v(r.length-1)}})),t.addEventListener("scroll",(()=>{clearTimeout(m),m=setTimeout((()=>{(()=>{const e="vertical"===i?t.scrollTop:t.scrollLeft,a=u(),o=Math.round(e/a);o!==c&&o>=0&&o<r.length&&(c=o,f(),h())})()}),100)})),n&&(e.addEventListener("mouseenter",g),e.addEventListener("mouseleave",E),e.addEventListener("focusin",g),e.addEventListener("focusout",E)),f(),h(),n&&E(),e.dataset.carouselInitialized=!0,e.dispatchEvent(new CustomEvent("basecoat:initialized"))};window.basecoat&&window.basecoat.register("carousel",".carousel:not([data-carousel-initialized])",e)})();
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
{#
|
|
2
|
-
Renders a carousel component with navigation controls and optional indicators.
|
|
3
|
-
|
|
4
|
-
@param id {string} [optional] - Unique identifier for the carousel component. Auto-generated if not provided.
|
|
5
|
-
@param slides {array} - An array of objects representing carousel slides.
|
|
6
|
-
Each object should have:
|
|
7
|
-
- content {string}: HTML content for the slide.
|
|
8
|
-
- attrs {object} [optional]: Additional HTML attributes for the slide item.
|
|
9
|
-
@param loop {boolean} [optional] [default=false] - Enable continuous looping.
|
|
10
|
-
@param autoplay {number} [optional] [default=0] - Auto-advance delay in milliseconds (0 = disabled).
|
|
11
|
-
@param align {string} [optional] [default='start'] - Slide alignment ('start' or 'center').
|
|
12
|
-
@param orientation {string} [optional] [default='horizontal'] - Carousel orientation ('horizontal' or 'vertical').
|
|
13
|
-
@param show_controls {boolean} [optional] [default=true] - Show previous/next navigation buttons.
|
|
14
|
-
@param show_indicators {boolean} [optional] [default=true] - Show slide indicator dots.
|
|
15
|
-
@param main_attrs {object} [optional] - Additional HTML attributes for the main container.
|
|
16
|
-
@param viewport_attrs {object} [optional] - Additional HTML attributes for the viewport container.
|
|
17
|
-
#}
|
|
18
|
-
{% macro carousel(
|
|
19
|
-
id=None,
|
|
20
|
-
slides=[],
|
|
21
|
-
loop=false,
|
|
22
|
-
autoplay=0,
|
|
23
|
-
align='start',
|
|
24
|
-
orientation='horizontal',
|
|
25
|
-
show_controls=true,
|
|
26
|
-
show_indicators=true,
|
|
27
|
-
main_attrs={},
|
|
28
|
-
viewport_attrs={}
|
|
29
|
-
)
|
|
30
|
-
%}
|
|
31
|
-
{% set id = id or ("carousel-" + (range(100000, 999999) | random | string)) %}
|
|
32
|
-
<div
|
|
33
|
-
class="carousel {{ main_attrs.class }}"
|
|
34
|
-
id="{{ id }}"
|
|
35
|
-
data-carousel-loop="{{ 'true' if loop else 'false' }}"
|
|
36
|
-
{% if autoplay > 0 %}data-carousel-autoplay="{{ autoplay }}"{% endif %}
|
|
37
|
-
data-orientation="{{ orientation }}"
|
|
38
|
-
role="region"
|
|
39
|
-
aria-roledescription="carousel"
|
|
40
|
-
aria-label="Carousel"
|
|
41
|
-
tabindex="0"
|
|
42
|
-
{% for key, value in main_attrs %}
|
|
43
|
-
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
|
|
44
|
-
{% endfor %}
|
|
45
|
-
>
|
|
46
|
-
<div
|
|
47
|
-
class="carousel-viewport {{ viewport_attrs.class }}"
|
|
48
|
-
{% for key, value in viewport_attrs %}
|
|
49
|
-
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
|
|
50
|
-
{% endfor %}
|
|
51
|
-
>
|
|
52
|
-
<div
|
|
53
|
-
class="carousel-slides"
|
|
54
|
-
data-orientation="{{ orientation }}"
|
|
55
|
-
>
|
|
56
|
-
{% for slide in slides %}
|
|
57
|
-
<div
|
|
58
|
-
class="carousel-item"
|
|
59
|
-
role="group"
|
|
60
|
-
aria-roledescription="slide"
|
|
61
|
-
aria-label="{{ loop.index }} of {{ slides | length }}"
|
|
62
|
-
{% if align == 'center' %}data-align="center"{% endif %}
|
|
63
|
-
{% if slide.attrs %}
|
|
64
|
-
{% for key, value in slide.attrs %}
|
|
65
|
-
{{ key }}="{{ value }}"
|
|
66
|
-
{% endfor %}
|
|
67
|
-
{% endif %}
|
|
68
|
-
>
|
|
69
|
-
{{ slide.content | safe }}
|
|
70
|
-
</div>
|
|
71
|
-
{% endfor %}
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
|
|
75
|
-
{% if show_controls %}
|
|
76
|
-
<div class="carousel-controls">
|
|
77
|
-
<button
|
|
78
|
-
type="button"
|
|
79
|
-
class="carousel-prev"
|
|
80
|
-
aria-label="Previous slide"
|
|
81
|
-
>
|
|
82
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
83
|
-
<path d="m15 18-6-6 6-6"/>
|
|
84
|
-
</svg>
|
|
85
|
-
</button>
|
|
86
|
-
<button
|
|
87
|
-
type="button"
|
|
88
|
-
class="carousel-next"
|
|
89
|
-
aria-label="Next slide"
|
|
90
|
-
>
|
|
91
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
92
|
-
<path d="m9 18 6-6-6-6"/>
|
|
93
|
-
</svg>
|
|
94
|
-
</button>
|
|
95
|
-
</div>
|
|
96
|
-
{% endif %}
|
|
97
|
-
|
|
98
|
-
{% if show_indicators %}
|
|
99
|
-
<div class="carousel-indicators" role="tablist" aria-label="Slides">
|
|
100
|
-
{% for slide in slides %}
|
|
101
|
-
<button
|
|
102
|
-
type="button"
|
|
103
|
-
role="tab"
|
|
104
|
-
aria-label="Slide {{ loop.index }}"
|
|
105
|
-
{% if loop.index == 1 %}aria-current="true"{% else %}aria-current="false"{% endif %}
|
|
106
|
-
></button>
|
|
107
|
-
{% endfor %}
|
|
108
|
-
</div>
|
|
109
|
-
{% endif %}
|
|
110
|
-
</div>
|
|
111
|
-
{% endmacro %}
|