Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/lib/cardbuilder/builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ export function mountCardBuilder({ form, data }) {
wasSet.wmode = wset;
wasSet.hmode = hset;
el('eb-px').hidden = !widthOpen;
el('eb-px-w').hidden = el('eb-widths').hidden = !wset;
el('eb-px-w').hidden = !wset;
el('eb-px-h').hidden = !hset;
el('eb-shapes').hidden = !(wset && hset);
el('eb-w-shown').textContent = wset && !widthOpen ? `${s.width}px` : 'set';
Expand Down Expand Up @@ -582,7 +582,7 @@ export function mountCardBuilder({ form, data }) {
}

// The surface the preview's modules are given.
const b = { form, el, items, space, areasOn, st, trackBetween, trackName, showTracks, tune, render, setRadio, sideKind, showGap, stackedIn, moveButton };
const b = { limits, form, el, items, space, areasOn, st, trackBetween, trackName, showTracks, tune, render, setRadio, sideKind, showGap, stackedIn, moveButton };
tuneAll.addEventListener('click', () => tune(tuneAll.textContent === 'hide all' ? [] : tuneRows.map((r) => r.dataset.tune)));

// The PNG or PDF, drawn here from the preview when asked for.
Expand Down
34 changes: 34 additions & 0 deletions src/lib/cardbuilder/overlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,40 @@ export function attachGrip(frame, b) {
});
}

/** A card of fixed width or height has a grip on its right or bottom edge:
* dragging it sizes that dimension live, and on release writes the px box. */
export function attachSize(frame, b) {
const { form, render, limits } = b;
const doc = frame.contentDocument, card = doc.querySelector('.card');
if (!card) return;
const { fixedMin, fixedMax, fixedMinHeight } = limits;
for (const [axis, mode, box, lo] of [['w', 'wmode', 'px', fixedMin], ['h', 'hmode', 'hpx', fixedMinHeight]]) {
if (form.elements[mode].value !== 'px') continue;
const g = doc.createElement('span');
g.className = 'eb-size-grip';
g.dataset.axis = axis;
g.title = `Drag to set the card’s ${axis === 'w' ? 'width' : 'height'}`;
card.append(g);
g.addEventListener('pointerdown', (e) => {
e.preventDefault();
e.stopPropagation();
g.setPointerCapture(e.pointerId);
const r = card.getBoundingClientRect(), x0 = e.clientX, y0 = e.clientY;
let v = null;
const move = (ev) => {
v = clampInt(axis === 'w' ? r.width + ev.clientX - x0 : r.height + ev.clientY - y0, lo, fixedMax);
if (axis === 'w') frame.style.width = `${v}px`; else card.style.height = `${v}px`;
};
const up = () => {
if (v == null) return;
form.elements[box].value = v;
render();
};
drag(g, move, up);
});
}
}

/** In the preview, a ⊕ between each two slots that show — the first track
* between them, where parts left out leave several — to add space there,
* and a hatched band over each track that has some. */
Expand Down
5 changes: 3 additions & 2 deletions src/lib/cardbuilder/preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { FIGURE_SLOTS } from '../cardname.js';
import { inBox } from './model.js';
import { cellGrid, partZones, venueDrops } from './geometry.js';
import { drag, shownIn } from './dom.js';
import { attachGrip, attachPlus } from './overlay.js';
import { attachGrip, attachPlus, attachSize } from './overlay.js';

// The preview's hitboxes: each part of the card, outlined, brings up what
// tunes it — first match wins, so a link button beats the box it sits in,
Expand Down Expand Up @@ -58,6 +58,7 @@ export function attachPreview(frame, b) {
doc.documentElement.classList.add('eb-hits');
attachGrip(frame, b);
attachPlus(frame, b);
attachSize(frame, b);
// A part is what it is; what is left — the card's own room, the box a
// buttons' box fills its side with, or a title's box past its words — is the
// area under the pointer, where there is one, not the part that happens
Expand All @@ -72,7 +73,7 @@ export function attachPreview(frame, b) {
return [...r.getClientRects()].some((b) => x >= b.left - 2 && x <= b.right + 2 && y >= b.top - 2 && y <= b.bottom + 2);
};
const find = (t, x, y) => {
if (t.closest?.('.eb-plus, .eb-band, .eb-area-grip, .eb-areabtn')) return null;
if (t.closest?.('.eb-plus, .eb-band, .eb-area-grip, .eb-size-grip, .eb-areabtn')) return null;
for (const [q, keys] of HITS) {
const el = t.closest?.(q);
if (!el) continue;
Expand Down
2 changes: 1 addition & 1 deletion src/pages/tools/card.astro
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ const data = {
<span class="eb-px" id="eb-px" role="group" aria-label="Width and height" hidden>
<span class="sep" aria-hidden="true">|</span>
<NumBox id="eb-px-w" title="The width, in pixels" name="px" min={FIXED_MIN} max={FIXED_MAX} value="320" label="Width in pixels" unit="px" after="wide" />
<span class="pilltoggle" id="eb-widths" role="radiogroup" aria-label="Preset widths"></span>
<span class="pilltoggle" id="eb-widths" hidden role="radiogroup" aria-label="Preset widths"></span>
<NumBox id="eb-px-h" title="The height, in pixels" name="hpx" min={FIXED_MIN_HEIGHT} max={FIXED_MAX} value="400" label="Height in pixels" unit="px" after="high" />
<span class="pilltoggle" id="eb-shapes" role="radiogroup" aria-label="Shape">
{['4x5', '1x1', '8x5', '4x1'].map((a) => <label title={`${a.replace('x', ' wide by ')} high`}><input type="radio" class="posradio" name="shape" value={a} />{a.replace('x', ':')}</label>)}
Expand Down
6 changes: 6 additions & 0 deletions src/styles/card-builder-preview.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
border:2px solid var(--accent); border-radius:2px; background:var(--ground); cursor:nwse-resize; touch-action:none}
.eb-hits .card{position:relative; isolation:isolate}
/* The areas, behind what is in them: outlined, as the parts are. */
.eb-size-grip{display:none}
.eb-hits .eb-size-grip{display:block; position:absolute; z-index:7; touch-action:none; background:var(--accent); opacity:0; transition:opacity .15s}
.eb-hits .card:hover .eb-size-grip{opacity:.35}
.eb-hits .eb-size-grip:hover, .eb-hits .eb-size-grip:active{opacity:1}
.eb-hits .eb-size-grip[data-axis=w]{top:0; bottom:0; right:0; width:6px; cursor:ew-resize}
.eb-hits .eb-size-grip[data-axis=h]{left:0; right:0; bottom:0; height:6px; cursor:ns-resize}
.eb-area{display:none}
.eb-hits .eb-area{display:block; position:absolute; z-index:-1}
/* A side's inner edge, dragged to set its width. */
Expand Down
Loading