@nvidia-elements/core 2.23.5 → 2.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/dist/accordion/accordion-group.js.map +1 -1
- package/dist/accordion/accordion.js.map +1 -1
- package/dist/accordion/accordion2.js +4 -4
- package/dist/alert/alert-group2.js +1 -1
- package/dist/alert/alert2.js +1 -1
- package/dist/avatar/avatar-group2.js +1 -1
- package/dist/avatar/avatar2.js +1 -1
- package/dist/badge/badge2.js +1 -1
- package/dist/breadcrumb/breadcrumb2.js +1 -1
- package/dist/bundle.d.ts +2 -0
- package/dist/bundles/index.d.ts +323 -56
- package/dist/bundles/index.js +9 -9
- package/dist/button/button2.js +1 -1
- package/dist/button-group/button-group2.js +1 -1
- package/dist/card/card2.js +4 -4
- package/dist/chat-message/chat-message2.js +1 -1
- package/dist/checkbox/checkbox-group2.js +1 -1
- package/dist/checkbox/checkbox2.js +1 -1
- package/dist/color/color2.js +1 -1
- package/dist/combobox/combobox2.js +1 -1
- package/dist/copy-button/copy-button2.js +1 -1
- package/dist/custom-elements-jsx.d.ts +167 -1
- package/dist/custom-elements-vue.d.ts +161 -1
- package/dist/custom-elements.json +5017 -268
- package/dist/dashboard/controllers/arrangement.controller.d.ts +30 -0
- package/dist/dashboard/controllers/arrangement.controller.js +68 -0
- package/dist/dashboard/controllers/arrangement.controller.js.map +1 -0
- package/dist/dashboard/controllers/command.controller.d.ts +28 -0
- package/dist/dashboard/controllers/command.controller.js +69 -0
- package/dist/dashboard/controllers/command.controller.js.map +1 -0
- package/dist/dashboard/controllers/composition.controller.d.ts +61 -0
- package/dist/dashboard/controllers/composition.controller.js +285 -0
- package/dist/dashboard/controllers/composition.controller.js.map +1 -0
- package/dist/dashboard/controllers/fullscreen.controller.d.ts +23 -0
- package/dist/dashboard/controllers/fullscreen.controller.js +46 -0
- package/dist/dashboard/controllers/fullscreen.controller.js.map +1 -0
- package/dist/dashboard/controllers/interaction.controller.d.ts +53 -0
- package/dist/dashboard/controllers/interaction.controller.js +407 -0
- package/dist/dashboard/controllers/interaction.controller.js.map +1 -0
- package/dist/dashboard/controllers/measurement.controller.d.ts +28 -0
- package/dist/dashboard/controllers/measurement.controller.js +77 -0
- package/dist/dashboard/controllers/measurement.controller.js.map +1 -0
- package/dist/dashboard/dashboard.d.ts +83 -0
- package/dist/dashboard/dashboard.examples.js +5 -0
- package/dist/dashboard/dashboard.examples.js.map +1 -0
- package/dist/dashboard/dashboard.examples.json +138 -0
- package/dist/dashboard/dashboard.js +5 -0
- package/dist/dashboard/dashboard.js.map +1 -0
- package/dist/dashboard/dashboard.types.d.ts +33 -0
- package/dist/dashboard/dashboard2.js +352 -0
- package/dist/dashboard/dashboard2.js.map +1 -0
- package/dist/dashboard/define.d.ts +10 -0
- package/dist/dashboard/define.js +9 -0
- package/dist/dashboard/define.js.map +1 -0
- package/dist/dashboard/index.d.ts +8 -0
- package/dist/dashboard/index.js +6 -0
- package/dist/dashboard/panel/panel.d.ts +88 -0
- package/dist/dashboard/panel/panel.js +5 -0
- package/dist/dashboard/panel/panel.js.map +1 -0
- package/dist/dashboard/panel/panel2.js +110 -0
- package/dist/dashboard/panel/panel2.js.map +1 -0
- package/dist/dashboard/panel-content/panel-content.d.ts +20 -0
- package/dist/dashboard/panel-content/panel-content.js +5 -0
- package/dist/dashboard/panel-content/panel-content.js.map +1 -0
- package/dist/dashboard/panel-content/panel-content2.js +22 -0
- package/dist/dashboard/panel-content/panel-content2.js.map +1 -0
- package/dist/dashboard/panel-footer/panel-footer.d.ts +25 -0
- package/dist/dashboard/panel-footer/panel-footer.js +5 -0
- package/dist/dashboard/panel-footer/panel-footer.js.map +1 -0
- package/dist/dashboard/panel-footer/panel-footer2.js +28 -0
- package/dist/dashboard/panel-footer/panel-footer2.js.map +1 -0
- package/dist/dashboard/panel-header/panel-header.d.ts +27 -0
- package/dist/dashboard/panel-header/panel-header.js +5 -0
- package/dist/dashboard/panel-header/panel-header.js.map +1 -0
- package/dist/dashboard/panel-header/panel-header2.js +28 -0
- package/dist/dashboard/panel-header/panel-header2.js.map +1 -0
- package/dist/dashboard/utils/action.utils.d.ts +17 -0
- package/dist/dashboard/utils/action.utils.js +144 -0
- package/dist/dashboard/utils/action.utils.js.map +1 -0
- package/dist/dashboard/utils/geometry.utils.d.ts +110 -0
- package/dist/dashboard/utils/geometry.utils.js +208 -0
- package/dist/dashboard/utils/geometry.utils.js.map +1 -0
- package/dist/dashboard/utils/intent.types.d.ts +67 -0
- package/dist/dashboard/utils/layout.utils.d.ts +20 -0
- package/dist/dashboard/utils/layout.utils.js +224 -0
- package/dist/dashboard/utils/layout.utils.js.map +1 -0
- package/dist/dashboard/utils/movement.utils.d.ts +7 -0
- package/dist/dashboard/utils/movement.utils.js +15 -0
- package/dist/dashboard/utils/movement.utils.js.map +1 -0
- package/dist/dashboard/utils/mutation.utils.d.ts +2 -0
- package/dist/dashboard/utils/mutation.utils.js +19 -0
- package/dist/dashboard/utils/mutation.utils.js.map +1 -0
- package/dist/dashboard/utils/packing.utils.d.ts +13 -0
- package/dist/dashboard/utils/packing.utils.js +421 -0
- package/dist/dashboard/utils/packing.utils.js.map +1 -0
- package/dist/data.html.json +141 -1
- package/dist/date/date2.js +1 -1
- package/dist/datetime/datetime2.js +1 -1
- package/dist/dialog/dialog-footer2.js +1 -1
- package/dist/dialog/dialog-header2.js +1 -1
- package/dist/dialog/dialog2.js +1 -1
- package/dist/divider/divider2.js +1 -1
- package/dist/dot/dot2.js +1 -1
- package/dist/drag-handle/drag-handle2.js +1 -1
- package/dist/drawer/drawer-content2.js +1 -1
- package/dist/drawer/drawer-footer2.js +1 -1
- package/dist/drawer/drawer-header2.js +1 -1
- package/dist/drawer/drawer2.js +1 -1
- package/dist/dropdown/dropdown-footer2.js +1 -1
- package/dist/dropdown/dropdown-header2.js +1 -1
- package/dist/dropdown/dropdown.examples.js.map +1 -1
- package/dist/dropdown/dropdown2.js +1 -1
- package/dist/dropdown-group/dropdown-group.js +1 -1
- package/dist/dropzone/dropzone2.js +1 -1
- package/dist/file/file2.js +1 -1
- package/dist/format-bytes/format-bytes2.js +1 -1
- package/dist/format-datetime/format-datetime2.js +1 -1
- package/dist/format-number/format-number2.js +1 -1
- package/dist/format-relative-time/format-relative-time2.js +1 -1
- package/dist/format-truncate/format-truncate2.js +1 -1
- package/dist/forms/control/control2.js +1 -1
- package/dist/forms/control-group/control-group2.js +1 -1
- package/dist/forms/control-message/control-message2.js +1 -1
- package/dist/gauge/gauge2.js +1 -1
- package/dist/ghost/ghost2.js +1 -1
- package/dist/grid/cell/cell2.js +1 -1
- package/dist/grid/column/column2.js +1 -1
- package/dist/grid/footer/footer2.js +1 -1
- package/dist/grid/grid.js.map +1 -1
- package/dist/grid/grid2.js +1 -1
- package/dist/grid/header/header2.js +1 -1
- package/dist/grid/placeholder/placeholder2.js +1 -1
- package/dist/grid/row/row2.js +1 -1
- package/dist/icon/icon2.js +1 -1
- package/dist/icon-button/icon-button2.js +1 -1
- package/dist/iframe/iframe2.js +1 -1
- package/dist/index.js +1 -1
- package/dist/input/input-group2.js +1 -1
- package/dist/input/input2.js +1 -1
- package/dist/internal/controllers/native-fullscreen.controller.d.ts +13 -0
- package/dist/internal/controllers/native-fullscreen.controller.js +73 -0
- package/dist/internal/controllers/native-fullscreen.controller.js.map +1 -0
- package/dist/internal/index.d.ts +1 -0
- package/dist/internal/index.js +59 -57
- package/dist/internal/index.js.map +1 -1
- package/dist/joystick/joystick2.js +1 -1
- package/dist/logo/logo2.js +1 -1
- package/dist/menu/menu-group2.js +1 -1
- package/dist/menu/menu-item2.js +1 -1
- package/dist/menu/menu2.js +1 -1
- package/dist/month/month2.js +1 -1
- package/dist/notification/notification-group2.js +1 -1
- package/dist/notification/notification2.js +1 -1
- package/dist/page/page-panel/page-panel-content2.js +1 -1
- package/dist/page/page-panel/page-panel-footer2.js +1 -1
- package/dist/page/page-panel/page-panel-header2.js +1 -1
- package/dist/page/page-panel/page-panel2.js +1 -1
- package/dist/page/page2.js +1 -1
- package/dist/page-header/page-header2.js +1 -1
- package/dist/page-loader/page-loader2.js +1 -1
- package/dist/pagination/pagination2.js +1 -1
- package/dist/panel/panel2.js +4 -4
- package/dist/password/password2.js +1 -1
- package/dist/preferences-input/preferences-input2.js +1 -1
- package/dist/progress-bar/progress-bar2.js +1 -1
- package/dist/progress-dot/progress-dot2.js +1 -1
- package/dist/progress-ring/progress-ring2.js +1 -1
- package/dist/progressive-filter-chip/progressive-filter-chip2.js +1 -1
- package/dist/pulse/pulse2.js +1 -1
- package/dist/radio/radio-group2.js +1 -1
- package/dist/radio/radio2.js +1 -1
- package/dist/range/range2.js +1 -1
- package/dist/resize-handle/resize-handle2.js +1 -1
- package/dist/search/search2.js +1 -1
- package/dist/select/select2.js +1 -1
- package/dist/skeleton/skeleton2.js +1 -1
- package/dist/sort-button/sort-button2.js +1 -1
- package/dist/sparkline/sparkline2.js +1 -1
- package/dist/star-rating/star-rating2.js +1 -1
- package/dist/steps/steps2.js +2 -2
- package/dist/switch/switch-group2.js +1 -1
- package/dist/switch/switch2.js +1 -1
- package/dist/tabs/tabs-group2.js +1 -1
- package/dist/tabs/tabs-item-group2.js +1 -1
- package/dist/tabs/tabs2.js +2 -2
- package/dist/tag/tag2.js +1 -1
- package/dist/textarea/textarea2.js +1 -1
- package/dist/time/time2.js +1 -1
- package/dist/toast/toast2.js +1 -1
- package/dist/toggletip/toggletip-footer2.js +1 -1
- package/dist/toggletip/toggletip-header2.js +1 -1
- package/dist/toggletip/toggletip2.js +1 -1
- package/dist/toolbar/toolbar2.js +1 -1
- package/dist/tooltip/tooltip2.js +1 -1
- package/dist/tree/tree-node2.js +1 -1
- package/dist/tree/tree2.js +1 -1
- package/dist/week/week2.js +1 -1
- package/dist/workspace/controllers/workspace-composition.controller.d.ts +4 -1
- package/dist/workspace/controllers/workspace-composition.controller.js +69 -39
- package/dist/workspace/controllers/workspace-composition.controller.js.map +1 -1
- package/dist/workspace/controllers/workspace-fullscreen.controller.d.ts +2 -4
- package/dist/workspace/controllers/workspace-fullscreen.controller.js +17 -47
- package/dist/workspace/controllers/workspace-fullscreen.controller.js.map +1 -1
- package/dist/workspace/controllers/workspace-rearrange.controller.js +27 -27
- package/dist/workspace/controllers/workspace-rearrange.controller.js.map +1 -1
- package/dist/workspace/controllers/workspace-restoration.controller.js +2 -2
- package/dist/workspace/controllers/workspace-restoration.controller.js.map +1 -1
- package/dist/workspace/panel/panel2.js +2 -2
- package/dist/workspace/panel/panel2.js.map +1 -1
- package/dist/workspace/panel-content/panel-content2.js +1 -1
- package/dist/workspace/panel-footer/panel-footer2.js +1 -1
- package/dist/workspace/panel-header/panel-header2.js +1 -1
- package/dist/workspace/utils/comparison.utils.d.ts +3 -0
- package/dist/workspace/utils/comparison.utils.js +13 -0
- package/dist/workspace/utils/comparison.utils.js.map +1 -0
- package/dist/workspace/utils/evaluation.utils.d.ts +65 -6
- package/dist/workspace/utils/evaluation.utils.js +334 -99
- package/dist/workspace/utils/evaluation.utils.js.map +1 -1
- package/dist/workspace/utils/geometry/allocation.utils.js +15 -13
- package/dist/workspace/utils/geometry/allocation.utils.js.map +1 -1
- package/dist/workspace/utils/geometry/sizing.utils.d.ts +2 -0
- package/dist/workspace/utils/geometry/sizing.utils.js +37 -17
- package/dist/workspace/utils/geometry/sizing.utils.js.map +1 -1
- package/dist/workspace/utils/interaction/boundary.utils.d.ts +2 -2
- package/dist/workspace/utils/interaction/boundary.utils.js +2 -2
- package/dist/workspace/utils/interaction/boundary.utils.js.map +1 -1
- package/dist/workspace/utils/interaction/drag-preview.utils.d.ts +3 -3
- package/dist/workspace/utils/interaction/drag-preview.utils.js.map +1 -1
- package/dist/workspace/utils/interaction/insertion-offers.utils.d.ts +11 -9
- package/dist/workspace/utils/interaction/insertion-offers.utils.js +37 -43
- package/dist/workspace/utils/interaction/insertion-offers.utils.js.map +1 -1
- package/dist/workspace/utils/interaction/placement-decision.utils.d.ts +6 -1
- package/dist/workspace/utils/interaction/placement-decision.utils.js +94 -87
- package/dist/workspace/utils/interaction/placement-decision.utils.js.map +1 -1
- package/dist/workspace/utils/model/layout.utils.d.ts +2 -1
- package/dist/workspace/utils/model/layout.utils.js +12 -10
- package/dist/workspace/utils/model/layout.utils.js.map +1 -1
- package/dist/workspace/utils/model/membership.utils.d.ts +4 -0
- package/dist/workspace/utils/model/membership.utils.js +13 -4
- package/dist/workspace/utils/model/membership.utils.js.map +1 -1
- package/dist/workspace/utils/model/operations.utils.d.ts +1 -0
- package/dist/workspace/utils/model/operations.utils.js +51 -46
- package/dist/workspace/utils/model/operations.utils.js.map +1 -1
- package/dist/workspace/utils/model/projection.utils.d.ts +4 -2
- package/dist/workspace/utils/model/projection.utils.js +49 -40
- package/dist/workspace/utils/model/projection.utils.js.map +1 -1
- package/dist/workspace/utils/model/value.utils.d.ts +4 -3
- package/dist/workspace/utils/model/value.utils.js +15 -50
- package/dist/workspace/utils/model/value.utils.js.map +1 -1
- package/dist/workspace/utils/placement/acquisition-sizing.utils.d.ts +2 -0
- package/dist/workspace/utils/placement/acquisition-sizing.utils.js +30 -22
- package/dist/workspace/utils/placement/acquisition-sizing.utils.js.map +1 -1
- package/dist/workspace/utils/placement/group-insertion.utils.d.ts +19 -13
- package/dist/workspace/utils/placement/group-insertion.utils.js +50 -47
- package/dist/workspace/utils/placement/group-insertion.utils.js.map +1 -1
- package/dist/workspace/utils/placement/planner.utils.d.ts +13 -2
- package/dist/workspace/utils/placement/planner.utils.js +79 -73
- package/dist/workspace/utils/placement/planner.utils.js.map +1 -1
- package/dist/workspace/utils/placement/preparation.utils.d.ts +5 -2
- package/dist/workspace/utils/placement/preparation.utils.js +45 -41
- package/dist/workspace/utils/placement/preparation.utils.js.map +1 -1
- package/dist/workspace/utils/placement/region.utils.js +32 -32
- package/dist/workspace/utils/placement/region.utils.js.map +1 -1
- package/dist/workspace/utils/placement/scope.utils.d.ts +34 -0
- package/dist/workspace/utils/placement/scope.utils.js +155 -0
- package/dist/workspace/utils/placement/scope.utils.js.map +1 -0
- package/dist/workspace/utils/placement/session.utils.d.ts +11 -0
- package/dist/workspace/utils/placement/session.utils.js +78 -0
- package/dist/workspace/utils/placement/session.utils.js.map +1 -0
- package/dist/workspace/utils/placement/split-sizing.utils.d.ts +2 -2
- package/dist/workspace/utils/placement/split-sizing.utils.js +19 -19
- package/dist/workspace/utils/placement/split-sizing.utils.js.map +1 -1
- package/dist/workspace/utils/presentation/composition.utils.d.ts +1 -1
- package/dist/workspace/utils/presentation/composition.utils.js +4 -2
- package/dist/workspace/utils/presentation/composition.utils.js.map +1 -1
- package/dist/workspace/utils/presentation/groups.utils.d.ts +3 -3
- package/dist/workspace/utils/presentation/groups.utils.js +40 -30
- package/dist/workspace/utils/presentation/groups.utils.js.map +1 -1
- package/dist/workspace/utils/presentation/measurements.utils.d.ts +1 -0
- package/dist/workspace/utils/presentation/measurements.utils.js +6 -14
- package/dist/workspace/utils/presentation/measurements.utils.js.map +1 -1
- package/dist/workspace/utils/presentation/offers.utils.d.ts +1 -1
- package/dist/workspace/utils/presentation/offers.utils.js +3 -3
- package/dist/workspace/utils/presentation/offers.utils.js.map +1 -1
- package/dist/workspace/utils/presentation/preview.utils.d.ts +6 -0
- package/dist/workspace/utils/presentation/preview.utils.js +14 -3
- package/dist/workspace/utils/presentation/preview.utils.js.map +1 -1
- package/dist/workspace/workspace.examples.js.map +1 -1
- package/dist/workspace/workspace.examples.json +4 -4
- package/dist/workspace/workspace.js +1 -1
- package/dist/workspace/workspace.js.map +1 -1
- package/dist/workspace/workspace2.js +206 -212
- package/dist/workspace/workspace2.js.map +1 -1
- package/package.json +16 -4
- package/dist/workspace/utils/placement/context.utils.d.ts +0 -36
- package/dist/workspace/utils/placement/context.utils.js +0 -135
- package/dist/workspace/utils/placement/context.utils.js.map +0 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { haveSameGridPitch as e, resolveDashboardMetrics as t } from "../utils/geometry.utils.js";
|
|
2
|
+
import { isServer as n } from "lit";
|
|
3
|
+
// src/dashboard/controllers/measurement.controller.ts
|
|
4
|
+
var r = class {
|
|
5
|
+
#e;
|
|
6
|
+
#t;
|
|
7
|
+
#n;
|
|
8
|
+
#r;
|
|
9
|
+
#i;
|
|
10
|
+
#a = /* @__PURE__ */ new Set();
|
|
11
|
+
constructor(e, t) {
|
|
12
|
+
this.#e = e, this.#t = t, e.addController(this);
|
|
13
|
+
}
|
|
14
|
+
get metrics() {
|
|
15
|
+
return this.#n;
|
|
16
|
+
}
|
|
17
|
+
hostConnected() {
|
|
18
|
+
n || (this.#r = new ResizeObserver(() => this.#c()), this.#e.hasUpdated && this.observe());
|
|
19
|
+
}
|
|
20
|
+
hostDisconnected() {
|
|
21
|
+
this.#r?.disconnect(), this.#i !== void 0 && cancelAnimationFrame(this.#i), this.#i = void 0, this.#a.clear();
|
|
22
|
+
}
|
|
23
|
+
observe() {
|
|
24
|
+
this.observePanels();
|
|
25
|
+
for (let e of this.#e.shadowRoot?.querySelectorAll(".viewport, .metric, .gap-metric") ?? []) this.#r?.observe(e);
|
|
26
|
+
}
|
|
27
|
+
observePanels() {
|
|
28
|
+
if (!this.#e.isConnected) return;
|
|
29
|
+
let e = new Set(this.#t.getPanels().flatMap((e) => {
|
|
30
|
+
let t = e.shadowRoot?.querySelector("[internal-host]");
|
|
31
|
+
return t ? [t] : [];
|
|
32
|
+
}));
|
|
33
|
+
for (let t of this.#a) e.has(t) || this.#r?.unobserve(t);
|
|
34
|
+
for (let t of e) this.#a.has(t) || this.#r?.observe(t, { box: "content-box" });
|
|
35
|
+
this.#a = e;
|
|
36
|
+
}
|
|
37
|
+
#o() {
|
|
38
|
+
let e = [...this.#a].flatMap((e) => {
|
|
39
|
+
let t = getComputedStyle(e);
|
|
40
|
+
return [
|
|
41
|
+
t.borderTopWidth,
|
|
42
|
+
t.borderRightWidth,
|
|
43
|
+
t.borderBottomWidth,
|
|
44
|
+
t.borderLeftWidth
|
|
45
|
+
].map((e) => Number.parseFloat(e));
|
|
46
|
+
}), t = e[0], n = `${this.#a.size === this.#t.getPanels().length && t !== void 0 && Number.isFinite(t) && t >= 0 && e.every((e) => e === t) ? t : 0}px`;
|
|
47
|
+
this.#e.style.getPropertyValue("--_geometry-border-width") !== n && this.#e.style.setProperty("--_geometry-border-width", n);
|
|
48
|
+
}
|
|
49
|
+
#s() {
|
|
50
|
+
let e = this.#t.getViewport(), n = this.#e.shadowRoot?.querySelector(".metric"), r = this.#e.shadowRoot?.querySelector(".gap-metric");
|
|
51
|
+
if (!e || !n || !r) return;
|
|
52
|
+
let i = n.getBoundingClientRect(), a = r.getBoundingClientRect(), o = this.#t.getGrid();
|
|
53
|
+
return t({
|
|
54
|
+
...o,
|
|
55
|
+
sizing: this.#t.getSizing(),
|
|
56
|
+
width: e.clientWidth,
|
|
57
|
+
height: e.clientHeight,
|
|
58
|
+
columnSize: i.width,
|
|
59
|
+
rowSize: i.height,
|
|
60
|
+
gap: a.width,
|
|
61
|
+
overlap: a.height
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
#c() {
|
|
65
|
+
this.#e.isConnected && this.#i === void 0 && (this.#i = requestAnimationFrame(() => {
|
|
66
|
+
this.#i = void 0, this.#e.isConnected && this.measure();
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
measure() {
|
|
70
|
+
this.#o();
|
|
71
|
+
let t = this.#s();
|
|
72
|
+
JSON.stringify(t) !== JSON.stringify(this.#n) && (e(t, this.#n) || this.#t.pitchChanged(), this.#n = t, this.#e.requestUpdate());
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
export { r as DashboardMeasurementController };
|
|
76
|
+
|
|
77
|
+
//# sourceMappingURL=measurement.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measurement.controller.js","names":["DashboardMeasurementController","#host","host","#delegate","delegate","#metrics","isServer","#resizeObserver","#scheduleMeasure","#resizeFrame","#borderTargets","target","next","surface","panel","widths","style","value","first","viewport","metric","gap","box","spacing","grid","resolveDashboardMetrics","#updateBorderWidth","#readMetrics","haveSameGridPitch"],"sources":["../../../src/dashboard/controllers/measurement.controller.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { isServer, type ReactiveControllerHost } from 'lit';\n\nimport { haveSameGridPitch, resolveDashboardMetrics } from '../utils/geometry.utils.js';\n\nimport type { DashboardMetrics } from '../utils/geometry.utils.js';\n\nimport type { DashboardPanel } from '../panel/panel.js';\n\ninterface DashboardMeasurementHost extends HTMLElement, ReactiveControllerHost {\n readonly hasUpdated: boolean;\n}\n\ninterface DashboardMeasurementDelegate {\n getPanels(): DashboardPanel[];\n getViewport(): HTMLElement | undefined;\n getGrid(): { flow: 'vertical' | 'horizontal'; tracks: number };\n getSizing(): 'fit' | 'fixed';\n pitchChanged(): void;\n}\n\n/** Measures viewport and cell geometry without owning arrangement policy. */\nexport class DashboardMeasurementController {\n readonly #host: DashboardMeasurementHost;\n readonly #delegate: DashboardMeasurementDelegate;\n #metrics?: DashboardMetrics;\n #resizeObserver?: ResizeObserver;\n #resizeFrame?: number;\n #borderTargets = new Set<HTMLElement>();\n\n constructor(host: DashboardMeasurementHost, delegate: DashboardMeasurementDelegate) {\n this.#host = host;\n this.#delegate = delegate;\n host.addController(this);\n }\n\n get metrics() {\n return this.#metrics;\n }\n\n hostConnected() {\n if (isServer) return;\n\n this.#resizeObserver = new ResizeObserver(() => this.#scheduleMeasure());\n\n if (this.#host.hasUpdated) {\n this.observe();\n }\n }\n\n hostDisconnected() {\n this.#resizeObserver?.disconnect();\n\n if (this.#resizeFrame !== undefined) {\n cancelAnimationFrame(this.#resizeFrame);\n }\n\n this.#resizeFrame = undefined;\n this.#borderTargets.clear();\n }\n\n observe() {\n this.observePanels();\n\n for (const target of this.#host.shadowRoot?.querySelectorAll('.viewport, .metric, .gap-metric') ?? []) {\n this.#resizeObserver?.observe(target);\n }\n }\n\n observePanels() {\n if (!this.#host.isConnected) return;\n\n const next = new Set(\n this.#delegate.getPanels().flatMap(panel => {\n const surface = panel.shadowRoot?.querySelector<HTMLElement>('[internal-host]');\n return surface ? [surface] : [];\n })\n );\n\n for (const target of this.#borderTargets) {\n if (!next.has(target)) {\n this.#resizeObserver?.unobserve(target);\n }\n }\n\n for (const target of next) {\n if (!this.#borderTargets.has(target)) {\n this.#resizeObserver?.observe(target, { box: 'content-box' });\n }\n }\n\n this.#borderTargets = next;\n }\n\n #updateBorderWidth() {\n const widths = [...this.#borderTargets].flatMap(target => {\n const style = getComputedStyle(target);\n return [style.borderTopWidth, style.borderRightWidth, style.borderBottomWidth, style.borderLeftWidth].map(value =>\n Number.parseFloat(value)\n );\n });\n const first = widths[0];\n const width =\n this.#borderTargets.size === this.#delegate.getPanels().length &&\n first !== undefined &&\n Number.isFinite(first) &&\n first >= 0 &&\n widths.every(value => value === first)\n ? first\n : 0;\n const value = `${width}px`;\n\n if (this.#host.style.getPropertyValue('--_geometry-border-width') !== value) {\n this.#host.style.setProperty('--_geometry-border-width', value);\n }\n }\n\n #readMetrics() {\n const viewport = this.#delegate.getViewport();\n const metric = this.#host.shadowRoot?.querySelector<HTMLElement>('.metric');\n const gap = this.#host.shadowRoot?.querySelector<HTMLElement>('.gap-metric');\n if (!viewport || !metric || !gap) {\n return;\n }\n\n const box = metric.getBoundingClientRect();\n const spacing = gap.getBoundingClientRect();\n const grid = this.#delegate.getGrid();\n\n return resolveDashboardMetrics({\n ...grid,\n sizing: this.#delegate.getSizing(),\n width: viewport.clientWidth,\n height: viewport.clientHeight,\n columnSize: box.width,\n rowSize: box.height,\n gap: spacing.width,\n overlap: spacing.height\n });\n }\n\n #scheduleMeasure() {\n if (!this.#host.isConnected || this.#resizeFrame !== undefined) return;\n\n this.#resizeFrame = requestAnimationFrame(() => {\n this.#resizeFrame = undefined;\n\n if (this.#host.isConnected) {\n this.measure();\n }\n });\n }\n\n measure() {\n this.#updateBorderWidth();\n\n const next = this.#readMetrics();\n if (JSON.stringify(next) === JSON.stringify(this.#metrics)) return;\n\n if (!haveSameGridPitch(next, this.#metrics)) {\n this.#delegate.pitchChanged();\n }\n\n this.#metrics = next;\n this.#host.requestUpdate();\n }\n}\n"],"mappings":";;;AAwBA,IAAaA,IAAb,MAA4C;CAC1C;CACA;CACA;CACA;CACA;CACA,qBAAiB,IAAI,IAAiB;CAEtC,YAAY,GAAgC,GAAwC;EAGlF,AAFA,KAAKC,KAAQC,GACb,KAAKC,KAAYC,GACjBF,EAAK,cAAc,IAAI;CACzB;CAEA,IAAI,UAAU;EACZ,OAAO,KAAKG;CACd;CAEA,gBAAgB;EACd,AAAIC,MAEJ,KAAKC,KAAkB,IAAI,qBAAqB,KAAKC,GAAiB,CAAC,GAEnE,KAAKP,GAAM,cACb,KAAK,QAAQ;CAEjB;CAEA,mBAAmB;EAQjB,AAPA,KAAKM,IAAiB,WAAW,GAE7B,KAAKE,OAAiB,KAAA,KACxB,qBAAqB,KAAKA,EAAY,GAGxC,KAAKA,KAAe,KAAA,GACpB,KAAKC,GAAe,MAAM;CAC5B;CAEA,UAAU;EACR,KAAK,cAAc;EAEnB,KAAK,IAAMC,KAAU,KAAKV,GAAM,YAAY,iBAAiB,iCAAiC,KAAK,CAAC,GAClG,KAAKM,IAAiB,QAAQI,CAAM;CAExC;CAEA,gBAAgB;EACd,IAAI,CAAC,KAAKV,GAAM,aAAa;EAE7B,IAAMW,IAAO,IAAI,IACf,KAAKT,GAAU,UAAU,CAAC,CAAC,SAAQ,MAAS;GAC1C,IAAMU,IAAUC,EAAM,YAAY,cAA2B,iBAAiB;GAC9E,OAAOD,IAAU,CAACA,CAAO,IAAI,CAAC;EAChC,CAAC,CACH;EAEA,KAAK,IAAMF,KAAU,KAAKD,IACxB,AAAKE,EAAK,IAAID,CAAM,KAClB,KAAKJ,IAAiB,UAAUI,CAAM;EAI1C,KAAK,IAAMA,KAAUC,GACnB,AAAK,KAAKF,GAAe,IAAIC,CAAM,KACjC,KAAKJ,IAAiB,QAAQI,GAAQ,EAAE,KAAK,cAAc,CAAC;EAIhE,KAAKD,KAAiBE;CACxB;CAEA,KAAqB;EACnB,IAAMG,IAAS,CAAC,GAAG,KAAKL,EAAc,CAAC,CAAC,SAAQ,MAAU;GACxD,IAAMM,IAAQ,iBAAiBL,CAAM;GACrC,OAAO;IAACK,EAAM;IAAgBA,EAAM;IAAkBA,EAAM;IAAmBA,EAAM;GAAe,CAAC,CAAC,KAAI,MACxG,OAAO,WAAWC,CAAK,CACzB;EACF,CAAC,GACKC,IAAQH,EAAO,IASfE,IAAQ,GAPZ,KAAKP,GAAe,SAAS,KAAKP,GAAU,UAAU,CAAC,CAAC,UACxDe,MAAU,KAAA,KACV,OAAO,SAASA,CAAK,KACrBA,KAAS,KACTH,EAAO,OAAM,MAASE,MAAUC,CAAK,IACjCA,IACA,EACiB;EAEvB,AAAI,KAAKjB,GAAM,MAAM,iBAAiB,0BAA0B,MAAMgB,KACpE,KAAKhB,GAAM,MAAM,YAAY,4BAA4BgB,CAAK;CAElE;CAEA,KAAe;EACb,IAAME,IAAW,KAAKhB,GAAU,YAAY,GACtCiB,IAAS,KAAKnB,GAAM,YAAY,cAA2B,SAAS,GACpEoB,IAAM,KAAKpB,GAAM,YAAY,cAA2B,aAAa;EAC3E,IAAI,CAACkB,KAAY,CAACC,KAAU,CAACC,GAC3B;EAGF,IAAMC,IAAMF,EAAO,sBAAsB,GACnCG,IAAUF,EAAI,sBAAsB,GACpCG,IAAO,KAAKrB,GAAU,QAAQ;EAEpC,OAAOsB,EAAwB;GAC7B,GAAGD;GACH,QAAQ,KAAKrB,GAAU,UAAU;GACjC,OAAOgB,EAAS;GAChB,QAAQA,EAAS;GACjB,YAAYG,EAAI;GAChB,SAASA,EAAI;GACb,KAAKC,EAAQ;GACb,SAASA,EAAQ;EACnB,CAAC;CACH;CAEA,KAAmB;EACjB,AAAK,KAAKtB,GAAM,eAAe,KAAKQ,OAAiB,KAAA,MAErD,KAAKA,KAAe,4BAA4B;GAG9C,AAFA,KAAKA,KAAe,KAAA,GAEhB,KAAKR,GAAM,eACb,KAAK,QAAQ;EAEjB,CAAC;CACH;CAEA,UAAU;EACR,KAAKyB,GAAmB;EAExB,IAAMd,IAAO,KAAKe,GAAa;EAC/B,AAAI,KAAK,UAAUf,CAAI,MAAM,KAAK,UAAU,KAAKP,EAAQ,MAEpDuB,EAAkBhB,GAAM,KAAKP,EAAQ,KACxC,KAAKF,GAAU,aAAa,GAG9B,KAAKE,KAAWO,GAChB,KAAKX,GAAM,cAAc;CAC3B;AACF"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { LitElement, type PropertyValues } from 'lit';
|
|
2
|
+
import { Ghost } from '@nvidia-elements/core/ghost';
|
|
3
|
+
import type { DashboardCommandContext, DashboardGridPlacement } from './dashboard.types.js';
|
|
4
|
+
/**
|
|
5
|
+
* @element nve-dashboard
|
|
6
|
+
* @description A dashboard arranges application panels on a resizable grid with a restorable layout.
|
|
7
|
+
* @documentation https://nvidia.github.io/elements/docs/elements/dashboard/
|
|
8
|
+
* @since 0.0.0
|
|
9
|
+
* @stable false
|
|
10
|
+
* @entrypoint \@nvidia-elements/core/dashboard
|
|
11
|
+
* @command --enter-fullscreen - Present the invoking panel in native fullscreen.
|
|
12
|
+
* @command --exit-fullscreen - Exit native fullscreen.
|
|
13
|
+
* @command --toggle-fullscreen - Toggle native fullscreen for the invoking panel.
|
|
14
|
+
* @command --place - Apply the invoking control's integer grid placement without pointer target snapping. Target a panel directly or identify it with value when targeting the dashboard. Anchored span changes require resizing; other position changes require movement.
|
|
15
|
+
* @command --move-left - Move left through the same contact-aware movement step as a movement-handle arrow key. Target a panel directly or identify it with value on an invoker targeting the dashboard.
|
|
16
|
+
* @command --move-right - Move right through the same contact-aware movement step as a movement-handle arrow key. Target a panel directly or identify it with value on an invoker targeting the dashboard.
|
|
17
|
+
* @command --move-up - Move up through the same contact-aware movement step as a movement-handle arrow key. Target a panel directly or identify it with value on an invoker targeting the dashboard.
|
|
18
|
+
* @command --move-down - Move down through the same contact-aware movement step as a movement-handle arrow key. Target a panel directly or identify it with value on an invoker targeting the dashboard.
|
|
19
|
+
* @command --move-to-start - Place at the growth-axis start, using available space before making room. Keep the bounded-axis coordinate unless placement supplies another. Uses the same operation as Home on the movement grip.
|
|
20
|
+
* @command --increase-width - Increase width by one cell, subject to panel constraints. Target a panel directly or identify it with value on an invoker targeting the dashboard.
|
|
21
|
+
* @command --decrease-width - Decrease width by one cell, subject to panel constraints. Target a panel directly or identify it with value on an invoker targeting the dashboard.
|
|
22
|
+
* @command --increase-height - Increase height by one cell, subject to panel constraints. Target a panel directly or identify it with value on an invoker targeting the dashboard.
|
|
23
|
+
* @command --decrease-height - Decrease height by one cell, subject to panel constraints. Target a panel directly or identify it with value on an invoker targeting the dashboard.
|
|
24
|
+
* @slot - Direct dashboard panels with unique durable IDs, required headers, and application dropdown groups. DOM order remains application authored. Native reading order follows committed placement where supported; previews preserve that order.
|
|
25
|
+
* @event change - Announces one committed arrangement after interaction, commands, or panel membership and span-constraint reconciliation. Read value on the dashboard; authored content events still bubble normally.
|
|
26
|
+
* @event {Event} commandavailabilitychange - Arrangement or fullscreen command availability may have changed.
|
|
27
|
+
* @cssprop --column-size - Single-cell outer column length in fixed sizing or horizontal flow. Defaults to 160px.
|
|
28
|
+
* @cssprop --row-size - Single-cell outer row length in fixed sizing or vertical flow. Defaults to 120px.
|
|
29
|
+
* @cssprop --gap - Nonnegative CSS length between cells. Include units, including 0px for no gap. At zero, uniform used border widths overlap; unequal widths keep independent geometry. Shared seams assume square panels with solid opaque borders.
|
|
30
|
+
* @cssprop --guide-color - Color of the circular cell-center guides. Defaults to the muted border color.
|
|
31
|
+
* @cssprop --guide-size - Nonnegative CSS length for the guide circle diameter. Defaults to 8px. Include units, including 0px to hide the circles.
|
|
32
|
+
* @cssprop --height - Default viewport height. Defaults to 400px; horizontal fit needs a definite height.
|
|
33
|
+
* @cssprop --animation-duration - Duration of panel geometry, destination ghost geometry, and arrangement control transitions. Defaults to 150ms; reduced motion uses 0ms. Panel geometry follows external container resizing immediately; explicit arrangement and sizing changes use transitions. Animation never delays logical placement commits.
|
|
34
|
+
* @cssprop --animation-easing - Easing of panel and destination ghost geometry transitions.
|
|
35
|
+
* @csspart ghost - Inert placement preview shown during pointer arrangement.
|
|
36
|
+
*/
|
|
37
|
+
export declare class Dashboard extends LitElement {
|
|
38
|
+
#private;
|
|
39
|
+
static styles: import("lit").CSSResult[];
|
|
40
|
+
static readonly metadata: {
|
|
41
|
+
tag: string;
|
|
42
|
+
version: string;
|
|
43
|
+
children: string[];
|
|
44
|
+
};
|
|
45
|
+
static elementDefinitions: {
|
|
46
|
+
[Ghost.metadata.tag]: typeof Ghost;
|
|
47
|
+
};
|
|
48
|
+
/** Localized labels and placement announcements. Grid placement placeholders are column, row, columnSpan, and rowSpan. */
|
|
49
|
+
i18n: Partial<import("@nvidia-elements/foundations/internal/i18n").I18nStrings & {
|
|
50
|
+
__set: boolean;
|
|
51
|
+
}>;
|
|
52
|
+
/** Enables moving and resizing panels through controls and placement commands. */
|
|
53
|
+
rearrangeable: boolean;
|
|
54
|
+
/** Enables native fullscreen commands and a header control for each panel. Turning this off preserves an accepted session and its exit control. Fullscreen does not change the saved arrangement. */
|
|
55
|
+
fullscreenable: boolean;
|
|
56
|
+
/** Selects panel content framing. */
|
|
57
|
+
container?: 'inset' | 'flat' | 'full';
|
|
58
|
+
/** Cell sizing, defaulting to fit. Fit sizing fits bounded tracks to the viewport and scrolls along the growth axis. Fixed sizing uses the configured --column-size and --row-size dimensions and may scroll on both axes. Does not change value. */
|
|
59
|
+
sizing: 'fit' | 'fixed';
|
|
60
|
+
/** Guide visibility: auto shows circular cell-center guides during pointer arrangement, visible always shows them, and hidden hides them while keeping the destination preview. Attribute keywords ignore case; missing, empty, or unrecognized values use auto. Does not change value or interaction permissions. */
|
|
61
|
+
guides: 'auto' | 'visible' | 'hidden';
|
|
62
|
+
/** Closes growth-axis gaps toward top in vertical flow or inline start in horizontal flow, preserving bounded-axis positions and spans. Defaults to false. Enabling silently canonicalizes the current arrangement; disabling keeps current coordinates. This policy is independent of value. */
|
|
63
|
+
get autoSettle(): boolean;
|
|
64
|
+
set autoSettle(value: boolean);
|
|
65
|
+
/** Version 1 JSON with grid {flow, tracks} and items {id, column, row, columnSpan, rowSpan}. Positions are zero-based cells from inline start and top; column zero is at the right in RTL. Spans count columns and rows. Defaults to an empty string, which seeds one-cell panels in DOM order. Assignment validates the saved model immediately and normalizes panels once their upgrades and unique nonempty IDs are ready; restoration is silent. Intentional gaps remain when autoSettle is false. After successful reconciliation, only direct default-slot panel children remain in the value, including hidden children. Removed panels lose their placement. Applications own content data, persistence, and any saved placement history. */
|
|
66
|
+
get value(): string;
|
|
67
|
+
set value(value: string);
|
|
68
|
+
/** Growth direction, defaulting to vertical with bounded columns. Horizontal flow bounds rows. Changing flow does not transpose panel coordinates or spans. Assignment updates the arrangement silently; changes that conflict with panel constraints throw before changing the arrangement. */
|
|
69
|
+
get flow(): 'vertical' | 'horizontal';
|
|
70
|
+
set flow(value: 'vertical' | 'horizontal');
|
|
71
|
+
/** Bounded-axis track count, defaulting to 12. Valid integers range from 1 through 1000000. Assignment updates the arrangement silently and rejects changes that conflict with panel constraints. */
|
|
72
|
+
get tracks(): number;
|
|
73
|
+
set tracks(value: number);
|
|
74
|
+
private announcement;
|
|
75
|
+
protected firstUpdated(): void;
|
|
76
|
+
protected willUpdate(changed: PropertyValues<this>): void;
|
|
77
|
+
protected updated(): void;
|
|
78
|
+
/** Requests an integer placement without gesture target snapping. Anchored span changes use resizing permission, including left and top edges that change the origin; other position changes require movement. Directional collisions and optional growth-axis settling determine the final arrangement. Returns false for unavailable, invalid, or unchanged normalized placement. Successful placement emits one change. */
|
|
79
|
+
place(id: string, placement: DashboardGridPlacement): boolean;
|
|
80
|
+
/** Queries arrangement and fullscreen commands using a panel ID. A placement supplies the full grid placement for --place, or the desired bounded-axis coordinate for --move-to-start. Availability compares the complete normalized proposal with the current arrangement. Directional movement derives from grid placement and panel permissions without requiring rendered controls. Native fullscreen admission remains subject to browser permission. */
|
|
81
|
+
isCommandAvailable(command: string, context?: DashboardCommandContext): boolean;
|
|
82
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.examples.js","names":["dashboard_examples_default"],"sources":["../../src/dashboard/dashboard.examples.ts"],"sourcesContent":["// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.\n// SPDX-License-Identifier: Apache-2.0\n\nimport { html } from 'lit';\n\nimport '@nvidia-elements/core/dashboard/define.js';\nimport '@nvidia-elements/core/button/define.js';\nimport '@nvidia-elements/core/input/define.js';\nimport '@nvidia-elements/core/icon-button/define.js';\nimport '@nvidia-elements/core/dropdown/define.js';\nimport '@nvidia-elements/core/dropdown-group/define.js';\nimport '@nvidia-elements/core/icon/define.js';\nimport '@nvidia-elements/core/menu/define.js';\nimport '@nvidia-elements/core/switch/define.js';\nimport '@nvidia-elements/core/range/define.js';\nimport '@nvidia-elements/core/select/define.js';\n\nexport default { title: 'Elements/Dashboard', component: 'nve-dashboard' };\n\n/**\n * @summary Arrange panels on a grid while retaining application content.\n */\nexport const Default = {\n render: () => html`\n <div id=\"default-dashboard-example\" nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:wrap\">\n <nve-button id=\"reset-default-layout\">Reset layout</nve-button>\n </div>\n <nve-dashboard id=\"default-dashboard\" rearrangeable style=\"height:600px;--row-size:90px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"hero-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"hero-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"hero-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"hero-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"hero-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"hero-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"hero-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"hero-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Changes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"hero-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Evidence</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"hero-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n <script type=\"module\">\n const example = document.querySelector('#default-dashboard-example');\n const dashboard = example.querySelector('nve-dashboard');\n const reset = example.querySelector('#reset-default-layout');\n const initialValue = dashboard.getAttribute('value');\n reset.addEventListener('click', () => { dashboard.value = initialValue; });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Rearrange and resize panels while retaining application content.\n */\nexport const Rearrangeable = {\n render: () => html`\n <div id=\"rearrangeable-dashboard-example\" nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:wrap\">\n <nve-button id=\"reset-rearrangeable-layout\">Reset layout</nve-button>\n <nve-switch id=\"toggle-rearrangeable\">\n <label>Rearrangeable</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n </div>\n <nve-dashboard id=\"rearrangeable-dashboard\" rearrangeable style=\"height:600px;--row-size:90px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"rearrangeable-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"rearrangeable-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"rearrangeable-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"rearrangeable-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"rearrangeable-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"rearrangeable-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"rearrangeable-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"rearrangeable-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Changes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"rearrangeable-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Evidence</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"rearrangeable-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n <script type=\"module\">\n const example = document.querySelector('#rearrangeable-dashboard-example');\n const dashboard = example.querySelector('nve-dashboard');\n const toggle = example.querySelector('#toggle-rearrangeable input');\n const initialValue = dashboard.getAttribute('value');\n toggle.addEventListener('change', () => {\n dashboard.rearrangeable = toggle.checked;\n });\n example.querySelector('#reset-rearrangeable-layout').addEventListener('click', () => {\n dashboard.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Grow vertically within bounded columns or horizontally within bounded rows.\n */\nexport const Flow = {\n render: () => html`\n <div id=\"flow-example\" nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:vertical-center align:wrap\">\n <nve-button id=\"reset-flow-layout\">Reset layout</nve-button>\n <nve-select layout=\"horizontal-inline\" fit-content>\n <label>Flow</label>\n <select id=\"flow-mode\">\n <option value=\"vertical\" selected>Vertical</option>\n <option value=\"horizontal\">Horizontal</option>\n </select>\n </nve-select>\n </div>\n <nve-dashboard id=\"flow-dashboard\" rearrangeable style=\"height:600px;--row-size:90px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"flow-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"flow-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"flow-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"flow-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"flow-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"flow-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"flow-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"flow-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Changes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"flow-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Evidence</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"flow-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n <script type=\"module\">\n const example = document.querySelector('#flow-example');\n const dashboard = example.querySelector('nve-dashboard');\n const select = example.querySelector('#flow-mode');\n const initialLayout = JSON.parse(dashboard.getAttribute('value'));\n // Transpose the cells, keeping application content in the same panels.\n function transposeForFlow(layout, flow) {\n if (layout.grid.flow === flow) return layout;\n return {\n ...layout,\n grid: { ...layout.grid, flow },\n items: layout.items.map(item => ({\n ...item,\n column: item.row,\n row: item.column,\n columnSpan: item.rowSpan,\n rowSpan: item.columnSpan\n }))\n };\n }\n select.addEventListener('change', () => {\n const layout = JSON.parse(dashboard.value);\n dashboard.value = JSON.stringify(transposeForFlow(layout, select.value));\n });\n example.querySelector('#reset-flow-layout').addEventListener('click', () => {\n dashboard.value = JSON.stringify(transposeForFlow(initialLayout, select.value));\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Compare tracks fitted to the viewport with fixed CSS cell dimensions.\n */\n// eslint-disable-next-line local-typescript/example-template-size -- Keep the complete sizing controls and five-panel content with the required viewport width.\nexport const Sizing = {\n render: () => html`\n <div id=\"sizing-dashboard-example\" nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:vertical-center align:wrap\">\n <nve-button id=\"reset-sizing-layout\">Reset layout</nve-button>\n <div nve-layout=\"row gap:md align:vertical-center align:wrap\">\n <nve-select layout=\"horizontal-inline\" fit-content>\n <label>Sizing</label>\n <select id=\"sizing-mode\">\n <option value=\"fit\" selected>Fit</option>\n <option value=\"fixed\">Fixed</option>\n </select>\n </nve-select>\n <nve-range layout=\"horizontal-inline\" fit-content style=\"width:auto\">\n <label>Viewport width: <output for=\"sizing-width\">100</output>%</label>\n <input id=\"sizing-width\" type=\"range\" min=\"50\" max=\"100\" value=\"100\" />\n </nve-range>\n </div>\n </div>\n <div id=\"sizing-viewport\" style=\"width:100%\">\n <nve-dashboard id=\"sizing-dashboard\" rearrangeable style=\"height:600px;--row-size:90px;--column-size:140px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"sizing-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"sizing-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"sizing-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"sizing-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"sizing-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"sizing-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"sizing-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"sizing-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Changes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"sizing-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Evidence</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"sizing-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n </div>\n <script type=\"module\">\n const example = document.querySelector('#sizing-dashboard-example');\n const dashboard = example.querySelector('nve-dashboard');\n const viewport = example.querySelector('#sizing-viewport');\n const select = example.querySelector('#sizing-mode');\n const range = example.querySelector('#sizing-width');\n const output = example.querySelector('output');\n const initialValue = dashboard.getAttribute('value');\n select.addEventListener('change', () => {\n dashboard.sizing = select.value;\n });\n range.addEventListener('input', () => {\n viewport.style.width = range.value + '%';\n output.value = range.value;\n });\n example.querySelector('#reset-sizing-layout').addEventListener('click', () => {\n dashboard.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Choose when to show the grid guides.\n */\nexport const Guides = {\n render: () => html`\n <div id=\"guides-example\" nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:vertical-center align:wrap\">\n <nve-button id=\"reset-guides-layout\">Reset layout</nve-button>\n <nve-select layout=\"horizontal-inline\" fit-content>\n <label>Guides</label>\n <select id=\"guides-mode\">\n <option value=\"auto\">Auto</option>\n <option value=\"visible\" selected>Visible</option>\n <option value=\"hidden\">Hidden</option>\n </select>\n </nve-select>\n </div>\n <nve-dashboard id=\"guided-dashboard\" guides=\"visible\" rearrangeable style=\"height:702px;--row-size:90px;--guide-size:var(--nve-ref-size-200)\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"guided-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"guided-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"guided-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"guided-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"guided-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"guided-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"guided-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"guided-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Changes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"guided-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Evidence</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"guided-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n <script type=\"module\">\n const example = document.querySelector('#guides-example');\n const dashboard = example.querySelector('nve-dashboard');\n const select = example.querySelector('#guides-mode');\n const initialValue = dashboard.getAttribute('value');\n select.addEventListener('change', () => {\n dashboard.guides = select.value;\n });\n example.querySelector('#reset-guides-layout').addEventListener('click', () => {\n dashboard.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Automatically close gaps along the growth axis.\n */\nexport const AutoSettle = {\n render: () => html`\n <div id=\"auto-settle-example\" nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:vertical-center align:wrap\">\n <nve-button id=\"reset-settle-layout\">Reset layout</nve-button>\n <nve-switch id=\"toggle-auto-settle\">\n <label>Auto Settle</label>\n <input type=\"checkbox\" />\n </nve-switch>\n </div>\n <nve-dashboard id=\"settle-dashboard\" guides=\"visible\" rearrangeable style=\"height:702px;--row-size:90px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"settle-baseline\",\"column\":0,\"row\":1,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"settle-candidate\",\"column\":3,\"row\":1,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"settle-changes\",\"column\":0,\"row\":3,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"settle-evidence\",\"column\":3,\"row\":3,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"settle-notes\",\"column\":0,\"row\":5,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"settle-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"settle-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"settle-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Changes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"settle-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Evidence</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"settle-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n <script type=\"module\">\n const example = document.querySelector('#auto-settle-example');\n const dashboard = example.querySelector('nve-dashboard');\n const toggle = example.querySelector('#toggle-auto-settle input');\n const initialValue = dashboard.getAttribute('value');\n toggle.addEventListener('change', () => {\n dashboard.autoSettle = toggle.checked;\n });\n example.querySelector('#reset-settle-layout').addEventListener('click', () => {\n dashboard.autoSettle = false;\n toggle.checked = false;\n dashboard.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Present one panel in native fullscreen without changing the saved arrangement.\n */\nexport const Fullscreenable = {\n render: () => html`\n <div id=\"fullscreen-dashboard-example\" nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:wrap\">\n <nve-button id=\"reset-fullscreen-layout\">Reset layout</nve-button>\n <nve-switch id=\"toggle-fullscreenable\">\n <label>Fullscreenable</label>\n <input type=\"checkbox\" checked />\n </nve-switch>\n </div>\n <nve-dashboard id=\"fullscreen-dashboard\" fullscreenable rearrangeable style=\"height:600px;--row-size:90px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"fullscreen-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"fullscreen-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"fullscreen-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"fullscreen-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"fullscreen-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"fullscreen-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"fullscreen-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"fullscreen-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Changes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"fullscreen-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Evidence</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"fullscreen-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n <script type=\"module\">\n const example = document.querySelector('#fullscreen-dashboard-example');\n const dashboard = example.querySelector('nve-dashboard');\n const toggle = example.querySelector('#toggle-fullscreenable input');\n const initialValue = dashboard.getAttribute('value');\n toggle.addEventListener('change', () => {\n dashboard.fullscreenable = toggle.checked;\n });\n example.querySelector('#reset-fullscreen-layout').addEventListener('click', () => {\n dashboard.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Add custom menus that use invoker commands to move and resize panels.\n */\n// eslint-disable-next-line local-typescript/example-template-size -- Keep the complete menu composition readable without compressing its markup.\nexport const CustomPanelActions = {\n render: () => html`\n <nve-dashboard id=\"actions-dashboard\" rearrangeable style=\"height:600px;--row-size:90px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"actions-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"actions-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"actions-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"actions-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"actions-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"actions-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>\n Baseline\n <nve-icon-button slot=\"suffix\" icon-name=\"more-actions\" container=\"flat\" size=\"sm\" aria-label=\"Baseline actions\" value=\"actions-baseline\" popovertarget=\"dashboard-actions-menu\"></nve-icon-button>\n </nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"actions-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>\n Candidate\n <nve-icon-button slot=\"suffix\" icon-name=\"more-actions\" container=\"flat\" size=\"sm\" aria-label=\"Candidate actions\" value=\"actions-candidate\" popovertarget=\"dashboard-actions-menu\"></nve-icon-button>\n </nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"actions-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>\n Changes\n <nve-icon-button slot=\"suffix\" icon-name=\"more-actions\" container=\"flat\" size=\"sm\" aria-label=\"Changes actions\" value=\"actions-changes\" popovertarget=\"dashboard-actions-menu\"></nve-icon-button>\n </nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"actions-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>\n Evidence\n <nve-icon-button slot=\"suffix\" icon-name=\"more-actions\" container=\"flat\" size=\"sm\" aria-label=\"Evidence actions\" value=\"actions-evidence\" popovertarget=\"dashboard-actions-menu\"></nve-icon-button>\n </nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"actions-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>\n Notes\n <nve-icon-button slot=\"suffix\" icon-name=\"more-actions\" container=\"flat\" size=\"sm\" aria-label=\"Notes actions\" value=\"actions-notes\" popovertarget=\"dashboard-actions-menu\"></nve-icon-button>\n </nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dropdown-group>\n <nve-dropdown id=\"dashboard-actions-menu\">\n <nve-menu>\n <nve-menu-item popovertarget=\"dashboard-move-menu\">\n Move\n <nve-icon name=\"caret\" direction=\"right\" size=\"sm\" slot=\"suffix\"></nve-icon>\n </nve-menu-item>\n <nve-menu-item popovertarget=\"dashboard-shrink-menu\">\n Shrink\n <nve-icon name=\"caret\" direction=\"right\" size=\"sm\" slot=\"suffix\"></nve-icon>\n </nve-menu-item>\n <nve-menu-item popovertarget=\"dashboard-grow-menu\">\n Grow\n <nve-icon name=\"caret\" direction=\"right\" size=\"sm\" slot=\"suffix\"></nve-icon>\n </nve-menu-item>\n </nve-menu>\n </nve-dropdown>\n <nve-dropdown id=\"dashboard-move-menu\" position=\"right\">\n <nve-menu>\n <nve-menu-item commandfor=\"actions-dashboard\" command=\"--move-to-start\">To start</nve-menu-item>\n <nve-menu-item commandfor=\"actions-dashboard\" command=\"--move-left\">Left</nve-menu-item>\n <nve-menu-item commandfor=\"actions-dashboard\" command=\"--move-right\">Right</nve-menu-item>\n <nve-menu-item commandfor=\"actions-dashboard\" command=\"--move-up\">Up</nve-menu-item>\n <nve-menu-item commandfor=\"actions-dashboard\" command=\"--move-down\">Down</nve-menu-item>\n </nve-menu>\n </nve-dropdown>\n <nve-dropdown id=\"dashboard-shrink-menu\" position=\"right\">\n <nve-menu>\n <nve-menu-item commandfor=\"actions-dashboard\" command=\"--decrease-width\">Width</nve-menu-item>\n <nve-menu-item commandfor=\"actions-dashboard\" command=\"--decrease-height\">Height</nve-menu-item>\n </nve-menu>\n </nve-dropdown>\n <nve-dropdown id=\"dashboard-grow-menu\" position=\"right\">\n <nve-menu>\n <nve-menu-item commandfor=\"actions-dashboard\" command=\"--increase-width\">Width</nve-menu-item>\n <nve-menu-item commandfor=\"actions-dashboard\" command=\"--increase-height\">Height</nve-menu-item>\n </nve-menu>\n </nve-dropdown>\n </nve-dropdown-group>\n <script type=\"module\">\n const dashboard = document.querySelector('#actions-dashboard');\n const dropdownGroup = dashboard.querySelector('nve-dropdown-group');\n let panelId = 'actions-baseline';\n function refresh() {\n for (const item of dropdownGroup.querySelectorAll('[command]')) {\n item.value = panelId;\n item.disabled = !dashboard.isCommandAvailable(item.command, { value: panelId });\n }\n for (const trigger of dropdownGroup.querySelectorAll('[popovertarget]')) {\n const items = trigger.popoverTargetElement.querySelectorAll('[command]');\n trigger.disabled = [...items].every(item => item.disabled);\n }\n }\n dropdownGroup.addEventListener('beforetoggle', event => {\n if (event.newState !== 'open') return;\n if (event.target.id === 'dashboard-actions-menu') panelId = event.source?.value ?? panelId;\n refresh();\n }, true);\n dashboard.addEventListener('commandavailabilitychange', refresh);\n dashboard.addEventListener('change', event => {\n if (event.target === dashboard) dropdownGroup.close();\n });\n refresh();\n </script>\n </nve-dashboard>\n `\n};\n\n/**\n * @summary Add and remove panels through the DOM while preserving application content.\n */\nexport const DynamicPanels = {\n render: () => html`\n <div id=\"dynamic-panels-example\" nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:wrap\">\n <nve-button id=\"reset-dynamic-layout\">Reset layout</nve-button>\n <div nve-layout=\"row gap:sm\">\n <nve-button id=\"add-dynamic-notes\">Add Notes</nve-button>\n <nve-button id=\"remove-dynamic-notes\" disabled>Remove Notes</nve-button>\n </div>\n </div>\n <nve-dashboard id=\"dynamic-dashboard\" rearrangeable style=\"height:400px;--row-size:90px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"dynamic-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"dynamic-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"dynamic-baseline\" min-column-span=\"3\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"dynamic-candidate\" min-column-span=\"3\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n </nve-dashboard>\n <template id=\"dynamic-notes-template\">\n <nve-dashboard-panel id=\"dynamic-notes\" min-column-span=\"3\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </template>\n <script type=\"module\">\n const example = document.querySelector('#dynamic-panels-example');\n const dashboard = example.querySelector('nve-dashboard');\n const add = example.querySelector('#add-dynamic-notes');\n const remove = example.querySelector('#remove-dynamic-notes');\n const notes = example.querySelector('#dynamic-notes-template').content.firstElementChild;\n const initialValue = dashboard.getAttribute('value');\n\n add.addEventListener('click', () => {\n dashboard.append(notes);\n add.disabled = true;\n remove.disabled = false;\n });\n\n remove.addEventListener('click', () => {\n notes.remove();\n add.disabled = false;\n remove.disabled = true;\n });\n\n example.querySelector('#reset-dynamic-layout').addEventListener('click', () => {\n dashboard.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Save and restore panel placement without recreating application content.\n */\nexport const SaveRestore = {\n render: () => html`\n <div nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:wrap\">\n <nve-button id=\"reset-layout\">Reset layout</nve-button>\n <div nve-layout=\"row gap:sm\">\n <nve-button id=\"save-layout\">Save layout</nve-button>\n <nve-button id=\"restore-layout\">Restore layout</nve-button>\n </div>\n </div>\n <nve-dashboard id=\"saved-layout\" rearrangeable style=\"height:600px;--row-size:90px\" value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"saved-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"saved-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"saved-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"saved-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"saved-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"saved-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"saved-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"saved-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Changes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"saved-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Evidence</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"saved-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n <script type=\"module\">\n const dashboard = document.querySelector('#saved-layout');\n const save = document.querySelector('#save-layout');\n const restore = document.querySelector('#restore-layout');\n const reset = document.querySelector('#reset-layout');\n const initialValue = dashboard.getAttribute('value');\n let savedValue = initialValue;\n save.addEventListener('click', () => { savedValue = dashboard.value; });\n restore.addEventListener('click', () => { dashboard.value = savedValue; });\n reset.addEventListener('click', () => { dashboard.value = initialValue; });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Match the surrounding layout with inset, flat, or full container framing.\n */\nexport const Container = {\n render: () => html`\n <div nve-layout=\"column gap:md\">\n <nve-dashboard container=\"inset\" rearrangeable style=\"height:260px\" value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":2},\"items\":[{\"id\":\"inset-baseline\",\"column\":0,\"row\":0,\"columnSpan\":1,\"rowSpan\":2},{\"id\":\"inset-candidate\",\"column\":1,\"row\":0,\"columnSpan\":1,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"inset-baseline\"><nve-dashboard-panel-header>Baseline (inset)</nve-dashboard-panel-header><nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content><nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer></nve-dashboard-panel>\n <nve-dashboard-panel id=\"inset-candidate\"><nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header><nve-dashboard-panel-content>Current run</nve-dashboard-panel-content><nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer></nve-dashboard-panel>\n </nve-dashboard>\n <nve-dashboard container=\"flat\" rearrangeable style=\"height:260px\" value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":2},\"items\":[{\"id\":\"flat-baseline\",\"column\":0,\"row\":0,\"columnSpan\":1,\"rowSpan\":2},{\"id\":\"flat-candidate\",\"column\":1,\"row\":0,\"columnSpan\":1,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"flat-baseline\"><nve-dashboard-panel-header>Baseline (flat)</nve-dashboard-panel-header><nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content><nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer></nve-dashboard-panel>\n <nve-dashboard-panel id=\"flat-candidate\"><nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header><nve-dashboard-panel-content>Current run</nve-dashboard-panel-content><nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer></nve-dashboard-panel>\n </nve-dashboard>\n <nve-dashboard container=\"full\" rearrangeable style=\"height:260px\" value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":2},\"items\":[{\"id\":\"full-baseline\",\"column\":0,\"row\":0,\"columnSpan\":1,\"rowSpan\":2},{\"id\":\"full-candidate\",\"column\":1,\"row\":0,\"columnSpan\":1,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"full-baseline\"><nve-dashboard-panel-header>Baseline (full)</nve-dashboard-panel-header><nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content><nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer></nve-dashboard-panel>\n <nve-dashboard-panel id=\"full-candidate\"><nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header><nve-dashboard-panel-content>Current run</nve-dashboard-panel-content><nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer></nve-dashboard-panel>\n </nve-dashboard>\n </div>\n `\n};\n\n/**\n * @summary Customize header and footer spacing, control sizes, and panel corners for a compact dashboard.\n * @tags theme\n */\nexport const CompactStyling = {\n render: () => html`\n <div id=\"compact-dashboard-example\" nve-layout=\"column gap:md\">\n <nve-button>Reset layout</nve-button>\n <style>\n #condensed-dashboard > nve-dashboard-panel {\n --box-shadow: none;\n --border-radius: 0;\n --control-width: var(--nve-ref-size-600);\n --control-height: var(--nve-ref-size-800);\n }\n #condensed-dashboard nve-dashboard-panel-header {\n --min-height: var(--nve-ref-size-800);\n --suffix-padding: var(--nve-ref-size-50);\n --padding: var(--nve-ref-size-100) var(--nve-ref-size-100) var(--nve-ref-size-100) var(--nve-ref-size-250);\n }\n #condensed-dashboard nve-dashboard-panel-footer {\n --suffix-padding: var(--nve-ref-size-50);\n --padding: var(--nve-ref-size-100) var(--nve-ref-size-250);\n }\n </style>\n <nve-dashboard id=\"condensed-dashboard\" rearrangeable style=\"height:480px;--gap:0px;--row-size:80px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"condensed-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"condensed-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"condensed-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"condensed-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"condensed-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"condensed-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header><span nve-text=\"label sm semibold\">Baseline</span></nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer><span nve-text=\"body sm\">Complete</span></nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"condensed-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header><span nve-text=\"label sm semibold\">Candidate</span></nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer><span nve-text=\"body sm\">Complete</span></nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"condensed-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header><span nve-text=\"label sm semibold\">Changes</span></nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"condensed-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header><span nve-text=\"label sm semibold\">Evidence</span></nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"condensed-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header><span nve-text=\"label sm semibold\">Notes</span></nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n <script type=\"module\">\n const example = document.querySelector('#compact-dashboard-example');\n const dashboard = example.querySelector('nve-dashboard');\n const initialValue = dashboard.getAttribute('value');\n example.querySelector('nve-button').addEventListener('click', () => {\n dashboard.value = initialValue;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Adjust spacing between panels with --gap. Zero joins borders with matching widths.\n * @tags test-case\n */\nexport const Gap = {\n render: () => html`\n <div id=\"dashboard-gap-example\" nve-layout=\"column gap:md\">\n <nve-range>\n <label>\n Gap:\n <output for=\"dashboard-gap-range\">0</output>\n px\n </label>\n <input id=\"dashboard-gap-range\" type=\"range\" min=\"0\" max=\"24\" value=\"0\" />\n </nve-range>\n <nve-dashboard id=\"gap-dashboard\" container=\"full\" rearrangeable style=\"height:600px;--row-size:90px;--gap:0px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"gap-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"gap-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"gap-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"gap-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"gap-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"gap-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"gap-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"gap-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Changes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"gap-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Evidence</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"gap-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n <script type=\"module\">\n const example = document.querySelector('#dashboard-gap-example');\n const dashboard = example.querySelector('nve-dashboard');\n const range = example.querySelector('input[type=\"range\"]');\n const output = example.querySelector('output');\n range.addEventListener('input', () => {\n dashboard.style.setProperty('--gap', range.value + 'px');\n output.value = range.value;\n });\n </script>\n </div>\n `\n};\n\n/**\n * @summary Mirror panel placement and controls with the reading direction.\n * @tags test-case\n */\nexport const RightToLeft = {\n render: () => html`\n <div id=\"rtl-dashboard-example\" nve-layout=\"column gap:md\">\n <div nve-layout=\"row gap:md align:space-between align:wrap\">\n <nve-button id=\"reset-rtl-layout\">Reset layout</nve-button>\n </div>\n <nve-dashboard id=\"rtl-dashboard\" dir=\"rtl\" rearrangeable guides=\"visible\" style=\"height:600px;--row-size:90px\"\n value='{\"version\":1,\"grid\":{\"flow\":\"vertical\",\"tracks\":6},\"items\":[{\"id\":\"rtl-baseline\",\"column\":0,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"rtl-candidate\",\"column\":3,\"row\":0,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"rtl-changes\",\"column\":0,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"rtl-evidence\",\"column\":3,\"row\":2,\"columnSpan\":3,\"rowSpan\":2},{\"id\":\"rtl-notes\",\"column\":0,\"row\":4,\"columnSpan\":6,\"rowSpan\":2}]}'>\n <nve-dashboard-panel id=\"rtl-baseline\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Baseline</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Reference run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"rtl-candidate\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Candidate</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Current run</nve-dashboard-panel-content>\n <nve-dashboard-panel-footer>Complete</nve-dashboard-panel-footer>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"rtl-changes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Changes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Comparison</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"rtl-evidence\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Evidence</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>Test cases</nve-dashboard-panel-content>\n </nve-dashboard-panel>\n <nve-dashboard-panel id=\"rtl-notes\" min-column-span=\"2\" min-row-span=\"2\">\n <nve-dashboard-panel-header>Notes</nve-dashboard-panel-header>\n <nve-dashboard-panel-content>\n <nve-input>\n <input aria-label=\"Notes\" value=\"Review findings.\" />\n </nve-input>\n </nve-dashboard-panel-content>\n </nve-dashboard-panel>\n </nve-dashboard>\n <script type=\"module\">\n const example = document.querySelector('#rtl-dashboard-example');\n const dashboard = example.querySelector('nve-dashboard');\n const reset = example.querySelector('#reset-rtl-layout');\n const initialValue = dashboard.getAttribute('value');\n reset.addEventListener('click', () => { dashboard.value = initialValue; });\n </script>\n </div>\n `\n};\n"],"mappings":";AAGA,IAAAA,IAAS"}
|