made-refine 0.2.13 → 0.2.15

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,225 @@ 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
+ return { isComponentPrimitive: false };
417
+ }
418
+
200
419
  // src/utils.ts
201
420
  function clamp(value, min, max) {
202
421
  if (!Number.isFinite(value)) return min;
@@ -1584,7 +1803,7 @@ function calculateDropPosition(container, pointerX, pointerY, draggedElement) {
1584
1803
  };
1585
1804
  return { insertBefore, indicator };
1586
1805
  }
1587
- function getFiberForElement(element) {
1806
+ function getFiberForElement2(element) {
1588
1807
  if (typeof window !== "undefined") {
1589
1808
  const devtools = window.__DIRECT_EDIT_DEVTOOLS__;
1590
1809
  if (devtools?.getFiberForElement) {
@@ -1845,7 +2064,7 @@ function getSourceFromDebugStack(fiber) {
1845
2064
  }
1846
2065
  return null;
1847
2066
  }
1848
- function getSourceFromFiber(fiber) {
2067
+ function getSourceFromFiber2(fiber) {
1849
2068
  const debugSource = fiber?._debugSource;
1850
2069
  if (debugSource?.fileName) return debugSource;
1851
2070
  const owner = fiber?._debugOwner;
@@ -1861,13 +2080,13 @@ function getSourceFromFiber(fiber) {
1861
2080
  if (fromDebugStack?.fileName) return fromDebugStack;
1862
2081
  return null;
1863
2082
  }
1864
- function buildFrame(fiber) {
2083
+ function buildFrame2(fiber) {
1865
2084
  const type = fiber?.type;
1866
2085
  if (typeof type !== "function" && typeof type !== "object") return null;
1867
2086
  const name = type?.displayName || type?.name || null;
1868
2087
  if (!name || name === "Fragment") return null;
1869
2088
  const frame = { name };
1870
- const source = getSourceFromFiber(fiber);
2089
+ const source = getSourceFromFiber2(fiber);
1871
2090
  if (source?.fileName) {
1872
2091
  frame.file = source.fileName;
1873
2092
  if (typeof source.lineNumber === "number") {
@@ -1879,7 +2098,7 @@ function buildFrame(fiber) {
1879
2098
  }
1880
2099
  return frame;
1881
2100
  }
1882
- function shouldIncludeFrame(frame, lastFrame) {
2101
+ function shouldIncludeFrame2(frame, lastFrame) {
1883
2102
  if (!lastFrame) return true;
1884
2103
  if (frame.name !== lastFrame.name) return true;
1885
2104
  if (!lastFrame.file && frame.file) return true;
@@ -1889,42 +2108,52 @@ function shouldIncludeFrame(frame, lastFrame) {
1889
2108
  }
1890
2109
  return false;
1891
2110
  }
1892
- function getOwnerStack(fiber) {
2111
+ function getOwnerStack2(fiber) {
1893
2112
  const frames = [];
1894
2113
  let current = fiber;
1895
2114
  let lastFrame = null;
2115
+ let nearestComponentFiber = null;
1896
2116
  while (current) {
1897
- const frame = buildFrame(current);
1898
- if (frame && shouldIncludeFrame(frame, lastFrame)) {
2117
+ const frame = buildFrame2(current);
2118
+ if (frame && shouldIncludeFrame2(frame, lastFrame)) {
1899
2119
  frames.push(frame);
1900
2120
  lastFrame = frame;
2121
+ if (!nearestComponentFiber) {
2122
+ nearestComponentFiber = current;
2123
+ }
1901
2124
  }
1902
2125
  current = current._debugOwner;
1903
2126
  }
1904
- return frames;
2127
+ return { frames, nearestComponentFiber };
1905
2128
  }
1906
- function getRenderStack(fiber) {
2129
+ function getRenderStack2(fiber) {
1907
2130
  const frames = [];
1908
2131
  let current = fiber;
1909
2132
  let lastFrame = null;
2133
+ let nearestComponentFiber = null;
1910
2134
  while (current) {
1911
- const frame = buildFrame(current);
1912
- if (frame && shouldIncludeFrame(frame, lastFrame)) {
2135
+ const frame = buildFrame2(current);
2136
+ if (frame && shouldIncludeFrame2(frame, lastFrame)) {
1913
2137
  frames.push(frame);
1914
2138
  lastFrame = frame;
2139
+ if (!nearestComponentFiber) {
2140
+ nearestComponentFiber = current;
2141
+ }
1915
2142
  }
1916
2143
  current = current.return;
1917
2144
  }
1918
- return frames;
2145
+ return { frames, nearestComponentFiber };
1919
2146
  }
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;
2147
+ function getReactComponentInfo2(element) {
2148
+ const fiber = getFiberForElement2(element);
2149
+ if (!fiber) return { frames: [], nearestComponentFiber: null };
2150
+ const elementSource = getSourceFromFiber2(fiber);
2151
+ const elementSourceFile = elementSource?.fileName || void 0;
2152
+ const ownerResult = getOwnerStack2(fiber);
2153
+ if (ownerResult.frames.length > 0) {
2154
+ return { ...ownerResult, elementSourceFile };
1926
2155
  }
1927
- return getRenderStack(fiber);
2156
+ return { ...getRenderStack2(fiber), elementSourceFile };
1928
2157
  }
1929
2158
  function getElementDisplayName(element) {
1930
2159
  const tag = element.tagName.toLowerCase();
@@ -2219,14 +2448,35 @@ function parseDomSource(element) {
2219
2448
  }
2220
2449
  return { file, line, column };
2221
2450
  }
2451
+ var MAX_SUB_ELEMENT_SOURCES = 20;
2452
+ function collectSubElementSources(element) {
2453
+ const sources = {};
2454
+ const children = element.querySelectorAll("[data-direct-edit-source]");
2455
+ const labelCounts = /* @__PURE__ */ new Map();
2456
+ let count = 0;
2457
+ for (const child of children) {
2458
+ if (count >= MAX_SUB_ELEMENT_SOURCES) break;
2459
+ if (!(child instanceof HTMLElement)) continue;
2460
+ const source = parseDomSource(child);
2461
+ if (!source) continue;
2462
+ const text = ((child.innerText || child.textContent) ?? "").trim();
2463
+ let baseLabel = text.length > 0 && text.length <= 30 ? text.slice(0, 30).toLowerCase().replace(/\s+/g, "_") : child.tagName.toLowerCase();
2464
+ const existing = labelCounts.get(baseLabel) ?? 0;
2465
+ labelCounts.set(baseLabel, existing + 1);
2466
+ const label = existing > 0 ? `${baseLabel}_${existing + 1}` : baseLabel;
2467
+ sources[label] = source;
2468
+ count++;
2469
+ }
2470
+ return sources;
2471
+ }
2222
2472
  function getElementSource(element) {
2223
2473
  const domSource = parseDomSource(element);
2224
2474
  if (domSource) return domSource;
2225
2475
  const seenFibers = /* @__PURE__ */ new Set();
2226
- let fiber = getFiberForElement(element);
2476
+ let fiber = getFiberForElement2(element);
2227
2477
  while (fiber && !seenFibers.has(fiber)) {
2228
2478
  seenFibers.add(fiber);
2229
- const fiberSource = getSourceFromFiber(fiber);
2479
+ const fiberSource = getSourceFromFiber2(fiber);
2230
2480
  if (fiberSource?.fileName) {
2231
2481
  return {
2232
2482
  file: fiberSource.fileName,
@@ -2241,8 +2491,15 @@ function getElementSource(element) {
2241
2491
  function getElementLocator(element) {
2242
2492
  const elementInfo = getElementInfo(element);
2243
2493
  const domSource = getElementSource(element);
2494
+ const { frames, nearestComponentFiber, elementSourceFile } = getReactComponentInfo2(element);
2495
+ const componentName = nearestComponentFiber?.type?.displayName || nearestComponentFiber?.type?.name || void 0;
2496
+ const authoredProps = nearestComponentFiber ? getComponentProps(nearestComponentFiber) : void 0;
2497
+ const classification = classifyComponentFiber(nearestComponentFiber, frames, elementSourceFile);
2498
+ const callSite = nearestComponentFiber ? getCallSiteSource(nearestComponentFiber) : null;
2499
+ const definitionSrc = classification.isComponentPrimitive ? deriveDefinitionSource(frames) : null;
2500
+ const subSources = collectSubElementSources(element);
2244
2501
  return {
2245
- reactStack: getReactComponentStack(element),
2502
+ reactStack: frames,
2246
2503
  domSelector: buildDomSelector(element),
2247
2504
  domContextHtml: buildDomContextHtml(element),
2248
2505
  targetHtml: buildTargetHtml(element),
@@ -2250,36 +2507,80 @@ function getElementLocator(element) {
2250
2507
  tagName: elementInfo.tagName,
2251
2508
  id: elementInfo.id,
2252
2509
  classList: elementInfo.classList,
2253
- domSource: domSource ?? void 0
2510
+ domSource: domSource ?? void 0,
2511
+ reactComponentName: componentName,
2512
+ authoredProps: authoredProps && Object.keys(authoredProps).length > 0 ? authoredProps : void 0,
2513
+ subElementSources: Object.keys(subSources).length > 0 ? subSources : void 0,
2514
+ callSiteSource: callSite ?? void 0,
2515
+ definitionSource: definitionSrc ?? void 0,
2516
+ isComponentPrimitive: nearestComponentFiber || elementSourceFile ? classification.isComponentPrimitive : void 0
2254
2517
  };
2255
2518
  }
2256
2519
  function getLocatorHeader(locator) {
2257
2520
  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 };
2521
+ const componentLabel = locator.reactComponentName ?? primaryFrame?.name ?? locator.tagName;
2522
+ let formattedSource;
2523
+ if (locator.isComponentPrimitive && locator.definitionSource?.file) {
2524
+ formattedSource = formatSourceLocation(
2525
+ locator.definitionSource.file,
2526
+ locator.definitionSource.line,
2527
+ locator.definitionSource.column
2528
+ );
2529
+ } else {
2530
+ formattedSource = locator.domSource?.file ? formatSourceLocation(locator.domSource.file, locator.domSource.line, locator.domSource.column) : primaryFrame?.file ? formatSourceLocation(primaryFrame.file, primaryFrame.line, primaryFrame.column) : null;
2531
+ }
2532
+ const formattedCallSite = locator.callSiteSource?.file ? formatSourceLocation(locator.callSiteSource.file, locator.callSiteSource.line, locator.callSiteSource.column) : null;
2533
+ return { componentLabel, formattedSource, formattedCallSite };
2534
+ }
2535
+ function formatComponentTree(reactStack) {
2536
+ const names = reactStack.map((f) => f.name).filter(Boolean);
2537
+ if (names.length === 0) return null;
2538
+ if (names.length === 1) return names[0];
2539
+ const [component, ...ancestors] = names;
2540
+ return `${component} (in ${ancestors.join(" > ")})`;
2261
2541
  }
2262
2542
  function buildLocatorContextLines(locator, options) {
2263
2543
  const lines = [];
2264
- const { componentLabel, formattedSource } = getLocatorHeader(locator);
2544
+ const { componentLabel, formattedSource, formattedCallSite } = getLocatorHeader(locator);
2265
2545
  const target = (locator.targetHtml || locator.domContextHtml || "").trim();
2266
2546
  const context = locator.domContextHtml?.trim() || "";
2267
- const selector = locator.domSelector?.trim();
2547
+ const path = locator.domSelector?.trim();
2268
2548
  const text = locator.textPreview?.trim();
2269
2549
  lines.push(`@<${componentLabel}>`);
2270
2550
  lines.push("");
2551
+ const tree = formatComponentTree(locator.reactStack);
2552
+ if (tree) {
2553
+ lines.push(`react: ${tree}`);
2554
+ }
2555
+ if (locator.authoredProps && Object.keys(locator.authoredProps).length > 0) {
2556
+ lines.push(`props: ${JSON.stringify(locator.authoredProps)}`);
2557
+ }
2558
+ if (locator.isComponentPrimitive != null) {
2559
+ lines.push(`type: ${locator.isComponentPrimitive ? "component" : "instance"}`);
2560
+ }
2561
+ lines.push(`source: ${formattedSource ?? "(file not available)"}`);
2562
+ if (formattedCallSite && formattedCallSite !== formattedSource) {
2563
+ lines.push(`call-site: ${formattedCallSite}`);
2564
+ }
2565
+ if (locator.subElementSources && Object.keys(locator.subElementSources).length > 0) {
2566
+ lines.push("source-map:");
2567
+ for (const [label, source] of Object.entries(locator.subElementSources)) {
2568
+ lines.push(` - ${label}: ${formatSourceLocation(source.file, source.line, source.column)}`);
2569
+ }
2570
+ }
2571
+ if (path) {
2572
+ lines.push(`path: ${path}`);
2573
+ }
2271
2574
  if (target) {
2575
+ lines.push("");
2272
2576
  lines.push("target:");
2273
2577
  lines.push(target);
2274
2578
  }
2275
2579
  if (!options?.skipContext && context && context !== target) {
2580
+ lines.push("");
2276
2581
  lines.push("context:");
2277
2582
  lines.push(context);
2278
2583
  }
2279
- lines.push(`in ${formattedSource ?? "(file not available)"}`);
2280
- if (selector) {
2281
- lines.push(`selector: ${selector}`);
2282
- }
2283
2584
  if (text) {
2284
2585
  lines.push(`text: ${text}`);
2285
2586
  }
@@ -4024,6 +4325,8 @@ function useSessionManager({
4024
4325
  const originalStyles = options?.originalStyles ?? existingEdit?.originalStyles ?? getOriginalInlineStyles(nextSingleElement);
4025
4326
  const pendingStyles = options?.pendingStyles ?? existingEdit?.pendingStyles ?? {};
4026
4327
  const elementInfo = getElementInfo(nextSingleElement);
4328
+ const { frames, nearestComponentFiber, elementSourceFile } = getReactComponentInfo(nextSingleElement);
4329
+ const isPrimitive = classifyComponentFiber(nearestComponentFiber, frames, elementSourceFile).isComponentPrimitive;
4027
4330
  setState((prev) => ({
4028
4331
  comments: prev.activeCommentId ? prev.comments.filter((comment) => {
4029
4332
  if (comment.id !== prev.activeCommentId) return true;
@@ -4042,6 +4345,7 @@ function useSessionManager({
4042
4345
  computedColor: computed.color,
4043
4346
  computedBoxShadow: computed.boxShadow,
4044
4347
  computedTypography: computed.typography,
4348
+ isComponentPrimitive: isPrimitive,
4045
4349
  originalStyles,
4046
4350
  pendingStyles,
4047
4351
  editModeActive: prev.editModeActive,
@@ -4072,6 +4376,7 @@ function useSessionManager({
4072
4376
  computedColor: null,
4073
4377
  computedBoxShadow: null,
4074
4378
  computedTypography: null,
4379
+ isComponentPrimitive: false,
4075
4380
  originalStyles: {},
4076
4381
  pendingStyles: {},
4077
4382
  activeCommentId: null,
@@ -4612,6 +4917,7 @@ function useSessionManager({
4612
4917
  computedColor: computed.color,
4613
4918
  computedBoxShadow: computed.boxShadow,
4614
4919
  computedTypography: computed.typography,
4920
+ isComponentPrimitive: prev.isComponentPrimitive,
4615
4921
  originalStyles: styleState.originalStyles,
4616
4922
  pendingStyles: styleState.pendingStyles,
4617
4923
  editModeActive: prev.editModeActive,
@@ -5396,6 +5702,8 @@ function withInstruction(profile, markdown) {
5396
5702
  ${markdown}` : markdown;
5397
5703
  }
5398
5704
  function buildLocatorPayload(locator) {
5705
+ const { componentLabel, formattedSource, formattedCallSite } = getLocatorHeader(locator);
5706
+ const reactTree = formatComponentTree(locator.reactStack);
5399
5707
  return {
5400
5708
  element: {
5401
5709
  tagName: locator.tagName,
@@ -5403,10 +5711,22 @@ function buildLocatorPayload(locator) {
5403
5711
  classList: locator.classList,
5404
5712
  domSelector: locator.domSelector,
5405
5713
  targetHtml: locator.targetHtml,
5714
+ contextHtml: locator.domContextHtml || null,
5406
5715
  textPreview: locator.textPreview
5407
5716
  },
5408
- source: locator.domSource || null,
5409
- reactStack: locator.reactStack
5717
+ componentLabel,
5718
+ reactTree,
5719
+ reactStack: locator.reactStack,
5720
+ reactComponentName: locator.reactComponentName ?? null,
5721
+ authoredProps: locator.authoredProps ?? null,
5722
+ type: locator.isComponentPrimitive != null ? locator.isComponentPrimitive ? "component" : "instance" : null,
5723
+ isComponentPrimitive: locator.isComponentPrimitive ?? false,
5724
+ source: formattedSource,
5725
+ callSite: formattedCallSite,
5726
+ rawSource: locator.domSource || null,
5727
+ callSiteSource: locator.callSiteSource ?? null,
5728
+ definitionSource: locator.definitionSource ?? null,
5729
+ subElementSources: locator.subElementSources ?? null
5410
5730
  };
5411
5731
  }
5412
5732
  function useAgentComms({ stateRef, sessionEditsRef, getSessionItems, saveCurrentToSession, removeSessionEdit, deleteComment }) {
@@ -6382,6 +6702,7 @@ function DirectEditProvider({ children }) {
6382
6702
  computedColor: null,
6383
6703
  computedBoxShadow: null,
6384
6704
  computedTypography: null,
6705
+ isComponentPrimitive: false,
6385
6706
  originalStyles: {},
6386
6707
  pendingStyles: {},
6387
6708
  editModeActive: false,
@@ -8674,6 +8995,7 @@ function useSelectionResize({
8674
8995
  var import_jsx_runtime9 = require("react/jsx-runtime");
8675
8996
  var BLUE3 = "#0D99FF";
8676
8997
  var MAGENTA = "#E11BB6";
8998
+ var COMPONENT_PURPLE = "#8B5CF6";
8677
8999
  var DRAG_THRESHOLD = 4;
8678
9000
  var DBLCLICK_DELAY = 300;
8679
9001
  var HANDLE_SIZE = 12;
@@ -8717,9 +9039,11 @@ function SelectionOverlay({
8717
9039
  onHoverElement,
8718
9040
  onClickThrough,
8719
9041
  onSelectPageFrame,
9042
+ isComponentPrimitive = false,
8720
9043
  enableResizeHandles = false,
8721
9044
  onResizeSizingChange
8722
9045
  }) {
9046
+ const selectionColor = isComponentPrimitive ? COMPONENT_PURPLE : BLUE3;
8723
9047
  const rectElement = isDragging && draggedElement ? draggedElement : selectedElement;
8724
9048
  const [rect, setRect] = React19.useState(() => rectElement.getBoundingClientRect());
8725
9049
  const [pageFrameRect, setPageFrameRect] = React19.useState(() => pageFrameElement ? pageFrameElement.getBoundingClientRect() : null);
@@ -9047,7 +9371,7 @@ function SelectionOverlay({
9047
9371
  zIndex: 99997,
9048
9372
  background: "transparent",
9049
9373
  border: "none",
9050
- color: BLUE3,
9374
+ color: selectionColor,
9051
9375
  fontSize: `${pageLabelFontSize}px`,
9052
9376
  lineHeight: `${pageLabelLineHeight}px`,
9053
9377
  padding: 0,
@@ -9075,7 +9399,7 @@ function SelectionOverlay({
9075
9399
  height: rect.height,
9076
9400
  pointerEvents: "none",
9077
9401
  zIndex: 99996,
9078
- border: `1px solid ${BLUE3}`,
9402
+ border: `1px solid ${selectionColor}`,
9079
9403
  borderRadius: "0px",
9080
9404
  boxSizing: "border-box"
9081
9405
  }
@@ -9092,18 +9416,28 @@ function SelectionOverlay({
9092
9416
  transform: "translateX(-50%)",
9093
9417
  pointerEvents: "none",
9094
9418
  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"
9419
+ display: "flex",
9420
+ alignItems: "center",
9421
+ gap: "4px"
9105
9422
  },
9106
- children: dimensionText
9423
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
9424
+ "span",
9425
+ {
9426
+ style: {
9427
+ background: selectionColor,
9428
+ color: "white",
9429
+ fontSize: "11px",
9430
+ lineHeight: "20px",
9431
+ padding: "0 6px",
9432
+ borderRadius: "4px",
9433
+ whiteSpace: "nowrap",
9434
+ fontFamily: "system-ui, sans-serif",
9435
+ fontWeight: 500,
9436
+ letterSpacing: "-0.01em"
9437
+ },
9438
+ children: dimensionText
9439
+ }
9440
+ )
9107
9441
  }
9108
9442
  ),
9109
9443
  !isDragging && !isTextEditing && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
@@ -9159,7 +9493,7 @@ function SelectionOverlay({
9159
9493
  position: "absolute",
9160
9494
  width: RESIZE_CORNER_SIZE,
9161
9495
  height: RESIZE_CORNER_SIZE,
9162
- border: `1px solid ${BLUE3}`,
9496
+ border: `1px solid ${selectionColor}`,
9163
9497
  background: "#fff",
9164
9498
  borderRadius: 1,
9165
9499
  boxSizing: "border-box",
@@ -12533,6 +12867,7 @@ function DirectEditPanelContent() {
12533
12867
  computedColor,
12534
12868
  computedBoxShadow,
12535
12869
  computedTypography,
12870
+ isComponentPrimitive,
12536
12871
  borderStyleControlPreference,
12537
12872
  pendingStyles,
12538
12873
  editModeActive,
@@ -12853,6 +13188,7 @@ function DirectEditPanelContent() {
12853
13188
  selectElement(child);
12854
13189
  }
12855
13190
  },
13191
+ isComponentPrimitive,
12856
13192
  enableResizeHandles: true,
12857
13193
  onResizeSizingChange: updateSizingProperties
12858
13194
  }