tmf-viewer: host [hidden] nascosto, wizard usa viewer-error al posto della sonda, test_dxf_preview senza zoom del wizard (Refs #122)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019A9CSrh9rfM5WwqKtg8BSE
This commit is contained in:
@@ -47,6 +47,8 @@
|
|||||||
'tmf-viewer{display:block;position:relative;overflow:hidden;background:#1f2937;min-width:0}',
|
'tmf-viewer{display:block;position:relative;overflow:hidden;background:#1f2937;min-width:0}',
|
||||||
'tmf-viewer *{box-sizing:border-box}',
|
'tmf-viewer *{box-sizing:border-box}',
|
||||||
'tmf-viewer [hidden]{display:none!important}',
|
'tmf-viewer [hidden]{display:none!important}',
|
||||||
|
// #122: anche l'host con l'attributo hidden si nasconde (display:block sopra vincerebbe sul [hidden] del browser)
|
||||||
|
'tmf-viewer[hidden]{display:none!important}',
|
||||||
'tmf-viewer .tmfv-vp{position:absolute;top:0;right:0;bottom:0;left:0;overflow:auto;display:flex}',
|
'tmf-viewer .tmfv-vp{position:absolute;top:0;right:0;bottom:0;left:0;overflow:auto;display:flex}',
|
||||||
'tmf-viewer[fit-height] .tmfv-vp{position:relative;width:100%}',
|
'tmf-viewer[fit-height] .tmfv-vp{position:relative;width:100%}',
|
||||||
'tmf-viewer .tmfv-stage{position:relative;flex:none;margin:auto;user-select:none;-webkit-user-select:none}',
|
'tmf-viewer .tmfv-stage{position:relative;flex:none;margin:auto;user-select:none;-webkit-user-select:none}',
|
||||||
|
|||||||
@@ -732,14 +732,13 @@
|
|||||||
<!-- #102: anteprima dell'immagine -->
|
<!-- #102: anteprima dell'immagine -->
|
||||||
{# #122: <tmf-viewer> standard (zoom, Adatta, Salva, pan) al posto della barra e del viewport scritti a mano (#113); altezza fissa 240px #}
|
{# #122: <tmf-viewer> standard (zoom, Adatta, Salva, pan) al posto della barra e del viewport scritti a mano (#113); altezza fissa 240px #}
|
||||||
<div x-show="!imageBroken">{# #122: x-show sul contenitore, mai sul <tmf-viewer> #}
|
<div x-show="!imageBroken">{# #122: x-show sul contenitore, mai sul <tmf-viewer> #}
|
||||||
|
{# #122: formato non mostrabile -> viewer-error del componente -> avviso imageBroken (al posto della sonda <img hidden>) #}
|
||||||
<tmf-viewer :src="imagePreviewUrl" save-name="immagine"
|
<tmf-viewer :src="imagePreviewUrl" save-name="immagine"
|
||||||
label-fit="{{ _('Adatta') }}" label-save="{{ _('Salva') }}"
|
label-fit="{{ _('Adatta') }}" label-save="{{ _('Salva') }}"
|
||||||
title-in="{{ _('Ingrandisci') }}" title-out="{{ _('Riduci') }}" title-save="{{ _('Salva immagine') }}"
|
title-in="{{ _('Ingrandisci') }}" title-out="{{ _('Riduci') }}" title-save="{{ _('Salva immagine') }}"
|
||||||
@viewer-load="onImagePreviewLoad($event.detail)"
|
@viewer-load="onImagePreviewLoad($event.detail)" @viewer-error="onImagePreviewError()"
|
||||||
class="rounded border border-[var(--border-color)]"
|
class="rounded border border-[var(--border-color)]"
|
||||||
style="height: 240px; background: var(--bg-primary);"></tmf-viewer>
|
style="height: 240px; background: var(--bg-primary);"></tmf-viewer>
|
||||||
{# #122: sonda nascosta: il componente non propaga l'errore di caricamento, la sonda si'; se il formato non e' mostrabile compare l'avviso #}
|
|
||||||
<img :src="imagePreviewUrl" alt="" hidden @error="onImagePreviewError()">
|
|
||||||
</div>
|
</div>
|
||||||
<p x-show="imageBroken" class="text-xs text-amber-600">{{ _('Anteprima non disponibile per questo formato') }}</p>
|
<p x-show="imageBroken" class="text-xs text-amber-600">{{ _('Anteprima non disponibile per questo formato') }}</p>
|
||||||
<p x-show="imagePreviewSummary" class="mt-1 text-xs text-[var(--text-muted)]" x-text="imagePreviewSummary"></p>
|
<p x-show="imagePreviewSummary" class="mt-1 text-xs text-[var(--text-muted)]" x-text="imagePreviewSummary"></p>
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ const PREVIEW = {
|
|||||||
global.URL.revokeObjectURL = () => {};
|
global.URL.revokeObjectURL = () => {};
|
||||||
wi._setImage({ name: 'a.bmp' }, 'file'); // #104: la scala a mano vale solo per file
|
wi._setImage({ name: 'a.bmp' }, 'file'); // #104: la scala a mano vale solo per file
|
||||||
check('#102 _setImage imposta URL e nome', wi.imagePreviewUrl === 'blob:x' && wi.imageName === 'a.bmp');
|
check('#102 _setImage imposta URL e nome', wi.imagePreviewUrl === 'blob:x' && wi.imageName === 'a.bmp');
|
||||||
wi.onImagePreviewLoad({ naturalWidth: 2000, naturalHeight: 1000 });
|
wi.onImagePreviewLoad({ width: 2000, height: 1000 }); // #122: detail di viewer-load
|
||||||
check('#102 senza scala: solo pixel', /2[. ]?000 × 1[. ]?000 px$/.test(wi.imagePreviewSummary), wi.imagePreviewSummary);
|
check('#102 senza scala: solo pixel', /2[. ]?000 × 1[. ]?000 px$/.test(wi.imagePreviewSummary), wi.imagePreviewSummary);
|
||||||
wi.mmPx = '0,01';
|
wi.mmPx = '0,01';
|
||||||
check('#102 con mm/px a mano: campo in mm', /px · campo ≈ 20,00 × 10,00 mm$/.test(wi.imagePreviewSummary), wi.imagePreviewSummary);
|
check('#102 con mm/px a mano: campo in mm', /px · campo ≈ 20,00 × 10,00 mm$/.test(wi.imagePreviewSummary), wi.imagePreviewSummary);
|
||||||
@@ -142,30 +142,9 @@ const PREVIEW = {
|
|||||||
w4.tested = true; w4.stationId = ''; await w4.onStation();
|
w4.tested = true; w4.stationId = ''; await w4.onStation();
|
||||||
check('#104 tested falso dopo onStation', w4.tested === false);
|
check('#104 tested falso dopo onStation', w4.tested === false);
|
||||||
|
|
||||||
// #104: zoomBy rispetta i limiti 0.05..8
|
// #122: zoom, Adatta e pan della Prova stanno in <tmf-viewer> (tests/js/test_image_viewer.js), non piu' nel wizard
|
||||||
const w5 = dxfRecipeWizard(1, () => 'tok', {});
|
const w5 = dxfRecipeWizard(1, () => 'tok', {});
|
||||||
w5.$nextTick = f => f();
|
check('#122 zoom e Adatta tolti dal wizard', ['zoomBy', 'fit', 'onPanDown', 'onPanMove', 'onPanEnd'].every(k => typeof w5[k] !== 'function'));
|
||||||
w5.$refs = {};
|
|
||||||
for (let i = 0; i < 40; i++) w5.zoomBy(1.25);
|
|
||||||
check('#104 zoom massimo 8', w5.zoom === 8, String(w5.zoom));
|
|
||||||
for (let i = 0; i < 80; i++) w5.zoomBy(1 / 1.25);
|
|
||||||
check('#104 zoom minimo 0.05', w5.zoom === 0.05, String(w5.zoom));
|
|
||||||
w5.zoom = 1;
|
|
||||||
const vp = { scrollLeft: 100, scrollTop: 50, clientWidth: 200, clientHeight: 100 };
|
|
||||||
w5.$refs = { viewport: vp };
|
|
||||||
w5.zoomBy(2);
|
|
||||||
check('#104 zoomBy tiene il centro', w5.zoom === 2 && vp.scrollLeft === 300 && vp.scrollTop === 150, vp.scrollLeft + ',' + vp.scrollTop);
|
|
||||||
check('#104 zoomPct', w5.zoomPct === '200 %');
|
|
||||||
|
|
||||||
// #104: fit = min(viewport/immagine)
|
|
||||||
w5.$refs = { viewport: { clientWidth: 500, clientHeight: 400, scrollLeft: 9, scrollTop: 9 }, img: { naturalWidth: 2000, naturalHeight: 1000 } };
|
|
||||||
w5.fit();
|
|
||||||
check('#104 fit limitato dalla larghezza', Math.abs(w5.zoom - 0.25) < 1e-9, String(w5.zoom));
|
|
||||||
w5.$refs.img = { naturalWidth: 1000, naturalHeight: 2000 };
|
|
||||||
w5.fit();
|
|
||||||
check('#104 fit limitato dall altezza massima (520 senza window)', Math.abs(w5.zoom - 0.26) < 1e-9, String(w5.zoom));
|
|
||||||
w5.$refs.viewport.clientWidth = 0; w5.zoom = 1; w5.fit();
|
|
||||||
check('#104 fit con viewport nascosto non cambia', w5.zoom === 1);
|
|
||||||
|
|
||||||
// #105: ricetta esistente -> wizard compilato
|
// #105: ricetta esistente -> wizard compilato
|
||||||
global.File = class { constructor(parts, name, opts) { this.parts = parts; this.name = name; this.type = (opts && opts.type) || ''; } };
|
global.File = class { constructor(parts, name, opts) { this.parts = parts; this.name = name; this.type = (opts && opts.type) || ''; } };
|
||||||
@@ -267,35 +246,6 @@ const PREVIEW = {
|
|||||||
await w11.run(true);
|
await w11.run(true);
|
||||||
check('#105 dopo Salva: existing letto e non ricompilato', w11.existing && w11.existing.band_mm === 0.3 && w11._existingApplied === true);
|
check('#105 dopo Salva: existing letto e non ricompilato', w11.existing && w11.existing.band_mm === 0.3 && w11._existingApplied === true);
|
||||||
|
|
||||||
// #104: pan col puntatore
|
|
||||||
const wpan = dxfRecipeWizard(1, () => 'tok', {});
|
|
||||||
const vppan = { scrollLeft: 100, scrollTop: 100, clientWidth: 500, clientHeight: 400, setPointerCapture() {} };
|
|
||||||
wpan.$refs = { viewport: vppan };
|
|
||||||
wpan.onPanDown({ clientX: 200, clientY: 200, pointerId: 1, pointerType: 'mouse', button: 0 });
|
|
||||||
wpan.onPanMove({ clientX: 170, clientY: 180 });
|
|
||||||
check('#104 pan: pointermove (-30,-20) -> scroll +30/+20', vppan.scrollLeft === 130 && vppan.scrollTop === 120, vppan.scrollLeft + ',' + vppan.scrollTop);
|
|
||||||
check('#104 pan: grabbing durante il trascinamento', wpan.panning === true);
|
|
||||||
wpan.onPanEnd();
|
|
||||||
wpan.onPanMove({ clientX: 0, clientY: 0 });
|
|
||||||
check('#104 pan: dopo pointerup non scrolla', vppan.scrollLeft === 130 && wpan.panning === false);
|
|
||||||
wpan.onPanDown({ clientX: 0, clientY: 0, pointerId: 1, pointerType: 'mouse', button: 2 });
|
|
||||||
check('#104 pan: il tasto destro non parte', wpan.panning === false);
|
|
||||||
|
|
||||||
// #104: altezza del viewport
|
|
||||||
global.window = { innerHeight: 1000 }; // max = min(700, 520) = 520
|
|
||||||
wpan.resPx = { w: 2000, h: 1000 };
|
|
||||||
wpan.$refs = { viewport: { clientWidth: 500, scrollLeft: 0, scrollTop: 0 }, img: { naturalWidth: 2000, naturalHeight: 1000 } };
|
|
||||||
wpan.fit(); // zoom = min(500/2000, 520/1000) = 0.25
|
|
||||||
check('#104 fit usa l altezza massima', Math.abs(wpan.zoom - 0.25) < 1e-9 && wpan.fitZoom === wpan.zoom, String(wpan.zoom));
|
|
||||||
check('#104 altezza a Fit = immagine scalata', wpan.vpHeight === 250 && wpan.canPan === false, String(wpan.vpHeight)); // zoomH = 250
|
|
||||||
wpan.resPx = { w: 2000, h: 400 }; // zoomH = 100 -> minimo 200
|
|
||||||
check('#104 altezza minima 200', wpan.vpHeight === 200, String(wpan.vpHeight));
|
|
||||||
wpan.zoom = 1;
|
|
||||||
check('#104 con zoom > Adatta altezza massima e pan attivo', wpan.vpHeight === 520 && wpan.canPan === true && wpan.panCursor === 'grab');
|
|
||||||
global.window = { innerHeight: 500 }; // 70vh = 350
|
|
||||||
check('#104 altezza massima = 70vh se minore di 520', wpan.vpHeight === 350, String(wpan.vpHeight));
|
|
||||||
delete global.window;
|
|
||||||
|
|
||||||
if (failures) { console.log(failures + ' fallimenti'); process.exit(1); }
|
if (failures) { console.log(failures + ' fallimenti'); process.exit(1); }
|
||||||
console.log('tutto ok');
|
console.log('tutto ok');
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user