@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.
Files changed (100) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +22 -0
  4. package/README.md +168 -2
  5. package/bin/serve.d.mts +62 -0
  6. package/bin/serve.mjs +257 -0
  7. package/bin/uhd-viewer.mjs +75 -0
  8. package/dist/app/assets/KodeMono-Bold-DdIivhPN.woff2 +0 -0
  9. package/dist/app/assets/KodeMono-Medium-CVnTuv5A.ttf +0 -0
  10. package/dist/app/assets/KodeMono-Regular-Bdr_-rJX.woff2 +0 -0
  11. package/dist/app/assets/KodeMono-SemiBold-JAfn5Dpm.ttf +0 -0
  12. package/dist/app/assets/index-Boi2erhd.css +2 -0
  13. package/dist/app/assets/index-CkpIRYgM.js +3853 -0
  14. package/dist/app/index.html +16 -0
  15. package/dist/components/components.css +6108 -0
  16. package/dist/components/index.d.ts +1 -0
  17. package/dist/components/index.js +26048 -0
  18. package/dist/components/index.js.map +1 -0
  19. package/dist/components/types/uhd-viewer/src/api.d.ts +286 -0
  20. package/dist/components/types/uhd-viewer/src/cad/CadView.d.ts +52 -0
  21. package/dist/components/types/uhd-viewer/src/cad/ModelView.d.ts +28 -0
  22. package/dist/components/types/uhd-viewer/src/cad/explode.d.ts +110 -0
  23. package/dist/components/types/uhd-viewer/src/cad/explodeSample.d.ts +25 -0
  24. package/dist/components/types/uhd-viewer/src/cad/findings.d.ts +41 -0
  25. package/dist/components/types/uhd-viewer/src/cad/labels.d.ts +76 -0
  26. package/dist/components/types/uhd-viewer/src/cad/model.d.ts +132 -0
  27. package/dist/components/types/uhd-viewer/src/cad/row.d.ts +15 -0
  28. package/dist/components/types/uhd-viewer/src/cad/scene.d.ts +95 -0
  29. package/dist/components/types/uhd-viewer/src/cad/scope.d.ts +89 -0
  30. package/dist/components/types/uhd-viewer/src/canvas/Canvas.d.ts +86 -0
  31. package/dist/components/types/uhd-viewer/src/canvas/Icon.d.ts +5 -0
  32. package/dist/components/types/uhd-viewer/src/canvas/LinkEdge.d.ts +40 -0
  33. package/dist/components/types/uhd-viewer/src/canvas/Port.d.ts +18 -0
  34. package/dist/components/types/uhd-viewer/src/canvas/actions.d.ts +5 -0
  35. package/dist/components/types/uhd-viewer/src/canvas/geometry.d.ts +72 -0
  36. package/dist/components/types/uhd-viewer/src/canvas/interaction.d.ts +162 -0
  37. package/dist/components/types/uhd-viewer/src/canvas/nodes.d.ts +43 -0
  38. package/dist/components/types/uhd-viewer/src/canvas/reveal.d.ts +37 -0
  39. package/dist/components/types/uhd-viewer/src/canvas/rightDrag.d.ts +51 -0
  40. package/dist/components/types/uhd-viewer/src/canvas/routing.d.ts +28 -0
  41. package/dist/components/types/uhd-viewer/src/chrome/ArtifactCards.d.ts +30 -0
  42. package/dist/components/types/uhd-viewer/src/chrome/Artifacts.d.ts +44 -0
  43. package/dist/components/types/uhd-viewer/src/chrome/BoardInspector.d.ts +53 -0
  44. package/dist/components/types/uhd-viewer/src/chrome/Chrome.d.ts +116 -0
  45. package/dist/components/types/uhd-viewer/src/chrome/Evidence.d.ts +20 -0
  46. package/dist/components/types/uhd-viewer/src/chrome/InterfaceCards.d.ts +56 -0
  47. package/dist/components/types/uhd-viewer/src/chrome/PairView.d.ts +37 -0
  48. package/dist/components/types/uhd-viewer/src/chrome/Sections.d.ts +107 -0
  49. package/dist/components/types/uhd-viewer/src/components.d.ts +60 -0
  50. package/dist/components/types/uhd-viewer/src/host/channel.d.ts +49 -0
  51. package/dist/components/types/uhd-viewer/src/host/context.d.ts +29 -0
  52. package/dist/components/types/uhd-viewer/src/host/protocol.d.ts +22 -0
  53. package/dist/components/types/uhd-viewer/src/host/targets.d.ts +85 -0
  54. package/dist/components/types/uhd-viewer/src/layout/board-layout.d.ts +69 -0
  55. package/dist/components/types/uhd-viewer/src/layout/card-body.d.ts +64 -0
  56. package/dist/components/types/uhd-viewer/src/layout/layout.d.ts +94 -0
  57. package/dist/components/types/uhd-viewer/src/layout/module-layout.d.ts +32 -0
  58. package/dist/components/types/uhd-viewer/src/layout/router.d.ts +55 -0
  59. package/dist/components/types/uhd-viewer/src/layout/taps.d.ts +20 -0
  60. package/dist/components/types/uhd-viewer/src/model/artifacts.d.ts +129 -0
  61. package/dist/components/types/uhd-viewer/src/model/classification.d.ts +38 -0
  62. package/dist/components/types/uhd-viewer/src/model/diagnostics.d.ts +27 -0
  63. package/dist/components/types/uhd-viewer/src/model/evidence.d.ts +63 -0
  64. package/dist/components/types/uhd-viewer/src/model/from-uhd.d.ts +57 -0
  65. package/dist/components/types/uhd-viewer/src/model/hierarchy.d.ts +169 -0
  66. package/dist/components/types/uhd-viewer/src/model/isolate.d.ts +33 -0
  67. package/dist/components/types/uhd-viewer/src/model/nets.d.ts +53 -0
  68. package/dist/components/types/uhd-viewer/src/model/outputs.d.ts +79 -0
  69. package/dist/components/types/uhd-viewer/src/model/slots.d.ts +182 -0
  70. package/dist/components/types/uhd-viewer/src/model/types.d.ts +213 -0
  71. package/dist/components/types/uhd-viewer/src/options.d.ts +27 -0
  72. package/dist/components/types/uhd-viewer/src/source/source.d.ts +109 -0
  73. package/dist/components/types/uhd-viewer/src/source/tolerant.d.ts +45 -0
  74. package/dist/components/types/uhd-viewer/src/theme/ThemeProvider.d.ts +33 -0
  75. package/dist/components/types/uhd-viewer/src/theme/adapters.d.ts +28 -0
  76. package/dist/components/types/uhd-viewer/src/theme/resolve.d.ts +19 -0
  77. package/dist/components/types/uhd-viewer/src/theme/themes.d.ts +67 -0
  78. package/dist/components/types/uhd-viewer/src/theme/tokens.d.ts +175 -0
  79. package/dist/components/types/uhd-viewer/src/ui/Inspector.d.ts +45 -0
  80. package/dist/components/types/uhd-viewer/src/ui/Legend.d.ts +40 -0
  81. package/dist/components/types/uhd-viewer/src/ui/ScrollArea.d.ts +16 -0
  82. package/dist/components/types/uhd-viewer/src/ui/Toolbar.d.ts +49 -0
  83. package/dist/components/types/uhd-viewer/src/ui/Tooltips.d.ts +3 -0
  84. package/dist/components/types/uhd-viewer/src/ui/cx.d.ts +2 -0
  85. package/dist/components/types/uhd-viewer/src/ui/legendFit.d.ts +42 -0
  86. package/dist/components/types/uhd-viewer/src/viewer/controller.d.ts +218 -0
  87. package/dist/components/types/uhd-viewer/src/viewer/details.d.ts +81 -0
  88. package/dist/components/types/uhd-viewer/src/viewer/hierarchy.d.ts +60 -0
  89. package/dist/components/types/uhd-viewer/src/viewer/mount.d.ts +12 -0
  90. package/dist/components/types/uhd-viewer/src/viewer/views.d.ts +156 -0
  91. package/dist/headless/index.d.ts +71 -0
  92. package/dist/headless/index.js +7425 -0
  93. package/dist/headless/index.js.map +1 -0
  94. package/dist/lib/api.d.ts +252 -0
  95. package/dist/lib/uhd-viewer.css +3 -0
  96. package/dist/lib/uhd-viewer.d.ts +4 -0
  97. package/dist/lib/uhd-viewer.js +97469 -0
  98. package/package.json +110 -4
  99. package/src/styles/fonts/OFL.txt +93 -0
  100. package/src/styles/tailwind-theme.css +48 -0
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Grid router (PB-803, design D12): orthogonal routes on the 16 px grid.
3
+ *
4
+ * A* over grid cells with a direction in the state. It avoids module cards,
5
+ * penalises bends and crossings, and keeps parallel runs one grid step apart
6
+ * by charging for cells another route already runs along. Pinned waypoints
7
+ * (dragged by the user, saved in the display file) are visited in order; the
8
+ * bends it chooses itself are the automatic waypoints.
9
+ */
10
+ import type { Pt, Side } from "../canvas/routing";
11
+ export declare const GRID = 16;
12
+ export interface Rect {
13
+ x: number;
14
+ y: number;
15
+ w: number;
16
+ h: number;
17
+ }
18
+ export declare const snap: (v: number) => number;
19
+ export declare class GridRouter {
20
+ private x0;
21
+ private y0;
22
+ private W;
23
+ private H;
24
+ private blocked;
25
+ /** Cells used by earlier routes: bit 1 horizontal run, bit 2 vertical run. */
26
+ private used;
27
+ /** Search state, allocated once and reused: a state is valid when its stamp is the current search's. */
28
+ private g;
29
+ private prev;
30
+ private stamp;
31
+ private gen;
32
+ private thorough;
33
+ /**
34
+ * `thorough`: a search that runs out of its budget is retried over the whole grid (off while
35
+ * dragging, where a frame cannot wait for it).
36
+ */
37
+ constructor(obstacles: Rect[], extra?: Pt[], margin?: number, thorough?: boolean);
38
+ private idx;
39
+ /**
40
+ * Route from a port (on `fromSide` of its card) to another port, through
41
+ * `pins` in order. Returns the polyline in canvas coordinates. With
42
+ * `within`, the route stays inside that rectangle (a link between two
43
+ * modules of a container expanded in place never leaves the container);
44
+ * where no such route exists it is routed without the limit.
45
+ */
46
+ route(from: Pt, fromSide: Side, to: Pt, toSide: Side, pins?: Pt[], within?: Rect): Pt[];
47
+ /** The cells a search may use, in grid coordinates (a container's inside), when a route is kept within one. */
48
+ private region;
49
+ /** One routing attempt; `strict` gives up (undefined, nothing marked) where a leg finds no way instead of jogging straight. */
50
+ private routeOnce;
51
+ private search;
52
+ /** Treat an existing route (canvas coordinates, axis-aligned) as occupied, as if it had just been routed. */
53
+ occupy(points: Pt[]): void;
54
+ private mark;
55
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Rail taps (PB-873): a supply rail drawn the way a schematic draws it.
3
+ *
4
+ * A rail joins most of a board (a 3V3 rail reaches 15–20 parts). Drawn as one
5
+ * junction it pulls a line from every corner of the sheet. Drawn as a net
6
+ * label at each place it is used, it reads at a glance: here the rail is
7
+ * split into taps, one per cluster of parts (a part and the passives that
8
+ * serve it, board-layout.ts), each joined only to the members of its cluster.
9
+ * The taps carry the net's name and colour; the one with the most members
10
+ * keeps the net's id, the others are `<net>~<cluster>` with `tapOf` set.
11
+ *
12
+ * Only the drawing changes: the inspector, the hierarchy and the findings
13
+ * read the level's view model, where the net is one node.
14
+ */
15
+ import type { ViewModel, ViewNode } from "../model/types";
16
+ /** A power net with at least this many members is drawn as taps. */
17
+ export declare const RAIL_TAP_MIN = 5;
18
+ export declare function tapRails(vm: ViewModel): ViewModel;
19
+ /** The node a selection names for a drawn node: a tap's net. */
20
+ export declare const selectionId: (node: ViewNode | undefined, id: string) => string;
@@ -0,0 +1,129 @@
1
+ /**
2
+ * A definition's artifacts as cards: every artifact is one card with a kind
3
+ * (image, 3D model, schematic, PCB, datasheet, document, …), a title, where
4
+ * it comes from (a file, or the host of its URL) and, where it has one, a
5
+ * picture to show. No React here: the inspector draws the cards
6
+ * (chrome/ArtifactCards.tsx), a host may read the same list.
7
+ */
8
+ import type { ArtifactDef, ModuleDef } from "@deltarobotics/uhd";
9
+ import type { ArtifactResolver } from "../api";
10
+ export type ArtifactKind = "image" | "model" | "schematic" | "pcb" | "drawing" | "datasheet" | "document" | "source" | "firmware" | "data" | "evidence";
11
+ /** The sections cards are shown in, in this order. */
12
+ export type ArtifactGroup = "images" | "models" | "board" | "datasheets" | "documents" | "evidence" | "design" | "data";
13
+ export declare const ARTIFACT_GROUPS: {
14
+ id: ArtifactGroup;
15
+ title: string;
16
+ }[];
17
+ /** What a card shows above its title: a picture, or a model a host may draw small. */
18
+ export type ArtifactPreview = {
19
+ kind: "image";
20
+ src: string;
21
+ } | {
22
+ kind: "model";
23
+ src: string;
24
+ };
25
+ export interface ArtifactCardModel {
26
+ /** Unique among a definition's cards. */
27
+ key: string;
28
+ defId: string;
29
+ /** The artifact's id (absent for a card that is not an artifact of the definition: an evidence source). */
30
+ artifactId?: string;
31
+ title: string;
32
+ kind: ArtifactKind;
33
+ group: ArtifactGroup;
34
+ /** The kind in words: "Datasheet", "STEP model", "PCB top". */
35
+ kindLabel: string;
36
+ /** The file format, upper case: "PDF", "STEP", "GLB". */
37
+ format?: string;
38
+ /** Where it comes from, short: a URL's host, a file's name. */
39
+ source?: string;
40
+ /** More about the source: its authority and when it was fetched ("manufacturer · fetched 2026-10-03"). */
41
+ sourceNote?: string;
42
+ /** The whole URL or path, for the tooltip. */
43
+ location?: string;
44
+ /** What a click opens when no host takes artifacts. */
45
+ href?: string;
46
+ /** Lucide icon name, drawn when there is no picture. */
47
+ icon: string;
48
+ preview?: ArtifactPreview;
49
+ /** The artifact is a web address, not a file of the project. */
50
+ remote: boolean;
51
+ description?: string;
52
+ /** The same model in other formats (a STEP and the GLB exported with it): one card, each format a way to open it. */
53
+ also?: {
54
+ artifactId: string;
55
+ format?: string;
56
+ href?: string;
57
+ }[];
58
+ }
59
+ /** An evidence source row (sources.json), as far as cards need it. */
60
+ export interface ArtifactSourceRow {
61
+ id: string;
62
+ title: string;
63
+ url: string;
64
+ type?: string;
65
+ authority?: string;
66
+ fetched_at?: string;
67
+ }
68
+ export interface ArtifactCardOptions {
69
+ /**
70
+ * A picture for an artifact that is not an image itself (a model's exported
71
+ * preview, or the model for the host to draw small). Not given: such cards
72
+ * show their icon.
73
+ */
74
+ previewFor?: (def: ModuleDef, artifact: ArtifactDef) => ArtifactPreview | undefined;
75
+ /** Load pictures from web addresses (default true). A host that loads only its own files turns it off: those cards show their icon. */
76
+ remoteImages?: boolean;
77
+ /** The definition's evidence sources: an artifact with the same URL says its authority and when it was fetched; `evidence: true` lists the others as cards of their own. */
78
+ sources?: ArtifactSourceRow[];
79
+ evidence?: boolean;
80
+ /** Artifacts to leave out (already shown another way). */
81
+ skip?: (artifact: ArtifactDef) => boolean;
82
+ /**
83
+ * Keep a part's internal geometry: the per-interface models its mates are computed from (role `interface`),
84
+ * which a module's cards leave out (QA B2: 17 "interface geometry" GLBs on a flight controller). An
85
+ * interface's own card asks for them.
86
+ */
87
+ internal?: boolean;
88
+ /** One card per model, its formats together (`mergeFormats`; default true). */
89
+ mergeFormats?: boolean;
90
+ }
91
+ /** An artifact that is a part's internal geometry, not something to open: one interface's mating model. */
92
+ export declare const isInternalArtifact: (a: Pick<ArtifactDef, "role">) => boolean;
93
+ /** A file's or URL's last path segment. */
94
+ export declare const artifactFileName: (a: Pick<ArtifactDef, "filePath" | "url">) => string;
95
+ /** The extension of an artifact's file or URL, lower case (only a short alphanumeric one counts). */
96
+ export declare function artifactExtension(a: Pick<ArtifactDef, "filePath" | "url">): string;
97
+ /** A URL's host without `www.`, or undefined when it is not a URL. */
98
+ export declare function hostOf(url: string | undefined): string | undefined;
99
+ interface Classified {
100
+ kind: ArtifactKind;
101
+ group: ArtifactGroup;
102
+ kindLabel: string;
103
+ icon: string;
104
+ }
105
+ /** What an artifact is, from its type, role, format and file name. */
106
+ export declare function classifyArtifact(a: ArtifactDef): Classified;
107
+ /** One artifact as a card. */
108
+ export declare function artifactCard(def: ModuleDef, a: ArtifactDef, resolve: ArtifactResolver, options?: ArtifactCardOptions): ArtifactCardModel;
109
+ /** A definition's evidence sources (sources.json), each as a card: its title, what kind of source, its host, its authority and when it was fetched. */
110
+ export declare const evidenceSourceCards: (defId: string, sources: ArtifactSourceRow[]) => ArtifactCardModel[];
111
+ /**
112
+ * Every artifact of a definition as a card, in the order of the groups; with
113
+ * `evidence`, the definition's evidence sources that no artifact names follow
114
+ * as cards too.
115
+ */
116
+ export declare function artifactCards(def: ModuleDef | undefined, resolve: ArtifactResolver, options?: ArtifactCardOptions): ArtifactCardModel[];
117
+ /**
118
+ * One card per model (QA B2): models that are one file in several formats (`body.step` and `body.glb`, beside
119
+ * each other) are one card, the first's (a STEP before its GLB), with every format named and the others in
120
+ * `also`. Its title loses a "(STEP)" that named the format.
121
+ */
122
+ export declare function mergeFormats(cards: ArtifactCardModel[]): ArtifactCardModel[];
123
+ /** Cards by group, in the groups' order; empty groups are left out. */
124
+ export declare function groupArtifactCards(cards: ArtifactCardModel[]): {
125
+ id: ArtifactGroup;
126
+ title: string;
127
+ cards: ArtifactCardModel[];
128
+ }[];
129
+ export {};
@@ -0,0 +1,38 @@
1
+ import type { LinkState } from "./types";
2
+ /**
3
+ * Interface/harness classification (design decision D7): the rule that
4
+ * colours ports and links. Domain is the default.
5
+ */
6
+ export type Classification = "domain" | "drc" | "signal";
7
+ export declare const CLASSIFICATIONS: {
8
+ id: Classification;
9
+ label: string;
10
+ }[];
11
+ export interface Colorable {
12
+ domain: string;
13
+ protocol: string;
14
+ state?: LinkState;
15
+ }
16
+ export declare function colorFor(item: Colorable, mode: Classification): string;
17
+ /** Items outside the classification's focus are faded (signal mode shows electrical only). */
18
+ export declare function isFaded(item: Colorable, mode: Classification): boolean;
19
+ /** One entry of a classification's legend. `key` is what `classKey` gives the items it stands for. */
20
+ export interface LegendEntry {
21
+ key: string;
22
+ label: string;
23
+ color: string;
24
+ }
25
+ /** The legend entry an item belongs to in a classification (the key of its colour). */
26
+ export declare function classKey(item: Colorable, mode: Classification): string;
27
+ /**
28
+ * What the colours of a classification mean. With `present` (the keys drawn
29
+ * on the level, `presentKeys`), the entries the fixed list leaves out (SPI,
30
+ * CAN, a domain of its own…) are added where the level has them, so every
31
+ * colour on screen has an entry to read and to isolate.
32
+ */
33
+ export declare function legendFor(mode: Classification, present?: ReadonlySet<string>): LegendEntry[];
34
+ /** Signal-type colour: one table for links, lanes and conductors ("uart_tx" is a UART). */
35
+ declare function signalColor(protocol: string): string;
36
+ /** Colour of one conductor in signal mode (the same table as links and lanes). */
37
+ export declare const conductorColor: typeof signalColor;
38
+ export {};
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The system checks the viewer runs itself (PB-823).
3
+ *
4
+ * UHD derives links per module: a parent does not see through a child
5
+ * board's nets (docs/boards-and-nets.md, "Limits"). So the root is checked,
6
+ * and so is every module below it that declares nets (a board), on its own.
7
+ * A board's findings are re-based onto the root: refs and ids carry the
8
+ * board's instance path (`board/u2:pin_14`, `link:board/<id>`, `board:sda`),
9
+ * and `scope` names the board, so the checks panel can say where a finding
10
+ * is and the diagram can overlay it when that board is drilled into.
11
+ */
12
+ import type { ModuleDef } from "@deltarobotics/uhd";
13
+ import type { ModuleLookup } from "@deltarobotics/uhd";
14
+ import { type SystemDiagnostic } from "@deltarobotics/uhd";
15
+ export interface ScopedDiagnostic extends SystemDiagnostic {
16
+ /** Instance path of the module that was checked ("" for the root). */
17
+ scope: string;
18
+ }
19
+ /** A canonical path below `scope`, re-based onto the root. */
20
+ export declare function rebase(ref: string, scope: string): string;
21
+ /** Instance paths of every module below `root` that declares nets, depth first. */
22
+ export declare function boardsBelow(root: ModuleDef, lookup: ModuleLookup): {
23
+ path: string;
24
+ def: ModuleDef;
25
+ }[];
26
+ /** The root's findings, then each board's, re-based onto the root. */
27
+ export declare function systemDiagnostics(root: ModuleDef, lookup: ModuleLookup): ScopedDiagnostic[];
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Evidence for a part: its sources.json and verification.json, when they are
3
+ * registered (registerEvidenceFiles; nothing does yet), plus the evidence
4
+ * traits on its definition.
5
+ *
6
+ * The traits come with the bundle. The two files do not (yet): UHD has no
7
+ * part library to read them from, so without a host that supplies them the
8
+ * viewer shows the traits only.
9
+ */
10
+ import type { ModuleDef } from "@deltarobotics/uhd";
11
+ export interface SourceRow {
12
+ id: string;
13
+ title: string;
14
+ url: string;
15
+ type: string;
16
+ authority: string;
17
+ supports?: string[];
18
+ fetched_at?: string;
19
+ }
20
+ export interface Verification {
21
+ audit: {
22
+ checked: number;
23
+ confirmed: number;
24
+ wrong: number;
25
+ unsupported: number;
26
+ } | null;
27
+ repairs: string | null;
28
+ assumptions: unknown[];
29
+ data_gaps: unknown[];
30
+ vocabulary_gaps: unknown[];
31
+ recorded_at: string;
32
+ }
33
+ /** Evidence files by part id (definition id). */
34
+ export declare function registerEvidenceFiles(files: {
35
+ sources: Record<string, SourceRow[]>;
36
+ verification: Record<string, Verification>;
37
+ }): void;
38
+ export interface Evidence {
39
+ /** Whether sources.json / verification.json were available at all (false: the audit state is unknown). */
40
+ filesKnown: boolean;
41
+ sources: SourceRow[];
42
+ verification?: Verification;
43
+ performance: {
44
+ kind: string;
45
+ facts: [string, string][];
46
+ }[];
47
+ assumptions: {
48
+ field: string;
49
+ value?: string;
50
+ reason?: string;
51
+ }[];
52
+ discrepancies: {
53
+ field: string;
54
+ resolution?: string;
55
+ }[];
56
+ gaps: string[];
57
+ }
58
+ /** A definition's evidence files as a host gives them (`files`), else as registered. */
59
+ export interface EvidenceFiles {
60
+ sources?: SourceRow[];
61
+ verification?: Verification;
62
+ }
63
+ export declare function evidenceFor(def: ModuleDef | undefined, files?: EvidenceFiles): Evidence | undefined;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Adapter: UHD system ModuleDef → neutral view model.
3
+ *
4
+ * A level shows the children of one module. Children that have children of
5
+ * their own are drawn expanded in place when listed in `expanded` (their
6
+ * boundary ports are exports, joined to the inner ports by pass-through
7
+ * lines); otherwise they are drawn as a single card with boundary ports.
8
+ * Harness children (kind "harness") become harness nodes, and every link
9
+ * they carry is drawn in two segments through them. System diagnostics
10
+ * (checkSystem) are overlaid onto link state for DRC colouring.
11
+ */
12
+ import type { ChildLink, ModuleDef } from "@deltarobotics/uhd";
13
+ import { type LinkResult, type ModuleLookup } from "@deltarobotics/uhd";
14
+ import type { SystemDiagnostic } from "@deltarobotics/uhd";
15
+ import type { ViewLink, ViewModel } from "./types";
16
+ /** Link ids whose child links are stored overrides. */
17
+ type Overrides = Record<string, ChildLink[]>;
18
+ export interface LevelLinks {
19
+ links: ViewLink[];
20
+ /** Harness children drawn as regions on links, not as nodes. */
21
+ regionHarnesses: Set<string>;
22
+ /** Stored or derived link id → the view link that draws it (for diagnostics). */
23
+ owners: Map<string, string>;
24
+ /** Every link UHD derives at this level (through cables and over nets). */
25
+ derived: LinkResult[];
26
+ }
27
+ /**
28
+ * The links of one level (PB-803/805). A harness with exactly two connector
29
+ * ends becomes one link from part to part with the harness as a region along
30
+ * it; its lanes are the links derived through its conductors and its
31
+ * conductors are the mated positions. Logical links that name a harness get
32
+ * the same region. Anything else keeps its own line.
33
+ */
34
+ export declare function levelLinks(def: ModuleDef, results: LinkResult[], lookup: ModuleLookup, prefix: string, overrides: Overrides | undefined): LevelLinks;
35
+ export interface BuildOptions {
36
+ /** Child ids (at this level) drawn expanded in place. */
37
+ expanded: Set<string>;
38
+ /** Stored child-link overrides keyed by link id (top level). */
39
+ overrides?: Overrides;
40
+ /**
41
+ * System diagnostics to overlay on link state. Refs are relative to the
42
+ * root; findings of a board checked on its own (see App) carry its path
43
+ * (`link:board/<id>`), so they overlay when that board is drilled into.
44
+ */
45
+ diagnostics?: SystemDiagnostic[];
46
+ /** Draw ground nets as junctions with wires (GND wires on) rather than as ground symbols. */
47
+ grounds?: boolean;
48
+ }
49
+ /** Apply child-link overrides to a module's stored links. */
50
+ export declare function withOverrides(def: ModuleDef, overrides: Overrides | undefined): ModuleDef;
51
+ /** Descend `drill` child ids from the root to find the module shown at this level. */
52
+ export declare function levelModule(root: ModuleDef, drill: string[], lookup: ModuleLookup): {
53
+ def: ModuleDef;
54
+ path: ViewModel["path"];
55
+ };
56
+ export declare function buildView(root: ModuleDef, lookup: ModuleLookup, drill: string[], opts: BuildOptions): ViewModel;
57
+ export {};
@@ -0,0 +1,169 @@
1
+ /**
2
+ * The hierarchy panel's model (PB-1042): the whole module tree of a system,
3
+ * every level at once (the root, its sub-modules, their parts and harnesses),
4
+ * with what each row shows (an icon by kind, the host's part mark, the worst
5
+ * finding here or below), the filter, the rows on screen, the keyboard, and
6
+ * how a row maps to the diagram's level and selection. Pure functions, so they
7
+ * test without a page; viewer/hierarchy.tsx draws them.
8
+ */
9
+ import type { ModuleDef } from "@deltarobotics/uhd";
10
+ import type { ModuleLookup } from "@deltarobotics/uhd";
11
+ import type { UhdBundleDiagnostic } from "@deltarobotics/uhd";
12
+ import type { NodeMark } from "../api";
13
+ import type { ScopedDiagnostic } from "./diagnostics";
14
+ import { type LevelSelection } from "../host/targets";
15
+ /** What a row is: the same kinds as a host's own module tree. */
16
+ export type HierarchyKind = "system" | "assembly" | "group" | "part" | "board" | "enclosure" | "structure" | "harness" | "fasteners";
17
+ export type Severity = "error" | "warning" | "info";
18
+ export interface Findings {
19
+ error: number;
20
+ warning: number;
21
+ info: number;
22
+ }
23
+ export interface HierarchyNode {
24
+ /** Instance path from the root ("" is the root). */
25
+ path: string;
26
+ /** The parent's path; undefined for the root. */
27
+ parent?: string;
28
+ label: string;
29
+ defId: string;
30
+ /** The definition's own name, when the instance is named otherwise ("FB upper" is a "Resistor 1 MΩ"). */
31
+ defName?: string;
32
+ kind: HierarchyKind;
33
+ /** A Lucide icon name for the kind. */
34
+ icon: string;
35
+ depth: number;
36
+ quantity?: number;
37
+ /** The host's mark for the definition (a part's status), as the diagram's dot shows it. */
38
+ mark?: NodeMark;
39
+ /** The bundle names the definition and does not hold it: drawn as a placeholder. */
40
+ missing?: boolean;
41
+ /** Findings on this module itself. */
42
+ findings: Findings;
43
+ /** The worst finding here or below. */
44
+ worst?: Severity;
45
+ /** The module has a level of its own (a module with children; not a harness). */
46
+ drillable: boolean;
47
+ /** A row of the panel's own that only holds others (`WIRING_PATH`): no module, nothing to select. */
48
+ group?: boolean;
49
+ /** In the wiring group: the module it belongs to ("Front-right arm"), since four "Prop nut" rows read alike. */
50
+ where?: string;
51
+ children: HierarchyNode[];
52
+ }
53
+ /** Icons by kind (Lucide names), matching a host tree's: a board, a package, a chip, a plug. */
54
+ export declare const KIND_ICON: Record<HierarchyKind, string>;
55
+ /** What a kind is called (tooltips, the accessible description). */
56
+ export declare const KIND_LABEL: Record<HierarchyKind, string>;
57
+ /** A module that stands for a part nobody has chosen yet (the host marks it with a ring). */
58
+ export declare const BLANK_ICON = "circle-dashed";
59
+ /** What kind of module a definition is, from what the bundle says (its UHD kind, nets, children, categories). */
60
+ export declare function kindOf(def: ModuleDef | undefined, isRoot: boolean): HierarchyKind;
61
+ export interface HierarchyOptions {
62
+ /** The host's marks by definition id (`ViewerOptions.nodeMarks`). */
63
+ marks?: Record<string, NodeMark>;
64
+ /** The viewer's own checks (systemDiagnostics). */
65
+ diagnostics?: readonly ScopedDiagnostic[];
66
+ /** The producer's and the host's findings. */
67
+ hostDiagnostics?: readonly UhdBundleDiagnostic[];
68
+ /** Whether the definition is a placeholder for one the bundle lacks. */
69
+ isMissing?: (def: ModuleDef) => boolean;
70
+ }
71
+ /** The module tree from the root: `[root]`. A definition that names itself further down stops there. */
72
+ export declare function buildHierarchy(root: ModuleDef, lookup: ModuleLookup, options?: HierarchyOptions): HierarchyNode[];
73
+ /** The module a canonical ref names: `board/u2:pin_14` → `board/u2`, `link:a/b/l1` → `a/b`, `:sda` on a scope → the scope. */
74
+ export declare function modulePart(ref: string, scope: string): string;
75
+ export declare function walkHierarchy(nodes: readonly HierarchyNode[]): Generator<HierarchyNode>;
76
+ /** Every node by path. */
77
+ export declare const hierarchyIndex: (nodes: readonly HierarchyNode[]) => Map<string, HierarchyNode>;
78
+ /** The paths above `path`, root first ("" for the root itself has none). */
79
+ export declare function ancestorsOf(path: string): string[];
80
+ /**
81
+ * The tree reduced to the rows that match `text` (every word, in the label,
82
+ * the definition's name, the instance path, the definition id or the kind;
83
+ * case-insensitive), with
84
+ * the modules that lead to them. A matching module keeps its own children.
85
+ * Returns the reduced tree and the paths to show open.
86
+ */
87
+ export declare function filterHierarchy(nodes: readonly HierarchyNode[], text: string): {
88
+ nodes: HierarchyNode[];
89
+ expanded: Set<string>;
90
+ matches: Set<string>;
91
+ };
92
+ /** One row on screen. */
93
+ export interface HierarchyRow {
94
+ node: HierarchyNode;
95
+ /** 1-based, as `aria-level` takes it. */
96
+ level: number;
97
+ /** Has rows below it (open or not). */
98
+ branch: boolean;
99
+ open: boolean;
100
+ /** 1-based place among its siblings, and how many there are (`aria-posinset`, `aria-setsize`). */
101
+ pos: number;
102
+ size: number;
103
+ }
104
+ /** The rows on screen: every node whose ancestors are all open. */
105
+ export declare function visibleRows(nodes: readonly HierarchyNode[], expanded: ReadonlySet<string>): HierarchyRow[];
106
+ /** What a key does on the tree: where the focus goes, what opens or closes, and what is asked of the viewer. */
107
+ export interface TreeKeyResult {
108
+ focus: string;
109
+ expanded: Set<string>;
110
+ action?: "select" | "drill";
111
+ }
112
+ /**
113
+ * The tree's keyboard (WAI-ARIA tree pattern): Up and Down move, Home and End
114
+ * go to the first and last row; Right opens a closed module, or moves to its
115
+ * first child; Left closes an open one, or moves to its parent; Enter and
116
+ * Space select the row (Enter on the row already selected drills into it,
117
+ * when it has a level of its own); `*` opens every sibling. Undefined: the key
118
+ * is not the tree's.
119
+ */
120
+ export declare function treeKey(rows: readonly HierarchyRow[], focus: string, key: string, expanded: ReadonlySet<string>, selected?: string): TreeKeyResult | undefined;
121
+ /** The module path the diagram has selected, from its level and selection; undefined for none, a link or a net. */
122
+ export declare function selectedPath(drill: readonly string[], selection: LevelSelection): string | undefined;
123
+ /**
124
+ * Where a click on a row takes the diagram: the level that holds the module,
125
+ * with it selected (the current level, when the module is drawn there; the
126
+ * root row is the top level with nothing selected).
127
+ */
128
+ export declare function rowTarget(root: ModuleDef, lookup: ModuleLookup, path: string, current: {
129
+ drill: string[];
130
+ expanded: ReadonlySet<string>;
131
+ }): {
132
+ drill: string[];
133
+ selection: LevelSelection;
134
+ };
135
+ /** Where drilling into a row takes the diagram: its own level, nothing selected. */
136
+ export declare function drillInto(node: HierarchyNode): {
137
+ drill: string[];
138
+ selection: LevelSelection;
139
+ };
140
+ /** The paths to open so that `path` shows: its ancestors. */
141
+ export declare function revealPaths(expanded: ReadonlySet<string>, path: string | undefined): Set<string>;
142
+ /** What the panel keeps per tab: open or folded to its rail, its width, the open modules. */
143
+ export interface HierarchyPanelState {
144
+ open: boolean;
145
+ width: number;
146
+ expanded: string[];
147
+ }
148
+ export declare const HIERARCHY_WIDTH: {
149
+ readonly min: 180;
150
+ readonly max: 520;
151
+ readonly default: 280;
152
+ };
153
+ /** A kept state, checked; anything malformed falls back to the default. */
154
+ export declare function panelState(v: unknown, fallbackOpen?: boolean): HierarchyPanelState;
155
+ export declare const clampWidth: (w: number, room?: number) => number;
156
+ /** The row that holds the wiring and hardware (harnesses, cables, fastener stacks): not a module of the system. */
157
+ export declare const WIRING_PATH = "#wiring";
158
+ /**
159
+ * The tree as the panel shows it: the system's structure first, and its
160
+ * wiring and hardware (every harness and fastener stack, wherever it sits)
161
+ * folded into one group row at the bottom, `WIRING_PATH`. Without any, the
162
+ * tree as it is.
163
+ */
164
+ export declare function groupWiring(nodes: readonly HierarchyNode[]): HierarchyNode[];
165
+ /** The marks the tree shows, once each, in the order of their tones: a legend (the first sentence of a mark's label names it). */
166
+ export declare function markLegend(nodes: readonly HierarchyNode[]): {
167
+ tone: NodeMark["tone"];
168
+ label: string;
169
+ }[];
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Isolating a legend entry (a signal type, a domain, a DRC state): the links
3
+ * of that kind stay, with the interfaces and modules they touch; everything
4
+ * else on the level fades. Pure functions of the level's view model, so the
5
+ * result follows the model as it rebuilds and the drill level as it changes.
6
+ */
7
+ import { type Classification } from "./classification";
8
+ import type { ViewLink, ViewModel } from "./types";
9
+ /** What stays at full strength while some legend entries are isolated. */
10
+ export interface Isolation {
11
+ /** View link ids (`ViewLink.id`: each drawn line). */
12
+ links: Set<string>;
13
+ /** Node ids: the ends of those links, the nets of that kind, and the containers that hold either. */
14
+ nodes: Set<string>;
15
+ /** Ports as `node|port`: the ends of those links, and ports of that kind on a node that stays. */
16
+ ports: Set<string>;
17
+ }
18
+ /**
19
+ * The legend entries a link belongs to: its own and, by signal type or
20
+ * domain, those of what it carries (a cable with power and a UART is in both;
21
+ * by DRC state a link has one state, its own).
22
+ */
23
+ export declare function linkKeys(link: ViewLink, mode: Classification): Set<string>;
24
+ /** Every legend entry the level has something of: its links (and what they carry) and its nets. */
25
+ export declare function presentKeys(vm: ViewModel, mode: Classification): Set<string>;
26
+ /** What stays when `keys` are isolated on the level; null when nothing is isolated. */
27
+ export declare function isolate(vm: ViewModel, mode: Classification, keys: ReadonlySet<string>): Isolation | null;
28
+ /**
29
+ * A click on a legend entry: it becomes the one isolated; a click on the only
30
+ * one isolated shows everything again. With `add` (a modifier key) it joins
31
+ * or leaves the ones held.
32
+ */
33
+ export declare function toggleIsolated(current: ReadonlySet<string>, key: string, add?: boolean): Set<string>;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Board nets in the view model (PB-823; UHD docs/boards-and-nets.md).
3
+ *
4
+ * A net is a `Net` interface on the board itself (protocol `net`, not
5
+ * exposed), joined to each pin on it by a stored membership link. Drawing a
6
+ * line per membership would draw a star of N lines per net, most of them to
7
+ * the same component; drawing every pair would be worse. Instead:
8
+ *
9
+ * - each net is a junction node (`:<net>`; `board:<net>` when the board is
10
+ * expanded in place);
11
+ * - each component on the net gets one port for it, named for the net, and
12
+ * one grouped line to the junction whose children are its pins on the net;
13
+ * - a ground net (a ground pin on it and no supply pin) is drawn as ground
14
+ * symbols at its members, like any ground link, unless GND wires are on;
15
+ * - the functional links UHD derives over the nets (an I2C bus, a supply to
16
+ * its loads) are listed by name, and their state is carried by the grouped
17
+ * lines they run over, so a `bus_incomplete` or `harness_wiring` finding
18
+ * on one turns those lines red, as it does for a cable's lanes.
19
+ */
20
+ import type { ModuleDef } from "@deltarobotics/uhd";
21
+ import type { LinkResult, ModuleLookup } from "@deltarobotics/uhd";
22
+ import type { ViewDerived, ViewLink, ViewNode, ViewPort } from "./types";
23
+ /** Node id of a net: the canonical path of the net interface (`:<net>`, or `board:<net>` inside an expanded board). */
24
+ export declare const netNodeId: (prefix: string, net: string) => string;
25
+ /** Port id on a component for its connection to a net. */
26
+ export declare const netPortId: (net: string) => string;
27
+ /**
28
+ * Label of a grouped membership line: the pin's name, or the distinct names
29
+ * of several ("VDD/VDDIO"), or the first and how many others ("IOVDD +3").
30
+ */
31
+ export declare function pinsLabel(names: string[]): string;
32
+ export interface LevelNets {
33
+ /** Junction nodes (ground nets left out unless `grounds`). */
34
+ nodes: ViewNode[];
35
+ /** One grouped line per component and net. */
36
+ links: ViewLink[];
37
+ /** Ports to add to the component nodes, by node id. */
38
+ ports: Map<string, ViewPort[]>;
39
+ derived: ViewDerived[];
40
+ /** Membership link id (prefixed) → grouped line id. */
41
+ owners: Map<string, string>;
42
+ /** Derived link id (prefixed) → grouped line ids it runs over. */
43
+ derivedOwners: Map<string, string[]>;
44
+ }
45
+ /**
46
+ * The nets of `def` drawn at a level (`prefix` "" for the level module itself,
47
+ * `<child>/` for a board expanded in place). `results` are the module's stored
48
+ * link results, `derived` the links UHD derives from them.
49
+ */
50
+ export declare function levelNets(def: ModuleDef, results: LinkResult[], derived: LinkResult[], lookup: ModuleLookup, prefix: string, opts: {
51
+ grounds: boolean;
52
+ parent?: string;
53
+ }): LevelNets;