@artooi/ag-ui-web-component 0.49.0 → 0.50.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +175 -1
  2. package/README.md +25 -14
  3. package/dist/ag-ui-web-component.bundle.js +168 -125
  4. package/dist/ag-ui-web-component.bundle.js.map +3 -3
  5. package/dist/core/ag_ui_chat.d.ts.map +1 -1
  6. package/dist/index.js +530 -110
  7. package/dist/index.js.map +2 -2
  8. package/dist/tools/chat_surface_tools.d.ts +8 -5
  9. package/dist/tools/chat_surface_tools.d.ts.map +1 -1
  10. package/dist/ui/placement/collapse_styles.d.ts.map +1 -1
  11. package/dist/ui/placement/panel_placement.d.ts +15 -1
  12. package/dist/ui/placement/panel_placement.d.ts.map +1 -1
  13. package/dist/ui/placement/resize_styles.d.ts.map +1 -1
  14. package/dist/ui/shell/frame_styles.d.ts.map +1 -1
  15. package/dist/ui/shell/token_styles.d.ts.map +1 -1
  16. package/dist/ui/themes/classic_tokens.d.ts.map +1 -1
  17. package/dist/ui/themes/ledger_styles.d.ts.map +1 -1
  18. package/dist/ui/themes/ledger_tokens.d.ts.map +1 -1
  19. package/dist/ui/themes/quiet_styles.d.ts.map +1 -1
  20. package/dist/ui/themes/soft_styles.d.ts.map +1 -1
  21. package/dist/ui/themes/soft_tokens.d.ts.map +1 -1
  22. package/dist/ui/transcript/transcript_styles.d.ts.map +1 -1
  23. package/package.json +1 -1
  24. package/src/core/ag_ui_chat.ts +73 -7
  25. package/src/tools/chat_surface_tools.ts +8 -5
  26. package/src/ui/placement/collapse_styles.ts +8 -0
  27. package/src/ui/placement/panel_placement.ts +512 -99
  28. package/src/ui/placement/resize_styles.ts +9 -0
  29. package/src/ui/shell/frame_styles.ts +22 -2
  30. package/src/ui/shell/token_styles.ts +7 -6
  31. package/src/ui/themes/classic_tokens.ts +1 -0
  32. package/src/ui/themes/ledger_styles.ts +4 -3
  33. package/src/ui/themes/ledger_tokens.ts +1 -0
  34. package/src/ui/themes/quiet_styles.ts +2 -15
  35. package/src/ui/themes/soft_styles.ts +4 -3
  36. package/src/ui/themes/soft_tokens.ts +1 -0
  37. package/src/ui/transcript/transcript_styles.ts +14 -1
  38. package/src/version.ts +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,178 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.50.1] — 2026-11-09
11
+
12
+ ### Fixed
13
+
14
+ - **A corner panel a grip placed goes full-bleed on a phone after a move is
15
+ undone.** Under `collapse-to="auto"`, with no spot stated, the sequence of a grip
16
+ on an edge the layout holds, `moveTo` with its announcement, another such grip and
17
+ the undo left an inline `--ag-ui-inset` that read as a host's own, so a phone kept
18
+ it, and the panel stood off the screen by as much as the grip had moved it. It now
19
+ fills the screen with no inline inset, and widening gives the grip's place back.
20
+ An undo also keeps the inset that stands a panel at the start of a window a host
21
+ fills, so the panel rests again once that fill has gone. **A host has nothing to
22
+ do.**
23
+ - **A moved panel under `data-launcher-drag="false"` gives way when a host's size
24
+ stands it off the screen.** Since 0.50.0 such a panel stays where it was moved
25
+ until the next window resize or reopen, and it still does while the reader types.
26
+ A host that then filled the window left it at -524,-144 at 1280x800, its header
27
+ out of reach, until one of those came. Any size that stands it off an edge of the
28
+ screen now hands it to the host's CSS at once, and a host that fills the window
29
+ gets it at 0,0. The stored spot stays for the day the attribute comes off. A size
30
+ that still fits moves nothing. **A host has nothing to do.**
31
+ - **A docked panel a host fills stands at 0,0.** Under `collapse-to="bar"` and
32
+ `"none"`, a panel a host sized to the whole window stood past the top of the window
33
+ by what the resting inset spends: at 1200x760, -24,-65 under the bar, where
34
+ the whole header was out of reach, and -24,-24 under a host's own control. It now
35
+ stands at the start of the room the host left free, moved or not, as a corner panel
36
+ has since 0.50.0, and under `data-launcher-drag="false"` too. While it does the bar
37
+ and the grips go, as they do on a phone, with `ag-ui-bar-height` saying 0 and the
38
+ header's minimise control as the way back, because the strip would draw over the
39
+ composer's foot. The bar comes back when the panel is collapsed, and both when the
40
+ size stops filling. A host that writes that height into its own
41
+ `--ag-ui-viewport-inset-bottom` settles with the bar gone: the panel stays judged
42
+ against the box it filled while the box has only grown by the bar's height on the same
43
+ window, where it would otherwise flip the bar and jump the header every frame. The
44
+ dock's stored spot stays unchanged, and the panel goes back
45
+ to its spot or its dock when the size stops filling. A host's own inline `--ag-ui-inset` stays
46
+ where the host wrote it, and a placement that owns its position is left alone. **A
47
+ host has nothing to do.**
48
+ - **A viewport inset token wider than the card holding an embedded chat adds no
49
+ scroll.** The box the component reads the four `--ag-ui-viewport-inset-*`
50
+ tokens from took its size from them, so a 200px card under a 240px left token
51
+ scrolled by 40px, and the same on the other axis. The tokens read back as
52
+ before, a percentage against the same box. **A host has nothing to do.**
53
+ - **A hidden panel stays where it was moved.** Hiding the element, or anything
54
+ holding it, had it place itself from a box of nothing and write that as its
55
+ inset, so a script reading the panel straight after showing it again found it
56
+ off the screen, until a few frames later it stood at its spot. A window resize
57
+ while hidden, connecting hidden and expanding hidden did the same. None of those
58
+ writes an inset now, and showing the element places it against the window as it
59
+ then is. The stored spot was never touched, and `ag-ui-bar-height` still says 0
60
+ while hidden. **A host has nothing to do.**
61
+
62
+ ## [0.50.0] — 2026-11-08
63
+
64
+ ### Changed
65
+
66
+ - **The themes demo sets `--ag-ui-header-btn-hover`.** A new control on its
67
+ page draws the header buttons' hover square in a colour you pick. The suite
68
+ now tests that square as a browser without relative colour syntax draws it,
69
+ mixed from the header text, which only a string check saw before. Demo and
70
+ tests only, nothing shipped changes. **A host has nothing to do.**
71
+
72
+ ### Fixed
73
+
74
+ - **A corner panel that was moved goes full-bleed on a phone, and stays there.**
75
+ Under `collapse-to="auto"`, a panel moved by its header, its launcher or
76
+ `moveTo` on a wide window kept an inline `--ag-ui-inset` when the window
77
+ narrowed below the small-viewport breakpoint, which held it 8px off two edges
78
+ and past the other two. It now fills the screen, with no inline inset, while
79
+ its launcher stays on the screen for when it is collapsed. A header drag no
80
+ longer moves a panel that is the screen, as `moveTo` already refused to, and its
81
+ cursor stops offering one. The
82
+ place the user put the panel is now kept as they stated it: a window that
83
+ narrows, by any amount, holds the panel inside it without changing the record,
84
+ and widening gives that place back, as a reload already did. A gesture made in
85
+ the narrower window states a new one. **A host has nothing to do.**
86
+ - **A corner panel remembers the corner a resize grip moved.** Under
87
+ `collapse-to="auto"`, growing a moved panel by a grip on its free edges, which
88
+ moves its top-left corner while the layout holds the opposite one, was lost on
89
+ the next reopen or reload: the panel came back at its old top-left, grown away
90
+ from its launcher. It now comes back as it was drawn, a host's maximum included,
91
+ and `resetSize()` keeps the panel where the size came off. The top-left stays as the
92
+ grip left it while the host's own `--ag-ui-width` or `--ag-ui-height` is in force at
93
+ that moment, and the stored spot stays as it was under `data-launcher-drag="false"`.
94
+ **A host has nothing to do.**
95
+ - **`read_chat_surface` reports the page's setting for `draggable`, whatever the
96
+ placement.** A sidebar, embedded, side, page or full panel under `collapse-to="auto"`
97
+ reported `draggable: false` with `movable: false`, so `move_chat` answered that
98
+ the page had turned off moving the panel when the placement owned its position,
99
+ while the same placement under `collapse-to="none"` or `"bar"` reported `true`.
100
+ `draggable` is now `true` for every placement unless the page sets
101
+ `data-launcher-drag="false"`, and whether this panel moves stays in `movable`.
102
+ The refusal names the placement. **A host has nothing to do.**
103
+ - **Every theme's header buttons follow `--ag-ui-header-fg`.** 0.49.0 did this
104
+ for Quiet alone, so the accent recipe still fell short under the others:
105
+ white on a `#3d5afe` header read 1.1 to 1.6:1 at rest under Soft and Ledger,
106
+ and 4.16:1 at rest and 3.75:1 hovered under Classic and code. Once a host sets
107
+ `--ag-ui-header-fg`, the buttons draw in it at full opacity under every theme
108
+ and scheme, and the hover square is the opposite of that text at 18%: that
109
+ pair now reads 5.13:1 at rest and 6.95:1 hovered under all of them. What
110
+ changes for a host that sets it, by theme. Soft: the glyph was the third ink,
111
+ the accent's ink hovered, on a square of `--ag-ui-tint-2`. Ledger: the glyph
112
+ was the third ink, the full ink hovered, on a square of `--ag-ui-hover`.
113
+ Classic and code: the glyph already was the header text, but at 0.85 opacity,
114
+ and the square was 18% white, so under white text it now darkens where it
115
+ lightened. Browsers without relative colour syntax (Firefox 120 to 127,
116
+ Safari 17.5 and 17.6) mix the square from the text itself, as under Quiet, at
117
+ 3.75:1 hovered for that pair.
118
+ **`--ag-ui-header-btn-hover`, inert until now under Soft, Ledger, Classic and
119
+ code, works under them**, as it does under Quiet: drawn exactly as given,
120
+ whether or not the header text is set. A host that set it for Quiet and also
121
+ wears one of these themes will now see it. With neither token set, every
122
+ theme's header buttons are exactly as they were, whatever the header colour
123
+ or `--ag-ui-hover`. **No opt-in is needed.** A page's own
124
+ `::part(header-button)` rules still win: a host that wrote one to get here may
125
+ delete it, and should at least delete a `:hover` background of 18% of the text,
126
+ which keeps the glyph at 3.75:1 on a mid-tone accent. A host that sets neither
127
+ token, the Django admin among them, sees no change.
128
+ - **A corner panel a host's own size makes the window stands at 0,0.** A host that
129
+ fills a wide window with `--ag-ui-width` and `--ag-ui-height` found a panel the
130
+ user had moved standing at 8,8 after a window resize, 8px past the right and
131
+ bottom edges. It now exactly fills the window, from the start of whatever the
132
+ viewport inset tokens reserve, as a
133
+ phone's full-bleed panel does, and comes back to where the user put it when the
134
+ host's size drops. A host's own `--ag-ui-inset` rule that already stands the box
135
+ on the screen is left alone. **A host has nothing to do.**
136
+ - **A panel placed only by a resize grip goes full-bleed on a phone.** A grip on
137
+ an edge the layout holds moves an unmoved corner panel without storing a spot,
138
+ and that inline inset stayed on when the window narrowed, which held the panel
139
+ off two edges and past the other two. It now fills the screen with no inline
140
+ inset, and widening gives the place back. An inset the host wrote inline stays
141
+ where the host wrote it. An unmoved panel a host's own size makes the window
142
+ stands at 0,0 as well. **A host has nothing to do.**
143
+ - **`data-launcher-drag="false"` on a moved panel hands it to the host's CSS.**
144
+ Turned on after the user had moved the panel, the attribute left an inline
145
+ inset behind for good, which put the panel off the screen on a phone. Nothing
146
+ moves when it goes on. The next window resize or reopen rests the panel where
147
+ the host's CSS puts it, as a reload under the attribute always did, and on a
148
+ phone that is full-bleed. The stored spot stays, and comes back at the first
149
+ restore after the attribute comes off. **A host has nothing to do.**
150
+ - **Undoing a move after the surface changed leaves everything in agreement.** A
151
+ move undone once the panel had gone from a corner to a sidebar, a side panel, a
152
+ page or a dock wrote the corner's inset back onto the new surface, which pinned
153
+ a sidebar or a page off the screen and took a docked panel off its dock, and
154
+ left the stored spot on the move the reader had just undone. Going the other way
155
+ left a docked panel's stored spot on the move too. The undo now puts both
156
+ records back, in memory and in storage, and leaves the new surface standing where
157
+ its own layout puts it; the spot comes back with the surface it belongs to.
158
+ **A host has nothing to do.**
159
+ - **A moved panel answers a host's size when the size changes.** A change to
160
+ `--ag-ui-width` or `--ag-ui-height` fires no event, so a panel the user had moved
161
+ stayed as the last restore left it until the next window resize or reopen. Reopened
162
+ under a host's size that then dropped, it stood short of its spot, at 716,232 for a
163
+ spot of 376,96, with the stored spot still right; sized up with no reopen, it could
164
+ grow past the top of the window. It now goes back to its spot as the size drops, and
165
+ under a bigger size it stands where a reopen already put it, held on the screen from
166
+ that spot, rather than growing away from the corner the layout held. A window-filling
167
+ size stands it at 0,0 at once, with no resize needed. **A host has nothing to do.**
168
+ - **A moved panel answers a viewport inset token when the token changes.** A page
169
+ that publishes `--ag-ui-viewport-inset-top` from its own `ResizeObserver`, as the
170
+ README recommends, does so after the window's resize event, so the restore that event
171
+ starts read the bar at its old height. Widening a window past the width where the bar
172
+ shrinks left the panel 35px below its spot on the playground, top 224 for a spot of
173
+ 189, and narrowing left it under a bar that had grown. It now settles from the token
174
+ as it stands, a frame later, on any of the four viewport inset tokens and however
175
+ late the page writes them. **A host has nothing to do.**
176
+ - **The header's cursor no longer offers a drag that cannot happen.** A panel that
177
+ had become the screen on a narrow window with a mouse, or a docked panel under
178
+ `collapse-to="bar"` or `"none"` that a host's own size had made the window, showed
179
+ `cursor: move` although its header could not move it. The cursor is now `auto` there,
180
+ and stays `move` everywhere the drag is allowed. **A host has nothing to do.**
181
+
10
182
  ## [0.49.0] — 2026-11-07
11
183
 
12
184
  ### Added
@@ -5048,7 +5220,9 @@ hosts that both arrange the page the way it expects.
5048
5220
  ### Notes
5049
5221
  - First release — exercising the automated npm OIDC publish pipeline end-to-end.
5050
5222
 
5051
- [Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.49.0...HEAD
5223
+ [Unreleased]: https://github.com/Artui/ag-ui-web-component/compare/v0.50.1...HEAD
5224
+ [0.50.1]: https://github.com/Artui/ag-ui-web-component/compare/v0.50.0...v0.50.1
5225
+ [0.50.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.49.0...v0.50.0
5052
5226
  [0.49.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.48.0...v0.49.0
5053
5227
  [0.48.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.47.0...v0.48.0
5054
5228
  [0.47.0]: https://github.com/Artui/ag-ui-web-component/compare/v0.46.0...v0.47.0
package/README.md CHANGED
@@ -1467,7 +1467,11 @@ the bar's height. The component never writes your CSS, and a custom property can
1467
1467
  height up to your page (it inherits down, never up), so it hands you a number:
1468
1468
  `barHeight` (CSS px, read-only) and an `ag-ui-bar-height` event (the `BAR_HEIGHT_EVENT`
1469
1469
  constant, detail `{ height }`) on every change, including a font-size change. Both read `0`
1470
- where no bar is drawn: under `auto` and `none`, and on a phone while the panel is open.
1470
+ where no bar is drawn: under `auto` and `none`, on a phone while the panel is open, and while your
1471
+ size fills the window with the panel open. If you write the height into
1472
+ `--ag-ui-viewport-inset-bottom`, a panel that fills the box that leaves stays judged against that
1473
+ box once the bar goes and the box grows by the bar's height: it settles with the bar gone and room
1474
+ at its foot. Writing some other share of the height does not settle; publish it to your page as below.
1471
1475
 
1472
1476
  ```js
1473
1477
  const chat = document.querySelector("ag-ui-chat");
@@ -1509,6 +1513,13 @@ launcher to drag: the bar and your own control stay where they are.
1509
1513
  forgetting the stored spot, so a reload opens it there too.
1510
1514
  - **Keeping it fixed.** `data-launcher-drag="false"` turns the header drag and `moveTo` off here as
1511
1515
  everywhere else, and the panel stays on its dock.
1516
+ - **A host's size that fills the window.** Set `--ag-ui-width` and `--ag-ui-height` to the whole
1517
+ window, with `--ag-ui-max-width` and `--ag-ui-max-height` out of the way (the defaults stop short
1518
+ of it), and the panel stands at the start of the room you left free, whether it was moved or not.
1519
+ The bar and the grips go while it does, as on a phone, with `barHeight` at 0 and the header's
1520
+ minimise control as the way back. The bar comes back when the panel is collapsed, and both when
1521
+ your size stops filling. The stored spot stays, and the panel goes back to it, or to its dock,
1522
+ once your size stops filling. An inline `--ag-ui-inset` of your own stays where you wrote it.
1512
1523
 
1513
1524
  Placements that own their position (`side` and `full` under `bar`, `sidebar` and `embedded`
1514
1525
  under `none`) do not move, as without `collapse-to`.
@@ -3330,7 +3341,8 @@ and set a mid-tone accent, set `--ag-ui-on-accent` yourself. There is no script
3330
3341
 
3331
3342
  Quiet draws the header, the launcher and the tool names in the panel's own colours, so a host that
3332
3343
  sets only `--ag-ui-accent` gets a neutral header. To put the accent back without leaving Quiet, set
3333
- the surfaces to the accent and the text on them to a colour that reads on it:
3344
+ the surfaces to the accent and the text on them to a colour that reads on it. The same recipe holds
3345
+ under every other theme:
3334
3346
 
3335
3347
  ```css
3336
3348
  ag-ui-chat {
@@ -3342,19 +3354,19 @@ ag-ui-chat {
3342
3354
  }
3343
3355
  ```
3344
3356
 
3345
- - **The header buttons follow `--ag-ui-header-fg`.** Unset, Quiet draws them in its third ink at
3346
- 0.85 opacity, on a hover square of the panel's hover shade. Once you set the header text they
3347
- draw in it at full opacity, and the hover square is the opposite of that text at about a fifth
3348
- (a darker square under white text, a lighter one under dark text), so a hovered button reads at
3349
- least what your header pair reads. The same holds under a theme word of your own, which starts
3350
- from Quiet. No `::part(header-button)` rule is needed. The opposite is computed with relative
3357
+ - **The header buttons follow `--ag-ui-header-fg`, under every theme.** Unset, each theme draws
3358
+ them its own way at 0.85 opacity: Quiet, Soft and Ledger in their third ink, Classic and Code in
3359
+ the header text, each on its own hover square. Once you set the header text they draw in it at
3360
+ full opacity, and the hover square is the opposite of that text at about a fifth (a darker square
3361
+ under white text, a lighter one under dark text), so a hovered button reads at least what your
3362
+ header pair reads. A theme word of your own starts from Quiet, so it holds there too. No
3363
+ `::part(header-button)` rule is needed. The opposite is computed with relative
3351
3364
  colour syntax; the browsers without it (see the fallback above) mix the square from the text
3352
3365
  itself, which on a mid-tone header can take the hovered glyph under your pair (white on
3353
3366
  `#3d5afe`: 3.75:1).
3354
- - **`--ag-ui-header-btn-hover` sets the hover square outright** under Quiet and a theme word of your
3355
- own, whether or not the header text is set, and is drawn exactly as given. Classic, Soft and
3356
- Ledger draw their own squares and do not read it. For a square that lightens under white text
3357
- instead, at the cost of contrast on a mid-tone header:
3367
+ - **`--ag-ui-header-btn-hover` sets the hover square outright** under every theme, whether or not
3368
+ the header text is set, and is drawn exactly as given. For a square that lightens under white
3369
+ text instead, at the cost of contrast on a mid-tone header:
3358
3370
 
3359
3371
  ```css
3360
3372
  ag-ui-chat { --ag-ui-header-btn-hover: color-mix(in srgb, #ffffff 18%, transparent); }
@@ -3362,8 +3374,7 @@ ag-ui-chat {
3362
3374
  - **`--ag-ui-tool-fg` colours every tool call**, in a step group as well as in the card displays.
3363
3375
  Unset, a grouped call is drawn in the second ink (`--ag-ui-ink-2`) under every theme.
3364
3376
  - Pick the pair yourself: `--ag-ui-header-fg` is not derived from the header colour the way
3365
- `--ag-ui-on-accent` is from the accent. Under Soft and Ledger the header buttons keep their own
3366
- third ink whatever you set.
3377
+ `--ag-ui-on-accent` is from the accent.
3367
3378
 
3368
3379
  #### Overriding a theme, lightest layer first
3369
3380