/* Dialog kit + toast, shared (BL-024, 2026-08-20). * * The T7.9 kit, extracted for the pages the S1 tasks never named: the launcher * (index.html), the admin console and the user console carried 21 native * dialogs between them. Same contract as the creator's copy: * * wpConfirmDialog({title, message, okLabel, cancelLabel}) -> Promise * wpPromptDialog({title, message, label, value, validate}) -> Promise * wpAlertDialog({title, message, okLabel}) -> Promise (value not meaningful) * toast(msg, kind) kind 'alert' interrupts (role=alert); default role=status * * Self-contained on purpose: markup and styles are injected on first use, the * styles are theme tokens only (the token rule), and the class names are its * own (wp-dlg-*) so the consoles' existing .modal styles are never touched. * The creator keeps its inline copy - it owns the same-id markup in its HTML - * so everything here is guarded: if the page already has the kit, this file * defines nothing. */ (function (global) { 'use strict'; if (typeof global.wpConfirmDialog === 'function') return; // the creator's copy wins var CSS = '#wp-dlg-overlay{position:fixed;inset:0;background:var(--wp-scrim-cool-strong);' + 'display:none;align-items:center;justify-content:center;z-index:10500;padding:20px;}' + '#wp-dlg-overlay.open{display:flex;}' + '.wp-dlg{background:var(--cds-layer);color:var(--cds-text-primary);max-width:480px;width:100%;' + 'border-radius:8px;box-shadow:0 12px 40px rgba(20,30,50,.3);overflow:hidden;' + 'font-family:ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;font-size:14px;}' + '.wp-dlg-head{display:flex;align-items:center;justify-content:space-between;padding:14px 18px;' + 'border-bottom:1px solid var(--cds-border-subtle);font-weight:700;}' + '.wp-dlg-x{background:none;border:none;font-size:18px;line-height:1;cursor:pointer;' + 'color:var(--cds-text-secondary);padding:4px 6px;}' + '.wp-dlg-x:focus-visible{outline:2px solid var(--cds-focus);outline-offset:1px;}' + '.wp-dlg-body{padding:16px 18px;}' + '#wp-dlg-msg{white-space:pre-wrap;line-height:1.5;}' + '#wp-dlg-input-wrap{margin-top:10px;}' + '#wp-dlg-input-wrap label{display:block;font-size:12px;margin-bottom:4px;color:var(--cds-text-secondary);}' + '#wp-dlg-input{width:100%;box-sizing:border-box;padding:8px 10px;font:inherit;' + 'border:1px solid var(--cds-border-strong);border-radius:4px;background:var(--cds-field);}' + '#wp-dlg-input:focus{outline:2px solid var(--cds-focus);outline-offset:-1px;}' + '#wp-dlg-err{color:var(--cds-text-error);font-size:12px;font-weight:600;margin-top:4px;}' + '#wp-dlg-err:empty{display:none;}' + '.wp-dlg-foot{display:flex;justify-content:flex-end;gap:10px;padding:12px 18px;' + 'border-top:1px solid var(--cds-border-subtle);}' + '.wp-dlg-btn{font:inherit;font-weight:600;padding:8px 16px;border-radius:6px;cursor:pointer;' + 'border:1px solid var(--cds-border-strong);background:var(--cds-layer);color:var(--cds-text-primary);}' + '.wp-dlg-btn.primary{background:var(--cds-interactive-01);border-color:var(--cds-interactive-01);' + 'color:var(--cds-text-on-color);}' + '.wp-dlg-btn:focus-visible{outline:2px solid var(--cds-focus);outline-offset:1px;}' + '@media(pointer:coarse){.wp-dlg-btn{min-height:44px;}.wp-dlg-x{min-width:44px;min-height:44px;}}' + '#toast{position:fixed;bottom:26px;left:50%;transform:translateX(-50%) translateY(20px);' + 'background:var(--cds-background-inverse);color:var(--cds-text-inverse);padding:9px 16px;' + 'border-radius:6px;font-size:13px;opacity:0;transition:opacity .18s,transform .18s;' + 'pointer-events:none;z-index:10600;max-width:min(480px,calc(100vw - 32px));}' + '#toast.show{opacity:1;transform:translateX(-50%) translateY(0);}'; function ensure() { var ov = document.getElementById('wp-dlg-overlay'); if (ov) return ov; var st = document.createElement('style'); st.textContent = CSS; document.head.appendChild(st); ov = document.createElement('div'); ov.id = 'wp-dlg-overlay'; ov.setAttribute('role', 'dialog'); ov.setAttribute('aria-modal', 'true'); ov.setAttribute('aria-labelledby', 'wp-dlg-title'); ov.innerHTML = '
' + '
' + '
' + '
' + '
' + '
' + '' + '' + '' + '
' + '
' + '
' + '' + '' + '
' + '
'; document.body.appendChild(ov); document.getElementById('wp-dlg-x').addEventListener('click', cancel); document.getElementById('wp-dlg-cancel').addEventListener('click', cancel); document.getElementById('wp-dlg-ok').addEventListener('click', ok); document.getElementById('wp-dlg-input').addEventListener('keydown', function (e) { if (e.key === 'Enter') ok(); }); document.addEventListener('keydown', function (e) { if (e.key === 'Escape' && ov.classList.contains('open')) cancel(); }); return ov; } var resolveFn = null; function open(opts) { return new Promise(function (res) { resolveFn = res; var ov = ensure(); ov._opts = opts || {}; document.getElementById('wp-dlg-title').textContent = opts.title || 'Confirm'; document.getElementById('wp-dlg-msg').textContent = opts.message || ''; document.getElementById('wp-dlg-input-wrap').style.display = opts.input ? '' : 'none'; document.getElementById('wp-dlg-label').textContent = opts.label || ''; var inp = document.getElementById('wp-dlg-input'); inp.value = (opts.value != null ? String(opts.value) : ''); document.getElementById('wp-dlg-err').textContent = ''; document.getElementById('wp-dlg-ok').textContent = opts.okLabel || 'OK'; var cb = document.getElementById('wp-dlg-cancel'); cb.textContent = opts.cancelLabel || 'Cancel'; cb.style.display = opts.okOnly ? 'none' : ''; ov.classList.add('open'); setTimeout(function () { (opts.input ? inp : document.getElementById('wp-dlg-ok')).focus(); }, 0); }); } function close(val) { var ov = document.getElementById('wp-dlg-overlay'); if (ov) ov.classList.remove('open'); var r = resolveFn; resolveFn = null; if (r) r(val); } function ok() { var ov = document.getElementById('wp-dlg-overlay'); var opts = (ov && ov._opts) || {}; if (opts.input) { var v = document.getElementById('wp-dlg-input').value; if (opts.validate) { var err = opts.validate(v); if (err) { document.getElementById('wp-dlg-err').textContent = err; document.getElementById('wp-dlg-input').focus(); return; } } close(v); } else close(true); } function cancel() { var ov = document.getElementById('wp-dlg-overlay'); var opts = (ov && ov._opts) || {}; close(opts.input ? null : false); } global.wpConfirmDialog = function (opts) { return open(Object.assign({}, opts, { input: false })); }; global.wpPromptDialog = function (opts) { return open(Object.assign({}, opts, { input: true })); }; global.wpAlertDialog = function (opts) { return open(Object.assign({}, opts, { input: false, okOnly: true })); }; if (typeof global.toast !== 'function') { // S10's rule, same as the creator: role BEFORE text, 'alert' interrupts. global.toast = function (msg, kind) { ensure(); var t = document.getElementById('toast'); if (!t) { t = document.createElement('div'); t.id = 'toast'; document.body.appendChild(t); } t.setAttribute('role', kind === 'alert' ? 'alert' : 'status'); t.textContent = msg; t.classList.add('show'); clearTimeout(global.toast._t); global.toast._t = setTimeout(function () { t.classList.remove('show'); }, 2200); }; } })(window);