made-refine 0.2.13 → 0.2.16

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/dist/index.js CHANGED
@@ -197,6 +197,228 @@ function getZoomScale() {
197
197
  return snap.active ? snap.zoom : 1;
198
198
  }
199
199
 
200
+ // src/utils/react-fiber.ts
201
+ function getFiberForElement(element) {
202
+ if (typeof window !== "undefined") {
203
+ const devtools = window.__DIRECT_EDIT_DEVTOOLS__;
204
+ if (devtools?.getFiberForElement) {
205
+ const fiber = devtools.getFiberForElement(element);
206
+ if (fiber) return fiber;
207
+ }
208
+ }
209
+ const fiberKey = Object.keys(element).find(
210
+ (key) => key.startsWith("__reactFiber$") || key.startsWith("__reactInternalInstance$")
211
+ );
212
+ if (!fiberKey) return null;
213
+ return element[fiberKey] || null;
214
+ }
215
+ function getSourceFromFiber(fiber) {
216
+ const debugSource = fiber?._debugSource;
217
+ if (debugSource?.fileName) return debugSource;
218
+ const owner = fiber?._debugOwner;
219
+ const ownerPending = owner?.pendingProps?.__source;
220
+ if (ownerPending?.fileName) return ownerPending;
221
+ const ownerMemo = owner?.memoizedProps?.__source;
222
+ if (ownerMemo?.fileName) return ownerMemo;
223
+ const pending = fiber?.pendingProps?.__source;
224
+ if (pending?.fileName) return pending;
225
+ const memo = fiber?.memoizedProps?.__source;
226
+ if (memo?.fileName) return memo;
227
+ return null;
228
+ }
229
+ function buildFrame(fiber) {
230
+ const type = fiber?.type;
231
+ if (typeof type !== "function" && typeof type !== "object") return null;
232
+ const name = type?.displayName || type?.name || null;
233
+ if (!name || name === "Fragment") return null;
234
+ const frame = { name };
235
+ const source = getSourceFromFiber(fiber);
236
+ if (source?.fileName) {
237
+ frame.file = source.fileName;
238
+ if (typeof source.lineNumber === "number") {
239
+ frame.line = source.lineNumber;
240
+ }
241
+ if (typeof source.columnNumber === "number") {
242
+ frame.column = source.columnNumber;
243
+ }
244
+ }
245
+ return frame;
246
+ }
247
+ function shouldIncludeFrame(frame, lastFrame) {
248
+ if (!lastFrame) return true;
249
+ if (frame.name !== lastFrame.name) return true;
250
+ if (!lastFrame.file && frame.file) return true;
251
+ if (lastFrame.file && frame.file && lastFrame.line == null && frame.line != null) return true;
252
+ if (lastFrame.file && frame.file && lastFrame.line != null && frame.line != null && lastFrame.column == null && frame.column != null) {
253
+ return true;
254
+ }
255
+ return false;
256
+ }
257
+ function getOwnerStack(fiber) {
258
+ const frames = [];
259
+ let current = fiber;
260
+ let lastFrame = null;
261
+ let nearestComponentFiber = null;
262
+ while (current) {
263
+ const frame = buildFrame(current);
264
+ if (frame && shouldIncludeFrame(frame, lastFrame)) {
265
+ frames.push(frame);
266
+ lastFrame = frame;
267
+ if (!nearestComponentFiber) {
268
+ nearestComponentFiber = current;
269
+ }
270
+ }
271
+ current = current._debugOwner;
272
+ }
273
+ return { frames, nearestComponentFiber };
274
+ }
275
+ function getRenderStack(fiber) {
276
+ const frames = [];
277
+ let current = fiber;
278
+ let lastFrame = null;
279
+ let nearestComponentFiber = null;
280
+ while (current) {
281
+ const frame = buildFrame(current);
282
+ if (frame && shouldIncludeFrame(frame, lastFrame)) {
283
+ frames.push(frame);
284
+ lastFrame = frame;
285
+ if (!nearestComponentFiber) {
286
+ nearestComponentFiber = current;
287
+ }
288
+ }
289
+ current = current.return;
290
+ }
291
+ return { frames, nearestComponentFiber };
292
+ }
293
+ function getReactComponentInfo(element) {
294
+ const fiber = getFiberForElement(element);
295
+ if (!fiber) return { frames: [], nearestComponentFiber: null };
296
+ const elementSource = getSourceFromFiber(fiber);
297
+ const elementSourceFile = elementSource?.fileName || void 0;
298
+ const ownerResult = getOwnerStack(fiber);
299
+ if (ownerResult.frames.length > 0) {
300
+ return { ...ownerResult, elementSourceFile };
301
+ }
302
+ return { ...getRenderStack(fiber), elementSourceFile };
303
+ }
304
+ var EXCLUDED_PROP_KEYS = /* @__PURE__ */ new Set([
305
+ "className",
306
+ "style",
307
+ "children",
308
+ "ref",
309
+ "key",
310
+ "render"
311
+ ]);
312
+ function serializePropValue(value) {
313
+ if (typeof value === "function") return "[function]";
314
+ if (typeof value === "symbol") return void 0;
315
+ if (value === void 0) return void 0;
316
+ if (value !== null && typeof value === "object") {
317
+ if ("$$typeof" in value) return "[element]";
318
+ try {
319
+ JSON.stringify(value);
320
+ return value;
321
+ } catch {
322
+ return "[object]";
323
+ }
324
+ }
325
+ return value;
326
+ }
327
+ function getComponentProps(fiber) {
328
+ const props = fiber?.memoizedProps ?? fiber?.pendingProps;
329
+ if (!props || typeof props !== "object") return {};
330
+ const result = {};
331
+ for (const [key, value] of Object.entries(props)) {
332
+ if (EXCLUDED_PROP_KEYS.has(key)) continue;
333
+ if (key.startsWith("data-")) continue;
334
+ const serialized = serializePropValue(value);
335
+ if (serialized !== void 0) {
336
+ result[key] = serialized;
337
+ }
338
+ }
339
+ return result;
340
+ }
341
+ function getCallSiteSource(fiber) {
342
+ const source = fiber?._debugSource;
343
+ if (source?.fileName) {
344
+ return {
345
+ file: source.fileName,
346
+ line: typeof source.lineNumber === "number" ? source.lineNumber : void 0,
347
+ column: typeof source.columnNumber === "number" ? source.columnNumber : void 0
348
+ };
349
+ }
350
+ const pending = fiber?.pendingProps?.__source;
351
+ if (pending?.fileName) {
352
+ return {
353
+ file: pending.fileName,
354
+ line: typeof pending.lineNumber === "number" ? pending.lineNumber : void 0,
355
+ column: typeof pending.columnNumber === "number" ? pending.columnNumber : void 0
356
+ };
357
+ }
358
+ return null;
359
+ }
360
+ function deriveDefinitionSource(frames) {
361
+ for (const frame of frames) {
362
+ if (frame.file && isComponentPrimitivePath(frame.file)) {
363
+ return { file: frame.file, line: frame.line, column: frame.column };
364
+ }
365
+ }
366
+ return null;
367
+ }
368
+ var PRIMITIVE_PATH_PATTERNS = [
369
+ /\/components\/ui\//,
370
+ /\/ui\/primitives\//,
371
+ /\/design-system\//
372
+ ];
373
+ var PRIMITIVE_NPM_PATTERNS = [
374
+ /@base-ui\//,
375
+ /@radix-ui\//,
376
+ /@headlessui\//,
377
+ /@chakra-ui\//,
378
+ /@mantine\//,
379
+ /@mui\//,
380
+ /@ark-ui\//
381
+ ];
382
+ var FRAMEWORK_EXCLUSION_PATTERNS = [
383
+ /node_modules\/react\//,
384
+ /node_modules\/react-dom\//,
385
+ /node_modules\/next\/dist\//,
386
+ /node_modules\/scheduler\//,
387
+ /node_modules\/react-server\//
388
+ ];
389
+ function isComponentPrimitivePath(filePath) {
390
+ const normalized = filePath.replace(/\\/g, "/");
391
+ for (const pattern of FRAMEWORK_EXCLUSION_PATTERNS) {
392
+ if (pattern.test(normalized)) return false;
393
+ }
394
+ for (const pattern of PRIMITIVE_NPM_PATTERNS) {
395
+ if (pattern.test(normalized)) return true;
396
+ }
397
+ for (const pattern of PRIMITIVE_PATH_PATTERNS) {
398
+ if (pattern.test(normalized)) return true;
399
+ }
400
+ return false;
401
+ }
402
+ function classifyComponentFiber(fiber, frames, elementSourceFile) {
403
+ if (elementSourceFile && isComponentPrimitivePath(elementSourceFile)) {
404
+ return { isComponentPrimitive: true };
405
+ }
406
+ if (!fiber) return { isComponentPrimitive: false };
407
+ const callSite = getCallSiteSource(fiber);
408
+ if (callSite?.file && isComponentPrimitivePath(callSite.file)) {
409
+ return { isComponentPrimitive: true };
410
+ }
411
+ for (const frame of frames) {
412
+ if (frame.file && isComponentPrimitivePath(frame.file)) {
413
+ return { isComponentPrimitive: true };
414
+ }
415
+ }
416
+ if (!elementSourceFile && fiber._debugSource) {
417
+ return { isComponentPrimitive: true };
418
+ }
419
+ return { isComponentPrimitive: false };
420
+ }
421
+
200
422
  // src/utils.ts
201
423
  function clamp(value, min, max) {
202
424
  if (!Number.isFinite(value)) return min;
@@ -1584,7 +1806,7 @@ function calculateDropPosition(container, pointerX, pointerY, draggedElement) {
1584
1806
  };
1585
1807
  return { insertBefore, indicator };
1586
1808
  }
1587
- function getFiberForElement(element) {
1809
+ function getFiberForElement2(element) {
1588
1810
  if (typeof window !== "undefined") {
1589
1811
  const devtools = window.__DIRECT_EDIT_DEVTOOLS__;
1590
1812
  if (devtools?.getFiberForElement) {
@@ -1845,7 +2067,7 @@ function getSourceFromDebugStack(fiber) {
1845
2067
  }
1846
2068
  return null;
1847
2069
  }
1848
- function getSourceFromFiber(fiber) {
2070
+ function getSourceFromFiber2(fiber) {
1849
2071
  const debugSource = fiber?._debugSource;
1850
2072
  if (debugSource?.fileName) return debugSource;
1851
2073
  const owner = fiber?._debugOwner;
@@ -1861,13 +2083,13 @@ function getSourceFromFiber(fiber) {
1861
2083
  if (fromDebugStack?.fileName) return fromDebugStack;
1862
2084
  return null;
1863
2085
  }
1864
- function buildFrame(fiber) {
2086
+ function buildFrame2(fiber) {
1865
2087
  const type = fiber?.type;
1866
2088
  if (typeof type !== "function" && typeof type !== "object") return null;
1867
2089
  const name = type?.displayName || type?.name || null;
1868
2090
  if (!name || name === "Fragment") return null;
1869
2091
  const frame = { name };
1870
- const source = getSourceFromFiber(fiber);
2092
+ const source = getSourceFromFiber2(fiber);
1871
2093
  if (source?.fileName) {
1872
2094
  frame.file = source.fileName;
1873
2095
  if (typeof source.lineNumber === "number") {
@@ -1879,7 +2101,7 @@ function buildFrame(fiber) {
1879
2101
  }
1880
2102
  return frame;
1881
2103
  }
1882
- function shouldIncludeFrame(frame, lastFrame) {
2104
+ function shouldIncludeFrame2(frame, lastFrame) {
1883
2105
  if (!lastFrame) return true;
1884
2106
  if (frame.name !== lastFrame.name) return true;
1885
2107
  if (!lastFrame.file && frame.file) return true;
@@ -1889,42 +2111,52 @@ function shouldIncludeFrame(frame, lastFrame) {
1889
2111
  }
1890
2112
  return false;
1891
2113
  }
1892
- function getOwnerStack(fiber) {
2114
+ function getOwnerStack2(fiber) {
1893
2115
  const frames = [];
1894
2116
  let current = fiber;
1895
2117
  let lastFrame = null;
2118
+ let nearestComponentFiber = null;
1896
2119
  while (current) {
1897
- const frame = buildFrame(current);
1898
- if (frame && shouldIncludeFrame(frame, lastFrame)) {
2120
+ const frame = buildFrame2(current);
2121
+ if (frame && shouldIncludeFrame2(frame, lastFrame)) {
1899
2122
  frames.push(frame);
1900
2123
  lastFrame = frame;
2124
+ if (!nearestComponentFiber) {
2125
+ nearestComponentFiber = current;
2126
+ }
1901
2127
  }
1902
2128
  current = current._debugOwner;
1903
2129
  }
1904
- return frames;
2130
+ return { frames, nearestComponentFiber };
1905
2131
  }
1906
- function getRenderStack(fiber) {
2132
+ function getRenderStack2(fiber) {
1907
2133
  const frames = [];
1908
2134
  let current = fiber;
1909
2135
  let lastFrame = null;
2136
+ let nearestComponentFiber = null;
1910
2137
  while (current) {
1911
- const frame = buildFrame(current);
1912
- if (frame && shouldIncludeFrame(frame, lastFrame)) {
2138
+ const frame = buildFrame2(current);
2139
+ if (frame && shouldIncludeFrame2(frame, lastFrame)) {
1913
2140
  frames.push(frame);
1914
2141
  lastFrame = frame;
2142
+ if (!nearestComponentFiber) {
2143
+ nearestComponentFiber = current;
2144
+ }
1915
2145
  }
1916
2146
  current = current.return;
1917
2147
  }
1918
- return frames;
2148
+ return { frames, nearestComponentFiber };
1919
2149
  }
1920
- function getReactComponentStack(element) {
1921
- const fiber = getFiberForElement(element);
1922
- if (!fiber) return [];
1923
- const ownerStack = getOwnerStack(fiber);
1924
- if (ownerStack.length > 0) {
1925
- return ownerStack;
2150
+ function getReactComponentInfo2(element) {
2151
+ const fiber = getFiberForElement2(element);
2152
+ if (!fiber) return { frames: [], nearestComponentFiber: null };
2153
+ const elementSource = getSourceFromFiber2(fiber);
2154
+ const elementSourceFile = elementSource?.fileName || void 0;
2155
+ const ownerResult = getOwnerStack2(fiber);
2156
+ if (ownerResult.frames.length > 0) {
2157
+ return { ...ownerResult, elementSourceFile };
1926
2158
  }
1927
- return getRenderStack(fiber);
2159
+ return { ...getRenderStack2(fiber), elementSourceFile };
1928
2160
  }
1929
2161
  function getElementDisplayName(element) {
1930
2162
  const tag = element.tagName.toLowerCase();
@@ -2219,14 +2451,35 @@ function parseDomSource(element) {
2219
2451
  }
2220
2452
  return { file, line, column };
2221
2453
  }
2454
+ var MAX_SUB_ELEMENT_SOURCES = 20;
2455
+ function collectSubElementSources(element) {
2456
+ const sources = {};
2457
+ const children = element.querySelectorAll("[data-direct-edit-source]");
2458
+ const labelCounts = /* @__PURE__ */ new Map();
2459
+ let count = 0;
2460
+ for (const child of children) {
2461
+ if (count >= MAX_SUB_ELEMENT_SOURCES) break;
2462
+ if (!(child instanceof HTMLElement)) continue;
2463
+ const source = parseDomSource(child);
2464
+ if (!source) continue;
2465
+ const text = ((child.innerText || child.textContent) ?? "").trim();
2466
+ let baseLabel = text.length > 0 && text.length <= 30 ? text.slice(0, 30).toLowerCase().replace(/\s+/g, "_") : child.tagName.toLowerCase();
2467
+ const existing = labelCounts.get(baseLabel) ?? 0;
2468
+ labelCounts.set(baseLabel, existing + 1);
2469
+ const label = existing > 0 ? `${baseLabel}_${existing + 1}` : baseLabel;
2470
+ sources[label] = source;
2471
+ count++;
2472
+ }
2473
+ return sources;
2474
+ }
2222
2475
  function getElementSource(element) {
2223
2476
  const domSource = parseDomSource(element);
2224
2477
  if (domSource) return domSource;
2225
2478
  const seenFibers = /* @__PURE__ */ new Set();
2226
- let fiber = getFiberForElement(element);
2479
+ let fiber = getFiberForElement2(element);
2227
2480
  while (fiber && !seenFibers.has(fiber)) {
2228
2481
  seenFibers.add(fiber);
2229
- const fiberSource = getSourceFromFiber(fiber);
2482
+ const fiberSource = getSourceFromFiber2(fiber);
2230
2483
  if (fiberSource?.fileName) {
2231
2484
  return {
2232
2485
  file: fiberSource.fileName,
@@ -2241,8 +2494,15 @@ function getElementSource(element) {
2241
2494
  function getElementLocator(element) {
2242
2495
  const elementInfo = getElementInfo(element);
2243
2496
  const domSource = getElementSource(element);
2497
+ const { frames, nearestComponentFiber, elementSourceFile } = getReactComponentInfo2(element);
2498
+ const componentName = nearestComponentFiber?.type?.displayName || nearestComponentFiber?.type?.name || void 0;
2499
+ const authoredProps = nearestComponentFiber ? getComponentProps(nearestComponentFiber) : void 0;
2500
+ const classification = classifyComponentFiber(nearestComponentFiber, frames, elementSourceFile);
2501
+ const callSite = nearestComponentFiber ? getCallSiteSource(nearestComponentFiber) : null;
2502
+ const definitionSrc = classification.isComponentPrimitive ? deriveDefinitionSource(frames) : null;
2503
+ const subSources = collectSubElementSources(element);
2244
2504
  return {
2245
- reactStack: getReactComponentStack(element),
2505
+ reactStack: frames,
2246
2506
  domSelector: buildDomSelector(element),
2247
2507
  domContextHtml: buildDomContextHtml(element),
2248
2508
  targetHtml: buildTargetHtml(element),
@@ -2250,36 +2510,80 @@ function getElementLocator(element) {
2250
2510
  tagName: elementInfo.tagName,
2251
2511
  id: elementInfo.id,
2252
2512
  classList: elementInfo.classList,
2253
- domSource: domSource ?? void 0
2513
+ domSource: domSource ?? void 0,
2514
+ reactComponentName: componentName,
2515
+ authoredProps: authoredProps && Object.keys(authoredProps).length > 0 ? authoredProps : void 0,
2516
+ subElementSources: Object.keys(subSources).length > 0 ? subSources : void 0,
2517
+ callSiteSource: callSite ?? void 0,
2518
+ definitionSource: definitionSrc ?? void 0,
2519
+ isComponentPrimitive: nearestComponentFiber || elementSourceFile ? classification.isComponentPrimitive : void 0
2254
2520
  };
2255
2521
  }
2256
2522
  function getLocatorHeader(locator) {
2257
2523
  const primaryFrame = getPrimaryFrame(locator);
2258
- const componentLabel = primaryFrame?.name ? primaryFrame.name : locator.tagName;
2259
- const formattedSource = locator.domSource?.file ? formatSourceLocation(locator.domSource.file, locator.domSource.line, locator.domSource.column) : primaryFrame?.file ? formatSourceLocation(primaryFrame.file, primaryFrame.line, primaryFrame.column) : null;
2260
- return { componentLabel, formattedSource };
2524
+ const componentLabel = locator.reactComponentName ?? primaryFrame?.name ?? locator.tagName;
2525
+ let formattedSource;
2526
+ if (locator.isComponentPrimitive && locator.definitionSource?.file) {
2527
+ formattedSource = formatSourceLocation(
2528
+ locator.definitionSource.file,
2529
+ locator.definitionSource.line,
2530
+ locator.definitionSource.column
2531
+ );
2532
+ } else {
2533
+ formattedSource = locator.domSource?.file ? formatSourceLocation(locator.domSource.file, locator.domSource.line, locator.domSource.column) : primaryFrame?.file ? formatSourceLocation(primaryFrame.file, primaryFrame.line, primaryFrame.column) : null;
2534
+ }
2535
+ const formattedCallSite = locator.callSiteSource?.file ? formatSourceLocation(locator.callSiteSource.file, locator.callSiteSource.line, locator.callSiteSource.column) : null;
2536
+ return { componentLabel, formattedSource, formattedCallSite };
2537
+ }
2538
+ function formatComponentTree(reactStack) {
2539
+ const names = reactStack.map((f) => f.name).filter(Boolean);
2540
+ if (names.length === 0) return null;
2541
+ if (names.length === 1) return names[0];
2542
+ const [component, ...ancestors] = names;
2543
+ return `${component} (in ${ancestors.join(" > ")})`;
2261
2544
  }
2262
2545
  function buildLocatorContextLines(locator, options) {
2263
2546
  const lines = [];
2264
- const { componentLabel, formattedSource } = getLocatorHeader(locator);
2547
+ const { componentLabel, formattedSource, formattedCallSite } = getLocatorHeader(locator);
2265
2548
  const target = (locator.targetHtml || locator.domContextHtml || "").trim();
2266
2549
  const context = locator.domContextHtml?.trim() || "";
2267
- const selector = locator.domSelector?.trim();
2550
+ const path = locator.domSelector?.trim();
2268
2551
  const text = locator.textPreview?.trim();
2269
2552
  lines.push(`@<${componentLabel}>`);
2270
2553
  lines.push("");
2554
+ const tree = formatComponentTree(locator.reactStack);
2555
+ if (tree) {
2556
+ lines.push(`react: ${tree}`);
2557
+ }
2558
+ if (locator.authoredProps && Object.keys(locator.authoredProps).length > 0) {
2559
+ lines.push(`props: ${JSON.stringify(locator.authoredProps)}`);
2560
+ }
2561
+ if (locator.isComponentPrimitive != null) {
2562
+ lines.push(`type: ${locator.isComponentPrimitive ? "component" : "instance"}`);
2563
+ }
2564
+ lines.push(`source: ${formattedSource ?? "(file not available)"}`);
2565
+ if (formattedCallSite && formattedCallSite !== formattedSource) {
2566
+ lines.push(`call-site: ${formattedCallSite}`);
2567
+ }
2568
+ if (locator.subElementSources && Object.keys(locator.subElementSources).length > 0) {
2569
+ lines.push("source-map:");
2570
+ for (const [label, source] of Object.entries(locator.subElementSources)) {
2571
+ lines.push(` - ${label}: ${formatSourceLocation(source.file, source.line, source.column)}`);
2572
+ }
2573
+ }
2574
+ if (path) {
2575
+ lines.push(`path: ${path}`);
2576
+ }
2271
2577
  if (target) {
2578
+ lines.push("");
2272
2579
  lines.push("target:");
2273
2580
  lines.push(target);
2274
2581
  }
2275
2582
  if (!options?.skipContext && context && context !== target) {
2583
+ lines.push("");
2276
2584
  lines.push("context:");
2277
2585
  lines.push(context);
2278
2586
  }
2279
- lines.push(`in ${formattedSource ?? "(file not available)"}`);
2280
- if (selector) {
2281
- lines.push(`selector: ${selector}`);
2282
- }
2283
2587
  if (text) {
2284
2588
  lines.push(`text: ${text}`);
2285
2589
  }
@@ -4024,6 +4328,8 @@ function useSessionManager({
4024
4328
  const originalStyles = options?.originalStyles ?? existingEdit?.originalStyles ?? getOriginalInlineStyles(nextSingleElement);
4025
4329
  const pendingStyles = options?.pendingStyles ?? existingEdit?.pendingStyles ?? {};
4026
4330
  const elementInfo = getElementInfo(nextSingleElement);
4331
+ const { frames, nearestComponentFiber, elementSourceFile } = getReactComponentInfo(nextSingleElement);
4332
+ const isPrimitive = classifyComponentFiber(nearestComponentFiber, frames, elementSourceFile).isComponentPrimitive;
4027
4333
  setState((prev) => ({
4028
4334
  comments: prev.activeCommentId ? prev.comments.filter((comment) => {
4029
4335
  if (comment.id !== prev.activeCommentId) return true;
@@ -4042,6 +4348,7 @@ function useSessionManager({
4042
4348
  computedColor: computed.color,
4043
4349
  computedBoxShadow: computed.boxShadow,
4044
4350
  computedTypography: computed.typography,
4351
+ isComponentPrimitive: isPrimitive,
4045
4352
  originalStyles,
4046
4353
  pendingStyles,
4047
4354
  editModeActive: prev.editModeActive,
@@ -4072,6 +4379,7 @@ function useSessionManager({
4072
4379
  computedColor: null,
4073
4380
  computedBoxShadow: null,
4074
4381
  computedTypography: null,
4382
+ isComponentPrimitive: false,
4075
4383
  originalStyles: {},
4076
4384
  pendingStyles: {},
4077
4385
  activeCommentId: null,
@@ -4612,6 +4920,7 @@ function useSessionManager({
4612
4920
  computedColor: computed.color,
4613
4921
  computedBoxShadow: computed.boxShadow,
4614
4922
  computedTypography: computed.typography,
4923
+ isComponentPrimitive: prev.isComponentPrimitive,
4615
4924
  originalStyles: styleState.originalStyles,
4616
4925
  pendingStyles: styleState.pendingStyles,
4617
4926
  editModeActive: prev.editModeActive,
@@ -5396,6 +5705,8 @@ function withInstruction(profile, markdown) {
5396
5705
  ${markdown}` : markdown;
5397
5706
  }
5398
5707
  function buildLocatorPayload(locator) {
5708
+ const { componentLabel, formattedSource, formattedCallSite } = getLocatorHeader(locator);
5709
+ const reactTree = formatComponentTree(locator.reactStack);
5399
5710
  return {
5400
5711
  element: {
5401
5712
  tagName: locator.tagName,
@@ -5403,10 +5714,22 @@ function buildLocatorPayload(locator) {
5403
5714
  classList: locator.classList,
5404
5715
  domSelector: locator.domSelector,
5405
5716
  targetHtml: locator.targetHtml,
5717
+ contextHtml: locator.domContextHtml || null,
5406
5718
  textPreview: locator.textPreview
5407
5719
  },
5408
- source: locator.domSource || null,
5409
- reactStack: locator.reactStack
5720
+ componentLabel,
5721
+ reactTree,
5722
+ reactStack: locator.reactStack,
5723
+ reactComponentName: locator.reactComponentName ?? null,
5724
+ authoredProps: locator.authoredProps ?? null,
5725
+ type: locator.isComponentPrimitive != null ? locator.isComponentPrimitive ? "component" : "instance" : null,
5726
+ isComponentPrimitive: locator.isComponentPrimitive ?? false,
5727
+ source: formattedSource,
5728
+ callSite: formattedCallSite,
5729
+ rawSource: locator.domSource || null,
5730
+ callSiteSource: locator.callSiteSource ?? null,
5731
+ definitionSource: locator.definitionSource ?? null,
5732
+ subElementSources: locator.subElementSources ?? null
5410
5733
  };
5411
5734
  }
5412
5735
  function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrentToSession, removeSessionEdit, deleteComment }) {
@@ -6382,6 +6705,7 @@ function DirectEditProvider({ children }) {
6382
6705
  computedColor: null,
6383
6706
  computedBoxShadow: null,
6384
6707
  computedTypography: null,
6708
+ isComponentPrimitive: false,
6385
6709
  originalStyles: {},
6386
6710
  pendingStyles: {},
6387
6711
  editModeActive: false,
@@ -8674,6 +8998,7 @@ function useSelectionResize({
8674
8998
  var import_jsx_runtime9 = require("react/jsx-runtime");
8675
8999
  var BLUE3 = "#0D99FF";
8676
9000
  var MAGENTA = "#E11BB6";
9001
+ var COMPONENT_PURPLE = "#8B5CF6";
8677
9002
  var DRAG_THRESHOLD = 4;
8678
9003
  var DBLCLICK_DELAY = 300;
8679
9004
  var HANDLE_SIZE = 12;
@@ -8717,9 +9042,11 @@ function SelectionOverlay({
8717
9042
  onHoverElement,
8718
9043
  onClickThrough,
8719
9044
  onSelectPageFrame,
9045
+ isComponentPrimitive = false,
8720
9046
  enableResizeHandles = false,
8721
9047
  onResizeSizingChange
8722
9048
  }) {
9049
+ const selectionColor = isComponentPrimitive ? COMPONENT_PURPLE : BLUE3;
8723
9050
  const rectElement = isDragging && draggedElement ? draggedElement : selectedElement;
8724
9051
  const [rect, setRect] = React19.useState(() => rectElement.getBoundingClientRect());
8725
9052
  const [pageFrameRect, setPageFrameRect] = React19.useState(() => pageFrameElement ? pageFrameElement.getBoundingClientRect() : null);
@@ -9047,7 +9374,7 @@ function SelectionOverlay({
9047
9374
  zIndex: 99997,
9048
9375
  background: "transparent",
9049
9376
  border: "none",
9050
- color: BLUE3,
9377
+ color: selectionColor,
9051
9378
  fontSize: `${pageLabelFontSize}px`,
9052
9379
  lineHeight: `${pageLabelLineHeight}px`,
9053
9380
  padding: 0,
@@ -9075,7 +9402,7 @@ function SelectionOverlay({
9075
9402
  height: rect.height,
9076
9403
  pointerEvents: "none",
9077
9404
  zIndex: 99996,
9078
- border: `1px solid ${BLUE3}`,
9405
+ border: `1px solid ${selectionColor}`,
9079
9406
  borderRadius: "0px",
9080
9407
  boxSizing: "border-box"
9081
9408
  }
@@ -9092,18 +9419,28 @@ function SelectionOverlay({
9092
9419
  transform: "translateX(-50%)",
9093
9420
  pointerEvents: "none",
9094
9421
  zIndex: 99992,
9095
- background: BLUE3,
9096
- color: "white",
9097
- fontSize: "11px",
9098
- lineHeight: "20px",
9099
- padding: "0 6px",
9100
- borderRadius: "4px",
9101
- whiteSpace: "nowrap",
9102
- fontFamily: "system-ui, sans-serif",
9103
- fontWeight: 500,
9104
- letterSpacing: "-0.01em"
9422
+ display: "flex",
9423
+ alignItems: "center",
9424
+ gap: "4px"
9105
9425
  },
9106
- children: dimensionText
9426
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
9427
+ "span",
9428
+ {
9429
+ style: {
9430
+ background: selectionColor,
9431
+ color: "white",
9432
+ fontSize: "11px",
9433
+ lineHeight: "20px",
9434
+ padding: "0 6px",
9435
+ borderRadius: "4px",
9436
+ whiteSpace: "nowrap",
9437
+ fontFamily: "system-ui, sans-serif",
9438
+ fontWeight: 500,
9439
+ letterSpacing: "-0.01em"
9440
+ },
9441
+ children: dimensionText
9442
+ }
9443
+ )
9107
9444
  }
9108
9445
  ),
9109
9446
  !isDragging && !isTextEditing && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
@@ -9159,7 +9496,7 @@ function SelectionOverlay({
9159
9496
  position: "absolute",
9160
9497
  width: RESIZE_CORNER_SIZE,
9161
9498
  height: RESIZE_CORNER_SIZE,
9162
- border: `1px solid ${BLUE3}`,
9499
+ border: `1px solid ${selectionColor}`,
9163
9500
  background: "#fff",
9164
9501
  borderRadius: 1,
9165
9502
  boxSizing: "border-box",
@@ -12533,6 +12870,7 @@ function DirectEditPanelContent() {
12533
12870
  computedColor,
12534
12871
  computedBoxShadow,
12535
12872
  computedTypography,
12873
+ isComponentPrimitive,
12536
12874
  borderStyleControlPreference,
12537
12875
  pendingStyles,
12538
12876
  editModeActive,
@@ -12853,6 +13191,7 @@ function DirectEditPanelContent() {
12853
13191
  selectElement(child);
12854
13192
  }
12855
13193
  },
13194
+ isComponentPrimitive,
12856
13195
  enableResizeHandles: true,
12857
13196
  onResizeSizingChange: updateSizingProperties
12858
13197
  }