| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659 |
- const _emptyNodeList = [];
- function isTouchable() {
- return window.matchMedia("(pointer: coarse)").matches;
- }
- function isDark() {
- return window.matchMedia("(prefers-color-scheme: dark)").matches;
- }
- async function wait(milliseconds) {
- await new Promise((resolve) => setTimeout(resolve, milliseconds));
- }
- function guid() {
- return "fxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
- const r = Math.random() * 16 | 0;
- const v = c === "x" ? r : r & 3 | 8;
- return v.toString(16);
- });
- }
- function query(selector, element) {
- try {
- return typeof selector === "string" ? (element ?? document).querySelector(selector) : selector;
- } catch {
- return null;
- }
- }
- function queryAll(selector, element) {
- try {
- return typeof selector === "string" ? (element ?? document).querySelectorAll(selector) : selector ?? _emptyNodeList;
- } catch {
- return _emptyNodeList;
- }
- }
- function hasClass(element, name) {
- return (element == null ? void 0 : element.classList.contains(name)) ?? false;
- }
- function hasTag(element, name) {
- var _a;
- return ((_a = element == null ? void 0 : element.tagName) == null ? void 0 : _a.toLowerCase()) === name;
- }
- function hasType(element, name) {
- var _a;
- return ((_a = element == null ? void 0 : element.type) == null ? void 0 : _a.toLowerCase()) === name;
- }
- function addClass(element, name) {
- if (element instanceof NodeList)
- for (let i = 0; i < element.length; i++)
- element[i].classList.add(name);
- else
- element == null ? void 0 : element.classList.add(name);
- }
- function removeClass(element, name) {
- if (element instanceof NodeList)
- for (let i = 0; i < element.length; i++)
- element[i].classList.remove(name);
- else
- element == null ? void 0 : element.classList.remove(name);
- }
- function on(element, name, callback, useCapture = true) {
- if (element == null ? void 0 : element.addEventListener)
- element.addEventListener(name, callback, useCapture);
- }
- function off(element, name, callback, useCapture = true) {
- if (element == null ? void 0 : element.removeEventListener)
- element.removeEventListener(name, callback, useCapture);
- }
- function insertBefore(newElement, element) {
- var _a;
- (_a = element == null ? void 0 : element.parentNode) == null ? void 0 : _a.insertBefore(newElement, element);
- }
- function prev(element) {
- return element == null ? void 0 : element.previousElementSibling;
- }
- function next(element) {
- return element == null ? void 0 : element.nextElementSibling;
- }
- function parent(element) {
- return element == null ? void 0 : element.parentElement;
- }
- function create(htmlAttributesAsJson) {
- const element = document.createElement("div");
- for (let i = 0, keys = Object.keys(htmlAttributesAsJson), n = keys.length; i < n; i++) {
- const key = keys[i];
- const value = htmlAttributesAsJson[key];
- element.setAttribute(key, value);
- }
- return element;
- }
- function blurActiveElement() {
- var _a;
- (_a = document.activeElement) == null ? void 0 : _a.blur();
- }
- function queryAllDataUi(id) {
- return queryAll('[data-ui="#' + id + '"]');
- }
- function queryDataUi(id) {
- return query('[data-ui="#' + id + '"]');
- }
- function updateAllClickable(element) {
- if (element.id && hasClass(element, "page"))
- element = queryDataUi(element.id) ?? element;
- const container = parent(element);
- if (!hasClass(container, "tabs") && !hasClass(container, "tabbed") && !hasTag(container, "nav"))
- return;
- const as = queryAll("a", container);
- for (let i = 0; i < as.length; i++)
- removeClass(as[i], "active");
- addClass(element, "active");
- }
- function updatePlaceholder(element) {
- if (!element.placeholder)
- element.placeholder = " ";
- }
- function onClickLabel(e) {
- const label = e.currentTarget;
- const field = parent(label);
- const input = query("input:not([type=file], [type=checkbox], [type=radio]), select, textarea", field);
- if (input)
- input.focus();
- }
- function onFocusInput(e) {
- const input = e.currentTarget;
- updateInput(input);
- }
- function onBlurInput(e) {
- const input = e.currentTarget;
- updateInput(input);
- }
- function onChangeFile(e) {
- const input = e.currentTarget;
- updateFile(input);
- }
- function onChangeColor(e) {
- const input = e.currentTarget;
- updateColor(input);
- }
- function onKeydownFile(e) {
- const input = e.currentTarget;
- updateFile(input, e);
- }
- function onKeydownColor(e) {
- const input = e.currentTarget;
- updateColor(input, e);
- }
- function onInputTextarea(e) {
- const textarea = e.currentTarget;
- updateTextarea(textarea);
- }
- function onPasswordIconClick(e) {
- var _a;
- const icon = e.currentTarget;
- const input = query("input", parent(icon));
- if (input && ((_a = icon.textContent) == null ? void 0 : _a.includes("visibility")))
- input.type = input.type === "password" ? "text" : "password";
- }
- function updateAllLabels() {
- const labels = queryAll(".field > label");
- for (let i = 0; i < labels.length; i++)
- on(labels[i], "click", onClickLabel);
- }
- function updateAllInputs() {
- const inputs = queryAll(".field > input:not([type=file], [type=color], [type=range])");
- for (let i = 0; i < inputs.length; i++) {
- on(inputs[i], "focus", onFocusInput);
- on(inputs[i], "blur", onBlurInput);
- updateInput(inputs[i]);
- }
- }
- function updateAllSelects() {
- const selects = queryAll(".field > select");
- for (let i = 0; i < selects.length; i++) {
- on(selects[i], "focus", onFocusInput);
- on(selects[i], "blur", onBlurInput);
- }
- }
- function updateAllFiles() {
- const files = queryAll(".field > input[type=file]");
- for (let i = 0; i < files.length; i++) {
- on(files[i], "change", onChangeFile);
- updateFile(files[i]);
- }
- }
- function updateAllColors() {
- const colors = queryAll(".field > input[type=color]");
- for (let i = 0; i < colors.length; i++) {
- on(colors[i], "change", onChangeColor);
- updateColor(colors[i]);
- }
- }
- function updateAllTextareas() {
- const textareas = queryAll(".field.textarea > textarea");
- for (let i = 0; i < textareas.length; i++) {
- on(textareas[i], "focus", onFocusInput);
- on(textareas[i], "blur", onBlurInput);
- on(textareas[i], "input", onInputTextarea);
- updateTextarea(textareas[i]);
- }
- }
- function updateAllPasswordIcons() {
- const icons = queryAll("input[type=password] ~ :is(i, a)");
- for (let i = 0; i < icons.length; i++)
- on(icons[i], "click", onPasswordIconClick);
- }
- function updateInput(input) {
- if (hasType(input, "number") && !input.value)
- input.value = "";
- updatePlaceholder(input);
- }
- function updateFile(input, e) {
- if ((e == null ? void 0 : e.key) === "Enter") {
- const previousInput = prev(input);
- if (!hasType(previousInput, "file"))
- return;
- previousInput.click();
- return;
- }
- const nextInput = next(input);
- if (!hasType(nextInput, "text"))
- return;
- nextInput.value = input.files ? Array.from(input.files).map((x) => x.name).join(", ") : "";
- nextInput.readOnly = true;
- on(nextInput, "keydown", onKeydownFile, false);
- updateInput(nextInput);
- }
- function updateColor(input, e) {
- if ((e == null ? void 0 : e.key) === "Enter") {
- const previousInput = prev(input);
- if (!hasType(previousInput, "color"))
- return;
- previousInput.click();
- return;
- }
- const nextInput = next(input);
- if (!hasType(nextInput, "text"))
- return;
- nextInput.readOnly = true;
- nextInput.value = input.value;
- on(nextInput, "keydown", onKeydownColor, false);
- updateInput(nextInput);
- }
- function updateTextarea(textarea) {
- updatePlaceholder(textarea);
- const field = parent(textarea);
- field.removeAttribute("style");
- if (hasClass(field, "min"))
- field.style.setProperty("---size", `${Math.max(textarea.scrollHeight, field.offsetHeight)}px`);
- }
- function updateAllFields() {
- updateAllLabels();
- updateAllInputs();
- updateAllSelects();
- updateAllFiles();
- updateAllColors();
- updateAllTextareas();
- updateAllPasswordIcons();
- }
- function onInputDocument(e) {
- const input = e.target;
- if (!hasTag(input, "input") && !hasTag(input, "select"))
- return;
- if (input.type === "range") {
- input.focus();
- updateRange(input);
- } else {
- updateAllRanges();
- }
- }
- function onFocusRange(e) {
- if (!isTouchable())
- return;
- const input = e.target;
- const label = parent(input);
- if (hasClass(label, "vertical"))
- document.body.classList.add("no-scroll");
- }
- function onBlurRange(e) {
- if (!isTouchable())
- return;
- const input = e.target;
- const label = parent(input);
- if (hasClass(label, "vertical"))
- document.body.classList.remove("no-scroll");
- }
- function updateAllRanges() {
- const body = document.body;
- const ranges = queryAll(".slider > input[type=range]");
- if (!ranges.length)
- off(body, "input", onInputDocument, false);
- else
- on(body, "input", onInputDocument, false);
- for (let i = 0; i < ranges.length; i++)
- updateRange(ranges[i]);
- }
- function updateRange(input) {
- on(input, "focus", onFocusRange);
- on(input, "blur", onBlurRange);
- const label = parent(input);
- const bar = query("span", label);
- const inputs = queryAll("input", label);
- if (!inputs.length || !bar)
- return;
- const rootSize = parseInt(getComputedStyle(document.documentElement).getPropertyValue("--size")) || 16;
- const thumb = hasClass(label, "max") ? 0 : 0.25 * rootSize * 100 / inputs[0].offsetWidth;
- const percents = [];
- const values = [];
- for (let i = 0, n = inputs.length; i < n; i++) {
- const min = parseFloat(inputs[i].min) || 0;
- const max = parseFloat(inputs[i].max) || 100;
- const value = parseFloat(inputs[i].value) || 0;
- const percent2 = (value - min) * 100 / (max - min);
- const fix = thumb / 2 - thumb * percent2 / 100;
- percents.push(percent2 + fix);
- values.push(value);
- }
- let percent = percents[0];
- let start2 = 0;
- let end = 100 - start2 - percent;
- let value1 = values[0];
- let value2 = values[1] || 0;
- if (inputs.length > 1) {
- percent = Math.abs(percents[1] - percents[0]);
- start2 = percents[1] > percents[0] ? percents[0] : percents[1];
- end = 100 - start2 - percent;
- if (value2 > value1) {
- value1 = values[1] || 0;
- value2 = values[0];
- }
- }
- label.style.setProperty("---start", `${start2}%`);
- label.style.setProperty("---end", `${end}%`);
- label.style.setProperty("---value1", `'${value1}'`);
- label.style.setProperty("---value2", `'${value2}'`);
- }
- function updateAllSliders() {
- updateAllRanges();
- }
- const _lastTheme = {
- light: "",
- dark: ""
- };
- function getMode() {
- var _a;
- return ((_a = document == null ? void 0 : document.body) == null ? void 0 : _a.classList.contains("dark")) ? "dark" : "light";
- }
- function lastTheme() {
- if (_lastTheme.light && _lastTheme.dark)
- return _lastTheme;
- const body = document.body;
- const light = document.createElement("body");
- light.className = "light";
- body.appendChild(light);
- const dark = document.createElement("body");
- dark.className = "dark";
- body.appendChild(dark);
- const fromLight = getComputedStyle(light);
- const fromDark = getComputedStyle(dark);
- const variables = ["--primary", "--on-primary", "--primary-container", "--on-primary-container", "--secondary", "--on-secondary", "--secondary-container", "--on-secondary-container", "--tertiary", "--on-tertiary", "--tertiary-container", "--on-tertiary-container", "--error", "--on-error", "--error-container", "--on-error-container", "--background", "--on-background", "--surface", "--on-surface", "--surface-variant", "--on-surface-variant", "--outline", "--outline-variant", "--shadow", "--scrim", "--inverse-surface", "--inverse-on-surface", "--inverse-primary", "--surface-dim", "--surface-bright", "--surface-container-lowest", "--surface-container-low", "--surface-container", "--surface-container-high", "--surface-container-highest"];
- for (let i = 0, n = variables.length; i < n; i++) {
- _lastTheme.light += variables[i] + ":" + fromLight.getPropertyValue(variables[i]) + ";";
- _lastTheme.dark += variables[i] + ":" + fromDark.getPropertyValue(variables[i]) + ";";
- }
- body.removeChild(light);
- body.removeChild(dark);
- return _lastTheme;
- }
- function updateTheme(source) {
- const context = globalThis;
- const body = document.body;
- if (!source || !context.materialDynamicColors)
- return lastTheme();
- const mode = getMode();
- if (source.light && source.dark) {
- _lastTheme.light = source.light;
- _lastTheme.dark = source.dark;
- body.setAttribute("style", source[mode]);
- return source;
- }
- return context.materialDynamicColors(source).then((theme) => {
- const toCss = (data) => {
- let style = "";
- for (let i = 0, keys = Object.keys(data), n = keys.length; i < n; i++) {
- const key = keys[i];
- const value = data[key];
- const kebabCase = key.replace(/([a-z0-9]|(?=[A-Z]))([A-Z])/g, "$1-$2").toLowerCase();
- style += "--" + kebabCase + ":" + value + ";";
- }
- return style;
- };
- _lastTheme.light = toCss(theme.light);
- _lastTheme.dark = toCss(theme.dark);
- body.setAttribute("style", _lastTheme[mode]);
- return _lastTheme;
- });
- }
- function updateMode(value) {
- const context = globalThis;
- const body = document.body;
- if (!body)
- return value;
- if (!value)
- return getMode();
- if (value === "auto")
- value = isDark() ? "dark" : "light";
- body.classList.remove("light", "dark");
- body.classList.add(value);
- const lastThemeStyle = value === "light" ? _lastTheme.light : _lastTheme.dark;
- if (context.materialDynamicColors)
- body.setAttribute("style", lastThemeStyle);
- return getMode();
- }
- const _dialogs = [];
- function onKeydownDialog(e) {
- if (e.key === "Escape") {
- const dialog = e.currentTarget;
- void updateDialog(dialog, dialog);
- }
- }
- function focusOnDialogOrElement(dialog) {
- const element = query("[autofocus]", dialog) ?? dialog;
- element.focus();
- }
- function closeDialog(dialog, overlay) {
- removeClass(queryAllDataUi(dialog.id), "active");
- removeClass(dialog, "active");
- removeClass(overlay, "active");
- dialog.close();
- _dialogs.pop();
- const previousDialog = _dialogs[_dialogs.length - 1];
- if (previousDialog)
- previousDialog.focus();
- else if (isTouchable())
- document.body.classList.remove("no-scroll");
- }
- async function openDialog(dialog, overlay, isModal, from) {
- if (!hasTag(from, "button") && !hasClass(from, "button") && !hasClass(from, "chip"))
- addClass(from, "active");
- addClass(overlay, "active");
- addClass(dialog, "active");
- if (isModal)
- dialog.showModal();
- else
- dialog.show();
- await wait(90);
- if (!isModal)
- on(dialog, "keydown", onKeydownDialog, false);
- _dialogs.push(dialog);
- if (isTouchable())
- document.body.classList.add("no-scroll");
- focusOnDialogOrElement(dialog);
- }
- function onClickOverlay(e) {
- const overlay = e.currentTarget;
- const dialog = next(overlay);
- if (hasTag(dialog, "dialog"))
- closeDialog(dialog, overlay);
- }
- async function updateDialog(from, dialog) {
- blurActiveElement();
- let overlay = prev(dialog);
- const isActive = hasClass(dialog, "active") || dialog.open;
- const isModal = hasClass(dialog, "modal");
- if (!isModal)
- off(dialog, "keydown", onKeydownDialog, false);
- if (!hasClass(overlay, "overlay")) {
- overlay = create({ class: "overlay" });
- insertBefore(overlay, dialog);
- await wait(90);
- }
- if (!isModal)
- on(overlay, "click", onClickOverlay, false);
- if (isActive)
- closeDialog(dialog, overlay);
- else
- void openDialog(dialog, overlay, isModal, from);
- }
- let _timeoutMenu;
- function onClickDocument(e) {
- off(document.body, "click", onClickDocument);
- const body = e.target;
- const menus = queryAll("menu.active");
- for (let i = 0; i < menus.length; i++)
- updateMenu(body, menus[i], e);
- }
- function focusOnMenuOrInput(menu) {
- setTimeout(() => {
- const input = query(".field > input", menu);
- if (input)
- input.focus();
- else
- menu.focus();
- }, 90);
- }
- function updateMenu(from, menu, e) {
- if (_timeoutMenu)
- clearTimeout(_timeoutMenu);
- _timeoutMenu = setTimeout(() => {
- on(document.body, "click", onClickDocument);
- if (!hasTag(document.activeElement, "input"))
- blurActiveElement();
- const isActive = hasClass(menu, "active");
- const isEvent = (e == null ? void 0 : e.target) === from;
- const isChild = !!from.closest("menu");
- if (!isActive && isChild || isActive && isEvent) {
- removeClass(menu, "active");
- return;
- }
- removeClass(queryAll("menu.active"), "active");
- addClass(menu, "active");
- focusOnMenuOrInput(menu);
- }, 90);
- }
- let _timeoutSnackbar;
- function onClickSnackbar(e) {
- const snackbar = e.currentTarget;
- removeClass(snackbar, "active");
- if (_timeoutSnackbar)
- clearTimeout(_timeoutSnackbar);
- }
- function updateSnackbar(snackbar, milliseconds) {
- blurActiveElement();
- const activeSnackbars = queryAll(".snackbar.active");
- for (let i = 0; i < activeSnackbars.length; i++)
- removeClass(activeSnackbars[i], "active");
- addClass(snackbar, "active");
- on(snackbar, "click", onClickSnackbar);
- if (_timeoutSnackbar)
- clearTimeout(_timeoutSnackbar);
- if (milliseconds === -1)
- return;
- _timeoutSnackbar = setTimeout(() => {
- removeClass(snackbar, "active");
- }, milliseconds ?? 6e3);
- }
- function updatePage(page) {
- const container = parent(page);
- if (container)
- removeClass(queryAll(":scope > .page", container), "active");
- addClass(page, "active");
- }
- function onPointerDownRipple(e) {
- updateRipple(e);
- }
- function updateRipple(e) {
- const element = e.currentTarget;
- const rect = element.getBoundingClientRect();
- const diameter = Math.max(rect.width, rect.height);
- const radius = diameter / 2;
- const x = e.clientX - rect.left - radius;
- const y = e.clientY - rect.top - radius;
- const rippleContainer = document.createElement("div");
- rippleContainer.className = "ripple-js";
- const ripple = document.createElement("div");
- ripple.style.inlineSize = ripple.style.blockSize = `${diameter}px`;
- ripple.style.left = `${x}px`;
- ripple.style.top = `${y}px`;
- ripple.addEventListener("animationend", () => {
- rippleContainer.remove();
- });
- rippleContainer.appendChild(ripple);
- element.appendChild(rippleContainer);
- }
- function updateAllRipples() {
- const ripples = queryAll(".slow-ripple, .ripple, .fast-ripple");
- for (let i = 0; i < ripples.length; i++)
- on(ripples[i], "pointerdown", onPointerDownRipple);
- }
- let _timeoutMutation;
- let _mutation;
- function onMutation() {
- if (_timeoutMutation)
- clearTimeout(_timeoutMutation);
- _timeoutMutation = setTimeout(async () => await ui(), 180);
- }
- async function run(from, to, options, e) {
- if (!to) {
- to = query(from.getAttribute("data-ui"));
- if (!to)
- return;
- }
- updateAllClickable(from);
- if (hasTag(to, "dialog")) {
- await updateDialog(from, to);
- return;
- }
- if (hasTag(to, "menu")) {
- updateMenu(from, to, e);
- return;
- }
- if (hasClass(to, "snackbar")) {
- updateSnackbar(to, options);
- return;
- }
- if (hasClass(to, "page")) {
- updatePage(to);
- return;
- }
- if (hasClass(to, "active")) {
- removeClass(from, "active");
- removeClass(to, "active");
- return;
- }
- addClass(to, "active");
- }
- function onClickElement(e) {
- void run(e.currentTarget, null, null, e);
- }
- function onKeydownElement(e) {
- if (e.key === "Enter")
- void run(e.currentTarget, null, null, e);
- }
- function setup() {
- if (_mutation)
- return;
- _mutation = new MutationObserver(onMutation);
- _mutation.observe(document.body, { childList: true, subtree: true });
- onMutation();
- }
- function updateAllDataUis() {
- const elements = queryAll("[data-ui]");
- for (let i = 0, n = elements.length; i < n; i++) {
- on(elements[i], "click", onClickElement);
- if (hasTag(elements[i], "a") && !elements[i].getAttribute("href"))
- on(elements[i], "keydown", onKeydownElement);
- }
- }
- function ui(selector, options) {
- if (selector) {
- if (selector === "setup") {
- setup();
- return;
- }
- if (selector === "guid")
- return guid();
- if (selector === "mode")
- return updateMode(options);
- if (selector === "theme")
- return updateTheme(options);
- const to = query(selector);
- if (!to)
- return;
- void run(to, to, options);
- }
- updateAllDataUis();
- updateAllFields();
- updateAllSliders();
- updateAllRipples();
- }
- function start() {
- var _a;
- const context = globalThis;
- const body = (_a = context == null ? void 0 : context.document) == null ? void 0 : _a.body;
- if (body && !body.classList.contains("dark") && !body.classList.contains("light"))
- updateMode("auto");
- on(context, "load", setup, false);
- context.ui = ui;
- }
- start();
- export {
- ui as default,
- ui
- };
|