@ripperts/poco-agent-embed 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/index.js +88 -28
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -120,4 +120,4 @@ export function AgentChat({ getAccessToken }: AgentChatProps) {
120
120
 
121
121
  支持现代 Chrome、Edge、Firefox 和 Safari。Vue 2 项目可以正常接入,但不支持 Internet Explorer 11。
122
122
 
123
- 完整参数和安全配置请参阅 [Agent 外部嵌入文档](https://ai-agent.fsxgt.cn/docs/external-integration/agent-embed)。
123
+ 完整参数和安全配置请参阅 [Agent 外部嵌入文档](https://ai-agent.fsxgt.cn/docs/getting-started/agent-embed)。
package/index.js CHANGED
@@ -18,6 +18,7 @@
18
18
  var MESSAGE_REQUEST_AUTH = "poco-agent-embed:request-auth";
19
19
  var MESSAGE_AUTHENTICATE = "poco-agent-embed:authenticate";
20
20
  var MESSAGE_ERROR = "poco-agent-embed:error";
21
+ var MESSAGE_DRAG = "poco-agent-embed:drag";
21
22
 
22
23
  function trimTrailingSlash(value) {
23
24
  return String(value || "").replace(/\/+$/, "");
@@ -106,10 +107,15 @@
106
107
  var language = ["en", "zh"].includes(requestedLanguage)
107
108
  ? requestedLanguage
108
109
  : "en";
110
+ var toggleButtonLabels =
111
+ language === "zh"
112
+ ? { open: "打开 AI 助手", close: "关闭 AI 助手" }
113
+ : { open: "Open AI Agent", close: "Close AI Agent" };
109
114
  var theme = ["light", "dark", "system"].includes(options.theme)
110
115
  ? options.theme
111
116
  : "system";
112
117
  var query = new URLSearchParams({ channel: channel, theme: theme });
118
+ if (!target && options.draggable !== false) query.set("draggable", "1");
113
119
  var iframe = document.createElement("iframe");
114
120
  iframe.src =
115
121
  baseUrl +
@@ -133,9 +139,26 @@
133
139
  var container = document.createElement("div");
134
140
  var button = null;
135
141
  var updateViewportPosition = null;
142
+ var handleFrameDrag = null;
136
143
  var openIcon = createIcon(options.openIcon, false);
137
144
  var closeIcon = createIcon(options.closeIcon, true);
138
145
 
146
+ function renderFloatingState() {
147
+ container.style.opacity = opened ? "1" : "0";
148
+ container.style.visibility = opened ? "visible" : "hidden";
149
+ container.style.pointerEvents = opened ? "auto" : "none";
150
+ container.style.transform = opened ? "scale(1)" : "scale(.96)";
151
+ if (!button) return;
152
+ button.replaceChildren(opened ? closeIcon : openIcon);
153
+ button.setAttribute("aria-expanded", opened ? "true" : "false");
154
+ button.setAttribute(
155
+ "aria-label",
156
+ opened
157
+ ? toggleButtonLabels.close
158
+ : options.ariaLabel || toggleButtonLabels.open,
159
+ );
160
+ }
161
+
139
162
  if (target) {
140
163
  container.style.cssText =
141
164
  "position:relative;width:100%;height:100%;overflow:hidden";
@@ -145,8 +168,6 @@
145
168
  container.style.cssText = [
146
169
  "position:fixed",
147
170
  "width:min(420px,calc(100vw - 24px))",
148
- "height:min(720px,calc(100dvh - 96px))",
149
- "min-height:min(360px,calc(100dvh - 96px))",
150
171
  "overflow:hidden",
151
172
  "border:1px solid color-mix(in srgb,CanvasText 25%,transparent)",
152
173
  "border-radius:16px",
@@ -160,7 +181,6 @@
160
181
 
161
182
  button = document.createElement("button");
162
183
  button.type = "button";
163
- button.setAttribute("aria-label", options.ariaLabel || "Open AI Agent");
164
184
  button.style.cssText = [
165
185
  "position:fixed",
166
186
  "display:flex",
@@ -182,25 +202,17 @@
182
202
  var position = options.position || "bottom-right";
183
203
  var vertical = position.indexOf("top") === 0 ? "top" : "bottom";
184
204
  var horizontal = position.indexOf("left") > -1 ? "left" : "right";
185
- button.style[vertical] = "20px";
205
+ var verticalOffset = vertical === "bottom" ? 100 : 20;
206
+ var popupAvailableHeight =
207
+ "calc(100dvh - " + (verticalOffset + 76) + "px)";
208
+ button.style[vertical] = verticalOffset + "px";
186
209
  button.style[horizontal] = "20px";
187
- container.style[vertical] = "84px";
210
+ container.style[vertical] = verticalOffset + 64 + "px";
188
211
  container.style[horizontal] = "20px";
212
+ container.style.height = "min(720px," + popupAvailableHeight + ")";
213
+ container.style.minHeight = "min(360px," + popupAvailableHeight + ")";
189
214
  container.style.transformOrigin = vertical + " " + horizontal;
190
215
 
191
- function renderButtonIcon() {
192
- button.replaceChildren(opened ? closeIcon : openIcon);
193
- button.setAttribute("aria-expanded", opened ? "true" : "false");
194
- }
195
-
196
- function renderOpenState() {
197
- container.style.opacity = opened ? "1" : "0";
198
- container.style.visibility = opened ? "visible" : "hidden";
199
- container.style.pointerEvents = opened ? "auto" : "none";
200
- container.style.transform = opened ? "scale(1)" : "scale(.96)";
201
- renderButtonIcon();
202
- }
203
-
204
216
  function anchorContainerToButton() {
205
217
  var rect = button.getBoundingClientRect();
206
218
  var useLeft = rect.left + rect.width / 2 < window.innerWidth / 2;
@@ -249,6 +261,52 @@
249
261
  anchorContainerToButton();
250
262
  };
251
263
 
264
+ var frameDrag = null;
265
+ handleFrameDrag = function (data) {
266
+ if (data.phase === "start") {
267
+ var buttonRect = button.getBoundingClientRect();
268
+ var containerRect = container.getBoundingClientRect();
269
+ frameDrag = {
270
+ buttonLeft: buttonRect.left,
271
+ buttonTop: buttonRect.top,
272
+ containerLeft: containerRect.left,
273
+ containerTop: containerRect.top,
274
+ minX: 8 - Math.min(buttonRect.left, containerRect.left),
275
+ maxX:
276
+ window.innerWidth -
277
+ 8 -
278
+ Math.max(buttonRect.right, containerRect.right),
279
+ minY: 8 - Math.min(buttonRect.top, containerRect.top),
280
+ maxY:
281
+ window.innerHeight -
282
+ 8 -
283
+ Math.max(buttonRect.bottom, containerRect.bottom),
284
+ };
285
+ container.style.height = containerRect.height + "px";
286
+ container.style.minHeight = containerRect.height + "px";
287
+ return;
288
+ }
289
+ if (!frameDrag) return;
290
+ if (data.phase === "move") {
291
+ var offsetX = Math.max(
292
+ frameDrag.minX,
293
+ Math.min(frameDrag.maxX, data.dx),
294
+ );
295
+ var offsetY = Math.max(
296
+ frameDrag.minY,
297
+ Math.min(frameDrag.maxY, data.dy),
298
+ );
299
+ button.style.left = frameDrag.buttonLeft + offsetX + "px";
300
+ button.style.top = frameDrag.buttonTop + offsetY + "px";
301
+ container.style.left = frameDrag.containerLeft + offsetX + "px";
302
+ container.style.top = frameDrag.containerTop + offsetY + "px";
303
+ container.style.bottom = "auto";
304
+ return;
305
+ }
306
+ frameDrag = null;
307
+ anchorContainerToButton();
308
+ };
309
+
252
310
  var dragState = null;
253
311
  var suppressClickUntil = 0;
254
312
  button.addEventListener("pointerdown", function (event) {
@@ -299,9 +357,10 @@
299
357
  button.addEventListener("click", function () {
300
358
  if (Date.now() < suppressClickUntil) return;
301
359
  opened = !opened;
302
- renderOpenState();
360
+ renderFloatingState();
303
361
  });
304
362
 
363
+ renderFloatingState();
305
364
  document.body.appendChild(container);
306
365
  document.body.appendChild(button);
307
366
  window.addEventListener("resize", updateViewportPosition);
@@ -313,7 +372,6 @@
313
372
  );
314
373
  }
315
374
  updateViewportPosition();
316
- renderOpenState();
317
375
  }
318
376
 
319
377
  async function authenticate() {
@@ -352,6 +410,15 @@
352
410
  event.data.type === MESSAGE_REQUEST_AUTH
353
411
  ) {
354
412
  authenticate();
413
+ } else if (
414
+ event.data.type === MESSAGE_DRAG &&
415
+ handleFrameDrag &&
416
+ options.draggable !== false &&
417
+ ["start", "move", "end"].includes(event.data.phase) &&
418
+ Number.isFinite(event.data.dx) &&
419
+ Number.isFinite(event.data.dy)
420
+ ) {
421
+ handleFrameDrag(event.data);
355
422
  } else if (
356
423
  event.data.type === MESSAGE_ERROR &&
357
424
  typeof options.onError === "function"
@@ -367,14 +434,7 @@
367
434
  function setOpened(next) {
368
435
  if (destroyed || target) return;
369
436
  opened = next;
370
- container.style.opacity = opened ? "1" : "0";
371
- container.style.visibility = opened ? "visible" : "hidden";
372
- container.style.pointerEvents = opened ? "auto" : "none";
373
- container.style.transform = opened ? "scale(1)" : "scale(.96)";
374
- if (button) {
375
- button.replaceChildren(opened ? closeIcon : openIcon);
376
- button.setAttribute("aria-expanded", opened ? "true" : "false");
377
- }
437
+ renderFloatingState();
378
438
  }
379
439
 
380
440
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ripperts/poco-agent-embed",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Zero-dependency SDK for embedding a Poco Agent conversation",
5
5
  "main": "index.js",
6
6
  "module": "index.mjs",