made-refine 0.2.11 → 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/utils.mjs CHANGED
@@ -40,6 +40,122 @@ function getZoomScale() {
40
40
  return snap.active ? snap.zoom : 1;
41
41
  }
42
42
 
43
+ // src/utils/react-fiber.ts
44
+ var EXCLUDED_PROP_KEYS = /* @__PURE__ */ new Set([
45
+ "className",
46
+ "style",
47
+ "children",
48
+ "ref",
49
+ "key",
50
+ "render"
51
+ ]);
52
+ function serializePropValue(value) {
53
+ if (typeof value === "function") return "[function]";
54
+ if (typeof value === "symbol") return void 0;
55
+ if (value === void 0) return void 0;
56
+ if (value !== null && typeof value === "object") {
57
+ if ("$$typeof" in value) return "[element]";
58
+ try {
59
+ JSON.stringify(value);
60
+ return value;
61
+ } catch {
62
+ return "[object]";
63
+ }
64
+ }
65
+ return value;
66
+ }
67
+ function getComponentProps(fiber) {
68
+ const props = fiber?.memoizedProps ?? fiber?.pendingProps;
69
+ if (!props || typeof props !== "object") return {};
70
+ const result = {};
71
+ for (const [key, value] of Object.entries(props)) {
72
+ if (EXCLUDED_PROP_KEYS.has(key)) continue;
73
+ if (key.startsWith("data-")) continue;
74
+ const serialized = serializePropValue(value);
75
+ if (serialized !== void 0) {
76
+ result[key] = serialized;
77
+ }
78
+ }
79
+ return result;
80
+ }
81
+ function getCallSiteSource(fiber) {
82
+ const source = fiber?._debugSource;
83
+ if (source?.fileName) {
84
+ return {
85
+ file: source.fileName,
86
+ line: typeof source.lineNumber === "number" ? source.lineNumber : void 0,
87
+ column: typeof source.columnNumber === "number" ? source.columnNumber : void 0
88
+ };
89
+ }
90
+ const pending = fiber?.pendingProps?.__source;
91
+ if (pending?.fileName) {
92
+ return {
93
+ file: pending.fileName,
94
+ line: typeof pending.lineNumber === "number" ? pending.lineNumber : void 0,
95
+ column: typeof pending.columnNumber === "number" ? pending.columnNumber : void 0
96
+ };
97
+ }
98
+ return null;
99
+ }
100
+ function deriveDefinitionSource(frames) {
101
+ for (const frame of frames) {
102
+ if (frame.file && isComponentPrimitivePath(frame.file)) {
103
+ return { file: frame.file, line: frame.line, column: frame.column };
104
+ }
105
+ }
106
+ return null;
107
+ }
108
+ var PRIMITIVE_PATH_PATTERNS = [
109
+ /\/components\/ui\//,
110
+ /\/ui\/primitives\//,
111
+ /\/design-system\//
112
+ ];
113
+ var PRIMITIVE_NPM_PATTERNS = [
114
+ /@base-ui\//,
115
+ /@radix-ui\//,
116
+ /@headlessui\//,
117
+ /@chakra-ui\//,
118
+ /@mantine\//,
119
+ /@mui\//,
120
+ /@ark-ui\//
121
+ ];
122
+ var FRAMEWORK_EXCLUSION_PATTERNS = [
123
+ /node_modules\/react\//,
124
+ /node_modules\/react-dom\//,
125
+ /node_modules\/next\/dist\//,
126
+ /node_modules\/scheduler\//,
127
+ /node_modules\/react-server\//
128
+ ];
129
+ function isComponentPrimitivePath(filePath) {
130
+ const normalized = filePath.replace(/\\/g, "/");
131
+ for (const pattern of FRAMEWORK_EXCLUSION_PATTERNS) {
132
+ if (pattern.test(normalized)) return false;
133
+ }
134
+ for (const pattern of PRIMITIVE_NPM_PATTERNS) {
135
+ if (pattern.test(normalized)) return true;
136
+ }
137
+ for (const pattern of PRIMITIVE_PATH_PATTERNS) {
138
+ if (pattern.test(normalized)) return true;
139
+ }
140
+ return false;
141
+ }
142
+ function classifyComponentFiber(fiber, frames, elementSourceFile) {
143
+ if (elementSourceFile && isComponentPrimitivePath(elementSourceFile)) {
144
+ return { isComponentPrimitive: true };
145
+ }
146
+ if (!fiber) return { isComponentPrimitive: false };
147
+ const callSite = getCallSiteSource(fiber);
148
+ if (callSite?.file && isComponentPrimitivePath(callSite.file)) {
149
+ return { isComponentPrimitive: true };
150
+ }
151
+ for (const frame of frames) {
152
+ if (frame.file && isComponentPrimitivePath(frame.file)) {
153
+ return { isComponentPrimitive: true };
154
+ }
155
+ }
156
+ return { isComponentPrimitive: false };
157
+ }
158
+
43
159
  // src/utils.ts
44
160
  function clamp(value, min, max) {
45
161
  if (!Number.isFinite(value)) return min;
@@ -1805,38 +1921,48 @@ function getOwnerStack(fiber) {
1805
1921
  const frames = [];
1806
1922
  let current = fiber;
1807
1923
  let lastFrame = null;
1924
+ let nearestComponentFiber = null;
1808
1925
  while (current) {
1809
1926
  const frame = buildFrame(current);
1810
1927
  if (frame && shouldIncludeFrame(frame, lastFrame)) {
1811
1928
  frames.push(frame);
1812
1929
  lastFrame = frame;
1930
+ if (!nearestComponentFiber) {
1931
+ nearestComponentFiber = current;
1932
+ }
1813
1933
  }
1814
1934
  current = current._debugOwner;
1815
1935
  }
1816
- return frames;
1936
+ return { frames, nearestComponentFiber };
1817
1937
  }
1818
1938
  function getRenderStack(fiber) {
1819
1939
  const frames = [];
1820
1940
  let current = fiber;
1821
1941
  let lastFrame = null;
1942
+ let nearestComponentFiber = null;
1822
1943
  while (current) {
1823
1944
  const frame = buildFrame(current);
1824
1945
  if (frame && shouldIncludeFrame(frame, lastFrame)) {
1825
1946
  frames.push(frame);
1826
1947
  lastFrame = frame;
1948
+ if (!nearestComponentFiber) {
1949
+ nearestComponentFiber = current;
1950
+ }
1827
1951
  }
1828
1952
  current = current.return;
1829
1953
  }
1830
- return frames;
1954
+ return { frames, nearestComponentFiber };
1831
1955
  }
1832
- function getReactComponentStack(element) {
1956
+ function getReactComponentInfo(element) {
1833
1957
  const fiber = getFiberForElement(element);
1834
- if (!fiber) return [];
1835
- const ownerStack = getOwnerStack(fiber);
1836
- if (ownerStack.length > 0) {
1837
- return ownerStack;
1958
+ if (!fiber) return { frames: [], nearestComponentFiber: null };
1959
+ const elementSource = getSourceFromFiber(fiber);
1960
+ const elementSourceFile = elementSource?.fileName || void 0;
1961
+ const ownerResult = getOwnerStack(fiber);
1962
+ if (ownerResult.frames.length > 0) {
1963
+ return { ...ownerResult, elementSourceFile };
1838
1964
  }
1839
- return getRenderStack(fiber);
1965
+ return { ...getRenderStack(fiber), elementSourceFile };
1840
1966
  }
1841
1967
  function getElementDisplayName(element) {
1842
1968
  const tag = element.tagName.toLowerCase();
@@ -2138,6 +2264,27 @@ function parseDomSource(element) {
2138
2264
  }
2139
2265
  return { file, line, column };
2140
2266
  }
2267
+ var MAX_SUB_ELEMENT_SOURCES = 20;
2268
+ function collectSubElementSources(element) {
2269
+ const sources = {};
2270
+ const children = element.querySelectorAll("[data-direct-edit-source]");
2271
+ const labelCounts = /* @__PURE__ */ new Map();
2272
+ let count = 0;
2273
+ for (const child of children) {
2274
+ if (count >= MAX_SUB_ELEMENT_SOURCES) break;
2275
+ if (!(child instanceof HTMLElement)) continue;
2276
+ const source = parseDomSource(child);
2277
+ if (!source) continue;
2278
+ const text = ((child.innerText || child.textContent) ?? "").trim();
2279
+ let baseLabel = text.length > 0 && text.length <= 30 ? text.slice(0, 30).toLowerCase().replace(/\s+/g, "_") : child.tagName.toLowerCase();
2280
+ const existing = labelCounts.get(baseLabel) ?? 0;
2281
+ labelCounts.set(baseLabel, existing + 1);
2282
+ const label = existing > 0 ? `${baseLabel}_${existing + 1}` : baseLabel;
2283
+ sources[label] = source;
2284
+ count++;
2285
+ }
2286
+ return sources;
2287
+ }
2141
2288
  function getElementSource(element) {
2142
2289
  const domSource = parseDomSource(element);
2143
2290
  if (domSource) return domSource;
@@ -2160,8 +2307,15 @@ function getElementSource(element) {
2160
2307
  function getElementLocator(element) {
2161
2308
  const elementInfo = getElementInfo(element);
2162
2309
  const domSource = getElementSource(element);
2310
+ const { frames, nearestComponentFiber, elementSourceFile } = getReactComponentInfo(element);
2311
+ const componentName = nearestComponentFiber?.type?.displayName || nearestComponentFiber?.type?.name || void 0;
2312
+ const authoredProps = nearestComponentFiber ? getComponentProps(nearestComponentFiber) : void 0;
2313
+ const classification = classifyComponentFiber(nearestComponentFiber, frames, elementSourceFile);
2314
+ const callSite = nearestComponentFiber ? getCallSiteSource(nearestComponentFiber) : null;
2315
+ const definitionSrc = classification.isComponentPrimitive ? deriveDefinitionSource(frames) : null;
2316
+ const subSources = collectSubElementSources(element);
2163
2317
  return {
2164
- reactStack: getReactComponentStack(element),
2318
+ reactStack: frames,
2165
2319
  domSelector: buildDomSelector(element),
2166
2320
  domContextHtml: buildDomContextHtml(element),
2167
2321
  targetHtml: buildTargetHtml(element),
@@ -2169,36 +2323,80 @@ function getElementLocator(element) {
2169
2323
  tagName: elementInfo.tagName,
2170
2324
  id: elementInfo.id,
2171
2325
  classList: elementInfo.classList,
2172
- domSource: domSource ?? void 0
2326
+ domSource: domSource ?? void 0,
2327
+ reactComponentName: componentName,
2328
+ authoredProps: authoredProps && Object.keys(authoredProps).length > 0 ? authoredProps : void 0,
2329
+ subElementSources: Object.keys(subSources).length > 0 ? subSources : void 0,
2330
+ callSiteSource: callSite ?? void 0,
2331
+ definitionSource: definitionSrc ?? void 0,
2332
+ isComponentPrimitive: nearestComponentFiber || elementSourceFile ? classification.isComponentPrimitive : void 0
2173
2333
  };
2174
2334
  }
2175
2335
  function getLocatorHeader(locator) {
2176
2336
  const primaryFrame = getPrimaryFrame(locator);
2177
- const componentLabel = primaryFrame?.name ? primaryFrame.name : locator.tagName;
2178
- 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;
2179
- return { componentLabel, formattedSource };
2337
+ const componentLabel = locator.reactComponentName ?? primaryFrame?.name ?? locator.tagName;
2338
+ let formattedSource;
2339
+ if (locator.isComponentPrimitive && locator.definitionSource?.file) {
2340
+ formattedSource = formatSourceLocation(
2341
+ locator.definitionSource.file,
2342
+ locator.definitionSource.line,
2343
+ locator.definitionSource.column
2344
+ );
2345
+ } else {
2346
+ formattedSource = locator.domSource?.file ? formatSourceLocation(locator.domSource.file, locator.domSource.line, locator.domSource.column) : primaryFrame?.file ? formatSourceLocation(primaryFrame.file, primaryFrame.line, primaryFrame.column) : null;
2347
+ }
2348
+ const formattedCallSite = locator.callSiteSource?.file ? formatSourceLocation(locator.callSiteSource.file, locator.callSiteSource.line, locator.callSiteSource.column) : null;
2349
+ return { componentLabel, formattedSource, formattedCallSite };
2350
+ }
2351
+ function formatComponentTree(reactStack) {
2352
+ const names = reactStack.map((f) => f.name).filter(Boolean);
2353
+ if (names.length === 0) return null;
2354
+ if (names.length === 1) return names[0];
2355
+ const [component, ...ancestors] = names;
2356
+ return `${component} (in ${ancestors.join(" > ")})`;
2180
2357
  }
2181
2358
  function buildLocatorContextLines(locator, options) {
2182
2359
  const lines = [];
2183
- const { componentLabel, formattedSource } = getLocatorHeader(locator);
2360
+ const { componentLabel, formattedSource, formattedCallSite } = getLocatorHeader(locator);
2184
2361
  const target = (locator.targetHtml || locator.domContextHtml || "").trim();
2185
2362
  const context = locator.domContextHtml?.trim() || "";
2186
- const selector = locator.domSelector?.trim();
2363
+ const path = locator.domSelector?.trim();
2187
2364
  const text = locator.textPreview?.trim();
2188
2365
  lines.push(`@<${componentLabel}>`);
2189
2366
  lines.push("");
2367
+ const tree = formatComponentTree(locator.reactStack);
2368
+ if (tree) {
2369
+ lines.push(`react: ${tree}`);
2370
+ }
2371
+ if (locator.authoredProps && Object.keys(locator.authoredProps).length > 0) {
2372
+ lines.push(`props: ${JSON.stringify(locator.authoredProps)}`);
2373
+ }
2374
+ if (locator.isComponentPrimitive != null) {
2375
+ lines.push(`type: ${locator.isComponentPrimitive ? "component" : "instance"}`);
2376
+ }
2377
+ lines.push(`source: ${formattedSource ?? "(file not available)"}`);
2378
+ if (formattedCallSite && formattedCallSite !== formattedSource) {
2379
+ lines.push(`call-site: ${formattedCallSite}`);
2380
+ }
2381
+ if (locator.subElementSources && Object.keys(locator.subElementSources).length > 0) {
2382
+ lines.push("source-map:");
2383
+ for (const [label, source] of Object.entries(locator.subElementSources)) {
2384
+ lines.push(` - ${label}: ${formatSourceLocation(source.file, source.line, source.column)}`);
2385
+ }
2386
+ }
2387
+ if (path) {
2388
+ lines.push(`path: ${path}`);
2389
+ }
2190
2390
  if (target) {
2391
+ lines.push("");
2191
2392
  lines.push("target:");
2192
2393
  lines.push(target);
2193
2394
  }
2194
2395
  if (!options?.skipContext && context && context !== target) {
2396
+ lines.push("");
2195
2397
  lines.push("context:");
2196
2398
  lines.push(context);
2197
2399
  }
2198
- lines.push(`in ${formattedSource ?? "(file not available)"}`);
2199
- if (selector) {
2200
- lines.push(`selector: ${selector}`);
2201
- }
2202
2400
  if (text) {
2203
2401
  lines.push(`text: ${text}`);
2204
2402
  }
@@ -2908,7 +3106,7 @@ function buildExportInstruction(profile) {
2908
3106
  return hasComments ? "Address this feedback on the UI. Use the provided source location and selector to find each element in the codebase." : "";
2909
3107
  }
2910
3108
  const parts = [];
2911
- if (hasCssEdits) parts.push("Apply the CSS changes to the targeted elements using the project's existing styling approach (Tailwind, CSS modules, etc.).");
3109
+ if (hasCssEdits) parts.push("Apply the CSS changes to the targeted elements using the project's existing styling approach (Tailwind, CSS modules, etc.). Map values to existing CSS variables, design tokens, or utility classes already used in the project whenever possible.");
2912
3110
  if (hasTextEdits) parts.push("Update the text content as specified.");
2913
3111
  if (hasMoves) parts.push("Implement the move plan below directly in source code. For `structural_move`, reorder/reparent elements using the target anchors. For `layout_refactor`, apply the listed flex/grid refactor steps. Do NOT simulate movement with absolute positioning, left/top offsets, transform, or margin hacks.");
2914
3112
  if (hasComments) parts.push("Address the comments on the relevant elements.");
@@ -2994,6 +3192,7 @@ export {
2994
3192
  findTextOwnerAtPoint,
2995
3193
  findTextOwnerByRangeScan,
2996
3194
  flexPropertyToCSSMap,
3195
+ formatComponentTree,
2997
3196
  formatPropertyValue,
2998
3197
  getAllComputedStyles,
2999
3198
  getChildBriefInfo,
@@ -3011,6 +3210,7 @@ export {
3011
3210
  getElementSource,
3012
3211
  getExportContentProfile,
3013
3212
  getFlexDirection,
3213
+ getLocatorHeader,
3014
3214
  getMoveIntentForEdit,
3015
3215
  getOriginalInlineStyles,
3016
3216
  getSelectionColors,