@zargaryanvh/react-component-inspector 1.0.8 → 1.0.9

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.
@@ -136,26 +136,18 @@ export const InspectionTooltip = () => {
136
136
  propsSignature: "default",
137
137
  sourceFile: "DOM",
138
138
  } : null);
139
- // Compute anchor position once per element change. The value is intentionally
140
- // NOT recomputed when tooltipSize updates (ResizeObserver may fire several
141
- // times as the tooltip's content renders) recomputing on every size update
142
- // makes the tooltip visibly slide and shrink as it settles. Pin location is
143
- // chosen as: below the element if there's room, otherwise above, right, left,
144
- // and finally a fixed corner for elements that fill the viewport.
145
- const tooltipSizeRef = useRef(tooltipSize);
146
- tooltipSizeRef.current = tooltipSize;
147
- const [anchoredPosition, setAnchoredPosition] = useState(null);
148
- useEffect(() => {
149
- if (!hoveredElement || !document.body.contains(hoveredElement)) {
150
- setAnchoredPosition(null);
151
- return;
152
- }
139
+ // Compute anchor based on the hovered element's rect. We re-run this when
140
+ // either the element or the measured tooltip size changes, but the state
141
+ // setter keeps the previous position whenever it still fits the tooltip in
142
+ // the viewport. That preserves a single stable position per element while
143
+ // self-correcting when the tooltip grows past the viewport bound (the case
144
+ // where content renders larger than the initial estimate).
145
+ const computeAnchor = (element, w, h) => {
153
146
  const padding = 10;
154
147
  const gap = 8;
155
- const { w, h } = tooltipSizeRef.current;
156
148
  const vw = window.innerWidth;
157
149
  const vh = window.innerHeight;
158
- const rect = hoveredElement.getBoundingClientRect();
150
+ const rect = element.getBoundingClientRect();
159
151
  const spaceBelow = vh - rect.bottom;
160
152
  const spaceAbove = rect.top;
161
153
  const spaceRight = vw - rect.right;
@@ -184,8 +176,35 @@ export const InspectionTooltip = () => {
184
176
  x = cx < vw / 2 ? vw - w - padding : padding;
185
177
  y = cy < vh / 2 ? vh - h - padding : padding;
186
178
  }
187
- setAnchoredPosition(clampToViewport(x, y, w, h));
188
- }, [hoveredElement]);
179
+ return clampToViewport(x, y, w, h);
180
+ };
181
+ const [anchoredPosition, setAnchoredPosition] = useState(null);
182
+ const anchoredForElementRef = useRef(null);
183
+ useEffect(() => {
184
+ if (!hoveredElement || !document.body.contains(hoveredElement)) {
185
+ setAnchoredPosition(null);
186
+ anchoredForElementRef.current = null;
187
+ return;
188
+ }
189
+ const { w, h } = tooltipSize;
190
+ const padding = 10;
191
+ const vw = window.innerWidth;
192
+ const vh = window.innerHeight;
193
+ setAnchoredPosition((prev) => {
194
+ const elementChanged = anchoredForElementRef.current !== hoveredElement;
195
+ const fitsNow = !!prev &&
196
+ prev.x >= padding &&
197
+ prev.y >= padding &&
198
+ prev.x + w <= vw - padding &&
199
+ prev.y + h <= vh - padding;
200
+ // Keep the existing anchor whenever it still fits — this is what stops
201
+ // the tooltip from sliding as the ResizeObserver settles content size.
202
+ if (!elementChanged && fitsNow)
203
+ return prev;
204
+ anchoredForElementRef.current = hoveredElement;
205
+ return computeAnchor(hoveredElement, w, h);
206
+ });
207
+ }, [hoveredElement, tooltipSize]);
189
208
  const positionFromElement = anchoredPosition;
190
209
  // Position is anchored to the hovered element's rect, not the cursor. This
191
210
  // keeps the tooltip static while the cursor moves around inside one element
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zargaryanvh/react-component-inspector",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "A development tool for inspecting React components with AI-friendly metadata extraction",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",