feat: components
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Component-editor for sonic-diamond.
|
||||
*
|
||||
* MVP: matrix view only. Diamonds need no per-variant tuning (all images
|
||||
* are pre-aligned), so single-mode and anchor editing are not implemented.
|
||||
* The "Copy snapshot" button still works — it produces the current
|
||||
* `anchorsDefault` and `variants` ready to paste between marker comments.
|
||||
*/
|
||||
await customElements.whenDefined('sonic-diamond');
|
||||
|
||||
const Comp = customElements.get('sonic-diamond');
|
||||
const { presetProps, chippedShapes } = Comp;
|
||||
|
||||
document.getElementById('meta').textContent =
|
||||
`${Object.keys(Comp.variants).length} variants · baseSize ${Comp.baseSize.w}×${Comp.baseSize.h}mm · origin (${Comp.origin.x}, ${Comp.origin.y})`;
|
||||
|
||||
const main = document.getElementById('main');
|
||||
renderGrid('Full', false);
|
||||
renderGrid('Chipped', true);
|
||||
|
||||
document.getElementById('btn-copy').addEventListener('click', async () => {
|
||||
const text = serializeSnapshot(Comp.anchorsDefault, Comp.variants);
|
||||
await navigator.clipboard.writeText(text);
|
||||
showToast('Snapshot copied');
|
||||
});
|
||||
|
||||
function renderGrid(title, chipped) {
|
||||
const shapes = chipped
|
||||
? presetProps.shape.filter(s => chippedShapes.has(s))
|
||||
: presetProps.shape;
|
||||
const colors = presetProps.color;
|
||||
|
||||
const section = document.createElement('section');
|
||||
const h2 = document.createElement('h2');
|
||||
h2.textContent = `${title} — ${shapes.length} × ${colors.length}`;
|
||||
section.appendChild(h2);
|
||||
|
||||
const grid = document.createElement('div');
|
||||
grid.className = 'grid';
|
||||
grid.style.gridTemplateColumns = `repeat(${colors.length}, 1fr)`;
|
||||
|
||||
for (const shape of shapes) {
|
||||
for (const color of colors) {
|
||||
grid.appendChild(makeCell(shape, color, chipped));
|
||||
}
|
||||
}
|
||||
|
||||
section.appendChild(grid);
|
||||
main.appendChild(section);
|
||||
}
|
||||
|
||||
function makeCell(shape, color, chipped) {
|
||||
const cell = document.createElement('div');
|
||||
cell.className = 'cell';
|
||||
|
||||
const preview = document.createElement('div');
|
||||
preview.className = 'preview';
|
||||
|
||||
const inst = document.createElement('sonic-diamond');
|
||||
inst.setAttribute('shape', shape);
|
||||
inst.setAttribute('color', color);
|
||||
inst.setAttribute('chipped', String(chipped));
|
||||
preview.appendChild(inst);
|
||||
|
||||
const label = document.createElement('div');
|
||||
label.className = 'label';
|
||||
label.innerHTML = `<div>${shape} · ${color}</div>`;
|
||||
|
||||
const key = document.createElement('div');
|
||||
key.className = 'key';
|
||||
key.textContent = inst._variantKey();
|
||||
|
||||
cell.appendChild(preview);
|
||||
cell.appendChild(label);
|
||||
cell.appendChild(key);
|
||||
return cell;
|
||||
}
|
||||
|
||||
function serializeSnapshot(anchorsDefault, variants) {
|
||||
const lines = [];
|
||||
lines.push(' // @editor:anchors-start');
|
||||
lines.push(` static anchorsDefault = ${formatAnchors(anchorsDefault, ' ')};`);
|
||||
lines.push(' // @editor:anchors-end');
|
||||
lines.push('');
|
||||
lines.push(' // @editor:variants-start');
|
||||
lines.push(' static variants = {');
|
||||
for (const [key, v] of Object.entries(variants)) {
|
||||
const a = formatAnchorsInline(v.anchors || {});
|
||||
lines.push(` ${key}: { img: ${JSON.stringify(v.img)}, dx: ${v.dx}, dy: ${v.dy}, scale: ${v.scale}, anchors: ${a} },`);
|
||||
}
|
||||
lines.push(' };');
|
||||
lines.push(' // @editor:variants-end');
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
function formatAnchors(anchors, indent) {
|
||||
const keys = Object.keys(anchors);
|
||||
if (keys.length === 0) return '{}';
|
||||
const inner = keys.map(k => `${indent} ${k}: { x: ${anchors[k].x}, y: ${anchors[k].y} }`).join(',\n');
|
||||
return `{\n${inner},\n${indent}}`;
|
||||
}
|
||||
|
||||
function formatAnchorsInline(anchors) {
|
||||
const keys = Object.keys(anchors);
|
||||
if (keys.length === 0) return '{}';
|
||||
const parts = keys.map(k => `${k}: { x: ${anchors[k].x}, y: ${anchors[k].y} }`);
|
||||
return `{ ${parts.join(', ')} }`;
|
||||
}
|
||||
|
||||
function showToast(msg) {
|
||||
const toast = document.getElementById('toast');
|
||||
toast.textContent = msg;
|
||||
toast.classList.add('show');
|
||||
setTimeout(() => toast.classList.remove('show'), 1500);
|
||||
}
|
||||
Reference in New Issue
Block a user