@mcp-b/char 0.1.3 → 0.1.4
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/README.md +11 -13
- package/dist/custom-elements.json +491 -141
- package/dist/display-mode-policy.d.ts.map +1 -1
- package/dist/index.d.ts +89 -114
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +699 -281
- package/dist/index.js.map +1 -1
- package/dist/shell-component.d.ts +79 -86
- package/dist/shell-component.d.ts.map +1 -1
- package/dist/shell-component.js +689 -281
- package/dist/shell-component.js.map +1 -1
- package/dist/shell-standalone.iife.js +689 -281
- package/dist/shell-standalone.iife.js.map +1 -1
- package/dist/utils.d.ts +0 -13
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +1 -2
- package/dist/utils.js.map +1 -1
- package/dist/web-component-standalone.iife.js +25 -89
- package/dist/web-component-standalone.iife.js.map +1 -1
- package/dist/web-component.d.ts +20 -83
- package/dist/web-component.d.ts.map +1 -1
- package/dist/web-component.js +25 -89
- package/dist/web-component.js.map +1 -1
- package/package.json +3 -3
|
@@ -94,8 +94,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
94
94
|
styles: mergeStyles(previous.styles, patch.styles),
|
|
95
95
|
containerDimensions: shallowMerge(previous.containerDimensions, patch.containerDimensions),
|
|
96
96
|
deviceCapabilities: shallowMerge(previous.deviceCapabilities, patch.deviceCapabilities),
|
|
97
|
-
safeAreaInsets: shallowMerge(previous.safeAreaInsets, patch.safeAreaInsets)
|
|
98
|
-
hostCapabilities: shallowMerge(previous.hostCapabilities, patch.hostCapabilities)
|
|
97
|
+
safeAreaInsets: shallowMerge(previous.safeAreaInsets, patch.safeAreaInsets)
|
|
99
98
|
};
|
|
100
99
|
}
|
|
101
100
|
|
|
@@ -507,25 +506,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
507
506
|
"pip"
|
|
508
507
|
];
|
|
509
508
|
/**
|
|
510
|
-
* Normalizes an API key by trimming whitespace and collapsing empty strings.
|
|
511
|
-
*/
|
|
512
|
-
function normalizeApiKey(value) {
|
|
513
|
-
const trimmed = value?.trim();
|
|
514
|
-
return trimmed ? trimmed : void 0;
|
|
515
|
-
}
|
|
516
|
-
/**
|
|
517
|
-
* Produces a sanitized dev-mode configuration and drops empty payloads.
|
|
518
|
-
*/
|
|
519
|
-
function resolveDevMode(devMode) {
|
|
520
|
-
if (!devMode) return void 0;
|
|
521
|
-
const normalized = {
|
|
522
|
-
anthropicApiKey: normalizeApiKey(devMode.anthropicApiKey),
|
|
523
|
-
openaiApiKey: normalizeApiKey(devMode.openaiApiKey),
|
|
524
|
-
useLocalApi: devMode.useLocalApi === true ? true : void 0
|
|
525
|
-
};
|
|
526
|
-
return !!normalized.anthropicApiKey || !!normalized.openaiApiKey || !!normalized.useLocalApi ? normalized : void 0;
|
|
527
|
-
}
|
|
528
|
-
/**
|
|
529
509
|
* Runtime guard for the message envelope emitted by the iframe.
|
|
530
510
|
*/
|
|
531
511
|
function isCharIframeMessageData(value) {
|
|
@@ -664,7 +644,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
664
644
|
*/
|
|
665
645
|
var CharAgentElement = class extends HTMLElement {
|
|
666
646
|
static observedAttributes = [
|
|
667
|
-
"
|
|
647
|
+
"publishable-key",
|
|
668
648
|
"enable-debug-tools",
|
|
669
649
|
"display-mode",
|
|
670
650
|
"api-base"
|
|
@@ -714,12 +694,12 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
714
694
|
return;
|
|
715
695
|
}
|
|
716
696
|
if (!this.style.display) this.style.display = "block";
|
|
717
|
-
const
|
|
718
|
-
const apiBase = this._resolveApiBaseOverride() ?? (resolvedDevMode?.useLocalApi ? window.location.origin : WEBMCP_PRODUCTION_API_BASE);
|
|
697
|
+
const apiBase = this._resolveApiBaseOverride() ?? WEBMCP_PRODUCTION_API_BASE;
|
|
719
698
|
const iframeOrigin = this._resolveIframeOrigin(apiBase);
|
|
720
699
|
const iframe = this._createIframe(apiBase);
|
|
721
700
|
this._iframe = iframe;
|
|
722
|
-
|
|
701
|
+
const publishableKey = this.publishableKey ?? this.getAttribute("publishable-key") ?? void 0;
|
|
702
|
+
if (publishableKey) this._pendingAuth = { publishableKey };
|
|
723
703
|
this._proxy = new CharIframeProxy(iframe, iframeOrigin);
|
|
724
704
|
this._proxy.start();
|
|
725
705
|
this._messageListener = this._createMessageListener(iframe, iframeOrigin);
|
|
@@ -928,15 +908,21 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
928
908
|
/**
|
|
929
909
|
* Reacts to observed attribute updates after iframe readiness.
|
|
930
910
|
* Attributes that affect iframe boot configuration are intentionally ignored
|
|
931
|
-
* after mount (`
|
|
911
|
+
* after mount (`enable-debug-tools`, `api-base`).
|
|
932
912
|
*/
|
|
933
913
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
934
914
|
if (!this._iframe || !this._iframeReady) return;
|
|
935
915
|
switch (name) {
|
|
916
|
+
case "publishable-key":
|
|
917
|
+
if (newValue) {
|
|
918
|
+
this._pendingAuth = { publishableKey: newValue };
|
|
919
|
+
const iframeOrigin = this._getIframeOrigin();
|
|
920
|
+
if (iframeOrigin) this._postAuth(iframeOrigin);
|
|
921
|
+
}
|
|
922
|
+
break;
|
|
936
923
|
case "display-mode":
|
|
937
924
|
this.setHostContext({ displayMode: resolveDisplayModeFromAttribute(newValue) });
|
|
938
925
|
break;
|
|
939
|
-
case "dev-mode":
|
|
940
926
|
case "enable-debug-tools":
|
|
941
927
|
case "api-base": break;
|
|
942
928
|
}
|
|
@@ -947,23 +933,17 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
947
933
|
* The token is stored as a JavaScript property (not as a DOM attribute),
|
|
948
934
|
* preventing exposure to DOM inspection and session replay tools.
|
|
949
935
|
*
|
|
950
|
-
* @param options - Authentication payload
|
|
936
|
+
* @param options - Authentication payload.
|
|
951
937
|
* @returns `true` when the payload is accepted; `false` when validation fails.
|
|
952
938
|
*/
|
|
953
939
|
connect(options) {
|
|
954
|
-
if (!options?.
|
|
955
|
-
this._emitCharError("
|
|
956
|
-
return false;
|
|
957
|
-
}
|
|
958
|
-
if (options?.idToken && !options?.ticketAuth && !options?.clientId) {
|
|
959
|
-
this._emitCharError("MISSING_CLIENT_ID", "connect() requires clientId when using idToken authentication");
|
|
940
|
+
if (!options?.publishableKey) {
|
|
941
|
+
this._emitCharError("MISSING_PUBLISHABLE_KEY", "connect() requires publishableKey");
|
|
960
942
|
return false;
|
|
961
943
|
}
|
|
962
944
|
this._pendingAuth = {
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
organizationId: options.ticketAuth ? void 0 : options.organizationId,
|
|
966
|
-
ticketAuth: options.ticketAuth
|
|
945
|
+
publishableKey: options.publishableKey,
|
|
946
|
+
idToken: options.idToken
|
|
967
947
|
};
|
|
968
948
|
const iframeOrigin = this._getIframeOrigin();
|
|
969
949
|
if (this._iframeReady && iframeOrigin) this._postAuth(iframeOrigin);
|
|
@@ -982,7 +962,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
982
962
|
}
|
|
983
963
|
/**
|
|
984
964
|
* Disconnect from the Char agent.
|
|
985
|
-
* Clears the
|
|
965
|
+
* Clears pending auth state and posts a disconnect message to the iframe.
|
|
986
966
|
*
|
|
987
967
|
* @returns `true` when the disconnect message was sent; `false` when the iframe was not ready.
|
|
988
968
|
*/
|
|
@@ -1046,11 +1026,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1046
1026
|
};
|
|
1047
1027
|
const safeAreaInsets = getSafeAreaInsets();
|
|
1048
1028
|
const displayMode = resolveDisplayModeFromAttribute(displayModeAttr) ?? "inline";
|
|
1049
|
-
const hostCapabilities = {
|
|
1050
|
-
supportedDisplayModes: [...DISPLAY_MODES],
|
|
1051
|
-
supportsOpenLink: true,
|
|
1052
|
-
supportsTeardown: true
|
|
1053
|
-
};
|
|
1054
1029
|
const context = {
|
|
1055
1030
|
theme,
|
|
1056
1031
|
styles: { variables: vars },
|
|
@@ -1061,9 +1036,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1061
1036
|
timeZone,
|
|
1062
1037
|
platform: detectPlatform(),
|
|
1063
1038
|
deviceCapabilities: getDeviceCapabilities(),
|
|
1064
|
-
safeAreaInsets
|
|
1065
|
-
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0,
|
|
1066
|
-
hostCapabilities
|
|
1039
|
+
safeAreaInsets
|
|
1067
1040
|
};
|
|
1068
1041
|
this._hostContext = context;
|
|
1069
1042
|
if (!this._iframe?.contentWindow) {
|
|
@@ -1106,22 +1079,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1106
1079
|
*/
|
|
1107
1080
|
_postAuth(iframeOrigin) {
|
|
1108
1081
|
if (!this._pendingAuth || !this._iframe?.contentWindow) return;
|
|
1109
|
-
if (!this._pendingAuth.
|
|
1110
|
-
console.error("[Char] _postAuth called but _pendingAuth has no
|
|
1082
|
+
if (!this._pendingAuth.publishableKey) {
|
|
1083
|
+
console.error("[Char] _postAuth called but _pendingAuth has no publishableKey");
|
|
1111
1084
|
this._pendingAuth = null;
|
|
1112
1085
|
return;
|
|
1113
1086
|
}
|
|
1114
|
-
const message =
|
|
1115
|
-
type: "char-auth",
|
|
1116
|
-
ticketAuth: this._pendingAuth.ticketAuth
|
|
1117
|
-
} : this._pendingAuth.anthropicApiKey ? {
|
|
1087
|
+
const message = {
|
|
1118
1088
|
type: "char-auth",
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
type: "char-auth",
|
|
1122
|
-
idToken: this._pendingAuth.idToken,
|
|
1123
|
-
clientId: this._pendingAuth.clientId,
|
|
1124
|
-
organizationId: this._pendingAuth.organizationId
|
|
1089
|
+
publishableKey: this._pendingAuth.publishableKey,
|
|
1090
|
+
idToken: this._pendingAuth.idToken
|
|
1125
1091
|
};
|
|
1126
1092
|
this._iframe.contentWindow.postMessage(message, iframeOrigin);
|
|
1127
1093
|
}
|
|
@@ -1268,36 +1234,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1268
1234
|
this._containerResizeObserver.observe(this);
|
|
1269
1235
|
}
|
|
1270
1236
|
/**
|
|
1271
|
-
* Resolve devMode from property (React 19) or attribute.
|
|
1272
|
-
*
|
|
1273
|
-
* @returns Parsed dev-mode configuration when valid.
|
|
1274
|
-
*/
|
|
1275
|
-
_resolveDevMode() {
|
|
1276
|
-
if (this.devMode && typeof this.devMode === "object") return this.devMode;
|
|
1277
|
-
const devModeAttr = this.getAttribute("dev-mode");
|
|
1278
|
-
if (!devModeAttr) return void 0;
|
|
1279
|
-
try {
|
|
1280
|
-
const parsed = JSON.parse(devModeAttr);
|
|
1281
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1282
|
-
const msg = `dev-mode attribute must be a JSON object, got: ${Array.isArray(parsed) ? "array" : typeof parsed}`;
|
|
1283
|
-
console.warn(`[Char] ${msg}`);
|
|
1284
|
-
this._emitCharError("INVALID_DEV_MODE", msg);
|
|
1285
|
-
return;
|
|
1286
|
-
}
|
|
1287
|
-
const obj = parsed;
|
|
1288
|
-
return {
|
|
1289
|
-
anthropicApiKey: typeof obj.anthropicApiKey === "string" ? obj.anthropicApiKey : void 0,
|
|
1290
|
-
openaiApiKey: typeof obj.openaiApiKey === "string" ? obj.openaiApiKey : void 0,
|
|
1291
|
-
useLocalApi: typeof obj.useLocalApi === "boolean" ? obj.useLocalApi : void 0
|
|
1292
|
-
};
|
|
1293
|
-
} catch (e) {
|
|
1294
|
-
const msg = `Failed to parse dev-mode attribute as JSON: ${e instanceof Error ? e.message : String(e)}`;
|
|
1295
|
-
console.warn(`[Char] ${msg}`);
|
|
1296
|
-
this._emitCharError("INVALID_DEV_MODE", msg);
|
|
1297
|
-
return;
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
/**
|
|
1301
1237
|
* Resolve apiBase override from property (React 19) or attribute.
|
|
1302
1238
|
*
|
|
1303
1239
|
* @returns Sanitized API base URL without trailing slash.
|
|
@@ -1326,22 +1262,36 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1326
1262
|
//#region src/shell-component.ts
|
|
1327
1263
|
const SHELL_OPEN_CHANGE_EVENT = "char-shell-open-change";
|
|
1328
1264
|
const SHELL_Z_INDEX = 2147483e3;
|
|
1329
|
-
const
|
|
1330
|
-
const
|
|
1331
|
-
const
|
|
1332
|
-
const
|
|
1333
|
-
const
|
|
1265
|
+
const FULLSCREEN_BREAKPOINT = 1024;
|
|
1266
|
+
const PANEL_WIDTH = 420;
|
|
1267
|
+
const PIP_WIDTH = 400;
|
|
1268
|
+
const PIP_HEIGHT = 60;
|
|
1269
|
+
const PIP_POSITION = "bottom-center";
|
|
1334
1270
|
const SHELL_HEALTH_TIMEOUT_MS = 1e4;
|
|
1335
|
-
const PANEL_BORDER = "1px solid rgba(15, 23, 42, 0.12)";
|
|
1336
1271
|
const SAFE_BOTTOM = "calc(16px + env(safe-area-inset-bottom, 0px))";
|
|
1337
|
-
const
|
|
1272
|
+
const THEME_LIGHT = {
|
|
1273
|
+
background: "oklch(1 0 0)",
|
|
1274
|
+
foreground: "oklch(0.141 0.005 285.823)",
|
|
1275
|
+
border: "oklch(0.92 0.004 286.32)",
|
|
1276
|
+
mutedForeground: "oklch(0.552 0.016 285.938)",
|
|
1277
|
+
primary: "oklch(0.21 0.006 285.885)"
|
|
1278
|
+
};
|
|
1279
|
+
const THEME_DARK = {
|
|
1280
|
+
background: "oklch(0.141 0.005 285.823)",
|
|
1281
|
+
foreground: "oklch(0.985 0 0)",
|
|
1282
|
+
border: "oklch(1 0 0 / 10%)",
|
|
1283
|
+
mutedForeground: "oklch(0.705 0.015 286.067)",
|
|
1284
|
+
primary: "oklch(0.92 0.004 286.32)"
|
|
1285
|
+
};
|
|
1286
|
+
const BODY_MARGIN_TRANSITION = "margin-right 220ms ease";
|
|
1287
|
+
const SHELL_LAYOUT_TRANSITION = "opacity 220ms ease, width 220ms ease, min-width 220ms ease, flex-basis 220ms ease";
|
|
1338
1288
|
const SHELL_REVEAL_FADE_MS = 280;
|
|
1339
1289
|
const PIP_MIN_COLLAPSED_WIDTH = 70;
|
|
1340
1290
|
const PIP_MIN_COLLAPSED_HEIGHT = 30;
|
|
1341
1291
|
const PIP_MAX_MEASURED_HEIGHT = 320;
|
|
1342
1292
|
const PIP_COLLAPSE_DELAY_MS = 400;
|
|
1343
1293
|
const PIP_PILL_HEIGHT = 40;
|
|
1344
|
-
const PIP_MORPH_TRANSITION = "width 280ms ease, height 280ms ease, bottom 280ms ease, border-radius 280ms ease, opacity
|
|
1294
|
+
const PIP_MORPH_TRANSITION = "width 280ms ease, height 280ms ease, bottom 280ms ease, border-radius 280ms ease, opacity 280ms ease, transform 280ms ease";
|
|
1345
1295
|
const PIP_MORPH_DURATION_MS = 280;
|
|
1346
1296
|
const PIP_SCROLL_HIDE_OFFSET = 100;
|
|
1347
1297
|
const PIP_COLLAPSED_WIDTH_RATIO = .75;
|
|
@@ -1349,23 +1299,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1349
1299
|
const PIP_SCROLL_DIRECTION_THRESHOLD = 40;
|
|
1350
1300
|
const WHEEL_DELTA_LINE_MULTIPLIER = 15;
|
|
1351
1301
|
const WHEEL_DELTA_PAGE_MULTIPLIER = 300;
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
if (value === null || value.trim() === "") return fallback;
|
|
1361
|
-
const parsed = Number.parseInt(value, 10);
|
|
1362
|
-
if (!Number.isFinite(parsed)) return fallback;
|
|
1363
|
-
return normalizePositiveInteger(parsed, fallback);
|
|
1364
|
-
}
|
|
1365
|
-
function normalizePipPosition(value) {
|
|
1366
|
-
if (value === "bottom-right" || value === "bottom-left") return value;
|
|
1367
|
-
return DEFAULT_PIP_POSITION;
|
|
1368
|
-
}
|
|
1302
|
+
const PANEL_MIN_WIDTH = 320;
|
|
1303
|
+
const PANEL_MAX_WIDTH = 700;
|
|
1304
|
+
const RESIZE_NUB_WIDTH = 6;
|
|
1305
|
+
const EDGE_TAB_WIDTH = 44;
|
|
1306
|
+
const EDGE_TAB_HEIGHT = 48;
|
|
1307
|
+
const EDGE_TAB_DRAG_THRESHOLD_PX = 4;
|
|
1308
|
+
const ICON_MESSAGE = `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>`;
|
|
1309
|
+
const ICON_CHEVRON_RIGHT = `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>`;
|
|
1369
1310
|
function getPipPositionStyles(position) {
|
|
1370
1311
|
if (position === "bottom-right") return {
|
|
1371
1312
|
left: "auto",
|
|
@@ -1422,25 +1363,28 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1422
1363
|
var CharAgentShellElement = class extends HTMLElement {
|
|
1423
1364
|
static observedAttributes = [
|
|
1424
1365
|
"open",
|
|
1425
|
-
"fullscreen-breakpoint",
|
|
1426
|
-
"panel-width",
|
|
1427
|
-
"pip-position",
|
|
1428
|
-
"pip-width",
|
|
1429
|
-
"pip-height",
|
|
1430
|
-
"dev-mode",
|
|
1431
1366
|
"enable-debug-tools",
|
|
1432
1367
|
"api-base"
|
|
1433
1368
|
];
|
|
1434
1369
|
_agent = null;
|
|
1435
1370
|
_open = false;
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1371
|
+
_savedBodyTransition = null;
|
|
1372
|
+
_bodyMarginTimeoutId = null;
|
|
1373
|
+
_currentPanelWidth = PANEL_WIDTH;
|
|
1374
|
+
_resizeNubElement = null;
|
|
1375
|
+
_edgeTabElement = null;
|
|
1376
|
+
_resizeDragging = false;
|
|
1377
|
+
_resizeDragOverlay = null;
|
|
1378
|
+
_resizeStartX = 0;
|
|
1379
|
+
_resizeStartWidth = 0;
|
|
1380
|
+
_edgeTabDragStartX = 0;
|
|
1381
|
+
_edgeTabDragging = false;
|
|
1441
1382
|
_isNarrowViewport = false;
|
|
1442
1383
|
_mediaQuery = null;
|
|
1443
1384
|
_mediaQueryHandler = null;
|
|
1385
|
+
_themeObserver = null;
|
|
1386
|
+
_themeMediaQuery = null;
|
|
1387
|
+
_themeMediaHandler = null;
|
|
1444
1388
|
_pendingConnectOptions = null;
|
|
1445
1389
|
_pendingHostContext = {};
|
|
1446
1390
|
_isApplyingOpenAttribute = false;
|
|
@@ -1458,6 +1402,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1458
1402
|
_pipAnimationTimeoutId = null;
|
|
1459
1403
|
_pendingPipMeasuredHeight = null;
|
|
1460
1404
|
_tapOutsideListener = null;
|
|
1405
|
+
_lastAppliedDisplayMode = null;
|
|
1461
1406
|
_pipHiddenByScroll = false;
|
|
1462
1407
|
_scrollListener = null;
|
|
1463
1408
|
_scrollRafId = null;
|
|
@@ -1477,75 +1422,36 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1477
1422
|
set open(value) {
|
|
1478
1423
|
this.setOpen(value);
|
|
1479
1424
|
}
|
|
1480
|
-
get fullscreenBreakpoint() {
|
|
1481
|
-
return this._fullscreenBreakpoint;
|
|
1482
|
-
}
|
|
1483
|
-
set fullscreenBreakpoint(value) {
|
|
1484
|
-
const normalized = normalizePositiveInteger(value, DEFAULT_FULLSCREEN_BREAKPOINT);
|
|
1485
|
-
if (normalized === this._fullscreenBreakpoint) return;
|
|
1486
|
-
this._fullscreenBreakpoint = normalized;
|
|
1487
|
-
this.setAttribute("fullscreen-breakpoint", String(normalized));
|
|
1488
|
-
this._setupViewportObserver();
|
|
1489
|
-
this._applyDisplayModeAndLayout();
|
|
1490
|
-
}
|
|
1491
|
-
get panelWidth() {
|
|
1492
|
-
return this._panelWidth;
|
|
1493
|
-
}
|
|
1494
|
-
set panelWidth(value) {
|
|
1495
|
-
const normalized = normalizePositiveInteger(value, DEFAULT_PANEL_WIDTH);
|
|
1496
|
-
if (normalized === this._panelWidth) return;
|
|
1497
|
-
this._panelWidth = normalized;
|
|
1498
|
-
this.setAttribute("panel-width", String(normalized));
|
|
1499
|
-
this._applyDisplayModeAndLayout();
|
|
1500
|
-
}
|
|
1501
|
-
get pipWidth() {
|
|
1502
|
-
return this._pipWidth;
|
|
1503
|
-
}
|
|
1504
|
-
set pipWidth(value) {
|
|
1505
|
-
const normalized = normalizePositiveInteger(value, DEFAULT_PIP_WIDTH);
|
|
1506
|
-
if (normalized === this._pipWidth) return;
|
|
1507
|
-
this._pipWidth = normalized;
|
|
1508
|
-
this.setAttribute("pip-width", String(normalized));
|
|
1509
|
-
this._applyDisplayModeAndLayout();
|
|
1510
|
-
}
|
|
1511
|
-
get pipHeight() {
|
|
1512
|
-
return this._pipHeight;
|
|
1513
|
-
}
|
|
1514
|
-
set pipHeight(value) {
|
|
1515
|
-
const normalized = normalizePositiveInteger(value, DEFAULT_PIP_HEIGHT);
|
|
1516
|
-
if (normalized === this._pipHeight) return;
|
|
1517
|
-
this._pipHeight = normalized;
|
|
1518
|
-
this.setAttribute("pip-height", String(normalized));
|
|
1519
|
-
this._applyDisplayModeAndLayout();
|
|
1520
|
-
}
|
|
1521
|
-
get pipPosition() {
|
|
1522
|
-
return this._pipPosition;
|
|
1523
|
-
}
|
|
1524
|
-
set pipPosition(value) {
|
|
1525
|
-
const normalized = normalizePipPosition(value);
|
|
1526
|
-
if (normalized === this._pipPosition) return;
|
|
1527
|
-
this._pipPosition = normalized;
|
|
1528
|
-
this.setAttribute("pip-position", normalized);
|
|
1529
|
-
this._applyDisplayModeAndLayout();
|
|
1530
|
-
}
|
|
1531
1425
|
connectedCallback() {
|
|
1532
1426
|
this._upgradeProperty("open");
|
|
1533
|
-
this._upgradeProperty("fullscreenBreakpoint");
|
|
1534
|
-
this._upgradeProperty("panelWidth");
|
|
1535
|
-
this._upgradeProperty("pipPosition");
|
|
1536
|
-
this._upgradeProperty("pipWidth");
|
|
1537
|
-
this._upgradeProperty("pipHeight");
|
|
1538
|
-
this._upgradeProperty("devMode");
|
|
1539
1427
|
this._upgradeProperty("apiBase");
|
|
1540
1428
|
registerChar();
|
|
1541
1429
|
this._ensureAgent();
|
|
1542
1430
|
this._readConfigFromAttributes();
|
|
1543
1431
|
this._syncForwardedAttributes();
|
|
1544
1432
|
this._setupViewportObserver();
|
|
1433
|
+
this._setupThemeObserver();
|
|
1545
1434
|
this._applyDisplayModeAndLayout();
|
|
1546
1435
|
this._flushPendingConnectAndContext();
|
|
1547
1436
|
}
|
|
1548
1437
|
disconnectedCallback() {
|
|
1438
|
+
this._removeBodyMargin();
|
|
1439
|
+
if (this._bodyMarginTimeoutId !== null) {
|
|
1440
|
+
window.clearTimeout(this._bodyMarginTimeoutId);
|
|
1441
|
+
this._bodyMarginTimeoutId = null;
|
|
1442
|
+
}
|
|
1443
|
+
this._removeResizeDragOverlay();
|
|
1444
|
+
this._teardownThemeObserver();
|
|
1445
|
+
document.removeEventListener("mousemove", this._onEdgeTabMouseMove);
|
|
1446
|
+
document.removeEventListener("mouseup", this._onEdgeTabMouseUp);
|
|
1447
|
+
document.removeEventListener("touchmove", this._onEdgeTabTouchMove);
|
|
1448
|
+
document.removeEventListener("touchend", this._onEdgeTabTouchEnd);
|
|
1449
|
+
this._removeEdgeTab();
|
|
1450
|
+
this._hideResizeNub();
|
|
1451
|
+
if (this._resizeNubElement) {
|
|
1452
|
+
this._resizeNubElement.remove();
|
|
1453
|
+
this._resizeNubElement = null;
|
|
1454
|
+
}
|
|
1549
1455
|
this._stopHealthWait();
|
|
1550
1456
|
this._cancelRevealFade();
|
|
1551
1457
|
this._teardownViewportObserver();
|
|
@@ -1574,48 +1480,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1574
1480
|
});
|
|
1575
1481
|
return;
|
|
1576
1482
|
}
|
|
1577
|
-
case "fullscreen-breakpoint": {
|
|
1578
|
-
const next = parsePositiveIntegerAttribute(newValue, DEFAULT_FULLSCREEN_BREAKPOINT);
|
|
1579
|
-
if (next !== this._fullscreenBreakpoint) {
|
|
1580
|
-
this._fullscreenBreakpoint = next;
|
|
1581
|
-
this._setupViewportObserver();
|
|
1582
|
-
this._applyDisplayModeAndLayout();
|
|
1583
|
-
}
|
|
1584
|
-
return;
|
|
1585
|
-
}
|
|
1586
|
-
case "panel-width": {
|
|
1587
|
-
const next = parsePositiveIntegerAttribute(newValue, DEFAULT_PANEL_WIDTH);
|
|
1588
|
-
if (next !== this._panelWidth) {
|
|
1589
|
-
this._panelWidth = next;
|
|
1590
|
-
this._applyDisplayModeAndLayout();
|
|
1591
|
-
}
|
|
1592
|
-
return;
|
|
1593
|
-
}
|
|
1594
|
-
case "pip-width": {
|
|
1595
|
-
const next = parsePositiveIntegerAttribute(newValue, DEFAULT_PIP_WIDTH);
|
|
1596
|
-
if (next !== this._pipWidth) {
|
|
1597
|
-
this._pipWidth = next;
|
|
1598
|
-
this._applyDisplayModeAndLayout();
|
|
1599
|
-
}
|
|
1600
|
-
return;
|
|
1601
|
-
}
|
|
1602
|
-
case "pip-height": {
|
|
1603
|
-
const next = parsePositiveIntegerAttribute(newValue, DEFAULT_PIP_HEIGHT);
|
|
1604
|
-
if (next !== this._pipHeight) {
|
|
1605
|
-
this._pipHeight = next;
|
|
1606
|
-
this._applyDisplayModeAndLayout();
|
|
1607
|
-
}
|
|
1608
|
-
return;
|
|
1609
|
-
}
|
|
1610
|
-
case "pip-position": {
|
|
1611
|
-
const next = normalizePipPosition(newValue);
|
|
1612
|
-
if (next !== this._pipPosition) {
|
|
1613
|
-
this._pipPosition = next;
|
|
1614
|
-
this._applyDisplayModeAndLayout();
|
|
1615
|
-
}
|
|
1616
|
-
return;
|
|
1617
|
-
}
|
|
1618
|
-
case "dev-mode":
|
|
1619
1483
|
case "enable-debug-tools":
|
|
1620
1484
|
case "api-base":
|
|
1621
1485
|
this._syncForwardedAttributes();
|
|
@@ -1625,7 +1489,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1625
1489
|
/**
|
|
1626
1490
|
* Connects shell authentication and starts availability health checks.
|
|
1627
1491
|
*
|
|
1628
|
-
* @param options - Authentication payload
|
|
1492
|
+
* @param options - Authentication payload (`publishableKey` + optional `idToken`).
|
|
1629
1493
|
* @returns `true` when connect is accepted by the inner element.
|
|
1630
1494
|
*/
|
|
1631
1495
|
connect(options) {
|
|
@@ -1733,15 +1597,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1733
1597
|
this._attachForwardedListeners();
|
|
1734
1598
|
}
|
|
1735
1599
|
_primeAgentBootConfig(agent) {
|
|
1736
|
-
for (const name of [
|
|
1737
|
-
"dev-mode",
|
|
1738
|
-
"enable-debug-tools",
|
|
1739
|
-
"api-base"
|
|
1740
|
-
]) {
|
|
1600
|
+
for (const name of ["enable-debug-tools", "api-base"]) {
|
|
1741
1601
|
const value = this.getAttribute(name);
|
|
1742
1602
|
if (value !== null) agent.setAttribute(name, value);
|
|
1743
1603
|
}
|
|
1744
|
-
agent.devMode = this.devMode && typeof this.devMode === "object" ? this.devMode : void 0;
|
|
1745
1604
|
agent.apiBase = typeof this.apiBase === "string" ? this.apiBase : void 0;
|
|
1746
1605
|
}
|
|
1747
1606
|
_attachForwardedListeners() {
|
|
@@ -1764,29 +1623,19 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1764
1623
|
}
|
|
1765
1624
|
_readConfigFromAttributes() {
|
|
1766
1625
|
this._open = parseBooleanAttribute(this.getAttribute("open"));
|
|
1767
|
-
this._fullscreenBreakpoint = parsePositiveIntegerAttribute(this.getAttribute("fullscreen-breakpoint"), DEFAULT_FULLSCREEN_BREAKPOINT);
|
|
1768
|
-
this._panelWidth = parsePositiveIntegerAttribute(this.getAttribute("panel-width"), DEFAULT_PANEL_WIDTH);
|
|
1769
|
-
this._pipWidth = parsePositiveIntegerAttribute(this.getAttribute("pip-width"), DEFAULT_PIP_WIDTH);
|
|
1770
|
-
this._pipHeight = parsePositiveIntegerAttribute(this.getAttribute("pip-height"), DEFAULT_PIP_HEIGHT);
|
|
1771
|
-
this._pipPosition = normalizePipPosition(this.getAttribute("pip-position"));
|
|
1772
1626
|
}
|
|
1773
1627
|
_syncForwardedAttributes() {
|
|
1774
1628
|
if (!this._agent) return;
|
|
1775
|
-
for (const name of [
|
|
1776
|
-
"dev-mode",
|
|
1777
|
-
"enable-debug-tools",
|
|
1778
|
-
"api-base"
|
|
1779
|
-
]) {
|
|
1629
|
+
for (const name of ["enable-debug-tools", "api-base"]) {
|
|
1780
1630
|
const value = this.getAttribute(name);
|
|
1781
1631
|
if (value === null) this._agent.removeAttribute(name);
|
|
1782
1632
|
else this._agent.setAttribute(name, value);
|
|
1783
1633
|
}
|
|
1784
|
-
this._agent.devMode = this.devMode && typeof this.devMode === "object" ? this.devMode : void 0;
|
|
1785
1634
|
this._agent.apiBase = typeof this.apiBase === "string" ? this.apiBase : void 0;
|
|
1786
1635
|
}
|
|
1787
1636
|
_setupViewportObserver() {
|
|
1788
1637
|
if (typeof window === "undefined") return;
|
|
1789
|
-
const query = `(max-width: ${
|
|
1638
|
+
const query = `(max-width: ${FULLSCREEN_BREAKPOINT - 1}px)`;
|
|
1790
1639
|
if (this._mediaQuery?.media === query) {
|
|
1791
1640
|
this._isNarrowViewport = this._mediaQuery.matches;
|
|
1792
1641
|
return;
|
|
@@ -1824,38 +1673,558 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1824
1673
|
if (displayMode !== "pip") {
|
|
1825
1674
|
if (this._pipMeasuredHeight !== null) this._pipMeasuredHeight = null;
|
|
1826
1675
|
}
|
|
1676
|
+
const prevMode = this._lastAppliedDisplayMode;
|
|
1677
|
+
this._lastAppliedDisplayMode = displayMode;
|
|
1827
1678
|
this._agent.setAttribute("display-mode", displayMode);
|
|
1828
1679
|
this._applyHostLayout(displayMode);
|
|
1829
|
-
this._applyAgentLayout(displayMode);
|
|
1680
|
+
this._applyAgentLayout(displayMode, prevMode);
|
|
1681
|
+
}
|
|
1682
|
+
_isParentFlex() {
|
|
1683
|
+
const parent = this.parentElement;
|
|
1684
|
+
if (!parent) return false;
|
|
1685
|
+
const display = getComputedStyle(parent).display;
|
|
1686
|
+
return display === "flex" || display === "inline-flex";
|
|
1687
|
+
}
|
|
1688
|
+
_isDarkMode() {
|
|
1689
|
+
const themeAttr = document.documentElement.getAttribute("data-theme");
|
|
1690
|
+
if (themeAttr === "dark") return true;
|
|
1691
|
+
if (themeAttr === "light") return false;
|
|
1692
|
+
return document.documentElement.classList.contains("dark") || window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
1693
|
+
}
|
|
1694
|
+
/**
|
|
1695
|
+
* Read a `--char-color-*` variable from the shell element. If the host
|
|
1696
|
+
* page has set it (directly or via inheritance) use that value; otherwise
|
|
1697
|
+
* fall back to the char design-system default for the current light/dark mode.
|
|
1698
|
+
*/
|
|
1699
|
+
_resolveColor(token) {
|
|
1700
|
+
const host = getComputedStyle(this).getPropertyValue({
|
|
1701
|
+
background: "--char-color-background",
|
|
1702
|
+
foreground: "--char-color-foreground",
|
|
1703
|
+
border: "--char-color-border",
|
|
1704
|
+
mutedForeground: "--char-color-muted-foreground",
|
|
1705
|
+
primary: "--char-color-primary"
|
|
1706
|
+
}[token]).trim();
|
|
1707
|
+
if (host) return host;
|
|
1708
|
+
return (this._isDarkMode() ? THEME_DARK : THEME_LIGHT)[token];
|
|
1709
|
+
}
|
|
1710
|
+
_panelBorder() {
|
|
1711
|
+
return `1px solid ${this._resolveColor("border")}`;
|
|
1712
|
+
}
|
|
1713
|
+
_setupThemeObserver() {
|
|
1714
|
+
const onThemeChange = () => {
|
|
1715
|
+
this._applyEdgeTabVisual();
|
|
1716
|
+
this._refreshResizeNubColors();
|
|
1717
|
+
if (this._open && !this._isNarrowViewport) {
|
|
1718
|
+
if (this._isParentFlex()) setStyleValue(this, "border-left", this._panelBorder());
|
|
1719
|
+
else if (this._agent) setStyleValue(this._agent, "border-left", this._panelBorder());
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
this._themeObserver = new MutationObserver(onThemeChange);
|
|
1723
|
+
this._themeObserver.observe(document.documentElement, {
|
|
1724
|
+
attributes: true,
|
|
1725
|
+
attributeFilter: [
|
|
1726
|
+
"class",
|
|
1727
|
+
"style",
|
|
1728
|
+
"data-theme"
|
|
1729
|
+
]
|
|
1730
|
+
});
|
|
1731
|
+
this._themeMediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
1732
|
+
this._themeMediaHandler = onThemeChange;
|
|
1733
|
+
this._themeMediaQuery.addEventListener("change", this._themeMediaHandler);
|
|
1734
|
+
}
|
|
1735
|
+
_teardownThemeObserver() {
|
|
1736
|
+
if (this._themeObserver) {
|
|
1737
|
+
this._themeObserver.disconnect();
|
|
1738
|
+
this._themeObserver = null;
|
|
1739
|
+
}
|
|
1740
|
+
if (this._themeMediaQuery && this._themeMediaHandler) {
|
|
1741
|
+
this._themeMediaQuery.removeEventListener("change", this._themeMediaHandler);
|
|
1742
|
+
this._themeMediaQuery = null;
|
|
1743
|
+
this._themeMediaHandler = null;
|
|
1744
|
+
}
|
|
1830
1745
|
}
|
|
1831
1746
|
_applyHostLayout(displayMode) {
|
|
1747
|
+
const useFlexLayout = this._isParentFlex();
|
|
1832
1748
|
if (displayMode === "inline" && !this._isNarrowViewport) {
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1749
|
+
if (useFlexLayout) {
|
|
1750
|
+
setStyleValue(this, "position", "relative");
|
|
1751
|
+
setStyleValue(this, "flex", `0 0 ${this._currentPanelWidth}px`);
|
|
1752
|
+
setStyleValue(this, "width", `${this._currentPanelWidth}px`);
|
|
1753
|
+
setStyleValue(this, "min-width", `${this._currentPanelWidth}px`);
|
|
1754
|
+
setStyleValue(this, "height", "100%");
|
|
1755
|
+
setStyleValue(this, "z-index", String(SHELL_Z_INDEX));
|
|
1756
|
+
setStyleValue(this, "border-left", this._panelBorder());
|
|
1757
|
+
setStyleValue(this, "transition", this._resizeDragging ? "none" : SHELL_LAYOUT_TRANSITION);
|
|
1758
|
+
resetStyleValue(this, "overflow");
|
|
1759
|
+
resetStyleValue(this, "pointer-events");
|
|
1760
|
+
this._removeBodyMargin();
|
|
1761
|
+
} else {
|
|
1762
|
+
setStyleValue(this, "position", "fixed");
|
|
1763
|
+
setStyleValue(this, "width", "0px");
|
|
1764
|
+
setStyleValue(this, "height", "0px");
|
|
1765
|
+
setStyleValue(this, "z-index", String(SHELL_Z_INDEX));
|
|
1766
|
+
resetStyleValue(this, "flex");
|
|
1767
|
+
resetStyleValue(this, "min-width");
|
|
1768
|
+
resetStyleValue(this, "border-left");
|
|
1769
|
+
resetStyleValue(this, "overflow");
|
|
1770
|
+
resetStyleValue(this, "pointer-events");
|
|
1771
|
+
this._applyBodyMargin(this._currentPanelWidth);
|
|
1772
|
+
}
|
|
1773
|
+
this._showResizeNub();
|
|
1774
|
+
this._showEdgeTab();
|
|
1775
|
+
if (useFlexLayout) this._syncEdgeTabWithPanelTransition();
|
|
1776
|
+
} else if (displayMode === "fullscreen") {
|
|
1777
|
+
if (useFlexLayout) {
|
|
1778
|
+
setStyleValue(this, "position", "relative");
|
|
1779
|
+
setStyleValue(this, "flex", "0 0 0px");
|
|
1780
|
+
setStyleValue(this, "width", "0px");
|
|
1781
|
+
setStyleValue(this, "min-width", "0px");
|
|
1782
|
+
setStyleValue(this, "height", "0px");
|
|
1783
|
+
setStyleValue(this, "z-index", String(SHELL_Z_INDEX));
|
|
1784
|
+
resetStyleValue(this, "border-left");
|
|
1785
|
+
setStyleValue(this, "transition", SHELL_LAYOUT_TRANSITION);
|
|
1786
|
+
resetStyleValue(this, "overflow");
|
|
1787
|
+
resetStyleValue(this, "pointer-events");
|
|
1788
|
+
} else {
|
|
1789
|
+
setStyleValue(this, "position", "relative");
|
|
1790
|
+
resetStyleValue(this, "flex");
|
|
1791
|
+
resetStyleValue(this, "min-width");
|
|
1792
|
+
resetStyleValue(this, "border-left");
|
|
1793
|
+
resetStyleValue(this, "overflow");
|
|
1794
|
+
resetStyleValue(this, "pointer-events");
|
|
1795
|
+
}
|
|
1796
|
+
this._removeBodyMargin();
|
|
1797
|
+
this._hideResizeNub();
|
|
1798
|
+
this._hideEdgeTab();
|
|
1799
|
+
} else {
|
|
1800
|
+
if (useFlexLayout) {
|
|
1801
|
+
setStyleValue(this, "position", "relative");
|
|
1802
|
+
setStyleValue(this, "flex", "0 0 0px");
|
|
1803
|
+
setStyleValue(this, "width", "0px");
|
|
1804
|
+
setStyleValue(this, "min-width", "0px");
|
|
1805
|
+
setStyleValue(this, "height", "0px");
|
|
1806
|
+
setStyleValue(this, "z-index", String(SHELL_Z_INDEX));
|
|
1807
|
+
resetStyleValue(this, "border-left");
|
|
1808
|
+
setStyleValue(this, "transition", SHELL_LAYOUT_TRANSITION);
|
|
1809
|
+
resetStyleValue(this, "overflow");
|
|
1810
|
+
resetStyleValue(this, "pointer-events");
|
|
1811
|
+
} else {
|
|
1812
|
+
setStyleValue(this, "position", "relative");
|
|
1813
|
+
resetStyleValue(this, "flex");
|
|
1814
|
+
resetStyleValue(this, "min-width");
|
|
1815
|
+
resetStyleValue(this, "border-left");
|
|
1816
|
+
resetStyleValue(this, "overflow");
|
|
1817
|
+
resetStyleValue(this, "pointer-events");
|
|
1818
|
+
}
|
|
1819
|
+
this._removeBodyMargin();
|
|
1820
|
+
this._hideResizeNub();
|
|
1821
|
+
this._showEdgeTab();
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
_applyBodyMargin(width) {
|
|
1825
|
+
const body = document.body;
|
|
1826
|
+
if (this._savedBodyTransition === null) this._savedBodyTransition = body.style.transition || "";
|
|
1827
|
+
if (!this._resizeDragging) body.style.transition = BODY_MARGIN_TRANSITION;
|
|
1828
|
+
body.style.marginRight = `${width}px`;
|
|
1829
|
+
}
|
|
1830
|
+
_removeBodyMargin() {
|
|
1831
|
+
const body = document.body;
|
|
1832
|
+
body.style.marginRight = "";
|
|
1833
|
+
if (this._bodyMarginTimeoutId !== null) {
|
|
1834
|
+
window.clearTimeout(this._bodyMarginTimeoutId);
|
|
1835
|
+
this._bodyMarginTimeoutId = null;
|
|
1836
|
+
}
|
|
1837
|
+
if (this._savedBodyTransition !== null) {
|
|
1838
|
+
const saved = this._savedBodyTransition;
|
|
1839
|
+
this._bodyMarginTimeoutId = window.setTimeout(() => {
|
|
1840
|
+
this._bodyMarginTimeoutId = null;
|
|
1841
|
+
if (body.style.transition === BODY_MARGIN_TRANSITION) body.style.transition = saved || "";
|
|
1842
|
+
}, 220);
|
|
1843
|
+
this._savedBodyTransition = null;
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
_ensureResizeNub() {
|
|
1847
|
+
if (this._resizeNubElement) return this._resizeNubElement;
|
|
1848
|
+
const nub = document.createElement("div");
|
|
1849
|
+
nub.setAttribute("role", "separator");
|
|
1850
|
+
nub.setAttribute("aria-orientation", "vertical");
|
|
1851
|
+
nub.setAttribute("aria-label", "Resize panel");
|
|
1852
|
+
nub.style.cssText = [
|
|
1853
|
+
"position:fixed",
|
|
1854
|
+
"top:0",
|
|
1855
|
+
`width:${RESIZE_NUB_WIDTH}px`,
|
|
1856
|
+
"height:100dvh",
|
|
1857
|
+
"cursor:col-resize",
|
|
1858
|
+
`z-index:${SHELL_Z_INDEX + 1}`,
|
|
1859
|
+
"background:transparent",
|
|
1860
|
+
"user-select:none",
|
|
1861
|
+
"-webkit-user-select:none",
|
|
1862
|
+
"touch-action:none"
|
|
1863
|
+
].join(";");
|
|
1864
|
+
const indicator = document.createElement("div");
|
|
1865
|
+
indicator.style.cssText = [
|
|
1866
|
+
"position:absolute",
|
|
1867
|
+
"top:0",
|
|
1868
|
+
"left:50%",
|
|
1869
|
+
"transform:translateX(-50%)",
|
|
1870
|
+
"width:2px",
|
|
1871
|
+
"height:100%",
|
|
1872
|
+
"border-radius:1px",
|
|
1873
|
+
"transition:background 150ms ease, width 150ms ease",
|
|
1874
|
+
"pointer-events:none"
|
|
1875
|
+
].join(";");
|
|
1876
|
+
nub.appendChild(indicator);
|
|
1877
|
+
this._applyResizeNubColors(indicator);
|
|
1878
|
+
nub.addEventListener("mouseenter", () => {
|
|
1879
|
+
const dark = this._isDarkMode();
|
|
1880
|
+
indicator.style.background = dark ? "rgba(255,255,255,0.2)" : "rgba(0,0,0,0.15)";
|
|
1881
|
+
indicator.style.width = "3px";
|
|
1882
|
+
});
|
|
1883
|
+
nub.addEventListener("mouseleave", () => {
|
|
1884
|
+
if (!this._resizeDragging) {
|
|
1885
|
+
this._applyResizeNubColors(indicator);
|
|
1886
|
+
indicator.style.width = "2px";
|
|
1887
|
+
}
|
|
1888
|
+
});
|
|
1889
|
+
nub.addEventListener("mousedown", this._onResizeStart);
|
|
1890
|
+
nub.addEventListener("touchstart", this._onResizeTouchStart, { passive: false });
|
|
1891
|
+
this._resizeNubElement = nub;
|
|
1892
|
+
return nub;
|
|
1893
|
+
}
|
|
1894
|
+
_applyResizeNubColors(indicator) {
|
|
1895
|
+
const el = indicator ?? this._resizeNubElement?.querySelector("div");
|
|
1896
|
+
if (!el) return;
|
|
1897
|
+
const dark = this._isDarkMode();
|
|
1898
|
+
el.style.background = dark ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.06)";
|
|
1899
|
+
}
|
|
1900
|
+
_refreshResizeNubColors() {
|
|
1901
|
+
this._applyResizeNubColors();
|
|
1902
|
+
}
|
|
1903
|
+
_showResizeNub() {
|
|
1904
|
+
const nub = this._ensureResizeNub();
|
|
1905
|
+
if (!nub.parentNode) document.body.appendChild(nub);
|
|
1906
|
+
setStyleValue(nub, "right", `${this._currentPanelWidth - Math.floor(RESIZE_NUB_WIDTH / 2)}px`);
|
|
1907
|
+
setStyleValue(nub, "display", "block");
|
|
1908
|
+
}
|
|
1909
|
+
_hideResizeNub() {
|
|
1910
|
+
if (this._resizeNubElement) setStyleValue(this._resizeNubElement, "display", "none");
|
|
1911
|
+
}
|
|
1912
|
+
_ensureEdgeTab() {
|
|
1913
|
+
if (this._edgeTabElement) return this._edgeTabElement;
|
|
1914
|
+
const tab = document.createElement("button");
|
|
1915
|
+
tab.setAttribute("type", "button");
|
|
1916
|
+
tab.setAttribute("aria-label", "Open assistant");
|
|
1917
|
+
tab.style.cssText = [
|
|
1918
|
+
"position:fixed",
|
|
1919
|
+
"top:50%",
|
|
1920
|
+
"right:0px",
|
|
1921
|
+
"transform:translateY(-50%)",
|
|
1922
|
+
`z-index:${SHELL_Z_INDEX + 2}`,
|
|
1923
|
+
`width:${EDGE_TAB_WIDTH}px`,
|
|
1924
|
+
`height:${EDGE_TAB_HEIGHT}px`,
|
|
1925
|
+
"display:flex",
|
|
1926
|
+
"align-items:center",
|
|
1927
|
+
"justify-content:center",
|
|
1928
|
+
"border-right:none",
|
|
1929
|
+
"border-radius:12px 0 0 12px",
|
|
1930
|
+
"padding:0",
|
|
1931
|
+
"outline:none",
|
|
1932
|
+
"transition:transform 200ms ease,background 150ms ease,color 150ms ease,box-shadow 200ms ease,border-color 150ms ease",
|
|
1933
|
+
"user-select:none",
|
|
1934
|
+
"-webkit-user-select:none"
|
|
1935
|
+
].join(";");
|
|
1936
|
+
const dot = document.createElement("span");
|
|
1937
|
+
dot.style.cssText = [
|
|
1938
|
+
"position:absolute",
|
|
1939
|
+
"top:8px",
|
|
1940
|
+
"right:10px",
|
|
1941
|
+
"width:7px",
|
|
1942
|
+
"height:7px",
|
|
1943
|
+
"border-radius:50%",
|
|
1944
|
+
"transition:opacity 200ms ease"
|
|
1945
|
+
].join(";");
|
|
1946
|
+
tab.appendChild(dot);
|
|
1947
|
+
const icon = document.createElement("span");
|
|
1948
|
+
icon.style.cssText = "display:flex;align-items:center;justify-content:center;pointer-events:none;";
|
|
1949
|
+
icon.innerHTML = ICON_MESSAGE;
|
|
1950
|
+
tab.appendChild(icon);
|
|
1951
|
+
tab.addEventListener("mouseenter", () => {
|
|
1952
|
+
const dark = this._isDarkMode();
|
|
1953
|
+
if (this._open && !this._isNarrowViewport) {
|
|
1954
|
+
tab.style.background = dark ? "rgba(255,255,255,0.06)" : "rgba(0,0,0,0.04)";
|
|
1955
|
+
tab.style.boxShadow = "none";
|
|
1956
|
+
tab.style.color = this._resolveColor("foreground");
|
|
1957
|
+
tab.style.cursor = "col-resize";
|
|
1958
|
+
} else {
|
|
1959
|
+
tab.style.transform = "translateY(-50%) translateX(-3px)";
|
|
1960
|
+
tab.style.boxShadow = dark ? "-4px 0 16px rgba(0,0,0,0.3)" : "-4px 0 16px rgba(0,0,0,0.12)";
|
|
1961
|
+
tab.style.color = this._resolveColor("foreground");
|
|
1962
|
+
tab.style.cursor = "pointer";
|
|
1963
|
+
}
|
|
1964
|
+
});
|
|
1965
|
+
tab.addEventListener("mouseleave", () => {
|
|
1966
|
+
this._applyEdgeTabVisual();
|
|
1967
|
+
});
|
|
1968
|
+
tab.addEventListener("mousedown", this._onEdgeTabMouseDown);
|
|
1969
|
+
tab.addEventListener("touchstart", this._onEdgeTabTouchStart, { passive: false });
|
|
1970
|
+
this._edgeTabElement = tab;
|
|
1971
|
+
return tab;
|
|
1972
|
+
}
|
|
1973
|
+
/** Apply visual style (colors, shadow) based on open state — no position change. */
|
|
1974
|
+
_applyEdgeTabVisual() {
|
|
1975
|
+
if (!this._edgeTabElement) return;
|
|
1976
|
+
const tab = this._edgeTabElement;
|
|
1977
|
+
const icon = tab.querySelector("span:last-child");
|
|
1978
|
+
const dot = tab.querySelector("span:first-child");
|
|
1979
|
+
const dark = this._isDarkMode();
|
|
1980
|
+
const bg = this._resolveColor("background");
|
|
1981
|
+
const borderColor = this._resolveColor("border");
|
|
1982
|
+
const mutedFg = this._resolveColor("mutedForeground");
|
|
1983
|
+
const primary = this._resolveColor("primary");
|
|
1984
|
+
tab.style.border = `1px solid ${borderColor}`;
|
|
1985
|
+
tab.style.borderRight = "none";
|
|
1986
|
+
if (this._open && !this._isNarrowViewport) {
|
|
1987
|
+
tab.setAttribute("aria-label", "Close assistant");
|
|
1988
|
+
tab.setAttribute("aria-expanded", "true");
|
|
1989
|
+
if (icon) icon.innerHTML = ICON_CHEVRON_RIGHT;
|
|
1990
|
+
if (dot) dot.style.opacity = "0";
|
|
1991
|
+
tab.style.background = bg;
|
|
1992
|
+
tab.style.boxShadow = "none";
|
|
1993
|
+
tab.style.backdropFilter = "none";
|
|
1994
|
+
tab.style.setProperty("-webkit-backdrop-filter", "none");
|
|
1995
|
+
tab.style.color = mutedFg;
|
|
1996
|
+
tab.style.cursor = "col-resize";
|
|
1997
|
+
tab.style.transform = "translateY(-50%)";
|
|
1998
|
+
} else {
|
|
1999
|
+
tab.setAttribute("aria-label", "Open assistant");
|
|
2000
|
+
tab.setAttribute("aria-expanded", "false");
|
|
2001
|
+
if (icon) icon.innerHTML = ICON_MESSAGE;
|
|
2002
|
+
if (dot) {
|
|
2003
|
+
dot.style.opacity = "1";
|
|
2004
|
+
dot.style.background = primary;
|
|
2005
|
+
}
|
|
2006
|
+
tab.style.background = dark ? "color-mix(in oklch, " + bg + ", white 4%)" : "color-mix(in oklch, " + bg + ", transparent 5%)";
|
|
2007
|
+
tab.style.boxShadow = dark ? "-2px 0 12px rgba(0,0,0,0.25)" : "-2px 0 12px rgba(0,0,0,0.08)";
|
|
2008
|
+
tab.style.backdropFilter = "blur(8px)";
|
|
2009
|
+
tab.style.setProperty("-webkit-backdrop-filter", "blur(8px)");
|
|
2010
|
+
tab.style.color = mutedFg;
|
|
2011
|
+
tab.style.cursor = "pointer";
|
|
2012
|
+
tab.style.transform = "translateY(-50%)";
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
/** Set the tab's `right` position immediately (no transition). */
|
|
2016
|
+
_positionEdgeTab(rightPx) {
|
|
2017
|
+
if (this._edgeTabElement) this._edgeTabElement.style.right = `${rightPx}px`;
|
|
2018
|
+
}
|
|
2019
|
+
_showEdgeTab() {
|
|
2020
|
+
const tab = this._ensureEdgeTab();
|
|
2021
|
+
if (!tab.parentNode) document.body.appendChild(tab);
|
|
2022
|
+
setStyleValue(tab, "display", "flex");
|
|
2023
|
+
if (this._open && !this._isNarrowViewport) this._positionEdgeTab(this._currentPanelWidth - 1);
|
|
2024
|
+
else this._positionEdgeTab(0);
|
|
2025
|
+
this._applyEdgeTabVisual();
|
|
2026
|
+
}
|
|
2027
|
+
_hideEdgeTab() {
|
|
2028
|
+
if (this._edgeTabElement) setStyleValue(this._edgeTabElement, "display", "none");
|
|
2029
|
+
}
|
|
2030
|
+
_removeEdgeTab() {
|
|
2031
|
+
if (this._edgeTabElement) {
|
|
2032
|
+
this._edgeTabElement.remove();
|
|
2033
|
+
this._edgeTabElement = null;
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
_onEdgeTabMouseDown = (e) => {
|
|
2037
|
+
e.preventDefault();
|
|
2038
|
+
this._edgeTabDragStartX = e.clientX;
|
|
2039
|
+
this._edgeTabDragging = false;
|
|
2040
|
+
document.addEventListener("mousemove", this._onEdgeTabMouseMove);
|
|
2041
|
+
document.addEventListener("mouseup", this._onEdgeTabMouseUp);
|
|
2042
|
+
};
|
|
2043
|
+
_onEdgeTabTouchStart = (e) => {
|
|
2044
|
+
if (e.touches.length !== 1) return;
|
|
2045
|
+
e.preventDefault();
|
|
2046
|
+
this._edgeTabDragStartX = e.touches[0].clientX;
|
|
2047
|
+
this._edgeTabDragging = false;
|
|
2048
|
+
document.addEventListener("touchmove", this._onEdgeTabTouchMove, { passive: false });
|
|
2049
|
+
document.addEventListener("touchend", this._onEdgeTabTouchEnd);
|
|
2050
|
+
};
|
|
2051
|
+
_onEdgeTabMouseMove = (e) => {
|
|
2052
|
+
const dx = Math.abs(e.clientX - this._edgeTabDragStartX);
|
|
2053
|
+
if (!this._edgeTabDragging && dx >= EDGE_TAB_DRAG_THRESHOLD_PX) {
|
|
2054
|
+
this._edgeTabDragging = true;
|
|
2055
|
+
this._promoteEdgeTabDragToResize(this._edgeTabDragStartX);
|
|
2056
|
+
}
|
|
2057
|
+
};
|
|
2058
|
+
_onEdgeTabTouchMove = (e) => {
|
|
2059
|
+
if (e.touches.length !== 1) return;
|
|
2060
|
+
e.preventDefault();
|
|
2061
|
+
const dx = Math.abs(e.touches[0].clientX - this._edgeTabDragStartX);
|
|
2062
|
+
if (!this._edgeTabDragging && dx >= EDGE_TAB_DRAG_THRESHOLD_PX) {
|
|
2063
|
+
this._edgeTabDragging = true;
|
|
2064
|
+
this._promoteEdgeTabDragToResize(this._edgeTabDragStartX);
|
|
2065
|
+
}
|
|
2066
|
+
};
|
|
2067
|
+
_onEdgeTabMouseUp = (_e) => {
|
|
2068
|
+
document.removeEventListener("mousemove", this._onEdgeTabMouseMove);
|
|
2069
|
+
document.removeEventListener("mouseup", this._onEdgeTabMouseUp);
|
|
2070
|
+
if (!this._edgeTabDragging) this.toggleOpen();
|
|
2071
|
+
};
|
|
2072
|
+
_onEdgeTabTouchEnd = (_e) => {
|
|
2073
|
+
document.removeEventListener("touchmove", this._onEdgeTabTouchMove);
|
|
2074
|
+
document.removeEventListener("touchend", this._onEdgeTabTouchEnd);
|
|
2075
|
+
if (!this._edgeTabDragging) this.toggleOpen();
|
|
2076
|
+
};
|
|
2077
|
+
/**
|
|
2078
|
+
* Once the edge tab drag crosses the threshold, hand off to the existing
|
|
2079
|
+
* resize machinery so the panel tracks the pointer smoothly.
|
|
2080
|
+
*/
|
|
2081
|
+
_promoteEdgeTabDragToResize(startX) {
|
|
2082
|
+
if (!this._open || this._isNarrowViewport) {
|
|
2083
|
+
this._edgeTabDragging = false;
|
|
1841
2084
|
return;
|
|
1842
2085
|
}
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
setStyleValue(this, "
|
|
1848
|
-
setStyleValue(this, "
|
|
1849
|
-
|
|
1850
|
-
|
|
2086
|
+
this._resizeDragging = true;
|
|
2087
|
+
this._resizeStartX = startX;
|
|
2088
|
+
this._resizeStartWidth = this._currentPanelWidth;
|
|
2089
|
+
this._showResizeDragOverlay();
|
|
2090
|
+
if (this._agent) setStyleValue(this._agent, "transition", "none");
|
|
2091
|
+
setStyleValue(this, "transition", "none");
|
|
2092
|
+
document.body.style.transition = "none";
|
|
2093
|
+
document.body.style.cursor = "col-resize";
|
|
2094
|
+
document.body.style.userSelect = "none";
|
|
2095
|
+
document.addEventListener("mousemove", this._onResizeMove);
|
|
2096
|
+
document.addEventListener("mouseup", this._onResizeEnd);
|
|
2097
|
+
document.addEventListener("touchmove", this._onResizeTouchMove, { passive: false });
|
|
2098
|
+
document.addEventListener("touchend", this._onResizeTouchEnd);
|
|
2099
|
+
}
|
|
2100
|
+
/**
|
|
2101
|
+
* Run a rAF loop that reads the shell element's actual rendered width
|
|
2102
|
+
* and pins the edge tab to it. Used during flex layout transitions so
|
|
2103
|
+
* the tab tracks the animated flex-basis exactly, frame by frame.
|
|
2104
|
+
*/
|
|
2105
|
+
_syncEdgeTabWithPanelTransition() {
|
|
2106
|
+
if (!this._edgeTabElement) return;
|
|
2107
|
+
const start = performance.now();
|
|
2108
|
+
const maxDuration = 300;
|
|
2109
|
+
const tick = () => {
|
|
2110
|
+
if (!this._edgeTabElement || !this._open) return;
|
|
2111
|
+
if (this._isParentFlex()) {
|
|
2112
|
+
const width = this.getBoundingClientRect().width;
|
|
2113
|
+
this._positionEdgeTab(width - 1);
|
|
2114
|
+
}
|
|
2115
|
+
if (performance.now() - start < maxDuration) requestAnimationFrame(tick);
|
|
2116
|
+
};
|
|
2117
|
+
requestAnimationFrame(tick);
|
|
2118
|
+
}
|
|
2119
|
+
_showResizeDragOverlay() {
|
|
2120
|
+
if (this._resizeDragOverlay) return;
|
|
2121
|
+
const overlay = document.createElement("div");
|
|
2122
|
+
overlay.style.cssText = [
|
|
2123
|
+
"position:fixed",
|
|
2124
|
+
"top:0",
|
|
2125
|
+
"left:0",
|
|
2126
|
+
"width:100vw",
|
|
2127
|
+
"height:100vh",
|
|
2128
|
+
"cursor:col-resize",
|
|
2129
|
+
`z-index:${SHELL_Z_INDEX + 1}`,
|
|
2130
|
+
"background:transparent",
|
|
2131
|
+
"user-select:none",
|
|
2132
|
+
"-webkit-user-select:none"
|
|
2133
|
+
].join(";");
|
|
2134
|
+
document.body.appendChild(overlay);
|
|
2135
|
+
this._resizeDragOverlay = overlay;
|
|
2136
|
+
}
|
|
2137
|
+
_removeResizeDragOverlay() {
|
|
2138
|
+
if (this._resizeDragOverlay) {
|
|
2139
|
+
this._resizeDragOverlay.remove();
|
|
2140
|
+
this._resizeDragOverlay = null;
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
_onResizeStart = (e) => {
|
|
2144
|
+
e.preventDefault();
|
|
2145
|
+
this._resizeDragging = true;
|
|
2146
|
+
this._resizeStartX = e.clientX;
|
|
2147
|
+
this._resizeStartWidth = this._currentPanelWidth;
|
|
2148
|
+
this._showResizeDragOverlay();
|
|
2149
|
+
if (this._agent) setStyleValue(this._agent, "transition", "none");
|
|
2150
|
+
setStyleValue(this, "transition", "none");
|
|
2151
|
+
document.body.style.transition = "none";
|
|
2152
|
+
document.body.style.cursor = "col-resize";
|
|
2153
|
+
document.body.style.userSelect = "none";
|
|
2154
|
+
document.addEventListener("mousemove", this._onResizeMove);
|
|
2155
|
+
document.addEventListener("mouseup", this._onResizeEnd);
|
|
2156
|
+
};
|
|
2157
|
+
_onResizeTouchStart = (e) => {
|
|
2158
|
+
if (e.touches.length !== 1) return;
|
|
2159
|
+
e.preventDefault();
|
|
2160
|
+
const touch = e.touches[0];
|
|
2161
|
+
this._resizeDragging = true;
|
|
2162
|
+
this._resizeStartX = touch.clientX;
|
|
2163
|
+
this._resizeStartWidth = this._currentPanelWidth;
|
|
2164
|
+
this._showResizeDragOverlay();
|
|
2165
|
+
if (this._agent) setStyleValue(this._agent, "transition", "none");
|
|
2166
|
+
setStyleValue(this, "transition", "none");
|
|
2167
|
+
document.body.style.transition = "none";
|
|
2168
|
+
document.addEventListener("touchmove", this._onResizeTouchMove, { passive: false });
|
|
2169
|
+
document.addEventListener("touchend", this._onResizeTouchEnd);
|
|
2170
|
+
};
|
|
2171
|
+
_onResizeMove = (e) => {
|
|
2172
|
+
if (!this._resizeDragging) return;
|
|
2173
|
+
const delta = this._resizeStartX - e.clientX;
|
|
2174
|
+
this._applyResizeWidth(this._resizeStartWidth + delta);
|
|
2175
|
+
};
|
|
2176
|
+
_onResizeTouchMove = (e) => {
|
|
2177
|
+
if (!this._resizeDragging || e.touches.length !== 1) return;
|
|
2178
|
+
e.preventDefault();
|
|
2179
|
+
const delta = this._resizeStartX - e.touches[0].clientX;
|
|
2180
|
+
this._applyResizeWidth(this._resizeStartWidth + delta);
|
|
2181
|
+
};
|
|
2182
|
+
_applyResizeWidth(rawWidth) {
|
|
2183
|
+
const width = Math.max(PANEL_MIN_WIDTH, Math.min(rawWidth, PANEL_MAX_WIDTH));
|
|
2184
|
+
this._currentPanelWidth = width;
|
|
2185
|
+
if (this._isParentFlex()) {
|
|
2186
|
+
setStyleValue(this, "flex", `0 0 ${width}px`);
|
|
2187
|
+
setStyleValue(this, "width", `${width}px`);
|
|
2188
|
+
setStyleValue(this, "min-width", `${width}px`);
|
|
2189
|
+
} else {
|
|
2190
|
+
if (this._agent) setStyleValue(this._agent, "width", `${width}px`);
|
|
2191
|
+
document.body.style.marginRight = `${width}px`;
|
|
2192
|
+
}
|
|
2193
|
+
if (this._resizeNubElement) {
|
|
2194
|
+
const rightPos = width - Math.floor(RESIZE_NUB_WIDTH / 2);
|
|
2195
|
+
setStyleValue(this._resizeNubElement, "right", `${rightPos}px`);
|
|
2196
|
+
}
|
|
2197
|
+
if (this._edgeTabElement) this._edgeTabElement.style.right = `${width - 1}px`;
|
|
2198
|
+
}
|
|
2199
|
+
_onResizeEnd = (e) => {
|
|
2200
|
+
this._finishResize(e.clientX);
|
|
2201
|
+
document.removeEventListener("mousemove", this._onResizeMove);
|
|
2202
|
+
document.removeEventListener("mouseup", this._onResizeEnd);
|
|
2203
|
+
};
|
|
2204
|
+
_onResizeTouchEnd = (e) => {
|
|
2205
|
+
const x = e.changedTouches[0]?.clientX ?? this._resizeStartX;
|
|
2206
|
+
this._finishResize(x);
|
|
2207
|
+
document.removeEventListener("touchmove", this._onResizeTouchMove);
|
|
2208
|
+
document.removeEventListener("touchend", this._onResizeTouchEnd);
|
|
2209
|
+
};
|
|
2210
|
+
_finishResize(endX) {
|
|
2211
|
+
this._resizeDragging = false;
|
|
2212
|
+
this._removeResizeDragOverlay();
|
|
2213
|
+
document.body.style.cursor = "";
|
|
2214
|
+
document.body.style.userSelect = "";
|
|
2215
|
+
document.body.style.transition = "";
|
|
2216
|
+
const delta = this._resizeStartX - endX;
|
|
2217
|
+
const finalWidth = this._resizeStartWidth + delta;
|
|
2218
|
+
this._currentPanelWidth = Math.max(PANEL_MIN_WIDTH, Math.min(finalWidth, PANEL_MAX_WIDTH));
|
|
2219
|
+
this._applyDisplayModeAndLayout();
|
|
1851
2220
|
}
|
|
1852
2221
|
_composePipTransform(opts) {
|
|
1853
2222
|
const parts = [];
|
|
1854
|
-
if (
|
|
2223
|
+
if (PIP_POSITION === "bottom-center") parts.push("translateX(-50%)");
|
|
1855
2224
|
if (opts.scrollHide) parts.push(`translateY(${PIP_SCROLL_HIDE_OFFSET}px)`);
|
|
1856
2225
|
return parts.length > 0 ? parts.join(" ") : "none";
|
|
1857
2226
|
}
|
|
1858
|
-
_applyAgentLayout(displayMode) {
|
|
2227
|
+
_applyAgentLayout(displayMode, prevMode) {
|
|
1859
2228
|
if (!this._agent) return;
|
|
1860
2229
|
if (displayMode === "inline" && !this._isNarrowViewport) {
|
|
1861
2230
|
this._detachPipInteractionListeners();
|
|
@@ -1863,20 +2232,32 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1863
2232
|
this._pipExpanded = false;
|
|
1864
2233
|
this._pipAnimating = false;
|
|
1865
2234
|
this._hidePipPill();
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
2235
|
+
if (this._isParentFlex()) {
|
|
2236
|
+
setStyleValue(this._agent, "position", "relative");
|
|
2237
|
+
resetStyleValue(this._agent, "top");
|
|
2238
|
+
resetStyleValue(this._agent, "right");
|
|
2239
|
+
resetStyleValue(this._agent, "bottom");
|
|
2240
|
+
resetStyleValue(this._agent, "left");
|
|
2241
|
+
setStyleValue(this._agent, "z-index", "auto");
|
|
2242
|
+
setStyleValue(this._agent, "width", "100%");
|
|
2243
|
+
setStyleValue(this._agent, "height", "100%");
|
|
2244
|
+
} else {
|
|
2245
|
+
setStyleValue(this._agent, "position", "fixed");
|
|
2246
|
+
setStyleValue(this._agent, "top", "0");
|
|
2247
|
+
setStyleValue(this._agent, "right", "0");
|
|
2248
|
+
resetStyleValue(this._agent, "bottom");
|
|
2249
|
+
resetStyleValue(this._agent, "left");
|
|
2250
|
+
setStyleValue(this._agent, "z-index", String(SHELL_Z_INDEX));
|
|
2251
|
+
setStyleValue(this._agent, "width", `${this._currentPanelWidth}px`);
|
|
2252
|
+
setStyleValue(this._agent, "height", "100dvh");
|
|
2253
|
+
setStyleValue(this._agent, "border-left", this._panelBorder());
|
|
2254
|
+
}
|
|
1871
2255
|
resetStyleValue(this._agent, "transform");
|
|
1872
2256
|
resetStyleValue(this._agent, "max-width");
|
|
1873
2257
|
resetStyleValue(this._agent, "max-height");
|
|
1874
|
-
setStyleValue(this._agent, "z-index", "auto");
|
|
1875
|
-
setStyleValue(this._agent, "width", "100%");
|
|
1876
|
-
setStyleValue(this._agent, "height", "100%");
|
|
1877
2258
|
setStyleValue(this._agent, "border-radius", "0");
|
|
1878
2259
|
setStyleValue(this._agent, "overflow", "hidden");
|
|
1879
|
-
|
|
2260
|
+
setStyleValue(this._agent, "transition", this._resizeDragging ? "none" : "width 220ms ease");
|
|
1880
2261
|
resetStyleValue(this._agent, "opacity");
|
|
1881
2262
|
resetStyleValue(this._agent, "pointer-events");
|
|
1882
2263
|
return;
|
|
@@ -1905,15 +2286,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1905
2286
|
resetStyleValue(this._agent, "pointer-events");
|
|
1906
2287
|
return;
|
|
1907
2288
|
}
|
|
1908
|
-
const pipPositionStyles = getPipPositionStyles(
|
|
1909
|
-
const expandedWidth = Math.max(PIP_MIN_COLLAPSED_WIDTH,
|
|
1910
|
-
const collapsedWidth = Math.max(PIP_MIN_COLLAPSED_WIDTH, Math.round(
|
|
2289
|
+
const pipPositionStyles = getPipPositionStyles(PIP_POSITION);
|
|
2290
|
+
const expandedWidth = Math.max(PIP_MIN_COLLAPSED_WIDTH, PIP_WIDTH);
|
|
2291
|
+
const collapsedWidth = Math.max(PIP_MIN_COLLAPSED_WIDTH, Math.round(PIP_WIDTH * PIP_COLLAPSED_WIDTH_RATIO));
|
|
1911
2292
|
const targetWidth = this._pipExpanded ? expandedWidth : collapsedWidth;
|
|
1912
|
-
const collapsedHeight = Math.max(PIP_MIN_COLLAPSED_HEIGHT,
|
|
1913
|
-
const hasExplicitPipHeight = this.hasAttribute("pip-height");
|
|
2293
|
+
const collapsedHeight = Math.max(PIP_MIN_COLLAPSED_HEIGHT, PIP_HEIGHT);
|
|
1914
2294
|
const measuredHeightFloor = typeof this._pipMeasuredHeight === "number" ? this._pipMeasuredHeight : 0;
|
|
1915
2295
|
const expandedHeight = Math.max(collapsedHeight, measuredHeightFloor);
|
|
1916
|
-
const collapsedPipHeight =
|
|
2296
|
+
const collapsedPipHeight = PIP_PILL_HEIGHT;
|
|
1917
2297
|
const heightDelta = expandedHeight - collapsedPipHeight;
|
|
1918
2298
|
let targetHeight;
|
|
1919
2299
|
let targetBottom;
|
|
@@ -1924,13 +2304,14 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1924
2304
|
targetHeight = collapsedPipHeight;
|
|
1925
2305
|
targetBottom = heightDelta > 0 ? `calc(${heightDelta}px + 16px + env(safe-area-inset-bottom, 0px))` : SAFE_BOTTOM;
|
|
1926
2306
|
}
|
|
2307
|
+
const enteringFromPanel = prevMode != null && prevMode !== "pip" && this._healthState === "healthy";
|
|
1927
2308
|
const composedTransform = this._composePipTransform({ scrollHide: this._pipHiddenByScroll });
|
|
2309
|
+
if (enteringFromPanel) setStyleValue(this._agent, "transition", "none");
|
|
1928
2310
|
setStyleValue(this._agent, "position", "fixed");
|
|
1929
2311
|
resetStyleValue(this._agent, "top");
|
|
1930
2312
|
setStyleValue(this._agent, "right", pipPositionStyles.right);
|
|
1931
2313
|
setStyleValue(this._agent, "left", pipPositionStyles.left);
|
|
1932
2314
|
setStyleValue(this._agent, "bottom", targetBottom);
|
|
1933
|
-
setStyleValue(this._agent, "transform", composedTransform);
|
|
1934
2315
|
setStyleValue(this._agent, "z-index", String(SHELL_Z_INDEX));
|
|
1935
2316
|
setStyleValue(this._agent, "width", `min(${targetWidth}px, calc(100vw - 24px))`);
|
|
1936
2317
|
setStyleValue(this._agent, "height", `${targetHeight}px`);
|
|
@@ -1938,7 +2319,22 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1938
2319
|
setStyleValue(this._agent, "max-width", "100vw");
|
|
1939
2320
|
setStyleValue(this._agent, "border-radius", "16px");
|
|
1940
2321
|
setStyleValue(this._agent, "overflow", "hidden");
|
|
1941
|
-
|
|
2322
|
+
resetStyleValue(this._agent, "border-left");
|
|
2323
|
+
if (enteringFromPanel) {
|
|
2324
|
+
setStyleValue(this._agent, "transform", this._composePipTransform({ scrollHide: true }));
|
|
2325
|
+
setStyleValue(this._agent, "opacity", "0");
|
|
2326
|
+
this._agent.offsetHeight;
|
|
2327
|
+
requestAnimationFrame(() => {
|
|
2328
|
+
if (!this._agent) return;
|
|
2329
|
+
setStyleValue(this._agent, "transition", PIP_MORPH_TRANSITION);
|
|
2330
|
+
setStyleValue(this._agent, "transform", composedTransform);
|
|
2331
|
+
setStyleValue(this._agent, "opacity", "1");
|
|
2332
|
+
});
|
|
2333
|
+
} else {
|
|
2334
|
+
setStyleValue(this._agent, "transform", composedTransform);
|
|
2335
|
+
setStyleValue(this._agent, "transition", this._healthState === "healthy" ? PIP_MORPH_TRANSITION : "none");
|
|
2336
|
+
resetStyleValue(this._agent, "opacity");
|
|
2337
|
+
}
|
|
1942
2338
|
if (this._healthState === "healthy") {
|
|
1943
2339
|
const pill = this._ensurePipPill();
|
|
1944
2340
|
if (!pill.parentNode) this.appendChild(pill);
|
|
@@ -1947,6 +2343,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1947
2343
|
this._attachScrollHideListener();
|
|
1948
2344
|
this._attachSwipeGestureListeners();
|
|
1949
2345
|
this._attachWheelFallbackListener();
|
|
2346
|
+
if (enteringFromPanel) {
|
|
2347
|
+
pill.style.opacity = "0";
|
|
2348
|
+
pill.style.pointerEvents = "none";
|
|
2349
|
+
pill.style.transition = "none";
|
|
2350
|
+
requestAnimationFrame(() => {
|
|
2351
|
+
pill.style.transition = PIP_MORPH_TRANSITION;
|
|
2352
|
+
pill.style.opacity = "1";
|
|
2353
|
+
pill.style.pointerEvents = "";
|
|
2354
|
+
});
|
|
2355
|
+
}
|
|
1950
2356
|
this._applyPipVisualState();
|
|
1951
2357
|
}
|
|
1952
2358
|
}
|
|
@@ -1956,7 +2362,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
1956
2362
|
pill.setAttribute("role", "button");
|
|
1957
2363
|
pill.setAttribute("aria-label", "Open assistant");
|
|
1958
2364
|
pill.setAttribute("tabindex", "0");
|
|
1959
|
-
const pipPositionStyles = getPipPositionStyles(
|
|
2365
|
+
const pipPositionStyles = getPipPositionStyles(PIP_POSITION);
|
|
1960
2366
|
pill.style.cssText = [
|
|
1961
2367
|
"position:fixed",
|
|
1962
2368
|
`left:${pipPositionStyles.left}`,
|
|
@@ -2342,6 +2748,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2342
2748
|
this._pipExpanded = false;
|
|
2343
2749
|
this._pipAnimating = false;
|
|
2344
2750
|
this._hidePipPill();
|
|
2751
|
+
this._hideEdgeTab();
|
|
2345
2752
|
if (this._agent) this._agent.removeAttribute("display-mode");
|
|
2346
2753
|
this._resetHostLayoutStyles();
|
|
2347
2754
|
this._resetAgentLayoutStyles();
|
|
@@ -2387,7 +2794,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2387
2794
|
this._revealFrameId = null;
|
|
2388
2795
|
setStyleValue(this, "opacity", "1");
|
|
2389
2796
|
window.setTimeout(() => {
|
|
2390
|
-
|
|
2797
|
+
resetStyleValue(this, "will-change");
|
|
2391
2798
|
}, SHELL_REVEAL_FADE_MS);
|
|
2392
2799
|
});
|
|
2393
2800
|
}
|
|
@@ -2439,6 +2846,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2439
2846
|
return;
|
|
2440
2847
|
}
|
|
2441
2848
|
this._open = nextOpen;
|
|
2849
|
+
if (!nextOpen) this._currentPanelWidth = PANEL_WIDTH;
|
|
2442
2850
|
if (options.reflect) this._reflectOpenAttribute(nextOpen);
|
|
2443
2851
|
this._applyDisplayModeAndLayout();
|
|
2444
2852
|
if (options.emit) this.dispatchEvent(new CustomEvent(SHELL_OPEN_CHANGE_EVENT, {
|