@cueloop/client 0.1.0-alpha.66 → 0.1.0-alpha.68

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.
Files changed (117) hide show
  1. package/package.json +6 -5
  2. package/src/App.autoclose.test.tsx +2 -2
  3. package/src/App.diff.test.tsx +71 -39
  4. package/src/App.plan-review.test.tsx +20 -21
  5. package/src/App.readonly.test.tsx +7 -3
  6. package/src/App.test.tsx +73 -14
  7. package/src/App.tsx +375 -129
  8. package/src/App.walk.test.tsx +14 -15
  9. package/src/App.workbench.test.tsx +390 -0
  10. package/src/__snapshots__/view-plan.regression.test.ts.snap +1 -1
  11. package/src/annotation-palette.ts +61 -0
  12. package/src/app-screens.tsx +176 -45
  13. package/src/app-view-model.ts +7 -65
  14. package/src/components/AnnotationCard.tsx +1 -1
  15. package/src/components/AnnotationCards.stories.tsx +87 -0
  16. package/src/components/AnnotationCards.tsx +303 -0
  17. package/src/components/AppHeader.stories.tsx +50 -0
  18. package/src/components/AppHeader.tsx +83 -0
  19. package/src/components/AppShell.stories.tsx +47 -42
  20. package/src/components/AppShell.tsx +212 -100
  21. package/src/components/AppShell.zoom.test.tsx +94 -0
  22. package/src/components/ChangesColumn.tsx +49 -26
  23. package/src/components/DiffSheet.scroll.test.tsx +38 -55
  24. package/src/components/DiffSheet.split.test.tsx +140 -0
  25. package/src/components/DiffSheet.stories.tsx +55 -53
  26. package/src/components/DiffSheet.syntax.test.tsx +24 -7
  27. package/src/components/DiffSheet.tsx +607 -276
  28. package/src/components/DiscussionMarkerRail.stories.tsx +54 -0
  29. package/src/components/DiscussionMarkerRail.tsx +181 -0
  30. package/src/components/EditorGrid.stories.tsx +59 -0
  31. package/src/components/EditorGrid.tabs.test.tsx +105 -0
  32. package/src/components/EditorGrid.tsx +338 -0
  33. package/src/components/EditorGrid.zoom.test.tsx +68 -0
  34. package/src/components/FileContentsView.stories.tsx +16 -0
  35. package/src/components/FileContentsView.test.tsx +29 -0
  36. package/src/components/FileContentsView.tsx +78 -0
  37. package/src/components/InboxList.tsx +159 -30
  38. package/src/components/PaneGrid.stories.tsx +84 -0
  39. package/src/components/PaneGrid.tsx +128 -0
  40. package/src/components/PanelColumn.stories.tsx +25 -0
  41. package/src/components/PanelColumn.tsx +95 -0
  42. package/src/components/ProjectTreeView.stories.tsx +25 -0
  43. package/src/components/ProjectTreeView.test.tsx +32 -0
  44. package/src/components/ProjectTreeView.tsx +82 -0
  45. package/src/components/PromptDialog.tsx +8 -1
  46. package/src/components/RootOverlay.stories.tsx +44 -0
  47. package/src/components/RootOverlay.tsx +35 -0
  48. package/src/components/SettingsDialog.tsx +2 -1
  49. package/src/components/SurfaceScrollbar.stories.tsx +34 -0
  50. package/src/components/SurfaceScrollbar.test.tsx +111 -0
  51. package/src/components/SurfaceScrollbar.tsx +93 -0
  52. package/src/components/ThreadFooter.stories.tsx +2 -2
  53. package/src/components/ThreadFooter.test.tsx +31 -0
  54. package/src/components/ThreadFooter.tsx +12 -7
  55. package/src/components/ThreadView.tsx +62 -1440
  56. package/src/components/ThreadsSidebar.tsx +14 -1
  57. package/src/components/Tooltip.stories.tsx +26 -0
  58. package/src/components/Tooltip.tsx +72 -0
  59. package/src/components/WelcomeSurface.stories.tsx +12 -0
  60. package/src/components/WelcomeSurface.tsx +52 -0
  61. package/src/components/__snapshots__/stories.test.tsx.snap +509 -559
  62. package/src/components/diff-sheet-layout.test.ts +125 -55
  63. package/src/components/diff-sheet-layout.ts +3 -103
  64. package/src/components/editor-grid.test.ts +86 -0
  65. package/src/components/editor-grid.ts +138 -0
  66. package/src/components/fade-title.test.ts +49 -0
  67. package/src/components/fade-title.ts +61 -0
  68. package/src/components/file-tree.test.ts +15 -0
  69. package/src/components/file-tree.ts +59 -4
  70. package/src/components/pages/Workspace.stories.tsx +2 -2
  71. package/src/components/primitives/IconButton.tsx +21 -2
  72. package/src/components/primitives/Tree.tsx +13 -4
  73. package/src/components/primitives/icons.ts +27 -4
  74. package/src/components/session-tree.test.ts +20 -0
  75. package/src/components/session-tree.ts +16 -2
  76. package/src/components/stories-app.tsx +2 -2
  77. package/src/config.test.ts +20 -49
  78. package/src/config.ts +26 -28
  79. package/src/diff-fold.test.ts +78 -0
  80. package/src/diff-fold.ts +126 -0
  81. package/src/diff-syntax.test.ts +16 -0
  82. package/src/diff-syntax.ts +6 -3
  83. package/src/discussions.ts +79 -0
  84. package/src/ghostty-terminal.test.ts +2 -1
  85. package/src/ghostty-terminal.ts +27 -4
  86. package/src/intent-dispatch.test.ts +31 -11
  87. package/src/intent-dispatch.ts +93 -48
  88. package/src/key-bindings.test.ts +1 -1
  89. package/src/keymap.test.ts +3 -25
  90. package/src/keymap.ts +17 -18
  91. package/src/mark-runs.ts +120 -0
  92. package/src/pty.ts +10 -2
  93. package/src/run.ts +17 -7
  94. package/src/serve.test.ts +4 -8
  95. package/src/session-controller.curate.test.ts +75 -0
  96. package/src/session-controller.share.test.ts +1 -0
  97. package/src/session-controller.tree.test.ts +26 -0
  98. package/src/session-controller.ts +153 -29
  99. package/src/slash-palette.ts +83 -0
  100. package/src/split-diff.test.ts +110 -0
  101. package/src/split-diff.ts +149 -0
  102. package/src/test-support.test.ts +15 -3
  103. package/src/test-support.ts +66 -15
  104. package/src/thread-chords.test.ts +25 -9
  105. package/src/thread-chords.ts +33 -8
  106. package/src/use-annotation-surface.tsx +837 -0
  107. package/src/use-changes-workbench.ts +151 -0
  108. package/src/use-frame-measure.ts +38 -0
  109. package/src/use-settings-dialog.tsx +14 -24
  110. package/src/use-terminal-virtualizer.ts +233 -0
  111. package/src/view-diff.ts +114 -0
  112. package/src/components/ReviewPanel.stories.tsx +0 -100
  113. package/src/components/ReviewPanel.tsx +0 -103
  114. package/src/components/ReviewRail.stories.tsx +0 -232
  115. package/src/components/ReviewRail.tsx +0 -327
  116. package/src/review-panel.test.ts +0 -113
  117. package/src/review-panel.ts +0 -83
@@ -13,9 +13,15 @@ export interface ThreadsSidebarProps {
13
13
  cursor: number;
14
14
  /** The open thread's id, highlighted in the list. */
15
15
  activeId?: string;
16
+ /** Ids of pinned threads. */
17
+ pinnedIds?: ReadonlySet<string>;
16
18
  onSelect: (sessionId: string) => void;
17
- /** Ask to delete a thread (the selected row's [delete] button). */
19
+ /** Ask to delete a thread (the row menu's Delete, wired to the confirm dialog). */
18
20
  onRequestDelete?: (id: string, title: string) => void;
21
+ /** Toggle a thread's pinned state (the row menu's Pin/Unpin). */
22
+ onPin?: (id: string) => void;
23
+ /** Rename a thread's title (the row menu's Rename). */
24
+ onRename?: (id: string, title: string) => void;
19
25
  width?: number;
20
26
  theme?: Theme;
21
27
  }
@@ -25,8 +31,11 @@ export function ThreadsSidebar({
25
31
  rows,
26
32
  cursor,
27
33
  activeId,
34
+ pinnedIds,
28
35
  onSelect,
29
36
  onRequestDelete,
37
+ onPin,
38
+ onRename,
30
39
  width = 30,
31
40
  theme,
32
41
  }: ThreadsSidebarProps): React.ReactNode {
@@ -47,8 +56,12 @@ export function ThreadsSidebar({
47
56
  rows={rows}
48
57
  cursor={cursor}
49
58
  activeId={activeId}
59
+ pinnedIds={pinnedIds}
60
+ width={width}
50
61
  onSelect={onSelect}
51
62
  onRequestDelete={onRequestDelete}
63
+ onPin={onPin}
64
+ onRename={onRename}
52
65
  theme={theme}
53
66
  />
54
67
  </scrollbox>
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import { DARK } from "../theme";
3
+ import type { Story, StoryMeta } from "./story";
4
+ import { TooltipProvider } from "./Tooltip";
5
+ import { IconButton } from "./primitives/IconButton";
6
+ import { NERD } from "./primitives/icons";
7
+
8
+ export const meta: StoryMeta = { title: "Layout/Tooltip" };
9
+
10
+ // The tooltip surfaces only on hover, so a static story shows the provider wrapping a labelled control.
11
+ export const HoverControl: Story = {
12
+ render: () => (
13
+ <TooltipProvider theme={DARK}>
14
+ <box style={{ flexDirection: "row", padding: 1, backgroundColor: DARK.panel }}>
15
+ <IconButton
16
+ glyph={NERD.sidebarRight}
17
+ tip="Toggle Right Sidebar"
18
+ onPress={() => {}}
19
+ theme={DARK}
20
+ />
21
+ </box>
22
+ </TooltipProvider>
23
+ ),
24
+ expectedColors: [DARK.textMuted],
25
+ size: { width: 40, height: 4 },
26
+ };
@@ -0,0 +1,72 @@
1
+ // Hover tooltips for the header controls. A tiny header cell clips its own children, so the label is
2
+ // surfaced at the screen root instead: controls report the hovered label and cursor cell, and this layer
3
+ // paints it one row below, nudged left when it would run past the right edge.
4
+
5
+ import React, { createContext, useContext, useMemo, useState } from "react";
6
+ import { useTerminalDimensions } from "@opentui/react";
7
+ import { DARK, type Theme } from "../theme";
8
+
9
+ interface TooltipTarget {
10
+ label: string;
11
+ x: number;
12
+ y: number;
13
+ }
14
+
15
+ interface TooltipApi {
16
+ showTooltip: (label: string, x: number, y: number) => void;
17
+ hideTooltip: () => void;
18
+ }
19
+
20
+ const TooltipContext = createContext<TooltipApi>({
21
+ showTooltip: () => {},
22
+ hideTooltip: () => {},
23
+ });
24
+
25
+ /** Report or clear the hovered control's tooltip; a no-op outside a TooltipProvider. */
26
+ export function useTooltip(): TooltipApi {
27
+ return useContext(TooltipContext);
28
+ }
29
+
30
+ /** Wrap a shell so its header controls can surface hover tooltips at the screen root. */
31
+ export function TooltipProvider({
32
+ theme,
33
+ children,
34
+ }: {
35
+ theme?: Theme;
36
+ children: React.ReactNode;
37
+ }): React.ReactNode {
38
+ const tokens = theme ?? DARK;
39
+ const { width, height } = useTerminalDimensions();
40
+ const [target, setTarget] = useState<TooltipTarget | null>(null);
41
+ const api = useMemo<TooltipApi>(
42
+ () => ({
43
+ showTooltip: (label, x, y) => setTarget({ label, x, y }),
44
+ hideTooltip: () => setTarget(null),
45
+ }),
46
+ [],
47
+ );
48
+
49
+ const boxWidth = target ? target.label.length + 2 : 0;
50
+ const left = target ? Math.max(0, Math.min(target.x, width - boxWidth)) : 0;
51
+ const top = target ? (target.y + 1 <= height - 1 ? target.y + 1 : Math.max(0, target.y - 1)) : 0;
52
+
53
+ return (
54
+ <TooltipContext.Provider value={api}>
55
+ {children}
56
+ {target ? (
57
+ <box
58
+ style={{
59
+ position: "absolute",
60
+ left,
61
+ top,
62
+ paddingLeft: 1,
63
+ paddingRight: 1,
64
+ backgroundColor: tokens.elevated,
65
+ }}
66
+ >
67
+ <text fg={tokens.text}>{target.label}</text>
68
+ </box>
69
+ ) : null}
70
+ </TooltipContext.Provider>
71
+ );
72
+ }
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ import { DARK } from "../theme";
3
+ import type { Story, StoryMeta } from "./story";
4
+ import { WelcomeSurface } from "./WelcomeSurface";
5
+
6
+ export const meta: StoryMeta = { title: "Surfaces/WelcomeSurface" };
7
+
8
+ export const Welcome: Story = {
9
+ render: () => <WelcomeSurface version="0.1.0-alpha.66" theme={DARK} />,
10
+ expectedColors: [DARK.accent],
11
+ size: { width: 60, height: 16 },
12
+ };
@@ -0,0 +1,52 @@
1
+ // The Welcome body: the disposable default tab's contents in the Changes panel,
2
+ // shown when nothing else is open. Points at where to start, the docs, and what
3
+ // shipped in this build. The tab chrome (label + close) lives in the panel header.
4
+
5
+ import React from "react";
6
+ import type { Theme } from "../theme";
7
+
8
+ const DOCS_URL = "www.cueloop.dev";
9
+
10
+ export interface WelcomeSurfaceProps {
11
+ version: string;
12
+ theme?: Theme;
13
+ }
14
+
15
+ function Section({
16
+ title,
17
+ children,
18
+ theme,
19
+ }: {
20
+ title: string;
21
+ children: React.ReactNode;
22
+ theme?: Theme;
23
+ }): React.ReactNode {
24
+ return (
25
+ <box style={{ flexDirection: "column", flexShrink: 0, marginTop: 1 }}>
26
+ <text fg={theme?.text}>{title}</text>
27
+ {children}
28
+ </box>
29
+ );
30
+ }
31
+
32
+ export function WelcomeSurface({ version, theme }: WelcomeSurfaceProps): React.ReactNode {
33
+ return (
34
+ <box
35
+ style={{ flexDirection: "column", flexGrow: 1, flexShrink: 0, paddingLeft: 2, paddingTop: 1 }}
36
+ >
37
+ <text fg={theme?.accent}>Welcome to cueloop</text>
38
+ <text fg={theme?.textDim}>a review loop for coding agents</text>
39
+ <Section title="Start" theme={theme}>
40
+ <text fg={theme?.textDim}>· select a thread on the left</text>
41
+ <text fg={theme?.textDim}>· or run cueloop plan / cueloop diff from a repo</text>
42
+ </Section>
43
+ <Section title="Learn" theme={theme}>
44
+ <text fg={theme?.textDim}>{`· docs ${DOCS_URL}`}</text>
45
+ <text fg={theme?.textDim}>{`· changelog ${DOCS_URL}/changelog`}</text>
46
+ </Section>
47
+ <Section title="What's new" theme={theme}>
48
+ <text fg={theme?.textDim}>{`· cueloop v${version}`}</text>
49
+ </Section>
50
+ </box>
51
+ );
52
+ }