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

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 (41) 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/SessionList-sfc.css +1 -1
  10. package/es/open-code-widget/src/components/SessionList.vue.js +27 -16
  11. package/es/open-code-widget/src/components/Trigger-sfc.css +1 -1
  12. package/es/open-code-widget/src/components/Trigger.vue.d.ts +0 -2
  13. package/es/open-code-widget/src/components/Trigger.vue.js +10 -27
  14. package/es/open-code-widget/src/context.d.ts +5 -1
  15. package/es/open-code-widget/src/index-sfc.css +1 -1
  16. package/es/open-code-widget/src/index.vue.d.ts +11 -11
  17. package/es/open-code-widget/src/index.vue.js +113 -30
  18. package/es/open-code-widget/src/types.d.ts +1 -1
  19. package/lib/@vite-plugin-opencode-assistant/components.cjs.js +340 -153
  20. package/lib/@vite-plugin-opencode-assistant/components.es.js +341 -154
  21. package/lib/components.css +4 -4
  22. package/lib/index.d.ts +1 -1
  23. package/lib/index.js +1 -1
  24. package/lib/open-code-widget/composables/use-inspector.js +118 -79
  25. package/lib/open-code-widget/composables/use-persist-state.d.ts +24 -0
  26. package/lib/open-code-widget/composables/use-persist-state.js +78 -0
  27. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -1
  28. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +2 -2
  29. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.js +37 -21
  30. package/lib/open-code-widget/src/components/SessionList-sfc.css +1 -1
  31. package/lib/open-code-widget/src/components/SessionList.vue.js +26 -15
  32. package/lib/open-code-widget/src/components/Trigger-sfc.css +1 -1
  33. package/lib/open-code-widget/src/components/Trigger.vue.d.ts +0 -2
  34. package/lib/open-code-widget/src/components/Trigger.vue.js +10 -27
  35. package/lib/open-code-widget/src/context.d.ts +5 -1
  36. package/lib/open-code-widget/src/index-sfc.css +1 -1
  37. package/lib/open-code-widget/src/index.vue.d.ts +11 -11
  38. package/lib/open-code-widget/src/index.vue.js +112 -29
  39. package/lib/open-code-widget/src/types.d.ts +1 -1
  40. package/lib/web-types.json +1 -1
  41. package/package.json +2 -2
package/es/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import OpenCodeWidget from './open-code-widget';
2
2
  import type { App } from 'vue';
3
- declare const version = "1.0.26";
3
+ declare const version = "1.0.28";
4
4
  declare function install(app: App<any>, options?: any): void;
5
5
  export { install, version, OpenCodeWidget };
6
6
  export default install;
package/es/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import OpenCodeWidget from "./open-code-widget";
2
- const version = "1.0.26";
2
+ const version = "1.0.28";
3
3
  function install(app, options) {
4
4
  const components = [
5
5
  OpenCodeWidget
@@ -202,35 +202,20 @@ function findFileInfo(element, inspector) {
202
202
  return fallbackFileInfo || { file: null, line: null, column: null };
203
203
  }
204
204
  function getPreciseElementAtPoint(x, y, boundary) {
205
- var _a, _b;
206
- const highlight = document.querySelector(".opencode-element-highlight");
207
- const tooltip = document.querySelector(".opencode-element-tooltip");
208
- const highlightDisplay = ((_a = highlight == null ? void 0 : highlight.getAttribute("style")) == null ? void 0 : _a.includes("display: block")) ? "block" : "none";
209
- const tooltipDisplay = ((_b = tooltip == null ? void 0 : tooltip.getAttribute("style")) == null ? void 0 : _b.includes("display: block")) ? "block" : "none";
210
- if (highlight) highlight.style.display = "none";
211
- if (tooltip) tooltip.style.display = "none";
212
- let element = null;
213
- try {
214
- const elements = document.elementsFromPoint(x, y);
215
- for (const el of elements) {
216
- if (el.closest("#vue-inspector-container")) continue;
217
- if (el.closest(".opencode-widget")) continue;
218
- if (el.hasAttribute("data-v-inspector-ignore")) continue;
219
- if (boundary) {
220
- if (boundary.contains(el) || el === boundary) {
221
- element = el;
222
- break;
223
- }
224
- } else {
225
- element = el;
226
- break;
205
+ const elements = document.elementsFromPoint(x, y);
206
+ for (const el of elements) {
207
+ if (el.closest("#vue-inspector-container")) continue;
208
+ if (el.closest(".opencode-widget")) continue;
209
+ if (el.hasAttribute("data-v-inspector-ignore")) continue;
210
+ if (boundary) {
211
+ if (boundary.contains(el) || el === boundary) {
212
+ return el;
227
213
  }
214
+ } else {
215
+ return el;
228
216
  }
229
- } finally {
230
- if (highlight) highlight.style.display = highlightDisplay;
231
- if (tooltip) tooltip.style.display = tooltipDisplay;
232
217
  }
233
- return element;
218
+ return null;
234
219
  }
235
220
  function useInspector(options) {
236
221
  const highlightVisible = ref(false);
@@ -245,67 +230,99 @@ function useInspector(options) {
245
230
  const tooltipContent = ref({ description: "", fileInfo: "" });
246
231
  const INSPECTOR_CHECK_INTERVAL = 500;
247
232
  let inspectorCheckTimer = null;
233
+ let currentHighlightElement = null;
234
+ let currentFileInfo = { file: null, line: null, column: null };
235
+ let currentPrimary = "#3b82f6";
236
+ let currentPrimaryBg = "rgba(59, 130, 246, 0.1)";
237
+ let currentDescription = "";
238
+ let currentFileInfoText = "";
248
239
  function handleMouseMoveCore(e) {
249
240
  var _a, _b;
250
241
  if (!options.selectMode.value) return;
251
242
  const inspector = window.__VUE_INSPECTOR__;
243
+ const highlight = document.querySelector(".opencode-element-highlight");
244
+ const tooltip = document.querySelector(".opencode-element-tooltip");
245
+ if (highlight) highlight.style.pointerEvents = "none";
246
+ if (tooltip) tooltip.style.pointerEvents = "none";
252
247
  let elementToHighlight = null;
248
+ let targetNode = null;
253
249
  let fileInfo = { file: null, line: null, column: null };
254
- if (inspector) {
255
- const { targetNode, params } = inspector.getTargetNode(e);
256
- if (targetNode) {
257
- const preciseElement = getPreciseElementAtPoint(e.clientX, e.clientY, targetNode);
258
- elementToHighlight = preciseElement || targetNode;
259
- if (params && params.file) {
260
- fileInfo = {
261
- file: params.file,
262
- line: (_a = params.line) != null ? _a : null,
263
- column: (_b = params.column) != null ? _b : null
264
- };
265
- } else if (elementToHighlight) {
266
- fileInfo = findFileInfo(elementToHighlight, inspector);
250
+ try {
251
+ if (inspector) {
252
+ const result = inspector.getTargetNode(e);
253
+ targetNode = result.targetNode;
254
+ const params = result.params;
255
+ if (targetNode) {
256
+ const preciseElement = getPreciseElementAtPoint(e.clientX, e.clientY, targetNode);
257
+ elementToHighlight = preciseElement || targetNode;
258
+ if (params && params.file) {
259
+ fileInfo = {
260
+ file: params.file,
261
+ line: (_a = params.line) != null ? _a : null,
262
+ column: (_b = params.column) != null ? _b : null
263
+ };
264
+ } else {
265
+ fileInfo = findFileInfo(targetNode, inspector);
266
+ }
267
267
  }
268
268
  }
269
- }
270
- if (!elementToHighlight) {
271
- elementToHighlight = getPreciseElementAtPoint(e.clientX, e.clientY, null);
272
- }
273
- if (elementToHighlight && !fileInfo.file) {
274
- fileInfo = getFileInfoFromVueInstance(elementToHighlight) || fileInfo;
269
+ if (!elementToHighlight) {
270
+ elementToHighlight = getPreciseElementAtPoint(e.clientX, e.clientY, null);
271
+ }
272
+ if (elementToHighlight && !fileInfo.file) {
273
+ fileInfo = getFileInfoFromVueInstance(elementToHighlight) || fileInfo;
274
+ }
275
+ } finally {
276
+ if (highlight) highlight.style.pointerEvents = "";
277
+ if (tooltip) tooltip.style.pointerEvents = "";
275
278
  }
276
279
  if (elementToHighlight) {
277
- const rect = elementToHighlight.getBoundingClientRect();
278
- const widget = document.querySelector(".opencode-widget");
279
- let primary = "#3b82f6";
280
- let primaryBg = "rgba(59, 130, 246, 0.1)";
281
- if (widget) {
282
- const style = getComputedStyle(widget);
283
- primary = style.getPropertyValue("--oc-primary").trim() || primary;
284
- primaryBg = style.getPropertyValue("--oc-primary-bg").trim() || primaryBg;
280
+ const elementChanged = currentHighlightElement !== elementToHighlight;
281
+ if (elementChanged) {
282
+ currentHighlightElement = elementToHighlight;
283
+ currentFileInfo = fileInfo;
284
+ const widget = document.querySelector(".opencode-widget");
285
+ if (widget) {
286
+ const style = getComputedStyle(widget);
287
+ currentPrimary = style.getPropertyValue("--oc-primary").trim() || currentPrimary;
288
+ currentPrimaryBg = style.getPropertyValue("--oc-primary-bg").trim() || currentPrimaryBg;
289
+ }
290
+ currentDescription = getElementDescription(elementToHighlight);
291
+ } else if (!currentFileInfo.file && fileInfo.file) {
292
+ currentFileInfo = fileInfo;
285
293
  }
286
- highlightVisible.value = true;
287
- highlightStyle.value = {
288
- top: `${rect.top}px`,
289
- left: `${rect.left}px`,
290
- width: `${rect.width}px`,
291
- height: `${rect.height}px`,
292
- border: `2px solid ${primary}`,
293
- background: primaryBg
294
- };
295
- const description = getElementDescription(elementToHighlight);
296
- const fileName = fileInfo.file ? fileInfo.file.split("/").pop() : "";
294
+ const fileName = currentFileInfo.file ? currentFileInfo.file.split("/").pop() : "";
297
295
  let lineInfo = "";
298
- if (fileInfo.line) {
299
- lineInfo = `:${fileInfo.line}`;
300
- if (fileInfo.column) {
301
- lineInfo += `:${fileInfo.column}`;
296
+ if (currentFileInfo.line) {
297
+ lineInfo = `:${currentFileInfo.line}`;
298
+ if (currentFileInfo.column) {
299
+ lineInfo += `:${currentFileInfo.column}`;
302
300
  }
303
301
  }
304
- tooltipContent.value = {
305
- description,
306
- fileInfo: fileName ? `${fileName}${lineInfo}` : ""
307
- };
308
- tooltipVisible.value = true;
302
+ const newFileInfoText = fileName ? `${fileName}${lineInfo}` : "";
303
+ const fileInfoChanged = currentFileInfoText !== newFileInfoText;
304
+ if (elementChanged || fileInfoChanged) {
305
+ currentFileInfoText = newFileInfoText;
306
+ tooltipContent.value = {
307
+ description: currentDescription,
308
+ fileInfo: currentFileInfoText
309
+ };
310
+ }
311
+ const rect = elementToHighlight.getBoundingClientRect();
312
+ const newTop = `${rect.top}px`;
313
+ const newLeft = `${rect.left}px`;
314
+ const newWidth = `${rect.width}px`;
315
+ const newHeight = `${rect.height}px`;
316
+ if (highlightStyle.value.top !== newTop || highlightStyle.value.left !== newLeft || highlightStyle.value.width !== newWidth || highlightStyle.value.height !== newHeight) {
317
+ highlightStyle.value = {
318
+ top: newTop,
319
+ left: newLeft,
320
+ width: newWidth,
321
+ height: newHeight,
322
+ border: `2px solid ${currentPrimary}`,
323
+ background: currentPrimaryBg
324
+ };
325
+ }
309
326
  const tooltipHeight = 50;
310
327
  const tooltipWidth = 200;
311
328
  let tooltipTop = rect.top - tooltipHeight - 8;
@@ -316,13 +333,31 @@ function useInspector(options) {
316
333
  if (tooltipLeft + tooltipWidth > window.innerWidth - 10) {
317
334
  tooltipLeft = window.innerWidth - tooltipWidth - 10;
318
335
  }
319
- tooltipStyle.value = {
320
- top: `${tooltipTop}px`,
321
- left: `${tooltipLeft}px`
322
- };
336
+ const newTooltipTop = `${tooltipTop}px`;
337
+ const newTooltipLeft = `${tooltipLeft}px`;
338
+ if (tooltipStyle.value.top !== newTooltipTop || tooltipStyle.value.left !== newTooltipLeft) {
339
+ tooltipStyle.value = {
340
+ top: newTooltipTop,
341
+ left: newTooltipLeft
342
+ };
343
+ }
344
+ if (!highlightVisible.value) {
345
+ highlightVisible.value = true;
346
+ }
347
+ if (!tooltipVisible.value) {
348
+ tooltipVisible.value = true;
349
+ }
323
350
  } else {
324
- highlightVisible.value = false;
325
- tooltipVisible.value = false;
351
+ currentHighlightElement = null;
352
+ currentDescription = "";
353
+ currentFileInfoText = "";
354
+ currentFileInfo = { file: null, line: null, column: null };
355
+ if (highlightVisible.value) {
356
+ highlightVisible.value = false;
357
+ }
358
+ if (tooltipVisible.value) {
359
+ tooltipVisible.value = false;
360
+ }
326
361
  }
327
362
  }
328
363
  const handleMouseMove = throttle(handleMouseMoveCore, 16);
@@ -394,6 +429,10 @@ function useInspector(options) {
394
429
  }
395
430
  document.removeEventListener("mousemove", handleMouseMove);
396
431
  document.removeEventListener("keydown", handleKeydown, true);
432
+ currentHighlightElement = null;
433
+ currentDescription = "";
434
+ currentFileInfoText = "";
435
+ currentFileInfo = { file: null, line: null, column: null };
397
436
  highlightVisible.value = false;
398
437
  tooltipVisible.value = false;
399
438
  }
@@ -0,0 +1,24 @@
1
+ import { type Ref } from "vue";
2
+ import type { FloatingBubbleOffset } from "../src/components/FloatingBubble/types";
3
+ import type { OpenCodeWidgetTheme } from "../src/types";
4
+ export interface WidgetPersistState {
5
+ open: boolean;
6
+ minimized: boolean;
7
+ promptDockVisible: boolean;
8
+ bubbleOffset?: FloatingBubbleOffset;
9
+ theme: OpenCodeWidgetTheme;
10
+ sessionListCollapsed: boolean;
11
+ }
12
+ export interface UsePersistStateOptions {
13
+ open: Ref<boolean>;
14
+ minimized: Ref<boolean>;
15
+ promptDockVisible: Ref<boolean>;
16
+ bubbleOffset: Ref<FloatingBubbleOffset | undefined>;
17
+ theme: Ref<OpenCodeWidgetTheme>;
18
+ sessionListCollapsed: Ref<boolean>;
19
+ onRestore?: (state: Partial<WidgetPersistState>) => void;
20
+ }
21
+ export declare function usePersistState(options: UsePersistStateOptions): {
22
+ restoreState: () => Partial<WidgetPersistState> | null;
23
+ persistState: () => void;
24
+ };
@@ -0,0 +1,59 @@
1
+ import { watch, onMounted } from "vue";
2
+ const STORAGE_KEY = "opencode-widget-state";
3
+ function loadState() {
4
+ if (typeof window === "undefined") return null;
5
+ try {
6
+ const stored = localStorage.getItem(STORAGE_KEY);
7
+ if (stored) {
8
+ return JSON.parse(stored);
9
+ }
10
+ } catch (e) {
11
+ console.warn("[OpenCodeWidget] Failed to load persisted state:", e);
12
+ }
13
+ return null;
14
+ }
15
+ function saveState(state) {
16
+ if (typeof window === "undefined") return;
17
+ try {
18
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
19
+ } catch (e) {
20
+ console.warn("[OpenCodeWidget] Failed to save state:", e);
21
+ }
22
+ }
23
+ function usePersistState(options) {
24
+ const restoreState = () => {
25
+ const saved = loadState();
26
+ if (options.onRestore) {
27
+ options.onRestore(saved || {});
28
+ }
29
+ return saved;
30
+ };
31
+ const getCurrentState = () => ({
32
+ open: options.open.value,
33
+ minimized: options.minimized.value,
34
+ promptDockVisible: options.promptDockVisible.value,
35
+ bubbleOffset: options.bubbleOffset.value,
36
+ theme: options.theme.value,
37
+ sessionListCollapsed: options.sessionListCollapsed.value
38
+ });
39
+ const persistState = () => {
40
+ saveState(getCurrentState());
41
+ };
42
+ onMounted(() => {
43
+ restoreState();
44
+ watch(
45
+ [options.open, options.minimized, options.promptDockVisible, options.bubbleOffset, options.theme, options.sessionListCollapsed],
46
+ () => {
47
+ persistState();
48
+ },
49
+ { deep: true }
50
+ );
51
+ });
52
+ return {
53
+ restoreState,
54
+ persistState
55
+ };
56
+ }
57
+ export {
58
+ usePersistState
59
+ };
@@ -1 +1 @@
1
- .floating-bubble{position:fixed;top:0;left:0;z-index:999999;cursor:grab;-webkit-user-select:none;-moz-user-select:none;user-select:none;touch-action:none;will-change:transform}.floating-bubble:active{cursor:grabbing}
1
+ .floating-bubble{position:fixed;top:0;left:0;z-index:999999;cursor:grab;-webkit-user-select:none;-moz-user-select:none;user-select:none;touch-action:none;will-change:transform}.floating-bubble:active{cursor:grabbing}body.floating-bubble-dragging *{pointer-events:none!important}body.floating-bubble-dragging .floating-bubble,body.floating-bubble-dragging .floating-bubble *{pointer-events:auto!important}
@@ -16,14 +16,14 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {
16
16
  y: number;
17
17
  }>;
18
18
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
19
- click: (event: MouseEvent) => any;
20
19
  "update:offset": (value: FloatingBubbleOffset) => any;
20
+ click: (event: MouseEvent) => any;
21
21
  "offset-change": (offset: FloatingBubbleOffset) => any;
22
22
  "drag-start": () => any;
23
23
  "drag-end": () => any;
24
24
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
25
- onClick?: ((event: MouseEvent) => any) | undefined;
26
25
  "onUpdate:offset"?: ((value: FloatingBubbleOffset) => any) | undefined;
26
+ onClick?: ((event: MouseEvent) => any) | undefined;
27
27
  "onOffset-change"?: ((offset: FloatingBubbleOffset) => any) | undefined;
28
28
  "onDrag-start"?: (() => any) | undefined;
29
29
  "onDrag-end"?: (() => any) | undefined;
@@ -57,6 +57,27 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
57
57
  bottom: windowHeight.value - state.value.height - gapY.value,
58
58
  left: gapX.value
59
59
  }));
60
+ const closest = (arr, target) => {
61
+ return arr.reduce(
62
+ (pre, cur) => Math.abs(pre - target) < Math.abs(cur - target) ? pre : cur
63
+ );
64
+ };
65
+ const applyMagnetic = () => {
66
+ if (props.magnetic === "x") {
67
+ const nextX = closest(
68
+ [boundary.value.left, boundary.value.right],
69
+ state.value.x
70
+ );
71
+ state.value.x = nextX;
72
+ }
73
+ if (props.magnetic === "y") {
74
+ const nextY = closest(
75
+ [boundary.value.top, boundary.value.bottom],
76
+ state.value.y
77
+ );
78
+ state.value.y = nextY;
79
+ }
80
+ };
60
81
  const dragging = ref(false);
61
82
  const initialized = ref(false);
62
83
  const rootStyle = computed(() => {
@@ -83,12 +104,22 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
83
104
  if (x > maxX) x = maxX;
84
105
  if (y < gapY.value) y = gapY.value;
85
106
  if (y > maxY) y = maxY;
107
+ const oldX = state.value.x;
108
+ const oldY = state.value.y;
86
109
  state.value = {
87
110
  x,
88
111
  y,
89
112
  width: rect.width,
90
113
  height: rect.height
91
114
  };
115
+ if (!dragging.value) {
116
+ applyMagnetic();
117
+ if (state.value.x !== oldX || state.value.y !== oldY) {
118
+ const offset2 = { x: state.value.x, y: state.value.y };
119
+ emit("update:offset", offset2);
120
+ emit("offset-change", offset2);
121
+ }
122
+ }
92
123
  };
93
124
  const touch = {
94
125
  startX: ref(0),
@@ -127,6 +158,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
127
158
  dragging.value = true;
128
159
  prevX = state.value.x;
129
160
  prevY = state.value.y;
161
+ document.body.classList.add("floating-bubble-dragging");
130
162
  if (!("touches" in e)) {
131
163
  window.addEventListener("mousemove", onTouchMove, { passive: false });
132
164
  window.addEventListener("mouseup", onTouchEnd);
@@ -159,32 +191,15 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
159
191
  emit("update:offset", offset);
160
192
  }
161
193
  };
162
- const closest = (arr, target) => {
163
- return arr.reduce(
164
- (pre, cur) => Math.abs(pre - target) < Math.abs(cur - target) ? pre : cur
165
- );
166
- };
167
194
  const onTouchEnd = (e) => {
168
195
  dragging.value = false;
196
+ document.body.classList.remove("floating-bubble-dragging");
169
197
  if (e && !("touches" in e) && e.type === "mouseup") {
170
198
  window.removeEventListener("mousemove", onTouchMove);
171
199
  window.removeEventListener("mouseup", onTouchEnd);
172
200
  }
173
201
  requestAnimationFrame(() => {
174
- if (props.magnetic === "x") {
175
- const nextX = closest(
176
- [boundary.value.left, boundary.value.right],
177
- state.value.x
178
- );
179
- state.value.x = nextX;
180
- }
181
- if (props.magnetic === "y") {
182
- const nextY = closest(
183
- [boundary.value.top, boundary.value.bottom],
184
- state.value.y
185
- );
186
- state.value.y = nextY;
187
- }
202
+ applyMagnetic();
188
203
  if (!touch.isTap.value) {
189
204
  emit("drag-end");
190
205
  const offset = { x: state.value.x, y: state.value.y };
@@ -223,6 +238,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
223
238
  }
224
239
  });
225
240
  onUnmounted(() => {
241
+ document.body.classList.remove("floating-bubble-dragging");
226
242
  if (typeof window !== "undefined") {
227
243
  window.removeEventListener("resize", handleResize);
228
244
  window.removeEventListener("mousemove", onTouchMove);
@@ -240,7 +256,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
240
256
  __expose({
241
257
  offset: computed(() => ({ x: state.value.x, y: state.value.y }))
242
258
  });
243
- const __returned__ = { props, emit, rootRef, state, isObject, gapX, gapY, windowWidth, windowHeight, boundary, dragging, initialized, rootStyle, updateState, touch, get prevX() {
259
+ const __returned__ = { props, emit, rootRef, state, isObject, gapX, gapY, windowWidth, windowHeight, boundary, closest, applyMagnetic, dragging, initialized, rootStyle, updateState, touch, get prevX() {
244
260
  return prevX;
245
261
  }, set prevX(v) {
246
262
  prevX = v;
@@ -248,7 +264,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
248
264
  return prevY;
249
265
  }, set prevY(v) {
250
266
  prevY = v;
251
- }, onTouchStart, onTouchMove, closest, onTouchEnd, onClick, handleResize };
267
+ }, onTouchStart, onTouchMove, onTouchEnd, onClick, handleResize };
252
268
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
253
269
  return __returned__;
254
270
  }
@@ -1 +1 @@
1
- .opencode-session-list{width:240px;background:var(--oc-bg-secondary);border-right:1px solid var(--oc-border-primary);display:flex;flex-direction:column;flex-shrink:0;transition:width .2s ease}.opencode-session-list.collapsed{width:0;overflow:hidden}.opencode-session-list.collapsed .opencode-session-list-header,.opencode-session-list.collapsed .opencode-session-list-content{display:none}.opencode-session-list-header{padding:16px;border-bottom:1px solid var(--oc-border-primary);display:flex;justify-content:space-between;align-items:center;font-weight:600;font-size:14px;color:var(--oc-text-primary)}.opencode-new-session-btn{width:28px;height:28px;border-radius:6px;border:none;background:var(--oc-primary);color:#fff;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s}.opencode-new-session-btn:hover{background:var(--oc-primary-hover);transform:scale(1.05)}.opencode-session-list-content{flex:1;overflow-y:auto;padding:8px;position:relative}.opencode-session-list-loading-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background:var(--oc-overlay-bg);display:flex;align-items:center;justify-content:center;z-index:10;border-radius:8px}.opencode-loading-spinner.small{width:24px;height:24px;border-width:2px}.opencode-session-item{padding:12px;border-radius:8px;cursor:pointer;transition:transform .2s;margin-bottom:4px;color:var(--oc-text-primary)}.opencode-session-item:hover{background:var(--oc-bg-tertiary)}.opencode-session-item.active{background:var(--oc-primary);color:#fff;transition:none}.opencode-session-title{font-size:14px;font-weight:500;margin-bottom:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.opencode-session-meta{font-size:12px;opacity:.6}.opencode-session-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px}.opencode-session-delete-btn{width:20px;height:20px;border-radius:4px;border:none;background:transparent;color:var(--oc-text-placeholder);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;opacity:0;flex-shrink:0}.opencode-session-item:hover .opencode-session-delete-btn{opacity:1}.opencode-session-delete-btn:hover{background:var(--oc-danger);color:#fff}.opencode-session-item.active .opencode-session-delete-btn{color:rgba(255,255,255,.7)}.opencode-session-item.active .opencode-session-delete-btn:hover{background:rgba(255,255,255,.2);color:#fff}.opencode-session-header-skeleton{padding:16px;border-bottom:1px solid var(--oc-border-primary);display:none;justify-content:space-between;align-items:center}.opencode-session-header-skeleton.visible{display:flex}.opencode-skeleton-header-title{height:18px;width:80px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px}.opencode-skeleton-header-btn{width:28px;height:28px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:6px}.opencode-session-skeleton{flex:1;overflow-y:auto;padding:8px;display:none}.opencode-session-skeleton.visible{display:block}.opencode-skeleton-item{padding:12px;border-radius:8px;margin-bottom:4px;background:var(--oc-skeleton-bg)}.opencode-skeleton-title{height:16px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px;margin-bottom:8px;width:70%}.opencode-skeleton-meta{height:12px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px;width:50%}.opencode-session-empty{padding:32px 16px;text-align:center;color:var(--oc-text-placeholder);font-size:13px}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}
1
+ .opencode-session-list{width:240px;background:var(--oc-bg-secondary);border-right:1px solid var(--oc-border-primary);display:flex;flex-direction:column;flex-shrink:0;transition:width .2s ease}.opencode-session-list.collapsed{width:0;overflow:hidden}.opencode-session-list.collapsed .opencode-session-list-header,.opencode-session-list.collapsed .opencode-session-list-content{display:none}.opencode-session-list-header{padding:16px;border-bottom:1px solid var(--oc-border-primary);display:flex;justify-content:space-between;align-items:center;font-weight:600;font-size:14px;color:var(--oc-text-primary)}.opencode-new-session-btn{width:28px;height:28px;border-radius:6px;border:none;background:var(--oc-primary);color:#fff;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s}.opencode-new-session-btn:hover{background:var(--oc-primary-hover);transform:scale(1.05)}.opencode-session-list-content{flex:1;overflow-y:auto;padding:8px;position:relative}.opencode-session-list-loading-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background:var(--oc-overlay-bg);display:flex;align-items:center;justify-content:center;z-index:10;border-radius:8px}.opencode-loading-spinner.small{width:24px;height:24px;border-width:2px}.opencode-session-item{padding:12px;border-radius:8px;cursor:pointer;transition:transform .2s;margin-bottom:4px;color:var(--oc-text-primary)}.opencode-session-item:hover{background:var(--oc-bg-tertiary)}.opencode-session-item.active{background:var(--oc-primary);color:#fff;transition:none}.opencode-session-title{font-size:14px;font-weight:500;margin-bottom:4px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.opencode-session-meta{font-size:12px;opacity:.6}.opencode-session-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:4px}.opencode-session-delete-btn{width:20px;height:20px;border-radius:4px;border:none;background:transparent;color:var(--oc-text-placeholder);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s;opacity:0;flex-shrink:0}.opencode-session-item:hover .opencode-session-delete-btn{opacity:1}.opencode-session-delete-btn:hover{background:var(--oc-danger);color:#fff}.opencode-session-item.active .opencode-session-delete-btn{color:rgba(255,255,255,.7)}.opencode-session-item.active .opencode-session-delete-btn:hover{background:rgba(255,255,255,.2);color:#fff}.opencode-session-header-skeleton{padding:16px;border-bottom:1px solid var(--oc-border-primary);display:none;justify-content:space-between;align-items:center}.opencode-session-header-skeleton.visible{display:flex}.opencode-skeleton-header-title{height:18px;width:80px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px}.opencode-skeleton-header-btn{width:28px;height:28px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:6px}.opencode-session-skeleton{flex:1;overflow-y:auto;padding:8px;display:none}.opencode-session-skeleton.visible{display:block}.opencode-skeleton-item{padding:12px;border-radius:8px;margin-bottom:4px;background:var(--oc-skeleton-bg)}.opencode-skeleton-title{height:16px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px;margin-bottom:8px;width:70%}.opencode-skeleton-meta{height:12px;background:var(--oc-skeleton-gradient);background-size:200% 100%;animation:skeleton-loading 1.5s ease-in-out infinite;border-radius:4px;width:50%}.opencode-session-empty{padding:32px 16px;text-align:center;color:var(--oc-text-placeholder);font-size:13px}.opencode-thinking-loading{display:inline-block;width:12px;height:12px;margin-right:6px;border:2px solid var(--oc-border-secondary);border-top-color:var(--oc-text-secondary);border-radius:50%;animation:thinking-spin .8s linear infinite;vertical-align:middle}.opencode-session-item.active .opencode-thinking-loading{border-color:rgba(255,255,255,.3);border-top-color:rgba(255,255,255,.9)}@keyframes thinking-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes skeleton-loading{0%{background-position:200% 0}to{background-position:-200% 0}}
@@ -14,7 +14,8 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
14
14
  handleCreateSession,
15
15
  handleSelectSession,
16
16
  handleDeleteSession,
17
- sessionKey
17
+ sessionKey,
18
+ sessionStates
18
19
  } = useOpenCodeWidgetContext();
19
20
  const isAnimating = ref(false);
20
21
  let animTimer = null;
@@ -30,16 +31,21 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
30
31
  if (showSessionListSkeleton.value) return true;
31
32
  return false;
32
33
  });
33
- const __returned__ = { collapsed, sessions, loadingSessionList, showSessionListSkeleton, handleCreateSession, handleSelectSession, handleDeleteSession, sessionKey, isAnimating, get animTimer() {
34
+ function isSessionThinking(sessionId) {
35
+ var _a, _b;
36
+ if (!(sessionStates == null ? void 0 : sessionStates.value) || !sessionId) return false;
37
+ return (_b = (_a = sessionStates.value[sessionId]) == null ? void 0 : _a.thinking) != null ? _b : false;
38
+ }
39
+ const __returned__ = { collapsed, sessions, loadingSessionList, showSessionListSkeleton, handleCreateSession, handleSelectSession, handleDeleteSession, sessionKey, sessionStates, isAnimating, get animTimer() {
34
40
  return animTimer;
35
41
  }, set animTimer(v) {
36
42
  animTimer = v;
37
- }, showSkeleton };
43
+ }, showSkeleton, isSessionThinking };
38
44
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
39
45
  return __returned__;
40
46
  }
41
47
  });
42
- import { createCommentVNode as _createCommentVNode, createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, Fragment as _Fragment, renderList as _renderList, toDisplayString as _toDisplayString, withModifiers as _withModifiers, normalizeClass as _normalizeClass, renderSlot as _renderSlot } from "vue";
48
+ import { createCommentVNode as _createCommentVNode, createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, Fragment as _Fragment, renderList as _renderList, toDisplayString as _toDisplayString, createTextVNode as _createTextVNode, withModifiers as _withModifiers, normalizeClass as _normalizeClass, renderSlot as _renderSlot } from "vue";
43
49
  const _hoisted_1 = {
44
50
  key: 0,
45
51
  class: "opencode-session-list-header"
@@ -60,8 +66,12 @@ const _hoisted_4 = {
60
66
  const _hoisted_5 = ["aria-selected", "onClick"];
61
67
  const _hoisted_6 = { class: "opencode-session-header" };
62
68
  const _hoisted_7 = { class: "opencode-session-title" };
63
- const _hoisted_8 = ["aria-label", "onClick"];
64
- const _hoisted_9 = { class: "opencode-session-meta" };
69
+ const _hoisted_8 = {
70
+ key: 0,
71
+ class: "opencode-thinking-loading"
72
+ };
73
+ const _hoisted_9 = ["aria-label", "onClick"];
74
+ const _hoisted_10 = { class: "opencode-session-meta" };
65
75
  function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
66
76
  return _openBlock(), _createElementBlock(
67
77
  "div",
@@ -154,29 +164,30 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
154
164
  _renderList($setup.sessions, (item) => {
155
165
  return _openBlock(), _createElementBlock("div", {
156
166
  key: item[$setup.sessionKey],
157
- class: _normalizeClass(["opencode-session-item", { active: item.active }]),
167
+ class: _normalizeClass(["opencode-session-item", { active: item.active, thinking: $setup.isSessionThinking(item.id) }]),
158
168
  role: "option",
159
169
  "aria-selected": item.active,
160
170
  onClick: ($event) => $setup.handleSelectSession(item)
161
171
  }, [
162
172
  _createElementVNode("div", _hoisted_6, [
163
- _createElementVNode(
164
- "div",
165
- _hoisted_7,
166
- _toDisplayString(item.title),
167
- 1
168
- /* TEXT */
169
- ),
173
+ _createElementVNode("div", _hoisted_7, [
174
+ $setup.isSessionThinking(item.id) ? (_openBlock(), _createElementBlock("span", _hoisted_8)) : _createCommentVNode("v-if", true),
175
+ _createTextVNode(
176
+ " " + _toDisplayString(item.title),
177
+ 1
178
+ /* TEXT */
179
+ )
180
+ ]),
170
181
  _createElementVNode("button", {
171
182
  class: "opencode-session-delete-btn",
172
183
  type: "button",
173
184
  "aria-label": `\u5220\u9664\u4F1A\u8BDD: ${item.title}`,
174
185
  onClick: _withModifiers(($event) => $setup.handleDeleteSession(item), ["stop"])
175
- }, " \xD7 ", 8, _hoisted_8)
186
+ }, " \xD7 ", 8, _hoisted_9)
176
187
  ]),
177
188
  _createElementVNode(
178
189
  "div",
179
- _hoisted_9,
190
+ _hoisted_10,
180
191
  _toDisplayString(item.meta),
181
192
  1
182
193
  /* TEXT */
@@ -1 +1 @@
1
- .opencode-button{width:42px;height:42px;border-radius:50%;background:#fff;border:none;cursor:pointer;box-shadow:0 4px 12px rgba(102,126,234,.4);transition:all .3s ease;display:flex;align-items:center;justify-content:center;padding:0;position:relative}.opencode-button svg{transform:rotate(180deg) scale(1.1);transition:transform .3s ease;width:100%;height:100%;display:block}.opencode-button:hover svg{transform:rotate(180deg) scale(1.1)}.opencode-button:hover{transform:scale(1.1);box-shadow:0 6px 16px rgba(102,126,234,.5)}.opencode-button.thinking{background:linear-gradient(135deg,#667eea,#764ba2);animation:thinking-glow 1.5s ease-in-out infinite,thinking-pulse 1.5s ease-in-out infinite;box-shadow:0 0 20px rgba(102,126,234,.6),0 0 40px rgba(118,75,162,.4),0 0 60px rgba(102,126,234,.2)}.opencode-button.thinking svg path{fill:#fff}.opencode-button.thinking:before{content:"";position:absolute;top:-2px;right:-2px;bottom:-2px;left:-2px;border-radius:50%;background:linear-gradient(135deg,#8b9cf5,#9d6bc7);z-index:-1}.opencode-button.thinking:after{content:"";position:absolute;top:-3px;right:-3px;bottom:-3px;left:-3px;border-radius:50%;background:conic-gradient(from 180deg,transparent,rgba(102,126,234,.3),transparent,rgba(118,75,162,.3),transparent);z-index:-2;animation:thinking-rotate 2s linear infinite reverse;filter:blur(8px)}@keyframes thinking-glow{0%,to{box-shadow:0 0 20px rgba(102,126,234,.6),0 0 40px rgba(118,75,162,.4),0 0 60px rgba(102,126,234,.2)}50%{box-shadow:0 0 30px rgba(102,126,234,.8),0 0 60px rgba(118,75,162,.6),0 0 90px rgba(102,126,234,.3)}}@keyframes thinking-rotate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes thinking-pulse{0%,to{transform:scale(1)}50%{transform:scale(.95)}}.opencode-button.opencode-theme-dark{background:linear-gradient(135deg,#667eea,#764ba2);box-shadow:0 4px 12px rgba(102,126,234,.3)}.opencode-button.opencode-theme-dark:before{content:"";position:absolute;top:-2px;right:-2px;bottom:-2px;left:-2px;border-radius:50%;background:linear-gradient(135deg,#8b9cf5,#9d6bc7);z-index:-1}.opencode-button.opencode-theme-dark:hover{box-shadow:0 6px 16px rgba(102,126,234,.4)}.opencode-button.opencode-theme-dark svg path{fill:#fff}
1
+ .opencode-button{width:42px;height:42px;border-radius:50%;background:#fff;border:none;cursor:pointer;box-shadow:0 4px 12px rgba(102,126,234,.4);transition:all .3s ease;display:flex;align-items:center;justify-content:center;padding:0;position:relative}.opencode-button svg{transform:rotate(180deg) scale(1.1);transition:transform .3s ease;width:100%;height:100%;display:block}.opencode-button:hover svg{transform:rotate(180deg) scale(1.1)}.opencode-button:hover{transform:scale(1.1);box-shadow:0 6px 16px rgba(102,126,234,.5)}.opencode-button.thinking{background:linear-gradient(135deg,#667eea,#764ba2);animation:thinking-glow 1.5s ease-in-out infinite,thinking-pulse 1.5s ease-in-out infinite;box-shadow:0 0 20px rgba(102,126,234,.6),0 0 40px rgba(118,75,162,.4),0 0 60px rgba(102,126,234,.2)}.opencode-button.thinking svg path{fill:#fff}.opencode-button.thinking:before{content:"";position:absolute;top:-2px;right:-2px;bottom:-2px;left:-2px;border-radius:50%;background:linear-gradient(135deg,#8b9cf5,#9d6bc7);z-index:-1}.opencode-button.thinking:after{content:"";position:absolute;top:-3px;right:-3px;bottom:-3px;left:-3px;border-radius:50%;background:conic-gradient(from 180deg,transparent,rgba(102,126,234,.3),transparent,rgba(118,75,162,.3),transparent);z-index:-2;animation:thinking-rotate 2s linear infinite reverse;filter:blur(8px)}@keyframes thinking-glow{0%,to{box-shadow:0 0 20px rgba(102,126,234,.6),0 0 40px rgba(118,75,162,.4),0 0 60px rgba(102,126,234,.2)}50%{box-shadow:0 0 30px rgba(102,126,234,.8),0 0 60px rgba(118,75,162,.6),0 0 90px rgba(102,126,234,.3)}}@keyframes thinking-rotate{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes thinking-pulse{0%,to{transform:scale(1)}50%{transform:scale(.85)}}.opencode-button.opencode-theme-dark{background:linear-gradient(135deg,#667eea,#764ba2);box-shadow:0 4px 12px rgba(102,126,234,.3)}.opencode-button.opencode-theme-dark:before{content:"";position:absolute;top:-2px;right:-2px;bottom:-2px;left:-2px;border-radius:50%;background:linear-gradient(135deg,#8b9cf5,#9d6bc7);z-index:-1}.opencode-button.opencode-theme-dark:hover{box-shadow:0 6px 16px rgba(102,126,234,.4)}.opencode-button.opencode-theme-dark svg path{fill:#fff}
@@ -12,11 +12,9 @@ declare const __VLS_component: import("vue").DefineComponent<{}, {
12
12
  y: number;
13
13
  } | undefined>;
14
14
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
15
- "offset-change": (offset: FloatingBubbleOffset | undefined) => any;
16
15
  "drag-start": () => any;
17
16
  "drag-end": () => any;
18
17
  }, string, import("vue").PublicProps, Readonly<{}> & Readonly<{
19
- "onOffset-change"?: ((offset: FloatingBubbleOffset | undefined) => any) | undefined;
20
18
  "onDrag-start"?: (() => any) | undefined;
21
19
  "onDrag-end"?: (() => any) | undefined;
22
20
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;