Initial commit — wiring diagram maker with full feature set
- FastAPI + SQLite backend with routers for diagrams, devices, wires, bundles, connectors, export, and Octopart/Nexar search - Konva.js canvas: ortho/direct/curved routing, wire crossings, harness mode, snap-to-grid, multi-select, drag, resize, undo - Wire features: color/stripe, twisted pair helix, shielded glow, gauge size label, multi-core bundle grouping, length/unit tracking - Device library: connector, terminal block, cable, splice, label, group, relay, fuse, switch, component with custom connector support - Exports: BOM CSV, assembly TXT, JSON, formboard layout, PNG image - Auto-migration for schema changes via ALTER TABLE at startup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
const API_BASE = "/api";
|
||||
|
||||
async function apiFetch(path, options = {}) {
|
||||
const res = await fetch(`${API_BASE}${path}`, options);
|
||||
if (!res.ok) {
|
||||
const text = await res.text();
|
||||
throw new Error(`API ${res.status}: ${text}`);
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
|
||||
const api = {
|
||||
diagrams: {
|
||||
list: () => apiFetch("/diagrams/"),
|
||||
create: (data) => apiFetch("/diagrams/", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }),
|
||||
get: (id) => apiFetch(`/diagrams/${id}`),
|
||||
update: (id, data) => apiFetch(`/diagrams/${id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }),
|
||||
delete: (id) => apiFetch(`/diagrams/${id}`, { method: "DELETE" }),
|
||||
},
|
||||
devices: {
|
||||
create: (data) => apiFetch("/devices/", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }),
|
||||
update: (id, data) => apiFetch(`/devices/${id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }),
|
||||
delete: (id) => apiFetch(`/devices/${id}`, { method: "DELETE" }),
|
||||
},
|
||||
wires: {
|
||||
create: (data) => apiFetch("/wires/", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }),
|
||||
update: (id, data) => apiFetch(`/wires/${id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }),
|
||||
delete: (id) => apiFetch(`/wires/${id}`, { method: "DELETE" }),
|
||||
},
|
||||
bundles: {
|
||||
listForDiagram: (diagramId) => apiFetch(`/bundles/diagram/${diagramId}`),
|
||||
create: (data) => apiFetch("/bundles/", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }),
|
||||
update: (id, data) => apiFetch(`/bundles/${id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }),
|
||||
delete: (id) => apiFetch(`/bundles/${id}`, { method: "DELETE" }),
|
||||
},
|
||||
connectors: {
|
||||
list: () => apiFetch("/connectors/"),
|
||||
create: (data) => apiFetch("/connectors/", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }),
|
||||
update: (id, data) => apiFetch(`/connectors/${id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(data) }),
|
||||
delete: (id) => apiFetch(`/connectors/${id}`, { method: "DELETE" }),
|
||||
},
|
||||
octopart: {
|
||||
status: () => apiFetch("/octopart/status"),
|
||||
search: (q, n) => apiFetch(`/octopart/search?q=${encodeURIComponent(q)}&limit=${n || 8}`),
|
||||
},
|
||||
export: {
|
||||
bomUrl: (id) => `${API_BASE}/export/${id}/bom/csv`,
|
||||
assemblyUrl: (id) => `${API_BASE}/export/${id}/assembly/txt`,
|
||||
jsonUrl: (id) => `${API_BASE}/export/${id}/json`,
|
||||
formboardUrl: (id) => `${API_BASE}/export/${id}/formboard`,
|
||||
},
|
||||
};
|
||||
+1449
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,184 @@
|
||||
// Automotive / EV connector library
|
||||
// Each entry: { id, name, manufacturer, partNumber, pinCount, pinLabels?, description }
|
||||
|
||||
const CONNECTOR_LIBRARY = {
|
||||
"Deutsch DT": [
|
||||
{ id: "dt-2p", name: "DT04-2P", manufacturer: "TE Connectivity", partNumber: "DT04-2P-P012", pinCount: 2, description: "2-pin weatherproof plug, 20–14 AWG" },
|
||||
{ id: "dt-3p", name: "DT04-3P", manufacturer: "TE Connectivity", partNumber: "DT04-3P-P012", pinCount: 3, description: "3-pin weatherproof plug, 20–14 AWG" },
|
||||
{ id: "dt-4p", name: "DT04-4P", manufacturer: "TE Connectivity", partNumber: "DT04-4P-P012", pinCount: 4, description: "4-pin weatherproof plug, 20–14 AWG" },
|
||||
{ id: "dt-6p", name: "DT04-6P", manufacturer: "TE Connectivity", partNumber: "DT04-6P-P012", pinCount: 6, description: "6-pin weatherproof plug, 20–14 AWG" },
|
||||
{ id: "dt-8p", name: "DT04-8P", manufacturer: "TE Connectivity", partNumber: "DT04-8P-P012", pinCount: 8, description: "8-pin weatherproof plug, 20–14 AWG" },
|
||||
{ id: "dt-12p", name: "DT04-12P", manufacturer: "TE Connectivity", partNumber: "DT04-12P-P014", pinCount: 12, description: "12-pin weatherproof plug, 20–14 AWG" },
|
||||
{ id: "dt-2s", name: "DT06-2S", manufacturer: "TE Connectivity", partNumber: "DT06-2S", pinCount: 2, description: "2-pin weatherproof socket (receptacle)" },
|
||||
{ id: "dt-4s", name: "DT06-4S", manufacturer: "TE Connectivity", partNumber: "DT06-4S", pinCount: 4, description: "4-pin weatherproof socket (receptacle)" },
|
||||
{ id: "dt-6s", name: "DT06-6S", manufacturer: "TE Connectivity", partNumber: "DT06-6S", pinCount: 6, description: "6-pin weatherproof socket (receptacle)" },
|
||||
{ id: "dt-8s", name: "DT06-8S", manufacturer: "TE Connectivity", partNumber: "DT06-8S", pinCount: 8, description: "8-pin weatherproof socket (receptacle)" },
|
||||
],
|
||||
"Deutsch DTM (Miniature)": [
|
||||
{ id: "dtm-2p", name: "DTM04-2P", manufacturer: "TE Connectivity", partNumber: "DTM04-2P", pinCount: 2, description: "2-pin miniature weatherproof, 24–20 AWG" },
|
||||
{ id: "dtm-3p", name: "DTM04-3P", manufacturer: "TE Connectivity", partNumber: "DTM04-3P", pinCount: 3, description: "3-pin miniature weatherproof" },
|
||||
{ id: "dtm-4p", name: "DTM04-4P", manufacturer: "TE Connectivity", partNumber: "DTM04-4P", pinCount: 4, description: "4-pin miniature weatherproof" },
|
||||
{ id: "dtm-6p", name: "DTM04-6P", manufacturer: "TE Connectivity", partNumber: "DTM04-6P", pinCount: 6, description: "6-pin miniature weatherproof" },
|
||||
{ id: "dtm-8p", name: "DTM04-8P", manufacturer: "TE Connectivity", partNumber: "DTM04-8P", pinCount: 8, description: "8-pin miniature weatherproof" },
|
||||
{ id: "dtm-2s", name: "DTM06-2S", manufacturer: "TE Connectivity", partNumber: "DTM06-2S", pinCount: 2, description: "2-pin miniature socket" },
|
||||
{ id: "dtm-4s", name: "DTM06-4S", manufacturer: "TE Connectivity", partNumber: "DTM06-4S", pinCount: 4, description: "4-pin miniature socket" },
|
||||
],
|
||||
"Deutsch DTP (High Current)": [
|
||||
{ id: "dtp-2p", name: "DTP04-2P", manufacturer: "TE Connectivity", partNumber: "DTP04-2P-E003", pinCount: 2, description: "2-pin high current plug, up to 40A per pin, 12–10 AWG", pinLabels: ["+", "−"] },
|
||||
{ id: "dtp-4p", name: "DTP04-4P", manufacturer: "TE Connectivity", partNumber: "DTP04-4P-E003", pinCount: 4, description: "4-pin high current plug, up to 40A per pin" },
|
||||
{ id: "dtp-2s", name: "DTP06-2S", manufacturer: "TE Connectivity", partNumber: "DTP06-2S-E003", pinCount: 2, description: "2-pin high current socket" },
|
||||
{ id: "dtp-4s", name: "DTP06-4S", manufacturer: "TE Connectivity", partNumber: "DTP06-4S-E003", pinCount: 4, description: "4-pin high current socket" },
|
||||
],
|
||||
"Deutsch HD (Heavy Duty)": [
|
||||
{ id: "hd-9", name: "HD30-9", manufacturer: "TE Connectivity", partNumber: "HD30-9-1939P", pinCount: 9, description: "9-pin heavy duty, SAE J1939 CAN" },
|
||||
{ id: "hd-18", name: "HD30-18", manufacturer: "TE Connectivity", partNumber: "HD30-18-14P", pinCount: 18, description: "18-pin heavy duty" },
|
||||
{ id: "hd-24", name: "HD30-24", manufacturer: "TE Connectivity", partNumber: "HD30-24-14P", pinCount: 24, description: "24-pin heavy duty" },
|
||||
],
|
||||
"Anderson Powerpole": [
|
||||
{ id: "ap-pp15", name: "PP15/30", manufacturer: "Anderson Power", partNumber: "1327G6", pinCount: 2, description: "15/30 A Powerpole, 15–12 AWG", pinLabels: ["+", "−"] },
|
||||
{ id: "ap-pp45", name: "PP45", manufacturer: "Anderson Power", partNumber: "1338G6", pinCount: 2, description: "45 A Powerpole, 12–10 AWG", pinLabels: ["+", "−"] },
|
||||
{ id: "ap-pp75", name: "PP75", manufacturer: "Anderson Power", partNumber: "5913G2", pinCount: 2, description: "75 A Powerpole, 8–4 AWG", pinLabels: ["+", "−"] },
|
||||
{ id: "ap-sb50", name: "SB 50", manufacturer: "Anderson Power", partNumber: "6319G1", pinCount: 2, description: "50 A SB connector, 6–2 AWG", pinLabels: ["+", "−"] },
|
||||
{ id: "ap-sb120", name: "SB 120", manufacturer: "Anderson Power", partNumber: "6352G1", pinCount: 2, description: "120 A SB connector, 2–4/0 AWG", pinLabels: ["+", "−"] },
|
||||
{ id: "ap-sb175", name: "SB 175", manufacturer: "Anderson Power", partNumber: "6321G1", pinCount: 2, description: "175 A SB connector, 2–4/0 AWG", pinLabels: ["+", "−"] },
|
||||
{ id: "ap-sb350", name: "SB 350", manufacturer: "Anderson Power", partNumber: "6348G1", pinCount: 2, description: "350 A SB connector, 4/0 AWG", pinLabels: ["+", "−"] },
|
||||
],
|
||||
"Molex Micro-Fit 3.0": [
|
||||
{ id: "mf-2", name: "Micro-Fit 2-pin", manufacturer: "Molex", partNumber: "43045-0200", pinCount: 2, description: "600 V, 5 A, 3.0 mm pitch" },
|
||||
{ id: "mf-4", name: "Micro-Fit 4-pin", manufacturer: "Molex", partNumber: "43045-0400", pinCount: 4, description: "600 V, 5 A" },
|
||||
{ id: "mf-6", name: "Micro-Fit 6-pin", manufacturer: "Molex", partNumber: "43045-0600", pinCount: 6, description: "600 V, 5 A" },
|
||||
{ id: "mf-8", name: "Micro-Fit 8-pin", manufacturer: "Molex", partNumber: "43045-0800", pinCount: 8, description: "600 V, 5 A" },
|
||||
{ id: "mf-10", name: "Micro-Fit 10-pin", manufacturer: "Molex", partNumber: "43045-1000", pinCount: 10, description: "600 V, 5 A" },
|
||||
{ id: "mf-12", name: "Micro-Fit 12-pin", manufacturer: "Molex", partNumber: "43045-1200", pinCount: 12, description: "600 V, 5 A" },
|
||||
],
|
||||
"Molex Mini-Fit Jr.": [
|
||||
{ id: "mfj-2", name: "Mini-Fit Jr. 2-pin", manufacturer: "Molex", partNumber: "39012020", pinCount: 2, description: "600 V, 9 A, 4.20 mm pitch" },
|
||||
{ id: "mfj-4", name: "Mini-Fit Jr. 4-pin", manufacturer: "Molex", partNumber: "39012040", pinCount: 4, description: "600 V, 9 A" },
|
||||
{ id: "mfj-6", name: "Mini-Fit Jr. 6-pin", manufacturer: "Molex", partNumber: "39012060", pinCount: 6, description: "600 V, 9 A" },
|
||||
{ id: "mfj-8", name: "Mini-Fit Jr. 8-pin", manufacturer: "Molex", partNumber: "39012080", pinCount: 8, description: "600 V, 9 A" },
|
||||
{ id: "mfj-12", name: "Mini-Fit Jr. 12-pin", manufacturer: "Molex", partNumber: "39012120", pinCount: 12, description: "600 V, 9 A" },
|
||||
],
|
||||
"Molex MX150 (Automotive)": [
|
||||
{ id: "mx-2", name: "MX150 2-pin", manufacturer: "Molex", partNumber: "33472-0201", pinCount: 2, description: "Sealed automotive, 600 V, 13 A" },
|
||||
{ id: "mx-4", name: "MX150 4-pin", manufacturer: "Molex", partNumber: "33472-0401", pinCount: 4, description: "Sealed automotive" },
|
||||
{ id: "mx-6", name: "MX150 6-pin", manufacturer: "Molex", partNumber: "33472-0601", pinCount: 6, description: "Sealed automotive" },
|
||||
{ id: "mx-8", name: "MX150 8-pin", manufacturer: "Molex", partNumber: "33472-0801", pinCount: 8, description: "Sealed automotive" },
|
||||
],
|
||||
"TE Superseal 1.5 mm (IP67)": [
|
||||
{ id: "ss-1", name: "Superseal 1-pin", manufacturer: "TE Connectivity", partNumber: "1-967616-1", pinCount: 1, description: "IP67, 0.5–1.0 mm², 8.5 A" },
|
||||
{ id: "ss-2", name: "Superseal 2-pin", manufacturer: "TE Connectivity", partNumber: "1-967616-2", pinCount: 2, description: "IP67, 0.5–1.0 mm²" },
|
||||
{ id: "ss-3", name: "Superseal 3-pin", manufacturer: "TE Connectivity", partNumber: "1-967616-3", pinCount: 3, description: "IP67, 0.5–1.0 mm²" },
|
||||
{ id: "ss-4", name: "Superseal 4-pin", manufacturer: "TE Connectivity", partNumber: "1-967616-4", pinCount: 4, description: "IP67, 0.5–1.0 mm²" },
|
||||
{ id: "ss-6", name: "Superseal 6-pin", manufacturer: "TE Connectivity", partNumber: "1-967616-6", pinCount: 6, description: "IP67, 0.5–1.0 mm²" },
|
||||
],
|
||||
"Delphi / Aptiv Weatherpack": [
|
||||
{ id: "wp-1", name: "Weatherpack 1-pin", manufacturer: "Aptiv (Delphi)", partNumber: "12015793", pinCount: 1, description: "GT series, 100 °C rated, 20–18 AWG" },
|
||||
{ id: "wp-2", name: "Weatherpack 2-pin", manufacturer: "Aptiv (Delphi)", partNumber: "12010299", pinCount: 2, description: "GT series, 100 °C rated" },
|
||||
{ id: "wp-3", name: "Weatherpack 3-pin", manufacturer: "Aptiv (Delphi)", partNumber: "12010325", pinCount: 3, description: "GT series" },
|
||||
{ id: "wp-4", name: "Weatherpack 4-pin", manufacturer: "Aptiv (Delphi)", partNumber: "12010298", pinCount: 4, description: "GT series" },
|
||||
{ id: "wp-6", name: "Weatherpack 6-pin", manufacturer: "Aptiv (Delphi)", partNumber: "12010973", pinCount: 6, description: "GT series" },
|
||||
],
|
||||
"Delphi Metripack": [
|
||||
{ id: "mp150-2", name: "Metripack 150 2-pin", manufacturer: "Aptiv (Delphi)", partNumber: "12162825", pinCount: 2, description: "Metripack 150, sealed" },
|
||||
{ id: "mp150-3", name: "Metripack 150 3-pin", manufacturer: "Aptiv (Delphi)", partNumber: "12162193", pinCount: 3, description: "Metripack 150, sealed" },
|
||||
{ id: "mp280-2", name: "Metripack 280 2-pin", manufacturer: "Aptiv (Delphi)", partNumber: "12010973", pinCount: 2, description: "Metripack 280 (larger terminal, higher current)" },
|
||||
{ id: "mp630-1", name: "Metripack 630 1-pin", manufacturer: "Aptiv (Delphi)", partNumber: "12110293", pinCount: 1, description: "Metripack 630, high current single contact" },
|
||||
],
|
||||
"Tesla (Proprietary / Approximate)": [
|
||||
{
|
||||
id: "tesla-hv23", name: "HV Battery 23-pin", manufacturer: "Tesla", partNumber: "Tesla OEM",
|
||||
pinCount: 23, description: "Model S/X HV battery main connector (proprietary pinout — verify with service manual)",
|
||||
pinLabels: ["HV+","HV+","HV−","HV−","SH","SH","HVIL+","HVIL−","CAN H","CAN L","CANH2","CANL2","12V","GND","GND","TP","TP","TP","TP","TP","TP","TP","TP"],
|
||||
},
|
||||
{
|
||||
id: "tesla-hvil2", name: "HV Interlock 2-pin", manufacturer: "Tesla", partNumber: "Tesla OEM",
|
||||
pinCount: 2, description: "High voltage interlock loop", pinLabels: ["HVIL+", "HVIL−"],
|
||||
},
|
||||
{
|
||||
id: "tesla-charge-m3", name: "Charge Port (Model 3/Y)", manufacturer: "Tesla", partNumber: "Tesla OEM",
|
||||
pinCount: 5, description: "AC charge port, Model 3 / Y (proprietary, similar to J1772)", pinLabels: ["L1","L2/N","GND","PP","CP"],
|
||||
},
|
||||
{
|
||||
id: "tesla-can4", name: "CAN Bus 4-pin", manufacturer: "Tesla", partNumber: "Tesla OEM",
|
||||
pinCount: 4, description: "Typical CAN bus connector (varies by model/year)", pinLabels: ["CAN H","CAN L","GND","12V"],
|
||||
},
|
||||
{
|
||||
id: "tesla-hv2", name: "HV 2-pin (Phase)", manufacturer: "Tesla", partNumber: "Tesla OEM",
|
||||
pinCount: 2, description: "HV 2-pin power connector (motor/inverter phase, approximate)", pinLabels: ["+","−"],
|
||||
},
|
||||
],
|
||||
"EV Charging Standards": [
|
||||
{
|
||||
id: "ev-j1772", name: "SAE J1772 Type 1", manufacturer: "Standard", partNumber: "SAE J1772",
|
||||
pinCount: 5, description: "AC Level 1/2 charging — North America", pinLabels: ["L1","N","GND","PP","CP"],
|
||||
},
|
||||
{
|
||||
id: "ev-type2", name: "IEC 62196 Type 2", manufacturer: "Standard", partNumber: "IEC 62196-2",
|
||||
pinCount: 7, description: "AC charging — Europe / international", pinLabels: ["L1","L2","L3","N","GND","PP","CP"],
|
||||
},
|
||||
{
|
||||
id: "ev-chademo", name: "CHAdeMO DC Fast", manufacturer: "Standard", partNumber: "CHAdeMO",
|
||||
pinCount: 10, description: "DC fast charge (up to 400 A / 500 V)", pinLabels: ["DC+","DC−","GND","CAN H","CAN L","Charge enable","Car ready","Charge stop","FG","Shield"],
|
||||
},
|
||||
{
|
||||
id: "ev-ccs1", name: "CCS Combo 1 (DC)", manufacturer: "Standard", partNumber: "SAE J1772 CCS",
|
||||
pinCount: 2, description: "CCS DC fast charge pins (2 large pins below J1772)", pinLabels: ["DC+","DC−"],
|
||||
},
|
||||
],
|
||||
"CAN / Network": [
|
||||
{ id: "can-dt2", name: "CAN Deutsch 2-pin", manufacturer: "TE Connectivity", partNumber: "DT04-2P", pinCount: 2, description: "Deutsch DT 2-pin for CAN bus", pinLabels: ["CAN H","CAN L"] },
|
||||
{ id: "can-j1939", name: "SAE J1939 9-pin", manufacturer: "Amphenol", partNumber: "HD10-9-1939P", pinCount: 9, description: "J1939 CAN heavy-vehicle datalink", pinLabels: ["−Battery","+Battery","GND","CAN H","Shield","GND","CAN L","NC","NC"] },
|
||||
{ id: "can-obd2", name: "OBD-II 16-pin", manufacturer: "Standard", partNumber: "SAE J1962", pinCount: 16, description: "On-board diagnostics port", pinLabels: ["Mfr","Mfr","GND","Mfr","Sig GND","CAN H","K-Line","Mfr","Bat+","Mfr","Mfr","Mfr","Mfr","CAN L","L-Line","OBD+"] },
|
||||
],
|
||||
"General Automotive / EV": [
|
||||
{ id: "ga-motor3", name: "Motor Phase 3-pin", manufacturer: "varies", partNumber: "varies", pinCount: 3, description: "3-phase motor connections", pinLabels: ["U","V","W"] },
|
||||
{ id: "ga-res2", name: "Resolver 2-pin", manufacturer: "varies", partNumber: "varies", pinCount: 2, description: "Motor resolver position sensor", pinLabels: ["SIN","COS"] },
|
||||
{ id: "ga-therm2", name: "Temperature Sensor 2-pin",manufacturer: "varies", partNumber: "varies", pinCount: 2, description: "NTC/PTC thermistor", pinLabels: ["SIG","GND"] },
|
||||
{ id: "ga-hall3", name: "Hall Sensor 3-pin", manufacturer: "varies", partNumber: "varies", pinCount: 3, description: "Hall effect position sensor", pinLabels: ["VCC","GND","SIG"] },
|
||||
{ id: "ga-batt2", name: "12 V Battery 2-pin", manufacturer: "varies", partNumber: "varies", pinCount: 2, description: "12 V battery / accessory supply", pinLabels: ["+12V","GND"] },
|
||||
{ id: "ga-ctrlr4", name: "Controller 4-pin", manufacturer: "varies", partNumber: "varies", pinCount: 4, description: "Generic 4-pin controller interface", pinLabels: ["VCC","GND","SIG","EN"] },
|
||||
{ id: "ga-fuse2", name: "Fuse Holder 2-pin", manufacturer: "varies", partNumber: "varies", pinCount: 2, description: "Inline fuse holder connections", pinLabels: ["IN","OUT"] },
|
||||
{ id: "ga-relay5", name: "Relay 5-pin (SPDT)", manufacturer: "varies", partNumber: "varies", pinCount: 5, description: "SPDT automotive relay", pinLabels: ["85","86","30","87","87a"] },
|
||||
],
|
||||
};
|
||||
|
||||
// Build a flat lookup map for quick access by id
|
||||
const _CONN_BY_ID = {};
|
||||
for (const conns of Object.values(CONNECTOR_LIBRARY)) {
|
||||
for (const c of conns) { _CONN_BY_ID[c.id] = c; }
|
||||
}
|
||||
|
||||
function getConnectorById(id) { return _CONN_BY_ID[id] || null; }
|
||||
|
||||
function connectorToDevice(connId, diagramId) {
|
||||
const conn = getConnectorById(connId);
|
||||
if (!conn) return null;
|
||||
|
||||
const pinCount = conn.pinCount || 2;
|
||||
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,
|
||||
}));
|
||||
|
||||
return {
|
||||
diagram_id: diagramId,
|
||||
device_type: "connector",
|
||||
label: conn.name,
|
||||
reference: "",
|
||||
x: 200, y: 200,
|
||||
width: w, height: h,
|
||||
properties: {
|
||||
pinCount,
|
||||
orientation: "right",
|
||||
partNumber: conn.partNumber || "",
|
||||
manufacturer: conn.manufacturer || "",
|
||||
connectorLibraryId: connId,
|
||||
},
|
||||
pins,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
const WIRE_COLORS = [
|
||||
{ name: "Black", hex: "#000000" },
|
||||
{ name: "Brown", hex: "#8B4513" },
|
||||
{ name: "Red", hex: "#CC0000" },
|
||||
{ name: "Orange", hex: "#FF8C00" },
|
||||
{ name: "Yellow", hex: "#FFD700" },
|
||||
{ name: "Green", hex: "#007700" },
|
||||
{ name: "Blue", hex: "#0000CC" },
|
||||
{ name: "Violet", hex: "#7B00CC" },
|
||||
{ name: "Grey", hex: "#808080" },
|
||||
{ name: "White", hex: "#DDDDDD" },
|
||||
{ name: "Pink", hex: "#FF69B4" },
|
||||
{ name: "Tan", hex: "#D2B48C" },
|
||||
];
|
||||
|
||||
const SIDE = { LEFT: "left", RIGHT: "right", TOP: "top", BOTTOM: "bottom" };
|
||||
|
||||
function makePins(side, count, w, h, prefix = "") {
|
||||
return Array.from({ length: count }, (_, i) => {
|
||||
const t = (i + 1) / (count + 1);
|
||||
const x = side === SIDE.LEFT ? 0 : side === SIDE.RIGHT ? w : t * w;
|
||||
const y = side === SIDE.TOP ? 0 : side === SIDE.BOTTOM ? h : t * h;
|
||||
return { id: `${prefix}pin_${i + 1}`, name: String(i + 1), side, x_offset: x, y_offset: y };
|
||||
});
|
||||
}
|
||||
|
||||
const DEVICE_TYPES = {
|
||||
connector: {
|
||||
label: "Connector",
|
||||
description: "Multi-pin connector (inline/header)",
|
||||
icon: "🔌",
|
||||
defaultProps: { pinCount: 4, orientation: "right", partNumber: "", manufacturer: "" },
|
||||
defaultSize: (p) => ({ w: 100, h: Math.max(60, (p.pinCount || 4) * 20 + 20) }),
|
||||
getPins: (p, w, h) => makePins(p.orientation || SIDE.RIGHT, p.pinCount || 4, w, h),
|
||||
},
|
||||
terminal_block: {
|
||||
label: "Terminal Block",
|
||||
description: "Screw terminal block",
|
||||
icon: "⬛",
|
||||
defaultProps: { terminalCount: 4, partNumber: "", manufacturer: "" },
|
||||
defaultSize: (p) => ({ w: Math.max(60, (p.terminalCount || 4) * 24), h: 60 }),
|
||||
getPins: (p, w, h) => {
|
||||
const count = p.terminalCount || 4;
|
||||
const pins = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
const x = ((i + 0.5) / count) * w;
|
||||
pins.push({ id: `t${i + 1}`, name: String(i + 1), side: SIDE.TOP, x_offset: x, y_offset: 0 });
|
||||
pins.push({ id: `b${i + 1}`, name: String(i + 1), side: SIDE.BOTTOM, x_offset: x, y_offset: h });
|
||||
}
|
||||
return pins;
|
||||
},
|
||||
},
|
||||
component: {
|
||||
label: "Component",
|
||||
description: "Generic component / IC",
|
||||
icon: "⬜",
|
||||
defaultProps: { leftPins: 2, rightPins: 2, partNumber: "", manufacturer: "" },
|
||||
defaultSize: () => ({ w: 120, h: 80 }),
|
||||
getPins: (p, w, h) => {
|
||||
const left = makePins(SIDE.LEFT, p.leftPins || 2, w, h, "L");
|
||||
const right = makePins(SIDE.RIGHT, p.rightPins || 2, w, h, "R");
|
||||
left.forEach((pin, i) => (pin.name = `L${i + 1}`));
|
||||
right.forEach((pin, i) => (pin.name = `R${i + 1}`));
|
||||
return [...left, ...right];
|
||||
},
|
||||
},
|
||||
splice: {
|
||||
label: "Splice / Junction",
|
||||
description: "Wire splice or junction point",
|
||||
icon: "✕",
|
||||
defaultProps: {},
|
||||
defaultSize: () => ({ w: 32, h: 32 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "left", name: "L", side: SIDE.LEFT, x_offset: 0, y_offset: h / 2 },
|
||||
{ id: "right", name: "R", side: SIDE.RIGHT, x_offset: w, y_offset: h / 2 },
|
||||
{ id: "top", name: "T", side: SIDE.TOP, x_offset: w / 2, y_offset: 0 },
|
||||
{ id: "bottom", name: "B", side: SIDE.BOTTOM, x_offset: w / 2, y_offset: h },
|
||||
],
|
||||
},
|
||||
label: {
|
||||
label: "Note / Label",
|
||||
description: "Text annotation on the diagram",
|
||||
icon: "📝",
|
||||
defaultProps: { text: "Note" },
|
||||
defaultSize: () => ({ w: 160, h: 40 }),
|
||||
getPins: () => [],
|
||||
},
|
||||
group: {
|
||||
label: "Section Box",
|
||||
description: "Labeled section rectangle for visual grouping",
|
||||
icon: "⬚",
|
||||
defaultProps: { fillColor: "#2828a0", fillOpacity: 0.15 },
|
||||
defaultSize: () => ({ w: 320, h: 220 }),
|
||||
getPins: () => [],
|
||||
},
|
||||
|
||||
// ── Electrical components ───────────────────────────────────────────────────
|
||||
fuse: {
|
||||
label: "Fuse",
|
||||
description: "In-line fuse or fusible link",
|
||||
icon: "⚡",
|
||||
defaultProps: { ampRating: "10A", fuseType: "blade", partNumber: "", manufacturer: "" },
|
||||
defaultSize: () => ({ w: 80, h: 44 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "A", name: "A", side: SIDE.LEFT, x_offset: 0, y_offset: h / 2 },
|
||||
{ id: "B", name: "B", side: SIDE.RIGHT, x_offset: w, y_offset: h / 2 },
|
||||
],
|
||||
},
|
||||
relay: {
|
||||
label: "Relay",
|
||||
description: "Electromagnetic relay — SPDT 5-pin (85/86/30/87/87a)",
|
||||
icon: "🔁",
|
||||
defaultProps: { coilVoltage: "12V", ampRating: "30A", partNumber: "", manufacturer: "" },
|
||||
defaultSize: () => ({ w: 110, h: 100 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "85", name: "85", side: SIDE.LEFT, x_offset: 0, y_offset: h * 0.30 },
|
||||
{ id: "86", name: "86", side: SIDE.LEFT, x_offset: 0, y_offset: h * 0.70 },
|
||||
{ id: "87a", name: "87a", side: SIDE.RIGHT, x_offset: w, y_offset: h * 0.20 },
|
||||
{ id: "30", name: "30", side: SIDE.RIGHT, x_offset: w, y_offset: h * 0.50 },
|
||||
{ id: "87", name: "87", side: SIDE.RIGHT, x_offset: w, y_offset: h * 0.80 },
|
||||
],
|
||||
},
|
||||
switch: {
|
||||
label: "Switch",
|
||||
description: "SPDT switch — common, normally-open, normally-closed",
|
||||
icon: "⎘",
|
||||
defaultProps: { switchType: "SPDT", partNumber: "", manufacturer: "" },
|
||||
defaultSize: () => ({ w: 90, h: 70 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "C", name: "C", side: SIDE.LEFT, x_offset: 0, y_offset: h / 2 },
|
||||
{ id: "NO", name: "NO", side: SIDE.RIGHT, x_offset: w, y_offset: h * 0.30 },
|
||||
{ id: "NC", name: "NC", side: SIDE.RIGHT, x_offset: w, y_offset: h * 0.70 },
|
||||
],
|
||||
},
|
||||
bulb: {
|
||||
label: "Bulb / Light",
|
||||
description: "Indicator lamp or lighting load",
|
||||
icon: "💡",
|
||||
defaultProps: { voltage: "12V", wattage: "", partNumber: "", manufacturer: "" },
|
||||
defaultSize: () => ({ w: 80, h: 50 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "+", name: "+", side: SIDE.LEFT, x_offset: 0, y_offset: h / 2 },
|
||||
{ id: "-", name: "−", side: SIDE.RIGHT, x_offset: w, y_offset: h / 2 },
|
||||
],
|
||||
},
|
||||
motor: {
|
||||
label: "Motor",
|
||||
description: "DC motor or actuator",
|
||||
icon: "⚙",
|
||||
defaultProps: { voltage: "12V", ampRating: "", partNumber: "", manufacturer: "" },
|
||||
defaultSize: () => ({ w: 90, h: 60 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "+", name: "+", side: SIDE.LEFT, x_offset: 0, y_offset: h / 2 },
|
||||
{ id: "-", name: "−", side: SIDE.RIGHT, x_offset: w, y_offset: h / 2 },
|
||||
],
|
||||
},
|
||||
diode: {
|
||||
label: "Diode",
|
||||
description: "Diode, Schottky, or TVS — anode / cathode",
|
||||
icon: "⊳",
|
||||
defaultProps: { diodeType: "rectifier", voltage: "", current: "", partNumber: "", manufacturer: "" },
|
||||
defaultSize: () => ({ w: 80, h: 44 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "A", name: "A", side: SIDE.LEFT, x_offset: 0, y_offset: h / 2 },
|
||||
{ id: "K", name: "K", side: SIDE.RIGHT, x_offset: w, y_offset: h / 2 },
|
||||
],
|
||||
},
|
||||
resistor: {
|
||||
label: "Resistor",
|
||||
description: "Fixed resistor or load",
|
||||
icon: "Ω",
|
||||
defaultProps: { resistance: "", wattage: "", partNumber: "", manufacturer: "" },
|
||||
defaultSize: () => ({ w: 80, h: 44 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "1", name: "1", side: SIDE.LEFT, x_offset: 0, y_offset: h / 2 },
|
||||
{ id: "2", name: "2", side: SIDE.RIGHT, x_offset: w, y_offset: h / 2 },
|
||||
],
|
||||
},
|
||||
capacitor: {
|
||||
label: "Capacitor",
|
||||
description: "Electrolytic or film capacitor",
|
||||
icon: "⊏",
|
||||
defaultProps: { capacitance: "", voltage: "", partNumber: "", manufacturer: "" },
|
||||
defaultSize: () => ({ w: 80, h: 44 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "+", name: "+", side: SIDE.LEFT, x_offset: 0, y_offset: h / 2 },
|
||||
{ id: "-", name: "−", side: SIDE.RIGHT, x_offset: w, y_offset: h / 2 },
|
||||
],
|
||||
},
|
||||
ground: {
|
||||
label: "Ground",
|
||||
description: "Chassis or signal ground reference",
|
||||
icon: "⏚",
|
||||
defaultProps: { groundType: "chassis", reference: "" },
|
||||
defaultSize: () => ({ w: 60, h: 50 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "GND", name: "GND", side: SIDE.TOP, x_offset: w / 2, y_offset: 0 },
|
||||
],
|
||||
},
|
||||
power: {
|
||||
label: "Power Rail",
|
||||
description: "Battery positive, ignition, or supply rail",
|
||||
icon: "⊕",
|
||||
defaultProps: { voltage: "12V", sourceType: "battery", reference: "" },
|
||||
defaultSize: () => ({ w: 70, h: 50 }),
|
||||
getPins: (p, w, h) => [
|
||||
{ id: "PWR", name: "+", side: SIDE.BOTTOM, x_offset: w / 2, y_offset: h },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const CABLE_DEFAULT_COLORS = [
|
||||
"#dddddd", "#cc0000", "#111111", "#007700",
|
||||
"#0000cc", "#ff8c00", "#8b4513", "#7b00cc",
|
||||
];
|
||||
|
||||
const DEVICE_TYPES_EXTRA = {
|
||||
cable: {
|
||||
label: "Cable",
|
||||
description: "Multi-conductor cable under one jacket",
|
||||
icon: "🔗",
|
||||
defaultProps: {
|
||||
conductorCount: 4,
|
||||
partNumber: "",
|
||||
manufacturer: "",
|
||||
jacketColor: "#2a2a2a",
|
||||
sleeveLength: 60,
|
||||
conductors: [
|
||||
{ name: "1", color: "#dddddd" },
|
||||
{ name: "2", color: "#cc0000" },
|
||||
{ name: "3", color: "#111111" },
|
||||
{ name: "4", color: "#007700" },
|
||||
],
|
||||
},
|
||||
defaultSize: (p) => {
|
||||
const n = p.conductorCount || p.conductors?.length || 4;
|
||||
return { w: 200, h: n * 24 + 40 };
|
||||
},
|
||||
getPins: (p, w, h) => {
|
||||
const conductors = p.conductors || Array.from({ length: p.conductorCount || 4 }, (_, i) => ({ name: String(i + 1) }));
|
||||
return conductors.flatMap((c, i) => {
|
||||
const yOff = 26 + i * 24 + 12;
|
||||
return [
|
||||
{ id: `L${i + 1}`, name: c.name || String(i + 1), side: "left", x_offset: 0, y_offset: yOff },
|
||||
{ id: `R${i + 1}`, name: c.name || String(i + 1), side: "right", x_offset: w, y_offset: yOff },
|
||||
];
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Object.assign(DEVICE_TYPES, DEVICE_TYPES_EXTRA);
|
||||
|
||||
function buildDefaultDevice(typeKey, diagramId) {
|
||||
const type = DEVICE_TYPES[typeKey];
|
||||
if (!type) return null;
|
||||
const props = { ...type.defaultProps };
|
||||
const { w, h } = type.defaultSize(props);
|
||||
const pins = type.getPins(props, w, h);
|
||||
return {
|
||||
diagram_id: diagramId,
|
||||
device_type: typeKey,
|
||||
label: type.label,
|
||||
reference: "",
|
||||
x: 200,
|
||||
y: 200,
|
||||
width: w,
|
||||
height: h,
|
||||
properties: props,
|
||||
pins,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user