Files
houseplan-card/demo/smoke_openwall_hover.mjs
T

96 lines
4.7 KiB
JavaScript

import { launch, checkAll, finish } from './serve.mjs';
const { page, browser } = await launch();
const res = await page.evaluate(async () => {
const out = {};
const c = window.__card;
const sr = () => c.shadowRoot || c.renderRoot;
const stage = () => sr().querySelector('.stage');
c._setMode('plan'); c._tool = 'boundary'; await c.updateComplete;
const H = 1000;
// A pure touch tap has no hover/pointermove. P1 must still be visible, and a
// pen uses the same coarse tolerances as touch.
c._boundaryPointerType = 'touch';
c._cursorPt = null;
c._boundaryClick([550, 200]); await c.updateComplete;
out.touchTapShowsAnchor = !!c._openWallAnchor && !!sr().querySelector('.boundary-point');
c._openWallAnchor = null;
c._boundaryPointerType = 'pen';
out.penUsesCoarseTolerance = Math.abs(c._boundaryTolerances().hit - c._cssPxToRender(22)) < 1e-6;
c._boundaryPointerType = 'mouse';
// The semantic hit width remains exactly 12 CSS px at both view scales.
const sp = c._curSpaceCfg;
const originalWalls = sp.walls;
delete sp.walls;
c._cfgEpoch++; c._boundaryTargetMemo = null;
const originalView = c._view ? { ...c._view } : null;
const baseView = c._viewOr(c._baseVb());
const atCssOffset = (px) => c._boundaryTargetAt([
550 + px * c._cssPxToRender(1), 300,
]).kind;
const fineAtBase = [atCssOffset(11), atCssOffset(13)];
c._view = {
x: baseView.x + baseView.w / 4, y: baseView.y + baseView.h / 4,
w: baseView.w / 2, h: baseView.h / 2,
};
const fineAtZoom = [atCssOffset(11), atCssOffset(13)];
out.cssPixelToleranceSurvivesZoom = fineAtBase[0] === 'shared' && fineAtBase[1] === 'none'
&& fineAtZoom[0] === 'shared' && fineAtZoom[1] === 'none';
c._view = originalView;
if (originalWalls) sp.walls = originalWalls;
else delete sp.walls;
c._cfgEpoch++; c._boundaryTargetMemo = null;
// Independent masonry is neutral away from room boundaries, but blocks a
// shared boundary directly below it.
const originalPartitions = sp.partitions;
sp.partitions = [...(originalPartitions || []),
{ id: 'smoke-center-partition', a: [0.2, 0.3], b: [0.4, 0.3], cm: 15 }];
c._cfgEpoch++; c._modelCache = null; c._boundaryTargetMemo = null;
out.barePartitionIsNeutral = c._boundaryTargetAt([300, 300]).kind === 'none';
c._toast = '';
c._boundaryClick([300, 300]);
out.barePartitionUsesBoundaryMessage = c._toast === c._t('toast.openwall_pick');
sp.partitions = [...(originalPartitions || []),
{ id: 'smoke-boundary-partition', a: [0.55, 0.14], b: [0.55, 0.46], cm: 15 }];
c._cfgEpoch++; c._modelCache = null; c._boundaryTargetMemo = null;
out.partitionAboveBoundaryBlocks = c._boundaryTargetAt([550, 300]).kind === 'blocked';
if (originalPartitions) sp.partitions = originalPartitions;
else delete sp.partitions;
c._cfgEpoch++; c._modelCache = null; c._boundaryTargetMemo = null;
// 1) idle: neutral until a semantic target is under the pointer
c._cursorPt = null; c.requestUpdate(); await c.updateComplete;
out.idleCursor = getComputedStyle(stage()).cursor === 'default';
out.noPreview = !sr().querySelector('.openwall-preview');
// 2) solid shared wall: local anchor marker, never a full-edge preview
c._cursorPt = [550, 0.25 * H]; c.requestUpdate(); await c.updateComplete;
out.hoverLocalMarker = !!sr().querySelector('.boundary-point') && !sr().querySelector('.openwall-preview');
out.hoverCursor = getComputedStyle(stage()).cursor === 'crosshair';
// 3) The same tool predicts the full body that one click will restore.
c._boundaryClick([550, 140]);
c._boundaryClick([550, 460]);
await c.updateComplete;
c._cursorPt = [550, 300]; c.requestUpdate(); await c.updateComplete;
const prev = sr().querySelector('.openwall-preview');
out.sameToolWillRestore = prev?.classList.contains('boundary-restore') === true;
out.restoreCursor = getComputedStyle(stage()).cursor === 'pointer';
const planClosedOpenSpan = c._planClosedOpenSpan.bind(c);
let previewPlans = 0;
c._planClosedOpenSpan = (...args) => { previewPlans++; return planClosedOpenSpan(...args); };
c._boundaryPreviewMemo = null;
void c._boundaryPreview; void c._boundaryPreview; void c._boundaryPreview;
c._planClosedOpenSpan = planClosedOpenSpan;
out.restorePreviewIsMemoized = previewPlans === 1;
// 4) with anchor set: rubber-band preview appears
c._boundaryClick([550, 300]);
await c.updateComplete;
c._boundaryClick([550, 300]);
out.samePlaceSecondTapDoesNotRearm = !c._openWallAnchor;
c._boundaryClick([550, 200]);
c._cursorPt = [550, 400]; c.requestUpdate(); await c.updateComplete;
const band = sr().querySelector('.openwall-preview');
out.anchorPreview = !!band && band.classList.contains('boundary-range');
c._openWallAnchor = null;
return out;
});
checkAll(res);
await finish(browser, res);