maverick-wave 3.10.0 → 4.0.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/.claude/skills/maverick-wave/SKILL.md +62 -30
- package/.claude/skills/maverick-wave/examples/angular-form.md +1 -1
- package/.claude/skills/maverick-wave/examples/angular-services.md +15 -8
- package/.claude/skills/maverick-wave/examples/static-landing-page.md +4 -4
- package/.claude/skills/maverick-wave/references/components.md +416 -27
- package/.claude/skills/maverick-wave/references/forms.md +8 -4
- package/.claude/skills/maverick-wave/references/javascript.md +32 -18
- package/.claude/skills/maverick-wave/references/layout.md +48 -3
- package/.claude/skills/maverick-wave/references/theming.md +34 -24
- package/CHANGELOG.md +56 -0
- package/index.html +25 -0
- package/maverick-wave.min.css +2 -2
- package/maverick-wave.min.js +1 -1
- package/package.json +2 -2
- package/src/js/main.js +314 -20
- package/src/partials/accordions-container.html +2 -2
- package/src/partials/button-bar-container.html +4 -2
- package/src/partials/buttons-container.html +35 -0
- package/src/partials/calendar-container.html +205 -0
- package/src/partials/cards-container.html +43 -0
- package/src/partials/documentation-container.html +3 -0
- package/src/partials/form-container.html +1 -1
- package/src/partials/get-started-container.html +2 -2
- package/src/partials/kanban-container.html +680 -715
- package/src/partials/modals-container.html +5 -5
- package/src/partials/pagination-container.html +50 -13
- package/src/partials/segmented-container.html +66 -0
- package/src/partials/tables-container.html +96 -24
- package/src/partials/tabs-container.html +16 -6
- package/src/partials/tags-container.html +15 -0
- package/src/partials/timelines-container.html +2 -2
- package/src/partials/utilities-container.html +81 -0
- package/src/scss/abstracts/_mixins.scss +34 -0
- package/src/scss/abstracts/_variables.scss +6 -2
- package/src/scss/base/_base.scss +21 -0
- package/src/scss/components/_accordions.scss +2 -0
- package/src/scss/components/_alerts.scss +5 -19
- package/src/scss/components/_button-bar.scss +6 -0
- package/src/scss/components/_buttons.scss +67 -0
- package/src/scss/components/_calendar.scss +290 -0
- package/src/scss/components/_content-slider.scss +1 -0
- package/src/scss/components/_index.scss +2 -0
- package/src/scss/components/_kanban.scss +2 -6
- package/src/scss/components/_modals.scss +15 -4
- package/src/scss/components/_pagination.scss +68 -64
- package/src/scss/components/_segmented.scss +85 -0
- package/src/scss/components/_tables.scss +16 -0
- package/src/scss/components/_tabs.scss +15 -0
- package/src/scss/components/_tags.scss +16 -0
- package/src/scss/components/_theme-toggle.scss +2 -0
- package/src/scss/components/_timelines.scss +3 -0
- package/src/scss/form-elements/_form.scss +13 -7
- package/src/scss/layout/_header.scss +3 -0
- package/src/scss/layout/_main.scss +5 -1
- package/src/scss/layout/_section.scss +1 -1
- package/src/scss/utilities/_accessibility.scss +14 -0
- package/src/scss/utilities/_flex.scss +17 -0
- package/src/scss/utilities/_index.scss +2 -0
- package/src/scss/utilities/_text.scss +17 -5
- package/src/scss/utilities/_touch-targets.scss +54 -0
package/maverick-wave.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(){"use strict";function e(){document.querySelectorAll(".color-swatch").forEach(e=>{const t=function(e){if(!e||"transparent"===e)return"#000000";const t=e=>Math.max(0,Math.min(255,Math.round(e))).toString(16).padStart(2,"0"),n=e.match(/color\(srgb\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+))?\)/);if(n){const e="#"+t(255*n[1])+t(255*n[2])+t(255*n[3]),c=void 0===n[4]?1:parseFloat(n[4]);return(c<1?`${e} / ${c}`:e).toUpperCase()}const c=e.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);if(!c)return e;const o="#"+t(c[1])+t(c[2])+t(c[3]),a=void 0===c[4]?1:parseFloat(c[4]);return(a<1?`${o} / ${a}`:o).toUpperCase()}(window.getComputedStyle(e).backgroundColor),n=e.parentElement.querySelector(".mw-text-muted");n&&(n.textContent=t)})}function t(e){const t=Array.from(e.querySelectorAll(".mw-kanban-column")),n=e.querySelector(".mw-kanban-composer"),c=e.querySelector(".mw-kanban-card-template"),o=e.dataset.kanbanPrefix||"MW",a=n.querySelector(".mw-kanban-composer-title"),r=n.querySelector(".mw-kanban-composer-text"),s=n.querySelector(".mw-kanban-composer-priority"),l=n.querySelector(".mw-kanban-composer-assignee");let i=null;function d(){t.forEach(function(e,n){const c=e.querySelectorAll(".mw-kanban-card"),o=e.querySelector(".mw-kanban-count");o&&(o.textContent=c.length),e.querySelectorAll("[data-kanban-move]").forEach(function(e){const c=n+parseInt(e.dataset.kanbanMove,10);e.disabled=c<0||c>=t.length})})}function u(e,t){const n=e.querySelector(t);return n?n.textContent.replace(/\s+/g," ").trim():""}function m(e,t){f(),i=t||null,a.value=t?u(t,".mw-kanban-card-title"):"",r.value=t?u(t,".mw-kanban-card-text"):"",s.value=t?function(e){const t=e.querySelector(".mw-card-ribbon");if(!t)return"";const n=Array.from(t.classList).find(function(e){return 0===e.indexOf("mw-card-addon-")});return n?n.replace("mw-card-addon-",""):""}(t):"",l.value=t?function(e){const t=e.querySelector(".mw-avatar-initials");return t?t.textContent.trim():""}(t):"",t?(t.classList.add("mw-kanban-editing"),t.before(n)):e.querySelector(".mw-kanban-column-body").prepend(n),n.classList.add("mw-active"),a.focus()}function f(){n.classList.remove("mw-active"),i&&i.classList.remove("mw-kanban-editing"),i=null}function h(){const t=a.value.trim();if(!t)return void a.focus();const u=i||c.content.firstElementChild.cloneNode(!0);if(u.querySelector(".mw-kanban-card-title").textContent=t,u.querySelector(".mw-kanban-card-text").textContent=r.value.trim(),function(e,t){const n=e.querySelector(".mw-card-ribbon");if(n&&n.remove(),!t||!t.value)return;const c=document.createElement("div");c.className="mw-card-ribbon mw-card-addon-"+t.value,c.textContent=t.textContent,e.prepend(c)}(u,s.selectedOptions[0]),function(e,t){const n=e.querySelector(".mw-kanban-card-actions"),c=n.querySelector(".mw-avatar");if(!t)return void(c&&c.remove());const o=c||document.createElement("div");o.className="mw-avatar mw-avatar-xs mw-avatar-initials",o.textContent=t,c||n.prepend(o)}(u,l.value),!i){const t=function(){const t=Array.from(e.querySelectorAll(".mw-kanban-card-id")).map(function(e){return parseInt(e.textContent.split("-").pop(),10)||0});return o+"-"+(Math.max(0,...t)+1)}();u.classList.add("mw-kanban-card-in"),u.querySelector(".mw-kanban-card-id").textContent=t,u.querySelectorAll("[aria-label]").forEach(function(e){e.setAttribute("aria-label",e.getAttribute("aria-label").replace(/[A-Z]+-\d+/,t))}),n.before(u)}f(),d()}e.addEventListener("click",function(e){const n=e.target.closest("[data-kanban-move]");if(n){if(function(e,n){const c=e.closest(".mw-kanban-column"),o=t[t.indexOf(c)+n];o&&(o.querySelector(".mw-kanban-column-body").appendChild(e),d())}(n.closest(".mw-kanban-card"),parseInt(n.dataset.kanbanMove,10)),n.disabled){const e=n.parentElement.querySelector("[data-kanban-move]:not(:disabled)");e&&e.focus()}return}const c=e.target.closest(".mw-kanban-edit");if(c){const e=c.closest(".mw-kanban-card");return void m(e.closest(".mw-kanban-column"),e)}const o=e.target.closest(".mw-kanban-delete");if(o){const e=o.closest(".mw-kanban-card");return e===i&&f(),e.remove(),void d()}const a=e.target.closest(".mw-kanban-add");a?m(a.closest(".mw-kanban-column"),null):e.target.closest(".mw-kanban-composer-cancel")&&f()}),n.addEventListener("submit",function(e){e.preventDefault(),h()}),n.addEventListener("keydown",function(e){"Escape"===e.key&&f()}),d()}document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll(".mw-gallery").forEach(e=>{const t=e.closest(".mw-gallery-container")||e.parentElement;t&&function(e,t){const n=t.querySelector(".mw-gallery-track");if(!n||!n.children.length)return;const c=n.children,o=e.querySelector(".mw-gallery-dots"),a=e.querySelector(".mw-gallery-desc"),r=t.querySelector(".mw-gallery-navi-prev"),s=t.querySelector(".mw-gallery-navi-next");let l=0;function i(e){const t=c.length;l=(e+t)%t,n.style.transform=`translateX(-${100*l}%)`,o&&o.querySelectorAll(".mw-gallery-dot").forEach((e,t)=>{e.classList.toggle("mw-active",t===l)}),a&&(a.textContent=c[l].dataset.desc||"")}if(o)for(let e=0;e<c.length;e++){const t=document.createElement("span");t.className="mw-gallery-dot"+(0===e?" mw-active":""),t.addEventListener("click",()=>i(e)),o.appendChild(t)}r&&r.addEventListener("click",()=>i(l-1)),s&&s.addEventListener("click",()=>i(l+1));let d=0;n.addEventListener("touchstart",e=>d=e.touches[0].clientX),n.addEventListener("touchend",e=>{const t=e.changedTouches[0].clientX-d;t>50&&i(l-1),t<-50&&i(l+1)}),i(0)}(t,e)}),function(){const t=document.querySelector(".mw-theme-toggle");if(!t)return;const n=document.body,c=t.querySelector(".mw-theme-toggle-slider i"),o=getComputedStyle(document.documentElement).getPropertyValue("--mw-internal-theme-mode").trim()||"switchable";if("switchable"!==o)return console.log(`Theme mode fixed to: ${o}. Disabling toggle.`),c&&(c.className="light"===o?"fas fa-sun":"fas fa-moon"),"light"===o?t.classList.add("active"):t.classList.remove("active"),t.style.opacity="0.4",t.style.pointerEvents="none",t.style.cursor="default",t.setAttribute("aria-disabled","true"),localStorage.removeItem("mw-theme"),void("dark"===o&&n.classList.remove("mw-theme-light"));let a="light"===localStorage.getItem("mw-theme");const r=e=>{n.classList.toggle("mw-theme-light",e),t.classList.toggle("active",e),c&&(c.className=e?"fas fa-sun":"fas fa-moon")};r(a),t.addEventListener("click",()=>{a=!a,r(a),localStorage.setItem("mw-theme",a?"light":"dark"),setTimeout(e,400)})}(),e(),document.querySelectorAll(".mw-accordion-header").forEach(e=>{e.addEventListener("click",function(){this.classList.toggle("active");const e=this.nextElementSibling;e&&e.classList.toggle("active")})}),function(){const e=document.querySelector(".mw-menu-btn"),t=document.querySelector(".mw-navbar");if(!e||!t)return;function n(){e.classList.remove("open"),t.classList.remove("open")}function c(n){n.preventDefault(),n.stopPropagation(),e.classList.toggle("open"),t.classList.toggle("open")}e.addEventListener("click",c),e.addEventListener("touchstart",c,{passive:!1}),document.addEventListener("click",function(c){t.classList.contains("open")&&(t.contains(c.target)||e.contains(c.target)||n())}),document.addEventListener("keydown",function(e){"Escape"===e.key&&n()})}(),function(){const e=document.querySelectorAll(".mw-progress-fill");if(!e.length)return;const t=new IntersectionObserver((e,t)=>{e.forEach(e=>{if(!e.isIntersecting)return;const n=e.target,c=n.dataset.value||0;n.style.width=c+"%",t.unobserve(n)})},{root:null,threshold:.2});e.forEach(e=>t.observe(e))}(),document.querySelectorAll('a[href^="#"]').forEach(e=>{e.addEventListener("click",function(e){const t=this.getAttribute("href");if("#"===t)return;if(!document.querySelector(t))return;const n=document.querySelector(".mw-menu-btn"),c=document.querySelector(".mw-navbar");n&&c&&(n.classList.remove("open"),c.classList.remove("open"))})}),function(){const e=document.querySelectorAll("section[id]"),t=document.querySelectorAll(".mw-navbar-link");if(0===e.length||0===t.length)return;window.addEventListener("scroll",function(e,t){let n;return function(){const c=this,o=arguments;clearTimeout(n),n=setTimeout(()=>e.apply(c,o),t)}}(function(){let n="";e.forEach(e=>{const t=e.offsetTop-100,c=e.clientHeight;scrollY>=t&&scrollY<t+c&&(n=e.getAttribute("id"))}),t.forEach(e=>{e.classList.remove("active");const t=e.getAttribute("href");if(t){const c=t.indexOf("#");if(-1!==c){t.substring(c+1)===n&&e.classList.add("active")}}})},100))}(),document.querySelectorAll(".mw-tabs-nav-item").forEach(e=>{e.addEventListener("click",function(){const e=this.closest(".mw-tabs");if(!e)return;e.querySelectorAll(".mw-tabs-nav-item").forEach(e=>{e.classList.remove("active")}),this.classList.add("active");const t=this.getAttribute("data-tab");if(!t)return;e.querySelectorAll(".mw-tabs-panel").forEach(e=>{e.classList.remove("active")});const n=document.getElementById(t);n&&n.classList.add("active")})}),document.querySelectorAll(".mw-alert-close").forEach(e=>{e.addEventListener("click",function(){const e=this.closest(".mw-alert");e&&(e.classList.add("mw-alert-closing"),setTimeout(()=>{e.classList.add("mw-alert-closed")},300))})}),function(){const e=document.querySelector(".mw-localhost-indicator-activated"),t=document.querySelector(".mw-header");if(e){if("localhost"===window.location.hostname||"127.0.0.1"===window.location.hostname||window.location.hostname.includes("192.168.")){const e=document.createElement("div");e.className="mw-localhost-indicator-pulse",t.prepend(e)}}}(),document.querySelectorAll(".mw-slider-container").forEach(e=>{const t=e.querySelector(".mw-slider"),n=e.querySelector(".mw-slider-value");if(!t||!n)return;const c=()=>{const e=Number(t.value),c=Number(t.max)||100,o=Math.round(e/c*100);t.style.setProperty("--value",o+"%"),n.classList.contains("mw-slider-numeric")?n.setAttribute("data-value",e):n.setAttribute("data-value",o)};t.addEventListener("input",c),c()}),document.querySelectorAll(".mw-modal-close").forEach(e=>{e.addEventListener("click",function(){const e=this.closest(".mw-modal-overlay");e&&e.classList.remove("mw-modal-open")})}),function(){const e=document.getElementById("login-button");e&&e.addEventListener("click",function(){const e=this.querySelector("i");e.classList.contains("fa-lock")?(e.classList.remove("fa-lock"),e.classList.add("fa-lock-open")):(e.classList.remove("fa-lock-open"),e.classList.add("fa-lock"))})}(),document.querySelectorAll(".mw-image-slider").forEach(e=>{const t=e.querySelectorAll(".mw-image-slider-overlay-image"),n=e.querySelectorAll("button[data-index]");if(!t.length||!n.length)return;let c=0;function o(){t.forEach(e=>{const t=parseInt(e.dataset.index);e.classList.toggle("active",t===c)}),n.forEach(e=>{const t=parseInt(e.dataset.index);e.classList.toggle("active",t===c)})}function a(e){c=e,o()}n.forEach(e=>{e.addEventListener("click",()=>{a(parseInt(e.dataset.index))})}),o()}),document.querySelectorAll(".mw-item-list-checkbox, .mw-item-list-checkbox-scroll").forEach(e=>{e.querySelectorAll("li").forEach(e=>{const t=e.querySelector('input[type="checkbox"]'),n=e.querySelector(".mw-checkbox");t&&n&&(t.checked&&e.classList.add("mw-selected"),e.addEventListener("click",function(e){e.target!==t&&e.target.closest(".mw-checkbox")!==n&&toggleCheckbox(this)}),t.addEventListener("change",function(){const e=this.closest("li");this.checked?e.classList.add("mw-selected"):e.classList.remove("mw-selected"),e.dispatchEvent(new CustomEvent("checkboxToggle",{detail:{checked:this.checked,item:e}}))}),n.addEventListener("click",function(e){setTimeout(()=>{const e=this.closest("li");this.querySelector('input[type="checkbox"]').checked?e.classList.add("mw-selected"):e.classList.remove("mw-selected")},0)}))})}),document.addEventListener("checkboxToggle",function(e){console.log("Checkbox toggled:",e.detail.checked,e.detail.item)}),document.querySelectorAll(".mw-kanban").forEach(t)}),window.toggleCheckbox=function(e){const t=e.querySelector('input[type="checkbox"]');if(!t)return;const n=t.checked;t.checked=!n,t.checked?e.classList.add("mw-selected"):e.classList.remove("mw-selected"),e.dispatchEvent(new CustomEvent("checkboxToggle",{detail:{checked:t.checked,item:e}}))}}();
|
|
1
|
+
!function(){"use strict";function e(e,t){e&&(e.classList.toggle("mw-active",t),t||e.classList.remove("active"))}function t(){document.querySelectorAll(".color-swatch").forEach(e=>{const t=function(e){if(!e||"transparent"===e)return"#000000";const t=e=>Math.max(0,Math.min(255,Math.round(e))).toString(16).padStart(2,"0"),n=e.match(/color\(srgb\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)(?:\s*\/\s*([\d.]+))?\)/);if(n){const e="#"+t(255*n[1])+t(255*n[2])+t(255*n[3]),a=void 0===n[4]?1:parseFloat(n[4]);return(a<1?`${e} / ${a}`:e).toUpperCase()}const a=e.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);if(!a)return e;const c="#"+t(a[1])+t(a[2])+t(a[3]),o=void 0===a[4]?1:parseFloat(a[4]);return(o<1?`${c} / ${o}`:c).toUpperCase()}(window.getComputedStyle(e).backgroundColor),n=e.parentElement.querySelector(".mw-text-muted");n&&(n.textContent=t)})}function n(e){const t=Array.from(e.querySelectorAll(".mw-kanban-column")),n=e.querySelector(".mw-kanban-composer"),a=e.querySelector(".mw-kanban-card-template"),c=e.dataset.kanbanPrefix||"MW",o=n.querySelector(".mw-kanban-composer-title"),r=n.querySelector(".mw-kanban-composer-text"),l=n.querySelector(".mw-kanban-composer-priority"),s=n.querySelector(".mw-kanban-composer-assignee");let i=null;function d(){t.forEach(function(e,n){const a=e.querySelectorAll(".mw-kanban-card"),c=e.querySelector(".mw-kanban-count");c&&(c.textContent=a.length),e.querySelectorAll("[data-kanban-move]").forEach(function(e){const a=n+parseInt(e.dataset.kanbanMove,10);e.disabled=a<0||a>=t.length})})}function u(e,t){const n=e.querySelector(t);return n?n.textContent.replace(/\s+/g," ").trim():""}function m(e,t){f(),i=t||null,o.value=t?u(t,".mw-kanban-card-title"):"",r.value=t?u(t,".mw-kanban-card-text"):"",l.value=t?function(e){const t=e.querySelector(".mw-card-ribbon");if(!t)return"";const n=Array.from(t.classList).find(function(e){return 0===e.indexOf("mw-card-addon-")});return n?n.replace("mw-card-addon-",""):""}(t):"",s.value=t?function(e){const t=e.querySelector(".mw-avatar-initials");return t?t.textContent.trim():""}(t):"",t?(t.classList.add("mw-kanban-editing"),t.before(n)):e.querySelector(".mw-kanban-column-body").prepend(n),n.classList.add("mw-active"),o.focus()}function f(){n.classList.remove("mw-active"),i&&i.classList.remove("mw-kanban-editing"),i=null}function w(){const t=o.value.trim();if(!t)return void o.focus();const u=i||a.content.firstElementChild.cloneNode(!0);if(u.querySelector(".mw-kanban-card-title").textContent=t,u.querySelector(".mw-kanban-card-text").textContent=r.value.trim(),function(e,t){const n=e.querySelector(".mw-card-ribbon");if(n&&n.remove(),!t||!t.value)return;const a=document.createElement("div");a.className="mw-card-ribbon mw-card-addon-"+t.value,a.textContent=t.textContent,e.prepend(a)}(u,l.selectedOptions[0]),function(e,t){const n=e.querySelector(".mw-kanban-card-actions"),a=n.querySelector(".mw-avatar");if(!t)return void(a&&a.remove());const c=a||document.createElement("div");c.className="mw-avatar mw-avatar-xs mw-avatar-initials",c.textContent=t,a||n.prepend(c)}(u,s.value),!i){const t=function(){const t=Array.from(e.querySelectorAll(".mw-kanban-card-id")).map(function(e){return parseInt(e.textContent.split("-").pop(),10)||0});return c+"-"+(Math.max(0,...t)+1)}();u.classList.add("mw-kanban-card-in"),u.querySelector(".mw-kanban-card-id").textContent=t,u.querySelectorAll("[aria-label]").forEach(function(e){e.setAttribute("aria-label",e.getAttribute("aria-label").replace(/[A-Z]+-\d+/,t))}),n.before(u)}f(),d()}e.addEventListener("click",function(e){const n=e.target.closest("[data-kanban-move]");if(n){if(function(e,n){const a=e.closest(".mw-kanban-column"),c=t[t.indexOf(a)+n];c&&(c.querySelector(".mw-kanban-column-body").appendChild(e),d())}(n.closest(".mw-kanban-card"),parseInt(n.dataset.kanbanMove,10)),n.disabled){const e=n.parentElement.querySelector("[data-kanban-move]:not(:disabled)");e&&e.focus()}return}const a=e.target.closest(".mw-kanban-edit");if(a){const e=a.closest(".mw-kanban-card");return void m(e.closest(".mw-kanban-column"),e)}const c=e.target.closest(".mw-kanban-delete");if(c){const e=c.closest(".mw-kanban-card");return e===i&&f(),e.remove(),void d()}const o=e.target.closest(".mw-kanban-add");o?m(o.closest(".mw-kanban-column"),null):e.target.closest(".mw-kanban-composer-cancel")&&f()}),n.addEventListener("submit",function(e){e.preventDefault(),w()}),n.addEventListener("keydown",function(e){"Escape"===e.key&&f()}),d()}function a(e){const t=e.querySelector(".mw-calendar-grid"),n=e.querySelector(".mw-calendar-title");if(!t)return;const a="week"===e.dataset.calendar,c=function(e){if(!e)return{};try{return JSON.parse(e)}catch(e){return{}}}(e.dataset.calendarMarkers),o=e.dataset.calendarLocale||document.documentElement.lang||void 0,r=new Date;r.setHours(0,0,0,0);let l=e.dataset.calendarDate?new Date(e.dataset.calendarDate+"T00:00:00"):new Date(r),s=e.dataset.calendarSelected||"";function i(e){const t=new Date(e);return t.setDate(t.getDate()-(t.getDay()+6)%7),t}function d(e){return e.getFullYear()+"-"+String(e.getMonth()+1).padStart(2,"0")+"-"+String(e.getDate()).padStart(2,"0")}function u(){if(!a)return l.toLocaleDateString(o,{month:"long",year:"numeric"});const e=i(l),t=new Date(e);t.setDate(t.getDate()+6);const n=e.toLocaleDateString(o,{day:"numeric",month:e.getMonth()===t.getMonth()?void 0:"short"}),c=t.toLocaleDateString(o,{day:"numeric",month:"short",year:"numeric"});return"Week "+function(e){const t=i(e);t.setDate(t.getDate()+3);const n=i(new Date(t.getFullYear(),0,4));return n.setDate(n.getDate()+3),1+Math.round((t-n)/6048e5)}(e)+" · "+n+" - "+c}function m(e){const t=e.getDay();return 0===t||6===t}function f(e,t){const n=d(e),l=document.createElement("button");l.type="button",l.className="mw-calendar-day",l.tabIndex=-1,l.dataset.calendarDay=n,l.setAttribute("aria-pressed",n===s?"true":"false"),l.setAttribute("aria-label",e.toLocaleDateString(o,{weekday:"long",day:"numeric",month:"long",year:"numeric"})),m(e)&&l.classList.add("mw-calendar-weekend"),a||e.getMonth()===t||l.classList.add("mw-calendar-adjacent"),n===d(r)&&(l.classList.add("mw-calendar-today"),l.setAttribute("aria-current","date")),n===s&&l.classList.add("mw-selected");const i=document.createElement("span");i.className="mw-calendar-date",i.textContent=e.getDate(),l.appendChild(i);const u=[].concat(c[n]||[]);if(u.length){const e=document.createElement("span");e.className="mw-calendar-dots",u.forEach(function(t){const n=document.createElement("span");n.className=t?"mw-calendar-dot mw-calendar-dot-"+t:"mw-calendar-dot",e.appendChild(n)}),l.appendChild(e)}return l}function w(){const e=l.getMonth(),c=a?7:42,r=i(a?l:new Date(l.getFullYear(),e,1));t.innerHTML="",function(){const e=i(new Date);for(let n=0;n<7;n++){const n=document.createElement("div");n.className="mw-calendar-weekday",m(e)&&n.classList.add("mw-calendar-weekend"),n.setAttribute("aria-hidden","true"),n.textContent=e.toLocaleDateString(o,{weekday:"short"}),t.appendChild(n),e.setDate(e.getDate()+1)}}();for(let n=0;n<c;n++)t.appendChild(f(r,e)),r.setDate(r.getDate()+1);n&&(n.textContent=u()),function(){const e=t.querySelector(".mw-selected")||t.querySelector(".mw-calendar-today")||t.querySelector(".mw-calendar-day:not(.mw-calendar-adjacent)")||t.querySelector(".mw-calendar-day");e&&(e.tabIndex=0)}()}e.addEventListener("click",function(n){const c=n.target.closest("[data-calendar-nav]");if(c)return o=parseInt(c.dataset.calendarNav,10),a?l.setDate(l.getDate()+7*o):l=new Date(l.getFullYear(),l.getMonth()+o,1),void w();var o;const r=n.target.closest(".mw-calendar-day");var i;r&&!r.disabled&&(i=r.dataset.calendarDay,s=i===s?"":i,t.querySelectorAll(".mw-calendar-day").forEach(function(e){const t=e.dataset.calendarDay===s;e.classList.toggle("mw-selected",t),e.setAttribute("aria-pressed",t?"true":"false")}),e.dispatchEvent(new CustomEvent("mw-calendar-select",{bubbles:!0,detail:{date:s}})))}),t.addEventListener("keydown",function(e){const n={ArrowLeft:-1,ArrowRight:1,ArrowUp:-7,ArrowDown:7}[e.key];if(!n)return;const a=e.target.closest(".mw-calendar-day");if(!a)return;e.preventDefault();const c=new Date(a.dataset.calendarDay+"T00:00:00");c.setDate(c.getDate()+n),function(e){const n=d(e);let a=t.querySelector('[data-calendar-day="'+n+'"]');a||(l=new Date(e),w(),a=t.querySelector('[data-calendar-day="'+n+'"]')),a&&(t.querySelectorAll(".mw-calendar-day").forEach(function(e){e.tabIndex=-1}),a.tabIndex=0,a.focus())}(c)}),w()}document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll(".mw-gallery").forEach(e=>{const t=e.closest(".mw-gallery-container")||e.parentElement;t&&function(e,t){const n=t.querySelector(".mw-gallery-track");if(!n||!n.children.length)return;const a=n.children,c=e.querySelector(".mw-gallery-dots"),o=e.querySelector(".mw-gallery-desc"),r=t.querySelector(".mw-gallery-navi-prev"),l=t.querySelector(".mw-gallery-navi-next");let s=0;function i(e){const t=a.length;s=(e+t)%t,n.style.transform=`translateX(-${100*s}%)`,c&&c.querySelectorAll(".mw-gallery-dot").forEach((e,t)=>{e.classList.toggle("mw-active",t===s)}),o&&(o.textContent=a[s].dataset.desc||"")}if(c)for(let e=0;e<a.length;e++){const t=document.createElement("span");t.className="mw-gallery-dot"+(0===e?" mw-active":""),t.addEventListener("click",()=>i(e)),c.appendChild(t)}r&&r.addEventListener("click",()=>i(s-1)),l&&l.addEventListener("click",()=>i(s+1));let d=0;n.addEventListener("touchstart",e=>d=e.touches[0].clientX),n.addEventListener("touchend",e=>{const t=e.changedTouches[0].clientX-d;t>50&&i(s-1),t<-50&&i(s+1)}),i(0)}(t,e)}),function(){const n=document.querySelector(".mw-theme-toggle");if(!n)return;const a=document.body,c=n.querySelector(".mw-theme-toggle-slider i"),o=getComputedStyle(document.documentElement).getPropertyValue("--mw-internal-theme-mode").trim()||"switchable";if("switchable"!==o)return console.log(`Theme mode fixed to: ${o}. Disabling toggle.`),c&&(c.className="light"===o?"fas fa-sun":"fas fa-moon"),e(n,"light"===o),n.style.opacity="0.4",n.style.pointerEvents="none",n.style.cursor="default",n.setAttribute("aria-disabled","true"),localStorage.removeItem("mw-theme"),void("dark"===o&&a.classList.remove("mw-theme-light"));let r="light"===localStorage.getItem("mw-theme");const l=t=>{a.classList.toggle("mw-theme-light",t),e(n,t),c&&(c.className=t?"fas fa-sun":"fas fa-moon")};l(r),n.addEventListener("click",()=>{r=!r,l(r),localStorage.setItem("mw-theme",r?"light":"dark"),setTimeout(t,400)})}(),t(),document.querySelectorAll(".mw-accordion-header").forEach(t=>{t.addEventListener("click",function(){const t=!((n=this)&&(n.classList.contains("mw-active")||n.classList.contains("active")));var n;e(this,t),e(this.nextElementSibling,t)})}),function(){const e=document.querySelector(".mw-menu-btn"),t=document.querySelector(".mw-navbar");if(!e||!t)return;function n(){e.classList.remove("open"),t.classList.remove("open")}function a(n){n.preventDefault(),n.stopPropagation(),e.classList.toggle("open"),t.classList.toggle("open")}e.addEventListener("click",a),e.addEventListener("touchstart",a,{passive:!1}),document.addEventListener("click",function(a){t.classList.contains("open")&&(t.contains(a.target)||e.contains(a.target)||n())}),document.addEventListener("keydown",function(e){"Escape"===e.key&&n()})}(),function(){const e=document.querySelectorAll(".mw-progress-fill");if(!e.length)return;const t=new IntersectionObserver((e,t)=>{e.forEach(e=>{if(!e.isIntersecting)return;const n=e.target,a=n.dataset.value||0;n.style.width=a+"%",t.unobserve(n)})},{root:null,threshold:.2});e.forEach(e=>t.observe(e))}(),document.querySelectorAll('a[href^="#"]').forEach(e=>{e.addEventListener("click",function(e){const t=this.getAttribute("href");if("#"===t)return;if(!document.querySelector(t))return;const n=document.querySelector(".mw-menu-btn"),a=document.querySelector(".mw-navbar");n&&a&&(n.classList.remove("open"),a.classList.remove("open"))})}),function(){const t=document.querySelectorAll("section[id]"),n=document.querySelectorAll(".mw-navbar-link");if(0===t.length||0===n.length)return;window.addEventListener("scroll",function(e,t){let n;return function(){const a=this,c=arguments;clearTimeout(n),n=setTimeout(()=>e.apply(a,c),t)}}(function(){let a="";t.forEach(e=>{const t=e.offsetTop-100,n=e.clientHeight;scrollY>=t&&scrollY<t+n&&(a=e.getAttribute("id"))}),n.forEach(t=>{e(t,!1);const n=t.getAttribute("href");if(n){const c=n.indexOf("#");if(-1!==c){n.substring(c+1)===a&&e(t,!0)}}})},100))}(),document.querySelectorAll(".mw-tabs-nav-item").forEach(t=>{t.addEventListener("click",function(){const t=this.closest(".mw-tabs");if(!t)return;t.querySelectorAll(".mw-tabs-nav-item").forEach(t=>{e(t,!1)}),e(this,!0);const n=this.getAttribute("data-tab");n&&(t.querySelectorAll(".mw-tabs-panel").forEach(t=>{e(t,!1)}),e(document.getElementById(n),!0))})}),document.querySelectorAll(".mw-alert-close").forEach(e=>{e.addEventListener("click",function(){const e=this.closest(".mw-alert");e&&(e.classList.add("mw-alert-closing"),setTimeout(()=>{e.classList.add("mw-alert-closed")},300))})}),function(){const e=document.querySelector(".mw-localhost-indicator-activated"),t=document.querySelector(".mw-header");if(e){if("localhost"===window.location.hostname||"127.0.0.1"===window.location.hostname||window.location.hostname.includes("192.168.")){const e=document.createElement("div");e.className="mw-localhost-indicator-pulse",t.prepend(e)}}}(),document.querySelectorAll(".mw-slider-container").forEach(e=>{const t=e.querySelector(".mw-slider"),n=e.querySelector(".mw-slider-value");if(!t||!n)return;const a=()=>{const e=Number(t.value),a=Number(t.max)||100,c=Math.round(e/a*100);t.style.setProperty("--value",c+"%"),n.classList.contains("mw-slider-numeric")?n.setAttribute("data-value",e):n.setAttribute("data-value",c)};t.addEventListener("input",a),a()}),document.querySelectorAll(".mw-modal-close").forEach(e=>{e.addEventListener("click",function(){const e=this.closest(".mw-modal-overlay");e&&e.classList.remove("mw-modal-open")})}),function(){const e=document.getElementById("login-button");e&&e.addEventListener("click",function(){const e=this.querySelector("i");e.classList.contains("fa-lock")?(e.classList.remove("fa-lock"),e.classList.add("fa-lock-open")):(e.classList.remove("fa-lock-open"),e.classList.add("fa-lock"))})}(),document.querySelectorAll(".mw-image-slider").forEach(t=>{const n=t.querySelectorAll(".mw-image-slider-overlay-image"),a=t.querySelectorAll("button[data-index]");if(!n.length||!a.length)return;let c=0;function o(){n.forEach(t=>{e(t,parseInt(t.dataset.index)===c)}),a.forEach(t=>{e(t,parseInt(t.dataset.index)===c)})}function r(e){c=e,o()}a.forEach(e=>{e.addEventListener("click",()=>{r(parseInt(e.dataset.index))})}),o()}),document.querySelectorAll(".mw-item-list-checkbox, .mw-item-list-checkbox-scroll").forEach(e=>{e.querySelectorAll("li").forEach(e=>{const t=e.querySelector('input[type="checkbox"]'),n=e.querySelector(".mw-checkbox");t&&n&&(t.checked&&e.classList.add("mw-selected"),e.addEventListener("click",function(e){e.target!==t&&e.target.closest(".mw-checkbox")!==n&&toggleCheckbox(this)}),t.addEventListener("change",function(){const e=this.closest("li");this.checked?e.classList.add("mw-selected"):e.classList.remove("mw-selected"),e.dispatchEvent(new CustomEvent("checkboxToggle",{detail:{checked:this.checked,item:e}}))}),n.addEventListener("click",function(e){setTimeout(()=>{const e=this.closest("li");this.querySelector('input[type="checkbox"]').checked?e.classList.add("mw-selected"):e.classList.remove("mw-selected")},0)}))})}),document.addEventListener("checkboxToggle",function(e){console.log("Checkbox toggled:",e.detail.checked,e.detail.item)}),document.querySelectorAll(".mw-kanban").forEach(n),document.querySelectorAll("[data-calendar]").forEach(a)}),window.toggleCheckbox=function(e){const t=e.querySelector('input[type="checkbox"]');if(!t)return;const n=t.checked;t.checked=!n,t.checked?e.classList.add("mw-selected"):e.classList.remove("mw-selected"),e.dispatchEvent(new CustomEvent("checkboxToggle",{detail:{checked:t.checked,item:e}}))}}();
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "maverick-wave",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"config": {
|
|
5
|
-
"version_short": "
|
|
5
|
+
"version_short": "4.0"
|
|
6
6
|
},
|
|
7
7
|
"description": "A lightweight, modern CSS framework for building responsive websites with elegance and speed.",
|
|
8
8
|
"main": "src/js/main.js",
|
package/src/js/main.js
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
(function () {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
// State classes: `mw-active` is the documented spelling, plain `active` is
|
|
5
|
+
// the one older markup uses. Both are styled, so turning a state *off* has
|
|
6
|
+
// to clear both - otherwise a stale `active` from the HTML would keep a
|
|
7
|
+
// second tab lit.
|
|
8
|
+
function setActive(el, on) {
|
|
9
|
+
if (!el) return;
|
|
10
|
+
el.classList.toggle('mw-active', on);
|
|
11
|
+
if (!on) el.classList.remove('active');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function isActive(el) {
|
|
15
|
+
return (
|
|
16
|
+
!!el &&
|
|
17
|
+
(el.classList.contains('mw-active') || el.classList.contains('active'))
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
4
21
|
// Initialize all components when DOM is ready
|
|
5
22
|
document.addEventListener('DOMContentLoaded', function () {
|
|
6
23
|
// Initialize all components
|
|
@@ -21,6 +38,7 @@
|
|
|
21
38
|
initImageSliders();
|
|
22
39
|
initCheckboxLists();
|
|
23
40
|
initKanbanBoards();
|
|
41
|
+
initCalendars();
|
|
24
42
|
});
|
|
25
43
|
|
|
26
44
|
// ===== Checkbox Lists =====
|
|
@@ -213,11 +231,7 @@
|
|
|
213
231
|
icon.className = themeMode === 'light' ? 'fas fa-sun' : 'fas fa-moon';
|
|
214
232
|
}
|
|
215
233
|
// Adjust toggle 'active' state if needed (assuming 'active' shows sun)
|
|
216
|
-
|
|
217
|
-
themeToggle.classList.add('active');
|
|
218
|
-
} else {
|
|
219
|
-
themeToggle.classList.remove('active');
|
|
220
|
-
}
|
|
234
|
+
setActive(themeToggle, themeMode === 'light');
|
|
221
235
|
|
|
222
236
|
// Disable existing toggle visually and functionally
|
|
223
237
|
themeToggle.style.opacity = '0.4';
|
|
@@ -243,7 +257,7 @@
|
|
|
243
257
|
const applyTheme = (lightMode) => {
|
|
244
258
|
// Use toggle's second argument for cleaner class switching
|
|
245
259
|
body.classList.toggle('mw-theme-light', lightMode);
|
|
246
|
-
themeToggle
|
|
260
|
+
setActive(themeToggle, lightMode);
|
|
247
261
|
if (icon) {
|
|
248
262
|
icon.className = lightMode ? 'fas fa-sun' : 'fas fa-moon';
|
|
249
263
|
}
|
|
@@ -318,9 +332,9 @@
|
|
|
318
332
|
const accordionHeaders = document.querySelectorAll('.mw-accordion-header');
|
|
319
333
|
accordionHeaders.forEach((header) => {
|
|
320
334
|
header.addEventListener('click', function () {
|
|
321
|
-
this
|
|
322
|
-
|
|
323
|
-
|
|
335
|
+
const open = !isActive(this);
|
|
336
|
+
setActive(this, open);
|
|
337
|
+
setActive(this.nextElementSibling, open);
|
|
324
338
|
});
|
|
325
339
|
});
|
|
326
340
|
}
|
|
@@ -428,7 +442,7 @@
|
|
|
428
442
|
});
|
|
429
443
|
|
|
430
444
|
navLinks.forEach((link) => {
|
|
431
|
-
link
|
|
445
|
+
setActive(link, false);
|
|
432
446
|
|
|
433
447
|
const href = link.getAttribute('href');
|
|
434
448
|
if (href) {
|
|
@@ -436,7 +450,7 @@
|
|
|
436
450
|
if (hashIndex !== -1) {
|
|
437
451
|
const linkTarget = href.substring(hashIndex + 1);
|
|
438
452
|
if (linkTarget === current) {
|
|
439
|
-
link
|
|
453
|
+
setActive(link, true);
|
|
440
454
|
}
|
|
441
455
|
}
|
|
442
456
|
}
|
|
@@ -457,20 +471,19 @@
|
|
|
457
471
|
tabsContainer
|
|
458
472
|
.querySelectorAll('.mw-tabs-nav-item')
|
|
459
473
|
.forEach((navItem) => {
|
|
460
|
-
navItem
|
|
474
|
+
setActive(navItem, false);
|
|
461
475
|
});
|
|
462
476
|
|
|
463
|
-
this
|
|
477
|
+
setActive(this, true);
|
|
464
478
|
|
|
465
479
|
const tabId = this.getAttribute('data-tab');
|
|
466
480
|
if (!tabId) return;
|
|
467
481
|
|
|
468
482
|
tabsContainer.querySelectorAll('.mw-tabs-panel').forEach((panel) => {
|
|
469
|
-
panel
|
|
483
|
+
setActive(panel, false);
|
|
470
484
|
});
|
|
471
485
|
|
|
472
|
-
|
|
473
|
-
if (targetPanel) targetPanel.classList.add('active');
|
|
486
|
+
setActive(document.getElementById(tabId), true);
|
|
474
487
|
});
|
|
475
488
|
});
|
|
476
489
|
}
|
|
@@ -601,13 +614,11 @@
|
|
|
601
614
|
|
|
602
615
|
function updateSliderView() {
|
|
603
616
|
overlayImages.forEach((img) => {
|
|
604
|
-
|
|
605
|
-
img.classList.toggle('active', imgIndex === current);
|
|
617
|
+
setActive(img, parseInt(img.dataset.index) === current);
|
|
606
618
|
});
|
|
607
619
|
|
|
608
620
|
buttons.forEach((btn) => {
|
|
609
|
-
|
|
610
|
-
btn.classList.toggle('active', btnIndex === current);
|
|
621
|
+
setActive(btn, parseInt(btn.dataset.index) === current);
|
|
611
622
|
});
|
|
612
623
|
}
|
|
613
624
|
|
|
@@ -841,4 +852,287 @@
|
|
|
841
852
|
|
|
842
853
|
refresh();
|
|
843
854
|
}
|
|
855
|
+
// ===== Calendars =====
|
|
856
|
+
function initCalendars() {
|
|
857
|
+
document.querySelectorAll('[data-calendar]').forEach(initCalendar);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
// Status dots come in as {"2026-08-19": ["success", "warning"]}
|
|
861
|
+
function parseCalendarMarkers(raw) {
|
|
862
|
+
if (!raw) return {};
|
|
863
|
+
|
|
864
|
+
try {
|
|
865
|
+
return JSON.parse(raw);
|
|
866
|
+
} catch (error) {
|
|
867
|
+
return {};
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
function initCalendar(calendar) {
|
|
872
|
+
const grid = calendar.querySelector('.mw-calendar-grid');
|
|
873
|
+
const title = calendar.querySelector('.mw-calendar-title');
|
|
874
|
+
if (!grid) return;
|
|
875
|
+
|
|
876
|
+
const weekMode = calendar.dataset.calendar === 'week';
|
|
877
|
+
const markers = parseCalendarMarkers(calendar.dataset.calendarMarkers);
|
|
878
|
+
// Falls back to the document language, so a German page gets German day
|
|
879
|
+
// names without configuring anything
|
|
880
|
+
const locale =
|
|
881
|
+
calendar.dataset.calendarLocale ||
|
|
882
|
+
document.documentElement.lang ||
|
|
883
|
+
undefined;
|
|
884
|
+
|
|
885
|
+
const today = new Date();
|
|
886
|
+
today.setHours(0, 0, 0, 0);
|
|
887
|
+
|
|
888
|
+
let cursor = calendar.dataset.calendarDate
|
|
889
|
+
? new Date(calendar.dataset.calendarDate + 'T00:00:00')
|
|
890
|
+
: new Date(today);
|
|
891
|
+
let selected = calendar.dataset.calendarSelected || '';
|
|
892
|
+
|
|
893
|
+
// Monday first: that is what ISO weeks use, and it keeps the weekend
|
|
894
|
+
// together as one block on the right
|
|
895
|
+
function startOfWeek(date) {
|
|
896
|
+
const result = new Date(date);
|
|
897
|
+
result.setDate(result.getDate() - ((result.getDay() + 6) % 7));
|
|
898
|
+
return result;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// Local date key - toISOString() would shift the day across a timezone
|
|
902
|
+
function dateKey(date) {
|
|
903
|
+
return (
|
|
904
|
+
date.getFullYear() +
|
|
905
|
+
'-' +
|
|
906
|
+
String(date.getMonth() + 1).padStart(2, '0') +
|
|
907
|
+
'-' +
|
|
908
|
+
String(date.getDate()).padStart(2, '0')
|
|
909
|
+
);
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
// ISO 8601: the week owning the Thursday owns the number
|
|
913
|
+
function weekNumber(date) {
|
|
914
|
+
const thursday = startOfWeek(date);
|
|
915
|
+
thursday.setDate(thursday.getDate() + 3);
|
|
916
|
+
|
|
917
|
+
const firstThursday = startOfWeek(new Date(thursday.getFullYear(), 0, 4));
|
|
918
|
+
firstThursday.setDate(firstThursday.getDate() + 3);
|
|
919
|
+
|
|
920
|
+
return 1 + Math.round((thursday - firstThursday) / 604800000);
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
function headline() {
|
|
924
|
+
if (!weekMode) {
|
|
925
|
+
return cursor.toLocaleDateString(locale, {
|
|
926
|
+
month: 'long',
|
|
927
|
+
year: 'numeric',
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
const from = startOfWeek(cursor);
|
|
932
|
+
const to = new Date(from);
|
|
933
|
+
to.setDate(to.getDate() + 6);
|
|
934
|
+
|
|
935
|
+
// The month is only spelled out twice when the week straddles two of them
|
|
936
|
+
const fromLabel = from.toLocaleDateString(locale, {
|
|
937
|
+
day: 'numeric',
|
|
938
|
+
month: from.getMonth() === to.getMonth() ? undefined : 'short',
|
|
939
|
+
});
|
|
940
|
+
const toLabel = to.toLocaleDateString(locale, {
|
|
941
|
+
day: 'numeric',
|
|
942
|
+
month: 'short',
|
|
943
|
+
year: 'numeric',
|
|
944
|
+
});
|
|
945
|
+
|
|
946
|
+
return 'Week ' + weekNumber(from) + ' · ' + fromLabel + ' - ' + toLabel;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
function isWeekend(date) {
|
|
950
|
+
const weekday = date.getDay();
|
|
951
|
+
return weekday === 0 || weekday === 6;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
function renderWeekdays() {
|
|
955
|
+
const day = startOfWeek(new Date());
|
|
956
|
+
|
|
957
|
+
for (let index = 0; index < 7; index++) {
|
|
958
|
+
const cell = document.createElement('div');
|
|
959
|
+
cell.className = 'mw-calendar-weekday';
|
|
960
|
+
if (isWeekend(day)) cell.classList.add('mw-calendar-weekend');
|
|
961
|
+
// Decorative: every day button already carries its weekday in the label
|
|
962
|
+
cell.setAttribute('aria-hidden', 'true');
|
|
963
|
+
cell.textContent = day.toLocaleDateString(locale, { weekday: 'short' });
|
|
964
|
+
grid.appendChild(cell);
|
|
965
|
+
day.setDate(day.getDate() + 1);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
function renderDay(date, month) {
|
|
970
|
+
const key = dateKey(date);
|
|
971
|
+
const cell = document.createElement('button');
|
|
972
|
+
|
|
973
|
+
cell.type = 'button';
|
|
974
|
+
cell.className = 'mw-calendar-day';
|
|
975
|
+
cell.tabIndex = -1;
|
|
976
|
+
cell.dataset.calendarDay = key;
|
|
977
|
+
cell.setAttribute('aria-pressed', key === selected ? 'true' : 'false');
|
|
978
|
+
// The bare number is not an accessible name - the arrows only announce
|
|
979
|
+
// where you are going, not where you landed
|
|
980
|
+
cell.setAttribute(
|
|
981
|
+
'aria-label',
|
|
982
|
+
date.toLocaleDateString(locale, {
|
|
983
|
+
weekday: 'long',
|
|
984
|
+
day: 'numeric',
|
|
985
|
+
month: 'long',
|
|
986
|
+
year: 'numeric',
|
|
987
|
+
})
|
|
988
|
+
);
|
|
989
|
+
|
|
990
|
+
if (isWeekend(date)) cell.classList.add('mw-calendar-weekend');
|
|
991
|
+
if (!weekMode && date.getMonth() !== month) {
|
|
992
|
+
cell.classList.add('mw-calendar-adjacent');
|
|
993
|
+
}
|
|
994
|
+
if (key === dateKey(today)) {
|
|
995
|
+
cell.classList.add('mw-calendar-today');
|
|
996
|
+
cell.setAttribute('aria-current', 'date');
|
|
997
|
+
}
|
|
998
|
+
if (key === selected) cell.classList.add('mw-selected');
|
|
999
|
+
|
|
1000
|
+
const number = document.createElement('span');
|
|
1001
|
+
number.className = 'mw-calendar-date';
|
|
1002
|
+
number.textContent = date.getDate();
|
|
1003
|
+
cell.appendChild(number);
|
|
1004
|
+
|
|
1005
|
+
const tones = [].concat(markers[key] || []);
|
|
1006
|
+
if (tones.length) {
|
|
1007
|
+
const dots = document.createElement('span');
|
|
1008
|
+
dots.className = 'mw-calendar-dots';
|
|
1009
|
+
|
|
1010
|
+
tones.forEach(function (tone) {
|
|
1011
|
+
const dot = document.createElement('span');
|
|
1012
|
+
dot.className = tone
|
|
1013
|
+
? 'mw-calendar-dot mw-calendar-dot-' + tone
|
|
1014
|
+
: 'mw-calendar-dot';
|
|
1015
|
+
dots.appendChild(dot);
|
|
1016
|
+
});
|
|
1017
|
+
|
|
1018
|
+
cell.appendChild(dots);
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
return cell;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
// A month always gets six rows. Rendering only the rows it needs would make
|
|
1025
|
+
// the calendar - and everything below it - jump on every month change.
|
|
1026
|
+
function render() {
|
|
1027
|
+
const month = cursor.getMonth();
|
|
1028
|
+
const cells = weekMode ? 7 : 42;
|
|
1029
|
+
const date = weekMode
|
|
1030
|
+
? startOfWeek(cursor)
|
|
1031
|
+
: startOfWeek(new Date(cursor.getFullYear(), month, 1));
|
|
1032
|
+
|
|
1033
|
+
grid.innerHTML = '';
|
|
1034
|
+
renderWeekdays();
|
|
1035
|
+
|
|
1036
|
+
for (let index = 0; index < cells; index++) {
|
|
1037
|
+
grid.appendChild(renderDay(date, month));
|
|
1038
|
+
date.setDate(date.getDate() + 1);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
if (title) title.textContent = headline();
|
|
1042
|
+
setTabStop();
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
// One tab stop for the whole grid; the arrow keys move inside it
|
|
1046
|
+
function setTabStop() {
|
|
1047
|
+
const cell =
|
|
1048
|
+
grid.querySelector('.mw-selected') ||
|
|
1049
|
+
grid.querySelector('.mw-calendar-today') ||
|
|
1050
|
+
grid.querySelector('.mw-calendar-day:not(.mw-calendar-adjacent)') ||
|
|
1051
|
+
grid.querySelector('.mw-calendar-day');
|
|
1052
|
+
|
|
1053
|
+
if (cell) cell.tabIndex = 0;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
function select(key) {
|
|
1057
|
+
selected = key === selected ? '' : key;
|
|
1058
|
+
|
|
1059
|
+
grid.querySelectorAll('.mw-calendar-day').forEach(function (cell) {
|
|
1060
|
+
const active = cell.dataset.calendarDay === selected;
|
|
1061
|
+
cell.classList.toggle('mw-selected', active);
|
|
1062
|
+
cell.setAttribute('aria-pressed', active ? 'true' : 'false');
|
|
1063
|
+
});
|
|
1064
|
+
|
|
1065
|
+
calendar.dispatchEvent(
|
|
1066
|
+
new CustomEvent('mw-calendar-select', {
|
|
1067
|
+
bubbles: true,
|
|
1068
|
+
detail: { date: selected },
|
|
1069
|
+
})
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
function step(offset) {
|
|
1074
|
+
if (weekMode) {
|
|
1075
|
+
cursor.setDate(cursor.getDate() + offset * 7);
|
|
1076
|
+
} else {
|
|
1077
|
+
// Snap to the first - stepping on from the 31st would skip February
|
|
1078
|
+
cursor = new Date(cursor.getFullYear(), cursor.getMonth() + offset, 1);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
render();
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
function focusDate(date) {
|
|
1085
|
+
const key = dateKey(date);
|
|
1086
|
+
let cell = grid.querySelector('[data-calendar-day="' + key + '"]');
|
|
1087
|
+
|
|
1088
|
+
// Walked off the rendered range - turn the page and look again
|
|
1089
|
+
if (!cell) {
|
|
1090
|
+
cursor = new Date(date);
|
|
1091
|
+
render();
|
|
1092
|
+
cell = grid.querySelector('[data-calendar-day="' + key + '"]');
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
if (!cell) return;
|
|
1096
|
+
|
|
1097
|
+
grid.querySelectorAll('.mw-calendar-day').forEach(function (other) {
|
|
1098
|
+
other.tabIndex = -1;
|
|
1099
|
+
});
|
|
1100
|
+
cell.tabIndex = 0;
|
|
1101
|
+
cell.focus();
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
calendar.addEventListener('click', function (event) {
|
|
1105
|
+
const navButton = event.target.closest('[data-calendar-nav]');
|
|
1106
|
+
if (navButton) {
|
|
1107
|
+
step(parseInt(navButton.dataset.calendarNav, 10));
|
|
1108
|
+
return;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
const dayButton = event.target.closest('.mw-calendar-day');
|
|
1112
|
+
if (dayButton && !dayButton.disabled) {
|
|
1113
|
+
select(dayButton.dataset.calendarDay);
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
|
|
1117
|
+
grid.addEventListener('keydown', function (event) {
|
|
1118
|
+
const offsets = {
|
|
1119
|
+
ArrowLeft: -1,
|
|
1120
|
+
ArrowRight: 1,
|
|
1121
|
+
ArrowUp: -7,
|
|
1122
|
+
ArrowDown: 7,
|
|
1123
|
+
};
|
|
1124
|
+
const offset = offsets[event.key];
|
|
1125
|
+
if (!offset) return;
|
|
1126
|
+
|
|
1127
|
+
const current = event.target.closest('.mw-calendar-day');
|
|
1128
|
+
if (!current) return;
|
|
1129
|
+
|
|
1130
|
+
event.preventDefault();
|
|
1131
|
+
const target = new Date(current.dataset.calendarDay + 'T00:00:00');
|
|
1132
|
+
target.setDate(target.getDate() + offset);
|
|
1133
|
+
focusDate(target);
|
|
1134
|
+
});
|
|
1135
|
+
|
|
1136
|
+
render();
|
|
1137
|
+
}
|
|
844
1138
|
})();
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
<div class="mw-accordion">
|
|
4
4
|
<div class="mw-accordion-item">
|
|
5
|
-
<div class="mw-accordion-header active">
|
|
5
|
+
<div class="mw-accordion-header mw-active">
|
|
6
6
|
<h3>What is MaverickWave?</h3>
|
|
7
7
|
<i class="fas fa-chevron-down mw-accordion-icon"></i>
|
|
8
8
|
</div>
|
|
9
|
-
<div class="mw-accordion-content active">
|
|
9
|
+
<div class="mw-accordion-content mw-active">
|
|
10
10
|
<div class="mw-accordion-content-inner">
|
|
11
11
|
<p>
|
|
12
12
|
MaverickWave is a lightweight, responsive CSS framework designed for
|
|
@@ -86,8 +86,10 @@
|
|
|
86
86
|
</div>
|
|
87
87
|
</div>
|
|
88
88
|
<div>
|
|
89
|
-
<p class="mw-mb-2"
|
|
90
|
-
|
|
89
|
+
<p class="mw-mb-2">
|
|
90
|
+
<strong>Center Aligned (also the default):</strong>
|
|
91
|
+
</p>
|
|
92
|
+
<div class="mw-button-bar mw-button-bar-center mw-button-bar-outline">
|
|
91
93
|
<button class="mw-btn">Left</button>
|
|
92
94
|
<button class="mw-btn">Center</button>
|
|
93
95
|
<button class="mw-btn">Right</button>
|
|
@@ -127,3 +127,38 @@
|
|
|
127
127
|
</div>
|
|
128
128
|
</div>
|
|
129
129
|
</div>
|
|
130
|
+
|
|
131
|
+
<h3 class="mw-mb-4 mw-mt-6">Plain Buttons</h3>
|
|
132
|
+
<p class="mw-text-muted">
|
|
133
|
+
<code>mw-btn-plain</code> is for everywhere a <code><button></code> is
|
|
134
|
+
the right element and a button is the wrong look - a calendar day, a time in a
|
|
135
|
+
request row, a modal backdrop. It brings nothing but the focus ring and the
|
|
136
|
+
pointer; everything else it inherits. Not the same as
|
|
137
|
+
<code>mw-btn-link</code>, which is a button dressed as a link with a colour
|
|
138
|
+
and a minimum width of its own.
|
|
139
|
+
</p>
|
|
140
|
+
<div class="mw-card mw-card-simple">
|
|
141
|
+
<p class="mw-mb-4">
|
|
142
|
+
Booked for
|
|
143
|
+
<button type="button" class="mw-btn-plain mw-text-bold">14:30</button>
|
|
144
|
+
on
|
|
145
|
+
<button type="button" class="mw-btn-plain mw-text-bold">19.09.2026</button>
|
|
146
|
+
– both are real buttons, reachable by tab.
|
|
147
|
+
</p>
|
|
148
|
+
<div class="mw-d-flex mw-gap-4 mw-flex-wrap">
|
|
149
|
+
<button type="button" class="mw-btn mw-btn-link">mw-btn-link</button>
|
|
150
|
+
<button type="button" class="mw-btn-plain">mw-btn-plain</button>
|
|
151
|
+
<button type="button" class="mw-btn-plain" disabled>disabled</button>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<h3 class="mw-mb-4 mw-mt-6">Touch Targets</h3>
|
|
156
|
+
<p class="mw-text-muted">
|
|
157
|
+
On a coarse pointer or below 768px the compact controls grow to a size a thumb
|
|
158
|
+
can actually hit: <code>mw-btn-sm</code>, <code>mw-input-sm</code> and
|
|
159
|
+
<code>mw-select-sm</code> to 2.5rem, a tab to 2.75rem, a calendar day to 44px.
|
|
160
|
+
WCAG 2.5.8 puts the floor at 24px, and that is a floor, not a goal.
|
|
161
|
+
<code>mw-btn-mini</code> keeps its 18px circle - it sits in tag rows and table
|
|
162
|
+
cells where a bigger one would shift the layout - and grows its hit area to
|
|
163
|
+
28px instead. Nothing to switch on; resize this page or open it on a phone.
|
|
164
|
+
</p>
|