@vite-plugin-opencode-assistant/components 1.0.26 → 1.0.27

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 (33) hide show
  1. package/es/index.d.ts +1 -1
  2. package/es/index.js +1 -1
  3. package/es/open-code-widget/composables/use-inspector.js +118 -79
  4. package/es/open-code-widget/composables/use-persist-state.d.ts +24 -0
  5. package/es/open-code-widget/composables/use-persist-state.js +59 -0
  6. package/es/open-code-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -1
  7. package/es/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +2 -2
  8. package/es/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.js +37 -21
  9. package/es/open-code-widget/src/components/Trigger.vue.d.ts +0 -2
  10. package/es/open-code-widget/src/components/Trigger.vue.js +10 -27
  11. package/es/open-code-widget/src/context.d.ts +3 -0
  12. package/es/open-code-widget/src/index-sfc.css +1 -1
  13. package/es/open-code-widget/src/index.vue.d.ts +10 -10
  14. package/es/open-code-widget/src/index.vue.js +107 -29
  15. package/lib/@vite-plugin-opencode-assistant/components.cjs.js +304 -140
  16. package/lib/@vite-plugin-opencode-assistant/components.es.js +305 -141
  17. package/lib/components.css +2 -2
  18. package/lib/index.d.ts +1 -1
  19. package/lib/index.js +1 -1
  20. package/lib/open-code-widget/composables/use-inspector.js +118 -79
  21. package/lib/open-code-widget/composables/use-persist-state.d.ts +24 -0
  22. package/lib/open-code-widget/composables/use-persist-state.js +78 -0
  23. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -1
  24. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +2 -2
  25. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.js +37 -21
  26. package/lib/open-code-widget/src/components/Trigger.vue.d.ts +0 -2
  27. package/lib/open-code-widget/src/components/Trigger.vue.js +10 -27
  28. package/lib/open-code-widget/src/context.d.ts +3 -0
  29. package/lib/open-code-widget/src/index-sfc.css +1 -1
  30. package/lib/open-code-widget/src/index.vue.d.ts +10 -10
  31. package/lib/open-code-widget/src/index.vue.js +106 -28
  32. package/lib/web-types.json +1 -1
  33. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createStaticVNode, createVNode, defineComponent, inject, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, provide, ref, renderList, renderSlot, toDisplayString, toRef, useCssVars, useSlots, vShow, watch, withCtx, withDirectives, withModifiers } from "vue";
1
+ import { Fragment, Teleport, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createStaticVNode, createVNode, defineComponent, inject, nextTick, normalizeClass, normalizeStyle, onMounted, onUnmounted, openBlock, provide, ref, renderList, renderSlot, toDisplayString, toRef, useCssVars, useSlots, vShow, watch, withCtx, withDirectives, withModifiers } from "vue";
2
2
  import { truncate } from "@vite-plugin-opencode-assistant/shared";
3
3
  import getCssSelector from "css-selector-generator";
4
4
  //#region es/open-code-widget/src/context.js
@@ -582,6 +582,19 @@ var __vue_sfc__$2 = /* @__PURE__ */ defineComponent(__spreadProps$1(__spreadValu
582
582
  bottom: windowHeight.value - state.value.height - gapY.value,
583
583
  left: gapX.value
584
584
  }));
585
+ const closest = (arr, target) => {
586
+ return arr.reduce((pre, cur) => Math.abs(pre - target) < Math.abs(cur - target) ? pre : cur);
587
+ };
588
+ const applyMagnetic = () => {
589
+ if (props.magnetic === "x") {
590
+ const nextX = closest([boundary.value.left, boundary.value.right], state.value.x);
591
+ state.value.x = nextX;
592
+ }
593
+ if (props.magnetic === "y") {
594
+ const nextY = closest([boundary.value.top, boundary.value.bottom], state.value.y);
595
+ state.value.y = nextY;
596
+ }
597
+ };
585
598
  const dragging = ref(false);
586
599
  const initialized = ref(false);
587
600
  const rootStyle = computed(() => {
@@ -603,12 +616,25 @@ var __vue_sfc__$2 = /* @__PURE__ */ defineComponent(__spreadProps$1(__spreadValu
603
616
  if (x > maxX) x = maxX;
604
617
  if (y < gapY.value) y = gapY.value;
605
618
  if (y > maxY) y = maxY;
619
+ const oldX = state.value.x;
620
+ const oldY = state.value.y;
606
621
  state.value = {
607
622
  x,
608
623
  y,
609
624
  width: rect.width,
610
625
  height: rect.height
611
626
  };
627
+ if (!dragging.value) {
628
+ applyMagnetic();
629
+ if (state.value.x !== oldX || state.value.y !== oldY) {
630
+ const offset2 = {
631
+ x: state.value.x,
632
+ y: state.value.y
633
+ };
634
+ emit("update:offset", offset2);
635
+ emit("offset-change", offset2);
636
+ }
637
+ }
612
638
  };
613
639
  const touch = {
614
640
  startX: ref(0),
@@ -645,6 +671,7 @@ var __vue_sfc__$2 = /* @__PURE__ */ defineComponent(__spreadProps$1(__spreadValu
645
671
  dragging.value = true;
646
672
  prevX = state.value.x;
647
673
  prevY = state.value.y;
674
+ document.body.classList.add("floating-bubble-dragging");
648
675
  if (!("touches" in e)) {
649
676
  window.addEventListener("mousemove", onTouchMove, { passive: false });
650
677
  window.addEventListener("mouseup", onTouchEnd);
@@ -675,24 +702,15 @@ var __vue_sfc__$2 = /* @__PURE__ */ defineComponent(__spreadProps$1(__spreadValu
675
702
  });
676
703
  }
677
704
  };
678
- const closest = (arr, target) => {
679
- return arr.reduce((pre, cur) => Math.abs(pre - target) < Math.abs(cur - target) ? pre : cur);
680
- };
681
705
  const onTouchEnd = (e) => {
682
706
  dragging.value = false;
707
+ document.body.classList.remove("floating-bubble-dragging");
683
708
  if (e && !("touches" in e) && e.type === "mouseup") {
684
709
  window.removeEventListener("mousemove", onTouchMove);
685
710
  window.removeEventListener("mouseup", onTouchEnd);
686
711
  }
687
712
  requestAnimationFrame(() => {
688
- if (props.magnetic === "x") {
689
- const nextX = closest([boundary.value.left, boundary.value.right], state.value.x);
690
- state.value.x = nextX;
691
- }
692
- if (props.magnetic === "y") {
693
- const nextY = closest([boundary.value.top, boundary.value.bottom], state.value.y);
694
- state.value.y = nextY;
695
- }
713
+ applyMagnetic();
696
714
  if (!touch.isTap.value) {
697
715
  emit("drag-end");
698
716
  const offset = {
@@ -723,6 +741,7 @@ var __vue_sfc__$2 = /* @__PURE__ */ defineComponent(__spreadProps$1(__spreadValu
723
741
  if (rootRef.value) rootRef.value.addEventListener("touchmove", onTouchMove, { passive: false });
724
742
  });
725
743
  onUnmounted(() => {
744
+ document.body.classList.remove("floating-bubble-dragging");
726
745
  if (typeof window !== "undefined") {
727
746
  window.removeEventListener("resize", handleResize);
728
747
  window.removeEventListener("mousemove", onTouchMove);
@@ -752,6 +771,8 @@ var __vue_sfc__$2 = /* @__PURE__ */ defineComponent(__spreadProps$1(__spreadValu
752
771
  windowWidth,
753
772
  windowHeight,
754
773
  boundary,
774
+ closest,
775
+ applyMagnetic,
755
776
  dragging,
756
777
  initialized,
757
778
  rootStyle,
@@ -771,7 +792,6 @@ var __vue_sfc__$2 = /* @__PURE__ */ defineComponent(__spreadProps$1(__spreadValu
771
792
  },
772
793
  onTouchStart,
773
794
  onTouchMove,
774
- closest,
775
795
  onTouchEnd,
776
796
  onClick,
777
797
  handleResize
@@ -799,38 +819,20 @@ __vue_sfc__$2.render = __vue_render__$2;
799
819
  var FloatingBubble_vue_default = __vue_sfc__$2;
800
820
  //#endregion
801
821
  //#region es/open-code-widget/src/components/Trigger.vue.js
802
- var STORAGE_KEY = "opencode-bubble-offset";
803
822
  var __vue_sfc__$1 = /* @__PURE__ */ defineComponent({
804
823
  __name: "Trigger",
805
- emits: [
806
- "offset-change",
807
- "drag-start",
808
- "drag-end"
809
- ],
824
+ emits: ["drag-start", "drag-end"],
810
825
  setup(__props, { expose: __expose, emit: __emit }) {
811
- const { buttonActive: active, open, hotkeyLabel, thinking, resolvedTheme, handleToggle } = useOpenCodeWidgetContext();
812
- const loadOffset = () => {
813
- try {
814
- const saved = localStorage.getItem(STORAGE_KEY);
815
- if (saved) {
816
- const parsed = JSON.parse(saved);
817
- if (parsed && (parsed.x !== 0 || parsed.y !== 0)) return parsed;
818
- }
819
- } catch (e) {}
820
- };
821
- const offset = ref(loadOffset());
826
+ const { buttonActive: active, open, hotkeyLabel, thinking, resolvedTheme, handleToggle, bubbleOffset, handleBubbleOffsetChange } = useOpenCodeWidgetContext();
827
+ const offset = ref(bubbleOffset.value);
822
828
  const emit = __emit;
823
- const saveOffset = (value) => {
824
- try {
825
- localStorage.setItem(STORAGE_KEY, JSON.stringify(value));
826
- } catch (e) {}
827
- };
828
829
  const handleOffsetChange = (value) => {
829
830
  offset.value = value;
830
- saveOffset(value);
831
- emit("offset-change", value);
831
+ handleBubbleOffsetChange(value);
832
832
  };
833
- watch(offset, handleOffsetChange, { immediate: true });
833
+ watch(bubbleOffset, (newOffset) => {
834
+ offset.value = newOffset;
835
+ });
834
836
  __expose({ offset });
835
837
  const __returned__ = {
836
838
  active,
@@ -839,11 +841,10 @@ var __vue_sfc__$1 = /* @__PURE__ */ defineComponent({
839
841
  thinking,
840
842
  resolvedTheme,
841
843
  handleToggle,
842
- STORAGE_KEY,
843
- loadOffset,
844
+ bubbleOffset,
845
+ handleBubbleOffsetChange,
844
846
  offset,
845
847
  emit,
846
- saveOffset,
847
848
  handleOffsetChange,
848
849
  FloatingBubble: FloatingBubble_vue_default
849
850
  };
@@ -1347,35 +1348,16 @@ function findFileInfo(element, inspector) {
1347
1348
  };
1348
1349
  }
1349
1350
  function getPreciseElementAtPoint(x, y, boundary) {
1350
- var _a, _b;
1351
- const highlight = document.querySelector(".opencode-element-highlight");
1352
- const tooltip = document.querySelector(".opencode-element-tooltip");
1353
- const highlightDisplay = ((_a = highlight == null ? void 0 : highlight.getAttribute("style")) == null ? void 0 : _a.includes("display: block")) ? "block" : "none";
1354
- const tooltipDisplay = ((_b = tooltip == null ? void 0 : tooltip.getAttribute("style")) == null ? void 0 : _b.includes("display: block")) ? "block" : "none";
1355
- if (highlight) highlight.style.display = "none";
1356
- if (tooltip) tooltip.style.display = "none";
1357
- let element = null;
1358
- try {
1359
- const elements = document.elementsFromPoint(x, y);
1360
- for (const el of elements) {
1361
- if (el.closest("#vue-inspector-container")) continue;
1362
- if (el.closest(".opencode-widget")) continue;
1363
- if (el.hasAttribute("data-v-inspector-ignore")) continue;
1364
- if (boundary) {
1365
- if (boundary.contains(el) || el === boundary) {
1366
- element = el;
1367
- break;
1368
- }
1369
- } else {
1370
- element = el;
1371
- break;
1372
- }
1373
- }
1374
- } finally {
1375
- if (highlight) highlight.style.display = highlightDisplay;
1376
- if (tooltip) tooltip.style.display = tooltipDisplay;
1351
+ const elements = document.elementsFromPoint(x, y);
1352
+ for (const el of elements) {
1353
+ if (el.closest("#vue-inspector-container")) continue;
1354
+ if (el.closest(".opencode-widget")) continue;
1355
+ if (el.hasAttribute("data-v-inspector-ignore")) continue;
1356
+ if (boundary) {
1357
+ if (boundary.contains(el) || el === boundary) return el;
1358
+ } else return el;
1377
1359
  }
1378
- return element;
1360
+ return null;
1379
1361
  }
1380
1362
  function useInspector(options) {
1381
1363
  const highlightVisible = ref(false);
@@ -1396,74 +1378,117 @@ function useInspector(options) {
1396
1378
  });
1397
1379
  const INSPECTOR_CHECK_INTERVAL = 500;
1398
1380
  let inspectorCheckTimer = null;
1381
+ let currentHighlightElement = null;
1382
+ let currentFileInfo = {
1383
+ file: null,
1384
+ line: null,
1385
+ column: null
1386
+ };
1387
+ let currentPrimary = "#3b82f6";
1388
+ let currentPrimaryBg = "rgba(59, 130, 246, 0.1)";
1389
+ let currentDescription = "";
1390
+ let currentFileInfoText = "";
1399
1391
  function handleMouseMoveCore(e) {
1400
1392
  var _a, _b;
1401
1393
  if (!options.selectMode.value) return;
1402
1394
  const inspector = window.__VUE_INSPECTOR__;
1395
+ const highlight = document.querySelector(".opencode-element-highlight");
1396
+ const tooltip = document.querySelector(".opencode-element-tooltip");
1397
+ if (highlight) highlight.style.pointerEvents = "none";
1398
+ if (tooltip) tooltip.style.pointerEvents = "none";
1403
1399
  let elementToHighlight = null;
1400
+ let targetNode = null;
1404
1401
  let fileInfo = {
1405
1402
  file: null,
1406
1403
  line: null,
1407
1404
  column: null
1408
1405
  };
1409
- if (inspector) {
1410
- const { targetNode, params } = inspector.getTargetNode(e);
1411
- if (targetNode) {
1412
- elementToHighlight = getPreciseElementAtPoint(e.clientX, e.clientY, targetNode) || targetNode;
1413
- if (params && params.file) fileInfo = {
1414
- file: params.file,
1415
- line: (_a = params.line) != null ? _a : null,
1416
- column: (_b = params.column) != null ? _b : null
1417
- };
1418
- else if (elementToHighlight) fileInfo = findFileInfo(elementToHighlight, inspector);
1406
+ try {
1407
+ if (inspector) {
1408
+ const result = inspector.getTargetNode(e);
1409
+ targetNode = result.targetNode;
1410
+ const params = result.params;
1411
+ if (targetNode) {
1412
+ elementToHighlight = getPreciseElementAtPoint(e.clientX, e.clientY, targetNode) || targetNode;
1413
+ if (params && params.file) fileInfo = {
1414
+ file: params.file,
1415
+ line: (_a = params.line) != null ? _a : null,
1416
+ column: (_b = params.column) != null ? _b : null
1417
+ };
1418
+ else fileInfo = findFileInfo(targetNode, inspector);
1419
+ }
1419
1420
  }
1421
+ if (!elementToHighlight) elementToHighlight = getPreciseElementAtPoint(e.clientX, e.clientY, null);
1422
+ if (elementToHighlight && !fileInfo.file) fileInfo = getFileInfoFromVueInstance(elementToHighlight) || fileInfo;
1423
+ } finally {
1424
+ if (highlight) highlight.style.pointerEvents = "";
1425
+ if (tooltip) tooltip.style.pointerEvents = "";
1420
1426
  }
1421
- if (!elementToHighlight) elementToHighlight = getPreciseElementAtPoint(e.clientX, e.clientY, null);
1422
- if (elementToHighlight && !fileInfo.file) fileInfo = getFileInfoFromVueInstance(elementToHighlight) || fileInfo;
1423
1427
  if (elementToHighlight) {
1424
- const rect = elementToHighlight.getBoundingClientRect();
1425
- const widget = document.querySelector(".opencode-widget");
1426
- let primary = "#3b82f6";
1427
- let primaryBg = "rgba(59, 130, 246, 0.1)";
1428
- if (widget) {
1429
- const style = getComputedStyle(widget);
1430
- primary = style.getPropertyValue("--oc-primary").trim() || primary;
1431
- primaryBg = style.getPropertyValue("--oc-primary-bg").trim() || primaryBg;
1432
- }
1433
- highlightVisible.value = true;
1434
- highlightStyle.value = {
1435
- top: `${rect.top}px`,
1436
- left: `${rect.left}px`,
1437
- width: `${rect.width}px`,
1438
- height: `${rect.height}px`,
1439
- border: `2px solid ${primary}`,
1440
- background: primaryBg
1441
- };
1442
- const description = getElementDescription(elementToHighlight);
1443
- const fileName = fileInfo.file ? fileInfo.file.split("/").pop() : "";
1428
+ const elementChanged = currentHighlightElement !== elementToHighlight;
1429
+ if (elementChanged) {
1430
+ currentHighlightElement = elementToHighlight;
1431
+ currentFileInfo = fileInfo;
1432
+ const widget = document.querySelector(".opencode-widget");
1433
+ if (widget) {
1434
+ const style = getComputedStyle(widget);
1435
+ currentPrimary = style.getPropertyValue("--oc-primary").trim() || currentPrimary;
1436
+ currentPrimaryBg = style.getPropertyValue("--oc-primary-bg").trim() || currentPrimaryBg;
1437
+ }
1438
+ currentDescription = getElementDescription(elementToHighlight);
1439
+ } else if (!currentFileInfo.file && fileInfo.file) currentFileInfo = fileInfo;
1440
+ const fileName = currentFileInfo.file ? currentFileInfo.file.split("/").pop() : "";
1444
1441
  let lineInfo = "";
1445
- if (fileInfo.line) {
1446
- lineInfo = `:${fileInfo.line}`;
1447
- if (fileInfo.column) lineInfo += `:${fileInfo.column}`;
1442
+ if (currentFileInfo.line) {
1443
+ lineInfo = `:${currentFileInfo.line}`;
1444
+ if (currentFileInfo.column) lineInfo += `:${currentFileInfo.column}`;
1445
+ }
1446
+ const newFileInfoText = fileName ? `${fileName}${lineInfo}` : "";
1447
+ if (elementChanged || currentFileInfoText !== newFileInfoText) {
1448
+ currentFileInfoText = newFileInfoText;
1449
+ tooltipContent.value = {
1450
+ description: currentDescription,
1451
+ fileInfo: currentFileInfoText
1452
+ };
1448
1453
  }
1449
- tooltipContent.value = {
1450
- description,
1451
- fileInfo: fileName ? `${fileName}${lineInfo}` : ""
1454
+ const rect = elementToHighlight.getBoundingClientRect();
1455
+ const newTop = `${rect.top}px`;
1456
+ const newLeft = `${rect.left}px`;
1457
+ const newWidth = `${rect.width}px`;
1458
+ const newHeight = `${rect.height}px`;
1459
+ if (highlightStyle.value.top !== newTop || highlightStyle.value.left !== newLeft || highlightStyle.value.width !== newWidth || highlightStyle.value.height !== newHeight) highlightStyle.value = {
1460
+ top: newTop,
1461
+ left: newLeft,
1462
+ width: newWidth,
1463
+ height: newHeight,
1464
+ border: `2px solid ${currentPrimary}`,
1465
+ background: currentPrimaryBg
1452
1466
  };
1453
- tooltipVisible.value = true;
1454
1467
  const tooltipHeight = 50;
1455
1468
  const tooltipWidth = 200;
1456
1469
  let tooltipTop = rect.top - tooltipHeight - 8;
1457
1470
  let tooltipLeft = rect.left;
1458
1471
  if (tooltipTop < 10) tooltipTop = rect.bottom + 8;
1459
1472
  if (tooltipLeft + tooltipWidth > window.innerWidth - 10) tooltipLeft = window.innerWidth - tooltipWidth - 10;
1460
- tooltipStyle.value = {
1461
- top: `${tooltipTop}px`,
1462
- left: `${tooltipLeft}px`
1473
+ const newTooltipTop = `${tooltipTop}px`;
1474
+ const newTooltipLeft = `${tooltipLeft}px`;
1475
+ if (tooltipStyle.value.top !== newTooltipTop || tooltipStyle.value.left !== newTooltipLeft) tooltipStyle.value = {
1476
+ top: newTooltipTop,
1477
+ left: newTooltipLeft
1463
1478
  };
1479
+ if (!highlightVisible.value) highlightVisible.value = true;
1480
+ if (!tooltipVisible.value) tooltipVisible.value = true;
1464
1481
  } else {
1465
- highlightVisible.value = false;
1466
- tooltipVisible.value = false;
1482
+ currentHighlightElement = null;
1483
+ currentDescription = "";
1484
+ currentFileInfoText = "";
1485
+ currentFileInfo = {
1486
+ file: null,
1487
+ line: null,
1488
+ column: null
1489
+ };
1490
+ if (highlightVisible.value) highlightVisible.value = false;
1491
+ if (tooltipVisible.value) tooltipVisible.value = false;
1467
1492
  }
1468
1493
  }
1469
1494
  const handleMouseMove = throttle(handleMouseMoveCore, 16);
@@ -1527,6 +1552,14 @@ function useInspector(options) {
1527
1552
  if (inspector) inspector.disable();
1528
1553
  document.removeEventListener("mousemove", handleMouseMove);
1529
1554
  document.removeEventListener("keydown", handleKeydown, true);
1555
+ currentHighlightElement = null;
1556
+ currentDescription = "";
1557
+ currentFileInfoText = "";
1558
+ currentFileInfo = {
1559
+ file: null,
1560
+ line: null,
1561
+ column: null
1562
+ };
1530
1563
  highlightVisible.value = false;
1531
1564
  tooltipVisible.value = false;
1532
1565
  }
@@ -1557,6 +1590,62 @@ function useInspector(options) {
1557
1590
  };
1558
1591
  }
1559
1592
  //#endregion
1593
+ //#region es/open-code-widget/composables/use-persist-state.js
1594
+ var STORAGE_KEY = "opencode-widget-state";
1595
+ function loadState() {
1596
+ if (typeof window === "undefined") return null;
1597
+ try {
1598
+ const stored = localStorage.getItem(STORAGE_KEY);
1599
+ if (stored) return JSON.parse(stored);
1600
+ } catch (e) {
1601
+ console.warn("[OpenCodeWidget] Failed to load persisted state:", e);
1602
+ }
1603
+ return null;
1604
+ }
1605
+ function saveState(state) {
1606
+ if (typeof window === "undefined") return;
1607
+ try {
1608
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
1609
+ } catch (e) {
1610
+ console.warn("[OpenCodeWidget] Failed to save state:", e);
1611
+ }
1612
+ }
1613
+ function usePersistState(options) {
1614
+ const restoreState = () => {
1615
+ const saved = loadState();
1616
+ if (options.onRestore) options.onRestore(saved || {});
1617
+ return saved;
1618
+ };
1619
+ const getCurrentState = () => ({
1620
+ open: options.open.value,
1621
+ minimized: options.minimized.value,
1622
+ promptDockVisible: options.promptDockVisible.value,
1623
+ bubbleOffset: options.bubbleOffset.value,
1624
+ theme: options.theme.value,
1625
+ sessionListCollapsed: options.sessionListCollapsed.value
1626
+ });
1627
+ const persistState = () => {
1628
+ saveState(getCurrentState());
1629
+ };
1630
+ onMounted(() => {
1631
+ restoreState();
1632
+ watch([
1633
+ options.open,
1634
+ options.minimized,
1635
+ options.promptDockVisible,
1636
+ options.bubbleOffset,
1637
+ options.theme,
1638
+ options.sessionListCollapsed
1639
+ ], () => {
1640
+ persistState();
1641
+ }, { deep: true });
1642
+ });
1643
+ return {
1644
+ restoreState,
1645
+ persistState
1646
+ };
1647
+ }
1648
+ //#endregion
1560
1649
  //#region es/open-code-widget/src/index.vue.js
1561
1650
  var __defProp = Object.defineProperty;
1562
1651
  var __defProps = Object.defineProperties;
@@ -1760,17 +1849,26 @@ var __vue_sfc__ = /* @__PURE__ */ defineComponent(__spreadProps(__spreadValues({
1760
1849
  var _a;
1761
1850
  (_a = frameRef.value) == null || _a.sendMessageToIframe(type, data);
1762
1851
  };
1852
+ const localSessionListCollapsed = ref(props.sessionListCollapsed);
1853
+ const minimized = ref(false);
1854
+ const promptDockVisible = ref(true);
1855
+ const isRestoring = ref(true);
1856
+ const iframeLoaded = ref(false);
1857
+ const syncStateToIframe = () => {
1858
+ if (!iframeLoaded.value) return;
1859
+ sendMessageToIframe("prompt-dock-visibility-change", { visible: promptDockVisible.value });
1860
+ sendMessageToIframe("minimize-state-change", { minimized: minimized.value });
1861
+ };
1763
1862
  const handleFrameLoaded = () => {
1764
1863
  emit("frame-loaded");
1864
+ iframeLoaded.value = true;
1865
+ syncStateToIframe();
1765
1866
  };
1766
1867
  __expose({
1767
1868
  showNotification,
1768
1869
  showConfirmDialog,
1769
1870
  sendMessageToIframe
1770
1871
  });
1771
- const localSessionListCollapsed = ref(props.sessionListCollapsed);
1772
- const minimized = ref(false);
1773
- const promptDockVisible = ref(true);
1774
1872
  watch(() => props.sessionListCollapsed, (val) => {
1775
1873
  localSessionListCollapsed.value = val;
1776
1874
  });
@@ -1845,6 +1943,48 @@ var __vue_sfc__ = /* @__PURE__ */ defineComponent(__spreadProps(__spreadValues({
1845
1943
  emit("toggle-select-mode", false);
1846
1944
  }
1847
1945
  });
1946
+ const bubbleOffset = ref(void 0);
1947
+ usePersistState({
1948
+ open: toRef(props, "open"),
1949
+ minimized,
1950
+ promptDockVisible,
1951
+ bubbleOffset,
1952
+ theme: toRef(props, "theme"),
1953
+ sessionListCollapsed: localSessionListCollapsed,
1954
+ onRestore: (state) => {
1955
+ if (state.open !== void 0 && state.open !== props.open) {
1956
+ emit("update:open", state.open);
1957
+ emit("toggle", state.open);
1958
+ }
1959
+ if (state.minimized !== void 0) minimized.value = state.minimized;
1960
+ if (state.bubbleOffset !== void 0) {
1961
+ const bubbleSize = 44;
1962
+ const margin = 10;
1963
+ const maxX = window.innerWidth - bubbleSize - margin;
1964
+ const maxY = window.innerHeight - bubbleSize - margin;
1965
+ bubbleOffset.value = {
1966
+ x: Math.max(margin, Math.min(state.bubbleOffset.x, maxX)),
1967
+ y: Math.max(margin, Math.min(state.bubbleOffset.y, maxY))
1968
+ };
1969
+ }
1970
+ if (state.theme !== void 0 && state.theme !== props.theme) {
1971
+ emit("update:theme", state.theme);
1972
+ emit("toggle-theme", state.theme);
1973
+ }
1974
+ if (state.sessionListCollapsed !== void 0 && state.sessionListCollapsed !== props.sessionListCollapsed) {
1975
+ localSessionListCollapsed.value = state.sessionListCollapsed;
1976
+ emit("update:sessionListCollapsed", state.sessionListCollapsed);
1977
+ }
1978
+ if (state.promptDockVisible !== void 0) promptDockVisible.value = state.promptDockVisible;
1979
+ else if (minimized.value) promptDockVisible.value = false;
1980
+ nextTick(() => {
1981
+ syncStateToIframe();
1982
+ setTimeout(() => {
1983
+ isRestoring.value = false;
1984
+ }, 50);
1985
+ });
1986
+ }
1987
+ });
1848
1988
  const handleToggleMinimize = () => {
1849
1989
  minimized.value = !minimized.value;
1850
1990
  promptDockVisible.value = !minimized.value;
@@ -1855,15 +1995,29 @@ var __vue_sfc__ = /* @__PURE__ */ defineComponent(__spreadProps(__spreadValues({
1855
1995
  promptDockVisible.value = !promptDockVisible.value;
1856
1996
  sendMessageToIframe("prompt-dock-visibility-change", { visible: promptDockVisible.value });
1857
1997
  };
1858
- const bubbleOffset = ref(void 0);
1998
+ const windowWidth = ref(typeof window !== "undefined" ? window.innerWidth : 0);
1999
+ const windowHeight = ref(typeof window !== "undefined" ? window.innerHeight : 0);
2000
+ const handleWindowResize = () => {
2001
+ if (typeof window !== "undefined") {
2002
+ windowWidth.value = window.innerWidth;
2003
+ windowHeight.value = window.innerHeight;
2004
+ }
2005
+ };
2006
+ onMounted(() => {
2007
+ if (typeof window !== "undefined") window.addEventListener("resize", handleWindowResize);
2008
+ });
2009
+ onUnmounted(() => {
2010
+ if (typeof window !== "undefined") window.removeEventListener("resize", handleWindowResize);
2011
+ });
1859
2012
  const bubbleQuadrant = computed(() => {
1860
2013
  var _a, _b, _c, _d;
1861
2014
  if (typeof window === "undefined") return "bottom-right";
1862
- const centerX = window.innerWidth / 2;
1863
- const centerY = window.innerHeight / 2;
2015
+ const centerX = windowWidth.value / 2;
2016
+ const centerY = windowHeight.value / 2;
1864
2017
  const bubbleSize = 44;
1865
- const effectiveX = ((_b = (_a = bubbleOffset.value) == null ? void 0 : _a.x) != null ? _b : window.innerWidth - bubbleSize - 24) + bubbleSize / 2;
1866
- const effectiveY = ((_d = (_c = bubbleOffset.value) == null ? void 0 : _c.y) != null ? _d : window.innerHeight - bubbleSize - 24) + bubbleSize / 2;
2018
+ const currentOffset = (_b = (_a = triggerRef.value) == null ? void 0 : _a.offset) != null ? _b : bubbleOffset.value;
2019
+ const effectiveX = ((_c = currentOffset == null ? void 0 : currentOffset.x) != null ? _c : windowWidth.value - bubbleSize - 24) + bubbleSize / 2;
2020
+ const effectiveY = ((_d = currentOffset == null ? void 0 : currentOffset.y) != null ? _d : windowHeight.value - bubbleSize - 24) + bubbleSize / 2;
1867
2021
  if (effectiveX >= centerX && effectiveY >= centerY) return "bottom-right";
1868
2022
  else if (effectiveX < centerX && effectiveY >= centerY) return "bottom-left";
1869
2023
  else if (effectiveX >= centerX && effectiveY < centerY) return "top-right";
@@ -1874,35 +2028,37 @@ var __vue_sfc__ = /* @__PURE__ */ defineComponent(__spreadProps(__spreadValues({
1874
2028
  return quadrant === "top-right" || quadrant === "bottom-right";
1875
2029
  });
1876
2030
  const chatPositionStyle = computed(() => {
1877
- var _a;
2031
+ var _a, _b, _c;
1878
2032
  if (typeof window === "undefined") return {};
1879
- const windowWidth = window.innerWidth;
1880
- const windowHeight = window.innerHeight;
1881
2033
  const chatWidth = minimized.value ? 300 : 700;
1882
- const chatHeight = minimized.value ? 300 : Math.min(windowHeight * .86, windowHeight - 40);
2034
+ const chatHeight = minimized.value ? 300 : Math.min(windowHeight.value * .86, windowHeight.value - 40);
1883
2035
  const gap = 24;
1884
2036
  const bubbleSize = 44;
1885
2037
  const screenMargin = 20;
1886
- const effectiveOffset = (_a = bubbleOffset.value) != null ? _a : {
1887
- x: windowWidth - bubbleSize - gap,
1888
- y: windowHeight - bubbleSize - gap
2038
+ const effectiveOffset = (_c = (_b = (_a = triggerRef.value) == null ? void 0 : _a.offset) != null ? _b : bubbleOffset.value) != null ? _c : {
2039
+ x: windowWidth.value - bubbleSize - gap,
2040
+ y: windowHeight.value - bubbleSize - gap
1889
2041
  };
1890
2042
  const style = {};
1891
2043
  if (isBubbleOnRightSide.value) {
1892
- let rightPos = windowWidth - effectiveOffset.x + gap;
1893
- const maxRight = windowWidth - chatWidth - screenMargin;
2044
+ let rightPos = windowWidth.value - effectiveOffset.x + gap;
2045
+ const minRight = screenMargin;
2046
+ const maxRight = windowWidth.value - chatWidth - screenMargin;
1894
2047
  if (rightPos > maxRight) rightPos = maxRight;
2048
+ if (rightPos < minRight) rightPos = minRight;
1895
2049
  style.right = `${rightPos}px`;
1896
2050
  style.left = "auto";
1897
2051
  } else {
1898
2052
  let leftPos = effectiveOffset.x + bubbleSize + gap;
1899
- const maxLeft = windowWidth - chatWidth - screenMargin;
2053
+ const minLeft = screenMargin;
2054
+ const maxLeft = windowWidth.value - chatWidth - screenMargin;
1900
2055
  if (leftPos > maxLeft) leftPos = maxLeft;
2056
+ if (leftPos < minLeft) leftPos = minLeft;
1901
2057
  style.left = `${leftPos}px`;
1902
2058
  style.right = "auto";
1903
2059
  }
1904
- let bottomPos = windowHeight - effectiveOffset.y - bubbleSize;
1905
- const maxBottom = windowHeight - chatHeight - screenMargin;
2060
+ let bottomPos = windowHeight.value - effectiveOffset.y - bubbleSize;
2061
+ const maxBottom = windowHeight.value - chatHeight - screenMargin;
1906
2062
  if (bottomPos > maxBottom) bottomPos = maxBottom;
1907
2063
  if (bottomPos < screenMargin) bottomPos = screenMargin;
1908
2064
  style.bottom = `${bottomPos}px`;
@@ -1964,6 +2120,7 @@ var __vue_sfc__ = /* @__PURE__ */ defineComponent(__spreadProps(__spreadValues({
1964
2120
  thinking: toRef(props, "thinking"),
1965
2121
  minimized,
1966
2122
  promptDockVisible,
2123
+ bubbleOffset,
1967
2124
  iframeSource,
1968
2125
  buttonActive,
1969
2126
  sessionListTitle,
@@ -1985,7 +2142,8 @@ var __vue_sfc__ = /* @__PURE__ */ defineComponent(__spreadProps(__spreadValues({
1985
2142
  handleClickSelectedNode,
1986
2143
  handleRemoveSelectedNode: (payload) => handleRemoveSelectedNode(payload.item, payload.index, payload.source),
1987
2144
  handleClearSelectedNodes,
1988
- handleFrameLoaded
2145
+ handleFrameLoaded,
2146
+ handleBubbleOffsetChange
1989
2147
  });
1990
2148
  const __returned__ = {
1991
2149
  props,
@@ -2015,10 +2173,13 @@ var __vue_sfc__ = /* @__PURE__ */ defineComponent(__spreadProps(__spreadValues({
2015
2173
  frameRef,
2016
2174
  triggerRef,
2017
2175
  sendMessageToIframe,
2018
- handleFrameLoaded,
2019
2176
  localSessionListCollapsed,
2020
2177
  minimized,
2021
2178
  promptDockVisible,
2179
+ isRestoring,
2180
+ iframeLoaded,
2181
+ syncStateToIframe,
2182
+ handleFrameLoaded,
2022
2183
  buttonActive,
2023
2184
  containerClasses,
2024
2185
  iframeSource,
@@ -2045,9 +2206,12 @@ var __vue_sfc__ = /* @__PURE__ */ defineComponent(__spreadProps(__spreadValues({
2045
2206
  tooltipVisible,
2046
2207
  tooltipStyle,
2047
2208
  tooltipContent,
2209
+ bubbleOffset,
2048
2210
  handleToggleMinimize,
2049
2211
  handleTogglePromptDock,
2050
- bubbleOffset,
2212
+ windowWidth,
2213
+ windowHeight,
2214
+ handleWindowResize,
2051
2215
  bubbleQuadrant,
2052
2216
  isBubbleOnRightSide,
2053
2217
  chatPositionStyle,
@@ -2104,7 +2268,6 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
2104
2268
  return openBlock(), createElementBlock("div", { class: normalizeClass($setup.containerClasses) }, [
2105
2269
  createVNode($setup["Trigger"], {
2106
2270
  ref: "triggerRef",
2107
- onOffsetChange: $setup.handleBubbleOffsetChange,
2108
2271
  onDragStart: $setup.handleDragStart,
2109
2272
  onDragEnd: $setup.handleDragEnd
2110
2273
  }, createSlots({ _: 2 }, [$setup.slots["button-icon"] ? {
@@ -2116,7 +2279,8 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
2116
2279
  class: normalizeClass(["opencode-chat", {
2117
2280
  open: $props.open,
2118
2281
  minimized: $setup.minimized,
2119
- dragging: $setup.isDragging
2282
+ dragging: $setup.isDragging,
2283
+ "no-transition": $setup.isRestoring
2120
2284
  }]),
2121
2285
  style: normalizeStyle($setup.chatPositionStyle)
2122
2286
  }, [
@@ -2171,11 +2335,11 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
2171
2335
  createVNode($setup["SelectHint"]),
2172
2336
  withDirectives(createElementVNode("div", {
2173
2337
  class: "opencode-element-highlight",
2174
- style: normalizeStyle(__spreadValues({ display: $setup.highlightVisible ? "block" : "none" }, $setup.highlightStyle))
2338
+ style: normalizeStyle($setup.highlightStyle)
2175
2339
  }, null, 4), [[vShow, $setup.highlightVisible]]),
2176
2340
  withDirectives(createElementVNode("div", {
2177
2341
  class: "opencode-element-tooltip",
2178
- style: normalizeStyle(__spreadValues({ display: $setup.tooltipVisible ? "block" : "none" }, $setup.tooltipStyle))
2342
+ style: normalizeStyle($setup.tooltipStyle)
2179
2343
  }, [createElementVNode("div", _hoisted_3, toDisplayString($setup.tooltipContent.description), 1), createElementVNode("div", _hoisted_4, toDisplayString($setup.tooltipContent.fileInfo), 1)], 4), [[vShow, $setup.tooltipVisible]]),
2180
2344
  $setup.dialogVisible ? (openBlock(), createElementBlock("div", _hoisted_5, [createElementVNode("div", _hoisted_6, [createElementVNode("div", _hoisted_7, [createElementVNode("div", _hoisted_8, toDisplayString($setup.dialogMessage), 1)]), createElementVNode("div", { class: "opencode-dialog-actions" }, [createElementVNode("button", {
2181
2345
  class: "opencode-dialog-btn cancel",
@@ -2193,7 +2357,7 @@ __vue_sfc__.render = __vue_render__;
2193
2357
  var open_code_widget_default = __vue_sfc__;
2194
2358
  //#endregion
2195
2359
  //#region es/index.js
2196
- var version = "1.0.26";
2360
+ var version = "1.0.27";
2197
2361
  function install(app, options) {
2198
2362
  [open_code_widget_default].forEach((item) => {
2199
2363
  if (item.install) app.use(item, options);