@deltarobotics/uhd-viewer 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/LICENSE +202 -0
- package/NOTICE +22 -0
- package/README.md +168 -2
- package/bin/serve.d.mts +62 -0
- package/bin/serve.mjs +257 -0
- package/bin/uhd-viewer.mjs +75 -0
- package/dist/app/assets/KodeMono-Bold-DdIivhPN.woff2 +0 -0
- package/dist/app/assets/KodeMono-Medium-CVnTuv5A.ttf +0 -0
- package/dist/app/assets/KodeMono-Regular-Bdr_-rJX.woff2 +0 -0
- package/dist/app/assets/KodeMono-SemiBold-JAfn5Dpm.ttf +0 -0
- package/dist/app/assets/index-Boi2erhd.css +2 -0
- package/dist/app/assets/index-CkpIRYgM.js +3853 -0
- package/dist/app/index.html +16 -0
- package/dist/components/components.css +6108 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +26048 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/types/uhd-viewer/src/api.d.ts +286 -0
- package/dist/components/types/uhd-viewer/src/cad/CadView.d.ts +52 -0
- package/dist/components/types/uhd-viewer/src/cad/ModelView.d.ts +28 -0
- package/dist/components/types/uhd-viewer/src/cad/explode.d.ts +110 -0
- package/dist/components/types/uhd-viewer/src/cad/explodeSample.d.ts +25 -0
- package/dist/components/types/uhd-viewer/src/cad/findings.d.ts +41 -0
- package/dist/components/types/uhd-viewer/src/cad/labels.d.ts +76 -0
- package/dist/components/types/uhd-viewer/src/cad/model.d.ts +132 -0
- package/dist/components/types/uhd-viewer/src/cad/row.d.ts +15 -0
- package/dist/components/types/uhd-viewer/src/cad/scene.d.ts +95 -0
- package/dist/components/types/uhd-viewer/src/cad/scope.d.ts +89 -0
- package/dist/components/types/uhd-viewer/src/canvas/Canvas.d.ts +86 -0
- package/dist/components/types/uhd-viewer/src/canvas/Icon.d.ts +5 -0
- package/dist/components/types/uhd-viewer/src/canvas/LinkEdge.d.ts +40 -0
- package/dist/components/types/uhd-viewer/src/canvas/Port.d.ts +18 -0
- package/dist/components/types/uhd-viewer/src/canvas/actions.d.ts +5 -0
- package/dist/components/types/uhd-viewer/src/canvas/geometry.d.ts +72 -0
- package/dist/components/types/uhd-viewer/src/canvas/interaction.d.ts +162 -0
- package/dist/components/types/uhd-viewer/src/canvas/nodes.d.ts +43 -0
- package/dist/components/types/uhd-viewer/src/canvas/reveal.d.ts +37 -0
- package/dist/components/types/uhd-viewer/src/canvas/rightDrag.d.ts +51 -0
- package/dist/components/types/uhd-viewer/src/canvas/routing.d.ts +28 -0
- package/dist/components/types/uhd-viewer/src/chrome/ArtifactCards.d.ts +30 -0
- package/dist/components/types/uhd-viewer/src/chrome/Artifacts.d.ts +44 -0
- package/dist/components/types/uhd-viewer/src/chrome/BoardInspector.d.ts +53 -0
- package/dist/components/types/uhd-viewer/src/chrome/Chrome.d.ts +116 -0
- package/dist/components/types/uhd-viewer/src/chrome/Evidence.d.ts +20 -0
- package/dist/components/types/uhd-viewer/src/chrome/InterfaceCards.d.ts +56 -0
- package/dist/components/types/uhd-viewer/src/chrome/PairView.d.ts +37 -0
- package/dist/components/types/uhd-viewer/src/chrome/Sections.d.ts +107 -0
- package/dist/components/types/uhd-viewer/src/components.d.ts +60 -0
- package/dist/components/types/uhd-viewer/src/host/channel.d.ts +49 -0
- package/dist/components/types/uhd-viewer/src/host/context.d.ts +29 -0
- package/dist/components/types/uhd-viewer/src/host/protocol.d.ts +22 -0
- package/dist/components/types/uhd-viewer/src/host/targets.d.ts +85 -0
- package/dist/components/types/uhd-viewer/src/layout/board-layout.d.ts +69 -0
- package/dist/components/types/uhd-viewer/src/layout/card-body.d.ts +64 -0
- package/dist/components/types/uhd-viewer/src/layout/layout.d.ts +94 -0
- package/dist/components/types/uhd-viewer/src/layout/module-layout.d.ts +32 -0
- package/dist/components/types/uhd-viewer/src/layout/router.d.ts +55 -0
- package/dist/components/types/uhd-viewer/src/layout/taps.d.ts +20 -0
- package/dist/components/types/uhd-viewer/src/model/artifacts.d.ts +129 -0
- package/dist/components/types/uhd-viewer/src/model/classification.d.ts +38 -0
- package/dist/components/types/uhd-viewer/src/model/diagnostics.d.ts +27 -0
- package/dist/components/types/uhd-viewer/src/model/evidence.d.ts +63 -0
- package/dist/components/types/uhd-viewer/src/model/from-uhd.d.ts +57 -0
- package/dist/components/types/uhd-viewer/src/model/hierarchy.d.ts +169 -0
- package/dist/components/types/uhd-viewer/src/model/isolate.d.ts +33 -0
- package/dist/components/types/uhd-viewer/src/model/nets.d.ts +53 -0
- package/dist/components/types/uhd-viewer/src/model/outputs.d.ts +79 -0
- package/dist/components/types/uhd-viewer/src/model/slots.d.ts +182 -0
- package/dist/components/types/uhd-viewer/src/model/types.d.ts +213 -0
- package/dist/components/types/uhd-viewer/src/options.d.ts +27 -0
- package/dist/components/types/uhd-viewer/src/source/source.d.ts +109 -0
- package/dist/components/types/uhd-viewer/src/source/tolerant.d.ts +45 -0
- package/dist/components/types/uhd-viewer/src/theme/ThemeProvider.d.ts +33 -0
- package/dist/components/types/uhd-viewer/src/theme/adapters.d.ts +28 -0
- package/dist/components/types/uhd-viewer/src/theme/resolve.d.ts +19 -0
- package/dist/components/types/uhd-viewer/src/theme/themes.d.ts +67 -0
- package/dist/components/types/uhd-viewer/src/theme/tokens.d.ts +175 -0
- package/dist/components/types/uhd-viewer/src/ui/Inspector.d.ts +45 -0
- package/dist/components/types/uhd-viewer/src/ui/Legend.d.ts +40 -0
- package/dist/components/types/uhd-viewer/src/ui/ScrollArea.d.ts +16 -0
- package/dist/components/types/uhd-viewer/src/ui/Toolbar.d.ts +49 -0
- package/dist/components/types/uhd-viewer/src/ui/Tooltips.d.ts +3 -0
- package/dist/components/types/uhd-viewer/src/ui/cx.d.ts +2 -0
- package/dist/components/types/uhd-viewer/src/ui/legendFit.d.ts +42 -0
- package/dist/components/types/uhd-viewer/src/viewer/controller.d.ts +218 -0
- package/dist/components/types/uhd-viewer/src/viewer/details.d.ts +81 -0
- package/dist/components/types/uhd-viewer/src/viewer/hierarchy.d.ts +60 -0
- package/dist/components/types/uhd-viewer/src/viewer/mount.d.ts +12 -0
- package/dist/components/types/uhd-viewer/src/viewer/views.d.ts +156 -0
- package/dist/headless/index.d.ts +71 -0
- package/dist/headless/index.js +7425 -0
- package/dist/headless/index.js.map +1 -0
- package/dist/lib/api.d.ts +252 -0
- package/dist/lib/uhd-viewer.css +3 -0
- package/dist/lib/uhd-viewer.d.ts +4 -0
- package/dist/lib/uhd-viewer.js +97469 -0
- package/package.json +110 -4
- package/src/styles/fonts/OFL.txt +93 -0
- package/src/styles/tailwind-theme.css +48 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standard outputs (PB-823): the files a capability provider exports for a
|
|
3
|
+
* custom module, which the viewer reads as ordinary artifacts. It finds them
|
|
4
|
+
* by their fixed file names (protoboard-cli docs/specs/tool-integrations.md
|
|
5
|
+
* §8) and never by the tool that wrote them:
|
|
6
|
+
*
|
|
7
|
+
* circuit board.glb, board.manifest.json, bom.csv, pnp.csv, netlist.json,
|
|
8
|
+
* and the drawings schematic.svg, pcb-top.svg, pcb-bottom.svg
|
|
9
|
+
* cad body.glb, body.manifest.json, and print/cut exports (.stl, .3mf, .dxf)
|
|
10
|
+
*
|
|
11
|
+
* PCB drawings are in board millimetres: one SVG user unit is 1 mm, the top
|
|
12
|
+
* view draws board (x, y) at (x, −y), and the bottom view, seen from below,
|
|
13
|
+
* at (−x, −y), with (x, y) as in pnp.csv and the geometry manifest. That is
|
|
14
|
+
* what lets the viewer mark a component on them from its pick-and-place row.
|
|
15
|
+
* A drawing whose viewBox does not hold the placed components is shown
|
|
16
|
+
* without marks.
|
|
17
|
+
*/
|
|
18
|
+
import type { ArtifactDef, ModuleDef } from "@deltarobotics/uhd";
|
|
19
|
+
import type { GeometryManifest } from "@deltarobotics/uhd";
|
|
20
|
+
import type { ModuleLookup } from "@deltarobotics/uhd";
|
|
21
|
+
export interface CircuitOutputs {
|
|
22
|
+
glb?: ArtifactDef;
|
|
23
|
+
manifest?: ArtifactDef;
|
|
24
|
+
bom?: ArtifactDef;
|
|
25
|
+
pnp?: ArtifactDef;
|
|
26
|
+
netlist?: ArtifactDef;
|
|
27
|
+
schematic?: ArtifactDef;
|
|
28
|
+
top?: ArtifactDef;
|
|
29
|
+
bottom?: ArtifactDef;
|
|
30
|
+
}
|
|
31
|
+
export interface CadOutputs {
|
|
32
|
+
glb?: ArtifactDef;
|
|
33
|
+
manifest?: ArtifactDef;
|
|
34
|
+
/** Manufacturing exports: STL, 3MF, DXF. */
|
|
35
|
+
exports: ArtifactDef[];
|
|
36
|
+
}
|
|
37
|
+
/** A module's circuit standard outputs, by file name; undefined when it has none of them. */
|
|
38
|
+
export declare function circuitOutputs(def: ModuleDef | undefined): CircuitOutputs | undefined;
|
|
39
|
+
/** A module's cad standard outputs, by file name; undefined when it has none of them. */
|
|
40
|
+
export declare function cadOutputs(def: ModuleDef | undefined): CadOutputs | undefined;
|
|
41
|
+
/** Standard output drawings are views of the board, not pictures of the part: never its thumbnail. */
|
|
42
|
+
export declare const isBoardDrawing: (a: ArtifactDef) => boolean;
|
|
43
|
+
/** RFC 4180 CSV with a header row, as rows of named fields. */
|
|
44
|
+
export declare function parseCsv(text: string): Record<string, string>[];
|
|
45
|
+
export interface PnpRow {
|
|
46
|
+
instance: string;
|
|
47
|
+
x: number;
|
|
48
|
+
y: number;
|
|
49
|
+
rotation: number;
|
|
50
|
+
side: "top" | "bottom";
|
|
51
|
+
}
|
|
52
|
+
/** Pick-and-place rows (`instance`, `x_mm`, `y_mm`, `rotation_deg`, `side`); rows that do not parse are left out. */
|
|
53
|
+
export declare function parsePnp(text: string): PnpRow[];
|
|
54
|
+
/** Where a component sits on the board: a rectangle in board millimetres. */
|
|
55
|
+
export interface Footprint {
|
|
56
|
+
instance: string;
|
|
57
|
+
side: "top" | "bottom";
|
|
58
|
+
/** Centre (board mm). */
|
|
59
|
+
x: number;
|
|
60
|
+
y: number;
|
|
61
|
+
/** Size along board x and y, after rotation. */
|
|
62
|
+
w: number;
|
|
63
|
+
h: number;
|
|
64
|
+
/** Where the size came from: the part's package facts, or the manifest feature's area. */
|
|
65
|
+
size: "package" | "manifest" | "unknown";
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Every placed component's rectangle: its pick-and-place position, sized by
|
|
69
|
+
* the part's package (length × width, turned by the row's rotation), else by
|
|
70
|
+
* the manifest feature named by its instance path (a square of its area),
|
|
71
|
+
* else a 1 mm square.
|
|
72
|
+
*/
|
|
73
|
+
export declare function footprints(board: ModuleDef, lookup: ModuleLookup, pnp: PnpRow[], manifest?: GeometryManifest): Footprint[];
|
|
74
|
+
/** Board millimetres → drawing units for one side (the convention above). */
|
|
75
|
+
export declare const toDrawing: (side: "top" | "bottom", x: number, y: number) => [number, number];
|
|
76
|
+
/** Whether a drawing's viewBox holds every component placed on its side (else its marks would be wrong). */
|
|
77
|
+
export declare function drawingFits(viewBox: [number, number, number, number], side: "top" | "bottom", fps: Footprint[]): boolean;
|
|
78
|
+
/** The component under a point of a drawing, smallest first (a resistor under a chip's corner wins). */
|
|
79
|
+
export declare function footprintAt(side: "top" | "bottom", fps: Footprint[], dx: number, dy: number, slack?: number): Footprint | undefined;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A module's interfaces as the inspector's slot cards (PB-1042, design A with
|
|
3
|
+
* expandable cards, 2026-10-21): what each interface is (its kind, protocol,
|
|
4
|
+
* role and pins), what it is linked to and through which harness, and, for
|
|
5
|
+
* the card opened, its pin mapping, its stated parameters, its links and the
|
|
6
|
+
* links derived over them with their state, its findings, its notes and
|
|
7
|
+
* assumptions, and the sources it cites. Plain data from the view model and
|
|
8
|
+
* the definitions; nothing here draws.
|
|
9
|
+
*/
|
|
10
|
+
import type { InterfaceDef, ModuleDef } from "@deltarobotics/uhd";
|
|
11
|
+
import type { ViewModel, ViewNode, ViewPort } from "./types";
|
|
12
|
+
export type SlotKind = "power" | "signal" | "mechanical";
|
|
13
|
+
/** A link's state in the inspector's words: a stored link is configured, a derived one compatible. */
|
|
14
|
+
export type SlotState = "configured" | "compatible" | "warning" | "incompatible" | "unconfigured";
|
|
15
|
+
/** One pin or slot of the interface, the leaf it binds, and what it meets on the other side. */
|
|
16
|
+
export interface SlotPin {
|
|
17
|
+
/** The pin or slot as the board names it ("RX2", "BAT+"). */
|
|
18
|
+
pin: string;
|
|
19
|
+
/** The leaf interface it binds on this module ("uart2_rx"), when it is not the pin itself. */
|
|
20
|
+
leaf?: string;
|
|
21
|
+
/** `←` into this module, `→` out of it, `—` a shared return (ground), `↔` both or not known. */
|
|
22
|
+
dir: "←" | "→" | "—" | "↔";
|
|
23
|
+
/** The pin it meets on the other side, and that module's name. */
|
|
24
|
+
other?: string;
|
|
25
|
+
otherModule?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface SlotParam {
|
|
28
|
+
label: string;
|
|
29
|
+
value: string;
|
|
30
|
+
}
|
|
31
|
+
export interface SlotLink {
|
|
32
|
+
/** The link's id as its module declares it ("rx_pads"), or a derived link's name. */
|
|
33
|
+
label: string;
|
|
34
|
+
/** Its name as declared ("Receiver wires on the FC"). */
|
|
35
|
+
name?: string;
|
|
36
|
+
/** What to select in the viewer for it: a canonical id on the level shown. */
|
|
37
|
+
select: string;
|
|
38
|
+
/** The harness or cable it runs through. */
|
|
39
|
+
via?: string;
|
|
40
|
+
state: SlotState;
|
|
41
|
+
/** A link UHD derives over this one (through a cable's conductors, over a net). */
|
|
42
|
+
derived?: boolean;
|
|
43
|
+
/** The finding messages the viewer's checks put on it. */
|
|
44
|
+
diagnostics: string[];
|
|
45
|
+
}
|
|
46
|
+
export interface SlotFinding {
|
|
47
|
+
/** The host's key for it, when the host gave the finding (its Locate). */
|
|
48
|
+
key?: string;
|
|
49
|
+
code: string;
|
|
50
|
+
message: string;
|
|
51
|
+
severity: "error" | "warning" | "info";
|
|
52
|
+
}
|
|
53
|
+
export interface SlotNote {
|
|
54
|
+
/** What the trait is ("Usage note", "Assumption", "Data gap"). */
|
|
55
|
+
label: string;
|
|
56
|
+
text: string;
|
|
57
|
+
/** An `assumption` trait, or a relation stated as assumed: marked as such. */
|
|
58
|
+
assumption?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface SlotSource {
|
|
61
|
+
label: string;
|
|
62
|
+
url: string;
|
|
63
|
+
}
|
|
64
|
+
export interface InterfaceSlot {
|
|
65
|
+
/** The port's id on the module. */
|
|
66
|
+
id: string;
|
|
67
|
+
name: string;
|
|
68
|
+
kind: SlotKind;
|
|
69
|
+
/** "UART · CRSF", "Power in", "USB". */
|
|
70
|
+
protocol?: string;
|
|
71
|
+
/** "host", "sink", "source", "device". */
|
|
72
|
+
role?: string;
|
|
73
|
+
/** Its pins, as chips. */
|
|
74
|
+
pins: string[];
|
|
75
|
+
/** The modules it is linked to, each with the harness the link runs through. */
|
|
76
|
+
linked: {
|
|
77
|
+
module: string;
|
|
78
|
+
via?: string;
|
|
79
|
+
}[];
|
|
80
|
+
/** Linked to nothing, and not part of an interface that is. */
|
|
81
|
+
open: boolean;
|
|
82
|
+
/** Linked through another interface of the module that binds it (an exported pad inside a linked pad group). */
|
|
83
|
+
usedBy?: string;
|
|
84
|
+
/** Exported to the boundary of the module it is in, by that name: linked from outside, not open. */
|
|
85
|
+
exportedAs?: string;
|
|
86
|
+
/** The worst state of its links. */
|
|
87
|
+
state?: SlotState;
|
|
88
|
+
pinMap: SlotPin[];
|
|
89
|
+
params: SlotParam[];
|
|
90
|
+
links: SlotLink[];
|
|
91
|
+
findings: SlotFinding[];
|
|
92
|
+
notes: SlotNote[];
|
|
93
|
+
sources: SlotSource[];
|
|
94
|
+
/** Canonical refs of the interface and its links, for findings and Locate (`stack:rx_fc_pads`, `rx_pads`). */
|
|
95
|
+
refs: string[];
|
|
96
|
+
/** A card for several alike interfaces (Motor pads ×4): their ids. */
|
|
97
|
+
members?: string[];
|
|
98
|
+
/** What such a card is linked to, said once ("4 arms" via "Motor phase leads"). */
|
|
99
|
+
together?: {
|
|
100
|
+
module: string;
|
|
101
|
+
via?: string;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/** A finding the host knows about, with the canonical ids it is about (links as the viewer selects them, interfaces as `path:id`). */
|
|
105
|
+
export interface HostFinding {
|
|
106
|
+
key: string;
|
|
107
|
+
code: string;
|
|
108
|
+
message: string;
|
|
109
|
+
severity: "error" | "warning" | "info";
|
|
110
|
+
refs: string[];
|
|
111
|
+
}
|
|
112
|
+
export interface SlotOptions {
|
|
113
|
+
/** Definitions by id: the module's own, its children's (leaves bound by its pad groups) and the other ends'. */
|
|
114
|
+
lookup: (id: string) => ModuleDef | undefined;
|
|
115
|
+
/** The level the view model is of, from the root (canonical ids are joined to it). */
|
|
116
|
+
drill?: string[];
|
|
117
|
+
/** Names as written in the model, by node id on the level (the view model's labels are upper case). */
|
|
118
|
+
names?: Map<string, string>;
|
|
119
|
+
/** Link names as declared, by link id on the level. */
|
|
120
|
+
linkNames?: Map<string, string>;
|
|
121
|
+
/** Findings of the host (with their keys) or of the viewer's own checks. */
|
|
122
|
+
findings?: HostFinding[];
|
|
123
|
+
}
|
|
124
|
+
/** "max_current" → "Max current", "rx_fc_pads" → "RX FC pads". */
|
|
125
|
+
export declare function humanize(id: string): string;
|
|
126
|
+
/** "BATTERY LEAD" → "Battery lead": a label the view model upper-cased, back in sentence case. */
|
|
127
|
+
export declare function sentence(label: string): string;
|
|
128
|
+
/** A parameter with its unit: "5 V", "6–30 V", "2–6" (dimensionless). */
|
|
129
|
+
export declare function paramValue(p: {
|
|
130
|
+
value?: number;
|
|
131
|
+
unit?: string;
|
|
132
|
+
range?: [number, number];
|
|
133
|
+
}): string | undefined;
|
|
134
|
+
/** An interface by id: the module's own, an export's child interface, or a leaf of a child (one or two levels down). */
|
|
135
|
+
export declare function findInterface(def: ModuleDef | undefined, id: string, lookup: SlotOptions["lookup"], depth?: number): InterfaceDef | undefined;
|
|
136
|
+
/** Which way a pin faces, from its leaf's roles, else from its name. */
|
|
137
|
+
export declare function direction(leaf: InterfaceDef | undefined, name: string): SlotPin["dir"];
|
|
138
|
+
/** Power (red), signal (blue) or mechanical (grey): the slot glyph's colour. */
|
|
139
|
+
export declare function slotKind(port: ViewPort, leaves: (InterfaceDef | undefined)[], lanes: string[]): SlotKind;
|
|
140
|
+
/** "dolphinrc.com · …e-165929bb5a.pdf": where a source is, short. */
|
|
141
|
+
export declare function sourceLabel(url: string): string;
|
|
142
|
+
/** Every interface of the node as a slot card, linked ones first, then open ones, then those used through another. */
|
|
143
|
+
export declare function interfaceSlots(node: ViewNode, vm: ViewModel, opts: SlotOptions): InterfaceSlot[];
|
|
144
|
+
/**
|
|
145
|
+
* Interfaces that differ only by a number (Motor 1 pads … Motor 4 pads), alike in kind, protocol and state of
|
|
146
|
+
* linking, as one card: "Motor pads ×4", its pins and its links those of every member. Three or more.
|
|
147
|
+
*/
|
|
148
|
+
export declare function groupSlots(slots: InterfaceSlot[]): InterfaceSlot[];
|
|
149
|
+
/** The Interfaces section's header: "6 linked · 1 open", counting each interface of a grouped card. */
|
|
150
|
+
export declare function slotSummary(slots: InterfaceSlot[]): {
|
|
151
|
+
total: number;
|
|
152
|
+
linked: number;
|
|
153
|
+
open: number;
|
|
154
|
+
used: number;
|
|
155
|
+
text: string;
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* The viewer's own findings as host findings: UHD's checks of the level and
|
|
159
|
+
* the bundle producer's, each with the canonical ids it is about (links
|
|
160
|
+
* without their `link:` prefix, re-based onto the root).
|
|
161
|
+
*/
|
|
162
|
+
export declare function checkFindings(checks: {
|
|
163
|
+
id: string;
|
|
164
|
+
rule: string;
|
|
165
|
+
severity: "error" | "warning" | "info";
|
|
166
|
+
message: string;
|
|
167
|
+
refs: string[];
|
|
168
|
+
scope?: string;
|
|
169
|
+
}[], producer?: {
|
|
170
|
+
code: string;
|
|
171
|
+
severity: "error" | "warning" | "info";
|
|
172
|
+
message: string;
|
|
173
|
+
entity?: {
|
|
174
|
+
kind: string;
|
|
175
|
+
id: string;
|
|
176
|
+
};
|
|
177
|
+
}[]): HostFinding[];
|
|
178
|
+
/** Names as written, by node id on a level (the view model's labels are upper case), and its links' names by id. */
|
|
179
|
+
export declare function levelNames(vm: ViewModel, level: ModuleDef | undefined, lookup: (id: string) => ModuleDef | undefined): {
|
|
180
|
+
names: Map<string, string>;
|
|
181
|
+
linkNames: Map<string, string>;
|
|
182
|
+
};
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Neutral view contract (PB-784). The canvas renders only these types; the
|
|
3
|
+
* UHD adapter (./from-uhd.ts) produces them from a system ModuleDef.
|
|
4
|
+
* Every id is a canonical path so layout and selection survive model edits.
|
|
5
|
+
*/
|
|
6
|
+
export type LinkState = "configured" | "partial" | "incompatible" | "unconfigured";
|
|
7
|
+
export type NodeKind = "module" | "group" | "harness" | "board" | "net";
|
|
8
|
+
export type Shape = "rect" | "circle" | "pill";
|
|
9
|
+
/** A child interface revealed when a link is opened (a slot and the leaf bound to it). */
|
|
10
|
+
export interface ViewChildPort {
|
|
11
|
+
slotId: string;
|
|
12
|
+
name: string;
|
|
13
|
+
/** Leaf interface id on the module, e.g. "gnss_uart_tx". */
|
|
14
|
+
leafId?: string;
|
|
15
|
+
/** Pad or pin label, e.g. "TX". */
|
|
16
|
+
pin?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ViewPort {
|
|
19
|
+
/** Interface id on its module (or export id on a group/module boundary). */
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
domain: string;
|
|
23
|
+
/** Primary protocol type, used for signal-type classification and grouping. */
|
|
24
|
+
protocol: string;
|
|
25
|
+
roles: string[];
|
|
26
|
+
children: ViewChildPort[];
|
|
27
|
+
/** True when the port is a boundary export of a child interface. */
|
|
28
|
+
exported?: {
|
|
29
|
+
child: string;
|
|
30
|
+
interfaceId: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export interface ViewNode {
|
|
34
|
+
/** Canonical path, e.g. "stack/esc" or "arm_fl". */
|
|
35
|
+
id: string;
|
|
36
|
+
label: string;
|
|
37
|
+
icon: string;
|
|
38
|
+
kind: NodeKind;
|
|
39
|
+
/** Parent node path when drawn inside an expanded module or group. */
|
|
40
|
+
parent?: string;
|
|
41
|
+
/** True when the node has children and is drawn expanded in place. */
|
|
42
|
+
expanded?: boolean;
|
|
43
|
+
ports: ViewPort[];
|
|
44
|
+
shape: Shape;
|
|
45
|
+
status: LinkState;
|
|
46
|
+
/** UHD definition id, for the inspector. */
|
|
47
|
+
defId?: string;
|
|
48
|
+
manufacturer?: string;
|
|
49
|
+
partNumber?: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
category?: string;
|
|
52
|
+
childCount: number;
|
|
53
|
+
/** A boundary port of the drilled-into module, drawn at the canvas edge. */
|
|
54
|
+
sheetPort?: boolean;
|
|
55
|
+
/** A board net (PB-823): drawn as a junction its members' grouped membership links meet at. */
|
|
56
|
+
net?: ViewNet;
|
|
57
|
+
/**
|
|
58
|
+
* A rail drawn in several places (PB-873): this junction is a local tap of the
|
|
59
|
+
* net junction with this id, joined to the members near it. Selecting a tap
|
|
60
|
+
* selects the net.
|
|
61
|
+
*/
|
|
62
|
+
tapOf?: string;
|
|
63
|
+
/** The bundle does not hold this module's definition: a placeholder with the interfaces its links name. */
|
|
64
|
+
missing?: boolean;
|
|
65
|
+
}
|
|
66
|
+
/** A net on a board (UHD `Net` interface, exposed: false), as a junction node. */
|
|
67
|
+
export interface ViewNet {
|
|
68
|
+
/** Net interface id on the board, e.g. "v3v3". */
|
|
69
|
+
id: string;
|
|
70
|
+
name: string;
|
|
71
|
+
/** What the net carries, for the signal classification: "power", "ground", "i2c", "digital"… */
|
|
72
|
+
signal: string;
|
|
73
|
+
/** Design voltage as stated on the net ("3.3 V", "2.5–5.5 V"). */
|
|
74
|
+
voltage?: string;
|
|
75
|
+
/** A ground net: drawn as ground symbols at its members unless GND wires are on. */
|
|
76
|
+
ground: boolean;
|
|
77
|
+
/** Pins on the net. */
|
|
78
|
+
pins: number;
|
|
79
|
+
}
|
|
80
|
+
export interface ViewEndpoint {
|
|
81
|
+
node: string;
|
|
82
|
+
port: string;
|
|
83
|
+
}
|
|
84
|
+
export interface ViewChildLink {
|
|
85
|
+
id: string;
|
|
86
|
+
label: string;
|
|
87
|
+
a: string;
|
|
88
|
+
b: string;
|
|
89
|
+
aPin?: string;
|
|
90
|
+
bPin?: string;
|
|
91
|
+
state: LinkState;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* One lane of an expanded link (PB-803/805): a child interface of the link,
|
|
95
|
+
* or a link derived through a cable. A lane with its own children is itself a
|
|
96
|
+
* bundle and can be opened in place.
|
|
97
|
+
*/
|
|
98
|
+
export interface ViewLane {
|
|
99
|
+
id: string;
|
|
100
|
+
name: string;
|
|
101
|
+
domain: string;
|
|
102
|
+
protocol: string;
|
|
103
|
+
state: LinkState;
|
|
104
|
+
children: ViewLane[];
|
|
105
|
+
/** Conductor ids this lane carries (ribbon mode groups them under the lane). */
|
|
106
|
+
conductors?: string[];
|
|
107
|
+
}
|
|
108
|
+
/** One physical conductor of a link, for ribbon (detailed) mode. */
|
|
109
|
+
export interface ViewConductor {
|
|
110
|
+
id: string;
|
|
111
|
+
label: string;
|
|
112
|
+
/** Signal protocol of the conductor, for its colour ("power", "ground", "uart", …). */
|
|
113
|
+
protocol: string;
|
|
114
|
+
domain: string;
|
|
115
|
+
/** DRC state of the connection this conductor carries. */
|
|
116
|
+
state: LinkState;
|
|
117
|
+
}
|
|
118
|
+
/** The harness a link runs through, drawn as a region along its route. */
|
|
119
|
+
export interface ViewHarnessRun {
|
|
120
|
+
/** Harness child path at this level. */
|
|
121
|
+
id: string;
|
|
122
|
+
/** Its UHD definition id (for the inspector: artifacts, thumbnail, CAD). */
|
|
123
|
+
defId: string;
|
|
124
|
+
name: string;
|
|
125
|
+
icon: string;
|
|
126
|
+
/** Carried by a physical cable (connector ends) rather than named on a logical link. */
|
|
127
|
+
physical: boolean;
|
|
128
|
+
/** Only the first link of a harness carries its name tab. */
|
|
129
|
+
tab: boolean;
|
|
130
|
+
}
|
|
131
|
+
export interface ViewLink {
|
|
132
|
+
id: string;
|
|
133
|
+
source: ViewEndpoint;
|
|
134
|
+
target: ViewEndpoint;
|
|
135
|
+
name: string;
|
|
136
|
+
domain: string;
|
|
137
|
+
protocol: string;
|
|
138
|
+
state: LinkState;
|
|
139
|
+
children: ViewChildLink[];
|
|
140
|
+
/** Pass-through from a boundary export to the child interface it exposes. */
|
|
141
|
+
passThrough?: boolean;
|
|
142
|
+
/** Ground return: drawn as ground symbols at both ports instead of a wire. */
|
|
143
|
+
ground?: boolean;
|
|
144
|
+
/** Harness node carrying the link, if any. */
|
|
145
|
+
harness?: string;
|
|
146
|
+
/**
|
|
147
|
+
* A link carried by a harness is drawn as two segments through the harness
|
|
148
|
+
* node: "a" (source → harness, carries the label) and "b" (harness → target).
|
|
149
|
+
*/
|
|
150
|
+
segment?: "a" | "b";
|
|
151
|
+
/** Stored link id (shared by both segments). */
|
|
152
|
+
linkId: string;
|
|
153
|
+
/** Other stored link ids drawn by this link (the second half of a cable). */
|
|
154
|
+
alsoIds?: string[];
|
|
155
|
+
/** Lanes shown when the link is expanded (basic mode). */
|
|
156
|
+
lanes?: ViewLane[];
|
|
157
|
+
/** Conductors shown in ribbon (detailed) mode. */
|
|
158
|
+
conductors?: ViewConductor[];
|
|
159
|
+
/** Harness region along the route. */
|
|
160
|
+
run?: ViewHarnessRun;
|
|
161
|
+
/** Child links are a stored override (remapped by the user). */
|
|
162
|
+
manual?: boolean;
|
|
163
|
+
/** Grouped net membership (PB-823): one line from a component to a net, its pins as children. */
|
|
164
|
+
net?: {
|
|
165
|
+
id: string;
|
|
166
|
+
name: string;
|
|
167
|
+
};
|
|
168
|
+
diagnostics: string[];
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* A functional link UHD derives over a board's nets (an I2C bus, a supply to
|
|
172
|
+
* a load). It is not drawn as a line of its own: the membership lines it runs
|
|
173
|
+
* over (`via`) carry its state, and the inspector lists it by name.
|
|
174
|
+
*/
|
|
175
|
+
export interface ViewDerived {
|
|
176
|
+
/** Derived link id (long: the membership links it runs over), prefixed like stored link ids. */
|
|
177
|
+
id: string;
|
|
178
|
+
/** Its name, "I2C0 ↔ I2C": what the viewer shows instead of the id. */
|
|
179
|
+
name: string;
|
|
180
|
+
protocol: string;
|
|
181
|
+
state: LinkState;
|
|
182
|
+
a: {
|
|
183
|
+
node: string;
|
|
184
|
+
iface: string;
|
|
185
|
+
};
|
|
186
|
+
b: {
|
|
187
|
+
node: string;
|
|
188
|
+
iface: string;
|
|
189
|
+
};
|
|
190
|
+
/** Net node ids it runs over. */
|
|
191
|
+
nets: string[];
|
|
192
|
+
/** View link ids (grouped memberships) it runs over. */
|
|
193
|
+
via: string[];
|
|
194
|
+
/** Conductors: each slot (or pin) and the one it is wired to. */
|
|
195
|
+
children: {
|
|
196
|
+
a: string;
|
|
197
|
+
aPin?: string;
|
|
198
|
+
b: string;
|
|
199
|
+
bPin?: string;
|
|
200
|
+
}[];
|
|
201
|
+
diagnostics: string[];
|
|
202
|
+
}
|
|
203
|
+
export interface ViewModel {
|
|
204
|
+
/** Breadcrumb labels for the level being viewed. */
|
|
205
|
+
path: {
|
|
206
|
+
id: string;
|
|
207
|
+
label: string;
|
|
208
|
+
}[];
|
|
209
|
+
nodes: ViewNode[];
|
|
210
|
+
links: ViewLink[];
|
|
211
|
+
/** Functional links derived over the level's nets (and nets of modules expanded in place). */
|
|
212
|
+
derived: ViewDerived[];
|
|
213
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a host's option changes apply (ViewerHandle.update). Kept apart from
|
|
3
|
+
* mount.tsx so it can be tested without a page.
|
|
4
|
+
*/
|
|
5
|
+
import type { ViewerLayout, ViewerOptions, ViewerViewport } from "./api";
|
|
6
|
+
/**
|
|
7
|
+
* The options after `update(change)`: the change is merged into the current
|
|
8
|
+
* options. A change that names `bundleUrl` and not `bundle` switches to
|
|
9
|
+
* loading from that URL (a given `bundle` would otherwise keep precedence).
|
|
10
|
+
*/
|
|
11
|
+
export declare function mergeOptions<T extends ViewerOptions>(current: T, change: Partial<ViewerOptions>): T;
|
|
12
|
+
/** The same layout edits (a host passing back what the viewer sent is not a change). */
|
|
13
|
+
export declare function sameLayout(a: ViewerLayout | undefined, b: ViewerLayout | undefined): boolean;
|
|
14
|
+
/** The same saved viewports, whatever order their levels come in (a host passing back what the viewer sent is not a change). */
|
|
15
|
+
export declare function sameViewports(a: Record<string, ViewerViewport> | undefined, b: Record<string, ViewerViewport> | undefined): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* What a host's `viewports` option asks of a mounted viewer (PB-1037):
|
|
18
|
+
* `replace` when the viewer must take them (the host passed viewports it was
|
|
19
|
+
* not sent, or it took over keeping them, or gave that up), `keep` otherwise.
|
|
20
|
+
* `known` is what the host has: what it passed last or what it was last sent.
|
|
21
|
+
*/
|
|
22
|
+
export declare function hostViewportsChange(o: {
|
|
23
|
+
hosted: boolean;
|
|
24
|
+
wasHosted: boolean;
|
|
25
|
+
host: Record<string, ViewerViewport> | undefined;
|
|
26
|
+
known: Record<string, ViewerViewport> | undefined;
|
|
27
|
+
}): "replace" | "keep";
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { type UhdBundle, type UhdBundleDiagnostic } from "@deltarobotics/uhd";
|
|
2
|
+
import type { ModuleDef } from "@deltarobotics/uhd";
|
|
3
|
+
import type { ModuleLookup } from "@deltarobotics/uhd";
|
|
4
|
+
import type { LevelLayout } from "../layout/layout";
|
|
5
|
+
import type { ArtifactResolver, ViewerOptions } from "../api";
|
|
6
|
+
import { type LeftOut, type MissingDefinition } from "./tolerant";
|
|
7
|
+
export interface ViewerScenario {
|
|
8
|
+
id: string;
|
|
9
|
+
label: string;
|
|
10
|
+
description: string;
|
|
11
|
+
system: ModuleDef;
|
|
12
|
+
lookup: ModuleLookup;
|
|
13
|
+
/** Definitions the bundle names and does not hold: drawn as placeholders (source/tolerant.ts). */
|
|
14
|
+
missing: MissingDefinition[];
|
|
15
|
+
/** Links and exports that could not be resolved, and are not drawn. */
|
|
16
|
+
leftOut: LeftOut[];
|
|
17
|
+
}
|
|
18
|
+
/** Surface appearance for a definition (and optionally named sub-bodies of its CAD). */
|
|
19
|
+
export interface Appearance {
|
|
20
|
+
color?: string;
|
|
21
|
+
metalness?: number;
|
|
22
|
+
roughness?: number;
|
|
23
|
+
opacity?: number;
|
|
24
|
+
parts?: Record<string, Omit<Appearance, "parts">>;
|
|
25
|
+
}
|
|
26
|
+
export interface LabelHint {
|
|
27
|
+
title?: string;
|
|
28
|
+
sub?: string;
|
|
29
|
+
hide?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** Presentation hints keyed by instance path. Never topology. */
|
|
32
|
+
export interface DisplayConfig {
|
|
33
|
+
diagram?: {
|
|
34
|
+
/** Hand layouts per drill level ("" = top). */
|
|
35
|
+
layouts?: Record<string, LevelLayout>;
|
|
36
|
+
/** Instance paths drawn expanded in place by default. */
|
|
37
|
+
expanded?: string[];
|
|
38
|
+
/** Links opened (conductors shown) by default. */
|
|
39
|
+
openLinks?: string[];
|
|
40
|
+
};
|
|
41
|
+
spatial?: {
|
|
42
|
+
/** Instance path the assembly is placed from (default: the best-connected structure). */
|
|
43
|
+
root?: string;
|
|
44
|
+
/** Explicit placements for modules no mate reaches (row-major 4×4, root coordinates). */
|
|
45
|
+
placements?: Record<string, {
|
|
46
|
+
matrix: number[];
|
|
47
|
+
note?: string;
|
|
48
|
+
}>;
|
|
49
|
+
labels?: {
|
|
50
|
+
modules?: Record<string, LabelHint>;
|
|
51
|
+
/** Fastener harnesses and routed wire harnesses, by instance path. */
|
|
52
|
+
harnesses?: Record<string, LabelHint>;
|
|
53
|
+
};
|
|
54
|
+
/** By definition id. */
|
|
55
|
+
appearance?: Record<string, Appearance>;
|
|
56
|
+
/** How the 3D view opens (PB-873). */
|
|
57
|
+
view?: SpatialView;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The 3D view's opening camera, in the root's coordinates. Presentation only:
|
|
62
|
+
* a watch modelled display-down (its case's frame has the display at −z)
|
|
63
|
+
* says `up: [0, 0, -1]` and opens display-up, without changing the model.
|
|
64
|
+
*/
|
|
65
|
+
export interface SpatialView {
|
|
66
|
+
/** The direction drawn up (default [0, 0, 1]): the camera's up, the orbit axis and the ground grid follow it. */
|
|
67
|
+
up?: [number, number, number];
|
|
68
|
+
/** A saved camera: azimuth and elevation (degrees, about `up`), distance (mm) and target. Without a distance the model is fitted. */
|
|
69
|
+
camera?: {
|
|
70
|
+
azimuth?: number;
|
|
71
|
+
elevation?: number;
|
|
72
|
+
distance?: number;
|
|
73
|
+
target?: [number, number, number];
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export interface LoadedSource {
|
|
77
|
+
name: string;
|
|
78
|
+
bundleUrl: string;
|
|
79
|
+
scenarios: ViewerScenario[];
|
|
80
|
+
/** URL for a definition's artifact file path, or undefined if it cannot be resolved. */
|
|
81
|
+
resolveArtifact: ArtifactResolver;
|
|
82
|
+
/** Findings from the bundle's producer (e.g. Protoboard's aggregated check). */
|
|
83
|
+
hostDiagnostics: UhdBundleDiagnostic[];
|
|
84
|
+
display: DisplayConfig;
|
|
85
|
+
/** The bundle as loaded (for host views that read more of it than the viewer draws). */
|
|
86
|
+
bundle: UhdBundle;
|
|
87
|
+
}
|
|
88
|
+
export interface SourceOptions {
|
|
89
|
+
/** Development only: absolute filesystem bases are served through Vite's /@fs route. */
|
|
90
|
+
fsRoute?: boolean;
|
|
91
|
+
/** A host's resolver; it receives the default one as `fallback`. */
|
|
92
|
+
resolveArtifact?: ViewerOptions["resolveArtifact"];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The bundle URL for the standalone app: `?bundle=<url>`, then the URL a
|
|
96
|
+
* server injected into the page, then the development default (none in a
|
|
97
|
+
* production build).
|
|
98
|
+
*/
|
|
99
|
+
export declare function pickBundleUrl(search: string, injected?: string | null, fallback?: string | null): string | undefined;
|
|
100
|
+
/**
|
|
101
|
+
* URL prefix for an artifact base (`UhdBundle.artifactBases`: an absolute
|
|
102
|
+
* path or a URL prefix), or undefined when it cannot be fetched over HTTP.
|
|
103
|
+
* Absolute filesystem paths only resolve in development, through /@fs.
|
|
104
|
+
*/
|
|
105
|
+
export declare function baseToUrl(base: string, options?: Pick<SourceOptions, "fsRoute">): string | undefined;
|
|
106
|
+
/** The default resolver: a definition's artifact base, or the bundle's own location. */
|
|
107
|
+
export declare function bundleResolver(bundle: UhdBundle, bundleUrl: string, options?: Pick<SourceOptions, "fsRoute">): ArtifactResolver;
|
|
108
|
+
export declare function loadBundle(url: string, options?: SourceOptions): Promise<LoadedSource>;
|
|
109
|
+
export declare function sourceFromBundle(bundle: UhdBundle, url: string, options?: SourceOptions): LoadedSource;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bundle that does not hold everything it names still draws.
|
|
3
|
+
*
|
|
4
|
+
* UHD's resolvers throw on a child whose definition is not in the bundle, and
|
|
5
|
+
* on a link or an export that names an interface nobody has. A producer that
|
|
6
|
+
* could not fetch some definitions (a library that was unreachable) writes
|
|
7
|
+
* exactly such a bundle, and the viewer drew nothing at all for it.
|
|
8
|
+
*
|
|
9
|
+
* `tolerantSystem` gives the viewer a system the resolvers accept: a missing
|
|
10
|
+
* definition is stood in for by a placeholder that has the interfaces its
|
|
11
|
+
* parents' links and exports name, and a link or an export that still cannot
|
|
12
|
+
* be resolved is left out. What was stood in for and what was left out is
|
|
13
|
+
* returned, so the views can say so.
|
|
14
|
+
*/
|
|
15
|
+
import type { ModuleDef } from "@deltarobotics/uhd";
|
|
16
|
+
import { type ModuleLookup } from "@deltarobotics/uhd";
|
|
17
|
+
/** A definition the bundle names and does not hold. */
|
|
18
|
+
export interface MissingDefinition {
|
|
19
|
+
/** The definition id the children name. */
|
|
20
|
+
id: string;
|
|
21
|
+
/** Where it is used: the parent definition and the child's id and label there. */
|
|
22
|
+
usedBy: {
|
|
23
|
+
parent: string;
|
|
24
|
+
child: string;
|
|
25
|
+
name?: string;
|
|
26
|
+
}[];
|
|
27
|
+
}
|
|
28
|
+
/** A link or an export left out because it could not be resolved. */
|
|
29
|
+
export interface LeftOut {
|
|
30
|
+
kind: "link" | "export";
|
|
31
|
+
/** The definition it was on. */
|
|
32
|
+
on: string;
|
|
33
|
+
id: string;
|
|
34
|
+
/** The resolver's message. */
|
|
35
|
+
why: string;
|
|
36
|
+
}
|
|
37
|
+
export interface TolerantSystem {
|
|
38
|
+
root: ModuleDef;
|
|
39
|
+
lookup: ModuleLookup;
|
|
40
|
+
missing: MissingDefinition[];
|
|
41
|
+
leftOut: LeftOut[];
|
|
42
|
+
}
|
|
43
|
+
/** Whether a definition is a placeholder for one the bundle does not hold. */
|
|
44
|
+
export declare function isPlaceholder(def: ModuleDef | undefined): boolean;
|
|
45
|
+
export declare function tolerantSystem(root: ModuleDef, lookup: ModuleLookup): TolerantSystem;
|