feat: standard parts library, fuse box configurator, and theming
Standard parts (partsLibrary.js) - ACDC TXL palette: 15 solids plus the 16 stocked stripe combinations - 29 wire functions fix colour, stripe and gauge per signal, so a wire drawn from a given pin comes out identical on every build - 16 pre-labelled parts: Skudak VCU (GRAY/BLACK), openinverter LDU 23-pin, Dilong OBC/DCDC, BMW pedal, Honeywell CSSV1500, Bender ISO175, Bosch iBooster, Prius EPS, Volvo PS pump, cluster, DNR switch, 32-way enclosure bulkhead, contactors, VW MEB BMS - OEM colours override the in-house standard where we splice into a factory loom (VW MEB LV connector, recovered from the VW bms diagram) - Brown is ground, matching the MEB loom and European practice; orange is reserved for AC mains and OEM high-voltage runs Fuse box configurator (pdmLibrary.js) - GEP FRH-A12/A24 and the 48-way PDM as 280-footprint cavity grids - Place, drag and rotate fuses, relays, diodes, breakers and bus bars - Bus bars occupy their own collision layer and feed the blades they cross, suppressing those inputs so one wire supplies the run - Cavity capacity is tracked; Apply is blocked while a placement overlaps or overhangs - Naming a circuit renames its pins: "VCU" gives "VCU in" / "VCU out" Theming (theme.js) - Light and dark modes; canvas background, grid dots, part fill and part outline are configurable and persisted - CSS converted to custom properties with property-aware light-mode pairs, since a colour used as text and as a surface must flip differently; no rule falls below 3:1 contrast in either theme - Canvas devices, pins, labels, cable rows and the harness view are themed too, since Konva bakes colours in at draw time and cannot read CSS variables Also - Pass-through bulkheads: one device covering both connector faces, with a single centred label per circuit - Pin labels scale with the device font instead of a fixed 8px - Keyboard handling is modal-scoped, so Delete no longer removes the canvas device while the fuse box editor is open Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -213,16 +213,77 @@ function connectorToDevice(connId, diagramId) {
|
||||
};
|
||||
}
|
||||
|
||||
// Standard rectangular connector
|
||||
const w = 120;
|
||||
const h = Math.max(60, pinCount * 18 + 20);
|
||||
const pins = Array.from({ length: pinCount }, (_, i) => ({
|
||||
id: `pin_${i + 1}`,
|
||||
name: conn.pinLabels ? (conn.pinLabels[i] || String(i + 1)) : String(i + 1),
|
||||
side: "right",
|
||||
x_offset: w,
|
||||
y_offset: ((i + 1) / (pinCount + 1)) * h,
|
||||
}));
|
||||
// Standard rectangular connector.
|
||||
// Parts carrying pinSpecs (see partsLibrary.js) get their standard wire
|
||||
// function stamped onto each pin, so wires drawn off them always come out the
|
||||
// same colour, stripe and gauge.
|
||||
const specs = conn.pinSpecs || null;
|
||||
|
||||
// Pass-through parts (bulkheads) present both faces of the same connector as
|
||||
// one device: every circuit gets an IN pin on the left and an OUT pin on the
|
||||
// right at the same height, sharing a single centred label. Wiring both sides
|
||||
// of a bulkhead then needs one device, not a mated pair.
|
||||
if (conn.passThrough) {
|
||||
const w = 240;
|
||||
const h = Math.max(60, pinCount * 18 + 24);
|
||||
const pins = [];
|
||||
(specs || Array.from({ length: pinCount })).forEach((spec, i) => {
|
||||
const y = ((i + 1) / (pinCount + 1)) * h;
|
||||
const base = {
|
||||
name: spec ? spec.name : String(i + 1),
|
||||
pin_number: spec ? spec.pin : String(i + 1),
|
||||
wire_fn: spec ? spec.fn : null,
|
||||
wire_oem: spec && spec.oem ? spec.oem : null,
|
||||
note: spec ? spec.note : "",
|
||||
};
|
||||
pins.push({ ...base, id: `pin_${i + 1}_in`, side: "left", x_offset: 0, y_offset: y, center_label: true });
|
||||
pins.push({ ...base, id: `pin_${i + 1}_out`, side: "right", x_offset: w, y_offset: y, hide_label: true });
|
||||
});
|
||||
return {
|
||||
diagram_id: diagramId,
|
||||
device_type: "connector",
|
||||
label: conn.name,
|
||||
reference: "",
|
||||
x: 200, y: 200,
|
||||
width: w, height: h,
|
||||
properties: {
|
||||
pinCount,
|
||||
orientation: "right",
|
||||
passThrough: true,
|
||||
partNumber: conn.partNumber || "",
|
||||
manufacturer: conn.manufacturer || "",
|
||||
connectorLibraryId: connId,
|
||||
standardPart: !!specs,
|
||||
verifyPinout: !!conn.verify,
|
||||
},
|
||||
pins,
|
||||
};
|
||||
}
|
||||
|
||||
// Wide parts get two columns so a 20- or 32-way body stays readable.
|
||||
const split = pinCount > 12;
|
||||
const perSide = split ? Math.ceil(pinCount / 2) : pinCount;
|
||||
const w = split ? 200 : 120;
|
||||
const h = Math.max(60, perSide * 18 + 20);
|
||||
|
||||
const pins = Array.from({ length: pinCount }, (_, i) => {
|
||||
const spec = specs ? specs[i] : null;
|
||||
const onRight = !split || i >= perSide;
|
||||
const idx = onRight && split ? i - perSide : i;
|
||||
const count = onRight && split ? pinCount - perSide : perSide;
|
||||
return {
|
||||
id: `pin_${i + 1}`,
|
||||
name: spec ? spec.name : (conn.pinLabels ? (conn.pinLabels[i] || String(i + 1)) : String(i + 1)),
|
||||
side: onRight ? "right" : "left",
|
||||
x_offset: onRight ? w : 0,
|
||||
y_offset: ((idx + 1) / (count + 1)) * h,
|
||||
// Standard-parts metadata — consumed by createWire() and the props panel.
|
||||
pin_number: spec ? spec.pin : String(i + 1),
|
||||
wire_fn: spec ? spec.fn : null,
|
||||
wire_oem: spec && spec.oem ? spec.oem : null,
|
||||
note: spec ? spec.note : "",
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
diagram_id: diagramId,
|
||||
@@ -237,6 +298,8 @@ function connectorToDevice(connId, diagramId) {
|
||||
partNumber: conn.partNumber || "",
|
||||
manufacturer: conn.manufacturer || "",
|
||||
connectorLibraryId: connId,
|
||||
standardPart: !!specs,
|
||||
verifyPinout: !!conn.verify,
|
||||
},
|
||||
pins,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user