Polish UI and billing flows: route fallback, searchable selectors, light-mode fixes

This commit is contained in:
Dwindi Ramadhana
2026-02-15 19:18:17 +07:00
parent a7a854886d
commit e6aef31dd1
8 changed files with 430 additions and 148 deletions

View File

@@ -279,6 +279,14 @@
h2 { font-size: var(--fs-l); font-weight: var(--fw-semibold); line-height: 1.25; }
h3 { font-size: var(--fs-m); font-weight: var(--fw-semibold); line-height: 1.3; }
html.theme-light .text-white:not(.force-white) { color: var(--app-fg) !important; }
html.theme-light button.text-white,
html.theme-light a.text-white,
html.theme-light [role="button"].text-white,
html.theme-light button .text-white,
html.theme-light a .text-white,
html.theme-light [role="button"] .text-white {
color: #ffffff !important;
}
html.theme-light .text-gray-200 { color: #334155 !important; }
html.theme-light .text-gray-300 { color: #475569 !important; }
html.theme-light .text-gray-400 { color: var(--muted-text) !important; }
@@ -606,67 +614,74 @@
</script>
<script>
(() => {
const normalizeCode = (raw) => {
const input = String(raw || '').trim().replace('_', '-');
if (!input) return null;
const parts = input.split('-');
if (parts.length === 1) {
const code = parts[0].toLowerCase();
return /^[a-z]{2,3}$/.test(code) ? code : null;
}
const base = parts[0].toLowerCase();
const region = parts[1].toUpperCase();
const code = `${base}-${region}`;
return /^[a-z]{2,3}-[A-Z]{2}$/.test(code) ? code : null;
const alpha = 'abcdefghijklmnopqrstuvwxyz';
const deprecatedAliases = {
in: 'id',
iw: 'he',
ji: 'yi',
jw: 'jv',
};
window.dewemojiPopulateLanguageOptions = (target) => {
const list = typeof target === 'string' ? document.getElementById(target) : target;
if (!list || list.dataset.generated === '1') return;
const makeIso6391Codes = () => {
const codes = [];
for (let i = 0; i < alpha.length; i += 1) {
for (let j = 0; j < alpha.length; j += 1) {
codes.push(alpha[i] + alpha[j]);
}
}
return codes;
};
const codeToName = new Map();
list.querySelectorAll('option[data-code]').forEach((option) => {
const code = normalizeCode(option.dataset.code);
if (!code) return;
const fallbackName = String(option.value || '').replace(/\s+\([^)]+\)\s*$/, '').trim() || code;
codeToName.set(code, fallbackName);
});
const canonicalLanguageCode = (raw) => {
const code = String(raw || '').trim().toLowerCase();
if (!code) return '';
return deprecatedAliases[code] || code;
};
if (!codeToName.has('und')) codeToName.set('und', 'Undetermined');
window.dewemojiCanonicalLanguageCode = canonicalLanguageCode;
if (typeof Intl !== 'undefined' && typeof Intl.supportedValuesOf === 'function') {
const display = typeof Intl.DisplayNames === 'function'
? new Intl.DisplayNames(['en'], { type: 'language' })
: null;
window.dewemojiPopulateLanguageSelect = (target) => {
const select = typeof target === 'string' ? document.getElementById(target) : target;
if (!(select instanceof HTMLSelectElement) || select.dataset.generated === '1') return;
Intl.supportedValuesOf('language').forEach((rawCode) => {
const code = normalizeCode(rawCode);
if (!code) return;
const name = display?.of(code) || display?.of(code.split('-')[0]) || code;
codeToName.set(code, name);
const existing = Array.from(select.options).map((opt) => ({
code: canonicalLanguageCode(opt.value),
label: (opt.textContent || '').trim(),
})).filter((row) => row.code !== '');
const byCode = new Map(existing.map((row) => [row.code.toLowerCase(), row]));
if (typeof Intl !== 'undefined' && typeof Intl.DisplayNames === 'function') {
const dn = new Intl.DisplayNames(['en'], { type: 'language' });
makeIso6391Codes().forEach((code) => {
const name = dn.of(code);
if (!name) return;
// Unknown/unsupported codes are echoed back by many engines.
if (name.toLowerCase() === code) return;
const canonical = canonicalLanguageCode(code);
if (!canonical) return;
byCode.set(canonical, { code: canonical, label: `${name} (${canonical})` });
});
}
const entries = Array.from(codeToName.entries()).sort((a, b) => {
if (a[0] === 'und') return -1;
if (b[0] === 'und') return 1;
return a[1].localeCompare(b[1]);
const rows = Array.from(byCode.values()).sort((a, b) => {
if (a.code === 'und') return -1;
if (b.code === 'und') return 1;
return a.label.localeCompare(b.label);
});
list.innerHTML = '';
entries.forEach(([code, name]) => {
const previous = (select.value || '').trim().toLowerCase();
select.innerHTML = '';
rows.forEach((row) => {
const option = document.createElement('option');
option.value = `${name} (${code})`;
option.dataset.code = code;
list.appendChild(option);
option.value = row.code;
option.textContent = row.label;
select.appendChild(option);
});
list.dataset.generated = '1';
select.value = previous || select.value;
select.dataset.generated = '1';
};
document.querySelectorAll('datalist[data-language-options="1"]').forEach((list) => {
window.dewemojiPopulateLanguageOptions(list);
});
})();
</script>
@stack('scripts')