Repo Interface für tests

This commit is contained in:
2026-03-05 08:26:51 +01:00
parent 8f4dd5840d
commit 4b31fc7664
171 changed files with 3518 additions and 2297 deletions

View File

@@ -1,28 +0,0 @@
import { optionalEl, warnOnce } from '../core/app-dom.js';
export function initTemplateFeature(root = document) {
const host = optionalEl('[data-template-feature]');
if (!host) {
return;
}
if (host.dataset.templateFeatureBound === '1') {
return;
}
host.dataset.templateFeatureBound = '1';
const action = host.querySelector('[data-template-action]');
if (!action) {
warnOnce('UI_EL_MISSING', 'Missing [data-template-action]', { module: 'template-feature' });
return;
}
action.addEventListener('click', () => {
host.classList.toggle('is-active');
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => initTemplateFeature());
} else {
initTemplateFeature();
}

View File

@@ -1,73 +0,0 @@
import { warnOnce } from '../core/app-dom.js';
const getEmptyValues = (field) => {
const own = field?.dataset?.filterEmpty || '';
const parent = field?.closest?.('[data-filter-empty]')?.dataset?.filterEmpty || '';
return [own, parent]
.filter(Boolean)
.join(',')
.split(',')
.map((value) => value.trim())
.filter(Boolean);
};
const isFieldActive = (field) => {
if (!field) {return false;}
if (field.disabled) {return false;}
if (field.type === 'hidden') {return false;}
if (field.type === 'checkbox') {return field.checked;}
if (field.tagName === 'SELECT' && field.multiple) {
return Array.from(field.selectedOptions || []).some((option) => option.value);
}
if (field.tagName === 'SELECT') {
const value = String(field.value || '').trim();
const empty = new Set(['', 'all', ...getEmptyValues(field)]);
return value !== '' && !empty.has(value);
}
return String(field.value || '').trim() !== '';
};
const isOptionalActive = (item) => {
const fields = item.matches('input, select, textarea')
? [item]
: Array.from(item.querySelectorAll('input, select, textarea'));
return fields.some(isFieldActive);
};
export function initFilterOverflow(root = document) {
const toolbars = root.querySelectorAll('[data-filter-overflow]');
toolbars.forEach((toolbar) => {
if (toolbar.dataset.filterOverflowBound === '1') {return;}
toolbar.dataset.filterOverflowBound = '1';
const optional = Array.from(toolbar.querySelectorAll('[data-filter-optional]'));
if (!optional.length) {return;}
const toggle = toolbar.querySelector('[data-filter-toggle]');
if (!toggle) {
warnOnce('UI_EL_MISSING', 'Missing filter overflow toggle', { module: 'filter-overflow' });
return;
}
const setExpanded = (expanded) => {
optional.forEach((item) => {
item.hidden = !expanded;
});
toggle.setAttribute('aria-expanded', expanded ? 'true' : 'false');
};
const hasActiveOptional = optional.some(isOptionalActive);
setExpanded(hasActiveOptional);
toggle.addEventListener('click', () => {
const expanded = toggle.getAttribute('aria-expanded') === 'true';
setExpanded(!expanded);
});
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => initFilterOverflow());
} else {
initFilterOverflow();
}

View File

@@ -1,92 +0,0 @@
export function initToolbarToggles(root = document) {
const toggles = root.querySelectorAll('[data-toolbar-toggle]');
toggles.forEach((toggle) => {
if (toggle.dataset.toolbarBound === '1') {
return;
}
toggle.dataset.toolbarBound = '1';
if (!toggle.hasAttribute('type')) {
toggle.setAttribute('type', 'button');
}
const targetSelector = toggle.dataset.toolbarTarget || toggle.getAttribute('aria-controls');
if (!targetSelector) {
return;
}
const targets = Array.from(root.querySelectorAll(targetSelector)).filter(Boolean);
if (!targets.length) {
return;
}
const labelTarget = toggle.querySelector('[data-toolbar-label]');
const showLabel = toggle.dataset.toolbarTextShow;
const hideLabel = toggle.dataset.toolbarTextHide;
const storageKey =
toggle.dataset.toolbarStorageKey ||
(targets.length === 1 && targets[0].id
? `toolbar:${targets[0].id}`
: `toolbar:${targetSelector}`);
if (!toggle.getAttribute('aria-controls') && targets.length === 1 && targets[0].id) {
toggle.setAttribute('aria-controls', targets[0].id);
}
targets.forEach((target) => {
if (target.dataset.toolbarInitialized === '1') {
return;
}
const initial = target.dataset.toolbarInitial;
if (initial === 'hidden') {
target.hidden = true;
} else if (initial === 'shown') {
target.hidden = false;
}
target.dataset.toolbarInitialized = '1';
});
if (storageKey) {
try {
const stored = localStorage.getItem(storageKey);
if (stored === 'hidden' || stored === 'shown') {
const shouldShow = stored === 'shown';
targets.forEach((target) => {
target.hidden = !shouldShow;
});
}
} catch (error) {
// localStorage not available
}
}
const getExpanded = () => targets.every((target) => !target.hidden);
const setExpanded = (expanded) => {
targets.forEach((target) => {
target.hidden = !expanded;
});
toggle.setAttribute('aria-expanded', expanded ? 'true' : 'false');
if (labelTarget && (showLabel || hideLabel)) {
labelTarget.textContent = expanded ? (hideLabel || labelTarget.textContent) : (showLabel || labelTarget.textContent);
}
if (storageKey) {
try {
localStorage.setItem(storageKey, expanded ? 'shown' : 'hidden');
} catch (error) {
// localStorage not available
}
}
};
setExpanded(getExpanded());
toggle.addEventListener('click', () => {
setExpanded(!getExpanded());
});
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => initToolbarToggles());
} else {
initToolbarToggles();
}