@flanksource/clicky-ui 0.3.4 → 0.3.6
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/ai.cjs +15 -0
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +15 -0
- package/dist/ai.js.map +1 -1
- package/dist/data/ProgressBars.cjs +194 -0
- package/dist/data/ProgressBars.cjs.map +1 -0
- package/dist/data/ProgressBars.d.ts +85 -0
- package/dist/data/ProgressBars.d.ts.map +1 -0
- package/dist/data/ProgressBars.js +194 -0
- package/dist/data/ProgressBars.js.map +1 -0
- package/dist/data/ProgressBars.model.cjs +27 -0
- package/dist/data/ProgressBars.model.cjs.map +1 -0
- package/dist/data/ProgressBars.model.d.ts +20 -0
- package/dist/data/ProgressBars.model.d.ts.map +1 -0
- package/dist/data/ProgressBars.model.js +27 -0
- package/dist/data/ProgressBars.model.js.map +1 -0
- package/dist/data/TimeseriesCoreBars.cjs +19 -173
- package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
- package/dist/data/TimeseriesCoreBars.d.ts +9 -26
- package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
- package/dist/data/TimeseriesCoreBars.js +20 -174
- package/dist/data/TimeseriesCoreBars.js.map +1 -1
- package/dist/data/WorkloadCard.model.cjs.map +1 -1
- package/dist/data/WorkloadCard.model.d.ts +2 -2
- package/dist/data/WorkloadCard.model.d.ts.map +1 -1
- package/dist/data/WorkloadCard.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.cjs +275 -0
- package/dist/data/ai/SessionViewer.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.d.ts +33 -0
- package/dist/data/ai/SessionViewer.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.fixtures.d.ts +4 -0
- package/dist/data/ai/SessionViewer.fixtures.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.js +275 -0
- package/dist/data/ai/SessionViewer.js.map +1 -0
- package/dist/data/ai/SessionViewer.model.cjs +275 -0
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.model.d.ts +87 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.model.js +275 -0
- package/dist/data/ai/SessionViewer.model.js.map +1 -0
- package/dist/data/ai/SessionViewerMenu.cjs +190 -0
- package/dist/data/ai/SessionViewerMenu.cjs.map +1 -0
- package/dist/data/ai/SessionViewerMenu.d.ts +24 -0
- package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -0
- package/dist/data/ai/SessionViewerMenu.js +190 -0
- package/dist/data/ai/SessionViewerMenu.js.map +1 -0
- package/dist/data/ai/index.d.ts +3 -0
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/session-categories.cjs +219 -0
- package/dist/data/ai/session-categories.cjs.map +1 -0
- package/dist/data/ai/session-categories.d.ts +36 -0
- package/dist/data/ai/session-categories.d.ts.map +1 -0
- package/dist/data/ai/session-categories.js +219 -0
- package/dist/data/ai/session-categories.js.map +1 -0
- package/dist/data/test-runner/TestRunner.fixtures.d.ts.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.cjs.map +1 -1
- package/dist/data/version-info.js +3 -3
- package/dist/data/version-info.js.map +1 -1
- package/dist/data.cjs +4 -2
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +3 -2
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +4 -2
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +4 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/dist/data/TimeseriesCoreBars.model.cjs +0 -27
- package/dist/data/TimeseriesCoreBars.model.cjs.map +0 -1
- package/dist/data/TimeseriesCoreBars.model.d.ts +0 -20
- package/dist/data/TimeseriesCoreBars.model.d.ts.map +0 -1
- package/dist/data/TimeseriesCoreBars.model.js +0 -27
- package/dist/data/TimeseriesCoreBars.model.js.map +0 -1
package/dist/ai.cjs
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const sessionCategories = require("./data/ai/session-categories.cjs");
|
|
3
4
|
const ChatFab = require("./data/ai/ChatFab.cjs");
|
|
4
5
|
const ChatWindow = require("./data/ai/ChatWindow.cjs");
|
|
5
6
|
const ChatWindowManager = require("./data/ai/ChatWindowManager.cjs");
|
|
6
7
|
const ContextBadges = require("./data/ai/ContextBadges.cjs");
|
|
7
8
|
const ContextUsage = require("./data/chat/ContextUsage.cjs");
|
|
9
|
+
const SessionViewer = require("./data/ai/SessionViewer.cjs");
|
|
8
10
|
const ThreadPicker = require("./data/ai/ThreadPicker.cjs");
|
|
9
11
|
const ToolPreferences = require("./data/ai/ToolPreferences.cjs");
|
|
12
|
+
const SessionViewer_model = require("./data/ai/SessionViewer.model.cjs");
|
|
10
13
|
const context = require("./data/ai/context.cjs");
|
|
11
14
|
const chatWindowContext = require("./data/ai/chat-window-context.cjs");
|
|
15
|
+
exports.CATEGORY_LABELS = sessionCategories.CATEGORY_LABELS;
|
|
16
|
+
exports.classifyCommand = sessionCategories.classifyCommand;
|
|
17
|
+
exports.classifyToolCategory = sessionCategories.classifyToolCategory;
|
|
18
|
+
exports.collectSessionFilters = sessionCategories.collectSessionFilters;
|
|
19
|
+
exports.eventCategory = sessionCategories.eventCategory;
|
|
20
|
+
exports.isEventVisible = sessionCategories.isEventVisible;
|
|
12
21
|
exports.ChatFab = ChatFab.ChatFab;
|
|
13
22
|
exports.ChatWindow = ChatWindow.ChatWindow;
|
|
14
23
|
exports.ChatWindowLayer = ChatWindow.ChatWindowLayer;
|
|
@@ -16,8 +25,14 @@ exports.ChatWindowManagerProvider = ChatWindowManager.ChatWindowManagerProvider;
|
|
|
16
25
|
exports.ContextBadges = ContextBadges.ContextBadges;
|
|
17
26
|
exports.ContextBadgesReadonly = ContextBadges.ContextBadgesReadonly;
|
|
18
27
|
exports.ContextUsage = ContextUsage.ContextUsage;
|
|
28
|
+
exports.SessionViewer = SessionViewer.SessionViewer;
|
|
19
29
|
exports.ThreadPicker = ThreadPicker.ThreadPicker;
|
|
20
30
|
exports.ToolPreferences = ToolPreferences.ToolPreferences;
|
|
31
|
+
exports.getSessionAction = SessionViewer_model.getSessionAction;
|
|
32
|
+
exports.normalizeSession = SessionViewer_model.normalizeSession;
|
|
33
|
+
exports.splitMcpTool = SessionViewer_model.splitMcpTool;
|
|
34
|
+
exports.summarizeSession = SessionViewer_model.summarizeSession;
|
|
35
|
+
exports.summarizeToolInput = SessionViewer_model.summarizeToolInput;
|
|
21
36
|
exports.makeContextId = context.makeContextId;
|
|
22
37
|
exports.parseContextPrefix = context.parseContextPrefix;
|
|
23
38
|
exports.serializeContext = context.serializeContext;
|
package/dist/ai.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ai.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/ai.js
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
import { CATEGORY_LABELS, classifyCommand, classifyToolCategory, collectSessionFilters, eventCategory, isEventVisible } from "./data/ai/session-categories.js";
|
|
1
2
|
import { ChatFab } from "./data/ai/ChatFab.js";
|
|
2
3
|
import { ChatWindow, ChatWindowLayer } from "./data/ai/ChatWindow.js";
|
|
3
4
|
import { ChatWindowManagerProvider } from "./data/ai/ChatWindowManager.js";
|
|
4
5
|
import { ContextBadges, ContextBadgesReadonly } from "./data/ai/ContextBadges.js";
|
|
5
6
|
import { ContextUsage } from "./data/chat/ContextUsage.js";
|
|
7
|
+
import { SessionViewer } from "./data/ai/SessionViewer.js";
|
|
6
8
|
import { ThreadPicker } from "./data/ai/ThreadPicker.js";
|
|
7
9
|
import { ToolPreferences } from "./data/ai/ToolPreferences.js";
|
|
10
|
+
import { getSessionAction, normalizeSession, splitMcpTool, summarizeSession, summarizeToolInput } from "./data/ai/SessionViewer.model.js";
|
|
8
11
|
import { makeContextId, parseContextPrefix, serializeContext } from "./data/ai/context.js";
|
|
9
12
|
import { nextPromptId, useChatWindowManager } from "./data/ai/chat-window-context.js";
|
|
10
13
|
export {
|
|
14
|
+
CATEGORY_LABELS,
|
|
11
15
|
ChatFab,
|
|
12
16
|
ChatWindow,
|
|
13
17
|
ChatWindowLayer,
|
|
@@ -15,12 +19,23 @@ export {
|
|
|
15
19
|
ContextBadges,
|
|
16
20
|
ContextBadgesReadonly,
|
|
17
21
|
ContextUsage,
|
|
22
|
+
SessionViewer,
|
|
18
23
|
ThreadPicker,
|
|
19
24
|
ToolPreferences,
|
|
25
|
+
classifyCommand,
|
|
26
|
+
classifyToolCategory,
|
|
27
|
+
collectSessionFilters,
|
|
28
|
+
eventCategory,
|
|
29
|
+
getSessionAction,
|
|
30
|
+
isEventVisible,
|
|
20
31
|
makeContextId,
|
|
21
32
|
nextPromptId,
|
|
33
|
+
normalizeSession,
|
|
22
34
|
parseContextPrefix,
|
|
23
35
|
serializeContext,
|
|
36
|
+
splitMcpTool,
|
|
37
|
+
summarizeSession,
|
|
38
|
+
summarizeToolInput,
|
|
24
39
|
useChatWindowManager
|
|
25
40
|
};
|
|
26
41
|
//# sourceMappingURL=ai.js.map
|
package/dist/ai.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ai.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const utils = require("../lib/utils.cjs");
|
|
5
|
+
const Icon = require("./Icon.cjs");
|
|
6
|
+
const ProgressBars_model = require("./ProgressBars.model.cjs");
|
|
7
|
+
const GaugeHoverCard = require("./GaugeHoverCard.cjs");
|
|
8
|
+
function toneClass(pct, [warn, danger]) {
|
|
9
|
+
if (pct >= danger) return "bg-red-500";
|
|
10
|
+
if (pct >= warn) return "bg-amber-500";
|
|
11
|
+
return "bg-emerald-500";
|
|
12
|
+
}
|
|
13
|
+
function ProgressBarsIcon({ icon }) {
|
|
14
|
+
if (typeof icon === "string") {
|
|
15
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16
|
+
Icon.Icon,
|
|
17
|
+
{
|
|
18
|
+
name: icon,
|
|
19
|
+
width: 14,
|
|
20
|
+
height: 14,
|
|
21
|
+
className: "text-muted-foreground"
|
|
22
|
+
}
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
26
|
+
Icon.Icon,
|
|
27
|
+
{
|
|
28
|
+
icon,
|
|
29
|
+
width: 14,
|
|
30
|
+
height: 14,
|
|
31
|
+
className: "text-muted-foreground"
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
function defaultFormatUnits(units) {
|
|
36
|
+
return Number.isInteger(units) ? String(units) : units.toFixed(1);
|
|
37
|
+
}
|
|
38
|
+
function ProgressBars({
|
|
39
|
+
usage,
|
|
40
|
+
max,
|
|
41
|
+
unit,
|
|
42
|
+
title,
|
|
43
|
+
icon,
|
|
44
|
+
thresholds = [75, 90],
|
|
45
|
+
variant = "default",
|
|
46
|
+
showLabel = true,
|
|
47
|
+
showValue = true,
|
|
48
|
+
showCapacity = false,
|
|
49
|
+
orientation,
|
|
50
|
+
stats,
|
|
51
|
+
hoverCard = true,
|
|
52
|
+
hoverFooter,
|
|
53
|
+
className
|
|
54
|
+
}) {
|
|
55
|
+
const perBar = (unit == null ? void 0 : unit.perBar) ?? 1e3;
|
|
56
|
+
const unitLabel = (unit == null ? void 0 : unit.label) ?? "cores";
|
|
57
|
+
const barLabel = (unit == null ? void 0 : unit.barLabel) ?? "core";
|
|
58
|
+
const formatUnits = (unit == null ? void 0 : unit.format) ?? defaultFormatUnits;
|
|
59
|
+
const model = ProgressBars_model.deriveProgressBars(usage, max, perBar);
|
|
60
|
+
const tone = toneClass(model.pct, thresholds);
|
|
61
|
+
const usageText = formatUnits(model.usageUnits);
|
|
62
|
+
const capacityText = model.limitUnits !== void 0 ? formatUnits(model.limitUnits) : "?";
|
|
63
|
+
const caption = !model.hasUsage ? "—" : showCapacity ? `${usageText} / ${capacityText} ${unitLabel}` : `${usageText} ${unitLabel}`;
|
|
64
|
+
const compactCaption = !model.hasUsage ? "—" : showCapacity ? `${usageText}/${capacityText} ${unitLabel}` : `${usageText} ${unitLabel}`;
|
|
65
|
+
const titleText = `${title}: ${compactCaption}`;
|
|
66
|
+
const isCell = variant === "cell";
|
|
67
|
+
const pctTone = model.limitUnits === void 0 ? void 0 : model.pct >= thresholds[1] ? "text-red-500" : model.pct >= thresholds[0] ? "text-amber-500" : "text-emerald-500";
|
|
68
|
+
const fmt = (n) => `${formatUnits(n)} ${unitLabel}`;
|
|
69
|
+
const hoverRows = model.hasUsage ? [
|
|
70
|
+
{ label: "Current", value: fmt(model.usageUnits), ...pctTone ? { tone: pctTone } : {} },
|
|
71
|
+
...stats ? [
|
|
72
|
+
{ label: "Min", value: fmt(stats.min / perBar) },
|
|
73
|
+
{ label: "Max", value: fmt(stats.max / perBar) },
|
|
74
|
+
{ label: "Avg", value: fmt(stats.avg / perBar) }
|
|
75
|
+
] : [],
|
|
76
|
+
...model.limitUnits !== void 0 ? [{ label: "Capacity", value: fmt(model.limitUnits) }] : []
|
|
77
|
+
] : [];
|
|
78
|
+
const resolvedOrientation = orientation ?? "vertical";
|
|
79
|
+
const isDense = model.barCount > 4;
|
|
80
|
+
const valueText = isCell ? compactCaption : caption;
|
|
81
|
+
const hiddenAccessibleText = !showLabel || !showValue ? titleText : void 0;
|
|
82
|
+
const bars = /* @__PURE__ */ jsxRuntime.jsx(
|
|
83
|
+
"span",
|
|
84
|
+
{
|
|
85
|
+
className: utils.cn(
|
|
86
|
+
"flex shrink-0",
|
|
87
|
+
resolvedOrientation === "vertical" ? utils.cn("items-end", isCell ? "h-4 gap-px" : "h-10 gap-0.5") : utils.cn(
|
|
88
|
+
"flex-col justify-center",
|
|
89
|
+
isCell ? "h-4 w-10 gap-px" : "h-10 w-16 gap-0.5"
|
|
90
|
+
)
|
|
91
|
+
),
|
|
92
|
+
"aria-hidden": isCell ? "true" : void 0,
|
|
93
|
+
"data-orientation": resolvedOrientation,
|
|
94
|
+
"data-bar-count": model.barCount,
|
|
95
|
+
"data-bar-density": isDense ? "compact" : "default",
|
|
96
|
+
children: model.bars.map((bar, i) => {
|
|
97
|
+
const barPct = Math.round(bar.fill * 100);
|
|
98
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
99
|
+
"span",
|
|
100
|
+
{
|
|
101
|
+
className: utils.cn(
|
|
102
|
+
"relative overflow-hidden bg-muted",
|
|
103
|
+
resolvedOrientation === "vertical" ? utils.cn(
|
|
104
|
+
"h-full",
|
|
105
|
+
isCell ? isDense ? "w-[3px] rounded-[2px]" : "w-1.5 rounded-[2px]" : isDense ? "w-1 rounded-sm" : "w-2 rounded-sm"
|
|
106
|
+
) : utils.cn("min-h-px w-full flex-1 rounded-[2px]")
|
|
107
|
+
),
|
|
108
|
+
title: `${barLabel} ${i + 1}: ${barPct}%`,
|
|
109
|
+
"aria-label": !isCell ? `${barLabel} ${i + 1}: ${barPct}%` : void 0,
|
|
110
|
+
"data-fill": bar.fill,
|
|
111
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
112
|
+
"span",
|
|
113
|
+
{
|
|
114
|
+
className: utils.cn(
|
|
115
|
+
"absolute bottom-0 left-0 transition-all duration-300",
|
|
116
|
+
tone
|
|
117
|
+
),
|
|
118
|
+
style: resolvedOrientation === "vertical" ? { height: `${barPct}%`, right: 0 } : { width: `${barPct}%`, top: 0 }
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
},
|
|
122
|
+
i
|
|
123
|
+
);
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
const valueNode = showValue ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
128
|
+
"span",
|
|
129
|
+
{
|
|
130
|
+
className: utils.cn(
|
|
131
|
+
"shrink-0 font-semibold tabular-nums text-foreground",
|
|
132
|
+
isCell ? null : "text-xs"
|
|
133
|
+
),
|
|
134
|
+
children: valueText
|
|
135
|
+
}
|
|
136
|
+
) : null;
|
|
137
|
+
const label = icon || showLabel ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
138
|
+
"span",
|
|
139
|
+
{
|
|
140
|
+
className: utils.cn(
|
|
141
|
+
"inline-flex min-w-0 items-center gap-1 text-xs text-muted-foreground"
|
|
142
|
+
),
|
|
143
|
+
children: [
|
|
144
|
+
icon ? /* @__PURE__ */ jsxRuntime.jsx(ProgressBarsIcon, { icon }) : null,
|
|
145
|
+
showLabel ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: title }) : null
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
) : null;
|
|
149
|
+
const useHover = hoverCard && hoverRows.length > 0;
|
|
150
|
+
if (isCell) {
|
|
151
|
+
const cell = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
152
|
+
"span",
|
|
153
|
+
{
|
|
154
|
+
className: utils.cn(
|
|
155
|
+
"inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap align-middle text-xs",
|
|
156
|
+
className
|
|
157
|
+
),
|
|
158
|
+
...useHover ? {} : { title: titleText },
|
|
159
|
+
"aria-label": useHover ? titleText : hiddenAccessibleText,
|
|
160
|
+
children: [
|
|
161
|
+
label,
|
|
162
|
+
bars,
|
|
163
|
+
valueNode
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
return useHover ? /* @__PURE__ */ jsxRuntime.jsx(GaugeHoverCard.GaugeHoverCard, { title, rows: hoverRows, footer: hoverFooter, trigger: cell }) : cell;
|
|
168
|
+
}
|
|
169
|
+
const block = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
170
|
+
"div",
|
|
171
|
+
{
|
|
172
|
+
className: utils.cn("flex flex-col items-center gap-1", className),
|
|
173
|
+
...useHover ? {} : { title: hiddenAccessibleText },
|
|
174
|
+
"aria-label": useHover ? titleText : hiddenAccessibleText,
|
|
175
|
+
children: [
|
|
176
|
+
bars,
|
|
177
|
+
valueNode,
|
|
178
|
+
label
|
|
179
|
+
]
|
|
180
|
+
}
|
|
181
|
+
);
|
|
182
|
+
return useHover ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
183
|
+
GaugeHoverCard.GaugeHoverCard,
|
|
184
|
+
{
|
|
185
|
+
title,
|
|
186
|
+
rows: hoverRows,
|
|
187
|
+
footer: hoverFooter,
|
|
188
|
+
trigger: block,
|
|
189
|
+
className: "w-full justify-center"
|
|
190
|
+
}
|
|
191
|
+
) : block;
|
|
192
|
+
}
|
|
193
|
+
exports.ProgressBars = ProgressBars;
|
|
194
|
+
//# sourceMappingURL=ProgressBars.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProgressBars.cjs","sources":["../../src/data/ProgressBars.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { deriveProgressBars } from \"./ProgressBars.model\";\nimport { GaugeHoverCard, type GaugeHoverRow } from \"./GaugeHoverCard\";\n\nexport type ProgressBarsVariant = \"default\" | \"cell\";\nexport type ProgressBarsOrientation = \"horizontal\" | \"vertical\";\n\n/**\n * Describes what one bar represents, letting the same component render CPU cores,\n * memory gigabytes, or any other quantised capacity. Defaults model CPU cores.\n */\nexport interface ProgressBarsUnit {\n /** Raw value that fills one bar, in the domain of `usage`/`max`. Default 1000 (millicores → 1 core). */\n perBar?: number;\n /** Caption/tooltip suffix naming the unit, plural. Default \"cores\". */\n label?: string;\n /** Per-bar hover tooltip noun, singular. Default \"core\". */\n barLabel?: string;\n /** Format a bar-unit count for the caption. Default: integers as-is, else 1 decimal. */\n format?: (units: number) => string;\n}\n\n/** Summary statistics for the hover card, in the same domain as `usage`/`max`. */\nexport interface ProgressBarsStats {\n /** Smallest value over the window. */\n min: number;\n /** Largest value over the window. */\n max: number;\n /** Mean value over the window. */\n avg: number;\n}\n\nexport interface ProgressBarsProps {\n /** Usage that fills the bars, in the raw domain (e.g. CPU millicores). */\n usage: number | undefined;\n /**\n * The capacity, in the same raw domain as `usage`. Determines the number of\n * bars (one per `unit.perBar`). When omitted or 0, the bar count falls back to\n * the ceiling of the usage so an unbounded reading still renders.\n */\n max?: number;\n /** What one bar represents. Defaults to CPU cores (perBar 1000, label \"cores\"). */\n unit?: ProgressBarsUnit;\n title: string;\n /** Iconify name or static icon component shown beside the label. */\n icon?: string | StaticIconComponent;\n /**\n * Utilisation thresholds (percent of capacity) at which the fill turns amber\n * then red. Defaults to [75, 90].\n */\n thresholds?: [warning: number, danger: number];\n /** Visual density/layout. `cell` is a compact inline form for table/grid cells. */\n variant?: ProgressBarsVariant;\n /** Show the title text. Icons and values remain visible unless separately hidden. */\n showLabel?: boolean;\n /** Show the value/capacity caption. Icons and bars remain visible when false. */\n showValue?: boolean;\n /**\n * Include the capacity in the caption (\"2.3 / 4 cores\"). Defaults to false — the\n * caption shows only the current value (\"2.3 cores\") since the bars already\n * convey capacity. Set true to append the \"/ <capacity>\".\n */\n showCapacity?: boolean;\n /** Bar direction. Vertical bars fill bottom-up; horizontal bars fill left-to-right. */\n orientation?: ProgressBarsOrientation;\n /**\n * Summary stats for the hover card's Min/Max/Avg rows, in the SAME raw domain as\n * `usage`/`max` (NOT divided by perBar). Pass null to omit those rows.\n */\n stats?: ProgressBarsStats | null;\n /**\n * Wrap the bars in a hover card summarising the metric (label + current / min /\n * max / avg / capacity). Defaults to true.\n */\n hoverCard?: boolean;\n /** Footer note in the hover card, e.g. the look-back window (\"over last 1h\"). */\n hoverFooter?: ReactNode;\n className?: string;\n}\n\nfunction toneClass(pct: number, [warn, danger]: [number, number]): string {\n if (pct >= danger) return \"bg-red-500\";\n if (pct >= warn) return \"bg-amber-500\";\n return \"bg-emerald-500\";\n}\n\nfunction ProgressBarsIcon({ icon }: { icon: string | StaticIconComponent }) {\n if (typeof icon === \"string\") {\n return (\n <Icon\n name={icon}\n width={14}\n height={14}\n className=\"text-muted-foreground\"\n />\n );\n }\n return (\n <Icon\n icon={icon}\n width={14}\n height={14}\n className=\"text-muted-foreground\"\n />\n );\n}\n\nfunction defaultFormatUnits(units: number): string {\n return Number.isInteger(units) ? String(units) : units.toFixed(1);\n}\n\n/**\n * ProgressBars renders quantised utilisation as a row of bars — one bar per unit\n * of capacity (the ceiling of the limit) — filled left to right by the usage. The\n * bar that straddles the usage boundary is partially filled (\"blocked out\") to\n * show the fractional unit in use, and the trailing bars stay empty to show\n * headroom; the bar colour crosses warning and danger thresholds. A \"<used> /\n * <capacity>\" caption sits below with the icon+title. It is purely presentational\n * — pass plain `usage`/`max` numbers (TimeseriesCoreBars wraps it with live data).\n */\nexport function ProgressBars({\n usage,\n max,\n unit,\n title,\n icon,\n thresholds = [75, 90],\n variant = \"default\",\n showLabel = true,\n showValue = true,\n showCapacity = false,\n orientation,\n stats,\n hoverCard = true,\n hoverFooter,\n className,\n}: ProgressBarsProps) {\n const perBar = unit?.perBar ?? 1000;\n const unitLabel = unit?.label ?? \"cores\";\n const barLabel = unit?.barLabel ?? \"core\";\n const formatUnits = unit?.format ?? defaultFormatUnits;\n\n const model = deriveProgressBars(usage, max, perBar);\n const tone = toneClass(model.pct, thresholds);\n const usageText = formatUnits(model.usageUnits);\n const capacityText =\n model.limitUnits !== undefined ? formatUnits(model.limitUnits) : \"?\";\n const caption = !model.hasUsage\n ? \"—\"\n : showCapacity\n ? `${usageText} / ${capacityText} ${unitLabel}`\n : `${usageText} ${unitLabel}`;\n const compactCaption = !model.hasUsage\n ? \"—\"\n : showCapacity\n ? `${usageText}/${capacityText} ${unitLabel}`\n : `${usageText} ${unitLabel}`;\n const titleText = `${title}: ${compactCaption}`;\n const isCell = variant === \"cell\";\n\n // Hover card: surface current/min/max/avg/capacity in bar-units (stats are in\n // the raw domain, so divide by perBar) so they read in the same unit as the\n // caption. A bounded reading colours the current row by its threshold.\n const pctTone =\n model.limitUnits === undefined\n ? undefined\n : model.pct >= thresholds[1]\n ? \"text-red-500\"\n : model.pct >= thresholds[0]\n ? \"text-amber-500\"\n : \"text-emerald-500\";\n const fmt = (n: number) => `${formatUnits(n)} ${unitLabel}`;\n const hoverRows: GaugeHoverRow[] = model.hasUsage\n ? [\n { label: \"Current\", value: fmt(model.usageUnits), ...(pctTone ? { tone: pctTone } : {}) },\n ...(stats\n ? [\n { label: \"Min\", value: fmt(stats.min / perBar) },\n { label: \"Max\", value: fmt(stats.max / perBar) },\n { label: \"Avg\", value: fmt(stats.avg / perBar) },\n ]\n : []),\n ...(model.limitUnits !== undefined\n ? [{ label: \"Capacity\", value: fmt(model.limitUnits) }]\n : []),\n ]\n : [];\n\n const resolvedOrientation = orientation ?? \"vertical\";\n const isDense = model.barCount > 4;\n const valueText = isCell ? compactCaption : caption;\n const hiddenAccessibleText = !showLabel || !showValue ? titleText : undefined;\n const bars = (\n <span\n className={cn(\n \"flex shrink-0\",\n resolvedOrientation === \"vertical\"\n ? cn(\"items-end\", isCell ? \"h-4 gap-px\" : \"h-10 gap-0.5\")\n : cn(\n \"flex-col justify-center\",\n isCell ? \"h-4 w-10 gap-px\" : \"h-10 w-16 gap-0.5\",\n ),\n )}\n aria-hidden={isCell ? \"true\" : undefined}\n data-orientation={resolvedOrientation}\n data-bar-count={model.barCount}\n data-bar-density={isDense ? \"compact\" : \"default\"}\n >\n {model.bars.map((bar, i) => {\n const barPct = Math.round(bar.fill * 100);\n return (\n <span\n key={i}\n className={cn(\n \"relative overflow-hidden bg-muted\",\n resolvedOrientation === \"vertical\"\n ? cn(\n \"h-full\",\n isCell\n ? isDense\n ? \"w-[3px] rounded-[2px]\"\n : \"w-1.5 rounded-[2px]\"\n : isDense\n ? \"w-1 rounded-sm\"\n : \"w-2 rounded-sm\",\n )\n : cn(\"min-h-px w-full flex-1 rounded-[2px]\"),\n )}\n title={`${barLabel} ${i + 1}: ${barPct}%`}\n aria-label={!isCell ? `${barLabel} ${i + 1}: ${barPct}%` : undefined}\n data-fill={bar.fill}\n >\n <span\n className={cn(\n \"absolute bottom-0 left-0 transition-all duration-300\",\n tone,\n )}\n style={\n resolvedOrientation === \"vertical\"\n ? { height: `${barPct}%`, right: 0 }\n : { width: `${barPct}%`, top: 0 }\n }\n />\n </span>\n );\n })}\n </span>\n );\n const valueNode = showValue ? (\n <span\n className={cn(\n \"shrink-0 font-semibold tabular-nums text-foreground\",\n isCell ? null : \"text-xs\",\n )}\n >\n {valueText}\n </span>\n ) : null;\n const label =\n icon || showLabel ? (\n <span\n className={cn(\n \"inline-flex min-w-0 items-center gap-1 text-xs text-muted-foreground\",\n )}\n >\n {icon ? <ProgressBarsIcon icon={icon} /> : null}\n {showLabel ? <span className=\"min-w-0 truncate\">{title}</span> : null}\n </span>\n ) : null;\n\n const useHover = hoverCard && hoverRows.length > 0;\n\n if (isCell) {\n const cell = (\n <span\n className={cn(\n \"inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap align-middle text-xs\",\n className,\n )}\n {...(useHover ? {} : { title: titleText })}\n aria-label={useHover ? titleText : hiddenAccessibleText}\n >\n {label}\n {bars}\n {valueNode}\n </span>\n );\n return useHover ? (\n <GaugeHoverCard title={title} rows={hoverRows} footer={hoverFooter} trigger={cell} />\n ) : (\n cell\n );\n }\n\n const block = (\n <div\n className={cn(\"flex flex-col items-center gap-1\", className)}\n {...(useHover ? {} : { title: hiddenAccessibleText })}\n aria-label={useHover ? titleText : hiddenAccessibleText}\n >\n {bars}\n {valueNode}\n {label}\n </div>\n );\n return useHover ? (\n <GaugeHoverCard\n title={title}\n rows={hoverRows}\n footer={hoverFooter}\n trigger={block}\n className=\"w-full justify-center\"\n />\n ) : (\n block\n );\n}\n"],"names":["jsx","Icon","deriveProgressBars","cn","jsxs","GaugeHoverCard"],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { StaticIconComponent } from './Icon';
|
|
3
|
+
export type ProgressBarsVariant = "default" | "cell";
|
|
4
|
+
export type ProgressBarsOrientation = "horizontal" | "vertical";
|
|
5
|
+
/**
|
|
6
|
+
* Describes what one bar represents, letting the same component render CPU cores,
|
|
7
|
+
* memory gigabytes, or any other quantised capacity. Defaults model CPU cores.
|
|
8
|
+
*/
|
|
9
|
+
export interface ProgressBarsUnit {
|
|
10
|
+
/** Raw value that fills one bar, in the domain of `usage`/`max`. Default 1000 (millicores → 1 core). */
|
|
11
|
+
perBar?: number;
|
|
12
|
+
/** Caption/tooltip suffix naming the unit, plural. Default "cores". */
|
|
13
|
+
label?: string;
|
|
14
|
+
/** Per-bar hover tooltip noun, singular. Default "core". */
|
|
15
|
+
barLabel?: string;
|
|
16
|
+
/** Format a bar-unit count for the caption. Default: integers as-is, else 1 decimal. */
|
|
17
|
+
format?: (units: number) => string;
|
|
18
|
+
}
|
|
19
|
+
/** Summary statistics for the hover card, in the same domain as `usage`/`max`. */
|
|
20
|
+
export interface ProgressBarsStats {
|
|
21
|
+
/** Smallest value over the window. */
|
|
22
|
+
min: number;
|
|
23
|
+
/** Largest value over the window. */
|
|
24
|
+
max: number;
|
|
25
|
+
/** Mean value over the window. */
|
|
26
|
+
avg: number;
|
|
27
|
+
}
|
|
28
|
+
export interface ProgressBarsProps {
|
|
29
|
+
/** Usage that fills the bars, in the raw domain (e.g. CPU millicores). */
|
|
30
|
+
usage: number | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* The capacity, in the same raw domain as `usage`. Determines the number of
|
|
33
|
+
* bars (one per `unit.perBar`). When omitted or 0, the bar count falls back to
|
|
34
|
+
* the ceiling of the usage so an unbounded reading still renders.
|
|
35
|
+
*/
|
|
36
|
+
max?: number;
|
|
37
|
+
/** What one bar represents. Defaults to CPU cores (perBar 1000, label "cores"). */
|
|
38
|
+
unit?: ProgressBarsUnit;
|
|
39
|
+
title: string;
|
|
40
|
+
/** Iconify name or static icon component shown beside the label. */
|
|
41
|
+
icon?: string | StaticIconComponent;
|
|
42
|
+
/**
|
|
43
|
+
* Utilisation thresholds (percent of capacity) at which the fill turns amber
|
|
44
|
+
* then red. Defaults to [75, 90].
|
|
45
|
+
*/
|
|
46
|
+
thresholds?: [warning: number, danger: number];
|
|
47
|
+
/** Visual density/layout. `cell` is a compact inline form for table/grid cells. */
|
|
48
|
+
variant?: ProgressBarsVariant;
|
|
49
|
+
/** Show the title text. Icons and values remain visible unless separately hidden. */
|
|
50
|
+
showLabel?: boolean;
|
|
51
|
+
/** Show the value/capacity caption. Icons and bars remain visible when false. */
|
|
52
|
+
showValue?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Include the capacity in the caption ("2.3 / 4 cores"). Defaults to false — the
|
|
55
|
+
* caption shows only the current value ("2.3 cores") since the bars already
|
|
56
|
+
* convey capacity. Set true to append the "/ <capacity>".
|
|
57
|
+
*/
|
|
58
|
+
showCapacity?: boolean;
|
|
59
|
+
/** Bar direction. Vertical bars fill bottom-up; horizontal bars fill left-to-right. */
|
|
60
|
+
orientation?: ProgressBarsOrientation;
|
|
61
|
+
/**
|
|
62
|
+
* Summary stats for the hover card's Min/Max/Avg rows, in the SAME raw domain as
|
|
63
|
+
* `usage`/`max` (NOT divided by perBar). Pass null to omit those rows.
|
|
64
|
+
*/
|
|
65
|
+
stats?: ProgressBarsStats | null;
|
|
66
|
+
/**
|
|
67
|
+
* Wrap the bars in a hover card summarising the metric (label + current / min /
|
|
68
|
+
* max / avg / capacity). Defaults to true.
|
|
69
|
+
*/
|
|
70
|
+
hoverCard?: boolean;
|
|
71
|
+
/** Footer note in the hover card, e.g. the look-back window ("over last 1h"). */
|
|
72
|
+
hoverFooter?: ReactNode;
|
|
73
|
+
className?: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* ProgressBars renders quantised utilisation as a row of bars — one bar per unit
|
|
77
|
+
* of capacity (the ceiling of the limit) — filled left to right by the usage. The
|
|
78
|
+
* bar that straddles the usage boundary is partially filled ("blocked out") to
|
|
79
|
+
* show the fractional unit in use, and the trailing bars stay empty to show
|
|
80
|
+
* headroom; the bar colour crosses warning and danger thresholds. A "<used> /
|
|
81
|
+
* <capacity>" caption sits below with the icon+title. It is purely presentational
|
|
82
|
+
* — pass plain `usage`/`max` numbers (TimeseriesCoreBars wraps it with live data).
|
|
83
|
+
*/
|
|
84
|
+
export declare function ProgressBars({ usage, max, unit, title, icon, thresholds, variant, showLabel, showValue, showCapacity, orientation, stats, hoverCard, hoverFooter, className, }: ProgressBarsProps): import("react/jsx-runtime").JSX.Element;
|
|
85
|
+
//# sourceMappingURL=ProgressBars.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProgressBars.d.ts","sourceRoot":"","sources":["../../src/data/ProgressBars.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAQ,KAAK,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAIxD,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,MAAM,CAAC;AACrD,MAAM,MAAM,uBAAuB,GAAG,YAAY,GAAG,UAAU,CAAC;AAEhE;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wGAAwG;IACxG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wFAAwF;IACxF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CACpC;AAED,kFAAkF;AAClF,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAC;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/C,mFAAmF;IACnF,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,qFAAqF;IACrF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uFAAuF;IACvF,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC;;;OAGG;IACH,KAAK,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iFAAiF;IACjF,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiCD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,GAAG,EACH,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,UAAqB,EACrB,OAAmB,EACnB,SAAgB,EAChB,SAAgB,EAChB,YAAoB,EACpB,WAAW,EACX,KAAK,EACL,SAAgB,EAChB,WAAW,EACX,SAAS,GACV,EAAE,iBAAiB,2CAoLnB"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { Icon } from "./Icon.js";
|
|
4
|
+
import { deriveProgressBars } from "./ProgressBars.model.js";
|
|
5
|
+
import { GaugeHoverCard } from "./GaugeHoverCard.js";
|
|
6
|
+
function toneClass(pct, [warn, danger]) {
|
|
7
|
+
if (pct >= danger) return "bg-red-500";
|
|
8
|
+
if (pct >= warn) return "bg-amber-500";
|
|
9
|
+
return "bg-emerald-500";
|
|
10
|
+
}
|
|
11
|
+
function ProgressBarsIcon({ icon }) {
|
|
12
|
+
if (typeof icon === "string") {
|
|
13
|
+
return /* @__PURE__ */ jsx(
|
|
14
|
+
Icon,
|
|
15
|
+
{
|
|
16
|
+
name: icon,
|
|
17
|
+
width: 14,
|
|
18
|
+
height: 14,
|
|
19
|
+
className: "text-muted-foreground"
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
return /* @__PURE__ */ jsx(
|
|
24
|
+
Icon,
|
|
25
|
+
{
|
|
26
|
+
icon,
|
|
27
|
+
width: 14,
|
|
28
|
+
height: 14,
|
|
29
|
+
className: "text-muted-foreground"
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function defaultFormatUnits(units) {
|
|
34
|
+
return Number.isInteger(units) ? String(units) : units.toFixed(1);
|
|
35
|
+
}
|
|
36
|
+
function ProgressBars({
|
|
37
|
+
usage,
|
|
38
|
+
max,
|
|
39
|
+
unit,
|
|
40
|
+
title,
|
|
41
|
+
icon,
|
|
42
|
+
thresholds = [75, 90],
|
|
43
|
+
variant = "default",
|
|
44
|
+
showLabel = true,
|
|
45
|
+
showValue = true,
|
|
46
|
+
showCapacity = false,
|
|
47
|
+
orientation,
|
|
48
|
+
stats,
|
|
49
|
+
hoverCard = true,
|
|
50
|
+
hoverFooter,
|
|
51
|
+
className
|
|
52
|
+
}) {
|
|
53
|
+
const perBar = (unit == null ? void 0 : unit.perBar) ?? 1e3;
|
|
54
|
+
const unitLabel = (unit == null ? void 0 : unit.label) ?? "cores";
|
|
55
|
+
const barLabel = (unit == null ? void 0 : unit.barLabel) ?? "core";
|
|
56
|
+
const formatUnits = (unit == null ? void 0 : unit.format) ?? defaultFormatUnits;
|
|
57
|
+
const model = deriveProgressBars(usage, max, perBar);
|
|
58
|
+
const tone = toneClass(model.pct, thresholds);
|
|
59
|
+
const usageText = formatUnits(model.usageUnits);
|
|
60
|
+
const capacityText = model.limitUnits !== void 0 ? formatUnits(model.limitUnits) : "?";
|
|
61
|
+
const caption = !model.hasUsage ? "—" : showCapacity ? `${usageText} / ${capacityText} ${unitLabel}` : `${usageText} ${unitLabel}`;
|
|
62
|
+
const compactCaption = !model.hasUsage ? "—" : showCapacity ? `${usageText}/${capacityText} ${unitLabel}` : `${usageText} ${unitLabel}`;
|
|
63
|
+
const titleText = `${title}: ${compactCaption}`;
|
|
64
|
+
const isCell = variant === "cell";
|
|
65
|
+
const pctTone = model.limitUnits === void 0 ? void 0 : model.pct >= thresholds[1] ? "text-red-500" : model.pct >= thresholds[0] ? "text-amber-500" : "text-emerald-500";
|
|
66
|
+
const fmt = (n) => `${formatUnits(n)} ${unitLabel}`;
|
|
67
|
+
const hoverRows = model.hasUsage ? [
|
|
68
|
+
{ label: "Current", value: fmt(model.usageUnits), ...pctTone ? { tone: pctTone } : {} },
|
|
69
|
+
...stats ? [
|
|
70
|
+
{ label: "Min", value: fmt(stats.min / perBar) },
|
|
71
|
+
{ label: "Max", value: fmt(stats.max / perBar) },
|
|
72
|
+
{ label: "Avg", value: fmt(stats.avg / perBar) }
|
|
73
|
+
] : [],
|
|
74
|
+
...model.limitUnits !== void 0 ? [{ label: "Capacity", value: fmt(model.limitUnits) }] : []
|
|
75
|
+
] : [];
|
|
76
|
+
const resolvedOrientation = orientation ?? "vertical";
|
|
77
|
+
const isDense = model.barCount > 4;
|
|
78
|
+
const valueText = isCell ? compactCaption : caption;
|
|
79
|
+
const hiddenAccessibleText = !showLabel || !showValue ? titleText : void 0;
|
|
80
|
+
const bars = /* @__PURE__ */ jsx(
|
|
81
|
+
"span",
|
|
82
|
+
{
|
|
83
|
+
className: cn(
|
|
84
|
+
"flex shrink-0",
|
|
85
|
+
resolvedOrientation === "vertical" ? cn("items-end", isCell ? "h-4 gap-px" : "h-10 gap-0.5") : cn(
|
|
86
|
+
"flex-col justify-center",
|
|
87
|
+
isCell ? "h-4 w-10 gap-px" : "h-10 w-16 gap-0.5"
|
|
88
|
+
)
|
|
89
|
+
),
|
|
90
|
+
"aria-hidden": isCell ? "true" : void 0,
|
|
91
|
+
"data-orientation": resolvedOrientation,
|
|
92
|
+
"data-bar-count": model.barCount,
|
|
93
|
+
"data-bar-density": isDense ? "compact" : "default",
|
|
94
|
+
children: model.bars.map((bar, i) => {
|
|
95
|
+
const barPct = Math.round(bar.fill * 100);
|
|
96
|
+
return /* @__PURE__ */ jsx(
|
|
97
|
+
"span",
|
|
98
|
+
{
|
|
99
|
+
className: cn(
|
|
100
|
+
"relative overflow-hidden bg-muted",
|
|
101
|
+
resolvedOrientation === "vertical" ? cn(
|
|
102
|
+
"h-full",
|
|
103
|
+
isCell ? isDense ? "w-[3px] rounded-[2px]" : "w-1.5 rounded-[2px]" : isDense ? "w-1 rounded-sm" : "w-2 rounded-sm"
|
|
104
|
+
) : cn("min-h-px w-full flex-1 rounded-[2px]")
|
|
105
|
+
),
|
|
106
|
+
title: `${barLabel} ${i + 1}: ${barPct}%`,
|
|
107
|
+
"aria-label": !isCell ? `${barLabel} ${i + 1}: ${barPct}%` : void 0,
|
|
108
|
+
"data-fill": bar.fill,
|
|
109
|
+
children: /* @__PURE__ */ jsx(
|
|
110
|
+
"span",
|
|
111
|
+
{
|
|
112
|
+
className: cn(
|
|
113
|
+
"absolute bottom-0 left-0 transition-all duration-300",
|
|
114
|
+
tone
|
|
115
|
+
),
|
|
116
|
+
style: resolvedOrientation === "vertical" ? { height: `${barPct}%`, right: 0 } : { width: `${barPct}%`, top: 0 }
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
},
|
|
120
|
+
i
|
|
121
|
+
);
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
const valueNode = showValue ? /* @__PURE__ */ jsx(
|
|
126
|
+
"span",
|
|
127
|
+
{
|
|
128
|
+
className: cn(
|
|
129
|
+
"shrink-0 font-semibold tabular-nums text-foreground",
|
|
130
|
+
isCell ? null : "text-xs"
|
|
131
|
+
),
|
|
132
|
+
children: valueText
|
|
133
|
+
}
|
|
134
|
+
) : null;
|
|
135
|
+
const label = icon || showLabel ? /* @__PURE__ */ jsxs(
|
|
136
|
+
"span",
|
|
137
|
+
{
|
|
138
|
+
className: cn(
|
|
139
|
+
"inline-flex min-w-0 items-center gap-1 text-xs text-muted-foreground"
|
|
140
|
+
),
|
|
141
|
+
children: [
|
|
142
|
+
icon ? /* @__PURE__ */ jsx(ProgressBarsIcon, { icon }) : null,
|
|
143
|
+
showLabel ? /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: title }) : null
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
) : null;
|
|
147
|
+
const useHover = hoverCard && hoverRows.length > 0;
|
|
148
|
+
if (isCell) {
|
|
149
|
+
const cell = /* @__PURE__ */ jsxs(
|
|
150
|
+
"span",
|
|
151
|
+
{
|
|
152
|
+
className: cn(
|
|
153
|
+
"inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap align-middle text-xs",
|
|
154
|
+
className
|
|
155
|
+
),
|
|
156
|
+
...useHover ? {} : { title: titleText },
|
|
157
|
+
"aria-label": useHover ? titleText : hiddenAccessibleText,
|
|
158
|
+
children: [
|
|
159
|
+
label,
|
|
160
|
+
bars,
|
|
161
|
+
valueNode
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
return useHover ? /* @__PURE__ */ jsx(GaugeHoverCard, { title, rows: hoverRows, footer: hoverFooter, trigger: cell }) : cell;
|
|
166
|
+
}
|
|
167
|
+
const block = /* @__PURE__ */ jsxs(
|
|
168
|
+
"div",
|
|
169
|
+
{
|
|
170
|
+
className: cn("flex flex-col items-center gap-1", className),
|
|
171
|
+
...useHover ? {} : { title: hiddenAccessibleText },
|
|
172
|
+
"aria-label": useHover ? titleText : hiddenAccessibleText,
|
|
173
|
+
children: [
|
|
174
|
+
bars,
|
|
175
|
+
valueNode,
|
|
176
|
+
label
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
);
|
|
180
|
+
return useHover ? /* @__PURE__ */ jsx(
|
|
181
|
+
GaugeHoverCard,
|
|
182
|
+
{
|
|
183
|
+
title,
|
|
184
|
+
rows: hoverRows,
|
|
185
|
+
footer: hoverFooter,
|
|
186
|
+
trigger: block,
|
|
187
|
+
className: "w-full justify-center"
|
|
188
|
+
}
|
|
189
|
+
) : block;
|
|
190
|
+
}
|
|
191
|
+
export {
|
|
192
|
+
ProgressBars
|
|
193
|
+
};
|
|
194
|
+
//# sourceMappingURL=ProgressBars.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProgressBars.js","sources":["../../src/data/ProgressBars.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"./Icon\";\nimport { deriveProgressBars } from \"./ProgressBars.model\";\nimport { GaugeHoverCard, type GaugeHoverRow } from \"./GaugeHoverCard\";\n\nexport type ProgressBarsVariant = \"default\" | \"cell\";\nexport type ProgressBarsOrientation = \"horizontal\" | \"vertical\";\n\n/**\n * Describes what one bar represents, letting the same component render CPU cores,\n * memory gigabytes, or any other quantised capacity. Defaults model CPU cores.\n */\nexport interface ProgressBarsUnit {\n /** Raw value that fills one bar, in the domain of `usage`/`max`. Default 1000 (millicores → 1 core). */\n perBar?: number;\n /** Caption/tooltip suffix naming the unit, plural. Default \"cores\". */\n label?: string;\n /** Per-bar hover tooltip noun, singular. Default \"core\". */\n barLabel?: string;\n /** Format a bar-unit count for the caption. Default: integers as-is, else 1 decimal. */\n format?: (units: number) => string;\n}\n\n/** Summary statistics for the hover card, in the same domain as `usage`/`max`. */\nexport interface ProgressBarsStats {\n /** Smallest value over the window. */\n min: number;\n /** Largest value over the window. */\n max: number;\n /** Mean value over the window. */\n avg: number;\n}\n\nexport interface ProgressBarsProps {\n /** Usage that fills the bars, in the raw domain (e.g. CPU millicores). */\n usage: number | undefined;\n /**\n * The capacity, in the same raw domain as `usage`. Determines the number of\n * bars (one per `unit.perBar`). When omitted or 0, the bar count falls back to\n * the ceiling of the usage so an unbounded reading still renders.\n */\n max?: number;\n /** What one bar represents. Defaults to CPU cores (perBar 1000, label \"cores\"). */\n unit?: ProgressBarsUnit;\n title: string;\n /** Iconify name or static icon component shown beside the label. */\n icon?: string | StaticIconComponent;\n /**\n * Utilisation thresholds (percent of capacity) at which the fill turns amber\n * then red. Defaults to [75, 90].\n */\n thresholds?: [warning: number, danger: number];\n /** Visual density/layout. `cell` is a compact inline form for table/grid cells. */\n variant?: ProgressBarsVariant;\n /** Show the title text. Icons and values remain visible unless separately hidden. */\n showLabel?: boolean;\n /** Show the value/capacity caption. Icons and bars remain visible when false. */\n showValue?: boolean;\n /**\n * Include the capacity in the caption (\"2.3 / 4 cores\"). Defaults to false — the\n * caption shows only the current value (\"2.3 cores\") since the bars already\n * convey capacity. Set true to append the \"/ <capacity>\".\n */\n showCapacity?: boolean;\n /** Bar direction. Vertical bars fill bottom-up; horizontal bars fill left-to-right. */\n orientation?: ProgressBarsOrientation;\n /**\n * Summary stats for the hover card's Min/Max/Avg rows, in the SAME raw domain as\n * `usage`/`max` (NOT divided by perBar). Pass null to omit those rows.\n */\n stats?: ProgressBarsStats | null;\n /**\n * Wrap the bars in a hover card summarising the metric (label + current / min /\n * max / avg / capacity). Defaults to true.\n */\n hoverCard?: boolean;\n /** Footer note in the hover card, e.g. the look-back window (\"over last 1h\"). */\n hoverFooter?: ReactNode;\n className?: string;\n}\n\nfunction toneClass(pct: number, [warn, danger]: [number, number]): string {\n if (pct >= danger) return \"bg-red-500\";\n if (pct >= warn) return \"bg-amber-500\";\n return \"bg-emerald-500\";\n}\n\nfunction ProgressBarsIcon({ icon }: { icon: string | StaticIconComponent }) {\n if (typeof icon === \"string\") {\n return (\n <Icon\n name={icon}\n width={14}\n height={14}\n className=\"text-muted-foreground\"\n />\n );\n }\n return (\n <Icon\n icon={icon}\n width={14}\n height={14}\n className=\"text-muted-foreground\"\n />\n );\n}\n\nfunction defaultFormatUnits(units: number): string {\n return Number.isInteger(units) ? String(units) : units.toFixed(1);\n}\n\n/**\n * ProgressBars renders quantised utilisation as a row of bars — one bar per unit\n * of capacity (the ceiling of the limit) — filled left to right by the usage. The\n * bar that straddles the usage boundary is partially filled (\"blocked out\") to\n * show the fractional unit in use, and the trailing bars stay empty to show\n * headroom; the bar colour crosses warning and danger thresholds. A \"<used> /\n * <capacity>\" caption sits below with the icon+title. It is purely presentational\n * — pass plain `usage`/`max` numbers (TimeseriesCoreBars wraps it with live data).\n */\nexport function ProgressBars({\n usage,\n max,\n unit,\n title,\n icon,\n thresholds = [75, 90],\n variant = \"default\",\n showLabel = true,\n showValue = true,\n showCapacity = false,\n orientation,\n stats,\n hoverCard = true,\n hoverFooter,\n className,\n}: ProgressBarsProps) {\n const perBar = unit?.perBar ?? 1000;\n const unitLabel = unit?.label ?? \"cores\";\n const barLabel = unit?.barLabel ?? \"core\";\n const formatUnits = unit?.format ?? defaultFormatUnits;\n\n const model = deriveProgressBars(usage, max, perBar);\n const tone = toneClass(model.pct, thresholds);\n const usageText = formatUnits(model.usageUnits);\n const capacityText =\n model.limitUnits !== undefined ? formatUnits(model.limitUnits) : \"?\";\n const caption = !model.hasUsage\n ? \"—\"\n : showCapacity\n ? `${usageText} / ${capacityText} ${unitLabel}`\n : `${usageText} ${unitLabel}`;\n const compactCaption = !model.hasUsage\n ? \"—\"\n : showCapacity\n ? `${usageText}/${capacityText} ${unitLabel}`\n : `${usageText} ${unitLabel}`;\n const titleText = `${title}: ${compactCaption}`;\n const isCell = variant === \"cell\";\n\n // Hover card: surface current/min/max/avg/capacity in bar-units (stats are in\n // the raw domain, so divide by perBar) so they read in the same unit as the\n // caption. A bounded reading colours the current row by its threshold.\n const pctTone =\n model.limitUnits === undefined\n ? undefined\n : model.pct >= thresholds[1]\n ? \"text-red-500\"\n : model.pct >= thresholds[0]\n ? \"text-amber-500\"\n : \"text-emerald-500\";\n const fmt = (n: number) => `${formatUnits(n)} ${unitLabel}`;\n const hoverRows: GaugeHoverRow[] = model.hasUsage\n ? [\n { label: \"Current\", value: fmt(model.usageUnits), ...(pctTone ? { tone: pctTone } : {}) },\n ...(stats\n ? [\n { label: \"Min\", value: fmt(stats.min / perBar) },\n { label: \"Max\", value: fmt(stats.max / perBar) },\n { label: \"Avg\", value: fmt(stats.avg / perBar) },\n ]\n : []),\n ...(model.limitUnits !== undefined\n ? [{ label: \"Capacity\", value: fmt(model.limitUnits) }]\n : []),\n ]\n : [];\n\n const resolvedOrientation = orientation ?? \"vertical\";\n const isDense = model.barCount > 4;\n const valueText = isCell ? compactCaption : caption;\n const hiddenAccessibleText = !showLabel || !showValue ? titleText : undefined;\n const bars = (\n <span\n className={cn(\n \"flex shrink-0\",\n resolvedOrientation === \"vertical\"\n ? cn(\"items-end\", isCell ? \"h-4 gap-px\" : \"h-10 gap-0.5\")\n : cn(\n \"flex-col justify-center\",\n isCell ? \"h-4 w-10 gap-px\" : \"h-10 w-16 gap-0.5\",\n ),\n )}\n aria-hidden={isCell ? \"true\" : undefined}\n data-orientation={resolvedOrientation}\n data-bar-count={model.barCount}\n data-bar-density={isDense ? \"compact\" : \"default\"}\n >\n {model.bars.map((bar, i) => {\n const barPct = Math.round(bar.fill * 100);\n return (\n <span\n key={i}\n className={cn(\n \"relative overflow-hidden bg-muted\",\n resolvedOrientation === \"vertical\"\n ? cn(\n \"h-full\",\n isCell\n ? isDense\n ? \"w-[3px] rounded-[2px]\"\n : \"w-1.5 rounded-[2px]\"\n : isDense\n ? \"w-1 rounded-sm\"\n : \"w-2 rounded-sm\",\n )\n : cn(\"min-h-px w-full flex-1 rounded-[2px]\"),\n )}\n title={`${barLabel} ${i + 1}: ${barPct}%`}\n aria-label={!isCell ? `${barLabel} ${i + 1}: ${barPct}%` : undefined}\n data-fill={bar.fill}\n >\n <span\n className={cn(\n \"absolute bottom-0 left-0 transition-all duration-300\",\n tone,\n )}\n style={\n resolvedOrientation === \"vertical\"\n ? { height: `${barPct}%`, right: 0 }\n : { width: `${barPct}%`, top: 0 }\n }\n />\n </span>\n );\n })}\n </span>\n );\n const valueNode = showValue ? (\n <span\n className={cn(\n \"shrink-0 font-semibold tabular-nums text-foreground\",\n isCell ? null : \"text-xs\",\n )}\n >\n {valueText}\n </span>\n ) : null;\n const label =\n icon || showLabel ? (\n <span\n className={cn(\n \"inline-flex min-w-0 items-center gap-1 text-xs text-muted-foreground\",\n )}\n >\n {icon ? <ProgressBarsIcon icon={icon} /> : null}\n {showLabel ? <span className=\"min-w-0 truncate\">{title}</span> : null}\n </span>\n ) : null;\n\n const useHover = hoverCard && hoverRows.length > 0;\n\n if (isCell) {\n const cell = (\n <span\n className={cn(\n \"inline-flex min-w-0 items-center gap-1.5 whitespace-nowrap align-middle text-xs\",\n className,\n )}\n {...(useHover ? {} : { title: titleText })}\n aria-label={useHover ? titleText : hiddenAccessibleText}\n >\n {label}\n {bars}\n {valueNode}\n </span>\n );\n return useHover ? (\n <GaugeHoverCard title={title} rows={hoverRows} footer={hoverFooter} trigger={cell} />\n ) : (\n cell\n );\n }\n\n const block = (\n <div\n className={cn(\"flex flex-col items-center gap-1\", className)}\n {...(useHover ? {} : { title: hiddenAccessibleText })}\n aria-label={useHover ? titleText : hiddenAccessibleText}\n >\n {bars}\n {valueNode}\n {label}\n </div>\n );\n return useHover ? (\n <GaugeHoverCard\n title={title}\n rows={hoverRows}\n footer={hoverFooter}\n trigger={block}\n className=\"w-full justify-center\"\n />\n ) : (\n block\n );\n}\n"],"names":[],"mappings":"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"}
|