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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/es/index.d.ts +1 -1
  2. package/es/index.js +1 -1
  3. package/es/open-code-widget/composables/use-inspector.js +118 -79
  4. package/es/open-code-widget/composables/use-persist-state.d.ts +24 -0
  5. package/es/open-code-widget/composables/use-persist-state.js +59 -0
  6. package/es/open-code-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -1
  7. package/es/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +2 -2
  8. package/es/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.js +37 -21
  9. package/es/open-code-widget/src/components/Trigger.vue.d.ts +0 -2
  10. package/es/open-code-widget/src/components/Trigger.vue.js +10 -27
  11. package/es/open-code-widget/src/context.d.ts +3 -0
  12. package/es/open-code-widget/src/index-sfc.css +1 -1
  13. package/es/open-code-widget/src/index.vue.d.ts +10 -10
  14. package/es/open-code-widget/src/index.vue.js +107 -29
  15. package/lib/@vite-plugin-opencode-assistant/components.cjs.js +304 -140
  16. package/lib/@vite-plugin-opencode-assistant/components.es.js +305 -141
  17. package/lib/components.css +2 -2
  18. package/lib/index.d.ts +1 -1
  19. package/lib/index.js +1 -1
  20. package/lib/open-code-widget/composables/use-inspector.js +118 -79
  21. package/lib/open-code-widget/composables/use-persist-state.d.ts +24 -0
  22. package/lib/open-code-widget/composables/use-persist-state.js +78 -0
  23. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -1
  24. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +2 -2
  25. package/lib/open-code-widget/src/components/FloatingBubble/FloatingBubble.vue.js +37 -21
  26. package/lib/open-code-widget/src/components/Trigger.vue.d.ts +0 -2
  27. package/lib/open-code-widget/src/components/Trigger.vue.js +10 -27
  28. package/lib/open-code-widget/src/context.d.ts +3 -0
  29. package/lib/open-code-widget/src/index-sfc.css +1 -1
  30. package/lib/open-code-widget/src/index.vue.d.ts +10 -10
  31. package/lib/open-code-widget/src/index.vue.js +106 -28
  32. package/lib/web-types.json +1 -1
  33. package/package.json +2 -2
@@ -1,9 +1,9 @@
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)}}
2
2
  .opencode-iframe-container{flex:1;position:relative;overflow:hidden;display:flex;flex-direction:column;margin-top:-42px}.opencode-loading-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background:var(--oc-overlay-bg);display:none;flex-direction:column;align-items:center;justify-content:center;z-index:10;transition:opacity .3s ease}.opencode-loading-overlay.visible{display:flex}.opencode-loading-spinner{width:40px;height:40px;border:3px solid var(--oc-border-primary);border-top-color:var(--oc-primary);border-radius:50%;animation:spin .8s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.opencode-loading-text{margin-top:12px;font-size:14px;color:var(--oc-text-placeholder)}.opencode-error-overlay{position:absolute;top:0;left:0;right:0;bottom:0;z-index:15;margin-top:42px;display:none}.opencode-error-overlay.visible{display:flex}.opencode-empty-state-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background:var(--oc-bg-secondary);display:none;flex-direction:column;align-items:center;justify-content:center;z-index:5;transition:opacity .3s ease;margin-top:42px}.opencode-empty-state-overlay.visible{display:flex}.opencode-empty-state-icon{color:var(--oc-text-placeholder);margin-bottom:16px}.opencode-empty-state-text{color:var(--oc-text-primary);font-size:16px;font-weight:500;margin-bottom:24px}.opencode-empty-state-btn{padding:10px 24px;border-radius:8px;border:none;background:var(--oc-primary);color:#fff;font-size:14px;font-weight:500;cursor:pointer;transition:all .2s;box-shadow:var(--oc-shadow-primary)}.opencode-empty-state-btn:hover{background:var(--oc-primary-hover);transform:translateY(-1px);box-shadow:var(--oc-shadow-primary-hover)}.opencode-empty-state-btn:active{transform:translateY(0)}.opencode-iframe{width:100%;height:100%;border:none}
3
3
  .opencode-chat-header{position:relative;flex-shrink:0;display:flex;align-items:center;justify-content:space-between;padding:0 12px;height:40px;background:var(--oc-bg-secondary);border-bottom:1px solid var(--oc-border-primary);z-index:5}.opencode-chat-header-left{display:flex;align-items:center;gap:4px}.opencode-chat-header-title{font-size:14px;font-weight:600;color:var(--oc-text-primary);position:absolute;left:50%;transform:translate(-50%)}.opencode-chat-header-actions{display:flex;gap:4px}.opencode-header-btn{width:28px;height:28px;border-radius:6px;border:none;background:transparent;color:var(--oc-text-placeholder);cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .2s}.opencode-header-btn:hover{background:var(--oc-bg-tertiary);color:var(--oc-text-primary)}.opencode-header-btn.close:hover{background:var(--oc-danger);color:#fff}.opencode-header-btn.select-btn.active,.opencode-header-btn.session-toggle.active{background:var(--oc-primary);color:#fff}
4
4
  .opencode-select-mode-hint{position:fixed;top:20px;left:50%;transform:translate(-50%);padding:10px;background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;border-radius:12px;font-size:14px;font-weight:500;box-shadow:0 6px 20px rgba(239,68,68,.5),0 0 0 3px rgba(239,68,68,.3);z-index:9999999;display:none;align-items:center;gap:12px;border:1px solid rgba(255,255,255,.3)}.opencode-select-mode-hint.visible{display:flex;animation:slideDown .3s ease,pulseHint 2s ease-in-out infinite}.opencode-hint-shortcut{padding:4px 10px;background:rgba(255,255,255,.25);border-radius:6px;font-size:13px;font-weight:600;border:1px solid rgba(255,255,255,.4)}@keyframes pulseHint{0%,to{box-shadow:0 6px 20px rgba(239,68,68,.5),0 0 0 3px rgba(239,68,68,.3)}50%{box-shadow:0 6px 20px rgba(239,68,68,.6),0 0 0 6px rgba(239,68,68,.4)}}
5
5
  .opencode-right-toolbar{width:140px;background:var(--oc-bg-secondary);border-left:1px solid var(--oc-border-primary);display:flex;flex-direction:column;flex-shrink:0;transition:width .2s ease;overflow:hidden}.opencode-right-toolbar.collapsed{width:0;overflow:hidden}.opencode-right-toolbar.collapsed .opencode-selected-nodes-header,.opencode-right-toolbar.collapsed .opencode-selected-nodes,.opencode-right-toolbar.collapsed .opencode-clear-all-btn{display:none}.opencode-selected-nodes-header{padding:12px 8px 8px;border-bottom:1px solid var(--oc-border-primary)}.opencode-selected-nodes-title{font-size:14px;font-weight:600;color:var(--oc-text-primary);margin-bottom:4px}.opencode-selected-nodes-desc{font-size:11px;color:var(--oc-text-placeholder);line-height:1.4}.opencode-selected-nodes{flex:1;display:flex;flex-direction:column;padding:8px;gap:6px;overflow-y:auto;overflow-x:hidden}.opencode-selected-nodes:empty:before{content:"\6682\65e0\9009\4e2d\5143\7d20";color:var(--oc-text-placeholder);font-size:12px;text-align:center;padding:20px 10px}.opencode-selected-node{display:flex;align-items:center;gap:8px;padding:8px 10px;background:var(--oc-bg-main);border:1px solid var(--oc-border-primary);border-radius:6px;font-size:12px;transition:all .2s}.opencode-selected-node:hover{border-color:var(--oc-primary);box-shadow:var(--oc-shadow-primary)}.opencode-node-content{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.opencode-node-text{color:var(--oc-text-primary);font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.opencode-node-file{color:var(--oc-text-placeholder);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.opencode-node-remove{width:18px;height:18px;border-radius:4px;border:none;background:transparent;color:var(--oc-text-placeholder);cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:14px;transition:all .2s;flex-shrink:0}.opencode-node-remove:hover{background:var(--oc-danger);color:#fff}.opencode-clear-all-btn{width:calc(100% - 16px);margin:8px;padding:8px 12px;border-radius:6px;border:none;background:var(--oc-danger);color:#fff;font-size:12px;font-weight:500;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:4px;transition:all .2s}.opencode-clear-all-btn:hover{background:var(--oc-danger-hover);transform:scale(1.02)}
6
6
  .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}}
7
7
  .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}
8
- .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}
8
+ .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}
9
9
  /*$vite$:1*/
package/lib/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.27";
4
4
  declare function install(app: App<any>, options?: any): void;
5
5
  export { install, version, OpenCodeWidget };
6
6
  export default install;
package/lib/index.js CHANGED
@@ -34,7 +34,7 @@ __export(lib_exports, {
34
34
  });
35
35
  module.exports = __toCommonJS(lib_exports);
36
36
  var import_open_code_widget = __toESM(require("./open-code-widget"));
37
- const version = "1.0.26";
37
+ const version = "1.0.27";
38
38
  function install(app, options) {
39
39
  const components = [
40
40
  import_open_code_widget.default
@@ -234,35 +234,20 @@ function findFileInfo(element, inspector) {
234
234
  return fallbackFileInfo || { file: null, line: null, column: null };
235
235
  }
236
236
  function getPreciseElementAtPoint(x, y, boundary) {
237
- var _a, _b;
238
- const highlight = document.querySelector(".opencode-element-highlight");
239
- const tooltip = document.querySelector(".opencode-element-tooltip");
240
- const highlightDisplay = ((_a = highlight == null ? void 0 : highlight.getAttribute("style")) == null ? void 0 : _a.includes("display: block")) ? "block" : "none";
241
- const tooltipDisplay = ((_b = tooltip == null ? void 0 : tooltip.getAttribute("style")) == null ? void 0 : _b.includes("display: block")) ? "block" : "none";
242
- if (highlight) highlight.style.display = "none";
243
- if (tooltip) tooltip.style.display = "none";
244
- let element = null;
245
- try {
246
- const elements = document.elementsFromPoint(x, y);
247
- for (const el of elements) {
248
- if (el.closest("#vue-inspector-container")) continue;
249
- if (el.closest(".opencode-widget")) continue;
250
- if (el.hasAttribute("data-v-inspector-ignore")) continue;
251
- if (boundary) {
252
- if (boundary.contains(el) || el === boundary) {
253
- element = el;
254
- break;
255
- }
256
- } else {
257
- element = el;
258
- break;
237
+ const elements = document.elementsFromPoint(x, y);
238
+ for (const el of elements) {
239
+ if (el.closest("#vue-inspector-container")) continue;
240
+ if (el.closest(".opencode-widget")) continue;
241
+ if (el.hasAttribute("data-v-inspector-ignore")) continue;
242
+ if (boundary) {
243
+ if (boundary.contains(el) || el === boundary) {
244
+ return el;
259
245
  }
246
+ } else {
247
+ return el;
260
248
  }
261
- } finally {
262
- if (highlight) highlight.style.display = highlightDisplay;
263
- if (tooltip) tooltip.style.display = tooltipDisplay;
264
249
  }
265
- return element;
250
+ return null;
266
251
  }
267
252
  function useInspector(options) {
268
253
  const highlightVisible = (0, import_vue.ref)(false);
@@ -277,67 +262,99 @@ function useInspector(options) {
277
262
  const tooltipContent = (0, import_vue.ref)({ description: "", fileInfo: "" });
278
263
  const INSPECTOR_CHECK_INTERVAL = 500;
279
264
  let inspectorCheckTimer = null;
265
+ let currentHighlightElement = null;
266
+ let currentFileInfo = { file: null, line: null, column: null };
267
+ let currentPrimary = "#3b82f6";
268
+ let currentPrimaryBg = "rgba(59, 130, 246, 0.1)";
269
+ let currentDescription = "";
270
+ let currentFileInfoText = "";
280
271
  function handleMouseMoveCore(e) {
281
272
  var _a, _b;
282
273
  if (!options.selectMode.value) return;
283
274
  const inspector = window.__VUE_INSPECTOR__;
275
+ const highlight = document.querySelector(".opencode-element-highlight");
276
+ const tooltip = document.querySelector(".opencode-element-tooltip");
277
+ if (highlight) highlight.style.pointerEvents = "none";
278
+ if (tooltip) tooltip.style.pointerEvents = "none";
284
279
  let elementToHighlight = null;
280
+ let targetNode = null;
285
281
  let fileInfo = { file: null, line: null, column: null };
286
- if (inspector) {
287
- const { targetNode, params } = inspector.getTargetNode(e);
288
- if (targetNode) {
289
- const preciseElement = getPreciseElementAtPoint(e.clientX, e.clientY, targetNode);
290
- elementToHighlight = preciseElement || targetNode;
291
- if (params && params.file) {
292
- fileInfo = {
293
- file: params.file,
294
- line: (_a = params.line) != null ? _a : null,
295
- column: (_b = params.column) != null ? _b : null
296
- };
297
- } else if (elementToHighlight) {
298
- fileInfo = findFileInfo(elementToHighlight, inspector);
282
+ try {
283
+ if (inspector) {
284
+ const result = inspector.getTargetNode(e);
285
+ targetNode = result.targetNode;
286
+ const params = result.params;
287
+ if (targetNode) {
288
+ const preciseElement = getPreciseElementAtPoint(e.clientX, e.clientY, targetNode);
289
+ elementToHighlight = preciseElement || targetNode;
290
+ if (params && params.file) {
291
+ fileInfo = {
292
+ file: params.file,
293
+ line: (_a = params.line) != null ? _a : null,
294
+ column: (_b = params.column) != null ? _b : null
295
+ };
296
+ } else {
297
+ fileInfo = findFileInfo(targetNode, inspector);
298
+ }
299
299
  }
300
300
  }
301
- }
302
- if (!elementToHighlight) {
303
- elementToHighlight = getPreciseElementAtPoint(e.clientX, e.clientY, null);
304
- }
305
- if (elementToHighlight && !fileInfo.file) {
306
- fileInfo = getFileInfoFromVueInstance(elementToHighlight) || fileInfo;
301
+ if (!elementToHighlight) {
302
+ elementToHighlight = getPreciseElementAtPoint(e.clientX, e.clientY, null);
303
+ }
304
+ if (elementToHighlight && !fileInfo.file) {
305
+ fileInfo = getFileInfoFromVueInstance(elementToHighlight) || fileInfo;
306
+ }
307
+ } finally {
308
+ if (highlight) highlight.style.pointerEvents = "";
309
+ if (tooltip) tooltip.style.pointerEvents = "";
307
310
  }
308
311
  if (elementToHighlight) {
309
- const rect = elementToHighlight.getBoundingClientRect();
310
- const widget = document.querySelector(".opencode-widget");
311
- let primary = "#3b82f6";
312
- let primaryBg = "rgba(59, 130, 246, 0.1)";
313
- if (widget) {
314
- const style = getComputedStyle(widget);
315
- primary = style.getPropertyValue("--oc-primary").trim() || primary;
316
- primaryBg = style.getPropertyValue("--oc-primary-bg").trim() || primaryBg;
312
+ const elementChanged = currentHighlightElement !== elementToHighlight;
313
+ if (elementChanged) {
314
+ currentHighlightElement = elementToHighlight;
315
+ currentFileInfo = fileInfo;
316
+ const widget = document.querySelector(".opencode-widget");
317
+ if (widget) {
318
+ const style = getComputedStyle(widget);
319
+ currentPrimary = style.getPropertyValue("--oc-primary").trim() || currentPrimary;
320
+ currentPrimaryBg = style.getPropertyValue("--oc-primary-bg").trim() || currentPrimaryBg;
321
+ }
322
+ currentDescription = getElementDescription(elementToHighlight);
323
+ } else if (!currentFileInfo.file && fileInfo.file) {
324
+ currentFileInfo = fileInfo;
317
325
  }
318
- highlightVisible.value = true;
319
- highlightStyle.value = {
320
- top: `${rect.top}px`,
321
- left: `${rect.left}px`,
322
- width: `${rect.width}px`,
323
- height: `${rect.height}px`,
324
- border: `2px solid ${primary}`,
325
- background: primaryBg
326
- };
327
- const description = getElementDescription(elementToHighlight);
328
- const fileName = fileInfo.file ? fileInfo.file.split("/").pop() : "";
326
+ const fileName = currentFileInfo.file ? currentFileInfo.file.split("/").pop() : "";
329
327
  let lineInfo = "";
330
- if (fileInfo.line) {
331
- lineInfo = `:${fileInfo.line}`;
332
- if (fileInfo.column) {
333
- lineInfo += `:${fileInfo.column}`;
328
+ if (currentFileInfo.line) {
329
+ lineInfo = `:${currentFileInfo.line}`;
330
+ if (currentFileInfo.column) {
331
+ lineInfo += `:${currentFileInfo.column}`;
334
332
  }
335
333
  }
336
- tooltipContent.value = {
337
- description,
338
- fileInfo: fileName ? `${fileName}${lineInfo}` : ""
339
- };
340
- tooltipVisible.value = true;
334
+ const newFileInfoText = fileName ? `${fileName}${lineInfo}` : "";
335
+ const fileInfoChanged = currentFileInfoText !== newFileInfoText;
336
+ if (elementChanged || fileInfoChanged) {
337
+ currentFileInfoText = newFileInfoText;
338
+ tooltipContent.value = {
339
+ description: currentDescription,
340
+ fileInfo: currentFileInfoText
341
+ };
342
+ }
343
+ const rect = elementToHighlight.getBoundingClientRect();
344
+ const newTop = `${rect.top}px`;
345
+ const newLeft = `${rect.left}px`;
346
+ const newWidth = `${rect.width}px`;
347
+ const newHeight = `${rect.height}px`;
348
+ if (highlightStyle.value.top !== newTop || highlightStyle.value.left !== newLeft || highlightStyle.value.width !== newWidth || highlightStyle.value.height !== newHeight) {
349
+ highlightStyle.value = {
350
+ top: newTop,
351
+ left: newLeft,
352
+ width: newWidth,
353
+ height: newHeight,
354
+ border: `2px solid ${currentPrimary}`,
355
+ background: currentPrimaryBg
356
+ };
357
+ }
341
358
  const tooltipHeight = 50;
342
359
  const tooltipWidth = 200;
343
360
  let tooltipTop = rect.top - tooltipHeight - 8;
@@ -348,13 +365,31 @@ function useInspector(options) {
348
365
  if (tooltipLeft + tooltipWidth > window.innerWidth - 10) {
349
366
  tooltipLeft = window.innerWidth - tooltipWidth - 10;
350
367
  }
351
- tooltipStyle.value = {
352
- top: `${tooltipTop}px`,
353
- left: `${tooltipLeft}px`
354
- };
368
+ const newTooltipTop = `${tooltipTop}px`;
369
+ const newTooltipLeft = `${tooltipLeft}px`;
370
+ if (tooltipStyle.value.top !== newTooltipTop || tooltipStyle.value.left !== newTooltipLeft) {
371
+ tooltipStyle.value = {
372
+ top: newTooltipTop,
373
+ left: newTooltipLeft
374
+ };
375
+ }
376
+ if (!highlightVisible.value) {
377
+ highlightVisible.value = true;
378
+ }
379
+ if (!tooltipVisible.value) {
380
+ tooltipVisible.value = true;
381
+ }
355
382
  } else {
356
- highlightVisible.value = false;
357
- tooltipVisible.value = false;
383
+ currentHighlightElement = null;
384
+ currentDescription = "";
385
+ currentFileInfoText = "";
386
+ currentFileInfo = { file: null, line: null, column: null };
387
+ if (highlightVisible.value) {
388
+ highlightVisible.value = false;
389
+ }
390
+ if (tooltipVisible.value) {
391
+ tooltipVisible.value = false;
392
+ }
358
393
  }
359
394
  }
360
395
  const handleMouseMove = throttle(handleMouseMoveCore, 16);
@@ -426,6 +461,10 @@ function useInspector(options) {
426
461
  }
427
462
  document.removeEventListener("mousemove", handleMouseMove);
428
463
  document.removeEventListener("keydown", handleKeydown, true);
464
+ currentHighlightElement = null;
465
+ currentDescription = "";
466
+ currentFileInfoText = "";
467
+ currentFileInfo = { file: null, line: null, column: null };
429
468
  highlightVisible.value = false;
430
469
  tooltipVisible.value = false;
431
470
  }
@@ -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,78 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+ var use_persist_state_exports = {};
19
+ __export(use_persist_state_exports, {
20
+ usePersistState: () => usePersistState
21
+ });
22
+ module.exports = __toCommonJS(use_persist_state_exports);
23
+ var import_vue = require("vue");
24
+ const STORAGE_KEY = "opencode-widget-state";
25
+ function loadState() {
26
+ if (typeof window === "undefined") return null;
27
+ try {
28
+ const stored = localStorage.getItem(STORAGE_KEY);
29
+ if (stored) {
30
+ return JSON.parse(stored);
31
+ }
32
+ } catch (e) {
33
+ console.warn("[OpenCodeWidget] Failed to load persisted state:", e);
34
+ }
35
+ return null;
36
+ }
37
+ function saveState(state) {
38
+ if (typeof window === "undefined") return;
39
+ try {
40
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
41
+ } catch (e) {
42
+ console.warn("[OpenCodeWidget] Failed to save state:", e);
43
+ }
44
+ }
45
+ function usePersistState(options) {
46
+ const restoreState = () => {
47
+ const saved = loadState();
48
+ if (options.onRestore) {
49
+ options.onRestore(saved || {});
50
+ }
51
+ return saved;
52
+ };
53
+ const getCurrentState = () => ({
54
+ open: options.open.value,
55
+ minimized: options.minimized.value,
56
+ promptDockVisible: options.promptDockVisible.value,
57
+ bubbleOffset: options.bubbleOffset.value,
58
+ theme: options.theme.value,
59
+ sessionListCollapsed: options.sessionListCollapsed.value
60
+ });
61
+ const persistState = () => {
62
+ saveState(getCurrentState());
63
+ };
64
+ (0, import_vue.onMounted)(() => {
65
+ restoreState();
66
+ (0, import_vue.watch)(
67
+ [options.open, options.minimized, options.promptDockVisible, options.bubbleOffset, options.theme, options.sessionListCollapsed],
68
+ () => {
69
+ persistState();
70
+ },
71
+ { deep: true }
72
+ );
73
+ });
74
+ return {
75
+ restoreState,
76
+ persistState
77
+ };
78
+ }
@@ -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;
@@ -78,6 +78,27 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)(__spreadProp
78
78
  bottom: windowHeight.value - state.value.height - gapY.value,
79
79
  left: gapX.value
80
80
  }));
81
+ const closest = (arr, target) => {
82
+ return arr.reduce(
83
+ (pre, cur) => Math.abs(pre - target) < Math.abs(cur - target) ? pre : cur
84
+ );
85
+ };
86
+ const applyMagnetic = () => {
87
+ if (props.magnetic === "x") {
88
+ const nextX = closest(
89
+ [boundary.value.left, boundary.value.right],
90
+ state.value.x
91
+ );
92
+ state.value.x = nextX;
93
+ }
94
+ if (props.magnetic === "y") {
95
+ const nextY = closest(
96
+ [boundary.value.top, boundary.value.bottom],
97
+ state.value.y
98
+ );
99
+ state.value.y = nextY;
100
+ }
101
+ };
81
102
  const dragging = (0, import_vue2.ref)(false);
82
103
  const initialized = (0, import_vue2.ref)(false);
83
104
  const rootStyle = (0, import_vue2.computed)(() => {
@@ -104,12 +125,22 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)(__spreadProp
104
125
  if (x > maxX) x = maxX;
105
126
  if (y < gapY.value) y = gapY.value;
106
127
  if (y > maxY) y = maxY;
128
+ const oldX = state.value.x;
129
+ const oldY = state.value.y;
107
130
  state.value = {
108
131
  x,
109
132
  y,
110
133
  width: rect.width,
111
134
  height: rect.height
112
135
  };
136
+ if (!dragging.value) {
137
+ applyMagnetic();
138
+ if (state.value.x !== oldX || state.value.y !== oldY) {
139
+ const offset2 = { x: state.value.x, y: state.value.y };
140
+ emit("update:offset", offset2);
141
+ emit("offset-change", offset2);
142
+ }
143
+ }
113
144
  };
114
145
  const touch = {
115
146
  startX: (0, import_vue2.ref)(0),
@@ -148,6 +179,7 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)(__spreadProp
148
179
  dragging.value = true;
149
180
  prevX = state.value.x;
150
181
  prevY = state.value.y;
182
+ document.body.classList.add("floating-bubble-dragging");
151
183
  if (!("touches" in e)) {
152
184
  window.addEventListener("mousemove", onTouchMove, { passive: false });
153
185
  window.addEventListener("mouseup", onTouchEnd);
@@ -180,32 +212,15 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)(__spreadProp
180
212
  emit("update:offset", offset);
181
213
  }
182
214
  };
183
- const closest = (arr, target) => {
184
- return arr.reduce(
185
- (pre, cur) => Math.abs(pre - target) < Math.abs(cur - target) ? pre : cur
186
- );
187
- };
188
215
  const onTouchEnd = (e) => {
189
216
  dragging.value = false;
217
+ document.body.classList.remove("floating-bubble-dragging");
190
218
  if (e && !("touches" in e) && e.type === "mouseup") {
191
219
  window.removeEventListener("mousemove", onTouchMove);
192
220
  window.removeEventListener("mouseup", onTouchEnd);
193
221
  }
194
222
  requestAnimationFrame(() => {
195
- if (props.magnetic === "x") {
196
- const nextX = closest(
197
- [boundary.value.left, boundary.value.right],
198
- state.value.x
199
- );
200
- state.value.x = nextX;
201
- }
202
- if (props.magnetic === "y") {
203
- const nextY = closest(
204
- [boundary.value.top, boundary.value.bottom],
205
- state.value.y
206
- );
207
- state.value.y = nextY;
208
- }
223
+ applyMagnetic();
209
224
  if (!touch.isTap.value) {
210
225
  emit("drag-end");
211
226
  const offset = { x: state.value.x, y: state.value.y };
@@ -244,6 +259,7 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)(__spreadProp
244
259
  }
245
260
  });
246
261
  (0, import_vue2.onUnmounted)(() => {
262
+ document.body.classList.remove("floating-bubble-dragging");
247
263
  if (typeof window !== "undefined") {
248
264
  window.removeEventListener("resize", handleResize);
249
265
  window.removeEventListener("mousemove", onTouchMove);
@@ -261,7 +277,7 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)(__spreadProp
261
277
  __expose({
262
278
  offset: (0, import_vue2.computed)(() => ({ x: state.value.x, y: state.value.y }))
263
279
  });
264
- const __returned__ = { props, emit, rootRef, state, isObject, gapX, gapY, windowWidth, windowHeight, boundary, dragging, initialized, rootStyle, updateState, touch, get prevX() {
280
+ const __returned__ = { props, emit, rootRef, state, isObject, gapX, gapY, windowWidth, windowHeight, boundary, closest, applyMagnetic, dragging, initialized, rootStyle, updateState, touch, get prevX() {
265
281
  return prevX;
266
282
  }, set prevX(v) {
267
283
  prevX = v;
@@ -269,7 +285,7 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)(__spreadProp
269
285
  return prevY;
270
286
  }, set prevY(v) {
271
287
  prevY = v;
272
- }, onTouchStart, onTouchMove, closest, onTouchEnd, onClick, handleResize };
288
+ }, onTouchStart, onTouchMove, onTouchEnd, onClick, handleResize };
273
289
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
274
290
  return __returned__;
275
291
  }
@@ -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>;
@@ -36,10 +36,9 @@ var import_vue2 = require("vue");
36
36
  var import_context = require("../context");
37
37
  var import_FloatingBubble_vue = __toESM(require("./FloatingBubble/FloatingBubble.vue.js"));
38
38
  var import_vue3 = require("vue");
39
- const STORAGE_KEY = "opencode-bubble-offset";
40
39
  const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
41
40
  __name: "Trigger",
42
- emits: ["offset-change", "drag-start", "drag-end"],
41
+ emits: ["drag-start", "drag-end"],
43
42
  setup(__props, { expose: __expose, emit: __emit }) {
44
43
  const {
45
44
  buttonActive: active,
@@ -47,39 +46,23 @@ const __vue_sfc__ = /* @__PURE__ */ (0, import_vue.defineComponent)({
47
46
  hotkeyLabel,
48
47
  thinking,
49
48
  resolvedTheme,
50
- handleToggle
49
+ handleToggle,
50
+ bubbleOffset,
51
+ handleBubbleOffsetChange
51
52
  } = (0, import_context.useOpenCodeWidgetContext)();
52
- const loadOffset = () => {
53
- try {
54
- const saved = localStorage.getItem(STORAGE_KEY);
55
- if (saved) {
56
- const parsed = JSON.parse(saved);
57
- if (parsed && (parsed.x !== 0 || parsed.y !== 0)) {
58
- return parsed;
59
- }
60
- }
61
- } catch (e) {
62
- }
63
- return void 0;
64
- };
65
- const offset = (0, import_vue2.ref)(loadOffset());
53
+ const offset = (0, import_vue2.ref)(bubbleOffset.value);
66
54
  const emit = __emit;
67
- const saveOffset = (value) => {
68
- try {
69
- localStorage.setItem(STORAGE_KEY, JSON.stringify(value));
70
- } catch (e) {
71
- }
72
- };
73
55
  const handleOffsetChange = (value) => {
74
56
  offset.value = value;
75
- saveOffset(value);
76
- emit("offset-change", value);
57
+ handleBubbleOffsetChange(value);
77
58
  };
78
- (0, import_vue2.watch)(offset, handleOffsetChange, { immediate: true });
59
+ (0, import_vue2.watch)(bubbleOffset, (newOffset) => {
60
+ offset.value = newOffset;
61
+ });
79
62
  __expose({
80
63
  offset
81
64
  });
82
- const __returned__ = { active, open, hotkeyLabel, thinking, resolvedTheme, handleToggle, STORAGE_KEY, loadOffset, offset, emit, saveOffset, handleOffsetChange, FloatingBubble: import_FloatingBubble_vue.default };
65
+ const __returned__ = { active, open, hotkeyLabel, thinking, resolvedTheme, handleToggle, bubbleOffset, handleBubbleOffsetChange, offset, emit, handleOffsetChange, FloatingBubble: import_FloatingBubble_vue.default };
83
66
  Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
84
67
  return __returned__;
85
68
  }