@el-j/magic-helix-plugins 4.0.0-beta.6 → 4.0.0-beta.8

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.
@@ -1,21 +1,22 @@
1
- import * as s from "node:fs";
2
- import * as a from "node:path";
3
- class l {
1
+ import * as n from "node:fs";
2
+ import * as s from "node:path";
3
+ import { fileURLToPath as c } from "node:url";
4
+ class u {
4
5
  // Helper methods for common operations
5
6
  /**
6
7
  * Check if a file exists in the project
7
8
  */
8
9
  fileExists(e, r) {
9
- return s.existsSync(a.join(e, r));
10
+ return n.existsSync(s.join(e, r));
10
11
  }
11
12
  /**
12
13
  * Read a file from the project
13
14
  */
14
15
  readFile(e, r) {
15
16
  try {
16
- const t = a.join(e, r);
17
- if (s.existsSync(t))
18
- return s.readFileSync(t, "utf-8");
17
+ const t = s.join(e, r);
18
+ if (n.existsSync(t))
19
+ return n.readFileSync(t, "utf-8");
19
20
  } catch {
20
21
  }
21
22
  return null;
@@ -36,15 +37,31 @@ class l {
36
37
  * Get project name from path
37
38
  */
38
39
  getProjectName(e) {
39
- return a.basename(e);
40
+ return s.basename(e);
41
+ }
42
+ /**
43
+ * List entries in a project directory (non-recursive)
44
+ */
45
+ listFiles(e) {
46
+ try {
47
+ return n.readdirSync(e);
48
+ } catch {
49
+ return [];
50
+ }
51
+ }
52
+ /**
53
+ * Get the directory name from import.meta.url (ES module alternative to __dirname)
54
+ */
55
+ getDirname(e) {
56
+ return s.dirname(c(e));
40
57
  }
41
58
  /**
42
59
  * Load template from file
43
60
  */
44
61
  async loadTemplateFromFile(e) {
45
62
  try {
46
- if (s.existsSync(e))
47
- return s.readFileSync(e, "utf-8");
63
+ if (n.existsSync(e))
64
+ return n.readFileSync(e, "utf-8");
48
65
  } catch {
49
66
  }
50
67
  return null;
@@ -52,12 +69,12 @@ class l {
52
69
  /**
53
70
  * Create a template definition with lazy loading
54
71
  */
55
- createTemplate(e, r, t, n = {}) {
72
+ createTemplate(e, r, t, i = {}) {
56
73
  return {
57
74
  name: e,
58
75
  tags: r,
59
76
  content: t,
60
- ...n
77
+ ...i
61
78
  };
62
79
  }
63
80
  /**
@@ -65,9 +82,9 @@ class l {
65
82
  */
66
83
  parseDependencies(e, ...r) {
67
84
  const t = {};
68
- for (const n of r) {
69
- const i = e[n];
70
- i && typeof i == "object" && Object.assign(t, i);
85
+ for (const i of r) {
86
+ const a = e[i];
87
+ a && typeof a == "object" && Object.assign(t, a);
71
88
  }
72
89
  return t;
73
90
  }
@@ -93,5 +110,5 @@ class l {
93
110
  }
94
111
  }
95
112
  export {
96
- l as B
113
+ u as B
97
114
  };
@@ -0,0 +1 @@
1
+ "use strict";var o=Object.create;var l=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var y=Object.getPrototypeOf,p=Object.prototype.hasOwnProperty;var g=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of d(e))!p.call(n,s)&&s!==t&&l(n,s,{get:()=>e[s],enumerable:!(r=f(e,s))||r.enumerable});return n};var m=(n,e,t)=>(t=n!=null?o(y(n)):{},g(e||!n||!n.__esModule?l(t,"default",{value:n,enumerable:!0}):t,n));const b=require("node:fs"),h=require("node:path"),F=require("node:url");function u(n){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const t in n)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(n,t);Object.defineProperty(e,t,r.get?r:{enumerable:!0,get:()=>n[t]})}}return e.default=n,Object.freeze(e)}const i=u(b),a=u(h);class S{fileExists(e,t){return i.existsSync(a.join(e,t))}readFile(e,t){try{const r=a.join(e,t);if(i.existsSync(r))return i.readFileSync(r,"utf-8")}catch{}return null}readJSON(e,t){try{const r=this.readFile(e,t);if(r)return JSON.parse(r)}catch{}return null}getProjectName(e){return a.basename(e)}listFiles(e){try{return i.readdirSync(e)}catch{return[]}}getDirname(e){return a.dirname(F.fileURLToPath(e))}async loadTemplateFromFile(e){try{if(i.existsSync(e))return i.readFileSync(e,"utf-8")}catch{}return null}createTemplate(e,t,r,s={}){return{name:e,tags:t,content:r,...s}}parseDependencies(e,...t){const r={};for(const s of t){const c=e[s];c&&typeof c=="object"&&Object.assign(r,c)}return r}async findFiles(e,t){try{const{glob:r}=await import("glob");return await r(t,{cwd:e,absolute:!1})}catch{return[]}}async hasFiles(e,t){return(await this.findFiles(e,t)).length>0}}exports.BasePlugin=S;
@@ -1,5 +1,5 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("../BasePlugin-odQJAKA-.cjs");class m extends u.BasePlugin{constructor(){super(...arguments),this.name="cpp",this.displayName="C/C++",this.version="3.0.0",this.priority=85}async detect(t){const i=[],s={};let r,o=this.getProjectName(t);const e=await this.detectPlatformIO(t);if(e&&(i.push("platformio"),r="platformio.ini",e.board&&i.push(`board-${e.board}`),e.platform&&(i.push(`platform-${e.platform}`),e.platform.includes("espressif32")&&i.push("esp32"),e.platform.includes("espressif8266")&&i.push("esp8266"),e.platform.includes("atmelavr")&&i.push("arduino")),e.framework&&(i.push(`framework-${e.framework}`),e.framework==="arduino"&&i.push("arduino")),e.libs))for(const a of e.libs)s[a]="*";if(this.fileExists(t,"CMakeLists.txt")){i.push("cmake"),r||(r="CMakeLists.txt");const a=this.readFile(t,"CMakeLists.txt");if(a){const c=a.match(/project\s*\(\s*([^\s)]+)/i);c&&(o=c[1])}}return(this.fileExists(t,"Makefile")||this.fileExists(t,"makefile"))&&(i.push("makefile"),r||(r="Makefile")),await this.hasFiles(t,"*.ino")&&(i.push("arduino"),r||(r="*.ino")),await this.hasFiles(t,"**/*.{cpp,c,h,hpp}")&&(i.push("cpp"),r||(r="*.cpp")),i.length===0?null:{language:"C/C++",name:o,dependencies:s,manifestFile:r,projectPath:t,tags:i}}async detectPlatformIO(t){if(!this.fileExists(t,"platformio.ini"))return null;const i=this.readFile(t,"platformio.ini");if(!i)return null;const s={libs:[]},r=i.split(`
2
- `);let o=!1,e=null;for(const p of r){const n=p.trim();if(n.startsWith("[env:")){o=!0,e=null;continue}if(n.startsWith("[")&&n.endsWith("]")){o=!1,e=null;continue}if(o||!s.board){const l=n.match(/^(\w+)\s*=\s*(.*)$/);if(l){const[,f,a]=l;switch(e=f,f){case"board":s.board=a.trim();break;case"platform":s.platform=a.trim();break;case"framework":s.framework=a.trim();break;case"lib_deps":a.trim()&&s.libs?.push(a.trim());break}}else e==="lib_deps"&&n&&!n.startsWith("[")&&s.libs?.push(n)}}return s.board||s.platform?s:null}getTemplates(){return[{name:"cpp-core",tags:["cpp"],content:this.getCppTemplate()},{name:"platformio-core",tags:["platformio"],content:this.getPlatformIOTemplate()},{name:"arduino-core",tags:["arduino"],content:this.getArduinoTemplate()}]}getDependencyTagMap(){return{boost:"boost",fmt:"fmt",spdlog:"spdlog",googletest:"gtest",catch2:"catch2","Adafruit GFX Library":"adafruit-gfx",WiFi:"wifi",ESP32:"esp32",FastLED:"fastled",ArduinoJson:"arduino-json"}}getConfigFileTagMap(){return{"platformio.ini":"platformio","CMakeLists.txt":"cmake",Makefile:"makefile",".clang-format":"clang-format",".clang-tidy":"clang-tidy"}}getCppTemplate(){return`# C/C++ Development Guidelines
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("../BasePlugin-Be6rLq9o.cjs");var p=typeof document<"u"?document.currentScript:null;class d extends m.BasePlugin{constructor(){super(...arguments),this.name="cpp",this.displayName="C/C++",this.version="3.0.0",this.priority=85}async detect(t){const i=[],r={};let s,o=this.getProjectName(t);const e=await this.detectPlatformIO(t);if(e&&(i.push("platformio"),s="platformio.ini",e.board&&i.push(`board-${e.board}`),e.platform&&(i.push(`platform-${e.platform}`),e.platform.includes("espressif32")&&i.push("esp32"),e.platform.includes("espressif8266")&&i.push("esp8266"),e.platform.includes("atmelavr")&&i.push("arduino")),e.framework&&(i.push(`framework-${e.framework}`),e.framework==="arduino"&&i.push("arduino")),e.libs))for(const n of e.libs)r[n]="*";if(this.fileExists(t,"CMakeLists.txt")){i.push("cmake"),s||(s="CMakeLists.txt");const n=this.readFile(t,"CMakeLists.txt");if(n){const u=n.match(/project\s*\(\s*([^\s)]+)/i);u&&(o=u[1])}}return(this.fileExists(t,"Makefile")||this.fileExists(t,"makefile"))&&(i.push("makefile"),s||(s="Makefile")),await this.hasFiles(t,"*.ino")&&(i.push("arduino"),s||(s="*.ino")),await this.hasFiles(t,"**/*.{cpp,c,h,hpp}")&&(i.push("cpp"),s||(s="*.cpp")),i.length===0?null:{language:"C/C++",name:o,dependencies:r,manifestFile:s,projectPath:t,tags:i}}async detectPlatformIO(t){if(!this.fileExists(t,"platformio.ini"))return null;const i=this.readFile(t,"platformio.ini");if(!i)return null;const r={libs:[]},s=i.split(`
2
+ `);let o=!1,e=null;for(const f of s){const a=f.trim();if(a.startsWith("[env:")){o=!0,e=null;continue}if(a.startsWith("[")&&a.endsWith("]")){o=!1,e=null;continue}if(o||!r.board){const l=a.match(/^(\w+)\s*=\s*(.*)$/);if(l){const[,c,n]=l;switch(e=c,c){case"board":r.board=n.trim();break;case"platform":r.platform=n.trim();break;case"framework":r.framework=n.trim();break;case"lib_deps":n.trim()&&r.libs?.push(n.trim());break}}else e==="lib_deps"&&a&&!a.startsWith("[")&&r.libs?.push(a)}}return r.board||r.platform?r:null}getTemplates(){return this.getDirname(typeof document>"u"?require("url").pathToFileURL(__filename).href:p&&p.tagName.toUpperCase()==="SCRIPT"&&p.src||new URL("cpp/index.cjs",document.baseURI).href),[{name:"cpp-core",tags:["cpp"],content:this.getCppTemplate()},{name:"platformio-core",tags:["platformio"],content:this.getPlatformIOTemplate()},{name:"arduino-core",tags:["arduino"],content:this.getArduinoTemplate()}]}getDependencyTagMap(){return{boost:"boost",fmt:"fmt",spdlog:"spdlog",googletest:"gtest",catch2:"catch2","Adafruit GFX Library":"adafruit-gfx",WiFi:"wifi",ESP32:"esp32",FastLED:"fastled",ArduinoJson:"arduino-json"}}getConfigFileTagMap(){return{"platformio.ini":"platformio","CMakeLists.txt":"cmake",Makefile:"makefile",".clang-format":"clang-format",".clang-tidy":"clang-tidy"}}getCppTemplate(){return`# C/C++ Development Guidelines
3
3
 
4
4
  This project uses C/C++.
5
5
 
@@ -76,4 +76,4 @@ This is an Arduino project.
76
76
  - Check Serial Monitor baud rate
77
77
  - Validate sensor readings
78
78
  - Test incrementally
79
- `}}exports.CppPlugin=m;
79
+ `}}exports.CppPlugin=d;
@@ -1,4 +1,4 @@
1
- import { B as u } from "../BasePlugin-6wv0hYJ9.js";
1
+ import { B as u } from "../BasePlugin-BXz3Zpy5.js";
2
2
  class g extends u {
3
3
  constructor() {
4
4
  super(...arguments), this.name = "cpp", this.displayName = "C/C++", this.version = "3.0.0", this.priority = 85;
@@ -74,7 +74,7 @@ class g extends u {
74
74
  return s.board || s.platform ? s : null;
75
75
  }
76
76
  getTemplates() {
77
- return [
77
+ return this.getDirname(import.meta.url), [
78
78
  {
79
79
  name: "cpp-core",
80
80
  tags: ["cpp"],
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("node:path"),p=require("../BasePlugin-odQJAKA-.cjs");function l(n){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const t in n)if(t!=="default"){const a=Object.getOwnPropertyDescriptor(n,t);Object.defineProperty(e,t,a.get?a:{enumerable:!0,get:()=>n[t]})}}return e.default=n,Object.freeze(e)}const u=l(c);class g extends p.BasePlugin{constructor(){super(...arguments),this.name="csharp",this.displayName="C#",this.version="3.0.0",this.priority=60}async detect(e){const t=await this.findFiles(e,"*.csproj");if(t.length===0)return null;const a=t[0],s=this.readFile(e,a),r={};if(s){const o=s.matchAll(/<PackageReference\s+Include="([^"]+)"(?:\s+Version="([^"]+)")?/g);for(const i of o)r[i[1]]=i[2]||"*"}return{language:"C#",name:a.replace(".csproj",""),dependencies:r,manifestFile:a,projectPath:e}}getTemplates(){return[{name:"csharp-core",tags:["csharp","dotnet"],content:()=>this.loadTemplateFromFile(u.join(__dirname,"templates/lang-csharp.md")).then(e=>e||this.getCSharpFallbackTemplate())}]}getCSharpFallbackTemplate(){return`# C# / .NET Development Guidelines
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const p=require("node:path"),l=require("../BasePlugin-Be6rLq9o.cjs");var a=typeof document<"u"?document.currentScript:null;function u(n){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const t in n)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(n,t);Object.defineProperty(e,t,r.get?r:{enumerable:!0,get:()=>n[t]})}}return e.default=n,Object.freeze(e)}const d=u(p);class g extends l.BasePlugin{constructor(){super(...arguments),this.name="csharp",this.displayName="C#",this.version="3.0.0",this.priority=60}async detect(e){const t=await this.findFiles(e,"*.csproj");if(t.length===0)return null;const r=t[0],s=this.readFile(e,r),i={};if(s){const o=s.matchAll(/<PackageReference\s+Include="([^"]+)"(?:\s+Version="([^"]+)")?/g);for(const c of o)i[c[1]]=c[2]||"*"}return{language:"C#",name:r.replace(".csproj",""),dependencies:i,manifestFile:r,projectPath:e}}getTemplates(){const e=this.getDirname(typeof document>"u"?require("url").pathToFileURL(__filename).href:a&&a.tagName.toUpperCase()==="SCRIPT"&&a.src||new URL("csharp/index.cjs",document.baseURI).href);return[{name:"csharp-core",tags:["csharp","dotnet"],content:()=>this.loadTemplateFromFile(d.join(e,"templates/lang-csharp.md")).then(t=>t||this.getCSharpFallbackTemplate())}]}getCSharpFallbackTemplate(){return`# C# / .NET Development Guidelines
2
2
 
3
3
  This project uses C# and .NET.
4
4
 
@@ -1,14 +1,14 @@
1
1
  import * as o from "node:path";
2
- import { B as p } from "../BasePlugin-6wv0hYJ9.js";
3
- class g extends p {
2
+ import { B as p } from "../BasePlugin-BXz3Zpy5.js";
3
+ class m extends p {
4
4
  constructor() {
5
5
  super(...arguments), this.name = "csharp", this.displayName = "C#", this.version = "3.0.0", this.priority = 60;
6
6
  }
7
7
  async detect(e) {
8
- const s = await this.findFiles(e, "*.csproj");
9
- if (s.length === 0)
8
+ const t = await this.findFiles(e, "*.csproj");
9
+ if (t.length === 0)
10
10
  return null;
11
- const t = s[0], n = this.readFile(e, t), a = {};
11
+ const s = t[0], n = this.readFile(e, s), a = {};
12
12
  if (n) {
13
13
  const i = n.matchAll(
14
14
  /<PackageReference\s+Include="([^"]+)"(?:\s+Version="([^"]+)")?/g
@@ -18,20 +18,21 @@ class g extends p {
18
18
  }
19
19
  return {
20
20
  language: "C#",
21
- name: t.replace(".csproj", ""),
21
+ name: s.replace(".csproj", ""),
22
22
  dependencies: a,
23
- manifestFile: t,
23
+ manifestFile: s,
24
24
  projectPath: e
25
25
  };
26
26
  }
27
27
  getTemplates() {
28
+ const e = this.getDirname(import.meta.url);
28
29
  return [
29
30
  {
30
31
  name: "csharp-core",
31
32
  tags: ["csharp", "dotnet"],
32
33
  content: () => this.loadTemplateFromFile(
33
- o.join(__dirname, "templates/lang-csharp.md")
34
- ).then((e) => e || this.getCSharpFallbackTemplate())
34
+ o.join(e, "templates/lang-csharp.md")
35
+ ).then((t) => t || this.getCSharpFallbackTemplate())
35
36
  }
36
37
  ];
37
38
  }
@@ -64,5 +65,5 @@ This project uses C# and .NET.
64
65
  }
65
66
  }
66
67
  export {
67
- g as CSharpPlugin
68
+ m as CSharpPlugin
68
69
  };
@@ -0,0 +1,340 @@
1
+ # Flutter Development Guidelines
2
+
3
+ ## Architecture & Structure
4
+
5
+ ### Project Organization
6
+ ```
7
+ lib/
8
+ ├── main.dart
9
+ ├── app.dart
10
+ ├── core/
11
+ │ ├── constants/
12
+ │ ├── theme/
13
+ │ └── utils/
14
+ ├── features/
15
+ │ ├── auth/
16
+ │ │ ├── data/
17
+ │ │ ├── domain/
18
+ │ │ └── presentation/
19
+ │ └── home/
20
+ └── shared/
21
+ ├── widgets/
22
+ └── models/
23
+ ```
24
+
25
+ ## Widget Best Practices
26
+
27
+ ### StatelessWidget
28
+ ```dart
29
+ class UserCard extends StatelessWidget {
30
+ const UserCard({
31
+ super.key,
32
+ required this.user,
33
+ this.onTap,
34
+ });
35
+
36
+ final User user;
37
+ final VoidCallback? onTap;
38
+
39
+ @override
40
+ Widget build(BuildContext context) {
41
+ return Card(
42
+ child: ListTile(
43
+ title: Text(user.name),
44
+ subtitle: Text(user.email),
45
+ onTap: onTap,
46
+ ),
47
+ );
48
+ }
49
+ }
50
+ ```
51
+
52
+ ### StatefulWidget
53
+ ```dart
54
+ class Counter extends StatefulWidget {
55
+ const Counter({super.key});
56
+
57
+ @override
58
+ State<Counter> createState() => _CounterState();
59
+ }
60
+
61
+ class _CounterState extends State<Counter> {
62
+ int _count = 0;
63
+
64
+ @override
65
+ void dispose() {
66
+ // Clean up resources
67
+ super.dispose();
68
+ }
69
+
70
+ @override
71
+ Widget build(BuildContext context) {
72
+ return Column(
73
+ children: [
74
+ Text('Count: $_count'),
75
+ ElevatedButton(
76
+ onPressed: () => setState(() => _count++),
77
+ child: const Text('Increment'),
78
+ ),
79
+ ],
80
+ );
81
+ }
82
+ }
83
+ ```
84
+
85
+ ## State Management
86
+
87
+ ### Riverpod (Recommended)
88
+ ```dart
89
+ final userProvider = StateNotifierProvider<UserNotifier, AsyncValue<User>>((ref) {
90
+ return UserNotifier();
91
+ });
92
+
93
+ class UserNotifier extends StateNotifier<AsyncValue<User>> {
94
+ UserNotifier() : super(const AsyncValue.loading());
95
+
96
+ Future<void> fetchUser(String id) async {
97
+ state = const AsyncValue.loading();
98
+ state = await AsyncValue.guard(() => api.getUser(id));
99
+ }
100
+ }
101
+
102
+ // Usage in widget
103
+ class UserProfile extends ConsumerWidget {
104
+ @override
105
+ Widget build(BuildContext context, WidgetRef ref) {
106
+ final userState = ref.watch(userProvider);
107
+
108
+ return userState.when(
109
+ data: (user) => Text(user.name),
110
+ loading: () => CircularProgressIndicator(),
111
+ error: (err, stack) => Text('Error: $err'),
112
+ );
113
+ }
114
+ }
115
+ ```
116
+
117
+ ### Bloc Pattern
118
+ ```dart
119
+ class UserBloc extends Bloc<UserEvent, UserState> {
120
+ UserBloc() : super(UserInitial()) {
121
+ on<LoadUser>(_onLoadUser);
122
+ }
123
+
124
+ Future<void> _onLoadUser(LoadUser event, Emitter<UserState> emit) async {
125
+ emit(UserLoading());
126
+ try {
127
+ final user = await repository.getUser(event.id);
128
+ emit(UserLoaded(user));
129
+ } catch (e) {
130
+ emit(UserError(e.toString()));
131
+ }
132
+ }
133
+ }
134
+ ```
135
+
136
+ ## Navigation
137
+
138
+ ### Named Routes
139
+ ```dart
140
+ // Define routes
141
+ final routes = {
142
+ '/': (context) => HomeScreen(),
143
+ '/profile': (context) => ProfileScreen(),
144
+ '/settings': (context) => SettingsScreen(),
145
+ };
146
+
147
+ // Navigate
148
+ Navigator.pushNamed(context, '/profile');
149
+
150
+ // With arguments
151
+ Navigator.pushNamed(
152
+ context,
153
+ '/profile',
154
+ arguments: {'userId': '123'},
155
+ );
156
+ ```
157
+
158
+ ### Go Router (Modern)
159
+ ```dart
160
+ final router = GoRouter(
161
+ routes: [
162
+ GoRoute(
163
+ path: '/',
164
+ builder: (context, state) => HomeScreen(),
165
+ ),
166
+ GoRoute(
167
+ path: '/profile/:id',
168
+ builder: (context, state) {
169
+ final id = state.pathParameters['id']!;
170
+ return ProfileScreen(userId: id);
171
+ },
172
+ ),
173
+ ],
174
+ );
175
+
176
+ // Navigate
177
+ context.go('/profile/123');
178
+ context.push('/settings');
179
+ ```
180
+
181
+ ## Performance Optimization
182
+
183
+ ### const Constructors
184
+ ```dart
185
+ // Use const wherever possible
186
+ const Text('Hello');
187
+ const Padding(padding: EdgeInsets.all(8.0));
188
+ const SizedBox(height: 16);
189
+ ```
190
+
191
+ ### ListView.builder
192
+ ```dart
193
+ // For large lists, use builder
194
+ ListView.builder(
195
+ itemCount: items.length,
196
+ itemBuilder: (context, index) {
197
+ return ListTile(title: Text(items[index]));
198
+ },
199
+ );
200
+ ```
201
+
202
+ ### Keys
203
+ ```dart
204
+ // Use keys for widgets that need to preserve state
205
+ ListView(
206
+ children: items.map((item) =>
207
+ ListTile(
208
+ key: ValueKey(item.id),
209
+ title: Text(item.name),
210
+ )
211
+ ).toList(),
212
+ );
213
+ ```
214
+
215
+ ## Responsive Design
216
+
217
+ ### MediaQuery
218
+ ```dart
219
+ final size = MediaQuery.of(context).size;
220
+ final isPortrait = size.height > size.width;
221
+
222
+ if (size.width > 600) {
223
+ // Tablet layout
224
+ } else {
225
+ // Mobile layout
226
+ }
227
+ ```
228
+
229
+ ### LayoutBuilder
230
+ ```dart
231
+ LayoutBuilder(
232
+ builder: (context, constraints) {
233
+ if (constraints.maxWidth > 600) {
234
+ return WideLayout();
235
+ }
236
+ return NarrowLayout();
237
+ },
238
+ );
239
+ ```
240
+
241
+ ## Testing
242
+
243
+ ### Widget Tests
244
+ ```dart
245
+ testWidgets('Counter increments', (tester) async {
246
+ await tester.pumpWidget(
247
+ MaterialApp(home: Counter()),
248
+ );
249
+
250
+ expect(find.text('0'), findsOneWidget);
251
+
252
+ await tester.tap(find.byType(ElevatedButton));
253
+ await tester.pump();
254
+
255
+ expect(find.text('1'), findsOneWidget);
256
+ });
257
+ ```
258
+
259
+ ### Integration Tests
260
+ ```dart
261
+ void main() {
262
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
263
+
264
+ testWidgets('Complete user flow', (tester) async {
265
+ await tester.pumpWidget(MyApp());
266
+
267
+ // Login
268
+ await tester.enterText(find.byKey(Key('email')), 'test@test.com');
269
+ await tester.tap(find.byKey(Key('login')));
270
+ await tester.pumpAndSettle();
271
+
272
+ // Verify home screen
273
+ expect(find.text('Welcome'), findsOneWidget);
274
+ });
275
+ }
276
+ ```
277
+
278
+ ## Best Practices
279
+
280
+ ### Widget Composition
281
+ - Break large widgets into smaller, reusable components
282
+ - Extract complex logic into separate methods or classes
283
+ - Use const constructors to improve performance
284
+
285
+ ### Error Handling
286
+ - Use ErrorWidget.builder for custom error widgets
287
+ - Wrap risky operations in try-catch
288
+ - Provide meaningful error messages to users
289
+
290
+ ### Asset Management
291
+ ```yaml
292
+ # pubspec.yaml
293
+ flutter:
294
+ assets:
295
+ - assets/images/
296
+ - assets/icons/
297
+ fonts:
298
+ - family: Roboto
299
+ fonts:
300
+ - asset: fonts/Roboto-Regular.ttf
301
+ ```
302
+
303
+ ### Platform-Specific Code
304
+ ```dart
305
+ import 'dart:io' show Platform;
306
+
307
+ if (Platform.isAndroid) {
308
+ // Android-specific
309
+ } else if (Platform.isIOS) {
310
+ // iOS-specific
311
+ }
312
+ ```
313
+
314
+ ## Common Patterns
315
+
316
+ ### Dependency Injection
317
+ ```dart
318
+ class MyApp extends StatelessWidget {
319
+ final ApiService apiService;
320
+ final AuthService authService;
321
+
322
+ const MyApp({
323
+ required this.apiService,
324
+ required this.authService,
325
+ });
326
+ }
327
+ ```
328
+
329
+ ### Service Locator
330
+ ```dart
331
+ final getIt = GetIt.instance;
332
+
333
+ void setupLocator() {
334
+ getIt.registerSingleton<ApiService>(ApiService());
335
+ getIt.registerLazySingleton<AuthService>(() => AuthService());
336
+ }
337
+
338
+ // Usage
339
+ final api = getIt<ApiService>();
340
+ ```