/** * 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 = `
${shape} · ${color}
`; 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); }