@workerdeck/ui 0.22.0 → 1.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.
- package/build/{SessionPanel-DgwjH4Ve.mjs → SessionPanel-DDgBkHsi.mjs} +2196 -3364
- package/build/SessionPanel-DDgBkHsi.mjs.map +1 -0
- package/build/SessionPanel-E_L_ldQ5.d.mts +207 -0
- package/build/format-B8ZM9LPy.d.mts +16 -0
- package/build/format.d.mts +8 -75
- package/build/format.mjs +2 -2
- package/build/index.d.mts +63 -1138
- package/build/index.mjs +4 -300
- package/build/index.mjs.map +1 -1
- package/build/scoped.css +80 -24
- package/build/{status-BE-zg88x.mjs → status-C0HSLZas.mjs} +14 -85
- package/build/status-C0HSLZas.mjs.map +1 -0
- package/build/workspace.d.mts +9 -124
- package/build/workspace.mjs +13 -143
- package/build/workspace.mjs.map +1 -1
- package/package.json +4 -4
- package/src/components/agent/CodeEditor.tsx +31 -103
- package/src/components/agent/Composer.tsx +114 -333
- package/src/components/agent/ContextDialog.tsx +20 -41
- package/src/components/agent/ContextRing.tsx +6 -28
- package/src/components/agent/Conversation.tsx +21 -33
- package/src/components/agent/EditorTabs.tsx +39 -67
- package/src/components/agent/EngineIcon.tsx +29 -72
- package/src/components/agent/EntryIcon.tsx +16 -0
- package/src/components/agent/FileCard.tsx +10 -16
- package/src/components/agent/FileTree.tsx +52 -125
- package/src/components/agent/FileViewer.tsx +30 -60
- package/src/components/agent/HostFilesDialog.tsx +40 -69
- package/src/components/agent/Loader.tsx +3 -24
- package/src/components/agent/McpDialog.tsx +64 -137
- package/src/components/agent/Message.tsx +2 -21
- package/src/components/agent/ModelSelect.tsx +33 -62
- package/src/components/agent/PermissionModeSelect.tsx +21 -79
- package/src/components/agent/PermissionPrompt.tsx +59 -63
- package/src/components/agent/ProjectIcon.tsx +228 -93
- package/src/components/agent/PromptTokenText.tsx +10 -16
- package/src/components/agent/QuestionPrompt.tsx +43 -64
- package/src/components/agent/Reasoning.tsx +13 -16
- package/src/components/agent/Response.tsx +4 -6
- package/src/components/agent/Scrubber.tsx +31 -80
- package/src/components/agent/SessionBrowser.tsx +64 -243
- package/src/components/agent/SessionEmptyState.tsx +10 -40
- package/src/components/agent/SessionInfoDialog.tsx +46 -78
- package/src/components/agent/SessionItem.tsx +53 -320
- package/src/components/agent/SessionList.tsx +23 -39
- package/src/components/agent/SessionPanel.tsx +345 -923
- package/src/components/agent/SessionStatusIcon.tsx +14 -28
- package/src/components/agent/SessionSteps.tsx +34 -187
- package/src/components/agent/SessionWorkspace.tsx +108 -215
- package/src/components/agent/SkillsDialog.tsx +35 -80
- package/src/components/agent/StatusBar.tsx +51 -136
- package/src/components/agent/SubagentStrip.tsx +12 -77
- package/src/components/agent/ToolCallCard.tsx +94 -135
- package/src/components/agent/Transcript.tsx +103 -1288
- package/src/components/agent/TranscriptItemView.tsx +155 -0
- package/src/components/agent/TranscriptRows.tsx +418 -0
- package/src/components/agent/UsageDialog.tsx +7 -29
- package/src/components/agent/UsageMeters.tsx +18 -73
- package/src/components/agent/pulse.tsx +9 -32
- package/src/components/agent/scrubber-marks.ts +33 -103
- package/src/components/agent/status.ts +1 -5
- package/src/components/agent/tool-result-fetch.tsx +3 -25
- package/src/components/agent/tool-result-image.tsx +32 -111
- package/src/components/agent/transcript-rows.ts +41 -118
- package/src/components/agent/transcript-variant.tsx +3 -80
- package/src/components/agent/use-height-epoch.ts +10 -24
- package/src/components/agent/use-path-links.ts +45 -63
- package/src/components/agent/use-subagent-frame.ts +106 -0
- package/src/components/agent/use-transcript-jumps.ts +49 -107
- package/src/components/prompt-area/animated-placeholder.tsx +6 -5
- package/src/components/prompt-area/clipboard-helpers.ts +26 -21
- package/src/components/prompt-area/cursor-helpers.ts +79 -37
- package/src/components/prompt-area/dom-helpers.ts +97 -69
- package/src/components/prompt-area/file-strip.tsx +90 -80
- package/src/components/prompt-area/html-to-markdown.ts +67 -46
- package/src/components/prompt-area/image-strip.tsx +8 -18
- package/src/components/prompt-area/index.ts +2 -15
- package/src/components/prompt-area/prompt-area-engine.ts +100 -115
- package/src/components/prompt-area/prompt-area-list-ops.ts +66 -59
- package/src/components/prompt-area/prompt-area.tsx +31 -38
- package/src/components/prompt-area/remove-button.tsx +3 -9
- package/src/components/prompt-area/segment-helpers.ts +4 -12
- package/src/components/prompt-area/trigger-popover.tsx +15 -27
- package/src/components/prompt-area/trigger-presets.ts +0 -10
- package/src/components/prompt-area/types.ts +3 -8
- package/src/components/prompt-area/use-chip-editing.ts +305 -0
- package/src/components/prompt-area/use-markdown-mode.ts +7 -17
- package/src/components/prompt-area/use-prompt-area-events.ts +80 -86
- package/src/components/prompt-area/use-prompt-area-keydown.ts +598 -0
- package/src/components/prompt-area/use-prompt-area-state.ts +5 -23
- package/src/components/prompt-area/use-prompt-area.ts +170 -896
- package/src/components/prompt-area/use-trigger-search.ts +21 -19
- package/src/components/terminal/PermissionPrompt.tsx +56 -59
- package/src/components/terminal/QuestionPrompt.tsx +28 -79
- package/src/components/terminal/StatusLine.tsx +13 -63
- package/src/components/terminal/TerminalTranscript.tsx +44 -160
- package/src/components/terminal/affordances.tsx +68 -98
- package/src/components/terminal/blocks.ts +20 -156
- package/src/components/terminal/diff.tsx +19 -67
- package/src/components/terminal/height.ts +163 -313
- package/src/components/terminal/image-box.ts +0 -44
- package/src/components/terminal/items.tsx +150 -305
- package/src/components/terminal/markdown.tsx +36 -95
- package/src/components/terminal/press.tsx +26 -53
- package/src/components/terminal/prompt.tsx +40 -170
- package/src/components/terminal/result-preview.ts +8 -56
- package/src/components/terminal/row.tsx +11 -98
- package/src/components/terminal/scrubber.tsx +108 -401
- package/src/components/terminal/surface.tsx +6 -54
- package/src/components/terminal/todos.ts +66 -0
- package/src/components/terminal/tool-run.ts +21 -192
- package/src/components/ui/AlertDialog.tsx +8 -23
- package/src/components/ui/Badge.tsx +18 -29
- package/src/components/ui/Button.tsx +7 -15
- package/src/components/ui/Card.tsx +2 -13
- package/src/components/ui/CodeBlock.tsx +10 -37
- package/src/components/ui/CopyButton.tsx +10 -23
- package/src/components/ui/Dialog.tsx +23 -36
- package/src/components/ui/Empty.tsx +6 -29
- package/src/components/ui/Input.tsx +14 -16
- package/src/components/ui/Menu.tsx +6 -18
- package/src/components/ui/PortalScope.tsx +1 -21
- package/src/components/ui/ProgressRing.tsx +8 -19
- package/src/components/ui/Select.tsx +18 -31
- package/src/components/ui/Sonner.tsx +1 -2
- package/src/components/ui/Spinner.tsx +1 -1
- package/src/components/ui/Splitter.tsx +30 -64
- package/src/components/ui/Textarea.tsx +2 -5
- package/src/components/ui/Tooltip.tsx +3 -13
- package/src/format.ts +0 -9
- package/src/index.ts +16 -113
- package/src/lib/clipboard.ts +8 -28
- package/src/lib/css.ts +8 -0
- package/src/lib/format.ts +101 -86
- package/src/lib/plan-request.ts +16 -0
- package/src/lib/status.ts +45 -95
- package/src/lib/tool-icon.ts +39 -47
- package/src/lib/utils.ts +1 -3
- package/src/styles/terminal.css +81 -49
- package/src/styles/theme.css +136 -19
- package/src/workspace.ts +1 -24
- package/build/SessionPanel-13l25ubU.d.mts +0 -609
- package/build/SessionPanel-DgwjH4Ve.mjs.map +0 -1
- package/build/format-ljc3lKpA.d.mts +0 -59
- package/build/status-BE-zg88x.mjs.map +0 -1
|
@@ -1,56 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useCallback,
|
|
3
|
-
useRef,
|
|
4
|
-
type KeyboardEvent as ReactKeyboardEvent,
|
|
5
|
-
type PointerEvent as ReactPointerEvent,
|
|
6
|
-
} from 'react'
|
|
1
|
+
import { useCallback, useRef, type KeyboardEvent as ReactKeyboardEvent, type PointerEvent as ReactPointerEvent } from 'react'
|
|
7
2
|
import { cn } from '../../lib/utils.ts'
|
|
8
3
|
|
|
9
4
|
export interface SplitterProps {
|
|
10
|
-
/**
|
|
11
|
-
* ARIA's sense of the word: a `vertical` splitter is a vertical bar between
|
|
12
|
-
* two side-by-side panes, and it resizes a **width**. A `horizontal` one sits
|
|
13
|
-
* between stacked panes and resizes a **height**.
|
|
14
|
-
*/
|
|
15
5
|
orientation: 'vertical' | 'horizontal'
|
|
16
|
-
/** Current size of the pane this splitter controls, in pixels. */
|
|
17
6
|
value: number
|
|
18
7
|
onValueChange: (value: number) => void
|
|
19
8
|
min: number
|
|
20
9
|
max: number
|
|
21
|
-
/** Keyboard step. */
|
|
22
10
|
step?: number
|
|
23
|
-
/**
|
|
24
|
-
* Size to snap back to on a double-click — the convention every pane divider
|
|
25
|
-
* that can be dragged is expected to honour. Omit and a double-click does
|
|
26
|
-
* nothing, which is the honest behaviour when there is no default to mean.
|
|
27
|
-
*/
|
|
28
11
|
defaultValue?: number
|
|
29
|
-
/** Set when dragging the splitter *away* from the origin should shrink the
|
|
30
|
-
* controlled pane — i.e. the pane is on the right or the bottom. */
|
|
31
12
|
inverted?: boolean
|
|
32
|
-
/** Required: "Resize" alone does not say which of two splitters this is. */
|
|
33
13
|
'aria-label': string
|
|
34
14
|
className?: string
|
|
35
15
|
}
|
|
36
16
|
|
|
37
|
-
/**
|
|
38
|
-
* A draggable pane divider.
|
|
39
|
-
*
|
|
40
|
-
* Hand-rolled rather than depended on: `@base-ui/react` ships no splitter, the
|
|
41
|
-
* behaviour is a hundred lines of pointer events, and this repo's instinct at
|
|
42
|
-
* this layer is to own it (the composer is vendored for the same reason).
|
|
43
|
-
*
|
|
44
|
-
* Pointer capture is what makes it survive a fast drag — without it the pointer
|
|
45
|
-
* leaves the 5px bar within a frame and the moves go to whatever is underneath,
|
|
46
|
-
* which for this layout is an iframe-free but still selection-happy code pane.
|
|
47
|
-
* The drag origin is captured on pointerdown and every move is measured against
|
|
48
|
-
* it, so the pane cannot drift relative to the cursor over a long drag the way
|
|
49
|
-
* per-move deltas do once clamping is involved.
|
|
50
|
-
*
|
|
51
|
-
* Keyboard-operable and announced as a separator, because a pane you can only
|
|
52
|
-
* size by dragging is a pane some people cannot size.
|
|
53
|
-
*/
|
|
54
17
|
export function Splitter({
|
|
55
18
|
orientation,
|
|
56
19
|
value,
|
|
@@ -69,8 +32,9 @@ export function Splitter({
|
|
|
69
32
|
const clamp = useCallback((next: number) => Math.min(max, Math.max(min, next)), [min, max])
|
|
70
33
|
|
|
71
34
|
const onPointerDown = (event: ReactPointerEvent<HTMLDivElement>) => {
|
|
72
|
-
|
|
73
|
-
|
|
35
|
+
if (event.button !== 0) {
|
|
36
|
+
return
|
|
37
|
+
}
|
|
74
38
|
event.preventDefault()
|
|
75
39
|
event.currentTarget.setPointerCapture(event.pointerId)
|
|
76
40
|
drag.current = { origin: vertical ? event.clientX : event.clientY, start: value }
|
|
@@ -78,43 +42,52 @@ export function Splitter({
|
|
|
78
42
|
|
|
79
43
|
const onPointerMove = (event: ReactPointerEvent<HTMLDivElement>) => {
|
|
80
44
|
const state = drag.current
|
|
81
|
-
if (!state)
|
|
45
|
+
if (!state) {
|
|
46
|
+
return
|
|
47
|
+
}
|
|
82
48
|
const delta = (vertical ? event.clientX : event.clientY) - state.origin
|
|
83
49
|
onValueChange(clamp(state.start + (inverted ? -delta : delta)))
|
|
84
50
|
}
|
|
85
51
|
|
|
86
52
|
const endDrag = (event: ReactPointerEvent<HTMLDivElement>) => {
|
|
87
|
-
if (!drag.current)
|
|
53
|
+
if (!drag.current) {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
88
56
|
drag.current = null
|
|
89
57
|
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
90
58
|
event.currentTarget.releasePointerCapture(event.pointerId)
|
|
91
59
|
}
|
|
92
60
|
}
|
|
93
61
|
|
|
94
|
-
//
|
|
95
|
-
// has to land after `endDrag` — which it does: dblclick fires after pointerup.
|
|
62
|
+
// Reached after `endDrag` — the second click of a double-click has already started a drag, and dblclick fires after pointerup.
|
|
96
63
|
const onDoubleClick = () => {
|
|
97
|
-
if (defaultValue !== undefined)
|
|
64
|
+
if (defaultValue !== undefined) {
|
|
65
|
+
onValueChange(clamp(defaultValue))
|
|
66
|
+
}
|
|
98
67
|
}
|
|
99
68
|
|
|
100
69
|
const onKeyDown = (event: ReactKeyboardEvent<HTMLDivElement>) => {
|
|
101
|
-
// The arrows that move *along* this splitter's axis of travel; the other
|
|
102
|
-
// pair is left to the page, which is what a separator should do with them.
|
|
103
70
|
const grow = vertical ? 'ArrowRight' : 'ArrowDown'
|
|
104
71
|
const shrink = vertical ? 'ArrowLeft' : 'ArrowUp'
|
|
105
72
|
const direction = inverted ? -1 : 1
|
|
106
|
-
if (event.key === grow)
|
|
107
|
-
|
|
108
|
-
else if (event.key ===
|
|
109
|
-
|
|
110
|
-
else
|
|
73
|
+
if (event.key === grow) {
|
|
74
|
+
onValueChange(clamp(value + step * direction))
|
|
75
|
+
} else if (event.key === shrink) {
|
|
76
|
+
onValueChange(clamp(value - step * direction))
|
|
77
|
+
} else if (event.key === 'Home') {
|
|
78
|
+
onValueChange(min)
|
|
79
|
+
} else if (event.key === 'End') {
|
|
80
|
+
onValueChange(max)
|
|
81
|
+
} else {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
111
84
|
event.preventDefault()
|
|
112
85
|
}
|
|
113
86
|
|
|
114
87
|
return (
|
|
115
88
|
<div
|
|
116
|
-
data-slot=
|
|
117
|
-
role=
|
|
89
|
+
data-slot="splitter"
|
|
90
|
+
role="separator"
|
|
118
91
|
tabIndex={0}
|
|
119
92
|
aria-label={label}
|
|
120
93
|
aria-orientation={orientation}
|
|
@@ -128,20 +101,13 @@ export function Splitter({
|
|
|
128
101
|
onDoubleClick={onDoubleClick}
|
|
129
102
|
onKeyDown={onKeyDown}
|
|
130
103
|
className={cn(
|
|
131
|
-
// A 1px line that reads as a border, with a larger invisible grab area
|
|
132
|
-
// around it — a hairline is an honest divider and a cruel target.
|
|
133
104
|
'group relative shrink-0 touch-none bg-border transition-colors',
|
|
134
105
|
'hover:bg-border-strong focus-visible:bg-accent focus-visible:outline-none',
|
|
135
106
|
vertical ? 'w-px cursor-col-resize' : 'h-px cursor-row-resize',
|
|
136
107
|
className,
|
|
137
|
-
)}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
className={cn(
|
|
141
|
-
'absolute',
|
|
142
|
-
vertical ? '-inset-x-[3px] inset-y-0' : '-inset-y-[3px] inset-x-0',
|
|
143
|
-
)}
|
|
144
|
-
/>
|
|
108
|
+
)}
|
|
109
|
+
>
|
|
110
|
+
<span aria-hidden className={cn('absolute', vertical ? '-inset-x-[3px] inset-y-0' : '-inset-y-[3px] inset-x-0')} />
|
|
145
111
|
</div>
|
|
146
112
|
)
|
|
147
113
|
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import { type TextareaHTMLAttributes, forwardRef } from 'react'
|
|
2
2
|
import { cn } from '../../lib/utils.ts'
|
|
3
3
|
|
|
4
|
-
export const Textarea = forwardRef<
|
|
5
|
-
HTMLTextAreaElement,
|
|
6
|
-
TextareaHTMLAttributes<HTMLTextAreaElement>
|
|
7
|
-
>(({ className, ...props }, ref) => (
|
|
4
|
+
export const Textarea = forwardRef<HTMLTextAreaElement, TextareaHTMLAttributes<HTMLTextAreaElement>>(({ className, ...props }, ref) => (
|
|
8
5
|
<textarea
|
|
9
6
|
ref={ref}
|
|
10
|
-
data-slot=
|
|
7
|
+
data-slot="textarea"
|
|
11
8
|
className={cn(
|
|
12
9
|
'w-full resize-none rounded-md border border-border bg-bg px-2.5 py-2 text-body-sm text-text',
|
|
13
10
|
'placeholder:text-fg-4 transition-colors outline-none',
|
|
@@ -10,9 +10,9 @@ export const TooltipContent: FunctionComponent<
|
|
|
10
10
|
> = ({ className, side = 'top', sideOffset = 6, ...props }) => (
|
|
11
11
|
<TooltipPrimitive.Portal>
|
|
12
12
|
<PortalScope>
|
|
13
|
-
<TooltipPrimitive.Positioner side={side} sideOffset={sideOffset} className=
|
|
13
|
+
<TooltipPrimitive.Positioner side={side} sideOffset={sideOffset} className="isolate z-90">
|
|
14
14
|
<TooltipPrimitive.Popup
|
|
15
|
-
data-slot=
|
|
15
|
+
data-slot="tooltip-content"
|
|
16
16
|
className={cn(
|
|
17
17
|
'rounded-md border border-border bg-surface px-2 py-1 text-label text-fg-2 shadow-(--shadow-md) outline-none',
|
|
18
18
|
className,
|
|
@@ -24,14 +24,6 @@ export const TooltipContent: FunctionComponent<
|
|
|
24
24
|
</TooltipPrimitive.Portal>
|
|
25
25
|
)
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
* Convenience wrapper: `<Tip content="..."><Button/></Tip>`.
|
|
29
|
-
*
|
|
30
|
-
* Pass `render` when the trigger must *be* an element you already have — a tab, a
|
|
31
|
-
* row — rather than something wrapped in a span. The default span is fine beside
|
|
32
|
-
* a button but would break any layout that styles its own children (a flex tab
|
|
33
|
-
* strip gets an extra box between the container and its items).
|
|
34
|
-
*/
|
|
35
27
|
export function Tip({
|
|
36
28
|
content,
|
|
37
29
|
render,
|
|
@@ -45,9 +37,7 @@ export function Tip({
|
|
|
45
37
|
}) {
|
|
46
38
|
return (
|
|
47
39
|
<TooltipPrimitive.Root>
|
|
48
|
-
<TooltipPrimitive.Trigger render={render ?? <span className=
|
|
49
|
-
{children}
|
|
50
|
-
</TooltipPrimitive.Trigger>
|
|
40
|
+
<TooltipPrimitive.Trigger render={render ?? <span className="inline-flex" />}>{children}</TooltipPrimitive.Trigger>
|
|
51
41
|
<TooltipContent side={side}>{content}</TooltipContent>
|
|
52
42
|
</TooltipPrimitive.Root>
|
|
53
43
|
)
|
package/src/format.ts
CHANGED
|
@@ -1,11 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The formatting helpers, on their own entry point.
|
|
3
|
-
*
|
|
4
|
-
* `src/index.ts` pulls in React and every component with it; a host that renders
|
|
5
|
-
* session readings *outside* React — the VS Code extension host drawing them in
|
|
6
|
-
* the window status bar, say — needs the numbers spelled the same way without
|
|
7
|
-
* paying for that. These functions are pure and dependency-free, so the subpath
|
|
8
|
-
* costs nothing and keeps one truth for what "45.2k" and "2h 10m" mean.
|
|
9
|
-
*/
|
|
10
1
|
export * from './lib/format.ts'
|
|
11
2
|
export * from './lib/status.ts'
|
package/src/index.ts
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
// Primitives
|
|
2
1
|
export { Button, buttonVariants, type ButtonProps } from './components/ui/Button.tsx'
|
|
3
2
|
export { Badge, badgeVariants, type BadgeProps } from './components/ui/Badge.tsx'
|
|
4
3
|
export { Card, CardContent, CardHeader, CardTitle } from './components/ui/Card.tsx'
|
|
5
4
|
export { Input } from './components/ui/Input.tsx'
|
|
6
5
|
export { Textarea } from './components/ui/Textarea.tsx'
|
|
7
|
-
export {
|
|
8
|
-
Select,
|
|
9
|
-
SelectContent,
|
|
10
|
-
SelectItem,
|
|
11
|
-
SelectItemText,
|
|
12
|
-
SelectTrigger,
|
|
13
|
-
SelectValue,
|
|
14
|
-
} from './components/ui/Select.tsx'
|
|
6
|
+
export { Select, SelectContent, SelectItem, SelectItemText, SelectTrigger, SelectValue } from './components/ui/Select.tsx'
|
|
15
7
|
export {
|
|
16
8
|
AlertDialog,
|
|
17
9
|
AlertDialogClose,
|
|
@@ -20,22 +12,8 @@ export {
|
|
|
20
12
|
AlertDialogTitle,
|
|
21
13
|
AlertDialogTrigger,
|
|
22
14
|
} from './components/ui/AlertDialog.tsx'
|
|
23
|
-
export {
|
|
24
|
-
|
|
25
|
-
MenuContent,
|
|
26
|
-
MenuItem,
|
|
27
|
-
MenuSeparator,
|
|
28
|
-
MenuTrigger,
|
|
29
|
-
} from './components/ui/Menu.tsx'
|
|
30
|
-
export {
|
|
31
|
-
Dialog,
|
|
32
|
-
DialogBody,
|
|
33
|
-
DialogClose,
|
|
34
|
-
DialogContent,
|
|
35
|
-
DialogHeader,
|
|
36
|
-
DialogRow,
|
|
37
|
-
DialogTrigger,
|
|
38
|
-
} from './components/ui/Dialog.tsx'
|
|
15
|
+
export { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger } from './components/ui/Menu.tsx'
|
|
16
|
+
export { Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogRow, DialogTrigger } from './components/ui/Dialog.tsx'
|
|
39
17
|
export { Tip, TooltipContent, TooltipProvider } from './components/ui/Tooltip.tsx'
|
|
40
18
|
export { Toaster, toast } from './components/ui/Sonner.tsx'
|
|
41
19
|
export { CopyButton, type CopyButtonProps } from './components/ui/CopyButton.tsx'
|
|
@@ -44,7 +22,6 @@ export { CodeBlock, type CodeBlockProps } from './components/ui/CodeBlock.tsx'
|
|
|
44
22
|
export { Splitter, type SplitterProps } from './components/ui/Splitter.tsx'
|
|
45
23
|
export { Empty, EmptyKey } from './components/ui/Empty.tsx'
|
|
46
24
|
export { ProgressRing, type ProgressRingProps } from './components/ui/ProgressRing.tsx'
|
|
47
|
-
// Prompt input (vendored just-marketing/prompt-area, themed to these tokens)
|
|
48
25
|
export {
|
|
49
26
|
PromptArea,
|
|
50
27
|
usePromptAreaState,
|
|
@@ -64,7 +41,6 @@ export {
|
|
|
64
41
|
type TriggerSuggestion,
|
|
65
42
|
} from './components/prompt-area/index.ts'
|
|
66
43
|
|
|
67
|
-
// Agent-control components
|
|
68
44
|
export {
|
|
69
45
|
SessionPanel,
|
|
70
46
|
type SessionControls,
|
|
@@ -73,48 +49,17 @@ export {
|
|
|
73
49
|
type SessionVitals,
|
|
74
50
|
type TerminalMetrics,
|
|
75
51
|
} from './components/agent/SessionPanel.tsx'
|
|
76
|
-
// The workspace layout and its Monaco editor live at `@workerdeck/ui/workspace`
|
|
77
|
-
// — deliberately unreachable from here, so importing this entry never drags
|
|
78
|
-
// Monaco into the bundle. See `src/workspace.ts`.
|
|
79
52
|
export { Transcript, type TranscriptProps } from './components/agent/Transcript.tsx'
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// host composing the surface by hand (a prompt outside the panel, a status line
|
|
83
|
-
// in its own chrome) and for the primitives, so a host's own row lands on the
|
|
84
|
-
// same character cell as ours.
|
|
85
|
-
export {
|
|
86
|
-
TerminalSurface,
|
|
87
|
-
type TerminalSurfaceProps,
|
|
88
|
-
} from './components/terminal/surface.tsx'
|
|
89
|
-
export {
|
|
90
|
-
TerminalTranscript,
|
|
91
|
-
TerminalItemView,
|
|
92
|
-
type TerminalTranscriptProps,
|
|
93
|
-
} from './components/terminal/TerminalTranscript.tsx'
|
|
53
|
+
export { TerminalSurface, type TerminalSurfaceProps } from './components/terminal/surface.tsx'
|
|
54
|
+
export { TerminalTranscript, TerminalItemView, type TerminalTranscriptProps } from './components/terminal/TerminalTranscript.tsx'
|
|
94
55
|
export { TerminalStatusLine, type TerminalStatusLineProps } from './components/terminal/StatusLine.tsx'
|
|
95
|
-
export {
|
|
96
|
-
|
|
97
|
-
type TerminalPermissionPromptProps,
|
|
98
|
-
} from './components/terminal/PermissionPrompt.tsx'
|
|
99
|
-
export {
|
|
100
|
-
TerminalQuestionPrompt,
|
|
101
|
-
type TerminalQuestionPromptProps,
|
|
102
|
-
} from './components/terminal/QuestionPrompt.tsx'
|
|
56
|
+
export { TerminalPermissionPrompt, type TerminalPermissionPromptProps } from './components/terminal/PermissionPrompt.tsx'
|
|
57
|
+
export { TerminalQuestionPrompt, type TerminalQuestionPromptProps } from './components/terminal/QuestionPrompt.tsx'
|
|
103
58
|
export { TerminalDiff, previewPatch } from './components/terminal/diff.tsx'
|
|
104
59
|
export { TerminalMarkdown, type TerminalMarkdownProps } from './components/terminal/markdown.tsx'
|
|
105
60
|
export { Band, Blank, Ink, Row, type RowProps, type Tone } from './components/terminal/row.tsx'
|
|
106
|
-
export {
|
|
107
|
-
|
|
108
|
-
WithActions,
|
|
109
|
-
useAffordances,
|
|
110
|
-
type TerminalAffordances,
|
|
111
|
-
} from './components/terminal/affordances.tsx'
|
|
112
|
-
export {
|
|
113
|
-
Conversation,
|
|
114
|
-
ConversationContent,
|
|
115
|
-
ConversationScrollButton,
|
|
116
|
-
type ConversationProps,
|
|
117
|
-
} from './components/agent/Conversation.tsx'
|
|
61
|
+
export { CopyAction, WithActions, useAffordances, type TerminalAffordances } from './components/terminal/affordances.tsx'
|
|
62
|
+
export { Conversation, ConversationContent, ConversationScrollButton, type ConversationProps } from './components/agent/Conversation.tsx'
|
|
118
63
|
export { Message, MessageContent, type MessageProps } from './components/agent/Message.tsx'
|
|
119
64
|
export {
|
|
120
65
|
TranscriptDensityProvider,
|
|
@@ -138,13 +83,7 @@ export {
|
|
|
138
83
|
type QuestionPromptProps,
|
|
139
84
|
type QuestionBehaviorMeta,
|
|
140
85
|
} from './components/agent/QuestionPrompt.tsx'
|
|
141
|
-
export {
|
|
142
|
-
Composer,
|
|
143
|
-
skillPrompt,
|
|
144
|
-
type ComposerFileMatch,
|
|
145
|
-
type ComposerHandle,
|
|
146
|
-
type ComposerProps,
|
|
147
|
-
} from './components/agent/Composer.tsx'
|
|
86
|
+
export { Composer, skillPrompt, type ComposerFileMatch, type ComposerHandle, type ComposerProps } from './components/agent/Composer.tsx'
|
|
148
87
|
export { ModelSelect, type ModelSelectProps } from './components/agent/ModelSelect.tsx'
|
|
149
88
|
export {
|
|
150
89
|
PERMISSION_MODES,
|
|
@@ -159,59 +98,23 @@ export { StatusBar, type StatusBarProps } from './components/agent/StatusBar.tsx
|
|
|
159
98
|
export { ContextDialog, type ContextDialogProps } from './components/agent/ContextDialog.tsx'
|
|
160
99
|
export { UsageDialog, type UsageDialogProps } from './components/agent/UsageDialog.tsx'
|
|
161
100
|
export { UsageMeters, useMinuteClock } from './components/agent/UsageMeters.tsx'
|
|
162
|
-
export {
|
|
163
|
-
SessionInfoDialog,
|
|
164
|
-
type SessionInfoDialogProps,
|
|
165
|
-
} from './components/agent/SessionInfoDialog.tsx'
|
|
101
|
+
export { SessionInfoDialog, type SessionInfoDialogProps } from './components/agent/SessionInfoDialog.tsx'
|
|
166
102
|
export { McpDialog, type McpDialogProps } from './components/agent/McpDialog.tsx'
|
|
167
103
|
export { SkillsDialog, type SkillsDialogProps } from './components/agent/SkillsDialog.tsx'
|
|
168
104
|
export { HostFilesDialog, type HostFilesDialogProps } from './components/agent/HostFilesDialog.tsx'
|
|
169
|
-
export {
|
|
170
|
-
|
|
171
|
-
SessionListItem,
|
|
172
|
-
type SessionListItemProps,
|
|
173
|
-
type SessionListProps,
|
|
174
|
-
} from './components/agent/SessionList.tsx'
|
|
175
|
-
export {
|
|
176
|
-
SessionBrowser,
|
|
177
|
-
rowShapeClass,
|
|
178
|
-
type SessionBrowserProps,
|
|
179
|
-
} from './components/agent/SessionBrowser.tsx'
|
|
180
|
-
// The session card itself — one component, every client. `SessionBrowser` is the
|
|
181
|
-
// dashboard's list *around* it; a host that wants only the card (the VS Code
|
|
182
|
-
// sidebar does, because the filtering chrome above it is native) takes this.
|
|
105
|
+
export { SessionList, SessionListItem, type SessionListItemProps, type SessionListProps } from './components/agent/SessionList.tsx'
|
|
106
|
+
export { SessionBrowser, rowShapeClass, type SessionBrowserProps } from './components/agent/SessionBrowser.tsx'
|
|
183
107
|
export { SessionItem, type SessionItemProps } from './components/agent/SessionItem.tsx'
|
|
184
108
|
export { SessionStatusIcon } from './components/agent/SessionStatusIcon.tsx'
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
export {
|
|
188
|
-
EngineIcon,
|
|
189
|
-
engineMark,
|
|
190
|
-
vendorMarkClass,
|
|
191
|
-
vendorTextClass,
|
|
192
|
-
} from './components/agent/EngineIcon.tsx'
|
|
193
|
-
// Lifted out of the sidebar for the same reason: the work under a row is a
|
|
194
|
-
// protocol fact, so every list annotates it with one component.
|
|
195
|
-
export {
|
|
196
|
-
type Step,
|
|
197
|
-
StepRow,
|
|
198
|
-
StepToggle,
|
|
199
|
-
runningSteps,
|
|
200
|
-
sessionSteps,
|
|
201
|
-
} from './components/agent/SessionSteps.tsx'
|
|
202
|
-
// The sub-agent takeover's one line. Exported for hosts that draw their own
|
|
203
|
-
// panel chrome; the panel raises it itself.
|
|
109
|
+
export { EngineIcon, engineMark, vendorMarkClass, vendorTextClass } from './components/agent/EngineIcon.tsx'
|
|
110
|
+
export { type Step, StepRow, StepToggle, runningSteps, sessionSteps } from './components/agent/SessionSteps.tsx'
|
|
204
111
|
export { SubagentStrip } from './components/agent/SubagentStrip.tsx'
|
|
205
112
|
export { ProjectIcon } from './components/agent/ProjectIcon.tsx'
|
|
206
|
-
export {
|
|
207
|
-
SessionEmptyState,
|
|
208
|
-
type SessionEmptyStateProps,
|
|
209
|
-
} from './components/agent/SessionEmptyState.tsx'
|
|
113
|
+
export { SessionEmptyState, type SessionEmptyStateProps } from './components/agent/SessionEmptyState.tsx'
|
|
210
114
|
export { PromptTokenText } from './components/agent/PromptTokenText.tsx'
|
|
211
115
|
export { STATUS_META } from './components/agent/status.ts'
|
|
212
116
|
export { ContextRing } from './components/agent/ContextRing.tsx'
|
|
213
117
|
|
|
214
|
-
// Utilities
|
|
215
118
|
export { cn } from './lib/utils.ts'
|
|
216
119
|
export { copyText } from './lib/clipboard.ts'
|
|
217
120
|
export { isMutatingTool, toolIcon } from './lib/tool-icon.ts'
|
package/src/lib/clipboard.ts
CHANGED
|
@@ -1,47 +1,25 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copy text to the clipboard, on origins where the modern API does not exist.
|
|
3
|
-
*
|
|
4
|
-
* `navigator.clipboard` is gated on a **secure context**: HTTPS, or localhost.
|
|
5
|
-
* A WorkerDeck dashboard reached the way it is meant to be reached — plain HTTP
|
|
6
|
-
* on a LAN address, from a laptop or a phone — is neither, so `navigator.clipboard`
|
|
7
|
-
* is `undefined` there and touching `.writeText` throws outright. That is the
|
|
8
|
-
* normal deployment, not an edge case, which is why this falls back rather than
|
|
9
|
-
* feature-detecting into a disabled button.
|
|
10
|
-
*
|
|
11
|
-
* The fallback is `document.execCommand('copy')` over an off-screen textarea.
|
|
12
|
-
* It is deprecated and it is also the only thing that works here; every browser
|
|
13
|
-
* still implements it. Returns whether the text actually landed, so a caller can
|
|
14
|
-
* avoid claiming success it did not have.
|
|
15
|
-
*/
|
|
16
1
|
export async function copyText(value: string): Promise<boolean> {
|
|
17
|
-
// Optional-chained, not `in`-checked:
|
|
18
|
-
// absent entirely, and some embedded webviews expose a `clipboard` object
|
|
19
|
-
// whose `writeText` rejects. Both end up in the fallback.
|
|
2
|
+
// Optional-chained, not `in`-checked: some embedded webviews expose a `clipboard` object whose `writeText` rejects.
|
|
20
3
|
try {
|
|
21
4
|
if (navigator.clipboard?.writeText) {
|
|
22
5
|
await navigator.clipboard.writeText(value)
|
|
23
6
|
return true
|
|
24
7
|
}
|
|
25
|
-
} catch {
|
|
26
|
-
// Permission denied, or a webview that lied about having the API.
|
|
27
|
-
}
|
|
8
|
+
} catch {}
|
|
28
9
|
return legacyCopy(value)
|
|
29
10
|
}
|
|
30
11
|
|
|
31
12
|
function legacyCopy(value: string): boolean {
|
|
32
|
-
if (typeof document === 'undefined')
|
|
13
|
+
if (typeof document === 'undefined') {
|
|
14
|
+
return false
|
|
15
|
+
}
|
|
33
16
|
const textarea = document.createElement('textarea')
|
|
34
17
|
textarea.value = value
|
|
35
|
-
// Off-screen rather than hidden: `display: none` and `visibility: hidden`
|
|
36
|
-
// elements cannot hold a selection, so the copy would silently do nothing.
|
|
37
|
-
// `readOnly` keeps the mobile keyboard from appearing for the instant it exists.
|
|
38
18
|
textarea.setAttribute('readonly', '')
|
|
39
19
|
textarea.style.position = 'fixed'
|
|
40
20
|
textarea.style.top = '-9999px'
|
|
41
21
|
textarea.style.opacity = '0'
|
|
42
22
|
document.body.appendChild(textarea)
|
|
43
|
-
// Preserve where the user was: selecting steals the current selection, and on
|
|
44
|
-
// a text field mid-edit that is visible and annoying.
|
|
45
23
|
const previous = document.activeElement
|
|
46
24
|
try {
|
|
47
25
|
textarea.select()
|
|
@@ -51,6 +29,8 @@ function legacyCopy(value: string): boolean {
|
|
|
51
29
|
return false
|
|
52
30
|
} finally {
|
|
53
31
|
document.body.removeChild(textarea)
|
|
54
|
-
if (previous instanceof HTMLElement)
|
|
32
|
+
if (previous instanceof HTMLElement) {
|
|
33
|
+
previous.focus()
|
|
34
|
+
}
|
|
55
35
|
}
|
|
56
36
|
}
|
package/src/lib/css.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pass a colour through only if this engine can actually parse it. Category colours arrive
|
|
3
|
+
* from the CLI as untrusted strings, and an unparseable one must fall back to the token
|
|
4
|
+
* colour rather than reaching the DOM.
|
|
5
|
+
*/
|
|
6
|
+
export function cssColor(color: string): string | undefined {
|
|
7
|
+
return typeof CSS !== 'undefined' && CSS.supports('color', color) ? color : undefined
|
|
8
|
+
}
|