@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
@@ -3,10 +3,9 @@ import { defineComponent as _defineComponent } from "vue";
3
3
  import { ref, watch } from "vue";
4
4
  import { useOpenCodeWidgetContext } from "../context";
5
5
  import FloatingBubble from "./FloatingBubble/FloatingBubble.vue.js";
6
- const STORAGE_KEY = "opencode-bubble-offset";
7
6
  const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
8
7
  __name: "Trigger",
9
- emits: ["offset-change", "drag-start", "drag-end"],
8
+ emits: ["drag-start", "drag-end"],
10
9
  setup(__props, { expose: __expose, emit: __emit }) {
11
10
  const {
12
11
  buttonActive: active,
@@ -14,39 +13,23 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
14
13
  hotkeyLabel,
15
14
  thinking,
16
15
  resolvedTheme,
17
- handleToggle
16
+ handleToggle,
17
+ bubbleOffset,
18
+ handleBubbleOffsetChange
18
19
  } = useOpenCodeWidgetContext();
19
- const loadOffset = () => {
20
- try {
21
- const saved = localStorage.getItem(STORAGE_KEY);
22
- if (saved) {
23
- const parsed = JSON.parse(saved);
24
- if (parsed && (parsed.x !== 0 || parsed.y !== 0)) {
25
- return parsed;
26
- }
27
- }
28
- } catch (e) {
29
- }
30
- return void 0;
31
- };
32
- const offset = ref(loadOffset());
20
+ const offset = ref(bubbleOffset.value);
33
21
  const emit = __emit;
34
- const saveOffset = (value) => {
35
- try {
36
- localStorage.setItem(STORAGE_KEY, JSON.stringify(value));
37
- } catch (e) {
38
- }
39
- };
40
22
  const handleOffsetChange = (value) => {
41
23
  offset.value = value;
42
- saveOffset(value);
43
- emit("offset-change", value);
24
+ handleBubbleOffsetChange(value);
44
25
  };
45
- watch(offset, handleOffsetChange, { immediate: true });
26
+ watch(bubbleOffset, (newOffset) => {
27
+ offset.value = newOffset;
28
+ });
46
29
  __expose({
47
30
  offset
48
31
  });
49
- const __returned__ = { active, open, hotkeyLabel, thinking, resolvedTheme, handleToggle, STORAGE_KEY, loadOffset, offset, emit, saveOffset, handleOffsetChange, FloatingBubble };
32
+ const __returned__ = { active, open, hotkeyLabel, thinking, resolvedTheme, handleToggle, bubbleOffset, handleBubbleOffsetChange, offset, emit, handleOffsetChange, FloatingBubble };
50
33
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
51
34
  return __returned__;
52
35
  }
@@ -1,5 +1,6 @@
1
1
  import { type Ref } from "vue";
2
- import type { OpenCodeWidgetSessionItem, OpenCodeSelectedElementItem, OpenCodeRemoveSelectedPayload } from "./types";
2
+ import type { OpenCodeWidgetSessionItem, OpenCodeSelectedElementItem, OpenCodeRemoveSelectedPayload, OpencodeSessionThinkingState } from "./types";
3
+ import type { FloatingBubbleOffset } from "./components/FloatingBubble/types";
3
4
  export interface OpenCodeWidgetContext {
4
5
  theme: Ref<string>;
5
6
  resolvedTheme: Ref<"light" | "dark">;
@@ -22,6 +23,8 @@ export interface OpenCodeWidgetContext {
22
23
  thinking: Ref<boolean>;
23
24
  minimized: Ref<boolean>;
24
25
  promptDockVisible: Ref<boolean>;
26
+ bubbleOffset: Ref<FloatingBubbleOffset | undefined>;
27
+ sessionStates: Ref<Record<string, OpencodeSessionThinkingState>>;
25
28
  iframeSource: Ref<string>;
26
29
  buttonActive: Ref<boolean>;
27
30
  sessionListTitle: Ref<string>;
@@ -48,6 +51,7 @@ export interface OpenCodeWidgetContext {
48
51
  }) => void;
49
52
  handleClearSelectedNodes: () => void;
50
53
  handleFrameLoaded: () => void;
54
+ handleBubbleOffsetChange: (offset: FloatingBubbleOffset | undefined) => void;
51
55
  }
52
56
  export declare function provideOpenCodeWidgetContext(context: OpenCodeWidgetContext): void;
53
57
  export declare function useOpenCodeWidgetContext(): OpenCodeWidgetContext;
@@ -1 +1 @@
1
- .opencode-widget{--oc-bg-main: #ffffff;--oc-bg-secondary: #f8f9fa;--oc-bg-tertiary: #f3f4f6;--oc-overlay-bg: rgba(255, 255, 255, .9);--oc-bg-inverse: #1e1e1e;--oc-text-primary: #282828;--oc-text-secondary: #4b5563;--oc-text-tertiary: #6b7280;--oc-text-placeholder: #9ca3af;--oc-text-inverse: #ffffff;--oc-border-primary: #e5e7eb;--oc-border-secondary: #d1d5db;--oc-primary: #3b82f6;--oc-primary-hover: #2563eb;--oc-primary-bg: rgba(59, 130, 246, .1);--oc-danger: #ef4444;--oc-danger-hover: #dc2626;--oc-danger-active: #b91c1c;--oc-success: #10b981;--oc-overlay: rgba(0, 0, 0, .5);--oc-tooltip-bg: #1e1e1e;--oc-dialog-overlay: rgba(0, 0, 0, .5);--oc-thinking-gradient-1: #10b981;--oc-thinking-gradient-2: #059669;--oc-thinking-glow: rgba(16, 185, 129, .3);--oc-thinking-glow-strong: rgba(16, 185, 129, .6);--oc-skeleton-bg: #e5e7eb;--oc-skeleton-gradient: linear-gradient(90deg, #e5e7eb 25%, #f3f4f6 50%, #e5e7eb 75%);--oc-shadow-sm: 0 2px 4px rgba(0, 0, 0, .1);--oc-shadow-md: 0 4px 12px rgba(0, 0, 0, .15);--oc-shadow-lg: 0 8px 32px rgba(0, 0, 0, .12);--oc-shadow-xl: 0 20px 60px rgba(0, 0, 0, .3);--oc-shadow-primary: 0 2px 4px rgba(59, 130, 246, .2);--oc-shadow-primary-hover: 0 4px 6px rgba(59, 130, 246, .3);--oc-shadow-danger: 0 4px 12px rgba(239, 68, 68, .3);--oc-trigger-bg: #3b82f6;--oc-trigger-bg-hover: #2563eb;--oc-trigger-bg-active: #1d4ed8;--oc-trigger-shadow: 0 2px 8px rgba(59, 130, 246, .3);--oc-trigger-shadow-hover: 0 4px 12px rgba(59, 130, 246, .4);--oc-trigger-shadow-active: 0 4px 12px rgba(59, 130, 246, .5);position:fixed;z-index:999999;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.opencode-widget.opencode-theme-dark{--oc-bg-main: #1a1a1a;--oc-bg-secondary: #1e1e1e;--oc-bg-tertiary: #282828;--oc-overlay-bg: rgba(26, 26, 26, .9);--oc-bg-inverse: #ffffff;--oc-text-primary: #f3f4f6;--oc-text-secondary: #d1d5db;--oc-text-tertiary: #9ca3af;--oc-text-placeholder: #6b7280;--oc-text-inverse: #282828;--oc-border-primary: #282828;--oc-border-secondary: #4b5563;--oc-primary: #3b82f6;--oc-primary-hover: #2563eb;--oc-primary-bg: rgba(59, 130, 246, .15);--oc-danger: #ef4444;--oc-danger-hover: #dc2626;--oc-danger-active: #b91c1c;--oc-success: #10b981;--oc-overlay: rgba(26, 26, 26, .9);--oc-tooltip-bg: #282828;--oc-dialog-overlay: rgba(0, 0, 0, .7);--oc-thinking-gradient-1: #34d399;--oc-thinking-gradient-2: #10b981;--oc-thinking-glow: rgba(52, 211, 153, .3);--oc-thinking-glow-strong: rgba(52, 211, 153, .6);--oc-skeleton-bg: #151515;--oc-skeleton-gradient: linear-gradient(90deg, #282828 25%, #4b5563 50%, #282828 75%);--oc-shadow-sm: 0 2px 4px rgba(0, 0, 0, .3);--oc-shadow-md: 0 4px 12px rgba(0, 0, 0, .4);--oc-shadow-lg: 0 8px 32px rgba(0, 0, 0, .4);--oc-shadow-xl: 0 20px 60px rgba(0, 0, 0, .6);--oc-shadow-primary: 0 2px 4px rgba(59, 130, 246, .3);--oc-shadow-primary-hover: 0 4px 6px rgba(59, 130, 246, .4);--oc-shadow-danger: 0 4px 12px rgba(239, 68, 68, .4);--oc-trigger-bg: #60a5fa;--oc-trigger-bg-hover: #3b82f6;--oc-trigger-bg-active: #2563eb;--oc-trigger-shadow: 0 2px 8px rgba(96, 165, 250, .4);--oc-trigger-shadow-hover: 0 4px 12px rgba(96, 165, 250, .5);--oc-trigger-shadow-active: 0 4px 12px rgba(96, 165, 250, .6)}.opencode-chat{position:fixed;bottom:20px;width:700px;height:86vh;max-height:calc(100vh - 40px);background:var(--oc-bg-main);border-radius:16px;box-shadow:var(--oc-shadow-lg);overflow:hidden;opacity:0;visibility:hidden;transform:translate3d(var(---chatAnimationOrigin\.x),var(---chatAnimationOrigin\.y),0) scale(.95);transition:all .3s ease;display:flex;flex-direction:column;z-index:99999}.opencode-chat.minimized{width:300px;height:300px}.opencode-chat.minimized .opencode-iframe-container{margin-top:-146px}.opencode-chat-content{display:flex;flex:1;overflow:hidden}.opencode-chat.open{opacity:1;visibility:visible;transform:translateZ(0) scale(1)}.opencode-notification{position:absolute;top:20px;left:50%;transform:translate(-50%);padding:12px 24px;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border-radius:10px;font-size:14px;font-weight:500;box-shadow:0 4px 16px rgba(59,130,246,.4),0 0 0 2px rgba(59,130,246,.2);animation:slideDown .3s ease;z-index:10000000;display:flex;align-items:center;gap:10px}.opencode-notification:before{content:"\1f4a1";font-size:16px}.opencode-dialog-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:var(--oc-dialog-overlay);display:flex;align-items:center;justify-content:center;z-index:9999999;animation:fadeIn .2s ease}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.opencode-dialog{background:var(--oc-bg-main);border-radius:12px;padding:24px;min-width:320px;max-width:400px;box-shadow:var(--oc-shadow-xl);animation:scaleIn .2s ease}@keyframes scaleIn{0%{transform:scale(.9);opacity:0}to{transform:scale(1);opacity:1}}.opencode-dialog-content{margin-bottom:20px}.opencode-dialog-message{font-size:15px;color:var(--oc-text-primary);line-height:1.5}.opencode-dialog-actions{display:flex;gap:12px;justify-content:flex-end}.opencode-dialog-btn{padding:10px 20px;border-radius:8px;border:none;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s}.opencode-dialog-btn.cancel{background:var(--oc-bg-tertiary);color:var(--oc-text-primary)}.opencode-dialog-btn.cancel:hover{background:var(--oc-text-primary);color:var(--oc-bg-main)}.opencode-dialog-btn.confirm{background:var(--oc-danger);color:#fff}.opencode-dialog-btn.confirm:hover{background:var(--oc-danger-hover)}@keyframes slideDown{0%{transform:translate(-50%) translateY(-100%);opacity:0}to{transform:translate(-50%) translateY(0);opacity:1}}.opencode-page-notification{position:fixed;top:20px;left:50%;transform:translate(-50%);padding:12px 24px;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border-radius:10px;font-size:14px;font-weight:500;box-shadow:0 4px 16px rgba(59,130,246,.4),0 0 0 2px rgba(59,130,246,.2);animation:slideDown .3s ease;z-index:2147483647;display:flex;align-items:center;gap:10px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.opencode-page-notification:before{content:"\1f4a1";font-size:16px}.opencode-element-highlight{position:fixed;pointer-events:none;z-index:999998;display:none;transition:all .1s ease;border-radius:4px}#vue-inspector-container{display:none!important}.opencode-element-tooltip{position:fixed;background:var(--oc-tooltip-bg);color:#fff;padding:8px 12px;border-radius:6px;font-size:12px;z-index:9999998;display:none;box-shadow:var(--oc-shadow-md);max-width:300px;pointer-events:none}.opencode-tooltip-tag{font-weight:500;margin-bottom:4px;word-break:break-all}.opencode-tooltip-file{font-size:11px;color:var(--oc-text-placeholder);word-break:break-all}.opencode-element-highlight-temp{position:absolute;pointer-events:none;z-index:999998;border-radius:4px;animation:highlight-pulse 2s ease-out forwards}@keyframes highlight-pulse{0%{opacity:1;transform:scale(1)}50%{opacity:.8;transform:scale(1.02)}to{opacity:0;transform:scale(1)}}@media(max-width:768px){.opencode-chat{width:calc(100vw - 40px);height:calc(100vh - 100px)}}
1
+ .opencode-widget{--oc-bg-main: #ffffff;--oc-bg-secondary: #f8f9fa;--oc-bg-tertiary: #f3f4f6;--oc-overlay-bg: rgba(255, 255, 255, .9);--oc-bg-inverse: #1e1e1e;--oc-text-primary: #282828;--oc-text-secondary: #4b5563;--oc-text-tertiary: #6b7280;--oc-text-placeholder: #9ca3af;--oc-text-inverse: #ffffff;--oc-border-primary: #e5e7eb;--oc-border-secondary: #d1d5db;--oc-primary: #3b82f6;--oc-primary-hover: #2563eb;--oc-primary-bg: rgba(59, 130, 246, .1);--oc-danger: #ef4444;--oc-danger-hover: #dc2626;--oc-danger-active: #b91c1c;--oc-success: #10b981;--oc-overlay: rgba(0, 0, 0, .5);--oc-tooltip-bg: #1e1e1e;--oc-dialog-overlay: rgba(0, 0, 0, .5);--oc-thinking-gradient-1: #10b981;--oc-thinking-gradient-2: #059669;--oc-thinking-glow: rgba(16, 185, 129, .3);--oc-thinking-glow-strong: rgba(16, 185, 129, .6);--oc-skeleton-bg: #e5e7eb;--oc-skeleton-gradient: linear-gradient(90deg, #e5e7eb 25%, #f3f4f6 50%, #e5e7eb 75%);--oc-shadow-sm: 0 2px 4px rgba(0, 0, 0, .1);--oc-shadow-md: 0 4px 12px rgba(0, 0, 0, .15);--oc-shadow-lg: 0 8px 32px rgba(0, 0, 0, .12);--oc-shadow-xl: 0 20px 60px rgba(0, 0, 0, .3);--oc-shadow-primary: 0 2px 4px rgba(59, 130, 246, .2);--oc-shadow-primary-hover: 0 4px 6px rgba(59, 130, 246, .3);--oc-shadow-danger: 0 4px 12px rgba(239, 68, 68, .3);--oc-trigger-bg: #3b82f6;--oc-trigger-bg-hover: #2563eb;--oc-trigger-bg-active: #1d4ed8;--oc-trigger-shadow: 0 2px 8px rgba(59, 130, 246, .3);--oc-trigger-shadow-hover: 0 4px 12px rgba(59, 130, 246, .4);--oc-trigger-shadow-active: 0 4px 12px rgba(59, 130, 246, .5);position:fixed;z-index:999999;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.opencode-widget.opencode-theme-dark{--oc-bg-main: #1a1a1a;--oc-bg-secondary: #1e1e1e;--oc-bg-tertiary: #282828;--oc-overlay-bg: rgba(26, 26, 26, .9);--oc-bg-inverse: #ffffff;--oc-text-primary: #f3f4f6;--oc-text-secondary: #d1d5db;--oc-text-tertiary: #9ca3af;--oc-text-placeholder: #6b7280;--oc-text-inverse: #282828;--oc-border-primary: #282828;--oc-border-secondary: #4b5563;--oc-primary: #3b82f6;--oc-primary-hover: #2563eb;--oc-primary-bg: rgba(59, 130, 246, .15);--oc-danger: #ef4444;--oc-danger-hover: #dc2626;--oc-danger-active: #b91c1c;--oc-success: #10b981;--oc-overlay: rgba(26, 26, 26, .9);--oc-tooltip-bg: #282828;--oc-dialog-overlay: rgba(0, 0, 0, .7);--oc-thinking-gradient-1: #34d399;--oc-thinking-gradient-2: #10b981;--oc-thinking-glow: rgba(52, 211, 153, .3);--oc-thinking-glow-strong: rgba(52, 211, 153, .6);--oc-skeleton-bg: #151515;--oc-skeleton-gradient: linear-gradient(90deg, #282828 25%, #4b5563 50%, #282828 75%);--oc-shadow-sm: 0 2px 4px rgba(0, 0, 0, .3);--oc-shadow-md: 0 4px 12px rgba(0, 0, 0, .4);--oc-shadow-lg: 0 8px 32px rgba(0, 0, 0, .4);--oc-shadow-xl: 0 20px 60px rgba(0, 0, 0, .6);--oc-shadow-primary: 0 2px 4px rgba(59, 130, 246, .3);--oc-shadow-primary-hover: 0 4px 6px rgba(59, 130, 246, .4);--oc-shadow-danger: 0 4px 12px rgba(239, 68, 68, .4);--oc-trigger-bg: #60a5fa;--oc-trigger-bg-hover: #3b82f6;--oc-trigger-bg-active: #2563eb;--oc-trigger-shadow: 0 2px 8px rgba(96, 165, 250, .4);--oc-trigger-shadow-hover: 0 4px 12px rgba(96, 165, 250, .5);--oc-trigger-shadow-active: 0 4px 12px rgba(96, 165, 250, .6)}.opencode-chat{position:fixed;bottom:20px;width:700px;height:86vh;max-height:calc(100vh - 40px);background:var(--oc-bg-main);border-radius:16px;box-shadow:var(--oc-shadow-lg);overflow:hidden;opacity:0;visibility:hidden;transform:translate3d(var(---chatAnimationOrigin\.x),var(---chatAnimationOrigin\.y),0) scale(.95);transition:all .3s ease;display:flex;flex-direction:column;z-index:99999}.opencode-chat.open{opacity:1;visibility:visible;transform:translateZ(0) scale(1)}.opencode-chat.no-transition,.opencode-chat.no-transition.open{transition:none!important}.opencode-chat.minimized{width:300px;height:300px}.opencode-chat.minimized .opencode-iframe-container{margin-top:-146px}.opencode-chat-content{display:flex;flex:1;overflow:hidden}.opencode-notification{position:absolute;top:20px;left:50%;transform:translate(-50%);padding:12px 24px;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border-radius:10px;font-size:14px;font-weight:500;box-shadow:0 4px 16px rgba(59,130,246,.4),0 0 0 2px rgba(59,130,246,.2);animation:slideDown .3s ease;z-index:10000000;display:flex;align-items:center;gap:10px}.opencode-notification:before{content:"\1f4a1";font-size:16px}.opencode-dialog-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:var(--oc-dialog-overlay);display:flex;align-items:center;justify-content:center;z-index:9999999;animation:fadeIn .2s ease}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.opencode-dialog{background:var(--oc-bg-main);border-radius:12px;padding:24px;min-width:320px;max-width:400px;box-shadow:var(--oc-shadow-xl);animation:scaleIn .2s ease}@keyframes scaleIn{0%{transform:scale(.9);opacity:0}to{transform:scale(1);opacity:1}}.opencode-dialog-content{margin-bottom:20px}.opencode-dialog-message{font-size:15px;color:var(--oc-text-primary);line-height:1.5}.opencode-dialog-actions{display:flex;gap:12px;justify-content:flex-end}.opencode-dialog-btn{padding:10px 20px;border-radius:8px;border:none;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s}.opencode-dialog-btn.cancel{background:var(--oc-bg-tertiary);color:var(--oc-text-primary)}.opencode-dialog-btn.cancel:hover{background:var(--oc-text-primary);color:var(--oc-bg-main)}.opencode-dialog-btn.confirm{background:var(--oc-danger);color:#fff}.opencode-dialog-btn.confirm:hover{background:var(--oc-danger-hover)}@keyframes slideDown{0%{transform:translate(-50%) translateY(-100%);opacity:0}to{transform:translate(-50%) translateY(0);opacity:1}}.opencode-page-notification{position:fixed;top:20px;left:50%;transform:translate(-50%);padding:12px 24px;background:linear-gradient(135deg,#3b82f6,#2563eb);color:#fff;border-radius:10px;font-size:14px;font-weight:500;box-shadow:0 4px 16px rgba(59,130,246,.4),0 0 0 2px rgba(59,130,246,.2);animation:slideDown .3s ease;z-index:2147483647;display:flex;align-items:center;gap:10px;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif}.opencode-page-notification:before{content:"\1f4a1";font-size:16px}.opencode-element-highlight{position:fixed;pointer-events:none;z-index:999998;border-radius:4px}#vue-inspector-container{display:none!important}.opencode-element-tooltip{position:fixed;background:var(--oc-tooltip-bg);color:#fff;padding:8px 12px;border-radius:6px;font-size:12px;z-index:9999998;box-shadow:var(--oc-shadow-md);max-width:300px;pointer-events:none}.opencode-tooltip-tag{font-weight:500;margin-bottom:4px;word-break:break-all}.opencode-tooltip-file{font-size:11px;color:var(--oc-text-placeholder);word-break:break-all}.opencode-element-highlight-temp{position:absolute;pointer-events:none;z-index:999998;border-radius:4px;animation:highlight-pulse 2s ease-out forwards}@keyframes highlight-pulse{0%{opacity:1;transform:scale(1)}50%{opacity:.8;transform:scale(1.02)}to{opacity:0;transform:scale(1)}}@media(max-width:768px){.opencode-chat{width:calc(100vw - 40px);height:calc(100vh - 100px)}}
@@ -1,23 +1,23 @@
1
1
  import type { OpenCodeWidgetProps } from "./types";
2
- declare var __VLS_12: {}, __VLS_17: {}, __VLS_19: {}, __VLS_21: {}, __VLS_26: {}, __VLS_33: {}, __VLS_35: {}, __VLS_37: {}, __VLS_39: {};
2
+ declare var __VLS_11: {}, __VLS_16: {}, __VLS_18: {}, __VLS_20: {}, __VLS_25: {}, __VLS_32: {}, __VLS_34: {}, __VLS_36: {}, __VLS_38: {};
3
3
  type __VLS_Slots = {} & {
4
- 'button-icon'?: (props: typeof __VLS_12) => any;
4
+ 'button-icon'?: (props: typeof __VLS_11) => any;
5
5
  } & {
6
- 'session-toggle-icon'?: (props: typeof __VLS_17) => any;
6
+ 'session-toggle-icon'?: (props: typeof __VLS_16) => any;
7
7
  } & {
8
- 'select-icon'?: (props: typeof __VLS_19) => any;
8
+ 'select-icon'?: (props: typeof __VLS_18) => any;
9
9
  } & {
10
- 'close-icon'?: (props: typeof __VLS_21) => any;
10
+ 'close-icon'?: (props: typeof __VLS_20) => any;
11
11
  } & {
12
- 'sessions-empty'?: (props: typeof __VLS_26) => any;
12
+ 'sessions-empty'?: (props: typeof __VLS_25) => any;
13
13
  } & {
14
- 'empty-state'?: (props: typeof __VLS_33) => any;
14
+ 'empty-state'?: (props: typeof __VLS_32) => any;
15
15
  } & {
16
- loading?: (props: typeof __VLS_35) => any;
16
+ loading?: (props: typeof __VLS_34) => any;
17
17
  } & {
18
- error?: (props: typeof __VLS_37) => any;
18
+ error?: (props: typeof __VLS_36) => any;
19
19
  } & {
20
- content?: (props: typeof __VLS_39) => any;
20
+ content?: (props: typeof __VLS_38) => any;
21
21
  };
22
22
  declare const __VLS_component: import("vue").DefineComponent<OpenCodeWidgetProps, {
23
23
  showNotification: (message: string, options?: {
@@ -87,9 +87,9 @@ declare const __VLS_component: import("vue").DefineComponent<OpenCodeWidgetProps
87
87
  showSessionListSkeleton: boolean;
88
88
  sessionKey: string;
89
89
  sessions: import("@vite-plugin-opencode-assistant/shared").OpenCodeWidgetSession[];
90
+ thinking: boolean;
90
91
  open: boolean;
91
92
  hotkeyLabel: string;
92
- thinking: boolean;
93
93
  currentSessionId: string | null;
94
94
  selectedElements: import("@vite-plugin-opencode-assistant/shared").OpenCodeSelectedElement[];
95
95
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -19,7 +19,7 @@ var __spreadValues = (a, b) => {
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
20
  import "./index-sfc.css";
21
21
  import { useCssVars as _useCssVars, defineComponent as _defineComponent } from "vue";
22
- import { useSlots, toRef, ref, watch, computed } from "vue";
22
+ import { useSlots, toRef, ref, watch, computed, nextTick, onMounted, onUnmounted } from "vue";
23
23
  import Frame from "./components/Frame.vue.js";
24
24
  import Header from "./components/Header.vue.js";
25
25
  import SelectHint from "./components/SelectHint.vue.js";
@@ -30,6 +30,7 @@ import { useSelection } from "../composables/use-selection";
30
30
  import { useSession } from "../composables/use-session";
31
31
  import { useWidget } from "../composables/use-widget";
32
32
  import { useInspector } from "../composables/use-inspector";
33
+ import { usePersistState } from "../composables/use-persist-state";
33
34
  import { provideOpenCodeWidgetContext } from "./context";
34
35
  const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValues({}, {
35
36
  name: "OpencodeWidget"
@@ -57,7 +58,8 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
57
58
  selectedElements: { type: Array, required: false, default: () => [] },
58
59
  showClearAll: { type: Boolean, required: false, default: true },
59
60
  selectEnabled: { type: Boolean, required: false, default: true },
60
- thinking: { type: Boolean, required: false, default: false }
61
+ thinking: { type: Boolean, required: false, default: false },
62
+ sessionStates: { type: Object, required: false }
61
63
  },
62
64
  emits: ["update:open", "update:selectMode", "update:sessionListCollapsed", "update:currentSessionId", "update:selectedElements", "update:theme", "update:thinking", "toggle", "close", "toggle-session-list", "toggle-select-mode", "toggle-theme", "create-session", "select-session", "delete-session", "click-selected-node", "remove-selected-node", "clear-selected-nodes", "empty-action", "frame-loaded", "thinking-change"],
63
65
  setup(__props, { expose: __expose, emit: __emit }) {
@@ -106,17 +108,26 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
106
108
  var _a;
107
109
  (_a = frameRef.value) == null ? void 0 : _a.sendMessageToIframe(type, data);
108
110
  };
111
+ const localSessionListCollapsed = ref(props.sessionListCollapsed);
112
+ const minimized = ref(false);
113
+ const promptDockVisible = ref(true);
114
+ const isRestoring = ref(true);
115
+ const iframeLoaded = ref(false);
116
+ const syncStateToIframe = () => {
117
+ if (!iframeLoaded.value) return;
118
+ sendMessageToIframe("prompt-dock-visibility-change", { visible: promptDockVisible.value });
119
+ sendMessageToIframe("minimize-state-change", { minimized: minimized.value });
120
+ };
109
121
  const handleFrameLoaded = () => {
110
122
  emit("frame-loaded");
123
+ iframeLoaded.value = true;
124
+ syncStateToIframe();
111
125
  };
112
126
  __expose({
113
127
  showNotification,
114
128
  showConfirmDialog,
115
129
  sendMessageToIframe
116
130
  });
117
- const localSessionListCollapsed = ref(props.sessionListCollapsed);
118
- const minimized = ref(false);
119
- const promptDockVisible = ref(true);
120
131
  watch(
121
132
  () => props.sessionListCollapsed,
122
133
  (val) => {
@@ -213,6 +224,53 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
213
224
  emit("toggle-select-mode", false);
214
225
  }
215
226
  });
227
+ const bubbleOffset = ref(void 0);
228
+ usePersistState({
229
+ open: toRef(props, "open"),
230
+ minimized,
231
+ promptDockVisible,
232
+ bubbleOffset,
233
+ theme: toRef(props, "theme"),
234
+ sessionListCollapsed: localSessionListCollapsed,
235
+ onRestore: (state) => {
236
+ if (state.open !== void 0 && state.open !== props.open) {
237
+ emit("update:open", state.open);
238
+ emit("toggle", state.open);
239
+ }
240
+ if (state.minimized !== void 0) {
241
+ minimized.value = state.minimized;
242
+ }
243
+ if (state.bubbleOffset !== void 0) {
244
+ const bubbleSize = 44;
245
+ const margin = 10;
246
+ const maxX = window.innerWidth - bubbleSize - margin;
247
+ const maxY = window.innerHeight - bubbleSize - margin;
248
+ bubbleOffset.value = {
249
+ x: Math.max(margin, Math.min(state.bubbleOffset.x, maxX)),
250
+ y: Math.max(margin, Math.min(state.bubbleOffset.y, maxY))
251
+ };
252
+ }
253
+ if (state.theme !== void 0 && state.theme !== props.theme) {
254
+ emit("update:theme", state.theme);
255
+ emit("toggle-theme", state.theme);
256
+ }
257
+ if (state.sessionListCollapsed !== void 0 && state.sessionListCollapsed !== props.sessionListCollapsed) {
258
+ localSessionListCollapsed.value = state.sessionListCollapsed;
259
+ emit("update:sessionListCollapsed", state.sessionListCollapsed);
260
+ }
261
+ if (state.promptDockVisible !== void 0) {
262
+ promptDockVisible.value = state.promptDockVisible;
263
+ } else if (minimized.value) {
264
+ promptDockVisible.value = false;
265
+ }
266
+ nextTick(() => {
267
+ syncStateToIframe();
268
+ setTimeout(() => {
269
+ isRestoring.value = false;
270
+ }, 50);
271
+ });
272
+ }
273
+ });
216
274
  const handleToggleMinimize = () => {
217
275
  minimized.value = !minimized.value;
218
276
  promptDockVisible.value = !minimized.value;
@@ -223,15 +281,33 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
223
281
  promptDockVisible.value = !promptDockVisible.value;
224
282
  sendMessageToIframe("prompt-dock-visibility-change", { visible: promptDockVisible.value });
225
283
  };
226
- const bubbleOffset = ref(void 0);
284
+ const windowWidth = ref(typeof window !== "undefined" ? window.innerWidth : 0);
285
+ const windowHeight = ref(typeof window !== "undefined" ? window.innerHeight : 0);
286
+ const handleWindowResize = () => {
287
+ if (typeof window !== "undefined") {
288
+ windowWidth.value = window.innerWidth;
289
+ windowHeight.value = window.innerHeight;
290
+ }
291
+ };
292
+ onMounted(() => {
293
+ if (typeof window !== "undefined") {
294
+ window.addEventListener("resize", handleWindowResize);
295
+ }
296
+ });
297
+ onUnmounted(() => {
298
+ if (typeof window !== "undefined") {
299
+ window.removeEventListener("resize", handleWindowResize);
300
+ }
301
+ });
227
302
  const bubbleQuadrant = computed(() => {
228
303
  var _a, _b, _c, _d;
229
304
  if (typeof window === "undefined") return "bottom-right";
230
- const centerX = window.innerWidth / 2;
231
- const centerY = window.innerHeight / 2;
305
+ const centerX = windowWidth.value / 2;
306
+ const centerY = windowHeight.value / 2;
232
307
  const bubbleSize = 44;
233
- const effectiveX = ((_b = (_a = bubbleOffset.value) == null ? void 0 : _a.x) != null ? _b : window.innerWidth - bubbleSize - 24) + bubbleSize / 2;
234
- const effectiveY = ((_d = (_c = bubbleOffset.value) == null ? void 0 : _c.y) != null ? _d : window.innerHeight - bubbleSize - 24) + bubbleSize / 2;
308
+ const currentOffset = (_b = (_a = triggerRef.value) == null ? void 0 : _a.offset) != null ? _b : bubbleOffset.value;
309
+ const effectiveX = ((_c = currentOffset == null ? void 0 : currentOffset.x) != null ? _c : windowWidth.value - bubbleSize - 24) + bubbleSize / 2;
310
+ const effectiveY = ((_d = currentOffset == null ? void 0 : currentOffset.y) != null ? _d : windowHeight.value - bubbleSize - 24) + bubbleSize / 2;
235
311
  if (effectiveX >= centerX && effectiveY >= centerY) {
236
312
  return "bottom-right";
237
313
  } else if (effectiveX < centerX && effectiveY >= centerY) {
@@ -247,36 +323,42 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
247
323
  return quadrant === "top-right" || quadrant === "bottom-right";
248
324
  });
249
325
  const chatPositionStyle = computed(() => {
250
- var _a;
326
+ var _a, _b, _c;
251
327
  if (typeof window === "undefined") return {};
252
- const windowWidth = window.innerWidth;
253
- const windowHeight = window.innerHeight;
254
328
  const chatWidth = minimized.value ? 300 : 700;
255
- const chatHeight = minimized.value ? 300 : Math.min(windowHeight * 0.86, windowHeight - 40);
329
+ const chatHeight = minimized.value ? 300 : Math.min(windowHeight.value * 0.86, windowHeight.value - 40);
256
330
  const gap = 24;
257
331
  const bubbleSize = 44;
258
332
  const screenMargin = 20;
259
- const effectiveOffset = (_a = bubbleOffset.value) != null ? _a : { x: windowWidth - bubbleSize - gap, y: windowHeight - bubbleSize - gap };
333
+ const effectiveOffset = (_c = (_b = (_a = triggerRef.value) == null ? void 0 : _a.offset) != null ? _b : bubbleOffset.value) != null ? _c : { x: windowWidth.value - bubbleSize - gap, y: windowHeight.value - bubbleSize - gap };
260
334
  const style = {};
261
335
  if (isBubbleOnRightSide.value) {
262
- let rightPos = windowWidth - effectiveOffset.x + gap;
263
- const maxRight = windowWidth - chatWidth - screenMargin;
336
+ let rightPos = windowWidth.value - effectiveOffset.x + gap;
337
+ const minRight = screenMargin;
338
+ const maxRight = windowWidth.value - chatWidth - screenMargin;
264
339
  if (rightPos > maxRight) {
265
340
  rightPos = maxRight;
266
341
  }
342
+ if (rightPos < minRight) {
343
+ rightPos = minRight;
344
+ }
267
345
  style.right = `${rightPos}px`;
268
346
  style.left = "auto";
269
347
  } else {
270
348
  let leftPos = effectiveOffset.x + bubbleSize + gap;
271
- const maxLeft = windowWidth - chatWidth - screenMargin;
349
+ const minLeft = screenMargin;
350
+ const maxLeft = windowWidth.value - chatWidth - screenMargin;
272
351
  if (leftPos > maxLeft) {
273
352
  leftPos = maxLeft;
274
353
  }
354
+ if (leftPos < minLeft) {
355
+ leftPos = minLeft;
356
+ }
275
357
  style.left = `${leftPos}px`;
276
358
  style.right = "auto";
277
359
  }
278
- let bottomPos = windowHeight - effectiveOffset.y - bubbleSize;
279
- const maxBottom = windowHeight - chatHeight - screenMargin;
360
+ let bottomPos = windowHeight.value - effectiveOffset.y - bubbleSize;
361
+ const maxBottom = windowHeight.value - chatHeight - screenMargin;
280
362
  if (bottomPos > maxBottom) {
281
363
  bottomPos = maxBottom;
282
364
  }
@@ -340,6 +422,11 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
340
422
  thinking: toRef(props, "thinking"),
341
423
  minimized,
342
424
  promptDockVisible,
425
+ bubbleOffset,
426
+ sessionStates: computed(() => {
427
+ var _a;
428
+ return (_a = props.sessionStates) != null ? _a : {};
429
+ }),
343
430
  iframeSource,
344
431
  buttonActive,
345
432
  sessionListTitle,
@@ -361,7 +448,8 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
361
448
  handleClickSelectedNode,
362
449
  handleRemoveSelectedNode: (payload) => handleRemoveSelectedNode(payload.item, payload.index, payload.source),
363
450
  handleClearSelectedNodes,
364
- handleFrameLoaded
451
+ handleFrameLoaded,
452
+ handleBubbleOffsetChange
365
453
  });
366
454
  const __returned__ = { props, emit, slots, notificationMessage, notificationVisible, notificationMode, get notificationTimer() {
367
455
  return notificationTimer;
@@ -371,7 +459,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
371
459
  return dialogResolve;
372
460
  }, set dialogResolve(v) {
373
461
  dialogResolve = v;
374
- }, showConfirmDialog, handleDialogConfirm, handleDialogCancel, frameRef, triggerRef, sendMessageToIframe, handleFrameLoaded, localSessionListCollapsed, minimized, promptDockVisible, buttonActive, containerClasses, iframeSource, sessionListTitle, resolvedTheme, handleClose, handleEmptyAction, handleToggle, handleToggleSessionList, handleToggleTheme, sessionItems, handleCreateSession, handleDeleteSession, handleSelectSession, bubbleVisible, hasSelectedElements, selectedElementItems, handleClearSelectedNodes, handleClickSelectedNode, handleRemoveSelectedNode, handleToggleSelectMode, highlightVisible, highlightStyle, tooltipVisible, tooltipStyle, tooltipContent, handleToggleMinimize, handleTogglePromptDock, bubbleOffset, bubbleQuadrant, isBubbleOnRightSide, chatPositionStyle, handleBubbleOffsetChange, chatAnimationOrigin, isDragging, get wasOpenBeforeDrag() {
462
+ }, showConfirmDialog, handleDialogConfirm, handleDialogCancel, frameRef, triggerRef, sendMessageToIframe, localSessionListCollapsed, minimized, promptDockVisible, isRestoring, iframeLoaded, syncStateToIframe, handleFrameLoaded, buttonActive, containerClasses, iframeSource, sessionListTitle, resolvedTheme, handleClose, handleEmptyAction, handleToggle, handleToggleSessionList, handleToggleTheme, sessionItems, handleCreateSession, handleDeleteSession, handleSelectSession, bubbleVisible, hasSelectedElements, selectedElementItems, handleClearSelectedNodes, handleClickSelectedNode, handleRemoveSelectedNode, handleToggleSelectMode, highlightVisible, highlightStyle, tooltipVisible, tooltipStyle, tooltipContent, bubbleOffset, handleToggleMinimize, handleTogglePromptDock, windowWidth, windowHeight, handleWindowResize, bubbleQuadrant, isBubbleOnRightSide, chatPositionStyle, handleBubbleOffsetChange, chatAnimationOrigin, isDragging, get wasOpenBeforeDrag() {
375
463
  return wasOpenBeforeDrag;
376
464
  }, set wasOpenBeforeDrag(v) {
377
465
  wasOpenBeforeDrag = v;
@@ -416,7 +504,6 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
416
504
  $setup["Trigger"],
417
505
  {
418
506
  ref: "triggerRef",
419
- onOffsetChange: $setup.handleBubbleOffsetChange,
420
507
  onDragStart: $setup.handleDragStart,
421
508
  onDragEnd: $setup.handleDragEnd
422
509
  },
@@ -438,7 +525,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
438
525
  _withDirectives(_createElementVNode(
439
526
  "div",
440
527
  {
441
- class: _normalizeClass(["opencode-chat", { open: $props.open, minimized: $setup.minimized, dragging: $setup.isDragging }]),
528
+ class: _normalizeClass(["opencode-chat", { open: $props.open, minimized: $setup.minimized, dragging: $setup.isDragging, "no-transition": $setup.isRestoring }]),
442
529
  style: _normalizeStyle($setup.chatPositionStyle)
443
530
  },
444
531
  [
@@ -549,9 +636,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
549
636
  "div",
550
637
  {
551
638
  class: "opencode-element-highlight",
552
- style: _normalizeStyle(__spreadValues({
553
- display: $setup.highlightVisible ? "block" : "none"
554
- }, $setup.highlightStyle))
639
+ style: _normalizeStyle($setup.highlightStyle)
555
640
  },
556
641
  null,
557
642
  4
@@ -563,9 +648,7 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
563
648
  "div",
564
649
  {
565
650
  class: "opencode-element-tooltip",
566
- style: _normalizeStyle(__spreadValues({
567
- display: $setup.tooltipVisible ? "block" : "none"
568
- }, $setup.tooltipStyle))
651
+ style: _normalizeStyle($setup.tooltipStyle)
569
652
  },
570
653
  [
571
654
  _createElementVNode(
@@ -1,2 +1,2 @@
1
- export type { OpenCodeWidgetTheme, OpenCodeWidgetSession, OpenCodeSelectedElement, OpenCodeRemoveSelectedPayload, OpenCodeWidgetSessionItem, OpenCodeSelectedElementItem, OpenCodeWidgetProps, OpenCodeWidgetEmits, } from "@vite-plugin-opencode-assistant/shared";
1
+ export type { OpenCodeWidgetTheme, OpenCodeWidgetSession, OpenCodeSelectedElement, OpenCodeRemoveSelectedPayload, OpenCodeWidgetSessionItem, OpenCodeSelectedElementItem, OpenCodeWidgetProps, OpenCodeWidgetEmits, OpencodeSessionThinkingState, } from "@vite-plugin-opencode-assistant/shared";
2
2
  export type OpenCodeWidgetThemeLocal = "light" | "dark" | "auto";