@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.
- package/es/AI-panel-widget/composables/use-inspector.d.ts +52 -0
- package/es/AI-panel-widget/composables/use-inspector.mjs +437 -0
- package/es/AI-panel-widget/composables/use-persist-state.d.ts +32 -0
- package/es/AI-panel-widget/composables/use-persist-state.mjs +83 -0
- package/es/AI-panel-widget/composables/use-selection.d.ts +19 -0
- package/es/AI-panel-widget/composables/use-selection.mjs +112 -0
- package/es/AI-panel-widget/composables/use-session.d.ts +16 -0
- package/es/AI-panel-widget/composables/use-session.mjs +47 -0
- package/es/AI-panel-widget/composables/use-split.d.ts +30 -0
- package/es/AI-panel-widget/composables/use-split.mjs +133 -0
- package/es/AI-panel-widget/composables/use-widget.d.ts +27 -0
- package/es/AI-panel-widget/composables/use-widget.mjs +78 -0
- package/es/AI-panel-widget/index.d.ts +5 -0
- package/es/AI-panel-widget/index.mjs +9 -0
- package/es/AI-panel-widget/src/assets/logo.svg +13 -0
- package/es/AI-panel-widget/src/components/AIPanelLogo-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/AIPanelLogo.vue.d.ts +8 -0
- package/es/AI-panel-widget/src/components/AIPanelLogo.vue.mjs +40 -0
- package/es/AI-panel-widget/src/components/ChatPanel-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/ChatPanel.vue.d.ts +179 -0
- package/es/AI-panel-widget/src/components/ChatPanel.vue.mjs +308 -0
- package/es/AI-panel-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +44 -0
- package/es/AI-panel-widget/src/components/FloatingBubble/FloatingBubble.vue.mjs +311 -0
- package/es/AI-panel-widget/src/components/FloatingBubble/index.d.ts +3 -0
- package/es/AI-panel-widget/src/components/FloatingBubble/index.mjs +5 -0
- package/es/AI-panel-widget/src/components/FloatingBubble/types.d.ts +24 -0
- package/es/AI-panel-widget/src/components/FloatingBubble/types.mjs +0 -0
- package/es/AI-panel-widget/src/components/Frame-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/Frame.vue.d.ts +22 -0
- package/es/AI-panel-widget/src/components/Frame.vue.mjs +143 -0
- package/es/AI-panel-widget/src/components/Header-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/Header.vue.d.ts +27 -0
- package/es/AI-panel-widget/src/components/Header.vue.mjs +683 -0
- package/es/AI-panel-widget/src/components/ResizeHandle-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/ResizeHandle.vue.d.ts +22 -0
- package/es/AI-panel-widget/src/components/ResizeHandle.vue.mjs +79 -0
- package/es/AI-panel-widget/src/components/SelectHint-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/SelectHint.vue.d.ts +3 -0
- package/es/AI-panel-widget/src/components/SelectHint.vue.mjs +40 -0
- package/es/AI-panel-widget/src/components/SelectedBubbles-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/SelectedBubbles.vue.d.ts +3 -0
- package/es/AI-panel-widget/src/components/SelectedBubbles.vue.mjs +84 -0
- package/es/AI-panel-widget/src/components/SelectedNodes-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/SelectedNodes.vue.d.ts +3 -0
- package/es/AI-panel-widget/src/components/SelectedNodes.vue.mjs +103 -0
- package/es/AI-panel-widget/src/components/SessionList-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/SessionList.vue.d.ts +13 -0
- package/es/AI-panel-widget/src/components/SessionList.vue.mjs +222 -0
- package/es/AI-panel-widget/src/components/SplitTrigger-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/SplitTrigger.vue.d.ts +18 -0
- package/es/AI-panel-widget/src/components/SplitTrigger.vue.mjs +112 -0
- package/es/AI-panel-widget/src/components/Trigger-sfc.css +1 -0
- package/es/AI-panel-widget/src/components/Trigger.vue.d.ts +28 -0
- package/es/AI-panel-widget/src/components/Trigger.vue.mjs +74 -0
- package/es/AI-panel-widget/src/context.d.ts +67 -0
- package/es/AI-panel-widget/src/context.mjs +16 -0
- package/es/AI-panel-widget/src/index-sfc.css +1 -0
- package/es/AI-panel-widget/src/index.vue.d.ts +69 -0
- package/es/AI-panel-widget/src/index.vue.mjs +782 -0
- package/es/AI-panel-widget/src/types.d.ts +2 -0
- package/es/AI-panel-widget/src/types.mjs +0 -0
- package/es/AI-panel-widget/style/index-pure.d.ts +0 -0
- package/es/AI-panel-widget/style/index-pure.mjs +0 -0
- package/es/AI-panel-widget/style/index.d.ts +0 -0
- package/es/AI-panel-widget/style/index.mjs +0 -0
- package/es/AI-panel-widget/style/less-pure.d.ts +0 -0
- package/es/AI-panel-widget/style/less-pure.mjs +0 -0
- package/es/AI-panel-widget/style/less.d.ts +0 -0
- package/es/AI-panel-widget/style/less.mjs +0 -0
- package/es/env.d.ts +15 -0
- package/es/index.d.ts +7 -0
- package/es/index.mjs +22 -0
- package/es/setup.d.ts +1 -0
- package/es/setup.mjs +4 -0
- package/lib/AI-panel-widget/composables/use-inspector.cjs +466 -0
- package/lib/AI-panel-widget/composables/use-inspector.d.ts +52 -0
- package/lib/AI-panel-widget/composables/use-persist-state.cjs +102 -0
- package/lib/AI-panel-widget/composables/use-persist-state.d.ts +32 -0
- package/lib/AI-panel-widget/composables/use-selection.cjs +131 -0
- package/lib/AI-panel-widget/composables/use-selection.d.ts +19 -0
- package/lib/AI-panel-widget/composables/use-session.cjs +66 -0
- package/lib/AI-panel-widget/composables/use-session.d.ts +16 -0
- package/lib/AI-panel-widget/composables/use-split.cjs +152 -0
- package/lib/AI-panel-widget/composables/use-split.d.ts +30 -0
- package/lib/AI-panel-widget/composables/use-widget.cjs +97 -0
- package/lib/AI-panel-widget/composables/use-widget.d.ts +27 -0
- package/lib/AI-panel-widget/index.cjs +39 -0
- package/lib/AI-panel-widget/index.d.ts +5 -0
- package/lib/AI-panel-widget/src/assets/logo.svg +13 -0
- package/lib/AI-panel-widget/src/components/AIPanelLogo-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/AIPanelLogo.vue.cjs +69 -0
- package/lib/AI-panel-widget/src/components/AIPanelLogo.vue.d.ts +8 -0
- package/lib/AI-panel-widget/src/components/ChatPanel-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/ChatPanel.vue.cjs +337 -0
- package/lib/AI-panel-widget/src/components/ChatPanel.vue.d.ts +179 -0
- package/lib/AI-panel-widget/src/components/FloatingBubble/FloatingBubble-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/FloatingBubble/FloatingBubble.vue.cjs +330 -0
- package/lib/AI-panel-widget/src/components/FloatingBubble/FloatingBubble.vue.d.ts +44 -0
- package/lib/AI-panel-widget/src/components/FloatingBubble/index.cjs +35 -0
- package/lib/AI-panel-widget/src/components/FloatingBubble/index.d.ts +3 -0
- package/lib/AI-panel-widget/src/components/FloatingBubble/types.cjs +15 -0
- package/lib/AI-panel-widget/src/components/FloatingBubble/types.d.ts +24 -0
- package/lib/AI-panel-widget/src/components/Frame-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/Frame.vue.cjs +162 -0
- package/lib/AI-panel-widget/src/components/Frame.vue.d.ts +22 -0
- package/lib/AI-panel-widget/src/components/Header-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/Header.vue.cjs +702 -0
- package/lib/AI-panel-widget/src/components/Header.vue.d.ts +27 -0
- package/lib/AI-panel-widget/src/components/ResizeHandle-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/ResizeHandle.vue.cjs +98 -0
- package/lib/AI-panel-widget/src/components/ResizeHandle.vue.d.ts +22 -0
- package/lib/AI-panel-widget/src/components/SelectHint-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/SelectHint.vue.cjs +59 -0
- package/lib/AI-panel-widget/src/components/SelectHint.vue.d.ts +3 -0
- package/lib/AI-panel-widget/src/components/SelectedBubbles-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/SelectedBubbles.vue.cjs +103 -0
- package/lib/AI-panel-widget/src/components/SelectedBubbles.vue.d.ts +3 -0
- package/lib/AI-panel-widget/src/components/SelectedNodes-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/SelectedNodes.vue.cjs +122 -0
- package/lib/AI-panel-widget/src/components/SelectedNodes.vue.d.ts +3 -0
- package/lib/AI-panel-widget/src/components/SessionList-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/SessionList.vue.cjs +241 -0
- package/lib/AI-panel-widget/src/components/SessionList.vue.d.ts +13 -0
- package/lib/AI-panel-widget/src/components/SplitTrigger-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/SplitTrigger.vue.cjs +131 -0
- package/lib/AI-panel-widget/src/components/SplitTrigger.vue.d.ts +18 -0
- package/lib/AI-panel-widget/src/components/Trigger-sfc.css +1 -0
- package/lib/AI-panel-widget/src/components/Trigger.vue.cjs +103 -0
- package/lib/AI-panel-widget/src/components/Trigger.vue.d.ts +28 -0
- package/lib/AI-panel-widget/src/context.cjs +35 -0
- package/lib/AI-panel-widget/src/context.d.ts +67 -0
- package/lib/AI-panel-widget/src/index-sfc.css +1 -0
- package/lib/AI-panel-widget/src/index.vue.cjs +811 -0
- package/lib/AI-panel-widget/src/index.vue.d.ts +69 -0
- package/lib/AI-panel-widget/src/types.cjs +15 -0
- package/lib/AI-panel-widget/src/types.d.ts +2 -0
- package/lib/AI-panel-widget/style/index-pure.cjs +0 -0
- package/lib/AI-panel-widget/style/index-pure.d.ts +0 -0
- package/lib/AI-panel-widget/style/index.cjs +0 -0
- package/lib/AI-panel-widget/style/index.d.ts +0 -0
- package/lib/AI-panel-widget/style/less-pure.cjs +0 -0
- package/lib/AI-panel-widget/style/less-pure.d.ts +0 -0
- package/lib/AI-panel-widget/style/less.cjs +0 -0
- package/lib/AI-panel-widget/style/less.d.ts +0 -0
- package/lib/env.d.ts +15 -0
- package/lib/index.cjs +42 -0
- package/lib/index.css +0 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.less +0 -0
- package/lib/setup.cjs +23 -0
- package/lib/setup.d.ts +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export type { AIPanelWidgetTheme, AIPanelWidgetSession, AIPanelSelectedElement, AIPanelRemoveSelectedPayload, AIPanelWidgetSessionItem, AIPanelSelectedElementItem, AIPanelWidgetProps, AIPanelWidgetEmits, AIPanelSessionThinkingState, DisplayMode, SplitModeOptions, } from "@aipanel/core";
|
|
2
|
+
export type AIPanelWidgetThemeLocal = "light" | "dark" | "auto";
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/es/env.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
/// <reference lib="dom.iterable" />
|
|
3
|
+
|
|
4
|
+
declare module "*.vue" {
|
|
5
|
+
import type { DefineComponent } from "vue";
|
|
6
|
+
|
|
7
|
+
const component: DefineComponent<Record<string, never>, Record<string, never>, unknown>;
|
|
8
|
+
|
|
9
|
+
export default component;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare module "*.svg?raw" {
|
|
13
|
+
const content: string;
|
|
14
|
+
export default content;
|
|
15
|
+
}
|
package/es/index.d.ts
ADDED
package/es/index.mjs
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { AIPanelWidget } from "./AI-panel-widget/index.mjs";
|
|
2
|
+
const version = "1.2.0-beta.0";
|
|
3
|
+
function install(app, options) {
|
|
4
|
+
const components = [
|
|
5
|
+
AIPanelWidget
|
|
6
|
+
];
|
|
7
|
+
components.forEach((item) => {
|
|
8
|
+
if (item.install) {
|
|
9
|
+
app.use(item, options);
|
|
10
|
+
} else if (item.name) {
|
|
11
|
+
app.component(item.name, item);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export * from "./AI-panel-widget/index.mjs";
|
|
16
|
+
export * from "./setup.mjs";
|
|
17
|
+
var es_default = install;
|
|
18
|
+
export {
|
|
19
|
+
es_default as default,
|
|
20
|
+
install,
|
|
21
|
+
version
|
|
22
|
+
};
|
package/es/setup.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AIPanelLogo } from "./AI-panel-widget";
|
package/es/setup.mjs
ADDED
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var use_inspector_exports = {};
|
|
29
|
+
__export(use_inspector_exports, {
|
|
30
|
+
useInspector: () => useInspector
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(use_inspector_exports);
|
|
33
|
+
var import_vue = require("vue");
|
|
34
|
+
var import_core = require("@aipanel/core");
|
|
35
|
+
var import_css_selector_generator = __toESM(require("css-selector-generator"));
|
|
36
|
+
const IGNORE_SELECTORS = [
|
|
37
|
+
"#vue-inspector-container",
|
|
38
|
+
".aipanel-widget",
|
|
39
|
+
".aipanel-element-highlight",
|
|
40
|
+
".aipanel-element-tooltip",
|
|
41
|
+
".aipanel-select-mode-hint",
|
|
42
|
+
".floating-bubble"
|
|
43
|
+
];
|
|
44
|
+
const IGNORE_ATTRIBUTE = "data-v-inspector-ignore";
|
|
45
|
+
const KEY_PROPS_DATA = "__v_inspector";
|
|
46
|
+
const KEY_DATA = "data-v-inspector";
|
|
47
|
+
function getDirectText(element) {
|
|
48
|
+
let text = "";
|
|
49
|
+
for (let i = 0; i < element.childNodes.length; i++) {
|
|
50
|
+
const child = element.childNodes[i];
|
|
51
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
52
|
+
text += child.textContent || "";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return text.trim();
|
|
56
|
+
}
|
|
57
|
+
const DYNAMIC_ID_PATTERN = /^(?:el-|:r[0-9]+:|radix-|uid-|ts-|uuid-|id-[a-f0-9]{4,}|.*[0-9]{4,}.*|.*-[a-f0-9]{6,}$)/i;
|
|
58
|
+
const STATE_CLASS_PATTERN = /^(?:hover|active|focus|focus-visible|focus-within|disabled|enabled|checked|selected|open|closed|loading|error|success|warning|hidden|visible|show|hide|current|expanded|collapsed|pressed|dragging|droppable|sortable|placeholder|transition|enter|leave|appear|move)$/i;
|
|
59
|
+
const STATE_CLASS_PREFIX_PATTERN = /^(?:is-|has-|was-|are-|can-|should-|will-|did-|does-|on-|off-|in-|out-|at-|to-|from-)/i;
|
|
60
|
+
function isDynamicId(id) {
|
|
61
|
+
if (!id) return false;
|
|
62
|
+
if (DYNAMIC_ID_PATTERN.test(id)) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
const digitCount = (id.match(/\d/g) || []).length;
|
|
66
|
+
const letterCount = (id.match(/[a-zA-Z]/g) || []).length;
|
|
67
|
+
if (digitCount > letterCount && digitCount >= 3) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
const dashParts = id.split("-");
|
|
71
|
+
if (dashParts.length >= 3) {
|
|
72
|
+
const lastPart = dashParts[dashParts.length - 1];
|
|
73
|
+
if (/^\d+$/.test(lastPart) || /^[a-f0-9]{4,}$/i.test(lastPart)) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
function isStateClass(className) {
|
|
80
|
+
if (!className) return false;
|
|
81
|
+
if (STATE_CLASS_PATTERN.test(className)) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
if (STATE_CLASS_PREFIX_PATTERN.test(className)) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
if (className.includes("-active") || className.includes("-hover") || className.includes("-focus")) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
if (/^(?:router-link|nuxt-link)/.test(className)) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
function getElementDescription(element) {
|
|
96
|
+
return (0, import_css_selector_generator.default)(element, {
|
|
97
|
+
selectors: ["id", "class", "tag", "nthchild"],
|
|
98
|
+
combineWithinSelector: true,
|
|
99
|
+
combineBetweenSelectors: true,
|
|
100
|
+
maxCombinations: 100,
|
|
101
|
+
maxCandidates: 100,
|
|
102
|
+
blacklist: [
|
|
103
|
+
(selectorValue) => {
|
|
104
|
+
const idMatch = selectorValue.match(/^#(.+)$/);
|
|
105
|
+
if (idMatch) {
|
|
106
|
+
return isDynamicId(idMatch[1]);
|
|
107
|
+
}
|
|
108
|
+
const classMatch = selectorValue.match(/^\.([a-zA-Z_-][\w-]*)$/);
|
|
109
|
+
if (classMatch) {
|
|
110
|
+
return isStateClass(classMatch[1]);
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function getFileInfoFromVueInstance(element) {
|
|
118
|
+
const vue3Instance = element.__vueParentComponent;
|
|
119
|
+
if (vue3Instance) {
|
|
120
|
+
let current = vue3Instance;
|
|
121
|
+
while (current) {
|
|
122
|
+
const file = current.type?.__file || current.vnode?.type?.__file;
|
|
123
|
+
if (file) {
|
|
124
|
+
return { file, line: null, column: null };
|
|
125
|
+
}
|
|
126
|
+
current = current.parent;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const vue2Instance = element.__vue__;
|
|
130
|
+
if (vue2Instance) {
|
|
131
|
+
let current = vue2Instance;
|
|
132
|
+
while (current) {
|
|
133
|
+
const file = current.$options?.__file;
|
|
134
|
+
if (file) {
|
|
135
|
+
return { file, line: null, column: null };
|
|
136
|
+
}
|
|
137
|
+
current = current.$parent;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
function shouldIgnoreElement(el) {
|
|
143
|
+
if (el.hasAttribute(IGNORE_ATTRIBUTE)) return true;
|
|
144
|
+
for (const selector of IGNORE_SELECTORS) {
|
|
145
|
+
if (el.closest(selector)) return true;
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
function getDataFromElement(el) {
|
|
150
|
+
const vnodeData = el.__vnode?.props?.[KEY_PROPS_DATA];
|
|
151
|
+
if (vnodeData) return vnodeData;
|
|
152
|
+
const ctxVNode = el.__vnode?.ctx?.vnode;
|
|
153
|
+
if (ctxVNode?.el === el) {
|
|
154
|
+
const ctxData = ctxVNode.props?.[KEY_PROPS_DATA];
|
|
155
|
+
if (ctxData) return ctxData;
|
|
156
|
+
}
|
|
157
|
+
const vueInstance = el.__vueParentComponent;
|
|
158
|
+
let currentParent = vueInstance?.parent;
|
|
159
|
+
while (currentParent) {
|
|
160
|
+
if (currentParent.vnode?.el === el) {
|
|
161
|
+
const parentData = currentParent.vnode.props?.[KEY_PROPS_DATA];
|
|
162
|
+
if (parentData) return parentData;
|
|
163
|
+
}
|
|
164
|
+
currentParent = currentParent.parent;
|
|
165
|
+
}
|
|
166
|
+
const attr = el.getAttribute(KEY_DATA);
|
|
167
|
+
return attr ?? void 0;
|
|
168
|
+
}
|
|
169
|
+
function findInspectorFileInfo(element) {
|
|
170
|
+
let current = element;
|
|
171
|
+
while (current) {
|
|
172
|
+
if (shouldIgnoreElement(current)) {
|
|
173
|
+
current = current.parentElement;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
const data = getDataFromElement(current);
|
|
177
|
+
if (data) {
|
|
178
|
+
const splitRE = /(.+):([\d]+):([\d]+)$/;
|
|
179
|
+
const match = data.match(splitRE);
|
|
180
|
+
if (match) {
|
|
181
|
+
return {
|
|
182
|
+
file: match[1],
|
|
183
|
+
line: parseInt(match[2], 10),
|
|
184
|
+
column: parseInt(match[3], 10)
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
current = current.parentElement;
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
function mergeFileInfo(inspectorFileInfo, vueFileInfo) {
|
|
193
|
+
if (!inspectorFileInfo?.file && !vueFileInfo?.file) {
|
|
194
|
+
return { file: null, line: null, column: null };
|
|
195
|
+
}
|
|
196
|
+
const isNodeModules = (path) => path.includes("node_modules");
|
|
197
|
+
if (inspectorFileInfo?.file && vueFileInfo?.file) {
|
|
198
|
+
if (!isNodeModules(inspectorFileInfo.file)) {
|
|
199
|
+
return inspectorFileInfo;
|
|
200
|
+
} else if (!isNodeModules(vueFileInfo.file)) {
|
|
201
|
+
return vueFileInfo;
|
|
202
|
+
} else {
|
|
203
|
+
return inspectorFileInfo;
|
|
204
|
+
}
|
|
205
|
+
} else if (inspectorFileInfo?.file) {
|
|
206
|
+
return inspectorFileInfo;
|
|
207
|
+
} else {
|
|
208
|
+
return vueFileInfo;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function getTargetElement(e) {
|
|
212
|
+
if (!e.target || !(e.target instanceof Element)) return null;
|
|
213
|
+
const el = e.target;
|
|
214
|
+
if (shouldIgnoreElement(el)) return null;
|
|
215
|
+
return el;
|
|
216
|
+
}
|
|
217
|
+
function getFileInfo(e, element) {
|
|
218
|
+
let inspectorFileInfo = null;
|
|
219
|
+
if (element) {
|
|
220
|
+
inspectorFileInfo = findInspectorFileInfo(element);
|
|
221
|
+
}
|
|
222
|
+
const vueFileInfo = element ? getFileInfoFromVueInstance(element) : null;
|
|
223
|
+
return mergeFileInfo(inspectorFileInfo, vueFileInfo);
|
|
224
|
+
}
|
|
225
|
+
function useInspector(options) {
|
|
226
|
+
const highlightVisible = (0, import_vue.ref)(false);
|
|
227
|
+
const highlightStyle = (0, import_vue.ref)({
|
|
228
|
+
top: "0px",
|
|
229
|
+
left: "0px",
|
|
230
|
+
width: "0px",
|
|
231
|
+
height: "0px"
|
|
232
|
+
});
|
|
233
|
+
const tooltipVisible = (0, import_vue.ref)(false);
|
|
234
|
+
const tooltipStyle = (0, import_vue.ref)({ top: "0px", left: "0px" });
|
|
235
|
+
const tooltipContent = (0, import_vue.ref)({ description: "", fileInfo: "" });
|
|
236
|
+
const INSPECTOR_CHECK_INTERVAL = 500;
|
|
237
|
+
let inspectorCheckTimer = null;
|
|
238
|
+
let currentPrimary = "#3b82f6";
|
|
239
|
+
let currentPrimaryBg = "rgba(59, 130, 246, 0.1)";
|
|
240
|
+
function setPointerEventsNone(elements) {
|
|
241
|
+
elements.forEach((el) => {
|
|
242
|
+
if (el) el.style.pointerEvents = "none";
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
function setPointerEventsAuto(elements) {
|
|
246
|
+
elements.forEach((el) => {
|
|
247
|
+
if (el) el.style.pointerEvents = "";
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
function handleMouseMoveCore(e) {
|
|
251
|
+
if (!options.selectMode.value) return;
|
|
252
|
+
const highlight = document.querySelector(".aipanel-element-highlight");
|
|
253
|
+
const tooltip = document.querySelector(".aipanel-element-tooltip");
|
|
254
|
+
const selectHint = document.querySelector(".aipanel-select-mode-hint");
|
|
255
|
+
const floatingBubble = document.querySelector(".floating-bubble");
|
|
256
|
+
const uiElements = [highlight, tooltip, selectHint, floatingBubble];
|
|
257
|
+
setPointerEventsNone(uiElements);
|
|
258
|
+
const elementToHighlight = getTargetElement(e);
|
|
259
|
+
const fileInfo = getFileInfo(e, elementToHighlight);
|
|
260
|
+
setPointerEventsAuto(uiElements);
|
|
261
|
+
if (elementToHighlight) {
|
|
262
|
+
const widget = document.querySelector(".aipanel-widget");
|
|
263
|
+
if (widget) {
|
|
264
|
+
const style = getComputedStyle(widget);
|
|
265
|
+
currentPrimary = style.getPropertyValue("--ap-primary").trim() || currentPrimary;
|
|
266
|
+
currentPrimaryBg = style.getPropertyValue("--ap-primary-bg").trim() || currentPrimaryBg;
|
|
267
|
+
}
|
|
268
|
+
const description = getElementDescription(elementToHighlight);
|
|
269
|
+
const fileName = fileInfo.file ? fileInfo.file.split("/").pop() : "";
|
|
270
|
+
let lineInfo = "";
|
|
271
|
+
if (fileInfo.line) {
|
|
272
|
+
lineInfo = `:${fileInfo.line}`;
|
|
273
|
+
if (fileInfo.column) {
|
|
274
|
+
lineInfo += `:${fileInfo.column}`;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
const fileInfoText = fileName ? `${fileName}${lineInfo}` : "";
|
|
278
|
+
tooltipContent.value = {
|
|
279
|
+
description,
|
|
280
|
+
fileInfo: fileInfoText
|
|
281
|
+
};
|
|
282
|
+
const rect = elementToHighlight.getBoundingClientRect();
|
|
283
|
+
const newTop = `${rect.top}px`;
|
|
284
|
+
const newLeft = `${rect.left}px`;
|
|
285
|
+
const newWidth = `${rect.width}px`;
|
|
286
|
+
const newHeight = `${rect.height}px`;
|
|
287
|
+
if (highlightStyle.value.top !== newTop || highlightStyle.value.left !== newLeft || highlightStyle.value.width !== newWidth || highlightStyle.value.height !== newHeight) {
|
|
288
|
+
highlightStyle.value = {
|
|
289
|
+
top: newTop,
|
|
290
|
+
left: newLeft,
|
|
291
|
+
width: newWidth,
|
|
292
|
+
height: newHeight,
|
|
293
|
+
border: `2px solid ${currentPrimary}`,
|
|
294
|
+
background: currentPrimaryBg
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
highlightVisible.value = true;
|
|
298
|
+
tooltipVisible.value = true;
|
|
299
|
+
void (0, import_vue.nextTick)(() => {
|
|
300
|
+
const tooltipEl = document.querySelector(".aipanel-element-tooltip");
|
|
301
|
+
if (!tooltipEl) return;
|
|
302
|
+
const tooltipWidth = tooltipEl.offsetWidth;
|
|
303
|
+
const tooltipHeight = tooltipEl.offsetHeight;
|
|
304
|
+
if (tooltipWidth === 0 || tooltipHeight === 0) return;
|
|
305
|
+
const margin = 10;
|
|
306
|
+
const gap = 4;
|
|
307
|
+
const viewportWidth = window.innerWidth;
|
|
308
|
+
const viewportHeight = window.innerHeight;
|
|
309
|
+
const clampLeft = (left) => Math.max(margin, Math.min(left, viewportWidth - tooltipWidth - margin));
|
|
310
|
+
const clampTop = (top) => Math.max(margin, Math.min(top, viewportHeight - tooltipHeight - margin));
|
|
311
|
+
const candidateTop = rect.top - tooltipHeight - gap;
|
|
312
|
+
const candidateBottom = rect.bottom + gap;
|
|
313
|
+
const candidateRight = rect.right + gap;
|
|
314
|
+
const candidateLeft = rect.left - tooltipWidth - gap;
|
|
315
|
+
const verticalCenter = rect.top + (rect.height - tooltipHeight) / 2;
|
|
316
|
+
let tooltipTop = 0;
|
|
317
|
+
let tooltipLeft = 0;
|
|
318
|
+
let placed = false;
|
|
319
|
+
if (candidateTop >= margin) {
|
|
320
|
+
tooltipTop = candidateTop;
|
|
321
|
+
tooltipLeft = clampLeft(rect.left);
|
|
322
|
+
placed = true;
|
|
323
|
+
}
|
|
324
|
+
if (!placed && candidateBottom + tooltipHeight <= viewportHeight - margin) {
|
|
325
|
+
tooltipTop = candidateBottom;
|
|
326
|
+
tooltipLeft = clampLeft(rect.left);
|
|
327
|
+
placed = true;
|
|
328
|
+
}
|
|
329
|
+
if (!placed && candidateRight + tooltipWidth <= viewportWidth - margin) {
|
|
330
|
+
tooltipLeft = candidateRight;
|
|
331
|
+
tooltipTop = clampTop(verticalCenter);
|
|
332
|
+
placed = true;
|
|
333
|
+
}
|
|
334
|
+
if (!placed && candidateLeft >= margin) {
|
|
335
|
+
tooltipLeft = candidateLeft;
|
|
336
|
+
tooltipTop = clampTop(verticalCenter);
|
|
337
|
+
placed = true;
|
|
338
|
+
}
|
|
339
|
+
if (!placed) {
|
|
340
|
+
const corners = [
|
|
341
|
+
{ top: margin, left: margin },
|
|
342
|
+
{ top: margin, left: viewportWidth - tooltipWidth - margin },
|
|
343
|
+
{ top: viewportHeight - tooltipHeight - margin, left: margin },
|
|
344
|
+
{
|
|
345
|
+
top: viewportHeight - tooltipHeight - margin,
|
|
346
|
+
left: viewportWidth - tooltipWidth - margin
|
|
347
|
+
}
|
|
348
|
+
];
|
|
349
|
+
for (const corner of corners) {
|
|
350
|
+
const tooltipRight = corner.left + tooltipWidth;
|
|
351
|
+
const tooltipBottom = corner.top + tooltipHeight;
|
|
352
|
+
const overlaps = tooltipRight <= rect.left || rect.right <= corner.left || tooltipBottom <= rect.top || rect.bottom <= corner.top;
|
|
353
|
+
if (overlaps) {
|
|
354
|
+
tooltipTop = corner.top;
|
|
355
|
+
tooltipLeft = corner.left;
|
|
356
|
+
placed = true;
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (!placed) {
|
|
361
|
+
tooltipTop = margin;
|
|
362
|
+
tooltipLeft = margin;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
const newTooltipTop = `${tooltipTop}px`;
|
|
366
|
+
const newTooltipLeft = `${tooltipLeft}px`;
|
|
367
|
+
if (tooltipStyle.value.top !== newTooltipTop || tooltipStyle.value.left !== newTooltipLeft) {
|
|
368
|
+
tooltipStyle.value = {
|
|
369
|
+
top: newTooltipTop,
|
|
370
|
+
left: newTooltipLeft
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
} else {
|
|
375
|
+
highlightVisible.value = false;
|
|
376
|
+
tooltipVisible.value = false;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
const handleMouseMove = handleMouseMoveCore;
|
|
380
|
+
function setupInspectorHook() {
|
|
381
|
+
const inspector = window.__VUE_INSPECTOR__;
|
|
382
|
+
if (!inspector || inspector.__aipanel_hooked) return;
|
|
383
|
+
const originalHandleClick = inspector.handleClick.bind(inspector);
|
|
384
|
+
inspector.handleClick = function(e) {
|
|
385
|
+
if (options.selectMode.value) {
|
|
386
|
+
const targetEl = e.target instanceof Element ? e.target : null;
|
|
387
|
+
if (targetEl && targetEl.closest(".aipanel-widget")) {
|
|
388
|
+
return originalHandleClick.call(inspector, e);
|
|
389
|
+
}
|
|
390
|
+
e.preventDefault();
|
|
391
|
+
e.stopPropagation();
|
|
392
|
+
const elementToSelect = getTargetElement(e);
|
|
393
|
+
const fileInfo = getFileInfo(e, elementToSelect);
|
|
394
|
+
if (elementToSelect) {
|
|
395
|
+
const innerText = getDirectText(elementToSelect);
|
|
396
|
+
const description = getElementDescription(elementToSelect);
|
|
397
|
+
const elementInfo = {
|
|
398
|
+
filePath: fileInfo.file,
|
|
399
|
+
line: fileInfo.line,
|
|
400
|
+
column: fileInfo.column,
|
|
401
|
+
innerText: (0, import_core.truncate)(innerText, 200),
|
|
402
|
+
description
|
|
403
|
+
};
|
|
404
|
+
options.onAddSelectedNode(elementInfo);
|
|
405
|
+
}
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
return originalHandleClick.call(inspector, e);
|
|
409
|
+
};
|
|
410
|
+
inspector.__aipanel_hooked = true;
|
|
411
|
+
}
|
|
412
|
+
function handleKeydown(e) {
|
|
413
|
+
if (e.key === "Escape" && options.selectMode.value) {
|
|
414
|
+
e.preventDefault();
|
|
415
|
+
e.stopPropagation();
|
|
416
|
+
options.onExitSelectMode();
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
(0, import_vue.watch)(options.selectMode, (newVal) => {
|
|
420
|
+
const inspector = window.__VUE_INSPECTOR__;
|
|
421
|
+
if (newVal) {
|
|
422
|
+
if (inspector) {
|
|
423
|
+
inspector.enable();
|
|
424
|
+
}
|
|
425
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
426
|
+
document.addEventListener("keydown", handleKeydown, true);
|
|
427
|
+
} else {
|
|
428
|
+
if (inspector) {
|
|
429
|
+
inspector.disable();
|
|
430
|
+
}
|
|
431
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
432
|
+
document.removeEventListener("keydown", handleKeydown, true);
|
|
433
|
+
highlightVisible.value = false;
|
|
434
|
+
tooltipVisible.value = false;
|
|
435
|
+
}
|
|
436
|
+
});
|
|
437
|
+
(0, import_vue.onMounted)(() => {
|
|
438
|
+
if (window.__VUE_INSPECTOR__) {
|
|
439
|
+
setupInspectorHook();
|
|
440
|
+
} else {
|
|
441
|
+
inspectorCheckTimer = window.setInterval(() => {
|
|
442
|
+
if (window.__VUE_INSPECTOR__) {
|
|
443
|
+
setupInspectorHook();
|
|
444
|
+
if (inspectorCheckTimer) {
|
|
445
|
+
window.clearInterval(inspectorCheckTimer);
|
|
446
|
+
inspectorCheckTimer = null;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}, INSPECTOR_CHECK_INTERVAL);
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
(0, import_vue.onUnmounted)(() => {
|
|
453
|
+
if (inspectorCheckTimer) {
|
|
454
|
+
window.clearInterval(inspectorCheckTimer);
|
|
455
|
+
}
|
|
456
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
457
|
+
document.removeEventListener("keydown", handleKeydown, true);
|
|
458
|
+
});
|
|
459
|
+
return {
|
|
460
|
+
highlightVisible,
|
|
461
|
+
highlightStyle,
|
|
462
|
+
tooltipVisible,
|
|
463
|
+
tooltipStyle,
|
|
464
|
+
tooltipContent
|
|
465
|
+
};
|
|
466
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type Ref } from "vue";
|
|
2
|
+
import type { AIPanelSelectedElement } from "../src/types";
|
|
3
|
+
interface VueInspector {
|
|
4
|
+
getTargetNode: (e: MouseEvent) => {
|
|
5
|
+
targetNode: Element | null;
|
|
6
|
+
params: {
|
|
7
|
+
file?: string;
|
|
8
|
+
line?: number;
|
|
9
|
+
column?: number;
|
|
10
|
+
} | null;
|
|
11
|
+
};
|
|
12
|
+
handleClick: (e: MouseEvent) => void;
|
|
13
|
+
enable: () => void;
|
|
14
|
+
disable: () => void;
|
|
15
|
+
__aipanel_hooked?: boolean;
|
|
16
|
+
}
|
|
17
|
+
declare global {
|
|
18
|
+
interface Window {
|
|
19
|
+
__VUE_INSPECTOR__?: VueInspector;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
interface UseInspectorOptions {
|
|
23
|
+
selectMode: Ref<boolean>;
|
|
24
|
+
onAddSelectedNode: (element: AIPanelSelectedElement) => void;
|
|
25
|
+
onExitSelectMode: () => void;
|
|
26
|
+
}
|
|
27
|
+
export declare function useInspector(options: UseInspectorOptions): {
|
|
28
|
+
highlightVisible: Ref<boolean, boolean>;
|
|
29
|
+
highlightStyle: Ref<Record<string, string>, Record<string, string>>;
|
|
30
|
+
tooltipVisible: Ref<boolean, boolean>;
|
|
31
|
+
tooltipStyle: Ref<{
|
|
32
|
+
top: string;
|
|
33
|
+
left: string;
|
|
34
|
+
}, {
|
|
35
|
+
top: string;
|
|
36
|
+
left: string;
|
|
37
|
+
} | {
|
|
38
|
+
top: string;
|
|
39
|
+
left: string;
|
|
40
|
+
}>;
|
|
41
|
+
tooltipContent: Ref<{
|
|
42
|
+
description: string;
|
|
43
|
+
fileInfo: string;
|
|
44
|
+
}, {
|
|
45
|
+
description: string;
|
|
46
|
+
fileInfo: string;
|
|
47
|
+
} | {
|
|
48
|
+
description: string;
|
|
49
|
+
fileInfo: string;
|
|
50
|
+
}>;
|
|
51
|
+
};
|
|
52
|
+
export {};
|