feat: gallery + generic blueprint viewer, add Grid blueprint

Refactor the List-specific screen into a data-driven, reusable viewer:
- generic Blueprint type + shared LoadState machine + registry
- vue-router: / (gallery) and /b/:slug (illustration)
- BlueprintViewer renders any blueprint; specimens stay bespoke
- add Grid blueprint (6 functions incl. Position) + GridSpecimen
This commit is contained in:
Julien Calixte
2026-07-02 18:34:49 +02:00
parent 4405497658
commit 03804b10dc
21 changed files with 2304 additions and 765 deletions

View File

@@ -1,6 +1,8 @@
<script setup lang="ts">
import { computed } from "vue"
import { COMP_CAPS, COMP_FUNCS, COMP_LINKS } from "@/data/listBlueprint"
import type { Composition } from "@/data/blueprint"
const props = defineProps<{ composition: Composition }>()
const PAL = {
boxFill: "#103763",
@@ -20,27 +22,29 @@ const bh = 34
const top = 16
const lstep = 40
const rstep = 52
const H = top + COMP_CAPS.length * lstep + 16
const capY = (i: number) => top + i * lstep + bh / 2
const funcY = (i: number) => top + i * rstep + bh / 2
const H = computed(() => top + props.composition.caps.length * lstep + 16)
const capIndex = computed(
() => Object.fromEntries(COMP_CAPS.map((c, i) => [c.id, i])) as Record<string, number>,
() =>
Object.fromEntries(props.composition.caps.map((c, i) => [c.id, i])) as Record<string, number>,
)
const funcIndex = computed(
() => Object.fromEntries(COMP_FUNCS.map((f, i) => [f, i])) as Record<string, number>,
() => Object.fromEntries(props.composition.funcs.map((f, i) => [f, i])) as Record<string, number>,
)
const leftBoxes = computed(() =>
COMP_CAPS.map((c, i) => ({ ...c, x: lx, y: capY(i) - bh / 2, w: lw, h: bh })),
props.composition.caps.map((c, i) => ({ ...c, x: lx, y: capY(i) - bh / 2, w: lw, h: bh })),
)
const rightBoxes = computed(() =>
COMP_FUNCS.map((f, i) => ({ label: f, x: rx, y: funcY(i) - bh / 2, w: rw, h: bh })),
props.composition.funcs.map((f, i) => ({ label: f, x: rx, y: funcY(i) - bh / 2, w: rw, h: bh })),
)
const edges = computed(() =>
COMP_LINKS.map(([a, b]) => {
props.composition.links.map(([a, b]) => {
const y1 = capY(capIndex.value[a])
const y2 = funcY(funcIndex.value[b])
const x1 = lx + lw