@vite-plugin-opencode-assistant/components 1.0.23 → 1.0.25

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-widget.d.ts +0 -1
  4. package/es/open-code-widget/composables/use-widget.js +0 -1
  5. package/es/open-code-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -0
  6. package/es/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +44 -0
  7. package/es/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.js +309 -0
  8. package/es/open-code-widget/src/components/FloatingBubble/index.d.ts +3 -0
  9. package/es/open-code-widget/src/components/FloatingBubble/index.js +5 -0
  10. package/es/open-code-widget/src/components/FloatingBubble/types.d.ts +24 -0
  11. package/es/open-code-widget/src/components/FloatingBubble/types.js +0 -0
  12. package/es/open-code-widget/src/components/Trigger-sfc.css +1 -1
  13. package/es/open-code-widget/src/components/Trigger.vue.d.ts +21 -3
  14. package/es/open-code-widget/src/components/Trigger.vue.js +127 -48
  15. package/es/open-code-widget/src/index-sfc.css +1 -1
  16. package/es/open-code-widget/src/index.vue.d.ts +10 -11
  17. package/es/open-code-widget/src/index.vue.js +82 -17
  18. package/es/open-code-widget/src/types.d.ts +1 -2
  19. package/lib/@vite-plugin-opencode-assistant/components.cjs.js +562 -99
  20. package/lib/@vite-plugin-opencode-assistant/components.es.js +558 -95
  21. package/lib/components.css +3 -2
  22. package/lib/index.d.ts +1 -1
  23. package/lib/index.js +1 -1
  24. package/lib/open-code-widget/composables/use-widget.d.ts +0 -1
  25. package/lib/open-code-widget/composables/use-widget.js +0 -1
  26. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -0
  27. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +44 -0
  28. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.js +326 -0
  29. package/lib/open-code-widget/src/components/FloatingBubble/index.d.ts +3 -0
  30. package/lib/open-code-widget/src/components/FloatingBubble/index.js +35 -0
  31. package/lib/open-code-widget/src/components/FloatingBubble/types.d.ts +24 -0
  32. package/lib/open-code-widget/src/components/FloatingBubble/types.js +15 -0
  33. package/lib/open-code-widget/src/components/Trigger-sfc.css +1 -1
  34. package/lib/open-code-widget/src/components/Trigger.vue.d.ts +21 -3
  35. package/lib/open-code-widget/src/components/Trigger.vue.js +137 -48
  36. package/lib/open-code-widget/src/index-sfc.css +1 -1
  37. package/lib/open-code-widget/src/index.vue.d.ts +10 -11
  38. package/lib/open-code-widget/src/index.vue.js +80 -15
  39. package/lib/open-code-widget/src/types.d.ts +1 -2
  40. package/lib/web-types.json +1 -1
  41. package/package.json +2 -2
@@ -1,69 +1,148 @@
1
1
  import "./Trigger-sfc.css";
2
2
  import { defineComponent as _defineComponent } from "vue";
3
+ import { ref, computed, onMounted } from "vue";
3
4
  import { useOpenCodeWidgetContext } from "../context";
5
+ import FloatingBubble from "./FloatingBubble/FloatingBubble.vue.js";
6
+ const STORAGE_KEY = "opencode-bubble-offset";
4
7
  const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
5
8
  __name: "Trigger",
6
- setup(__props, { expose: __expose }) {
7
- __expose();
9
+ emits: ["offset-change", "drag-start", "drag-end"],
10
+ setup(__props, { expose: __expose, emit: __emit }) {
8
11
  const {
9
12
  buttonActive: active,
10
13
  open,
11
14
  hotkeyLabel,
12
15
  thinking,
16
+ resolvedTheme,
13
17
  handleToggle
14
18
  } = useOpenCodeWidgetContext();
15
- const __returned__ = { active, open, hotkeyLabel, thinking, handleToggle };
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 { x: 0, y: 0 };
31
+ };
32
+ const offset = ref(loadOffset());
33
+ const emit = __emit;
34
+ const saveOffset = (value) => {
35
+ try {
36
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(value));
37
+ } catch (e) {
38
+ }
39
+ };
40
+ const handleOffsetChange = (value) => {
41
+ offset.value = value;
42
+ saveOffset(value);
43
+ emit("offset-change", value);
44
+ };
45
+ const bubbleRef = ref(null);
46
+ const isOnRightSide = computed(() => {
47
+ if (typeof window === "undefined") return true;
48
+ const centerX = window.innerWidth / 2;
49
+ return offset.value.x > centerX;
50
+ });
51
+ onMounted(() => {
52
+ if (offset.value.x !== 0 || offset.value.y !== 0) {
53
+ emit("offset-change", offset.value);
54
+ }
55
+ });
56
+ __expose({
57
+ isOnRightSide,
58
+ offset
59
+ });
60
+ const __returned__ = { active, open, hotkeyLabel, thinking, resolvedTheme, handleToggle, STORAGE_KEY, loadOffset, offset, emit, saveOffset, handleOffsetChange, bubbleRef, isOnRightSide, FloatingBubble };
16
61
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
17
62
  return __returned__;
18
63
  }
19
64
  });
20
- import { renderSlot as _renderSlot, createElementVNode as _createElementVNode, normalizeClass as _normalizeClass, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue";
65
+ import { renderSlot as _renderSlot, createElementVNode as _createElementVNode, normalizeClass as _normalizeClass, withCtx as _withCtx, openBlock as _openBlock, createBlock as _createBlock } from "vue";
21
66
  const _hoisted_1 = ["aria-expanded", "title"];
22
67
  function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
23
- return _openBlock(), _createElementBlock("button", {
24
- class: _normalizeClass(["opencode-button", { active: $setup.active, thinking: $setup.thinking }]),
25
- type: "button",
26
- "aria-expanded": $setup.open,
27
- "aria-label": "\u6253\u5F00 AI \u52A9\u624B",
28
- title: `AI \u52A9\u624B (${$setup.hotkeyLabel})`,
29
- onClick: _cache[0] || (_cache[0] = (...args) => $setup.handleToggle && $setup.handleToggle(...args))
30
- }, [
31
- _renderSlot(_ctx.$slots, "default", {}, () => [
32
- _cache[1] || (_cache[1] = _createElementVNode(
33
- "svg",
34
- {
35
- t: "1775402599580",
36
- class: "icon",
37
- viewBox: "0 0 1024 1024",
38
- version: "1.1",
39
- xmlns: "http://www.w3.org/2000/svg",
40
- "p-id": "5390",
41
- "xmlns:xlink": "http://www.w3.org/1999/xlink",
42
- width: "100%",
43
- height: "100%"
44
- },
45
- [
46
- _createElementVNode("path", {
47
- d: "M512 981.33H85.34c-15.85 0-30.38-8.77-37.77-22.81a42.624 42.624 0 0 1 2.6-44.02L135 791.08C75.25 710.5 42.67 612.6 42.67 512 42.67 253.21 253.21 42.67 512 42.67S981.34 253.21 981.34 512 770.8 981.33 512 981.33zM166.44 896H512c211.73 0 384-172.27 384-384S723.73 128 512 128 128 300.27 128 512c0 91.29 32.83 179.9 92.46 249.46 12.58 14.69 13.73 36 2.77 51.94L166.44 896z",
48
- fill: "white",
49
- "p-id": "5391"
50
- }),
51
- _createElementVNode("path", {
52
- d: "M384 448m-64 0a64 64 0 1 0 128 0 64 64 0 1 0 -128 0Z",
53
- fill: "white",
54
- "p-id": "5392"
55
- }),
56
- _createElementVNode("path", {
57
- d: "M640 448m-64 0a64 64 0 1 0 128 0 64 64 0 1 0 -128 0Z",
58
- fill: "white",
59
- "p-id": "5393"
60
- })
61
- ],
62
- -1
63
- /* CACHED */
64
- ))
65
- ])
66
- ], 10, _hoisted_1);
68
+ return _openBlock(), _createBlock($setup["FloatingBubble"], {
69
+ ref: "bubbleRef",
70
+ offset: $setup.offset,
71
+ "onUpdate:offset": _cache[0] || (_cache[0] = ($event) => $setup.offset = $event),
72
+ axis: "xy",
73
+ magnetic: "x",
74
+ gap: 24,
75
+ onClick: $setup.handleToggle,
76
+ onOffsetChange: $setup.handleOffsetChange,
77
+ onDragStart: _cache[1] || (_cache[1] = ($event) => $setup.emit("drag-start")),
78
+ onDragEnd: _cache[2] || (_cache[2] = ($event) => $setup.emit("drag-end"))
79
+ }, {
80
+ default: _withCtx(() => [
81
+ _createElementVNode("button", {
82
+ class: _normalizeClass(["opencode-button", { active: $setup.active, thinking: $setup.thinking, "opencode-theme-dark": $setup.resolvedTheme === "dark" }]),
83
+ type: "button",
84
+ "aria-expanded": $setup.open,
85
+ "aria-label": "\u6253\u5F00 AI \u52A9\u624B",
86
+ title: `AI \u52A9\u624B (${$setup.hotkeyLabel})`
87
+ }, [
88
+ _renderSlot(_ctx.$slots, "default", {}, () => [
89
+ _cache[3] || (_cache[3] = _createElementVNode(
90
+ "svg",
91
+ {
92
+ t: "1775402599580",
93
+ class: "icon",
94
+ viewBox: "0 0 1024 1024",
95
+ version: "1.1",
96
+ xmlns: "http://www.w3.org/2000/svg",
97
+ "p-id": "5390",
98
+ "xmlns:xlink": "http://www.w3.org/1999/xlink",
99
+ width: "100%",
100
+ height: "100%"
101
+ },
102
+ [
103
+ _createElementVNode("defs", null, [
104
+ _createElementVNode("linearGradient", {
105
+ id: "opencode-logo-gradient",
106
+ x1: "0%",
107
+ y1: "0%",
108
+ x2: "100%",
109
+ y2: "100%"
110
+ }, [
111
+ _createElementVNode("stop", {
112
+ offset: "0%",
113
+ style: { "stop-color": "#667eea" }
114
+ }),
115
+ _createElementVNode("stop", {
116
+ offset: "100%",
117
+ style: { "stop-color": "#764ba2" }
118
+ })
119
+ ])
120
+ ]),
121
+ _createElementVNode("path", {
122
+ d: "M512 981.33H85.34c-15.85 0-30.38-8.77-37.77-22.81a42.624 42.624 0 0 1 2.6-44.02L135 791.08C75.25 710.5 42.67 612.6 42.67 512 42.67 253.21 253.21 42.67 512 42.67S981.34 253.21 981.34 512 770.8 981.33 512 981.33zM166.44 896H512c211.73 0 384-172.27 384-384S723.73 128 512 128 128 300.27 128 512c0 91.29 32.83 179.9 92.46 249.46 12.58 14.69 13.73 36 2.77 51.94L166.44 896z",
123
+ fill: "url(#opencode-logo-gradient)",
124
+ "p-id": "5391"
125
+ }),
126
+ _createElementVNode("path", {
127
+ d: "M384 448m-64 0a64 64 0 1 0 128 0 64 64 0 1 0 -128 0Z",
128
+ fill: "url(#opencode-logo-gradient)",
129
+ "p-id": "5392"
130
+ }),
131
+ _createElementVNode("path", {
132
+ d: "M640 448m-64 0a64 64 0 1 0 128 0 64 64 0 1 0 -128 0Z",
133
+ fill: "url(#opencode-logo-gradient)",
134
+ "p-id": "5393"
135
+ })
136
+ ],
137
+ -1
138
+ /* CACHED */
139
+ ))
140
+ ])
141
+ ], 10, _hoisted_1)
142
+ ]),
143
+ _: 3
144
+ /* FORWARDED */
145
+ }, 8, ["offset", "onClick"]);
67
146
  }
68
147
  __vue_sfc__.render = __vue_render__;
69
148
  var Trigger_vue_default = __vue_sfc__;
@@ -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-widget.bottom-right{bottom:20px;right:20px}.opencode-widget.bottom-left{bottom:20px;left:20px}.opencode-widget.top-right{top:20px;right:20px}.opencode-widget.top-left{top:20px;left:20px}.opencode-chat{position:absolute;width:700px;height:86vh;background:var(--oc-bg-main);border-radius:16px;box-shadow:var(--oc-shadow-lg);overflow:hidden;opacity:0;visibility:hidden;transform:translateY(20px) scale(.95);transition:all .3s ease;display:flex;flex-direction:column}.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-widget.bottom-right .opencode-chat{bottom:56px;right:0}.opencode-widget.bottom-left .opencode-chat{bottom:56px;left:0}.opencode-widget.top-right .opencode-chat{top:56px;right:0}.opencode-widget.top-left .opencode-chat{top:56px;left:0}.opencode-widget.bottom-right .opencode-selected-bubbles{bottom:56px;right:0}.opencode-widget.bottom-left .opencode-selected-bubbles{bottom:56px;left:0}.opencode-widget.top-right .opencode-selected-bubbles{top:56px;bottom:auto;right:0}.opencode-widget.top-left .opencode-selected-bubbles{top:56px;bottom:auto;left:0}.opencode-chat.open{opacity:1;visibility:visible;transform:translateY(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:translateY(20px) 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:translateY(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,23 +1,23 @@
1
1
  import type { OpenCodeWidgetProps } from "./types";
2
- declare var __VLS_4: {}, __VLS_9: {}, __VLS_11: {}, __VLS_13: {}, __VLS_18: {}, __VLS_25: {}, __VLS_27: {}, __VLS_29: {}, __VLS_31: {};
2
+ declare var __VLS_12: {}, __VLS_17: {}, __VLS_19: {}, __VLS_21: {}, __VLS_26: {}, __VLS_33: {}, __VLS_35: {}, __VLS_37: {}, __VLS_39: {};
3
3
  type __VLS_Slots = {} & {
4
- 'button-icon'?: (props: typeof __VLS_4) => any;
4
+ 'button-icon'?: (props: typeof __VLS_12) => any;
5
5
  } & {
6
- 'session-toggle-icon'?: (props: typeof __VLS_9) => any;
6
+ 'session-toggle-icon'?: (props: typeof __VLS_17) => any;
7
7
  } & {
8
- 'select-icon'?: (props: typeof __VLS_11) => any;
8
+ 'select-icon'?: (props: typeof __VLS_19) => any;
9
9
  } & {
10
- 'close-icon'?: (props: typeof __VLS_13) => any;
10
+ 'close-icon'?: (props: typeof __VLS_21) => any;
11
11
  } & {
12
- 'sessions-empty'?: (props: typeof __VLS_18) => any;
12
+ 'sessions-empty'?: (props: typeof __VLS_26) => any;
13
13
  } & {
14
- 'empty-state'?: (props: typeof __VLS_25) => any;
14
+ 'empty-state'?: (props: typeof __VLS_33) => any;
15
15
  } & {
16
- loading?: (props: typeof __VLS_27) => any;
16
+ loading?: (props: typeof __VLS_35) => any;
17
17
  } & {
18
- error?: (props: typeof __VLS_29) => any;
18
+ error?: (props: typeof __VLS_37) => any;
19
19
  } & {
20
- content?: (props: typeof __VLS_31) => any;
20
+ content?: (props: typeof __VLS_39) => any;
21
21
  };
22
22
  declare const __VLS_component: import("vue").DefineComponent<OpenCodeWidgetProps, {
23
23
  showNotification: (message: string, options?: {
@@ -90,7 +90,6 @@ declare const __VLS_component: import("vue").DefineComponent<OpenCodeWidgetProps
90
90
  open: boolean;
91
91
  hotkeyLabel: string;
92
92
  thinking: boolean;
93
- position: import("@vite-plugin-opencode-assistant/shared").OpenCodeWidgetPosition;
94
93
  currentSessionId: string | null;
95
94
  selectedElements: import("@vite-plugin-opencode-assistant/shared").OpenCodeSelectedElement[];
96
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 { defineComponent as _defineComponent } from "vue";
22
- import { useSlots, toRef, ref, watch } from "vue";
22
+ import { useSlots, toRef, ref, watch, computed } 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";
@@ -36,7 +36,6 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
36
36
  }), {
37
37
  __name: "index",
38
38
  props: {
39
- position: { type: String, required: false, default: "bottom-right" },
40
39
  open: { type: Boolean, required: false, default: false },
41
40
  theme: { type: String, required: false, default: "auto" },
42
41
  title: { type: String, required: false, default: "AI \u52A9\u624B" },
@@ -98,6 +97,7 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
98
97
  if (dialogResolve) dialogResolve(false);
99
98
  };
100
99
  const frameRef = ref(null);
100
+ const triggerRef = ref(null);
101
101
  const sendMessageToIframe = (type, data) => {
102
102
  var _a;
103
103
  (_a = frameRef.value) == null ? void 0 : _a.sendMessageToIframe(type, data);
@@ -131,7 +131,6 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
131
131
  handleToggleSessionList,
132
132
  handleToggleTheme
133
133
  } = useWidget({
134
- position: toRef(props, "position"),
135
134
  theme: toRef(props, "theme"),
136
135
  open: toRef(props, "open"),
137
136
  selectMode: toRef(props, "selectMode"),
@@ -220,6 +219,68 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
220
219
  promptDockVisible.value = !promptDockVisible.value;
221
220
  sendMessageToIframe("prompt-dock-visibility-change", { visible: promptDockVisible.value });
222
221
  };
222
+ const bubbleOffset = ref({ x: 0, y: 0 });
223
+ const isBubbleOnRightSide = computed(() => {
224
+ if (typeof window === "undefined") return true;
225
+ const centerX = window.innerWidth / 2;
226
+ return bubbleOffset.value.x > centerX;
227
+ });
228
+ const chatPositionStyle = computed(() => {
229
+ if (typeof window === "undefined") return {};
230
+ const windowWidth = window.innerWidth;
231
+ const windowHeight = window.innerHeight;
232
+ const chatWidth = minimized.value ? 300 : 700;
233
+ const chatHeight = minimized.value ? 300 : Math.min(windowHeight * 0.86, windowHeight - 40);
234
+ const gap = 24;
235
+ const bubbleSize = 44;
236
+ const screenMargin = 20;
237
+ const style = {};
238
+ if (isBubbleOnRightSide.value) {
239
+ let rightPos = windowWidth - bubbleOffset.value.x + gap;
240
+ const maxRight = windowWidth - chatWidth - screenMargin;
241
+ if (rightPos > maxRight) {
242
+ rightPos = maxRight;
243
+ }
244
+ style.right = `${rightPos}px`;
245
+ style.left = "auto";
246
+ } else {
247
+ let leftPos = bubbleOffset.value.x + bubbleSize + gap;
248
+ const maxLeft = windowWidth - chatWidth - screenMargin;
249
+ if (leftPos > maxLeft) {
250
+ leftPos = maxLeft;
251
+ }
252
+ style.left = `${leftPos}px`;
253
+ style.right = "auto";
254
+ }
255
+ let bottomPos = windowHeight - bubbleOffset.value.y - bubbleSize;
256
+ const maxBottom = windowHeight - chatHeight - screenMargin;
257
+ if (bottomPos > maxBottom) {
258
+ bottomPos = maxBottom;
259
+ }
260
+ if (bottomPos < screenMargin) {
261
+ bottomPos = screenMargin;
262
+ }
263
+ style.bottom = `${bottomPos}px`;
264
+ return style;
265
+ });
266
+ const handleBubbleOffsetChange = (offset) => {
267
+ bubbleOffset.value = offset;
268
+ };
269
+ const isDragging = ref(false);
270
+ let wasOpenBeforeDrag = false;
271
+ const handleDragStart = () => {
272
+ isDragging.value = true;
273
+ wasOpenBeforeDrag = props.open;
274
+ if (props.open) {
275
+ emit("update:open", false);
276
+ }
277
+ };
278
+ const handleDragEnd = () => {
279
+ isDragging.value = false;
280
+ if (wasOpenBeforeDrag) {
281
+ emit("update:open", true);
282
+ }
283
+ };
223
284
  provideOpenCodeWidgetContext({
224
285
  theme: toRef(props, "theme"),
225
286
  resolvedTheme,
@@ -273,12 +334,16 @@ const __vue_sfc__ = /* @__PURE__ */ _defineComponent(__spreadProps(__spreadValue
273
334
  return dialogResolve;
274
335
  }, set dialogResolve(v) {
275
336
  dialogResolve = v;
276
- }, showConfirmDialog, handleDialogConfirm, handleDialogCancel, frameRef, 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, Frame, Header, SelectHint, SelectedNodes, SessionList, Trigger };
337
+ }, 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, isBubbleOnRightSide, chatPositionStyle, handleBubbleOffsetChange, isDragging, get wasOpenBeforeDrag() {
338
+ return wasOpenBeforeDrag;
339
+ }, set wasOpenBeforeDrag(v) {
340
+ wasOpenBeforeDrag = v;
341
+ }, handleDragStart, handleDragEnd, Frame, Header, SelectHint, SelectedNodes, SessionList, Trigger };
277
342
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
278
343
  return __returned__;
279
344
  }
280
345
  }));
281
- import { renderSlot as _renderSlot, withCtx as _withCtx, createSlots as _createSlots, createVNode as _createVNode, createCommentVNode as _createCommentVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock, createElementVNode as _createElementVNode, vShow as _vShow, normalizeClass as _normalizeClass, withDirectives as _withDirectives, normalizeStyle as _normalizeStyle, Teleport as _Teleport, createBlock as _createBlock } from "vue";
346
+ import { renderSlot as _renderSlot, withCtx as _withCtx, createSlots as _createSlots, createVNode as _createVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock, createCommentVNode as _createCommentVNode, createElementVNode as _createElementVNode, vShow as _vShow, normalizeClass as _normalizeClass, normalizeStyle as _normalizeStyle, withDirectives as _withDirectives, Teleport as _Teleport, createBlock as _createBlock } from "vue";
282
347
  const _hoisted_1 = {
283
348
  key: 0,
284
349
  class: "opencode-notification",
@@ -312,7 +377,12 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
312
377
  [
313
378
  _createVNode(
314
379
  $setup["Trigger"],
315
- null,
380
+ {
381
+ ref: "triggerRef",
382
+ onOffsetChange: $setup.handleBubbleOffsetChange,
383
+ onDragStart: $setup.handleDragStart,
384
+ onDragEnd: $setup.handleDragEnd
385
+ },
316
386
  _createSlots({
317
387
  _: 2
318
388
  /* DYNAMIC */
@@ -325,14 +395,14 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
325
395
  key: "0"
326
396
  } : void 0
327
397
  ]),
328
- 1024
329
- /* DYNAMIC_SLOTS */
398
+ 1536
399
+ /* NEED_PATCH, DYNAMIC_SLOTS */
330
400
  ),
331
- _createCommentVNode(' <SelectedBubbles v-if="bubbleVisible" /> '),
332
401
  _withDirectives(_createElementVNode(
333
402
  "div",
334
403
  {
335
- class: _normalizeClass(["opencode-chat", { open: $props.open, minimized: $setup.minimized }])
404
+ class: _normalizeClass(["opencode-chat", { open: $props.open, minimized: $setup.minimized, dragging: $setup.isDragging }]),
405
+ style: _normalizeStyle($setup.chatPositionStyle)
336
406
  },
337
407
  [
338
408
  _createVNode(
@@ -367,7 +437,6 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
367
437
  1024
368
438
  /* DYNAMIC_SLOTS */
369
439
  ),
370
- _createCommentVNode(" Notification "),
371
440
  $setup.notificationVisible && $setup.notificationMode === "widget" ? (_openBlock(), _createElementBlock(
372
441
  "div",
373
442
  _hoisted_1,
@@ -433,13 +502,12 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
433
502
  _createVNode($setup["SelectedNodes"])
434
503
  ])
435
504
  ],
436
- 2
437
- /* CLASS */
505
+ 6
506
+ /* CLASS, STYLE */
438
507
  ), [
439
508
  [_vShow, !$props.selectMode]
440
509
  ]),
441
510
  _createVNode($setup["SelectHint"]),
442
- _createCommentVNode(" Inspector Highlight "),
443
511
  _withDirectives(_createElementVNode(
444
512
  "div",
445
513
  {
@@ -454,7 +522,6 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
454
522
  ), [
455
523
  [_vShow, $setup.highlightVisible]
456
524
  ]),
457
- _createCommentVNode(" Inspector Tooltip "),
458
525
  _withDirectives(_createElementVNode(
459
526
  "div",
460
527
  {
@@ -484,7 +551,6 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
484
551
  ), [
485
552
  [_vShow, $setup.tooltipVisible]
486
553
  ]),
487
- _createCommentVNode(" Dialog "),
488
554
  $setup.dialogVisible ? (_openBlock(), _createElementBlock("div", _hoisted_5, [
489
555
  _createElementVNode("div", _hoisted_6, [
490
556
  _createElementVNode("div", _hoisted_7, [
@@ -508,7 +574,6 @@ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
508
574
  ])
509
575
  ])
510
576
  ])) : _createCommentVNode("v-if", true),
511
- _createCommentVNode(" Page-level Notification "),
512
577
  (_openBlock(), _createBlock(_Teleport, { to: "body" }, [
513
578
  $setup.notificationVisible && $setup.notificationMode === "page" ? (_openBlock(), _createElementBlock(
514
579
  "div",
@@ -1,3 +1,2 @@
1
- export type { OpenCodeWidgetPosition, OpenCodeWidgetTheme, OpenCodeWidgetSession, OpenCodeSelectedElement, OpenCodeRemoveSelectedPayload, OpenCodeWidgetSessionItem, OpenCodeSelectedElementItem, OpenCodeWidgetProps, OpenCodeWidgetEmits, } from "@vite-plugin-opencode-assistant/shared";
2
- export type OpenCodeWidgetPositionLocal = "bottom-right" | "bottom-left" | "top-right" | "top-left";
1
+ export type { OpenCodeWidgetTheme, OpenCodeWidgetSession, OpenCodeSelectedElement, OpenCodeRemoveSelectedPayload, OpenCodeWidgetSessionItem, OpenCodeSelectedElementItem, OpenCodeWidgetProps, OpenCodeWidgetEmits, } from "@vite-plugin-opencode-assistant/shared";
3
2
  export type OpenCodeWidgetThemeLocal = "light" | "dark" | "auto";