@camstack/ui-library 1.2.0 → 1.2.2
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/dist/composites/pipeline-matrix-shared.d.ts +29 -6
- package/dist/index.cjs +46 -20
- package/dist/index.js +46 -20
- package/package.json +1 -1
|
@@ -70,6 +70,12 @@ export type CellState = {
|
|
|
70
70
|
readonly kind: 'enabled';
|
|
71
71
|
readonly modelId: string;
|
|
72
72
|
readonly overridden?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Step-tree device jump (phase 1): a short label of the OTHER same-node
|
|
75
|
+
* device this step runs on (operator manual override). Renders a subtle
|
|
76
|
+
* "→ label" badge on the cell.
|
|
77
|
+
*/
|
|
78
|
+
readonly jumpTo?: string;
|
|
73
79
|
} | {
|
|
74
80
|
readonly kind: 'disabled';
|
|
75
81
|
readonly overridden?: boolean;
|
|
@@ -77,6 +83,12 @@ export type CellState = {
|
|
|
77
83
|
readonly kind: 'na';
|
|
78
84
|
} | {
|
|
79
85
|
readonly kind: 'skip';
|
|
86
|
+
/**
|
|
87
|
+
* Step-tree device jump (phase 1): this device's format can't run the
|
|
88
|
+
* step, but it AUTO-jumps to this labelled same-node device — renders a
|
|
89
|
+
* subtle "→ label" badge in place of the "⚠ skip" degrade marker.
|
|
90
|
+
*/
|
|
91
|
+
readonly jumpTo?: string;
|
|
80
92
|
};
|
|
81
93
|
/**
|
|
82
94
|
* Fixed column geometry (rem). Both matrices use CSS-grid STATIC track widths
|
|
@@ -94,14 +106,25 @@ export interface FlatRow {
|
|
|
94
106
|
export declare function flattenTree(nodes: readonly StepTreeNode[]): readonly FlatRow[];
|
|
95
107
|
/**
|
|
96
108
|
* Layout decision for the responsive A↔B switch. Pure so it can be unit-tested
|
|
97
|
-
* in isolation from the DOM.
|
|
109
|
+
* in isolation from the DOM. An unmeasured container (`width <= 0`) always
|
|
110
|
+
* defaults to the wide matrix so there is no first-paint flash into the
|
|
111
|
+
* fallback.
|
|
98
112
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
113
|
+
* Two regimes, because the sticky step column occludes the scroll area on a
|
|
114
|
+
* narrow viewport:
|
|
115
|
+
* - MULTI-node (`nodeCount >= 2`): fall back when the container can't show the
|
|
116
|
+
* step column plus at least TWO node columns side by side — the fallback
|
|
117
|
+
* picks ONE node.
|
|
118
|
+
* - SINGLE node expanded into `columnCount` device sub-columns (the per-node
|
|
119
|
+
* BASE matrix): the wide grid pins a `sticky left-0` step column (`stepColPx`
|
|
120
|
+
* wide); on a phone that column covers nearly the whole viewport, so the
|
|
121
|
+
* horizontal-scroll area behind it shows only slivers of each device column
|
|
122
|
+
* and no column can be brought fully into view. Fall back to the FLUID
|
|
123
|
+
* single-node layout whenever all `columnCount` device columns can't sit
|
|
124
|
+
* beside the step column without scrolling. `columnCount` defaults to
|
|
125
|
+
* `nodeCount` (one column per node) for the multi-node consumers.
|
|
103
126
|
*/
|
|
104
|
-
export declare function shouldUseSingleNode(width: number, nodeCount: number, stepColPx: number, agentColPx?: number): boolean;
|
|
127
|
+
export declare function shouldUseSingleNode(width: number, nodeCount: number, stepColPx: number, agentColPx?: number, columnCount?: number): boolean;
|
|
105
128
|
export declare function SlotHeading({ slot }: {
|
|
106
129
|
readonly slot: PipelineSlot;
|
|
107
130
|
}): import("react").JSX.Element;
|
package/dist/index.cjs
CHANGED
|
@@ -14669,16 +14669,27 @@ function flattenTree(nodes) {
|
|
|
14669
14669
|
}
|
|
14670
14670
|
/**
|
|
14671
14671
|
* Layout decision for the responsive A↔B switch. Pure so it can be unit-tested
|
|
14672
|
-
* in isolation from the DOM.
|
|
14673
|
-
*
|
|
14674
|
-
*
|
|
14675
|
-
*
|
|
14676
|
-
*
|
|
14677
|
-
*
|
|
14678
|
-
|
|
14679
|
-
|
|
14680
|
-
|
|
14672
|
+
* in isolation from the DOM. An unmeasured container (`width <= 0`) always
|
|
14673
|
+
* defaults to the wide matrix so there is no first-paint flash into the
|
|
14674
|
+
* fallback.
|
|
14675
|
+
*
|
|
14676
|
+
* Two regimes, because the sticky step column occludes the scroll area on a
|
|
14677
|
+
* narrow viewport:
|
|
14678
|
+
* - MULTI-node (`nodeCount >= 2`): fall back when the container can't show the
|
|
14679
|
+
* step column plus at least TWO node columns side by side — the fallback
|
|
14680
|
+
* picks ONE node.
|
|
14681
|
+
* - SINGLE node expanded into `columnCount` device sub-columns (the per-node
|
|
14682
|
+
* BASE matrix): the wide grid pins a `sticky left-0` step column (`stepColPx`
|
|
14683
|
+
* wide); on a phone that column covers nearly the whole viewport, so the
|
|
14684
|
+
* horizontal-scroll area behind it shows only slivers of each device column
|
|
14685
|
+
* and no column can be brought fully into view. Fall back to the FLUID
|
|
14686
|
+
* single-node layout whenever all `columnCount` device columns can't sit
|
|
14687
|
+
* beside the step column without scrolling. `columnCount` defaults to
|
|
14688
|
+
* `nodeCount` (one column per node) for the multi-node consumers.
|
|
14689
|
+
*/
|
|
14690
|
+
function shouldUseSingleNode(width, nodeCount, stepColPx, agentColPx = 208, columnCount = nodeCount) {
|
|
14681
14691
|
if (width <= 0) return false;
|
|
14692
|
+
if (nodeCount <= 1) return width < stepColPx + agentColPx * columnCount;
|
|
14682
14693
|
return width < stepColPx + agentColPx * 2;
|
|
14683
14694
|
}
|
|
14684
14695
|
var SLOT_LABEL = {
|
|
@@ -14797,7 +14808,12 @@ function renderCellContent(state) {
|
|
|
14797
14808
|
className: "font-mono text-foreground truncate",
|
|
14798
14809
|
children: state.modelId
|
|
14799
14810
|
}),
|
|
14800
|
-
state.
|
|
14811
|
+
state.jumpTo !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
14812
|
+
className: "ml-auto shrink-0 text-[8px] font-semibold text-sky-500",
|
|
14813
|
+
title: `runs on ${state.jumpTo}`,
|
|
14814
|
+
children: ["→ ", state.jumpTo]
|
|
14815
|
+
}),
|
|
14816
|
+
state.overridden && state.jumpTo === void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
14801
14817
|
className: "ml-auto shrink-0 text-[8px] font-semibold uppercase text-amber-500",
|
|
14802
14818
|
children: "ovr"
|
|
14803
14819
|
})
|
|
@@ -14818,14 +14834,24 @@ function renderCellContent(state) {
|
|
|
14818
14834
|
})
|
|
14819
14835
|
]
|
|
14820
14836
|
});
|
|
14821
|
-
if (state.kind === "skip")
|
|
14822
|
-
|
|
14823
|
-
|
|
14824
|
-
|
|
14825
|
-
className: "
|
|
14826
|
-
|
|
14827
|
-
|
|
14828
|
-
|
|
14837
|
+
if (state.kind === "skip") {
|
|
14838
|
+
if (state.jumpTo !== void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
14839
|
+
className: "flex min-w-0 items-center gap-1 text-sky-500",
|
|
14840
|
+
title: `no build for this device — auto-jumps to ${state.jumpTo}`,
|
|
14841
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-sky-500 shrink-0" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
14842
|
+
className: "truncate font-medium",
|
|
14843
|
+
children: ["→ ", state.jumpTo]
|
|
14844
|
+
})]
|
|
14845
|
+
});
|
|
14846
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
14847
|
+
className: "flex min-w-0 items-center gap-1 text-amber-500",
|
|
14848
|
+
title: "Gated on for this camera, but no compatible model on this node — click to provision",
|
|
14849
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-amber-500 shrink-0" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
14850
|
+
className: "truncate font-medium",
|
|
14851
|
+
children: "⚠ skip"
|
|
14852
|
+
})]
|
|
14853
|
+
});
|
|
14854
|
+
}
|
|
14829
14855
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
14830
14856
|
className: "flex min-w-0 items-center gap-1 text-foreground-subtle/70",
|
|
14831
14857
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "h-1.5 w-1.5 rounded-full bg-muted shrink-0" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -15209,7 +15235,7 @@ function DeviceStepMatrix({ tree, agents, gateFor, getCellState, onCellClick, se
|
|
|
15209
15235
|
return () => RO?.disconnect();
|
|
15210
15236
|
}, []);
|
|
15211
15237
|
const nodes = (0, react$1.useMemo)(() => groupAgentColumns(agents), [agents]);
|
|
15212
|
-
const single = shouldUseSingleNode(width, nodes.length, STEP_COL_PX);
|
|
15238
|
+
const single = shouldUseSingleNode(width, nodes.length, STEP_COL_PX, 208, agents.length);
|
|
15213
15239
|
const selectedNode = (0, react$1.useMemo)(() => {
|
|
15214
15240
|
if (nodes.length === 0) return null;
|
|
15215
15241
|
return nodes.find((n) => n.agentNodeId === fallbackNodeId) ?? nodes[0] ?? null;
|
|
@@ -15218,7 +15244,7 @@ function DeviceStepMatrix({ tree, agents, gateFor, getCellState, onCellClick, se
|
|
|
15218
15244
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
15219
15245
|
ref: containerRef,
|
|
15220
15246
|
className: "w-full space-y-2",
|
|
15221
|
-
children: [single && selectedNode && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NodeSelectorBar, {
|
|
15247
|
+
children: [single && selectedNode && nodes.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NodeSelectorBar, {
|
|
15222
15248
|
nodes,
|
|
15223
15249
|
selected: selectedNode.agentNodeId,
|
|
15224
15250
|
onSelect: onFallbackNodeChange
|
package/dist/index.js
CHANGED
|
@@ -14645,16 +14645,27 @@ function flattenTree(nodes) {
|
|
|
14645
14645
|
}
|
|
14646
14646
|
/**
|
|
14647
14647
|
* Layout decision for the responsive A↔B switch. Pure so it can be unit-tested
|
|
14648
|
-
* in isolation from the DOM.
|
|
14649
|
-
*
|
|
14650
|
-
*
|
|
14651
|
-
*
|
|
14652
|
-
*
|
|
14653
|
-
*
|
|
14654
|
-
|
|
14655
|
-
|
|
14656
|
-
|
|
14648
|
+
* in isolation from the DOM. An unmeasured container (`width <= 0`) always
|
|
14649
|
+
* defaults to the wide matrix so there is no first-paint flash into the
|
|
14650
|
+
* fallback.
|
|
14651
|
+
*
|
|
14652
|
+
* Two regimes, because the sticky step column occludes the scroll area on a
|
|
14653
|
+
* narrow viewport:
|
|
14654
|
+
* - MULTI-node (`nodeCount >= 2`): fall back when the container can't show the
|
|
14655
|
+
* step column plus at least TWO node columns side by side — the fallback
|
|
14656
|
+
* picks ONE node.
|
|
14657
|
+
* - SINGLE node expanded into `columnCount` device sub-columns (the per-node
|
|
14658
|
+
* BASE matrix): the wide grid pins a `sticky left-0` step column (`stepColPx`
|
|
14659
|
+
* wide); on a phone that column covers nearly the whole viewport, so the
|
|
14660
|
+
* horizontal-scroll area behind it shows only slivers of each device column
|
|
14661
|
+
* and no column can be brought fully into view. Fall back to the FLUID
|
|
14662
|
+
* single-node layout whenever all `columnCount` device columns can't sit
|
|
14663
|
+
* beside the step column without scrolling. `columnCount` defaults to
|
|
14664
|
+
* `nodeCount` (one column per node) for the multi-node consumers.
|
|
14665
|
+
*/
|
|
14666
|
+
function shouldUseSingleNode(width, nodeCount, stepColPx, agentColPx = 208, columnCount = nodeCount) {
|
|
14657
14667
|
if (width <= 0) return false;
|
|
14668
|
+
if (nodeCount <= 1) return width < stepColPx + agentColPx * columnCount;
|
|
14658
14669
|
return width < stepColPx + agentColPx * 2;
|
|
14659
14670
|
}
|
|
14660
14671
|
var SLOT_LABEL = {
|
|
@@ -14773,7 +14784,12 @@ function renderCellContent(state) {
|
|
|
14773
14784
|
className: "font-mono text-foreground truncate",
|
|
14774
14785
|
children: state.modelId
|
|
14775
14786
|
}),
|
|
14776
|
-
state.
|
|
14787
|
+
state.jumpTo !== void 0 && /* @__PURE__ */ jsxs("span", {
|
|
14788
|
+
className: "ml-auto shrink-0 text-[8px] font-semibold text-sky-500",
|
|
14789
|
+
title: `runs on ${state.jumpTo}`,
|
|
14790
|
+
children: ["→ ", state.jumpTo]
|
|
14791
|
+
}),
|
|
14792
|
+
state.overridden && state.jumpTo === void 0 && /* @__PURE__ */ jsx("span", {
|
|
14777
14793
|
className: "ml-auto shrink-0 text-[8px] font-semibold uppercase text-amber-500",
|
|
14778
14794
|
children: "ovr"
|
|
14779
14795
|
})
|
|
@@ -14794,14 +14810,24 @@ function renderCellContent(state) {
|
|
|
14794
14810
|
})
|
|
14795
14811
|
]
|
|
14796
14812
|
});
|
|
14797
|
-
if (state.kind === "skip")
|
|
14798
|
-
|
|
14799
|
-
|
|
14800
|
-
|
|
14801
|
-
className: "
|
|
14802
|
-
|
|
14803
|
-
|
|
14804
|
-
|
|
14813
|
+
if (state.kind === "skip") {
|
|
14814
|
+
if (state.jumpTo !== void 0) return /* @__PURE__ */ jsxs("span", {
|
|
14815
|
+
className: "flex min-w-0 items-center gap-1 text-sky-500",
|
|
14816
|
+
title: `no build for this device — auto-jumps to ${state.jumpTo}`,
|
|
14817
|
+
children: [/* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-sky-500 shrink-0" }), /* @__PURE__ */ jsxs("span", {
|
|
14818
|
+
className: "truncate font-medium",
|
|
14819
|
+
children: ["→ ", state.jumpTo]
|
|
14820
|
+
})]
|
|
14821
|
+
});
|
|
14822
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
14823
|
+
className: "flex min-w-0 items-center gap-1 text-amber-500",
|
|
14824
|
+
title: "Gated on for this camera, but no compatible model on this node — click to provision",
|
|
14825
|
+
children: [/* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-amber-500 shrink-0" }), /* @__PURE__ */ jsx("span", {
|
|
14826
|
+
className: "truncate font-medium",
|
|
14827
|
+
children: "⚠ skip"
|
|
14828
|
+
})]
|
|
14829
|
+
});
|
|
14830
|
+
}
|
|
14805
14831
|
return /* @__PURE__ */ jsxs("span", {
|
|
14806
14832
|
className: "flex min-w-0 items-center gap-1 text-foreground-subtle/70",
|
|
14807
14833
|
children: [/* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-muted shrink-0" }), /* @__PURE__ */ jsx("span", {
|
|
@@ -15185,7 +15211,7 @@ function DeviceStepMatrix({ tree, agents, gateFor, getCellState, onCellClick, se
|
|
|
15185
15211
|
return () => RO?.disconnect();
|
|
15186
15212
|
}, []);
|
|
15187
15213
|
const nodes = useMemo(() => groupAgentColumns(agents), [agents]);
|
|
15188
|
-
const single = shouldUseSingleNode(width, nodes.length, STEP_COL_PX);
|
|
15214
|
+
const single = shouldUseSingleNode(width, nodes.length, STEP_COL_PX, 208, agents.length);
|
|
15189
15215
|
const selectedNode = useMemo(() => {
|
|
15190
15216
|
if (nodes.length === 0) return null;
|
|
15191
15217
|
return nodes.find((n) => n.agentNodeId === fallbackNodeId) ?? nodes[0] ?? null;
|
|
@@ -15194,7 +15220,7 @@ function DeviceStepMatrix({ tree, agents, gateFor, getCellState, onCellClick, se
|
|
|
15194
15220
|
return /* @__PURE__ */ jsxs("div", {
|
|
15195
15221
|
ref: containerRef,
|
|
15196
15222
|
className: "w-full space-y-2",
|
|
15197
|
-
children: [single && selectedNode && /* @__PURE__ */ jsx(NodeSelectorBar, {
|
|
15223
|
+
children: [single && selectedNode && nodes.length > 1 && /* @__PURE__ */ jsx(NodeSelectorBar, {
|
|
15198
15224
|
nodes,
|
|
15199
15225
|
selected: selectedNode.agentNodeId,
|
|
15200
15226
|
onSelect: onFallbackNodeChange
|