import { icons } from './icons'; import { knopf, meldung } from './util'; import { ordner, type Ordnerstand } from './api'; import { auswahl, type Auswahlfeld } from './auswahl'; /* Dialoge über dem Inhalt statt Blöcken darin. * * **Mit dem `` des Browsers, nicht mit einem nachgebauten.** Der * kann, was ein `
` erst lernen müsste: Escape schliesst, der * Hintergrund wird unbedienbar, der Tastaturfokus bleibt gefangen, und * Vorlesesoftware kündigt ihn als Dialog an. Jede Zeile, die das selbst * baut, ist eine Zeile, die es schlechter kann. */ export type Feldart = 'text' | 'password' | 'number' | 'ordner' | 'zeitpunkt' | 'mehrzeilig'; export type Dialogfeld = { name: string; beschriftung: string; art?: Feldart; wert?: string; platzhalter?: string; hinweis?: string; /** Eine Auswahl statt eines Feldes. */ auswahl?: { wert: string; text: string }[]; /** Ein Schalter statt eines Feldes. */ schalter?: boolean; /** Frühester erlaubter Zeitpunkt — nur bei `art: 'zeitpunkt'`. */ min?: string; /** Wie hoch es aufmacht — nur bei `art: 'mehrzeilig'`. */ zeilen?: number; }; /** Liest einen Feldwert — nie `undefined`, ein unbekannter Name ergibt „". * * Als Funktion statt als Objekt: ein Tippfehler im Feldnamen gäbe sonst * stillschweigend `undefined` zurück und landete so im Server. */ export type Dialogwerte = (name: string) => string; /** Zeigt einen Dialog mit Feldern und gibt zurück, was eingetippt wurde. * * `null` heisst abgebrochen — nicht „leer". Die beiden zu verwechseln hiesse, * ein Abbrechen wie ein Speichern zu behandeln. */ export function dialog(optionen: { titel: string; text?: string; felder?: Dialogfeld[]; bestaetigen: string; /** Färbt den Knopf rot — für alles, was etwas wegnimmt. */ gefaehrlich?: boolean; /** Wird mit den Werten gerufen; wirft sie, bleibt der Dialog offen. */ tun: (wert: Dialogwerte) => Promise; /** Ein dritter Knopf links, für den Weg zurück — etwa „Wieder automatisch". */ weiterer?: { text: string; tun: () => Promise }; }): void { const d = document.createElement('dialog'); d.className = 'dlg'; const kopf = document.createElement('div'); kopf.className = 'dlg-kopf'; const h = document.createElement('h2'); h.textContent = optionen.titel; const zu = document.createElement('button'); zu.className = 'dlg-zu'; zu.innerHTML = icons.schliessen; zu.setAttribute('aria-label', 'Schliessen'); zu.onclick = () => d.close(); kopf.append(h, zu); const koerper = document.createElement('div'); koerper.className = 'dlg-koerper'; if (optionen.text) { const p = document.createElement('p'); p.className = 'hinweis'; p.textContent = optionen.text; koerper.appendChild(p); } const eingaben = new Map(); (optionen.felder ?? []).forEach(f => { // **Ein `