- ajoute un .dockerignore. - met à jour les dépendances. - utilise bun comme gestionnaire de paquets npm. - utilise une configuration Vite en TypeScript. - ajoute les fichiers compilés JavaScript aux fichiers pris en charge par Git.
325 lines
No EOL
12 KiB
JavaScript
325 lines
No EOL
12 KiB
JavaScript
import { r as _defineProperty } from "./journalisation.CEgm28xa.js";
|
|
import { dt as pipe } from "./exports.CurVqjr0.js";
|
|
import { _t as ATTRIBUT_MENU_MOBILE_ACTIVE, a as mustGetEleInDocument, dn as Ra, kt as DOM_BOUTON_MENU_MOBILE, tn as DOM_MENU_MOBILE } from "./dom.emspS_OW.js";
|
|
import "./belt_Option-91f3b350.CMbgtZ-W.js";
|
|
import { t as P } from "./index-c1cc4c86.D2nZEikK.js";
|
|
|
|
//#region node_modules/a11y-dialog/dist/a11y-dialog.esm.js
|
|
var not = {
|
|
inert: ":not([inert]):not([inert] *)",
|
|
negTabIndex: ":not([tabindex^=\"-\"])",
|
|
disabled: ":not(:disabled)"
|
|
};
|
|
var focusableSelectors = [
|
|
`a[href]${not.inert}${not.negTabIndex}`,
|
|
`area[href]${not.inert}${not.negTabIndex}`,
|
|
`input:not([type="hidden"]):not([type="radio"])${not.inert}${not.negTabIndex}${not.disabled}`,
|
|
`input[type="radio"]${not.inert}${not.negTabIndex}${not.disabled}`,
|
|
`select${not.inert}${not.negTabIndex}${not.disabled}`,
|
|
`textarea${not.inert}${not.negTabIndex}${not.disabled}`,
|
|
`button${not.inert}${not.negTabIndex}${not.disabled}`,
|
|
`details${not.inert} > summary:first-of-type${not.negTabIndex}`,
|
|
`iframe${not.inert}${not.negTabIndex}`,
|
|
`audio[controls]${not.inert}${not.negTabIndex}`,
|
|
`video[controls]${not.inert}${not.negTabIndex}`,
|
|
`[contenteditable]${not.inert}${not.negTabIndex}`,
|
|
`[tabindex]${not.inert}${not.negTabIndex}`
|
|
];
|
|
/**
|
|
* Set the focus to the first element with `autofocus` with the element or the
|
|
* element itself.
|
|
*/
|
|
function focus(el) {
|
|
(el.querySelector("[autofocus]") || el).focus();
|
|
}
|
|
/**
|
|
* Get the first and last focusable elements within a given element.
|
|
*/
|
|
function getFocusableEdges(el) {
|
|
const firstEl = findFocusableEl(el, true);
|
|
return [firstEl, firstEl ? findFocusableEl(el, false) || firstEl : null];
|
|
}
|
|
/**
|
|
* Find the first focusable element inside the given element if `forward` is
|
|
* truthy or the last focusable element otherwise.
|
|
*/
|
|
function findFocusableEl(el, forward) {
|
|
if (forward && isFocusable(el)) return el;
|
|
if (canHaveFocusableChildren(el)) if (el.shadowRoot) {
|
|
let next = getNextChildEl(el.shadowRoot, forward);
|
|
while (next) {
|
|
const focusableEl = findFocusableEl(next, forward);
|
|
if (focusableEl) return focusableEl;
|
|
next = getNextSiblingEl(next, forward);
|
|
}
|
|
} else if (el.localName === "slot") {
|
|
const assignedElements = el.assignedElements({ flatten: true });
|
|
if (!forward) assignedElements.reverse();
|
|
for (const assignedElement of assignedElements) {
|
|
const focusableEl = findFocusableEl(assignedElement, forward);
|
|
if (focusableEl) return focusableEl;
|
|
}
|
|
} else {
|
|
let next = getNextChildEl(el, forward);
|
|
while (next) {
|
|
const focusableEl = findFocusableEl(next, forward);
|
|
if (focusableEl) return focusableEl;
|
|
next = getNextSiblingEl(next, forward);
|
|
}
|
|
}
|
|
if (!forward && isFocusable(el)) return el;
|
|
return null;
|
|
}
|
|
function getNextChildEl(el, forward) {
|
|
return forward ? el.firstElementChild : el.lastElementChild;
|
|
}
|
|
function getNextSiblingEl(el, forward) {
|
|
return forward ? el.nextElementSibling : el.previousElementSibling;
|
|
}
|
|
/**
|
|
* Determine if an element is hidden from the user.
|
|
*/
|
|
var isHidden = (el) => {
|
|
if (el.matches("details:not([open]) *") && !el.matches("details>summary:first-of-type")) return true;
|
|
return !(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
|
|
};
|
|
/**
|
|
* Determine if an element is focusable and has user-visible painted dimensions.
|
|
*/
|
|
var isFocusable = (el) => {
|
|
if (el.shadowRoot?.delegatesFocus) return false;
|
|
return el.matches(focusableSelectors.join(",")) && !isHidden(el);
|
|
};
|
|
/**
|
|
* Determine if an element can have focusable children. Useful for bailing out
|
|
* early when walking the DOM tree.
|
|
* @example
|
|
* This div is inert, so none of its children can be focused, even though they
|
|
* meet our criteria for what is focusable. Once we check the div, we can skip
|
|
* the rest of the subtree.
|
|
* ```html
|
|
* <div inert>
|
|
* <button>Button</button>
|
|
* <a href="#">Link</a>
|
|
* </div>
|
|
* ```
|
|
*/
|
|
function canHaveFocusableChildren(el) {
|
|
if (el.shadowRoot && el.getAttribute("tabindex") === "-1") return false;
|
|
return !el.matches(":disabled,[hidden],[inert]");
|
|
}
|
|
/**
|
|
* Get the active element, accounting for Shadow DOM subtrees.
|
|
* @author Cory LaViska
|
|
* @see: https://www.abeautifulsite.net/posts/finding-the-active-element-in-a-shadow-root/
|
|
*/
|
|
function getActiveEl(root = document) {
|
|
const activeEl = root.activeElement;
|
|
if (!activeEl) return null;
|
|
if (activeEl.shadowRoot) return getActiveEl(activeEl.shadowRoot) || document.activeElement;
|
|
return activeEl;
|
|
}
|
|
/**
|
|
* Trap the focus inside the given element
|
|
*/
|
|
function trapTabKey(el, event) {
|
|
const [firstFocusableEl, lastFocusableEl] = getFocusableEdges(el);
|
|
if (!firstFocusableEl) return event.preventDefault();
|
|
const activeEl = getActiveEl();
|
|
if (event.shiftKey && activeEl === firstFocusableEl) {
|
|
lastFocusableEl.focus();
|
|
event.preventDefault();
|
|
} else if (!event.shiftKey && activeEl === lastFocusableEl) {
|
|
firstFocusableEl.focus();
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
/**
|
|
* Find the closest element to the given element matching the given selector,
|
|
* accounting for Shadow DOM subtrees.
|
|
* @author Louis St-Amour
|
|
* @see: https://stackoverflow.com/a/56105394
|
|
*/
|
|
function closest(selector, base) {
|
|
function from(el) {
|
|
if (!el || el === document || el === window) return null;
|
|
const slot = findAssignedSlot(el);
|
|
if (slot) el = slot;
|
|
return el.closest(selector) || from(el.getRootNode().host);
|
|
}
|
|
return from(base);
|
|
}
|
|
function findAssignedSlot(node) {
|
|
return node.assignedSlot || (node.parentNode ? findAssignedSlot(node.parentNode) : null);
|
|
}
|
|
var SCOPE = "data-a11y-dialog";
|
|
var A11yDialog = class {
|
|
constructor(element) {
|
|
_defineProperty(this, "$el", void 0);
|
|
_defineProperty(this, "id", void 0);
|
|
_defineProperty(this, "previouslyFocused", void 0);
|
|
_defineProperty(this, "shown", void 0);
|
|
this.$el = element;
|
|
this.id = this.$el.getAttribute(SCOPE) || this.$el.id;
|
|
this.previouslyFocused = null;
|
|
this.shown = false;
|
|
this.maintainFocus = this.maintainFocus.bind(this);
|
|
this.bindKeypress = this.bindKeypress.bind(this);
|
|
this.handleTriggerClicks = this.handleTriggerClicks.bind(this);
|
|
this.show = this.show.bind(this);
|
|
this.hide = this.hide.bind(this);
|
|
this.$el.setAttribute("aria-hidden", "true");
|
|
this.$el.setAttribute("aria-modal", "true");
|
|
this.$el.setAttribute("tabindex", "-1");
|
|
if (!this.$el.hasAttribute("role")) this.$el.setAttribute("role", "dialog");
|
|
document.addEventListener("click", this.handleTriggerClicks, true);
|
|
}
|
|
/**
|
|
* Destroy the current instance (after making sure the dialog has been hidden)
|
|
* and remove all associated listeners from dialog openers and closers
|
|
*/
|
|
destroy() {
|
|
if (this.fire("destroy").defaultPrevented) return this;
|
|
this.hide();
|
|
document.removeEventListener("click", this.handleTriggerClicks, true);
|
|
this.$el.replaceWith(this.$el.cloneNode(true));
|
|
return this;
|
|
}
|
|
/**
|
|
* Show the dialog element, trap the current focus within it, listen for some
|
|
* specific key presses and fire all registered callbacks for `show` event
|
|
*/
|
|
show(event) {
|
|
if (this.shown) return this;
|
|
if (this.fire("show", event).defaultPrevented) return this;
|
|
this.shown = true;
|
|
this.$el.removeAttribute("aria-hidden");
|
|
this.previouslyFocused = getActiveEl();
|
|
if (this.previouslyFocused?.tagName === "BODY" && event?.target) this.previouslyFocused = event.target;
|
|
if (event?.type === "focus") this.maintainFocus();
|
|
else focus(this.$el);
|
|
document.body.addEventListener("focus", this.maintainFocus, true);
|
|
this.$el.addEventListener("keydown", this.bindKeypress, true);
|
|
return this;
|
|
}
|
|
/**
|
|
* Hide the dialog element, restore the focus to the previously active
|
|
* element, stop listening for some specific key presses and fire all
|
|
* registered callbacks for `hide` event
|
|
*/
|
|
hide(event) {
|
|
if (!this.shown) return this;
|
|
if (this.fire("hide", event).defaultPrevented) return this;
|
|
this.shown = false;
|
|
this.$el.setAttribute("aria-hidden", "true");
|
|
document.body.removeEventListener("focus", this.maintainFocus, true);
|
|
this.$el.removeEventListener("keydown", this.bindKeypress, true);
|
|
this.previouslyFocused?.focus?.();
|
|
return this;
|
|
}
|
|
/**
|
|
* Register a new callback for the given event type
|
|
*/
|
|
on(type, handler, options) {
|
|
this.$el.addEventListener(type, handler, options);
|
|
return this;
|
|
}
|
|
/**
|
|
* Unregister an existing callback for the given event type
|
|
*/
|
|
off(type, handler, options) {
|
|
this.$el.removeEventListener(type, handler, options);
|
|
return this;
|
|
}
|
|
/**
|
|
* Dispatch and return a custom event from the DOM element associated with
|
|
* this dialog; this allows authors to listen for and respond to the events
|
|
* in their own code
|
|
*/
|
|
fire(type, event) {
|
|
const customEvent = new CustomEvent(type, {
|
|
detail: event,
|
|
cancelable: true
|
|
});
|
|
this.$el.dispatchEvent(customEvent);
|
|
return customEvent;
|
|
}
|
|
/**
|
|
* Add a delegated event listener for when elememts that open or close the
|
|
* dialog are clicked, and call `show` or `hide`, respectively
|
|
*/
|
|
handleTriggerClicks(event) {
|
|
const target = event.composedPath()[0];
|
|
const opener = closest(`[${SCOPE}-show="${this.id}"]`, target);
|
|
const explicitCloser = closest(`[${SCOPE}-hide="${this.id}"]`, target);
|
|
const implicitCloser = closest(`[${SCOPE}-hide]`, target) && closest("[aria-modal=\"true\"]", target) === this.$el;
|
|
if (opener) this.show(event);
|
|
if (explicitCloser || implicitCloser) this.hide(event);
|
|
}
|
|
/**
|
|
* Private event handler used when listening to some specific key presses
|
|
* (namely ESC and TAB)
|
|
*/
|
|
bindKeypress(event) {
|
|
if (closest("[aria-modal=\"true\"]", getActiveEl()) !== this.$el) return;
|
|
let hasOpenPopover = false;
|
|
try {
|
|
hasOpenPopover = !!this.$el.querySelector("[popover]:not([popover=\"manual\"]):popover-open");
|
|
} catch {}
|
|
if (event.key === "Escape" && this.$el.getAttribute("role") !== "alertdialog" && !hasOpenPopover) {
|
|
event.preventDefault();
|
|
this.hide(event);
|
|
}
|
|
if (event.key === "Tab") trapTabKey(this.$el, event);
|
|
}
|
|
/**
|
|
* If the dialog is shown and the focus is not within a dialog element (either
|
|
* this one or another one in case of nested dialogs) or an element with the
|
|
* ignore attribute, move it back to the dialog container
|
|
* See: https://github.com/KittyGiraudel/a11y-dialog/issues/177
|
|
*/
|
|
maintainFocus() {
|
|
const target = getActiveEl();
|
|
if (!closest(`[aria-modal="true"], [${SCOPE}-ignore-focus-trap]`, target)) focus(this.$el);
|
|
}
|
|
};
|
|
function instantiateDialogs() {
|
|
for (const el of document.querySelectorAll("[data-a11y-dialog]")) new A11yDialog(el);
|
|
}
|
|
if (typeof document !== "undefined") if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", instantiateDialogs);
|
|
else instantiateDialogs();
|
|
|
|
//#endregion
|
|
//#region web/app/themes/haiku-atelier-2024/src/scripts/scripts-menu-mobile.ts
|
|
var E = {
|
|
BOUTON_MENU_MOBILE: mustGetEleInDocument(DOM_BOUTON_MENU_MOBILE),
|
|
CORPS_HTML: mustGetEleInDocument("body"),
|
|
MENU_MOBILE: mustGetEleInDocument(DOM_MENU_MOBILE)
|
|
};
|
|
var initialiseBoutonMenuMobile = () => {
|
|
const menuMobile = new A11yDialog(E.MENU_MOBILE);
|
|
new ResizeObserver((entrees) => pipe(Ra.head(entrees), P.filter((entree) => entree.borderBoxSize[0].inlineSize > 1e3), P.tap((_) => menuMobile.hide()))).observe(E.CORPS_HTML);
|
|
E.BOUTON_MENU_MOBILE.addEventListener("click", () => {
|
|
if (window.innerWidth > 1e3) {
|
|
window.location.href = "/";
|
|
return;
|
|
}
|
|
if (E.BOUTON_MENU_MOBILE.hasAttribute("data-menu-mobile-active")) {
|
|
menuMobile.hide();
|
|
return;
|
|
}
|
|
menuMobile.show();
|
|
});
|
|
menuMobile.on("show", () => {
|
|
E.BOUTON_MENU_MOBILE.setAttribute(ATTRIBUT_MENU_MOBILE_ACTIVE, "");
|
|
});
|
|
menuMobile.on("hide", () => {
|
|
E.BOUTON_MENU_MOBILE.removeAttribute(ATTRIBUT_MENU_MOBILE_ACTIVE);
|
|
});
|
|
};
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
initialiseBoutonMenuMobile();
|
|
});
|
|
|
|
//#endregion
|
|
//# sourceMappingURL=scripts-menu-mobile.js.map
|