@camstack/ui-library 0.1.34 → 0.1.36
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/index.cjs +778 -460
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -4
- package/dist/index.d.ts +32 -4
- package/dist/index.js +728 -413
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -683,7 +683,7 @@ function DialogTrigger({ children, ...props }) {
|
|
|
683
683
|
return /* @__PURE__ */ jsx13("button", { type: "button", onClick: () => setOpen(true), ...props, children });
|
|
684
684
|
}
|
|
685
685
|
var contentVariants = cva7(
|
|
686
|
-
"bg-background-elevated border border-border rounded-lg p-4 backdrop:bg-black/50 backdrop:backdrop-blur-sm",
|
|
686
|
+
"bg-background-elevated border border-border rounded-lg p-4 backdrop:bg-black/50 backdrop:backdrop-blur-sm max-w-[calc(100vw-2rem)] max-h-[calc(100dvh-2rem)] overflow-y-auto",
|
|
687
687
|
{
|
|
688
688
|
variants: {
|
|
689
689
|
width: {
|
|
@@ -917,12 +917,92 @@ import {
|
|
|
917
917
|
createContext as createContext5,
|
|
918
918
|
useCallback as useCallback4,
|
|
919
919
|
useContext as useContext5,
|
|
920
|
-
useEffect as
|
|
920
|
+
useEffect as useEffect5,
|
|
921
921
|
useId as useId4,
|
|
922
922
|
useRef as useRef4,
|
|
923
923
|
useState as useState5
|
|
924
924
|
} from "react";
|
|
925
|
-
|
|
925
|
+
|
|
926
|
+
// src/hooks/use-is-mobile.ts
|
|
927
|
+
import { useSyncExternalStore } from "react";
|
|
928
|
+
var MOBILE_QUERY = "(max-width: 767px)";
|
|
929
|
+
function subscribe(callback) {
|
|
930
|
+
const mql = window.matchMedia(MOBILE_QUERY);
|
|
931
|
+
mql.addEventListener("change", callback);
|
|
932
|
+
return () => mql.removeEventListener("change", callback);
|
|
933
|
+
}
|
|
934
|
+
function getSnapshot() {
|
|
935
|
+
return window.matchMedia(MOBILE_QUERY).matches;
|
|
936
|
+
}
|
|
937
|
+
function getServerSnapshot() {
|
|
938
|
+
return false;
|
|
939
|
+
}
|
|
940
|
+
function useIsMobile() {
|
|
941
|
+
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// src/primitives/bottom-sheet.tsx
|
|
945
|
+
import { useEffect as useEffect4 } from "react";
|
|
946
|
+
import { X } from "lucide-react";
|
|
947
|
+
import { Fragment, jsx as jsx16, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
948
|
+
function BottomSheet({ open, onClose, title, children, className }) {
|
|
949
|
+
useEffect4(() => {
|
|
950
|
+
if (!open) return;
|
|
951
|
+
const handleKeyDown = (e) => {
|
|
952
|
+
if (e.key === "Escape") onClose();
|
|
953
|
+
};
|
|
954
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
955
|
+
document.body.style.overflow = "hidden";
|
|
956
|
+
return () => {
|
|
957
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
958
|
+
document.body.style.overflow = "";
|
|
959
|
+
};
|
|
960
|
+
}, [open, onClose]);
|
|
961
|
+
return /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
962
|
+
/* @__PURE__ */ jsx16(
|
|
963
|
+
"div",
|
|
964
|
+
{
|
|
965
|
+
className: cn(
|
|
966
|
+
"fixed inset-0 z-40 bg-black/50 transition-opacity duration-200",
|
|
967
|
+
open ? "opacity-100" : "pointer-events-none opacity-0"
|
|
968
|
+
),
|
|
969
|
+
onClick: onClose,
|
|
970
|
+
"aria-hidden": "true"
|
|
971
|
+
}
|
|
972
|
+
),
|
|
973
|
+
/* @__PURE__ */ jsxs5(
|
|
974
|
+
"div",
|
|
975
|
+
{
|
|
976
|
+
role: "dialog",
|
|
977
|
+
"aria-modal": "true",
|
|
978
|
+
className: cn(
|
|
979
|
+
"fixed inset-x-0 bottom-0 z-50 flex flex-col bg-background-elevated border-t border-border rounded-t-xl shadow-2xl transition-transform duration-200 ease-out",
|
|
980
|
+
"max-h-[80dvh]",
|
|
981
|
+
open ? "translate-y-0" : "translate-y-full",
|
|
982
|
+
className
|
|
983
|
+
),
|
|
984
|
+
children: [
|
|
985
|
+
/* @__PURE__ */ jsx16("div", { className: "flex justify-center pt-2 pb-1", children: /* @__PURE__ */ jsx16("div", { className: "h-1 w-8 rounded-full bg-foreground-subtle/30" }) }),
|
|
986
|
+
title && /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between px-4 pb-2", children: [
|
|
987
|
+
/* @__PURE__ */ jsx16("span", { className: "text-sm font-medium text-foreground", children: title }),
|
|
988
|
+
/* @__PURE__ */ jsx16(
|
|
989
|
+
"button",
|
|
990
|
+
{
|
|
991
|
+
onClick: onClose,
|
|
992
|
+
className: "p-1 rounded-md hover:bg-surface-hover text-foreground-muted transition-colors",
|
|
993
|
+
children: /* @__PURE__ */ jsx16(X, { className: "h-4 w-4" })
|
|
994
|
+
}
|
|
995
|
+
)
|
|
996
|
+
] }),
|
|
997
|
+
/* @__PURE__ */ jsx16("div", { className: "flex-1 overflow-y-auto px-4 pb-4", children })
|
|
998
|
+
]
|
|
999
|
+
}
|
|
1000
|
+
)
|
|
1001
|
+
] });
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
// src/primitives/popover.tsx
|
|
1005
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
926
1006
|
var PopoverContext = createContext5(null);
|
|
927
1007
|
function usePopoverContext() {
|
|
928
1008
|
const ctx = useContext5(PopoverContext);
|
|
@@ -941,11 +1021,11 @@ function Popover({ children, open: controlledOpen, onOpenChange }) {
|
|
|
941
1021
|
},
|
|
942
1022
|
[controlledOpen, onOpenChange]
|
|
943
1023
|
);
|
|
944
|
-
return /* @__PURE__ */
|
|
1024
|
+
return /* @__PURE__ */ jsx17(PopoverContext.Provider, { value: { open, setOpen, triggerId, contentId }, children: /* @__PURE__ */ jsx17("div", { className: "relative inline-block", children }) });
|
|
945
1025
|
}
|
|
946
1026
|
function PopoverTrigger({ children, ...props }) {
|
|
947
1027
|
const { open, setOpen, triggerId, contentId } = usePopoverContext();
|
|
948
|
-
return /* @__PURE__ */
|
|
1028
|
+
return /* @__PURE__ */ jsx17(
|
|
949
1029
|
"button",
|
|
950
1030
|
{
|
|
951
1031
|
type: "button",
|
|
@@ -961,9 +1041,10 @@ function PopoverTrigger({ children, ...props }) {
|
|
|
961
1041
|
}
|
|
962
1042
|
function PopoverContent({ className, children, ...props }) {
|
|
963
1043
|
const { open, setOpen, contentId, triggerId } = usePopoverContext();
|
|
1044
|
+
const isMobile = useIsMobile();
|
|
964
1045
|
const ref = useRef4(null);
|
|
965
|
-
|
|
966
|
-
if (!open) return;
|
|
1046
|
+
useEffect5(() => {
|
|
1047
|
+
if (!open || isMobile) return;
|
|
967
1048
|
const handler = (e) => {
|
|
968
1049
|
const el = ref.current;
|
|
969
1050
|
const trigger = document.getElementById(triggerId);
|
|
@@ -980,9 +1061,12 @@ function PopoverContent({ className, children, ...props }) {
|
|
|
980
1061
|
document.removeEventListener("mousedown", handler);
|
|
981
1062
|
document.removeEventListener("keydown", escHandler);
|
|
982
1063
|
};
|
|
983
|
-
}, [open, setOpen, triggerId]);
|
|
1064
|
+
}, [open, setOpen, triggerId, isMobile]);
|
|
984
1065
|
if (!open) return null;
|
|
985
|
-
|
|
1066
|
+
if (isMobile) {
|
|
1067
|
+
return /* @__PURE__ */ jsx17(BottomSheet, { open, onClose: () => setOpen(false), children });
|
|
1068
|
+
}
|
|
1069
|
+
return /* @__PURE__ */ jsx17(
|
|
986
1070
|
"div",
|
|
987
1071
|
{
|
|
988
1072
|
ref,
|
|
@@ -1006,7 +1090,7 @@ import {
|
|
|
1006
1090
|
useContext as useContext6,
|
|
1007
1091
|
useState as useState6
|
|
1008
1092
|
} from "react";
|
|
1009
|
-
import { jsx as
|
|
1093
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
1010
1094
|
var TabsContext = createContext6(null);
|
|
1011
1095
|
function useTabsContext() {
|
|
1012
1096
|
const ctx = useContext6(TabsContext);
|
|
@@ -1029,10 +1113,10 @@ function Tabs({
|
|
|
1029
1113
|
},
|
|
1030
1114
|
[controlledValue, onValueChange]
|
|
1031
1115
|
);
|
|
1032
|
-
return /* @__PURE__ */
|
|
1116
|
+
return /* @__PURE__ */ jsx18(TabsContext.Provider, { value: { value, setValue }, children: /* @__PURE__ */ jsx18("div", { className, ...props }) });
|
|
1033
1117
|
}
|
|
1034
1118
|
function TabsList({ className, ...props }) {
|
|
1035
|
-
return /* @__PURE__ */
|
|
1119
|
+
return /* @__PURE__ */ jsx18(
|
|
1036
1120
|
"div",
|
|
1037
1121
|
{
|
|
1038
1122
|
role: "tablist",
|
|
@@ -1045,7 +1129,7 @@ function TabsTrigger({ value, className, ...props }) {
|
|
|
1045
1129
|
const { value: activeValue, setValue } = useTabsContext();
|
|
1046
1130
|
const isActive = value === activeValue;
|
|
1047
1131
|
const panelId = `tabpanel-${value}`;
|
|
1048
|
-
return /* @__PURE__ */
|
|
1132
|
+
return /* @__PURE__ */ jsx18(
|
|
1049
1133
|
"button",
|
|
1050
1134
|
{
|
|
1051
1135
|
type: "button",
|
|
@@ -1066,7 +1150,7 @@ function TabsTrigger({ value, className, ...props }) {
|
|
|
1066
1150
|
function TabsContent({ value, className, ...props }) {
|
|
1067
1151
|
const { value: activeValue } = useTabsContext();
|
|
1068
1152
|
if (value !== activeValue) return null;
|
|
1069
|
-
return /* @__PURE__ */
|
|
1153
|
+
return /* @__PURE__ */ jsx18(
|
|
1070
1154
|
"div",
|
|
1071
1155
|
{
|
|
1072
1156
|
role: "tabpanel",
|
|
@@ -1079,10 +1163,10 @@ function TabsContent({ value, className, ...props }) {
|
|
|
1079
1163
|
|
|
1080
1164
|
// src/primitives/scroll-area.tsx
|
|
1081
1165
|
import { forwardRef as forwardRef13 } from "react";
|
|
1082
|
-
import { jsx as
|
|
1166
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
1083
1167
|
var ScrollArea = forwardRef13(
|
|
1084
1168
|
({ className, ...props }, ref) => {
|
|
1085
|
-
return /* @__PURE__ */
|
|
1169
|
+
return /* @__PURE__ */ jsx19(
|
|
1086
1170
|
"div",
|
|
1087
1171
|
{
|
|
1088
1172
|
ref,
|
|
@@ -1098,9 +1182,9 @@ var ScrollArea = forwardRef13(
|
|
|
1098
1182
|
ScrollArea.displayName = "ScrollArea";
|
|
1099
1183
|
|
|
1100
1184
|
// src/primitives/floating-panel.tsx
|
|
1101
|
-
import { useRef as useRef5, useState as useState7, useCallback as useCallback6, useEffect as
|
|
1102
|
-
import { X, Minimize2, Maximize2, GripHorizontal } from "lucide-react";
|
|
1103
|
-
import { jsx as
|
|
1185
|
+
import { useRef as useRef5, useState as useState7, useCallback as useCallback6, useEffect as useEffect6 } from "react";
|
|
1186
|
+
import { X as X2, Minimize2, Maximize2, GripHorizontal } from "lucide-react";
|
|
1187
|
+
import { jsx as jsx20, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1104
1188
|
function FloatingPanel({
|
|
1105
1189
|
title,
|
|
1106
1190
|
onClose,
|
|
@@ -1118,6 +1202,7 @@ function FloatingPanel({
|
|
|
1118
1202
|
const dragging = useRef5(false);
|
|
1119
1203
|
const resizing = useRef5(false);
|
|
1120
1204
|
const offset = useRef5({ x: 0, y: 0 });
|
|
1205
|
+
const isMobile = useIsMobile();
|
|
1121
1206
|
const onDragStart = useCallback6((e) => {
|
|
1122
1207
|
e.preventDefault();
|
|
1123
1208
|
dragging.current = true;
|
|
@@ -1129,7 +1214,7 @@ function FloatingPanel({
|
|
|
1129
1214
|
resizing.current = true;
|
|
1130
1215
|
offset.current = { x: e.clientX, y: e.clientY };
|
|
1131
1216
|
}, []);
|
|
1132
|
-
|
|
1217
|
+
useEffect6(() => {
|
|
1133
1218
|
const onMouseMove = (e) => {
|
|
1134
1219
|
if (dragging.current) setPos({ x: e.clientX - offset.current.x, y: e.clientY - offset.current.y });
|
|
1135
1220
|
if (resizing.current) {
|
|
@@ -1150,7 +1235,43 @@ function FloatingPanel({
|
|
|
1150
1235
|
window.removeEventListener("mouseup", onMouseUp);
|
|
1151
1236
|
};
|
|
1152
1237
|
}, [minWidth, minHeight]);
|
|
1153
|
-
|
|
1238
|
+
if (isMobile) {
|
|
1239
|
+
return /* @__PURE__ */ jsxs6(
|
|
1240
|
+
"div",
|
|
1241
|
+
{
|
|
1242
|
+
className: cn(
|
|
1243
|
+
"fixed inset-x-0 bottom-0 z-50 rounded-t-xl border-t border-border bg-background-elevated shadow-2xl flex flex-col overflow-hidden",
|
|
1244
|
+
className
|
|
1245
|
+
),
|
|
1246
|
+
style: { maxHeight: "60dvh" },
|
|
1247
|
+
children: [
|
|
1248
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2 px-3 py-2 border-b border-border shrink-0 bg-surface", children: [
|
|
1249
|
+
/* @__PURE__ */ jsx20("span", { className: "text-[11px] font-medium truncate", children: title }),
|
|
1250
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1 shrink-0", children: [
|
|
1251
|
+
/* @__PURE__ */ jsx20(
|
|
1252
|
+
"button",
|
|
1253
|
+
{
|
|
1254
|
+
onClick: () => setMinimized(!minimized),
|
|
1255
|
+
className: "p-0.5 rounded hover:bg-surface-hover text-foreground-muted transition-colors",
|
|
1256
|
+
children: minimized ? /* @__PURE__ */ jsx20(Maximize2, { size: 12 }) : /* @__PURE__ */ jsx20(Minimize2, { size: 12 })
|
|
1257
|
+
}
|
|
1258
|
+
),
|
|
1259
|
+
/* @__PURE__ */ jsx20(
|
|
1260
|
+
"button",
|
|
1261
|
+
{
|
|
1262
|
+
onClick: onClose,
|
|
1263
|
+
className: "p-0.5 rounded hover:bg-danger/20 text-foreground-muted hover:text-danger transition-colors",
|
|
1264
|
+
children: /* @__PURE__ */ jsx20(X2, { size: 12 })
|
|
1265
|
+
}
|
|
1266
|
+
)
|
|
1267
|
+
] })
|
|
1268
|
+
] }),
|
|
1269
|
+
!minimized && /* @__PURE__ */ jsx20("div", { className: "flex-1 min-h-0 overflow-y-auto", children })
|
|
1270
|
+
]
|
|
1271
|
+
}
|
|
1272
|
+
);
|
|
1273
|
+
}
|
|
1274
|
+
return /* @__PURE__ */ jsxs6(
|
|
1154
1275
|
"div",
|
|
1155
1276
|
{
|
|
1156
1277
|
className: cn(
|
|
@@ -1159,42 +1280,42 @@ function FloatingPanel({
|
|
|
1159
1280
|
),
|
|
1160
1281
|
style: { left: pos.x, top: pos.y, width: minimized ? 280 : size.w, height: minimized ? "auto" : size.h },
|
|
1161
1282
|
children: [
|
|
1162
|
-
/* @__PURE__ */
|
|
1283
|
+
/* @__PURE__ */ jsxs6(
|
|
1163
1284
|
"div",
|
|
1164
1285
|
{
|
|
1165
1286
|
onMouseDown: onDragStart,
|
|
1166
1287
|
className: "flex items-center justify-between gap-2 px-3 py-2 border-b border-border cursor-move select-none shrink-0 bg-surface",
|
|
1167
1288
|
children: [
|
|
1168
|
-
/* @__PURE__ */
|
|
1169
|
-
/* @__PURE__ */
|
|
1170
|
-
/* @__PURE__ */
|
|
1289
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
1290
|
+
/* @__PURE__ */ jsx20(GripHorizontal, { size: 12, className: "text-foreground-subtle shrink-0" }),
|
|
1291
|
+
/* @__PURE__ */ jsx20("span", { className: "text-[11px] font-medium truncate", children: title })
|
|
1171
1292
|
] }),
|
|
1172
|
-
/* @__PURE__ */
|
|
1173
|
-
/* @__PURE__ */
|
|
1293
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1 shrink-0", children: [
|
|
1294
|
+
/* @__PURE__ */ jsx20(
|
|
1174
1295
|
"button",
|
|
1175
1296
|
{
|
|
1176
1297
|
onClick: () => setMinimized(!minimized),
|
|
1177
1298
|
className: "p-0.5 rounded hover:bg-surface-hover text-foreground-muted transition-colors",
|
|
1178
1299
|
title: minimized ? "Restore" : "Minimize",
|
|
1179
|
-
children: minimized ? /* @__PURE__ */
|
|
1300
|
+
children: minimized ? /* @__PURE__ */ jsx20(Maximize2, { size: 12 }) : /* @__PURE__ */ jsx20(Minimize2, { size: 12 })
|
|
1180
1301
|
}
|
|
1181
1302
|
),
|
|
1182
|
-
/* @__PURE__ */
|
|
1303
|
+
/* @__PURE__ */ jsx20(
|
|
1183
1304
|
"button",
|
|
1184
1305
|
{
|
|
1185
1306
|
onClick: onClose,
|
|
1186
1307
|
className: "p-0.5 rounded hover:bg-danger/20 text-foreground-muted hover:text-danger transition-colors",
|
|
1187
1308
|
title: "Close",
|
|
1188
|
-
children: /* @__PURE__ */
|
|
1309
|
+
children: /* @__PURE__ */ jsx20(X2, { size: 12 })
|
|
1189
1310
|
}
|
|
1190
1311
|
)
|
|
1191
1312
|
] })
|
|
1192
1313
|
]
|
|
1193
1314
|
}
|
|
1194
1315
|
),
|
|
1195
|
-
!minimized && /* @__PURE__ */
|
|
1316
|
+
!minimized && /* @__PURE__ */ jsxs6("div", { className: "flex-1 min-h-0 overflow-y-auto relative", children: [
|
|
1196
1317
|
children,
|
|
1197
|
-
/* @__PURE__ */
|
|
1318
|
+
/* @__PURE__ */ jsx20(
|
|
1198
1319
|
"div",
|
|
1199
1320
|
{
|
|
1200
1321
|
onMouseDown: onResizeStart,
|
|
@@ -1208,8 +1329,55 @@ function FloatingPanel({
|
|
|
1208
1329
|
);
|
|
1209
1330
|
}
|
|
1210
1331
|
|
|
1332
|
+
// src/primitives/mobile-drawer.tsx
|
|
1333
|
+
import { useEffect as useEffect7, useRef as useRef6 } from "react";
|
|
1334
|
+
import { Fragment as Fragment2, jsx as jsx21, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1335
|
+
function MobileDrawer({ open, onClose, children, className, width = "w-64" }) {
|
|
1336
|
+
const drawerRef = useRef6(null);
|
|
1337
|
+
useEffect7(() => {
|
|
1338
|
+
if (!open) return;
|
|
1339
|
+
const handleKeyDown = (e) => {
|
|
1340
|
+
if (e.key === "Escape") onClose();
|
|
1341
|
+
};
|
|
1342
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
1343
|
+
document.body.style.overflow = "hidden";
|
|
1344
|
+
return () => {
|
|
1345
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
1346
|
+
document.body.style.overflow = "";
|
|
1347
|
+
};
|
|
1348
|
+
}, [open, onClose]);
|
|
1349
|
+
return /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
1350
|
+
/* @__PURE__ */ jsx21(
|
|
1351
|
+
"div",
|
|
1352
|
+
{
|
|
1353
|
+
className: cn(
|
|
1354
|
+
"fixed inset-0 z-40 bg-black/50 backdrop-blur-sm transition-opacity duration-200",
|
|
1355
|
+
open ? "opacity-100" : "pointer-events-none opacity-0"
|
|
1356
|
+
),
|
|
1357
|
+
onClick: onClose,
|
|
1358
|
+
"aria-hidden": "true"
|
|
1359
|
+
}
|
|
1360
|
+
),
|
|
1361
|
+
/* @__PURE__ */ jsx21(
|
|
1362
|
+
"div",
|
|
1363
|
+
{
|
|
1364
|
+
ref: drawerRef,
|
|
1365
|
+
role: "dialog",
|
|
1366
|
+
"aria-modal": "true",
|
|
1367
|
+
className: cn(
|
|
1368
|
+
"fixed inset-y-0 left-0 z-50 flex flex-col bg-surface border-r border-border shadow-2xl transition-transform duration-200 ease-out",
|
|
1369
|
+
width,
|
|
1370
|
+
open ? "translate-x-0" : "-translate-x-full",
|
|
1371
|
+
className
|
|
1372
|
+
),
|
|
1373
|
+
children
|
|
1374
|
+
}
|
|
1375
|
+
)
|
|
1376
|
+
] });
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1211
1379
|
// src/composites/status-badge.tsx
|
|
1212
|
-
import { jsx as
|
|
1380
|
+
import { jsx as jsx22, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1213
1381
|
var statusConfig = {
|
|
1214
1382
|
online: { colorClass: "bg-success", label: "Online" },
|
|
1215
1383
|
offline: { colorClass: "bg-danger", label: "Offline" },
|
|
@@ -1224,7 +1392,7 @@ function StatusBadge({
|
|
|
1224
1392
|
className
|
|
1225
1393
|
}) {
|
|
1226
1394
|
const config = statusConfig[status];
|
|
1227
|
-
return /* @__PURE__ */
|
|
1395
|
+
return /* @__PURE__ */ jsxs8(
|
|
1228
1396
|
"span",
|
|
1229
1397
|
{
|
|
1230
1398
|
className: cn(
|
|
@@ -1233,21 +1401,21 @@ function StatusBadge({
|
|
|
1233
1401
|
className
|
|
1234
1402
|
),
|
|
1235
1403
|
children: [
|
|
1236
|
-
showDot && /* @__PURE__ */
|
|
1404
|
+
showDot && /* @__PURE__ */ jsx22(
|
|
1237
1405
|
"span",
|
|
1238
1406
|
{
|
|
1239
1407
|
className: cn("h-1.5 w-1.5 shrink-0 rounded-full", config.colorClass),
|
|
1240
1408
|
"aria-hidden": "true"
|
|
1241
1409
|
}
|
|
1242
1410
|
),
|
|
1243
|
-
showLabel && /* @__PURE__ */
|
|
1411
|
+
showLabel && /* @__PURE__ */ jsx22("span", { className: "text-foreground", children: config.label })
|
|
1244
1412
|
]
|
|
1245
1413
|
}
|
|
1246
1414
|
);
|
|
1247
1415
|
}
|
|
1248
1416
|
|
|
1249
1417
|
// src/composites/provider-badge.tsx
|
|
1250
|
-
import { jsx as
|
|
1418
|
+
import { jsx as jsx23, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1251
1419
|
var providerConfig = {
|
|
1252
1420
|
frigate: { colorClass: "bg-provider-frigate", label: "Frigate" },
|
|
1253
1421
|
scrypted: { colorClass: "bg-provider-scrypted", label: "Scrypted" },
|
|
@@ -1261,20 +1429,20 @@ function ProviderBadge({
|
|
|
1261
1429
|
className
|
|
1262
1430
|
}) {
|
|
1263
1431
|
const config = providerConfig[provider];
|
|
1264
|
-
return /* @__PURE__ */
|
|
1265
|
-
/* @__PURE__ */
|
|
1432
|
+
return /* @__PURE__ */ jsxs9("span", { className: cn("inline-flex items-center gap-1.5 text-xs", className), children: [
|
|
1433
|
+
/* @__PURE__ */ jsx23(
|
|
1266
1434
|
"span",
|
|
1267
1435
|
{
|
|
1268
1436
|
className: cn("h-1.5 w-1.5 shrink-0 rounded-sm", config.colorClass),
|
|
1269
1437
|
"aria-hidden": "true"
|
|
1270
1438
|
}
|
|
1271
1439
|
),
|
|
1272
|
-
showLabel && /* @__PURE__ */
|
|
1440
|
+
showLabel && /* @__PURE__ */ jsx23("span", { className: "text-foreground", children: config.label })
|
|
1273
1441
|
] });
|
|
1274
1442
|
}
|
|
1275
1443
|
|
|
1276
1444
|
// src/composites/version-badge.tsx
|
|
1277
|
-
import { jsx as
|
|
1445
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1278
1446
|
var VARIANT_STYLES = {
|
|
1279
1447
|
success: "bg-emerald-400 text-emerald-950",
|
|
1280
1448
|
warning: "bg-amber-400 text-amber-950",
|
|
@@ -1283,7 +1451,7 @@ var VARIANT_STYLES = {
|
|
|
1283
1451
|
neutral: "bg-foreground-subtle/20 text-foreground"
|
|
1284
1452
|
};
|
|
1285
1453
|
function SemanticBadge({ children, variant = "neutral", mono, className }) {
|
|
1286
|
-
return /* @__PURE__ */
|
|
1454
|
+
return /* @__PURE__ */ jsx24("span", { className: cn(
|
|
1287
1455
|
"inline-flex items-center rounded-md px-2 py-0.5 text-[11px] font-bold leading-tight",
|
|
1288
1456
|
mono && "font-mono",
|
|
1289
1457
|
VARIANT_STYLES[variant],
|
|
@@ -1292,11 +1460,11 @@ function SemanticBadge({ children, variant = "neutral", mono, className }) {
|
|
|
1292
1460
|
}
|
|
1293
1461
|
function VersionBadge({ version, preRelease, className }) {
|
|
1294
1462
|
const isPreRelease = preRelease ?? /-(alpha|beta|rc|dev|canary|next)/i.test(version);
|
|
1295
|
-
return /* @__PURE__ */
|
|
1463
|
+
return /* @__PURE__ */ jsx24(SemanticBadge, { variant: isPreRelease ? "warning" : "success", mono: true, className, children: version });
|
|
1296
1464
|
}
|
|
1297
1465
|
|
|
1298
1466
|
// src/composites/form-field.tsx
|
|
1299
|
-
import { jsx as
|
|
1467
|
+
import { jsx as jsx25, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1300
1468
|
function FormField({
|
|
1301
1469
|
label,
|
|
1302
1470
|
description,
|
|
@@ -1307,7 +1475,7 @@ function FormField({
|
|
|
1307
1475
|
className
|
|
1308
1476
|
}) {
|
|
1309
1477
|
const isHorizontal = orientation === "horizontal";
|
|
1310
|
-
return /* @__PURE__ */
|
|
1478
|
+
return /* @__PURE__ */ jsxs10(
|
|
1311
1479
|
"div",
|
|
1312
1480
|
{
|
|
1313
1481
|
className: cn(
|
|
@@ -1316,34 +1484,34 @@ function FormField({
|
|
|
1316
1484
|
className
|
|
1317
1485
|
),
|
|
1318
1486
|
children: [
|
|
1319
|
-
/* @__PURE__ */
|
|
1320
|
-
/* @__PURE__ */
|
|
1487
|
+
/* @__PURE__ */ jsxs10("div", { className: cn(isHorizontal ? "flex-1" : ""), children: [
|
|
1488
|
+
/* @__PURE__ */ jsxs10(Label, { children: [
|
|
1321
1489
|
label,
|
|
1322
|
-
required && /* @__PURE__ */
|
|
1490
|
+
required && /* @__PURE__ */ jsx25("span", { className: "text-danger ml-0.5", children: "*" })
|
|
1323
1491
|
] }),
|
|
1324
|
-
description && /* @__PURE__ */
|
|
1492
|
+
description && /* @__PURE__ */ jsx25("p", { className: "text-foreground-subtle text-xs mt-0.5", children: description })
|
|
1325
1493
|
] }),
|
|
1326
|
-
/* @__PURE__ */
|
|
1327
|
-
error && /* @__PURE__ */
|
|
1494
|
+
/* @__PURE__ */ jsx25("div", { className: cn(isHorizontal ? "shrink-0" : ""), children }),
|
|
1495
|
+
error && /* @__PURE__ */ jsx25("p", { className: "text-danger text-xs", children: error })
|
|
1328
1496
|
]
|
|
1329
1497
|
}
|
|
1330
1498
|
);
|
|
1331
1499
|
}
|
|
1332
1500
|
|
|
1333
1501
|
// src/composites/page-header.tsx
|
|
1334
|
-
import { jsx as
|
|
1502
|
+
import { jsx as jsx26, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1335
1503
|
function PageHeader({ title, subtitle, actions, className }) {
|
|
1336
|
-
return /* @__PURE__ */
|
|
1337
|
-
/* @__PURE__ */
|
|
1338
|
-
/* @__PURE__ */
|
|
1339
|
-
subtitle && /* @__PURE__ */
|
|
1504
|
+
return /* @__PURE__ */ jsxs11("div", { className: cn("flex flex-col gap-2 mb-3 sm:flex-row sm:items-center sm:justify-between", className), children: [
|
|
1505
|
+
/* @__PURE__ */ jsxs11("div", { children: [
|
|
1506
|
+
/* @__PURE__ */ jsx26("h1", { className: "text-sm font-semibold text-foreground", children: title }),
|
|
1507
|
+
subtitle && /* @__PURE__ */ jsx26("p", { className: "text-foreground-subtle text-xs", children: subtitle })
|
|
1340
1508
|
] }),
|
|
1341
|
-
actions && /* @__PURE__ */
|
|
1509
|
+
actions && /* @__PURE__ */ jsx26("div", { className: "flex items-center gap-2 flex-wrap", children: actions })
|
|
1342
1510
|
] });
|
|
1343
1511
|
}
|
|
1344
1512
|
|
|
1345
1513
|
// src/composites/empty-state.tsx
|
|
1346
|
-
import { jsx as
|
|
1514
|
+
import { jsx as jsx27, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1347
1515
|
function EmptyState({
|
|
1348
1516
|
icon: Icon,
|
|
1349
1517
|
title,
|
|
@@ -1351,18 +1519,18 @@ function EmptyState({
|
|
|
1351
1519
|
action,
|
|
1352
1520
|
className
|
|
1353
1521
|
}) {
|
|
1354
|
-
return /* @__PURE__ */
|
|
1355
|
-
Icon && /* @__PURE__ */
|
|
1356
|
-
/* @__PURE__ */
|
|
1357
|
-
/* @__PURE__ */
|
|
1358
|
-
description && /* @__PURE__ */
|
|
1522
|
+
return /* @__PURE__ */ jsxs12("div", { className: cn("flex flex-col items-center justify-center gap-3 py-12", className), children: [
|
|
1523
|
+
Icon && /* @__PURE__ */ jsx27(Icon, { className: "h-12 w-12 text-foreground-subtle", "aria-hidden": "true" }),
|
|
1524
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center gap-1 text-center", children: [
|
|
1525
|
+
/* @__PURE__ */ jsx27("p", { className: "text-foreground-muted text-sm font-medium", children: title }),
|
|
1526
|
+
description && /* @__PURE__ */ jsx27("p", { className: "text-foreground-subtle text-xs max-w-xs", children: description })
|
|
1359
1527
|
] }),
|
|
1360
|
-
action && /* @__PURE__ */
|
|
1528
|
+
action && /* @__PURE__ */ jsx27("div", { className: "mt-1", children: action })
|
|
1361
1529
|
] });
|
|
1362
1530
|
}
|
|
1363
1531
|
|
|
1364
1532
|
// src/composites/confirm-dialog.tsx
|
|
1365
|
-
import { jsx as
|
|
1533
|
+
import { jsx as jsx28, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1366
1534
|
function ConfirmDialog({
|
|
1367
1535
|
title,
|
|
1368
1536
|
message,
|
|
@@ -1374,14 +1542,14 @@ function ConfirmDialog({
|
|
|
1374
1542
|
open,
|
|
1375
1543
|
onOpenChange
|
|
1376
1544
|
}) {
|
|
1377
|
-
return /* @__PURE__ */
|
|
1378
|
-
/* @__PURE__ */
|
|
1379
|
-
/* @__PURE__ */
|
|
1380
|
-
/* @__PURE__ */
|
|
1545
|
+
return /* @__PURE__ */ jsx28(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs13(DialogContent, { children: [
|
|
1546
|
+
/* @__PURE__ */ jsxs13(DialogHeader, { children: [
|
|
1547
|
+
/* @__PURE__ */ jsx28(DialogTitle, { children: title }),
|
|
1548
|
+
/* @__PURE__ */ jsx28(DialogDescription, { children: message })
|
|
1381
1549
|
] }),
|
|
1382
|
-
/* @__PURE__ */
|
|
1383
|
-
/* @__PURE__ */
|
|
1384
|
-
/* @__PURE__ */
|
|
1550
|
+
/* @__PURE__ */ jsxs13(DialogFooter, { children: [
|
|
1551
|
+
/* @__PURE__ */ jsx28(Button, { variant: "ghost", onClick: onCancel, children: cancelLabel }),
|
|
1552
|
+
/* @__PURE__ */ jsx28(
|
|
1385
1553
|
Button,
|
|
1386
1554
|
{
|
|
1387
1555
|
variant: variant === "danger" ? "danger" : "primary",
|
|
@@ -1395,12 +1563,12 @@ function ConfirmDialog({
|
|
|
1395
1563
|
|
|
1396
1564
|
// src/composites/stat-card.tsx
|
|
1397
1565
|
import { TrendingUp, TrendingDown } from "lucide-react";
|
|
1398
|
-
import { jsx as
|
|
1566
|
+
import { jsx as jsx29, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1399
1567
|
function StatCard({ value, label, trend, className }) {
|
|
1400
|
-
return /* @__PURE__ */
|
|
1401
|
-
/* @__PURE__ */
|
|
1402
|
-
/* @__PURE__ */
|
|
1403
|
-
trend && /* @__PURE__ */
|
|
1568
|
+
return /* @__PURE__ */ jsxs14(Card, { className: cn("flex flex-col gap-1", className), children: [
|
|
1569
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-baseline gap-2", children: [
|
|
1570
|
+
/* @__PURE__ */ jsx29("span", { className: "text-2xl font-semibold text-foreground", children: value }),
|
|
1571
|
+
trend && /* @__PURE__ */ jsxs14(
|
|
1404
1572
|
"span",
|
|
1405
1573
|
{
|
|
1406
1574
|
className: cn(
|
|
@@ -1408,27 +1576,27 @@ function StatCard({ value, label, trend, className }) {
|
|
|
1408
1576
|
trend.direction === "up" ? "text-success" : "text-danger"
|
|
1409
1577
|
),
|
|
1410
1578
|
children: [
|
|
1411
|
-
trend.direction === "up" ? /* @__PURE__ */
|
|
1579
|
+
trend.direction === "up" ? /* @__PURE__ */ jsx29(TrendingUp, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx29(TrendingDown, { className: "h-3 w-3" }),
|
|
1412
1580
|
trend.value,
|
|
1413
1581
|
"%"
|
|
1414
1582
|
]
|
|
1415
1583
|
}
|
|
1416
1584
|
)
|
|
1417
1585
|
] }),
|
|
1418
|
-
/* @__PURE__ */
|
|
1586
|
+
/* @__PURE__ */ jsx29("span", { className: "text-xs text-foreground-muted", children: label })
|
|
1419
1587
|
] });
|
|
1420
1588
|
}
|
|
1421
1589
|
|
|
1422
1590
|
// src/composites/key-value-list.tsx
|
|
1423
|
-
import { jsx as
|
|
1591
|
+
import { jsx as jsx30, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1424
1592
|
function KeyValueList({ items, className }) {
|
|
1425
|
-
return /* @__PURE__ */
|
|
1593
|
+
return /* @__PURE__ */ jsx30("dl", { className: cn("flex flex-col", className), children: items.map((item) => /* @__PURE__ */ jsxs15(
|
|
1426
1594
|
"div",
|
|
1427
1595
|
{
|
|
1428
1596
|
className: "flex items-center h-7",
|
|
1429
1597
|
children: [
|
|
1430
|
-
/* @__PURE__ */
|
|
1431
|
-
/* @__PURE__ */
|
|
1598
|
+
/* @__PURE__ */ jsx30("dt", { className: "text-foreground-subtle text-xs w-1/3 shrink-0", children: item.key }),
|
|
1599
|
+
/* @__PURE__ */ jsx30("dd", { className: "text-foreground text-xs", children: item.value })
|
|
1432
1600
|
]
|
|
1433
1601
|
},
|
|
1434
1602
|
item.key
|
|
@@ -1438,7 +1606,7 @@ function KeyValueList({ items, className }) {
|
|
|
1438
1606
|
// src/composites/code-block.tsx
|
|
1439
1607
|
import { useCallback as useCallback7, useState as useState8 } from "react";
|
|
1440
1608
|
import { Copy, Check } from "lucide-react";
|
|
1441
|
-
import { jsx as
|
|
1609
|
+
import { jsx as jsx31, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1442
1610
|
function CodeBlock({ children, maxHeight = 300, className }) {
|
|
1443
1611
|
const [copied, setCopied] = useState8(false);
|
|
1444
1612
|
const handleCopy = useCallback7(() => {
|
|
@@ -1447,9 +1615,9 @@ function CodeBlock({ children, maxHeight = 300, className }) {
|
|
|
1447
1615
|
setTimeout(() => setCopied(false), 2e3);
|
|
1448
1616
|
});
|
|
1449
1617
|
}, [children]);
|
|
1450
|
-
return /* @__PURE__ */
|
|
1451
|
-
/* @__PURE__ */
|
|
1452
|
-
/* @__PURE__ */
|
|
1618
|
+
return /* @__PURE__ */ jsxs16("div", { className: cn("relative group", className), children: [
|
|
1619
|
+
/* @__PURE__ */ jsx31(ScrollArea, { style: { maxHeight }, children: /* @__PURE__ */ jsx31("pre", { className: "font-mono text-xs bg-surface p-3 rounded-md border border-border-subtle", children: /* @__PURE__ */ jsx31("code", { children }) }) }),
|
|
1620
|
+
/* @__PURE__ */ jsx31("div", { className: "absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsx31(
|
|
1453
1621
|
IconButton,
|
|
1454
1622
|
{
|
|
1455
1623
|
icon: copied ? Check : Copy,
|
|
@@ -1463,28 +1631,95 @@ function CodeBlock({ children, maxHeight = 300, className }) {
|
|
|
1463
1631
|
}
|
|
1464
1632
|
|
|
1465
1633
|
// src/composites/filter-bar.tsx
|
|
1466
|
-
import {
|
|
1467
|
-
import {
|
|
1634
|
+
import { useState as useState9 } from "react";
|
|
1635
|
+
import { Search, SlidersHorizontal } from "lucide-react";
|
|
1636
|
+
import { Fragment as Fragment3, jsx as jsx32, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1468
1637
|
function FilterBar({ filters, values, onChange, className }) {
|
|
1638
|
+
const isMobile = useIsMobile();
|
|
1639
|
+
const [sheetOpen, setSheetOpen] = useState9(false);
|
|
1469
1640
|
const handleChange = (key, value) => {
|
|
1470
1641
|
onChange({ ...values, [key]: value });
|
|
1471
1642
|
};
|
|
1472
|
-
|
|
1643
|
+
const activeCount = Object.values(values).filter((v) => v !== void 0 && v !== "").length;
|
|
1644
|
+
if (isMobile) {
|
|
1645
|
+
const searchFilter = filters.find((f) => f.type === "search");
|
|
1646
|
+
const hasNonSearchFilters = filters.some((f) => f.type !== "search");
|
|
1647
|
+
return /* @__PURE__ */ jsxs17("div", { className: cn("flex items-center gap-2", className), children: [
|
|
1648
|
+
searchFilter && /* @__PURE__ */ jsx32(
|
|
1649
|
+
Input,
|
|
1650
|
+
{
|
|
1651
|
+
placeholder: searchFilter.placeholder ?? "Search...",
|
|
1652
|
+
value: values[searchFilter.key] ?? "",
|
|
1653
|
+
onChange: (e) => handleChange(searchFilter.key, e.target.value),
|
|
1654
|
+
leftSlot: /* @__PURE__ */ jsx32(Search, { className: "h-3 w-3 text-foreground-subtle" }),
|
|
1655
|
+
className: "flex-1"
|
|
1656
|
+
}
|
|
1657
|
+
),
|
|
1658
|
+
hasNonSearchFilters && /* @__PURE__ */ jsxs17(Fragment3, { children: [
|
|
1659
|
+
/* @__PURE__ */ jsxs17(
|
|
1660
|
+
"button",
|
|
1661
|
+
{
|
|
1662
|
+
onClick: () => setSheetOpen(true),
|
|
1663
|
+
className: "flex items-center gap-1.5 rounded-md border border-border px-2.5 py-1.5 text-xs text-foreground-muted hover:bg-surface-hover transition-colors shrink-0",
|
|
1664
|
+
children: [
|
|
1665
|
+
/* @__PURE__ */ jsx32(SlidersHorizontal, { className: "h-3.5 w-3.5" }),
|
|
1666
|
+
"Filters",
|
|
1667
|
+
activeCount > 0 && /* @__PURE__ */ jsx32(Badge, { variant: "info", className: "ml-1 text-[10px] px-1 py-0", children: activeCount })
|
|
1668
|
+
]
|
|
1669
|
+
}
|
|
1670
|
+
),
|
|
1671
|
+
/* @__PURE__ */ jsx32(BottomSheet, { open: sheetOpen, onClose: () => setSheetOpen(false), title: "Filters", children: /* @__PURE__ */ jsx32("div", { className: "flex flex-col gap-3", children: filters.filter((f) => f.type !== "search").map((filter) => {
|
|
1672
|
+
switch (filter.type) {
|
|
1673
|
+
case "select":
|
|
1674
|
+
return /* @__PURE__ */ jsxs17("div", { children: [
|
|
1675
|
+
/* @__PURE__ */ jsx32("label", { className: "text-xs text-foreground-muted mb-1 block", children: filter.label }),
|
|
1676
|
+
/* @__PURE__ */ jsx32(
|
|
1677
|
+
Select,
|
|
1678
|
+
{
|
|
1679
|
+
options: filter.options,
|
|
1680
|
+
value: values[filter.key] ?? "",
|
|
1681
|
+
onChange: (e) => handleChange(filter.key, e.target.value),
|
|
1682
|
+
className: "w-full"
|
|
1683
|
+
}
|
|
1684
|
+
)
|
|
1685
|
+
] }, filter.key);
|
|
1686
|
+
case "badge-toggle":
|
|
1687
|
+
return /* @__PURE__ */ jsx32("div", { className: "flex items-center gap-1 flex-wrap", children: filter.options.map((option) => {
|
|
1688
|
+
const currentValue = values[filter.key];
|
|
1689
|
+
const isActive = currentValue === option.value;
|
|
1690
|
+
return /* @__PURE__ */ jsx32(
|
|
1691
|
+
"button",
|
|
1692
|
+
{
|
|
1693
|
+
type: "button",
|
|
1694
|
+
onClick: () => handleChange(filter.key, isActive ? void 0 : option.value),
|
|
1695
|
+
children: /* @__PURE__ */ jsx32(Badge, { variant: isActive ? "info" : "default", className: "cursor-pointer", children: option.label })
|
|
1696
|
+
},
|
|
1697
|
+
option.value
|
|
1698
|
+
);
|
|
1699
|
+
}) }, filter.key);
|
|
1700
|
+
default:
|
|
1701
|
+
return null;
|
|
1702
|
+
}
|
|
1703
|
+
}) }) })
|
|
1704
|
+
] })
|
|
1705
|
+
] });
|
|
1706
|
+
}
|
|
1707
|
+
return /* @__PURE__ */ jsx32("div", { className: cn("flex items-center gap-2 flex-wrap", className), children: filters.map((filter) => {
|
|
1473
1708
|
switch (filter.type) {
|
|
1474
1709
|
case "search":
|
|
1475
|
-
return /* @__PURE__ */
|
|
1710
|
+
return /* @__PURE__ */ jsx32(
|
|
1476
1711
|
Input,
|
|
1477
1712
|
{
|
|
1478
1713
|
placeholder: filter.placeholder ?? "Search...",
|
|
1479
1714
|
value: values[filter.key] ?? "",
|
|
1480
1715
|
onChange: (e) => handleChange(filter.key, e.target.value),
|
|
1481
|
-
leftSlot: /* @__PURE__ */
|
|
1716
|
+
leftSlot: /* @__PURE__ */ jsx32(Search, { className: "h-3 w-3 text-foreground-subtle" }),
|
|
1482
1717
|
className: "w-48"
|
|
1483
1718
|
},
|
|
1484
1719
|
filter.key
|
|
1485
1720
|
);
|
|
1486
1721
|
case "select":
|
|
1487
|
-
return /* @__PURE__ */
|
|
1722
|
+
return /* @__PURE__ */ jsx32(
|
|
1488
1723
|
Select,
|
|
1489
1724
|
{
|
|
1490
1725
|
options: filter.options,
|
|
@@ -1495,25 +1730,15 @@ function FilterBar({ filters, values, onChange, className }) {
|
|
|
1495
1730
|
filter.key
|
|
1496
1731
|
);
|
|
1497
1732
|
case "badge-toggle":
|
|
1498
|
-
return /* @__PURE__ */
|
|
1733
|
+
return /* @__PURE__ */ jsx32("div", { className: "flex items-center gap-1", children: filter.options.map((option) => {
|
|
1499
1734
|
const currentValue = values[filter.key];
|
|
1500
1735
|
const isActive = currentValue === option.value;
|
|
1501
|
-
return /* @__PURE__ */
|
|
1736
|
+
return /* @__PURE__ */ jsx32(
|
|
1502
1737
|
"button",
|
|
1503
1738
|
{
|
|
1504
1739
|
type: "button",
|
|
1505
|
-
onClick: () => handleChange(
|
|
1506
|
-
|
|
1507
|
-
isActive ? void 0 : option.value
|
|
1508
|
-
),
|
|
1509
|
-
children: /* @__PURE__ */ jsx30(
|
|
1510
|
-
Badge,
|
|
1511
|
-
{
|
|
1512
|
-
variant: isActive ? "info" : "default",
|
|
1513
|
-
className: "cursor-pointer",
|
|
1514
|
-
children: option.label
|
|
1515
|
-
}
|
|
1516
|
-
)
|
|
1740
|
+
onClick: () => handleChange(filter.key, isActive ? void 0 : option.value),
|
|
1741
|
+
children: /* @__PURE__ */ jsx32(Badge, { variant: isActive ? "info" : "default", className: "cursor-pointer", children: option.label })
|
|
1517
1742
|
},
|
|
1518
1743
|
option.value
|
|
1519
1744
|
);
|
|
@@ -1525,7 +1750,7 @@ function FilterBar({ filters, values, onChange, className }) {
|
|
|
1525
1750
|
}
|
|
1526
1751
|
|
|
1527
1752
|
// src/composites/app-shell/sidebar-item.tsx
|
|
1528
|
-
import { jsx as
|
|
1753
|
+
import { jsx as jsx33, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1529
1754
|
function SidebarItem({
|
|
1530
1755
|
label,
|
|
1531
1756
|
icon: Icon,
|
|
@@ -1534,7 +1759,7 @@ function SidebarItem({
|
|
|
1534
1759
|
active = false,
|
|
1535
1760
|
className
|
|
1536
1761
|
}) {
|
|
1537
|
-
return /* @__PURE__ */
|
|
1762
|
+
return /* @__PURE__ */ jsxs18(
|
|
1538
1763
|
"a",
|
|
1539
1764
|
{
|
|
1540
1765
|
href,
|
|
@@ -1544,33 +1769,33 @@ function SidebarItem({
|
|
|
1544
1769
|
className
|
|
1545
1770
|
),
|
|
1546
1771
|
children: [
|
|
1547
|
-
/* @__PURE__ */
|
|
1548
|
-
/* @__PURE__ */
|
|
1549
|
-
badge !== void 0 && /* @__PURE__ */
|
|
1772
|
+
/* @__PURE__ */ jsx33(Icon, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
1773
|
+
/* @__PURE__ */ jsx33("span", { className: "truncate flex-1", children: label }),
|
|
1774
|
+
badge !== void 0 && /* @__PURE__ */ jsx33(Badge, { className: "ml-auto text-[10px] px-1.5 py-0", children: badge })
|
|
1550
1775
|
]
|
|
1551
1776
|
}
|
|
1552
1777
|
);
|
|
1553
1778
|
}
|
|
1554
1779
|
|
|
1555
1780
|
// src/composites/app-shell/sidebar.tsx
|
|
1556
|
-
import { jsx as
|
|
1557
|
-
function Sidebar({ logo, sections, footer, className }) {
|
|
1558
|
-
return /* @__PURE__ */
|
|
1781
|
+
import { jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1782
|
+
function Sidebar({ logo, sections, footer, onNavigate, className }) {
|
|
1783
|
+
return /* @__PURE__ */ jsxs19(
|
|
1559
1784
|
"nav",
|
|
1560
1785
|
{
|
|
1561
1786
|
className: cn(
|
|
1562
|
-
"
|
|
1787
|
+
"bg-surface border-r border-border h-full flex flex-col",
|
|
1563
1788
|
className
|
|
1564
1789
|
),
|
|
1565
1790
|
children: [
|
|
1566
|
-
logo && /* @__PURE__ */
|
|
1567
|
-
/* @__PURE__ */
|
|
1568
|
-
section.label && /* @__PURE__ */
|
|
1569
|
-
/* @__PURE__ */
|
|
1791
|
+
logo && /* @__PURE__ */ jsx34("div", { className: "px-3 py-2 shrink-0", children: logo }),
|
|
1792
|
+
/* @__PURE__ */ jsx34("div", { className: "flex-1 overflow-auto px-1 py-1", children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs19("div", { className: cn(sectionIndex > 0 ? "mt-3" : ""), children: [
|
|
1793
|
+
section.label && /* @__PURE__ */ jsx34("span", { className: "text-[10px] text-foreground-disabled uppercase tracking-wider px-2 mb-1 block", children: section.label }),
|
|
1794
|
+
/* @__PURE__ */ jsx34("div", { className: "flex flex-col gap-0.5", onClick: onNavigate, children: section.items.map((item) => /* @__PURE__ */ jsx34(SidebarItem, { ...item }, item.href)) })
|
|
1570
1795
|
] }, sectionIndex)) }),
|
|
1571
|
-
footer && footer.length > 0 && /* @__PURE__ */
|
|
1572
|
-
/* @__PURE__ */
|
|
1573
|
-
/* @__PURE__ */
|
|
1796
|
+
footer && footer.length > 0 && /* @__PURE__ */ jsxs19("div", { className: "shrink-0 px-1 pb-1", children: [
|
|
1797
|
+
/* @__PURE__ */ jsx34(Separator, { className: "mb-1" }),
|
|
1798
|
+
/* @__PURE__ */ jsx34("div", { className: "flex flex-col gap-0.5", onClick: onNavigate, children: footer.map((item) => /* @__PURE__ */ jsx34(SidebarItem, { ...item }, item.href)) })
|
|
1574
1799
|
] })
|
|
1575
1800
|
]
|
|
1576
1801
|
}
|
|
@@ -1578,30 +1803,54 @@ function Sidebar({ logo, sections, footer, className }) {
|
|
|
1578
1803
|
}
|
|
1579
1804
|
|
|
1580
1805
|
// src/composites/app-shell/app-shell.tsx
|
|
1581
|
-
import {
|
|
1582
|
-
import {
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1806
|
+
import { useState as useState10 } from "react";
|
|
1807
|
+
import { ChevronRight, Menu } from "lucide-react";
|
|
1808
|
+
import { jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1809
|
+
function AppShell({ sidebar, header, mobileLogo, mobileActions, children, className }) {
|
|
1810
|
+
const isMobile = useIsMobile();
|
|
1811
|
+
const [drawerOpen, setDrawerOpen] = useState10(false);
|
|
1812
|
+
return /* @__PURE__ */ jsxs20("div", { className: cn("flex h-screen", className), children: [
|
|
1813
|
+
!isMobile && /* @__PURE__ */ jsx35(Sidebar, { ...sidebar, className: cn("w-44", sidebar.className) }),
|
|
1814
|
+
isMobile && /* @__PURE__ */ jsx35(MobileDrawer, { open: drawerOpen, onClose: () => setDrawerOpen(false), width: "w-64", children: /* @__PURE__ */ jsx35(
|
|
1815
|
+
Sidebar,
|
|
1816
|
+
{
|
|
1817
|
+
...sidebar,
|
|
1818
|
+
onNavigate: () => setDrawerOpen(false),
|
|
1819
|
+
className: "w-full border-r-0"
|
|
1820
|
+
}
|
|
1821
|
+
) }),
|
|
1822
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex flex-1 flex-col min-w-0", children: [
|
|
1823
|
+
isMobile && /* @__PURE__ */ jsxs20("header", { className: "flex items-center h-12 border-b border-border px-3 shrink-0 bg-surface/80 backdrop-blur-sm", children: [
|
|
1824
|
+
/* @__PURE__ */ jsx35(
|
|
1825
|
+
"button",
|
|
1826
|
+
{
|
|
1827
|
+
onClick: () => setDrawerOpen(true),
|
|
1828
|
+
className: "p-1.5 -ml-1.5 rounded-md hover:bg-surface-hover text-foreground-muted transition-colors",
|
|
1829
|
+
"aria-label": "Open menu",
|
|
1830
|
+
children: /* @__PURE__ */ jsx35(Menu, { className: "h-5 w-5" })
|
|
1831
|
+
}
|
|
1832
|
+
),
|
|
1833
|
+
mobileLogo && /* @__PURE__ */ jsx35("div", { className: "flex-1 flex justify-center", children: mobileLogo }),
|
|
1834
|
+
mobileActions && /* @__PURE__ */ jsx35("div", { className: "shrink-0", children: mobileActions })
|
|
1835
|
+
] }),
|
|
1836
|
+
!isMobile && header && /* @__PURE__ */ jsxs20("header", { className: "flex items-center h-10 border-b border-border px-4 shrink-0", children: [
|
|
1837
|
+
header.breadcrumbs && header.breadcrumbs.length > 0 && /* @__PURE__ */ jsx35("nav", { className: "flex items-center gap-1 text-xs flex-1 min-w-0", children: header.breadcrumbs.map((crumb, index) => {
|
|
1589
1838
|
const isLast = index === header.breadcrumbs.length - 1;
|
|
1590
|
-
return /* @__PURE__ */
|
|
1591
|
-
index > 0 && /* @__PURE__ */
|
|
1592
|
-
crumb.href && !isLast ? /* @__PURE__ */
|
|
1839
|
+
return /* @__PURE__ */ jsxs20("span", { className: "flex items-center gap-1", children: [
|
|
1840
|
+
index > 0 && /* @__PURE__ */ jsx35(ChevronRight, { className: "h-3 w-3 text-foreground-subtle shrink-0" }),
|
|
1841
|
+
crumb.href && !isLast ? /* @__PURE__ */ jsx35(
|
|
1593
1842
|
"a",
|
|
1594
1843
|
{
|
|
1595
1844
|
href: crumb.href,
|
|
1596
1845
|
className: "text-foreground-subtle hover:text-foreground transition-colors truncate",
|
|
1597
1846
|
children: crumb.label
|
|
1598
1847
|
}
|
|
1599
|
-
) : /* @__PURE__ */
|
|
1848
|
+
) : /* @__PURE__ */ jsx35("span", { className: "text-foreground truncate", children: crumb.label })
|
|
1600
1849
|
] }, index);
|
|
1601
1850
|
}) }),
|
|
1602
|
-
header.actions && /* @__PURE__ */
|
|
1851
|
+
header.actions && /* @__PURE__ */ jsx35("div", { className: "flex items-center gap-2 ml-auto shrink-0", children: header.actions })
|
|
1603
1852
|
] }),
|
|
1604
|
-
/* @__PURE__ */
|
|
1853
|
+
/* @__PURE__ */ jsx35("main", { className: "flex-1 overflow-auto p-4", children })
|
|
1605
1854
|
] })
|
|
1606
1855
|
] });
|
|
1607
1856
|
}
|
|
@@ -1619,20 +1868,20 @@ import {
|
|
|
1619
1868
|
|
|
1620
1869
|
// src/composites/data-table/data-table-header.tsx
|
|
1621
1870
|
import { ArrowUpDown, ArrowUp, ArrowDown } from "lucide-react";
|
|
1622
|
-
import { jsx as
|
|
1871
|
+
import { jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1623
1872
|
function DataTableHeader({
|
|
1624
1873
|
headerGroups,
|
|
1625
1874
|
onSortingChange,
|
|
1626
1875
|
stickyHeader,
|
|
1627
1876
|
flexRender: render
|
|
1628
1877
|
}) {
|
|
1629
|
-
return /* @__PURE__ */
|
|
1878
|
+
return /* @__PURE__ */ jsx36(
|
|
1630
1879
|
"thead",
|
|
1631
1880
|
{
|
|
1632
1881
|
className: cn(
|
|
1633
1882
|
stickyHeader && "sticky top-0 z-10 bg-background"
|
|
1634
1883
|
),
|
|
1635
|
-
children: headerGroups.map((headerGroup) => /* @__PURE__ */
|
|
1884
|
+
children: headerGroups.map((headerGroup) => /* @__PURE__ */ jsx36("tr", { className: "h-6", children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx36(
|
|
1636
1885
|
HeaderCell,
|
|
1637
1886
|
{
|
|
1638
1887
|
header,
|
|
@@ -1647,7 +1896,7 @@ function DataTableHeader({
|
|
|
1647
1896
|
function HeaderCell({ header, sortable, flexRender: render }) {
|
|
1648
1897
|
const sorted = header.column.getIsSorted();
|
|
1649
1898
|
const SortIcon = sorted === "asc" ? ArrowUp : sorted === "desc" ? ArrowDown : ArrowUpDown;
|
|
1650
|
-
return /* @__PURE__ */
|
|
1899
|
+
return /* @__PURE__ */ jsx36(
|
|
1651
1900
|
"th",
|
|
1652
1901
|
{
|
|
1653
1902
|
className: cn(
|
|
@@ -1655,9 +1904,9 @@ function HeaderCell({ header, sortable, flexRender: render }) {
|
|
|
1655
1904
|
sortable && "cursor-pointer select-none"
|
|
1656
1905
|
),
|
|
1657
1906
|
onClick: sortable ? header.column.getToggleSortingHandler() : void 0,
|
|
1658
|
-
children: /* @__PURE__ */
|
|
1907
|
+
children: /* @__PURE__ */ jsxs21("span", { className: "inline-flex items-center gap-1", children: [
|
|
1659
1908
|
header.isPlaceholder ? null : render(header.column.columnDef.header, header.getContext()),
|
|
1660
|
-
sortable && /* @__PURE__ */
|
|
1909
|
+
sortable && /* @__PURE__ */ jsx36(SortIcon, { className: "h-3 w-3" })
|
|
1661
1910
|
] })
|
|
1662
1911
|
}
|
|
1663
1912
|
);
|
|
@@ -1665,7 +1914,7 @@ function HeaderCell({ header, sortable, flexRender: render }) {
|
|
|
1665
1914
|
|
|
1666
1915
|
// src/composites/data-table/data-table-row.tsx
|
|
1667
1916
|
import { MoreHorizontal } from "lucide-react";
|
|
1668
|
-
import { jsx as
|
|
1917
|
+
import { jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1669
1918
|
function DataTableRow({
|
|
1670
1919
|
row,
|
|
1671
1920
|
onRowClick,
|
|
@@ -1673,7 +1922,7 @@ function DataTableRow({
|
|
|
1673
1922
|
flexRender: render
|
|
1674
1923
|
}) {
|
|
1675
1924
|
const actions = rowActions ? rowActions(row.original) : [];
|
|
1676
|
-
return /* @__PURE__ */
|
|
1925
|
+
return /* @__PURE__ */ jsxs22(
|
|
1677
1926
|
"tr",
|
|
1678
1927
|
{
|
|
1679
1928
|
className: cn(
|
|
@@ -1683,17 +1932,17 @@ function DataTableRow({
|
|
|
1683
1932
|
),
|
|
1684
1933
|
onClick: onRowClick ? () => onRowClick(row.original) : void 0,
|
|
1685
1934
|
children: [
|
|
1686
|
-
row.getVisibleCells().map((cell) => /* @__PURE__ */
|
|
1687
|
-
actions.length > 0 && /* @__PURE__ */
|
|
1688
|
-
/* @__PURE__ */
|
|
1935
|
+
row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx37(DataTableCell, { cell, flexRender: render }, cell.id)),
|
|
1936
|
+
actions.length > 0 && /* @__PURE__ */ jsx37("td", { className: "px-2 py-1.5 w-8", children: /* @__PURE__ */ jsxs22(Dropdown, { children: [
|
|
1937
|
+
/* @__PURE__ */ jsx37(
|
|
1689
1938
|
DropdownTrigger,
|
|
1690
1939
|
{
|
|
1691
1940
|
className: "p-0.5 rounded hover:bg-surface-hover",
|
|
1692
1941
|
onClick: (e) => e.stopPropagation(),
|
|
1693
|
-
children: /* @__PURE__ */
|
|
1942
|
+
children: /* @__PURE__ */ jsx37(MoreHorizontal, { className: "h-3.5 w-3.5 text-foreground-muted" })
|
|
1694
1943
|
}
|
|
1695
1944
|
),
|
|
1696
|
-
/* @__PURE__ */
|
|
1945
|
+
/* @__PURE__ */ jsx37(DropdownContent, { className: "right-0 left-auto", children: actions.map((action) => /* @__PURE__ */ jsx37(
|
|
1697
1946
|
DropdownItem,
|
|
1698
1947
|
{
|
|
1699
1948
|
icon: action.icon,
|
|
@@ -1712,12 +1961,12 @@ function DataTableRow({
|
|
|
1712
1961
|
);
|
|
1713
1962
|
}
|
|
1714
1963
|
function DataTableCell({ cell, flexRender: render }) {
|
|
1715
|
-
return /* @__PURE__ */
|
|
1964
|
+
return /* @__PURE__ */ jsx37("td", { className: "px-2 py-1.5 text-xs text-foreground", children: render(cell.column.columnDef.cell, cell.getContext()) });
|
|
1716
1965
|
}
|
|
1717
1966
|
|
|
1718
1967
|
// src/composites/data-table/data-table-pagination.tsx
|
|
1719
1968
|
import { ChevronLeft, ChevronRight as ChevronRight2 } from "lucide-react";
|
|
1720
|
-
import { jsx as
|
|
1969
|
+
import { jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1721
1970
|
var PAGE_SIZE_OPTIONS = [
|
|
1722
1971
|
{ value: "10", label: "10" },
|
|
1723
1972
|
{ value: "25", label: "25" },
|
|
@@ -1732,10 +1981,10 @@ function DataTablePagination({
|
|
|
1732
1981
|
}) {
|
|
1733
1982
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
1734
1983
|
const currentPage = page + 1;
|
|
1735
|
-
return /* @__PURE__ */
|
|
1736
|
-
/* @__PURE__ */
|
|
1737
|
-
/* @__PURE__ */
|
|
1738
|
-
/* @__PURE__ */
|
|
1984
|
+
return /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between px-2 py-2 text-xs text-foreground-muted", children: [
|
|
1985
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2", children: [
|
|
1986
|
+
/* @__PURE__ */ jsx38("span", { children: "Rows per page" }),
|
|
1987
|
+
/* @__PURE__ */ jsx38("div", { className: "w-16", children: /* @__PURE__ */ jsx38(
|
|
1739
1988
|
Select,
|
|
1740
1989
|
{
|
|
1741
1990
|
options: PAGE_SIZE_OPTIONS,
|
|
@@ -1747,14 +1996,14 @@ function DataTablePagination({
|
|
|
1747
1996
|
}
|
|
1748
1997
|
) })
|
|
1749
1998
|
] }),
|
|
1750
|
-
/* @__PURE__ */
|
|
1751
|
-
/* @__PURE__ */
|
|
1999
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-2", children: [
|
|
2000
|
+
/* @__PURE__ */ jsxs23("span", { children: [
|
|
1752
2001
|
"Page ",
|
|
1753
2002
|
currentPage,
|
|
1754
2003
|
" of ",
|
|
1755
2004
|
totalPages
|
|
1756
2005
|
] }),
|
|
1757
|
-
/* @__PURE__ */
|
|
2006
|
+
/* @__PURE__ */ jsx38(
|
|
1758
2007
|
IconButton,
|
|
1759
2008
|
{
|
|
1760
2009
|
icon: ChevronLeft,
|
|
@@ -1765,7 +2014,7 @@ function DataTablePagination({
|
|
|
1765
2014
|
onClick: () => onPaginationChange?.({ pageIndex: page - 1, pageSize })
|
|
1766
2015
|
}
|
|
1767
2016
|
),
|
|
1768
|
-
/* @__PURE__ */
|
|
2017
|
+
/* @__PURE__ */ jsx38(
|
|
1769
2018
|
IconButton,
|
|
1770
2019
|
{
|
|
1771
2020
|
icon: ChevronRight2,
|
|
@@ -1781,7 +2030,7 @@ function DataTablePagination({
|
|
|
1781
2030
|
}
|
|
1782
2031
|
|
|
1783
2032
|
// src/composites/data-table/data-table.tsx
|
|
1784
|
-
import { Fragment, jsx as
|
|
2033
|
+
import { Fragment as Fragment4, jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1785
2034
|
function DataTable({
|
|
1786
2035
|
data,
|
|
1787
2036
|
columns: userColumns,
|
|
@@ -1798,13 +2047,14 @@ function DataTable({
|
|
|
1798
2047
|
selectable = false,
|
|
1799
2048
|
compact = true,
|
|
1800
2049
|
stickyHeader = false,
|
|
1801
|
-
className
|
|
2050
|
+
className,
|
|
2051
|
+
mobileMode = "scroll"
|
|
1802
2052
|
}) {
|
|
1803
2053
|
const columns = useMemo2(() => {
|
|
1804
2054
|
if (!selectable) return userColumns;
|
|
1805
2055
|
const selectColumn = {
|
|
1806
2056
|
id: "__select",
|
|
1807
|
-
header: ({ table: table2 }) => /* @__PURE__ */
|
|
2057
|
+
header: ({ table: table2 }) => /* @__PURE__ */ jsx39(
|
|
1808
2058
|
Checkbox,
|
|
1809
2059
|
{
|
|
1810
2060
|
checked: table2.getIsAllPageRowsSelected(),
|
|
@@ -1812,7 +2062,7 @@ function DataTable({
|
|
|
1812
2062
|
"aria-label": "Select all"
|
|
1813
2063
|
}
|
|
1814
2064
|
),
|
|
1815
|
-
cell: ({ row }) => /* @__PURE__ */
|
|
2065
|
+
cell: ({ row }) => /* @__PURE__ */ jsx39(
|
|
1816
2066
|
Checkbox,
|
|
1817
2067
|
{
|
|
1818
2068
|
checked: row.getIsSelected(),
|
|
@@ -1850,9 +2100,71 @@ function DataTable({
|
|
|
1850
2100
|
pageCount: pagination ? Math.ceil(pagination.total / pagination.pageSize) : void 0
|
|
1851
2101
|
});
|
|
1852
2102
|
const hasActions = !!rowActions;
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
2103
|
+
const isMobile = useIsMobile();
|
|
2104
|
+
const showCards = isMobile && mobileMode === "cards";
|
|
2105
|
+
if (showCards) {
|
|
2106
|
+
const rows = table.getRowModel().rows;
|
|
2107
|
+
if (loading) {
|
|
2108
|
+
return /* @__PURE__ */ jsx39("div", { className: cn("space-y-2", className), children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs24("div", { className: "rounded-lg border border-border bg-surface p-3 space-y-2", children: [
|
|
2109
|
+
/* @__PURE__ */ jsx39(Skeleton, { className: "h-3 w-3/4" }),
|
|
2110
|
+
/* @__PURE__ */ jsx39(Skeleton, { className: "h-3 w-1/2" }),
|
|
2111
|
+
/* @__PURE__ */ jsx39(Skeleton, { className: "h-3 w-2/3" })
|
|
2112
|
+
] }, i)) });
|
|
2113
|
+
}
|
|
2114
|
+
if (rows.length === 0) {
|
|
2115
|
+
return /* @__PURE__ */ jsx39("div", { className: cn("text-center py-8 text-xs text-foreground-muted", className), children: emptyState ?? "No data" });
|
|
2116
|
+
}
|
|
2117
|
+
return /* @__PURE__ */ jsxs24("div", { className: cn("space-y-2", className), children: [
|
|
2118
|
+
rows.map((row) => /* @__PURE__ */ jsxs24(
|
|
2119
|
+
"div",
|
|
2120
|
+
{
|
|
2121
|
+
className: cn(
|
|
2122
|
+
"rounded-lg border border-border bg-surface p-3 space-y-1.5",
|
|
2123
|
+
onRowClick && "cursor-pointer hover:bg-surface-hover transition-colors"
|
|
2124
|
+
),
|
|
2125
|
+
onClick: onRowClick ? () => onRowClick(row.original) : void 0,
|
|
2126
|
+
children: [
|
|
2127
|
+
row.getVisibleCells().filter((cell) => cell.column.id !== "__select").map((cell) => {
|
|
2128
|
+
const header = cell.column.columnDef.header;
|
|
2129
|
+
const label = typeof header === "string" ? header : cell.column.id;
|
|
2130
|
+
return /* @__PURE__ */ jsxs24("div", { className: "flex items-baseline justify-between gap-2 text-xs", children: [
|
|
2131
|
+
/* @__PURE__ */ jsx39("span", { className: "text-foreground-muted shrink-0", children: label }),
|
|
2132
|
+
/* @__PURE__ */ jsx39("span", { className: "text-foreground text-right truncate", children: flexRender(cell.column.columnDef.cell, cell.getContext()) })
|
|
2133
|
+
] }, cell.id);
|
|
2134
|
+
}),
|
|
2135
|
+
rowActions && /* @__PURE__ */ jsx39("div", { className: "flex items-center gap-1 pt-1 border-t border-border mt-1.5", children: rowActions(row.original).map((action, i) => /* @__PURE__ */ jsx39(
|
|
2136
|
+
"button",
|
|
2137
|
+
{
|
|
2138
|
+
onClick: (e) => {
|
|
2139
|
+
e.stopPropagation();
|
|
2140
|
+
action.onClick();
|
|
2141
|
+
},
|
|
2142
|
+
className: cn(
|
|
2143
|
+
"text-[11px] px-2 py-1 rounded-md transition-colors",
|
|
2144
|
+
action.variant === "danger" ? "text-danger hover:bg-danger/10" : "text-foreground-muted hover:bg-surface-hover"
|
|
2145
|
+
),
|
|
2146
|
+
children: action.label
|
|
2147
|
+
},
|
|
2148
|
+
i
|
|
2149
|
+
)) })
|
|
2150
|
+
]
|
|
2151
|
+
},
|
|
2152
|
+
row.id
|
|
2153
|
+
)),
|
|
2154
|
+
pagination && /* @__PURE__ */ jsx39(
|
|
2155
|
+
DataTablePagination,
|
|
2156
|
+
{
|
|
2157
|
+
page: pagination.page,
|
|
2158
|
+
pageSize: pagination.pageSize,
|
|
2159
|
+
total: pagination.total,
|
|
2160
|
+
onPaginationChange
|
|
2161
|
+
}
|
|
2162
|
+
)
|
|
2163
|
+
] });
|
|
2164
|
+
}
|
|
2165
|
+
return /* @__PURE__ */ jsxs24("div", { className: cn("overflow-x-auto", className), children: [
|
|
2166
|
+
/* @__PURE__ */ jsxs24("table", { className: "w-full border-collapse", children: [
|
|
2167
|
+
/* @__PURE__ */ jsx39(
|
|
1856
2168
|
DataTableHeader,
|
|
1857
2169
|
{
|
|
1858
2170
|
headerGroups: table.getHeaderGroups(),
|
|
@@ -1861,14 +2173,14 @@ function DataTable({
|
|
|
1861
2173
|
flexRender
|
|
1862
2174
|
}
|
|
1863
2175
|
),
|
|
1864
|
-
/* @__PURE__ */
|
|
2176
|
+
/* @__PURE__ */ jsx39("tbody", { children: loading ? /* @__PURE__ */ jsx39(LoadingRows, { colSpan: columns.length + (hasActions ? 1 : 0), compact }) : table.getRowModel().rows.length === 0 ? /* @__PURE__ */ jsx39("tr", { children: /* @__PURE__ */ jsx39(
|
|
1865
2177
|
"td",
|
|
1866
2178
|
{
|
|
1867
2179
|
colSpan: columns.length + (hasActions ? 1 : 0),
|
|
1868
2180
|
className: "text-center py-8 text-xs text-foreground-muted",
|
|
1869
2181
|
children: emptyState ?? "No data"
|
|
1870
2182
|
}
|
|
1871
|
-
) }) : table.getRowModel().rows.map((row) => /* @__PURE__ */
|
|
2183
|
+
) }) : table.getRowModel().rows.map((row) => /* @__PURE__ */ jsx39(
|
|
1872
2184
|
DataTableRow,
|
|
1873
2185
|
{
|
|
1874
2186
|
row,
|
|
@@ -1879,7 +2191,7 @@ function DataTable({
|
|
|
1879
2191
|
row.id
|
|
1880
2192
|
)) })
|
|
1881
2193
|
] }),
|
|
1882
|
-
pagination && /* @__PURE__ */
|
|
2194
|
+
pagination && /* @__PURE__ */ jsx39(
|
|
1883
2195
|
DataTablePagination,
|
|
1884
2196
|
{
|
|
1885
2197
|
page: pagination.page,
|
|
@@ -1891,11 +2203,11 @@ function DataTable({
|
|
|
1891
2203
|
] });
|
|
1892
2204
|
}
|
|
1893
2205
|
function LoadingRows({ colSpan, compact }) {
|
|
1894
|
-
return /* @__PURE__ */
|
|
2206
|
+
return /* @__PURE__ */ jsx39(Fragment4, { children: Array.from({ length: 5 }).map((_, rowIdx) => /* @__PURE__ */ jsx39("tr", { className: compact ? "h-7" : "h-9", children: Array.from({ length: colSpan }).map((_2, colIdx) => /* @__PURE__ */ jsx39("td", { className: "px-2 py-1.5", children: /* @__PURE__ */ jsx39(Skeleton, { className: "h-3 w-full" }) }, colIdx)) }, rowIdx)) });
|
|
1895
2207
|
}
|
|
1896
2208
|
|
|
1897
2209
|
// src/composites/device-card.tsx
|
|
1898
|
-
import { jsx as
|
|
2210
|
+
import { jsx as jsx40, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1899
2211
|
var STATUS_COLORS = {
|
|
1900
2212
|
online: "bg-success",
|
|
1901
2213
|
offline: "bg-danger",
|
|
@@ -1914,7 +2226,7 @@ function DeviceCard({
|
|
|
1914
2226
|
className
|
|
1915
2227
|
}) {
|
|
1916
2228
|
const isOffline = status === "offline";
|
|
1917
|
-
return /* @__PURE__ */
|
|
2229
|
+
return /* @__PURE__ */ jsxs25(
|
|
1918
2230
|
"div",
|
|
1919
2231
|
{
|
|
1920
2232
|
onClick,
|
|
@@ -1926,18 +2238,18 @@ function DeviceCard({
|
|
|
1926
2238
|
className
|
|
1927
2239
|
),
|
|
1928
2240
|
children: [
|
|
1929
|
-
/* @__PURE__ */
|
|
1930
|
-
/* @__PURE__ */
|
|
1931
|
-
status && /* @__PURE__ */
|
|
2241
|
+
/* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between mb-2", children: [
|
|
2242
|
+
/* @__PURE__ */ jsx40("span", { className: "text-sm font-medium truncate", children: title }),
|
|
2243
|
+
status && /* @__PURE__ */ jsx40("span", { className: cn("h-2 w-2 rounded-full shrink-0", STATUS_COLORS[status]) })
|
|
1932
2244
|
] }),
|
|
1933
|
-
subtitle && /* @__PURE__ */
|
|
1934
|
-
badges && badges.length > 0 && /* @__PURE__ */
|
|
2245
|
+
subtitle && /* @__PURE__ */ jsx40("div", { className: "text-[11px] text-foreground-muted", children: subtitle }),
|
|
2246
|
+
badges && badges.length > 0 && /* @__PURE__ */ jsx40("div", { className: "flex flex-wrap gap-1 mt-2", children: badges.map((badge, i) => {
|
|
1935
2247
|
const cls = cn(
|
|
1936
2248
|
"rounded px-1.5 py-0.5 text-[10px] flex items-center gap-0.5",
|
|
1937
2249
|
selected ? "bg-primary/20" : "bg-surface-hover",
|
|
1938
2250
|
badge.onClick && "hover:opacity-80 transition-opacity cursor-pointer"
|
|
1939
2251
|
);
|
|
1940
|
-
return badge.onClick ? /* @__PURE__ */
|
|
2252
|
+
return badge.onClick ? /* @__PURE__ */ jsxs25(
|
|
1941
2253
|
"button",
|
|
1942
2254
|
{
|
|
1943
2255
|
onClick: (e) => {
|
|
@@ -1951,12 +2263,12 @@ function DeviceCard({
|
|
|
1951
2263
|
]
|
|
1952
2264
|
},
|
|
1953
2265
|
i
|
|
1954
|
-
) : /* @__PURE__ */
|
|
2266
|
+
) : /* @__PURE__ */ jsxs25("span", { className: cls, children: [
|
|
1955
2267
|
badge.icon,
|
|
1956
2268
|
badge.label
|
|
1957
2269
|
] }, i);
|
|
1958
2270
|
}) }),
|
|
1959
|
-
!isOffline && actions && actions.length > 0 && /* @__PURE__ */
|
|
2271
|
+
!isOffline && actions && actions.length > 0 && /* @__PURE__ */ jsx40("div", { className: "flex items-center gap-0.5 mt-2 -mb-1", children: actions.map((action, i) => /* @__PURE__ */ jsx40(
|
|
1960
2272
|
"button",
|
|
1961
2273
|
{
|
|
1962
2274
|
onClick: (e) => {
|
|
@@ -1970,21 +2282,21 @@ function DeviceCard({
|
|
|
1970
2282
|
},
|
|
1971
2283
|
i
|
|
1972
2284
|
)) }),
|
|
1973
|
-
isOffline && offlineAction && /* @__PURE__ */
|
|
2285
|
+
isOffline && offlineAction && /* @__PURE__ */ jsx40("div", { className: "mt-2", onClick: (e) => e.stopPropagation(), children: offlineAction })
|
|
1974
2286
|
]
|
|
1975
2287
|
}
|
|
1976
2288
|
);
|
|
1977
2289
|
}
|
|
1978
2290
|
|
|
1979
2291
|
// src/composites/device-grid.tsx
|
|
1980
|
-
import { jsx as
|
|
2292
|
+
import { jsx as jsx41 } from "react/jsx-runtime";
|
|
1981
2293
|
function DeviceGrid({
|
|
1982
2294
|
children,
|
|
1983
2295
|
minCardWidth = 220,
|
|
1984
2296
|
gap = 3,
|
|
1985
2297
|
className
|
|
1986
2298
|
}) {
|
|
1987
|
-
return /* @__PURE__ */
|
|
2299
|
+
return /* @__PURE__ */ jsx41(
|
|
1988
2300
|
"div",
|
|
1989
2301
|
{
|
|
1990
2302
|
className: cn(
|
|
@@ -2002,9 +2314,9 @@ function DeviceGrid({
|
|
|
2002
2314
|
}
|
|
2003
2315
|
|
|
2004
2316
|
// src/composites/pipeline-step.tsx
|
|
2005
|
-
import { useState as
|
|
2317
|
+
import { useState as useState11 } from "react";
|
|
2006
2318
|
import { ChevronRight as ChevronRight3, ChevronDown as ChevronDown2 } from "lucide-react";
|
|
2007
|
-
import { jsx as
|
|
2319
|
+
import { jsx as jsx42, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2008
2320
|
var ADDON_COLORS = {
|
|
2009
2321
|
"object-detection": "border-l-blue-500",
|
|
2010
2322
|
"motion-detection": "border-l-amber-500",
|
|
@@ -2080,7 +2392,7 @@ function PipelineStep({
|
|
|
2080
2392
|
onDelete,
|
|
2081
2393
|
readOnly = false
|
|
2082
2394
|
}) {
|
|
2083
|
-
const [expanded, setExpanded] =
|
|
2395
|
+
const [expanded, setExpanded] = useState11(false);
|
|
2084
2396
|
const color = borderColor(step.addonId, step.slot);
|
|
2085
2397
|
const backends = backendsForRuntime(step.runtime, capabilities, schema);
|
|
2086
2398
|
const rtOptions = runtimeOptions(capabilities);
|
|
@@ -2103,7 +2415,7 @@ function PipelineStep({
|
|
|
2103
2415
|
if (e.target.closest(".step-config")) return;
|
|
2104
2416
|
setExpanded((v) => !v);
|
|
2105
2417
|
}
|
|
2106
|
-
return /* @__PURE__ */
|
|
2418
|
+
return /* @__PURE__ */ jsx42("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs26(
|
|
2107
2419
|
"div",
|
|
2108
2420
|
{
|
|
2109
2421
|
className: cn(
|
|
@@ -2112,18 +2424,18 @@ function PipelineStep({
|
|
|
2112
2424
|
!step.enabled && "opacity-[0.45]"
|
|
2113
2425
|
),
|
|
2114
2426
|
children: [
|
|
2115
|
-
/* @__PURE__ */
|
|
2116
|
-
/* @__PURE__ */
|
|
2117
|
-
/* @__PURE__ */
|
|
2118
|
-
/* @__PURE__ */
|
|
2119
|
-
/* @__PURE__ */
|
|
2120
|
-
/* @__PURE__ */
|
|
2121
|
-
step.inputClasses.map((c) => /* @__PURE__ */
|
|
2122
|
-
step.inputClasses.length > 0 && step.outputClasses.length > 0 && /* @__PURE__ */
|
|
2123
|
-
step.outputClasses.map((c) => /* @__PURE__ */
|
|
2427
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-2.5 px-3 py-2.5 cursor-pointer select-none", onClick: handleClick, children: [
|
|
2428
|
+
/* @__PURE__ */ jsx42("span", { className: "text-foreground-subtle", children: expanded ? /* @__PURE__ */ jsx42(ChevronDown2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx42(ChevronRight3, { className: "h-4 w-4" }) }),
|
|
2429
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex-1 min-w-0", children: [
|
|
2430
|
+
/* @__PURE__ */ jsx42("span", { className: "text-[10px] uppercase tracking-wider font-medium text-foreground-subtle/60 block leading-none", children: step.slot }),
|
|
2431
|
+
/* @__PURE__ */ jsx42("span", { className: "text-sm font-semibold text-foreground truncate block leading-tight", children: step.addonName }),
|
|
2432
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-1 mt-0.5 flex-wrap", children: [
|
|
2433
|
+
step.inputClasses.map((c) => /* @__PURE__ */ jsx42("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-blue-500/12 text-blue-400", children: c }, c)),
|
|
2434
|
+
step.inputClasses.length > 0 && step.outputClasses.length > 0 && /* @__PURE__ */ jsx42("span", { className: "text-foreground-subtle/40 text-[10px]", children: "\u2192" }),
|
|
2435
|
+
step.outputClasses.map((c) => /* @__PURE__ */ jsx42("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-green-500/12 text-green-400", children: c }, c))
|
|
2124
2436
|
] })
|
|
2125
2437
|
] }),
|
|
2126
|
-
/* @__PURE__ */
|
|
2438
|
+
/* @__PURE__ */ jsx42(
|
|
2127
2439
|
"button",
|
|
2128
2440
|
{
|
|
2129
2441
|
onClick: (e) => {
|
|
@@ -2134,16 +2446,16 @@ function PipelineStep({
|
|
|
2134
2446
|
"relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors",
|
|
2135
2447
|
step.enabled ? "bg-success" : "bg-foreground-subtle/30"
|
|
2136
2448
|
),
|
|
2137
|
-
children: /* @__PURE__ */
|
|
2449
|
+
children: /* @__PURE__ */ jsx42("span", { className: cn(
|
|
2138
2450
|
"inline-block h-4 w-4 rounded-full bg-white shadow transition-transform",
|
|
2139
2451
|
step.enabled ? "translate-x-6" : "translate-x-1"
|
|
2140
2452
|
) })
|
|
2141
2453
|
}
|
|
2142
2454
|
)
|
|
2143
2455
|
] }),
|
|
2144
|
-
expanded && /* @__PURE__ */
|
|
2145
|
-
/* @__PURE__ */
|
|
2146
|
-
/* @__PURE__ */
|
|
2456
|
+
expanded && /* @__PURE__ */ jsxs26("div", { className: "step-config border-t border-border bg-background px-4 py-4 space-y-3", children: [
|
|
2457
|
+
/* @__PURE__ */ jsxs26("div", { className: "grid grid-cols-2 gap-3", children: [
|
|
2458
|
+
/* @__PURE__ */ jsx42(
|
|
2147
2459
|
ConfigSelect,
|
|
2148
2460
|
{
|
|
2149
2461
|
label: "Agent",
|
|
@@ -2153,7 +2465,7 @@ function PipelineStep({
|
|
|
2153
2465
|
onChange: (v) => onChange({ ...step, agentId: v })
|
|
2154
2466
|
}
|
|
2155
2467
|
),
|
|
2156
|
-
/* @__PURE__ */
|
|
2468
|
+
/* @__PURE__ */ jsx42(
|
|
2157
2469
|
ConfigSelect,
|
|
2158
2470
|
{
|
|
2159
2471
|
label: "Runtime",
|
|
@@ -2163,7 +2475,7 @@ function PipelineStep({
|
|
|
2163
2475
|
onChange: (v) => onChange({ ...step, runtime: v })
|
|
2164
2476
|
}
|
|
2165
2477
|
),
|
|
2166
|
-
/* @__PURE__ */
|
|
2478
|
+
/* @__PURE__ */ jsx42(
|
|
2167
2479
|
ConfigSelect,
|
|
2168
2480
|
{
|
|
2169
2481
|
label: "Backend",
|
|
@@ -2173,7 +2485,7 @@ function PipelineStep({
|
|
|
2173
2485
|
onChange: (v) => onChange({ ...step, backend: v })
|
|
2174
2486
|
}
|
|
2175
2487
|
),
|
|
2176
|
-
/* @__PURE__ */
|
|
2488
|
+
/* @__PURE__ */ jsx42(
|
|
2177
2489
|
ConfigSelect,
|
|
2178
2490
|
{
|
|
2179
2491
|
label: "Model",
|
|
@@ -2184,15 +2496,15 @@ function PipelineStep({
|
|
|
2184
2496
|
}
|
|
2185
2497
|
)
|
|
2186
2498
|
] }),
|
|
2187
|
-
/* @__PURE__ */
|
|
2188
|
-
/* @__PURE__ */
|
|
2189
|
-
/* @__PURE__ */
|
|
2190
|
-
/* @__PURE__ */
|
|
2499
|
+
/* @__PURE__ */ jsxs26("div", { children: [
|
|
2500
|
+
/* @__PURE__ */ jsxs26("div", { className: "flex items-center justify-between mb-1", children: [
|
|
2501
|
+
/* @__PURE__ */ jsx42("span", { className: "text-[10px] font-medium text-foreground-subtle uppercase tracking-wide", children: "Confidence" }),
|
|
2502
|
+
/* @__PURE__ */ jsxs26("span", { className: "text-xs font-medium text-foreground tabular-nums", children: [
|
|
2191
2503
|
(step.confidence * 100).toFixed(0),
|
|
2192
2504
|
"%"
|
|
2193
2505
|
] })
|
|
2194
2506
|
] }),
|
|
2195
|
-
/* @__PURE__ */
|
|
2507
|
+
/* @__PURE__ */ jsx42(
|
|
2196
2508
|
"input",
|
|
2197
2509
|
{
|
|
2198
2510
|
type: "range",
|
|
@@ -2212,9 +2524,9 @@ function PipelineStep({
|
|
|
2212
2524
|
) });
|
|
2213
2525
|
}
|
|
2214
2526
|
function ConfigSelect({ label, value, options, disabled, onChange }) {
|
|
2215
|
-
return /* @__PURE__ */
|
|
2216
|
-
/* @__PURE__ */
|
|
2217
|
-
/* @__PURE__ */
|
|
2527
|
+
return /* @__PURE__ */ jsxs26("div", { children: [
|
|
2528
|
+
/* @__PURE__ */ jsx42("label", { className: "block text-[10px] font-medium text-foreground-subtle uppercase tracking-wide mb-1.5", children: label }),
|
|
2529
|
+
/* @__PURE__ */ jsxs26(
|
|
2218
2530
|
"select",
|
|
2219
2531
|
{
|
|
2220
2532
|
value,
|
|
@@ -2222,8 +2534,8 @@ function ConfigSelect({ label, value, options, disabled, onChange }) {
|
|
|
2222
2534
|
disabled,
|
|
2223
2535
|
className: "w-full rounded-lg border border-border bg-surface px-3 py-2 text-xs text-foreground focus:outline-none focus:border-primary/50",
|
|
2224
2536
|
children: [
|
|
2225
|
-
options.length === 0 && /* @__PURE__ */
|
|
2226
|
-
options.map((o) => /* @__PURE__ */
|
|
2537
|
+
options.length === 0 && /* @__PURE__ */ jsx42("option", { value, children: value || "default" }),
|
|
2538
|
+
options.map((o) => /* @__PURE__ */ jsx42("option", { value: o.value, disabled: o.disabled, children: o.label }, o.value))
|
|
2227
2539
|
]
|
|
2228
2540
|
}
|
|
2229
2541
|
)
|
|
@@ -2232,29 +2544,29 @@ function ConfigSelect({ label, value, options, disabled, onChange }) {
|
|
|
2232
2544
|
|
|
2233
2545
|
// src/composites/pipeline-runtime-selector.tsx
|
|
2234
2546
|
import { Cpu, Star } from "lucide-react";
|
|
2235
|
-
import { jsx as
|
|
2547
|
+
import { jsx as jsx43, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2236
2548
|
function PipelineRuntimeSelector({ options, value, onChange }) {
|
|
2237
|
-
return /* @__PURE__ */
|
|
2549
|
+
return /* @__PURE__ */ jsx43("div", { className: "flex flex-wrap gap-2", children: options.map((opt) => {
|
|
2238
2550
|
const active = opt.id === value;
|
|
2239
|
-
return /* @__PURE__ */
|
|
2551
|
+
return /* @__PURE__ */ jsxs27(
|
|
2240
2552
|
"button",
|
|
2241
2553
|
{
|
|
2242
2554
|
onClick: () => opt.available && onChange(opt.id),
|
|
2243
2555
|
disabled: !opt.available,
|
|
2244
2556
|
className: `flex items-center gap-2 rounded-lg border px-3 py-2 text-xs font-medium transition-all ${active ? "border-primary/40 bg-primary/10 text-primary" : opt.available ? "border-border bg-surface text-foreground-subtle hover:bg-surface-hover hover:text-foreground" : "border-border/40 bg-surface/40 text-foreground-subtle/40 cursor-not-allowed"}`,
|
|
2245
2557
|
children: [
|
|
2246
|
-
/* @__PURE__ */
|
|
2558
|
+
/* @__PURE__ */ jsx43(Cpu, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
2247
2559
|
opt.label,
|
|
2248
|
-
opt.isBest && /* @__PURE__ */
|
|
2249
|
-
/* @__PURE__ */
|
|
2560
|
+
opt.isBest && /* @__PURE__ */ jsxs27("span", { className: "inline-flex items-center gap-0.5 rounded-full bg-amber-500/15 px-1.5 py-0.5 text-[10px] font-semibold text-amber-400", children: [
|
|
2561
|
+
/* @__PURE__ */ jsx43(Star, { className: "h-2.5 w-2.5" }),
|
|
2250
2562
|
"Best"
|
|
2251
2563
|
] }),
|
|
2252
|
-
opt.platformScore != null && /* @__PURE__ */
|
|
2564
|
+
opt.platformScore != null && /* @__PURE__ */ jsxs27("span", { className: "text-[10px] text-foreground-subtle/60", children: [
|
|
2253
2565
|
"(",
|
|
2254
2566
|
opt.platformScore,
|
|
2255
2567
|
")"
|
|
2256
2568
|
] }),
|
|
2257
|
-
/* @__PURE__ */
|
|
2569
|
+
/* @__PURE__ */ jsx43(
|
|
2258
2570
|
"span",
|
|
2259
2571
|
{
|
|
2260
2572
|
className: `h-1.5 w-1.5 rounded-full ${opt.available ? "bg-success" : "bg-danger"}`
|
|
@@ -2268,8 +2580,8 @@ function PipelineRuntimeSelector({ options, value, onChange }) {
|
|
|
2268
2580
|
}
|
|
2269
2581
|
|
|
2270
2582
|
// src/composites/pipeline-builder.tsx
|
|
2271
|
-
import { useMemo as useMemo3, useState as
|
|
2272
|
-
import { Save, CopyPlus, Trash2, PlusCircle, X as
|
|
2583
|
+
import { useMemo as useMemo3, useState as useState12 } from "react";
|
|
2584
|
+
import { Save, CopyPlus, Trash2, PlusCircle, X as X3 } from "lucide-react";
|
|
2273
2585
|
|
|
2274
2586
|
// src/lib/validate-template.ts
|
|
2275
2587
|
function validateTemplate(steps, schema) {
|
|
@@ -2301,7 +2613,7 @@ function validateTemplate(steps, schema) {
|
|
|
2301
2613
|
}
|
|
2302
2614
|
|
|
2303
2615
|
// src/composites/pipeline-builder.tsx
|
|
2304
|
-
import { jsx as
|
|
2616
|
+
import { jsx as jsx44, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2305
2617
|
function buildSchemaMap(schema) {
|
|
2306
2618
|
const map = /* @__PURE__ */ new Map();
|
|
2307
2619
|
for (const slot of schema.slots) {
|
|
@@ -2330,20 +2642,20 @@ function createDefaultStep(addon, fallbackRuntime, fallbackBackend) {
|
|
|
2330
2642
|
};
|
|
2331
2643
|
}
|
|
2332
2644
|
function PlaceholderStep({ addon, onClick }) {
|
|
2333
|
-
return /* @__PURE__ */
|
|
2645
|
+
return /* @__PURE__ */ jsx44(
|
|
2334
2646
|
"button",
|
|
2335
2647
|
{
|
|
2336
2648
|
type: "button",
|
|
2337
2649
|
onClick,
|
|
2338
2650
|
className: "w-full rounded-xl border-2 border-dashed border-border/60 px-4 py-3 text-left transition-all hover:border-primary/30 hover:bg-surface/60 group",
|
|
2339
|
-
children: /* @__PURE__ */
|
|
2340
|
-
/* @__PURE__ */
|
|
2341
|
-
/* @__PURE__ */
|
|
2342
|
-
/* @__PURE__ */
|
|
2343
|
-
/* @__PURE__ */
|
|
2344
|
-
addon.inputClasses.map((c) => /* @__PURE__ */
|
|
2345
|
-
addon.inputClasses.length > 0 && addon.outputClasses.length > 0 && /* @__PURE__ */
|
|
2346
|
-
addon.outputClasses.map((c) => /* @__PURE__ */
|
|
2651
|
+
children: /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-3", children: [
|
|
2652
|
+
/* @__PURE__ */ jsx44(PlusCircle, { className: "h-[18px] w-[18px] text-foreground-subtle/30 group-hover:text-primary/60 shrink-0" }),
|
|
2653
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex-1 min-w-0", children: [
|
|
2654
|
+
/* @__PURE__ */ jsx44("span", { className: "text-[13px] font-medium text-foreground-subtle/50 group-hover:text-foreground-subtle block truncate", children: addon.name }),
|
|
2655
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-1 mt-0.5 flex-wrap", children: [
|
|
2656
|
+
addon.inputClasses.map((c) => /* @__PURE__ */ jsx44("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-blue-500/8 text-blue-400/50", children: c }, c)),
|
|
2657
|
+
addon.inputClasses.length > 0 && addon.outputClasses.length > 0 && /* @__PURE__ */ jsx44("span", { className: "text-foreground-subtle/25 text-[10px]", children: "\u2192" }),
|
|
2658
|
+
addon.outputClasses.map((c) => /* @__PURE__ */ jsx44("span", { className: "text-[9px] uppercase font-semibold tracking-wide px-1.5 py-0.5 rounded bg-green-500/8 text-green-400/50", children: c }, c))
|
|
2347
2659
|
] })
|
|
2348
2660
|
] })
|
|
2349
2661
|
] })
|
|
@@ -2366,7 +2678,7 @@ function PipelineBuilder({
|
|
|
2366
2678
|
}) {
|
|
2367
2679
|
const excluded = useMemo3(() => new Set(excludeAddons), [excludeAddons]);
|
|
2368
2680
|
const schemaMap = useMemo3(() => buildSchemaMap(schema), [schema]);
|
|
2369
|
-
const [warnings, setWarnings] =
|
|
2681
|
+
const [warnings, setWarnings] = useState12([]);
|
|
2370
2682
|
const bestPlatformScore = capabilities.platformScores?.find((s) => s.available);
|
|
2371
2683
|
const hasPython = capabilities.runtimes.python.available && capabilities.runtimes.python.backends.some((b) => b.available);
|
|
2372
2684
|
const defaultRuntime = bestPlatformScore?.runtime ?? (hasPython ? "python" : "node");
|
|
@@ -2455,8 +2767,8 @@ function PipelineBuilder({
|
|
|
2455
2767
|
}
|
|
2456
2768
|
function renderStep(step) {
|
|
2457
2769
|
const childPlaceholders = getChildPlaceholders(step);
|
|
2458
|
-
return /* @__PURE__ */
|
|
2459
|
-
/* @__PURE__ */
|
|
2770
|
+
return /* @__PURE__ */ jsxs28("div", { className: "space-y-1.5", children: [
|
|
2771
|
+
/* @__PURE__ */ jsx44(
|
|
2460
2772
|
PipelineStep,
|
|
2461
2773
|
{
|
|
2462
2774
|
step,
|
|
@@ -2468,12 +2780,12 @@ function PipelineBuilder({
|
|
|
2468
2780
|
readOnly
|
|
2469
2781
|
}
|
|
2470
2782
|
),
|
|
2471
|
-
(step.children.length > 0 || childPlaceholders.length > 0) && /* @__PURE__ */
|
|
2472
|
-
/* @__PURE__ */
|
|
2783
|
+
(step.children.length > 0 || childPlaceholders.length > 0) && /* @__PURE__ */ jsxs28("div", { className: "ml-6 pl-4 border-l-2 border-dashed border-border/40 space-y-1.5", children: [
|
|
2784
|
+
/* @__PURE__ */ jsx44("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/40", children: "Slot: Cropper / Classifier" }),
|
|
2473
2785
|
step.children.map((child) => {
|
|
2474
2786
|
const childChildPlaceholders = getChildPlaceholders(child);
|
|
2475
|
-
return /* @__PURE__ */
|
|
2476
|
-
/* @__PURE__ */
|
|
2787
|
+
return /* @__PURE__ */ jsxs28("div", { className: "space-y-1.5", children: [
|
|
2788
|
+
/* @__PURE__ */ jsx44(
|
|
2477
2789
|
PipelineStep,
|
|
2478
2790
|
{
|
|
2479
2791
|
step: child,
|
|
@@ -2496,9 +2808,9 @@ function PipelineBuilder({
|
|
|
2496
2808
|
readOnly
|
|
2497
2809
|
}
|
|
2498
2810
|
),
|
|
2499
|
-
(child.children.length > 0 || childChildPlaceholders.length > 0) && /* @__PURE__ */
|
|
2500
|
-
/* @__PURE__ */
|
|
2501
|
-
child.children.map((grandchild) => /* @__PURE__ */
|
|
2811
|
+
(child.children.length > 0 || childChildPlaceholders.length > 0) && /* @__PURE__ */ jsxs28("div", { className: "ml-6 pl-4 border-l-2 border-dashed border-border/30 space-y-1.5", children: [
|
|
2812
|
+
/* @__PURE__ */ jsx44("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/30", children: "Slot: Recognizer" }),
|
|
2813
|
+
child.children.map((grandchild) => /* @__PURE__ */ jsx44(
|
|
2502
2814
|
PipelineStep,
|
|
2503
2815
|
{
|
|
2504
2816
|
step: grandchild,
|
|
@@ -2526,7 +2838,7 @@ function PipelineBuilder({
|
|
|
2526
2838
|
},
|
|
2527
2839
|
grandchild.addonId
|
|
2528
2840
|
)),
|
|
2529
|
-
!readOnly && childChildPlaceholders.map((addon) => /* @__PURE__ */
|
|
2841
|
+
!readOnly && childChildPlaceholders.map((addon) => /* @__PURE__ */ jsx44(
|
|
2530
2842
|
PlaceholderStep,
|
|
2531
2843
|
{
|
|
2532
2844
|
addon,
|
|
@@ -2545,7 +2857,7 @@ function PipelineBuilder({
|
|
|
2545
2857
|
] })
|
|
2546
2858
|
] }, child.addonId);
|
|
2547
2859
|
}),
|
|
2548
|
-
!readOnly && childPlaceholders.map((addon) => /* @__PURE__ */
|
|
2860
|
+
!readOnly && childPlaceholders.map((addon) => /* @__PURE__ */ jsx44(
|
|
2549
2861
|
PlaceholderStep,
|
|
2550
2862
|
{
|
|
2551
2863
|
addon,
|
|
@@ -2557,22 +2869,22 @@ function PipelineBuilder({
|
|
|
2557
2869
|
] }, step.addonId);
|
|
2558
2870
|
}
|
|
2559
2871
|
const rootSlots = schema.slots.filter((s) => s.parentSlot === null).sort((a, b) => a.priority - b.priority);
|
|
2560
|
-
return /* @__PURE__ */
|
|
2561
|
-
/* @__PURE__ */
|
|
2562
|
-
/* @__PURE__ */
|
|
2872
|
+
return /* @__PURE__ */ jsxs28("div", { className: "space-y-4", children: [
|
|
2873
|
+
/* @__PURE__ */ jsx44("div", { className: "rounded-xl border border-border bg-surface p-3", children: /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2", children: [
|
|
2874
|
+
/* @__PURE__ */ jsx44("div", { className: "relative flex-1 min-w-0", children: /* @__PURE__ */ jsxs28(
|
|
2563
2875
|
"select",
|
|
2564
2876
|
{
|
|
2565
2877
|
value: selectedTemplateId ?? "",
|
|
2566
2878
|
onChange: handleSelectTemplate,
|
|
2567
2879
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm text-foreground focus:outline-none focus:border-primary/50",
|
|
2568
2880
|
children: [
|
|
2569
|
-
/* @__PURE__ */
|
|
2570
|
-
templates.map((t) => /* @__PURE__ */
|
|
2881
|
+
/* @__PURE__ */ jsx44("option", { value: "", children: "No template" }),
|
|
2882
|
+
templates.map((t) => /* @__PURE__ */ jsx44("option", { value: t.id, children: t.name }, t.id))
|
|
2571
2883
|
]
|
|
2572
2884
|
}
|
|
2573
2885
|
) }),
|
|
2574
|
-
dirty && /* @__PURE__ */
|
|
2575
|
-
/* @__PURE__ */
|
|
2886
|
+
dirty && /* @__PURE__ */ jsx44("span", { className: "h-1.5 w-1.5 rounded-full bg-amber-500 shrink-0" }),
|
|
2887
|
+
/* @__PURE__ */ jsx44(
|
|
2576
2888
|
"button",
|
|
2577
2889
|
{
|
|
2578
2890
|
onClick: handleSave,
|
|
@@ -2582,10 +2894,10 @@ function PipelineBuilder({
|
|
|
2582
2894
|
"p-2 rounded-lg border border-border transition-colors",
|
|
2583
2895
|
selectedTemplateId && !readOnly ? "text-foreground-subtle hover:bg-surface-hover" : "text-foreground-subtle/30 cursor-not-allowed"
|
|
2584
2896
|
),
|
|
2585
|
-
children: /* @__PURE__ */
|
|
2897
|
+
children: /* @__PURE__ */ jsx44(Save, { className: "h-4 w-4" })
|
|
2586
2898
|
}
|
|
2587
2899
|
),
|
|
2588
|
-
/* @__PURE__ */
|
|
2900
|
+
/* @__PURE__ */ jsx44(
|
|
2589
2901
|
"button",
|
|
2590
2902
|
{
|
|
2591
2903
|
onClick: handleSaveAs,
|
|
@@ -2595,10 +2907,10 @@ function PipelineBuilder({
|
|
|
2595
2907
|
"p-2 rounded-lg border border-border transition-colors",
|
|
2596
2908
|
!readOnly ? "text-foreground-subtle hover:bg-surface-hover" : "text-foreground-subtle/30 cursor-not-allowed"
|
|
2597
2909
|
),
|
|
2598
|
-
children: /* @__PURE__ */
|
|
2910
|
+
children: /* @__PURE__ */ jsx44(CopyPlus, { className: "h-4 w-4" })
|
|
2599
2911
|
}
|
|
2600
2912
|
),
|
|
2601
|
-
/* @__PURE__ */
|
|
2913
|
+
/* @__PURE__ */ jsx44(
|
|
2602
2914
|
"button",
|
|
2603
2915
|
{
|
|
2604
2916
|
onClick: handleDelete,
|
|
@@ -2608,16 +2920,16 @@ function PipelineBuilder({
|
|
|
2608
2920
|
"p-2 rounded-lg border border-border transition-colors",
|
|
2609
2921
|
selectedTemplateId && !readOnly ? "text-foreground-subtle hover:text-danger" : "text-foreground-subtle/30 cursor-not-allowed"
|
|
2610
2922
|
),
|
|
2611
|
-
children: /* @__PURE__ */
|
|
2923
|
+
children: /* @__PURE__ */ jsx44(Trash2, { className: "h-4 w-4" })
|
|
2612
2924
|
}
|
|
2613
2925
|
)
|
|
2614
2926
|
] }) }),
|
|
2615
|
-
warnings.length > 0 && /* @__PURE__ */
|
|
2616
|
-
/* @__PURE__ */
|
|
2617
|
-
/* @__PURE__ */
|
|
2618
|
-
/* @__PURE__ */
|
|
2927
|
+
warnings.length > 0 && /* @__PURE__ */ jsxs28("div", { className: "rounded-lg border border-amber-500/30 bg-amber-500/5 p-3 text-xs text-amber-400 space-y-1", children: [
|
|
2928
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex items-center justify-between", children: [
|
|
2929
|
+
/* @__PURE__ */ jsx44("span", { className: "font-medium", children: "Template loaded with warnings:" }),
|
|
2930
|
+
/* @__PURE__ */ jsx44("button", { onClick: () => setWarnings([]), className: "text-amber-400/60 hover:text-amber-400", children: /* @__PURE__ */ jsx44(X3, { className: "h-3.5 w-3.5" }) })
|
|
2619
2931
|
] }),
|
|
2620
|
-
warnings.map((w, i) => /* @__PURE__ */
|
|
2932
|
+
warnings.map((w, i) => /* @__PURE__ */ jsxs28("div", { children: [
|
|
2621
2933
|
"\u2022 ",
|
|
2622
2934
|
w
|
|
2623
2935
|
] }, i))
|
|
@@ -2625,13 +2937,13 @@ function PipelineBuilder({
|
|
|
2625
2937
|
rootSlots.map((slot) => {
|
|
2626
2938
|
const slotSteps = steps.filter((s) => s.slot === slot.id && !excluded.has(s.addonId));
|
|
2627
2939
|
const missingRootAddons = slot.addons.filter((a) => !existingIds.has(a.id) && !excluded.has(a.id));
|
|
2628
|
-
return /* @__PURE__ */
|
|
2629
|
-
/* @__PURE__ */
|
|
2940
|
+
return /* @__PURE__ */ jsxs28("div", { className: "space-y-2", children: [
|
|
2941
|
+
/* @__PURE__ */ jsxs28("span", { className: "text-[10px] font-semibold uppercase tracking-widest text-foreground-subtle/50", children: [
|
|
2630
2942
|
"Slot: ",
|
|
2631
2943
|
slot.label
|
|
2632
2944
|
] }),
|
|
2633
2945
|
slotSteps.map((step) => renderStep(step)),
|
|
2634
|
-
!readOnly && missingRootAddons.map((addon) => /* @__PURE__ */
|
|
2946
|
+
!readOnly && missingRootAddons.map((addon) => /* @__PURE__ */ jsx44(PlaceholderStep, { addon, onClick: () => {
|
|
2635
2947
|
onChange([...steps, createDefaultStep(addon, defaultRuntime, defaultBackend)]);
|
|
2636
2948
|
} }, addon.id))
|
|
2637
2949
|
] }, slot.id);
|
|
@@ -2711,8 +3023,8 @@ function getClassColor(className, customColors) {
|
|
|
2711
3023
|
}
|
|
2712
3024
|
|
|
2713
3025
|
// src/composites/detection-canvas.tsx
|
|
2714
|
-
import { useRef as
|
|
2715
|
-
import { Fragment as
|
|
3026
|
+
import { useRef as useRef7, useEffect as useEffect8 } from "react";
|
|
3027
|
+
import { Fragment as Fragment5, jsx as jsx45, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2716
3028
|
var DEFAULT_CLASS_COLORS = CLASS_COLORS;
|
|
2717
3029
|
function DetectionCanvas({
|
|
2718
3030
|
src,
|
|
@@ -2732,7 +3044,7 @@ function DetectionCanvas({
|
|
|
2732
3044
|
}
|
|
2733
3045
|
const ratio = aspectRatio ?? (imageWidth && imageHeight ? `${imageWidth}/${imageHeight}` : "16/9");
|
|
2734
3046
|
const filteredDetections = detections.filter((d) => d.confidence >= minConfidence);
|
|
2735
|
-
return /* @__PURE__ */
|
|
3047
|
+
return /* @__PURE__ */ jsx45(
|
|
2736
3048
|
"div",
|
|
2737
3049
|
{
|
|
2738
3050
|
className: cn(
|
|
@@ -2740,10 +3052,10 @@ function DetectionCanvas({
|
|
|
2740
3052
|
className
|
|
2741
3053
|
),
|
|
2742
3054
|
style: { aspectRatio: ratio },
|
|
2743
|
-
children: src ? /* @__PURE__ */
|
|
2744
|
-
/* @__PURE__ */
|
|
3055
|
+
children: src ? /* @__PURE__ */ jsxs29(Fragment5, { children: [
|
|
3056
|
+
/* @__PURE__ */ jsx45("img", { src, className: "absolute inset-0 w-full h-full object-fill", alt: "" }),
|
|
2745
3057
|
filteredDetections.map(
|
|
2746
|
-
(d, i) => d.mask && d.maskWidth && d.maskHeight ? /* @__PURE__ */
|
|
3058
|
+
(d, i) => d.mask && d.maskWidth && d.maskHeight ? /* @__PURE__ */ jsx45(
|
|
2747
3059
|
MaskOverlay,
|
|
2748
3060
|
{
|
|
2749
3061
|
mask: d.mask,
|
|
@@ -2757,7 +3069,7 @@ function DetectionCanvas({
|
|
|
2757
3069
|
`mask-${i}`
|
|
2758
3070
|
) : null
|
|
2759
3071
|
),
|
|
2760
|
-
filteredDetections.map((d, i) => /* @__PURE__ */
|
|
3072
|
+
filteredDetections.map((d, i) => /* @__PURE__ */ jsx45(
|
|
2761
3073
|
BoundingBox,
|
|
2762
3074
|
{
|
|
2763
3075
|
detection: d,
|
|
@@ -2777,7 +3089,7 @@ function DetectionCanvas({
|
|
|
2777
3089
|
const ph = py2 - py1;
|
|
2778
3090
|
if (pw > 0 && ph > 0 && cw * ch / (pw * ph) > 0.8) return false;
|
|
2779
3091
|
return true;
|
|
2780
|
-
}).map((child, j) => /* @__PURE__ */
|
|
3092
|
+
}).map((child, j) => /* @__PURE__ */ jsx45(
|
|
2781
3093
|
ChildBoundingBox,
|
|
2782
3094
|
{
|
|
2783
3095
|
child,
|
|
@@ -2790,7 +3102,7 @@ function DetectionCanvas({
|
|
|
2790
3102
|
},
|
|
2791
3103
|
`det-${i}`
|
|
2792
3104
|
))
|
|
2793
|
-
] }) : /* @__PURE__ */
|
|
3105
|
+
] }) : /* @__PURE__ */ jsx45("div", { className: "w-full h-full flex items-center justify-center text-foreground-subtle text-sm", children: placeholder ?? "No image loaded" })
|
|
2794
3106
|
}
|
|
2795
3107
|
);
|
|
2796
3108
|
}
|
|
@@ -2807,15 +3119,15 @@ function BoundingBox({
|
|
|
2807
3119
|
const labelCount = 1 + (detection.labelsData?.length ?? 0);
|
|
2808
3120
|
const labelHeightPx = labelCount * 16 + 4;
|
|
2809
3121
|
const topPct = y1 / imageHeight * 100;
|
|
2810
|
-
const containerRef =
|
|
3122
|
+
const containerRef = useRef7(null);
|
|
2811
3123
|
const showBelow = topPct < labelHeightPx / imageHeight * 100 * 1.5;
|
|
2812
|
-
const labelsElement = /* @__PURE__ */
|
|
3124
|
+
const labelsElement = /* @__PURE__ */ jsxs29(
|
|
2813
3125
|
"div",
|
|
2814
3126
|
{
|
|
2815
3127
|
className: `absolute left-0 flex flex-col items-start gap-px ${showBelow ? "" : ""}`,
|
|
2816
3128
|
style: showBelow ? { top: "100%", marginTop: "2px" } : { bottom: "100%", marginBottom: "2px" },
|
|
2817
3129
|
children: [
|
|
2818
|
-
/* @__PURE__ */
|
|
3130
|
+
/* @__PURE__ */ jsxs29(
|
|
2819
3131
|
"span",
|
|
2820
3132
|
{
|
|
2821
3133
|
className: "text-[10px] px-1 rounded-sm whitespace-nowrap text-white",
|
|
@@ -2826,7 +3138,7 @@ function BoundingBox({
|
|
|
2826
3138
|
]
|
|
2827
3139
|
}
|
|
2828
3140
|
),
|
|
2829
|
-
detection.labelsData?.map((l, k) => /* @__PURE__ */
|
|
3141
|
+
detection.labelsData?.map((l, k) => /* @__PURE__ */ jsxs29(
|
|
2830
3142
|
"span",
|
|
2831
3143
|
{
|
|
2832
3144
|
className: "text-[9px] font-semibold px-1 rounded-sm whitespace-nowrap text-white",
|
|
@@ -2843,7 +3155,7 @@ function BoundingBox({
|
|
|
2843
3155
|
]
|
|
2844
3156
|
}
|
|
2845
3157
|
);
|
|
2846
|
-
return /* @__PURE__ */
|
|
3158
|
+
return /* @__PURE__ */ jsxs29(
|
|
2847
3159
|
"div",
|
|
2848
3160
|
{
|
|
2849
3161
|
ref: containerRef,
|
|
@@ -2873,8 +3185,8 @@ function MaskOverlay({
|
|
|
2873
3185
|
imageHeight,
|
|
2874
3186
|
color
|
|
2875
3187
|
}) {
|
|
2876
|
-
const canvasRef =
|
|
2877
|
-
|
|
3188
|
+
const canvasRef = useRef7(null);
|
|
3189
|
+
useEffect8(() => {
|
|
2878
3190
|
const canvas = canvasRef.current;
|
|
2879
3191
|
if (!canvas) return;
|
|
2880
3192
|
const ctx = canvas.getContext("2d");
|
|
@@ -2902,7 +3214,7 @@ function MaskOverlay({
|
|
|
2902
3214
|
ctx.putImageData(imageData, 0, 0);
|
|
2903
3215
|
}, [mask, maskWidth, maskHeight, color]);
|
|
2904
3216
|
const [x1, y1, x2, y2] = bbox;
|
|
2905
|
-
return /* @__PURE__ */
|
|
3217
|
+
return /* @__PURE__ */ jsx45(
|
|
2906
3218
|
"canvas",
|
|
2907
3219
|
{
|
|
2908
3220
|
ref: canvasRef,
|
|
@@ -2928,7 +3240,7 @@ function ChildBoundingBox({
|
|
|
2928
3240
|
const pw = px2 - px1;
|
|
2929
3241
|
const ph = py2 - py1;
|
|
2930
3242
|
if (pw <= 0 || ph <= 0) return null;
|
|
2931
|
-
return /* @__PURE__ */
|
|
3243
|
+
return /* @__PURE__ */ jsx45(
|
|
2932
3244
|
"div",
|
|
2933
3245
|
{
|
|
2934
3246
|
className: "absolute rounded-sm",
|
|
@@ -2945,13 +3257,13 @@ function ChildBoundingBox({
|
|
|
2945
3257
|
const labelCount = 1 + (child.labelsData?.length ?? 0);
|
|
2946
3258
|
const relTop = (cy1 - py1) / ph * 100;
|
|
2947
3259
|
const showBelow = relTop < labelCount * 6;
|
|
2948
|
-
return /* @__PURE__ */
|
|
3260
|
+
return /* @__PURE__ */ jsxs29(
|
|
2949
3261
|
"div",
|
|
2950
3262
|
{
|
|
2951
3263
|
className: "absolute left-0 flex flex-col items-start gap-px",
|
|
2952
3264
|
style: showBelow ? { top: "100%", marginTop: "1px" } : { bottom: "100%", marginBottom: "1px" },
|
|
2953
3265
|
children: [
|
|
2954
|
-
/* @__PURE__ */
|
|
3266
|
+
/* @__PURE__ */ jsxs29(
|
|
2955
3267
|
"span",
|
|
2956
3268
|
{
|
|
2957
3269
|
className: "text-[9px] px-0.5 rounded-sm whitespace-nowrap text-white",
|
|
@@ -2962,7 +3274,7 @@ function ChildBoundingBox({
|
|
|
2962
3274
|
]
|
|
2963
3275
|
}
|
|
2964
3276
|
),
|
|
2965
|
-
child.labelsData?.map((l, k) => /* @__PURE__ */
|
|
3277
|
+
child.labelsData?.map((l, k) => /* @__PURE__ */ jsxs29(
|
|
2966
3278
|
"span",
|
|
2967
3279
|
{
|
|
2968
3280
|
className: "text-[8px] font-semibold px-0.5 rounded-sm whitespace-nowrap text-white",
|
|
@@ -2985,7 +3297,7 @@ function ChildBoundingBox({
|
|
|
2985
3297
|
}
|
|
2986
3298
|
|
|
2987
3299
|
// src/composites/detection-result-tree.tsx
|
|
2988
|
-
import { jsx as
|
|
3300
|
+
import { jsx as jsx46, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2989
3301
|
function DetectionResultTree({
|
|
2990
3302
|
detections,
|
|
2991
3303
|
classColors,
|
|
@@ -2995,15 +3307,15 @@ function DetectionResultTree({
|
|
|
2995
3307
|
}) {
|
|
2996
3308
|
const colors = classColors;
|
|
2997
3309
|
if (detections.length === 0) {
|
|
2998
|
-
return /* @__PURE__ */
|
|
3310
|
+
return /* @__PURE__ */ jsx46("div", { className: "text-sm text-foreground-subtle italic text-center py-4", children: "No detections" });
|
|
2999
3311
|
}
|
|
3000
|
-
return /* @__PURE__ */
|
|
3001
|
-
/* @__PURE__ */
|
|
3312
|
+
return /* @__PURE__ */ jsxs30("div", { className, children: [
|
|
3313
|
+
/* @__PURE__ */ jsxs30("div", { className: "text-xs font-medium text-foreground-subtle uppercase tracking-wide mb-2", children: [
|
|
3002
3314
|
"Detections (",
|
|
3003
3315
|
detections.length,
|
|
3004
3316
|
")"
|
|
3005
3317
|
] }),
|
|
3006
|
-
/* @__PURE__ */
|
|
3318
|
+
/* @__PURE__ */ jsx46("div", { className: "space-y-2", children: detections.map((d, i) => /* @__PURE__ */ jsx46(
|
|
3007
3319
|
DetectionNode,
|
|
3008
3320
|
{
|
|
3009
3321
|
detection: d,
|
|
@@ -3025,10 +3337,10 @@ function DetectionNode({
|
|
|
3025
3337
|
}) {
|
|
3026
3338
|
const color = getClassColor(detection.className, colors);
|
|
3027
3339
|
const isVisible = !hiddenKeys?.has(path);
|
|
3028
|
-
return /* @__PURE__ */
|
|
3029
|
-
/* @__PURE__ */
|
|
3030
|
-
/* @__PURE__ */
|
|
3031
|
-
onToggleVisibility && /* @__PURE__ */
|
|
3340
|
+
return /* @__PURE__ */ jsxs30("div", { className: `rounded-md border border-border bg-surface p-3 space-y-1 ${isVisible ? "" : "opacity-40"}`, children: [
|
|
3341
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex justify-between items-center", children: [
|
|
3342
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
|
|
3343
|
+
onToggleVisibility && /* @__PURE__ */ jsx46(
|
|
3032
3344
|
"input",
|
|
3033
3345
|
{
|
|
3034
3346
|
type: "checkbox",
|
|
@@ -3037,45 +3349,45 @@ function DetectionNode({
|
|
|
3037
3349
|
className: "h-3.5 w-3.5 rounded border-border accent-primary cursor-pointer shrink-0"
|
|
3038
3350
|
}
|
|
3039
3351
|
),
|
|
3040
|
-
/* @__PURE__ */
|
|
3352
|
+
/* @__PURE__ */ jsx46(
|
|
3041
3353
|
"span",
|
|
3042
3354
|
{
|
|
3043
3355
|
className: "h-2.5 w-2.5 rounded-full shrink-0",
|
|
3044
3356
|
style: { backgroundColor: color }
|
|
3045
3357
|
}
|
|
3046
3358
|
),
|
|
3047
|
-
/* @__PURE__ */
|
|
3048
|
-
detection.mask && detection.maskWidth && detection.maskHeight && /* @__PURE__ */
|
|
3359
|
+
/* @__PURE__ */ jsx46("span", { className: "text-sm font-medium text-foreground", children: detection.className }),
|
|
3360
|
+
detection.mask && detection.maskWidth && detection.maskHeight && /* @__PURE__ */ jsxs30("span", { className: "text-[9px] font-mono px-1 py-0.5 rounded bg-primary/10 text-primary", children: [
|
|
3049
3361
|
"mask ",
|
|
3050
3362
|
detection.maskWidth,
|
|
3051
3363
|
"x",
|
|
3052
3364
|
detection.maskHeight
|
|
3053
3365
|
] })
|
|
3054
3366
|
] }),
|
|
3055
|
-
/* @__PURE__ */
|
|
3367
|
+
/* @__PURE__ */ jsx46(ConfidenceBadge, { confidence: detection.confidence })
|
|
3056
3368
|
] }),
|
|
3057
|
-
/* @__PURE__ */
|
|
3369
|
+
/* @__PURE__ */ jsxs30("div", { className: "text-[10px] text-foreground-subtle font-mono", children: [
|
|
3058
3370
|
"bbox: [",
|
|
3059
3371
|
detection.bbox.map((v) => Math.round(v)).join(", "),
|
|
3060
3372
|
"]"
|
|
3061
3373
|
] }),
|
|
3062
|
-
detection.labelsData && detection.labelsData.length > 0 && /* @__PURE__ */
|
|
3374
|
+
detection.labelsData && detection.labelsData.length > 0 && /* @__PURE__ */ jsx46("div", { className: "flex flex-wrap gap-1 mt-1", children: detection.labelsData.map((l, k) => /* @__PURE__ */ jsxs30(
|
|
3063
3375
|
"span",
|
|
3064
3376
|
{
|
|
3065
3377
|
className: "inline-flex items-center gap-1 text-[10px] font-medium px-1.5 py-0.5 rounded-full",
|
|
3066
3378
|
style: { backgroundColor: getClassColor(l.addonId ?? l.label, colors) + "20", color: getClassColor(l.addonId ?? l.label, colors) },
|
|
3067
3379
|
children: [
|
|
3068
3380
|
l.label,
|
|
3069
|
-
/* @__PURE__ */
|
|
3381
|
+
/* @__PURE__ */ jsxs30("span", { className: "opacity-60", children: [
|
|
3070
3382
|
(l.score * 100).toFixed(0),
|
|
3071
3383
|
"%"
|
|
3072
3384
|
] }),
|
|
3073
|
-
l.addonId && /* @__PURE__ */
|
|
3385
|
+
l.addonId && /* @__PURE__ */ jsx46("span", { className: "opacity-40 text-[8px]", children: l.addonId })
|
|
3074
3386
|
]
|
|
3075
3387
|
},
|
|
3076
3388
|
k
|
|
3077
3389
|
)) }),
|
|
3078
|
-
detection.children && detection.children.length > 0 && /* @__PURE__ */
|
|
3390
|
+
detection.children && detection.children.length > 0 && /* @__PURE__ */ jsx46(
|
|
3079
3391
|
ChildrenTree,
|
|
3080
3392
|
{
|
|
3081
3393
|
children: detection.children,
|
|
@@ -3094,13 +3406,13 @@ function ChildrenTree({
|
|
|
3094
3406
|
hiddenKeys,
|
|
3095
3407
|
onToggleVisibility
|
|
3096
3408
|
}) {
|
|
3097
|
-
return /* @__PURE__ */
|
|
3409
|
+
return /* @__PURE__ */ jsx46("div", { className: "ml-4 mt-1.5 space-y-1.5 border-l-2 border-border pl-3", children: children.map((child, j) => {
|
|
3098
3410
|
const childPath = `${parentPath}.${j}`;
|
|
3099
3411
|
const childColor = getClassColor(child.className, colors);
|
|
3100
3412
|
const isVisible = !hiddenKeys?.has(childPath);
|
|
3101
|
-
return /* @__PURE__ */
|
|
3102
|
-
/* @__PURE__ */
|
|
3103
|
-
onToggleVisibility && /* @__PURE__ */
|
|
3413
|
+
return /* @__PURE__ */ jsxs30("div", { className: `text-xs space-y-0.5 ${isVisible ? "" : "opacity-40"}`, children: [
|
|
3414
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-1.5", children: [
|
|
3415
|
+
onToggleVisibility && /* @__PURE__ */ jsx46(
|
|
3104
3416
|
"input",
|
|
3105
3417
|
{
|
|
3106
3418
|
type: "checkbox",
|
|
@@ -3109,26 +3421,26 @@ function ChildrenTree({
|
|
|
3109
3421
|
className: "h-3 w-3 rounded border-border accent-primary cursor-pointer shrink-0"
|
|
3110
3422
|
}
|
|
3111
3423
|
),
|
|
3112
|
-
/* @__PURE__ */
|
|
3424
|
+
/* @__PURE__ */ jsx46(
|
|
3113
3425
|
"span",
|
|
3114
3426
|
{
|
|
3115
3427
|
className: "h-1.5 w-1.5 rounded-full shrink-0",
|
|
3116
3428
|
style: { backgroundColor: childColor }
|
|
3117
3429
|
}
|
|
3118
3430
|
),
|
|
3119
|
-
/* @__PURE__ */
|
|
3120
|
-
/* @__PURE__ */
|
|
3431
|
+
/* @__PURE__ */ jsx46("span", { className: "font-medium", style: { color: childColor }, children: child.className }),
|
|
3432
|
+
/* @__PURE__ */ jsxs30("span", { className: "text-foreground-subtle", children: [
|
|
3121
3433
|
(child.confidence * 100).toFixed(0),
|
|
3122
3434
|
"%"
|
|
3123
3435
|
] }),
|
|
3124
|
-
child.mask && child.maskWidth && child.maskHeight && /* @__PURE__ */
|
|
3436
|
+
child.mask && child.maskWidth && child.maskHeight && /* @__PURE__ */ jsxs30("span", { className: "text-[9px] font-mono px-1 py-0.5 rounded bg-primary/10 text-primary", children: [
|
|
3125
3437
|
"mask ",
|
|
3126
3438
|
child.maskWidth,
|
|
3127
3439
|
"x",
|
|
3128
3440
|
child.maskHeight
|
|
3129
3441
|
] })
|
|
3130
3442
|
] }),
|
|
3131
|
-
child.labelsData && child.labelsData.length > 0 && /* @__PURE__ */
|
|
3443
|
+
child.labelsData && child.labelsData.length > 0 && /* @__PURE__ */ jsx46("div", { className: "flex flex-wrap gap-1 ml-5 mt-0.5", children: child.labelsData.map((l, k) => /* @__PURE__ */ jsxs30(
|
|
3132
3444
|
"span",
|
|
3133
3445
|
{
|
|
3134
3446
|
className: "inline-flex items-center gap-0.5 text-[9px] font-medium px-1 py-0.5 rounded-full",
|
|
@@ -3136,7 +3448,7 @@ function ChildrenTree({
|
|
|
3136
3448
|
children: [
|
|
3137
3449
|
l.label,
|
|
3138
3450
|
" ",
|
|
3139
|
-
/* @__PURE__ */
|
|
3451
|
+
/* @__PURE__ */ jsxs30("span", { className: "opacity-60", children: [
|
|
3140
3452
|
(l.score * 100).toFixed(0),
|
|
3141
3453
|
"%"
|
|
3142
3454
|
] })
|
|
@@ -3144,7 +3456,7 @@ function ChildrenTree({
|
|
|
3144
3456
|
},
|
|
3145
3457
|
k
|
|
3146
3458
|
)) }),
|
|
3147
|
-
child.children && child.children.length > 0 && /* @__PURE__ */
|
|
3459
|
+
child.children && child.children.length > 0 && /* @__PURE__ */ jsx46(
|
|
3148
3460
|
ChildrenTree,
|
|
3149
3461
|
{
|
|
3150
3462
|
children: child.children,
|
|
@@ -3159,30 +3471,30 @@ function ChildrenTree({
|
|
|
3159
3471
|
}
|
|
3160
3472
|
function ConfidenceBadge({ confidence }) {
|
|
3161
3473
|
const level = confidence >= 0.8 ? "bg-success/10 text-success" : confidence >= 0.5 ? "bg-warning/10 text-warning" : "bg-danger/10 text-danger";
|
|
3162
|
-
return /* @__PURE__ */
|
|
3474
|
+
return /* @__PURE__ */ jsxs30("span", { className: `text-xs font-medium px-2 py-0.5 rounded-full ${level}`, children: [
|
|
3163
3475
|
(confidence * 100).toFixed(1),
|
|
3164
3476
|
"%"
|
|
3165
3477
|
] });
|
|
3166
3478
|
}
|
|
3167
3479
|
|
|
3168
3480
|
// src/composites/step-timings.tsx
|
|
3169
|
-
import { jsx as
|
|
3481
|
+
import { jsx as jsx47, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
3170
3482
|
function StepTimings({ timings, totalMs, className }) {
|
|
3171
3483
|
const entries = Object.entries(timings);
|
|
3172
3484
|
if (entries.length === 0 && totalMs === void 0) return null;
|
|
3173
|
-
return /* @__PURE__ */
|
|
3174
|
-
/* @__PURE__ */
|
|
3175
|
-
/* @__PURE__ */
|
|
3176
|
-
entries.map(([step, ms]) => /* @__PURE__ */
|
|
3177
|
-
/* @__PURE__ */
|
|
3178
|
-
/* @__PURE__ */
|
|
3485
|
+
return /* @__PURE__ */ jsxs31("div", { className: `rounded-lg border border-border bg-surface p-3 space-y-2 ${className ?? ""}`, children: [
|
|
3486
|
+
/* @__PURE__ */ jsx47("div", { className: "text-xs font-medium text-foreground-subtle uppercase tracking-wide", children: "Timings" }),
|
|
3487
|
+
/* @__PURE__ */ jsxs31("div", { className: "space-y-1 text-xs", children: [
|
|
3488
|
+
entries.map(([step, ms]) => /* @__PURE__ */ jsxs31("div", { className: "flex justify-between", children: [
|
|
3489
|
+
/* @__PURE__ */ jsx47("span", { className: "text-foreground-subtle", children: step }),
|
|
3490
|
+
/* @__PURE__ */ jsxs31("span", { className: "font-mono text-foreground", children: [
|
|
3179
3491
|
ms.toFixed(1),
|
|
3180
3492
|
"ms"
|
|
3181
3493
|
] })
|
|
3182
3494
|
] }, step)),
|
|
3183
|
-
totalMs !== void 0 && /* @__PURE__ */
|
|
3184
|
-
/* @__PURE__ */
|
|
3185
|
-
/* @__PURE__ */
|
|
3495
|
+
totalMs !== void 0 && /* @__PURE__ */ jsxs31("div", { className: "flex justify-between pt-1 border-t border-border font-medium text-foreground", children: [
|
|
3496
|
+
/* @__PURE__ */ jsx47("span", { children: "Total" }),
|
|
3497
|
+
/* @__PURE__ */ jsxs31("span", { className: "font-mono", children: [
|
|
3186
3498
|
totalMs.toFixed(1),
|
|
3187
3499
|
"ms"
|
|
3188
3500
|
] })
|
|
@@ -3192,7 +3504,7 @@ function StepTimings({ timings, totalMs, className }) {
|
|
|
3192
3504
|
}
|
|
3193
3505
|
|
|
3194
3506
|
// src/composites/image-selector.tsx
|
|
3195
|
-
import { jsx as
|
|
3507
|
+
import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
3196
3508
|
function ImageSelector({
|
|
3197
3509
|
images,
|
|
3198
3510
|
selectedFilename,
|
|
@@ -3218,8 +3530,8 @@ function ImageSelector({
|
|
|
3218
3530
|
};
|
|
3219
3531
|
input.click();
|
|
3220
3532
|
};
|
|
3221
|
-
return /* @__PURE__ */
|
|
3222
|
-
images.map((img) => /* @__PURE__ */
|
|
3533
|
+
return /* @__PURE__ */ jsxs32("div", { className: `flex flex-wrap items-center gap-2 ${className ?? ""}`, children: [
|
|
3534
|
+
images.map((img) => /* @__PURE__ */ jsx48(
|
|
3223
3535
|
"button",
|
|
3224
3536
|
{
|
|
3225
3537
|
onClick: () => onSelect(img.filename),
|
|
@@ -3228,7 +3540,7 @@ function ImageSelector({
|
|
|
3228
3540
|
},
|
|
3229
3541
|
img.filename
|
|
3230
3542
|
)),
|
|
3231
|
-
/* @__PURE__ */
|
|
3543
|
+
/* @__PURE__ */ jsx48(
|
|
3232
3544
|
"button",
|
|
3233
3545
|
{
|
|
3234
3546
|
onClick: handleUploadClick,
|
|
@@ -3236,12 +3548,12 @@ function ImageSelector({
|
|
|
3236
3548
|
children: "Upload..."
|
|
3237
3549
|
}
|
|
3238
3550
|
),
|
|
3239
|
-
uploadedName && /* @__PURE__ */
|
|
3551
|
+
uploadedName && /* @__PURE__ */ jsx48("span", { className: "text-xs text-foreground-subtle", children: uploadedName })
|
|
3240
3552
|
] });
|
|
3241
3553
|
}
|
|
3242
3554
|
|
|
3243
3555
|
// src/composites/inference-config-selector.tsx
|
|
3244
|
-
import { jsx as
|
|
3556
|
+
import { jsx as jsx49, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
3245
3557
|
var SELECT_CLASS = "w-full px-3 py-2 text-sm rounded-md border border-border bg-surface text-foreground focus:outline-none focus:ring-2 focus:ring-primary/50";
|
|
3246
3558
|
function InferenceConfigSelector({
|
|
3247
3559
|
runtime,
|
|
@@ -3261,16 +3573,16 @@ function InferenceConfigSelector({
|
|
|
3261
3573
|
showAgent = false
|
|
3262
3574
|
}) {
|
|
3263
3575
|
const containerClass = layout === "grid" ? "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4" : layout === "horizontal" ? "flex flex-wrap items-end gap-4" : "space-y-3";
|
|
3264
|
-
return /* @__PURE__ */
|
|
3265
|
-
showAgent && agents.length > 0 && /* @__PURE__ */
|
|
3266
|
-
/* @__PURE__ */
|
|
3267
|
-
/* @__PURE__ */
|
|
3576
|
+
return /* @__PURE__ */ jsxs33("div", { className: `${containerClass} ${className ?? ""}`, children: [
|
|
3577
|
+
showAgent && agents.length > 0 && /* @__PURE__ */ jsxs33("label", { className: "space-y-1", children: [
|
|
3578
|
+
/* @__PURE__ */ jsx49("span", { className: "text-xs font-medium text-foreground-subtle", children: "Agent" }),
|
|
3579
|
+
/* @__PURE__ */ jsx49(
|
|
3268
3580
|
"select",
|
|
3269
3581
|
{
|
|
3270
3582
|
value: agentId,
|
|
3271
3583
|
onChange: (e) => onAgentChange?.(e.target.value),
|
|
3272
3584
|
className: SELECT_CLASS,
|
|
3273
|
-
children: agents.map((a) => /* @__PURE__ */
|
|
3585
|
+
children: agents.map((a) => /* @__PURE__ */ jsxs33("option", { value: a.id, children: [
|
|
3274
3586
|
a.name,
|
|
3275
3587
|
" (",
|
|
3276
3588
|
a.status,
|
|
@@ -3279,45 +3591,45 @@ function InferenceConfigSelector({
|
|
|
3279
3591
|
}
|
|
3280
3592
|
)
|
|
3281
3593
|
] }),
|
|
3282
|
-
/* @__PURE__ */
|
|
3283
|
-
/* @__PURE__ */
|
|
3284
|
-
/* @__PURE__ */
|
|
3594
|
+
/* @__PURE__ */ jsxs33("label", { className: "space-y-1", children: [
|
|
3595
|
+
/* @__PURE__ */ jsx49("span", { className: "text-xs font-medium text-foreground-subtle", children: "Runtime" }),
|
|
3596
|
+
/* @__PURE__ */ jsx49(
|
|
3285
3597
|
"select",
|
|
3286
3598
|
{
|
|
3287
3599
|
value: runtime,
|
|
3288
3600
|
onChange: (e) => onRuntimeChange(e.target.value),
|
|
3289
3601
|
className: SELECT_CLASS,
|
|
3290
|
-
children: runtimes.map((r) => /* @__PURE__ */
|
|
3602
|
+
children: runtimes.map((r) => /* @__PURE__ */ jsxs33("option", { value: r.value, disabled: !r.available, children: [
|
|
3291
3603
|
r.label,
|
|
3292
3604
|
!r.available ? " (unavailable)" : ""
|
|
3293
3605
|
] }, r.value))
|
|
3294
3606
|
}
|
|
3295
3607
|
)
|
|
3296
3608
|
] }),
|
|
3297
|
-
/* @__PURE__ */
|
|
3298
|
-
/* @__PURE__ */
|
|
3299
|
-
/* @__PURE__ */
|
|
3609
|
+
/* @__PURE__ */ jsxs33("label", { className: "space-y-1", children: [
|
|
3610
|
+
/* @__PURE__ */ jsx49("span", { className: "text-xs font-medium text-foreground-subtle", children: "Backend" }),
|
|
3611
|
+
/* @__PURE__ */ jsx49(
|
|
3300
3612
|
"select",
|
|
3301
3613
|
{
|
|
3302
3614
|
value: backend,
|
|
3303
3615
|
onChange: (e) => onBackendChange(e.target.value),
|
|
3304
3616
|
className: SELECT_CLASS,
|
|
3305
|
-
children: backends.map((b) => /* @__PURE__ */
|
|
3617
|
+
children: backends.map((b) => /* @__PURE__ */ jsxs33("option", { value: b.id, disabled: !b.available, children: [
|
|
3306
3618
|
b.label,
|
|
3307
3619
|
!b.available ? " (unavailable)" : ""
|
|
3308
3620
|
] }, b.id))
|
|
3309
3621
|
}
|
|
3310
3622
|
)
|
|
3311
3623
|
] }),
|
|
3312
|
-
/* @__PURE__ */
|
|
3313
|
-
/* @__PURE__ */
|
|
3314
|
-
/* @__PURE__ */
|
|
3624
|
+
/* @__PURE__ */ jsxs33("label", { className: "space-y-1", children: [
|
|
3625
|
+
/* @__PURE__ */ jsx49("span", { className: "text-xs font-medium text-foreground-subtle", children: "Model" }),
|
|
3626
|
+
/* @__PURE__ */ jsx49(
|
|
3315
3627
|
"select",
|
|
3316
3628
|
{
|
|
3317
3629
|
value: modelId,
|
|
3318
3630
|
onChange: (e) => onModelChange(e.target.value),
|
|
3319
3631
|
className: SELECT_CLASS,
|
|
3320
|
-
children: models.length === 0 ? /* @__PURE__ */
|
|
3632
|
+
children: models.length === 0 ? /* @__PURE__ */ jsx49("option", { value: "", children: "No compatible models" }) : models.map((m) => /* @__PURE__ */ jsxs33("option", { value: m.id, children: [
|
|
3321
3633
|
m.name,
|
|
3322
3634
|
m.downloaded ? " \u2713" : ""
|
|
3323
3635
|
] }, m.id))
|
|
@@ -3332,15 +3644,15 @@ import { createElement } from "react";
|
|
|
3332
3644
|
import { createRoot } from "react-dom/client";
|
|
3333
3645
|
|
|
3334
3646
|
// src/composites/dev-shell.tsx
|
|
3335
|
-
import { createContext as createContext7, useCallback as useCallback8, useContext as useContext7, useMemo as useMemo4, useState as
|
|
3647
|
+
import { createContext as createContext7, useCallback as useCallback8, useContext as useContext7, useMemo as useMemo4, useState as useState14 } from "react";
|
|
3336
3648
|
import { createTRPCClient, createWSClient, wsLink, httpLink, splitLink } from "@trpc/client";
|
|
3337
3649
|
import superjson from "superjson";
|
|
3338
3650
|
|
|
3339
3651
|
// src/composites/login-form.tsx
|
|
3340
|
-
import { useState as
|
|
3341
|
-
import { jsx as
|
|
3652
|
+
import { useState as useState13 } from "react";
|
|
3653
|
+
import { jsx as jsx50, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
3342
3654
|
function EyeIcon({ className }) {
|
|
3343
|
-
return /* @__PURE__ */
|
|
3655
|
+
return /* @__PURE__ */ jsxs34(
|
|
3344
3656
|
"svg",
|
|
3345
3657
|
{
|
|
3346
3658
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -3352,14 +3664,14 @@ function EyeIcon({ className }) {
|
|
|
3352
3664
|
strokeLinejoin: "round",
|
|
3353
3665
|
className,
|
|
3354
3666
|
children: [
|
|
3355
|
-
/* @__PURE__ */
|
|
3356
|
-
/* @__PURE__ */
|
|
3667
|
+
/* @__PURE__ */ jsx50("path", { d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0" }),
|
|
3668
|
+
/* @__PURE__ */ jsx50("circle", { cx: "12", cy: "12", r: "3" })
|
|
3357
3669
|
]
|
|
3358
3670
|
}
|
|
3359
3671
|
);
|
|
3360
3672
|
}
|
|
3361
3673
|
function EyeOffIcon({ className }) {
|
|
3362
|
-
return /* @__PURE__ */
|
|
3674
|
+
return /* @__PURE__ */ jsxs34(
|
|
3363
3675
|
"svg",
|
|
3364
3676
|
{
|
|
3365
3677
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -3371,16 +3683,16 @@ function EyeOffIcon({ className }) {
|
|
|
3371
3683
|
strokeLinejoin: "round",
|
|
3372
3684
|
className,
|
|
3373
3685
|
children: [
|
|
3374
|
-
/* @__PURE__ */
|
|
3375
|
-
/* @__PURE__ */
|
|
3376
|
-
/* @__PURE__ */
|
|
3377
|
-
/* @__PURE__ */
|
|
3686
|
+
/* @__PURE__ */ jsx50("path", { d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49" }),
|
|
3687
|
+
/* @__PURE__ */ jsx50("path", { d: "M14.084 14.158a3 3 0 0 1-4.242-4.242" }),
|
|
3688
|
+
/* @__PURE__ */ jsx50("path", { d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" }),
|
|
3689
|
+
/* @__PURE__ */ jsx50("path", { d: "m2 2 20 20" })
|
|
3378
3690
|
]
|
|
3379
3691
|
}
|
|
3380
3692
|
);
|
|
3381
3693
|
}
|
|
3382
3694
|
function SpinnerIcon({ className }) {
|
|
3383
|
-
return /* @__PURE__ */
|
|
3695
|
+
return /* @__PURE__ */ jsx50(
|
|
3384
3696
|
"svg",
|
|
3385
3697
|
{
|
|
3386
3698
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -3391,7 +3703,7 @@ function SpinnerIcon({ className }) {
|
|
|
3391
3703
|
strokeLinecap: "round",
|
|
3392
3704
|
strokeLinejoin: "round",
|
|
3393
3705
|
className,
|
|
3394
|
-
children: /* @__PURE__ */
|
|
3706
|
+
children: /* @__PURE__ */ jsx50("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
|
|
3395
3707
|
}
|
|
3396
3708
|
);
|
|
3397
3709
|
}
|
|
@@ -3402,11 +3714,11 @@ function LoginForm({
|
|
|
3402
3714
|
error: externalError,
|
|
3403
3715
|
className
|
|
3404
3716
|
}) {
|
|
3405
|
-
const [username, setUsername] =
|
|
3406
|
-
const [password, setPassword] =
|
|
3407
|
-
const [showPassword, setShowPassword] =
|
|
3408
|
-
const [submitting, setSubmitting] =
|
|
3409
|
-
const [internalError, setInternalError] =
|
|
3717
|
+
const [username, setUsername] = useState13("");
|
|
3718
|
+
const [password, setPassword] = useState13("");
|
|
3719
|
+
const [showPassword, setShowPassword] = useState13(false);
|
|
3720
|
+
const [submitting, setSubmitting] = useState13(false);
|
|
3721
|
+
const [internalError, setInternalError] = useState13(null);
|
|
3410
3722
|
const error = externalError ?? internalError;
|
|
3411
3723
|
const handleSubmit = async (e) => {
|
|
3412
3724
|
e.preventDefault();
|
|
@@ -3422,26 +3734,26 @@ function LoginForm({
|
|
|
3422
3734
|
setSubmitting(false);
|
|
3423
3735
|
}
|
|
3424
3736
|
};
|
|
3425
|
-
return /* @__PURE__ */
|
|
3737
|
+
return /* @__PURE__ */ jsx50(
|
|
3426
3738
|
"div",
|
|
3427
3739
|
{
|
|
3428
3740
|
className: cn(
|
|
3429
3741
|
"flex min-h-screen items-center justify-center bg-background p-4",
|
|
3430
3742
|
className
|
|
3431
3743
|
),
|
|
3432
|
-
children: /* @__PURE__ */
|
|
3433
|
-
logoSrc && /* @__PURE__ */
|
|
3434
|
-
serverUrl && /* @__PURE__ */
|
|
3435
|
-
/* @__PURE__ */
|
|
3744
|
+
children: /* @__PURE__ */ jsxs34("div", { className: "w-full max-w-sm", children: [
|
|
3745
|
+
logoSrc && /* @__PURE__ */ jsx50("div", { className: "flex justify-center mb-8", children: /* @__PURE__ */ jsx50("img", { src: logoSrc, alt: "Logo", className: "h-12" }) }),
|
|
3746
|
+
serverUrl && /* @__PURE__ */ jsx50("p", { className: "mb-4 text-center text-xs text-foreground-subtle truncate", children: serverUrl }),
|
|
3747
|
+
/* @__PURE__ */ jsxs34(
|
|
3436
3748
|
"form",
|
|
3437
3749
|
{
|
|
3438
3750
|
onSubmit: handleSubmit,
|
|
3439
3751
|
className: "space-y-4 rounded-xl border border-border bg-surface p-6 shadow-xl shadow-black/10",
|
|
3440
3752
|
children: [
|
|
3441
|
-
error && /* @__PURE__ */
|
|
3442
|
-
/* @__PURE__ */
|
|
3443
|
-
/* @__PURE__ */
|
|
3444
|
-
/* @__PURE__ */
|
|
3753
|
+
error && /* @__PURE__ */ jsx50("div", { className: "rounded-md bg-danger/10 border border-danger/20 px-3 py-2 text-xs text-danger", children: error }),
|
|
3754
|
+
/* @__PURE__ */ jsxs34("div", { className: "space-y-1.5", children: [
|
|
3755
|
+
/* @__PURE__ */ jsx50("label", { className: "text-xs font-medium text-foreground-subtle", children: "Username" }),
|
|
3756
|
+
/* @__PURE__ */ jsx50(
|
|
3445
3757
|
"input",
|
|
3446
3758
|
{
|
|
3447
3759
|
type: "text",
|
|
@@ -3453,10 +3765,10 @@ function LoginForm({
|
|
|
3453
3765
|
}
|
|
3454
3766
|
)
|
|
3455
3767
|
] }),
|
|
3456
|
-
/* @__PURE__ */
|
|
3457
|
-
/* @__PURE__ */
|
|
3458
|
-
/* @__PURE__ */
|
|
3459
|
-
/* @__PURE__ */
|
|
3768
|
+
/* @__PURE__ */ jsxs34("div", { className: "space-y-1.5", children: [
|
|
3769
|
+
/* @__PURE__ */ jsx50("label", { className: "text-xs font-medium text-foreground-subtle", children: "Password" }),
|
|
3770
|
+
/* @__PURE__ */ jsxs34("div", { className: "relative", children: [
|
|
3771
|
+
/* @__PURE__ */ jsx50(
|
|
3460
3772
|
"input",
|
|
3461
3773
|
{
|
|
3462
3774
|
type: showPassword ? "text" : "password",
|
|
@@ -3467,26 +3779,26 @@ function LoginForm({
|
|
|
3467
3779
|
className: "w-full rounded-lg border border-border bg-background px-3 py-2.5 pr-10 text-sm text-foreground placeholder:text-foreground-subtle focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary"
|
|
3468
3780
|
}
|
|
3469
3781
|
),
|
|
3470
|
-
/* @__PURE__ */
|
|
3782
|
+
/* @__PURE__ */ jsx50(
|
|
3471
3783
|
"button",
|
|
3472
3784
|
{
|
|
3473
3785
|
type: "button",
|
|
3474
3786
|
onClick: () => setShowPassword((prev) => !prev),
|
|
3475
3787
|
className: "absolute right-2.5 top-1/2 -translate-y-1/2 text-foreground-subtle hover:text-foreground",
|
|
3476
3788
|
tabIndex: -1,
|
|
3477
|
-
children: showPassword ? /* @__PURE__ */
|
|
3789
|
+
children: showPassword ? /* @__PURE__ */ jsx50(EyeOffIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx50(EyeIcon, { className: "h-4 w-4" })
|
|
3478
3790
|
}
|
|
3479
3791
|
)
|
|
3480
3792
|
] })
|
|
3481
3793
|
] }),
|
|
3482
|
-
/* @__PURE__ */
|
|
3794
|
+
/* @__PURE__ */ jsxs34(
|
|
3483
3795
|
"button",
|
|
3484
3796
|
{
|
|
3485
3797
|
type: "submit",
|
|
3486
3798
|
disabled: submitting,
|
|
3487
3799
|
className: "w-full rounded-lg bg-primary px-4 py-2.5 text-sm font-semibold text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors flex items-center justify-center gap-2",
|
|
3488
3800
|
children: [
|
|
3489
|
-
submitting && /* @__PURE__ */
|
|
3801
|
+
submitting && /* @__PURE__ */ jsx50(SpinnerIcon, { className: "h-4 w-4 animate-spin" }),
|
|
3490
3802
|
submitting ? "Logging in..." : "Log in"
|
|
3491
3803
|
]
|
|
3492
3804
|
}
|
|
@@ -3500,7 +3812,7 @@ function LoginForm({
|
|
|
3500
3812
|
}
|
|
3501
3813
|
|
|
3502
3814
|
// src/composites/dev-shell.tsx
|
|
3503
|
-
import { jsx as
|
|
3815
|
+
import { jsx as jsx51, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3504
3816
|
var STORAGE_KEY = "camstack_dev_token";
|
|
3505
3817
|
var DevShellContext = createContext7(null);
|
|
3506
3818
|
function useDevShell() {
|
|
@@ -3515,7 +3827,7 @@ function getStoredToken() {
|
|
|
3515
3827
|
return localStorage.getItem(STORAGE_KEY);
|
|
3516
3828
|
}
|
|
3517
3829
|
function SunIcon({ className }) {
|
|
3518
|
-
return /* @__PURE__ */
|
|
3830
|
+
return /* @__PURE__ */ jsxs35(
|
|
3519
3831
|
"svg",
|
|
3520
3832
|
{
|
|
3521
3833
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -3527,21 +3839,21 @@ function SunIcon({ className }) {
|
|
|
3527
3839
|
strokeLinejoin: "round",
|
|
3528
3840
|
className,
|
|
3529
3841
|
children: [
|
|
3530
|
-
/* @__PURE__ */
|
|
3531
|
-
/* @__PURE__ */
|
|
3532
|
-
/* @__PURE__ */
|
|
3533
|
-
/* @__PURE__ */
|
|
3534
|
-
/* @__PURE__ */
|
|
3535
|
-
/* @__PURE__ */
|
|
3536
|
-
/* @__PURE__ */
|
|
3537
|
-
/* @__PURE__ */
|
|
3538
|
-
/* @__PURE__ */
|
|
3842
|
+
/* @__PURE__ */ jsx51("circle", { cx: "12", cy: "12", r: "4" }),
|
|
3843
|
+
/* @__PURE__ */ jsx51("path", { d: "M12 2v2" }),
|
|
3844
|
+
/* @__PURE__ */ jsx51("path", { d: "M12 20v2" }),
|
|
3845
|
+
/* @__PURE__ */ jsx51("path", { d: "m4.93 4.93 1.41 1.41" }),
|
|
3846
|
+
/* @__PURE__ */ jsx51("path", { d: "m17.66 17.66 1.41 1.41" }),
|
|
3847
|
+
/* @__PURE__ */ jsx51("path", { d: "M2 12h2" }),
|
|
3848
|
+
/* @__PURE__ */ jsx51("path", { d: "M20 12h2" }),
|
|
3849
|
+
/* @__PURE__ */ jsx51("path", { d: "m6.34 17.66-1.41 1.41" }),
|
|
3850
|
+
/* @__PURE__ */ jsx51("path", { d: "m19.07 4.93-1.41 1.41" })
|
|
3539
3851
|
]
|
|
3540
3852
|
}
|
|
3541
3853
|
);
|
|
3542
3854
|
}
|
|
3543
3855
|
function MoonIcon({ className }) {
|
|
3544
|
-
return /* @__PURE__ */
|
|
3856
|
+
return /* @__PURE__ */ jsx51(
|
|
3545
3857
|
"svg",
|
|
3546
3858
|
{
|
|
3547
3859
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -3552,7 +3864,7 @@ function MoonIcon({ className }) {
|
|
|
3552
3864
|
strokeLinecap: "round",
|
|
3553
3865
|
strokeLinejoin: "round",
|
|
3554
3866
|
className,
|
|
3555
|
-
children: /* @__PURE__ */
|
|
3867
|
+
children: /* @__PURE__ */ jsx51("path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" })
|
|
3556
3868
|
}
|
|
3557
3869
|
);
|
|
3558
3870
|
}
|
|
@@ -3591,15 +3903,15 @@ function DevShellInner({
|
|
|
3591
3903
|
() => ({ trpc, token, logout: onLogout }),
|
|
3592
3904
|
[trpc, token, onLogout]
|
|
3593
3905
|
);
|
|
3594
|
-
return /* @__PURE__ */
|
|
3595
|
-
/* @__PURE__ */
|
|
3596
|
-
/* @__PURE__ */
|
|
3597
|
-
/* @__PURE__ */
|
|
3598
|
-
title && /* @__PURE__ */
|
|
3599
|
-
/* @__PURE__ */
|
|
3906
|
+
return /* @__PURE__ */ jsx51(DevShellContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs35("div", { className: "min-h-screen bg-background text-foreground", children: [
|
|
3907
|
+
/* @__PURE__ */ jsxs35("div", { className: "flex items-center justify-between border-b border-border bg-surface px-4 py-2", children: [
|
|
3908
|
+
/* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-2", children: [
|
|
3909
|
+
/* @__PURE__ */ jsx51("span", { className: "rounded bg-warning/20 px-2 py-0.5 text-xs font-bold text-warning", children: "DEV MODE" }),
|
|
3910
|
+
title && /* @__PURE__ */ jsx51("span", { className: "text-sm font-medium text-foreground", children: title }),
|
|
3911
|
+
/* @__PURE__ */ jsx51("span", { className: "text-xs text-foreground-subtle", children: serverUrl })
|
|
3600
3912
|
] }),
|
|
3601
|
-
/* @__PURE__ */
|
|
3602
|
-
/* @__PURE__ */
|
|
3913
|
+
/* @__PURE__ */ jsxs35("div", { className: "flex items-center gap-2", children: [
|
|
3914
|
+
/* @__PURE__ */ jsxs35(
|
|
3603
3915
|
"button",
|
|
3604
3916
|
{
|
|
3605
3917
|
type: "button",
|
|
@@ -3607,12 +3919,12 @@ function DevShellInner({
|
|
|
3607
3919
|
className: "flex items-center gap-1.5 rounded-md px-2 py-1 text-xs font-medium text-foreground-subtle hover:text-foreground hover:bg-surface-hover transition-colors",
|
|
3608
3920
|
title: `Theme: ${theme.mode}`,
|
|
3609
3921
|
children: [
|
|
3610
|
-
theme.resolvedMode === "dark" ? /* @__PURE__ */
|
|
3922
|
+
theme.resolvedMode === "dark" ? /* @__PURE__ */ jsx51(SunIcon, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx51(MoonIcon, { className: "h-3.5 w-3.5" }),
|
|
3611
3923
|
theme.mode === "dark" ? "Dark" : theme.mode === "light" ? "Light" : "System"
|
|
3612
3924
|
]
|
|
3613
3925
|
}
|
|
3614
3926
|
),
|
|
3615
|
-
/* @__PURE__ */
|
|
3927
|
+
/* @__PURE__ */ jsx51(
|
|
3616
3928
|
"button",
|
|
3617
3929
|
{
|
|
3618
3930
|
type: "button",
|
|
@@ -3623,7 +3935,7 @@ function DevShellInner({
|
|
|
3623
3935
|
)
|
|
3624
3936
|
] })
|
|
3625
3937
|
] }),
|
|
3626
|
-
/* @__PURE__ */
|
|
3938
|
+
/* @__PURE__ */ jsx51("div", { className: "p-4", children: children({ trpc, theme }) })
|
|
3627
3939
|
] }) });
|
|
3628
3940
|
}
|
|
3629
3941
|
function DevShell({
|
|
@@ -3631,7 +3943,7 @@ function DevShell({
|
|
|
3631
3943
|
serverUrl = "https://localhost:4443",
|
|
3632
3944
|
title
|
|
3633
3945
|
}) {
|
|
3634
|
-
const [token, setToken] =
|
|
3946
|
+
const [token, setToken] = useState14(getStoredToken);
|
|
3635
3947
|
const handleLogin = useCallback8(
|
|
3636
3948
|
async (username, password) => {
|
|
3637
3949
|
const anonClient = createTRPCClient({
|
|
@@ -3654,9 +3966,9 @@ function DevShell({
|
|
|
3654
3966
|
setToken(null);
|
|
3655
3967
|
}, []);
|
|
3656
3968
|
if (!token) {
|
|
3657
|
-
return /* @__PURE__ */
|
|
3969
|
+
return /* @__PURE__ */ jsx51(ThemeProvider, { children: /* @__PURE__ */ jsx51(LoginForm, { onLogin: handleLogin, serverUrl }) });
|
|
3658
3970
|
}
|
|
3659
|
-
return /* @__PURE__ */
|
|
3971
|
+
return /* @__PURE__ */ jsx51(ThemeProvider, { children: /* @__PURE__ */ jsx51(
|
|
3660
3972
|
DevShellInner,
|
|
3661
3973
|
{
|
|
3662
3974
|
serverUrl,
|
|
@@ -3697,6 +4009,7 @@ function mountAddonPage(PageComponent, options = {}) {
|
|
|
3697
4009
|
export {
|
|
3698
4010
|
AppShell,
|
|
3699
4011
|
Badge,
|
|
4012
|
+
BottomSheet,
|
|
3700
4013
|
Button,
|
|
3701
4014
|
CLASS_COLORS,
|
|
3702
4015
|
Card,
|
|
@@ -3733,6 +4046,7 @@ export {
|
|
|
3733
4046
|
KeyValueList,
|
|
3734
4047
|
Label,
|
|
3735
4048
|
LoginForm,
|
|
4049
|
+
MobileDrawer,
|
|
3736
4050
|
PageHeader,
|
|
3737
4051
|
PipelineBuilder,
|
|
3738
4052
|
PipelineRuntimeSelector,
|
|
@@ -3772,6 +4086,7 @@ export {
|
|
|
3772
4086
|
statusIcons,
|
|
3773
4087
|
themeToCss,
|
|
3774
4088
|
useDevShell,
|
|
4089
|
+
useIsMobile,
|
|
3775
4090
|
useThemeMode
|
|
3776
4091
|
};
|
|
3777
4092
|
//# sourceMappingURL=index.js.map
|