codemeld 2.1.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 (243) hide show
  1. package/README.md +514 -0
  2. package/bin/cli.js +2 -0
  3. package/dist/ai/agent.d.ts +124 -0
  4. package/dist/ai/agent.d.ts.map +1 -0
  5. package/dist/ai/agent.js +289 -0
  6. package/dist/ai/agent.js.map +1 -0
  7. package/dist/ai/index.d.ts +10 -0
  8. package/dist/ai/index.d.ts.map +1 -0
  9. package/dist/ai/index.js +10 -0
  10. package/dist/ai/index.js.map +1 -0
  11. package/dist/ai/prompts.d.ts +35 -0
  12. package/dist/ai/prompts.d.ts.map +1 -0
  13. package/dist/ai/prompts.js +166 -0
  14. package/dist/ai/prompts.js.map +1 -0
  15. package/dist/ai/refinement-loop.d.ts +29 -0
  16. package/dist/ai/refinement-loop.d.ts.map +1 -0
  17. package/dist/ai/refinement-loop.js +180 -0
  18. package/dist/ai/refinement-loop.js.map +1 -0
  19. package/dist/ai/tools.d.ts +17 -0
  20. package/dist/ai/tools.d.ts.map +1 -0
  21. package/dist/ai/tools.js +353 -0
  22. package/dist/ai/tools.js.map +1 -0
  23. package/dist/ai/visual-compare.d.ts +43 -0
  24. package/dist/ai/visual-compare.d.ts.map +1 -0
  25. package/dist/ai/visual-compare.js +176 -0
  26. package/dist/ai/visual-compare.js.map +1 -0
  27. package/dist/cli.d.ts +3 -0
  28. package/dist/cli.d.ts.map +1 -0
  29. package/dist/cli.js +179 -0
  30. package/dist/cli.js.map +1 -0
  31. package/dist/converter.d.ts +10 -0
  32. package/dist/converter.d.ts.map +1 -0
  33. package/dist/converter.js +836 -0
  34. package/dist/converter.js.map +1 -0
  35. package/dist/deconverter.d.ts +19 -0
  36. package/dist/deconverter.d.ts.map +1 -0
  37. package/dist/deconverter.js +188 -0
  38. package/dist/deconverter.js.map +1 -0
  39. package/dist/frameworks/angular-adapter.d.ts +27 -0
  40. package/dist/frameworks/angular-adapter.d.ts.map +1 -0
  41. package/dist/frameworks/angular-adapter.js +617 -0
  42. package/dist/frameworks/angular-adapter.js.map +1 -0
  43. package/dist/frameworks/index.d.ts +10 -0
  44. package/dist/frameworks/index.d.ts.map +1 -0
  45. package/dist/frameworks/index.js +21 -0
  46. package/dist/frameworks/index.js.map +1 -0
  47. package/dist/frameworks/nextjs-adapter.d.ts +22 -0
  48. package/dist/frameworks/nextjs-adapter.d.ts.map +1 -0
  49. package/dist/frameworks/nextjs-adapter.js +392 -0
  50. package/dist/frameworks/nextjs-adapter.js.map +1 -0
  51. package/dist/frameworks/react-adapter.d.ts +21 -0
  52. package/dist/frameworks/react-adapter.d.ts.map +1 -0
  53. package/dist/frameworks/react-adapter.js +71 -0
  54. package/dist/frameworks/react-adapter.js.map +1 -0
  55. package/dist/frameworks/svelte-adapter.d.ts +27 -0
  56. package/dist/frameworks/svelte-adapter.d.ts.map +1 -0
  57. package/dist/frameworks/svelte-adapter.js +519 -0
  58. package/dist/frameworks/svelte-adapter.js.map +1 -0
  59. package/dist/frameworks/types.d.ts +78 -0
  60. package/dist/frameworks/types.d.ts.map +1 -0
  61. package/dist/frameworks/types.js +2 -0
  62. package/dist/frameworks/types.js.map +1 -0
  63. package/dist/frameworks/vue-adapter.d.ts +34 -0
  64. package/dist/frameworks/vue-adapter.d.ts.map +1 -0
  65. package/dist/frameworks/vue-adapter.js +632 -0
  66. package/dist/frameworks/vue-adapter.js.map +1 -0
  67. package/dist/generators/accessibility-generator.d.ts +43 -0
  68. package/dist/generators/accessibility-generator.d.ts.map +1 -0
  69. package/dist/generators/accessibility-generator.js +507 -0
  70. package/dist/generators/accessibility-generator.js.map +1 -0
  71. package/dist/generators/asset-handler.d.ts +14 -0
  72. package/dist/generators/asset-handler.d.ts.map +1 -0
  73. package/dist/generators/asset-handler.js +79 -0
  74. package/dist/generators/asset-handler.js.map +1 -0
  75. package/dist/generators/build-verifier.d.ts +8 -0
  76. package/dist/generators/build-verifier.d.ts.map +1 -0
  77. package/dist/generators/build-verifier.js +64 -0
  78. package/dist/generators/build-verifier.js.map +1 -0
  79. package/dist/generators/component-extractor.d.ts +25 -0
  80. package/dist/generators/component-extractor.d.ts.map +1 -0
  81. package/dist/generators/component-extractor.js +146 -0
  82. package/dist/generators/component-extractor.js.map +1 -0
  83. package/dist/generators/component-generator.d.ts +12 -0
  84. package/dist/generators/component-generator.d.ts.map +1 -0
  85. package/dist/generators/component-generator.js +724 -0
  86. package/dist/generators/component-generator.js.map +1 -0
  87. package/dist/generators/deploy-generator.d.ts +9 -0
  88. package/dist/generators/deploy-generator.d.ts.map +1 -0
  89. package/dist/generators/deploy-generator.js +409 -0
  90. package/dist/generators/deploy-generator.js.map +1 -0
  91. package/dist/generators/error-boundary.d.ts +5 -0
  92. package/dist/generators/error-boundary.d.ts.map +1 -0
  93. package/dist/generators/error-boundary.js +59 -0
  94. package/dist/generators/error-boundary.js.map +1 -0
  95. package/dist/generators/form-generator.d.ts +42 -0
  96. package/dist/generators/form-generator.d.ts.map +1 -0
  97. package/dist/generators/form-generator.js +662 -0
  98. package/dist/generators/form-generator.js.map +1 -0
  99. package/dist/generators/hooks-generator.d.ts +40 -0
  100. package/dist/generators/hooks-generator.d.ts.map +1 -0
  101. package/dist/generators/hooks-generator.js +297 -0
  102. package/dist/generators/hooks-generator.js.map +1 -0
  103. package/dist/generators/html-generator.d.ts +27 -0
  104. package/dist/generators/html-generator.d.ts.map +1 -0
  105. package/dist/generators/html-generator.js +772 -0
  106. package/dist/generators/html-generator.js.map +1 -0
  107. package/dist/generators/jquery-converter.d.ts +41 -0
  108. package/dist/generators/jquery-converter.d.ts.map +1 -0
  109. package/dist/generators/jquery-converter.js +594 -0
  110. package/dist/generators/jquery-converter.js.map +1 -0
  111. package/dist/generators/pattern-implementer.d.ts +26 -0
  112. package/dist/generators/pattern-implementer.d.ts.map +1 -0
  113. package/dist/generators/pattern-implementer.js +336 -0
  114. package/dist/generators/pattern-implementer.js.map +1 -0
  115. package/dist/generators/performance-generator.d.ts +51 -0
  116. package/dist/generators/performance-generator.d.ts.map +1 -0
  117. package/dist/generators/performance-generator.js +428 -0
  118. package/dist/generators/performance-generator.js.map +1 -0
  119. package/dist/generators/router-generator.d.ts +21 -0
  120. package/dist/generators/router-generator.d.ts.map +1 -0
  121. package/dist/generators/router-generator.js +178 -0
  122. package/dist/generators/router-generator.js.map +1 -0
  123. package/dist/generators/scaffolder.d.ts +28 -0
  124. package/dist/generators/scaffolder.d.ts.map +1 -0
  125. package/dist/generators/scaffolder.js +266 -0
  126. package/dist/generators/scaffolder.js.map +1 -0
  127. package/dist/generators/seo-generator.d.ts +29 -0
  128. package/dist/generators/seo-generator.d.ts.map +1 -0
  129. package/dist/generators/seo-generator.js +223 -0
  130. package/dist/generators/seo-generator.js.map +1 -0
  131. package/dist/generators/test-generator.d.ts +19 -0
  132. package/dist/generators/test-generator.d.ts.map +1 -0
  133. package/dist/generators/test-generator.js +398 -0
  134. package/dist/generators/test-generator.js.map +1 -0
  135. package/dist/generators/type-generator.d.ts +33 -0
  136. package/dist/generators/type-generator.d.ts.map +1 -0
  137. package/dist/generators/type-generator.js +663 -0
  138. package/dist/generators/type-generator.js.map +1 -0
  139. package/dist/index.d.ts +23 -0
  140. package/dist/index.d.ts.map +1 -0
  141. package/dist/index.js +12 -0
  142. package/dist/index.js.map +1 -0
  143. package/dist/parsers/css-processor.d.ts +23 -0
  144. package/dist/parsers/css-processor.d.ts.map +1 -0
  145. package/dist/parsers/css-processor.js +129 -0
  146. package/dist/parsers/css-processor.js.map +1 -0
  147. package/dist/parsers/framework-parser.d.ts +48 -0
  148. package/dist/parsers/framework-parser.d.ts.map +1 -0
  149. package/dist/parsers/framework-parser.js +770 -0
  150. package/dist/parsers/framework-parser.js.map +1 -0
  151. package/dist/parsers/html-parser.d.ts +12 -0
  152. package/dist/parsers/html-parser.d.ts.map +1 -0
  153. package/dist/parsers/html-parser.js +444 -0
  154. package/dist/parsers/html-parser.js.map +1 -0
  155. package/dist/parsers/js-analyzer.d.ts +199 -0
  156. package/dist/parsers/js-analyzer.d.ts.map +1 -0
  157. package/dist/parsers/js-analyzer.js +680 -0
  158. package/dist/parsers/js-analyzer.js.map +1 -0
  159. package/dist/parsers/js-resolver.d.ts +8 -0
  160. package/dist/parsers/js-resolver.d.ts.map +1 -0
  161. package/dist/parsers/js-resolver.js +45 -0
  162. package/dist/parsers/js-resolver.js.map +1 -0
  163. package/dist/parsers/tailwind-detector.d.ts +23 -0
  164. package/dist/parsers/tailwind-detector.d.ts.map +1 -0
  165. package/dist/parsers/tailwind-detector.js +104 -0
  166. package/dist/parsers/tailwind-detector.js.map +1 -0
  167. package/dist/tests/advanced-features.test.d.ts +2 -0
  168. package/dist/tests/advanced-features.test.d.ts.map +1 -0
  169. package/dist/tests/advanced-features.test.js +235 -0
  170. package/dist/tests/advanced-features.test.js.map +1 -0
  171. package/dist/tests/css-modules.test.d.ts +2 -0
  172. package/dist/tests/css-modules.test.d.ts.map +1 -0
  173. package/dist/tests/css-modules.test.js +61 -0
  174. package/dist/tests/css-modules.test.js.map +1 -0
  175. package/dist/tests/css-processor.test.d.ts +2 -0
  176. package/dist/tests/css-processor.test.d.ts.map +1 -0
  177. package/dist/tests/css-processor.test.js +48 -0
  178. package/dist/tests/css-processor.test.js.map +1 -0
  179. package/dist/tests/html-parser.test.d.ts +2 -0
  180. package/dist/tests/html-parser.test.d.ts.map +1 -0
  181. package/dist/tests/html-parser.test.js +78 -0
  182. package/dist/tests/html-parser.test.js.map +1 -0
  183. package/dist/tests/integration.test.d.ts +2 -0
  184. package/dist/tests/integration.test.d.ts.map +1 -0
  185. package/dist/tests/integration.test.js +65 -0
  186. package/dist/tests/integration.test.js.map +1 -0
  187. package/dist/tests/js-analyzer.test.d.ts +2 -0
  188. package/dist/tests/js-analyzer.test.d.ts.map +1 -0
  189. package/dist/tests/js-analyzer.test.js +58 -0
  190. package/dist/tests/js-analyzer.test.js.map +1 -0
  191. package/dist/tests/naming.test.d.ts +2 -0
  192. package/dist/tests/naming.test.d.ts.map +1 -0
  193. package/dist/tests/naming.test.js +43 -0
  194. package/dist/tests/naming.test.js.map +1 -0
  195. package/dist/tests/router-generator.test.d.ts +2 -0
  196. package/dist/tests/router-generator.test.d.ts.map +1 -0
  197. package/dist/tests/router-generator.test.js +60 -0
  198. package/dist/tests/router-generator.test.js.map +1 -0
  199. package/dist/tui/chat.d.ts +13 -0
  200. package/dist/tui/chat.d.ts.map +1 -0
  201. package/dist/tui/chat.js +499 -0
  202. package/dist/tui/chat.js.map +1 -0
  203. package/dist/tui/design-guide.d.ts +41 -0
  204. package/dist/tui/design-guide.d.ts.map +1 -0
  205. package/dist/tui/design-guide.js +184 -0
  206. package/dist/tui/design-guide.js.map +1 -0
  207. package/dist/tui/input.d.ts +30 -0
  208. package/dist/tui/input.d.ts.map +1 -0
  209. package/dist/tui/input.js +239 -0
  210. package/dist/tui/input.js.map +1 -0
  211. package/dist/tui/renderer.d.ts +48 -0
  212. package/dist/tui/renderer.d.ts.map +1 -0
  213. package/dist/tui/renderer.js +212 -0
  214. package/dist/tui/renderer.js.map +1 -0
  215. package/dist/tui/tools.d.ts +14 -0
  216. package/dist/tui/tools.d.ts.map +1 -0
  217. package/dist/tui/tools.js +1370 -0
  218. package/dist/tui/tools.js.map +1 -0
  219. package/dist/types.d.ts +93 -0
  220. package/dist/types.d.ts.map +1 -0
  221. package/dist/types.js +2 -0
  222. package/dist/types.js.map +1 -0
  223. package/dist/utils/config.d.ts +20 -0
  224. package/dist/utils/config.d.ts.map +1 -0
  225. package/dist/utils/config.js +33 -0
  226. package/dist/utils/config.js.map +1 -0
  227. package/dist/utils/formatter.d.ts +5 -0
  228. package/dist/utils/formatter.d.ts.map +1 -0
  229. package/dist/utils/formatter.js +68 -0
  230. package/dist/utils/formatter.js.map +1 -0
  231. package/dist/utils/logger.d.ts +8 -0
  232. package/dist/utils/logger.d.ts.map +1 -0
  233. package/dist/utils/logger.js +19 -0
  234. package/dist/utils/logger.js.map +1 -0
  235. package/dist/utils/naming.d.ts +17 -0
  236. package/dist/utils/naming.d.ts.map +1 -0
  237. package/dist/utils/naming.js +48 -0
  238. package/dist/utils/naming.js.map +1 -0
  239. package/dist/utils/report.d.ts +56 -0
  240. package/dist/utils/report.d.ts.map +1 -0
  241. package/dist/utils/report.js +339 -0
  242. package/dist/utils/report.js.map +1 -0
  243. package/package.json +61 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Pattern Implementation Engine
3
+ *
4
+ * Transforms detected interactive patterns into actual working React code.
5
+ * Takes JSX strings and pattern detections, returns modified JSX with
6
+ * proper state management, event handlers, and conditional rendering.
7
+ */
8
+ import type { InteractivePatterns } from '../parsers/js-analyzer.js';
9
+ export interface PatternImplementation {
10
+ /** Modified JSX with event handlers and conditional classNames injected */
11
+ jsx: string;
12
+ /** State declarations to add to the component body */
13
+ stateDeclarations: string[];
14
+ /** Handler functions to add to the component body */
15
+ handlers: string[];
16
+ /** useEffect hooks to add */
17
+ effects: string[];
18
+ /** Additional React imports needed (e.g., 'useCallback') */
19
+ additionalHooks: Set<string>;
20
+ }
21
+ /**
22
+ * Apply all detected interactive patterns to the JSX, generating real
23
+ * working React implementations instead of stubs.
24
+ */
25
+ export declare function implementPatterns(jsx: string, patterns: InteractivePatterns, customHooks?: string[]): PatternImplementation;
26
+ //# sourceMappingURL=pattern-implementer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-implementer.d.ts","sourceRoot":"","sources":["../../src/generators/pattern-implementer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EACV,mBAAmB,EAKpB,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,qBAAqB;IACpC,2EAA2E;IAC3E,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qDAAqD;IACrD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,4DAA4D;IAC5D,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,mBAAmB,EAC7B,WAAW,GAAE,MAAM,EAAO,GACzB,qBAAqB,CAwBvB"}
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Apply all detected interactive patterns to the JSX, generating real
3
+ * working React implementations instead of stubs.
4
+ */
5
+ export function implementPatterns(jsx, patterns, customHooks = []) {
6
+ const result = {
7
+ jsx,
8
+ stateDeclarations: [],
9
+ handlers: [],
10
+ effects: [],
11
+ additionalHooks: new Set(),
12
+ };
13
+ // Apply each pattern type
14
+ for (let i = 0; i < patterns.accordions.length; i++) {
15
+ implementAccordion(result, patterns.accordions[i], i, patterns.accordions.length > 1);
16
+ }
17
+ for (let i = 0; i < patterns.tabs.length; i++) {
18
+ implementTabs(result, patterns.tabs[i], i, patterns.tabs.length > 1);
19
+ }
20
+ implementMobileMenu(result);
21
+ implementBillingToggle(result);
22
+ implementCtaForm(result);
23
+ implementRipple(result);
24
+ return result;
25
+ }
26
+ // ─── Accordion / FAQ ───────────────────────────────────────────────
27
+ function implementAccordion(result, pattern, index, multiple) {
28
+ const suffix = multiple ? String(index + 1) : '';
29
+ const stateVar = `openAccordion${suffix}`;
30
+ const setter = `setOpenAccordion${suffix}`;
31
+ result.stateDeclarations.push(`const [${stateVar}, ${setter}] = useState<number | null>(null);`);
32
+ result.handlers.push(`const toggleAccordion${suffix} = (idx: number) => {\n` +
33
+ ` ${setter}(prev => prev === idx ? null : idx);\n` +
34
+ ` };`);
35
+ // Clean trigger selector: '.faq-q' → 'faq-q'
36
+ const triggerClass = pattern.triggerSelector.replace(/^\./, '');
37
+ const itemClass = pattern.itemSelector.replace(/^\./, '');
38
+ // Inject onClick on accordion trigger buttons and conditional open class on items
39
+ // Strategy: Find elements with the trigger class and add onClick + index tracking
40
+ // We do this by finding accordion items and wrapping them with state logic
41
+ // Find and index all accordion items
42
+ let itemIndex = 0;
43
+ result.jsx = result.jsx.replace(new RegExp(`(className="[^"]*\\b${escapeRegex(itemClass)}\\b[^"]*")`, 'g'), (_match, classAttr) => {
44
+ const idx = itemIndex++;
45
+ // Add conditional open class
46
+ return `${classAttr.slice(0, -1)} \${${stateVar} === ${idx} ? '${pattern.openClass}' : ''}"`.replace('className="', 'className={`').replace(/"$/, '`}');
47
+ });
48
+ // Add onClick to trigger buttons
49
+ let btnIndex = 0;
50
+ result.jsx = result.jsx.replace(new RegExp(`(<button[^>]*className="[^"]*\\b${escapeRegex(triggerClass)}\\b[^"]*"[^>]*)(>)`, 'g'), (_match, before, after) => {
51
+ const idx = btnIndex++;
52
+ return `${before} onClick={() => toggleAccordion${suffix}(${idx})}${after}`;
53
+ });
54
+ }
55
+ // ─── Tabs ──────────────────────────────────────────────────────────
56
+ function implementTabs(result, pattern, index, multiple) {
57
+ const suffix = multiple ? String(index + 1) : '';
58
+ const stateVar = `activeTab${suffix}`;
59
+ const setter = `setActiveTab${suffix}`;
60
+ result.stateDeclarations.push(`const [${stateVar}, ${setter}] = useState(0);`);
61
+ const tabClass = pattern.tabSelector.replace(/^\./, '');
62
+ const panelClass = pattern.panelSelector.replace(/^\./, '');
63
+ const activeClass = pattern.activeClass;
64
+ // Collect tab data-attribute values for mapping
65
+ const tabValues = [];
66
+ const tabValueRe = new RegExp(`<button[^>]*className="[^"]*\\b${escapeRegex(tabClass)}\\b[^"]*"[^>]*${escapeRegex(pattern.dataAttr)}="([^"]*)"`, 'g');
67
+ let tvMatch;
68
+ while ((tvMatch = tabValueRe.exec(result.jsx)) !== null) {
69
+ tabValues.push(tvMatch[1]);
70
+ }
71
+ // Add onClick + conditional active class to tab buttons
72
+ let tabIdx = 0;
73
+ result.jsx = result.jsx.replace(new RegExp(`(<button[^>]*)(className="[^"]*\\b${escapeRegex(tabClass)}\\b[^"]*(?:\\s+${escapeRegex(activeClass)})?[^"]*")([^>]*>)`, 'g'), (_match, before, classAttr, after) => {
74
+ const idx = tabIdx++;
75
+ // Replace static class with conditional
76
+ const baseClasses = classAttr
77
+ .replace(/className="/, '')
78
+ .replace(/"$/, '')
79
+ .replace(new RegExp(`\\s*\\b${escapeRegex(activeClass)}\\b`, 'g'), '')
80
+ .trim();
81
+ const newClass = `className={\`${baseClasses} \${${stateVar} === ${idx} ? '${activeClass}' : ''}\`}`;
82
+ return `${before}${newClass} onClick={() => ${setter}(${idx})}${after}`;
83
+ });
84
+ // Add conditional active class to panels and hide inactive panels
85
+ let panelIdx = 0;
86
+ result.jsx = result.jsx.replace(new RegExp(`(<div[^>]*)(className="[^"]*\\b${escapeRegex(panelClass)}\\b[^"]*(?:\\s+${escapeRegex(activeClass)})?[^"]*")([^>]*>)`, 'g'), (_match, before, classAttr, after) => {
87
+ const idx = panelIdx++;
88
+ const baseClasses = classAttr
89
+ .replace(/className="/, '')
90
+ .replace(/"$/, '')
91
+ .replace(new RegExp(`\\s*\\b${escapeRegex(activeClass)}\\b`, 'g'), '')
92
+ .trim();
93
+ const newClass = `className={\`${baseClasses} \${${stateVar} === ${idx} ? '${activeClass}' : ''}\`}`;
94
+ const styleAttr = ` style={{ display: ${stateVar} === ${idx} ? 'block' : 'none' }}`;
95
+ return `${before}${newClass}${styleAttr}${after}`;
96
+ });
97
+ }
98
+ // ─── Mobile Menu ───────────────────────────────────────────────────
99
+ function implementMobileMenu(result) {
100
+ // Detect hamburger pattern: element with class containing 'ham', 'hamburger', 'menu-toggle', 'burger'
101
+ const hamPatterns = ['ham', 'hamburger', 'menu-toggle', 'burger', 'mobile-toggle', 'nav-toggle'];
102
+ const mobPatterns = ['mob', 'mobile-menu', 'mobile-nav', 'nav-mobile', 'side-menu', 'offcanvas'];
103
+ let hasHamburger = false;
104
+ let hasMobileMenu = false;
105
+ for (const p of hamPatterns) {
106
+ if (result.jsx.includes(p)) {
107
+ hasHamburger = true;
108
+ break;
109
+ }
110
+ }
111
+ for (const p of mobPatterns) {
112
+ if (result.jsx.includes(p)) {
113
+ hasMobileMenu = true;
114
+ break;
115
+ }
116
+ }
117
+ if (!hasHamburger && !hasMobileMenu)
118
+ return;
119
+ result.stateDeclarations.push(`const [menuOpen, setMenuOpen] = useState(false);`);
120
+ result.handlers.push(`const toggleMenu = () => {\n` +
121
+ ` setMenuOpen(prev => !prev);\n` +
122
+ ` document.body.style.overflow = !menuOpen ? 'hidden' : '';\n` +
123
+ ` };`);
124
+ result.effects.push(`// Cleanup body overflow on unmount\n` +
125
+ ` return () => { document.body.style.overflow = ''; };`);
126
+ // Add onClick to hamburger button
127
+ let hamApplied = false;
128
+ for (const p of hamPatterns) {
129
+ if (hamApplied)
130
+ break;
131
+ const hamRe = new RegExp(`(<(?:button|div|span)[^>]*className="[^"]*\\b${escapeRegex(p)}\\b[^"]*"[^>]*)(>)`, 'g');
132
+ const original = result.jsx;
133
+ result.jsx = result.jsx.replace(hamRe, (_m, before, after) => {
134
+ if (before.includes('onClick'))
135
+ return _m;
136
+ const newBefore = before.replace(/className="([^"]*)"/, `className={\`$1 \${menuOpen ? 'open' : ''}\`}`);
137
+ return `${newBefore} onClick={toggleMenu}${after}`;
138
+ });
139
+ if (result.jsx !== original)
140
+ hamApplied = true;
141
+ }
142
+ // Add conditional 'open' class to mobile menu
143
+ let mobApplied = false;
144
+ for (const p of mobPatterns) {
145
+ if (mobApplied)
146
+ break;
147
+ const mobRe = new RegExp(`(className="[^"]*\\b${escapeRegex(p)}\\b[^"]*")`, 'g');
148
+ const original = result.jsx;
149
+ result.jsx = result.jsx.replace(mobRe, (_m, classAttr) => {
150
+ return classAttr.replace(/className="([^"]*)"/, `className={\`$1 \${menuOpen ? 'open' : ''}\`}`);
151
+ });
152
+ if (result.jsx !== original)
153
+ mobApplied = true;
154
+ }
155
+ }
156
+ // ─── Billing / Toggle Switch ───────────────────────────────────────
157
+ function implementBillingToggle(result) {
158
+ // Detect billing toggle pattern: elements with classes like 'btog', 'billing-toggle', 'toggle-switch'
159
+ // and price elements with data-m/data-a attributes
160
+ const hasToggle = /data-m=|data-monthly=|data-m\b/.test(result.jsx);
161
+ const hasToggleBtn = /btog|billing-toggle|toggle-billing|price-toggle/.test(result.jsx);
162
+ if (!hasToggle && !hasToggleBtn)
163
+ return;
164
+ result.stateDeclarations.push(`const [annual, setAnnual] = useState(false);`);
165
+ result.handlers.push(`const toggleBilling = () => {\n` +
166
+ ` setAnnual(prev => !prev);\n` +
167
+ ` };`);
168
+ // Add onClick to the outer billing-toggle wrapper only.
169
+ // Remove any existing onClick on the inner #btog to prevent double-toggle from bubbling.
170
+ result.jsx = result.jsx.replace(/(<(?:button|div|span)[^>]*className="[^"]*(?:billing-toggle|toggle-billing|price-toggle)[^"]*"[^>]*)(>)/g, (_m, before, after) => {
171
+ if (before.includes('onClick'))
172
+ return _m;
173
+ const newBefore = before.includes('className="')
174
+ ? before.replace(/className="([^"]*)"/, `className={\`$1 \${annual ? 'on' : ''}\`}`)
175
+ : before;
176
+ return `${newBefore} onClick={toggleBilling}${after}`;
177
+ });
178
+ // Remove existing onClick on inner #btog element (parent already handles it)
179
+ // Use brace-counting since handlers have nested braces like onClick={() => { fn(); }}
180
+ result.jsx = removeAttrFromElement(result.jsx, 'id="btog"', 'onClick');
181
+ // Add conditional 'on' class to #btog
182
+ result.jsx = result.jsx.replace(/(<[^>]*id="btog"[^>]*)className="([^"]*)"([^>]*>)/g, (_m, before, cls, after) => {
183
+ return `${before}className={\`${cls} \${annual ? 'on' : ''}\`}${after}`;
184
+ });
185
+ // Replace price value spans with conditional rendering
186
+ // Match elements that have data-m and data-a attributes (pval class can be in any position)
187
+ // Use [^>]* for attrs to avoid crossing tag boundaries
188
+ result.jsx = result.jsx.replace(/<(span|div)\b([^>]*?)data-m="([^"]*)"([^>]*?)data-a="([^"]*)"([^>]*)>[^<]*<\/\1>/g, (match, tag, pre, monthly, mid, annualVal, post) => {
189
+ const attrs = `${pre}data-m="${monthly}"${mid}data-a="${annualVal}"${post}`;
190
+ return `<${tag}${attrs}>{annual ? '${annualVal}' : '${monthly}'}</${tag}>`;
191
+ });
192
+ // Also handle data-a before data-m order
193
+ result.jsx = result.jsx.replace(/<(span|div)\b([^>]*?)data-a="([^"]*)"([^>]*?)data-m="([^"]*)"([^>]*)>[^<]*<\/\1>/g, (match, tag, pre, annualVal, mid, monthly, post) => {
194
+ const attrs = `${pre}data-a="${annualVal}"${mid}data-m="${monthly}"${post}`;
195
+ return `<${tag}${attrs}>{annual ? '${annualVal}' : '${monthly}'}</${tag}>`;
196
+ });
197
+ // Replace period text elements
198
+ result.jsx = result.jsx.replace(/(<[^>]*id="proPer"[^>]*>)[^<]*(<\/[^>]+>)/g, (_m, open, close) => `${open}{annual ? 'per month · billed annually' : 'per month · billed monthly'}${close}`);
199
+ result.jsx = result.jsx.replace(/(<[^>]*id="teamPer"[^>]*>)[^<]*(<\/[^>]+>)/g, (_m, open, close) => `${open}{annual ? 'per month · billed annually' : 'per month · up to 10 devs'}${close}`);
200
+ }
201
+ // ─── CTA Email Form ────────────────────────────────────────────────
202
+ function implementCtaForm(result) {
203
+ // Detect CTA email input pattern
204
+ const hasCtaEmail = /id="ctaEmail"|name="email"[^>]*class[^>]*cta/i.test(result.jsx) ||
205
+ /input-group/.test(result.jsx);
206
+ const hasEmailInput = /type="email"/.test(result.jsx);
207
+ if (!hasCtaEmail && !hasEmailInput)
208
+ return;
209
+ result.stateDeclarations.push(`const [ctaEmail, setCtaEmail] = useState('');`, `const [ctaStatus, setCtaStatus] = useState<'idle' | 'success' | 'error'>('idle');`);
210
+ result.additionalHooks.add('useCallback');
211
+ result.handlers.push(`const handleCta = useCallback(() => {\n` +
212
+ ` if (ctaEmail && ctaEmail.includes('@')) {\n` +
213
+ ` setCtaStatus('success');\n` +
214
+ ` setCtaEmail('');\n` +
215
+ ` setTimeout(() => setCtaStatus('idle'), 4000);\n` +
216
+ ` } else {\n` +
217
+ ` setCtaStatus('error');\n` +
218
+ ` setTimeout(() => setCtaStatus('idle'), 2000);\n` +
219
+ ` }\n` +
220
+ ` }, [ctaEmail]);`);
221
+ // Wire up the email input
222
+ result.jsx = result.jsx.replace(/(<input[^>]*(?:id="ctaEmail"|type="email")[^>]*?)\s*\/?>/g, (_match, before) => {
223
+ // Remove existing value/onChange/placeholder attributes that we'll replace
224
+ let cleaned = before
225
+ .replace(/\s*value="[^"]*"/g, '')
226
+ .replace(/\s*onChange=\{[^}]*\}/g, '')
227
+ .replace(/\s*onKeyDown=\{[^}]*\}/g, '')
228
+ .replace(/\s*placeholder="[^"]*"/g, '');
229
+ return `${cleaned} value={ctaEmail} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setCtaEmail(e.target.value)} onKeyDown={(e: React.KeyboardEvent) => { if (e.key === 'Enter') handleCta(); }} placeholder={ctaStatus === 'success' ? "We'll be in touch soon." : "your@email.com"} style={ctaStatus === 'error' ? { outline: '1px solid var(--red, #e74c3c)' } : undefined} />`;
230
+ });
231
+ // Wire up the CTA button — match buttons that call handleCta or are in input-group
232
+ result.jsx = result.jsx.replace(/(<button[^>]*(?:className="[^"]*(?:cta|get-access|early-access|submit)[^"]*"|onClick=\{[^}]*handleCta[^}]*\})[^>]*>)([^<]*?)(<\/button>)/gi, (_m, open, text, close) => {
233
+ // Replace onClick if it's a stub
234
+ let newOpen = open.replace(/onClick=\{[^}]*\}/, 'onClick={handleCta}');
235
+ if (!newOpen.includes('onClick')) {
236
+ newOpen = newOpen.replace(/>$/, ' onClick={handleCta}>');
237
+ }
238
+ // Add conditional style for success state
239
+ if (!newOpen.includes('style=')) {
240
+ newOpen = newOpen.replace(/>$/, ` style={ctaStatus === 'success' ? { background: '#3ecf6e' } : undefined}>`);
241
+ }
242
+ return `${newOpen}{ctaStatus === 'success' ? "You're on the list ✓" : '${text.trim()}'}${close}`;
243
+ });
244
+ // Simplify any stub-style onClick handlers for handleCta
245
+ result.jsx = result.jsx.replace(/onClick=\{\(\)\s*=>\s*\{\s*handleCta\(\);\s*\}\}/g, 'onClick={handleCta}');
246
+ // Also fix any double-brace issues from the replacement
247
+ result.jsx = result.jsx.replace(/onClick=\{handleCta\}\}/g, 'onClick={handleCta}');
248
+ }
249
+ // ─── Ripple Effect ─────────────────────────────────────────────────
250
+ function implementRipple(result) {
251
+ // Detect primary buttons that should have ripple effect
252
+ const hasRippleTargets = /btn-primary|plan-btn|nav-install/.test(result.jsx);
253
+ if (!hasRippleTargets)
254
+ return;
255
+ // We add a ripple handler and inject it on matching buttons
256
+ result.handlers.push(`const handleRipple = (e: React.MouseEvent<HTMLElement>) => {\n` +
257
+ ` const btn = e.currentTarget;\n` +
258
+ ` const rect = btn.getBoundingClientRect();\n` +
259
+ ` const ripple = document.createElement('span');\n` +
260
+ ` ripple.style.cssText = \`position:absolute;border-radius:50%;background:rgba(255,255,255,0.18);width:80px;height:80px;pointer-events:none;transform:scale(0);animation:ripple 0.6s ease forwards;left:\${e.clientX - rect.left - 40}px;top:\${e.clientY - rect.top - 40}px\`;\n` +
261
+ ` btn.style.position = 'relative';\n` +
262
+ ` btn.style.overflow = 'hidden';\n` +
263
+ ` btn.appendChild(ripple);\n` +
264
+ ` setTimeout(() => ripple.remove(), 600);\n` +
265
+ ` };`);
266
+ // Add onClick ripple handler to matching buttons
267
+ // For buttons that already have onClick, wrap to call both
268
+ const rippleClasses = ['btn-primary', 'plan-btn', 'nav-install'];
269
+ for (const cls of rippleClasses) {
270
+ const btnRe = new RegExp(`(<(?:button|a)[^>]*className="[^"]*\\b${escapeRegex(cls)}\\b[^"]*"[^>]*?)(\\s*onClick=\\{([^}]*)\\})([^>]*>)`, 'g');
271
+ if (btnRe.test(result.jsx)) {
272
+ // Has existing onClick — wrap it
273
+ result.jsx = result.jsx.replace(btnRe, (_m, before, _onClick, handler, after) => {
274
+ return `${before} onClick={(e) => { handleRipple(e); (${handler})(e); }}${after}`;
275
+ });
276
+ }
277
+ else {
278
+ // No existing onClick — add one
279
+ const simpleRe = new RegExp(`(<(?:button|a)[^>]*className="[^"]*\\b${escapeRegex(cls)}\\b[^"]*"[^>]*?)(>)`, 'g');
280
+ result.jsx = result.jsx.replace(simpleRe, (_m, before, after) => {
281
+ if (before.includes('onClick'))
282
+ return _m;
283
+ return `${before} onClick={handleRipple}${after}`;
284
+ });
285
+ }
286
+ }
287
+ }
288
+ // ─── Helpers ───────────────────────────────────────────────────────
289
+ function escapeRegex(str) {
290
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
291
+ }
292
+ /**
293
+ * Remove a JSX attribute (with brace-balanced value) from an element matching an identifier.
294
+ * Handles nested braces like onClick={() => { fn(); }}.
295
+ */
296
+ function removeAttrFromElement(jsx, elementMatch, attrName) {
297
+ const elemIdx = jsx.indexOf(elementMatch);
298
+ if (elemIdx === -1)
299
+ return jsx;
300
+ // Find the onClick={...} within this element's tag
301
+ const searchStart = elemIdx;
302
+ // Find the closing > of this element's opening tag
303
+ const tagEnd = jsx.indexOf('>', searchStart);
304
+ if (tagEnd === -1)
305
+ return jsx;
306
+ const tagContent = jsx.slice(searchStart, tagEnd + 1);
307
+ const attrStart = tagContent.indexOf(`${attrName}={`);
308
+ if (attrStart === -1)
309
+ return jsx;
310
+ // Count braces from the opening { to find the matching }
311
+ const absAttrStart = searchStart + attrStart;
312
+ const braceStart = jsx.indexOf('{', absAttrStart + attrName.length);
313
+ if (braceStart === -1)
314
+ return jsx;
315
+ let depth = 0;
316
+ let i = braceStart;
317
+ while (i < jsx.length) {
318
+ if (jsx[i] === '{')
319
+ depth++;
320
+ else if (jsx[i] === '}') {
321
+ depth--;
322
+ if (depth === 0)
323
+ break;
324
+ }
325
+ i++;
326
+ }
327
+ // Remove the attribute including any leading whitespace
328
+ let removeStart = absAttrStart;
329
+ while (removeStart > 0 && jsx[removeStart - 1] === ' ')
330
+ removeStart--;
331
+ // Keep at least one space if there's content before
332
+ if (removeStart > 0 && jsx[removeStart - 1] !== ' ' && jsx[removeStart - 1] !== '"')
333
+ removeStart++;
334
+ return jsx.slice(0, removeStart) + jsx.slice(i + 1);
335
+ }
336
+ //# sourceMappingURL=pattern-implementer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pattern-implementer.js","sourceRoot":"","sources":["../../src/generators/pattern-implementer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Performance optimizations for converted React components.
3
+ *
4
+ * Provides helpers that wrap components with React.memo, add lazy-loading,
5
+ * optimise images, configure code-splitting, insert useMemo / useCallback,
6
+ * and generate reusable performance utilities.
7
+ */
8
+ /**
9
+ * Wraps a React component export with React.memo().
10
+ *
11
+ * Handles both `export default function Foo` and `export default Foo` patterns
12
+ * and ensures `memo` is imported from React.
13
+ */
14
+ export declare function wrapWithMemo(componentCode: string, componentName: string): string;
15
+ /**
16
+ * Converts static component imports to React.lazy() and wraps the
17
+ * rendered tree in a <Suspense> boundary with a <Loading /> fallback.
18
+ */
19
+ export declare function addLazyLoading(appCode: string, componentNames: string[]): string;
20
+ /**
21
+ * Converts `<img>` tags to include loading="lazy", adds missing
22
+ * width / height attributes, and adds a comment suggesting a
23
+ * `<picture>` + WebP srcset alternative.
24
+ */
25
+ export declare function generateImageOptimization(html: string): string;
26
+ /**
27
+ * Returns Vite config additions for manual chunk splitting
28
+ * (vendor, router, and UI framework chunks).
29
+ */
30
+ export declare function generateCodeSplitConfig(): string;
31
+ /**
32
+ * Scans JSX for inline object / array literals and arrow functions
33
+ * passed as props and wraps them with useMemo / useCallback.
34
+ *
35
+ * This is a best-effort transformation. Complex patterns may need
36
+ * manual review.
37
+ */
38
+ export declare function addUseMemoCallbacks(componentCode: string): string;
39
+ /**
40
+ * Returns a utility module with common performance helpers:
41
+ * - useIntersectionObserver hook
42
+ * - useDeferredValue wrapper for search inputs
43
+ * - debounce / throttle utility functions
44
+ */
45
+ export declare function generatePerformanceUtils(): string;
46
+ /**
47
+ * Returns a simple Loading / Skeleton component with a CSS animation
48
+ * suitable as a Suspense fallback.
49
+ */
50
+ export declare function generateLoadingFallback(): string;
51
+ //# sourceMappingURL=performance-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance-generator.d.ts","sourceRoot":"","sources":["../../src/generators/performance-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAgDjF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,CAgDhF;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAyD9D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CA+BhD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CA4DjE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CA6HjD;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CA8ChD"}