@artooi/ag-ui-web-component 0.48.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 +192 -1
- package/README.md +70 -7
- package/dist/ag-ui-web-component.bundle.js +171 -107
- package/dist/ag-ui-web-component.bundle.js.map +3 -3
- package/dist/core/ag_ui_chat.d.ts +8 -2
- package/dist/core/ag_ui_chat.d.ts.map +1 -1
- package/dist/index.js +591 -82
- package/dist/index.js.map +3 -3
- 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/dock_styles.d.ts.map +1 -1
- package/dist/ui/placement/panel_placement.d.ts +18 -1
- package/dist/ui/placement/panel_placement.d.ts.map +1 -1
- package/dist/ui/placement/surface_for.d.ts +15 -6
- package/dist/ui/placement/surface_for.d.ts.map +1 -1
- package/dist/ui/progress/tool_group_styles.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 +56 -8
- package/src/tools/chat_surface_tools.ts +11 -10
- package/src/ui/placement/dock_styles.ts +5 -1
- package/src/ui/placement/panel_placement.ts +587 -82
- package/src/ui/placement/surface_for.ts +33 -8
- package/src/ui/progress/tool_group_styles.ts +3 -2
- package/src/ui/shell/frame_styles.ts +22 -2
- package/src/ui/shell/token_styles.ts +31 -0
- 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 +6 -3
- 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
|
@@ -284,7 +284,7 @@ function createChatSurfaceTools(surface) {
|
|
|
284
284
|
if (!report.movable) {
|
|
285
285
|
return {
|
|
286
286
|
moved: false,
|
|
287
|
-
reason: report.fullBleed ? "the panel fills the screen, so there is nowhere to move it to" : report.
|
|
287
|
+
reason: report.fullBleed ? "the panel fills the screen, so there is nowhere to move it to" : report.draggable === false ? "this page has turned off moving the panel" : `the "${report.placement ?? ""}" placement owns the panel's position`,
|
|
288
288
|
suggestion: report.collapsible ? "minimise_chat" : null
|
|
289
289
|
};
|
|
290
290
|
}
|
|
@@ -5810,12 +5810,14 @@ function boxAt(grip, axis, rect, x2, y2) {
|
|
|
5810
5810
|
var CORNER = {
|
|
5811
5811
|
collapseTo: "launcher",
|
|
5812
5812
|
launcherDraggable: true,
|
|
5813
|
+
panelMovable: true,
|
|
5813
5814
|
resizeAxis: "both",
|
|
5814
5815
|
startsCollapsed: true
|
|
5815
5816
|
};
|
|
5816
5817
|
var DOCKED = {
|
|
5817
5818
|
collapseTo: "launcher",
|
|
5818
5819
|
launcherDraggable: false,
|
|
5820
|
+
panelMovable: false,
|
|
5819
5821
|
resizeAxis: "width",
|
|
5820
5822
|
startsCollapsed: false
|
|
5821
5823
|
};
|
|
@@ -5831,22 +5833,36 @@ var SURFACES = /* @__PURE__ */ new Map([
|
|
|
5831
5833
|
{
|
|
5832
5834
|
collapseTo: "launcher",
|
|
5833
5835
|
launcherDraggable: false,
|
|
5836
|
+
panelMovable: false,
|
|
5834
5837
|
resizeAxis: "none",
|
|
5835
5838
|
startsCollapsed: false
|
|
5836
5839
|
}
|
|
5837
5840
|
],
|
|
5838
5841
|
[
|
|
5839
5842
|
"page",
|
|
5840
|
-
{
|
|
5843
|
+
{
|
|
5844
|
+
collapseTo: null,
|
|
5845
|
+
launcherDraggable: false,
|
|
5846
|
+
panelMovable: false,
|
|
5847
|
+
resizeAxis: "none",
|
|
5848
|
+
startsCollapsed: false
|
|
5849
|
+
}
|
|
5841
5850
|
],
|
|
5842
5851
|
[
|
|
5843
5852
|
"embedded",
|
|
5844
|
-
{
|
|
5853
|
+
{
|
|
5854
|
+
collapseTo: "header",
|
|
5855
|
+
launcherDraggable: false,
|
|
5856
|
+
panelMovable: false,
|
|
5857
|
+
resizeAxis: "both",
|
|
5858
|
+
startsCollapsed: false
|
|
5859
|
+
}
|
|
5845
5860
|
]
|
|
5846
5861
|
]);
|
|
5847
5862
|
var UNKNOWN = {
|
|
5848
5863
|
collapseTo: "launcher",
|
|
5849
5864
|
launcherDraggable: false,
|
|
5865
|
+
panelMovable: false,
|
|
5850
5866
|
resizeAxis: "both",
|
|
5851
5867
|
startsCollapsed: false
|
|
5852
5868
|
};
|
|
@@ -5868,6 +5884,7 @@ var DRAG_HEIGHT = "--_drag-height";
|
|
|
5868
5884
|
var DOCK_BOTTOM = "--_dock-bottom";
|
|
5869
5885
|
var DOCK_RIGHT = "--_dock-right";
|
|
5870
5886
|
var LAUNCHER_KEY = "ag-ui-chat:launcher";
|
|
5887
|
+
var DOCK_KEY = "ag-ui-chat:dock";
|
|
5871
5888
|
function asPoint(value) {
|
|
5872
5889
|
if (typeof value !== "object" || value === null) {
|
|
5873
5890
|
return null;
|
|
@@ -5878,6 +5895,18 @@ function asPoint(value) {
|
|
|
5878
5895
|
function coversViewport(box, viewport) {
|
|
5879
5896
|
return box.width >= viewport.width - 1 && box.height >= viewport.height - 1;
|
|
5880
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
|
+
}
|
|
5881
5910
|
function insetFrom(corner, box, screen) {
|
|
5882
5911
|
const side = (value) => `${Math.round(value)}px`;
|
|
5883
5912
|
return [
|
|
@@ -5907,8 +5936,9 @@ var PanelPlacement = class {
|
|
|
5907
5936
|
* header on screen, and the launcher is the handle then.
|
|
5908
5937
|
*/
|
|
5909
5938
|
enablePanelDrag(header) {
|
|
5939
|
+
this.#header = header;
|
|
5910
5940
|
enablePanelDrag(header, {
|
|
5911
|
-
enabled: () => !this.#host.collapsed() && this.#
|
|
5941
|
+
enabled: () => !this.#host.collapsed() && this.#canDragPanel(),
|
|
5912
5942
|
rect: () => this.#host.element.getBoundingClientRect(),
|
|
5913
5943
|
apply: (box, from) => this.#movePanel(box, from),
|
|
5914
5944
|
commit: (box, from) => this.#commitPanel(box, from)
|
|
@@ -5931,12 +5961,19 @@ var PanelPlacement = class {
|
|
|
5931
5961
|
}
|
|
5932
5962
|
/** Build the eight resize grips into `chat`, with one of them in the tab order. */
|
|
5933
5963
|
mountResizeGrips(chat) {
|
|
5964
|
+
this.#resizing = false;
|
|
5934
5965
|
for (const grip of RESIZE_GRIPS) {
|
|
5935
5966
|
const handle = createResizeHandle(grip, {
|
|
5936
5967
|
axis: () => this.#resizeAxis(),
|
|
5937
5968
|
rect: () => this.#host.element.getBoundingClientRect(),
|
|
5938
|
-
apply: (box) =>
|
|
5939
|
-
|
|
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
|
+
},
|
|
5940
5977
|
label: this.#host.strings().resizePanel
|
|
5941
5978
|
});
|
|
5942
5979
|
handle.tabIndex = -1;
|
|
@@ -5954,13 +5991,63 @@ var PanelPlacement = class {
|
|
|
5954
5991
|
* Drop the dragged size and its stored copy, so the placement's own size and
|
|
5955
5992
|
* the host's tokens apply again. For a host entering a sized state of its
|
|
5956
5993
|
* own, which a user's drag would otherwise outrank.
|
|
5994
|
+
*
|
|
5995
|
+
* A docked panel the user dragged off its dock goes back to it as well, and
|
|
5996
|
+
* the stored spot with it: there the position is part of the same resting
|
|
5997
|
+
* state the host is asking for. A corner panel keeps a dragged position, as
|
|
5998
|
+
* it always has.
|
|
5957
5999
|
*/
|
|
5958
6000
|
resetSize() {
|
|
6001
|
+
const sized = this.#host.element.getBoundingClientRect();
|
|
5959
6002
|
this.#host.element.style.removeProperty(DRAG_WIDTH);
|
|
5960
6003
|
this.#host.element.style.removeProperty(DRAG_HEIGHT);
|
|
5961
6004
|
this.#host.clearPreference(SIZE_KEY);
|
|
6005
|
+
if (this.#docked()) {
|
|
6006
|
+
if (this.#dockPos !== null) {
|
|
6007
|
+
this.#host.element.style.removeProperty("--ag-ui-inset");
|
|
6008
|
+
}
|
|
6009
|
+
this.#dockPos = null;
|
|
6010
|
+
this.#storeDockPosition(null);
|
|
6011
|
+
} else {
|
|
6012
|
+
this.#carrySpotWithSize(sized);
|
|
6013
|
+
}
|
|
5962
6014
|
this.syncResizeAnchor();
|
|
5963
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
|
+
}
|
|
5964
6051
|
/**
|
|
5965
6052
|
* A zero-sized box carrying the host's viewport insets as padding, so they
|
|
5966
6053
|
* can be read back as used pixel lengths. See the `.viewport-probe` rule for
|
|
@@ -5985,6 +6072,49 @@ var PanelPlacement = class {
|
|
|
5985
6072
|
* from the launcher would move the panel the user just placed.
|
|
5986
6073
|
*/
|
|
5987
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;
|
|
6101
|
+
/**
|
|
6102
|
+
* Where the user dragged a docked panel, in viewport coordinates, or null
|
|
6103
|
+
* while it stands on the bar or the anchor.
|
|
6104
|
+
*
|
|
6105
|
+
* Apart from the two corner positions above because it moves nothing else:
|
|
6106
|
+
* a docked panel has no launcher to carry, and the corner it opens from is
|
|
6107
|
+
* the dock's. Held as the user stated it and never as clamped, so a bar that
|
|
6108
|
+
* grew, or a phone that took the panel full-bleed, gives the spot back
|
|
6109
|
+
* unchanged once there is room for it again.
|
|
6110
|
+
*/
|
|
6111
|
+
#dockPos = null;
|
|
6112
|
+
/**
|
|
6113
|
+
* The line a docked panel stays above, in viewport coordinates: the bar's
|
|
6114
|
+
* top, or the anchor's. Infinite where neither is drawn. Measured by
|
|
6115
|
+
* syncDock, which runs on every change either can make.
|
|
6116
|
+
*/
|
|
6117
|
+
#dockTop = Number.POSITIVE_INFINITY;
|
|
5988
6118
|
/**
|
|
5989
6119
|
* The corner the panel opens away from, once this element is placing itself.
|
|
5990
6120
|
* Null means the host's layout still decides, and the anchor is measured.
|
|
@@ -5996,6 +6126,10 @@ var PanelPlacement = class {
|
|
|
5996
6126
|
* second while the panel is already being laid out on every one of them.
|
|
5997
6127
|
*/
|
|
5998
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;
|
|
5999
6133
|
/** The eight grips, by name, so the keyboard-reachable one can be moved. */
|
|
6000
6134
|
#resizeHandles = /* @__PURE__ */ new Map();
|
|
6001
6135
|
/**
|
|
@@ -6013,7 +6147,7 @@ var PanelPlacement = class {
|
|
|
6013
6147
|
* rather than collapsed to nothing.
|
|
6014
6148
|
*/
|
|
6015
6149
|
#withinViewport(box) {
|
|
6016
|
-
const viewport = this.#viewport();
|
|
6150
|
+
const viewport = this.#docked() && this.#panelMovable() ? this.#dockRoom() : this.#viewport();
|
|
6017
6151
|
const left = viewport.left + SCREEN_EDGE_MARGIN;
|
|
6018
6152
|
const top = viewport.top + SCREEN_EDGE_MARGIN;
|
|
6019
6153
|
const right = viewport.left + viewport.width - SCREEN_EDGE_MARGIN;
|
|
@@ -6030,10 +6164,12 @@ var PanelPlacement = class {
|
|
|
6030
6164
|
*
|
|
6031
6165
|
* Read from the stamp the drag helpers already set, rather than tracked
|
|
6032
6166
|
* separately: one source of truth, and it clears on `pointercancel` as well
|
|
6033
|
-
* 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.
|
|
6034
6170
|
*/
|
|
6035
6171
|
dragging() {
|
|
6036
|
-
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;
|
|
6037
6173
|
}
|
|
6038
6174
|
/** The report behind `AgUiChat.describeSurface`, whose doc is the contract. */
|
|
6039
6175
|
describeSurface() {
|
|
@@ -6045,8 +6181,13 @@ var PanelPlacement = class {
|
|
|
6045
6181
|
collapseTo: this.#surface().collapseTo,
|
|
6046
6182
|
collapsed: this.#host.collapsed(),
|
|
6047
6183
|
collapsible: this.#host.collapsible(),
|
|
6048
|
-
movable: this.#
|
|
6049
|
-
|
|
6184
|
+
movable: this.#panelMovable() && !fullBleed,
|
|
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",
|
|
6050
6191
|
fullBleed,
|
|
6051
6192
|
box: {
|
|
6052
6193
|
left: Math.round(box.left),
|
|
@@ -6064,7 +6205,7 @@ var PanelPlacement = class {
|
|
|
6064
6205
|
}
|
|
6065
6206
|
/** The move behind `AgUiChat.moveTo`, whose doc is the contract. */
|
|
6066
6207
|
moveTo(corner, options = {}) {
|
|
6067
|
-
if (!this.#
|
|
6208
|
+
if (!this.#panelMovable()) {
|
|
6068
6209
|
return false;
|
|
6069
6210
|
}
|
|
6070
6211
|
const restore = options.announce === true ? this.#captureGeometry() : null;
|
|
@@ -6074,11 +6215,22 @@ var PanelPlacement = class {
|
|
|
6074
6215
|
return false;
|
|
6075
6216
|
}
|
|
6076
6217
|
const [edgeY, edgeX] = corner.split("-");
|
|
6077
|
-
const
|
|
6078
|
-
const
|
|
6079
|
-
const
|
|
6080
|
-
const
|
|
6218
|
+
const docked = this.#docked();
|
|
6219
|
+
const room = docked ? this.#dockRoom() : viewport;
|
|
6220
|
+
const nearX = room.left + EDGE_MARGIN;
|
|
6221
|
+
const nearY = room.top + EDGE_MARGIN;
|
|
6222
|
+
const left = edgeX === "left" ? nearX : Math.max(nearX, room.left + room.width - EDGE_MARGIN - box.width);
|
|
6223
|
+
const top = edgeY === "top" ? nearY : Math.max(nearY, room.top + room.height - EDGE_MARGIN - box.height);
|
|
6081
6224
|
const host = { left, top, right: left + box.width, bottom: top + box.height };
|
|
6225
|
+
if (docked) {
|
|
6226
|
+
this.#dockPos = { left, top };
|
|
6227
|
+
this.#writeDockInset(host);
|
|
6228
|
+
this.#storeDockPosition(this.#dockPos);
|
|
6229
|
+
if (restore !== null) {
|
|
6230
|
+
this.#host.announceSurfaceChange(this.#host.strings().chatMoved, restore);
|
|
6231
|
+
}
|
|
6232
|
+
return true;
|
|
6233
|
+
}
|
|
6082
6234
|
const launcherWidth = this.#host.launcher.offsetWidth;
|
|
6083
6235
|
const launcherHeight = this.#host.launcher.offsetHeight;
|
|
6084
6236
|
this.#placePanelAndLauncher(host, {
|
|
@@ -6102,6 +6254,13 @@ var PanelPlacement = class {
|
|
|
6102
6254
|
* puts the box back and animates it out of the wrong side. Absent values are
|
|
6103
6255
|
* captured as absent and removed on the way back, rather than written as
|
|
6104
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.
|
|
6105
6264
|
*/
|
|
6106
6265
|
#captureGeometry() {
|
|
6107
6266
|
const inset2 = this.#host.element.style.getPropertyValue("--ag-ui-inset");
|
|
@@ -6109,26 +6268,44 @@ var PanelPlacement = class {
|
|
|
6109
6268
|
const corner = this.#host.element.getAttribute("data-expand-corner");
|
|
6110
6269
|
const launcherPos = this.#launcherPos;
|
|
6111
6270
|
const panelPos = this.#panelPos;
|
|
6271
|
+
const dockPos = this.#dockPos ?? this.#readDockPosition();
|
|
6112
6272
|
const expandCorner = this.#expandCorner;
|
|
6273
|
+
const cornerSpot = this.#cornerSpot ?? this.#readLauncherPosition();
|
|
6274
|
+
const owner = this.#positionOwner();
|
|
6113
6275
|
return () => {
|
|
6114
|
-
this.#
|
|
6115
|
-
this.#
|
|
6116
|
-
if (
|
|
6117
|
-
this.#
|
|
6276
|
+
this.#dockPos = dockPos;
|
|
6277
|
+
this.#storeDockPosition(dockPos);
|
|
6278
|
+
if (cornerSpot === null) {
|
|
6279
|
+
this.#cornerSpot = null;
|
|
6280
|
+
this.#host.clearPreference(LAUNCHER_KEY);
|
|
6118
6281
|
} else {
|
|
6119
|
-
this.#
|
|
6282
|
+
this.#writeCornerSpot(cornerSpot);
|
|
6120
6283
|
}
|
|
6121
|
-
this.#
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
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;
|
|
6126
6295
|
} else {
|
|
6127
|
-
this.#
|
|
6296
|
+
this.#forgetCornerPosition();
|
|
6128
6297
|
}
|
|
6298
|
+
this.restoreLauncherPosition();
|
|
6129
6299
|
this.syncResizeAnchor();
|
|
6130
6300
|
};
|
|
6131
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
|
+
}
|
|
6132
6309
|
/**
|
|
6133
6310
|
* Which axes the current placement allows.
|
|
6134
6311
|
*
|
|
@@ -6189,6 +6366,18 @@ var PanelPlacement = class {
|
|
|
6189
6366
|
this.#anchor = anchor;
|
|
6190
6367
|
this.#host.element.setAttribute("data-resize-anchor", `${anchor.y}-${anchor.x}`);
|
|
6191
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());
|
|
6192
6381
|
}
|
|
6193
6382
|
/** Put a custom property back to a previous value, or remove it if there was none. */
|
|
6194
6383
|
#restoreProperty(name, value) {
|
|
@@ -6242,7 +6431,10 @@ var PanelPlacement = class {
|
|
|
6242
6431
|
const element = this.#host.element;
|
|
6243
6432
|
return surfaceFor(element.getAttribute("placement"), element.getAttribute("collapse-to"));
|
|
6244
6433
|
}
|
|
6245
|
-
/**
|
|
6434
|
+
/**
|
|
6435
|
+
* Whether the panel rises from the bottom bar or the host's anchor, until the
|
|
6436
|
+
* user drags it somewhere else.
|
|
6437
|
+
*/
|
|
6246
6438
|
#docked() {
|
|
6247
6439
|
const target = this.#surface().collapseTo;
|
|
6248
6440
|
return target === "bar" || target === "none";
|
|
@@ -6275,8 +6467,98 @@ var PanelPlacement = class {
|
|
|
6275
6467
|
element.style.removeProperty(DOCK_RIGHT);
|
|
6276
6468
|
}
|
|
6277
6469
|
element.toggleAttribute("data-dock-anchored", target === "none" && anchor !== null);
|
|
6470
|
+
this.#dockTop = target === "bar" && height > 0 ? bar.getBoundingClientRect().top : target === "none" && anchor !== null ? anchor.getBoundingClientRect().top : Number.POSITIVE_INFINITY;
|
|
6471
|
+
this.#placeDocked();
|
|
6278
6472
|
return height;
|
|
6279
6473
|
}
|
|
6474
|
+
/**
|
|
6475
|
+
* The part of the usable viewport a docked panel may stand in: all of it
|
|
6476
|
+
* above the dock's line. The bar is what it minimises to, and the anchor is
|
|
6477
|
+
* the host's own way back, so a dragged panel never covers either.
|
|
6478
|
+
*/
|
|
6479
|
+
#dockRoom() {
|
|
6480
|
+
const viewport = this.#viewport();
|
|
6481
|
+
const bottom = Math.min(viewport.top + viewport.height, this.#dockTop);
|
|
6482
|
+
return { ...viewport, height: Math.max(0, bottom - viewport.top) };
|
|
6483
|
+
}
|
|
6484
|
+
/**
|
|
6485
|
+
* Put a docked panel back where the user dragged it, held inside its room.
|
|
6486
|
+
*
|
|
6487
|
+
* The inline inset comes off first, which is both how the panel's resting
|
|
6488
|
+
* box is measured and what leaves a phone full-bleed: the small-viewport
|
|
6489
|
+
* block reads the host's inset before its own, so a dragged spot written
|
|
6490
|
+
* there would hold the panel off the screen's edges. The spot itself stays,
|
|
6491
|
+
* for the next time there is room for it.
|
|
6492
|
+
*/
|
|
6493
|
+
#placeDocked() {
|
|
6494
|
+
if (!this.#docked() || !this.#panelMovable() || this.dragging()) {
|
|
6495
|
+
return;
|
|
6496
|
+
}
|
|
6497
|
+
const at2 = this.#dockPos ?? this.#readDockPosition();
|
|
6498
|
+
if (at2 === null) {
|
|
6499
|
+
return;
|
|
6500
|
+
}
|
|
6501
|
+
this.#dockPos = at2;
|
|
6502
|
+
this.#host.element.style.removeProperty("--ag-ui-inset");
|
|
6503
|
+
const rest = this.#host.element.getBoundingClientRect();
|
|
6504
|
+
if (coversViewport(rest, this.#viewport())) {
|
|
6505
|
+
return;
|
|
6506
|
+
}
|
|
6507
|
+
this.syncResizeAnchor();
|
|
6508
|
+
this.#writeDockInset(
|
|
6509
|
+
clampPanel(
|
|
6510
|
+
{ left: at2.left, top: at2.top, right: at2.left + rest.width, bottom: at2.top + rest.height },
|
|
6511
|
+
this.#dockRoom(),
|
|
6512
|
+
SCREEN_EDGE_MARGIN
|
|
6513
|
+
)
|
|
6514
|
+
);
|
|
6515
|
+
}
|
|
6516
|
+
/** Write the inset that stands a docked panel at `box`. */
|
|
6517
|
+
#writeDockInset(box) {
|
|
6518
|
+
this.#host.element.style.setProperty(
|
|
6519
|
+
"--ag-ui-inset",
|
|
6520
|
+
insetFrom(this.#anchor, box, this.#screen())
|
|
6521
|
+
);
|
|
6522
|
+
}
|
|
6523
|
+
/** Remember a docked panel's dragged spot, or forget it for null. */
|
|
6524
|
+
#storeDockPosition(at2) {
|
|
6525
|
+
if (at2 === null) {
|
|
6526
|
+
this.#host.clearPreference(DOCK_KEY);
|
|
6527
|
+
return;
|
|
6528
|
+
}
|
|
6529
|
+
this.#host.writePreference(DOCK_KEY, JSON.stringify({ left: at2.left, top: at2.top }));
|
|
6530
|
+
}
|
|
6531
|
+
/** The stored spot of a docked panel, or null for none or anything corrupt. */
|
|
6532
|
+
#readDockPosition() {
|
|
6533
|
+
const raw = this.#host.readPreference(DOCK_KEY);
|
|
6534
|
+
if (raw === null) {
|
|
6535
|
+
return null;
|
|
6536
|
+
}
|
|
6537
|
+
try {
|
|
6538
|
+
return asPoint(JSON.parse(raw));
|
|
6539
|
+
} catch {
|
|
6540
|
+
return null;
|
|
6541
|
+
}
|
|
6542
|
+
}
|
|
6543
|
+
/**
|
|
6544
|
+
* Whether the header drag and moveTo may move the open panel: the
|
|
6545
|
+
* placement's answer, unless the host turned moving off.
|
|
6546
|
+
*/
|
|
6547
|
+
#panelMovable() {
|
|
6548
|
+
return this.#host.element.getAttribute("data-launcher-drag") !== "false" && this.#surface().panelMovable;
|
|
6549
|
+
}
|
|
6550
|
+
/**
|
|
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.
|
|
6554
|
+
*/
|
|
6555
|
+
#canDragPanel() {
|
|
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());
|
|
6561
|
+
}
|
|
6280
6562
|
/**
|
|
6281
6563
|
* Whether this placement lets the launcher be dragged, read per interaction
|
|
6282
6564
|
* because `placement` is a live attribute. `data-launcher-drag="false"` opts
|
|
@@ -6408,9 +6690,6 @@ var PanelPlacement = class {
|
|
|
6408
6690
|
* back rather than leaving a stale inline one behind.
|
|
6409
6691
|
*/
|
|
6410
6692
|
#applyLauncherPlacement(at2) {
|
|
6411
|
-
if (!this.#launcherDraggable()) {
|
|
6412
|
-
return;
|
|
6413
|
-
}
|
|
6414
6693
|
this.#launcherPos = at2;
|
|
6415
6694
|
this.#panelPos = null;
|
|
6416
6695
|
const panel = this.#host.element.getBoundingClientRect();
|
|
@@ -6431,6 +6710,7 @@ var PanelPlacement = class {
|
|
|
6431
6710
|
}
|
|
6432
6711
|
/** Move the launcher live during a drag, without persisting. */
|
|
6433
6712
|
#moveLauncher(left, top) {
|
|
6713
|
+
this.#cornerSpot = { left, top };
|
|
6434
6714
|
this.#applyLauncherPlacement({ left, top });
|
|
6435
6715
|
}
|
|
6436
6716
|
/** Move the launcher and remember where, per tab, like the dragged size. */
|
|
@@ -6453,6 +6733,12 @@ var PanelPlacement = class {
|
|
|
6453
6733
|
* other still names the old one would move the launcher for no reason.
|
|
6454
6734
|
*/
|
|
6455
6735
|
#movePanel(box, from) {
|
|
6736
|
+
if (this.#docked()) {
|
|
6737
|
+
const held2 = clampPanel(box, this.#dockRoom(), SCREEN_EDGE_MARGIN);
|
|
6738
|
+
this.#dockPos = { left: held2.left, top: held2.top };
|
|
6739
|
+
this.#writeDockInset(held2);
|
|
6740
|
+
return { held: held2, launcher: null };
|
|
6741
|
+
}
|
|
6456
6742
|
if (!this.#launcherDraggable()) {
|
|
6457
6743
|
return { held: box, launcher: null };
|
|
6458
6744
|
}
|
|
@@ -6492,6 +6778,10 @@ var PanelPlacement = class {
|
|
|
6492
6778
|
*/
|
|
6493
6779
|
#commitPanel(box, from) {
|
|
6494
6780
|
const { held, launcher } = this.#movePanel(box, from);
|
|
6781
|
+
if (this.#docked()) {
|
|
6782
|
+
this.#storeDockPosition({ left: held.left, top: held.top });
|
|
6783
|
+
return;
|
|
6784
|
+
}
|
|
6495
6785
|
if (launcher === null) {
|
|
6496
6786
|
return;
|
|
6497
6787
|
}
|
|
@@ -6525,9 +6815,6 @@ var PanelPlacement = class {
|
|
|
6525
6815
|
* its own right.
|
|
6526
6816
|
*/
|
|
6527
6817
|
#restorePanelPosition(at2) {
|
|
6528
|
-
if (!this.#launcherDraggable()) {
|
|
6529
|
-
return;
|
|
6530
|
-
}
|
|
6531
6818
|
const rect = this.#host.element.getBoundingClientRect();
|
|
6532
6819
|
const held = clampPanel(
|
|
6533
6820
|
{ left: at2.left, top: at2.top, right: at2.left + rect.width, bottom: at2.top + rect.height },
|
|
@@ -6553,6 +6840,9 @@ var PanelPlacement = class {
|
|
|
6553
6840
|
* with it, the panel goes back where it was put; without it, the panel is
|
|
6554
6841
|
* re-derived from the launcher and opens into whatever room the viewport has
|
|
6555
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.
|
|
6556
6846
|
*/
|
|
6557
6847
|
#storeLauncherPosition() {
|
|
6558
6848
|
const position = this.#launcherPos;
|
|
@@ -6560,34 +6850,140 @@ var PanelPlacement = class {
|
|
|
6560
6850
|
return;
|
|
6561
6851
|
}
|
|
6562
6852
|
const panel = this.#panelPos;
|
|
6563
|
-
this.#
|
|
6564
|
-
|
|
6565
|
-
|
|
6566
|
-
|
|
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));
|
|
6567
6859
|
}
|
|
6568
6860
|
/**
|
|
6569
6861
|
* Re-apply the dragged position against the current viewport: on connect,
|
|
6570
6862
|
* whenever the window resizes, and before an expand. The viewport that
|
|
6571
6863
|
* stored a position may since have shrunk, and a launcher past the edge is
|
|
6572
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.
|
|
6573
6868
|
*/
|
|
6574
6869
|
restoreLauncherPosition() {
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
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) {
|
|
6885
|
+
if (this.#docked()) {
|
|
6886
|
+
this.#placeDocked();
|
|
6887
|
+
return;
|
|
6888
|
+
}
|
|
6889
|
+
if (!this.#surface().launcherDraggable) {
|
|
6578
6890
|
return;
|
|
6579
6891
|
}
|
|
6580
|
-
const
|
|
6581
|
-
if (
|
|
6582
|
-
|
|
6583
|
-
|
|
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();
|
|
6902
|
+
return;
|
|
6903
|
+
}
|
|
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);
|
|
6584
6910
|
return;
|
|
6585
6911
|
}
|
|
6586
6912
|
const box = this.#launcherBox();
|
|
6587
6913
|
this.#applyLauncherPlacement(
|
|
6588
|
-
clampLauncher({ ...box, left:
|
|
6914
|
+
clampLauncher({ ...box, left: spot.left, top: spot.top }, this.#viewport())
|
|
6589
6915
|
);
|
|
6590
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
|
+
}
|
|
6591
6987
|
/** The persisted position for this instance, or null. */
|
|
6592
6988
|
#readLauncherPosition() {
|
|
6593
6989
|
const raw = this.#host.readPreference(LAUNCHER_KEY);
|
|
@@ -6615,12 +7011,22 @@ var PanelPlacement = class {
|
|
|
6615
7011
|
* the switch inline and pins a sidebar to wherever the floating launcher was.
|
|
6616
7012
|
*/
|
|
6617
7013
|
releaseLauncherPosition() {
|
|
7014
|
+
if (this.#dockPos !== null && !(this.#docked() && this.#panelMovable())) {
|
|
7015
|
+
this.#dockPos = null;
|
|
7016
|
+
this.#host.element.style.removeProperty("--ag-ui-inset");
|
|
7017
|
+
}
|
|
6618
7018
|
if (this.#launcherDraggable()) {
|
|
6619
7019
|
return;
|
|
6620
7020
|
}
|
|
7021
|
+
this.#forgetCornerPosition();
|
|
7022
|
+
}
|
|
7023
|
+
/** Take everything off that placed a corner panel, leaving its record alone. */
|
|
7024
|
+
#forgetCornerPosition() {
|
|
6621
7025
|
this.#launcherPos = null;
|
|
6622
7026
|
this.#panelPos = null;
|
|
6623
7027
|
this.#expandCorner = null;
|
|
7028
|
+
this.#gripInset = null;
|
|
7029
|
+
this.#fillInset = null;
|
|
6624
7030
|
this.#host.element.style.removeProperty("--ag-ui-inset");
|
|
6625
7031
|
this.#host.element.style.removeProperty("--ag-ui-launcher-inset");
|
|
6626
7032
|
this.#host.element.removeAttribute("data-expand-corner");
|
|
@@ -6641,7 +7047,7 @@ var PanelPlacement = class {
|
|
|
6641
7047
|
*/
|
|
6642
7048
|
#applyResize(grip, box) {
|
|
6643
7049
|
box = this.#withinViewport(box);
|
|
6644
|
-
if (this.#docked()) {
|
|
7050
|
+
if (this.#docked() && this.#dockPos === null) {
|
|
6645
7051
|
const now = this.#host.element.getBoundingClientRect();
|
|
6646
7052
|
box = {
|
|
6647
7053
|
left: grip.x === this.#anchor.x ? now.left : box.left,
|
|
@@ -6653,28 +7059,40 @@ var PanelPlacement = class {
|
|
|
6653
7059
|
return box;
|
|
6654
7060
|
}
|
|
6655
7061
|
this.#applySize({ width: box.right - box.left, height: box.bottom - box.top });
|
|
6656
|
-
if (
|
|
6657
|
-
|
|
6658
|
-
}
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
this.#
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
7062
|
+
if (this.#docked()) {
|
|
7063
|
+
this.#dockPos = { left: box.left, top: box.top };
|
|
7064
|
+
}
|
|
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
|
+
}
|
|
6667
7077
|
}
|
|
6668
|
-
if (this.#panelPos !== null) {
|
|
6669
|
-
|
|
7078
|
+
if (this.#panelPos !== null && !this.#docked()) {
|
|
7079
|
+
const drawn = this.#host.element.getBoundingClientRect();
|
|
7080
|
+
this.#panelPos = { left: drawn.left, top: drawn.top };
|
|
6670
7081
|
}
|
|
6671
7082
|
return box;
|
|
6672
7083
|
}
|
|
6673
7084
|
/** Finish a resize: keep the box, remember it, and re-read the pinned edges. */
|
|
6674
7085
|
#commitResize(grip, box) {
|
|
6675
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
|
+
}
|
|
6676
7091
|
this.#persistSize({ width: held.right - held.left, height: held.bottom - held.top });
|
|
6677
7092
|
this.#storeLauncherPosition();
|
|
7093
|
+
if (this.#dockPos !== null) {
|
|
7094
|
+
this.#storeDockPosition(this.#dockPos);
|
|
7095
|
+
}
|
|
6678
7096
|
this.syncResizeAnchor();
|
|
6679
7097
|
}
|
|
6680
7098
|
/**
|
|
@@ -8914,7 +9332,11 @@ var DOCK_STYLES = `
|
|
|
8914
9332
|
The cap follows the token block's rule: what the host left free less the
|
|
8915
9333
|
one gutter the anchored edge spends, so a panel grown to the cap runs from
|
|
8916
9334
|
just above the bar to the far edge. A host therefore needs no inset to keep
|
|
8917
|
-
the panel off its bar; --ag-ui-inset still wins when set.
|
|
9335
|
+
the panel off its bar; --ag-ui-inset still wins when set. A panel the user
|
|
9336
|
+
dragged off its dock is written there inline, which is how the dragged spot
|
|
9337
|
+
outranks every rule below, the anchor gap included; the element holds that
|
|
9338
|
+
spot above the bar or the anchor itself, and drops it on a phone, where the
|
|
9339
|
+
small-viewport block reads the same property first.
|
|
8918
9340
|
|
|
8919
9341
|
These blocks restate tokens and nothing else, and sit ahead of the phone
|
|
8920
9342
|
block at no more weight than it has, so on a phone the panel is the screen
|
|
@@ -9891,7 +10313,8 @@ ${GROUPED} .tool-group[data-open="false"] .tool-group-list {
|
|
|
9891
10313
|
|
|
9892
10314
|
/* A card inside the group is one line of the list: icon, name, and its
|
|
9893
10315
|
Details control at the end, with the arguments and result opening under
|
|
9894
|
-
the whole row.
|
|
10316
|
+
the whole row. Its ink is the second ink in every theme, unless the host
|
|
10317
|
+
set the tool token, which then reaches the grouped calls too. */
|
|
9895
10318
|
${GROUPED} .tool-group .tool-call {
|
|
9896
10319
|
max-width: 100%;
|
|
9897
10320
|
align-self: stretch;
|
|
@@ -9902,7 +10325,7 @@ ${GROUPED} .tool-group .tool-call {
|
|
|
9902
10325
|
border: 0;
|
|
9903
10326
|
border-radius: 0;
|
|
9904
10327
|
background: transparent;
|
|
9905
|
-
color: var(--_ink-2);
|
|
10328
|
+
color: var(--_tool-fg-set, var(--_ink-2));
|
|
9906
10329
|
font-family: inherit;
|
|
9907
10330
|
font-size: var(--_text-sm);
|
|
9908
10331
|
}
|
|
@@ -10517,6 +10940,15 @@ var FRAME_STYLES = `
|
|
|
10517
10940
|
touch-action: auto;
|
|
10518
10941
|
}
|
|
10519
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
|
+
|
|
10520
10952
|
/* :host is carried for the specificity, not the scope: the placement rules
|
|
10521
10953
|
above are a host selector plus a class plus an attribute, and a bare
|
|
10522
10954
|
.header[data-dragging] loses to them -- silently, because the drag still
|
|
@@ -10566,6 +10998,14 @@ var FRAME_STYLES = `
|
|
|
10566
10998
|
flex: none;
|
|
10567
10999
|
}
|
|
10568
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. */
|
|
10569
11009
|
.header-btn {
|
|
10570
11010
|
display: inline-flex;
|
|
10571
11011
|
flex: 0 0 auto;
|
|
@@ -10582,12 +11022,15 @@ var FRAME_STYLES = `
|
|
|
10582
11022
|
padding: 0;
|
|
10583
11023
|
border-radius: 6px;
|
|
10584
11024
|
cursor: pointer;
|
|
10585
|
-
opacity: 0.85;
|
|
11025
|
+
opacity: var(--_header-fg-set, 0.85);
|
|
10586
11026
|
}
|
|
10587
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. */
|
|
10588
11031
|
.header-btn:hover {
|
|
10589
11032
|
opacity: 1;
|
|
10590
|
-
background:
|
|
11033
|
+
background: var(--_header-btn-hover);
|
|
10591
11034
|
}
|
|
10592
11035
|
`;
|
|
10593
11036
|
|
|
@@ -10662,6 +11105,24 @@ var TOKEN_STYLES = `
|
|
|
10662
11105
|
--_tool-fg: var(--ag-ui-tool-fg, var(--_ink-2));
|
|
10663
11106
|
--_header-bg: var(--ag-ui-header-bg, var(--_bg));
|
|
10664
11107
|
--_header-fg: var(--ag-ui-header-fg, var(--_fg));
|
|
11108
|
+
/* Switches: a public token read with no fallback, named for it with -set.
|
|
11109
|
+
With the token unset the switch computes to the guaranteed-invalid value,
|
|
11110
|
+
so a rule that reads it with a fallback gets the fallback; that is how a
|
|
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). */
|
|
11115
|
+
--_header-fg-set: var(--ag-ui-header-fg);
|
|
11116
|
+
--_tool-fg-set: var(--ag-ui-tool-fg);
|
|
11117
|
+
/* The header buttons' hover square, by default, once the header text is
|
|
11118
|
+
set. Here it is the text at about a fifth, which every browser can mix;
|
|
11119
|
+
where relative colour syntax is supported (see the block at the end) it
|
|
11120
|
+
is the text's opposite instead. It reads the switch, so it is unset with
|
|
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. */
|
|
11124
|
+
--_header-btn-hover-auto: color-mix(in srgb, var(--_header-fg-set) 18%, transparent);
|
|
11125
|
+
--_header-btn-hover: var(--ag-ui-header-btn-hover, var(--_header-btn-hover-auto, var(--_hover)));
|
|
10665
11126
|
--_border: var(--ag-ui-border, var(--_line));
|
|
10666
11127
|
--_radius: var(--ag-ui-radius, 12px);
|
|
10667
11128
|
/* The panel's own frame, which is the one corner a placement can put against
|
|
@@ -11034,6 +11495,19 @@ var TOKEN_STYLES = `
|
|
|
11034
11495
|
--_on-accent: var(--ag-ui-on-accent, #ffffff);
|
|
11035
11496
|
}
|
|
11036
11497
|
}
|
|
11498
|
+
|
|
11499
|
+
/* The header buttons' default hover square as the header text's opposite,
|
|
11500
|
+
so white text gets a darker square and dark text a lighter one. A square
|
|
11501
|
+
mixed from the text itself moves the ground toward the glyph: white on a
|
|
11502
|
+
mid-blue header fell from 5.1:1 to 3.75:1 under the pointer. Moving away
|
|
11503
|
+
from it can only raise what the host's own pair reads. Gated on this
|
|
11504
|
+
exact expression, so a browser that cannot compute it keeps the square
|
|
11505
|
+
mixed from the text rather than losing the square altogether. */
|
|
11506
|
+
@supports (color: rgb(from red calc(255 - r) calc(255 - g) calc(255 - b))) {
|
|
11507
|
+
:host {
|
|
11508
|
+
--_header-btn-hover-auto: color-mix(in srgb, rgb(from var(--_header-fg-set) calc(255 - r) calc(255 - g) calc(255 - b)) 18%, transparent);
|
|
11509
|
+
}
|
|
11510
|
+
}
|
|
11037
11511
|
`;
|
|
11038
11512
|
|
|
11039
11513
|
// src/ui/themes/classic_styles.ts
|
|
@@ -11087,6 +11561,7 @@ var CLASSIC_TOKENS = `
|
|
|
11087
11561
|
--_tool-fg: var(--ag-ui-tool-fg, var(--_accent));
|
|
11088
11562
|
--_header-bg: var(--ag-ui-header-bg, light-dark(var(--_accent), #1f1f30));
|
|
11089
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)));
|
|
11090
11565
|
--_border: var(--ag-ui-border, light-dark(#e2e2ec, #33334a));
|
|
11091
11566
|
--_muted: var(--ag-ui-muted, light-dark(#6b7280, #9aa0b4));
|
|
11092
11567
|
--_success: var(--ag-ui-success, #15803d);
|
|
@@ -11173,14 +11648,15 @@ var LEDGER_STYLES = `
|
|
|
11173
11648
|
vertical-align: 1px;
|
|
11174
11649
|
}
|
|
11175
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). */
|
|
11176
11653
|
:host([theme~="ledger"]) .header-btn {
|
|
11177
|
-
color: var(--_ink-3);
|
|
11654
|
+
color: var(--_header-fg-set, var(--_ink-3));
|
|
11178
11655
|
border-radius: 3px;
|
|
11179
11656
|
}
|
|
11180
11657
|
|
|
11181
11658
|
:host([theme~="ledger"]) .header-btn:hover {
|
|
11182
|
-
|
|
11183
|
-
color: var(--_fg);
|
|
11659
|
+
color: var(--_header-fg-set, var(--_fg));
|
|
11184
11660
|
}
|
|
11185
11661
|
|
|
11186
11662
|
:host([theme~="ledger"]) .message--user {
|
|
@@ -11330,6 +11806,7 @@ var LEDGER_TOKENS = `
|
|
|
11330
11806
|
--_msg-radius: var(--ag-ui-msg-radius, 0px);
|
|
11331
11807
|
--_composer-radius: var(--ag-ui-composer-radius, 4px);
|
|
11332
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)));
|
|
11333
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));
|
|
11334
11811
|
--_launcher-bg: var(--ag-ui-launcher-bg, var(--_fg));
|
|
11335
11812
|
--_launcher-fg: var(--ag-ui-launcher-fg, var(--_bg));
|
|
@@ -11448,14 +11925,17 @@ ${THEME_HOST.quiet} .header-title {
|
|
|
11448
11925
|
letter-spacing: -0.01em;
|
|
11449
11926
|
}
|
|
11450
11927
|
|
|
11928
|
+
/* The buttons sit back in the third ink on the panel. Once the host sets the
|
|
11929
|
+
header text they draw in it instead, since the header behind them is then
|
|
11930
|
+
the host's colour (see the switches in the token defaults). */
|
|
11451
11931
|
${THEME_HOST.quiet} .header-btn {
|
|
11452
|
-
color: var(--_ink-3);
|
|
11932
|
+
color: var(--_header-fg-set, var(--_ink-3));
|
|
11453
11933
|
border-radius: 8px;
|
|
11454
11934
|
}
|
|
11455
11935
|
|
|
11936
|
+
/* The glyph takes the header text, which is the full ink when that is unset. */
|
|
11456
11937
|
${THEME_HOST.quiet} .header-btn:hover {
|
|
11457
|
-
color: var(--
|
|
11458
|
-
background: var(--_hover);
|
|
11938
|
+
color: var(--_header-fg);
|
|
11459
11939
|
}
|
|
11460
11940
|
|
|
11461
11941
|
${THEME_HOST.quiet} .message--user {
|
|
@@ -11598,14 +12078,15 @@ var SOFT_STYLES = `
|
|
|
11598
12078
|
background: linear-gradient(140deg, color-mix(in oklch, var(--_accent) 55%, var(--_bg)), var(--_accent));
|
|
11599
12079
|
}
|
|
11600
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). */
|
|
11601
12083
|
:host([theme~="soft"]) .header-btn {
|
|
11602
|
-
color: var(--_ink-3);
|
|
12084
|
+
color: var(--_header-fg-set, var(--_ink-3));
|
|
11603
12085
|
border-radius: 10px;
|
|
11604
12086
|
}
|
|
11605
12087
|
|
|
11606
12088
|
:host([theme~="soft"]) .header-btn:hover {
|
|
11607
|
-
|
|
11608
|
-
color: var(--_accent-ink);
|
|
12089
|
+
color: var(--_header-fg-set, var(--_accent-ink));
|
|
11609
12090
|
}
|
|
11610
12091
|
|
|
11611
12092
|
:host([theme~="soft"]) .messages {
|
|
@@ -11726,6 +12207,7 @@ var SOFT_TOKENS = `
|
|
|
11726
12207
|
--_tint: var(--ag-ui-tint, color-mix(in oklch, var(--_accent) 5%, var(--_bg)));
|
|
11727
12208
|
--_tint-2: var(--ag-ui-tint-2, color-mix(in oklch, var(--_accent) 13%, var(--_bg)));
|
|
11728
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)));
|
|
11729
12211
|
--_user-bg: var(--ag-ui-user-bg, var(--_tint-2));
|
|
11730
12212
|
--_border: var(--ag-ui-border, color-mix(in oklch, var(--_accent) 14%, var(--_bg)));
|
|
11731
12213
|
--_radius: var(--ag-ui-radius, 16px);
|
|
@@ -19612,13 +20094,26 @@ var AgUiChat = class extends HTMLElement {
|
|
|
19612
20094
|
* a field so `removeEventListener` on disconnect gets the same reference.
|
|
19613
20095
|
*/
|
|
19614
20096
|
#onViewportResize = () => {
|
|
19615
|
-
this.#
|
|
19616
|
-
|
|
19617
|
-
|
|
19618
|
-
|
|
20097
|
+
if (this.#readyToPlace()) {
|
|
20098
|
+
this.#placement.restoreLauncherPosition();
|
|
20099
|
+
}
|
|
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();
|
|
19619
20109
|
}
|
|
19620
|
-
this.#placement.restoreLauncherPosition();
|
|
19621
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
|
+
}
|
|
19622
20117
|
/** Mic button mount point (input row); the control mounts on connect when enabled. */
|
|
19623
20118
|
#voiceSlot;
|
|
19624
20119
|
/** The composer's mic, mounted on connect when transcription is available. */
|
|
@@ -20411,6 +20906,12 @@ var AgUiChat = class extends HTMLElement {
|
|
|
20411
20906
|
const dockObserver = new ResizeObserver(() => this.#syncDock());
|
|
20412
20907
|
dockObserver.observe(this.#dockBar);
|
|
20413
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
|
+
});
|
|
20414
20915
|
this.#syncDock();
|
|
20415
20916
|
if (this.#surface().collapseTo === "none") {
|
|
20416
20917
|
this.dispatchEvent(
|
|
@@ -20800,7 +21301,9 @@ var AgUiChat = class extends HTMLElement {
|
|
|
20800
21301
|
* `movable` folds two separate reasons into the one answer a caller needs:
|
|
20801
21302
|
* a placement that places itself owns its position, and a panel that fills
|
|
20802
21303
|
* the screen has nowhere to go. Reporting them apart would make every caller
|
|
20803
|
-
* re-derive the same conjunction.
|
|
21304
|
+
* re-derive the same conjunction. A corner panel docked under
|
|
21305
|
+
* `collapse-to="bar"` or `"none"` is movable on a wide viewport, like the
|
|
21306
|
+
* corner panel it is.
|
|
20804
21307
|
*/
|
|
20805
21308
|
describeSurface() {
|
|
20806
21309
|
return this.#placement.describeSurface();
|
|
@@ -20814,7 +21317,8 @@ var AgUiChat = class extends HTMLElement {
|
|
|
20814
21317
|
* the corner it opens from is re-picked, and switching placement hands
|
|
20815
21318
|
* everything back. What it must not do is claim a move it did not make --
|
|
20816
21319
|
* hence the boolean, and hence {@link describeSurface} existing so a caller
|
|
20817
|
-
* can ask first.
|
|
21320
|
+
* can ask first. A docked panel moves too, within the room above its bar or
|
|
21321
|
+
* anchor, and remembers the spot as a header drag would.
|
|
20818
21322
|
*/
|
|
20819
21323
|
moveTo(corner, options = {}) {
|
|
20820
21324
|
return this.#placement.moveTo(corner, options);
|
|
@@ -20822,6 +21326,9 @@ var AgUiChat = class extends HTMLElement {
|
|
|
20822
21326
|
/**
|
|
20823
21327
|
* Drop a size the user dragged, and its stored copy, so the placement's
|
|
20824
21328
|
* default and the host's `--ag-ui-width` / `--ag-ui-height` apply again.
|
|
21329
|
+
* Under `collapse-to="bar"` or `"none"` it also returns a panel the user
|
|
21330
|
+
* dragged off its dock to the dock, and forgets the stored spot; a corner
|
|
21331
|
+
* panel keeps a dragged position.
|
|
20825
21332
|
*/
|
|
20826
21333
|
resetSize() {
|
|
20827
21334
|
this.#placement.resetSize();
|
|
@@ -21337,6 +21844,8 @@ var AgUiChat = class extends HTMLElement {
|
|
|
21337
21844
|
const probe = this.#placement.probe;
|
|
21338
21845
|
probe.className = "viewport-probe";
|
|
21339
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";
|
|
21340
21849
|
this.#root.replaceChildren(probe, this.#announcer.region, this.#chat, this.#dockBar);
|
|
21341
21850
|
}
|
|
21342
21851
|
/**
|
|
@@ -21984,7 +22493,7 @@ function setControlValue(el2, value) {
|
|
|
21984
22493
|
}
|
|
21985
22494
|
|
|
21986
22495
|
// src/version.ts
|
|
21987
|
-
var VERSION = "0.
|
|
22496
|
+
var VERSION = "0.50.0";
|
|
21988
22497
|
export {
|
|
21989
22498
|
ATTACHMENT_EVENT,
|
|
21990
22499
|
AgUiChat,
|