Skip to content

Commit 542a190

Browse files
committed
test bug fr mask
1 parent 5547a3f commit 542a190

5 files changed

Lines changed: 229 additions & 18 deletions

File tree

.prettierrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
"$schema": "https://json.schemastore.org/prettierrc",
33
"tabWidth": 2,
44
"useTabs": false,
5-
"printWidth": 450,
5+
"printWidth": 550,
66
"singleQuote": false,
7+
"proseWrap": "never",
78
"trailingComma": "es5",
89
"semi": true,
910
"endOfLine": "lf"

dist-types/client/europlate.client.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/assets/css/epv.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@
200200
--epv-gap: 0.375rem; /* spazio icona↔testo */
201201
--epv-icon: 14px; /* lato dell’icona semplice */
202202
--epv-pill: 18px; /* diametro della pill */
203-
--epv-textch: 12ch; /* spazio tipico per testo */
203+
--epv-textch: 12.5ch; /* spazio tipico per testo */
204204
}
205205

206206
/* Host inline */
@@ -281,7 +281,7 @@
281281
}
282282
/* to check */
283283
.epv__input-wrap {
284-
min-width: 70%;
284+
min-width: 60%;
285285
display: flex;
286286
flex: 1;
287287
}

src/assets/css/epv.theme.css

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/* === TOKENS (LIGHT di default) ===================== */
2+
:root{
3+
/* superfici & testo */
4+
--epv-bg: #ffffff;
5+
--epv-surface: #f8fafc; /* slate-50 */
6+
--epv-text: #0f172a; /* slate-900 */
7+
--epv-muted: #64748b; /* slate-500 */
8+
--epv-border: #cbd5e1; /* slate-300 */
9+
--epv-border-focus: #60a5fa; /* blue-400 */
10+
--epv-ring: rgba(59,130,246,.35); /* blue-500/35% */
11+
12+
/* input */
13+
--epv-input-bg: #ffffff;
14+
--epv-input-fg: #0f172a;
15+
--epv-input-placeholder: #94a3b8; /* slate-400 */
16+
17+
/* stato */
18+
--epv-ok: #16a34a; /* green-600 */
19+
--epv-err: #dc2626; /* red-600 */
20+
--epv-info: #3b82f6; /* blue-500 */
21+
22+
/* dropdown */
23+
--epv-dd-bg: #ffffff;
24+
--epv-dd-item: #0f172a;
25+
--epv-dd-hover: #eef2ff; /* indigo-50 */
26+
--epv-dd-border: #cbd5e1;
27+
28+
/* pulsante bandiera */
29+
--epv-flagbtn-bg: #ffffff;
30+
--epv-flagbtn-fg: #0f172a;
31+
--epv-flagbtn-border: #cbd5e1;
32+
}
33+
34+
/* === HOOK ai selettori esistenti (senza stravolgere) === */
35+
/* status inline: usa i token invece degli hex fissi */
36+
.status-inline-host{
37+
color: var(--epv-muted);
38+
}
39+
.status-inline-host[data-state="ok"]{ color: var(--epv-ok); }
40+
.status-inline-host[data-state="err"]{ color: var(--epv-err); }
41+
42+
/* block status */
43+
.status.ok{ color: var(--epv-ok); }
44+
.status.err{ color: var(--epv-err); }
45+
46+
/* input & wrapper suggeriti (se già li hai, questi sono solo override safe) */
47+
.plate-epv .plate-input{
48+
background: var(--epv-input-bg);
49+
color: var(--epv-input-fg);
50+
border: 1px solid var(--epv-border);
51+
}
52+
.plate-epv .plate-input::placeholder{ color: var(--epv-input-placeholder); }
53+
.plate-epv .plate-input:focus{
54+
outline: none;
55+
border-color: var(--epv-border-focus);
56+
box-shadow: 0 0 0 3px var(--epv-ring);
57+
}
58+
59+
/* dropdown */
60+
.plate-epv .dropdown{
61+
background: var(--epv-dd-bg);
62+
border: 1px solid var(--epv-dd-border);
63+
}
64+
.plate-epv .dropdown .country-item{
65+
color: var(--epv-dd-item);
66+
}
67+
.plate-epv .dropdown .country-item:hover{
68+
background: var(--epv-dd-hover);
69+
}
70+
71+
/* flag button */
72+
.plate-epv .flag-btn{
73+
background: var(--epv-flagbtn-bg);
74+
color: var(--epv-flagbtn-fg);
75+
border: 1px solid var(--epv-flagbtn-border);
76+
}
77+
78+
/* PANNOKKIANERA — media query */
79+
@media (prefers-color-scheme: dark){
80+
:root{
81+
--epv-bg: #0b0f19; /* quasi-black */
82+
--epv-surface: #111827; /* gray-900 */
83+
--epv-text: #e5e7eb; /* gray-200 */
84+
--epv-muted: #94a3b8; /* slate-400 */
85+
--epv-border: #334155; /* slate-700 */
86+
--epv-border-focus: #93c5fd; /* blue-300 */
87+
--epv-ring: rgba(96,165,250,.35);
88+
89+
--epv-input-bg: #0f172a; /* slate-900 */
90+
--epv-input-fg: #e5e7eb;
91+
--epv-input-placeholder: #64748b;
92+
93+
/* stati un filo più accesi in dark */
94+
--epv-ok: #22c55e; /* green-500 */
95+
--epv-err: #f87171; /* red-400 */
96+
--epv-info: #60a5fa;
97+
98+
--epv-dd-bg: #0f172a;
99+
--epv-dd-item: #e5e7eb;
100+
--epv-dd-hover: #1f2937; /* gray-800 */
101+
--epv-dd-border: #334155;
102+
103+
--epv-flagbtn-bg: #0f172a;
104+
--epv-flagbtn-fg: #e5e7eb;
105+
--epv-flagbtn-border: #334155;
106+
}
107+
108+
/* superfici globali (se vuoi) */
109+
body.test_mode{ background: var(--epv-bg); color: var(--epv-text); }
110+
}
111+
112+
/* PANNOKKIANERA — class based */
113+
.scheme_dark,
114+
html.scheme_dark,
115+
body.scheme_dark,
116+
:root[class*="scheme_dark"]{
117+
--epv-bg: #0b0f19;
118+
--epv-surface: #111827;
119+
--epv-text: #e5e7eb;
120+
--epv-muted: #94a3b8;
121+
--epv-border: #334155;
122+
--epv-border-focus: #93c5fd;
123+
--epv-ring: rgba(96,165,250,.35);
124+
125+
--epv-input-bg: #0f172a;
126+
--epv-input-fg: #e5e7eb;
127+
--epv-input-placeholder: #64748b;
128+
129+
--epv-ok: #22c55e;
130+
--epv-err: #f87171;
131+
--epv-info: #60a5fa;
132+
133+
--epv-dd-bg: #0f172a;
134+
--epv-dd-item: #e5e7eb;
135+
--epv-dd-hover: #1f2937;
136+
--epv-dd-border: #334155;
137+
138+
--epv-flagbtn-bg: #0f172a;
139+
--epv-flagbtn-fg: #e5e7eb;
140+
--epv-flagbtn-border: #334155;
141+
}
142+
143+
144+
/*
145+
* ## Note veloci
146+
* Gli **SVG in `mode-icon`/`mode-pill`** usano `currentColor`: con i token sopra cambiano automaticamente tra light/dark (non serve altro).
147+
* Se hai **background chiari** in card/container (`.plate-epv-wrapper`, `.plate-epv`) puoi fare:
148+
*
149+
* .plate-epv-wrapper{ background: var(--epv-surface); }
150+
*
151+
*/

src/client/europlate.client.ts

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,6 @@ async function ensureDeps(opts: EuroPlateOptions, log: Logger, BADGE: BadgeFn =
709709
// —————————————————————————————————————
710710
const msg = err instanceof Error ? err.message : JSON.stringify(err ?? "unknown");
711711
BADGE("EPV[Deps]", `Error during ensureDeps: ${msg}`, "err");
712-
log.error?.("ensureDeps failed:", err);
713712
} finally {
714713
// —————————————————————————————————————
715714
// Log tempo di completamento / debug telemetria
@@ -1208,7 +1207,7 @@ export function createEuroPlate(EuroMod: any, opts: EuroPlateOptions): EuroPlate
12081207
} catch {}
12091208
(el as any)._imInstance = null;
12101209
}, 0);
1211-
log.debug?.("mask:clear (hard)");
1210+
BADGE("EuroPlate", "mask:clear (hard)", "debug");
12121211
}
12131212
const hardClearMaskDebounced = debounce(hardClearMask, timings.clear);
12141213

@@ -1219,13 +1218,13 @@ export function createEuroPlate(EuroMod: any, opts: EuroPlateOptions): EuroPlate
12191218

12201219
const applyMaskDebounced = debounce((inputEl: HTMLInputElement, country: string) => {
12211220
if (!hasIMBound()) {
1222-
log.warn?.("Inputmask non disponibile: salto applyMask");
1221+
BADGE("EuroPlate", "Inputmask non disponibile: salto applyMask", "warn");
12231222
return;
12241223
}
12251224
const IM = getIMBound()! as IMGlobal; // tipo: IMGlobal
12261225

12271226
if (!IM) {
1228-
log.warn?.("AGAIN: Inputmask non disponibile: RETURN!");
1227+
BADGE("EuroPlate", "Inputmask non disponibile (again): RETURN!", "warn");
12291228
return;
12301229
}
12311230

@@ -1277,9 +1276,42 @@ export function createEuroPlate(EuroMod: any, opts: EuroPlateOptions): EuroPlate
12771276

12781277
instance.mask(inputEl);
12791278
(inputEl as any)._imInstance = instance;
1280-
log.debug?.("mask:apply", country, optsIM.mask);
1279+
BADGE("EuroPlate", JSON.stringify({ logMsg: "mask:apply", country, mask: optsIM.mask }, null, 2), "debug");
12811280
}, timings.debounce);
12821281

1282+
function clearStatusUI(input: HTMLInputElement, status?: HTMLElement, wrap?: HTMLElement | null) {
1283+
// input & wrapper: rimuovi classi stato
1284+
input.classList.remove("valid", "invalid");
1285+
if (wrap) wrap.classList.remove("valid", "invalid");
1286+
input.setAttribute("aria-invalid", "false");
1287+
input.setCustomValidity("");
1288+
1289+
if (!status) return;
1290+
1291+
// inline: togli proprio data-state → niente padding via :has()
1292+
// // ✨ chiave: sparisce lo stato → niente :has([data-state]) nel CSS
1293+
status.removeAttribute("data-state");
1294+
1295+
// pulisci icona/testo se presenti
1296+
const iconEl = status.querySelector(".s-icon") as HTMLElement | null;
1297+
const textEl = status.querySelector(".s-text") as HTMLElement | null;
1298+
// reset eventuale .pill ok/err
1299+
if (iconEl) {
1300+
iconEl.className = "s-icon";
1301+
iconEl.textContent = "";
1302+
}
1303+
if (textEl) {
1304+
textEl.textContent = "";
1305+
textEl.style.display = "none";
1306+
}
1307+
1308+
// block mode: neutro
1309+
if (status.classList.contains("status")) {
1310+
status.className = "status";
1311+
status.textContent = "";
1312+
}
1313+
}
1314+
12831315
// setValidityUI
12841316
function setValidityUI(ok: boolean | null, msg: string, matchCountry: CountryKey | null, input: HTMLInputElement, status: HTMLElement | undefined, lang: Lang, wrap?: HTMLElement | null) {
12851317
// INPUT: classi + aria
@@ -1424,7 +1456,7 @@ export function createEuroPlate(EuroMod: any, opts: EuroPlateOptions): EuroPlate
14241456
//setValidityUI(true as any, "", null, input, statusEl, lang, wrapperEl);
14251457
//input.classList.remove("valid", "invalid");
14261458
//wrapperEl?.classList.remove("valid", "invalid");
1427-
setValidityUI(null, "", null, input, statusEl, lang, wrapperEl); // 👈 idle
1459+
clearStatusUI(input, statusEl, wrapperEl); // 👈 niente stato
14281460
if (selected === "AUTO") {
14291461
hardClearMaskDebounced(input);
14301462
input.placeholder = placeholders.auto || "";
@@ -1445,7 +1477,7 @@ export function createEuroPlate(EuroMod: any, opts: EuroPlateOptions): EuroPlate
14451477
if (v2 !== raw) input.value = raw = v2;
14461478
}
14471479
// non validiamo finche nn c e un risultato minimo
1448-
if(raw.trim()?.length <= 2) return { ok: false, value: raw };
1480+
if (raw.trim()?.length <= 2) return { ok: false, value: raw };
14491481

14501482
const countries = selected === "AUTO" ? allowed : [selected];
14511483
const res = validatePlate(raw, countries, { vehicleType });
@@ -1527,22 +1559,49 @@ export function createEuroPlate(EuroMod: any, opts: EuroPlateOptions): EuroPlate
15271559
let next: "AUTO" | CountryKey = "AUTO";
15281560
if (code !== "AUTO") {
15291561
const n = normalize(String(code || ""));
1530-
if (isCountryKey(n)) next = n;
1531-
else next = "AUTO";
1562+
next = isCountryKey(n) ? (n as CountryKey) : "AUTO";
15321563
}
1564+
1565+
// salva il precedente per sicurezza (se ti serve altrove)
1566+
const prev = selected;
15331567
selected = next;
15341568

1569+
// flag + placeholder
1570+
setFlag(selected, flagIcon, flagLabel, lang);
1571+
updatePlaceholderForCurrentSelection(selected, input, EuroMod, lang);
15351572
// flag + placeholder
15361573
setFlag(selected, flagIcon, flagLabel, lang);
15371574
updatePlaceholderForCurrentSelection(selected, input, EuroMod, lang);
15381575

1539-
// mask
1576+
// ⚠️ IMPORTANTISSIMO: rimuovi SUBITO la vecchia mask (no debounce)
1577+
hardClearMask(input); // usa la versione NON debounced
1578+
1579+
const hasText = !!input.value.trim();
1580+
const short = hasText && input.value.trim().length <= 2;
1581+
15401582
if (selected === "AUTO") {
1541-
hardClearMaskDebounced(input);
1583+
// AUTO: niente mask
1584+
if (!hasText) {
1585+
clearStatusUI(input, statusEl, wrapperEl); // stato neutro
1586+
} else {
1587+
// opzionale: riallinea subito contro allowed
1588+
validateNow();
1589+
}
15421590
} else {
1543-
const v = fmtFor(selected, input.value);
1544-
if (input.value !== v) input.value = v;
1591+
// NON-AUTO: applica la NUOVA mask SEMPRE (anche a campo vuoto)
1592+
if (hasText) {
1593+
const v = fmtFor(selected, input.value);
1594+
if (input.value !== v) input.value = v;
1595+
}
15451596
applyMaskDebounced(input, selected);
1597+
1598+
// stato neutro se vuoto o corto
1599+
if (!hasText || short) {
1600+
clearStatusUI(input, statusEl, wrapperEl);
1601+
} else {
1602+
// se vuoi allineare subito (facoltativo)
1603+
validateNow();
1604+
}
15461605
}
15471606

15481607
// chiudi dropdown
@@ -1608,7 +1667,7 @@ export function createEuroPlate(EuroMod: any, opts: EuroPlateOptions): EuroPlate
16081667
renderDropdown();
16091668
selectCountry(mode, !!autoFocusOnInit); // 👈 niente autofocus all’avvio // ok: la funzione normalizza e imposta selected ("AUTO" | CountryKey)
16101669

1611-
log.notify?.("EuroPlate pronto ✅", "success");
1670+
BADGE("EuroPlate", "Pronto ✅", "ok");
16121671

16131672
return instance;
16141673
}

0 commit comments

Comments
 (0)