@aipanel/ui 1.2.0-beta.0

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 (153) hide show
  1. package/es/AI-panel-widget/composables/use-inspector.d.ts +52 -0
  2. package/es/AI-panel-widget/composables/use-inspector.mjs +437 -0
  3. package/es/AI-panel-widget/composables/use-persist-state.d.ts +32 -0
  4. package/es/AI-panel-widget/composables/use-persist-state.mjs +83 -0
  5. package/es/AI-panel-widget/composables/use-selection.d.ts +19 -0
  6. package/es/AI-panel-widget/composables/use-selection.mjs +112 -0
  7. package/es/AI-panel-widget/composables/use-session.d.ts +16 -0
  8. package/es/AI-panel-widget/composables/use-session.mjs +47 -0
  9. package/es/AI-panel-widget/composables/use-split.d.ts +30 -0
  10. package/es/AI-panel-widget/composables/use-split.mjs +133 -0
  11. package/es/AI-panel-widget/composables/use-widget.d.ts +27 -0
  12. package/es/AI-panel-widget/composables/use-widget.mjs +78 -0
  13. package/es/AI-panel-widget/index.d.ts +5 -0
  14. package/es/AI-panel-widget/index.mjs +9 -0
  15. package/es/AI-panel-widget/src/assets/logo.svg +13 -0
  16. package/es/AI-panel-widget/src/components/AIPanelLogo-sfc.css +1 -0
  17. package/es/AI-panel-widget/src/components/AIPanelLogo.vue.d.ts +8 -0
  18. package/es/AI-panel-widget/src/components/AIPanelLogo.vue.mjs +40 -0
  19. package/es/AI-panel-widget/src/components/ChatPanel-sfc.css +1 -0
  20. package/es/AI-panel-widget/src/components/ChatPanel.vue.d.ts +179 -0
  21. package/es/AI-panel-widget/src/components/ChatPanel.vue.mjs +308 -0
  22. package/es/AI-panel-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -0
  23. package/es/AI-panel-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +44 -0
  24. package/es/AI-panel-widget/src/components/FloatingBubble/FloatingBubble.vue.mjs +311 -0
  25. package/es/AI-panel-widget/src/components/FloatingBubble/index.d.ts +3 -0
  26. package/es/AI-panel-widget/src/components/FloatingBubble/index.mjs +5 -0
  27. package/es/AI-panel-widget/src/components/FloatingBubble/types.d.ts +24 -0
  28. package/es/AI-panel-widget/src/components/FloatingBubble/types.mjs +0 -0
  29. package/es/AI-panel-widget/src/components/Frame-sfc.css +1 -0
  30. package/es/AI-panel-widget/src/components/Frame.vue.d.ts +22 -0
  31. package/es/AI-panel-widget/src/components/Frame.vue.mjs +143 -0
  32. package/es/AI-panel-widget/src/components/Header-sfc.css +1 -0
  33. package/es/AI-panel-widget/src/components/Header.vue.d.ts +27 -0
  34. package/es/AI-panel-widget/src/components/Header.vue.mjs +683 -0
  35. package/es/AI-panel-widget/src/components/ResizeHandle-sfc.css +1 -0
  36. package/es/AI-panel-widget/src/components/ResizeHandle.vue.d.ts +22 -0
  37. package/es/AI-panel-widget/src/components/ResizeHandle.vue.mjs +79 -0
  38. package/es/AI-panel-widget/src/components/SelectHint-sfc.css +1 -0
  39. package/es/AI-panel-widget/src/components/SelectHint.vue.d.ts +3 -0
  40. package/es/AI-panel-widget/src/components/SelectHint.vue.mjs +40 -0
  41. package/es/AI-panel-widget/src/components/SelectedBubbles-sfc.css +1 -0
  42. package/es/AI-panel-widget/src/components/SelectedBubbles.vue.d.ts +3 -0
  43. package/es/AI-panel-widget/src/components/SelectedBubbles.vue.mjs +84 -0
  44. package/es/AI-panel-widget/src/components/SelectedNodes-sfc.css +1 -0
  45. package/es/AI-panel-widget/src/components/SelectedNodes.vue.d.ts +3 -0
  46. package/es/AI-panel-widget/src/components/SelectedNodes.vue.mjs +103 -0
  47. package/es/AI-panel-widget/src/components/SessionList-sfc.css +1 -0
  48. package/es/AI-panel-widget/src/components/SessionList.vue.d.ts +13 -0
  49. package/es/AI-panel-widget/src/components/SessionList.vue.mjs +222 -0
  50. package/es/AI-panel-widget/src/components/SplitTrigger-sfc.css +1 -0
  51. package/es/AI-panel-widget/src/components/SplitTrigger.vue.d.ts +18 -0
  52. package/es/AI-panel-widget/src/components/SplitTrigger.vue.mjs +112 -0
  53. package/es/AI-panel-widget/src/components/Trigger-sfc.css +1 -0
  54. package/es/AI-panel-widget/src/components/Trigger.vue.d.ts +28 -0
  55. package/es/AI-panel-widget/src/components/Trigger.vue.mjs +74 -0
  56. package/es/AI-panel-widget/src/context.d.ts +67 -0
  57. package/es/AI-panel-widget/src/context.mjs +16 -0
  58. package/es/AI-panel-widget/src/index-sfc.css +1 -0
  59. package/es/AI-panel-widget/src/index.vue.d.ts +69 -0
  60. package/es/AI-panel-widget/src/index.vue.mjs +782 -0
  61. package/es/AI-panel-widget/src/types.d.ts +2 -0
  62. package/es/AI-panel-widget/src/types.mjs +0 -0
  63. package/es/AI-panel-widget/style/index-pure.d.ts +0 -0
  64. package/es/AI-panel-widget/style/index-pure.mjs +0 -0
  65. package/es/AI-panel-widget/style/index.d.ts +0 -0
  66. package/es/AI-panel-widget/style/index.mjs +0 -0
  67. package/es/AI-panel-widget/style/less-pure.d.ts +0 -0
  68. package/es/AI-panel-widget/style/less-pure.mjs +0 -0
  69. package/es/AI-panel-widget/style/less.d.ts +0 -0
  70. package/es/AI-panel-widget/style/less.mjs +0 -0
  71. package/es/env.d.ts +15 -0
  72. package/es/index.d.ts +7 -0
  73. package/es/index.mjs +22 -0
  74. package/es/setup.d.ts +1 -0
  75. package/es/setup.mjs +4 -0
  76. package/lib/AI-panel-widget/composables/use-inspector.cjs +466 -0
  77. package/lib/AI-panel-widget/composables/use-inspector.d.ts +52 -0
  78. package/lib/AI-panel-widget/composables/use-persist-state.cjs +102 -0
  79. package/lib/AI-panel-widget/composables/use-persist-state.d.ts +32 -0
  80. package/lib/AI-panel-widget/composables/use-selection.cjs +131 -0
  81. package/lib/AI-panel-widget/composables/use-selection.d.ts +19 -0
  82. package/lib/AI-panel-widget/composables/use-session.cjs +66 -0
  83. package/lib/AI-panel-widget/composables/use-session.d.ts +16 -0
  84. package/lib/AI-panel-widget/composables/use-split.cjs +152 -0
  85. package/lib/AI-panel-widget/composables/use-split.d.ts +30 -0
  86. package/lib/AI-panel-widget/composables/use-widget.cjs +97 -0
  87. package/lib/AI-panel-widget/composables/use-widget.d.ts +27 -0
  88. package/lib/AI-panel-widget/index.cjs +39 -0
  89. package/lib/AI-panel-widget/index.d.ts +5 -0
  90. package/lib/AI-panel-widget/src/assets/logo.svg +13 -0
  91. package/lib/AI-panel-widget/src/components/AIPanelLogo-sfc.css +1 -0
  92. package/lib/AI-panel-widget/src/components/AIPanelLogo.vue.cjs +69 -0
  93. package/lib/AI-panel-widget/src/components/AIPanelLogo.vue.d.ts +8 -0
  94. package/lib/AI-panel-widget/src/components/ChatPanel-sfc.css +1 -0
  95. package/lib/AI-panel-widget/src/components/ChatPanel.vue.cjs +337 -0
  96. package/lib/AI-panel-widget/src/components/ChatPanel.vue.d.ts +179 -0
  97. package/lib/AI-panel-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -0
  98. package/lib/AI-panel-widget/src/components/FloatingBubble/FloatingBubble.vue.cjs +330 -0
  99. package/lib/AI-panel-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +44 -0
  100. package/lib/AI-panel-widget/src/components/FloatingBubble/index.cjs +35 -0
  101. package/lib/AI-panel-widget/src/components/FloatingBubble/index.d.ts +3 -0
  102. package/lib/AI-panel-widget/src/components/FloatingBubble/types.cjs +15 -0
  103. package/lib/AI-panel-widget/src/components/FloatingBubble/types.d.ts +24 -0
  104. package/lib/AI-panel-widget/src/components/Frame-sfc.css +1 -0
  105. package/lib/AI-panel-widget/src/components/Frame.vue.cjs +162 -0
  106. package/lib/AI-panel-widget/src/components/Frame.vue.d.ts +22 -0
  107. package/lib/AI-panel-widget/src/components/Header-sfc.css +1 -0
  108. package/lib/AI-panel-widget/src/components/Header.vue.cjs +702 -0
  109. package/lib/AI-panel-widget/src/components/Header.vue.d.ts +27 -0
  110. package/lib/AI-panel-widget/src/components/ResizeHandle-sfc.css +1 -0
  111. package/lib/AI-panel-widget/src/components/ResizeHandle.vue.cjs +98 -0
  112. package/lib/AI-panel-widget/src/components/ResizeHandle.vue.d.ts +22 -0
  113. package/lib/AI-panel-widget/src/components/SelectHint-sfc.css +1 -0
  114. package/lib/AI-panel-widget/src/components/SelectHint.vue.cjs +59 -0
  115. package/lib/AI-panel-widget/src/components/SelectHint.vue.d.ts +3 -0
  116. package/lib/AI-panel-widget/src/components/SelectedBubbles-sfc.css +1 -0
  117. package/lib/AI-panel-widget/src/components/SelectedBubbles.vue.cjs +103 -0
  118. package/lib/AI-panel-widget/src/components/SelectedBubbles.vue.d.ts +3 -0
  119. package/lib/AI-panel-widget/src/components/SelectedNodes-sfc.css +1 -0
  120. package/lib/AI-panel-widget/src/components/SelectedNodes.vue.cjs +122 -0
  121. package/lib/AI-panel-widget/src/components/SelectedNodes.vue.d.ts +3 -0
  122. package/lib/AI-panel-widget/src/components/SessionList-sfc.css +1 -0
  123. package/lib/AI-panel-widget/src/components/SessionList.vue.cjs +241 -0
  124. package/lib/AI-panel-widget/src/components/SessionList.vue.d.ts +13 -0
  125. package/lib/AI-panel-widget/src/components/SplitTrigger-sfc.css +1 -0
  126. package/lib/AI-panel-widget/src/components/SplitTrigger.vue.cjs +131 -0
  127. package/lib/AI-panel-widget/src/components/SplitTrigger.vue.d.ts +18 -0
  128. package/lib/AI-panel-widget/src/components/Trigger-sfc.css +1 -0
  129. package/lib/AI-panel-widget/src/components/Trigger.vue.cjs +103 -0
  130. package/lib/AI-panel-widget/src/components/Trigger.vue.d.ts +28 -0
  131. package/lib/AI-panel-widget/src/context.cjs +35 -0
  132. package/lib/AI-panel-widget/src/context.d.ts +67 -0
  133. package/lib/AI-panel-widget/src/index-sfc.css +1 -0
  134. package/lib/AI-panel-widget/src/index.vue.cjs +811 -0
  135. package/lib/AI-panel-widget/src/index.vue.d.ts +69 -0
  136. package/lib/AI-panel-widget/src/types.cjs +15 -0
  137. package/lib/AI-panel-widget/src/types.d.ts +2 -0
  138. package/lib/AI-panel-widget/style/index-pure.cjs +0 -0
  139. package/lib/AI-panel-widget/style/index-pure.d.ts +0 -0
  140. package/lib/AI-panel-widget/style/index.cjs +0 -0
  141. package/lib/AI-panel-widget/style/index.d.ts +0 -0
  142. package/lib/AI-panel-widget/style/less-pure.cjs +0 -0
  143. package/lib/AI-panel-widget/style/less-pure.d.ts +0 -0
  144. package/lib/AI-panel-widget/style/less.cjs +0 -0
  145. package/lib/AI-panel-widget/style/less.d.ts +0 -0
  146. package/lib/env.d.ts +15 -0
  147. package/lib/index.cjs +42 -0
  148. package/lib/index.css +0 -0
  149. package/lib/index.d.ts +7 -0
  150. package/lib/index.less +0 -0
  151. package/lib/setup.cjs +23 -0
  152. package/lib/setup.d.ts +1 -0
  153. package/package.json +42 -0
@@ -0,0 +1,782 @@
1
+ import "./index-sfc.css";
2
+ import { useCssVars as _useCssVars, defineComponent as _defineComponent } from "vue";
3
+ import { useSlots, toRef, ref, watch, computed, nextTick, onMounted, onUnmounted } from "vue";
4
+ import ChatPanel from "./components/ChatPanel.vue.mjs";
5
+ import SelectHint from "./components/SelectHint.vue.mjs";
6
+ import Trigger from "./components/Trigger.vue.mjs";
7
+ import { useSelection } from "../composables/use-selection.mjs";
8
+ import { useSession } from "../composables/use-session.mjs";
9
+ import { useWidget } from "../composables/use-widget.mjs";
10
+ import { useInspector } from "../composables/use-inspector.mjs";
11
+ import { usePersistState } from "../composables/use-persist-state.mjs";
12
+ import { useSplitMode } from "../composables/use-split.mjs";
13
+ import { provideAIPanelWidgetContext } from "./context.mjs";
14
+ import { WIDGET_MSG } from "@aipanel/core";
15
+ const __vue_sfc__ = /* @__PURE__ */ _defineComponent({
16
+ ...{
17
+ name: "AIPanelWidget"
18
+ },
19
+ __name: "index",
20
+ props: {
21
+ open: { type: Boolean, required: false, default: false },
22
+ theme: { type: String, required: false, default: "auto" },
23
+ title: { type: String, required: false, default: "AI \u52A9\u624B" },
24
+ hotkeyLabel: { type: String, required: false, default: "Ctrl+K" },
25
+ selectShortcutLabel: { type: String, required: false, default: "\u6309 ESC \u6216 Ctrl+P \u9000\u51FA" },
26
+ selectMode: { type: Boolean, required: false, default: false },
27
+ sessionListCollapsed: { type: Boolean, required: false, default: true },
28
+ sessionKey: { type: String, required: false, default: "id" },
29
+ frameLoading: { type: Boolean, required: false, default: false },
30
+ loadingSessionList: { type: Boolean, required: false },
31
+ showSessionListSkeleton: { type: Boolean, required: false, default: false },
32
+ showEmptyState: { type: Boolean, required: false, default: false },
33
+ showError: { type: Boolean, required: false, default: false },
34
+ emptyStateText: { type: String, required: false, default: "\u5F53\u524D\u9879\u76EE\u6682\u65E0\u4F1A\u8BDD" },
35
+ emptyStateActionText: { type: String, required: false, default: "\u7ACB\u5373\u521B\u5EFA" },
36
+ iframeSrc: { type: String, required: false, default: "" },
37
+ sessions: { type: Array, required: false, default: () => [] },
38
+ currentSessionId: { type: [String, null], required: false, default: null },
39
+ selectedElements: { type: Array, required: false, default: () => [] },
40
+ showClearAll: { type: Boolean, required: false, default: true },
41
+ selectEnabled: { type: Boolean, required: false, default: true },
42
+ thinking: { type: Boolean, required: false, default: false },
43
+ sessionStates: { type: Object, required: false },
44
+ displayMode: { type: String, required: false, default: "bubble" },
45
+ splitMode: { type: Object, required: false, default: void 0 },
46
+ splitPanelWidth: { type: Number, required: false, default: 500 },
47
+ hideBubble: { type: Boolean, required: false, default: false },
48
+ reviewPanelEnabled: { type: Boolean, required: false, default: false }
49
+ },
50
+ emits: ["update:open", "update:selectMode", "update:sessionListCollapsed", "update:currentSessionId", "update:selectedElements", "update:theme", "update:thinking", "update:splitPanelWidth", "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", "split-panel-width-change"],
51
+ setup(__props, { expose: __expose, emit: __emit }) {
52
+ _useCssVars((_ctx) => ({
53
+ "-chatAnimationOrigin.x": chatAnimationOrigin.value.x,
54
+ "-chatAnimationOrigin.y": chatAnimationOrigin.value.y
55
+ }));
56
+ const props = __props;
57
+ const emit = __emit;
58
+ const slots = useSlots();
59
+ const notificationMessage = ref("");
60
+ const notificationVisible = ref(false);
61
+ const notificationMode = ref("widget");
62
+ let notificationTimer = null;
63
+ const showNotification = (message, options) => {
64
+ const { duration = 3e3, mode = "widget" } = options || {};
65
+ notificationMessage.value = message;
66
+ notificationVisible.value = true;
67
+ notificationMode.value = mode;
68
+ if (notificationTimer) clearTimeout(notificationTimer);
69
+ notificationTimer = setTimeout(() => {
70
+ notificationVisible.value = false;
71
+ }, duration);
72
+ };
73
+ const dialogVisible = ref(false);
74
+ const dialogMessage = ref("");
75
+ let dialogResolve = null;
76
+ const showConfirmDialog = (message) => {
77
+ dialogMessage.value = message;
78
+ dialogVisible.value = true;
79
+ return new Promise((resolve) => {
80
+ dialogResolve = resolve;
81
+ });
82
+ };
83
+ const handleDialogConfirm = () => {
84
+ dialogVisible.value = false;
85
+ if (dialogResolve) dialogResolve(true);
86
+ };
87
+ const handleDialogCancel = () => {
88
+ dialogVisible.value = false;
89
+ if (dialogResolve) dialogResolve(false);
90
+ };
91
+ const frameRef = ref(null);
92
+ const triggerRef = ref(null);
93
+ const sendMessageToIframe = (type, data) => {
94
+ frameRef.value?.sendMessageToIframe(type, data);
95
+ };
96
+ const localSessionListCollapsed = ref(props.sessionListCollapsed);
97
+ const localDisplayMode = ref(props.displayMode);
98
+ const localSplitPosition = ref(
99
+ props.splitMode?.position ?? "right"
100
+ );
101
+ const minimized = ref(false);
102
+ const promptDockVisible = ref(true);
103
+ const reviewPanelVisible = ref(false);
104
+ const isRestoring = ref(true);
105
+ const iframeLoaded = ref(false);
106
+ const iframeReady = ref(false);
107
+ const splitPanelWidth = ref(props.splitPanelWidth);
108
+ const syncStateToIframe = () => {
109
+ if (!iframeLoaded.value || !iframeReady.value) return;
110
+ sendMessageToIframe(WIDGET_MSG.PROMPT_DOCK_VISIBILITY, { visible: promptDockVisible.value });
111
+ sendMessageToIframe(WIDGET_MSG.MINIMIZE_STATE, { minimized: minimized.value });
112
+ if (props.reviewPanelEnabled) {
113
+ sendMessageToIframe(WIDGET_MSG.REVIEW_PANEL_TOGGLE, { visible: reviewPanelVisible.value });
114
+ }
115
+ };
116
+ const handleFrameLoaded = () => {
117
+ emit("frame-loaded");
118
+ iframeLoaded.value = true;
119
+ };
120
+ watch(
121
+ () => props.sessionListCollapsed,
122
+ (val) => {
123
+ localSessionListCollapsed.value = val;
124
+ }
125
+ );
126
+ watch(
127
+ () => props.splitPanelWidth,
128
+ (val) => {
129
+ splitPanelWidth.value = val;
130
+ }
131
+ );
132
+ watch(
133
+ () => props.displayMode,
134
+ (val) => {
135
+ localDisplayMode.value = val;
136
+ }
137
+ );
138
+ const handleToggleDisplayMode = () => {
139
+ if (localDisplayMode.value === "extension" || localDisplayMode.value === "extension-selector") return;
140
+ const modes = ["bubble", "split", "auto"];
141
+ const currentIndex = modes.indexOf(localDisplayMode.value);
142
+ const nextIndex = (currentIndex + 1) % modes.length;
143
+ localDisplayMode.value = modes[nextIndex];
144
+ };
145
+ const {
146
+ buttonActive,
147
+ containerClasses,
148
+ iframeSource,
149
+ sessionListTitle,
150
+ resolvedTheme,
151
+ handleClose,
152
+ handleEmptyAction,
153
+ handleToggle,
154
+ handleToggleSessionList,
155
+ handleToggleTheme
156
+ } = useWidget({
157
+ theme: toRef(props, "theme"),
158
+ open: toRef(props, "open"),
159
+ selectMode: toRef(props, "selectMode"),
160
+ iframeSrc: toRef(props, "iframeSrc"),
161
+ sessionListCollapsed: localSessionListCollapsed,
162
+ onToggle: (nextOpen) => {
163
+ emit("update:open", nextOpen);
164
+ emit("toggle", nextOpen);
165
+ },
166
+ onToggleSelectMode: (mode) => {
167
+ emit("update:selectMode", mode);
168
+ emit("toggle-select-mode", mode);
169
+ },
170
+ onClose: () => {
171
+ emit("update:open", false);
172
+ emit("close");
173
+ },
174
+ onToggleSessionList: (collapsed) => {
175
+ localSessionListCollapsed.value = collapsed;
176
+ emit("update:sessionListCollapsed", collapsed);
177
+ emit("toggle-session-list", collapsed);
178
+ },
179
+ onEmptyAction: () => {
180
+ emit("empty-action");
181
+ },
182
+ onToggleTheme: (newTheme) => {
183
+ emit("update:theme", newTheme);
184
+ emit("toggle-theme", newTheme);
185
+ }
186
+ });
187
+ const { sessionItems, handleCreateSession, handleDeleteSession, handleSelectSession } = useSession({
188
+ sessions: toRef(props, "sessions"),
189
+ currentSessionId: toRef(props, "currentSessionId"),
190
+ onCreateSession: () => emit("create-session"),
191
+ onSelectSession: (session) => {
192
+ emit("update:currentSessionId", session.id);
193
+ emit("select-session", session);
194
+ },
195
+ onDeleteSession: (session) => emit("delete-session", session),
196
+ showConfirmDialog
197
+ });
198
+ const {
199
+ bubbleVisible,
200
+ hasSelectedElements,
201
+ selectedElementItems,
202
+ handleClearSelectedNodes,
203
+ handleClickSelectedNode,
204
+ handleRemoveSelectedNode,
205
+ handleToggleSelectMode
206
+ } = useSelection({
207
+ selectMode: toRef(props, "selectMode"),
208
+ selectedElements: toRef(props, "selectedElements"),
209
+ onToggleSelectMode: (mode) => {
210
+ emit("update:selectMode", mode);
211
+ emit("toggle-select-mode", mode);
212
+ },
213
+ onRemoveSelectedNode: (payload) => {
214
+ emit("remove-selected-node", payload);
215
+ const newElements = [...props.selectedElements];
216
+ newElements.splice(payload.index, 1);
217
+ emit("update:selectedElements", newElements);
218
+ },
219
+ onClearSelectedNodes: () => {
220
+ emit("clear-selected-nodes");
221
+ emit("update:selectedElements", []);
222
+ },
223
+ showConfirmDialog
224
+ });
225
+ const { highlightVisible, highlightStyle, tooltipVisible, tooltipStyle, tooltipContent } = useInspector({
226
+ selectMode: toRef(props, "selectMode"),
227
+ onAddSelectedNode: (element) => {
228
+ emit("click-selected-node", element);
229
+ },
230
+ onExitSelectMode: () => {
231
+ emit("update:selectMode", false);
232
+ emit("toggle-select-mode", false);
233
+ }
234
+ });
235
+ const bubbleOffset = ref(void 0);
236
+ const {
237
+ effectiveMode,
238
+ isSplitMode,
239
+ isExtensionMode,
240
+ panelWidth,
241
+ splitConfig,
242
+ splitPosition,
243
+ handleResize,
244
+ handleToggle: handleSplitToggle,
245
+ handleTogglePosition
246
+ } = useSplitMode({
247
+ displayMode: localDisplayMode,
248
+ splitMode: toRef(props, "splitMode"),
249
+ open: toRef(props, "open"),
250
+ splitPosition: localSplitPosition,
251
+ onOpenChange: (nextOpen) => {
252
+ emit("update:open", nextOpen);
253
+ emit("toggle", nextOpen);
254
+ },
255
+ onWidthChange: (width) => {
256
+ splitPanelWidth.value = width;
257
+ emit("update:splitPanelWidth", width);
258
+ emit("split-panel-width-change", width);
259
+ },
260
+ onPositionChange: (position) => {
261
+ localSplitPosition.value = position;
262
+ }
263
+ });
264
+ usePersistState({
265
+ open: toRef(props, "open"),
266
+ minimized,
267
+ promptDockVisible,
268
+ reviewPanelVisible,
269
+ bubbleOffset,
270
+ theme: toRef(props, "theme"),
271
+ sessionListCollapsed: localSessionListCollapsed,
272
+ splitPanelWidth,
273
+ displayMode: localDisplayMode,
274
+ splitPosition: localSplitPosition,
275
+ onRestore: (state) => {
276
+ if (state.open !== void 0 && state.open !== props.open) {
277
+ emit("update:open", state.open);
278
+ emit("toggle", state.open);
279
+ }
280
+ if (state.minimized !== void 0) {
281
+ minimized.value = state.minimized;
282
+ }
283
+ if (state.bubbleOffset !== void 0) {
284
+ const bubbleSize = 44;
285
+ const margin = 10;
286
+ const maxX = window.innerWidth - bubbleSize - margin;
287
+ const maxY = window.innerHeight - bubbleSize - margin;
288
+ bubbleOffset.value = {
289
+ x: Math.max(margin, Math.min(state.bubbleOffset.x, maxX)),
290
+ y: Math.max(margin, Math.min(state.bubbleOffset.y, maxY))
291
+ };
292
+ }
293
+ if (state.theme !== void 0 && state.theme !== props.theme) {
294
+ emit("update:theme", state.theme);
295
+ emit("toggle-theme", state.theme);
296
+ }
297
+ if (state.sessionListCollapsed !== void 0 && state.sessionListCollapsed !== props.sessionListCollapsed) {
298
+ localSessionListCollapsed.value = state.sessionListCollapsed;
299
+ emit("update:sessionListCollapsed", state.sessionListCollapsed);
300
+ }
301
+ if (state.promptDockVisible !== void 0) {
302
+ promptDockVisible.value = state.promptDockVisible;
303
+ } else if (minimized.value) {
304
+ promptDockVisible.value = false;
305
+ }
306
+ if (state.reviewPanelVisible !== void 0) {
307
+ reviewPanelVisible.value = state.reviewPanelVisible;
308
+ }
309
+ if (state.splitPanelWidth !== void 0 && state.splitPanelWidth !== props.splitPanelWidth) {
310
+ handleResize(state.splitPanelWidth);
311
+ }
312
+ if (state.displayMode !== void 0 && state.displayMode !== props.displayMode) {
313
+ if (props.displayMode !== "extension" && props.displayMode !== "extension-selector") {
314
+ localDisplayMode.value = state.displayMode;
315
+ }
316
+ }
317
+ if (state.splitPosition !== void 0) {
318
+ localSplitPosition.value = state.splitPosition;
319
+ }
320
+ nextTick(() => {
321
+ syncStateToIframe();
322
+ setTimeout(() => {
323
+ isRestoring.value = false;
324
+ }, 50);
325
+ });
326
+ }
327
+ });
328
+ const handleToggleMinimize = () => {
329
+ minimized.value = !minimized.value;
330
+ promptDockVisible.value = !minimized.value;
331
+ sendMessageToIframe(WIDGET_MSG.PROMPT_DOCK_VISIBILITY, { visible: promptDockVisible.value });
332
+ sendMessageToIframe(WIDGET_MSG.MINIMIZE_STATE, { minimized: minimized.value });
333
+ };
334
+ const handleTogglePromptDock = () => {
335
+ promptDockVisible.value = !promptDockVisible.value;
336
+ sendMessageToIframe(WIDGET_MSG.PROMPT_DOCK_VISIBILITY, { visible: promptDockVisible.value });
337
+ };
338
+ const handleToggleReviewPanel = () => {
339
+ reviewPanelVisible.value = !reviewPanelVisible.value;
340
+ sendMessageToIframe(WIDGET_MSG.REVIEW_PANEL_TOGGLE, { visible: reviewPanelVisible.value });
341
+ };
342
+ const handleRefresh = () => {
343
+ window.location.reload();
344
+ };
345
+ const windowWidth = ref(typeof window !== "undefined" ? window.innerWidth : 0);
346
+ const windowHeight = ref(typeof window !== "undefined" ? window.innerHeight : 0);
347
+ const handleWindowResize = () => {
348
+ if (typeof window !== "undefined") {
349
+ windowWidth.value = window.innerWidth;
350
+ windowHeight.value = window.innerHeight;
351
+ }
352
+ };
353
+ const handleIframeMessage = (event) => {
354
+ if (event.data?.type === WIDGET_MSG.READY) {
355
+ iframeReady.value = true;
356
+ syncStateToIframe();
357
+ }
358
+ };
359
+ onMounted(() => {
360
+ if (typeof window !== "undefined") {
361
+ window.addEventListener("resize", handleWindowResize);
362
+ window.addEventListener("message", handleIframeMessage);
363
+ }
364
+ });
365
+ onUnmounted(() => {
366
+ if (typeof window !== "undefined") {
367
+ window.removeEventListener("resize", handleWindowResize);
368
+ window.removeEventListener("message", handleIframeMessage);
369
+ }
370
+ });
371
+ const bubbleQuadrant = computed(() => {
372
+ if (typeof window === "undefined") return "bottom-right";
373
+ const centerX = windowWidth.value / 2;
374
+ const centerY = windowHeight.value / 2;
375
+ const bubbleSize = 44;
376
+ const currentOffset = triggerRef.value?.offset ?? bubbleOffset.value;
377
+ const effectiveX = (currentOffset?.x ?? windowWidth.value - bubbleSize - 24) + bubbleSize / 2;
378
+ const effectiveY = (currentOffset?.y ?? windowHeight.value - bubbleSize - 24) + bubbleSize / 2;
379
+ if (effectiveX >= centerX && effectiveY >= centerY) {
380
+ return "bottom-right";
381
+ } else if (effectiveX < centerX && effectiveY >= centerY) {
382
+ return "bottom-left";
383
+ } else if (effectiveX >= centerX && effectiveY < centerY) {
384
+ return "top-right";
385
+ } else {
386
+ return "top-left";
387
+ }
388
+ });
389
+ const isBubbleOnRightSide = computed(() => {
390
+ const quadrant = bubbleQuadrant.value;
391
+ return quadrant === "top-right" || quadrant === "bottom-right";
392
+ });
393
+ const chatPositionStyle = computed(() => {
394
+ if (typeof window === "undefined") return {};
395
+ const chatWidth = minimized.value ? 300 : 700;
396
+ const chatHeight = minimized.value ? 300 : Math.min(windowHeight.value * 0.86, windowHeight.value - 40);
397
+ const gap = 24;
398
+ const bubbleSize = 44;
399
+ const screenMargin = 20;
400
+ const effectiveOffset = triggerRef.value?.offset ?? bubbleOffset.value ?? { x: windowWidth.value - bubbleSize - gap, y: windowHeight.value - bubbleSize - gap };
401
+ const style = {};
402
+ if (isBubbleOnRightSide.value) {
403
+ let rightPos = windowWidth.value - effectiveOffset.x + gap;
404
+ const minRight = screenMargin;
405
+ const maxRight = windowWidth.value - chatWidth - screenMargin;
406
+ if (rightPos > maxRight) {
407
+ rightPos = maxRight;
408
+ }
409
+ if (rightPos < minRight) {
410
+ rightPos = minRight;
411
+ }
412
+ style.right = `${rightPos}px`;
413
+ style.left = "auto";
414
+ } else {
415
+ let leftPos = effectiveOffset.x + bubbleSize + gap;
416
+ const minLeft = screenMargin;
417
+ const maxLeft = windowWidth.value - chatWidth - screenMargin;
418
+ if (leftPos > maxLeft) {
419
+ leftPos = maxLeft;
420
+ }
421
+ if (leftPos < minLeft) {
422
+ leftPos = minLeft;
423
+ }
424
+ style.left = `${leftPos}px`;
425
+ style.right = "auto";
426
+ }
427
+ let bottomPos = windowHeight.value - effectiveOffset.y - bubbleSize;
428
+ const maxBottom = windowHeight.value - chatHeight - screenMargin;
429
+ if (bottomPos > maxBottom) {
430
+ bottomPos = maxBottom;
431
+ }
432
+ if (bottomPos < screenMargin) {
433
+ bottomPos = screenMargin;
434
+ }
435
+ style.bottom = `${bottomPos}px`;
436
+ return style;
437
+ });
438
+ const handleBubbleOffsetChange = (offset) => {
439
+ bubbleOffset.value = offset;
440
+ };
441
+ const handleResizeStart = () => {
442
+ isDragging.value = true;
443
+ };
444
+ const handleResizeEnd = () => {
445
+ isDragging.value = false;
446
+ };
447
+ const chatAnimationOrigin = computed(() => {
448
+ const quadrant = bubbleQuadrant.value;
449
+ switch (quadrant) {
450
+ case "top-left":
451
+ return { x: "-20px", y: "-20px" };
452
+ case "top-right":
453
+ return { x: "20px", y: "-20px" };
454
+ case "bottom-left":
455
+ return { x: "-20px", y: "20px" };
456
+ case "bottom-right":
457
+ default:
458
+ return { x: "20px", y: "20px" };
459
+ }
460
+ });
461
+ const isDragging = ref(false);
462
+ let wasOpenBeforeDrag = false;
463
+ const handleDragStart = () => {
464
+ isDragging.value = true;
465
+ wasOpenBeforeDrag = props.open;
466
+ if (props.open) {
467
+ emit("update:open", false);
468
+ }
469
+ };
470
+ const handleDragEnd = () => {
471
+ isDragging.value = false;
472
+ if (wasOpenBeforeDrag) {
473
+ emit("update:open", true);
474
+ }
475
+ };
476
+ provideAIPanelWidgetContext({
477
+ theme: toRef(props, "theme"),
478
+ resolvedTheme,
479
+ title: toRef(props, "title"),
480
+ hotkeyLabel: toRef(props, "hotkeyLabel"),
481
+ selectShortcutLabel: toRef(props, "selectShortcutLabel"),
482
+ selectMode: toRef(props, "selectMode"),
483
+ selectEnabled: toRef(props, "selectEnabled"),
484
+ sessionListCollapsed: localSessionListCollapsed,
485
+ sessionKey: toRef(props, "sessionKey"),
486
+ frameLoading: toRef(props, "frameLoading"),
487
+ loadingSessionList: toRef(props, "loadingSessionList"),
488
+ showSessionListSkeleton: toRef(props, "showSessionListSkeleton"),
489
+ showEmptyState: toRef(props, "showEmptyState"),
490
+ showError: toRef(props, "showError"),
491
+ emptyStateText: toRef(props, "emptyStateText"),
492
+ emptyStateActionText: toRef(props, "emptyStateActionText"),
493
+ showClearAll: toRef(props, "showClearAll"),
494
+ open: toRef(props, "open"),
495
+ thinking: toRef(props, "thinking"),
496
+ minimized,
497
+ promptDockVisible,
498
+ reviewPanelVisible,
499
+ reviewPanelEnabled: toRef(props, "reviewPanelEnabled"),
500
+ bubbleOffset,
501
+ mode: effectiveMode,
502
+ displayMode: localDisplayMode,
503
+ splitPosition,
504
+ sessionStates: computed(() => props.sessionStates ?? {}),
505
+ iframeSource,
506
+ buttonActive,
507
+ sessionListTitle,
508
+ bubbleVisible,
509
+ hasSelectedElements,
510
+ sessionItems,
511
+ selectedElementItems,
512
+ handleToggle,
513
+ handleClose,
514
+ handleToggleMinimize,
515
+ handleTogglePromptDock,
516
+ handleToggleReviewPanel,
517
+ handleToggleSessionList,
518
+ handleToggleTheme,
519
+ handleToggleDisplayMode,
520
+ handleToggleSplitPosition: handleTogglePosition,
521
+ handleEmptyAction,
522
+ handleCreateSession,
523
+ handleSelectSession,
524
+ handleDeleteSession,
525
+ handleToggleSelectMode,
526
+ handleClickSelectedNode,
527
+ handleRemoveSelectedNode: (payload) => handleRemoveSelectedNode(payload.item, payload.index, payload.source),
528
+ handleClearSelectedNodes,
529
+ handleFrameLoaded,
530
+ handleBubbleOffsetChange,
531
+ handleRefresh
532
+ });
533
+ __expose({
534
+ showNotification,
535
+ showConfirmDialog,
536
+ sendMessageToIframe,
537
+ isSplitMode
538
+ });
539
+ const __returned__ = { props, emit, slots, notificationMessage, notificationVisible, notificationMode, get notificationTimer() {
540
+ return notificationTimer;
541
+ }, set notificationTimer(v) {
542
+ notificationTimer = v;
543
+ }, showNotification, dialogVisible, dialogMessage, get dialogResolve() {
544
+ return dialogResolve;
545
+ }, set dialogResolve(v) {
546
+ dialogResolve = v;
547
+ }, showConfirmDialog, handleDialogConfirm, handleDialogCancel, frameRef, triggerRef, sendMessageToIframe, localSessionListCollapsed, localDisplayMode, localSplitPosition, minimized, promptDockVisible, reviewPanelVisible, isRestoring, iframeLoaded, iframeReady, splitPanelWidth, syncStateToIframe, handleFrameLoaded, handleToggleDisplayMode, 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, effectiveMode, isSplitMode, isExtensionMode, panelWidth, splitConfig, splitPosition, handleResize, handleSplitToggle, handleTogglePosition, handleToggleMinimize, handleTogglePromptDock, handleToggleReviewPanel, handleRefresh, windowWidth, windowHeight, handleWindowResize, handleIframeMessage, bubbleQuadrant, isBubbleOnRightSide, chatPositionStyle, handleBubbleOffsetChange, handleResizeStart, handleResizeEnd, chatAnimationOrigin, isDragging, get wasOpenBeforeDrag() {
548
+ return wasOpenBeforeDrag;
549
+ }, set wasOpenBeforeDrag(v) {
550
+ wasOpenBeforeDrag = v;
551
+ }, handleDragStart, handleDragEnd, ChatPanel, SelectHint, Trigger };
552
+ Object.defineProperty(__returned__, "__isScriptSetup", { enumerable: false, value: true });
553
+ return __returned__;
554
+ }
555
+ });
556
+ import { renderSlot as _renderSlot, withCtx as _withCtx, createSlots as _createSlots, openBlock as _openBlock, createBlock as _createBlock, createCommentVNode as _createCommentVNode, createElementVNode as _createElementVNode, createVNode as _createVNode, Fragment as _Fragment, createElementBlock as _createElementBlock, vShow as _vShow, normalizeStyle as _normalizeStyle, withDirectives as _withDirectives, toDisplayString as _toDisplayString, normalizeClass as _normalizeClass, Teleport as _Teleport } from "vue";
557
+ const _hoisted_1 = { class: "aipanel-tooltip-tag" };
558
+ const _hoisted_2 = { class: "aipanel-tooltip-file" };
559
+ const _hoisted_3 = {
560
+ key: 1,
561
+ class: "aipanel-dialog-overlay"
562
+ };
563
+ const _hoisted_4 = {
564
+ class: "aipanel-dialog",
565
+ role: "alertdialog",
566
+ "aria-modal": "true"
567
+ };
568
+ const _hoisted_5 = { class: "aipanel-dialog-content" };
569
+ const _hoisted_6 = { class: "aipanel-dialog-message" };
570
+ function __vue_render__(_ctx, _cache, $props, $setup, $data, $options) {
571
+ return _openBlock(), _createElementBlock(
572
+ "div",
573
+ {
574
+ class: _normalizeClass([...$setup.containerClasses, { "extension-mode": $setup.isExtensionMode }])
575
+ },
576
+ [
577
+ $props.displayMode !== "extension-selector" ? (_openBlock(), _createElementBlock(
578
+ _Fragment,
579
+ { key: 0 },
580
+ [
581
+ !$setup.isSplitMode && !$setup.props.hideBubble ? (_openBlock(), _createBlock(
582
+ $setup["Trigger"],
583
+ {
584
+ key: 0,
585
+ ref: "triggerRef",
586
+ onDragStart: $setup.handleDragStart,
587
+ onDragEnd: $setup.handleDragEnd
588
+ },
589
+ _createSlots({
590
+ _: 2
591
+ /* DYNAMIC */
592
+ }, [
593
+ $setup.slots["button-icon"] ? {
594
+ name: "default",
595
+ fn: _withCtx(() => [
596
+ _renderSlot(_ctx.$slots, "button-icon")
597
+ ]),
598
+ key: "0"
599
+ } : void 0
600
+ ]),
601
+ 1536
602
+ /* NEED_PATCH, DYNAMIC_SLOTS */
603
+ )) : _createCommentVNode("v-if", true),
604
+ _createVNode($setup["ChatPanel"], {
605
+ ref: "frameRef",
606
+ mode: $setup.effectiveMode,
607
+ open: $props.open,
608
+ minimized: $setup.minimized,
609
+ "position-style": $setup.chatPositionStyle,
610
+ "animation-origin": $setup.chatAnimationOrigin,
611
+ "panel-width": $setup.panelWidth,
612
+ resizable: $setup.splitConfig.resizable,
613
+ "min-width": $setup.splitConfig.minWidth,
614
+ "max-width": $setup.splitConfig.maxWidth,
615
+ "no-transition": $setup.isRestoring,
616
+ dragging: $setup.isDragging,
617
+ thinking: $props.thinking,
618
+ "resolved-theme": $setup.resolvedTheme,
619
+ "split-position": $setup.splitPosition,
620
+ extension: $setup.isExtensionMode,
621
+ onResize: $setup.handleResize,
622
+ onResizeStart: $setup.handleResizeStart,
623
+ onResizeEnd: $setup.handleResizeEnd,
624
+ onToggle: $setup.handleSplitToggle
625
+ }, _createSlots({
626
+ "sessions-empty": _withCtx(() => [
627
+ _renderSlot(_ctx.$slots, "sessions-empty", {}, () => [
628
+ _cache[0] || (_cache[0] = _createElementVNode(
629
+ "div",
630
+ { class: "aipanel-session-empty" },
631
+ "\u6682\u65E0\u4F1A\u8BDD",
632
+ -1
633
+ /* CACHED */
634
+ ))
635
+ ])
636
+ ]),
637
+ _: 2
638
+ /* DYNAMIC */
639
+ }, [
640
+ $setup.slots["session-toggle-icon"] ? {
641
+ name: "session-toggle-icon",
642
+ fn: _withCtx(() => [
643
+ _renderSlot(_ctx.$slots, "session-toggle-icon")
644
+ ]),
645
+ key: "0"
646
+ } : void 0,
647
+ $setup.slots["select-icon"] ? {
648
+ name: "select-icon",
649
+ fn: _withCtx(() => [
650
+ _renderSlot(_ctx.$slots, "select-icon")
651
+ ]),
652
+ key: "1"
653
+ } : void 0,
654
+ $setup.slots["close-icon"] ? {
655
+ name: "close-icon",
656
+ fn: _withCtx(() => [
657
+ _renderSlot(_ctx.$slots, "close-icon")
658
+ ]),
659
+ key: "2"
660
+ } : void 0,
661
+ $setup.slots["empty-state"] ? {
662
+ name: "empty-state",
663
+ fn: _withCtx(() => [
664
+ _renderSlot(_ctx.$slots, "empty-state")
665
+ ]),
666
+ key: "3"
667
+ } : void 0,
668
+ $setup.slots.loading ? {
669
+ name: "loading",
670
+ fn: _withCtx(() => [
671
+ _renderSlot(_ctx.$slots, "loading")
672
+ ]),
673
+ key: "4"
674
+ } : void 0,
675
+ $setup.slots.error ? {
676
+ name: "error",
677
+ fn: _withCtx(() => [
678
+ _renderSlot(_ctx.$slots, "error")
679
+ ]),
680
+ key: "5"
681
+ } : void 0,
682
+ $setup.slots.content ? {
683
+ name: "content",
684
+ fn: _withCtx(() => [
685
+ _renderSlot(_ctx.$slots, "content")
686
+ ]),
687
+ key: "6"
688
+ } : void 0
689
+ ]), 1032, ["mode", "open", "minimized", "position-style", "animation-origin", "panel-width", "resizable", "min-width", "max-width", "no-transition", "dragging", "thinking", "resolved-theme", "split-position", "extension", "onResize", "onToggle"]),
690
+ _createVNode($setup["SelectHint"])
691
+ ],
692
+ 64
693
+ /* STABLE_FRAGMENT */
694
+ )) : _createCommentVNode("v-if", true),
695
+ _withDirectives(_createElementVNode(
696
+ "div",
697
+ {
698
+ class: "aipanel-element-highlight",
699
+ style: _normalizeStyle($setup.highlightStyle)
700
+ },
701
+ null,
702
+ 4
703
+ /* STYLE */
704
+ ), [
705
+ [_vShow, $setup.highlightVisible]
706
+ ]),
707
+ _withDirectives(_createElementVNode(
708
+ "div",
709
+ {
710
+ class: "aipanel-element-tooltip",
711
+ style: _normalizeStyle($setup.tooltipStyle)
712
+ },
713
+ [
714
+ _createElementVNode(
715
+ "div",
716
+ _hoisted_1,
717
+ _toDisplayString($setup.tooltipContent.description),
718
+ 1
719
+ /* TEXT */
720
+ ),
721
+ _createElementVNode(
722
+ "div",
723
+ _hoisted_2,
724
+ _toDisplayString($setup.tooltipContent.fileInfo),
725
+ 1
726
+ /* TEXT */
727
+ )
728
+ ],
729
+ 4
730
+ /* STYLE */
731
+ ), [
732
+ [_vShow, $setup.tooltipVisible]
733
+ ]),
734
+ $setup.dialogVisible ? (_openBlock(), _createElementBlock("div", _hoisted_3, [
735
+ _createElementVNode("div", _hoisted_4, [
736
+ _createElementVNode("div", _hoisted_5, [
737
+ _createElementVNode(
738
+ "div",
739
+ _hoisted_6,
740
+ _toDisplayString($setup.dialogMessage),
741
+ 1
742
+ /* TEXT */
743
+ )
744
+ ]),
745
+ _createElementVNode("div", { class: "aipanel-dialog-actions" }, [
746
+ _createElementVNode("button", {
747
+ class: "aipanel-dialog-btn cancel",
748
+ onClick: $setup.handleDialogCancel
749
+ }, "\u53D6\u6D88"),
750
+ _createElementVNode("button", {
751
+ class: "aipanel-dialog-btn confirm",
752
+ onClick: $setup.handleDialogConfirm
753
+ }, "\u786E\u8BA4")
754
+ ])
755
+ ])
756
+ ])) : _createCommentVNode("v-if", true),
757
+ (_openBlock(), _createBlock(_Teleport, {
758
+ to: "body",
759
+ disabled: $setup.notificationMode === "widget"
760
+ }, [
761
+ $setup.notificationVisible ? (_openBlock(), _createElementBlock(
762
+ "div",
763
+ {
764
+ key: 0,
765
+ class: _normalizeClass($setup.notificationMode === "page" ? "aipanel-page-notification" : "aipanel-notification"),
766
+ role: "alert"
767
+ },
768
+ _toDisplayString($setup.notificationMessage),
769
+ 3
770
+ /* TEXT, CLASS */
771
+ )) : _createCommentVNode("v-if", true)
772
+ ], 8, ["disabled"]))
773
+ ],
774
+ 2
775
+ /* CLASS */
776
+ );
777
+ }
778
+ __vue_sfc__.render = __vue_render__;
779
+ var index_vue_default = __vue_sfc__;
780
+ export {
781
+ index_vue_default as default
782
+ };