@deltarobotics/uhd-viewer 0.2.0 → 0.2.1
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 +33 -0
- package/dist/app/assets/index-CEJyT8hF.css +2 -0
- package/dist/app/assets/{index-CkpIRYgM.js → index-DWZ-48wc.js} +35 -35
- package/dist/app/index.html +2 -2
- package/dist/components/components.css +320 -56
- package/dist/components/index.js +1166 -605
- package/dist/components/index.js.map +1 -1
- package/dist/components/types/uhd-viewer/src/cad/ModelView.d.ts +3 -1
- package/dist/components/types/uhd-viewer/src/canvas/Canvas.d.ts +5 -1
- package/dist/components/types/uhd-viewer/src/canvas/interaction.d.ts +2 -2
- package/dist/components/types/uhd-viewer/src/canvas/reveal.d.ts +18 -0
- package/dist/components/types/uhd-viewer/src/chrome/Chrome.d.ts +12 -2
- package/dist/components/types/uhd-viewer/src/chrome/InterfaceCards.d.ts +11 -1
- package/dist/components/types/uhd-viewer/src/chrome/Sections.d.ts +22 -1
- package/dist/components/types/uhd-viewer/src/components.d.ts +4 -4
- package/dist/components/types/uhd-viewer/src/host/targets.d.ts +16 -0
- package/dist/components/types/uhd-viewer/src/model/classification.d.ts +3 -0
- package/dist/components/types/uhd-viewer/src/model/from-uhd.d.ts +3 -2
- package/dist/components/types/uhd-viewer/src/model/hierarchy.d.ts +10 -6
- package/dist/components/types/uhd-viewer/src/model/level.d.ts +7 -0
- package/dist/components/types/uhd-viewer/src/model/slots.d.ts +2 -0
- package/dist/components/types/uhd-viewer/src/ui/Legend.d.ts +23 -4
- package/dist/components/types/uhd-viewer/src/ui/legendFit.d.ts +26 -13
- package/dist/components/types/uhd-viewer/src/viewer/controller.d.ts +1 -0
- package/dist/components/types/uhd-viewer/src/viewer/hierarchy.d.ts +34 -12
- package/dist/components/types/uhd-viewer/src/viewer/views.d.ts +49 -18
- package/dist/headless/index.js.map +1 -1
- package/dist/lib/uhd-viewer.css +1 -1
- package/dist/lib/uhd-viewer.js +11291 -10973
- package/package.json +1 -1
- package/dist/app/assets/index-Boi2erhd.css +0 -2
package/dist/components/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Component, StrictMode, createContext, forwardRef, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
|
|
1
|
+
import { Component, Fragment, StrictMode, createContext, forwardRef, memo, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
|
|
2
2
|
import { createRoot } from "react-dom/client";
|
|
3
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
import { Background, BackgroundVariant, BaseEdge, ConnectionMode, EdgeLabelRenderer, Handle, Position, ReactFlow, ReactFlowProvider, useNodesInitialized, useReactFlow, useStore } from "@xyflow/react";
|
|
5
5
|
import * as Radix from "@radix-ui/react-scroll-area";
|
|
6
6
|
import { icons } from "lucide-react";
|
|
@@ -7417,6 +7417,16 @@ function systemDiagnostics(root, lookup) {
|
|
|
7417
7417
|
return out;
|
|
7418
7418
|
}
|
|
7419
7419
|
//#endregion
|
|
7420
|
+
//#region src/model/level.ts
|
|
7421
|
+
/**
|
|
7422
|
+
* The modules a level draws: its nodes less what is not a module of its own
|
|
7423
|
+
* (the drilled-into module's boundary ports, a board's net junctions and
|
|
7424
|
+
* their taps). A level with none is empty, whatever ports it shows.
|
|
7425
|
+
*/
|
|
7426
|
+
function levelModules(nodes) {
|
|
7427
|
+
return nodes.filter((n) => !n.sheetPort && !n.net && !n.tapOf);
|
|
7428
|
+
}
|
|
7429
|
+
//#endregion
|
|
7420
7430
|
//#region src/model/classification.ts
|
|
7421
7431
|
var CLASSIFICATIONS = [
|
|
7422
7432
|
{
|
|
@@ -7487,64 +7497,76 @@ function classKey(item, mode) {
|
|
|
7487
7497
|
var DRC_LEGEND = [
|
|
7488
7498
|
{
|
|
7489
7499
|
key: "configured",
|
|
7490
|
-
label: "
|
|
7500
|
+
label: "Configured",
|
|
7501
|
+
meaning: "No findings",
|
|
7491
7502
|
color: DRC_COLORS.configured
|
|
7492
7503
|
},
|
|
7493
7504
|
{
|
|
7494
7505
|
key: "partial",
|
|
7495
|
-
label: "
|
|
7506
|
+
label: "Partial",
|
|
7507
|
+
meaning: "Warnings",
|
|
7496
7508
|
color: DRC_COLORS.partial
|
|
7497
7509
|
},
|
|
7498
7510
|
{
|
|
7499
7511
|
key: "incompatible",
|
|
7500
|
-
label: "
|
|
7512
|
+
label: "Incompatible",
|
|
7513
|
+
meaning: "Errors",
|
|
7501
7514
|
color: DRC_COLORS.incompatible
|
|
7502
7515
|
},
|
|
7503
7516
|
{
|
|
7504
7517
|
key: "unconfigured",
|
|
7505
|
-
label: "
|
|
7518
|
+
label: "Not configured",
|
|
7519
|
+
meaning: "Nothing linked",
|
|
7506
7520
|
color: DRC_COLORS.unconfigured
|
|
7507
7521
|
}
|
|
7508
7522
|
];
|
|
7509
7523
|
var SIGNAL_LEGEND = [
|
|
7510
7524
|
{
|
|
7511
7525
|
key: "power",
|
|
7512
|
-
label: "
|
|
7526
|
+
label: "Power",
|
|
7527
|
+
meaning: "Supply rails",
|
|
7513
7528
|
color: SIGNAL_COLORS.power
|
|
7514
7529
|
},
|
|
7515
7530
|
{
|
|
7516
7531
|
key: "ground",
|
|
7517
|
-
label: "
|
|
7532
|
+
label: "Ground",
|
|
7533
|
+
meaning: "Return paths",
|
|
7518
7534
|
color: SIGNAL_COLORS.ground
|
|
7519
7535
|
},
|
|
7520
7536
|
{
|
|
7521
7537
|
key: "phase",
|
|
7522
|
-
label: "
|
|
7538
|
+
label: "Motor phase",
|
|
7539
|
+
meaning: "ESC to motor windings",
|
|
7523
7540
|
color: SIGNAL_COLORS.bldc_3phase
|
|
7524
7541
|
},
|
|
7525
7542
|
{
|
|
7526
7543
|
key: "pwm",
|
|
7527
|
-
label: "
|
|
7544
|
+
label: "DShot / ESC",
|
|
7545
|
+
meaning: "Motor control",
|
|
7528
7546
|
color: SIGNAL_COLORS.dshot
|
|
7529
7547
|
},
|
|
7530
7548
|
{
|
|
7531
7549
|
key: "uart",
|
|
7532
7550
|
label: "UART / CRSF",
|
|
7551
|
+
meaning: "Serial links",
|
|
7533
7552
|
color: SIGNAL_COLORS.uart
|
|
7534
7553
|
},
|
|
7535
7554
|
{
|
|
7536
7555
|
key: "i2c",
|
|
7537
7556
|
label: "I2C",
|
|
7557
|
+
meaning: "Sensor bus",
|
|
7538
7558
|
color: SIGNAL_COLORS.i2c
|
|
7539
7559
|
},
|
|
7540
7560
|
{
|
|
7541
7561
|
key: "rf",
|
|
7542
7562
|
label: "RF",
|
|
7563
|
+
meaning: "Antenna feeds",
|
|
7543
7564
|
color: SIGNAL_COLORS.rf
|
|
7544
7565
|
},
|
|
7545
7566
|
{
|
|
7546
7567
|
key: "other-domains",
|
|
7547
|
-
label: "
|
|
7568
|
+
label: "Other domains",
|
|
7569
|
+
meaning: "Not electrical",
|
|
7548
7570
|
color: "var(--uhd-domain-other)"
|
|
7549
7571
|
}
|
|
7550
7572
|
];
|
|
@@ -7553,68 +7575,81 @@ var SIGNAL_EXTRA = [
|
|
|
7553
7575
|
{
|
|
7554
7576
|
key: "spi",
|
|
7555
7577
|
label: "SPI",
|
|
7578
|
+
meaning: "Peripheral bus",
|
|
7556
7579
|
color: SIGNAL_COLORS.spi
|
|
7557
7580
|
},
|
|
7558
7581
|
{
|
|
7559
7582
|
key: "analog",
|
|
7560
|
-
label: "
|
|
7583
|
+
label: "Analog",
|
|
7584
|
+
meaning: "Analog signals",
|
|
7561
7585
|
color: SIGNAL_COLORS.analog
|
|
7562
7586
|
},
|
|
7563
7587
|
{
|
|
7564
7588
|
key: "digital",
|
|
7565
|
-
label: "
|
|
7589
|
+
label: "Digital",
|
|
7590
|
+
meaning: "Logic I/O",
|
|
7566
7591
|
color: SIGNAL_COLORS.digital
|
|
7567
7592
|
},
|
|
7568
7593
|
{
|
|
7569
7594
|
key: "can",
|
|
7570
7595
|
label: "CAN",
|
|
7596
|
+
meaning: "Field bus",
|
|
7571
7597
|
color: SIGNAL_COLORS.can
|
|
7572
7598
|
},
|
|
7573
7599
|
{
|
|
7574
7600
|
key: "other",
|
|
7575
|
-
label: "
|
|
7601
|
+
label: "Other signals",
|
|
7602
|
+
meaning: "Unclassified protocols",
|
|
7576
7603
|
color: "var(--uhd-signal-other)"
|
|
7577
7604
|
}
|
|
7578
7605
|
];
|
|
7579
7606
|
var DOMAIN_LEGEND = [
|
|
7580
7607
|
{
|
|
7581
7608
|
key: "electrical",
|
|
7582
|
-
label: "
|
|
7609
|
+
label: "Electrical",
|
|
7610
|
+
meaning: "Power and signals",
|
|
7583
7611
|
color: DOMAIN_COLORS.electrical
|
|
7584
7612
|
},
|
|
7585
7613
|
{
|
|
7586
7614
|
key: "mechanical",
|
|
7587
|
-
label: "
|
|
7615
|
+
label: "Mechanical",
|
|
7616
|
+
meaning: "Mounts and fasteners",
|
|
7588
7617
|
color: DOMAIN_COLORS.mechanical
|
|
7589
7618
|
},
|
|
7590
7619
|
{
|
|
7591
7620
|
key: "pneumatic",
|
|
7592
|
-
label: "
|
|
7621
|
+
label: "Pneumatic",
|
|
7622
|
+
meaning: "Air lines",
|
|
7593
7623
|
color: DOMAIN_COLORS.pneumatic
|
|
7594
7624
|
},
|
|
7595
7625
|
{
|
|
7596
7626
|
key: "hydraulic",
|
|
7597
|
-
label: "
|
|
7627
|
+
label: "Hydraulic",
|
|
7628
|
+
meaning: "Fluid lines",
|
|
7598
7629
|
color: DOMAIN_COLORS.hydraulic
|
|
7599
7630
|
},
|
|
7600
7631
|
{
|
|
7601
7632
|
key: "thermal",
|
|
7602
|
-
label: "
|
|
7633
|
+
label: "Thermal",
|
|
7634
|
+
meaning: "Heat paths",
|
|
7603
7635
|
color: DOMAIN_COLORS.thermal
|
|
7604
7636
|
},
|
|
7605
7637
|
{
|
|
7606
7638
|
key: "network",
|
|
7607
|
-
label: "
|
|
7639
|
+
label: "Network",
|
|
7640
|
+
meaning: "Data links",
|
|
7608
7641
|
color: DOMAIN_COLORS.network
|
|
7609
7642
|
}
|
|
7610
7643
|
];
|
|
7611
7644
|
var DOMAIN_EXTRA = [{
|
|
7612
7645
|
key: "software",
|
|
7613
|
-
label: "
|
|
7646
|
+
label: "Software",
|
|
7647
|
+
meaning: "Software interfaces",
|
|
7614
7648
|
color: DOMAIN_COLORS.software
|
|
7615
7649
|
}, {
|
|
7616
7650
|
key: "other",
|
|
7617
|
-
label: "
|
|
7651
|
+
label: "Other",
|
|
7652
|
+
meaning: "Other domains",
|
|
7618
7653
|
color: "var(--uhd-signal-other)"
|
|
7619
7654
|
}];
|
|
7620
7655
|
/**
|
|
@@ -10619,12 +10654,12 @@ var rightRelease = (press) => press.panning ? "pan" : "menu";
|
|
|
10619
10654
|
var TOOL_OPTIONS = [{
|
|
10620
10655
|
id: "select",
|
|
10621
10656
|
icon: "mouse-pointer-2",
|
|
10622
|
-
label: "Select
|
|
10657
|
+
label: "Select",
|
|
10623
10658
|
shortcut: "V"
|
|
10624
10659
|
}, {
|
|
10625
10660
|
id: "pan",
|
|
10626
10661
|
icon: "hand",
|
|
10627
|
-
label: "Pan
|
|
10662
|
+
label: "Pan",
|
|
10628
10663
|
shortcut: "H"
|
|
10629
10664
|
}];
|
|
10630
10665
|
var ARROWS = {
|
|
@@ -12454,7 +12489,7 @@ function PairPreview({ vm, link, mode, onOpen }) {
|
|
|
12454
12489
|
}), /* @__PURE__ */ jsx(IconButton, {
|
|
12455
12490
|
icon: "git-compare-arrows",
|
|
12456
12491
|
size: "sm",
|
|
12457
|
-
label: "
|
|
12492
|
+
label: "Pair view",
|
|
12458
12493
|
onClick: onOpen
|
|
12459
12494
|
})]
|
|
12460
12495
|
}),
|
|
@@ -12663,6 +12698,36 @@ function selectableLink(vm, id) {
|
|
|
12663
12698
|
id: line.linkId
|
|
12664
12699
|
} : null;
|
|
12665
12700
|
}
|
|
12701
|
+
/**
|
|
12702
|
+
* The lines a harness is drawn along on this level, when it has no card of
|
|
12703
|
+
* its own: a cable between two parts is one line with the harness as a region
|
|
12704
|
+
* along it, and the links that name a harness carry its region too. Empty for
|
|
12705
|
+
* a harness drawn as a card (and for anything else).
|
|
12706
|
+
*/
|
|
12707
|
+
function harnessLines(vm, id) {
|
|
12708
|
+
if (vm.nodes.some((n) => n.id === id)) return [];
|
|
12709
|
+
return vm.links.filter((l) => l.run?.id === id);
|
|
12710
|
+
}
|
|
12711
|
+
/**
|
|
12712
|
+
* A module selection as the diagram can show it: a harness drawn along its
|
|
12713
|
+
* lines (no card of its own) is selected as the line that carries its name
|
|
12714
|
+
* tab, so a row of the hierarchy or a host's focus on it selects and frames
|
|
12715
|
+
* something drawn. Anything else as it is.
|
|
12716
|
+
*/
|
|
12717
|
+
function drawnSelection(vm, selection) {
|
|
12718
|
+
if (selection?.kind !== "node") return selection;
|
|
12719
|
+
const lines = harnessLines(vm, selection.id);
|
|
12720
|
+
const line = lines.find((l) => l.run?.tab) ?? lines[0];
|
|
12721
|
+
return line ? {
|
|
12722
|
+
kind: "link",
|
|
12723
|
+
id: line.linkId
|
|
12724
|
+
} : selection;
|
|
12725
|
+
}
|
|
12726
|
+
/** The harness a selected line runs through (its path on the level), if any: its row in the hierarchy. */
|
|
12727
|
+
function selectedHarness(vm, selection) {
|
|
12728
|
+
if (selection?.kind !== "link") return void 0;
|
|
12729
|
+
return vm.links.find((l) => (l.linkId === selection.id || l.id === selection.id) && l.run)?.run?.id;
|
|
12730
|
+
}
|
|
12666
12731
|
/** `id` relative to the level at `drill`: itself, and without the level's path when it starts with it. */
|
|
12667
12732
|
function relative(id, drill) {
|
|
12668
12733
|
const at = drill.join("/");
|
|
@@ -12687,6 +12752,10 @@ function selectTarget(vm, drill, ids) {
|
|
|
12687
12752
|
kind: "node",
|
|
12688
12753
|
id: c
|
|
12689
12754
|
};
|
|
12755
|
+
if (kind !== "link" && harnessLines(vm, c).length) return drawnSelection(vm, {
|
|
12756
|
+
kind: "node",
|
|
12757
|
+
id: c
|
|
12758
|
+
});
|
|
12690
12759
|
if (kind !== "node") {
|
|
12691
12760
|
const link = selectableLink(vm, c);
|
|
12692
12761
|
if (link) return link;
|
|
@@ -13142,13 +13211,20 @@ function useViewerController(source, options, host) {
|
|
|
13142
13211
|
menu: Boolean(menu)
|
|
13143
13212
|
};
|
|
13144
13213
|
const seq = useRef(0);
|
|
13214
|
+
const viewAt = (at) => at.join("/") === drill.join("/") ? vm : buildView(system, scenario.lookup, at, {
|
|
13215
|
+
expanded,
|
|
13216
|
+
overrides,
|
|
13217
|
+
diagnostics,
|
|
13218
|
+
grounds: showGrounds
|
|
13219
|
+
});
|
|
13145
13220
|
const latest = useRef({
|
|
13146
13221
|
system,
|
|
13147
13222
|
lookup: scenario.lookup,
|
|
13148
13223
|
drill,
|
|
13149
13224
|
expanded,
|
|
13150
13225
|
vm,
|
|
13151
|
-
view
|
|
13226
|
+
view,
|
|
13227
|
+
viewAt
|
|
13152
13228
|
});
|
|
13153
13229
|
latest.current = {
|
|
13154
13230
|
system,
|
|
@@ -13156,7 +13232,28 @@ function useViewerController(source, options, host) {
|
|
|
13156
13232
|
drill,
|
|
13157
13233
|
expanded,
|
|
13158
13234
|
vm,
|
|
13159
|
-
view
|
|
13235
|
+
view,
|
|
13236
|
+
viewAt
|
|
13237
|
+
};
|
|
13238
|
+
/**
|
|
13239
|
+
* A focus on a module (a row of the hierarchy, a host's focus, a finding's Locate), as the diagram shows it at
|
|
13240
|
+
* `at`: the module selected and framed; a harness drawn along its lines (no card of its own) selected as the
|
|
13241
|
+
* line with its name tab, and its lines framed.
|
|
13242
|
+
*/
|
|
13243
|
+
const focusOn = (at, target, n) => {
|
|
13244
|
+
if (target?.kind !== "node") return target;
|
|
13245
|
+
const levelVm = latest.current.viewAt(at);
|
|
13246
|
+
const shown = drawnSelection(levelVm, target);
|
|
13247
|
+
const lines = shown?.kind === "link" ? harnessLines(levelVm, target.id).map((l) => l.id) : void 0;
|
|
13248
|
+
setCentre(lines?.length ? {
|
|
13249
|
+
id: target.id,
|
|
13250
|
+
seq: n,
|
|
13251
|
+
lines
|
|
13252
|
+
} : {
|
|
13253
|
+
id: target.id,
|
|
13254
|
+
seq: n
|
|
13255
|
+
});
|
|
13256
|
+
return shown;
|
|
13160
13257
|
};
|
|
13161
13258
|
useEffect(() => {
|
|
13162
13259
|
if (!host) return;
|
|
@@ -13175,32 +13272,36 @@ function useViewerController(source, options, host) {
|
|
|
13175
13272
|
drill: d,
|
|
13176
13273
|
expanded: ex
|
|
13177
13274
|
});
|
|
13275
|
+
const n = ++seq.current;
|
|
13178
13276
|
setDrill(sameDrill(t.drill));
|
|
13179
|
-
setSelection(t.selection);
|
|
13277
|
+
setSelection(focusOn(t.drill, t.selection, n));
|
|
13180
13278
|
setPairLink(null);
|
|
13181
13279
|
setPanel((p) => p ?? "hierarchy");
|
|
13182
|
-
if (t.selection) {
|
|
13183
|
-
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
seq: n
|
|
13187
|
-
});
|
|
13188
|
-
setCadFocus({
|
|
13189
|
-
path: fullId(t.drill, t.selection.id),
|
|
13190
|
-
seq: n
|
|
13191
|
-
});
|
|
13192
|
-
}
|
|
13280
|
+
if (t.selection) setCadFocus({
|
|
13281
|
+
path: fullId(t.drill, t.selection.id),
|
|
13282
|
+
seq: n
|
|
13283
|
+
});
|
|
13193
13284
|
return;
|
|
13194
13285
|
}
|
|
13195
13286
|
case "uhd-viewer:select": {
|
|
13196
13287
|
const sel = selectTarget(v, d, m.ids);
|
|
13197
13288
|
if (sel !== void 0) setSelection(sel);
|
|
13198
|
-
|
|
13289
|
+
const run = selectedHarness(v, sel ?? null);
|
|
13290
|
+
const named = run !== void 0 && m.ids.some((id) => [run, fullId(d, run)].includes(id.replace(/^node:/, "")));
|
|
13291
|
+
if (sel && named && m.reveal !== false && shownView !== "3d") setCentre({
|
|
13292
|
+
id: run,
|
|
13293
|
+
seq: ++seq.current,
|
|
13294
|
+
lines: harnessLines(v, run).map((l) => l.id)
|
|
13295
|
+
});
|
|
13296
|
+
else if (sel && m.reveal !== false && shownView !== "3d") setReveal({
|
|
13199
13297
|
selection: sel,
|
|
13200
13298
|
seq: ++seq.current
|
|
13201
13299
|
});
|
|
13202
13300
|
if (shownView === "3d") {
|
|
13203
|
-
const t =
|
|
13301
|
+
const t = named ? {
|
|
13302
|
+
kind: "node",
|
|
13303
|
+
path: fullId(d, run)
|
|
13304
|
+
} : cadSelectTarget(sys, lookup, d, sel, m.ids);
|
|
13204
13305
|
if (t) setCadFocus({
|
|
13205
13306
|
...t,
|
|
13206
13307
|
seq: ++seq.current,
|
|
@@ -13289,11 +13390,7 @@ function useViewerController(source, options, host) {
|
|
|
13289
13390
|
expanded: ex
|
|
13290
13391
|
});
|
|
13291
13392
|
setDrill((cur) => cur.join("/") === t.drill.join("/") ? cur : t.drill);
|
|
13292
|
-
setSelection(t.selection);
|
|
13293
|
-
if (t.selection) setCentre({
|
|
13294
|
-
id: t.selection.id,
|
|
13295
|
-
seq: n
|
|
13296
|
-
});
|
|
13393
|
+
setSelection(focusOn(t.drill, t.selection, n));
|
|
13297
13394
|
}, [setSelection]);
|
|
13298
13395
|
const focusRef = useRef(focusPath);
|
|
13299
13396
|
focusRef.current = focusPath;
|
|
@@ -13350,57 +13447,85 @@ function useViewerController(source, options, host) {
|
|
|
13350
13447
|
y
|
|
13351
13448
|
}), []);
|
|
13352
13449
|
const menuNode = menu?.id ? vm.nodes.find((n) => n.id === menu.id) : void 0;
|
|
13450
|
+
/** What a module's menu offers about it: inspect, open, its source, copy its path. */
|
|
13451
|
+
const nodeItems = (node) => {
|
|
13452
|
+
const items = [];
|
|
13453
|
+
if (node.sheetPort) return items;
|
|
13454
|
+
const path = fullId(drill, node.tapOf ?? node.id);
|
|
13455
|
+
const { defId } = node;
|
|
13456
|
+
items.push({
|
|
13457
|
+
label: "Inspect",
|
|
13458
|
+
icon: "scan-search",
|
|
13459
|
+
run: () => hostActions.inspect ? hostActions.inspect(path, defId) : setPanel("hierarchy")
|
|
13460
|
+
});
|
|
13461
|
+
if (openAction(node, Boolean(hostActions.openModule)) === "open") {
|
|
13462
|
+
const at = fullId(drill, node.id);
|
|
13463
|
+
items.push({
|
|
13464
|
+
label: "Open in new tab",
|
|
13465
|
+
icon: "square-arrow-out-up-right",
|
|
13466
|
+
run: () => hostActions.openModule(at)
|
|
13467
|
+
});
|
|
13468
|
+
}
|
|
13469
|
+
if (defId && hostActions.openSource) items.push({
|
|
13470
|
+
label: "Open source",
|
|
13471
|
+
icon: "file-code",
|
|
13472
|
+
run: () => hostActions.openSource(defId, fullId(drill, node.id))
|
|
13473
|
+
});
|
|
13474
|
+
if (typeof navigator !== "undefined" && navigator.clipboard) items.push({
|
|
13475
|
+
label: "Copy path",
|
|
13476
|
+
icon: "copy",
|
|
13477
|
+
run: () => void navigator.clipboard.writeText(path).catch(() => void 0)
|
|
13478
|
+
});
|
|
13479
|
+
return items;
|
|
13480
|
+
};
|
|
13353
13481
|
const menuItems = [];
|
|
13354
13482
|
if (menu && !menu.id) {
|
|
13355
13483
|
menuItems.push({
|
|
13356
|
-
label: "
|
|
13484
|
+
label: "Fit view",
|
|
13485
|
+
icon: "maximize",
|
|
13486
|
+
shortcut: "F",
|
|
13357
13487
|
run: () => viewDo("fit")
|
|
13358
13488
|
});
|
|
13359
13489
|
if (drawn.nodes.length > 1) menuItems.push({
|
|
13360
|
-
label: "
|
|
13490
|
+
label: "Select all",
|
|
13491
|
+
icon: "square-dashed",
|
|
13492
|
+
shortcut: "Ctrl+A",
|
|
13361
13493
|
run: onSelectAll
|
|
13362
13494
|
});
|
|
13363
13495
|
menuItems.push(interaction.tool === "pan" ? {
|
|
13364
|
-
label: "
|
|
13496
|
+
label: "Select tool",
|
|
13497
|
+
icon: "mouse-pointer-2",
|
|
13498
|
+
shortcut: "V",
|
|
13365
13499
|
run: () => setTool("select")
|
|
13366
13500
|
} : {
|
|
13367
|
-
label: "
|
|
13501
|
+
label: "Pan tool",
|
|
13502
|
+
icon: "hand",
|
|
13503
|
+
shortcut: "H",
|
|
13368
13504
|
run: () => setTool("pan")
|
|
13369
13505
|
});
|
|
13370
13506
|
if (isolated.size) menuItems.push({
|
|
13371
|
-
label: "
|
|
13507
|
+
label: "Show all",
|
|
13508
|
+
icon: "eye",
|
|
13509
|
+
shortcut: "Esc",
|
|
13372
13510
|
run: clearIsolated
|
|
13373
13511
|
});
|
|
13512
|
+
const chosen = selection?.kind === "node" && group.length <= 1 ? levelModules(vm.nodes).find((n) => n.id === selection.id) : void 0;
|
|
13513
|
+
(chosen ? nodeItems(chosen) : []).forEach((it, i) => menuItems.push(i === 0 ? {
|
|
13514
|
+
...it,
|
|
13515
|
+
separator: true
|
|
13516
|
+
} : it));
|
|
13374
13517
|
}
|
|
13375
|
-
if (menuNode
|
|
13376
|
-
const path = fullId(drill, menuNode.tapOf ?? menuNode.id);
|
|
13377
|
-
const { defId } = menuNode;
|
|
13378
|
-
menuItems.push({
|
|
13379
|
-
label: "INSPECT",
|
|
13380
|
-
run: () => hostActions.inspect ? hostActions.inspect(path, defId) : setPanel("hierarchy")
|
|
13381
|
-
});
|
|
13382
|
-
}
|
|
13383
|
-
if (menuNode && openAction(menuNode, Boolean(hostActions.openModule)) === "open") {
|
|
13384
|
-
const path = fullId(drill, menuNode.id);
|
|
13385
|
-
menuItems.push({
|
|
13386
|
-
label: "OPEN IN NEW TAB",
|
|
13387
|
-
run: () => hostActions.openModule(path)
|
|
13388
|
-
});
|
|
13389
|
-
}
|
|
13390
|
-
if (menuNode?.defId && hostActions.openSource) {
|
|
13391
|
-
const { defId } = menuNode;
|
|
13392
|
-
menuItems.push({
|
|
13393
|
-
label: "OPEN SOURCE",
|
|
13394
|
-
run: () => hostActions.openSource(defId, fullId(drill, menuNode.id))
|
|
13395
|
-
});
|
|
13396
|
-
}
|
|
13518
|
+
if (menuNode) menuItems.push(...nodeItems(menuNode));
|
|
13397
13519
|
if (menuNode?.childCount) {
|
|
13398
13520
|
menuItems.push({
|
|
13399
|
-
label: menuNode.expanded ? "
|
|
13521
|
+
label: menuNode.expanded ? "Collapse" : "Expand in place",
|
|
13522
|
+
icon: menuNode.expanded ? "chevrons-down-up" : "chevrons-up-down",
|
|
13523
|
+
separator: true,
|
|
13400
13524
|
run: () => onToggleExpand(menuNode.id)
|
|
13401
13525
|
});
|
|
13402
13526
|
menuItems.push({
|
|
13403
|
-
label: "
|
|
13527
|
+
label: "Open as canvas",
|
|
13528
|
+
icon: "layers",
|
|
13404
13529
|
run: () => onDrill(menuNode.id)
|
|
13405
13530
|
});
|
|
13406
13531
|
}
|
|
@@ -13675,7 +13800,7 @@ function Port({ placed, x, y, color, faded, exported, label, ground, selected, d
|
|
|
13675
13800
|
const mechanical = placed.port.domain === "mechanical";
|
|
13676
13801
|
const size = exported ? 11 : 9;
|
|
13677
13802
|
const id = `p:${placed.port.id}`;
|
|
13678
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
13803
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
13679
13804
|
/* @__PURE__ */ jsx(Handle, {
|
|
13680
13805
|
type: "source",
|
|
13681
13806
|
id,
|
|
@@ -13767,7 +13892,7 @@ function Ports({ data, labels, border = 2 }) {
|
|
|
13767
13892
|
const { box, ports, mode, showGrounds, selectedPorts, node } = data;
|
|
13768
13893
|
const perSide = (side) => ports.filter((q) => q.side === side).length;
|
|
13769
13894
|
const widthFor = (p) => p.side === "left" || p.side === "right" ? sideLabelWidth(box.w) : Math.max(30, Math.min(160, (box.w - 32) / (perSide(p.side) + 1) - 4));
|
|
13770
|
-
return /* @__PURE__ */ jsx(Fragment, { children: ports.map((p) => {
|
|
13895
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: ports.map((p) => {
|
|
13771
13896
|
const onlyGround = p.links.every((l) => l.ground);
|
|
13772
13897
|
return /* @__PURE__ */ jsx(Port, {
|
|
13773
13898
|
placed: p,
|
|
@@ -14751,7 +14876,7 @@ function LinkEdge({ id, data, selected }) {
|
|
|
14751
14876
|
]
|
|
14752
14877
|
}, `${kind}${index}`);
|
|
14753
14878
|
const anchor = geo.anchor;
|
|
14754
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14879
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
14755
14880
|
geo.region && /* @__PURE__ */ jsx("path", {
|
|
14756
14881
|
d: geo.region,
|
|
14757
14882
|
fill: "color-mix(in oklab, var(--uhd-text) 5%, transparent)",
|
|
@@ -14908,22 +15033,57 @@ function selectionBounds(vm, layout, selection) {
|
|
|
14908
15033
|
y1: Math.max(...ys)
|
|
14909
15034
|
};
|
|
14910
15035
|
}
|
|
14911
|
-
/**
|
|
14912
|
-
|
|
14913
|
-
|
|
14914
|
-
|
|
14915
|
-
|
|
14916
|
-
|
|
15036
|
+
/** Where several lines are drawn together (a harness along the lines that carry it), in flow coordinates. */
|
|
15037
|
+
function linesBounds(layout, lineIds) {
|
|
15038
|
+
const pts = lineIds.flatMap((id) => layout.routes[id] ?? []);
|
|
15039
|
+
if (!pts.length) return void 0;
|
|
15040
|
+
const xs = pts.map((p) => p[0]);
|
|
15041
|
+
const ys = pts.map((p) => p[1]);
|
|
15042
|
+
return {
|
|
15043
|
+
x0: Math.min(...xs),
|
|
15044
|
+
y0: Math.min(...ys),
|
|
15045
|
+
x1: Math.max(...xs),
|
|
15046
|
+
y1: Math.max(...ys)
|
|
15047
|
+
};
|
|
15048
|
+
}
|
|
15049
|
+
/** The part of the pane clear of the floating chrome (the inspector too, when open). */
|
|
15050
|
+
function clearView(pane, inspector) {
|
|
14917
15051
|
const left = 64;
|
|
14918
15052
|
const top = 56;
|
|
14919
15053
|
const bottom = 72;
|
|
14920
15054
|
const right = inspector ? Math.max(64, Math.min(376, pane.width - left - 160)) : 64;
|
|
14921
|
-
|
|
15055
|
+
return {
|
|
14922
15056
|
x0: left,
|
|
14923
15057
|
y0: top,
|
|
14924
15058
|
x1: pane.width - right,
|
|
14925
15059
|
y1: pane.height - bottom
|
|
14926
15060
|
};
|
|
15061
|
+
}
|
|
15062
|
+
/**
|
|
15063
|
+
* The viewport that frames `rect`, as a module is framed when it is focused:
|
|
15064
|
+
* centred in the view clear of the floating chrome, zoomed to fit it, never
|
|
15065
|
+
* past `maxZoom`.
|
|
15066
|
+
*/
|
|
15067
|
+
function frameViewport(rect, pane, inspector, { maxZoom = 1, minZoom = .2 } = {}) {
|
|
15068
|
+
const view = clearView(pane, inspector);
|
|
15069
|
+
const w = Math.max(1, view.x1 - view.x0 - 48);
|
|
15070
|
+
const h = Math.max(1, view.y1 - view.y0 - 48);
|
|
15071
|
+
const zoom = Math.max(minZoom, Math.min(maxZoom, w / Math.max(1, rect.x1 - rect.x0), h / Math.max(1, rect.y1 - rect.y0)));
|
|
15072
|
+
const cx = (rect.x0 + rect.x1) / 2;
|
|
15073
|
+
const cy = (rect.y0 + rect.y1) / 2;
|
|
15074
|
+
return {
|
|
15075
|
+
x: (view.x0 + view.x1) / 2 - cx * zoom,
|
|
15076
|
+
y: (view.y0 + view.y1) / 2 - cy * zoom,
|
|
15077
|
+
zoom
|
|
15078
|
+
};
|
|
15079
|
+
}
|
|
15080
|
+
/**
|
|
15081
|
+
* The viewport that shows `rect` clear of the floating chrome (the inspector
|
|
15082
|
+
* too, when open), or undefined when it is in view already. It keeps the zoom
|
|
15083
|
+
* and pans, zooming out only as far as the selection needs; never in.
|
|
15084
|
+
*/
|
|
15085
|
+
function revealViewport(rect, viewport, pane, inspector, minZoom = .2) {
|
|
15086
|
+
const view = clearView(pane, inspector);
|
|
14927
15087
|
const z = viewport.zoom;
|
|
14928
15088
|
const on = {
|
|
14929
15089
|
x0: rect.x0 * z + viewport.x,
|
|
@@ -15303,8 +15463,24 @@ function Canvas(props) {
|
|
|
15303
15463
|
const moved = useRef(false);
|
|
15304
15464
|
const centred = useRef(0);
|
|
15305
15465
|
const { centre, inspector } = props;
|
|
15466
|
+
const paneWidth = useStore((s) => s.width);
|
|
15467
|
+
const paneHeight = useStore((s) => s.height);
|
|
15306
15468
|
useEffect(() => {
|
|
15307
|
-
if (!centre || !drawn || centred.current === centre.seq
|
|
15469
|
+
if (!centre || !drawn || centred.current === centre.seq) return;
|
|
15470
|
+
if (centre.lines) {
|
|
15471
|
+
const rect = linesBounds(layout, centre.lines);
|
|
15472
|
+
if (!rect || !paneWidth || !paneHeight) return;
|
|
15473
|
+
const t = setTimeout(() => {
|
|
15474
|
+
centred.current = centre.seq;
|
|
15475
|
+
moved.current = true;
|
|
15476
|
+
flow.setViewport(frameViewport(rect, {
|
|
15477
|
+
width: paneWidth,
|
|
15478
|
+
height: paneHeight
|
|
15479
|
+
}, inspector ?? false), { duration: 300 });
|
|
15480
|
+
}, 60);
|
|
15481
|
+
return () => clearTimeout(t);
|
|
15482
|
+
}
|
|
15483
|
+
if (!nodes.some((n) => n.id === centre.id)) return;
|
|
15308
15484
|
const t = setTimeout(() => {
|
|
15309
15485
|
centred.current = centre.seq;
|
|
15310
15486
|
moved.current = true;
|
|
@@ -15320,13 +15496,14 @@ function Canvas(props) {
|
|
|
15320
15496
|
centre,
|
|
15321
15497
|
drawn,
|
|
15322
15498
|
nodes,
|
|
15499
|
+
layout,
|
|
15323
15500
|
flow,
|
|
15324
|
-
inspector
|
|
15501
|
+
inspector,
|
|
15502
|
+
paneWidth,
|
|
15503
|
+
paneHeight
|
|
15325
15504
|
]);
|
|
15326
15505
|
const revealed = useRef(0);
|
|
15327
15506
|
const { reveal } = props;
|
|
15328
|
-
const paneWidth = useStore((s) => s.width);
|
|
15329
|
-
const paneHeight = useStore((s) => s.height);
|
|
15330
15507
|
useEffect(() => {
|
|
15331
15508
|
if (!reveal || !drawn || revealed.current === reveal.seq || !paneWidth || !paneHeight) return;
|
|
15332
15509
|
const rect = selectionBounds(vm, layout, reveal.selection);
|
|
@@ -16242,7 +16419,7 @@ function PackageSection({ def, titled = true }) {
|
|
|
16242
16419
|
const pkg = def ? partPackage(def) : void 0;
|
|
16243
16420
|
if (!pkg) return null;
|
|
16244
16421
|
const s = pkg.size_mm;
|
|
16245
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [titled && /* @__PURE__ */ jsx("div", {
|
|
16422
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [titled && /* @__PURE__ */ jsx("div", {
|
|
16246
16423
|
className: "section-title",
|
|
16247
16424
|
children: "PACKAGE"
|
|
16248
16425
|
}), /* @__PURE__ */ jsxs("div", {
|
|
@@ -16322,7 +16499,7 @@ function PinTable({ def, node, vm, titled = true }) {
|
|
|
16322
16499
|
return m;
|
|
16323
16500
|
}, [vm, node]);
|
|
16324
16501
|
if (!pins.length) return null;
|
|
16325
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [titled && /* @__PURE__ */ jsxs("div", {
|
|
16502
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [titled && /* @__PURE__ */ jsxs("div", {
|
|
16326
16503
|
className: "section-title",
|
|
16327
16504
|
children: [
|
|
16328
16505
|
"PINS · ",
|
|
@@ -16364,7 +16541,7 @@ function PinTable({ def, node, vm, titled = true }) {
|
|
|
16364
16541
|
/** Functional links derived over nets, listed by name. */
|
|
16365
16542
|
function DerivedList({ items, title, onSelect, titled = true }) {
|
|
16366
16543
|
if (!items.length) return null;
|
|
16367
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [titled && /* @__PURE__ */ jsxs("div", {
|
|
16544
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [titled && /* @__PURE__ */ jsxs("div", {
|
|
16368
16545
|
className: "section-title",
|
|
16369
16546
|
children: [
|
|
16370
16547
|
title,
|
|
@@ -16518,7 +16695,7 @@ function DerivedDetails({ d, vm, onSelect, bare }) {
|
|
|
16518
16695
|
children: label(n)
|
|
16519
16696
|
}, n))
|
|
16520
16697
|
}),
|
|
16521
|
-
d.children.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
16698
|
+
d.children.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
16522
16699
|
className: "section-title",
|
|
16523
16700
|
children: ["CONDUCTORS · ", d.children.length]
|
|
16524
16701
|
}), /* @__PURE__ */ jsx("table", {
|
|
@@ -16537,7 +16714,7 @@ function DerivedDetails({ d, vm, onSelect, bare }) {
|
|
|
16537
16714
|
})
|
|
16538
16715
|
] }, i)) })
|
|
16539
16716
|
})] }),
|
|
16540
|
-
d.diagnostics.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
16717
|
+
d.diagnostics.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
16541
16718
|
className: "section-title",
|
|
16542
16719
|
children: "DIAGNOSTICS"
|
|
16543
16720
|
}), d.diagnostics.map((m) => /* @__PURE__ */ jsx("p", {
|
|
@@ -16610,7 +16787,7 @@ function BoardViews({ def, lookup, resolve, highlight, onPick, drawings = true }
|
|
|
16610
16787
|
].filter((a) => Boolean(a));
|
|
16611
16788
|
const shown = new Set(files);
|
|
16612
16789
|
const sample = files.some((a) => a?.tags?.includes("sample"));
|
|
16613
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
16790
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
16614
16791
|
/* @__PURE__ */ jsx("div", {
|
|
16615
16792
|
className: "section-title",
|
|
16616
16793
|
children: /* @__PURE__ */ jsxs("span", { children: ["BOARD OUTPUTS", sample && /* @__PURE__ */ jsx("span", {
|
|
@@ -16618,7 +16795,7 @@ function BoardViews({ def, lookup, resolve, highlight, onPick, drawings = true }
|
|
|
16618
16795
|
children: "SAMPLE"
|
|
16619
16796
|
})] })
|
|
16620
16797
|
}),
|
|
16621
|
-
drawings && current && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
16798
|
+
drawings && current && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
16622
16799
|
className: "artifact-parts board-tabs",
|
|
16623
16800
|
children: tabs.map((t) => /* @__PURE__ */ jsx("button", {
|
|
16624
16801
|
className: `mini${t.id === current ? " on" : ""}`,
|
|
@@ -17245,62 +17422,6 @@ function ArtifactLink({ defId, artifactId, href, title, children }) {
|
|
|
17245
17422
|
});
|
|
17246
17423
|
}
|
|
17247
17424
|
var urlOf = (def, a, resolve) => a.url ?? (a.filePath ? resolve(def.id, a.filePath) : void 0);
|
|
17248
|
-
var hasArtifacts = (def) => Boolean(thumbnailOf(def) || glbFor(def));
|
|
17249
|
-
/**
|
|
17250
|
-
* An assembly (FC + ESC stack, an arm) usually has no CAD of its own: show its
|
|
17251
|
-
* parts' artifacts instead, one part at a time, picked from a row of names.
|
|
17252
|
-
*/
|
|
17253
|
-
function AssemblyArtifacts({ def, lookup, resolve, appearance, titled = true }) {
|
|
17254
|
-
const [pick, setPick] = useState(0);
|
|
17255
|
-
if (!def) return null;
|
|
17256
|
-
if (hasArtifacts(def)) return /* @__PURE__ */ jsx(ArtifactsSection, {
|
|
17257
|
-
def,
|
|
17258
|
-
resolve,
|
|
17259
|
-
appearance: appearance?.[def.id],
|
|
17260
|
-
titled
|
|
17261
|
-
});
|
|
17262
|
-
const parts = [];
|
|
17263
|
-
const seen = /* @__PURE__ */ new Set();
|
|
17264
|
-
const walk = (d, depth) => {
|
|
17265
|
-
for (const ref of d.children ?? []) {
|
|
17266
|
-
const c = lookup(ref.moduleDefId);
|
|
17267
|
-
if (!c || seen.has(c.id)) continue;
|
|
17268
|
-
seen.add(c.id);
|
|
17269
|
-
if (hasArtifacts(c)) parts.push({
|
|
17270
|
-
name: ref.name ?? c.name,
|
|
17271
|
-
def: c
|
|
17272
|
-
});
|
|
17273
|
-
else if (depth < 3) walk(c, depth + 1);
|
|
17274
|
-
}
|
|
17275
|
-
};
|
|
17276
|
-
walk(def, 0);
|
|
17277
|
-
const cur = parts[Math.min(pick, parts.length - 1)];
|
|
17278
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ArtifactsSection, {
|
|
17279
|
-
def,
|
|
17280
|
-
resolve,
|
|
17281
|
-
appearance: appearance?.[def.id],
|
|
17282
|
-
titled
|
|
17283
|
-
}), cur && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
17284
|
-
/* @__PURE__ */ jsx("div", {
|
|
17285
|
-
className: "section-title",
|
|
17286
|
-
children: "ARTIFACTS · PARTS"
|
|
17287
|
-
}),
|
|
17288
|
-
/* @__PURE__ */ jsx("div", {
|
|
17289
|
-
className: "artifact-parts",
|
|
17290
|
-
children: parts.map((p, i) => /* @__PURE__ */ jsx("button", {
|
|
17291
|
-
className: `mini${p === cur ? " on" : ""}`,
|
|
17292
|
-
onClick: () => setPick(i),
|
|
17293
|
-
children: p.name.toUpperCase()
|
|
17294
|
-
}, p.def.id))
|
|
17295
|
-
}),
|
|
17296
|
-
/* @__PURE__ */ jsx(ArtifactsSection, {
|
|
17297
|
-
def: cur.def,
|
|
17298
|
-
resolve,
|
|
17299
|
-
appearance: appearance?.[cur.def.id],
|
|
17300
|
-
titled: false
|
|
17301
|
-
})
|
|
17302
|
-
] })] });
|
|
17303
|
-
}
|
|
17304
17425
|
/**
|
|
17305
17426
|
* A definition's artifacts: its picture, its body model (turning in a small
|
|
17306
17427
|
* 3D preview, unless the host shows models as cards), and every artifact as
|
|
@@ -17324,7 +17445,7 @@ function ArtifactsSection({ def, resolve, appearance, titled = true }) {
|
|
|
17324
17445
|
sources: files?.sources
|
|
17325
17446
|
});
|
|
17326
17447
|
if (!thumb && !glb && !cards.length) return null;
|
|
17327
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
17448
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
17328
17449
|
titled && /* @__PURE__ */ jsxs("div", {
|
|
17329
17450
|
className: "section-title",
|
|
17330
17451
|
children: ["ARTIFACTS · ", (def.artifacts ?? []).filter((a) => (a.filePath || a.url) && !board.has(a) && !isInternalArtifact(a)).length]
|
|
@@ -17491,7 +17612,7 @@ function EvidenceSection({ def, titled = true, performance = true }) {
|
|
|
17491
17612
|
if (!def || !ev || !hasEvidence(ev, performance)) return null;
|
|
17492
17613
|
const v = ev.verification;
|
|
17493
17614
|
const named = (v?.assumptions ?? []).map(text).filter((a) => !ev.assumptions.some((t) => t.field === a));
|
|
17494
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [titled && /* @__PURE__ */ jsx("div", {
|
|
17615
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [titled && /* @__PURE__ */ jsx("div", {
|
|
17495
17616
|
className: "section-title",
|
|
17496
17617
|
children: "EVIDENCE"
|
|
17497
17618
|
}), /* @__PURE__ */ jsxs("div", {
|
|
@@ -17813,19 +17934,23 @@ function interfaceSlots(node, vm, opts) {
|
|
|
17813
17934
|
const mine = lines.filter((l) => l.source.node === node.id && l.source.port === port || l.target.node === node.id && l.target.port === port);
|
|
17814
17935
|
return mine.filter((l, i) => mine.findIndex((m) => m.linkId === l.linkId) === i);
|
|
17815
17936
|
};
|
|
17816
|
-
const
|
|
17937
|
+
const drawn = new Set(node.ports.map((p) => p.id));
|
|
17938
|
+
const ports = [...node.ports, ...def && node.kind !== "harness" ? def.interfaces.filter((i) => !drawn.has(i.id)).map((i) => toPort(i, def)) : []];
|
|
17939
|
+
const boundInto = /* @__PURE__ */ new Map();
|
|
17940
|
+
for (const i of def?.interfaces ?? []) for (const profile of i.profiles ?? []) for (const v of Object.values(profile.bindings)) for (const id of Array.isArray(v) ? v : [v]) if (id !== i.id && !boundInto.has(id)) boundInto.set(id, i.name && i.name !== i.id ? i.name : humanize(i.id));
|
|
17941
|
+
const linkedIds = new Set(ports.filter((p) => linksOf(p.id).length).map((p) => p.id));
|
|
17817
17942
|
const exportedAs = /* @__PURE__ */ new Map();
|
|
17818
17943
|
for (const l of vm.links) if (l.passThrough && l.target.node === node.id && !exportedAs.has(l.target.port)) exportedAs.set(l.target.port, l.name);
|
|
17819
17944
|
const usedBy = /* @__PURE__ */ new Map();
|
|
17820
|
-
for (const p of
|
|
17945
|
+
for (const p of ports) if (linkedIds.has(p.id)) {
|
|
17821
17946
|
for (const c of p.children) if (c.leafId && !usedBy.has(c.leafId)) usedBy.set(c.leafId, p.name === p.id ? humanize(p.id) : p.name);
|
|
17822
17947
|
}
|
|
17823
|
-
for (const p of
|
|
17948
|
+
for (const p of ports) {
|
|
17824
17949
|
if (linkedIds.has(p.id) || usedBy.has(p.id)) continue;
|
|
17825
17950
|
const via = p.children.map((c) => c.leafId && usedBy.get(c.leafId)).find(Boolean);
|
|
17826
17951
|
if (via) usedBy.set(p.id, via);
|
|
17827
17952
|
}
|
|
17828
|
-
const slots =
|
|
17953
|
+
const slots = ports.map((port) => {
|
|
17829
17954
|
const iface = findInterface(def, port.id, lookup);
|
|
17830
17955
|
const leaves = port.children.map((c) => c.leafId ? findInterface(def, c.leafId, lookup) : void 0);
|
|
17831
17956
|
const links = linksOf(port.id);
|
|
@@ -17963,9 +18088,10 @@ function interfaceSlots(node, vm, opts) {
|
|
|
17963
18088
|
...role ? { role } : {},
|
|
17964
18089
|
pins,
|
|
17965
18090
|
linked: linked.filter((x, i) => linked.findIndex((y) => y.module === x.module && y.via === x.via) === i),
|
|
17966
|
-
open: !links.length && !usedBy.has(port.id) && !exportedAs.has(port.id) && !vm.derived.some((d) => d.a.node === node.id && d.a.iface === port.id || d.b.node === node.id && d.b.iface === port.id),
|
|
18091
|
+
open: !links.length && !usedBy.has(port.id) && !exportedAs.has(port.id) && !(!drawn.has(port.id) && boundInto.has(port.id)) && !vm.derived.some((d) => d.a.node === node.id && d.a.iface === port.id || d.b.node === node.id && d.b.iface === port.id),
|
|
17967
18092
|
...!links.length && usedBy.has(port.id) ? { usedBy: usedBy.get(port.id) } : {},
|
|
17968
18093
|
...!links.length && !usedBy.has(port.id) && exportedAs.has(port.id) ? { exportedAs: exportedAs.get(port.id) } : {},
|
|
18094
|
+
...!links.length && !usedBy.has(port.id) && !exportedAs.has(port.id) && !drawn.has(port.id) && boundInto.has(port.id) ? { partOf: boundInto.get(port.id) } : {},
|
|
17969
18095
|
...state ? { state } : {},
|
|
17970
18096
|
pinMap,
|
|
17971
18097
|
params,
|
|
@@ -17976,7 +18102,7 @@ function interfaceSlots(node, vm, opts) {
|
|
|
17976
18102
|
refs: [...refs]
|
|
17977
18103
|
};
|
|
17978
18104
|
});
|
|
17979
|
-
const order = (s) => s.linked.length || s.links.length ? s.kind === "mechanical" ? 3 : s.kind === "power" ? 0 : 1 : s.open ? 2 : 4;
|
|
18105
|
+
const order = (s) => s.linked.length || s.links.length ? s.kind === "mechanical" ? 3 : s.kind === "power" ? 0 : 1 : s.open ? 2 : s.partOf ? 5 : 4;
|
|
17980
18106
|
return groupSlots(slots.map((s, i) => ({
|
|
17981
18107
|
s,
|
|
17982
18108
|
i
|
|
@@ -18005,7 +18131,7 @@ var shape = (name) => name.replace(/\d+/g, "#");
|
|
|
18005
18131
|
*/
|
|
18006
18132
|
function groupSlots(slots) {
|
|
18007
18133
|
const out = [];
|
|
18008
|
-
const key = (s) => `${shape(s.name)}|${s.kind}|${s.protocol}|${s.linked.length ? "linked" : s.open ? "open" : s.exportedAs ? "exported" : "used"}`;
|
|
18134
|
+
const key = (s) => `${shape(s.name)}|${s.kind}|${s.protocol}|${s.linked.length ? "linked" : s.open ? "open" : s.exportedAs ? "exported" : s.partOf ? `part of ${s.partOf}` : "used"}`;
|
|
18009
18135
|
for (const s of slots) {
|
|
18010
18136
|
if (!/\d/.test(s.name)) {
|
|
18011
18137
|
out.push(s);
|
|
@@ -18316,7 +18442,122 @@ function KeyValues({ rows, limit }) {
|
|
|
18316
18442
|
})]
|
|
18317
18443
|
}, `${r.key}-${i}`)) });
|
|
18318
18444
|
}
|
|
18319
|
-
/**
|
|
18445
|
+
/** How many rows of a long list are shown at first, and how many more each "Show more" adds (PB-1088). */
|
|
18446
|
+
var LIST_STEP = 10;
|
|
18447
|
+
var MORE_LOOK = {
|
|
18448
|
+
row: "flex min-h-6 items-center gap-3 pt-1",
|
|
18449
|
+
button: "inline-flex h-6 cursor-pointer items-center gap-1 rounded-[3px] px-1 -mx-1 text-[11px] leading-none text-fg-muted hover:text-fg focus-visible:outline focus-visible:outline-1 focus-visible:outline-focus"
|
|
18450
|
+
};
|
|
18451
|
+
/**
|
|
18452
|
+
* A long list shown `step` rows at a time (PB-1088): "Show 10 more" under the
|
|
18453
|
+
* rows adds the next ones, "Show fewer" goes back to the first `step`.
|
|
18454
|
+
* `keep`: rows that must stay shown (an expanded card), counted from the top.
|
|
18455
|
+
*/
|
|
18456
|
+
function useLoadMore(total, step = 10, keep = 0) {
|
|
18457
|
+
const [shown, setShown] = useState(step);
|
|
18458
|
+
const limit = Math.min(total, Math.max(shown, keep));
|
|
18459
|
+
if (total <= step) return {
|
|
18460
|
+
limit: total,
|
|
18461
|
+
footer: null
|
|
18462
|
+
};
|
|
18463
|
+
const next = Math.min(step, total - limit);
|
|
18464
|
+
return {
|
|
18465
|
+
limit,
|
|
18466
|
+
footer: /* @__PURE__ */ jsxs("div", {
|
|
18467
|
+
className: MORE_LOOK.row,
|
|
18468
|
+
"data-load-more": "",
|
|
18469
|
+
children: [next > 0 && /* @__PURE__ */ jsxs("button", {
|
|
18470
|
+
type: "button",
|
|
18471
|
+
"data-nav": "",
|
|
18472
|
+
onKeyDown: onNavKey,
|
|
18473
|
+
className: MORE_LOOK.button,
|
|
18474
|
+
onClick: () => setShown(limit + next),
|
|
18475
|
+
children: [
|
|
18476
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
18477
|
+
name: "chevron-down",
|
|
18478
|
+
size: 12,
|
|
18479
|
+
strokeWidth: 1.75,
|
|
18480
|
+
"aria-hidden": true,
|
|
18481
|
+
className: "shrink-0"
|
|
18482
|
+
}),
|
|
18483
|
+
"Show ",
|
|
18484
|
+
next,
|
|
18485
|
+
" more"
|
|
18486
|
+
]
|
|
18487
|
+
}), limit > step && /* @__PURE__ */ jsxs("button", {
|
|
18488
|
+
type: "button",
|
|
18489
|
+
"data-nav": "",
|
|
18490
|
+
onKeyDown: onNavKey,
|
|
18491
|
+
className: cx(MORE_LOOK.button, next > 0 && "ml-auto"),
|
|
18492
|
+
onClick: () => setShown(step),
|
|
18493
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
18494
|
+
name: "chevron-up",
|
|
18495
|
+
size: 12,
|
|
18496
|
+
strokeWidth: 1.75,
|
|
18497
|
+
"aria-hidden": true,
|
|
18498
|
+
className: "shrink-0"
|
|
18499
|
+
}), "Show fewer"]
|
|
18500
|
+
})]
|
|
18501
|
+
})
|
|
18502
|
+
};
|
|
18503
|
+
}
|
|
18504
|
+
/**
|
|
18505
|
+
* A long free text (a module's description) cut to `lines` lines, with "More"
|
|
18506
|
+
* to read it all and "Less" to cut it again (PB-1088). The toggle shows only
|
|
18507
|
+
* when the text is cut.
|
|
18508
|
+
*/
|
|
18509
|
+
function ClampedText({ text, lines = 5, className }) {
|
|
18510
|
+
const [open, setOpen] = useState(false);
|
|
18511
|
+
const [cut, setCut] = useState(() => text.length > lines * 60);
|
|
18512
|
+
const ref = useRef(null);
|
|
18513
|
+
useLayoutEffect(() => {
|
|
18514
|
+
const el = ref.current;
|
|
18515
|
+
if (!el || open) return;
|
|
18516
|
+
const measure = () => {
|
|
18517
|
+
setCut(el.clientHeight > 0 ? el.scrollHeight > el.clientHeight + 1 : text.length > lines * 60);
|
|
18518
|
+
};
|
|
18519
|
+
measure();
|
|
18520
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
18521
|
+
const ro = new ResizeObserver(measure);
|
|
18522
|
+
ro.observe(el);
|
|
18523
|
+
return () => ro.disconnect();
|
|
18524
|
+
}, [
|
|
18525
|
+
text,
|
|
18526
|
+
lines,
|
|
18527
|
+
open
|
|
18528
|
+
]);
|
|
18529
|
+
const id = useId();
|
|
18530
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
18531
|
+
className: "pb-1.5",
|
|
18532
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
18533
|
+
ref,
|
|
18534
|
+
id,
|
|
18535
|
+
"data-clamped": !open && cut ? "" : void 0,
|
|
18536
|
+
className: cx("m-0 [overflow-wrap:anywhere] whitespace-pre-line", className),
|
|
18537
|
+
style: open ? void 0 : {
|
|
18538
|
+
display: "-webkit-box",
|
|
18539
|
+
WebkitBoxOrient: "vertical",
|
|
18540
|
+
WebkitLineClamp: lines,
|
|
18541
|
+
overflow: "hidden"
|
|
18542
|
+
},
|
|
18543
|
+
children: text
|
|
18544
|
+
}), (cut || open) && /* @__PURE__ */ jsxs("button", {
|
|
18545
|
+
type: "button",
|
|
18546
|
+
"aria-expanded": open,
|
|
18547
|
+
"aria-controls": id,
|
|
18548
|
+
className: cx(MORE_LOOK.button, "mt-0.5"),
|
|
18549
|
+
onClick: () => setOpen(!open),
|
|
18550
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
18551
|
+
name: open ? "chevron-up" : "chevron-down",
|
|
18552
|
+
size: 12,
|
|
18553
|
+
strokeWidth: 1.75,
|
|
18554
|
+
"aria-hidden": true,
|
|
18555
|
+
className: "shrink-0"
|
|
18556
|
+
}), open ? "Less" : "More"]
|
|
18557
|
+
})]
|
|
18558
|
+
});
|
|
18559
|
+
}
|
|
18560
|
+
/** A section's rows shown in part, and the header action that shows them all. Lists use `useLoadMore` (PB-1088). */
|
|
18320
18561
|
function useShowAll(total, limit) {
|
|
18321
18562
|
const [all, setAll] = useState(false);
|
|
18322
18563
|
if (total <= limit) return {
|
|
@@ -18360,6 +18601,16 @@ var CARD_LOOK = {
|
|
|
18360
18601
|
toggle: "min-w-0 truncate text-left text-[12px] leading-[18px] text-fg outline-none after:absolute after:inset-0 after:content-[''] cursor-pointer",
|
|
18361
18602
|
chip: "inline-flex h-[18px] shrink-0 items-center rounded-[4px] bg-[color-mix(in_oklab,var(--uhd-text)_8%,transparent)] px-1.5 text-[10px] leading-none text-fg-muted",
|
|
18362
18603
|
pin: "inline-flex h-4 shrink-0 items-center rounded-[4px] border border-line px-1 text-[10px] leading-none text-fg-muted",
|
|
18604
|
+
/**
|
|
18605
|
+
* The pin mapping's columns, shared by its rows: the pin as wide as the widest (at least 44 px, its cell's
|
|
18606
|
+
* minimum; at most 40 % of the card), the leaf (when any pin binds one) at most 30 %, and what it meets in the rest.
|
|
18607
|
+
*/
|
|
18608
|
+
pinMap: "grid gap-x-2 gap-y-[3px] text-[11px] leading-none",
|
|
18609
|
+
pinMapPins: "grid-cols-[fit-content(40%)_minmax(0,1fr)]",
|
|
18610
|
+
pinMapLeaves: "grid-cols-[fit-content(40%)_fit-content(30%)_minmax(0,1fr)]",
|
|
18611
|
+
pinRow: "col-span-full grid min-h-5 grid-cols-subgrid items-center",
|
|
18612
|
+
/** A pin in the mapping: a chip that ends in an ellipsis when the column is narrower than its name. */
|
|
18613
|
+
pinName: "inline-block h-4 max-w-full truncate rounded-[4px] border border-line px-1 align-middle text-[10px] leading-[14px] text-fg-muted",
|
|
18363
18614
|
meta: "mt-[5px] flex min-w-0 items-center gap-1",
|
|
18364
18615
|
role: "ml-auto shrink-0 text-[10px] leading-none text-fg-faint",
|
|
18365
18616
|
linked: "mt-[5px] flex min-w-0 items-center gap-1.5 text-[11px] leading-[16px]",
|
|
@@ -18434,6 +18685,61 @@ function Group({ title, children }) {
|
|
|
18434
18685
|
}), children]
|
|
18435
18686
|
});
|
|
18436
18687
|
}
|
|
18688
|
+
/**
|
|
18689
|
+
* The pin mapping: one row per pin, in columns shared by every row (the pin,
|
|
18690
|
+
* the leaf it binds when it is not the pin itself, and what it meets across
|
|
18691
|
+
* the link). Every column fits the card: a pin or name too long for it ends
|
|
18692
|
+
* in an ellipsis and says itself in full in its tooltip, so nothing runs over
|
|
18693
|
+
* the next column or the next line in a narrow Inspector.
|
|
18694
|
+
*/
|
|
18695
|
+
function PinMap({ pins }) {
|
|
18696
|
+
const leaves = pins.some((p) => p.leaf);
|
|
18697
|
+
return /* @__PURE__ */ jsx("div", {
|
|
18698
|
+
className: cx(CARD_LOOK.pinMap, leaves ? CARD_LOOK.pinMapLeaves : CARD_LOOK.pinMapPins),
|
|
18699
|
+
children: pins.map((p, i) => /* @__PURE__ */ jsxs("div", {
|
|
18700
|
+
className: CARD_LOOK.pinRow,
|
|
18701
|
+
"data-pin": p.pin,
|
|
18702
|
+
children: [
|
|
18703
|
+
/* @__PURE__ */ jsx("span", {
|
|
18704
|
+
className: "min-w-11",
|
|
18705
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
18706
|
+
className: CARD_LOOK.pinName,
|
|
18707
|
+
"data-tooltip": p.pin.length > 6 ? p.pin : void 0,
|
|
18708
|
+
children: p.pin
|
|
18709
|
+
})
|
|
18710
|
+
}),
|
|
18711
|
+
leaves && /* @__PURE__ */ jsx("span", {
|
|
18712
|
+
className: "min-w-0 truncate text-fg-muted",
|
|
18713
|
+
"data-tooltip": p.leaf,
|
|
18714
|
+
children: p.leaf ?? ""
|
|
18715
|
+
}),
|
|
18716
|
+
/* @__PURE__ */ jsxs("span", {
|
|
18717
|
+
className: "flex min-w-0 items-center gap-1.5",
|
|
18718
|
+
children: [
|
|
18719
|
+
/* @__PURE__ */ jsx("span", {
|
|
18720
|
+
className: "shrink-0 text-fg",
|
|
18721
|
+
"aria-label": p.dir === "←" ? "from" : p.dir === "→" ? "to" : p.dir === "—" ? "shared with" : "with",
|
|
18722
|
+
children: p.dir
|
|
18723
|
+
}),
|
|
18724
|
+
p.other ? /* @__PURE__ */ jsx("span", {
|
|
18725
|
+
className: "max-w-[60%] min-w-0 shrink-0 truncate text-fg",
|
|
18726
|
+
"data-tooltip": p.other.length > 12 ? p.other : void 0,
|
|
18727
|
+
children: p.other
|
|
18728
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
18729
|
+
className: "shrink-0 text-fg-faint",
|
|
18730
|
+
children: p.otherModule ? "" : "not linked"
|
|
18731
|
+
}),
|
|
18732
|
+
p.otherModule && /* @__PURE__ */ jsx("span", {
|
|
18733
|
+
className: "min-w-0 truncate text-fg-faint",
|
|
18734
|
+
"data-tooltip": p.otherModule.length > 12 ? p.otherModule : void 0,
|
|
18735
|
+
children: p.otherModule
|
|
18736
|
+
})
|
|
18737
|
+
]
|
|
18738
|
+
})
|
|
18739
|
+
]
|
|
18740
|
+
}, `${p.pin}-${i}`))
|
|
18741
|
+
});
|
|
18742
|
+
}
|
|
18437
18743
|
/** What an expanded card shows below its summary. */
|
|
18438
18744
|
function CardDetail({ slot, actions }) {
|
|
18439
18745
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -18442,46 +18748,7 @@ function CardDetail({ slot, actions }) {
|
|
|
18442
18748
|
children: [
|
|
18443
18749
|
slot.pinMap.length > 0 && /* @__PURE__ */ jsx(Group, {
|
|
18444
18750
|
title: "Pin mapping",
|
|
18445
|
-
children:
|
|
18446
|
-
className: "flex min-h-5 min-w-0 items-center gap-2 text-[11px] leading-none",
|
|
18447
|
-
"data-pin": p.pin,
|
|
18448
|
-
children: [
|
|
18449
|
-
/* @__PURE__ */ jsx("span", {
|
|
18450
|
-
className: "w-11 shrink-0",
|
|
18451
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
18452
|
-
className: CARD_LOOK.pin,
|
|
18453
|
-
children: p.pin
|
|
18454
|
-
})
|
|
18455
|
-
}),
|
|
18456
|
-
/* @__PURE__ */ jsx("span", {
|
|
18457
|
-
className: "w-[88px] shrink-0 truncate text-fg-muted",
|
|
18458
|
-
"data-tooltip": p.leaf,
|
|
18459
|
-
children: p.leaf ?? ""
|
|
18460
|
-
}),
|
|
18461
|
-
/* @__PURE__ */ jsxs("span", {
|
|
18462
|
-
className: "flex min-w-0 flex-1 items-center gap-1.5",
|
|
18463
|
-
children: [
|
|
18464
|
-
/* @__PURE__ */ jsx("span", {
|
|
18465
|
-
className: "shrink-0 text-fg",
|
|
18466
|
-
"aria-label": p.dir === "←" ? "from" : p.dir === "→" ? "to" : p.dir === "—" ? "shared with" : "with",
|
|
18467
|
-
children: p.dir
|
|
18468
|
-
}),
|
|
18469
|
-
p.other ? /* @__PURE__ */ jsx("span", {
|
|
18470
|
-
className: "max-w-[60%] min-w-0 shrink-0 truncate text-fg",
|
|
18471
|
-
"data-tooltip": p.other.length > 12 ? p.other : void 0,
|
|
18472
|
-
children: p.other
|
|
18473
|
-
}) : /* @__PURE__ */ jsx("span", {
|
|
18474
|
-
className: "text-fg-faint",
|
|
18475
|
-
children: p.otherModule ? "" : "not linked"
|
|
18476
|
-
}),
|
|
18477
|
-
p.otherModule && /* @__PURE__ */ jsx("span", {
|
|
18478
|
-
className: "min-w-0 truncate text-fg-faint",
|
|
18479
|
-
children: p.otherModule
|
|
18480
|
-
})
|
|
18481
|
-
]
|
|
18482
|
-
})
|
|
18483
|
-
]
|
|
18484
|
-
}, `${p.pin}-${i}`))
|
|
18751
|
+
children: /* @__PURE__ */ jsx(PinMap, { pins: slot.pinMap })
|
|
18485
18752
|
}),
|
|
18486
18753
|
(slot.protocol || slot.params.length > 0) && /* @__PURE__ */ jsxs(Group, {
|
|
18487
18754
|
title: "Protocol and parameters",
|
|
@@ -18799,6 +19066,18 @@ function InterfaceCard({ slot, open, onToggle, actions }) {
|
|
|
18799
19066
|
className: "min-w-0 truncate text-fg-faint",
|
|
18800
19067
|
children: ["in use through ", slot.usedBy]
|
|
18801
19068
|
})]
|
|
19069
|
+
}) : slot.partOf ? /* @__PURE__ */ jsxs("div", {
|
|
19070
|
+
className: CARD_LOOK.linked,
|
|
19071
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
19072
|
+
name: "corner-down-right",
|
|
19073
|
+
size: 12,
|
|
19074
|
+
strokeWidth: 1.75,
|
|
19075
|
+
"aria-hidden": true,
|
|
19076
|
+
className: "shrink-0 text-fg-faint"
|
|
19077
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
19078
|
+
className: "min-w-0 truncate text-fg-faint",
|
|
19079
|
+
children: ["part of ", slot.partOf]
|
|
19080
|
+
})]
|
|
18802
19081
|
}) : null
|
|
18803
19082
|
]
|
|
18804
19083
|
}), /* @__PURE__ */ jsx("div", {
|
|
@@ -18811,46 +19090,20 @@ function InterfaceCard({ slot, open, onToggle, actions }) {
|
|
|
18811
19090
|
})]
|
|
18812
19091
|
});
|
|
18813
19092
|
}
|
|
18814
|
-
/** The cards,
|
|
18815
|
-
function InterfaceCards({ slots, actions, first =
|
|
19093
|
+
/** The cards, ten at a time (PB-1088): "Show 10 more" adds the next ten, "Show fewer" goes back to the first ten. */
|
|
19094
|
+
function InterfaceCards({ slots, actions, first = 10 }) {
|
|
18816
19095
|
const [expanded, toggle] = useExpandedCards();
|
|
18817
|
-
const [all, setAll] = useState(false);
|
|
18818
19096
|
const lastOpen = slots.reduce((m, s, i) => expanded.has(s.id) ? i : m, -1);
|
|
18819
|
-
const
|
|
18820
|
-
const shown = slots.slice(0, cut);
|
|
18821
|
-
const rest = slots.slice(cut);
|
|
19097
|
+
const more = useLoadMore(slots.length, first, lastOpen + 1);
|
|
18822
19098
|
return /* @__PURE__ */ jsxs("div", {
|
|
18823
19099
|
className: CARD_LOOK.list,
|
|
18824
19100
|
"data-interface-cards": "",
|
|
18825
|
-
children: [
|
|
19101
|
+
children: [slots.slice(0, more.limit).map((s) => /* @__PURE__ */ jsx(InterfaceCard, {
|
|
18826
19102
|
slot: s,
|
|
18827
19103
|
open: expanded.has(s.id),
|
|
18828
19104
|
onToggle: () => toggle(s.id),
|
|
18829
19105
|
actions
|
|
18830
|
-
}, s.id)),
|
|
18831
|
-
type: "button",
|
|
18832
|
-
"data-nav": "",
|
|
18833
|
-
onKeyDown: onNavKey,
|
|
18834
|
-
className: CARD_LOOK.more,
|
|
18835
|
-
"aria-expanded": false,
|
|
18836
|
-
onClick: () => setAll(true),
|
|
18837
|
-
"data-tooltip": rest.map((s) => s.name).join(", "),
|
|
18838
|
-
"data-tooltip-clamp": "4",
|
|
18839
|
-
children: [/* @__PURE__ */ jsx(Icon, {
|
|
18840
|
-
name: "chevron-right",
|
|
18841
|
-
size: 12,
|
|
18842
|
-
strokeWidth: 1.75,
|
|
18843
|
-
"aria-hidden": true,
|
|
18844
|
-
className: "shrink-0"
|
|
18845
|
-
}), /* @__PURE__ */ jsxs("span", {
|
|
18846
|
-
className: "min-w-0 truncate",
|
|
18847
|
-
children: [
|
|
18848
|
-
rest.length,
|
|
18849
|
-
" more · ",
|
|
18850
|
-
rest.map((s) => s.name).join(", ")
|
|
18851
|
-
]
|
|
18852
|
-
})]
|
|
18853
|
-
})]
|
|
19106
|
+
}, s.id)), more.footer]
|
|
18854
19107
|
});
|
|
18855
19108
|
}
|
|
18856
19109
|
//#endregion
|
|
@@ -18862,25 +19115,18 @@ function factRows(rows) {
|
|
|
18862
19115
|
value
|
|
18863
19116
|
}));
|
|
18864
19117
|
}
|
|
18865
|
-
/**
|
|
18866
|
-
|
|
19118
|
+
/**
|
|
19119
|
+
* "4 models · 2 docs · 1 evidence": what a definition's own artifacts are, by group. A parent's are its own only
|
|
19120
|
+
* (PB-1088): its children's are theirs, a selection away.
|
|
19121
|
+
*/
|
|
19122
|
+
function artifactSummary(def, _lookup) {
|
|
18867
19123
|
if (!def) return {
|
|
18868
19124
|
count: 0,
|
|
18869
19125
|
text: ""
|
|
18870
19126
|
};
|
|
18871
|
-
const
|
|
18872
|
-
const
|
|
18873
|
-
const
|
|
18874
|
-
for (const ref of d.children ?? []) {
|
|
18875
|
-
const c = lookup(ref.moduleDefId);
|
|
18876
|
-
if (!c || seen.has(c.id)) continue;
|
|
18877
|
-
seen.add(c.id);
|
|
18878
|
-
defs.push(c);
|
|
18879
|
-
if (depth < 3) walk(c, depth + 1);
|
|
18880
|
-
}
|
|
18881
|
-
};
|
|
18882
|
-
walk(def, 0);
|
|
18883
|
-
const cards = defs.flatMap((d) => artifactCards(d, () => void 0));
|
|
19127
|
+
const outs = circuitOutputs(def);
|
|
19128
|
+
const board = new Set(outs ? Object.values(outs).filter(Boolean) : []);
|
|
19129
|
+
const cards = artifactCards(def, () => void 0, { skip: (a) => board.has(a) });
|
|
18884
19130
|
const WORD = {
|
|
18885
19131
|
images: ["image", "images"],
|
|
18886
19132
|
models: ["model", "models"],
|
|
@@ -18953,7 +19199,7 @@ function ModuleDetails({ node, vm, def, onDrill, onToggleExpand, onSelect, artif
|
|
|
18953
19199
|
["Part number", node.partNumber],
|
|
18954
19200
|
["Path", node.id || void 0]
|
|
18955
19201
|
]), ...performance];
|
|
18956
|
-
const
|
|
19202
|
+
const more = useLoadMore(params.length);
|
|
18957
19203
|
const slots = useMemo(() => node.kind === "harness" ? [] : interfaceSlots(node, vm, {
|
|
18958
19204
|
lookup: (id) => find(id),
|
|
18959
19205
|
drill,
|
|
@@ -18970,7 +19216,6 @@ function ModuleDetails({ node, vm, def, onDrill, onToggleExpand, onSelect, artif
|
|
|
18970
19216
|
findings
|
|
18971
19217
|
]);
|
|
18972
19218
|
const summary = slotSummary(slots);
|
|
18973
|
-
const firstCards = Math.min(12, Math.max(4, slots.filter((s) => s.links.length && s.kind !== "mechanical" || s.open).length));
|
|
18974
19219
|
const arts = artifactSummary(def, find);
|
|
18975
19220
|
const derived = vm.derived.filter((d) => d.a.node === node.id || d.b.node === node.id);
|
|
18976
19221
|
const pins = (def?.interfaces ?? []).filter((i) => i.pin !== void 0).length;
|
|
@@ -19009,14 +19254,18 @@ function ModuleDetails({ node, vm, def, onDrill, onToggleExpand, onSelect, artif
|
|
|
19009
19254
|
/* @__PURE__ */ jsxs(DetailsSection, {
|
|
19010
19255
|
id: "parameters",
|
|
19011
19256
|
title: "Parameters",
|
|
19012
|
-
|
|
19013
|
-
|
|
19014
|
-
|
|
19015
|
-
|
|
19016
|
-
|
|
19017
|
-
|
|
19018
|
-
|
|
19019
|
-
|
|
19257
|
+
children: [
|
|
19258
|
+
node.description && /* @__PURE__ */ jsx(ClampedText, {
|
|
19259
|
+
text: node.description,
|
|
19260
|
+
lines: 5,
|
|
19261
|
+
className: "text-[11px] leading-[1.5] text-fg-muted"
|
|
19262
|
+
}, node.description),
|
|
19263
|
+
/* @__PURE__ */ jsx(KeyValues, {
|
|
19264
|
+
rows: params,
|
|
19265
|
+
limit: more.limit
|
|
19266
|
+
}),
|
|
19267
|
+
more.footer
|
|
19268
|
+
]
|
|
19020
19269
|
}),
|
|
19021
19270
|
board && /* @__PURE__ */ jsx(DetailsSection, {
|
|
19022
19271
|
id: "board",
|
|
@@ -19030,12 +19279,12 @@ function ModuleDetails({ node, vm, def, onDrill, onToggleExpand, onSelect, artif
|
|
|
19030
19279
|
summary: summary.text,
|
|
19031
19280
|
children: /* @__PURE__ */ jsx(InterfaceCards, {
|
|
19032
19281
|
slots,
|
|
19033
|
-
first:
|
|
19282
|
+
first: 10,
|
|
19034
19283
|
actions: cardActions ?? { selectLink: (id) => onSelect({
|
|
19035
19284
|
kind: "link",
|
|
19036
19285
|
id
|
|
19037
19286
|
}) }
|
|
19038
|
-
})
|
|
19287
|
+
}, node.id)
|
|
19039
19288
|
}),
|
|
19040
19289
|
artifacts && arts.count > 0 && /* @__PURE__ */ jsx(DetailsSection, {
|
|
19041
19290
|
id: "artifacts",
|
|
@@ -19297,7 +19546,7 @@ function Hierarchy({ vm, selection, onSelect, board, onContext }) {
|
|
|
19297
19546
|
children: ["MODULES · ", vm.nodes.filter((n) => !n.sheetPort && n.kind !== "net").length]
|
|
19298
19547
|
}),
|
|
19299
19548
|
roots.map((n) => item(n, 0)),
|
|
19300
|
-
nets.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
19549
|
+
nets.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
19301
19550
|
className: "section-title",
|
|
19302
19551
|
children: ["NETS · ", nets.length]
|
|
19303
19552
|
}), nets.map((n) => /* @__PURE__ */ jsxs("button", {
|
|
@@ -19601,11 +19850,10 @@ function InspectorView(props) {
|
|
|
19601
19850
|
onSelect: props.onSelect,
|
|
19602
19851
|
board: boardFor(node),
|
|
19603
19852
|
onOpenSource: host.openSource && node.defId ? () => host.openSource(node.defId, fullId(props.drill, node.id)) : void 0,
|
|
19604
|
-
artifacts: /* @__PURE__ */ jsx(
|
|
19853
|
+
artifacts: /* @__PURE__ */ jsx(ArtifactsSection, {
|
|
19605
19854
|
def: props.defFor(node.defId),
|
|
19606
|
-
lookup: props.defFor,
|
|
19607
19855
|
resolve: props.resolveArtifact,
|
|
19608
|
-
appearance: props.appearance,
|
|
19856
|
+
appearance: node.defId ? props.appearance?.[node.defId] : void 0,
|
|
19609
19857
|
titled: false
|
|
19610
19858
|
}, node.id),
|
|
19611
19859
|
lookup: props.defFor,
|
|
@@ -19709,8 +19957,9 @@ function NodeMenu({ x, y, items, onClose }) {
|
|
|
19709
19957
|
};
|
|
19710
19958
|
}, [onClose]);
|
|
19711
19959
|
if (!items.length) return null;
|
|
19712
|
-
const
|
|
19713
|
-
const
|
|
19960
|
+
const rules = items.filter((it, i) => it.separator && i > 0).length;
|
|
19961
|
+
const left = Math.min(x, window.innerWidth - 228);
|
|
19962
|
+
const top = Math.max(4, Math.min(y, window.innerHeight - 12 - items.length * 28 - rules * 9));
|
|
19714
19963
|
return /* @__PURE__ */ jsx("div", {
|
|
19715
19964
|
ref,
|
|
19716
19965
|
className: "context-menu",
|
|
@@ -19719,14 +19968,36 @@ function NodeMenu({ x, y, items, onClose }) {
|
|
|
19719
19968
|
top
|
|
19720
19969
|
},
|
|
19721
19970
|
role: "menu",
|
|
19722
|
-
children: items.map((it) => /* @__PURE__ */ jsx("
|
|
19971
|
+
children: items.map((it, i) => /* @__PURE__ */ jsxs(Fragment, { children: [it.separator && i > 0 && /* @__PURE__ */ jsx("div", {
|
|
19972
|
+
role: "separator",
|
|
19973
|
+
className: "context-menu-rule"
|
|
19974
|
+
}), /* @__PURE__ */ jsxs("button", {
|
|
19975
|
+
type: "button",
|
|
19723
19976
|
role: "menuitem",
|
|
19724
19977
|
onClick: () => {
|
|
19725
19978
|
onClose();
|
|
19726
19979
|
it.run();
|
|
19727
19980
|
},
|
|
19728
|
-
children:
|
|
19729
|
-
|
|
19981
|
+
children: [
|
|
19982
|
+
/* @__PURE__ */ jsx("span", {
|
|
19983
|
+
className: "context-menu-icon",
|
|
19984
|
+
"aria-hidden": true,
|
|
19985
|
+
children: it.icon && /* @__PURE__ */ jsx(Icon, {
|
|
19986
|
+
name: it.icon,
|
|
19987
|
+
size: 14,
|
|
19988
|
+
strokeWidth: 1.75
|
|
19989
|
+
})
|
|
19990
|
+
}),
|
|
19991
|
+
/* @__PURE__ */ jsx("span", {
|
|
19992
|
+
className: "context-menu-label",
|
|
19993
|
+
children: it.label
|
|
19994
|
+
}),
|
|
19995
|
+
it.shortcut && /* @__PURE__ */ jsx("kbd", {
|
|
19996
|
+
className: "context-menu-key",
|
|
19997
|
+
children: it.shortcut
|
|
19998
|
+
})
|
|
19999
|
+
]
|
|
20000
|
+
})] }, it.label))
|
|
19730
20001
|
});
|
|
19731
20002
|
}
|
|
19732
20003
|
/** Memoised: re-renders only when its props change, not on every frame of a canvas drag. */
|
|
@@ -20296,7 +20567,7 @@ function vscodeThemeAdapter(doc = typeof document === "undefined" ? void 0 : doc
|
|
|
20296
20567
|
* component, and the tooltip lives inside the themed root, so it keeps the
|
|
20297
20568
|
* host's tokens.
|
|
20298
20569
|
*/
|
|
20299
|
-
var OPEN_DELAY =
|
|
20570
|
+
var OPEN_DELAY = 250;
|
|
20300
20571
|
/** Moving from one control to the next within this time shows the next tip at once. */
|
|
20301
20572
|
var SKIP_DELAY = 300;
|
|
20302
20573
|
/** Where to put the tip for a target: below it unless it says otherwise, kept inside the root. */
|
|
@@ -20390,7 +20661,7 @@ function Tooltips({ root }) {
|
|
|
20390
20661
|
return /* @__PURE__ */ jsxs("div", {
|
|
20391
20662
|
ref,
|
|
20392
20663
|
role: "tooltip",
|
|
20393
|
-
className: `uhd-tooltip pointer-events-none absolute z-[1000] flex items-center gap-2 rounded-md border border-line bg-raised px-2 py-1 font-ui text-[11px] leading-4 text-fg shadow-float outline outline-1 -outline-offset-1 outline-contrast ${tip.clamp ? "w-max max-w-[min(300px,calc(100%-12px))] whitespace-normal" : "whitespace-nowrap"}`,
|
|
20664
|
+
className: `uhd-tooltip pointer-events-none absolute select-none z-[1000] flex items-center gap-2 rounded-md border border-line bg-raised px-2 py-1 font-ui text-[11px] leading-4 text-fg shadow-float outline outline-1 -outline-offset-1 outline-contrast ${tip.clamp ? "w-max max-w-[min(300px,calc(100%-12px))] whitespace-normal" : "whitespace-nowrap"}`,
|
|
20394
20665
|
style: {
|
|
20395
20666
|
left: tip.x + nudge,
|
|
20396
20667
|
top: tip.y,
|
|
@@ -22433,10 +22704,12 @@ function CadView({ system, lookup, source, diagnostics = [], hostDiagnostics = [
|
|
|
22433
22704
|
const h = handle.current;
|
|
22434
22705
|
const recs = selectionRecs(sel.body);
|
|
22435
22706
|
const rec = recs.length === 1 && sel.body !== void 0 ? bodies.current.get(sel.body) : void 0;
|
|
22436
|
-
|
|
22437
|
-
|
|
22707
|
+
const wire = sel.body === void 0 && sel.harness !== void 0 ? harnessObjs.current.get(sel.harness) : void 0;
|
|
22708
|
+
const objs = wire ? [wire] : recs.map((r) => r.obj);
|
|
22709
|
+
if (!h || !objs.length) return;
|
|
22710
|
+
if (wire || !sel.iface || !rec) {
|
|
22438
22711
|
const box = new THREE.Box3();
|
|
22439
|
-
for (const
|
|
22712
|
+
for (const o of objs) box.expandByObject(o);
|
|
22440
22713
|
if (box.isEmpty()) return;
|
|
22441
22714
|
const size = box.getSize(new THREE.Vector3());
|
|
22442
22715
|
const grow = Math.max(size.length() * .5, 40);
|
|
@@ -22518,6 +22791,11 @@ function CadView({ system, lookup, source, diagnostics = [], hostDiagnostics = [
|
|
|
22518
22791
|
if (model.assembly.mates.some((m) => m.linkId === key)) setSel({ mate: key });
|
|
22519
22792
|
return;
|
|
22520
22793
|
}
|
|
22794
|
+
if (model.assembly.harnesses.some((hp) => hp.key === key)) {
|
|
22795
|
+
setSel({ harness: key });
|
|
22796
|
+
look.current = focusOn.look !== false && harnessObjs.current.has(key);
|
|
22797
|
+
return;
|
|
22798
|
+
}
|
|
22521
22799
|
const has = (k) => model.bodies.some((b) => b.key === k);
|
|
22522
22800
|
const holder = model.within.get(key);
|
|
22523
22801
|
const parts = key.split("/");
|
|
@@ -22532,7 +22810,8 @@ function CadView({ system, lookup, source, diagnostics = [], hostDiagnostics = [
|
|
|
22532
22810
|
look.current = focusOn.look !== false;
|
|
22533
22811
|
}, [focusOn, model]);
|
|
22534
22812
|
useEffect(() => {
|
|
22535
|
-
if (!look.current
|
|
22813
|
+
if (!look.current) return;
|
|
22814
|
+
if (!(sel.body === void 0 && sel.harness !== void 0 && harnessObjs.current.has(sel.harness)) && (sel.body === void 0 || !selectionRecs(sel.body).length)) return;
|
|
22536
22815
|
look.current = false;
|
|
22537
22816
|
focus();
|
|
22538
22817
|
handle.current?.renderOnce();
|
|
@@ -22571,11 +22850,11 @@ function CadView({ system, lookup, source, diagnostics = [], hostDiagnostics = [
|
|
|
22571
22850
|
options: [{
|
|
22572
22851
|
id: "assembled",
|
|
22573
22852
|
icon: "box",
|
|
22574
|
-
label: "Assembled
|
|
22853
|
+
label: "Assembled"
|
|
22575
22854
|
}, {
|
|
22576
22855
|
id: "exploded",
|
|
22577
22856
|
icon: "layers",
|
|
22578
|
-
label: "Exploded
|
|
22857
|
+
label: "Exploded"
|
|
22579
22858
|
}],
|
|
22580
22859
|
value: exploded ? "exploded" : "assembled",
|
|
22581
22860
|
onChange: (v) => toggleExploded(v === "exploded")
|
|
@@ -22629,7 +22908,7 @@ function CadView({ system, lookup, source, diagnostics = [], hostDiagnostics = [
|
|
|
22629
22908
|
}),
|
|
22630
22909
|
(model?.assembly.hardware.length ?? 0) > 0 && /* @__PURE__ */ jsx(IconButton, {
|
|
22631
22910
|
icon: "wrench",
|
|
22632
|
-
label: "Mounting hardware
|
|
22911
|
+
label: "Mounting hardware",
|
|
22633
22912
|
tooltipSide: "top",
|
|
22634
22913
|
pressed: showHardware,
|
|
22635
22914
|
onClick: () => setShowHardware(!showHardware)
|
|
@@ -22654,7 +22933,7 @@ function CadView({ system, lookup, source, diagnostics = [], hostDiagnostics = [
|
|
|
22654
22933
|
children: [
|
|
22655
22934
|
/* @__PURE__ */ jsx(IconButton, {
|
|
22656
22935
|
icon: "scissors",
|
|
22657
|
-
label: "Section
|
|
22936
|
+
label: "Section",
|
|
22658
22937
|
tooltipSide: "top",
|
|
22659
22938
|
pressed: Boolean(section),
|
|
22660
22939
|
onClick: () => setSection(section ? null : {
|
|
@@ -22728,7 +23007,7 @@ function CadView({ system, lookup, source, diagnostics = [], hostDiagnostics = [
|
|
|
22728
23007
|
}),
|
|
22729
23008
|
/* @__PURE__ */ jsx(IconButton, {
|
|
22730
23009
|
icon: "scan-eye",
|
|
22731
|
-
label: shells ? "X-ray
|
|
23010
|
+
label: shells ? "X-ray" : "X-ray: nothing to see through",
|
|
22732
23011
|
tooltipSide: "top",
|
|
22733
23012
|
pressed: xray && shells > 0,
|
|
22734
23013
|
"aria-disabled": !shells || void 0,
|
|
@@ -22764,7 +23043,7 @@ function CadView({ system, lookup, source, diagnostics = [], hostDiagnostics = [
|
|
|
22764
23043
|
}),
|
|
22765
23044
|
/* @__PURE__ */ jsx(IconButton, {
|
|
22766
23045
|
icon: "crosshair",
|
|
22767
|
-
label: "Look along
|
|
23046
|
+
label: "Look along normal",
|
|
22768
23047
|
tooltipSide: "top",
|
|
22769
23048
|
disabled: !sel.body,
|
|
22770
23049
|
onClick: focus
|
|
@@ -22814,7 +23093,7 @@ function CadView({ system, lookup, source, diagnostics = [], hostDiagnostics = [
|
|
|
22814
23093
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
22815
23094
|
className: "cad-caption-brand",
|
|
22816
23095
|
children: [/* @__PURE__ */ jsx("span", { children: "UHD" }), " VIEWER · 5-INCH 6S QUADCOPTER"]
|
|
22817
|
-
}), caption && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
|
|
23096
|
+
}), caption && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("div", {
|
|
22818
23097
|
className: "cad-caption-title",
|
|
22819
23098
|
children: caption[0]
|
|
22820
23099
|
}), caption[1] && /* @__PURE__ */ jsx("div", {
|
|
@@ -22879,7 +23158,7 @@ function FrameTable({ frame }) {
|
|
|
22879
23158
|
return /* @__PURE__ */ jsxs("div", {
|
|
22880
23159
|
className: "kv-grid",
|
|
22881
23160
|
children: [
|
|
22882
|
-
frame.artifact && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
23161
|
+
frame.artifact && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
22883
23162
|
className: "k",
|
|
22884
23163
|
children: "body"
|
|
22885
23164
|
}), /* @__PURE__ */ jsx("span", {
|
|
@@ -22949,7 +23228,7 @@ function CadInspector({ model, sel, onSel, direction, findings, resolve }) {
|
|
|
22949
23228
|
}), /* @__PURE__ */ jsx(ScrollArea, {
|
|
22950
23229
|
className: "inspector-scroll",
|
|
22951
23230
|
contentClassName: "inspector-body",
|
|
22952
|
-
children: body ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23231
|
+
children: body ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
22953
23232
|
/* @__PURE__ */ jsx("h3", {
|
|
22954
23233
|
className: "cad-title",
|
|
22955
23234
|
children: body.def.name
|
|
@@ -22960,7 +23239,7 @@ function CadInspector({ model, sel, onSel, direction, findings, resolve }) {
|
|
|
22960
23239
|
}),
|
|
22961
23240
|
/* @__PURE__ */ jsx("div", {
|
|
22962
23241
|
className: "cad-sub",
|
|
22963
|
-
children: body.via ? /* @__PURE__ */ jsxs(Fragment, { children: ["placed by link ", /* @__PURE__ */ jsx("button", {
|
|
23242
|
+
children: body.via ? /* @__PURE__ */ jsxs(Fragment$1, { children: ["placed by link ", /* @__PURE__ */ jsx("button", {
|
|
22964
23243
|
className: "linklike",
|
|
22965
23244
|
onClick: () => onSel({ mate: body.via }),
|
|
22966
23245
|
children: body.via
|
|
@@ -23024,7 +23303,7 @@ function CadInspector({ model, sel, onSel, direction, findings, resolve }) {
|
|
|
23024
23303
|
]
|
|
23025
23304
|
}, a.id))
|
|
23026
23305
|
})
|
|
23027
|
-
] }) : harness ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23306
|
+
] }) : harness ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
23028
23307
|
/* @__PURE__ */ jsx("h3", {
|
|
23029
23308
|
className: "cad-title",
|
|
23030
23309
|
children: harness.def.name
|
|
@@ -23048,7 +23327,7 @@ function CadInspector({ model, sel, onSel, direction, findings, resolve }) {
|
|
|
23048
23327
|
className: "v",
|
|
23049
23328
|
children: cableSummary(harness, hm)
|
|
23050
23329
|
}),
|
|
23051
|
-
hm && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23330
|
+
hm && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
23052
23331
|
/* @__PURE__ */ jsx("span", {
|
|
23053
23332
|
className: "k",
|
|
23054
23333
|
children: "routed"
|
|
@@ -23134,7 +23413,7 @@ function CadInspector({ model, sel, onSel, direction, findings, resolve }) {
|
|
|
23134
23413
|
]
|
|
23135
23414
|
}, a.id))
|
|
23136
23415
|
})
|
|
23137
|
-
] }) : mate ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23416
|
+
] }) : mate ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
23138
23417
|
/* @__PURE__ */ jsx("h3", {
|
|
23139
23418
|
className: "cad-title",
|
|
23140
23419
|
children: mate.linkId
|
|
@@ -23180,7 +23459,7 @@ function CadInspector({ model, sel, onSel, direction, findings, resolve }) {
|
|
|
23180
23459
|
})
|
|
23181
23460
|
]
|
|
23182
23461
|
})
|
|
23183
|
-
] }) : route ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23462
|
+
] }) : route ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
23184
23463
|
/* @__PURE__ */ jsx("h3", {
|
|
23185
23464
|
className: "cad-title",
|
|
23186
23465
|
children: route.linkId
|
|
@@ -23212,7 +23491,7 @@ function CadInspector({ model, sel, onSel, direction, findings, resolve }) {
|
|
|
23212
23491
|
")"
|
|
23213
23492
|
]
|
|
23214
23493
|
})
|
|
23215
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23494
|
+
] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
23216
23495
|
/* @__PURE__ */ jsxs("div", {
|
|
23217
23496
|
className: "section-title",
|
|
23218
23497
|
children: ["PLACED FROM LINKS · ", model.assembly.placements.length]
|
|
@@ -23231,7 +23510,7 @@ function CadInspector({ model, sel, onSel, direction, findings, resolve }) {
|
|
|
23231
23510
|
})]
|
|
23232
23511
|
}, b.key))
|
|
23233
23512
|
}),
|
|
23234
|
-
findings.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
23513
|
+
findings.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
23235
23514
|
className: "section-title",
|
|
23236
23515
|
children: ["FINDINGS ON THE MODEL · ", findings.length]
|
|
23237
23516
|
}), findings.map((f) => /* @__PURE__ */ jsxs("button", {
|
|
@@ -23309,7 +23588,7 @@ function CadInspector({ model, sel, onSel, direction, findings, resolve }) {
|
|
|
23309
23588
|
]
|
|
23310
23589
|
})]
|
|
23311
23590
|
}, r.linkId)),
|
|
23312
|
-
unrouted.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
23591
|
+
unrouted.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
23313
23592
|
className: "section-title",
|
|
23314
23593
|
children: ["UNROUTED · ", unrouted.length]
|
|
23315
23594
|
}), /* @__PURE__ */ jsxs("div", {
|
|
@@ -23336,8 +23615,8 @@ function BodyContents({ model, body, sel, onSel, resolve }) {
|
|
|
23336
23615
|
const named = Object.entries(manifest?.bodies ?? {});
|
|
23337
23616
|
const cad = cadOutputs(body.def);
|
|
23338
23617
|
const circuit = circuitOutputs(body.def);
|
|
23339
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23340
|
-
components.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
23618
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
23619
|
+
components.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
23341
23620
|
className: "section-title",
|
|
23342
23621
|
children: ["COMPONENTS · ", components.length]
|
|
23343
23622
|
}), /* @__PURE__ */ jsx("div", {
|
|
@@ -23357,7 +23636,7 @@ function BodyContents({ model, body, sel, onSel, resolve }) {
|
|
|
23357
23636
|
})]
|
|
23358
23637
|
}, c.id))
|
|
23359
23638
|
})] }),
|
|
23360
|
-
named.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23639
|
+
named.length > 1 && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
23361
23640
|
/* @__PURE__ */ jsxs("div", {
|
|
23362
23641
|
className: "section-title",
|
|
23363
23642
|
children: ["BODIES · ", named.length]
|
|
@@ -23380,7 +23659,7 @@ function BodyContents({ model, body, sel, onSel, resolve }) {
|
|
|
23380
23659
|
children: "Exploding separates them along the line between their centres."
|
|
23381
23660
|
})
|
|
23382
23661
|
] }),
|
|
23383
|
-
cad && cad.exports.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
23662
|
+
cad && cad.exports.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
23384
23663
|
className: "section-title",
|
|
23385
23664
|
children: ["MANUFACTURING EXPORTS · ", cad.exports.length]
|
|
23386
23665
|
}), /* @__PURE__ */ jsx("div", {
|
|
@@ -23477,13 +23756,27 @@ function Legend({ title, children, className, compact, ...rest }) {
|
|
|
23477
23756
|
}), children]
|
|
23478
23757
|
});
|
|
23479
23758
|
}
|
|
23480
|
-
function LegendItem({ color, label, shape = "line", onSelect, pressed, dimmed, absent, hint, hintShortcut, compact }) {
|
|
23759
|
+
function LegendItem({ color, label, shape = "line", onSelect, pressed, dimmed, absent, hint, hintShortcut, compact, meaning }) {
|
|
23760
|
+
const two = !compact && !!meaning;
|
|
23481
23761
|
const swatch = /* @__PURE__ */ jsx("span", {
|
|
23482
23762
|
"aria-hidden": true,
|
|
23483
|
-
className: cx("shrink-0", shape === "dot" ? "size-2 rounded-full" : "h-[3px] w-4 rounded-sm"),
|
|
23763
|
+
className: cx("shrink-0", shape === "dot" ? "size-2 rounded-full" : two ? "h-1 w-[18px] rounded-sm" : "h-[3px] w-4 rounded-sm"),
|
|
23484
23764
|
style: shape === "dash" ? { background: `repeating-linear-gradient(90deg, ${color} 0 4px, transparent 4px 7px)` } : { background: color }
|
|
23485
23765
|
});
|
|
23486
23766
|
const name = typeof label === "string" ? label : void 0;
|
|
23767
|
+
const text = two ? /* @__PURE__ */ jsxs("span", {
|
|
23768
|
+
className: "flex min-w-0 flex-1 flex-col",
|
|
23769
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
23770
|
+
className: "truncate text-[11.5px] leading-[15px] text-fg",
|
|
23771
|
+
children: label
|
|
23772
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
23773
|
+
className: "truncate text-[10px] leading-[13px] text-fg-muted",
|
|
23774
|
+
children: meaning
|
|
23775
|
+
})]
|
|
23776
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
23777
|
+
className: "min-w-0 flex-1 truncate",
|
|
23778
|
+
children: label
|
|
23779
|
+
});
|
|
23487
23780
|
if (!onSelect) {
|
|
23488
23781
|
if (compact) return /* @__PURE__ */ jsx("span", {
|
|
23489
23782
|
role: "img",
|
|
@@ -23493,8 +23786,8 @@ function LegendItem({ color, label, shape = "line", onSelect, pressed, dimmed, a
|
|
|
23493
23786
|
children: swatch
|
|
23494
23787
|
});
|
|
23495
23788
|
return /* @__PURE__ */ jsxs("div", {
|
|
23496
|
-
className: "flex items-center
|
|
23497
|
-
children: [swatch,
|
|
23789
|
+
className: cx("flex items-center text-[9.5px] text-fg-muted", two ? "gap-2.5" : "gap-2"),
|
|
23790
|
+
children: [swatch, text]
|
|
23498
23791
|
});
|
|
23499
23792
|
}
|
|
23500
23793
|
return /* @__PURE__ */ jsxs("button", {
|
|
@@ -23504,13 +23797,10 @@ function LegendItem({ color, label, shape = "line", onSelect, pressed, dimmed, a
|
|
|
23504
23797
|
"aria-label": compact ? name : void 0,
|
|
23505
23798
|
"data-tooltip": compact ? name : hint,
|
|
23506
23799
|
"data-tooltip-shortcut": hintShortcut,
|
|
23507
|
-
"data-tooltip-side": compact ? "top" : "
|
|
23800
|
+
"data-tooltip-side": compact ? "top" : "left",
|
|
23508
23801
|
onClick: (e) => !absent && onSelect(e.shiftKey || e.ctrlKey || e.metaKey),
|
|
23509
|
-
className: cx("uhd-legend-item flex min-h-[18px] items-center rounded-sm border-0 bg-transparent font-ui text-[9.5px] text-fg-muted transition-[opacity,background-color]", compact ? "h-[18px] w-6 justify-center p-0" : "-mx-1.5 -my-0.5 gap-2 px-1.5 py-0.5 text-left", "focus-visible:outline focus-visible:outline-1 focus-visible:-outline-offset-1 focus-visible:outline-focus", absent ? "cursor-default opacity-40" : "cursor-pointer hover:bg-hover hover:text-fg", pressed && "bg-accent-tint text-fg outline outline-1 -outline-offset-1 outline-contrast-active", dimmed && !absent && "opacity-55"),
|
|
23510
|
-
children: [swatch, !compact &&
|
|
23511
|
-
className: "min-w-0 flex-1 truncate",
|
|
23512
|
-
children: label
|
|
23513
|
-
})]
|
|
23802
|
+
className: cx("uhd-legend-item flex min-h-[18px] items-center rounded-sm border-0 bg-transparent font-ui text-[9.5px] text-fg-muted transition-[opacity,background-color]", compact ? "h-[18px] w-6 justify-center p-0" : two ? "-mx-1.5 gap-2.5 px-1.5 py-1 text-left" : "-mx-1.5 -my-0.5 gap-2 px-1.5 py-0.5 text-left", "focus-visible:outline focus-visible:outline-1 focus-visible:-outline-offset-1 focus-visible:outline-focus", absent ? "cursor-default opacity-40" : "cursor-pointer hover:bg-hover hover:text-fg", pressed && "bg-accent-tint text-fg outline outline-1 -outline-offset-1 outline-contrast-active", dimmed && !absent && "opacity-55"),
|
|
23803
|
+
children: [swatch, !compact && text]
|
|
23514
23804
|
});
|
|
23515
23805
|
}
|
|
23516
23806
|
/** Compact items side by side, `columns` to a row: a legend as narrow as its swatches. */
|
|
@@ -23524,22 +23814,49 @@ function LegendSwatches({ columns = 3, children, label }) {
|
|
|
23524
23814
|
});
|
|
23525
23815
|
}
|
|
23526
23816
|
/**
|
|
23527
|
-
*
|
|
23528
|
-
*
|
|
23529
|
-
|
|
23530
|
-
|
|
23817
|
+
* A folded legend: a narrow tab at the right edge, a chevron and the
|
|
23818
|
+
* colours it explains as dots. A click opens the legend; its label names it.
|
|
23819
|
+
*/
|
|
23820
|
+
function LegendTab({ dots, className, ...rest }) {
|
|
23821
|
+
return /* @__PURE__ */ jsxs("button", {
|
|
23822
|
+
type: "button",
|
|
23823
|
+
...rest,
|
|
23824
|
+
className: cx("uhd-legend-tab group flex w-9 cursor-pointer flex-col items-center gap-3 rounded-l-panel border border-r-0 border-line bg-surface px-0 py-3 text-fg-muted shadow-panel outline outline-1 -outline-offset-1 outline-contrast transition-colors", "hover:text-fg hover:outline-contrast-active focus-visible:outline-focus", className),
|
|
23825
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
23826
|
+
name: "chevron-left",
|
|
23827
|
+
size: 16,
|
|
23828
|
+
strokeWidth: 1.75,
|
|
23829
|
+
"aria-hidden": true
|
|
23830
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
23831
|
+
"aria-hidden": true,
|
|
23832
|
+
className: "flex flex-col items-center gap-1.5",
|
|
23833
|
+
children: dots.map((d) => /* @__PURE__ */ jsx("span", {
|
|
23834
|
+
className: cx("size-1.5 rounded-full transition-opacity", d.dimmed && "opacity-35"),
|
|
23835
|
+
style: { background: d.color }
|
|
23836
|
+
}, d.key))
|
|
23837
|
+
})]
|
|
23838
|
+
});
|
|
23839
|
+
}
|
|
23840
|
+
/** Below this canvas height (px) the legend folds by itself: open, it would cover much of the drawing. */
|
|
23841
|
+
var LEGEND_SHORT = 500;
|
|
23842
|
+
/**
|
|
23843
|
+
* The room the legend has before the toolbar (px): from the toolbar's right
|
|
23844
|
+
* edge to the legend's, less the gap. The toolbar is centred, so its button
|
|
23845
|
+
* for the legend moves its right edge by half the button: that half is taken
|
|
23846
|
+
* back, and the room is the same whether or not the button is in it.
|
|
23531
23847
|
*/
|
|
23532
23848
|
function legendRoom(m) {
|
|
23533
23849
|
if (!m.toolbar) return Infinity;
|
|
23534
|
-
return m.toolbar.
|
|
23850
|
+
return m.right - (m.toolbar.right - (m.slot ?? 0) / 2) - 8;
|
|
23535
23851
|
}
|
|
23536
23852
|
var overlapsY = (a, b) => a.top < b.bottom && b.top < a.bottom;
|
|
23537
23853
|
/**
|
|
23538
23854
|
* The largest form that does not run into the toolbar. A form fits when it is
|
|
23539
23855
|
* clear of the toolbar's height, or narrower than the room. Moving up to a
|
|
23540
|
-
* larger form than `current` takes `LEGEND_HYSTERESIS` more.
|
|
23856
|
+
* larger form than `current` takes `LEGEND_HYSTERESIS` more. Folded
|
|
23857
|
+
* (`folded`), the tab is the only form: "full" while it fits, else "button".
|
|
23541
23858
|
*/
|
|
23542
|
-
function legendStage(m, current = "full") {
|
|
23859
|
+
function legendStage(m, current = "full", folded = false) {
|
|
23543
23860
|
const room = legendRoom(m);
|
|
23544
23861
|
const order = [
|
|
23545
23862
|
"full",
|
|
@@ -23547,16 +23864,25 @@ function legendStage(m, current = "full") {
|
|
|
23547
23864
|
"button"
|
|
23548
23865
|
];
|
|
23549
23866
|
const at = order.indexOf(current);
|
|
23550
|
-
const fits = (stage) => {
|
|
23551
|
-
const box = m[stage];
|
|
23867
|
+
const fits = (box, stage) => {
|
|
23552
23868
|
if (!m.toolbar || !overlapsY(box, m.toolbar)) return true;
|
|
23553
23869
|
const spare = order.indexOf(stage) < at ? 6 : 0;
|
|
23554
23870
|
return box.right - box.left + spare <= room;
|
|
23555
23871
|
};
|
|
23556
|
-
if (fits("full")
|
|
23557
|
-
if (fits("
|
|
23872
|
+
if (folded) return !m.tab || fits(m.tab, "full") ? "full" : "button";
|
|
23873
|
+
if (fits(m.full, "full")) return "full";
|
|
23874
|
+
if (fits(m.compact, "compact")) return "compact";
|
|
23558
23875
|
return "button";
|
|
23559
23876
|
}
|
|
23877
|
+
/**
|
|
23878
|
+
* Whether the legend shows folded: the user folded it, or the canvas is
|
|
23879
|
+
* shorter than `LEGEND_SHORT` and the user has not opened it since it became
|
|
23880
|
+
* so (`peek`).
|
|
23881
|
+
*/
|
|
23882
|
+
function legendFolded(open, canvasHeight, peek) {
|
|
23883
|
+
if (!open) return true;
|
|
23884
|
+
return canvasHeight > 0 && canvasHeight < 500 && !peek;
|
|
23885
|
+
}
|
|
23560
23886
|
//#endregion
|
|
23561
23887
|
//#region src/viewer/views.tsx
|
|
23562
23888
|
/**
|
|
@@ -23566,7 +23892,7 @@ function legendStage(m, current = "full") {
|
|
|
23566
23892
|
* none of them is app chrome.
|
|
23567
23893
|
*/
|
|
23568
23894
|
/** The diagram of the current level: modules, interfaces, links and harnesses. */
|
|
23569
|
-
function DiagramCanvas({ toolbar = true, legend = true, coveredRight, missingHint, className }) {
|
|
23895
|
+
function DiagramCanvas({ toolbar = true, legend = true, coveredRight, missingHint, emptyAction, className }) {
|
|
23570
23896
|
const c = useViewer();
|
|
23571
23897
|
const covered = coveredRight ?? Boolean(c.panel);
|
|
23572
23898
|
return /* @__PURE__ */ jsxs("main", {
|
|
@@ -23608,16 +23934,38 @@ function DiagramCanvas({ toolbar = true, legend = true, coveredRight, missingHin
|
|
|
23608
23934
|
viewport: c.viewport,
|
|
23609
23935
|
onViewport: c.onViewport
|
|
23610
23936
|
}, `${c.scenario.id}/${c.levelKey}/${c.viewportsSeq}`),
|
|
23611
|
-
c.
|
|
23937
|
+
levelModules(c.vm.nodes).length === 0 && (emptyAction ? /* @__PURE__ */ jsx("div", {
|
|
23938
|
+
className: cx("canvas-empty", covered && "covered-right"),
|
|
23939
|
+
role: "status",
|
|
23940
|
+
"aria-label": `${c.levelDef.name}: no modules`,
|
|
23941
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
23942
|
+
type: "button",
|
|
23943
|
+
className: "canvas-empty-add",
|
|
23944
|
+
"data-add-part": "",
|
|
23945
|
+
onClick: emptyAction.onClick,
|
|
23946
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
23947
|
+
className: "canvas-empty-box",
|
|
23948
|
+
"aria-hidden": true,
|
|
23949
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
23950
|
+
name: "plus",
|
|
23951
|
+
size: 48,
|
|
23952
|
+
strokeWidth: 1.5
|
|
23953
|
+
})
|
|
23954
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
23955
|
+
className: "canvas-empty-label",
|
|
23956
|
+
children: emptyAction.label
|
|
23957
|
+
})]
|
|
23958
|
+
})
|
|
23959
|
+
}) : /* @__PURE__ */ jsxs("div", {
|
|
23612
23960
|
className: cx("canvas-empty", covered && "covered-right"),
|
|
23613
23961
|
role: "status",
|
|
23614
23962
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
23615
23963
|
className: "canvas-empty-title",
|
|
23616
23964
|
children: [c.levelDef.name, " has no modules yet"]
|
|
23617
23965
|
}), /* @__PURE__ */ jsx("p", { children: "Add child modules to its definition to see them here." })]
|
|
23618
|
-
}),
|
|
23966
|
+
})),
|
|
23619
23967
|
toolbar && /* @__PURE__ */ jsx(DiagramToolbar, { coveredRight: covered }),
|
|
23620
|
-
legend && /* @__PURE__ */ jsx(DiagramLegend, {}),
|
|
23968
|
+
legend && /* @__PURE__ */ jsx(DiagramLegend, { coveredRight: covered }),
|
|
23621
23969
|
c.pair && /* @__PURE__ */ jsx(PairView, {
|
|
23622
23970
|
vm: c.vm,
|
|
23623
23971
|
link: c.pair,
|
|
@@ -23708,7 +24056,7 @@ function MissingNotice({ hint, className }) {
|
|
|
23708
24056
|
icon: "x",
|
|
23709
24057
|
size: "sm",
|
|
23710
24058
|
tooltipSide: "bottom",
|
|
23711
|
-
label: "Hide
|
|
24059
|
+
label: "Hide",
|
|
23712
24060
|
onClick: () => setDismissed(key),
|
|
23713
24061
|
className: "size-6 shrink-0"
|
|
23714
24062
|
})
|
|
@@ -23736,11 +24084,11 @@ var CLASSIFICATION_OPTIONS = [
|
|
|
23736
24084
|
var DETAIL_OPTIONS = [{
|
|
23737
24085
|
id: "bundled",
|
|
23738
24086
|
icon: "minus",
|
|
23739
|
-
label: "
|
|
24087
|
+
label: "One line per link"
|
|
23740
24088
|
}, {
|
|
23741
24089
|
id: "conductors",
|
|
23742
24090
|
icon: "rows-3",
|
|
23743
|
-
label: "
|
|
24091
|
+
label: "Every conductor"
|
|
23744
24092
|
}];
|
|
23745
24093
|
/**
|
|
23746
24094
|
* The pointer's tool: select (a drag on the empty canvas draws a selection
|
|
@@ -23782,7 +24130,7 @@ function ViewButtons({ tooltipSide = "top" }) {
|
|
|
23782
24130
|
});
|
|
23783
24131
|
}
|
|
23784
24132
|
function ViewButtonsView({ onFit, onZoomIn, onZoomOut, tooltipSide }) {
|
|
23785
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
24133
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
23786
24134
|
/* @__PURE__ */ jsx(IconButton, {
|
|
23787
24135
|
icon: "maximize",
|
|
23788
24136
|
label: "Fit view",
|
|
@@ -23818,7 +24166,7 @@ var DiagramToolbarView = memo(function DiagramToolbarView(p) {
|
|
|
23818
24166
|
tooltipSide: "top"
|
|
23819
24167
|
}),
|
|
23820
24168
|
/* @__PURE__ */ jsx(ToolbarSeparator, {}),
|
|
23821
|
-
p.controls && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
24169
|
+
p.controls && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
23822
24170
|
/* @__PURE__ */ jsx(ToggleGroup, {
|
|
23823
24171
|
label: "Classification",
|
|
23824
24172
|
tooltipSide: "top",
|
|
@@ -23837,7 +24185,7 @@ var DiagramToolbarView = memo(function DiagramToolbarView(p) {
|
|
|
23837
24185
|
/* @__PURE__ */ jsx(IconButton, {
|
|
23838
24186
|
icon: "arrow-down-to-line",
|
|
23839
24187
|
tooltipSide: "top",
|
|
23840
|
-
label: p.showGrounds ? "
|
|
24188
|
+
label: p.showGrounds ? "Grounds as symbols" : "Grounds as wires",
|
|
23841
24189
|
pressed: p.showGrounds,
|
|
23842
24190
|
onClick: () => p.onGrounds(!p.showGrounds)
|
|
23843
24191
|
}),
|
|
@@ -23852,7 +24200,7 @@ var DiagramToolbarView = memo(function DiagramToolbarView(p) {
|
|
|
23852
24200
|
/* @__PURE__ */ jsx(ToolbarSeparator, {}),
|
|
23853
24201
|
/* @__PURE__ */ jsx(IconButton, {
|
|
23854
24202
|
icon: "rotate-ccw",
|
|
23855
|
-
label: "Reset layout
|
|
24203
|
+
label: "Reset layout",
|
|
23856
24204
|
tooltipSide: "top",
|
|
23857
24205
|
onClick: p.onReset
|
|
23858
24206
|
})
|
|
@@ -23887,19 +24235,19 @@ function DiagramToolbar({ coveredRight, className, controls = true, legend }) {
|
|
|
23887
24235
|
});
|
|
23888
24236
|
}
|
|
23889
24237
|
var LegendItemsView = memo(function LegendItemsView({ mode, present, isolated, onIsolate, compact }) {
|
|
23890
|
-
|
|
23891
|
-
return /* @__PURE__ */ jsx(Fragment, { children: legendFor(mode, present).map((item) => {
|
|
24238
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: legendFor(mode, present).map((item) => {
|
|
23892
24239
|
const pressed = isolated.has(item.key);
|
|
23893
24240
|
const absent = !present.has(item.key) && !pressed;
|
|
23894
24241
|
return /* @__PURE__ */ jsx(LegendItem, {
|
|
23895
24242
|
color: item.color,
|
|
23896
24243
|
label: item.label,
|
|
24244
|
+
meaning: item.meaning,
|
|
23897
24245
|
onSelect: (add) => onIsolate(item.key, add),
|
|
23898
24246
|
pressed,
|
|
23899
24247
|
dimmed: isolated.size > 0 && !pressed,
|
|
23900
24248
|
absent,
|
|
23901
|
-
hint: absent ?
|
|
23902
|
-
hintShortcut: absent ? void 0 : pressed && isolated.size === 1 ? "Esc" : "Shift+click:
|
|
24249
|
+
hint: absent ? "Not on this level" : pressed ? isolated.size > 1 ? "Release" : "Show all" : "Isolate",
|
|
24250
|
+
hintShortcut: absent ? void 0 : pressed && isolated.size === 1 ? "Esc" : "Shift+click: several",
|
|
23903
24251
|
compact
|
|
23904
24252
|
}, item.key);
|
|
23905
24253
|
}) });
|
|
@@ -23908,8 +24256,9 @@ var LegendItemsView = memo(function LegendItemsView({ mode, present, isolated, o
|
|
|
23908
24256
|
* The entries of the current classification's legend, as buttons: a click
|
|
23909
24257
|
* isolates one (its links stay, with the interfaces and modules they touch;
|
|
23910
24258
|
* the rest of the level fades), a click on it again shows everything, a
|
|
23911
|
-
* click on another switches, and Shift, Ctrl or Cmd holds several.
|
|
23912
|
-
*
|
|
24259
|
+
* click on another switches, and Shift, Ctrl or Cmd holds several. Each
|
|
24260
|
+
* reads as its name and, under it, what it stands for. For a shell that
|
|
24261
|
+
* draws its own legend card.
|
|
23913
24262
|
*/
|
|
23914
24263
|
function DiagramLegendItems({ compact, columns = 3 } = {}) {
|
|
23915
24264
|
const c = useViewer();
|
|
@@ -23920,7 +24269,10 @@ function DiagramLegendItems({ compact, columns = 3 } = {}) {
|
|
|
23920
24269
|
onIsolate: c.onIsolate,
|
|
23921
24270
|
compact
|
|
23922
24271
|
});
|
|
23923
|
-
if (!compact) return
|
|
24272
|
+
if (!compact) return /* @__PURE__ */ jsx("div", {
|
|
24273
|
+
className: "flex flex-col gap-1",
|
|
24274
|
+
children: items
|
|
24275
|
+
});
|
|
23924
24276
|
return /* @__PURE__ */ jsx(LegendSwatches, {
|
|
23925
24277
|
columns,
|
|
23926
24278
|
label: CLASSIFICATIONS.find((x) => x.id === c.mode)?.label,
|
|
@@ -23935,66 +24287,127 @@ function IsolationClear({ className }) {
|
|
|
23935
24287
|
icon: "x",
|
|
23936
24288
|
size: "sm",
|
|
23937
24289
|
tooltipSide: "top",
|
|
23938
|
-
label: "Show
|
|
24290
|
+
label: "Show all",
|
|
23939
24291
|
shortcut: "Esc",
|
|
23940
24292
|
onClick: c.clearIsolated,
|
|
23941
24293
|
className: cx("size-6", className)
|
|
23942
24294
|
});
|
|
23943
24295
|
}
|
|
24296
|
+
/** What a legend that folds gives the content it draws: the way to fold it (`FittedLegend`). */
|
|
24297
|
+
var LegendFoldContext = createContext(null);
|
|
24298
|
+
/**
|
|
24299
|
+
* The legend's fold button, at the right of its header: the legend becomes a
|
|
24300
|
+
* tab at the right edge. Nothing where the legend does not fold (the
|
|
24301
|
+
* toolbar's popover).
|
|
24302
|
+
*/
|
|
24303
|
+
function LegendFold({ className }) {
|
|
24304
|
+
const fold = useContext(LegendFoldContext);
|
|
24305
|
+
if (!fold) return null;
|
|
24306
|
+
return /* @__PURE__ */ jsx(IconButton, {
|
|
24307
|
+
icon: "chevron-right",
|
|
24308
|
+
size: "sm",
|
|
24309
|
+
tooltipSide: "top",
|
|
24310
|
+
label: "Hide legend",
|
|
24311
|
+
onClick: fold,
|
|
24312
|
+
className: cx("size-6", className)
|
|
24313
|
+
});
|
|
24314
|
+
}
|
|
23944
24315
|
/**
|
|
23945
24316
|
* What the legend shows in a form: `full` the title and the entries with their
|
|
23946
|
-
*
|
|
23947
|
-
* named by its label).
|
|
24317
|
+
* names and meanings; `compact` the classification's icon and the swatches
|
|
24318
|
+
* alone (each named by its label).
|
|
23948
24319
|
*/
|
|
23949
24320
|
function DiagramLegendBody({ form }) {
|
|
23950
24321
|
const c = useViewer();
|
|
23951
24322
|
const title = CLASSIFICATIONS.find((x) => x.id === c.mode)?.label;
|
|
23952
24323
|
if (form === "compact") {
|
|
23953
24324
|
const icon = CLASSIFICATION_OPTIONS.find((o) => o.id === c.mode)?.icon ?? "layers";
|
|
23954
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
24325
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
23955
24326
|
className: "flex min-h-6 items-center justify-between gap-1",
|
|
23956
|
-
children: [
|
|
23957
|
-
|
|
23958
|
-
|
|
23959
|
-
|
|
23960
|
-
|
|
23961
|
-
|
|
23962
|
-
|
|
23963
|
-
|
|
24327
|
+
children: [
|
|
24328
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
24329
|
+
name: icon,
|
|
24330
|
+
size: 13,
|
|
24331
|
+
strokeWidth: 1.75,
|
|
24332
|
+
className: "text-fg-muted",
|
|
24333
|
+
"aria-label": title,
|
|
24334
|
+
role: "img"
|
|
24335
|
+
}),
|
|
24336
|
+
/* @__PURE__ */ jsx(IsolationClear, { className: "-my-1" }),
|
|
24337
|
+
/* @__PURE__ */ jsx(LegendFold, { className: "-my-1 -mr-1.5" })
|
|
24338
|
+
]
|
|
23964
24339
|
}), /* @__PURE__ */ jsx(DiagramLegendItems, {
|
|
23965
24340
|
compact: true,
|
|
23966
24341
|
columns: 3
|
|
23967
24342
|
})] });
|
|
23968
24343
|
}
|
|
23969
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
23970
|
-
className: "mb-
|
|
24344
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
24345
|
+
className: "legend-head -mx-3 -mt-1 mb-1 flex min-h-7 items-center justify-between gap-2 border-b border-line-subtle px-3 pb-1",
|
|
23971
24346
|
children: [/* @__PURE__ */ jsx("span", {
|
|
23972
24347
|
className: "font-label text-[10px] tracking-[0.8px] text-fg-muted uppercase",
|
|
23973
24348
|
children: title
|
|
23974
|
-
}), /* @__PURE__ */
|
|
24349
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
24350
|
+
className: "-mr-1.5 flex items-center",
|
|
24351
|
+
children: [/* @__PURE__ */ jsx(IsolationClear, {}), /* @__PURE__ */ jsx(LegendFold, {})]
|
|
24352
|
+
})]
|
|
23975
24353
|
}), /* @__PURE__ */ jsx(DiagramLegendItems, {})] });
|
|
23976
24354
|
}
|
|
23977
24355
|
/** What the link colours mean in the current classification; a click on an entry isolates it. It gives way to the toolbar as the canvas narrows (`FittedLegend`). */
|
|
23978
|
-
function DiagramLegend({ className }) {
|
|
24356
|
+
function DiagramLegend({ className, coveredRight }) {
|
|
23979
24357
|
return /* @__PURE__ */ jsx(FittedLegend, {
|
|
23980
24358
|
label: "Legend",
|
|
23981
24359
|
className,
|
|
24360
|
+
coveredRight,
|
|
23982
24361
|
render: (form) => /* @__PURE__ */ jsx(DiagramLegendBody, { form })
|
|
23983
24362
|
});
|
|
23984
24363
|
}
|
|
23985
24364
|
/**
|
|
23986
|
-
* A legend card at the canvas's bottom
|
|
24365
|
+
* A legend card at the canvas's bottom right that stays there and gives way
|
|
23987
24366
|
* to the bottom toolbar (ui/legendFit.ts): the full form while it fits beside
|
|
23988
24367
|
* the toolbar, then the compact one, and at its smallest none, the toolbar
|
|
23989
|
-
* then offering it behind a button (`LegendToolbarButton`).
|
|
23990
|
-
*
|
|
23991
|
-
*
|
|
23992
|
-
*
|
|
24368
|
+
* then offering it behind a button (`LegendToolbarButton`). Folded, it is a
|
|
24369
|
+
* tab at the right edge with a dot per colour, which opens it; a canvas
|
|
24370
|
+
* shorter than `LEGEND_SHORT` folds it until the user opens it there. It
|
|
24371
|
+
* measures the room it has (a `ResizeObserver` on the canvas, the toolbar and
|
|
24372
|
+
* every form) from hidden copies of the forms, so it never overlaps the
|
|
24373
|
+
* toolbar. `render` draws a form; the card is a sibling of the toolbar
|
|
24374
|
+
* (`.toolbar`).
|
|
23993
24375
|
*/
|
|
23994
|
-
function FittedLegend({ label, render, className }) {
|
|
23995
|
-
const { legendStage: stage, setLegendStage, panel } = useViewer();
|
|
24376
|
+
function FittedLegend({ label, render, className, open: given, onOpenChange, defaultOpen = true, coveredRight = false }) {
|
|
24377
|
+
const { legendStage: stage, setLegendStage, panel, mode, present, isolated } = useViewer();
|
|
24378
|
+
const [own, setOwn] = useState(defaultOpen);
|
|
24379
|
+
const open = given ?? own;
|
|
24380
|
+
const setOpen = (next) => {
|
|
24381
|
+
if (given === void 0) setOwn(next);
|
|
24382
|
+
onOpenChange?.(next);
|
|
24383
|
+
};
|
|
24384
|
+
const [height, setHeight] = useState(0);
|
|
24385
|
+
const [peek, setPeek] = useState(false);
|
|
24386
|
+
const short = height > 0 && height < 500;
|
|
24387
|
+
useEffect(() => {
|
|
24388
|
+
if (!short) setPeek(false);
|
|
24389
|
+
}, [short]);
|
|
24390
|
+
const folded = legendFolded(open, height, peek);
|
|
24391
|
+
const unfold = () => {
|
|
24392
|
+
if (!open) setOpen(true);
|
|
24393
|
+
if (short) setPeek(true);
|
|
24394
|
+
};
|
|
24395
|
+
const fold = useCallback(() => {
|
|
24396
|
+
if (open && short && peek) setPeek(false);
|
|
24397
|
+
else {
|
|
24398
|
+
if (given === void 0) setOwn(false);
|
|
24399
|
+
onOpenChange?.(false);
|
|
24400
|
+
}
|
|
24401
|
+
}, [
|
|
24402
|
+
open,
|
|
24403
|
+
short,
|
|
24404
|
+
peek,
|
|
24405
|
+
given,
|
|
24406
|
+
onOpenChange
|
|
24407
|
+
]);
|
|
23996
24408
|
const full = useRef(null);
|
|
23997
24409
|
const compact = useRef(null);
|
|
24410
|
+
const tab = useRef(null);
|
|
23998
24411
|
const current = useRef(stage);
|
|
23999
24412
|
current.current = stage;
|
|
24000
24413
|
const measure = useCallback(() => {
|
|
@@ -24002,27 +24415,31 @@ function FittedLegend({ label, render, className }) {
|
|
|
24002
24415
|
const k = compact.current;
|
|
24003
24416
|
const host = f?.parentElement;
|
|
24004
24417
|
if (!f || !k || !host) return;
|
|
24418
|
+
setHeight(host.clientHeight);
|
|
24005
24419
|
const toolbar = host.querySelector(":scope > .toolbar");
|
|
24006
24420
|
const box = toolbar && toolbar.getClientRects().length ? toolbar.getBoundingClientRect() : null;
|
|
24007
24421
|
const slotEl = toolbar?.querySelector("[data-legend-slot]");
|
|
24008
24422
|
const slot = slotEl ? slotEl.getBoundingClientRect().width + (parseFloat(getComputedStyle(toolbar).columnGap) || 0) : 0;
|
|
24009
24423
|
const fr = f.getBoundingClientRect();
|
|
24424
|
+
const tr = tab.current?.getBoundingClientRect();
|
|
24010
24425
|
const next = legendStage({
|
|
24011
|
-
|
|
24426
|
+
right: fr.right,
|
|
24012
24427
|
full: fr,
|
|
24013
24428
|
compact: k.getBoundingClientRect(),
|
|
24429
|
+
...tr ? { tab: tr } : {},
|
|
24014
24430
|
toolbar: box,
|
|
24015
24431
|
slot
|
|
24016
|
-
}, current.current);
|
|
24432
|
+
}, current.current, folded);
|
|
24017
24433
|
if (next !== current.current) {
|
|
24018
24434
|
current.current = next;
|
|
24019
24435
|
setLegendStage(next);
|
|
24020
24436
|
}
|
|
24021
|
-
}, [setLegendStage]);
|
|
24437
|
+
}, [setLegendStage, folded]);
|
|
24022
24438
|
useLayoutEffect(measure, [
|
|
24023
24439
|
measure,
|
|
24024
24440
|
panel,
|
|
24025
|
-
stage
|
|
24441
|
+
stage,
|
|
24442
|
+
coveredRight
|
|
24026
24443
|
]);
|
|
24027
24444
|
useEffect(() => {
|
|
24028
24445
|
const host = full.current?.parentElement;
|
|
@@ -24031,36 +24448,66 @@ function FittedLegend({ label, render, className }) {
|
|
|
24031
24448
|
ro.observe(host);
|
|
24032
24449
|
if (full.current) ro.observe(full.current);
|
|
24033
24450
|
if (compact.current) ro.observe(compact.current);
|
|
24451
|
+
if (tab.current) ro.observe(tab.current);
|
|
24034
24452
|
const toolbar = host.querySelector(":scope > .toolbar");
|
|
24035
24453
|
if (toolbar) ro.observe(toolbar);
|
|
24036
24454
|
return () => ro.disconnect();
|
|
24037
24455
|
}, [measure]);
|
|
24038
24456
|
useEffect(() => () => setLegendStage("full"), [setLegendStage]);
|
|
24039
|
-
|
|
24040
|
-
|
|
24041
|
-
|
|
24042
|
-
|
|
24043
|
-
|
|
24044
|
-
|
|
24045
|
-
|
|
24046
|
-
|
|
24047
|
-
|
|
24048
|
-
|
|
24049
|
-
|
|
24050
|
-
"
|
|
24051
|
-
|
|
24052
|
-
|
|
24053
|
-
|
|
24054
|
-
|
|
24055
|
-
|
|
24056
|
-
|
|
24057
|
-
|
|
24058
|
-
|
|
24059
|
-
|
|
24060
|
-
|
|
24061
|
-
|
|
24062
|
-
|
|
24063
|
-
|
|
24457
|
+
const entries = legendFor(mode, present);
|
|
24458
|
+
const shown = entries.filter((e) => present.has(e.key) || isolated.has(e.key));
|
|
24459
|
+
const dots = (shown.length ? shown : entries).slice(0, 8).map((e) => ({
|
|
24460
|
+
key: e.key,
|
|
24461
|
+
color: e.color,
|
|
24462
|
+
dimmed: isolated.size > 0 && !isolated.has(e.key)
|
|
24463
|
+
}));
|
|
24464
|
+
const side = cx(coveredRight && "covered-right", className);
|
|
24465
|
+
return /* @__PURE__ */ jsxs(LegendFoldContext.Provider, {
|
|
24466
|
+
value: fold,
|
|
24467
|
+
children: [
|
|
24468
|
+
stage !== "button" && (folded ? /* @__PURE__ */ jsx(LegendTab, {
|
|
24469
|
+
ref: tab,
|
|
24470
|
+
dots,
|
|
24471
|
+
"aria-label": label,
|
|
24472
|
+
"aria-expanded": false,
|
|
24473
|
+
"data-tooltip": label,
|
|
24474
|
+
"data-tooltip-side": "left",
|
|
24475
|
+
"data-legend-tab": "",
|
|
24476
|
+
onClick: unfold,
|
|
24477
|
+
className: cx("legend-tab", side)
|
|
24478
|
+
}) : /* @__PURE__ */ jsx(Legend, {
|
|
24479
|
+
role: "group",
|
|
24480
|
+
"aria-label": label,
|
|
24481
|
+
compact: stage === "compact",
|
|
24482
|
+
className: cx("legend", side),
|
|
24483
|
+
"data-legend-stage": stage,
|
|
24484
|
+
children: render(stage)
|
|
24485
|
+
})),
|
|
24486
|
+
/* @__PURE__ */ jsx(Legend, {
|
|
24487
|
+
ref: full,
|
|
24488
|
+
"aria-hidden": true,
|
|
24489
|
+
inert: true,
|
|
24490
|
+
className: cx("legend-measure", side),
|
|
24491
|
+
children: render("full")
|
|
24492
|
+
}),
|
|
24493
|
+
/* @__PURE__ */ jsx(Legend, {
|
|
24494
|
+
ref: compact,
|
|
24495
|
+
"aria-hidden": true,
|
|
24496
|
+
inert: true,
|
|
24497
|
+
compact: true,
|
|
24498
|
+
className: cx("legend-measure", side),
|
|
24499
|
+
children: render("compact")
|
|
24500
|
+
}),
|
|
24501
|
+
folded && stage === "button" && /* @__PURE__ */ jsx(LegendTab, {
|
|
24502
|
+
ref: tab,
|
|
24503
|
+
dots,
|
|
24504
|
+
"aria-hidden": true,
|
|
24505
|
+
inert: true,
|
|
24506
|
+
tabIndex: -1,
|
|
24507
|
+
className: cx("legend-tab legend-measure", side)
|
|
24508
|
+
})
|
|
24509
|
+
]
|
|
24510
|
+
});
|
|
24064
24511
|
}
|
|
24065
24512
|
/**
|
|
24066
24513
|
* The legend's button in the toolbar, shown only when the legend has no room
|
|
@@ -24225,7 +24672,9 @@ function ViewerNodeMenu() {
|
|
|
24225
24672
|
* assembly): a GLB by URL, or a scene a host built (a STEP it converted), in
|
|
24226
24673
|
* the 3D view's own scene, lights, materials and theme colours, with a
|
|
24227
24674
|
* floating icon toolbar (fit, standard views, wireframe, x-ray, grid, turn)
|
|
24228
|
-
* and a card with its
|
|
24675
|
+
* and, on request from the toolbar, a card with its name and size (PB-1074:
|
|
24676
|
+
* shown all the time it covered the model, and a Select All lit it up). Nothing
|
|
24677
|
+
* here is specific to a host.
|
|
24229
24678
|
*/
|
|
24230
24679
|
var VIEWS = [
|
|
24231
24680
|
{
|
|
@@ -24291,7 +24740,7 @@ function stats(root) {
|
|
|
24291
24740
|
};
|
|
24292
24741
|
}
|
|
24293
24742
|
var mm = (n) => n >= 100 ? n.toFixed(0) : n >= 10 ? n.toFixed(1) : n.toFixed(2);
|
|
24294
|
-
function ModelView({ url, object, name, detail, error, onReady, actions, className }) {
|
|
24743
|
+
function ModelView({ url, object, name, detail, error, onReady, actions, infoOpen = false, className }) {
|
|
24295
24744
|
const host = useRef(null);
|
|
24296
24745
|
const handle = useRef(null);
|
|
24297
24746
|
const model = useRef(null);
|
|
@@ -24301,6 +24750,7 @@ function ModelView({ url, object, name, detail, error, onReady, actions, classNa
|
|
|
24301
24750
|
const [grid, setGrid] = useState(true);
|
|
24302
24751
|
const [spin, setSpin] = useState(false);
|
|
24303
24752
|
const [view, setView] = useState("iso");
|
|
24753
|
+
const [showInfo, setShowInfo] = useState(infoOpen);
|
|
24304
24754
|
useEffect(() => {
|
|
24305
24755
|
if (!host.current) return;
|
|
24306
24756
|
let h;
|
|
@@ -24458,14 +24908,16 @@ function ModelView({ url, object, name, detail, error, onReady, actions, classNa
|
|
|
24458
24908
|
}, [spin]);
|
|
24459
24909
|
const info = state.info;
|
|
24460
24910
|
return /* @__PURE__ */ jsxs("div", {
|
|
24461
|
-
className: cx("uhd-model-view relative size-full min-h-[240px] min-w-[280px] overflow-hidden bg-canvas", className),
|
|
24911
|
+
className: cx("uhd-model-view relative size-full min-h-[240px] min-w-[280px] overflow-hidden bg-canvas select-none", className),
|
|
24462
24912
|
children: [
|
|
24463
24913
|
/* @__PURE__ */ jsx("div", {
|
|
24464
24914
|
ref: host,
|
|
24465
24915
|
className: "absolute inset-0 [&>canvas]:block [&>canvas]:size-full"
|
|
24466
24916
|
}),
|
|
24467
|
-
(name || info) && /* @__PURE__ */ jsxs("div", {
|
|
24468
|
-
|
|
24917
|
+
showInfo && (name || info) && /* @__PURE__ */ jsxs("div", {
|
|
24918
|
+
role: "note",
|
|
24919
|
+
"aria-label": "Model info",
|
|
24920
|
+
className: "pointer-events-none absolute top-[calc(var(--uhd-inset-top,0px)+12px)] left-3 max-w-[min(360px,calc(100%-24px))] rounded-panel border border-line bg-surface px-3 py-2 shadow-panel outline outline-1 -outline-offset-1 outline-contrast",
|
|
24469
24921
|
children: [
|
|
24470
24922
|
name && /* @__PURE__ */ jsx("div", {
|
|
24471
24923
|
className: "truncate font-label text-[12px] tracking-[0.06em] text-fg uppercase",
|
|
@@ -24554,7 +25006,7 @@ function ModelView({ url, object, name, detail, error, onReady, actions, classNa
|
|
|
24554
25006
|
}),
|
|
24555
25007
|
/* @__PURE__ */ jsx(IconButton, {
|
|
24556
25008
|
icon: "scan-eye",
|
|
24557
|
-
label: "X-ray
|
|
25009
|
+
label: "X-ray",
|
|
24558
25010
|
tooltipSide: "top",
|
|
24559
25011
|
pressed: xray,
|
|
24560
25012
|
onClick: () => setXray(!xray)
|
|
@@ -24573,6 +25025,13 @@ function ModelView({ url, object, name, detail, error, onReady, actions, classNa
|
|
|
24573
25025
|
pressed: spin,
|
|
24574
25026
|
onClick: () => setSpin(!spin)
|
|
24575
25027
|
}),
|
|
25028
|
+
(name || info) && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(ToolbarSeparator, {}), /* @__PURE__ */ jsx(IconButton, {
|
|
25029
|
+
icon: "info",
|
|
25030
|
+
label: showInfo ? "Hide the model info" : "Model info: name and size",
|
|
25031
|
+
tooltipSide: "top",
|
|
25032
|
+
pressed: showInfo,
|
|
25033
|
+
onClick: () => setShowInfo(!showInfo)
|
|
25034
|
+
})] }),
|
|
24576
25035
|
actions && /* @__PURE__ */ jsx(ToolbarSeparator, {}),
|
|
24577
25036
|
actions
|
|
24578
25037
|
]
|
|
@@ -24902,25 +25361,30 @@ function panelState(v, fallbackOpen = true) {
|
|
|
24902
25361
|
};
|
|
24903
25362
|
}
|
|
24904
25363
|
var clampWidth = (w, room = Infinity) => Math.round(Math.max(HIERARCHY_WIDTH.min, Math.min(HIERARCHY_WIDTH.max, room, w)));
|
|
24905
|
-
/** The row that holds the
|
|
25364
|
+
/** The row "Harnesses & links" that holds the harnesses, cables and fastener stacks: not a module of the system. */
|
|
24906
25365
|
var WIRING_PATH = "#wiring";
|
|
24907
25366
|
var WIRING_KINDS = /* @__PURE__ */ new Set(["harness", "fasteners"]);
|
|
24908
25367
|
/**
|
|
24909
|
-
* The tree as the panel shows it: the system's structure first, and
|
|
24910
|
-
*
|
|
24911
|
-
*
|
|
24912
|
-
*
|
|
25368
|
+
* The tree as the panel shows it: the system's structure first, and the
|
|
25369
|
+
* harnesses and links (harnesses, cables and fastener stacks) folded into one
|
|
25370
|
+
* group row at the bottom, `WIRING_PATH`. With `level` (the instance path of
|
|
25371
|
+
* the level on screen, "" for the root), the group holds only that level's own
|
|
25372
|
+
* harnesses, not those of the modules inside it: they show once that module is
|
|
25373
|
+
* the level. Without `level`, every harness, wherever it sits, each with the
|
|
25374
|
+
* module it belongs to. Harnesses never show in the structure. Without any for
|
|
25375
|
+
* the group, the structure alone.
|
|
24913
25376
|
*/
|
|
24914
|
-
function groupWiring(nodes) {
|
|
25377
|
+
function groupWiring(nodes, level) {
|
|
24915
25378
|
const wiring = [];
|
|
24916
25379
|
const strip = (n) => {
|
|
24917
25380
|
if (!n.children.some((c) => WIRING_KINDS.has(c.kind) || c.children.length)) return n;
|
|
24918
25381
|
const kept = [];
|
|
24919
|
-
for (const c of n.children) if (WIRING_KINDS.has(c.kind))
|
|
25382
|
+
for (const c of n.children) if (!WIRING_KINDS.has(c.kind)) kept.push(strip(c));
|
|
25383
|
+
else if (level === void 0) wiring.push({
|
|
24920
25384
|
...c,
|
|
24921
25385
|
where: n.label
|
|
24922
25386
|
});
|
|
24923
|
-
else
|
|
25387
|
+
else if (n.path === level) wiring.push(c);
|
|
24924
25388
|
return {
|
|
24925
25389
|
...n,
|
|
24926
25390
|
children: kept,
|
|
@@ -24933,7 +25397,7 @@ function groupWiring(nodes) {
|
|
|
24933
25397
|
for (const w of wiring) worst = worse(worst, w.worst);
|
|
24934
25398
|
const group = {
|
|
24935
25399
|
path: WIRING_PATH,
|
|
24936
|
-
label: "
|
|
25400
|
+
label: "Harnesses & links",
|
|
24937
25401
|
defId: "",
|
|
24938
25402
|
kind: "group",
|
|
24939
25403
|
icon: "cable",
|
|
@@ -24974,21 +25438,28 @@ function markLegend(nodes) {
|
|
|
24974
25438
|
//#endregion
|
|
24975
25439
|
//#region src/viewer/hierarchy.tsx
|
|
24976
25440
|
/**
|
|
24977
|
-
* The hierarchy panel (PB-1042): the module tree of the viewer's system,
|
|
24978
|
-
*
|
|
24979
|
-
* (one tab) and follows it: a click on a row selects the module on the
|
|
24980
|
-
* that holds it, a double-click (or Enter on the selected row) drills
|
|
24981
|
-
* a selection on the canvas opens and highlights its row, and the
|
|
24982
|
-
* diagram shows is marked.
|
|
24983
|
-
*
|
|
25441
|
+
* The hierarchy panel (PB-1042): the module tree of the viewer's system, a
|
|
25442
|
+
* floating card at the left of the view, beside the canvas. It belongs to one
|
|
25443
|
+
* viewer (one tab) and follows it: a click on a row selects the module on the
|
|
25444
|
+
* level that holds it, a double-click (or Enter on the selected row) drills
|
|
25445
|
+
* into it, a selection on the canvas opens and highlights its row, and the
|
|
25446
|
+
* level the diagram shows is marked. Its own button folds it away, to a
|
|
25447
|
+
* small icon-only button floating at the top left of the view that opens it
|
|
25448
|
+
* again (PB-1070); it is resized by its edge, filters as you type, and is a
|
|
25449
|
+
* tree to the keyboard and to screen readers.
|
|
24984
25450
|
*
|
|
24985
25451
|
* Its look is the viewer's tokens only (a floating card: radius, border,
|
|
24986
25452
|
* shadow, faces of the theme), so a host's theme decides it. What a host keeps
|
|
24987
25453
|
* per tab (open, width, open rows) comes in as `state` and goes out through
|
|
24988
25454
|
* `onStateChange`.
|
|
24989
25455
|
*/
|
|
24990
|
-
/** The
|
|
24991
|
-
|
|
25456
|
+
/** The row of the selection on the diagram: the module selected, or the harness a selected line runs through. */
|
|
25457
|
+
function selectedRow(drill, vm, selection) {
|
|
25458
|
+
const harness = selectedHarness(vm, selection);
|
|
25459
|
+
return harness !== void 0 ? fullId(drill, harness) : selectedPath(drill, selection);
|
|
25460
|
+
}
|
|
25461
|
+
/** What the folded panel keeps of the view's width: nothing (its button to open it again floats over the view). */
|
|
25462
|
+
var RAIL_WIDTH = 0;
|
|
24992
25463
|
var ROW_INDENT = 12;
|
|
24993
25464
|
var SEVERITY_TEXT = {
|
|
24994
25465
|
error: "text-error",
|
|
@@ -24996,16 +25467,28 @@ var SEVERITY_TEXT = {
|
|
|
24996
25467
|
info: "text-info"
|
|
24997
25468
|
};
|
|
24998
25469
|
/**
|
|
24999
|
-
* The panel's look, in one place (PB-1042
|
|
25000
|
-
*
|
|
25001
|
-
*
|
|
25002
|
-
* the viewer's tokens, so a host's theme
|
|
25003
|
-
* under the Protoboard theme). Swap these to
|
|
25470
|
+
* The panel's look, in one place (PB-1042, PB-1070): a floating card like the
|
|
25471
|
+
* host's header, 4 px from the view's edges and below the header, with the
|
|
25472
|
+
* panel radius, a border all round and the panel shadow; rows highlighted in
|
|
25473
|
+
* the theme's selection colour. Only the viewer's tokens, so a host's theme
|
|
25474
|
+
* decides the colours (orange only under the Protoboard theme). Swap these to
|
|
25475
|
+
* restyle it.
|
|
25004
25476
|
*/
|
|
25005
25477
|
var HIERARCHY_LOOK = {
|
|
25006
|
-
dock: "uhd-hierarchy-dock absolute
|
|
25007
|
-
|
|
25008
|
-
|
|
25478
|
+
dock: "uhd-hierarchy-dock absolute bottom-1 left-1 z-30 flex flex-col top-[calc(var(--uhd-inset-top,0px)+4px)] transition-[transform,opacity] duration-200 ease-out motion-reduce:transition-none",
|
|
25479
|
+
/** The dock while it opens or folds (and while folded): slid out to the left, faded. */
|
|
25480
|
+
dockAway: "pointer-events-none -translate-x-[calc(100%+8px)] opacity-0",
|
|
25481
|
+
panel: "relative flex min-h-0 flex-1 flex-col overflow-hidden rounded-panel border border-line bg-surface font-ui text-fg shadow-panel outline outline-1 -outline-offset-1 outline-contrast",
|
|
25482
|
+
/**
|
|
25483
|
+
* The folded panel: the icon alone, floating over the canvas at the card's
|
|
25484
|
+
* corner (no border, face or shadow of its own), that opens it again. On
|
|
25485
|
+
* hover it takes a soft rounded fill with a faint glow, in the theme's
|
|
25486
|
+
* toolbar hover colour (high contrast: a dashed outline instead). It fades
|
|
25487
|
+
* in as the card leaves and out as it comes.
|
|
25488
|
+
*/
|
|
25489
|
+
folded: "uhd-hierarchy-reopen absolute left-1 z-30 top-[calc(var(--uhd-inset-top,0px)+4px)] grid size-8 cursor-pointer place-items-center rounded-md border-0 bg-transparent p-0 text-fg-muted transition-[opacity,background-color,color,box-shadow] duration-200 ease-out motion-reduce:transition-none hover:bg-hover hover:text-fg hover:shadow-[0_0_10px_1px_var(--uhd-hover)] hover:outline hover:outline-1 hover:outline-dashed hover:-outline-offset-1 hover:outline-contrast-active focus-visible:outline focus-visible:outline-1 focus-visible:-outline-offset-1 focus-visible:outline-focus",
|
|
25490
|
+
/** The button while it fades in or out (and while the panel is open). */
|
|
25491
|
+
foldedAway: "pointer-events-none opacity-0",
|
|
25009
25492
|
header: "flex h-8 shrink-0 items-center gap-0.5 pr-1 pl-3",
|
|
25010
25493
|
title: "min-w-0 flex-1 truncate font-label text-[11px] tracking-[0.08em] text-fg-muted uppercase",
|
|
25011
25494
|
filterBox: "mx-2 mb-1.5 flex h-7 shrink-0 items-center gap-1.5 rounded-md border border-line bg-sunken px-2 focus-within:outline focus-within:outline-1 focus-within:-outline-offset-1 focus-within:outline-focus",
|
|
@@ -25070,7 +25553,8 @@ function ViewerHierarchy({ state: given, onStateChange, onOpenChange, command, r
|
|
|
25070
25553
|
c.diagnostics,
|
|
25071
25554
|
c.hostDiagnostics
|
|
25072
25555
|
]);
|
|
25073
|
-
const
|
|
25556
|
+
const level = c.drill.join("/");
|
|
25557
|
+
const shown = useMemo(() => groupWiring(tree, level), [tree, level]);
|
|
25074
25558
|
const index = useMemo(() => hierarchyIndex(shown), [shown]);
|
|
25075
25559
|
const wiring = useMemo(() => new Set(index.get("#wiring")?.children.map((n) => n.path) ?? []), [index]);
|
|
25076
25560
|
const legend = useMemo(() => markLegend(tree), [tree]);
|
|
@@ -25085,8 +25569,7 @@ function ViewerHierarchy({ state: given, onStateChange, onOpenChange, command, r
|
|
|
25085
25569
|
shut
|
|
25086
25570
|
]);
|
|
25087
25571
|
const rows = useMemo(() => visibleRows(filtered.nodes, open), [filtered, open]);
|
|
25088
|
-
const
|
|
25089
|
-
const selected = c.view === "3d" ? c.cadSelection?.kind === "node" && !c.cadSelection.id.includes("#") ? c.cadSelection.id : void 0 : selectedPath(c.drill, c.selection);
|
|
25572
|
+
const selected = c.view === "3d" ? c.cadSelection?.kind === "node" && !c.cadSelection.id.includes("#") ? c.cadSelection.id : void 0 : selectedRow(c.drill, c.vm, c.selection);
|
|
25090
25573
|
const together = useMemo(() => new Set(c.view === "3d" ? [] : c.group.map((g) => fullId(c.drill, g))), [
|
|
25091
25574
|
c.view,
|
|
25092
25575
|
c.group,
|
|
@@ -25226,38 +25709,48 @@ function ViewerHierarchy({ state: given, onStateChange, onOpenChange, command, r
|
|
|
25226
25709
|
if (menuNode && !menuNode.group) {
|
|
25227
25710
|
const node = menuNode;
|
|
25228
25711
|
menuItems.push({
|
|
25229
|
-
label: "
|
|
25712
|
+
label: "Select",
|
|
25713
|
+
icon: "mouse-pointer-2",
|
|
25230
25714
|
run: () => select(node.path)
|
|
25231
25715
|
});
|
|
25232
25716
|
if (node.drillable) menuItems.push({
|
|
25233
|
-
label: "
|
|
25717
|
+
label: "Open as canvas",
|
|
25718
|
+
icon: "layers",
|
|
25234
25719
|
run: () => drill(node)
|
|
25235
25720
|
});
|
|
25236
25721
|
if (node.drillable && node.path && c.hostActions.openModule) menuItems.push({
|
|
25237
|
-
label: "
|
|
25722
|
+
label: "Open in new tab",
|
|
25723
|
+
icon: "square-arrow-out-up-right",
|
|
25238
25724
|
run: () => c.hostActions.openModule(node.path)
|
|
25239
25725
|
});
|
|
25240
25726
|
if (c.hostActions.openSource) menuItems.push({
|
|
25241
|
-
label: "
|
|
25727
|
+
label: "Open source",
|
|
25728
|
+
icon: "file-code",
|
|
25242
25729
|
run: () => c.hostActions.openSource(node.defId, node.path || void 0)
|
|
25243
25730
|
});
|
|
25244
25731
|
if (node.path && c.hostActions.inspect) menuItems.push({
|
|
25245
|
-
label: "
|
|
25732
|
+
label: "Inspect",
|
|
25733
|
+
icon: "scan-search",
|
|
25246
25734
|
run: () => c.hostActions.inspect(node.path, node.defId)
|
|
25247
25735
|
});
|
|
25248
25736
|
if (node.children.length) {
|
|
25249
25737
|
const below = [...hierarchyIndex([node]).values()].filter((n) => n.children.length).map((n) => n.path);
|
|
25250
25738
|
const allOpen = below.every((p) => expanded.has(p));
|
|
25251
25739
|
menuItems.push(allOpen ? {
|
|
25252
|
-
label: "
|
|
25740
|
+
label: "Collapse all below",
|
|
25741
|
+
icon: "chevrons-down-up",
|
|
25742
|
+
separator: true,
|
|
25253
25743
|
run: () => setExpanded(new Set([...expanded].filter((p) => !below.includes(p))))
|
|
25254
25744
|
} : {
|
|
25255
|
-
label: "
|
|
25745
|
+
label: "Expand all below",
|
|
25746
|
+
icon: "chevrons-up-down",
|
|
25747
|
+
separator: true,
|
|
25256
25748
|
run: () => setExpanded(/* @__PURE__ */ new Set([...expanded, ...below]))
|
|
25257
25749
|
});
|
|
25258
25750
|
}
|
|
25259
25751
|
if (typeof navigator !== "undefined" && navigator.clipboard) menuItems.push({
|
|
25260
|
-
label: "
|
|
25752
|
+
label: "Copy path",
|
|
25753
|
+
icon: "copy",
|
|
25261
25754
|
run: () => void navigator.clipboard.writeText(node.path || node.defId).catch(() => void 0)
|
|
25262
25755
|
});
|
|
25263
25756
|
}
|
|
@@ -25299,13 +25792,45 @@ function ViewerHierarchy({ state: given, onStateChange, onOpenChange, command, r
|
|
|
25299
25792
|
if (wasWide.current || kept.open) autoFolded.current = autoFolded.current && !kept.open;
|
|
25300
25793
|
}, [kept.open]);
|
|
25301
25794
|
const shownWidth = clampWidth(kept.width, Math.max(HIERARCHY_WIDTH.min, viewWidth * .6));
|
|
25302
|
-
const
|
|
25795
|
+
const motion = useFold(kept.open);
|
|
25796
|
+
const reopen = useFold(!kept.open);
|
|
25797
|
+
const foldRef = useRef(null);
|
|
25798
|
+
const reopenRef = useRef(null);
|
|
25799
|
+
const cardRef = useRef(null);
|
|
25800
|
+
const wasOpenForFocus = useRef(kept.open);
|
|
25801
|
+
const focusFrom = useRef(null);
|
|
25802
|
+
if (wasOpenForFocus.current !== kept.open && typeof document !== "undefined") {
|
|
25803
|
+
const active = document.activeElement;
|
|
25804
|
+
focusFrom.current = !active ? null : cardRef.current?.contains(active) ? "card" : active === reopenRef.current ? "reopen" : null;
|
|
25805
|
+
}
|
|
25806
|
+
useLayoutEffect(() => {
|
|
25807
|
+
if (wasOpenForFocus.current === kept.open) return;
|
|
25808
|
+
wasOpenForFocus.current = kept.open;
|
|
25809
|
+
const from = focusFrom.current;
|
|
25810
|
+
focusFrom.current = null;
|
|
25811
|
+
if (!kept.open && from === "card") reopenRef.current?.focus();
|
|
25812
|
+
else if (kept.open && from === "reopen") foldRef.current?.focus();
|
|
25813
|
+
}, [kept.open]);
|
|
25814
|
+
const docked = kept.open ? 4 + shownWidth + 4 : 0;
|
|
25303
25815
|
useLayoutEffect(() => {
|
|
25304
25816
|
const parent = dock.current?.parentElement;
|
|
25305
25817
|
if (!parent) return;
|
|
25306
25818
|
parent.style.setProperty("--uhd-dock-left", `${docked}px`);
|
|
25307
25819
|
return () => void parent.style.removeProperty("--uhd-dock-left");
|
|
25308
25820
|
}, [docked]);
|
|
25821
|
+
const wasOpen = useRef(kept.open);
|
|
25822
|
+
useLayoutEffect(() => {
|
|
25823
|
+
if (wasOpen.current === kept.open) return;
|
|
25824
|
+
wasOpen.current = kept.open;
|
|
25825
|
+
const parent = dock.current?.parentElement;
|
|
25826
|
+
if (!parent) return;
|
|
25827
|
+
parent.classList.add("uhd-dock-moving");
|
|
25828
|
+
const t = setTimeout(() => parent.classList.remove("uhd-dock-moving"), 240);
|
|
25829
|
+
return () => {
|
|
25830
|
+
clearTimeout(t);
|
|
25831
|
+
parent.classList.remove("uhd-dock-moving");
|
|
25832
|
+
};
|
|
25833
|
+
}, [kept.open]);
|
|
25309
25834
|
const room = () => Math.max(HIERARCHY_WIDTH.min, (dock.current?.parentElement?.clientWidth ?? window.innerWidth) * .6);
|
|
25310
25835
|
const onResizeStart = (e) => {
|
|
25311
25836
|
if (e.button !== 0) return;
|
|
@@ -25337,185 +25862,216 @@ function ViewerHierarchy({ state: given, onStateChange, onOpenChange, command, r
|
|
|
25337
25862
|
const count = hierarchyIndex(tree).size;
|
|
25338
25863
|
const rootLabel = tree[0]?.label ?? "System";
|
|
25339
25864
|
const L = HIERARCHY_LOOK;
|
|
25340
|
-
if (!kept.open) return /* @__PURE__ */ jsx("div", {
|
|
25341
|
-
ref: dock,
|
|
25342
|
-
className: cx(L.dock, className),
|
|
25343
|
-
style: { width: 36 },
|
|
25344
|
-
"data-hierarchy": "folded",
|
|
25345
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
25346
|
-
className: L.rail,
|
|
25347
|
-
children: [/* @__PURE__ */ jsx(IconButton, {
|
|
25348
|
-
icon: "panel-left-open",
|
|
25349
|
-
size: "sm",
|
|
25350
|
-
label: "Show the hierarchy",
|
|
25351
|
-
tooltipSide: "right",
|
|
25352
|
-
"aria-expanded": false,
|
|
25353
|
-
"aria-controls": "uhd-hierarchy",
|
|
25354
|
-
onClick: () => setKept({ open: true })
|
|
25355
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
25356
|
-
type: "button",
|
|
25357
|
-
onClick: () => setKept({ open: true }),
|
|
25358
|
-
className: "mt-1 cursor-pointer border-0 bg-transparent p-0 font-label text-[10px] tracking-[0.12em] text-fg-muted uppercase [writing-mode:vertical-rl] hover:text-fg",
|
|
25359
|
-
tabIndex: -1,
|
|
25360
|
-
"aria-hidden": true,
|
|
25361
|
-
children: "Hierarchy"
|
|
25362
|
-
})]
|
|
25363
|
-
})
|
|
25364
|
-
});
|
|
25365
25865
|
return /* @__PURE__ */ jsxs("div", {
|
|
25366
25866
|
ref: dock,
|
|
25367
|
-
className:
|
|
25368
|
-
|
|
25369
|
-
|
|
25370
|
-
|
|
25371
|
-
|
|
25372
|
-
|
|
25373
|
-
|
|
25374
|
-
|
|
25375
|
-
|
|
25376
|
-
|
|
25377
|
-
|
|
25378
|
-
|
|
25379
|
-
|
|
25380
|
-
|
|
25381
|
-
|
|
25382
|
-
|
|
25383
|
-
|
|
25384
|
-
|
|
25385
|
-
|
|
25386
|
-
|
|
25387
|
-
|
|
25388
|
-
|
|
25389
|
-
|
|
25390
|
-
|
|
25391
|
-
|
|
25392
|
-
|
|
25393
|
-
|
|
25394
|
-
|
|
25395
|
-
|
|
25396
|
-
|
|
25397
|
-
|
|
25398
|
-
|
|
25399
|
-
|
|
25400
|
-
|
|
25401
|
-
|
|
25402
|
-
|
|
25403
|
-
|
|
25404
|
-
|
|
25405
|
-
|
|
25406
|
-
|
|
25407
|
-
|
|
25408
|
-
|
|
25409
|
-
|
|
25410
|
-
|
|
25411
|
-
|
|
25412
|
-
|
|
25413
|
-
|
|
25414
|
-
|
|
25415
|
-
|
|
25416
|
-
|
|
25417
|
-
|
|
25418
|
-
|
|
25419
|
-
|
|
25420
|
-
|
|
25421
|
-
|
|
25422
|
-
|
|
25423
|
-
|
|
25424
|
-
|
|
25425
|
-
|
|
25426
|
-
|
|
25427
|
-
|
|
25428
|
-
|
|
25429
|
-
|
|
25430
|
-
|
|
25431
|
-
|
|
25432
|
-
|
|
25433
|
-
|
|
25434
|
-
|
|
25435
|
-
|
|
25436
|
-
|
|
25437
|
-
|
|
25438
|
-
name: "x",
|
|
25867
|
+
className: "contents",
|
|
25868
|
+
children: [reopen.mounted && /* @__PURE__ */ jsx("button", {
|
|
25869
|
+
ref: reopenRef,
|
|
25870
|
+
type: "button",
|
|
25871
|
+
"aria-label": "Show hierarchy",
|
|
25872
|
+
"aria-expanded": false,
|
|
25873
|
+
"aria-controls": "uhd-hierarchy",
|
|
25874
|
+
"data-tooltip": "Show hierarchy",
|
|
25875
|
+
"data-tooltip-side": "right",
|
|
25876
|
+
"data-hierarchy-reopen": "",
|
|
25877
|
+
inert: kept.open || void 0,
|
|
25878
|
+
onClick: () => setKept({ open: true }),
|
|
25879
|
+
className: cx(L.folded, !reopen.shown && L.foldedAway, className),
|
|
25880
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
25881
|
+
name: "panel-left-open",
|
|
25882
|
+
size: 16,
|
|
25883
|
+
strokeWidth: 1.75,
|
|
25884
|
+
"aria-hidden": true
|
|
25885
|
+
})
|
|
25886
|
+
}), motion.mounted && /* @__PURE__ */ jsxs("div", {
|
|
25887
|
+
ref: cardRef,
|
|
25888
|
+
className: cx(L.dock, !motion.shown && L.dockAway, className),
|
|
25889
|
+
style: { width: shownWidth },
|
|
25890
|
+
"data-hierarchy": kept.open ? "open" : "folded",
|
|
25891
|
+
inert: !kept.open || void 0,
|
|
25892
|
+
"aria-hidden": !kept.open || void 0,
|
|
25893
|
+
children: [
|
|
25894
|
+
/* @__PURE__ */ jsxs("section", {
|
|
25895
|
+
id: "uhd-hierarchy",
|
|
25896
|
+
"aria-label": "Hierarchy",
|
|
25897
|
+
className: L.panel,
|
|
25898
|
+
children: [
|
|
25899
|
+
/* @__PURE__ */ jsxs("header", {
|
|
25900
|
+
className: L.header,
|
|
25901
|
+
children: [
|
|
25902
|
+
/* @__PURE__ */ jsxs("span", {
|
|
25903
|
+
className: L.title,
|
|
25904
|
+
children: ["Hierarchy", /* @__PURE__ */ jsxs("span", {
|
|
25905
|
+
className: "text-fg-faint",
|
|
25906
|
+
children: [" · ", count]
|
|
25907
|
+
})]
|
|
25908
|
+
}),
|
|
25909
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
25910
|
+
icon: "list-filter",
|
|
25911
|
+
size: "sm",
|
|
25912
|
+
label: "Filter modules",
|
|
25913
|
+
pressed: Boolean(filter),
|
|
25914
|
+
onClick: () => filterRef.current?.focus()
|
|
25915
|
+
}),
|
|
25916
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
25917
|
+
icon: "chevrons-down-up",
|
|
25918
|
+
size: "sm",
|
|
25919
|
+
label: "Collapse all",
|
|
25920
|
+
onClick: () => setExpanded(/* @__PURE__ */ new Set([""]))
|
|
25921
|
+
}),
|
|
25922
|
+
/* @__PURE__ */ jsx(IconButton, {
|
|
25923
|
+
ref: foldRef,
|
|
25924
|
+
icon: "panel-left-close",
|
|
25925
|
+
size: "sm",
|
|
25926
|
+
label: "Hide hierarchy",
|
|
25927
|
+
"aria-expanded": true,
|
|
25928
|
+
"aria-controls": "uhd-hierarchy",
|
|
25929
|
+
onClick: () => setKept({ open: false })
|
|
25930
|
+
})
|
|
25931
|
+
]
|
|
25932
|
+
}),
|
|
25933
|
+
/* @__PURE__ */ jsxs("label", {
|
|
25934
|
+
className: L.filterBox,
|
|
25935
|
+
children: [
|
|
25936
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
25937
|
+
name: "search",
|
|
25439
25938
|
size: 12,
|
|
25939
|
+
strokeWidth: 1.75,
|
|
25940
|
+
className: "shrink-0 text-fg-faint",
|
|
25440
25941
|
"aria-hidden": true
|
|
25942
|
+
}),
|
|
25943
|
+
/* @__PURE__ */ jsx("input", {
|
|
25944
|
+
ref: filterRef,
|
|
25945
|
+
type: "text",
|
|
25946
|
+
value: filter,
|
|
25947
|
+
onChange: (e) => setFilter(e.target.value),
|
|
25948
|
+
onKeyDown: onFilterKey,
|
|
25949
|
+
placeholder: "Filter modules",
|
|
25950
|
+
"aria-label": "Filter the hierarchy",
|
|
25951
|
+
"aria-controls": "uhd-hierarchy-tree",
|
|
25952
|
+
spellCheck: false,
|
|
25953
|
+
className: "min-w-0 flex-1 border-0 bg-transparent p-0 font-ui text-[12px] text-fg outline-none placeholder:text-fg-faint"
|
|
25954
|
+
}),
|
|
25955
|
+
filter && /* @__PURE__ */ jsx("button", {
|
|
25956
|
+
type: "button",
|
|
25957
|
+
"aria-label": "Clear the filter",
|
|
25958
|
+
"data-tooltip": "Clear the filter",
|
|
25959
|
+
onClick: () => (setFilter(""), filterRef.current?.focus()),
|
|
25960
|
+
className: "grid size-5 cursor-pointer place-items-center rounded border-0 bg-transparent p-0 text-fg-muted hover:bg-hover hover:text-fg",
|
|
25961
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
25962
|
+
name: "x",
|
|
25963
|
+
size: 12,
|
|
25964
|
+
"aria-hidden": true
|
|
25965
|
+
})
|
|
25441
25966
|
})
|
|
25967
|
+
]
|
|
25968
|
+
}),
|
|
25969
|
+
/* @__PURE__ */ jsx(ScrollArea, {
|
|
25970
|
+
className: "min-h-0 flex-1",
|
|
25971
|
+
axis: "vertical",
|
|
25972
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
25973
|
+
ref: treeRef,
|
|
25974
|
+
id: "uhd-hierarchy-tree",
|
|
25975
|
+
role: "tree",
|
|
25976
|
+
"aria-label": `Hierarchy of ${rootLabel}`,
|
|
25977
|
+
onKeyDown: onTreeKey,
|
|
25978
|
+
className: "pb-1",
|
|
25979
|
+
children: [rows.map((r) => /* @__PURE__ */ jsx(Row, {
|
|
25980
|
+
row: r,
|
|
25981
|
+
focus: focus === r.node.path,
|
|
25982
|
+
selected: selected === r.node.path || together.has(r.node.path),
|
|
25983
|
+
current: level === r.node.path,
|
|
25984
|
+
match: filtered.matches.has(r.node.path),
|
|
25985
|
+
dim: filtered.matches.size > 0 && !filtered.matches.has(r.node.path) && !r.node.group,
|
|
25986
|
+
attributes: r.node.group ? void 0 : rowAttributes?.(r.node),
|
|
25987
|
+
onSelect: select,
|
|
25988
|
+
onDrill: drill,
|
|
25989
|
+
onToggle: toggle,
|
|
25990
|
+
onContext: onRowContext
|
|
25991
|
+
}, r.node.path)), !rows.length && /* @__PURE__ */ jsxs("p", {
|
|
25992
|
+
role: "status",
|
|
25993
|
+
className: "m-0 px-3 py-2 text-[12px] text-fg-muted",
|
|
25994
|
+
children: [
|
|
25995
|
+
"Nothing matches “",
|
|
25996
|
+
filter,
|
|
25997
|
+
"”."
|
|
25998
|
+
]
|
|
25999
|
+
})]
|
|
25442
26000
|
})
|
|
25443
|
-
|
|
25444
|
-
|
|
25445
|
-
|
|
25446
|
-
|
|
25447
|
-
|
|
25448
|
-
|
|
25449
|
-
|
|
25450
|
-
|
|
25451
|
-
|
|
25452
|
-
|
|
25453
|
-
|
|
25454
|
-
|
|
25455
|
-
children: [rows.map((r) => /* @__PURE__ */ jsx(Row, {
|
|
25456
|
-
row: r,
|
|
25457
|
-
focus: focus === r.node.path,
|
|
25458
|
-
selected: selected === r.node.path || together.has(r.node.path),
|
|
25459
|
-
current: level === r.node.path,
|
|
25460
|
-
match: filtered.matches.has(r.node.path),
|
|
25461
|
-
dim: filtered.matches.size > 0 && !filtered.matches.has(r.node.path) && !r.node.group,
|
|
25462
|
-
attributes: r.node.group ? void 0 : rowAttributes?.(r.node),
|
|
25463
|
-
onSelect: select,
|
|
25464
|
-
onDrill: drill,
|
|
25465
|
-
onToggle: toggle,
|
|
25466
|
-
onContext: onRowContext
|
|
25467
|
-
}, r.node.path)), !rows.length && /* @__PURE__ */ jsxs("p", {
|
|
25468
|
-
role: "status",
|
|
25469
|
-
className: "m-0 px-3 py-2 text-[12px] text-fg-muted",
|
|
25470
|
-
children: [
|
|
25471
|
-
"Nothing matches “",
|
|
25472
|
-
filter,
|
|
25473
|
-
"”."
|
|
25474
|
-
]
|
|
25475
|
-
})]
|
|
26001
|
+
}),
|
|
26002
|
+
legend.length > 0 && /* @__PURE__ */ jsx("footer", {
|
|
26003
|
+
className: L.legend,
|
|
26004
|
+
"aria-label": "Part status",
|
|
26005
|
+
children: legend.map((l) => /* @__PURE__ */ jsxs("span", {
|
|
26006
|
+
className: "flex items-center gap-1.5",
|
|
26007
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
26008
|
+
"aria-hidden": true,
|
|
26009
|
+
className: "uhd-tree-mark",
|
|
26010
|
+
"data-tone": l.tone
|
|
26011
|
+
}), l.label]
|
|
26012
|
+
}, l.tone))
|
|
25476
26013
|
})
|
|
25477
|
-
|
|
25478
|
-
|
|
25479
|
-
|
|
25480
|
-
|
|
25481
|
-
|
|
25482
|
-
|
|
25483
|
-
|
|
25484
|
-
|
|
25485
|
-
|
|
25486
|
-
|
|
25487
|
-
|
|
25488
|
-
|
|
26014
|
+
]
|
|
26015
|
+
}),
|
|
26016
|
+
/* @__PURE__ */ jsx("div", {
|
|
26017
|
+
role: "separator",
|
|
26018
|
+
"aria-orientation": "vertical",
|
|
26019
|
+
"aria-label": "Resize the hierarchy",
|
|
26020
|
+
"aria-valuemin": HIERARCHY_WIDTH.min,
|
|
26021
|
+
"aria-valuemax": HIERARCHY_WIDTH.max,
|
|
26022
|
+
"aria-valuenow": shownWidth,
|
|
26023
|
+
"aria-controls": "uhd-hierarchy",
|
|
26024
|
+
tabIndex: 0,
|
|
26025
|
+
onPointerDown: onResizeStart,
|
|
26026
|
+
onKeyDown: onResizeKey,
|
|
26027
|
+
onDoubleClick: () => setKept({ width: HIERARCHY_WIDTH.default }),
|
|
26028
|
+
className: "group absolute inset-y-2 -right-1 z-10 w-2 cursor-col-resize touch-none focus-visible:outline-none",
|
|
26029
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
26030
|
+
"aria-hidden": true,
|
|
26031
|
+
className: "absolute inset-y-0 left-[3px] w-0.5 bg-transparent transition-colors group-hover:bg-focus group-focus-visible:bg-focus group-active:bg-focus"
|
|
25489
26032
|
})
|
|
25490
|
-
|
|
25491
|
-
|
|
25492
|
-
|
|
25493
|
-
|
|
25494
|
-
|
|
25495
|
-
|
|
25496
|
-
"aria-valuemin": HIERARCHY_WIDTH.min,
|
|
25497
|
-
"aria-valuemax": HIERARCHY_WIDTH.max,
|
|
25498
|
-
"aria-valuenow": shownWidth,
|
|
25499
|
-
"aria-controls": "uhd-hierarchy",
|
|
25500
|
-
tabIndex: 0,
|
|
25501
|
-
onPointerDown: onResizeStart,
|
|
25502
|
-
onKeyDown: onResizeKey,
|
|
25503
|
-
onDoubleClick: () => setKept({ width: HIERARCHY_WIDTH.default }),
|
|
25504
|
-
className: "group absolute top-[var(--uhd-inset-top,0px)] -right-1 bottom-0 z-10 w-2 cursor-col-resize touch-none focus-visible:outline-none",
|
|
25505
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
25506
|
-
"aria-hidden": true,
|
|
25507
|
-
className: "absolute inset-y-0 left-[3px] w-0.5 bg-transparent transition-colors group-hover:bg-focus group-focus-visible:bg-focus group-active:bg-focus"
|
|
26033
|
+
}),
|
|
26034
|
+
menuNode && ownMenu && /* @__PURE__ */ jsx(NodeMenu, {
|
|
26035
|
+
x: menu.x,
|
|
26036
|
+
y: menu.y,
|
|
26037
|
+
items: menuItems,
|
|
26038
|
+
onClose: closeMenu
|
|
25508
26039
|
})
|
|
25509
|
-
|
|
25510
|
-
|
|
25511
|
-
x: menu.x,
|
|
25512
|
-
y: menu.y,
|
|
25513
|
-
items: menuItems,
|
|
25514
|
-
onClose: closeMenu
|
|
25515
|
-
})
|
|
25516
|
-
]
|
|
26040
|
+
]
|
|
26041
|
+
})]
|
|
25517
26042
|
});
|
|
25518
26043
|
}
|
|
26044
|
+
/**
|
|
26045
|
+
* The way in and out of the card (and of the button that opens it): mounted
|
|
26046
|
+
* while open and while it leaves, and shown (in place) one frame after it
|
|
26047
|
+
* mounts, so the transition runs both ways. With reduced motion it simply
|
|
26048
|
+
* appears and goes.
|
|
26049
|
+
*/
|
|
26050
|
+
function useFold(open) {
|
|
26051
|
+
const [mounted, setMounted] = useState(open);
|
|
26052
|
+
const [shown, setShown] = useState(open);
|
|
26053
|
+
useEffect(() => {
|
|
26054
|
+
const still = typeof window === "undefined" || window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
26055
|
+
if (open) {
|
|
26056
|
+
setMounted(true);
|
|
26057
|
+
if (still) return setShown(true);
|
|
26058
|
+
let inner = 0;
|
|
26059
|
+
const outer = requestAnimationFrame(() => inner = requestAnimationFrame(() => setShown(true)));
|
|
26060
|
+
return () => {
|
|
26061
|
+
cancelAnimationFrame(outer);
|
|
26062
|
+
cancelAnimationFrame(inner);
|
|
26063
|
+
};
|
|
26064
|
+
}
|
|
26065
|
+
setShown(false);
|
|
26066
|
+
if (still) return setMounted(false);
|
|
26067
|
+
const t = setTimeout(() => setMounted(false), 200);
|
|
26068
|
+
return () => clearTimeout(t);
|
|
26069
|
+
}, [open]);
|
|
26070
|
+
return {
|
|
26071
|
+
mounted: mounted || open,
|
|
26072
|
+
shown: shown && open
|
|
26073
|
+
};
|
|
26074
|
+
}
|
|
25519
26075
|
var Row = memo(function Row({ row, focus, selected, current, match, dim, attributes, onSelect, onDrill, onToggle, onContext }) {
|
|
25520
26076
|
const n = row.node;
|
|
25521
26077
|
const L = HIERARCHY_LOOK;
|
|
@@ -25610,7 +26166,13 @@ var Row = memo(function Row({ row, focus, selected, current, match, dim, attribu
|
|
|
25610
26166
|
]
|
|
25611
26167
|
});
|
|
25612
26168
|
});
|
|
25613
|
-
/**
|
|
26169
|
+
/**
|
|
26170
|
+
* A toolbar button that opens and folds the panel from a host's header.
|
|
26171
|
+
*
|
|
26172
|
+
* @deprecated The panel has its own fold button and, folded, its own button to
|
|
26173
|
+
* open it again (PB-1070); a host needs no toggle of its own. Kept for hosts
|
|
26174
|
+
* written against 0.2.0; it will be removed in a later minor release.
|
|
26175
|
+
*/
|
|
25614
26176
|
function HierarchyToggle({ open, onClick, disabled, className }) {
|
|
25615
26177
|
return /* @__PURE__ */ jsxs("button", {
|
|
25616
26178
|
type: "button",
|
|
@@ -25776,7 +26338,7 @@ function SelectionDetails({ bundle, definitions, target, resolveArtifact = NO_FI
|
|
|
25776
26338
|
bundle
|
|
25777
26339
|
]);
|
|
25778
26340
|
const named = useMemo(() => found ? levelNames(found.vm, found.levelDef, lookup) : void 0, [found, lookup]);
|
|
25779
|
-
if (!found || !found.node && !found.link && !found.derived) return /* @__PURE__ */ jsx(Fragment, { children: missing });
|
|
26341
|
+
if (!found || !found.node && !found.link && !found.derived) return /* @__PURE__ */ jsx(Fragment$1, { children: missing });
|
|
25780
26342
|
const { vm, drill, node, link, derived } = found;
|
|
25781
26343
|
const defFor = (id) => id ? lookup(id) : void 0;
|
|
25782
26344
|
const select = (s) => s && onSelect?.({
|
|
@@ -25851,11 +26413,10 @@ function SelectionDetails({ bundle, definitions, target, resolveArtifact = NO_FI
|
|
|
25851
26413
|
onToggleExpand: () => void 0,
|
|
25852
26414
|
onSelect: select,
|
|
25853
26415
|
board: boardFor(node),
|
|
25854
|
-
artifacts: /* @__PURE__ */ jsx(
|
|
26416
|
+
artifacts: /* @__PURE__ */ jsx(ArtifactsSection, {
|
|
25855
26417
|
def: defFor(node.defId),
|
|
25856
|
-
lookup: defFor,
|
|
25857
26418
|
resolve: resolveArtifact,
|
|
25858
|
-
appearance,
|
|
26419
|
+
appearance: node.defId ? appearance?.[node.defId] : void 0,
|
|
25859
26420
|
titled: false
|
|
25860
26421
|
}, node.defId),
|
|
25861
26422
|
lookup: defFor,
|
|
@@ -26043,6 +26604,6 @@ function resolveTheme(option) {
|
|
|
26043
26604
|
return staticTheme(completeTheme(option));
|
|
26044
26605
|
}
|
|
26045
26606
|
//#endregion
|
|
26046
|
-
export { ARTIFACT_GROUPS, ArtifactCard, ArtifactCards, ArtifactGrid, Badge, CARD_LOOK, CARD_W, CARD_W_MAX, CLASSIFICATIONS, CLASSIFICATION_OPTIONS, DARK_DATA_TOKENS, DERIVED, DETAIL_OPTIONS, DRC_TOKENS, DetailsSection, DiagramCanvas, DiagramLegend, DiagramLegendBody, DiagramLegendItems, DiagramToolbar, EmptyState, EvidenceSection, FittedLegend, KIND_LABEL as HIERARCHY_KIND_LABEL, HIERARCHY_LOOK, HIERARCHY_WIDTH, PREFIX as HOST_MESSAGE_PREFIX, HierarchyToggle, HostContext, Icon, IconButton, InspectorPanel, InterfaceCard, InterfaceCards, IsolationClear, KIND_ICON, KeyValues, LIGHT_DATA_TOKENS, Legend, LegendItem, LegendSwatches, LegendToolbarButton, MissingNotice, ModelView, PropertyRow, RAIL_WIDTH, SECTION_LOOK, SLOT_COLOR, ScenarioBanner, Scene3D, ScrollArea, Section, Sections, SelectionDetails, SelectionKey, SlotGlyph, StatusDot, TOKEN_NAMES, TOOL_OPTIONS, ThemeProvider, ToggleGroup, ToolToggle, Toolbar, ToolbarSeparator, Tooltips, UhdViewer, ViewButtons, ViewerBoundary, ViewerHierarchy, ViewerInspector, ViewerNodeMenu, ViewerProvider, WIRING_PATH, ancestorsOf, applySelectChanges, applyTheme, artifactCard, artifactCards, buildHierarchy, canvasCommand, cardWidth, checkFindings, classKey, classifyArtifact, colorFor, completeTheme, cx, defaultDark, defaultLight, defaultTheme, defaultThemeAdapter, defineTheme, drillInto, evidenceSourceCards, filterHierarchy, firstView, groupArtifactCards, groupSlots, groupWiring, hierarchyIndex, humanize, initialInteraction, interactionProps, interactionReducer, interfaceSlots, isInternalArtifact, isPlaceholder, isViewerEvent, isolate, keptInspectorState, kindOf, labelIsCut, legendFor, legendRoom, legendStage, levelNames, linkKeys, markLegend, mergeFormats, mix, navTarget, onNavKey, openAction, originAllowed, panelState, paramValue, parseHostMessage, pickTheme, presentKeys, readToken, renderViewer, resolveTheme, revealPaths, rowTarget, selectedPath, sentence, slotSummary, staticTheme, themeCss, themeDeclarations, toggleIsolated, token, tokenColor, tokenVar, tolerantSystem, treeKey, useExpandedCards, useSectionOpen, useShowAll, useTheme, useViewer, useViewerController, useViewerSource, visibleRows, vscodeScheme, vscodeTheme, vscodeThemeAdapter, walkHierarchy };
|
|
26607
|
+
export { ARTIFACT_GROUPS, ArtifactCard, ArtifactCards, ArtifactGrid, Badge, CARD_LOOK, CARD_W, CARD_W_MAX, CLASSIFICATIONS, CLASSIFICATION_OPTIONS, ClampedText, DARK_DATA_TOKENS, DERIVED, DETAIL_OPTIONS, DRC_TOKENS, DetailsSection, DiagramCanvas, DiagramLegend, DiagramLegendBody, DiagramLegendItems, DiagramToolbar, EmptyState, EvidenceSection, FittedLegend, KIND_LABEL as HIERARCHY_KIND_LABEL, HIERARCHY_LOOK, HIERARCHY_WIDTH, PREFIX as HOST_MESSAGE_PREFIX, HierarchyToggle, HostContext, Icon, IconButton, InspectorPanel, InterfaceCard, InterfaceCards, IsolationClear, KIND_ICON, KeyValues, LEGEND_SHORT, LIGHT_DATA_TOKENS, LIST_STEP, Legend, LegendFold, LegendItem, LegendSwatches, LegendTab, LegendToolbarButton, MissingNotice, ModelView, PropertyRow, RAIL_WIDTH, SECTION_LOOK, SLOT_COLOR, ScenarioBanner, Scene3D, ScrollArea, Section, Sections, SelectionDetails, SelectionKey, SlotGlyph, StatusDot, TOKEN_NAMES, TOOL_OPTIONS, ThemeProvider, ToggleGroup, ToolToggle, Toolbar, ToolbarSeparator, Tooltips, UhdViewer, ViewButtons, ViewerBoundary, ViewerHierarchy, ViewerInspector, ViewerNodeMenu, ViewerProvider, WIRING_PATH, ancestorsOf, applySelectChanges, applyTheme, artifactCard, artifactCards, buildHierarchy, canvasCommand, cardWidth, checkFindings, classKey, classifyArtifact, colorFor, completeTheme, cx, defaultDark, defaultLight, defaultTheme, defaultThemeAdapter, defineTheme, drillInto, evidenceSourceCards, filterHierarchy, firstView, groupArtifactCards, groupSlots, groupWiring, hierarchyIndex, humanize, initialInteraction, interactionProps, interactionReducer, interfaceSlots, isInternalArtifact, isPlaceholder, isViewerEvent, isolate, keptInspectorState, kindOf, labelIsCut, legendFolded, legendFor, legendRoom, legendStage, levelNames, linkKeys, markLegend, mergeFormats, mix, navTarget, onNavKey, openAction, originAllowed, panelState, paramValue, parseHostMessage, pickTheme, presentKeys, readToken, renderViewer, resolveTheme, revealPaths, rowTarget, selectedPath, sentence, slotSummary, staticTheme, themeCss, themeDeclarations, toggleIsolated, token, tokenColor, tokenVar, tolerantSystem, treeKey, useExpandedCards, useLoadMore, useSectionOpen, useShowAll, useTheme, useViewer, useViewerController, useViewerSource, visibleRows, vscodeScheme, vscodeTheme, vscodeThemeAdapter, walkHierarchy };
|
|
26047
26608
|
|
|
26048
26609
|
//# sourceMappingURL=index.js.map
|