@stsgs1980/fab-inspector 3.4.1 → 3.5.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 (61) hide show
  1. package/README.md +27 -0
  2. package/dist/api-source-route.d.ts +14 -0
  3. package/dist/api-source-route.d.ts.map +1 -0
  4. package/dist/api-source-route.js +54 -0
  5. package/dist/api-source-route.js.map +1 -0
  6. package/dist/box-model-section.d.ts +5 -0
  7. package/dist/box-model-section.d.ts.map +1 -0
  8. package/dist/box-model-section.js +15 -0
  9. package/dist/box-model-section.js.map +1 -0
  10. package/dist/highlight-overlay.d.ts +4 -0
  11. package/dist/highlight-overlay.d.ts.map +1 -0
  12. package/dist/highlight-overlay.js +14 -0
  13. package/dist/highlight-overlay.js.map +1 -0
  14. package/dist/index.d.ts +4 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +3 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/inspector-fab.d.ts +6 -0
  19. package/dist/inspector-fab.d.ts.map +1 -0
  20. package/dist/inspector-fab.js +14 -0
  21. package/dist/inspector-fab.js.map +1 -0
  22. package/dist/inspector-panel.d.ts +14 -0
  23. package/dist/inspector-panel.d.ts.map +1 -0
  24. package/dist/inspector-panel.js +36 -0
  25. package/dist/inspector-panel.js.map +1 -0
  26. package/dist/panel-sections.d.ts +25 -0
  27. package/dist/panel-sections.d.ts.map +1 -0
  28. package/dist/panel-sections.js +48 -0
  29. package/dist/panel-sections.js.map +1 -0
  30. package/dist/plugins/data-src-plugin.d.ts +38 -0
  31. package/dist/plugins/data-src-plugin.d.ts.map +1 -0
  32. package/dist/plugins/data-src-plugin.js +90 -0
  33. package/dist/plugins/data-src-plugin.js.map +1 -0
  34. package/dist/select-element-fab.d.ts +2 -0
  35. package/dist/select-element-fab.d.ts.map +1 -0
  36. package/{select-element-fab.tsx → dist/select-element-fab.js} +8 -45
  37. package/dist/select-element-fab.js.map +1 -0
  38. package/dist/types.d.ts +43 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +2 -0
  41. package/dist/types.js.map +1 -0
  42. package/dist/use-element-inspector.d.ts +19 -0
  43. package/dist/use-element-inspector.d.ts.map +1 -0
  44. package/dist/use-element-inspector.js +239 -0
  45. package/dist/use-element-inspector.js.map +1 -0
  46. package/dist/use-panel-drag.d.ts +11 -0
  47. package/dist/use-panel-drag.d.ts.map +1 -0
  48. package/dist/use-panel-drag.js +35 -0
  49. package/dist/use-panel-drag.js.map +1 -0
  50. package/package.json +25 -9
  51. package/api-source-route.ts +0 -60
  52. package/box-model-section.tsx +0 -97
  53. package/highlight-overlay.tsx +0 -23
  54. package/index.ts +0 -10
  55. package/inspector-fab.tsx +0 -63
  56. package/inspector-panel.tsx +0 -190
  57. package/panel-sections.tsx +0 -207
  58. package/plugins/data-src-plugin.ts +0 -110
  59. package/types.ts +0 -45
  60. package/use-element-inspector.ts +0 -264
  61. package/use-panel-drag.ts +0 -47
@@ -1,59 +1,22 @@
1
1
  'use client';
2
-
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { AnimatePresence } from 'framer-motion';
4
4
  import { useElementInspector } from './use-element-inspector';
5
5
  import { usePanelDrag } from './use-panel-drag';
6
6
  import { HighlightOverlay } from './highlight-overlay';
7
7
  import { InspectorPanel } from './inspector-panel';
8
8
  import { InspectorFab } from './inspector-fab';
9
-
10
9
  // Dev-only guard: FAB не должен попасть в production-bundle.
11
10
  // Это страховка на случай, если потребитель забыл поставить пакет
12
11
  // в devDependencies или не убрал импорт из layout для прод-сборки.
13
12
  // В проде next/build подставляет NODE_ENV=production и tree-shaking
14
13
  // вырезает весь модуль целиком (sideEffects: false в package.json).
15
14
  const IS_DEV = process.env.NODE_ENV === 'development';
16
-
17
15
  export function SelectElementFab() {
18
- const {
19
- active,
20
- elementInfo,
21
- panelPos,
22
- setPanelPos,
23
- highlightBox,
24
- snippet,
25
- snippetLoading,
26
- toggleActive,
27
- closePanel,
28
- } = useElementInspector();
29
-
30
- const { isDragging, handleDragStart } = usePanelDrag(panelPos, setPanelPos);
31
-
32
- if (!IS_DEV) return null;
33
-
34
- return (
35
- <>
36
- {active && highlightBox && <HighlightOverlay highlightBox={highlightBox} />}
37
-
38
- <AnimatePresence>
39
- {active && elementInfo && (
40
- <InspectorPanel
41
- elementInfo={elementInfo}
42
- panelPos={panelPos}
43
- isDragging={isDragging}
44
- onDragStart={handleDragStart}
45
- onClose={closePanel}
46
- snippet={snippet}
47
- snippetLoading={snippetLoading}
48
- />
49
- )}
50
- </AnimatePresence>
51
-
52
- <InspectorFab
53
- active={active}
54
- onToggle={toggleActive}
55
- showTooltip={active && !elementInfo}
56
- />
57
- </>
58
- );
59
- }
16
+ const { active, elementInfo, panelPos, setPanelPos, highlightBox, snippet, snippetLoading, toggleActive, closePanel, } = useElementInspector();
17
+ const { isDragging, handleDragStart } = usePanelDrag(panelPos, setPanelPos);
18
+ if (!IS_DEV)
19
+ return null;
20
+ return (_jsxs(_Fragment, { children: [active && highlightBox && _jsx(HighlightOverlay, { highlightBox: highlightBox }), _jsx(AnimatePresence, { children: active && elementInfo && (_jsx(InspectorPanel, { elementInfo: elementInfo, panelPos: panelPos, isDragging: isDragging, onDragStart: handleDragStart, onClose: closePanel, snippet: snippet, snippetLoading: snippetLoading })) }), _jsx(InspectorFab, { active: active, onToggle: toggleActive, showTooltip: active && !elementInfo })] }));
21
+ }
22
+ //# sourceMappingURL=select-element-fab.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"select-element-fab.js","sourceRoot":"","sources":["../select-element-fab.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,6DAA6D;AAC7D,kEAAkE;AAClE,mEAAmE;AACnE,oEAAoE;AACpE,oEAAoE;AACpE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC;AAEtD,MAAM,UAAU,gBAAgB;IAC9B,MAAM,EACJ,MAAM,EACN,WAAW,EACX,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,OAAO,EACP,cAAc,EACd,YAAY,EACZ,UAAU,GACX,GAAG,mBAAmB,EAAE,CAAC;IAE1B,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,YAAY,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAE5E,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,OAAO,CACL,8BACG,MAAM,IAAI,YAAY,IAAI,KAAC,gBAAgB,IAAC,YAAY,EAAE,YAAY,GAAI,EAE3E,KAAC,eAAe,cACb,MAAM,IAAI,WAAW,IAAI,CACxB,KAAC,cAAc,IACb,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,eAAe,EAC5B,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,OAAO,EAChB,cAAc,EAAE,cAAc,GAC9B,CACH,GACe,EAElB,KAAC,YAAY,IACX,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,YAAY,EACtB,WAAW,EAAE,MAAM,IAAI,CAAC,WAAW,GACnC,IACD,CACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,43 @@
1
+ export interface SourceInfo {
2
+ file: string;
3
+ line: number;
4
+ }
5
+ export interface BoxModel {
6
+ marginTop: string;
7
+ marginRight: string;
8
+ marginBottom: string;
9
+ marginLeft: string;
10
+ paddingTop: string;
11
+ paddingRight: string;
12
+ paddingBottom: string;
13
+ paddingLeft: string;
14
+ borderTop: string;
15
+ borderRight: string;
16
+ borderBottom: string;
17
+ borderLeft: string;
18
+ width: string;
19
+ height: string;
20
+ }
21
+ export interface ElementInfo {
22
+ tag: string;
23
+ id: string;
24
+ classes: string;
25
+ rect: DOMRect;
26
+ text: string;
27
+ outerHTML: string;
28
+ cssPath: string;
29
+ computedStyles: Record<string, string>;
30
+ boxModel: BoxModel | null;
31
+ source: SourceInfo | null;
32
+ }
33
+ export interface SnippetData {
34
+ file: string;
35
+ line: number;
36
+ totalLines: number;
37
+ snippet: {
38
+ startLine: number;
39
+ lines: string[];
40
+ highlightLine: number;
41
+ };
42
+ }
43
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;CACH"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,19 @@
1
+ import type { ElementInfo, SnippetData } from './types';
2
+ export declare function useElementInspector(): {
3
+ active: boolean;
4
+ elementInfo: ElementInfo | null;
5
+ panelPos: {
6
+ x: number;
7
+ y: number;
8
+ };
9
+ setPanelPos: import("react").Dispatch<import("react").SetStateAction<{
10
+ x: number;
11
+ y: number;
12
+ }>>;
13
+ highlightBox: DOMRect | null;
14
+ snippet: SnippetData | null;
15
+ snippetLoading: boolean;
16
+ toggleActive: () => void;
17
+ closePanel: () => void;
18
+ };
19
+ //# sourceMappingURL=use-element-inspector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-element-inspector.d.ts","sourceRoot":"","sources":["../use-element-inspector.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAwB,MAAM,SAAS,CAAC;AA2I9E,wBAAgB,mBAAmB;;;;;;;;;;;;;;;;EA2HlC"}
@@ -0,0 +1,239 @@
1
+ import { useState, useCallback, useEffect } from 'react';
2
+ function findSource(el) {
3
+ let current = el;
4
+ while (current) {
5
+ const src = current.getAttribute('data-src');
6
+ if (src) {
7
+ const lastColon = src.lastIndexOf(':');
8
+ if (lastColon > 0) {
9
+ return {
10
+ file: src.slice(0, lastColon),
11
+ line: parseInt(src.slice(lastColon + 1), 10) || 1,
12
+ };
13
+ }
14
+ return { file: src, line: 1 };
15
+ }
16
+ current = current.parentElement;
17
+ }
18
+ return null;
19
+ }
20
+ function getCssPath(el) {
21
+ const parts = [];
22
+ let current = el;
23
+ while (current && current !== document.body && current !== document.documentElement) {
24
+ let selector = current.tagName.toLowerCase();
25
+ if (current.id) {
26
+ selector += '#' + current.id;
27
+ parts.unshift(selector);
28
+ break;
29
+ }
30
+ const parent = current.parentElement;
31
+ if (parent) {
32
+ const siblings = Array.from(parent.children).filter((c) => c.tagName === current.tagName);
33
+ if (siblings.length > 1) {
34
+ const index = siblings.indexOf(current) + 1;
35
+ selector += `:nth-of-type(${index})`;
36
+ }
37
+ }
38
+ parts.unshift(selector);
39
+ current = parent;
40
+ }
41
+ return parts.join(' > ');
42
+ }
43
+ function getTextForInspector(el) {
44
+ const TEXT_TAGS = new Set([
45
+ 'H1', 'H2', 'H3', 'H4', 'H5', 'H6',
46
+ 'BUTTON', 'A', 'LABEL', 'P', 'SPAN', 'LI', 'TD', 'TH', 'DT', 'DD',
47
+ ]);
48
+ if (!TEXT_TAGS.has(el.tagName))
49
+ return '';
50
+ // Только прямые текстовые узлы — без содержимого дочерних элементов.
51
+ // Для <span><Icon /> Wiki Codex <em>v2</em></span> вернёт "Wiki Codex",
52
+ // а не "Wiki Codex v2" (как textContent).
53
+ let direct = '';
54
+ for (const node of Array.from(el.childNodes)) {
55
+ if (node.nodeType === Node.TEXT_NODE && node.textContent) {
56
+ direct += node.textContent;
57
+ }
58
+ }
59
+ const directTrim = direct.trim();
60
+ // Если прямого текста нет (всё во вложенных) — fallback на textContent,
61
+ // чтобы не потерять <button><Icon />Save</button> (там текст прямой,
62
+ // но иногда иконка съедает весь текст).
63
+ const fallback = (el.textContent || '').trim();
64
+ const result = directTrim || fallback;
65
+ return result.slice(0, 120);
66
+ }
67
+ function getElementInfo(el) {
68
+ const rect = el.getBoundingClientRect();
69
+ const cs = window.getComputedStyle(el);
70
+ if (el.closest('[data-se-fab]') ||
71
+ el.closest('[data-se-panel]') ||
72
+ el.closest('[data-se-highlight]')) {
73
+ return null;
74
+ }
75
+ let outerHTML = el.outerHTML;
76
+ if (outerHTML.length > 2000) {
77
+ outerHTML = outerHTML.slice(0, 2000) + '\n ...';
78
+ }
79
+ return {
80
+ tag: el.tagName.toLowerCase(),
81
+ id: el.id || '',
82
+ classes: typeof el.className === 'string' ? el.className : '',
83
+ rect,
84
+ text: getTextForInspector(el),
85
+ outerHTML,
86
+ cssPath: getCssPath(el),
87
+ computedStyles: {
88
+ fontSize: cs.fontSize,
89
+ fontWeight: cs.fontWeight,
90
+ color: cs.color,
91
+ lineHeight: cs.lineHeight,
92
+ width: `${Math.round(rect.width)}px`,
93
+ height: `${Math.round(rect.height)}px`,
94
+ },
95
+ boxModel: {
96
+ marginTop: cs.marginTop,
97
+ marginRight: cs.marginRight,
98
+ marginBottom: cs.marginBottom,
99
+ marginLeft: cs.marginLeft,
100
+ paddingTop: cs.paddingTop,
101
+ paddingRight: cs.paddingRight,
102
+ paddingBottom: cs.paddingBottom,
103
+ paddingLeft: cs.paddingLeft,
104
+ borderTop: cs.borderTopWidth,
105
+ borderRight: cs.borderRightWidth,
106
+ borderBottom: cs.borderBottomWidth,
107
+ borderLeft: cs.borderLeftWidth,
108
+ width: cs.width,
109
+ height: cs.height,
110
+ },
111
+ source: findSource(el),
112
+ };
113
+ }
114
+ function computePanelPos(rect) {
115
+ const panelW = 380;
116
+ const panelH = 400;
117
+ let x = rect.right + 8;
118
+ let y = rect.top;
119
+ if (x + panelW > window.innerWidth - 16) {
120
+ x = rect.left - panelW - 8;
121
+ }
122
+ if (x < 8)
123
+ x = 8;
124
+ if (y + panelH > window.innerHeight - 16) {
125
+ y = window.innerHeight - panelH - 16;
126
+ }
127
+ if (y < 8)
128
+ y = 8;
129
+ return { x, y };
130
+ }
131
+ export function useElementInspector() {
132
+ const [active, setActive] = useState(false);
133
+ const [elementInfo, setElementInfo] = useState(null);
134
+ const [panelPos, setPanelPos] = useState({ x: 0, y: 0 });
135
+ const [highlightBox, setHighlightBox] = useState(null);
136
+ const [snippet, setSnippet] = useState(null);
137
+ const [snippetLoading, setSnippetLoading] = useState(false);
138
+ const fetchSnippet = useCallback(async (file, line) => {
139
+ setSnippetLoading(true);
140
+ setSnippet(null);
141
+ try {
142
+ const res = await fetch(`/api/source?file=${encodeURIComponent(file)}&line=${line}&ctx=10`);
143
+ if (res.ok) {
144
+ const data = await res.json();
145
+ setSnippet(data);
146
+ }
147
+ }
148
+ catch {
149
+ // ignore
150
+ }
151
+ setSnippetLoading(false);
152
+ }, []);
153
+ const handleMouseMove = useCallback((e) => {
154
+ const target = e.target;
155
+ if (target.closest('[data-se-fab]') ||
156
+ target.closest('[data-se-panel]') ||
157
+ target.closest('[data-se-highlight]')) {
158
+ setHighlightBox(null);
159
+ return;
160
+ }
161
+ setHighlightBox(target.getBoundingClientRect());
162
+ }, []);
163
+ const handleClick = useCallback((e) => {
164
+ const target = e.target;
165
+ if (target.closest('[data-se-fab]') ||
166
+ target.closest('[data-se-panel]') ||
167
+ target.closest('[data-se-highlight]')) {
168
+ return;
169
+ }
170
+ e.preventDefault();
171
+ e.stopPropagation();
172
+ const info = getElementInfo(target);
173
+ if (info) {
174
+ setElementInfo(info);
175
+ setSnippet(null);
176
+ setPanelPos(computePanelPos(info.rect));
177
+ if (info.source) {
178
+ fetchSnippet(info.source.file, info.source.line);
179
+ }
180
+ }
181
+ }, [fetchSnippet]);
182
+ const handleScroll = useCallback(() => {
183
+ setHighlightBox(null);
184
+ }, []);
185
+ useEffect(() => {
186
+ if (!active)
187
+ return;
188
+ document.addEventListener('mousemove', handleMouseMove, true);
189
+ document.addEventListener('click', handleClick, true);
190
+ document.addEventListener('scroll', handleScroll, true);
191
+ document.body.style.cursor = 'crosshair';
192
+ return () => {
193
+ document.removeEventListener('mousemove', handleMouseMove, true);
194
+ document.removeEventListener('click', handleClick, true);
195
+ document.removeEventListener('scroll', handleScroll, true);
196
+ document.body.style.cursor = '';
197
+ };
198
+ }, [active, handleMouseMove, handleClick, handleScroll]);
199
+ useEffect(() => {
200
+ if (!active)
201
+ return;
202
+ const handler = (e) => {
203
+ if (e.key === 'Escape') {
204
+ setActive(false);
205
+ setElementInfo(null);
206
+ setHighlightBox(null);
207
+ setSnippet(null);
208
+ }
209
+ };
210
+ window.addEventListener('keydown', handler);
211
+ return () => window.removeEventListener('keydown', handler);
212
+ }, [active]);
213
+ const toggleActive = useCallback(() => {
214
+ setActive((v) => {
215
+ const next = !v;
216
+ if (!next) {
217
+ setElementInfo(null);
218
+ setHighlightBox(null);
219
+ setSnippet(null);
220
+ }
221
+ return next;
222
+ });
223
+ }, []);
224
+ const closePanel = useCallback(() => {
225
+ setElementInfo(null);
226
+ }, []);
227
+ return {
228
+ active,
229
+ elementInfo,
230
+ panelPos,
231
+ setPanelPos,
232
+ highlightBox,
233
+ snippet,
234
+ snippetLoading,
235
+ toggleActive,
236
+ closePanel,
237
+ };
238
+ }
239
+ //# sourceMappingURL=use-element-inspector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-element-inspector.js","sourceRoot":"","sources":["../use-element-inspector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare function usePanelDrag(panelPos: {
2
+ x: number;
3
+ y: number;
4
+ }, setPanelPos: (pos: {
5
+ x: number;
6
+ y: number;
7
+ }) => void): {
8
+ isDragging: boolean;
9
+ handleDragStart: (e: React.MouseEvent) => void;
10
+ };
11
+ //# sourceMappingURL=use-panel-drag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-panel-drag.d.ts","sourceRoot":"","sources":["../use-panel-drag.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAC1B,QAAQ,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAClC,WAAW,EAAE,CAAC,GAAG,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI;;yBAW9C,KAAK,CAAC,UAAU;EA+BvB"}
@@ -0,0 +1,35 @@
1
+ import { useState, useCallback, useRef } from 'react';
2
+ export function usePanelDrag(panelPos, setPanelPos) {
3
+ const [isDragging, setIsDragging] = useState(false);
4
+ const dragRef = useRef(null);
5
+ const handleDragStart = useCallback((e) => {
6
+ e.preventDefault();
7
+ setIsDragging(true);
8
+ dragRef.current = {
9
+ startX: e.clientX,
10
+ startY: e.clientY,
11
+ startLeft: panelPos.x,
12
+ startTop: panelPos.y,
13
+ };
14
+ const onMove = (ev) => {
15
+ if (!dragRef.current)
16
+ return;
17
+ const dx = ev.clientX - dragRef.current.startX;
18
+ const dy = ev.clientY - dragRef.current.startY;
19
+ setPanelPos({
20
+ x: Math.max(0, Math.min(window.innerWidth - 396, dragRef.current.startLeft + dx)),
21
+ y: Math.max(0, Math.min(window.innerHeight - 48, dragRef.current.startTop + dy)),
22
+ });
23
+ };
24
+ const onUp = () => {
25
+ setIsDragging(false);
26
+ dragRef.current = null;
27
+ document.removeEventListener('mousemove', onMove);
28
+ document.removeEventListener('mouseup', onUp);
29
+ };
30
+ document.addEventListener('mousemove', onMove);
31
+ document.addEventListener('mouseup', onUp);
32
+ }, [panelPos, setPanelPos]);
33
+ return { isDragging, handleDragStart };
34
+ }
35
+ //# sourceMappingURL=use-panel-drag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-panel-drag.js","sourceRoot":"","sources":["../use-panel-drag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAEtD,MAAM,UAAU,YAAY,CAC1B,QAAkC,EAClC,WAAoD;IAEpD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,MAAM,CAKZ,IAAI,CAAC,CAAC;IAEhB,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,CAAmB,EAAE,EAAE;QACtB,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO,CAAC,OAAO,GAAG;YAChB,MAAM,EAAE,CAAC,CAAC,OAAO;YACjB,MAAM,EAAE,CAAC,CAAC,OAAO;YACjB,SAAS,EAAE,QAAQ,CAAC,CAAC;YACrB,QAAQ,EAAE,QAAQ,CAAC,CAAC;SACrB,CAAC;QACF,MAAM,MAAM,GAAG,CAAC,EAAc,EAAE,EAAE;YAChC,IAAI,CAAC,OAAO,CAAC,OAAO;gBAAE,OAAO;YAC7B,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;YAC/C,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;YAC/C,WAAW,CAAC;gBACV,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC;gBACjF,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,GAAG,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC;aACjF,CAAC,CAAC;QACL,CAAC,CAAC;QACF,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;YACvB,QAAQ,CAAC,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YAClD,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAChD,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC/C,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC7C,CAAC,EACD,CAAC,QAAQ,EAAE,WAAW,CAAC,CACxB,CAAC;IAEF,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC;AACzC,CAAC"}
package/package.json CHANGED
@@ -1,9 +1,14 @@
1
1
  {
2
2
  "name": "@stsgs1980/fab-inspector",
3
- "version": "3.4.1",
3
+ "version": "3.5.0",
4
4
  "description": "Visual element inspector for Next.js dev mode — GitHub Dark themed, with SyntaxHighlighter and Box-model visualization.",
5
5
  "license": "MIT",
6
6
  "author": "STS",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "sideEffects": false,
7
12
  "repository": {
8
13
  "type": "git",
9
14
  "url": "https://github.com/stsgs1980/FabInspector.git"
@@ -25,6 +30,8 @@
25
30
  "react-syntax-highlighter": ">=15.0.0"
26
31
  },
27
32
  "scripts": {
33
+ "build": "tsc -p tsconfig.build.json",
34
+ "prepublishOnly": "npm run build",
28
35
  "install:inspector": "bash scripts/install.sh",
29
36
  "uninstall:inspector": "bash scripts/uninstall.sh",
30
37
  "update:inspector": "bash scripts/update.sh",
@@ -33,23 +40,32 @@
33
40
  "typecheck": "tsc --noEmit"
34
41
  },
35
42
  "exports": {
36
- ".": "./index.ts",
37
- "./types": "./types.ts",
38
- "./api/source": "./api-source-route.ts",
39
- "./plugins/data-src-plugin": "./plugins/data-src-plugin.ts",
43
+ ".": {
44
+ "types": "./dist/index.d.ts",
45
+ "default": "./dist/index.js"
46
+ },
47
+ "./types": {
48
+ "types": "./dist/types.d.ts",
49
+ "default": "./dist/types.js"
50
+ },
51
+ "./api/source": {
52
+ "types": "./dist/api-source-route.d.ts",
53
+ "default": "./dist/api-source-route.js"
54
+ },
55
+ "./plugins/data-src-plugin": {
56
+ "types": "./dist/plugins/data-src-plugin.d.ts",
57
+ "default": "./dist/plugins/data-src-plugin.js"
58
+ },
40
59
  "./package.json": "./package.json"
41
60
  },
42
61
  "bin": {
43
62
  "fab-inspector": "./cli/init.mjs"
44
63
  },
45
64
  "files": [
46
- "*.ts",
47
- "*.tsx",
48
- "plugins/",
65
+ "dist/",
49
66
  "cli/",
50
67
  "README.md"
51
68
  ],
52
- "sideEffects": false,
53
69
  "publishConfig": {
54
70
  "access": "public"
55
71
  }
@@ -1,60 +0,0 @@
1
- // Шаблон API-роута для установки.
2
- // В проекте-потребителе создайте src/app/api/source/route.ts:
3
- // export { GET } from '@stsgs1980/fab-inspector/api/source';
4
- // Либо, если модуль подключён как локальный путь:
5
- // export { GET } from '@/components/inspector/api-source-route';
6
-
7
- import { NextRequest, NextResponse } from 'next/server';
8
- import { readFile } from 'fs/promises';
9
- import { resolve } from 'path';
10
-
11
- // process.cwd() в Next.js = корень проекта-потребителя.
12
- // Никаких '..' — иначе путь уходит за пределы проекта и isAllowed() всегда false.
13
- const PROJECT_ROOT = process.cwd();
14
- const ALLOWED_PREFIXES = [
15
- resolve(PROJECT_ROOT, 'src/components/'),
16
- resolve(PROJECT_ROOT, 'src/app/'),
17
- resolve(PROJECT_ROOT, 'src/content/'),
18
- resolve(PROJECT_ROOT, 'src/hooks/'),
19
- resolve(PROJECT_ROOT, 'src/lib/'),
20
- ];
21
-
22
- function isAllowed(filePath: string): boolean {
23
- const resolved = resolve(PROJECT_ROOT, filePath);
24
- return ALLOWED_PREFIXES.some((prefix) => resolved.startsWith(prefix));
25
- }
26
-
27
- export async function GET(request: NextRequest) {
28
- const { searchParams } = new URL(request.url);
29
- const file = searchParams.get('file');
30
- const line = parseInt(searchParams.get('line') || '1', 10);
31
- const ctx = parseInt(searchParams.get('ctx') || '8', 10);
32
-
33
- if (!file || !isAllowed(file)) {
34
- return NextResponse.json({ error: 'File not allowed' }, { status: 403 });
35
- }
36
-
37
- try {
38
- const filePath = resolve(PROJECT_ROOT, file);
39
- const content = await readFile(filePath, 'utf-8');
40
- const lines = content.split('\n');
41
-
42
- const start = Math.max(0, line - 1 - ctx);
43
- const end = Math.min(lines.length, line - 1 + ctx + 1);
44
- const snippet = lines.slice(start, end);
45
- const startLine = start + 1;
46
-
47
- return NextResponse.json({
48
- file,
49
- line,
50
- totalLines: lines.length,
51
- snippet: {
52
- startLine,
53
- lines: snippet,
54
- highlightLine: line,
55
- },
56
- });
57
- } catch {
58
- return NextResponse.json({ error: 'File not found' }, { status: 404 });
59
- }
60
- }