@artooi/ag-ui-web-component 0.49.0 → 0.50.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/CHANGELOG.md +122 -1
- package/README.md +13 -13
- package/dist/ag-ui-web-component.bundle.js +137 -124
- package/dist/ag-ui-web-component.bundle.js.map +3 -3
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/index.js +368 -100
- package/dist/index.js.map +2 -2
- package/dist/tools/chat_surface_tools.d.ts +8 -5
- package/dist/tools/chat_surface_tools.d.ts.map +1 -1
- package/dist/ui/placement/panel_placement.d.ts +13 -1
- package/dist/ui/placement/panel_placement.d.ts.map +1 -1
- package/dist/ui/shell/frame_styles.d.ts.map +1 -1
- package/dist/ui/shell/token_styles.d.ts.map +1 -1
- package/dist/ui/themes/classic_tokens.d.ts.map +1 -1
- package/dist/ui/themes/ledger_styles.d.ts.map +1 -1
- package/dist/ui/themes/ledger_tokens.d.ts.map +1 -1
- package/dist/ui/themes/quiet_styles.d.ts.map +1 -1
- package/dist/ui/themes/soft_styles.d.ts.map +1 -1
- package/dist/ui/themes/soft_tokens.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/ag_ui_chat.ts +46 -5
- package/src/tools/chat_surface_tools.ts +8 -5
- package/src/ui/placement/panel_placement.ts +382 -93
- package/src/ui/shell/frame_styles.ts +22 -2
- package/src/ui/shell/token_styles.ts +7 -6
- package/src/ui/themes/classic_tokens.ts +1 -0
- package/src/ui/themes/ledger_styles.ts +4 -3
- package/src/ui/themes/ledger_tokens.ts +1 -0
- package/src/ui/themes/quiet_styles.ts +2 -15
- package/src/ui/themes/soft_styles.ts +4 -3
- package/src/ui/themes/soft_tokens.ts +1 -0
- package/src/version.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -5895,6 +5895,18 @@ function asPoint(value) {
|
|
|
5895
5895
|
function coversViewport(box, viewport) {
|
|
5896
5896
|
return box.width >= viewport.width - 1 && box.height >= viewport.height - 1;
|
|
5897
5897
|
}
|
|
5898
|
+
function hangsOff(box, viewport, screen) {
|
|
5899
|
+
const slack = 0.5;
|
|
5900
|
+
return box.left < viewport.left - slack || box.top < viewport.top - slack || box.right > screen.width + slack || box.bottom > screen.height + slack;
|
|
5901
|
+
}
|
|
5902
|
+
function atStartOf(viewport, box) {
|
|
5903
|
+
return {
|
|
5904
|
+
left: viewport.left,
|
|
5905
|
+
top: viewport.top,
|
|
5906
|
+
right: viewport.left + (box.right - box.left),
|
|
5907
|
+
bottom: viewport.top + (box.bottom - box.top)
|
|
5908
|
+
};
|
|
5909
|
+
}
|
|
5898
5910
|
function insetFrom(corner, box, screen) {
|
|
5899
5911
|
const side = (value) => `${Math.round(value)}px`;
|
|
5900
5912
|
return [
|
|
@@ -5924,6 +5936,7 @@ var PanelPlacement = class {
|
|
|
5924
5936
|
* header on screen, and the launcher is the handle then.
|
|
5925
5937
|
*/
|
|
5926
5938
|
enablePanelDrag(header) {
|
|
5939
|
+
this.#header = header;
|
|
5927
5940
|
enablePanelDrag(header, {
|
|
5928
5941
|
enabled: () => !this.#host.collapsed() && this.#canDragPanel(),
|
|
5929
5942
|
rect: () => this.#host.element.getBoundingClientRect(),
|
|
@@ -5948,12 +5961,19 @@ var PanelPlacement = class {
|
|
|
5948
5961
|
}
|
|
5949
5962
|
/** Build the eight resize grips into `chat`, with one of them in the tab order. */
|
|
5950
5963
|
mountResizeGrips(chat) {
|
|
5964
|
+
this.#resizing = false;
|
|
5951
5965
|
for (const grip of RESIZE_GRIPS) {
|
|
5952
5966
|
const handle = createResizeHandle(grip, {
|
|
5953
5967
|
axis: () => this.#resizeAxis(),
|
|
5954
5968
|
rect: () => this.#host.element.getBoundingClientRect(),
|
|
5955
|
-
apply: (box) =>
|
|
5956
|
-
|
|
5969
|
+
apply: (box) => {
|
|
5970
|
+
this.#resizing = true;
|
|
5971
|
+
this.#applyResize(grip, box);
|
|
5972
|
+
},
|
|
5973
|
+
commit: (box) => {
|
|
5974
|
+
this.#resizing = false;
|
|
5975
|
+
this.#commitResize(grip, box);
|
|
5976
|
+
},
|
|
5957
5977
|
label: this.#host.strings().resizePanel
|
|
5958
5978
|
});
|
|
5959
5979
|
handle.tabIndex = -1;
|
|
@@ -5978,6 +5998,7 @@ var PanelPlacement = class {
|
|
|
5978
5998
|
* it always has.
|
|
5979
5999
|
*/
|
|
5980
6000
|
resetSize() {
|
|
6001
|
+
const sized = this.#host.element.getBoundingClientRect();
|
|
5981
6002
|
this.#host.element.style.removeProperty(DRAG_WIDTH);
|
|
5982
6003
|
this.#host.element.style.removeProperty(DRAG_HEIGHT);
|
|
5983
6004
|
this.#host.clearPreference(SIZE_KEY);
|
|
@@ -5987,9 +6008,46 @@ var PanelPlacement = class {
|
|
|
5987
6008
|
}
|
|
5988
6009
|
this.#dockPos = null;
|
|
5989
6010
|
this.#storeDockPosition(null);
|
|
6011
|
+
} else {
|
|
6012
|
+
this.#carrySpotWithSize(sized);
|
|
5990
6013
|
}
|
|
5991
6014
|
this.syncResizeAnchor();
|
|
5992
6015
|
}
|
|
6016
|
+
/**
|
|
6017
|
+
* Carry a stated corner spot along with a dragged size coming off.
|
|
6018
|
+
*
|
|
6019
|
+
* The size comes off toward the corner the layout holds still, so the top-left
|
|
6020
|
+
* the spot is kept as moves with it, and a restore from the old one would swing
|
|
6021
|
+
* the panel away from its launcher. Only that movement goes onto the spot, not
|
|
6022
|
+
* where the box stands: in a window narrower than the spot the box is held
|
|
6023
|
+
* short of it, and that is not something the user stated.
|
|
6024
|
+
*
|
|
6025
|
+
* Left alone while a host's own size is in force, because that cannot be told
|
|
6026
|
+
* from the dragged size coming off, and it may be a state the host is about to
|
|
6027
|
+
* leave: counting it would throw the spot off by as much as that state is
|
|
6028
|
+
* bigger. A panel that is the screen needs no case of its own: the small-viewport
|
|
6029
|
+
* block ignores a dragged size, so its box does not move.
|
|
6030
|
+
*
|
|
6031
|
+
* Left alone too under data-launcher-drag="false", where a spot left over from
|
|
6032
|
+
* before the attribute is a record kept for the day it comes off, and nothing
|
|
6033
|
+
* that happens to the box now is a statement about it.
|
|
6034
|
+
*/
|
|
6035
|
+
#carrySpotWithSize(sized) {
|
|
6036
|
+
const element = this.#host.element;
|
|
6037
|
+
const box = element.getBoundingClientRect();
|
|
6038
|
+
const spot = this.#cornerSpot ?? this.#readLauncherPosition();
|
|
6039
|
+
const style = getComputedStyle(element);
|
|
6040
|
+
if (spot?.panel === void 0 || !this.#launcherDraggable() || style.getPropertyValue("--ag-ui-width") !== "" || style.getPropertyValue("--ag-ui-height") !== "") {
|
|
6041
|
+
return;
|
|
6042
|
+
}
|
|
6043
|
+
this.#writeCornerSpot({
|
|
6044
|
+
...spot,
|
|
6045
|
+
panel: {
|
|
6046
|
+
left: spot.panel.left + box.left - sized.left,
|
|
6047
|
+
top: spot.panel.top + box.top - sized.top
|
|
6048
|
+
}
|
|
6049
|
+
});
|
|
6050
|
+
}
|
|
5993
6051
|
/**
|
|
5994
6052
|
* A zero-sized box carrying the host's viewport insets as padding, so they
|
|
5995
6053
|
* can be read back as used pixel lengths. See the `.viewport-probe` rule for
|
|
@@ -6014,6 +6072,32 @@ var PanelPlacement = class {
|
|
|
6014
6072
|
* from the launcher would move the panel the user just placed.
|
|
6015
6073
|
*/
|
|
6016
6074
|
#panelPos = null;
|
|
6075
|
+
/**
|
|
6076
|
+
* The spot #launcherPos and #panelPos were last stated as, or null while
|
|
6077
|
+
* nothing has been stated since this element connected.
|
|
6078
|
+
*
|
|
6079
|
+
* Those two say where the launcher and the panel stand now, held inside the
|
|
6080
|
+
* viewport, because that is where a press finds them and a drag starts from.
|
|
6081
|
+
* This is what the user asked for, kept apart so that a window narrower than
|
|
6082
|
+
* the spot, or a phone that took the panel full-bleed, gives it back unchanged
|
|
6083
|
+
* once there is room again. Only a gesture, a move or a dragged size coming off
|
|
6084
|
+
* changes it; re-applying it against a viewport never does, which is the difference from a clamped
|
|
6085
|
+
* position quietly becoming the record one resize at a time.
|
|
6086
|
+
*/
|
|
6087
|
+
#cornerSpot = null;
|
|
6088
|
+
/**
|
|
6089
|
+
* The inset a grip wrote on a corner panel with no spot, or null. A grip on an
|
|
6090
|
+
* edge the layout holds moves the panel without stating a spot, so this is the
|
|
6091
|
+
* only way to tell its inline inset from one a host wrote there, which stays,
|
|
6092
|
+
* and to give it back once a phone has taken the panel full-bleed.
|
|
6093
|
+
*/
|
|
6094
|
+
#gripInset = null;
|
|
6095
|
+
/**
|
|
6096
|
+
* The inset standing a panel with no spot at the start of a window a host's
|
|
6097
|
+
* size fills, or null. Told apart from a host's own for the same reason, and it
|
|
6098
|
+
* lasts only as long as that size does.
|
|
6099
|
+
*/
|
|
6100
|
+
#fillInset = null;
|
|
6017
6101
|
/**
|
|
6018
6102
|
* Where the user dragged a docked panel, in viewport coordinates, or null
|
|
6019
6103
|
* while it stands on the bar or the anchor.
|
|
@@ -6042,6 +6126,10 @@ var PanelPlacement = class {
|
|
|
6042
6126
|
* second while the panel is already being laid out on every one of them.
|
|
6043
6127
|
*/
|
|
6044
6128
|
#anchor = { x: "right", y: "bottom" };
|
|
6129
|
+
/** The header the panel drag listens on, stamped by #stampHeader. */
|
|
6130
|
+
#header = null;
|
|
6131
|
+
/** Whether a grip has applied a box it has not committed yet. */
|
|
6132
|
+
#resizing = false;
|
|
6045
6133
|
/** The eight grips, by name, so the keyboard-reachable one can be moved. */
|
|
6046
6134
|
#resizeHandles = /* @__PURE__ */ new Map();
|
|
6047
6135
|
/**
|
|
@@ -6076,10 +6164,12 @@ var PanelPlacement = class {
|
|
|
6076
6164
|
*
|
|
6077
6165
|
* Read from the stamp the drag helpers already set, rather than tracked
|
|
6078
6166
|
* separately: one source of truth, and it clears on `pointercancel` as well
|
|
6079
|
-
* as `pointerup`, which is the end a touch gesture usually gets.
|
|
6167
|
+
* as `pointerup`, which is the end a touch gesture usually gets. The one
|
|
6168
|
+
* gesture that stamps nothing is an arrow key on a grip, which applies a box
|
|
6169
|
+
* per key and states it only when the key comes up, hence #resizing.
|
|
6080
6170
|
*/
|
|
6081
6171
|
dragging() {
|
|
6082
|
-
return this.#host.launcher.hasAttribute("data-dragging") || this.#host.root.querySelector(".header[data-dragging]") !== null;
|
|
6172
|
+
return this.#resizing || this.#host.launcher.hasAttribute("data-dragging") || this.#host.root.querySelector(".header[data-dragging], .resize-handle[data-dragging]") !== null;
|
|
6083
6173
|
}
|
|
6084
6174
|
/** The report behind `AgUiChat.describeSurface`, whose doc is the contract. */
|
|
6085
6175
|
describeSurface() {
|
|
@@ -6092,11 +6182,12 @@ var PanelPlacement = class {
|
|
|
6092
6182
|
collapsed: this.#host.collapsed(),
|
|
6093
6183
|
collapsible: this.#host.collapsible(),
|
|
6094
6184
|
movable: this.#panelMovable() && !fullBleed,
|
|
6095
|
-
//
|
|
6096
|
-
//
|
|
6097
|
-
//
|
|
6098
|
-
//
|
|
6099
|
-
|
|
6185
|
+
// The page's setting alone: true for every placement unless the host set
|
|
6186
|
+
// `data-launcher-drag="false"`. Whether this panel moves is `movable`,
|
|
6187
|
+
// and reading the launcher or the dock in here made the field change
|
|
6188
|
+
// with `collapse-to`, so a docked sidebar reported that the page had
|
|
6189
|
+
// turned moving off when the placement owned its position.
|
|
6190
|
+
draggable: this.#host.element.getAttribute("data-launcher-drag") !== "false",
|
|
6100
6191
|
fullBleed,
|
|
6101
6192
|
box: {
|
|
6102
6193
|
left: Math.round(box.left),
|
|
@@ -6163,6 +6254,13 @@ var PanelPlacement = class {
|
|
|
6163
6254
|
* puts the box back and animates it out of the wrong side. Absent values are
|
|
6164
6255
|
* captured as absent and removed on the way back, rather than written as
|
|
6165
6256
|
* empty strings that would outrank the placement.
|
|
6257
|
+
*
|
|
6258
|
+
* The surface may have changed by the time of the undo, so the two halves are
|
|
6259
|
+
* put back apart. Both records are, always, each to its own store, so the
|
|
6260
|
+
* memory and the storage cannot disagree and the surface they belong to finds
|
|
6261
|
+
* them when it comes back. The inline values only mean something to the surface
|
|
6262
|
+
* they were read from: written on any other, they pin a sidebar to where a
|
|
6263
|
+
* floating panel used to be.
|
|
6166
6264
|
*/
|
|
6167
6265
|
#captureGeometry() {
|
|
6168
6266
|
const inset2 = this.#host.element.style.getPropertyValue("--ag-ui-inset");
|
|
@@ -6170,33 +6268,44 @@ var PanelPlacement = class {
|
|
|
6170
6268
|
const corner = this.#host.element.getAttribute("data-expand-corner");
|
|
6171
6269
|
const launcherPos = this.#launcherPos;
|
|
6172
6270
|
const panelPos = this.#panelPos;
|
|
6173
|
-
const dockPos = this.#dockPos;
|
|
6271
|
+
const dockPos = this.#dockPos ?? this.#readDockPosition();
|
|
6174
6272
|
const expandCorner = this.#expandCorner;
|
|
6273
|
+
const cornerSpot = this.#cornerSpot ?? this.#readLauncherPosition();
|
|
6274
|
+
const owner = this.#positionOwner();
|
|
6175
6275
|
return () => {
|
|
6176
|
-
this.#restoreProperty("--ag-ui-inset", inset2);
|
|
6177
|
-
this.#restoreProperty("--ag-ui-launcher-inset", launcherInset);
|
|
6178
|
-
if (corner === null) {
|
|
6179
|
-
this.#host.element.removeAttribute("data-expand-corner");
|
|
6180
|
-
} else {
|
|
6181
|
-
this.#host.element.setAttribute("data-expand-corner", corner);
|
|
6182
|
-
}
|
|
6183
|
-
this.#launcherPos = launcherPos;
|
|
6184
|
-
this.#panelPos = panelPos;
|
|
6185
6276
|
this.#dockPos = dockPos;
|
|
6186
|
-
this.#
|
|
6187
|
-
if (
|
|
6188
|
-
this.#
|
|
6189
|
-
this.syncResizeAnchor();
|
|
6190
|
-
return;
|
|
6191
|
-
}
|
|
6192
|
-
if (launcherPos === null) {
|
|
6277
|
+
this.#storeDockPosition(dockPos);
|
|
6278
|
+
if (cornerSpot === null) {
|
|
6279
|
+
this.#cornerSpot = null;
|
|
6193
6280
|
this.#host.clearPreference(LAUNCHER_KEY);
|
|
6194
6281
|
} else {
|
|
6195
|
-
this.#
|
|
6282
|
+
this.#writeCornerSpot(cornerSpot);
|
|
6283
|
+
}
|
|
6284
|
+
if (owner === this.#positionOwner()) {
|
|
6285
|
+
this.#restoreProperty("--ag-ui-inset", inset2);
|
|
6286
|
+
this.#restoreProperty("--ag-ui-launcher-inset", launcherInset);
|
|
6287
|
+
if (corner === null) {
|
|
6288
|
+
this.#host.element.removeAttribute("data-expand-corner");
|
|
6289
|
+
} else {
|
|
6290
|
+
this.#host.element.setAttribute("data-expand-corner", corner);
|
|
6291
|
+
}
|
|
6292
|
+
this.#launcherPos = launcherPos;
|
|
6293
|
+
this.#panelPos = panelPos;
|
|
6294
|
+
this.#expandCorner = expandCorner;
|
|
6295
|
+
} else {
|
|
6296
|
+
this.#forgetCornerPosition();
|
|
6196
6297
|
}
|
|
6298
|
+
this.restoreLauncherPosition();
|
|
6197
6299
|
this.syncResizeAnchor();
|
|
6198
6300
|
};
|
|
6199
6301
|
}
|
|
6302
|
+
/** Which of the three kinds of surface decides where the panel stands. */
|
|
6303
|
+
#positionOwner() {
|
|
6304
|
+
if (this.#docked()) {
|
|
6305
|
+
return "dock";
|
|
6306
|
+
}
|
|
6307
|
+
return this.#surface().launcherDraggable ? "corner" : "placement";
|
|
6308
|
+
}
|
|
6200
6309
|
/**
|
|
6201
6310
|
* Which axes the current placement allows.
|
|
6202
6311
|
*
|
|
@@ -6257,6 +6366,18 @@ var PanelPlacement = class {
|
|
|
6257
6366
|
this.#anchor = anchor;
|
|
6258
6367
|
this.#host.element.setAttribute("data-resize-anchor", `${anchor.y}-${anchor.x}`);
|
|
6259
6368
|
this.#focusableGrip();
|
|
6369
|
+
this.#stampHeader();
|
|
6370
|
+
}
|
|
6371
|
+
/**
|
|
6372
|
+
* Tell the stylesheet whether the panel is the screen, for the header's cursor.
|
|
6373
|
+
*
|
|
6374
|
+
* Only this half of what refuses a header drag: the resting rules already answer
|
|
6375
|
+
* for the placement and for data-launcher-drag="false", and neither of those
|
|
6376
|
+
* re-applies anything when it changes, so a stamp taking them in would go on
|
|
6377
|
+
* refusing, in the cursor, a drag the header would take.
|
|
6378
|
+
*/
|
|
6379
|
+
#stampHeader() {
|
|
6380
|
+
this.#header?.toggleAttribute("data-fills-screen", this.#fillsScreen());
|
|
6260
6381
|
}
|
|
6261
6382
|
/** Put a custom property back to a previous value, or remove it if there was none. */
|
|
6262
6383
|
#restoreProperty(name, value) {
|
|
@@ -6427,15 +6548,16 @@ var PanelPlacement = class {
|
|
|
6427
6548
|
return this.#host.element.getAttribute("data-launcher-drag") !== "false" && this.#surface().panelMovable;
|
|
6428
6549
|
}
|
|
6429
6550
|
/**
|
|
6430
|
-
* Whether a header drag may start now. A
|
|
6431
|
-
*
|
|
6432
|
-
*
|
|
6551
|
+
* Whether a header drag may start now. A panel that is the screen, on a phone
|
|
6552
|
+
* or by a host's own sizing, has nowhere to go, and a drag there would pull it
|
|
6553
|
+
* off the edges it fills.
|
|
6433
6554
|
*/
|
|
6434
6555
|
#canDragPanel() {
|
|
6435
|
-
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
|
|
6556
|
+
return this.#panelMovable() && !this.#fillsScreen();
|
|
6557
|
+
}
|
|
6558
|
+
/** Whether the panel covers the usable viewport, as it stands now. */
|
|
6559
|
+
#fillsScreen() {
|
|
6560
|
+
return coversViewport(this.#host.element.getBoundingClientRect(), this.#viewport());
|
|
6439
6561
|
}
|
|
6440
6562
|
/**
|
|
6441
6563
|
* Whether this placement lets the launcher be dragged, read per interaction
|
|
@@ -6568,9 +6690,6 @@ var PanelPlacement = class {
|
|
|
6568
6690
|
* back rather than leaving a stale inline one behind.
|
|
6569
6691
|
*/
|
|
6570
6692
|
#applyLauncherPlacement(at2) {
|
|
6571
|
-
if (!this.#launcherDraggable()) {
|
|
6572
|
-
return;
|
|
6573
|
-
}
|
|
6574
6693
|
this.#launcherPos = at2;
|
|
6575
6694
|
this.#panelPos = null;
|
|
6576
6695
|
const panel = this.#host.element.getBoundingClientRect();
|
|
@@ -6591,6 +6710,7 @@ var PanelPlacement = class {
|
|
|
6591
6710
|
}
|
|
6592
6711
|
/** Move the launcher live during a drag, without persisting. */
|
|
6593
6712
|
#moveLauncher(left, top) {
|
|
6713
|
+
this.#cornerSpot = { left, top };
|
|
6594
6714
|
this.#applyLauncherPlacement({ left, top });
|
|
6595
6715
|
}
|
|
6596
6716
|
/** Move the launcher and remember where, per tab, like the dragged size. */
|
|
@@ -6695,9 +6815,6 @@ var PanelPlacement = class {
|
|
|
6695
6815
|
* its own right.
|
|
6696
6816
|
*/
|
|
6697
6817
|
#restorePanelPosition(at2) {
|
|
6698
|
-
if (!this.#launcherDraggable()) {
|
|
6699
|
-
return;
|
|
6700
|
-
}
|
|
6701
6818
|
const rect = this.#host.element.getBoundingClientRect();
|
|
6702
6819
|
const held = clampPanel(
|
|
6703
6820
|
{ left: at2.left, top: at2.top, right: at2.left + rect.width, bottom: at2.top + rect.height },
|
|
@@ -6723,6 +6840,9 @@ var PanelPlacement = class {
|
|
|
6723
6840
|
* with it, the panel goes back where it was put; without it, the panel is
|
|
6724
6841
|
* re-derived from the launcher and opens into whatever room the viewport has
|
|
6725
6842
|
* now.
|
|
6843
|
+
*
|
|
6844
|
+
* Every caller is a gesture ending or a move being made, so where the two
|
|
6845
|
+
* stand now is what was stated. A restore never calls this.
|
|
6726
6846
|
*/
|
|
6727
6847
|
#storeLauncherPosition() {
|
|
6728
6848
|
const position = this.#launcherPos;
|
|
@@ -6730,38 +6850,140 @@ var PanelPlacement = class {
|
|
|
6730
6850
|
return;
|
|
6731
6851
|
}
|
|
6732
6852
|
const panel = this.#panelPos;
|
|
6733
|
-
this.#
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6853
|
+
this.#writeCornerSpot(panel === null ? position : { ...position, panel });
|
|
6854
|
+
}
|
|
6855
|
+
/** Make `spot` the stated one, and remember it. */
|
|
6856
|
+
#writeCornerSpot(spot) {
|
|
6857
|
+
this.#cornerSpot = spot;
|
|
6858
|
+
this.#host.writePreference(LAUNCHER_KEY, JSON.stringify(spot));
|
|
6737
6859
|
}
|
|
6738
6860
|
/**
|
|
6739
6861
|
* Re-apply the dragged position against the current viewport: on connect,
|
|
6740
6862
|
* whenever the window resizes, and before an expand. The viewport that
|
|
6741
6863
|
* stored a position may since have shrunk, and a launcher past the edge is
|
|
6742
6864
|
* unreachable -- it is the only way back to a collapsed conversation.
|
|
6865
|
+
*
|
|
6866
|
+
* The one gate on whether a stored position is this element's to honour: the
|
|
6867
|
+
* gestures check their own before they ever reach the placing below.
|
|
6743
6868
|
*/
|
|
6744
6869
|
restoreLauncherPosition() {
|
|
6870
|
+
this.#placeFromRecord(true);
|
|
6871
|
+
this.#stampHeader();
|
|
6872
|
+
}
|
|
6873
|
+
/**
|
|
6874
|
+
* Re-apply it for a change in the panel's own layout, which needs no window or
|
|
6875
|
+
* reopen to happen: a line typed in the composer is one. A position waiting to
|
|
6876
|
+
* be handed back under data-launcher-drag="false" waits on, because a panel that leaves for the
|
|
6877
|
+
* host's corner as the reader starts typing is a jump with no cause they can see.
|
|
6878
|
+
*/
|
|
6879
|
+
settleLauncherPosition() {
|
|
6880
|
+
this.#placeFromRecord(false);
|
|
6881
|
+
this.#stampHeader();
|
|
6882
|
+
}
|
|
6883
|
+
/** The placing behind {@link restoreLauncherPosition}. */
|
|
6884
|
+
#placeFromRecord(handBack) {
|
|
6745
6885
|
if (this.#docked()) {
|
|
6746
6886
|
this.#placeDocked();
|
|
6747
6887
|
return;
|
|
6748
6888
|
}
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
6889
|
+
if (!this.#surface().launcherDraggable) {
|
|
6890
|
+
return;
|
|
6891
|
+
}
|
|
6892
|
+
const draggable = this.#launcherDraggable();
|
|
6893
|
+
if (!draggable && this.#launcherPos !== null) {
|
|
6894
|
+
if (!handBack) {
|
|
6895
|
+
return;
|
|
6896
|
+
}
|
|
6897
|
+
this.releaseLauncherPosition();
|
|
6898
|
+
}
|
|
6899
|
+
const spot = draggable ? this.#cornerSpot ?? this.#readLauncherPosition() : null;
|
|
6900
|
+
if (spot === null) {
|
|
6901
|
+
this.#placeUnstated();
|
|
6752
6902
|
return;
|
|
6753
6903
|
}
|
|
6754
|
-
|
|
6755
|
-
|
|
6756
|
-
|
|
6757
|
-
|
|
6904
|
+
if (this.#standFullBleed(spot)) {
|
|
6905
|
+
return;
|
|
6906
|
+
}
|
|
6907
|
+
if (spot.panel !== void 0) {
|
|
6908
|
+
this.#launcherPos = { left: spot.left, top: spot.top };
|
|
6909
|
+
this.#restorePanelPosition(spot.panel);
|
|
6758
6910
|
return;
|
|
6759
6911
|
}
|
|
6760
6912
|
const box = this.#launcherBox();
|
|
6761
6913
|
this.#applyLauncherPlacement(
|
|
6762
|
-
clampLauncher({ ...box, left:
|
|
6914
|
+
clampLauncher({ ...box, left: spot.left, top: spot.top }, this.#viewport())
|
|
6763
6915
|
);
|
|
6764
6916
|
}
|
|
6917
|
+
/**
|
|
6918
|
+
* Leave a corner panel full-bleed if it has become the screen, and say whether
|
|
6919
|
+
* it has.
|
|
6920
|
+
*
|
|
6921
|
+
* The inline inset comes off, because the small-viewport block reads the
|
|
6922
|
+
* host's inset before its own: a spot written there holds the panel off the
|
|
6923
|
+
* edges it should fill, and past them by the same amount, since its size is
|
|
6924
|
+
* the screen's. What the panel covers is read before that, from the size
|
|
6925
|
+
* alone, which no inset changes.
|
|
6926
|
+
*
|
|
6927
|
+
* The launcher stays a place of its own. It is positioned from the host box,
|
|
6928
|
+
* so it is measured again from the box that has just moved, and it is held on
|
|
6929
|
+
* the screen, because it is the way back from a collapsed conversation. The
|
|
6930
|
+
* spot itself is untouched, for the next time there is room for it.
|
|
6931
|
+
*
|
|
6932
|
+
* Above the breakpoint nothing in the stylesheet takes the panel to the edges.
|
|
6933
|
+
* A host's own size makes it the screen while the resting inset still spends a
|
|
6934
|
+
* gutter on one corner, which hangs the box off the opposite one, so there it
|
|
6935
|
+
* stands at the start of the room the host left free and keeps that inset. A
|
|
6936
|
+
* box the placement already holds on the screen has no inset to keep, which is
|
|
6937
|
+
* every phone, and a host's rule that placed the box itself.
|
|
6938
|
+
*/
|
|
6939
|
+
#standFullBleed(spot) {
|
|
6940
|
+
const element = this.#host.element;
|
|
6941
|
+
const viewport = this.#viewport();
|
|
6942
|
+
if (!coversViewport(element.getBoundingClientRect(), viewport)) {
|
|
6943
|
+
return false;
|
|
6944
|
+
}
|
|
6945
|
+
element.style.removeProperty("--ag-ui-inset");
|
|
6946
|
+
const rest = element.getBoundingClientRect();
|
|
6947
|
+
const hanging = hangsOff(rest, viewport, this.#screen());
|
|
6948
|
+
const box = hanging ? atStartOf(viewport, rest) : rest;
|
|
6949
|
+
const launcher = { ...this.#launcherBox(), left: spot.left, top: spot.top };
|
|
6950
|
+
this.#placePanelAndLauncher(box, { ...launcher, ...clampLauncher(launcher, viewport) });
|
|
6951
|
+
if (!hanging) {
|
|
6952
|
+
element.style.removeProperty("--ag-ui-inset");
|
|
6953
|
+
}
|
|
6954
|
+
return true;
|
|
6955
|
+
}
|
|
6956
|
+
/**
|
|
6957
|
+
* Place a corner panel that has no spot, the half of {@link #standFullBleed}
|
|
6958
|
+
* with nothing stated to keep and no launcher of its own to measure.
|
|
6959
|
+
*
|
|
6960
|
+
* Only an inset this element wrote comes off or goes back. One the host wrote
|
|
6961
|
+
* inline is a token a host may state on a phone as anywhere else, and with no
|
|
6962
|
+
* spot it never came from here.
|
|
6963
|
+
*/
|
|
6964
|
+
#placeUnstated() {
|
|
6965
|
+
const element = this.#host.element;
|
|
6966
|
+
const inline = element.style.getPropertyValue("--ag-ui-inset");
|
|
6967
|
+
const viewport = this.#viewport();
|
|
6968
|
+
if (!coversViewport(element.getBoundingClientRect(), viewport)) {
|
|
6969
|
+
if (inline === "" || inline === this.#fillInset) {
|
|
6970
|
+
this.#restoreProperty("--ag-ui-inset", this.#gripInset ?? "");
|
|
6971
|
+
this.syncResizeAnchor();
|
|
6972
|
+
}
|
|
6973
|
+
this.#fillInset = null;
|
|
6974
|
+
return;
|
|
6975
|
+
}
|
|
6976
|
+
if (inline === this.#gripInset || inline === this.#fillInset) {
|
|
6977
|
+
element.style.removeProperty("--ag-ui-inset");
|
|
6978
|
+
}
|
|
6979
|
+
const rest = element.getBoundingClientRect();
|
|
6980
|
+
const screen = this.#screen();
|
|
6981
|
+
if (element.style.getPropertyValue("--ag-ui-inset") === "" && hangsOff(rest, viewport, screen)) {
|
|
6982
|
+
this.#fillInset = insetFrom({ x: "left", y: "top" }, atStartOf(viewport, rest), screen);
|
|
6983
|
+
element.style.setProperty("--ag-ui-inset", this.#fillInset);
|
|
6984
|
+
this.syncResizeAnchor();
|
|
6985
|
+
}
|
|
6986
|
+
}
|
|
6765
6987
|
/** The persisted position for this instance, or null. */
|
|
6766
6988
|
#readLauncherPosition() {
|
|
6767
6989
|
const raw = this.#host.readPreference(LAUNCHER_KEY);
|
|
@@ -6796,9 +7018,15 @@ var PanelPlacement = class {
|
|
|
6796
7018
|
if (this.#launcherDraggable()) {
|
|
6797
7019
|
return;
|
|
6798
7020
|
}
|
|
7021
|
+
this.#forgetCornerPosition();
|
|
7022
|
+
}
|
|
7023
|
+
/** Take everything off that placed a corner panel, leaving its record alone. */
|
|
7024
|
+
#forgetCornerPosition() {
|
|
6799
7025
|
this.#launcherPos = null;
|
|
6800
7026
|
this.#panelPos = null;
|
|
6801
7027
|
this.#expandCorner = null;
|
|
7028
|
+
this.#gripInset = null;
|
|
7029
|
+
this.#fillInset = null;
|
|
6802
7030
|
this.#host.element.style.removeProperty("--ag-ui-inset");
|
|
6803
7031
|
this.#host.element.style.removeProperty("--ag-ui-launcher-inset");
|
|
6804
7032
|
this.#host.element.removeAttribute("data-expand-corner");
|
|
@@ -6834,26 +7062,32 @@ var PanelPlacement = class {
|
|
|
6834
7062
|
if (this.#docked()) {
|
|
6835
7063
|
this.#dockPos = { left: box.left, top: box.top };
|
|
6836
7064
|
}
|
|
6837
|
-
if (grip.x
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
7065
|
+
if (grip.x === this.#anchor.x || grip.y === this.#anchor.y) {
|
|
7066
|
+
const anchor = this.#anchor;
|
|
7067
|
+
const inset2 = insetFrom(anchor, box, this.#screen());
|
|
7068
|
+
this.#host.element.style.setProperty("--ag-ui-inset", inset2);
|
|
7069
|
+
this.#gripInset = this.#launcherPos === null && !this.#docked() ? inset2 : null;
|
|
7070
|
+
if (this.#launcherPos !== null) {
|
|
7071
|
+
const size = this.#host.launcher.offsetWidth;
|
|
7072
|
+
this.#launcherPos = {
|
|
7073
|
+
left: anchor.x === "left" ? box.left : box.right - size,
|
|
7074
|
+
top: anchor.y === "top" ? box.top : box.bottom - size
|
|
7075
|
+
};
|
|
7076
|
+
}
|
|
6848
7077
|
}
|
|
6849
|
-
if (this.#panelPos !== null) {
|
|
6850
|
-
|
|
7078
|
+
if (this.#panelPos !== null && !this.#docked()) {
|
|
7079
|
+
const drawn = this.#host.element.getBoundingClientRect();
|
|
7080
|
+
this.#panelPos = { left: drawn.left, top: drawn.top };
|
|
6851
7081
|
}
|
|
6852
7082
|
return box;
|
|
6853
7083
|
}
|
|
6854
7084
|
/** Finish a resize: keep the box, remember it, and re-read the pinned edges. */
|
|
6855
7085
|
#commitResize(grip, box) {
|
|
6856
7086
|
const held = this.#applyResize(grip, box);
|
|
7087
|
+
if (this.#host.element.style.getPropertyValue("--ag-ui-inset") === this.#fillInset) {
|
|
7088
|
+
this.#gripInset = this.#fillInset;
|
|
7089
|
+
this.#fillInset = null;
|
|
7090
|
+
}
|
|
6857
7091
|
this.#persistSize({ width: held.right - held.left, height: held.bottom - held.top });
|
|
6858
7092
|
this.#storeLauncherPosition();
|
|
6859
7093
|
if (this.#dockPos !== null) {
|
|
@@ -10706,6 +10940,15 @@ var FRAME_STYLES = `
|
|
|
10706
10940
|
touch-action: auto;
|
|
10707
10941
|
}
|
|
10708
10942
|
|
|
10943
|
+
/* A panel that is the screen has nowhere to go, so its header refuses the drag
|
|
10944
|
+
and must not offer it. No selector can see that a host has sized the panel to
|
|
10945
|
+
the window, so the placement stamps this from the measurement that refuses the
|
|
10946
|
+
drag. :host is carried for the specificity, not the scope, as below. Before the
|
|
10947
|
+
dragging rule, so a drag the header did take keeps its grabbing cursor. */
|
|
10948
|
+
:host .header[data-fills-screen] {
|
|
10949
|
+
cursor: auto;
|
|
10950
|
+
}
|
|
10951
|
+
|
|
10709
10952
|
/* :host is carried for the specificity, not the scope: the placement rules
|
|
10710
10953
|
above are a host selector plus a class plus an attribute, and a bare
|
|
10711
10954
|
.header[data-dragging] loses to them -- silently, because the drag still
|
|
@@ -10755,6 +10998,14 @@ var FRAME_STYLES = `
|
|
|
10755
10998
|
flex: none;
|
|
10756
10999
|
}
|
|
10757
11000
|
|
|
11001
|
+
/* Under every theme: once the host sets the header text, the header behind the
|
|
11002
|
+
buttons is the host's colour, so their rest opacity goes. The frame's 0.85
|
|
11003
|
+
lets the header through the glyph, which took white on a mid-blue header from
|
|
11004
|
+
5.1:1 to 4.2:1. With the header text set, the opacity below reads a colour,
|
|
11005
|
+
which no opacity can be, so it is invalid at computed-value time and falls to
|
|
11006
|
+
the initial 1; unset, it reads the fallback. The glyph is each theme's own
|
|
11007
|
+
business: this inherits the header text, and a theme that draws the buttons
|
|
11008
|
+
in another ink reads the same switch to yield. */
|
|
10758
11009
|
.header-btn {
|
|
10759
11010
|
display: inline-flex;
|
|
10760
11011
|
flex: 0 0 auto;
|
|
@@ -10771,12 +11022,15 @@ var FRAME_STYLES = `
|
|
|
10771
11022
|
padding: 0;
|
|
10772
11023
|
border-radius: 6px;
|
|
10773
11024
|
cursor: pointer;
|
|
10774
|
-
opacity: 0.85;
|
|
11025
|
+
opacity: var(--_header-fg-set, 0.85);
|
|
10775
11026
|
}
|
|
10776
11027
|
|
|
11028
|
+
/* The square is the host's own when it set one; otherwise it is mixed from the
|
|
11029
|
+
header text when the host set that, so it reads on any header the host
|
|
11030
|
+
painted; otherwise it is the theme's own. See the alias in the token defaults. */
|
|
10777
11031
|
.header-btn:hover {
|
|
10778
11032
|
opacity: 1;
|
|
10779
|
-
background:
|
|
11033
|
+
background: var(--_header-btn-hover);
|
|
10780
11034
|
}
|
|
10781
11035
|
`;
|
|
10782
11036
|
|
|
@@ -10854,18 +11108,19 @@ var TOKEN_STYLES = `
|
|
|
10854
11108
|
/* Switches: a public token read with no fallback, named for it with -set.
|
|
10855
11109
|
With the token unset the switch computes to the guaranteed-invalid value,
|
|
10856
11110
|
so a rule that reads it with a fallback gets the fallback; that is how a
|
|
10857
|
-
rule tells a token the host set from the theme's default for it.
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
10861
|
-
drew). */
|
|
11111
|
+
rule tells a token the host set from the theme's default for it. Every
|
|
11112
|
+
theme's header buttons follow the header text only once a host sets it,
|
|
11113
|
+
and a step group's calls follow the tool token only once a host sets it
|
|
11114
|
+
(classic defaults --_tool-fg to the accent, which a group never drew). */
|
|
10862
11115
|
--_header-fg-set: var(--ag-ui-header-fg);
|
|
10863
11116
|
--_tool-fg-set: var(--ag-ui-tool-fg);
|
|
10864
11117
|
/* The header buttons' hover square, by default, once the header text is
|
|
10865
11118
|
set. Here it is the text at about a fifth, which every browser can mix;
|
|
10866
11119
|
where relative colour syntax is supported (see the block at the end) it
|
|
10867
11120
|
is the text's opposite instead. It reads the switch, so it is unset with
|
|
10868
|
-
it, and the square below falls to the panel's hover shade
|
|
11121
|
+
it, and the square below falls to the theme's own: the panel's hover shade
|
|
11122
|
+
here, restated by each theme that draws another, so one rule in the frame
|
|
11123
|
+
paints them all. */
|
|
10869
11124
|
--_header-btn-hover-auto: color-mix(in srgb, var(--_header-fg-set) 18%, transparent);
|
|
10870
11125
|
--_header-btn-hover: var(--ag-ui-header-btn-hover, var(--_header-btn-hover-auto, var(--_hover)));
|
|
10871
11126
|
--_border: var(--ag-ui-border, var(--_line));
|
|
@@ -11306,6 +11561,7 @@ var CLASSIC_TOKENS = `
|
|
|
11306
11561
|
--_tool-fg: var(--ag-ui-tool-fg, var(--_accent));
|
|
11307
11562
|
--_header-bg: var(--ag-ui-header-bg, light-dark(var(--_accent), #1f1f30));
|
|
11308
11563
|
--_header-fg: var(--ag-ui-header-fg, light-dark(#ffffff, #e8e8f2));
|
|
11564
|
+
--_header-btn-hover: var(--ag-ui-header-btn-hover, var(--_header-btn-hover-auto, rgba(255, 255, 255, 0.18)));
|
|
11309
11565
|
--_border: var(--ag-ui-border, light-dark(#e2e2ec, #33334a));
|
|
11310
11566
|
--_muted: var(--ag-ui-muted, light-dark(#6b7280, #9aa0b4));
|
|
11311
11567
|
--_success: var(--ag-ui-success, #15803d);
|
|
@@ -11392,14 +11648,15 @@ var LEDGER_STYLES = `
|
|
|
11392
11648
|
vertical-align: 1px;
|
|
11393
11649
|
}
|
|
11394
11650
|
|
|
11651
|
+
/* Both inks yield once the host sets the header text, since the header behind
|
|
11652
|
+
them is then the host's colour (see the switches in the token defaults). */
|
|
11395
11653
|
:host([theme~="ledger"]) .header-btn {
|
|
11396
|
-
color: var(--_ink-3);
|
|
11654
|
+
color: var(--_header-fg-set, var(--_ink-3));
|
|
11397
11655
|
border-radius: 3px;
|
|
11398
11656
|
}
|
|
11399
11657
|
|
|
11400
11658
|
:host([theme~="ledger"]) .header-btn:hover {
|
|
11401
|
-
|
|
11402
|
-
color: var(--_fg);
|
|
11659
|
+
color: var(--_header-fg-set, var(--_fg));
|
|
11403
11660
|
}
|
|
11404
11661
|
|
|
11405
11662
|
:host([theme~="ledger"]) .message--user {
|
|
@@ -11549,6 +11806,7 @@ var LEDGER_TOKENS = `
|
|
|
11549
11806
|
--_msg-radius: var(--ag-ui-msg-radius, 0px);
|
|
11550
11807
|
--_composer-radius: var(--ag-ui-composer-radius, 4px);
|
|
11551
11808
|
--_user-bg: var(--ag-ui-user-bg, transparent);
|
|
11809
|
+
--_header-btn-hover: var(--ag-ui-header-btn-hover, var(--_header-btn-hover-auto, var(--_hover)));
|
|
11552
11810
|
--_frame-shadow: var(--ag-ui-frame-shadow, 0 0 0 1px var(--_line-strong), 0 20px 40px -28px rgb(0 0 0 / 0.45));
|
|
11553
11811
|
--_launcher-bg: var(--ag-ui-launcher-bg, var(--_fg));
|
|
11554
11812
|
--_launcher-fg: var(--ag-ui-launcher-fg, var(--_bg));
|
|
@@ -11669,28 +11927,15 @@ ${THEME_HOST.quiet} .header-title {
|
|
|
11669
11927
|
|
|
11670
11928
|
/* The buttons sit back in the third ink on the panel. Once the host sets the
|
|
11671
11929
|
header text they draw in it instead, since the header behind them is then
|
|
11672
|
-
the host's colour (see the switches in the token defaults).
|
|
11673
|
-
rest opacity: the frame's 0.85 lets the header through the glyph, which
|
|
11674
|
-
took white on a mid-blue header from 5.1:1 to 4.2:1. With the header text
|
|
11675
|
-
set, the opacity below reads a colour, which no opacity can be, so it is
|
|
11676
|
-
invalid at computed-value time and falls to the initial 1; unset, it reads
|
|
11677
|
-
the fallback, the frame's own 0.85. */
|
|
11930
|
+
the host's colour (see the switches in the token defaults). */
|
|
11678
11931
|
${THEME_HOST.quiet} .header-btn {
|
|
11679
11932
|
color: var(--_header-fg-set, var(--_ink-3));
|
|
11680
|
-
opacity: var(--_header-fg-set, 0.85);
|
|
11681
11933
|
border-radius: 8px;
|
|
11682
11934
|
}
|
|
11683
11935
|
|
|
11684
|
-
/* The
|
|
11685
|
-
from the header text when the host set that, so it reads on any header the
|
|
11686
|
-
host painted; otherwise it is the panel shade.
|
|
11687
|
-
The glyph takes the header text, which is the full ink when that is unset.
|
|
11688
|
-
The opacity restates the frame's hover value, which the rest rule above
|
|
11689
|
-
outweighs. */
|
|
11936
|
+
/* The glyph takes the header text, which is the full ink when that is unset. */
|
|
11690
11937
|
${THEME_HOST.quiet} .header-btn:hover {
|
|
11691
11938
|
color: var(--_header-fg);
|
|
11692
|
-
opacity: 1;
|
|
11693
|
-
background: var(--_header-btn-hover);
|
|
11694
11939
|
}
|
|
11695
11940
|
|
|
11696
11941
|
${THEME_HOST.quiet} .message--user {
|
|
@@ -11833,14 +12078,15 @@ var SOFT_STYLES = `
|
|
|
11833
12078
|
background: linear-gradient(140deg, color-mix(in oklch, var(--_accent) 55%, var(--_bg)), var(--_accent));
|
|
11834
12079
|
}
|
|
11835
12080
|
|
|
12081
|
+
/* Both inks yield once the host sets the header text, since the header behind
|
|
12082
|
+
them is then the host's colour (see the switches in the token defaults). */
|
|
11836
12083
|
:host([theme~="soft"]) .header-btn {
|
|
11837
|
-
color: var(--_ink-3);
|
|
12084
|
+
color: var(--_header-fg-set, var(--_ink-3));
|
|
11838
12085
|
border-radius: 10px;
|
|
11839
12086
|
}
|
|
11840
12087
|
|
|
11841
12088
|
:host([theme~="soft"]) .header-btn:hover {
|
|
11842
|
-
|
|
11843
|
-
color: var(--_accent-ink);
|
|
12089
|
+
color: var(--_header-fg-set, var(--_accent-ink));
|
|
11844
12090
|
}
|
|
11845
12091
|
|
|
11846
12092
|
:host([theme~="soft"]) .messages {
|
|
@@ -11961,6 +12207,7 @@ var SOFT_TOKENS = `
|
|
|
11961
12207
|
--_tint: var(--ag-ui-tint, color-mix(in oklch, var(--_accent) 5%, var(--_bg)));
|
|
11962
12208
|
--_tint-2: var(--ag-ui-tint-2, color-mix(in oklch, var(--_accent) 13%, var(--_bg)));
|
|
11963
12209
|
--_header-bg: var(--ag-ui-header-bg, var(--_tint));
|
|
12210
|
+
--_header-btn-hover: var(--ag-ui-header-btn-hover, var(--_header-btn-hover-auto, var(--_tint-2)));
|
|
11964
12211
|
--_user-bg: var(--ag-ui-user-bg, var(--_tint-2));
|
|
11965
12212
|
--_border: var(--ag-ui-border, color-mix(in oklch, var(--_accent) 14%, var(--_bg)));
|
|
11966
12213
|
--_radius: var(--ag-ui-radius, 16px);
|
|
@@ -19847,13 +20094,26 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19847
20094
|
* a field so `removeEventListener` on disconnect gets the same reference.
|
|
19848
20095
|
*/
|
|
19849
20096
|
#onViewportResize = () => {
|
|
19850
|
-
this.#
|
|
19851
|
-
|
|
19852
|
-
if (this.#placement.dragging()) {
|
|
19853
|
-
return;
|
|
20097
|
+
if (this.#readyToPlace()) {
|
|
20098
|
+
this.#placement.restoreLauncherPosition();
|
|
19854
20099
|
}
|
|
19855
|
-
this.#placement.restoreLauncherPosition();
|
|
19856
20100
|
};
|
|
20101
|
+
/**
|
|
20102
|
+
* The same for a change only the panel's own layout shows: a host's size, a
|
|
20103
|
+
* viewport inset token, a line typed in the composer. Not a moment to hand a
|
|
20104
|
+
* position back, so a panel under data-launcher-drag="false" stays put.
|
|
20105
|
+
*/
|
|
20106
|
+
#onLayoutChange = () => {
|
|
20107
|
+
if (this.#readyToPlace()) {
|
|
20108
|
+
this.#placement.settleLauncherPosition();
|
|
20109
|
+
}
|
|
20110
|
+
};
|
|
20111
|
+
/** Bring the viewport's readings up to date, and say whether placing may follow. */
|
|
20112
|
+
#readyToPlace() {
|
|
20113
|
+
this.#placement.publishVisualViewport();
|
|
20114
|
+
this.#syncDock();
|
|
20115
|
+
return !this.#placement.dragging();
|
|
20116
|
+
}
|
|
19857
20117
|
/** Mic button mount point (input row); the control mounts on connect when enabled. */
|
|
19858
20118
|
#voiceSlot;
|
|
19859
20119
|
/** The composer's mic, mounted on connect when transcription is available. */
|
|
@@ -20646,6 +20906,12 @@ var AgUiChat = class extends HTMLElement {
|
|
|
20646
20906
|
const dockObserver = new ResizeObserver(() => this.#syncDock());
|
|
20647
20907
|
dockObserver.observe(this.#dockBar);
|
|
20648
20908
|
this.#connection.signal.addEventListener("abort", () => dockObserver.disconnect());
|
|
20909
|
+
const layoutObserver = new ResizeObserver(this.#onLayoutChange);
|
|
20910
|
+
layoutObserver.observe(this.#messages);
|
|
20911
|
+
this.#connection.signal.addEventListener("abort", () => layoutObserver.disconnect());
|
|
20912
|
+
this.#placement.probe.addEventListener("transitionrun", this.#onLayoutChange, {
|
|
20913
|
+
signal: this.#connection.signal
|
|
20914
|
+
});
|
|
20649
20915
|
this.#syncDock();
|
|
20650
20916
|
if (this.#surface().collapseTo === "none") {
|
|
20651
20917
|
this.dispatchEvent(
|
|
@@ -21578,6 +21844,8 @@ var AgUiChat = class extends HTMLElement {
|
|
|
21578
21844
|
const probe = this.#placement.probe;
|
|
21579
21845
|
probe.className = "viewport-probe";
|
|
21580
21846
|
probe.setAttribute("aria-hidden", "true");
|
|
21847
|
+
probe.style.borderRadius = "var(--_viewport-inset-top) var(--_viewport-inset-right) var(--_viewport-inset-bottom) var(--_viewport-inset-left)";
|
|
21848
|
+
probe.style.transition = "border-radius 1ms";
|
|
21581
21849
|
this.#root.replaceChildren(probe, this.#announcer.region, this.#chat, this.#dockBar);
|
|
21582
21850
|
}
|
|
21583
21851
|
/**
|
|
@@ -22225,7 +22493,7 @@ function setControlValue(el2, value) {
|
|
|
22225
22493
|
}
|
|
22226
22494
|
|
|
22227
22495
|
// src/version.ts
|
|
22228
|
-
var VERSION = "0.
|
|
22496
|
+
var VERSION = "0.50.0";
|
|
22229
22497
|
export {
|
|
22230
22498
|
ATTACHMENT_EVENT,
|
|
22231
22499
|
AgUiChat,
|