@bugbug-io/cli 13.39.2 → 14.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,28 +1,17 @@
1
1
  import {
2
- BaseSuiteRunDetails,
3
- BaseTestRunDetails,
4
- DEFAULT_RESERVED_TERMINAL_ROWS,
5
- EscProvider,
6
- MenuList,
7
- ROUTES,
8
- SelectableOption,
9
- SelectionPrefix,
10
- ShortcutProvider,
11
- Status,
12
- ViewLayout,
13
- VirtualizedList,
14
2
  analytics,
15
3
  defaultJunitReportPath,
16
4
  detectFormat,
17
5
  exportProject,
18
6
  exportTest,
19
7
  formatCwd,
20
- formatDuration,
21
8
  formatErrorMessage,
9
+ formatFinalResults,
22
10
  formatRunStatus,
23
11
  getCliConfig,
24
12
  getIdentity,
25
13
  getProjectById,
14
+ getRunErrorMessage,
26
15
  getSuite,
27
16
  getSuiteDetails,
28
17
  getSuiteRunDetails,
@@ -38,6 +27,8 @@ import {
38
27
  initProject,
39
28
  isAuthenticationError,
40
29
  isAuthorizationError,
30
+ isCompletedStatus,
31
+ isRunningStatus,
41
32
  listProfiles,
42
33
  listProjects,
43
34
  listSuiteRuns,
@@ -52,18 +43,16 @@ import {
52
43
  runTest,
53
44
  switchProject,
54
45
  updateSdkConfig,
55
- useEscHandler,
56
- useShortcutBlocker,
57
- useShortcutHandler,
58
- useTheme,
59
46
  userCwd,
47
+ waitForSuiteRun,
48
+ waitForTestRun,
60
49
  writeReportXml
61
- } from "./chunk-GNCJ7Y4W.js";
50
+ } from "./chunk-4IJVD32G.js";
62
51
  import "./chunk-BSHFIPEX.js";
63
52
  import "./chunk-PR4QN5HX.js";
64
53
 
65
54
  // src/app/NavigatorApp.tsx
66
- import { useState as useState17 } from "react";
55
+ import { useState as useState21 } from "react";
67
56
  import { RouterProvider } from "react-router";
68
57
 
69
58
  // src/app/contexts/navigatorSession/NavigatorSessionContext.tsx
@@ -131,6 +120,14 @@ var NavigatorSessionProvider = ({ children }) => {
131
120
  setAuthState({});
132
121
  setAuthError(null);
133
122
  }, []);
123
+ const adoptTokenProject = useCallback((projectId) => {
124
+ const trimmedProjectId = projectId.trim();
125
+ if (!trimmedProjectId) return;
126
+ updateSdkConfig({ projectId: trimmedProjectId });
127
+ setAuthState(
128
+ (current) => current.projectId ? current : { ...current, projectId: trimmedProjectId }
129
+ );
130
+ }, []);
134
131
  const setSessionProject = useCallback((projectId) => {
135
132
  try {
136
133
  const trimmedProjectId = projectId.trim();
@@ -147,7 +144,15 @@ var NavigatorSessionProvider = ({ children }) => {
147
144
  return /* @__PURE__ */ jsx(
148
145
  NavigatorSessionContext.Provider,
149
146
  {
150
- value: { auth, config, authError, completeSession, clearSession, setSessionProject },
147
+ value: {
148
+ auth,
149
+ config,
150
+ authError,
151
+ completeSession,
152
+ clearSession,
153
+ setSessionProject,
154
+ adoptTokenProject
155
+ },
151
156
  children
152
157
  }
153
158
  );
@@ -164,7 +169,7 @@ var useNavigatorSession = () => {
164
169
  import { createMemoryRouter, createRoutesFromElements, Route } from "react-router";
165
170
 
166
171
  // src/app/Navigator.tsx
167
- import { Box as Box4, useApp, useInput } from "ink";
172
+ import { Box as Box4, useApp, useInput as useInput3 } from "ink";
168
173
  import { useState as useState4 } from "react";
169
174
  import { Outlet, useLocation as useLocation3, useNavigate as useNavigate2 } from "react-router";
170
175
 
@@ -216,15 +221,21 @@ var useConnectionStatus = (enabled) => {
216
221
  import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
217
222
  var INIT_ROUTE = "/init";
218
223
  var AuthGate = ({ children }) => {
219
- const { auth } = useNavigatorSession();
224
+ const { auth, adoptTokenProject } = useNavigatorSession();
220
225
  const location = useLocation();
221
226
  const navigate = useNavigate();
222
227
  const onInitRoute = location.pathname === INIT_ROUTE;
223
- const hasConfiguredAuth = auth.kind === "ready";
228
+ const hasConfiguredAuth = Boolean(auth.token);
224
229
  const connectionStatus = useConnectionStatus(hasConfiguredAuth);
230
+ const identity = connectionStatus.identity;
231
+ const tokenProjectId = identity?.tokenType === "project" ? identity.projectId : null;
232
+ const projectId = auth.projectId ?? tokenProjectId;
225
233
  const authCheckPending = hasConfiguredAuth && connectionStatus.state === "checking";
226
234
  const authRejected = hasConfiguredAuth && connectionStatus.state === "unauthenticated";
227
- const authenticated = hasConfiguredAuth && !authRejected;
235
+ const authenticated = hasConfiguredAuth && !authRejected && Boolean(projectId);
236
+ useEffect2(() => {
237
+ if (tokenProjectId && !auth.projectId) adoptTokenProject(tokenProjectId);
238
+ }, [adoptTokenProject, auth.projectId, tokenProjectId]);
228
239
  useEffect2(() => {
229
240
  if (!authCheckPending && !authenticated && !onInitRoute) {
230
241
  navigate(INIT_ROUTE, {
@@ -246,6 +257,90 @@ var AuthGate = ({ children }) => {
246
257
  // src/app/components/Header/Header.tsx
247
258
  import { Box, Text } from "ink";
248
259
 
260
+ // src/features/tui/theme.ts
261
+ var colors = {
262
+ brand: "#4c2b8b",
263
+ primary: "#521ec9",
264
+ primarySoft: "#8466CA",
265
+ accent: "#ffcd1c",
266
+ accentSoft: "#FFF8EA",
267
+ primaryActive: "#6029df",
268
+ primaryInactive: "#a489e2",
269
+ common: {
270
+ transparent: "transparent",
271
+ white: "#ffffff",
272
+ black: "#000000",
273
+ muted: "#f4f3fb"
274
+ },
275
+ background: {
276
+ primary: "#E8E9FF",
277
+ primary97: "#F4F3FB",
278
+ primary99: "#F9F9FF",
279
+ accent: "#FFF8EA",
280
+ surface: "#FFFFFF",
281
+ success: "#D1FBE2",
282
+ failure: "#FFF0F0",
283
+ neutral: "#FAFAFA",
284
+ highlight: "#F4F3FB",
285
+ highlightLight: "#F9F9FF"
286
+ },
287
+ text: {
288
+ normal: "#2b2b2b",
289
+ secondary: "#666666",
290
+ subtle: "#7A7F86",
291
+ lighter: "#8B8B8B",
292
+ secondaryAllCaps: "#A2A1A1",
293
+ emptyState: "#999999"
294
+ },
295
+ border: {
296
+ normal: "#2B2B2B",
297
+ dark: "#AAAAAA",
298
+ important: "#CCC9C9",
299
+ medium: "#E5E5E5",
300
+ semi: "#EBEBEB",
301
+ light: "#EFEFEF",
302
+ superLight: "#F1F1F3"
303
+ },
304
+ neutrals: {
305
+ "40": "#666666",
306
+ "80": "#CCCBCB",
307
+ "92": "#EAEAEA",
308
+ "94": "#EFEFEF",
309
+ "96": "#F5F5F5",
310
+ "97": "#F7F7F7"
311
+ },
312
+ status: {
313
+ success: "#4dbf8b",
314
+ success90: "#D1FBE2",
315
+ failure: "#e85b5b",
316
+ stopped: "#898989",
317
+ info: "blue",
318
+ debugging: "#ffcd1c",
319
+ warning: "#FFB100",
320
+ initialized: "#999999",
321
+ recording: "#EF2E51",
322
+ paused: "#ffcd1c",
323
+ skipped: "#8A8A8A"
324
+ },
325
+ code: {
326
+ blue: "#82aaff",
327
+ violet: "#c792ea",
328
+ yellow: "#d4c612",
329
+ red: "#ff5370",
330
+ ruby: "#f17c83"
331
+ },
332
+ block: {
333
+ if: {
334
+ background: "#f2f8fc",
335
+ marker: "#cfeeff"
336
+ }
337
+ }
338
+ };
339
+ var theme = {
340
+ colors
341
+ };
342
+ var useTheme = () => ({ theme });
343
+
249
344
  // src/app/hooks/useFeatureQuery.ts
250
345
  import { useCallback as useCallback2, useEffect as useEffect3, useState as useState3 } from "react";
251
346
  var useFeatureQuery = (fn, deps) => {
@@ -326,14 +421,14 @@ var STATUS_COLOR = {
326
421
  // src/app/components/Header/Header.tsx
327
422
  import { jsx as jsx3, jsxs } from "react/jsx-runtime";
328
423
  var Header = ({ authenticated }) => {
329
- const { theme } = useTheme();
424
+ const { theme: theme2 } = useTheme();
330
425
  const status = useConnectionStatus(authenticated);
331
426
  const project = useCurrentProject(authenticated);
332
427
  const identity = authenticated ? status.identity : void 0;
333
428
  const state = authenticated ? status.state : "unauthenticated";
334
429
  const showDetail = authenticated && (status.state === "error" || status.state === "unauthenticated") && !!status.message;
335
430
  return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, children: [
336
- /* @__PURE__ */ jsx3(Box, { marginRight: 1, children: /* @__PURE__ */ jsx3(Text, { color: theme.colors.brand, children: BUGBUG_LOGO_ASCII }) }),
431
+ /* @__PURE__ */ jsx3(Box, { marginRight: 1, children: /* @__PURE__ */ jsx3(Text, { color: theme2.colors.brand, children: BUGBUG_LOGO_ASCII }) }),
337
432
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
338
433
  /* @__PURE__ */ jsxs(Text, { children: [
339
434
  /* @__PURE__ */ jsx3(Text, { bold: true, children: "BugBug" }),
@@ -489,15 +584,152 @@ var ShortcutsGrid = () => /* @__PURE__ */ jsxs2(Box3, { marginTop: 1, borderStyl
489
584
  /* @__PURE__ */ jsx5(ShortcutColumn, { title: "Actions", items: ACTION_SHORTCUTS })
490
585
  ] });
491
586
 
587
+ // src/features/tui/EscController.tsx
588
+ import { useInput } from "ink";
589
+ import { createContext as createContext2, useContext as useContext2, useEffect as useEffect4, useRef } from "react";
590
+ import { jsx as jsx6 } from "react/jsx-runtime";
591
+ var EscContext = createContext2(null);
592
+ var EscProvider = ({
593
+ onUnhandled,
594
+ canGoBack = true,
595
+ children
596
+ }) => {
597
+ const handlersRef = useRef([]);
598
+ const register = (handler) => {
599
+ handlersRef.current.push(handler);
600
+ return () => {
601
+ handlersRef.current = handlersRef.current.filter((h) => h !== handler);
602
+ };
603
+ };
604
+ useInput((_input, key) => {
605
+ if (!key.escape) return;
606
+ for (let i = handlersRef.current.length - 1; i >= 0; i -= 1) {
607
+ if (handlersRef.current[i]()) return;
608
+ }
609
+ onUnhandled();
610
+ });
611
+ return /* @__PURE__ */ jsx6(EscContext.Provider, { value: { register, canGoBack }, children });
612
+ };
613
+ var useEscHandler = (handler) => {
614
+ const registry = useContext2(EscContext);
615
+ const handlerRef = useRef(handler);
616
+ handlerRef.current = handler;
617
+ useEffect4(() => {
618
+ if (!registry) return void 0;
619
+ return registry.register(() => handlerRef.current());
620
+ }, [registry]);
621
+ };
622
+ var useCanGoBack = () => {
623
+ const registry = useContext2(EscContext);
624
+ return registry?.canGoBack ?? false;
625
+ };
626
+
627
+ // src/features/tui/ShortcutController.tsx
628
+ import { useInput as useInput2 } from "ink";
629
+ import { createContext as createContext3, useContext as useContext3, useEffect as useEffect5, useRef as useRef2 } from "react";
630
+ import { jsx as jsx7 } from "react/jsx-runtime";
631
+ var ShortcutContext = createContext3(null);
632
+ var ShortcutProvider = ({ children }) => {
633
+ const entriesRef = useRef2([]);
634
+ const blockerCountRef = useRef2(0);
635
+ const nextOrderRef = useRef2(0);
636
+ const register = (handler, options = {}) => {
637
+ const entry = {
638
+ handler,
639
+ priority: options.priority ?? 0,
640
+ order: nextOrderRef.current
641
+ };
642
+ nextOrderRef.current += 1;
643
+ entriesRef.current.push(entry);
644
+ return () => {
645
+ entriesRef.current = entriesRef.current.filter((current) => current !== entry);
646
+ };
647
+ };
648
+ const block = () => {
649
+ blockerCountRef.current += 1;
650
+ return () => {
651
+ blockerCountRef.current = Math.max(0, blockerCountRef.current - 1);
652
+ };
653
+ };
654
+ useInput2((input, key) => {
655
+ if (blockerCountRef.current > 0) return;
656
+ const entries = entriesRef.current.toSorted((a, b) => {
657
+ if (a.priority !== b.priority) return b.priority - a.priority;
658
+ return b.order - a.order;
659
+ });
660
+ for (const entry of entries) {
661
+ if (entry.handler({ input, key })) return;
662
+ }
663
+ });
664
+ return /* @__PURE__ */ jsx7(ShortcutContext.Provider, { value: { register, block }, children });
665
+ };
666
+ var useShortcutHandler = (handler, options = {}) => {
667
+ const registry = useContext3(ShortcutContext);
668
+ const handlerRef = useRef2(handler);
669
+ const priorityRef = useRef2(options.priority);
670
+ handlerRef.current = handler;
671
+ priorityRef.current = options.priority;
672
+ useEffect5(() => {
673
+ if (!registry) return void 0;
674
+ return registry.register((event) => handlerRef.current(event), {
675
+ priority: priorityRef.current
676
+ });
677
+ }, [registry]);
678
+ };
679
+ var useShortcutBlocker = (enabled = true) => {
680
+ const registry = useContext3(ShortcutContext);
681
+ useEffect5(() => {
682
+ if (!registry || !enabled) return void 0;
683
+ return registry.block();
684
+ }, [registry, enabled]);
685
+ };
686
+
492
687
  // src/features/tui/ShortcutController.constants.ts
493
688
  var GLOBAL_SHORTCUT_PRIORITY = -100;
494
689
  var HELP_SHORTCUT_PRIORITY = 100;
495
690
 
691
+ // src/app/routes.ts
692
+ var ROUTES = {
693
+ root: () => "/",
694
+ view: (viewKey) => `/${viewKey}`,
695
+ action: (viewKey, actionKey) => `/${viewKey}/${actionKey}`,
696
+ tests: {
697
+ list: () => "/tests/list",
698
+ details: (testId) => `/tests/${testId}`,
699
+ run: (testId) => `/tests/${testId}/run`,
700
+ lastRun: (testId) => `/tests/${testId}/lastRun`,
701
+ export: (testId) => `/tests/${testId}/export`,
702
+ open: (testId) => `/tests/${testId}/open`
703
+ },
704
+ testRuns: {
705
+ root: () => "/testruns",
706
+ list: () => "/testruns/list",
707
+ details: (runId) => `/testruns/${runId}`,
708
+ debugArtifacts: (runId) => `/testruns/${runId}/debugArtifacts`,
709
+ junitReport: (runId) => `/testruns/${runId}/junitReport`,
710
+ open: (runId) => `/testruns/${runId}/open`
711
+ },
712
+ suites: {
713
+ list: () => "/suites/list",
714
+ details: (suiteId) => `/suites/${suiteId}`,
715
+ run: (suiteId) => `/suites/${suiteId}/run`,
716
+ lastRun: (suiteId) => `/suites/${suiteId}/lastRun`,
717
+ open: (suiteId) => `/suites/${suiteId}/open`
718
+ },
719
+ suiteRuns: {
720
+ root: () => "/suiteruns",
721
+ list: () => "/suiteruns/list",
722
+ details: (runId) => `/suiteruns/${runId}`,
723
+ showTestRuns: (runId) => `/suiteruns/${runId}/showTestRuns`,
724
+ open: (runId) => `/suiteruns/${runId}/open`
725
+ }
726
+ };
727
+
496
728
  // src/app/Navigator.tsx
497
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
729
+ import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
498
730
  var Navigator = () => {
499
731
  const [shortcutsVisible, setShortcutsVisible] = useState4(false);
500
- return /* @__PURE__ */ jsx6(ShortcutProvider, { children: /* @__PURE__ */ jsx6(
732
+ return /* @__PURE__ */ jsx8(ShortcutProvider, { children: /* @__PURE__ */ jsx8(
501
733
  NavigatorShell,
502
734
  {
503
735
  shortcutsVisible,
@@ -513,7 +745,7 @@ var NavigatorShell = ({
513
745
  const navigate = useNavigate2();
514
746
  const location = useLocation3();
515
747
  const atRoot = location.pathname === ROUTES.root();
516
- useInput((input, key) => {
748
+ useInput3((input, key) => {
517
749
  if (key.ctrl && input === "c") {
518
750
  exit();
519
751
  return;
@@ -546,7 +778,7 @@ var NavigatorShell = ({
546
778
  },
547
779
  { priority: GLOBAL_SHORTCUT_PRIORITY }
548
780
  );
549
- return /* @__PURE__ */ jsx6(Box4, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx6(AuthGate, { children: (authenticated) => /* @__PURE__ */ jsxs3(
781
+ return /* @__PURE__ */ jsx8(Box4, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx8(AuthGate, { children: (authenticated) => /* @__PURE__ */ jsxs3(
550
782
  EscProvider,
551
783
  {
552
784
  canGoBack: !atRoot,
@@ -554,10 +786,10 @@ var NavigatorShell = ({
554
786
  if (!atRoot) navigate(-1);
555
787
  },
556
788
  children: [
557
- /* @__PURE__ */ jsx6(Header, { authenticated }),
558
- authenticated && /* @__PURE__ */ jsx6(Breadcrumb, {}),
559
- /* @__PURE__ */ jsx6(Outlet, {}),
560
- shortcutsVisible && /* @__PURE__ */ jsx6(ShortcutsGrid, {})
789
+ /* @__PURE__ */ jsx8(Header, { authenticated }),
790
+ authenticated && /* @__PURE__ */ jsx8(Breadcrumb, {}),
791
+ /* @__PURE__ */ jsx8(Outlet, {}),
792
+ shortcutsVisible && /* @__PURE__ */ jsx8(ShortcutsGrid, {})
561
793
  ]
562
794
  }
563
795
  ) }) });
@@ -566,12 +798,115 @@ var NavigatorShell = ({
566
798
  // src/app/views/logout/Logout.tsx
567
799
  import { StatusMessage } from "@inkjs/ui";
568
800
  import { useApp as useApp2 } from "ink";
569
- import { useEffect as useEffect4, useState as useState5 } from "react";
570
- import { jsx as jsx7 } from "react/jsx-runtime";
801
+ import { useEffect as useEffect7, useState as useState6 } from "react";
802
+
803
+ // src/features/tui/layouts/ViewLayout/ViewLayout.tsx
804
+ import { Box as Box5, Text as Text4, useInput as useInput4 } from "ink";
805
+ import { useEffect as useEffect6, useState as useState5 } from "react";
806
+
807
+ // src/features/tui/layouts/ViewLayout/ViewLayout.constants.ts
808
+ var GO_BACK = "Esc to go back";
809
+ var CLOSE = "q to close";
810
+ var NAVIGATION = "\u2191/\u2193 to navigate";
811
+ var SELECT = "Enter to select";
812
+ var SEARCH = "/ search";
813
+ var HELP = "? for shortcuts";
814
+ var VIEW_HINTS = {
815
+ GO_BACK,
816
+ CLOSE,
817
+ SELECT,
818
+ SEARCH,
819
+ HELP,
820
+ SEARCH_MODE_DEFAULT: "type to search \xB7 Enter to search \xB7 Esc to clear",
821
+ NAVIGATION_SELECT: `${NAVIGATION} \xB7 ${SELECT}`,
822
+ CONFIRM: "Enter to confirm",
823
+ NAVIGATION_OPEN_SELECT: `${NAVIGATION} \xB7 Enter to open/select`
824
+ };
825
+ var HINT_TEXT = {
826
+ confirm: VIEW_HINTS.CONFIRM,
827
+ navigationOpenSelect: VIEW_HINTS.NAVIGATION_OPEN_SELECT,
828
+ navigationSelect: VIEW_HINTS.NAVIGATION_SELECT
829
+ };
830
+
831
+ // src/features/tui/layouts/ViewLayout/ViewLayout.tsx
832
+ import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
833
+ var ViewLayout = ({
834
+ title,
835
+ hints: hintsOverride,
836
+ hintsHidden = false,
837
+ hintsPosition = "top",
838
+ searchable = false,
839
+ onSearch,
840
+ onSearchModeChange,
841
+ children
842
+ }) => {
843
+ const canGoBack = useCanGoBack();
844
+ const [searchMode, setSearchMode] = useState5(false);
845
+ const [searchText, setSearchText] = useState5("");
846
+ const defaultHints = [VIEW_HINTS.NAVIGATION_SELECT, searchable ? VIEW_HINTS.SEARCH : null];
847
+ const localHints = hintsOverride === "none" ? [] : hintsOverride !== void 0 ? [HINT_TEXT[hintsOverride]] : defaultHints;
848
+ const hintsParts = [
849
+ ...hintsHidden ? [] : localHints,
850
+ VIEW_HINTS.HELP,
851
+ canGoBack ? VIEW_HINTS.GO_BACK : VIEW_HINTS.CLOSE
852
+ ];
853
+ const hints = hintsHidden ? hintsParts.filter(Boolean).join(" \xB7 ") : searchMode ? VIEW_HINTS.SEARCH_MODE_DEFAULT : hintsParts.filter(Boolean).join(" \xB7 ");
854
+ const showSearch = searchable && (searchMode || searchText);
855
+ const showTopHints = hints && hintsPosition === "top";
856
+ const showBottomHints = hints && hintsPosition === "bottom";
857
+ useEffect6(() => {
858
+ onSearchModeChange?.(searchMode);
859
+ }, [onSearchModeChange, searchMode]);
860
+ useShortcutBlocker(searchMode);
861
+ useEscHandler(() => {
862
+ if (!searchable) return false;
863
+ if (searchMode) {
864
+ setSearchMode(false);
865
+ setSearchText("");
866
+ if (onSearch && searchText) onSearch("");
867
+ return true;
868
+ }
869
+ if (searchText) {
870
+ setSearchText("");
871
+ onSearch?.("");
872
+ return true;
873
+ }
874
+ return false;
875
+ });
876
+ useInput4((input, key) => {
877
+ if (!searchable) return;
878
+ if (searchMode) {
879
+ if (key.return) {
880
+ setSearchMode(false);
881
+ onSearch?.(searchText);
882
+ return;
883
+ }
884
+ if (key.backspace || key.delete) {
885
+ setSearchText((current) => current.slice(0, -1));
886
+ return;
887
+ }
888
+ if (input && !key.ctrl && !key.meta && !key.escape) {
889
+ setSearchText((current) => current + input);
890
+ }
891
+ return;
892
+ }
893
+ if (input === "/") setSearchMode(true);
894
+ });
895
+ return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", children: [
896
+ title && /* @__PURE__ */ jsx9(Box5, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text4, { bold: true, children: title }) }),
897
+ showTopHints && /* @__PURE__ */ jsx9(Box5, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text4, { dimColor: true, children: hints }) }),
898
+ showSearch && /* @__PURE__ */ jsx9(Box5, { marginBottom: 1, children: /* @__PURE__ */ jsx9(Text4, { children: `Search: ${searchText}${searchMode ? "\u2588" : ""}` }) }),
899
+ /* @__PURE__ */ jsx9(Box5, { flexDirection: "column", children }),
900
+ showBottomHints && /* @__PURE__ */ jsx9(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text4, { dimColor: true, children: hints }) })
901
+ ] });
902
+ };
903
+
904
+ // src/app/views/logout/Logout.tsx
905
+ import { jsx as jsx10 } from "react/jsx-runtime";
571
906
  var Logout = () => {
572
907
  const { exit } = useApp2();
573
- const [error, setError] = useState5(null);
574
- useEffect4(() => {
908
+ const [error, setError] = useState6(null);
909
+ useEffect7(() => {
575
910
  let cleared;
576
911
  try {
577
912
  ({ cleared } = logout());
@@ -582,7 +917,7 @@ var Logout = () => {
582
917
  process.stdout.write(cleared ? "Logged out.\n" : "Already logged out.\n");
583
918
  exit();
584
919
  }, [exit]);
585
- return /* @__PURE__ */ jsx7(ViewLayout, { title: "Logout", hintsHidden: true, children: error && /* @__PURE__ */ jsx7(StatusMessage, { variant: "error", children: `Error: ${error}` }) });
920
+ return /* @__PURE__ */ jsx10(ViewLayout, { title: "Logout", hintsHidden: true, children: error && /* @__PURE__ */ jsx10(StatusMessage, { variant: "error", children: `Error: ${error}` }) });
586
921
  };
587
922
 
588
923
  // src/app/hooks/useIsUserToken.ts
@@ -596,8 +931,162 @@ var useIsUserToken = () => {
596
931
  return auth.isUserToken || query.data === "user";
597
932
  };
598
933
 
934
+ // src/features/tui/components/MenuList/MenuList.tsx
935
+ import { useNavigate as useNavigate3 } from "react-router";
936
+
937
+ // src/features/tui/components/VirtualizedList/VirtualizedList.tsx
938
+ import { Box as Box6, Text as Text5, useInput as useInput5, useStdout } from "ink";
939
+ import { useRef as useRef3, useState as useState7 } from "react";
940
+
941
+ // src/features/tui/components/VirtualizedList/VirtualizedList.constants.ts
942
+ var DEFAULT_RESERVED_TERMINAL_ROWS = 13;
943
+ var MIN_VIEWPORT_ROWS = 3;
944
+ var FALLBACK_TERMINAL_ROWS = 24;
945
+
946
+ // src/features/tui/components/VirtualizedList/VirtualizedList.utils.ts
947
+ var getVirtualizedListRange = ({
948
+ itemCount,
949
+ activeIndex,
950
+ viewportSize,
951
+ previousStart = 0
952
+ }) => {
953
+ const maxStart = Math.max(0, itemCount - viewportSize);
954
+ let start = Math.min(previousStart, maxStart);
955
+ if (activeIndex < start) start = activeIndex;
956
+ else if (activeIndex >= start + viewportSize) start = activeIndex - viewportSize + 1;
957
+ start = Math.max(0, Math.min(start, maxStart));
958
+ const end = Math.min(itemCount, start + viewportSize);
959
+ return {
960
+ start,
961
+ end,
962
+ hiddenAbove: start,
963
+ hiddenBelow: itemCount - end
964
+ };
965
+ };
966
+
967
+ // src/features/tui/components/VirtualizedList/VirtualizedList.tsx
968
+ import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
969
+ var VirtualizedList = ({
970
+ items,
971
+ initialSelectedIndex = 0,
972
+ getKey,
973
+ renderItem,
974
+ onSelect,
975
+ reservedTerminalRows = DEFAULT_RESERVED_TERMINAL_ROWS,
976
+ navigationDisabled = false
977
+ }) => {
978
+ const [internalIndex, setInternalIndex] = useState7(initialSelectedIndex);
979
+ const activeIndex = internalIndex;
980
+ useInput5((_input, key) => {
981
+ if (navigationDisabled) return;
982
+ if (key.upArrow) {
983
+ setInternalIndex((index) => Math.max(0, index - 1));
984
+ } else if (key.downArrow) {
985
+ setInternalIndex((index) => Math.min(Math.max(0, items.length - 1), index + 1));
986
+ } else if (key.return && onSelect) {
987
+ const item = items[activeIndex];
988
+ if (item) onSelect(item, activeIndex);
989
+ }
990
+ });
991
+ const { stdout } = useStdout();
992
+ const terminalRows = stdout?.rows ?? FALLBACK_TERMINAL_ROWS;
993
+ const viewportSize = Math.max(
994
+ MIN_VIEWPORT_ROWS,
995
+ Math.min(items.length, terminalRows - reservedTerminalRows)
996
+ );
997
+ const startRef = useRef3(0);
998
+ const { start, end, hiddenAbove, hiddenBelow } = getVirtualizedListRange({
999
+ itemCount: items.length,
1000
+ activeIndex,
1001
+ viewportSize,
1002
+ previousStart: startRef.current
1003
+ });
1004
+ startRef.current = start;
1005
+ const visibleItems = items.slice(start, end);
1006
+ return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
1007
+ hiddenAbove > 0 && /* @__PURE__ */ jsx11(Text5, { dimColor: true, children: ` \u2191 ${hiddenAbove} more` }, "virtualized-list-hidden-above"),
1008
+ visibleItems.map((item, offset) => {
1009
+ const index = start + offset;
1010
+ return /* @__PURE__ */ jsx11(Box6, { children: renderItem(item, index, index === activeIndex) }, getKey(item, index));
1011
+ }),
1012
+ hiddenBelow > 0 && /* @__PURE__ */ jsx11(Text5, { dimColor: true, children: ` \u2193 ${hiddenBelow} more` }, "virtualized-list-hidden-below")
1013
+ ] });
1014
+ };
1015
+
1016
+ // src/features/tui/components/MenuList/MenuListItem.tsx
1017
+ import { Box as Box7, Text as Text8 } from "ink";
1018
+
1019
+ // src/features/tui/components/SelectableOption/SelectableOption.tsx
1020
+ import { Text as Text7 } from "ink";
1021
+
1022
+ // src/features/tui/components/SelectableOption/SelectableOption.utils.ts
1023
+ var SELECTION_PREFIX = "\u25BA ";
1024
+ var SELECTION_PREFIX_EMPTY = " ";
1025
+ var getSelectableColors = (selected, theme2) => ({
1026
+ color: selected ? "white" : void 0,
1027
+ backgroundColor: selected ? theme2.colors.primary : void 0
1028
+ });
1029
+
1030
+ // src/features/tui/components/SelectableOption/SelectionPrefix.tsx
1031
+ import { Text as Text6 } from "ink";
1032
+ import { jsx as jsx12 } from "react/jsx-runtime";
1033
+ var SelectionPrefix = ({ selected }) => {
1034
+ const { theme: theme2 } = useTheme();
1035
+ const { color, backgroundColor } = getSelectableColors(selected, theme2);
1036
+ return /* @__PURE__ */ jsx12(Text6, { color, backgroundColor, children: selected ? SELECTION_PREFIX : SELECTION_PREFIX_EMPTY });
1037
+ };
1038
+
1039
+ // src/features/tui/components/SelectableOption/SelectableOption.tsx
1040
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
1041
+ var SelectableOption = ({ selected, children }) => {
1042
+ const { theme: theme2 } = useTheme();
1043
+ const { color, backgroundColor } = getSelectableColors(selected, theme2);
1044
+ if (typeof children === "function") {
1045
+ return /* @__PURE__ */ jsx13(Fragment2, { children: children({ selected, color, backgroundColor }) });
1046
+ }
1047
+ return /* @__PURE__ */ jsxs6(Text7, { color, backgroundColor, children: [
1048
+ /* @__PURE__ */ jsx13(SelectionPrefix, { selected }),
1049
+ children
1050
+ ] });
1051
+ };
1052
+
1053
+ // src/features/tui/components/MenuList/MenuListItem.tsx
1054
+ import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
1055
+ var MenuListItem = ({ item, selected }) => /* @__PURE__ */ jsxs7(Box7, { children: [
1056
+ SelectableOption({ selected, children: item.label }),
1057
+ item.description && selected && /* @__PURE__ */ jsx14(Text8, { dimColor: true, children: ` \u2014 ${item.description}` })
1058
+ ] });
1059
+
1060
+ // src/features/tui/components/MenuList/MenuList.tsx
1061
+ import { jsx as jsx15 } from "react/jsx-runtime";
1062
+ var MenuList = ({ options, onSelect }) => {
1063
+ const navigate = useNavigate3();
1064
+ const handleSelectItem = (item) => {
1065
+ if (item.to) {
1066
+ navigate(item.to, { state: item.state });
1067
+ return;
1068
+ }
1069
+ onSelect?.(item);
1070
+ };
1071
+ useShortcutHandler(({ input }) => {
1072
+ const item = options.find((option) => option.shortcut === input);
1073
+ if (!item) return false;
1074
+ handleSelectItem(item);
1075
+ return true;
1076
+ });
1077
+ return /* @__PURE__ */ jsx15(
1078
+ VirtualizedList,
1079
+ {
1080
+ items: options,
1081
+ getKey: (item) => item.key ?? item.to ?? item.label,
1082
+ renderItem: (item, _index, selected) => /* @__PURE__ */ jsx15(MenuListItem, { item, selected }),
1083
+ onSelect: handleSelectItem
1084
+ }
1085
+ );
1086
+ };
1087
+
599
1088
  // src/app/views/MainMenu.tsx
600
- import { jsx as jsx8 } from "react/jsx-runtime";
1089
+ import { jsx as jsx16 } from "react/jsx-runtime";
601
1090
  var MainMenu = () => {
602
1091
  const isUserToken = useIsUserToken();
603
1092
  const canSwitchProject = !hasProjectConfigFile();
@@ -650,7 +1139,7 @@ var MainMenu = () => {
650
1139
  }
651
1140
  ] : []
652
1141
  ];
653
- return /* @__PURE__ */ jsx8(ViewLayout, { children: /* @__PURE__ */ jsx8(MenuList, { options }) });
1142
+ return /* @__PURE__ */ jsx16(ViewLayout, { children: /* @__PURE__ */ jsx16(MenuList, { options }) });
654
1143
  };
655
1144
 
656
1145
  // src/app/hooks/useProfiles.ts
@@ -672,11 +1161,11 @@ var getProfileRow = (profile) => ({
672
1161
 
673
1162
  // src/features/tui/components/BaseResourceListScreen/BaseResourceListScreen.tsx
674
1163
  import { Spinner, StatusMessage as StatusMessage2 } from "@inkjs/ui";
675
- import { Box as Box7 } from "ink";
676
- import { useState as useState6 } from "react";
1164
+ import { Box as Box10 } from "ink";
1165
+ import { useState as useState8 } from "react";
677
1166
 
678
1167
  // src/features/tui/components/TableList/TableList.tsx
679
- import { Box as Box6, Text as Text5 } from "ink";
1168
+ import { Box as Box9, Text as Text10 } from "ink";
680
1169
 
681
1170
  // src/features/tui/components/TableList/TableList.utils.ts
682
1171
  var fitCell = (value, width) => {
@@ -686,21 +1175,21 @@ var fitCell = (value, width) => {
686
1175
  };
687
1176
 
688
1177
  // src/features/tui/components/TableList/TableListRow.tsx
689
- import { Box as Box5, Text as Text4 } from "ink";
690
- import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1178
+ import { Box as Box8, Text as Text9 } from "ink";
1179
+ import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
691
1180
  var TableListRow = ({
692
1181
  columns,
693
1182
  row,
694
1183
  selected
695
- }) => /* @__PURE__ */ jsx9(SelectableOption, { selected, children: ({ color, backgroundColor }) => /* @__PURE__ */ jsxs4(Box5, { children: [
696
- /* @__PURE__ */ jsx9(SelectionPrefix, { selected }),
1184
+ }) => /* @__PURE__ */ jsx17(SelectableOption, { selected, children: ({ color, backgroundColor }) => /* @__PURE__ */ jsxs8(Box8, { children: [
1185
+ /* @__PURE__ */ jsx17(SelectionPrefix, { selected }),
697
1186
  columns.map((column, i) => {
698
1187
  const sep = i === 0 ? "" : " ";
699
1188
  const cell = row.cells[column.key];
700
1189
  if (column.render) {
701
- return /* @__PURE__ */ jsxs4(Box5, { children: [
702
- sep ? /* @__PURE__ */ jsx9(Text4, { backgroundColor, children: sep }) : null,
703
- /* @__PURE__ */ jsx9(Box5, { width: column.width, children: column.render(cell, row, {
1190
+ return /* @__PURE__ */ jsxs8(Box8, { children: [
1191
+ sep ? /* @__PURE__ */ jsx17(Text9, { backgroundColor, children: sep }) : null,
1192
+ /* @__PURE__ */ jsx17(Box8, { width: column.width, children: column.render(cell, row, {
704
1193
  selected,
705
1194
  width: column.width,
706
1195
  color,
@@ -708,7 +1197,7 @@ var TableListRow = ({
708
1197
  }) })
709
1198
  ] }, column.key);
710
1199
  }
711
- return /* @__PURE__ */ jsxs4(Text4, { color, backgroundColor, children: [
1200
+ return /* @__PURE__ */ jsxs8(Text9, { color, backgroundColor, children: [
712
1201
  sep,
713
1202
  fitCell(cell, column.width)
714
1203
  ] }, column.key);
@@ -716,32 +1205,32 @@ var TableListRow = ({
716
1205
  ] }) });
717
1206
 
718
1207
  // src/features/tui/components/TableList/TableList.tsx
719
- import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
1208
+ import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
720
1209
  var TableList = ({
721
1210
  columns,
722
1211
  rows,
723
1212
  navigationDisabled = false,
724
1213
  onSelect
725
- }) => /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
726
- /* @__PURE__ */ jsx10(Box6, { children: /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1214
+ }) => /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
1215
+ /* @__PURE__ */ jsx18(Box9, { children: /* @__PURE__ */ jsxs9(Text10, { dimColor: true, children: [
727
1216
  " ",
728
1217
  columns.map((column) => fitCell(column.label, column.width)).join(" ")
729
1218
  ] }) }),
730
- /* @__PURE__ */ jsx10(
1219
+ /* @__PURE__ */ jsx18(
731
1220
  VirtualizedList,
732
1221
  {
733
1222
  items: rows,
734
1223
  reservedTerminalRows: DEFAULT_RESERVED_TERMINAL_ROWS + 1,
735
1224
  navigationDisabled,
736
1225
  getKey: (row) => row.key,
737
- renderItem: (row, _rowIndex, selected) => /* @__PURE__ */ jsx10(TableListRow, { columns, row, selected: !navigationDisabled && selected }),
1226
+ renderItem: (row, _rowIndex, selected) => /* @__PURE__ */ jsx18(TableListRow, { columns, row, selected: !navigationDisabled && selected }),
738
1227
  onSelect: (row) => onSelect?.(row)
739
1228
  }
740
1229
  )
741
1230
  ] });
742
1231
 
743
1232
  // src/features/tui/components/BaseResourceListScreen/BaseResourceListScreen.tsx
744
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
1233
+ import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
745
1234
  var BaseResourceListScreen = ({
746
1235
  title,
747
1236
  loadingLabel,
@@ -758,11 +1247,11 @@ var BaseResourceListScreen = ({
758
1247
  onSelectResource
759
1248
  }) => {
760
1249
  const rows = resources ?? [];
761
- const [searchMode, setSearchMode] = useState6(false);
1250
+ const [searchMode, setSearchMode] = useState8(false);
762
1251
  const handleSelect = (row) => {
763
1252
  if (row.value !== void 0 && onSelectResource) onSelectResource(row.value);
764
1253
  };
765
- return /* @__PURE__ */ jsxs6(
1254
+ return /* @__PURE__ */ jsxs10(
766
1255
  ViewLayout,
767
1256
  {
768
1257
  title: query ? `Search: "${query}"` : title,
@@ -770,10 +1259,10 @@ var BaseResourceListScreen = ({
770
1259
  onSearch,
771
1260
  onSearchModeChange: setSearchMode,
772
1261
  children: [
773
- isLoading && /* @__PURE__ */ jsx11(Box7, { children: /* @__PURE__ */ jsx11(Spinner, { label: loadingLabel }) }),
774
- isError && /* @__PURE__ */ jsx11(StatusMessage2, { variant: "error", children: error }),
775
- !isLoading && !isError && rows.length === 0 && !query && /* @__PURE__ */ jsx11(StatusMessage2, { variant: "warning", children: emptyMessage }),
776
- !isLoading && !isError && (rows.length > 0 || query) && /* @__PURE__ */ jsx11(
1262
+ isLoading && /* @__PURE__ */ jsx19(Box10, { children: /* @__PURE__ */ jsx19(Spinner, { label: loadingLabel }) }),
1263
+ isError && /* @__PURE__ */ jsx19(StatusMessage2, { variant: "error", children: error }),
1264
+ !isLoading && !isError && rows.length === 0 && !query && /* @__PURE__ */ jsx19(StatusMessage2, { variant: "warning", children: emptyMessage }),
1265
+ !isLoading && !isError && (rows.length > 0 || query) && /* @__PURE__ */ jsx19(
777
1266
  TableList,
778
1267
  {
779
1268
  columns,
@@ -788,10 +1277,10 @@ var BaseResourceListScreen = ({
788
1277
  };
789
1278
 
790
1279
  // src/app/views/profiles/ProfilesList.tsx
791
- import { jsx as jsx12 } from "react/jsx-runtime";
1280
+ import { jsx as jsx20 } from "react/jsx-runtime";
792
1281
  var ProfilesList = () => {
793
1282
  const request = useProfilesList();
794
- return /* @__PURE__ */ jsx12(
1283
+ return /* @__PURE__ */ jsx20(
795
1284
  BaseResourceListScreen,
796
1285
  {
797
1286
  title: "Profiles",
@@ -809,27 +1298,27 @@ var ProfilesList = () => {
809
1298
 
810
1299
  // src/app/views/profiles/ProfilesMenu.tsx
811
1300
  import { Spinner as Spinner2 } from "@inkjs/ui";
812
- import { useEffect as useEffect5 } from "react";
813
- import { useNavigate as useNavigate3 } from "react-router";
814
- import { jsx as jsx13 } from "react/jsx-runtime";
1301
+ import { useEffect as useEffect8 } from "react";
1302
+ import { useNavigate as useNavigate4 } from "react-router";
1303
+ import { jsx as jsx21 } from "react/jsx-runtime";
815
1304
  var ProfilesMenu = () => {
816
- const navigate = useNavigate3();
817
- useEffect5(() => {
1305
+ const navigate = useNavigate4();
1306
+ useEffect8(() => {
818
1307
  navigate("/profiles/list", { replace: true });
819
1308
  }, [navigate]);
820
- return /* @__PURE__ */ jsx13(Spinner2, { label: "Loading..." });
1309
+ return /* @__PURE__ */ jsx21(Spinner2, { label: "Loading..." });
821
1310
  };
822
1311
 
823
1312
  // src/app/views/project/ProjectExport.tsx
824
1313
  import { Spinner as Spinner3, StatusMessage as StatusMessage3 } from "@inkjs/ui";
825
- import { useEffect as useEffect6, useState as useState8 } from "react";
1314
+ import { useEffect as useEffect9, useState as useState10 } from "react";
826
1315
 
827
1316
  // src/app/hooks/useFeatureMutation.ts
828
- import { useCallback as useCallback3, useRef, useState as useState7 } from "react";
1317
+ import { useCallback as useCallback3, useRef as useRef4, useState as useState9 } from "react";
829
1318
  var useFeatureMutation = (fn) => {
830
- const fnRef = useRef(fn);
831
- const activeMutationRef = useRef(0);
832
- const [state, setState] = useState7({
1319
+ const fnRef = useRef4(fn);
1320
+ const activeMutationRef = useRef4(0);
1321
+ const [state, setState] = useState9({
833
1322
  data: void 0,
834
1323
  error: void 0,
835
1324
  status: "idle"
@@ -870,48 +1359,48 @@ var useFeatureMutation = (fn) => {
870
1359
  };
871
1360
 
872
1361
  // src/features/tui/components/TextInput/TextInput.tsx
873
- import { Box as Box8, Text as Text6 } from "ink";
1362
+ import { Box as Box11, Text as Text11 } from "ink";
874
1363
  import InkTextInput from "ink-text-input";
875
- import { jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
1364
+ import { jsx as jsx22, jsxs as jsxs11 } from "react/jsx-runtime";
876
1365
  var TextInput = (props) => {
877
1366
  useShortcutBlocker();
878
- return /* @__PURE__ */ jsxs7(Box8, { children: [
879
- /* @__PURE__ */ jsx14(Text6, { color: "cyan", children: "\u203A " }),
880
- /* @__PURE__ */ jsx14(InkTextInput, { ...props })
1367
+ return /* @__PURE__ */ jsxs11(Box11, { children: [
1368
+ /* @__PURE__ */ jsx22(Text11, { color: "cyan", children: "\u203A " }),
1369
+ /* @__PURE__ */ jsx22(InkTextInput, { ...props })
881
1370
  ] });
882
1371
  };
883
1372
 
884
1373
  // src/app/views/project/ProjectExport.tsx
885
- import { jsx as jsx15, jsxs as jsxs8 } from "react/jsx-runtime";
1374
+ import { jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
886
1375
  var ProjectExport = () => {
887
- const [outputValue, setOutputValue] = useState8("");
888
- const [output, setOutput] = useState8(null);
1376
+ const [outputValue, setOutputValue] = useState10("");
1377
+ const [output, setOutput] = useState10(null);
889
1378
  const [exportProjectMutation, exportProjectResult] = useFeatureMutation(
890
1379
  (outputPath) => exportProject(outputPath || void 0)
891
1380
  );
892
- useEffect6(() => {
1381
+ useEffect9(() => {
893
1382
  if (output !== null) void exportProjectMutation(output);
894
1383
  }, [exportProjectMutation, output]);
895
1384
  if (output === null) {
896
- return /* @__PURE__ */ jsx15(ViewLayout, { title: "Output file (blank = auto)", hints: "confirm", hintsPosition: "bottom", children: /* @__PURE__ */ jsx15(TextInput, { value: outputValue, onChange: setOutputValue, onSubmit: setOutput }) });
1385
+ return /* @__PURE__ */ jsx23(ViewLayout, { title: "Output file (blank = auto)", hints: "confirm", hintsPosition: "bottom", children: /* @__PURE__ */ jsx23(TextInput, { value: outputValue, onChange: setOutputValue, onSubmit: setOutput }) });
897
1386
  }
898
- return /* @__PURE__ */ jsxs8(ViewLayout, { hintsHidden: true, children: [
899
- exportProjectResult.isLoading && /* @__PURE__ */ jsx15(Spinner3, { label: "Exporting project..." }),
900
- exportProjectResult.isError && /* @__PURE__ */ jsx15(StatusMessage3, { variant: "error", children: exportProjectResult.error }),
901
- exportProjectResult.data && /* @__PURE__ */ jsx15(StatusMessage3, { variant: "success", children: `Exported project to ${exportProjectResult.data.outPath} (${exportProjectResult.data.size} bytes)` })
1387
+ return /* @__PURE__ */ jsxs12(ViewLayout, { hintsHidden: true, children: [
1388
+ exportProjectResult.isLoading && /* @__PURE__ */ jsx23(Spinner3, { label: "Exporting project..." }),
1389
+ exportProjectResult.isError && /* @__PURE__ */ jsx23(StatusMessage3, { variant: "error", children: exportProjectResult.error }),
1390
+ exportProjectResult.data && /* @__PURE__ */ jsx23(StatusMessage3, { variant: "success", children: `Exported project to ${exportProjectResult.data.outPath} (${exportProjectResult.data.size} bytes)` })
902
1391
  ] });
903
1392
  };
904
1393
 
905
1394
  // src/app/views/project/ProjectImport.tsx
906
1395
  import { Spinner as Spinner4, StatusMessage as StatusMessage4 } from "@inkjs/ui";
907
- import { useEffect as useEffect7, useState as useState10 } from "react";
908
- import { useNavigate as useNavigate4 } from "react-router";
1396
+ import { useEffect as useEffect10, useState as useState12 } from "react";
1397
+ import { useNavigate as useNavigate5 } from "react-router";
909
1398
 
910
1399
  // src/features/tui/components/FilePicker/FilePicker.tsx
911
1400
  import { readdirSync } from "fs";
912
1401
  import { dirname, join, resolve } from "path";
913
- import { Box as Box9, Text as Text7 } from "ink";
914
- import { useMemo, useState as useState9 } from "react";
1402
+ import { Box as Box12, Text as Text12 } from "ink";
1403
+ import { useMemo, useState as useState11 } from "react";
915
1404
 
916
1405
  // src/utils/filePicker.ts
917
1406
  import { extname } from "path";
@@ -937,7 +1426,7 @@ var toFilePickerItems = (entries, allowedExtensions) => {
937
1426
  };
938
1427
 
939
1428
  // src/features/tui/components/FilePicker/FilePicker.tsx
940
- import { jsx as jsx16, jsxs as jsxs9 } from "react/jsx-runtime";
1429
+ import { jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
941
1430
  var FilePicker = ({
942
1431
  label,
943
1432
  extensions,
@@ -945,7 +1434,7 @@ var FilePicker = ({
945
1434
  onSubmit,
946
1435
  onBack
947
1436
  }) => {
948
- const [currentDir, setCurrentDir] = useState9(() => resolve(userCwd(), initialDir));
1437
+ const [currentDir, setCurrentDir] = useState11(() => resolve(userCwd(), initialDir));
949
1438
  useEscHandler(() => {
950
1439
  onBack();
951
1440
  return true;
@@ -981,8 +1470,8 @@ var FilePicker = ({
981
1470
  }
982
1471
  onSubmit(join(currentDir, selected.name));
983
1472
  };
984
- return /* @__PURE__ */ jsx16(Box9, { flexDirection: "column", children: /* @__PURE__ */ jsxs9(ViewLayout, { title: `${label}: ${currentDir}`, hints: "navigationOpenSelect", children: [
985
- /* @__PURE__ */ jsx16(
1473
+ return /* @__PURE__ */ jsx24(Box12, { flexDirection: "column", children: /* @__PURE__ */ jsxs13(ViewLayout, { title: `${label}: ${currentDir}`, hints: "navigationOpenSelect", children: [
1474
+ /* @__PURE__ */ jsx24(
986
1475
  MenuList,
987
1476
  {
988
1477
  options: items.map((item) => ({ label: item.label, value: item })),
@@ -990,22 +1479,22 @@ var FilePicker = ({
990
1479
  },
991
1480
  currentDir
992
1481
  ),
993
- items.length === 0 && /* @__PURE__ */ jsx16(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text7, { dimColor: true, children: "No matching files in this directory." }) }),
994
- error && /* @__PURE__ */ jsx16(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text7, { color: "red", children: error }) })
1482
+ items.length === 0 && /* @__PURE__ */ jsx24(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text12, { dimColor: true, children: "No matching files in this directory." }) }),
1483
+ error && /* @__PURE__ */ jsx24(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text12, { color: "red", children: error }) })
995
1484
  ] }) });
996
1485
  };
997
1486
 
998
1487
  // src/app/views/project/ProjectImport.tsx
999
- import { jsx as jsx17, jsxs as jsxs10 } from "react/jsx-runtime";
1488
+ import { jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
1000
1489
  var ProjectImport = () => {
1001
- const navigate = useNavigate4();
1002
- const [file, setFile] = useState10(null);
1490
+ const navigate = useNavigate5();
1491
+ const [file, setFile] = useState12(null);
1003
1492
  const [importProjectMutation, importProjectResult] = useFeatureMutation(importProject);
1004
- useEffect7(() => {
1493
+ useEffect10(() => {
1005
1494
  if (file) importProjectMutation(file);
1006
1495
  }, [file, importProjectMutation]);
1007
1496
  if (!file) {
1008
- return /* @__PURE__ */ jsx17(
1497
+ return /* @__PURE__ */ jsx25(
1009
1498
  FilePicker,
1010
1499
  {
1011
1500
  label: "Select .zip file",
@@ -1015,29 +1504,29 @@ var ProjectImport = () => {
1015
1504
  }
1016
1505
  );
1017
1506
  }
1018
- return /* @__PURE__ */ jsxs10(ViewLayout, { hintsHidden: true, children: [
1019
- importProjectResult.isLoading && /* @__PURE__ */ jsx17(Spinner4, { label: `Importing project from ${file}...` }),
1020
- importProjectResult.isError && /* @__PURE__ */ jsx17(StatusMessage4, { variant: "error", children: importProjectResult.error }),
1021
- importProjectResult.data && /* @__PURE__ */ jsx17(StatusMessage4, { variant: "success", children: `Project import started from ${importProjectResult.data.path} (${importProjectResult.data.size} bytes)` })
1507
+ return /* @__PURE__ */ jsxs14(ViewLayout, { hintsHidden: true, children: [
1508
+ importProjectResult.isLoading && /* @__PURE__ */ jsx25(Spinner4, { label: `Importing project from ${file}...` }),
1509
+ importProjectResult.isError && /* @__PURE__ */ jsx25(StatusMessage4, { variant: "error", children: importProjectResult.error }),
1510
+ importProjectResult.data && /* @__PURE__ */ jsx25(StatusMessage4, { variant: "success", children: `Project import started from ${importProjectResult.data.path} (${importProjectResult.data.size} bytes)` })
1022
1511
  ] });
1023
1512
  };
1024
1513
 
1025
1514
  // src/app/views/project/ProjectInit.tsx
1026
1515
  import { useApp as useApp3 } from "ink";
1027
- import { useEffect as useEffect8, useState as useState12 } from "react";
1028
- import { useLocation as useLocation4, useNavigate as useNavigate5 } from "react-router";
1516
+ import { useEffect as useEffect11, useState as useState14 } from "react";
1517
+ import { useLocation as useLocation4, useNavigate as useNavigate6 } from "react-router";
1029
1518
 
1030
1519
  // src/app/components/ProjectPicker/ProjectPicker.tsx
1031
1520
  import { Spinner as Spinner5, StatusMessage as StatusMessage5 } from "@inkjs/ui";
1032
- import { jsx as jsx18, jsxs as jsxs11 } from "react/jsx-runtime";
1521
+ import { jsx as jsx26, jsxs as jsxs15 } from "react/jsx-runtime";
1033
1522
  var ProjectPicker = ({ onSelect, currentProjectId }) => {
1034
1523
  const projectsQuery = useFeatureQuery(listProjects, []);
1035
1524
  const projects = projectsQuery.data ?? [];
1036
- return /* @__PURE__ */ jsxs11(ViewLayout, { title: "Choose BugBug project", hints: "navigationSelect", children: [
1037
- projectsQuery.isLoading && /* @__PURE__ */ jsx18(Spinner5, { label: "Loading projects..." }),
1038
- projectsQuery.isError && /* @__PURE__ */ jsx18(StatusMessage5, { variant: "error", children: `Error: ${projectsQuery.error ?? "Unknown error"}` }),
1039
- !projectsQuery.isLoading && !projectsQuery.isError && projects.length === 0 && /* @__PURE__ */ jsx18(StatusMessage5, { variant: "warning", children: "No projects found" }),
1040
- !projectsQuery.isLoading && !projectsQuery.isError && projects.length > 0 && /* @__PURE__ */ jsx18(
1525
+ return /* @__PURE__ */ jsxs15(ViewLayout, { title: "Choose BugBug project", hints: "navigationSelect", children: [
1526
+ projectsQuery.isLoading && /* @__PURE__ */ jsx26(Spinner5, { label: "Loading projects..." }),
1527
+ projectsQuery.isError && /* @__PURE__ */ jsx26(StatusMessage5, { variant: "error", children: `Error: ${projectsQuery.error ?? "Unknown error"}` }),
1528
+ !projectsQuery.isLoading && !projectsQuery.isError && projects.length === 0 && /* @__PURE__ */ jsx26(StatusMessage5, { variant: "warning", children: "No projects found" }),
1529
+ !projectsQuery.isLoading && !projectsQuery.isError && projects.length > 0 && /* @__PURE__ */ jsx26(
1041
1530
  MenuList,
1042
1531
  {
1043
1532
  options: projects.map((project) => ({
@@ -1055,15 +1544,15 @@ var ProjectPicker = ({ onSelect, currentProjectId }) => {
1055
1544
 
1056
1545
  // src/app/views/project/ProjectInitAuth.tsx
1057
1546
  import { StatusMessage as StatusMessage6 } from "@inkjs/ui";
1058
- import { useState as useState11 } from "react";
1059
- import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
1547
+ import { useState as useState13 } from "react";
1548
+ import { jsx as jsx27, jsxs as jsxs16 } from "react/jsx-runtime";
1060
1549
  var ProjectInitAuth = ({
1061
1550
  onTokenReceive,
1062
1551
  onTokenError,
1063
1552
  message
1064
1553
  }) => {
1065
- const [method, setMethod] = useState11("choose");
1066
- const [tokenInput, setTokenInput] = useState11("");
1554
+ const [method, setMethod] = useState13("choose");
1555
+ const [tokenInput, setTokenInput] = useState13("");
1067
1556
  const handleLogin = () => {
1068
1557
  void (async () => {
1069
1558
  try {
@@ -1089,8 +1578,8 @@ var ProjectInitAuth = ({
1089
1578
  }
1090
1579
  };
1091
1580
  if (method === "token") {
1092
- return /* @__PURE__ */ jsx19(EscProvider, { onUnhandled: () => setMethod("choose"), children: /* @__PURE__ */ jsxs12(ViewLayout, { title: "BugBug project API token", hints: "confirm", hintsPosition: "bottom", children: [
1093
- /* @__PURE__ */ jsx19(
1581
+ return /* @__PURE__ */ jsx27(EscProvider, { onUnhandled: () => setMethod("choose"), children: /* @__PURE__ */ jsxs16(ViewLayout, { title: "BugBug project API token", hints: "confirm", hintsPosition: "bottom", children: [
1582
+ /* @__PURE__ */ jsx27(
1094
1583
  TextInput,
1095
1584
  {
1096
1585
  value: tokenInput,
@@ -1099,11 +1588,11 @@ var ProjectInitAuth = ({
1099
1588
  mask: "*"
1100
1589
  }
1101
1590
  ),
1102
- message && /* @__PURE__ */ jsx19(StatusMessage6, { variant: "error", children: `Error: ${message}` })
1591
+ message && /* @__PURE__ */ jsx27(StatusMessage6, { variant: "error", children: `Error: ${message}` })
1103
1592
  ] }) });
1104
1593
  }
1105
- return /* @__PURE__ */ jsxs12(ViewLayout, { title: "How do you want to authenticate?", hints: "navigationSelect", children: [
1106
- /* @__PURE__ */ jsx19(
1594
+ return /* @__PURE__ */ jsxs16(ViewLayout, { title: "How do you want to authenticate?", hints: "navigationSelect", children: [
1595
+ /* @__PURE__ */ jsx27(
1107
1596
  MenuList,
1108
1597
  {
1109
1598
  options: [
@@ -1124,27 +1613,27 @@ var ProjectInitAuth = ({
1124
1613
  }
1125
1614
  }
1126
1615
  ),
1127
- message && /* @__PURE__ */ jsx19(StatusMessage6, { variant: "error", children: `Error: ${message}` })
1616
+ message && /* @__PURE__ */ jsx27(StatusMessage6, { variant: "error", children: `Error: ${message}` })
1128
1617
  ] });
1129
1618
  };
1130
1619
 
1131
1620
  // src/app/views/project/ProjectInit.tsx
1132
- import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
1621
+ import { jsx as jsx28, jsxs as jsxs17 } from "react/jsx-runtime";
1133
1622
  var ProjectInit = () => {
1134
1623
  const { exit } = useApp3();
1135
- const navigate = useNavigate5();
1624
+ const navigate = useNavigate6();
1136
1625
  const location = useLocation4();
1137
1626
  const state = location.state;
1138
1627
  const redirectUrl = state?.redirectUrl ?? "/";
1139
1628
  const onlyThisSession = state?.onlyThisSession ?? false;
1140
1629
  const ignoreConfiguredAuth = state?.ignoreConfiguredAuth ?? false;
1141
1630
  const { auth, config, authError, completeSession } = useNavigatorSession();
1142
- const [token, setToken] = useState12(
1631
+ const [token, setToken] = useState14(
1143
1632
  ignoreConfiguredAuth ? null : auth.token ?? null
1144
1633
  );
1145
- const [usingUserToken, setUsingUserToken] = useState12(false);
1146
- const [error, setError] = useState12(null);
1147
- useEffect8(() => {
1634
+ const [usingUserToken, setUsingUserToken] = useState14(false);
1635
+ const [error, setError] = useState14(null);
1636
+ useEffect11(() => {
1148
1637
  if (auth.kind !== "ready" || ignoreConfiguredAuth) return;
1149
1638
  if (onlyThisSession) {
1150
1639
  navigate(redirectUrl, { replace: true });
@@ -1181,8 +1670,8 @@ var ProjectInit = () => {
1181
1670
  })();
1182
1671
  };
1183
1672
  const message = error ?? authError;
1184
- return /* @__PURE__ */ jsxs13(EscProvider, { onUnhandled: exit, children: [
1185
- !token && /* @__PURE__ */ jsx20(
1673
+ return /* @__PURE__ */ jsxs17(EscProvider, { onUnhandled: exit, children: [
1674
+ !token && /* @__PURE__ */ jsx28(
1186
1675
  ProjectInitAuth,
1187
1676
  {
1188
1677
  onTokenReceive: handleTokenReceive,
@@ -1190,15 +1679,15 @@ var ProjectInit = () => {
1190
1679
  message
1191
1680
  }
1192
1681
  ),
1193
- token && /* @__PURE__ */ jsx20(ProjectPicker, { onSelect: handleProjectSelectAndFinish, currentProjectId: auth.projectId })
1682
+ token && /* @__PURE__ */ jsx28(ProjectPicker, { onSelect: handleProjectSelectAndFinish, currentProjectId: auth.projectId })
1194
1683
  ] });
1195
1684
  };
1196
1685
 
1197
1686
  // src/app/views/project/ProjectMenu.tsx
1198
- import { jsx as jsx21 } from "react/jsx-runtime";
1687
+ import { jsx as jsx29 } from "react/jsx-runtime";
1199
1688
  var ProjectMenu = () => {
1200
1689
  const canSwitchProject = !hasProjectConfigFile();
1201
- return /* @__PURE__ */ jsx21(ViewLayout, { children: /* @__PURE__ */ jsx21(
1690
+ return /* @__PURE__ */ jsx29(ViewLayout, { children: /* @__PURE__ */ jsx29(
1202
1691
  MenuList,
1203
1692
  {
1204
1693
  options: [
@@ -1210,21 +1699,21 @@ var ProjectMenu = () => {
1210
1699
  };
1211
1700
 
1212
1701
  // src/app/views/project/ProjectSwitch.tsx
1213
- import { useNavigate as useNavigate6 } from "react-router";
1214
- import { jsx as jsx22 } from "react/jsx-runtime";
1702
+ import { useNavigate as useNavigate7 } from "react-router";
1703
+ import { jsx as jsx30 } from "react/jsx-runtime";
1215
1704
  var ProjectSwitch = () => {
1216
- const navigate = useNavigate6();
1705
+ const navigate = useNavigate7();
1217
1706
  const { config, setSessionProject } = useNavigatorSession();
1218
1707
  const handleSelect = (project) => {
1219
1708
  switchProject(project.id, { currentProjectId: config.projectId });
1220
1709
  setSessionProject(project.id);
1221
1710
  navigate("/", { replace: true });
1222
1711
  };
1223
- return /* @__PURE__ */ jsx22(ProjectPicker, { onSelect: handleSelect, currentProjectId: config.projectId });
1712
+ return /* @__PURE__ */ jsx30(ProjectPicker, { onSelect: handleSelect, currentProjectId: config.projectId });
1224
1713
  };
1225
1714
 
1226
1715
  // src/app/views/settings/SettingsMenu.tsx
1227
- import { jsx as jsx23 } from "react/jsx-runtime";
1716
+ import { jsx as jsx31 } from "react/jsx-runtime";
1228
1717
  var SettingsMenu = () => {
1229
1718
  const isUserToken = useIsUserToken();
1230
1719
  const options = [
@@ -1240,19 +1729,19 @@ var SettingsMenu = () => {
1240
1729
  }
1241
1730
  ] : []
1242
1731
  ];
1243
- return /* @__PURE__ */ jsx23(ViewLayout, { children: /* @__PURE__ */ jsx23(MenuList, { options }) });
1732
+ return /* @__PURE__ */ jsx31(ViewLayout, { children: /* @__PURE__ */ jsx31(MenuList, { options }) });
1244
1733
  };
1245
1734
 
1246
1735
  // src/app/views/settings/SettingsSetSessionToken.tsx
1247
1736
  import { StatusMessage as StatusMessage7 } from "@inkjs/ui";
1248
- import { useState as useState13 } from "react";
1249
- import { jsx as jsx24, jsxs as jsxs14 } from "react/jsx-runtime";
1737
+ import { useState as useState15 } from "react";
1738
+ import { jsx as jsx32, jsxs as jsxs18 } from "react/jsx-runtime";
1250
1739
  var SettingsSetSessionToken = () => {
1251
1740
  const { auth, completeSession } = useNavigatorSession();
1252
- const [tokenValue, setTokenValue] = useState13("");
1253
- const [token, setToken] = useState13(null);
1254
- const [error, setError] = useState13(null);
1255
- const [saved, setSaved] = useState13(false);
1741
+ const [tokenValue, setTokenValue] = useState15("");
1742
+ const [token, setToken] = useState15(null);
1743
+ const [error, setError] = useState15(null);
1744
+ const [saved, setSaved] = useState15(false);
1256
1745
  const handleTokenSubmit = (value) => {
1257
1746
  const trimmed = value.trim();
1258
1747
  if (!trimmed) {
@@ -1274,8 +1763,8 @@ var SettingsSetSessionToken = () => {
1274
1763
  setSaved(true);
1275
1764
  };
1276
1765
  if (token === null) {
1277
- return /* @__PURE__ */ jsxs14(ViewLayout, { title: "Project API token", hints: "confirm", hintsPosition: "bottom", children: [
1278
- /* @__PURE__ */ jsx24(
1766
+ return /* @__PURE__ */ jsxs18(ViewLayout, { title: "Project API token", hints: "confirm", hintsPosition: "bottom", children: [
1767
+ /* @__PURE__ */ jsx32(
1279
1768
  TextInput,
1280
1769
  {
1281
1770
  value: tokenValue,
@@ -1284,20 +1773,330 @@ var SettingsSetSessionToken = () => {
1284
1773
  mask: "*"
1285
1774
  }
1286
1775
  ),
1287
- error && /* @__PURE__ */ jsx24(StatusMessage7, { variant: "error", children: `Error: ${error}` })
1776
+ error && /* @__PURE__ */ jsx32(StatusMessage7, { variant: "error", children: `Error: ${error}` })
1288
1777
  ] });
1289
1778
  }
1290
1779
  if (!saved) {
1291
- return /* @__PURE__ */ jsx24(ProjectPicker, { onSelect: handleProjectSelect, currentProjectId: auth.projectId });
1780
+ return /* @__PURE__ */ jsx32(ProjectPicker, { onSelect: handleProjectSelect, currentProjectId: auth.projectId });
1292
1781
  }
1293
- return /* @__PURE__ */ jsx24(ViewLayout, { hintsHidden: true, children: /* @__PURE__ */ jsx24(StatusMessage7, { variant: "success", children: "Token saved and valid only for this session" }) });
1782
+ return /* @__PURE__ */ jsx32(ViewLayout, { hintsHidden: true, children: /* @__PURE__ */ jsx32(StatusMessage7, { variant: "success", children: "Token saved and valid only for this session" }) });
1294
1783
  };
1295
1784
 
1296
1785
  // src/app/views/suiteRuns/SuiteRunDetails.tsx
1297
- import { Spinner as Spinner6, StatusMessage as StatusMessage8 } from "@inkjs/ui";
1298
- import { Text as Text8 } from "ink";
1786
+ import { Spinner as Spinner8, StatusMessage as StatusMessage9 } from "@inkjs/ui";
1787
+ import { Text as Text17 } from "ink";
1299
1788
  import { useLocation as useLocation5, useParams } from "react-router";
1300
1789
 
1790
+ // src/app/components/BaseSuiteRunDetails/BaseSuiteRunDetails.tsx
1791
+ import { Spinner as Spinner7, StatusMessage as StatusMessage8 } from "@inkjs/ui";
1792
+ import { Box as Box17, useApp as useApp4 } from "ink";
1793
+ import { useEffect as useEffect12, useState as useState16 } from "react";
1794
+
1795
+ // ../core/dist/utils/duration.js
1796
+ var formatDuration = (duration, fallback) => {
1797
+ let totalSeconds = null;
1798
+ if (duration != null && duration !== "") {
1799
+ totalSeconds = typeof duration === "number" ? duration : parseDurationString(duration);
1800
+ }
1801
+ if (totalSeconds == null && fallback?.started && fallback?.ended) {
1802
+ const start = Date.parse(fallback.started);
1803
+ const end = Date.parse(fallback.ended);
1804
+ if (Number.isFinite(start) && Number.isFinite(end) && end >= start) {
1805
+ totalSeconds = (end - start) / 1e3;
1806
+ }
1807
+ }
1808
+ if (totalSeconds == null || !Number.isFinite(totalSeconds) || totalSeconds < 0) {
1809
+ return "-";
1810
+ }
1811
+ const hours = Math.floor(totalSeconds / 3600);
1812
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
1813
+ const seconds = totalSeconds - hours * 3600 - minutes * 60;
1814
+ const secondsStr = `${seconds.toFixed(2).padStart(5, "0")}s`;
1815
+ if (hours > 0) {
1816
+ return `${String(hours).padStart(2, "0")}h ${String(minutes).padStart(2, "0")}m ${secondsStr}`;
1817
+ }
1818
+ if (minutes > 0) {
1819
+ return `${String(minutes).padStart(2, "0")}m ${secondsStr}`;
1820
+ }
1821
+ return secondsStr;
1822
+ };
1823
+ var parseDurationString = (value) => {
1824
+ const trimmed = value.trim();
1825
+ if (trimmed === "") {
1826
+ return null;
1827
+ }
1828
+ const numeric = Number(trimmed);
1829
+ if (Number.isFinite(numeric)) {
1830
+ return numeric;
1831
+ }
1832
+ const iso = /^P(?:(\d+(?:\.\d+)?)D)?(?:T(?:(\d+(?:\.\d+)?)H)?(?:(\d+(?:\.\d+)?)M)?(?:(\d+(?:\.\d+)?)S)?)?$/i.exec(trimmed);
1833
+ if (iso) {
1834
+ const days = Number(iso[1] ?? 0);
1835
+ const hours = Number(iso[2] ?? 0);
1836
+ const minutes = Number(iso[3] ?? 0);
1837
+ const seconds = Number(iso[4] ?? 0);
1838
+ return days * 86400 + hours * 3600 + minutes * 60 + seconds;
1839
+ }
1840
+ const hms = /^(?:(\d+):)?(\d{1,2}):(\d{1,2}(?:\.\d+)?)$/.exec(trimmed);
1841
+ if (hms) {
1842
+ const hours = Number(hms[1] ?? 0);
1843
+ const minutes = Number(hms[2]);
1844
+ const seconds = Number(hms[3]);
1845
+ return hours * 3600 + minutes * 60 + seconds;
1846
+ }
1847
+ return null;
1848
+ };
1849
+
1850
+ // src/app/components/RunBody/RunBody.tsx
1851
+ import { Box as Box16, Text as Text16 } from "ink";
1852
+
1853
+ // src/app/components/RunProgress/RunProgress.tsx
1854
+ import { Box as Box13, Text as Text13 } from "ink";
1855
+
1856
+ // src/app/components/RunProgress/RunProgress.constants.ts
1857
+ var BAR_WIDTH = 20;
1858
+
1859
+ // src/app/components/RunProgress/RunProgress.utils.ts
1860
+ var renderBar = (finished, total) => {
1861
+ if (!total) return "";
1862
+ const filled = Math.min(BAR_WIDTH, Math.round(finished / total * BAR_WIDTH));
1863
+ return `[${"\u2588".repeat(filled)}${"\u2591".repeat(BAR_WIDTH - filled)}]`;
1864
+ };
1865
+
1866
+ // src/app/components/RunProgress/RunProgress.tsx
1867
+ import { jsx as jsx33, jsxs as jsxs19 } from "react/jsx-runtime";
1868
+ var RunProgress = ({ runState, isRunning }) => {
1869
+ if (!isRunning) return null;
1870
+ const { progress, resultsSummary: summary } = runState;
1871
+ if (progress && progress.total > 0) {
1872
+ const pct = Math.round(progress.finished / progress.total * 100);
1873
+ return /* @__PURE__ */ jsx33(Box13, { marginTop: 1, flexDirection: "column", children: /* @__PURE__ */ jsxs19(Text13, { children: [
1874
+ progress.unit === "steps" ? "Steps" : "Tests",
1875
+ ": ",
1876
+ progress.finished,
1877
+ "/",
1878
+ progress.total,
1879
+ " ",
1880
+ renderBar(progress.finished, progress.total),
1881
+ " ",
1882
+ pct,
1883
+ "%"
1884
+ ] }) });
1885
+ }
1886
+ if (!summary) return null;
1887
+ const passed = summary.passedSteps ?? 0;
1888
+ const failed = summary.failedSteps ?? 0;
1889
+ const skipped = summary.skippedSteps ?? 0;
1890
+ const total = summary.totalSteps;
1891
+ return /* @__PURE__ */ jsxs19(Box13, { marginTop: 1, flexDirection: "column", children: [
1892
+ /* @__PURE__ */ jsxs19(Text13, { children: [
1893
+ "Progress: ",
1894
+ passed,
1895
+ " passed",
1896
+ failed ? `, ${failed} failed` : "",
1897
+ skipped ? `, ${skipped} skipped` : "",
1898
+ total ? ` / ${total} total` : ""
1899
+ ] }),
1900
+ total ? /* @__PURE__ */ jsxs19(Text13, { dimColor: true, children: [
1901
+ "Completion: ",
1902
+ Math.round((passed + failed) / total * 100),
1903
+ "%"
1904
+ ] }) : null
1905
+ ] });
1906
+ };
1907
+
1908
+ // src/app/components/Status/Status.tsx
1909
+ import { Box as Box15, Text as Text15 } from "ink";
1910
+
1911
+ // src/app/components/StatusIndicator/StatusIndicator.tsx
1912
+ import { Spinner as Spinner6 } from "@inkjs/ui";
1913
+ import { Box as Box14, Text as Text14 } from "ink";
1914
+
1915
+ // src/app/components/StatusIndicator/StatusIndicator.constants.ts
1916
+ var DOT = "\u25CF";
1917
+
1918
+ // src/app/components/StatusIndicator/StatusIndicator.tsx
1919
+ import { jsx as jsx34 } from "react/jsx-runtime";
1920
+ var StatusIndicator = ({ status, autoRetried = false }) => {
1921
+ const { theme: theme2 } = useTheme();
1922
+ if (autoRetried) {
1923
+ return /* @__PURE__ */ jsx34(Text14, { color: theme2.colors.status.failure, children: DOT });
1924
+ }
1925
+ switch (status) {
1926
+ case "running":
1927
+ case "queued":
1928
+ case "recording":
1929
+ case "auto_retrying":
1930
+ return /* @__PURE__ */ jsx34(Box14, { children: /* @__PURE__ */ jsx34(Spinner6, {}) });
1931
+ case "passed":
1932
+ return /* @__PURE__ */ jsx34(Text14, { color: theme2.colors.status.success, children: DOT });
1933
+ case "failed":
1934
+ case "error":
1935
+ return /* @__PURE__ */ jsx34(Text14, { color: theme2.colors.status.failure, children: DOT });
1936
+ case "skipped":
1937
+ case "stopped":
1938
+ return /* @__PURE__ */ jsx34(Text14, { color: theme2.colors.status.stopped, children: DOT });
1939
+ case "paused":
1940
+ return /* @__PURE__ */ jsx34(Text14, { color: theme2.colors.status.paused, children: DOT });
1941
+ default:
1942
+ return /* @__PURE__ */ jsx34(Text14, { color: theme2.colors.status.info, children: DOT });
1943
+ }
1944
+ };
1945
+
1946
+ // src/app/components/Status/Status.tsx
1947
+ import { Fragment as Fragment3, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
1948
+ var ERROR_CODE_STATUSES = /* @__PURE__ */ new Set([
1949
+ "failed",
1950
+ "error",
1951
+ "passed-with-issues",
1952
+ "passed_with_issues"
1953
+ ]);
1954
+ var Status = ({
1955
+ status,
1956
+ color,
1957
+ backgroundColor,
1958
+ autoRetried = false,
1959
+ errorCode
1960
+ }) => {
1961
+ const label = status ? formatRunStatus(status, autoRetried) : "-";
1962
+ const shouldShowErrorCode = Boolean(errorCode) && status !== void 0 && (autoRetried || ERROR_CODE_STATUSES.has(status));
1963
+ return /* @__PURE__ */ jsxs20(Box15, { backgroundColor, width: "100%", children: [
1964
+ status && /* @__PURE__ */ jsxs20(Fragment3, { children: [
1965
+ /* @__PURE__ */ jsx35(StatusIndicator, { status, autoRetried }),
1966
+ /* @__PURE__ */ jsx35(Text15, { backgroundColor, children: " " })
1967
+ ] }),
1968
+ /* @__PURE__ */ jsxs20(Text15, { color, backgroundColor, children: [
1969
+ label,
1970
+ shouldShowErrorCode ? ` (${errorCode})` : ""
1971
+ ] })
1972
+ ] });
1973
+ };
1974
+
1975
+ // src/app/components/RunBody/RunBody.tsx
1976
+ import { jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
1977
+ var RunBody = ({ runState, isRunning, isCompleted = !isRunning }) => {
1978
+ const duration = formatDuration(runState.duration, {
1979
+ started: runState.started,
1980
+ ended: runState.ended
1981
+ });
1982
+ const finalResults = isCompleted ? formatFinalResults(runState) : null;
1983
+ const errorMessage = isCompleted ? getRunErrorMessage(runState) : null;
1984
+ return /* @__PURE__ */ jsxs21(Box16, { flexDirection: "column", children: [
1985
+ /* @__PURE__ */ jsxs21(Box16, { flexDirection: "column", children: [
1986
+ /* @__PURE__ */ jsx36(Box16, { children: /* @__PURE__ */ jsxs21(Text16, { children: [
1987
+ "Run id: ",
1988
+ runState.id
1989
+ ] }) }),
1990
+ /* @__PURE__ */ jsxs21(Box16, { flexDirection: "row", rowGap: 2, children: [
1991
+ /* @__PURE__ */ jsx36(Text16, { children: "Status: " }),
1992
+ /* @__PURE__ */ jsx36(
1993
+ Status,
1994
+ {
1995
+ status: runState.status,
1996
+ autoRetried: runState.isAutoRetried,
1997
+ errorCode: runState.errorCode
1998
+ }
1999
+ )
2000
+ ] }),
2001
+ /* @__PURE__ */ jsx36(Box16, { children: /* @__PURE__ */ jsxs21(Text16, { dimColor: true, children: [
2002
+ "Duration: ",
2003
+ duration
2004
+ ] }) }),
2005
+ finalResults ? /* @__PURE__ */ jsx36(Box16, { children: /* @__PURE__ */ jsx36(Text16, { children: finalResults }) }) : null,
2006
+ errorMessage ? /* @__PURE__ */ jsx36(Box16, { children: /* @__PURE__ */ jsxs21(Text16, { children: [
2007
+ "Error: ",
2008
+ errorMessage
2009
+ ] }) }) : null
2010
+ ] }),
2011
+ /* @__PURE__ */ jsx36(RunProgress, { runState, isRunning })
2012
+ ] });
2013
+ };
2014
+
2015
+ // src/app/components/BaseSuiteRunDetails/BaseSuiteRunDetails.tsx
2016
+ import { jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
2017
+ var menuOptions = (runId, state) => [
2018
+ {
2019
+ label: "Show test runs",
2020
+ shortcut: "t",
2021
+ description: "Drill into the test runs that belong to this suite run",
2022
+ to: ROUTES.suiteRuns.showTestRuns(runId),
2023
+ state
2024
+ },
2025
+ {
2026
+ label: "Open in BugBug",
2027
+ shortcut: "o",
2028
+ description: "Open the suite run page in your browser",
2029
+ to: ROUTES.suiteRuns.open(runId),
2030
+ state
2031
+ }
2032
+ ];
2033
+ var BaseSuiteRunDetails = ({
2034
+ runId,
2035
+ title,
2036
+ menuState,
2037
+ headless = false,
2038
+ intervalMs = 4e3,
2039
+ timeoutMs,
2040
+ exitDelayMs = 300,
2041
+ onComplete,
2042
+ onError
2043
+ }) => {
2044
+ const { exit } = useApp4();
2045
+ const [runState, setRunState] = useState16(null);
2046
+ const [error, setError] = useState16(null);
2047
+ useEffect12(() => {
2048
+ let cancelled = false;
2049
+ void (async () => {
2050
+ try {
2051
+ const finalStatus = await waitForSuiteRun(
2052
+ runId,
2053
+ intervalMs,
2054
+ (status) => {
2055
+ if (!cancelled) setRunState(status);
2056
+ },
2057
+ timeoutMs
2058
+ );
2059
+ if (!cancelled) {
2060
+ setRunState(finalStatus);
2061
+ onComplete?.(finalStatus);
2062
+ if (headless) setTimeout(exit, exitDelayMs);
2063
+ }
2064
+ } catch (err) {
2065
+ if (!cancelled) {
2066
+ const nextError = err instanceof Error ? err : new Error("Unknown error occurred");
2067
+ setError(nextError.message);
2068
+ onError?.(nextError);
2069
+ if (headless) setTimeout(exit, exitDelayMs);
2070
+ }
2071
+ }
2072
+ })();
2073
+ return () => {
2074
+ cancelled = true;
2075
+ };
2076
+ }, [runId, intervalMs, timeoutMs, headless, exitDelayMs, exit, onComplete, onError]);
2077
+ const isRunning = runState ? isRunningStatus(runState.status) : false;
2078
+ const isCompleted = runState ? isCompletedStatus(runState.status) : false;
2079
+ const body = /* @__PURE__ */ jsxs22(Box17, { flexDirection: "column", children: [
2080
+ error && /* @__PURE__ */ jsx37(StatusMessage8, { variant: "error", children: `Failed to complete suite run: ${error}` }),
2081
+ !error && !runState && /* @__PURE__ */ jsx37(Spinner7, { label: "Initializing..." }),
2082
+ !error && runState && /* @__PURE__ */ jsx37(RunBody, { runState, isRunning, isCompleted })
2083
+ ] });
2084
+ if (headless) return body;
2085
+ return /* @__PURE__ */ jsxs22(
2086
+ ViewLayout,
2087
+ {
2088
+ title,
2089
+ hints: isCompleted ? "navigationSelect" : "none",
2090
+ hintsHidden: !isCompleted,
2091
+ hintsPosition: "bottom",
2092
+ children: [
2093
+ body,
2094
+ isCompleted && /* @__PURE__ */ jsx37(MenuList, { options: menuOptions(runId, menuState) })
2095
+ ]
2096
+ }
2097
+ );
2098
+ };
2099
+
1301
2100
  // src/app/hooks/useSuiteRuns.ts
1302
2101
  var useSuiteRunsList = () => useFeatureQuery(() => listSuiteRuns(), []);
1303
2102
  var useSuiteRunDetails = (runId) => useFeatureQuery(async () => {
@@ -1309,7 +2108,7 @@ var useSuiteRunDetails = (runId) => useFeatureQuery(async () => {
1309
2108
  var getSuiteRunName = (run) => run.name || run.id;
1310
2109
 
1311
2110
  // src/app/views/suiteRuns/SuiteRunDetails.tsx
1312
- import { jsx as jsx25, jsxs as jsxs15 } from "react/jsx-runtime";
2111
+ import { jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
1313
2112
  var SuiteRunDetails = () => {
1314
2113
  const { runId } = useParams();
1315
2114
  const location = useLocation5();
@@ -1318,37 +2117,37 @@ var SuiteRunDetails = () => {
1318
2117
  const title = request.data ? getSuiteRunName(request.data) : state?.suiteRunName;
1319
2118
  const menuState = title ? { suiteRunName: title } : void 0;
1320
2119
  if (!request.data || !runId) {
1321
- return /* @__PURE__ */ jsxs15(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
1322
- request.isLoading && /* @__PURE__ */ jsx25(Spinner6, { label: "Loading suite run..." }),
1323
- request.isError && /* @__PURE__ */ jsx25(StatusMessage8, { variant: "error", children: request.error }),
1324
- !request.isLoading && !request.isError && !request.data && /* @__PURE__ */ jsx25(Text8, { color: "yellow", children: "Suite run not found." })
2120
+ return /* @__PURE__ */ jsxs23(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
2121
+ request.isLoading && /* @__PURE__ */ jsx38(Spinner8, { label: "Loading suite run..." }),
2122
+ request.isError && /* @__PURE__ */ jsx38(StatusMessage9, { variant: "error", children: request.error }),
2123
+ !request.isLoading && !request.isError && !request.data && /* @__PURE__ */ jsx38(Text17, { color: "yellow", children: "Suite run not found." })
1325
2124
  ] });
1326
2125
  }
1327
- return /* @__PURE__ */ jsx25(BaseSuiteRunDetails, { runId, title, menuState });
2126
+ return /* @__PURE__ */ jsx38(BaseSuiteRunDetails, { runId, title, menuState });
1328
2127
  };
1329
2128
 
1330
2129
  // src/app/views/suiteRuns/SuiteRunOpen.tsx
1331
- import { Spinner as Spinner7, StatusMessage as StatusMessage9 } from "@inkjs/ui";
1332
- import { Box as Box10, Text as Text9 } from "ink";
1333
- import { useEffect as useEffect9 } from "react";
2130
+ import { Spinner as Spinner9, StatusMessage as StatusMessage10 } from "@inkjs/ui";
2131
+ import { Box as Box18, Text as Text18 } from "ink";
2132
+ import { useEffect as useEffect13 } from "react";
1334
2133
  import { useLocation as useLocation6, useParams as useParams2 } from "react-router";
1335
- import { Fragment as Fragment2, jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
1336
- var WebUrlUnavailableMessage = () => /* @__PURE__ */ jsx26(StatusMessage9, { variant: "warning", children: "No web URL available for this run" });
2134
+ import { Fragment as Fragment4, jsx as jsx39, jsxs as jsxs24 } from "react/jsx-runtime";
2135
+ var WebUrlUnavailableMessage = () => /* @__PURE__ */ jsx39(StatusMessage10, { variant: "warning", children: "No web URL available for this run" });
1337
2136
  var OpenSuiteRun = ({ url }) => {
1338
2137
  const [openSuiteRun, openSuiteRunResult] = useFeatureMutation(async (url2) => {
1339
2138
  await openExternalUrl(url2);
1340
2139
  return url2;
1341
2140
  });
1342
- useEffect9(() => {
2141
+ useEffect13(() => {
1343
2142
  if (url) void openSuiteRun(url);
1344
2143
  }, [openSuiteRun, url]);
1345
- if (!url) return /* @__PURE__ */ jsx26(WebUrlUnavailableMessage, {});
1346
- return /* @__PURE__ */ jsxs16(Fragment2, { children: [
1347
- openSuiteRunResult.isLoading && /* @__PURE__ */ jsx26(Spinner7, { label: "Opening BugBug..." }),
1348
- openSuiteRunResult.isError && /* @__PURE__ */ jsx26(StatusMessage9, { variant: "error", children: openSuiteRunResult.error }),
1349
- openSuiteRunResult.data && /* @__PURE__ */ jsxs16(Box10, { flexDirection: "column", children: [
1350
- /* @__PURE__ */ jsx26(StatusMessage9, { variant: "success", children: "Opened in BugBug" }),
1351
- /* @__PURE__ */ jsx26(Text9, { dimColor: true, children: openSuiteRunResult.data })
2144
+ if (!url) return /* @__PURE__ */ jsx39(WebUrlUnavailableMessage, {});
2145
+ return /* @__PURE__ */ jsxs24(Fragment4, { children: [
2146
+ openSuiteRunResult.isLoading && /* @__PURE__ */ jsx39(Spinner9, { label: "Opening BugBug..." }),
2147
+ openSuiteRunResult.isError && /* @__PURE__ */ jsx39(StatusMessage10, { variant: "error", children: openSuiteRunResult.error }),
2148
+ openSuiteRunResult.data && /* @__PURE__ */ jsxs24(Box18, { flexDirection: "column", children: [
2149
+ /* @__PURE__ */ jsx39(StatusMessage10, { variant: "success", children: "Opened in BugBug" }),
2150
+ /* @__PURE__ */ jsx39(Text18, { dimColor: true, children: openSuiteRunResult.data })
1352
2151
  ] })
1353
2152
  ] });
1354
2153
  };
@@ -1358,20 +2157,20 @@ var SuiteRunOpen = () => {
1358
2157
  const state = location.state;
1359
2158
  const request = useSuiteRunDetails(runId);
1360
2159
  const title = request.data ? getSuiteRunName(request.data) : state?.suiteRunName ?? runId;
1361
- return /* @__PURE__ */ jsxs16(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
1362
- request.isLoading && /* @__PURE__ */ jsx26(Spinner7, { label: "Loading..." }),
1363
- request.isError && /* @__PURE__ */ jsx26(Text9, { color: "red", children: request.error }),
1364
- !request.isLoading && !request.isError && /* @__PURE__ */ jsx26(OpenSuiteRun, { url: request.data?.webappUrl })
2160
+ return /* @__PURE__ */ jsxs24(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
2161
+ request.isLoading && /* @__PURE__ */ jsx39(Spinner9, { label: "Loading..." }),
2162
+ request.isError && /* @__PURE__ */ jsx39(Text18, { color: "red", children: request.error }),
2163
+ !request.isLoading && !request.isError && /* @__PURE__ */ jsx39(OpenSuiteRun, { url: request.data?.webappUrl })
1365
2164
  ] });
1366
2165
  };
1367
2166
 
1368
2167
  // src/app/views/suiteRuns/SuiteRunShowTestRuns.tsx
1369
- import { Spinner as Spinner8 } from "@inkjs/ui";
1370
- import { StatusMessage as StatusMessage10 } from "@inkjs/ui";
2168
+ import { Spinner as Spinner10 } from "@inkjs/ui";
2169
+ import { StatusMessage as StatusMessage11 } from "@inkjs/ui";
1371
2170
  import { useLocation as useLocation7, useParams as useParams3 } from "react-router";
1372
2171
 
1373
2172
  // src/features/testRuns/components/TestRunsList.tsx
1374
- import { useNavigate as useNavigate7 } from "react-router";
2173
+ import { useNavigate as useNavigate8 } from "react-router";
1375
2174
 
1376
2175
  // src/features/testRuns/testRuns.utils.ts
1377
2176
  var getTestRunName = (run) => run.name || run.id;
@@ -1387,7 +2186,7 @@ var DEBUG_ARTIFACT_LABELS = {
1387
2186
  var getDebugArtifactLabel = (artifact) => DEBUG_ARTIFACT_LABELS[artifact.kind];
1388
2187
 
1389
2188
  // src/features/testRuns/components/TestRunsList.constants.tsx
1390
- import { jsx as jsx27 } from "react/jsx-runtime";
2189
+ import { jsx as jsx40 } from "react/jsx-runtime";
1391
2190
  var TEST_RUN_LIST_COLUMNS = [
1392
2191
  { key: "name", label: "Name", width: 30 },
1393
2192
  { key: "duration", label: "Duration", width: 8 },
@@ -1398,7 +2197,7 @@ var TEST_RUN_LIST_COLUMNS = [
1398
2197
  key: "status",
1399
2198
  label: "Status",
1400
2199
  width: 15,
1401
- render: (_cell, row, ctx) => /* @__PURE__ */ jsx27(
2200
+ render: (_cell, row, ctx) => /* @__PURE__ */ jsx40(
1402
2201
  Status,
1403
2202
  {
1404
2203
  status: row.value?.status,
@@ -1428,7 +2227,7 @@ var getTestRunRow = (run) => {
1428
2227
  };
1429
2228
 
1430
2229
  // src/features/testRuns/components/TestRunsList.tsx
1431
- import { jsx as jsx28 } from "react/jsx-runtime";
2230
+ import { jsx as jsx41 } from "react/jsx-runtime";
1432
2231
  var TestRunsList = ({
1433
2232
  title,
1434
2233
  loadingLabel = "Loading test runs...",
@@ -1438,8 +2237,8 @@ var TestRunsList = ({
1438
2237
  isError,
1439
2238
  error
1440
2239
  }) => {
1441
- const navigate = useNavigate7();
1442
- return /* @__PURE__ */ jsx28(
2240
+ const navigate = useNavigate8();
2241
+ return /* @__PURE__ */ jsx41(
1443
2242
  BaseResourceListScreen,
1444
2243
  {
1445
2244
  title,
@@ -1457,10 +2256,10 @@ var TestRunsList = ({
1457
2256
  };
1458
2257
 
1459
2258
  // src/app/views/suiteRuns/SuiteRunShowTestRuns.tsx
1460
- import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
2259
+ import { jsx as jsx42, jsxs as jsxs25 } from "react/jsx-runtime";
1461
2260
  var SuiteRunTestRuns = ({ run, title }) => {
1462
2261
  const request = useFeatureQuery(() => getSuiteRunTestRuns(run.id), [run.id]);
1463
- return /* @__PURE__ */ jsx29(
2262
+ return /* @__PURE__ */ jsx42(
1464
2263
  TestRunsList,
1465
2264
  {
1466
2265
  title,
@@ -1480,20 +2279,20 @@ var SuiteRunShowTestRuns = () => {
1480
2279
  const request = useSuiteRunDetails(runId);
1481
2280
  const title = request.data ? `Test runs in "${getSuiteRunName(request.data)}"` : state?.suiteRunName ? `Test runs in "${state.suiteRunName}"` : void 0;
1482
2281
  if (!request.data) {
1483
- return /* @__PURE__ */ jsxs17(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
1484
- request.isLoading && /* @__PURE__ */ jsx29(Spinner8, { label: "Loading..." }),
1485
- request.isError && /* @__PURE__ */ jsx29(StatusMessage10, { variant: "error", children: request.error }),
1486
- !request.isLoading && !request.isError && /* @__PURE__ */ jsx29(StatusMessage10, { variant: "warning", children: "No test runs available" })
2282
+ return /* @__PURE__ */ jsxs25(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
2283
+ request.isLoading && /* @__PURE__ */ jsx42(Spinner10, { label: "Loading..." }),
2284
+ request.isError && /* @__PURE__ */ jsx42(StatusMessage11, { variant: "error", children: request.error }),
2285
+ !request.isLoading && !request.isError && /* @__PURE__ */ jsx42(StatusMessage11, { variant: "warning", children: "No test runs available" })
1487
2286
  ] });
1488
2287
  }
1489
- return /* @__PURE__ */ jsx29(SuiteRunTestRuns, { run: request.data, title: title ?? "" });
2288
+ return /* @__PURE__ */ jsx42(SuiteRunTestRuns, { run: request.data, title: title ?? "" });
1490
2289
  };
1491
2290
 
1492
2291
  // src/app/views/suiteRuns/SuiteRunsList.tsx
1493
- import { useNavigate as useNavigate8 } from "react-router";
2292
+ import { useNavigate as useNavigate9 } from "react-router";
1494
2293
 
1495
2294
  // src/app/views/suiteRuns/SuiteRunsList.constants.tsx
1496
- import { jsx as jsx30 } from "react/jsx-runtime";
2295
+ import { jsx as jsx43 } from "react/jsx-runtime";
1497
2296
  var SUITE_RUN_LIST_COLUMNS = [
1498
2297
  { key: "name", label: "Name", width: 30 },
1499
2298
  { key: "duration", label: "Duration", width: 10 },
@@ -1504,7 +2303,7 @@ var SUITE_RUN_LIST_COLUMNS = [
1504
2303
  key: "status",
1505
2304
  label: "Status",
1506
2305
  width: 10,
1507
- render: (_cell, row, ctx) => /* @__PURE__ */ jsx30(Status, { status: row.value?.status, color: ctx.color, backgroundColor: ctx.backgroundColor })
2306
+ render: (_cell, row, ctx) => /* @__PURE__ */ jsx43(Status, { status: row.value?.status, color: ctx.color, backgroundColor: ctx.backgroundColor })
1508
2307
  }
1509
2308
  ];
1510
2309
 
@@ -1532,11 +2331,11 @@ var getSuiteRunRow = (run) => {
1532
2331
  };
1533
2332
 
1534
2333
  // src/app/views/suiteRuns/SuiteRunsList.tsx
1535
- import { jsx as jsx31 } from "react/jsx-runtime";
2334
+ import { jsx as jsx44 } from "react/jsx-runtime";
1536
2335
  var SuiteRunsList = () => {
1537
- const navigate = useNavigate8();
2336
+ const navigate = useNavigate9();
1538
2337
  const request = useSuiteRunsList();
1539
- return /* @__PURE__ */ jsx31(
2338
+ return /* @__PURE__ */ jsx44(
1540
2339
  BaseResourceListScreen,
1541
2340
  {
1542
2341
  loadingLabel: "Loading suite runs...",
@@ -1555,21 +2354,21 @@ var SuiteRunsList = () => {
1555
2354
  };
1556
2355
 
1557
2356
  // src/app/views/suiteRuns/SuiteRunsMenu.tsx
1558
- import { useEffect as useEffect10 } from "react";
1559
- import { useNavigate as useNavigate9 } from "react-router";
2357
+ import { useEffect as useEffect14 } from "react";
2358
+ import { useNavigate as useNavigate10 } from "react-router";
1560
2359
  var SuiteRunsMenu = () => {
1561
- const navigate = useNavigate9();
1562
- useEffect10(() => {
2360
+ const navigate = useNavigate10();
2361
+ useEffect14(() => {
1563
2362
  navigate(ROUTES.suiteRuns.list(), { replace: true });
1564
2363
  }, [navigate]);
1565
2364
  return null;
1566
2365
  };
1567
2366
 
1568
2367
  // src/app/views/suites/RunSuite.tsx
1569
- import { useNavigate as useNavigate10 } from "react-router";
2368
+ import { useNavigate as useNavigate11 } from "react-router";
1570
2369
 
1571
2370
  // src/app/views/suites/BaseSuitesList.tsx
1572
- import { useState as useState14 } from "react";
2371
+ import { useState as useState17 } from "react";
1573
2372
 
1574
2373
  // src/app/hooks/useSuites.ts
1575
2374
  var useSuitesList = (query) => useFeatureQuery(() => loadSuiteTableResources(query), [query]);
@@ -1579,14 +2378,14 @@ var useSuiteDetails = (suiteId) => useFeatureQuery(async () => {
1579
2378
  }, [suiteId]);
1580
2379
 
1581
2380
  // src/features/suites/suites.constants.tsx
1582
- import { jsx as jsx32 } from "react/jsx-runtime";
2381
+ import { jsx as jsx45 } from "react/jsx-runtime";
1583
2382
  var SUITE_COLUMNS = [
1584
2383
  { key: "name", label: "Name", width: 42 },
1585
2384
  {
1586
2385
  key: "status",
1587
2386
  label: "Status",
1588
2387
  width: 14,
1589
- render: (_cell, row, ctx) => /* @__PURE__ */ jsx32(Status, { status: row.value?.status, color: ctx.color, backgroundColor: ctx.backgroundColor })
2388
+ render: (_cell, row, ctx) => /* @__PURE__ */ jsx45(Status, { status: row.value?.status, color: ctx.color, backgroundColor: ctx.backgroundColor })
1590
2389
  }
1591
2390
  ];
1592
2391
 
@@ -1602,15 +2401,15 @@ var getSuiteRow = (suite) => ({
1602
2401
  var getSuiteName = (suite) => suite.name || suite.id || "Untitled";
1603
2402
 
1604
2403
  // src/app/views/suites/BaseSuitesList.tsx
1605
- import { jsx as jsx33 } from "react/jsx-runtime";
2404
+ import { jsx as jsx46 } from "react/jsx-runtime";
1606
2405
  var BaseSuitesList = ({
1607
2406
  title,
1608
2407
  emptyMessage = "No suites found",
1609
2408
  onSelectSuite
1610
2409
  }) => {
1611
- const [query, setQuery] = useState14("");
2410
+ const [query, setQuery] = useState17("");
1612
2411
  const request = useSuitesList(query);
1613
- return /* @__PURE__ */ jsx33(
2412
+ return /* @__PURE__ */ jsx46(
1614
2413
  BaseResourceListScreen,
1615
2414
  {
1616
2415
  title,
@@ -1631,10 +2430,10 @@ var BaseSuitesList = ({
1631
2430
  };
1632
2431
 
1633
2432
  // src/app/views/suites/RunSuite.tsx
1634
- import { jsx as jsx34 } from "react/jsx-runtime";
2433
+ import { jsx as jsx47 } from "react/jsx-runtime";
1635
2434
  var RunSuite = () => {
1636
- const navigate = useNavigate10();
1637
- return /* @__PURE__ */ jsx34(
2435
+ const navigate = useNavigate11();
2436
+ return /* @__PURE__ */ jsx47(
1638
2437
  BaseSuitesList,
1639
2438
  {
1640
2439
  title: "Select a suite to run:",
@@ -1645,10 +2444,10 @@ var RunSuite = () => {
1645
2444
  };
1646
2445
 
1647
2446
  // src/app/views/suites/SuiteDetails.tsx
1648
- import { Spinner as Spinner9, StatusMessage as StatusMessage11 } from "@inkjs/ui";
1649
- import { Box as Box11 } from "ink";
2447
+ import { Spinner as Spinner11, StatusMessage as StatusMessage12 } from "@inkjs/ui";
2448
+ import { Box as Box19 } from "ink";
1650
2449
  import { useLocation as useLocation8, useParams as useParams4 } from "react-router";
1651
- import { jsx as jsx35, jsxs as jsxs18 } from "react/jsx-runtime";
2450
+ import { jsx as jsx48, jsxs as jsxs26 } from "react/jsx-runtime";
1652
2451
  var SuiteDetails = () => {
1653
2452
  const { suiteId } = useParams4();
1654
2453
  const location = useLocation8();
@@ -1682,19 +2481,19 @@ var SuiteDetails = () => {
1682
2481
  to: ROUTES.suites.open(suiteId ?? "")
1683
2482
  }
1684
2483
  ];
1685
- return /* @__PURE__ */ jsxs18(ViewLayout, { title, hints, children: [
1686
- request.isLoading && /* @__PURE__ */ jsx35(Box11, { children: /* @__PURE__ */ jsx35(Spinner9, { label: "Loading suite..." }) }),
1687
- request.isError && /* @__PURE__ */ jsx35(StatusMessage11, { variant: "error", children: request.error }),
1688
- isNotFound && /* @__PURE__ */ jsx35(StatusMessage11, { variant: "warning", children: "Suite not found" }),
1689
- isReady && /* @__PURE__ */ jsx35(MenuList, { options })
2484
+ return /* @__PURE__ */ jsxs26(ViewLayout, { title, hints, children: [
2485
+ request.isLoading && /* @__PURE__ */ jsx48(Box19, { children: /* @__PURE__ */ jsx48(Spinner11, { label: "Loading suite..." }) }),
2486
+ request.isError && /* @__PURE__ */ jsx48(StatusMessage12, { variant: "error", children: request.error }),
2487
+ isNotFound && /* @__PURE__ */ jsx48(StatusMessage12, { variant: "warning", children: "Suite not found" }),
2488
+ isReady && /* @__PURE__ */ jsx48(MenuList, { options })
1690
2489
  ] });
1691
2490
  };
1692
2491
 
1693
2492
  // src/app/views/suites/SuiteDetailsLastRun.tsx
1694
- import { Spinner as Spinner10, StatusMessage as StatusMessage12 } from "@inkjs/ui";
1695
- import { Text as Text10 } from "ink";
2493
+ import { Spinner as Spinner12, StatusMessage as StatusMessage13 } from "@inkjs/ui";
2494
+ import { Text as Text19 } from "ink";
1696
2495
  import { useLocation as useLocation9, useParams as useParams5 } from "react-router";
1697
- import { jsx as jsx36, jsxs as jsxs19 } from "react/jsx-runtime";
2496
+ import { jsx as jsx49, jsxs as jsxs27 } from "react/jsx-runtime";
1698
2497
  var SuiteDetailsLastRun = () => {
1699
2498
  const { suiteId } = useParams5();
1700
2499
  const location = useLocation9();
@@ -1704,13 +2503,13 @@ var SuiteDetailsLastRun = () => {
1704
2503
  const isReady = !request.isLoading && !request.isError;
1705
2504
  const title = suite ? getSuiteName(suite) : state?.suiteName ?? suiteId;
1706
2505
  if (!isReady || !suite?.lastRunId) {
1707
- return /* @__PURE__ */ jsxs19(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
1708
- request.isLoading && /* @__PURE__ */ jsx36(Spinner10, { label: "Loading..." }),
1709
- request.isError && /* @__PURE__ */ jsx36(Text10, { color: "red", children: request.error }),
1710
- isReady && !suite?.lastRunId && /* @__PURE__ */ jsx36(StatusMessage12, { variant: "warning", children: `No previous run found for ${suite ? getSuiteName(suite) : suiteId ?? "suite"}` })
2506
+ return /* @__PURE__ */ jsxs27(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
2507
+ request.isLoading && /* @__PURE__ */ jsx49(Spinner12, { label: "Loading..." }),
2508
+ request.isError && /* @__PURE__ */ jsx49(Text19, { color: "red", children: request.error }),
2509
+ isReady && !suite?.lastRunId && /* @__PURE__ */ jsx49(StatusMessage13, { variant: "warning", children: `No previous run found for ${suite ? getSuiteName(suite) : suiteId ?? "suite"}` })
1711
2510
  ] });
1712
2511
  }
1713
- return /* @__PURE__ */ jsx36(
2512
+ return /* @__PURE__ */ jsx49(
1714
2513
  BaseSuiteRunDetails,
1715
2514
  {
1716
2515
  runId: suite.lastRunId,
@@ -1721,13 +2520,13 @@ var SuiteDetailsLastRun = () => {
1721
2520
  };
1722
2521
 
1723
2522
  // src/app/views/suites/SuiteDetailsOpen.tsx
1724
- import { StatusMessage as StatusMessage13 } from "@inkjs/ui";
1725
- import { Spinner as Spinner11 } from "@inkjs/ui";
1726
- import { Box as Box12, Text as Text11 } from "ink";
1727
- import { useEffect as useEffect11 } from "react";
2523
+ import { StatusMessage as StatusMessage14 } from "@inkjs/ui";
2524
+ import { Spinner as Spinner13 } from "@inkjs/ui";
2525
+ import { Box as Box20, Text as Text20 } from "ink";
2526
+ import { useEffect as useEffect15 } from "react";
1728
2527
  import { useParams as useParams6 } from "react-router";
1729
- import { jsx as jsx37, jsxs as jsxs20 } from "react/jsx-runtime";
1730
- var WebUrlUnavailableMessage2 = () => /* @__PURE__ */ jsx37(StatusMessage13, { variant: "warning", children: "No web URL available for this suite" });
2528
+ import { jsx as jsx50, jsxs as jsxs28 } from "react/jsx-runtime";
2529
+ var WebUrlUnavailableMessage2 = () => /* @__PURE__ */ jsx50(StatusMessage14, { variant: "warning", children: "No web URL available for this suite" });
1731
2530
  var SuiteDetailsOpen = () => {
1732
2531
  const { suiteId } = useParams6();
1733
2532
  const request = useFeatureQuery(async () => {
@@ -1740,41 +2539,41 @@ var SuiteDetailsOpen = () => {
1740
2539
  await openExternalUrl(url2);
1741
2540
  return url2;
1742
2541
  });
1743
- useEffect11(() => {
2542
+ useEffect15(() => {
1744
2543
  if (isReady && url) void openSuite(url);
1745
2544
  }, [isReady, openSuite, url]);
1746
- return /* @__PURE__ */ jsxs20(ViewLayout, { hintsHidden: true, children: [
1747
- request.isLoading && /* @__PURE__ */ jsx37(Spinner11, { label: "Loading..." }),
1748
- request.isError && /* @__PURE__ */ jsx37(Text11, { color: "red", children: request.error }),
1749
- isReady && !url && /* @__PURE__ */ jsx37(WebUrlUnavailableMessage2, {}),
1750
- isReady && url && openSuiteResult.isLoading && /* @__PURE__ */ jsx37(Spinner11, { label: "Opening BugBug..." }),
1751
- isReady && url && openSuiteResult.isError && /* @__PURE__ */ jsx37(StatusMessage13, { variant: "error", children: openSuiteResult.error }),
1752
- isReady && url && openSuiteResult.data && /* @__PURE__ */ jsxs20(Box12, { flexDirection: "column", children: [
1753
- /* @__PURE__ */ jsx37(StatusMessage13, { variant: "success", children: "Opened in BugBug" }),
1754
- /* @__PURE__ */ jsx37(Text11, { dimColor: true, children: openSuiteResult.data })
2545
+ return /* @__PURE__ */ jsxs28(ViewLayout, { hintsHidden: true, children: [
2546
+ request.isLoading && /* @__PURE__ */ jsx50(Spinner13, { label: "Loading..." }),
2547
+ request.isError && /* @__PURE__ */ jsx50(Text20, { color: "red", children: request.error }),
2548
+ isReady && !url && /* @__PURE__ */ jsx50(WebUrlUnavailableMessage2, {}),
2549
+ isReady && url && openSuiteResult.isLoading && /* @__PURE__ */ jsx50(Spinner13, { label: "Opening BugBug..." }),
2550
+ isReady && url && openSuiteResult.isError && /* @__PURE__ */ jsx50(StatusMessage14, { variant: "error", children: openSuiteResult.error }),
2551
+ isReady && url && openSuiteResult.data && /* @__PURE__ */ jsxs28(Box20, { flexDirection: "column", children: [
2552
+ /* @__PURE__ */ jsx50(StatusMessage14, { variant: "success", children: "Opened in BugBug" }),
2553
+ /* @__PURE__ */ jsx50(Text20, { dimColor: true, children: openSuiteResult.data })
1755
2554
  ] })
1756
2555
  ] });
1757
2556
  };
1758
2557
 
1759
2558
  // src/app/views/suites/SuiteDetailsRun.tsx
1760
- import { Spinner as Spinner12, StatusMessage as StatusMessage14 } from "@inkjs/ui";
1761
- import { useEffect as useEffect12 } from "react";
1762
- import { useLocation as useLocation10, useNavigate as useNavigate11, useParams as useParams7 } from "react-router";
1763
- import { jsx as jsx38, jsxs as jsxs21 } from "react/jsx-runtime";
2559
+ import { Spinner as Spinner14, StatusMessage as StatusMessage15 } from "@inkjs/ui";
2560
+ import { useEffect as useEffect16 } from "react";
2561
+ import { useLocation as useLocation10, useNavigate as useNavigate12, useParams as useParams7 } from "react-router";
2562
+ import { jsx as jsx51, jsxs as jsxs29 } from "react/jsx-runtime";
1764
2563
  var SuiteDetailsRun = () => {
1765
2564
  const { suiteId } = useParams7();
1766
2565
  const location = useLocation10();
1767
- const navigate = useNavigate11();
2566
+ const navigate = useNavigate12();
1768
2567
  const state = location.state;
1769
2568
  const title = state?.suiteName ?? suiteId;
1770
2569
  const [runSuiteMutation, runSuiteResult] = useFeatureMutation((id) => runSuite(id, {}));
1771
- useEffect12(() => {
2570
+ useEffect16(() => {
1772
2571
  if (!suiteId) return;
1773
2572
  const startRun = async () => {
1774
2573
  try {
1775
2574
  const result = await runSuiteMutation(suiteId);
1776
2575
  if ("data" in result) {
1777
- navigate(ROUTES.suites.lastRun(suiteId), { replace: true, state });
2576
+ navigate(ROUTES.suiteRuns.details(result.data.id), { replace: true, state });
1778
2577
  }
1779
2578
  } catch {
1780
2579
  }
@@ -1782,20 +2581,20 @@ var SuiteDetailsRun = () => {
1782
2581
  startRun();
1783
2582
  }, [navigate, runSuiteMutation, state, suiteId]);
1784
2583
  if (!runSuiteResult.data) {
1785
- return /* @__PURE__ */ jsxs21(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
1786
- runSuiteResult.isError && /* @__PURE__ */ jsx38(StatusMessage14, { variant: "error", children: runSuiteResult.error }),
1787
- !runSuiteResult.isError && /* @__PURE__ */ jsx38(Spinner12, { label: "Initializing..." })
2584
+ return /* @__PURE__ */ jsxs29(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
2585
+ runSuiteResult.isError && /* @__PURE__ */ jsx51(StatusMessage15, { variant: "error", children: runSuiteResult.error }),
2586
+ !runSuiteResult.isError && /* @__PURE__ */ jsx51(Spinner14, { label: "Initializing..." })
1788
2587
  ] });
1789
2588
  }
1790
- return /* @__PURE__ */ jsx38(BaseSuiteRunDetails, { runId: runSuiteResult.data.id, title, menuState: state });
2589
+ return /* @__PURE__ */ jsx51(BaseSuiteRunDetails, { runId: runSuiteResult.data.id, title, menuState: state });
1791
2590
  };
1792
2591
 
1793
2592
  // src/app/views/suites/SuitesList.tsx
1794
- import { useNavigate as useNavigate12 } from "react-router";
1795
- import { jsx as jsx39 } from "react/jsx-runtime";
2593
+ import { useNavigate as useNavigate13 } from "react-router";
2594
+ import { jsx as jsx52 } from "react/jsx-runtime";
1796
2595
  var SuitesList = () => {
1797
- const navigate = useNavigate12();
1798
- return /* @__PURE__ */ jsx39(
2596
+ const navigate = useNavigate13();
2597
+ return /* @__PURE__ */ jsx52(
1799
2598
  BaseSuitesList,
1800
2599
  {
1801
2600
  onSelectSuite: (suite) => navigate(ROUTES.suites.details(suite.id), { state: { suiteName: getSuiteName(suite) } })
@@ -1804,9 +2603,9 @@ var SuitesList = () => {
1804
2603
  };
1805
2604
 
1806
2605
  // src/app/views/suites/SuitesMenu.tsx
1807
- import { jsx as jsx40 } from "react/jsx-runtime";
2606
+ import { jsx as jsx53 } from "react/jsx-runtime";
1808
2607
  var SuitesMenu = () => {
1809
- return /* @__PURE__ */ jsx40(ViewLayout, { children: /* @__PURE__ */ jsx40(
2608
+ return /* @__PURE__ */ jsx53(ViewLayout, { children: /* @__PURE__ */ jsx53(
1810
2609
  MenuList,
1811
2610
  {
1812
2611
  options: [
@@ -1818,7 +2617,7 @@ var SuitesMenu = () => {
1818
2617
  };
1819
2618
 
1820
2619
  // src/app/views/testRuns/TestRunDebugArtifacts.tsx
1821
- import { Spinner as Spinner13, StatusMessage as StatusMessage15 } from "@inkjs/ui";
2620
+ import { Spinner as Spinner15, StatusMessage as StatusMessage16 } from "@inkjs/ui";
1822
2621
  import { useLocation as useLocation11, useParams as useParams8 } from "react-router";
1823
2622
 
1824
2623
  // src/app/hooks/useTestRuns.ts
@@ -1829,20 +2628,20 @@ var useTestRunDetails = (runId) => useFeatureQuery(async () => {
1829
2628
  }, [runId]);
1830
2629
 
1831
2630
  // src/app/views/testRuns/TestRunDebugArtifacts.tsx
1832
- import { jsx as jsx41 } from "react/jsx-runtime";
1833
- var ArtifactsUnavailableMessage = () => /* @__PURE__ */ jsx41(StatusMessage15, { variant: "warning", children: "No debug artifacts available" });
2631
+ import { jsx as jsx54 } from "react/jsx-runtime";
2632
+ var ArtifactsUnavailableMessage = () => /* @__PURE__ */ jsx54(StatusMessage16, { variant: "warning", children: "No debug artifacts available" });
1834
2633
  var DebugArtifacts = ({ runId }) => {
1835
2634
  const request = useFeatureQuery(() => listTestRunDebugArtifacts(runId), [runId]);
1836
2635
  if (request.isLoading) {
1837
- return /* @__PURE__ */ jsx41(Spinner13, { label: `Loading debug artifacts for ${runId}...` });
2636
+ return /* @__PURE__ */ jsx54(Spinner15, { label: `Loading debug artifacts for ${runId}...` });
1838
2637
  }
1839
2638
  if (request.isError) {
1840
- return /* @__PURE__ */ jsx41(StatusMessage15, { variant: "error", children: request.error });
2639
+ return /* @__PURE__ */ jsx54(StatusMessage16, { variant: "error", children: request.error });
1841
2640
  }
1842
2641
  if (!request.data || request.data.length === 0) {
1843
- return /* @__PURE__ */ jsx41(ArtifactsUnavailableMessage, {});
2642
+ return /* @__PURE__ */ jsx54(ArtifactsUnavailableMessage, {});
1844
2643
  }
1845
- return /* @__PURE__ */ jsx41(
2644
+ return /* @__PURE__ */ jsx54(
1846
2645
  MenuList,
1847
2646
  {
1848
2647
  options: request.data.map((artifact) => ({
@@ -1864,22 +2663,119 @@ var TestRunDebugArtifacts = () => {
1864
2663
  const state = location.state;
1865
2664
  const detailsRequest = useTestRunDetails(runId);
1866
2665
  const title = detailsRequest.data ? getTestRunName(detailsRequest.data) : state?.testRunName ?? "Debug artifacts";
1867
- return /* @__PURE__ */ jsx41(
2666
+ return /* @__PURE__ */ jsx54(
1868
2667
  ViewLayout,
1869
2668
  {
1870
2669
  title,
1871
2670
  hints: runId ? "navigationOpenSelect" : "none",
1872
2671
  hintsPosition: "bottom",
1873
- children: runId ? /* @__PURE__ */ jsx41(DebugArtifacts, { runId }) : /* @__PURE__ */ jsx41(ArtifactsUnavailableMessage, {})
2672
+ children: runId ? /* @__PURE__ */ jsx54(DebugArtifacts, { runId }) : /* @__PURE__ */ jsx54(ArtifactsUnavailableMessage, {})
1874
2673
  }
1875
2674
  );
1876
2675
  };
1877
2676
 
1878
2677
  // src/app/views/testRuns/TestRunDetails.tsx
1879
- import { Spinner as Spinner14, StatusMessage as StatusMessage16 } from "@inkjs/ui";
1880
- import { Text as Text12 } from "ink";
2678
+ import { Spinner as Spinner17, StatusMessage as StatusMessage18 } from "@inkjs/ui";
2679
+ import { Text as Text21 } from "ink";
1881
2680
  import { useLocation as useLocation12, useParams as useParams9 } from "react-router";
1882
- import { jsx as jsx42, jsxs as jsxs22 } from "react/jsx-runtime";
2681
+
2682
+ // src/app/components/BaseTestRunDetails/BaseTestRunDetails.tsx
2683
+ import { Spinner as Spinner16, StatusMessage as StatusMessage17 } from "@inkjs/ui";
2684
+ import { Box as Box21, useApp as useApp5 } from "ink";
2685
+ import { useEffect as useEffect17, useState as useState18 } from "react";
2686
+ import { jsx as jsx55, jsxs as jsxs30 } from "react/jsx-runtime";
2687
+ var getMenuOptions = (runId, state) => [
2688
+ {
2689
+ label: "Show run artifacts",
2690
+ shortcut: "a",
2691
+ description: "Browse console logs and downloadable debug artifacts",
2692
+ to: ROUTES.testRuns.debugArtifacts(runId),
2693
+ state
2694
+ },
2695
+ {
2696
+ label: "Download JUnit report",
2697
+ shortcut: "j",
2698
+ description: "Save the JUnit XML report to the current directory",
2699
+ to: ROUTES.testRuns.junitReport(runId),
2700
+ state
2701
+ },
2702
+ {
2703
+ label: "Open in BugBug",
2704
+ shortcut: "o",
2705
+ description: "Open the run page in your browser",
2706
+ to: ROUTES.testRuns.open(runId),
2707
+ state
2708
+ }
2709
+ ];
2710
+ var BaseTestRunDetails = ({
2711
+ runId,
2712
+ title,
2713
+ menuState,
2714
+ headless = false,
2715
+ intervalMs = 4e3,
2716
+ timeoutMs,
2717
+ exitDelayMs = 300,
2718
+ onComplete,
2719
+ onError
2720
+ }) => {
2721
+ const { exit } = useApp5();
2722
+ const [runState, setRunState] = useState18(null);
2723
+ const [error, setError] = useState18(null);
2724
+ useEffect17(() => {
2725
+ let cancelled = false;
2726
+ void (async () => {
2727
+ try {
2728
+ const finalStatus = await waitForTestRun(
2729
+ runId,
2730
+ intervalMs,
2731
+ (status) => {
2732
+ if (!cancelled) setRunState(status);
2733
+ },
2734
+ timeoutMs
2735
+ );
2736
+ if (!cancelled) {
2737
+ setRunState(finalStatus);
2738
+ onComplete?.(finalStatus);
2739
+ if (headless) setTimeout(exit, exitDelayMs);
2740
+ }
2741
+ } catch (err) {
2742
+ if (!cancelled) {
2743
+ const nextError = err instanceof Error ? err : new Error("Unknown error occurred");
2744
+ setError(nextError.message);
2745
+ onError?.(nextError);
2746
+ if (headless) setTimeout(exit, exitDelayMs);
2747
+ }
2748
+ }
2749
+ })();
2750
+ return () => {
2751
+ cancelled = true;
2752
+ };
2753
+ }, [runId, intervalMs, timeoutMs, headless, exitDelayMs, exit, onComplete, onError]);
2754
+ const isRunning = runState ? isRunningStatus(runState.status) : false;
2755
+ const isCompleted = runState ? isCompletedStatus(runState.status) : false;
2756
+ const body = /* @__PURE__ */ jsxs30(Box21, { flexDirection: "column", children: [
2757
+ error && /* @__PURE__ */ jsx55(StatusMessage17, { variant: "error", children: `Failed to complete test run: ${error}` }),
2758
+ !error && !runState && /* @__PURE__ */ jsx55(Spinner16, { label: "Initializing..." }),
2759
+ !error && runState && /* @__PURE__ */ jsx55(RunBody, { runState, isRunning })
2760
+ ] });
2761
+ if (headless) return body;
2762
+ return /* @__PURE__ */ jsxs30(
2763
+ ViewLayout,
2764
+ {
2765
+ title,
2766
+ hints: isCompleted ? "navigationSelect" : "none",
2767
+ hintsHidden: !isCompleted,
2768
+ hintsPosition: "bottom",
2769
+ children: [
2770
+ body,
2771
+ isCompleted && /* @__PURE__ */ jsx55(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx55(MenuList, { options: getMenuOptions(runId, menuState) }) })
2772
+ ]
2773
+ }
2774
+ );
2775
+ };
2776
+
2777
+ // src/app/views/testRuns/TestRunDetails.tsx
2778
+ import { jsx as jsx56, jsxs as jsxs31 } from "react/jsx-runtime";
1883
2779
  var TestRunDetails = () => {
1884
2780
  const { runId } = useParams9();
1885
2781
  const location = useLocation12();
@@ -1888,33 +2784,33 @@ var TestRunDetails = () => {
1888
2784
  const title = request.data ? getTestRunName(request.data) : state?.testRunName;
1889
2785
  const menuState = title ? { testRunName: title } : void 0;
1890
2786
  if (!request.data || !runId) {
1891
- return /* @__PURE__ */ jsxs22(ViewLayout, { title, hintsHidden: true, children: [
1892
- request.isLoading && /* @__PURE__ */ jsx42(Spinner14, { label: "Loading test run..." }),
1893
- request.isError && /* @__PURE__ */ jsx42(StatusMessage16, { variant: "error", children: request.error }),
1894
- !request.isLoading && !request.isError && !request.data && /* @__PURE__ */ jsx42(Text12, { color: "yellow", children: "Test run not found." })
2787
+ return /* @__PURE__ */ jsxs31(ViewLayout, { title, hintsHidden: true, children: [
2788
+ request.isLoading && /* @__PURE__ */ jsx56(Spinner17, { label: "Loading test run..." }),
2789
+ request.isError && /* @__PURE__ */ jsx56(StatusMessage18, { variant: "error", children: request.error }),
2790
+ !request.isLoading && !request.isError && !request.data && /* @__PURE__ */ jsx56(Text21, { color: "yellow", children: "Test run not found." })
1895
2791
  ] });
1896
2792
  }
1897
- return /* @__PURE__ */ jsx42(BaseTestRunDetails, { runId, title, menuState });
2793
+ return /* @__PURE__ */ jsx56(BaseTestRunDetails, { runId, title, menuState });
1898
2794
  };
1899
2795
 
1900
2796
  // src/app/views/testRuns/TestRunJunitReport.tsx
1901
- import { Spinner as Spinner15, StatusMessage as StatusMessage17 } from "@inkjs/ui";
1902
- import { Text as Text13 } from "ink";
1903
- import { useEffect as useEffect13 } from "react";
2797
+ import { Spinner as Spinner18, StatusMessage as StatusMessage19 } from "@inkjs/ui";
2798
+ import { Text as Text22 } from "ink";
2799
+ import { useEffect as useEffect18 } from "react";
1904
2800
  import { useLocation as useLocation13, useParams as useParams10 } from "react-router";
1905
- import { Fragment as Fragment3, jsx as jsx43, jsxs as jsxs23 } from "react/jsx-runtime";
2801
+ import { Fragment as Fragment5, jsx as jsx57, jsxs as jsxs32 } from "react/jsx-runtime";
1906
2802
  var DownloadReport = ({ runId }) => {
1907
2803
  const [downloadReport, downloadReportResult] = useFeatureMutation(async (runId2) => {
1908
2804
  const xml = await getTestRunJunitReport(runId2);
1909
2805
  return writeReportXml(xml, defaultJunitReportPath("test", runId2));
1910
2806
  });
1911
- useEffect13(() => {
2807
+ useEffect18(() => {
1912
2808
  void downloadReport(runId);
1913
2809
  }, [downloadReport, runId]);
1914
- return /* @__PURE__ */ jsxs23(Fragment3, { children: [
1915
- downloadReportResult.isLoading && /* @__PURE__ */ jsx43(Spinner15, { label: "Downloading JUnit report..." }),
1916
- downloadReportResult.isError && /* @__PURE__ */ jsx43(StatusMessage17, { variant: "error", children: downloadReportResult.error }),
1917
- downloadReportResult.data?.outPath && /* @__PURE__ */ jsx43(StatusMessage17, { variant: "success", children: `Saved JUnit report to ${downloadReportResult.data.outPath} (${downloadReportResult.data.size} chars)` })
2810
+ return /* @__PURE__ */ jsxs32(Fragment5, { children: [
2811
+ downloadReportResult.isLoading && /* @__PURE__ */ jsx57(Spinner18, { label: "Downloading JUnit report..." }),
2812
+ downloadReportResult.isError && /* @__PURE__ */ jsx57(StatusMessage19, { variant: "error", children: downloadReportResult.error }),
2813
+ downloadReportResult.data?.outPath && /* @__PURE__ */ jsx57(StatusMessage19, { variant: "success", children: `Saved JUnit report to ${downloadReportResult.data.outPath} (${downloadReportResult.data.size} chars)` })
1918
2814
  ] });
1919
2815
  };
1920
2816
  var TestRunJunitReport = () => {
@@ -1923,36 +2819,36 @@ var TestRunJunitReport = () => {
1923
2819
  const state = location.state;
1924
2820
  const request = useTestRunDetails(runId);
1925
2821
  const title = request.data ? getTestRunName(request.data) : state?.testRunName ?? runId;
1926
- return /* @__PURE__ */ jsxs23(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
1927
- request.isLoading && /* @__PURE__ */ jsx43(Spinner15, { label: "Loading..." }),
1928
- request.isError && /* @__PURE__ */ jsx43(Text13, { color: "red", children: request.error }),
1929
- !request.isLoading && !request.isError && runId && /* @__PURE__ */ jsx43(DownloadReport, { runId }),
1930
- !request.isLoading && !request.isError && !runId && /* @__PURE__ */ jsx43(StatusMessage17, { variant: "warning", children: "No test run selected" })
2822
+ return /* @__PURE__ */ jsxs32(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
2823
+ request.isLoading && /* @__PURE__ */ jsx57(Spinner18, { label: "Loading..." }),
2824
+ request.isError && /* @__PURE__ */ jsx57(Text22, { color: "red", children: request.error }),
2825
+ !request.isLoading && !request.isError && runId && /* @__PURE__ */ jsx57(DownloadReport, { runId }),
2826
+ !request.isLoading && !request.isError && !runId && /* @__PURE__ */ jsx57(StatusMessage19, { variant: "warning", children: "No test run selected" })
1931
2827
  ] });
1932
2828
  };
1933
2829
 
1934
2830
  // src/app/views/testRuns/TestRunOpen.tsx
1935
- import { Spinner as Spinner16, StatusMessage as StatusMessage18 } from "@inkjs/ui";
1936
- import { Box as Box13, Text as Text14 } from "ink";
1937
- import { useEffect as useEffect14 } from "react";
2831
+ import { Spinner as Spinner19, StatusMessage as StatusMessage20 } from "@inkjs/ui";
2832
+ import { Box as Box22, Text as Text23 } from "ink";
2833
+ import { useEffect as useEffect19 } from "react";
1938
2834
  import { useLocation as useLocation14, useParams as useParams11 } from "react-router";
1939
- import { Fragment as Fragment4, jsx as jsx44, jsxs as jsxs24 } from "react/jsx-runtime";
1940
- var WebUrlUnavailableMessage3 = () => /* @__PURE__ */ jsx44(StatusMessage18, { variant: "warning", children: "No web URL available for this run" });
2835
+ import { Fragment as Fragment6, jsx as jsx58, jsxs as jsxs33 } from "react/jsx-runtime";
2836
+ var WebUrlUnavailableMessage3 = () => /* @__PURE__ */ jsx58(StatusMessage20, { variant: "warning", children: "No web URL available for this run" });
1941
2837
  var OpenRun = ({ url }) => {
1942
2838
  const [openRun, openRunResult] = useFeatureMutation(async (url2) => {
1943
2839
  await openExternalUrl(url2);
1944
2840
  return url2;
1945
2841
  });
1946
- useEffect14(() => {
2842
+ useEffect19(() => {
1947
2843
  if (url) void openRun(url);
1948
2844
  }, [openRun, url]);
1949
- if (!url) return /* @__PURE__ */ jsx44(WebUrlUnavailableMessage3, {});
1950
- return /* @__PURE__ */ jsxs24(Fragment4, { children: [
1951
- openRunResult.isLoading && /* @__PURE__ */ jsx44(Spinner16, { label: "Opening BugBug..." }),
1952
- openRunResult.isError && /* @__PURE__ */ jsx44(StatusMessage18, { variant: "error", children: openRunResult.error }),
1953
- openRunResult.data && /* @__PURE__ */ jsxs24(Box13, { flexDirection: "column", children: [
1954
- /* @__PURE__ */ jsx44(StatusMessage18, { variant: "success", children: "Opened in BugBug" }),
1955
- /* @__PURE__ */ jsx44(Text14, { dimColor: true, children: openRunResult.data })
2845
+ if (!url) return /* @__PURE__ */ jsx58(WebUrlUnavailableMessage3, {});
2846
+ return /* @__PURE__ */ jsxs33(Fragment6, { children: [
2847
+ openRunResult.isLoading && /* @__PURE__ */ jsx58(Spinner19, { label: "Opening BugBug..." }),
2848
+ openRunResult.isError && /* @__PURE__ */ jsx58(StatusMessage20, { variant: "error", children: openRunResult.error }),
2849
+ openRunResult.data && /* @__PURE__ */ jsxs33(Box22, { flexDirection: "column", children: [
2850
+ /* @__PURE__ */ jsx58(StatusMessage20, { variant: "success", children: "Opened in BugBug" }),
2851
+ /* @__PURE__ */ jsx58(Text23, { dimColor: true, children: openRunResult.data })
1956
2852
  ] })
1957
2853
  ] });
1958
2854
  };
@@ -1962,18 +2858,18 @@ var TestRunOpen = () => {
1962
2858
  const state = location.state;
1963
2859
  const request = useTestRunDetails(runId);
1964
2860
  const title = request.data ? getTestRunName(request.data) : state?.testRunName ?? runId;
1965
- return /* @__PURE__ */ jsxs24(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
1966
- request.isLoading && /* @__PURE__ */ jsx44(Spinner16, { label: "Loading..." }),
1967
- request.isError && /* @__PURE__ */ jsx44(Text14, { color: "red", children: request.error }),
1968
- !request.isLoading && !request.isError && /* @__PURE__ */ jsx44(OpenRun, { url: request.data?.webappUrl })
2861
+ return /* @__PURE__ */ jsxs33(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
2862
+ request.isLoading && /* @__PURE__ */ jsx58(Spinner19, { label: "Loading..." }),
2863
+ request.isError && /* @__PURE__ */ jsx58(Text23, { color: "red", children: request.error }),
2864
+ !request.isLoading && !request.isError && /* @__PURE__ */ jsx58(OpenRun, { url: request.data?.webappUrl })
1969
2865
  ] });
1970
2866
  };
1971
2867
 
1972
2868
  // src/app/views/testRuns/TestRunsList.tsx
1973
- import { jsx as jsx45 } from "react/jsx-runtime";
2869
+ import { jsx as jsx59 } from "react/jsx-runtime";
1974
2870
  var TestRunsList2 = () => {
1975
2871
  const request = useTestRunsList();
1976
- return /* @__PURE__ */ jsx45(
2872
+ return /* @__PURE__ */ jsx59(
1977
2873
  TestRunsList,
1978
2874
  {
1979
2875
  testRuns: request.data,
@@ -1985,21 +2881,21 @@ var TestRunsList2 = () => {
1985
2881
  };
1986
2882
 
1987
2883
  // src/app/views/testRuns/TestRunsMenu.tsx
1988
- import { useEffect as useEffect15 } from "react";
1989
- import { useNavigate as useNavigate13 } from "react-router";
2884
+ import { useEffect as useEffect20 } from "react";
2885
+ import { useNavigate as useNavigate14 } from "react-router";
1990
2886
  var TestRunsMenu = () => {
1991
- const navigate = useNavigate13();
1992
- useEffect15(() => {
2887
+ const navigate = useNavigate14();
2888
+ useEffect20(() => {
1993
2889
  navigate(ROUTES.testRuns.list(), { replace: true });
1994
2890
  }, [navigate]);
1995
2891
  return null;
1996
2892
  };
1997
2893
 
1998
2894
  // src/app/views/tests/RunTest.tsx
1999
- import { useNavigate as useNavigate14 } from "react-router";
2895
+ import { useNavigate as useNavigate15 } from "react-router";
2000
2896
 
2001
2897
  // src/app/views/tests/BaseTestsList.tsx
2002
- import { useState as useState15 } from "react";
2898
+ import { useState as useState19 } from "react";
2003
2899
 
2004
2900
  // src/app/hooks/useTests.ts
2005
2901
  var useTestsList = (query) => useFeatureQuery(() => loadTestTableResources(query), [query]);
@@ -2009,14 +2905,14 @@ var useTestDetails = (testId) => useFeatureQuery(async () => {
2009
2905
  }, [testId]);
2010
2906
 
2011
2907
  // src/features/tests/tests.constants.tsx
2012
- import { jsx as jsx46 } from "react/jsx-runtime";
2908
+ import { jsx as jsx60 } from "react/jsx-runtime";
2013
2909
  var TEST_COLUMNS = [
2014
2910
  { key: "name", label: "Name", width: 42 },
2015
2911
  {
2016
2912
  key: "status",
2017
2913
  label: "Status",
2018
2914
  width: 14,
2019
- render: (_cell, row, ctx) => /* @__PURE__ */ jsx46(Status, { status: row.value?.status, color: ctx.color, backgroundColor: ctx.backgroundColor })
2915
+ render: (_cell, row, ctx) => /* @__PURE__ */ jsx60(Status, { status: row.value?.status, color: ctx.color, backgroundColor: ctx.backgroundColor })
2020
2916
  }
2021
2917
  ];
2022
2918
 
@@ -2032,15 +2928,15 @@ var getTestRow = (test) => ({
2032
2928
  var getTestName = (test) => test.name || test.id || "Untitled";
2033
2929
 
2034
2930
  // src/app/views/tests/BaseTestsList.tsx
2035
- import { jsx as jsx47 } from "react/jsx-runtime";
2931
+ import { jsx as jsx61 } from "react/jsx-runtime";
2036
2932
  var BaseTestsList = ({
2037
2933
  title,
2038
2934
  emptyMessage = "No tests found",
2039
2935
  onSelectTest
2040
2936
  }) => {
2041
- const [query, setQuery] = useState15("");
2937
+ const [query, setQuery] = useState19("");
2042
2938
  const request = useTestsList(query);
2043
- return /* @__PURE__ */ jsx47(
2939
+ return /* @__PURE__ */ jsx61(
2044
2940
  BaseResourceListScreen,
2045
2941
  {
2046
2942
  title,
@@ -2061,10 +2957,10 @@ var BaseTestsList = ({
2061
2957
  };
2062
2958
 
2063
2959
  // src/app/views/tests/RunTest.tsx
2064
- import { jsx as jsx48 } from "react/jsx-runtime";
2960
+ import { jsx as jsx62 } from "react/jsx-runtime";
2065
2961
  var RunTest = () => {
2066
- const navigate = useNavigate14();
2067
- return /* @__PURE__ */ jsx48(
2962
+ const navigate = useNavigate15();
2963
+ return /* @__PURE__ */ jsx62(
2068
2964
  BaseTestsList,
2069
2965
  {
2070
2966
  title: "Select a test to run:",
@@ -2075,10 +2971,10 @@ var RunTest = () => {
2075
2971
  };
2076
2972
 
2077
2973
  // src/app/views/tests/TestDetails.tsx
2078
- import { Spinner as Spinner17, StatusMessage as StatusMessage19 } from "@inkjs/ui";
2079
- import { Box as Box14 } from "ink";
2974
+ import { Spinner as Spinner20, StatusMessage as StatusMessage21 } from "@inkjs/ui";
2975
+ import { Box as Box23 } from "ink";
2080
2976
  import { useLocation as useLocation15, useParams as useParams12 } from "react-router";
2081
- import { jsx as jsx49, jsxs as jsxs25 } from "react/jsx-runtime";
2977
+ import { jsx as jsx63, jsxs as jsxs34 } from "react/jsx-runtime";
2082
2978
  var TestDetails = () => {
2083
2979
  const { testId } = useParams12();
2084
2980
  const location = useLocation15();
@@ -2118,40 +3014,40 @@ var TestDetails = () => {
2118
3014
  to: ROUTES.tests.open(testId ?? "")
2119
3015
  }
2120
3016
  ];
2121
- return /* @__PURE__ */ jsxs25(ViewLayout, { title, hints, children: [
2122
- request.isLoading && /* @__PURE__ */ jsx49(Box14, { children: /* @__PURE__ */ jsx49(Spinner17, { label: "Loading test..." }) }),
2123
- request.isError && /* @__PURE__ */ jsx49(StatusMessage19, { variant: "error", children: request.error }),
2124
- isNotFound && /* @__PURE__ */ jsx49(StatusMessage19, { variant: "warning", children: "Test not found." }),
2125
- isReady && /* @__PURE__ */ jsx49(MenuList, { options })
3017
+ return /* @__PURE__ */ jsxs34(ViewLayout, { title, hints, children: [
3018
+ request.isLoading && /* @__PURE__ */ jsx63(Box23, { children: /* @__PURE__ */ jsx63(Spinner20, { label: "Loading test..." }) }),
3019
+ request.isError && /* @__PURE__ */ jsx63(StatusMessage21, { variant: "error", children: request.error }),
3020
+ isNotFound && /* @__PURE__ */ jsx63(StatusMessage21, { variant: "warning", children: "Test not found." }),
3021
+ isReady && /* @__PURE__ */ jsx63(MenuList, { options })
2126
3022
  ] });
2127
3023
  };
2128
3024
 
2129
3025
  // src/app/views/tests/TestDetailsExport.tsx
2130
- import { StatusMessage as StatusMessage20 } from "@inkjs/ui";
2131
- import { Spinner as Spinner18 } from "@inkjs/ui";
2132
- import { useEffect as useEffect16 } from "react";
3026
+ import { StatusMessage as StatusMessage22 } from "@inkjs/ui";
3027
+ import { Spinner as Spinner21 } from "@inkjs/ui";
3028
+ import { useEffect as useEffect21 } from "react";
2133
3029
  import { useParams as useParams13 } from "react-router";
2134
- import { jsx as jsx50, jsxs as jsxs26 } from "react/jsx-runtime";
3030
+ import { jsx as jsx64, jsxs as jsxs35 } from "react/jsx-runtime";
2135
3031
  var TestDetailsExport = () => {
2136
3032
  const { testId } = useParams13();
2137
3033
  const [exportTestMutation, exportTestResult] = useFeatureMutation(
2138
3034
  (id) => exportTest(id, "yaml")
2139
3035
  );
2140
- useEffect16(() => {
3036
+ useEffect21(() => {
2141
3037
  if (testId) void exportTestMutation(testId);
2142
3038
  }, [exportTestMutation, testId]);
2143
- return /* @__PURE__ */ jsxs26(ViewLayout, { hintsHidden: true, children: [
2144
- exportTestResult.isLoading && /* @__PURE__ */ jsx50(Spinner18, { label: `Exporting ${testId}...` }),
2145
- exportTestResult.isError && /* @__PURE__ */ jsx50(StatusMessage20, { variant: "error", children: exportTestResult.error }),
2146
- exportTestResult.data && /* @__PURE__ */ jsx50(StatusMessage20, { variant: "success", children: `Exported to ${exportTestResult.data.outPath} (${exportTestResult.data.size} chars)` })
3039
+ return /* @__PURE__ */ jsxs35(ViewLayout, { hintsHidden: true, children: [
3040
+ exportTestResult.isLoading && /* @__PURE__ */ jsx64(Spinner21, { label: `Exporting ${testId}...` }),
3041
+ exportTestResult.isError && /* @__PURE__ */ jsx64(StatusMessage22, { variant: "error", children: exportTestResult.error }),
3042
+ exportTestResult.data && /* @__PURE__ */ jsx64(StatusMessage22, { variant: "success", children: `Exported to ${exportTestResult.data.outPath} (${exportTestResult.data.size} chars)` })
2147
3043
  ] });
2148
3044
  };
2149
3045
 
2150
3046
  // src/app/views/tests/TestDetailsLastRun.tsx
2151
- import { Spinner as Spinner19, StatusMessage as StatusMessage21 } from "@inkjs/ui";
2152
- import { Text as Text15 } from "ink";
3047
+ import { Spinner as Spinner22, StatusMessage as StatusMessage23 } from "@inkjs/ui";
3048
+ import { Text as Text24 } from "ink";
2153
3049
  import { useLocation as useLocation16, useParams as useParams14 } from "react-router";
2154
- import { jsx as jsx51, jsxs as jsxs27 } from "react/jsx-runtime";
3050
+ import { jsx as jsx65, jsxs as jsxs36 } from "react/jsx-runtime";
2155
3051
  var TestDetailsLastRun = () => {
2156
3052
  const { testId } = useParams14();
2157
3053
  const location = useLocation16();
@@ -2161,23 +3057,23 @@ var TestDetailsLastRun = () => {
2161
3057
  const isReady = !request.isLoading && !request.isError;
2162
3058
  const title = test ? getTestName(test) : state?.testName ?? testId;
2163
3059
  if (!isReady || !test?.lastRunId) {
2164
- return /* @__PURE__ */ jsxs27(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
2165
- request.isLoading && /* @__PURE__ */ jsx51(Spinner19, { label: "Loading..." }),
2166
- request.isError && /* @__PURE__ */ jsx51(Text15, { color: "red", children: request.error }),
2167
- isReady && !test?.lastRunId && /* @__PURE__ */ jsx51(StatusMessage21, { variant: "warning", children: `No previous run found for ${test ? getTestName(test) : testId ?? "test"}` })
3060
+ return /* @__PURE__ */ jsxs36(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
3061
+ request.isLoading && /* @__PURE__ */ jsx65(Spinner22, { label: "Loading..." }),
3062
+ request.isError && /* @__PURE__ */ jsx65(Text24, { color: "red", children: request.error }),
3063
+ isReady && !test?.lastRunId && /* @__PURE__ */ jsx65(StatusMessage23, { variant: "warning", children: `No previous run found for ${test ? getTestName(test) : testId ?? "test"}` })
2168
3064
  ] });
2169
3065
  }
2170
- return /* @__PURE__ */ jsx51(BaseTestRunDetails, { runId: test.lastRunId, title, menuState: { testRunName: title } });
3066
+ return /* @__PURE__ */ jsx65(BaseTestRunDetails, { runId: test.lastRunId, title, menuState: { testRunName: title } });
2171
3067
  };
2172
3068
 
2173
3069
  // src/app/views/tests/TestDetailsOpen.tsx
2174
- import { StatusMessage as StatusMessage22 } from "@inkjs/ui";
2175
- import { Spinner as Spinner20 } from "@inkjs/ui";
2176
- import { Box as Box15, Text as Text16 } from "ink";
2177
- import { useEffect as useEffect17 } from "react";
3070
+ import { StatusMessage as StatusMessage24 } from "@inkjs/ui";
3071
+ import { Spinner as Spinner23 } from "@inkjs/ui";
3072
+ import { Box as Box24, Text as Text25 } from "ink";
3073
+ import { useEffect as useEffect22 } from "react";
2178
3074
  import { useParams as useParams15 } from "react-router";
2179
- import { jsx as jsx52, jsxs as jsxs28 } from "react/jsx-runtime";
2180
- var WebUrlUnavailableMessage4 = () => /* @__PURE__ */ jsx52(StatusMessage22, { variant: "warning", children: "No web URL available for this test" });
3075
+ import { jsx as jsx66, jsxs as jsxs37 } from "react/jsx-runtime";
3076
+ var WebUrlUnavailableMessage4 = () => /* @__PURE__ */ jsx66(StatusMessage24, { variant: "warning", children: "No web URL available for this test" });
2181
3077
  var TestDetailsOpen = () => {
2182
3078
  const { testId } = useParams15();
2183
3079
  const request = useFeatureQuery(async () => {
@@ -2190,41 +3086,41 @@ var TestDetailsOpen = () => {
2190
3086
  await openExternalUrl(url2);
2191
3087
  return url2;
2192
3088
  });
2193
- useEffect17(() => {
3089
+ useEffect22(() => {
2194
3090
  if (isReady && url) void openTest(url);
2195
3091
  }, [isReady, openTest, url]);
2196
- return /* @__PURE__ */ jsxs28(ViewLayout, { hintsHidden: true, children: [
2197
- request.isLoading && /* @__PURE__ */ jsx52(Spinner20, { label: "Loading..." }),
2198
- request.isError && /* @__PURE__ */ jsx52(Text16, { color: "red", children: request.error }),
2199
- isReady && !url && /* @__PURE__ */ jsx52(WebUrlUnavailableMessage4, {}),
2200
- isReady && url && openTestResult.isLoading && /* @__PURE__ */ jsx52(Spinner20, { label: "Opening BugBug..." }),
2201
- isReady && url && openTestResult.isError && /* @__PURE__ */ jsx52(StatusMessage22, { variant: "error", children: openTestResult.error }),
2202
- isReady && url && openTestResult.data && /* @__PURE__ */ jsxs28(Box15, { flexDirection: "column", children: [
2203
- /* @__PURE__ */ jsx52(StatusMessage22, { variant: "success", children: "Opened in BugBug" }),
2204
- /* @__PURE__ */ jsx52(Text16, { dimColor: true, children: openTestResult.data })
3092
+ return /* @__PURE__ */ jsxs37(ViewLayout, { hintsHidden: true, children: [
3093
+ request.isLoading && /* @__PURE__ */ jsx66(Spinner23, { label: "Loading..." }),
3094
+ request.isError && /* @__PURE__ */ jsx66(Text25, { color: "red", children: request.error }),
3095
+ isReady && !url && /* @__PURE__ */ jsx66(WebUrlUnavailableMessage4, {}),
3096
+ isReady && url && openTestResult.isLoading && /* @__PURE__ */ jsx66(Spinner23, { label: "Opening BugBug..." }),
3097
+ isReady && url && openTestResult.isError && /* @__PURE__ */ jsx66(StatusMessage24, { variant: "error", children: openTestResult.error }),
3098
+ isReady && url && openTestResult.data && /* @__PURE__ */ jsxs37(Box24, { flexDirection: "column", children: [
3099
+ /* @__PURE__ */ jsx66(StatusMessage24, { variant: "success", children: "Opened in BugBug" }),
3100
+ /* @__PURE__ */ jsx66(Text25, { dimColor: true, children: openTestResult.data })
2205
3101
  ] })
2206
3102
  ] });
2207
3103
  };
2208
3104
 
2209
3105
  // src/app/views/tests/TestDetailsRun.tsx
2210
- import { Spinner as Spinner21, StatusMessage as StatusMessage23 } from "@inkjs/ui";
2211
- import { useEffect as useEffect18 } from "react";
2212
- import { useLocation as useLocation17, useNavigate as useNavigate15, useParams as useParams16 } from "react-router";
2213
- import { jsx as jsx53, jsxs as jsxs29 } from "react/jsx-runtime";
3106
+ import { Spinner as Spinner24, StatusMessage as StatusMessage25 } from "@inkjs/ui";
3107
+ import { useEffect as useEffect23 } from "react";
3108
+ import { useLocation as useLocation17, useNavigate as useNavigate16, useParams as useParams16 } from "react-router";
3109
+ import { jsx as jsx67, jsxs as jsxs38 } from "react/jsx-runtime";
2214
3110
  var TestDetailsRun = () => {
2215
3111
  const { testId } = useParams16();
2216
3112
  const location = useLocation17();
2217
- const navigate = useNavigate15();
3113
+ const navigate = useNavigate16();
2218
3114
  const state = location.state;
2219
3115
  const title = state?.testName ?? testId;
2220
3116
  const [runTestMutation, runTestResult] = useFeatureMutation((id) => runTest(id, {}));
2221
- useEffect18(() => {
3117
+ useEffect23(() => {
2222
3118
  if (!testId) return;
2223
3119
  const startRun = async () => {
2224
3120
  try {
2225
3121
  const result = await runTestMutation(testId);
2226
3122
  if ("data" in result) {
2227
- navigate(ROUTES.tests.lastRun(testId), { replace: true, state });
3123
+ navigate(ROUTES.testRuns.details(result.data.id), { replace: true, state });
2228
3124
  }
2229
3125
  } catch {
2230
3126
  }
@@ -2232,23 +3128,23 @@ var TestDetailsRun = () => {
2232
3128
  startRun();
2233
3129
  }, [navigate, runTestMutation, state, testId]);
2234
3130
  if (!runTestResult.data) {
2235
- return /* @__PURE__ */ jsxs29(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
2236
- runTestResult.isError && /* @__PURE__ */ jsx53(StatusMessage23, { variant: "error", children: runTestResult.error }),
2237
- !runTestResult.isError && /* @__PURE__ */ jsx53(Spinner21, { label: "Initializing..." })
3131
+ return /* @__PURE__ */ jsxs38(ViewLayout, { title, hintsHidden: true, hintsPosition: "bottom", children: [
3132
+ runTestResult.isError && /* @__PURE__ */ jsx67(StatusMessage25, { variant: "error", children: runTestResult.error }),
3133
+ !runTestResult.isError && /* @__PURE__ */ jsx67(Spinner24, { label: "Initializing..." })
2238
3134
  ] });
2239
3135
  }
2240
- return /* @__PURE__ */ jsx53(BaseTestRunDetails, { runId: runTestResult.data.id, title, menuState: state });
3136
+ return /* @__PURE__ */ jsx67(BaseTestRunDetails, { runId: runTestResult.data.id, title, menuState: state });
2241
3137
  };
2242
3138
 
2243
3139
  // src/app/views/tests/TestImport.tsx
2244
- import { Spinner as Spinner22, StatusMessage as StatusMessage24 } from "@inkjs/ui";
2245
- import { useEffect as useEffect19, useState as useState16 } from "react";
2246
- import { useNavigate as useNavigate16 } from "react-router";
2247
- import { jsx as jsx54, jsxs as jsxs30 } from "react/jsx-runtime";
3140
+ import { Spinner as Spinner25, StatusMessage as StatusMessage26 } from "@inkjs/ui";
3141
+ import { useEffect as useEffect24, useState as useState20 } from "react";
3142
+ import { useNavigate as useNavigate17 } from "react-router";
3143
+ import { jsx as jsx68, jsxs as jsxs39 } from "react/jsx-runtime";
2248
3144
  var TestImport = ({ initialDirectory } = {}) => {
2249
- const navigate = useNavigate16();
2250
- const [file, setFile] = useState16(null);
2251
- const [conflictMode, setConflictMode] = useState16(null);
3145
+ const navigate = useNavigate17();
3146
+ const [file, setFile] = useState20(null);
3147
+ const [conflictMode, setConflictMode] = useState20(null);
2252
3148
  const [importTestMutation, importTestResult] = useFeatureMutation(
2253
3149
  async ({ file: file2, conflictMode: conflictMode2 }) => {
2254
3150
  detectFormat(file2);
@@ -2257,7 +3153,7 @@ var TestImport = ({ initialDirectory } = {}) => {
2257
3153
  });
2258
3154
  }
2259
3155
  );
2260
- useEffect19(() => {
3156
+ useEffect24(() => {
2261
3157
  if (file && conflictMode !== null) {
2262
3158
  void importTestMutation({ file, conflictMode });
2263
3159
  }
@@ -2268,7 +3164,7 @@ var TestImport = ({ initialDirectory } = {}) => {
2268
3164
  return true;
2269
3165
  });
2270
3166
  if (!file) {
2271
- return /* @__PURE__ */ jsx54(
3167
+ return /* @__PURE__ */ jsx68(
2272
3168
  FilePicker,
2273
3169
  {
2274
3170
  label: "Select .yaml/.yml/.zip file",
@@ -2280,7 +3176,7 @@ var TestImport = ({ initialDirectory } = {}) => {
2280
3176
  );
2281
3177
  }
2282
3178
  if (conflictMode === null) {
2283
- return /* @__PURE__ */ jsx54(ViewLayout, { title: "Conflict mode (blank = API default)", children: /* @__PURE__ */ jsx54(
3179
+ return /* @__PURE__ */ jsx68(ViewLayout, { title: "Conflict mode (blank = API default)", children: /* @__PURE__ */ jsx68(
2284
3180
  MenuList,
2285
3181
  {
2286
3182
  options: [
@@ -2291,19 +3187,19 @@ var TestImport = ({ initialDirectory } = {}) => {
2291
3187
  }
2292
3188
  ) });
2293
3189
  }
2294
- return /* @__PURE__ */ jsxs30(ViewLayout, { hintsHidden: true, hintsPosition: "bottom", children: [
2295
- importTestResult.isLoading && /* @__PURE__ */ jsx54(Spinner22, { label: `Importing ${file}...` }),
2296
- importTestResult.isError && /* @__PURE__ */ jsx54(StatusMessage24, { variant: "error", children: importTestResult.error }),
2297
- importTestResult.data && /* @__PURE__ */ jsx54(StatusMessage24, { variant: "success", children: `Imported test: ${importTestResult.data.id ?? "(unknown)"}${importTestResult.data.name ? ` (${importTestResult.data.name})` : ""}` })
3190
+ return /* @__PURE__ */ jsxs39(ViewLayout, { hintsHidden: true, hintsPosition: "bottom", children: [
3191
+ importTestResult.isLoading && /* @__PURE__ */ jsx68(Spinner25, { label: `Importing ${file}...` }),
3192
+ importTestResult.isError && /* @__PURE__ */ jsx68(StatusMessage26, { variant: "error", children: importTestResult.error }),
3193
+ importTestResult.data && /* @__PURE__ */ jsx68(StatusMessage26, { variant: "success", children: `Imported test: ${importTestResult.data.id ?? "(unknown)"}${importTestResult.data.name ? ` (${importTestResult.data.name})` : ""}` })
2298
3194
  ] });
2299
3195
  };
2300
3196
 
2301
3197
  // src/app/views/tests/TestsList.tsx
2302
- import { useNavigate as useNavigate17 } from "react-router";
2303
- import { jsx as jsx55 } from "react/jsx-runtime";
3198
+ import { useNavigate as useNavigate18 } from "react-router";
3199
+ import { jsx as jsx69 } from "react/jsx-runtime";
2304
3200
  var TestsList = () => {
2305
- const navigate = useNavigate17();
2306
- return /* @__PURE__ */ jsx55(
3201
+ const navigate = useNavigate18();
3202
+ return /* @__PURE__ */ jsx69(
2307
3203
  BaseTestsList,
2308
3204
  {
2309
3205
  onSelectTest: (test) => navigate(ROUTES.tests.details(test.id), { state: { testName: getTestName(test) } })
@@ -2312,9 +3208,9 @@ var TestsList = () => {
2312
3208
  };
2313
3209
 
2314
3210
  // src/app/views/tests/TestsMenu.tsx
2315
- import { jsx as jsx56 } from "react/jsx-runtime";
3211
+ import { jsx as jsx70 } from "react/jsx-runtime";
2316
3212
  var TestsMenu = () => {
2317
- return /* @__PURE__ */ jsx56(ViewLayout, { children: /* @__PURE__ */ jsx56(
3213
+ return /* @__PURE__ */ jsx70(ViewLayout, { children: /* @__PURE__ */ jsx70(
2318
3214
  MenuList,
2319
3215
  {
2320
3216
  options: [
@@ -2332,7 +3228,7 @@ var TestsMenu = () => {
2332
3228
  };
2333
3229
 
2334
3230
  // src/app/router.tsx
2335
- import { jsx as jsx57, jsxs as jsxs31 } from "react/jsx-runtime";
3231
+ import { jsx as jsx71, jsxs as jsxs40 } from "react/jsx-runtime";
2336
3232
  var createNavigatorRouter = ({
2337
3233
  initialRoute,
2338
3234
  initialRouteState
@@ -2347,45 +3243,45 @@ var createNavigatorRouter = ({
2347
3243
  const initialEntries = getInitialEntries();
2348
3244
  const router = createMemoryRouter(
2349
3245
  createRoutesFromElements(
2350
- /* @__PURE__ */ jsxs31(Route, { element: /* @__PURE__ */ jsx57(Navigator, {}), children: [
2351
- /* @__PURE__ */ jsx57(Route, { index: true, element: /* @__PURE__ */ jsx57(MainMenu, {}) }),
2352
- /* @__PURE__ */ jsx57(Route, { path: "/init", element: /* @__PURE__ */ jsx57(ProjectInit, {}) }),
2353
- /* @__PURE__ */ jsx57(Route, { path: "/tests", element: /* @__PURE__ */ jsx57(TestsMenu, {}) }),
2354
- /* @__PURE__ */ jsx57(Route, { path: "/tests/list", element: /* @__PURE__ */ jsx57(TestsList, {}) }),
2355
- /* @__PURE__ */ jsx57(Route, { path: "/tests/import", element: /* @__PURE__ */ jsx57(TestImport, {}) }),
2356
- /* @__PURE__ */ jsx57(Route, { path: "/tests/run", element: /* @__PURE__ */ jsx57(RunTest, {}) }),
2357
- /* @__PURE__ */ jsx57(Route, { path: "/tests/:testId", element: /* @__PURE__ */ jsx57(TestDetails, {}) }),
2358
- /* @__PURE__ */ jsx57(Route, { path: "/tests/:testId/run", element: /* @__PURE__ */ jsx57(TestDetailsRun, {}) }),
2359
- /* @__PURE__ */ jsx57(Route, { path: "/tests/:testId/lastRun", element: /* @__PURE__ */ jsx57(TestDetailsLastRun, {}) }),
2360
- /* @__PURE__ */ jsx57(Route, { path: "/tests/:testId/export", element: /* @__PURE__ */ jsx57(TestDetailsExport, {}) }),
2361
- /* @__PURE__ */ jsx57(Route, { path: "/tests/:testId/open", element: /* @__PURE__ */ jsx57(TestDetailsOpen, {}) }),
2362
- /* @__PURE__ */ jsx57(Route, { path: "/testruns", element: /* @__PURE__ */ jsx57(TestRunsMenu, {}) }),
2363
- /* @__PURE__ */ jsx57(Route, { path: "/testruns/list", element: /* @__PURE__ */ jsx57(TestRunsList2, {}) }),
2364
- /* @__PURE__ */ jsx57(Route, { path: "/testruns/:runId", element: /* @__PURE__ */ jsx57(TestRunDetails, {}) }),
2365
- /* @__PURE__ */ jsx57(Route, { path: "/testruns/:runId/debugArtifacts", element: /* @__PURE__ */ jsx57(TestRunDebugArtifacts, {}) }),
2366
- /* @__PURE__ */ jsx57(Route, { path: "/testruns/:runId/junitReport", element: /* @__PURE__ */ jsx57(TestRunJunitReport, {}) }),
2367
- /* @__PURE__ */ jsx57(Route, { path: "/testruns/:runId/open", element: /* @__PURE__ */ jsx57(TestRunOpen, {}) }),
2368
- /* @__PURE__ */ jsx57(Route, { path: "/suites", element: /* @__PURE__ */ jsx57(SuitesMenu, {}) }),
2369
- /* @__PURE__ */ jsx57(Route, { path: "/suites/list", element: /* @__PURE__ */ jsx57(SuitesList, {}) }),
2370
- /* @__PURE__ */ jsx57(Route, { path: "/suites/run", element: /* @__PURE__ */ jsx57(RunSuite, {}) }),
2371
- /* @__PURE__ */ jsx57(Route, { path: "/suites/:suiteId", element: /* @__PURE__ */ jsx57(SuiteDetails, {}) }),
2372
- /* @__PURE__ */ jsx57(Route, { path: "/suites/:suiteId/run", element: /* @__PURE__ */ jsx57(SuiteDetailsRun, {}) }),
2373
- /* @__PURE__ */ jsx57(Route, { path: "/suites/:suiteId/lastRun", element: /* @__PURE__ */ jsx57(SuiteDetailsLastRun, {}) }),
2374
- /* @__PURE__ */ jsx57(Route, { path: "/suites/:suiteId/open", element: /* @__PURE__ */ jsx57(SuiteDetailsOpen, {}) }),
2375
- /* @__PURE__ */ jsx57(Route, { path: "/suiteruns", element: /* @__PURE__ */ jsx57(SuiteRunsMenu, {}) }),
2376
- /* @__PURE__ */ jsx57(Route, { path: "/suiteruns/list", element: /* @__PURE__ */ jsx57(SuiteRunsList, {}) }),
2377
- /* @__PURE__ */ jsx57(Route, { path: "/suiteruns/:runId", element: /* @__PURE__ */ jsx57(SuiteRunDetails, {}) }),
2378
- /* @__PURE__ */ jsx57(Route, { path: "/suiteruns/:runId/showTestRuns", element: /* @__PURE__ */ jsx57(SuiteRunShowTestRuns, {}) }),
2379
- /* @__PURE__ */ jsx57(Route, { path: "/suiteruns/:runId/open", element: /* @__PURE__ */ jsx57(SuiteRunOpen, {}) }),
2380
- /* @__PURE__ */ jsx57(Route, { path: "/profiles", element: /* @__PURE__ */ jsx57(ProfilesMenu, {}) }),
2381
- /* @__PURE__ */ jsx57(Route, { path: "/profiles/list", element: /* @__PURE__ */ jsx57(ProfilesList, {}) }),
2382
- /* @__PURE__ */ jsx57(Route, { path: "/project", element: /* @__PURE__ */ jsx57(ProjectMenu, {}) }),
2383
- /* @__PURE__ */ jsx57(Route, { path: "/project/switch", element: /* @__PURE__ */ jsx57(ProjectSwitch, {}) }),
2384
- /* @__PURE__ */ jsx57(Route, { path: "/project/export", element: /* @__PURE__ */ jsx57(ProjectExport, {}) }),
2385
- /* @__PURE__ */ jsx57(Route, { path: "/project/import", element: /* @__PURE__ */ jsx57(ProjectImport, {}) }),
2386
- /* @__PURE__ */ jsx57(Route, { path: "/settings", element: /* @__PURE__ */ jsx57(SettingsMenu, {}) }),
2387
- /* @__PURE__ */ jsx57(Route, { path: "/settings/setSessionToken", element: /* @__PURE__ */ jsx57(SettingsSetSessionToken, {}) }),
2388
- /* @__PURE__ */ jsx57(Route, { path: "/logout", element: /* @__PURE__ */ jsx57(Logout, {}) })
3246
+ /* @__PURE__ */ jsxs40(Route, { element: /* @__PURE__ */ jsx71(Navigator, {}), children: [
3247
+ /* @__PURE__ */ jsx71(Route, { index: true, element: /* @__PURE__ */ jsx71(MainMenu, {}) }),
3248
+ /* @__PURE__ */ jsx71(Route, { path: "/init", element: /* @__PURE__ */ jsx71(ProjectInit, {}) }),
3249
+ /* @__PURE__ */ jsx71(Route, { path: "/tests", element: /* @__PURE__ */ jsx71(TestsMenu, {}) }),
3250
+ /* @__PURE__ */ jsx71(Route, { path: "/tests/list", element: /* @__PURE__ */ jsx71(TestsList, {}) }),
3251
+ /* @__PURE__ */ jsx71(Route, { path: "/tests/import", element: /* @__PURE__ */ jsx71(TestImport, {}) }),
3252
+ /* @__PURE__ */ jsx71(Route, { path: "/tests/run", element: /* @__PURE__ */ jsx71(RunTest, {}) }),
3253
+ /* @__PURE__ */ jsx71(Route, { path: "/tests/:testId", element: /* @__PURE__ */ jsx71(TestDetails, {}) }),
3254
+ /* @__PURE__ */ jsx71(Route, { path: "/tests/:testId/run", element: /* @__PURE__ */ jsx71(TestDetailsRun, {}) }),
3255
+ /* @__PURE__ */ jsx71(Route, { path: "/tests/:testId/lastRun", element: /* @__PURE__ */ jsx71(TestDetailsLastRun, {}) }),
3256
+ /* @__PURE__ */ jsx71(Route, { path: "/tests/:testId/export", element: /* @__PURE__ */ jsx71(TestDetailsExport, {}) }),
3257
+ /* @__PURE__ */ jsx71(Route, { path: "/tests/:testId/open", element: /* @__PURE__ */ jsx71(TestDetailsOpen, {}) }),
3258
+ /* @__PURE__ */ jsx71(Route, { path: "/testruns", element: /* @__PURE__ */ jsx71(TestRunsMenu, {}) }),
3259
+ /* @__PURE__ */ jsx71(Route, { path: "/testruns/list", element: /* @__PURE__ */ jsx71(TestRunsList2, {}) }),
3260
+ /* @__PURE__ */ jsx71(Route, { path: "/testruns/:runId", element: /* @__PURE__ */ jsx71(TestRunDetails, {}) }),
3261
+ /* @__PURE__ */ jsx71(Route, { path: "/testruns/:runId/debugArtifacts", element: /* @__PURE__ */ jsx71(TestRunDebugArtifacts, {}) }),
3262
+ /* @__PURE__ */ jsx71(Route, { path: "/testruns/:runId/junitReport", element: /* @__PURE__ */ jsx71(TestRunJunitReport, {}) }),
3263
+ /* @__PURE__ */ jsx71(Route, { path: "/testruns/:runId/open", element: /* @__PURE__ */ jsx71(TestRunOpen, {}) }),
3264
+ /* @__PURE__ */ jsx71(Route, { path: "/suites", element: /* @__PURE__ */ jsx71(SuitesMenu, {}) }),
3265
+ /* @__PURE__ */ jsx71(Route, { path: "/suites/list", element: /* @__PURE__ */ jsx71(SuitesList, {}) }),
3266
+ /* @__PURE__ */ jsx71(Route, { path: "/suites/run", element: /* @__PURE__ */ jsx71(RunSuite, {}) }),
3267
+ /* @__PURE__ */ jsx71(Route, { path: "/suites/:suiteId", element: /* @__PURE__ */ jsx71(SuiteDetails, {}) }),
3268
+ /* @__PURE__ */ jsx71(Route, { path: "/suites/:suiteId/run", element: /* @__PURE__ */ jsx71(SuiteDetailsRun, {}) }),
3269
+ /* @__PURE__ */ jsx71(Route, { path: "/suites/:suiteId/lastRun", element: /* @__PURE__ */ jsx71(SuiteDetailsLastRun, {}) }),
3270
+ /* @__PURE__ */ jsx71(Route, { path: "/suites/:suiteId/open", element: /* @__PURE__ */ jsx71(SuiteDetailsOpen, {}) }),
3271
+ /* @__PURE__ */ jsx71(Route, { path: "/suiteruns", element: /* @__PURE__ */ jsx71(SuiteRunsMenu, {}) }),
3272
+ /* @__PURE__ */ jsx71(Route, { path: "/suiteruns/list", element: /* @__PURE__ */ jsx71(SuiteRunsList, {}) }),
3273
+ /* @__PURE__ */ jsx71(Route, { path: "/suiteruns/:runId", element: /* @__PURE__ */ jsx71(SuiteRunDetails, {}) }),
3274
+ /* @__PURE__ */ jsx71(Route, { path: "/suiteruns/:runId/showTestRuns", element: /* @__PURE__ */ jsx71(SuiteRunShowTestRuns, {}) }),
3275
+ /* @__PURE__ */ jsx71(Route, { path: "/suiteruns/:runId/open", element: /* @__PURE__ */ jsx71(SuiteRunOpen, {}) }),
3276
+ /* @__PURE__ */ jsx71(Route, { path: "/profiles", element: /* @__PURE__ */ jsx71(ProfilesMenu, {}) }),
3277
+ /* @__PURE__ */ jsx71(Route, { path: "/profiles/list", element: /* @__PURE__ */ jsx71(ProfilesList, {}) }),
3278
+ /* @__PURE__ */ jsx71(Route, { path: "/project", element: /* @__PURE__ */ jsx71(ProjectMenu, {}) }),
3279
+ /* @__PURE__ */ jsx71(Route, { path: "/project/switch", element: /* @__PURE__ */ jsx71(ProjectSwitch, {}) }),
3280
+ /* @__PURE__ */ jsx71(Route, { path: "/project/export", element: /* @__PURE__ */ jsx71(ProjectExport, {}) }),
3281
+ /* @__PURE__ */ jsx71(Route, { path: "/project/import", element: /* @__PURE__ */ jsx71(ProjectImport, {}) }),
3282
+ /* @__PURE__ */ jsx71(Route, { path: "/settings", element: /* @__PURE__ */ jsx71(SettingsMenu, {}) }),
3283
+ /* @__PURE__ */ jsx71(Route, { path: "/settings/setSessionToken", element: /* @__PURE__ */ jsx71(SettingsSetSessionToken, {}) }),
3284
+ /* @__PURE__ */ jsx71(Route, { path: "/logout", element: /* @__PURE__ */ jsx71(Logout, {}) })
2389
3285
  ] })
2390
3286
  ),
2391
3287
  { initialEntries, initialIndex: initialEntries.length - 1 }
@@ -2394,12 +3290,12 @@ var createNavigatorRouter = ({
2394
3290
  };
2395
3291
 
2396
3292
  // src/app/NavigatorApp.tsx
2397
- import { jsx as jsx58 } from "react/jsx-runtime";
3293
+ import { jsx as jsx72 } from "react/jsx-runtime";
2398
3294
  var NavigatorApp = ({ initialRoute, initialRouteState }) => {
2399
- const [router] = useState17(() => createNavigatorRouter({ initialRoute, initialRouteState }));
2400
- return /* @__PURE__ */ jsx58(NavigatorSessionProvider, { children: /* @__PURE__ */ jsx58(RouterProvider, { router }) });
3295
+ const [router] = useState21(() => createNavigatorRouter({ initialRoute, initialRouteState }));
3296
+ return /* @__PURE__ */ jsx72(NavigatorSessionProvider, { children: /* @__PURE__ */ jsx72(RouterProvider, { router }) });
2401
3297
  };
2402
3298
  export {
2403
3299
  NavigatorApp
2404
3300
  };
2405
- //# sourceMappingURL=NavigatorApp-6ZB6F4RF.js.map
3301
+ //# sourceMappingURL=NavigatorApp-3SRWEK5J.js.map