@artooi/ag-ui-web-component 0.34.0 → 0.35.1
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/CHANGELOG.md +517 -1
- package/README.md +243 -13
- package/dist/ag-ui-web-component.bundle.js +614 -96
- package/dist/ag-ui-web-component.bundle.js.map +4 -4
- package/dist/constants.d.ts +76 -3
- package/dist/constants.d.ts.map +1 -1
- package/dist/core/ag_ui_chat.d.ts +37 -2
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/dom/animations.d.ts +14 -0
- package/dist/dom/animations.d.ts.map +1 -1
- package/dist/dom/highlight_overlay.d.ts +47 -0
- package/dist/dom/highlight_overlay.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1886 -320
- package/dist/index.js.map +4 -4
- package/dist/tools/chat_surface_tools.d.ts +96 -0
- package/dist/tools/chat_surface_tools.d.ts.map +1 -0
- package/dist/tools/page_action_tools.d.ts +2 -0
- package/dist/tools/page_action_tools.d.ts.map +1 -1
- package/dist/ui/clamp_launcher.d.ts +10 -5
- package/dist/ui/clamp_launcher.d.ts.map +1 -1
- package/dist/ui/clamp_panel.d.ts +2 -2
- package/dist/ui/clamp_panel.d.ts.map +1 -1
- package/dist/ui/launcher_drag.d.ts +2 -2
- package/dist/ui/launcher_drag.d.ts.map +1 -1
- package/dist/ui/launcher_placement.d.ts +14 -1
- package/dist/ui/launcher_placement.d.ts.map +1 -1
- package/dist/ui/panel_drag.d.ts.map +1 -1
- package/dist/ui/place_widget.d.ts +9 -1
- package/dist/ui/place_widget.d.ts.map +1 -1
- package/dist/ui/run_notice.d.ts +14 -3
- package/dist/ui/run_notice.d.ts.map +1 -1
- package/dist/ui/styles.d.ts +1 -1
- package/dist/ui/styles.d.ts.map +1 -1
- package/dist/ui/thread_drawer.d.ts +21 -0
- package/dist/ui/thread_drawer.d.ts.map +1 -1
- package/dist/ui/ui_strings.d.ts +16 -0
- package/dist/ui/ui_strings.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +82 -3
- package/src/core/ag_ui_chat.ts +965 -55
- package/src/dom/animations.ts +30 -0
- package/src/dom/highlight_overlay.ts +256 -0
- package/src/index.ts +12 -0
- package/src/tools/chat_surface_tools.ts +207 -0
- package/src/tools/page_action_tools.ts +2 -0
- package/src/ui/clamp_launcher.ts +25 -7
- package/src/ui/clamp_panel.ts +10 -4
- package/src/ui/launcher_drag.ts +11 -2
- package/src/ui/launcher_placement.ts +34 -8
- package/src/ui/panel_drag.ts +4 -0
- package/src/ui/place_widget.ts +11 -3
- package/src/ui/run_notice.ts +32 -3
- package/src/ui/styles.ts +563 -45
- package/src/ui/thread_drawer.ts +138 -8
- package/src/ui/ui_strings.ts +24 -0
- package/src/version.ts +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SCREEN_EDGE_MARGIN } from "../constants.js";
|
|
2
2
|
import { clampPanel } from "./clamp_panel.js";
|
|
3
3
|
import { placeWidget } from "./place_widget.js";
|
|
4
4
|
|
|
@@ -10,6 +10,20 @@ export interface LauncherBox {
|
|
|
10
10
|
readonly height: number;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* The part of the screen a widget may rest in: a width and height, and the
|
|
15
|
+
* corner they start from.
|
|
16
|
+
*
|
|
17
|
+
* The origin is not always zero. A host can reserve the edges its own chrome
|
|
18
|
+
* occupies, and a panel clamped against a viewport that starts at the top-left
|
|
19
|
+
* of the screen will happily park itself underneath a sticky header -- where it
|
|
20
|
+
* cannot be reached, and where collapsing it only hides it further.
|
|
21
|
+
*/
|
|
22
|
+
export interface ViewportBox extends Extent {
|
|
23
|
+
readonly left: number;
|
|
24
|
+
readonly top: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
13
27
|
/** A width/height pair, in CSS pixels. */
|
|
14
28
|
export interface Extent {
|
|
15
29
|
readonly width: number;
|
|
@@ -71,15 +85,24 @@ export interface LauncherPlacement {
|
|
|
71
85
|
export function launcherPlacement(
|
|
72
86
|
launcher: LauncherBox,
|
|
73
87
|
panel: Extent,
|
|
74
|
-
viewport:
|
|
75
|
-
|
|
88
|
+
viewport: ViewportBox,
|
|
89
|
+
screen: Extent,
|
|
90
|
+
margin: number = SCREEN_EDGE_MARGIN,
|
|
76
91
|
): LauncherPlacement {
|
|
77
92
|
// Room for a panel pinned to each side of the launcher. A tie goes to the
|
|
78
93
|
// first branch, so the result is deterministic for a centred launcher.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
//
|
|
95
|
+
// Measured against the usable box's own edges, not against its width and
|
|
96
|
+
// height as if it started at the origin. The launcher's coordinates are the
|
|
97
|
+
// screen's, while the extents have already had the host's reserved edges
|
|
98
|
+
// taken out of them, so mixing the two understates the room on one side and
|
|
99
|
+
// overstates it on the other -- by the same reserved inset, in opposite
|
|
100
|
+
// directions, which is what makes the comparison flip rather than merely
|
|
101
|
+
// drift. The clamp below reads `viewport.left`/`top`; this had to as well.
|
|
102
|
+
const roomRunningRight = viewport.left + viewport.width - launcher.left;
|
|
103
|
+
const roomRunningLeft = launcher.left + launcher.width - viewport.left;
|
|
104
|
+
const roomRunningDown = viewport.top + viewport.height - launcher.top;
|
|
105
|
+
const roomRunningUp = launcher.top + launcher.height - viewport.top;
|
|
83
106
|
const corner: ExpandCorner = {
|
|
84
107
|
x: roomRunningRight >= roomRunningLeft ? "left" : "right",
|
|
85
108
|
y: roomRunningDown >= roomRunningUp ? "top" : "bottom",
|
|
@@ -103,5 +126,8 @@ export function launcherPlacement(
|
|
|
103
126
|
margin,
|
|
104
127
|
);
|
|
105
128
|
|
|
106
|
-
|
|
129
|
+
// The usable box decides where things may rest; the screen is what the
|
|
130
|
+
// resulting insets are measured from. They are the same only when the host
|
|
131
|
+
// has reserved nothing.
|
|
132
|
+
return { corner, ...placeWidget(host, launcher, corner, screen) };
|
|
107
133
|
}
|
package/src/ui/panel_drag.ts
CHANGED
|
@@ -99,6 +99,7 @@ export function enablePanelDrag(handle: HTMLElement, options: PanelDragOptions):
|
|
|
99
99
|
const onUp = (up: PointerEvent): void => {
|
|
100
100
|
window.removeEventListener("pointermove", onMove);
|
|
101
101
|
window.removeEventListener("pointerup", onUp);
|
|
102
|
+
window.removeEventListener("pointercancel", onUp);
|
|
102
103
|
if (!dragging) {
|
|
103
104
|
return;
|
|
104
105
|
}
|
|
@@ -113,6 +114,9 @@ export function enablePanelDrag(handle: HTMLElement, options: PanelDragOptions):
|
|
|
113
114
|
// and would otherwise strand the panel mid-move with no pointerup.
|
|
114
115
|
window.addEventListener("pointermove", onMove);
|
|
115
116
|
window.addEventListener("pointerup", onUp);
|
|
117
|
+
// Routine on touch rather than exceptional: the browser takes the pointer
|
|
118
|
+
// back for a scroll or a system gesture and never sends pointerup.
|
|
119
|
+
window.addEventListener("pointercancel", onUp);
|
|
116
120
|
});
|
|
117
121
|
}
|
|
118
122
|
|
package/src/ui/place_widget.ts
CHANGED
|
@@ -20,18 +20,26 @@ export interface WidgetInsets {
|
|
|
20
20
|
* moves nothing, and the launcher may sit outside its own host box. Nothing
|
|
21
21
|
* clips it there, and that is what lets a launcher be flush to a screen corner
|
|
22
22
|
* while the panel it opens keeps its margin.
|
|
23
|
+
*
|
|
24
|
+
* `screen` is the **whole** viewport, not the part a host has left free. These
|
|
25
|
+
* are CSS `inset` values on a fixed element, and the browser measures those
|
|
26
|
+
* from the real edges -- so a `bottom` expressed against a box inset from the
|
|
27
|
+
* top comes out short by exactly that inset. It only shows when the corner
|
|
28
|
+
* flips mid-drag, because that is when the same point stops being expressed
|
|
29
|
+
* from `top` and starts being expressed from `bottom`: the widget then leaps by
|
|
30
|
+
* the reserved edge, which is a jump the gesture cannot explain.
|
|
23
31
|
*/
|
|
24
32
|
export function placeWidget(
|
|
25
33
|
host: PanelRect,
|
|
26
34
|
launcher: LauncherBox,
|
|
27
35
|
corner: ExpandCorner,
|
|
28
|
-
|
|
36
|
+
screen: Extent,
|
|
29
37
|
): WidgetInsets {
|
|
30
38
|
return {
|
|
31
39
|
hostInset: inset({
|
|
32
40
|
top: corner.y === "top" ? host.top : null,
|
|
33
|
-
right: corner.x === "right" ?
|
|
34
|
-
bottom: corner.y === "bottom" ?
|
|
41
|
+
right: corner.x === "right" ? screen.width - host.right : null,
|
|
42
|
+
bottom: corner.y === "bottom" ? screen.height - host.bottom : null,
|
|
35
43
|
left: corner.x === "left" ? host.left : null,
|
|
36
44
|
}),
|
|
37
45
|
launcherInset: inset({
|
package/src/ui/run_notice.ts
CHANGED
|
@@ -3,10 +3,23 @@
|
|
|
3
3
|
* skill loaded), rendered inline between turns.
|
|
4
4
|
*
|
|
5
5
|
* Distinct from a tool card, which reports work the agent asked for and
|
|
6
|
-
* settles, and from an error, which is a failure. A notice never settles
|
|
7
|
-
* no action
|
|
6
|
+
* settles, and from an error, which is a failure. A notice never settles and
|
|
7
|
+
* takes no action of its own.
|
|
8
|
+
*
|
|
9
|
+
* It may carry exactly one control, and only ever an undo. That is a narrower
|
|
10
|
+
* rule than "no controls", which is what this said until the agent could move
|
|
11
|
+
* the panel it speaks from: something that rearranges the user's window without
|
|
12
|
+
* being asked has to be both visible and reversible, and a notice is already
|
|
13
|
+
* the surface that says what the run did. Anything the user has to *decide* is
|
|
14
|
+
* a confirmation card instead -- the difference is that this reports something
|
|
15
|
+
* already done.
|
|
8
16
|
*/
|
|
9
|
-
export function renderRunNotice(
|
|
17
|
+
export function renderRunNotice(
|
|
18
|
+
icon: string,
|
|
19
|
+
text: string,
|
|
20
|
+
kind: string,
|
|
21
|
+
undo?: { readonly label: string; readonly onActivate: () => void },
|
|
22
|
+
): HTMLDivElement {
|
|
10
23
|
const notice = document.createElement("div");
|
|
11
24
|
notice.className = `run-notice run-notice--${kind}`;
|
|
12
25
|
notice.setAttribute("part", `run-notice run-notice-${kind}`);
|
|
@@ -28,5 +41,21 @@ export function renderRunNotice(icon: string, text: string, kind: string): HTMLD
|
|
|
28
41
|
label.textContent = text;
|
|
29
42
|
|
|
30
43
|
notice.append(glyph, label);
|
|
44
|
+
|
|
45
|
+
if (undo !== undefined) {
|
|
46
|
+
const button = document.createElement("button");
|
|
47
|
+
button.type = "button";
|
|
48
|
+
button.className = "run-notice-undo";
|
|
49
|
+
button.setAttribute("part", "run-notice-undo");
|
|
50
|
+
button.textContent = undo.label;
|
|
51
|
+
button.addEventListener("click", () => {
|
|
52
|
+
// One use. The state it restores is the state as it was when the notice
|
|
53
|
+
// was written, so offering it twice would put back something that has
|
|
54
|
+
// since moved again.
|
|
55
|
+
button.disabled = true;
|
|
56
|
+
undo.onActivate();
|
|
57
|
+
});
|
|
58
|
+
notice.append(button);
|
|
59
|
+
}
|
|
31
60
|
return notice;
|
|
32
61
|
}
|