mtrl-addons 0.1.2 → 0.2.2

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 (117) hide show
  1. package/AI.md +28 -230
  2. package/CLAUDE.md +882 -0
  3. package/build.js +253 -24
  4. package/package.json +14 -4
  5. package/scripts/debug/vlist-selection.ts +121 -0
  6. package/src/components/index.ts +5 -41
  7. package/src/components/{list → vlist}/config.ts +66 -95
  8. package/src/components/vlist/constants.ts +23 -0
  9. package/src/components/vlist/features/api.ts +626 -0
  10. package/src/components/vlist/features/index.ts +10 -0
  11. package/src/components/vlist/features/selection.ts +436 -0
  12. package/src/components/vlist/features/viewport.ts +59 -0
  13. package/src/components/vlist/index.ts +17 -0
  14. package/src/components/{list → vlist}/types.ts +242 -32
  15. package/src/components/vlist/vlist.ts +92 -0
  16. package/src/core/compose/features/gestures/index.ts +227 -0
  17. package/src/core/compose/features/gestures/longpress.ts +383 -0
  18. package/src/core/compose/features/gestures/pan.ts +424 -0
  19. package/src/core/compose/features/gestures/pinch.ts +475 -0
  20. package/src/core/compose/features/gestures/rotate.ts +485 -0
  21. package/src/core/compose/features/gestures/swipe.ts +492 -0
  22. package/src/core/compose/features/gestures/tap.ts +334 -0
  23. package/src/core/compose/features/index.ts +2 -38
  24. package/src/core/compose/index.ts +13 -29
  25. package/src/core/gestures/index.ts +31 -0
  26. package/src/core/gestures/longpress.ts +68 -0
  27. package/src/core/gestures/manager.ts +418 -0
  28. package/src/core/gestures/pan.ts +48 -0
  29. package/src/core/gestures/pinch.ts +58 -0
  30. package/src/core/gestures/rotate.ts +58 -0
  31. package/src/core/gestures/swipe.ts +66 -0
  32. package/src/core/gestures/tap.ts +45 -0
  33. package/src/core/gestures/types.ts +387 -0
  34. package/src/core/gestures/utils.ts +128 -0
  35. package/src/core/index.ts +27 -151
  36. package/src/core/layout/schema.ts +153 -72
  37. package/src/core/layout/types.ts +5 -2
  38. package/src/core/viewport/constants.ts +145 -0
  39. package/src/core/viewport/features/base.ts +73 -0
  40. package/src/core/viewport/features/collection.ts +1182 -0
  41. package/src/core/viewport/features/events.ts +130 -0
  42. package/src/core/viewport/features/index.ts +20 -0
  43. package/src/core/{list-manager/features/viewport → viewport/features}/item-size.ts +31 -34
  44. package/src/core/{list-manager/features/viewport → viewport/features}/loading.ts +4 -4
  45. package/src/core/viewport/features/momentum.ts +269 -0
  46. package/src/core/viewport/features/placeholders.ts +335 -0
  47. package/src/core/viewport/features/rendering.ts +962 -0
  48. package/src/core/viewport/features/scrollbar.ts +434 -0
  49. package/src/core/viewport/features/scrolling.ts +634 -0
  50. package/src/core/viewport/features/utils.ts +94 -0
  51. package/src/core/viewport/features/virtual.ts +525 -0
  52. package/src/core/viewport/index.ts +31 -0
  53. package/src/core/viewport/types.ts +133 -0
  54. package/src/core/viewport/utils/speed-tracker.ts +79 -0
  55. package/src/core/viewport/viewport.ts +265 -0
  56. package/src/index.ts +0 -7
  57. package/src/styles/components/_vlist.scss +352 -0
  58. package/src/styles/index.scss +1 -1
  59. package/test/components/vlist-selection.test.ts +240 -0
  60. package/test/components/vlist.test.ts +63 -0
  61. package/test/core/collection/adapter.test.ts +161 -0
  62. package/bun.lock +0 -792
  63. package/src/components/list/api.ts +0 -314
  64. package/src/components/list/constants.ts +0 -56
  65. package/src/components/list/features/api.ts +0 -428
  66. package/src/components/list/features/index.ts +0 -31
  67. package/src/components/list/features/list-manager.ts +0 -502
  68. package/src/components/list/index.ts +0 -39
  69. package/src/components/list/list.ts +0 -234
  70. package/src/core/collection/base-collection.ts +0 -100
  71. package/src/core/collection/collection-composer.ts +0 -178
  72. package/src/core/collection/collection.ts +0 -745
  73. package/src/core/collection/constants.ts +0 -172
  74. package/src/core/collection/events.ts +0 -428
  75. package/src/core/collection/features/api/loading.ts +0 -279
  76. package/src/core/collection/features/operations/data-operations.ts +0 -147
  77. package/src/core/collection/index.ts +0 -104
  78. package/src/core/collection/state.ts +0 -497
  79. package/src/core/collection/types.ts +0 -404
  80. package/src/core/compose/features/collection.ts +0 -119
  81. package/src/core/compose/features/selection.ts +0 -213
  82. package/src/core/compose/features/styling.ts +0 -108
  83. package/src/core/list-manager/api.ts +0 -599
  84. package/src/core/list-manager/config.ts +0 -593
  85. package/src/core/list-manager/constants.ts +0 -268
  86. package/src/core/list-manager/features/api.ts +0 -58
  87. package/src/core/list-manager/features/collection/collection.ts +0 -705
  88. package/src/core/list-manager/features/collection/index.ts +0 -17
  89. package/src/core/list-manager/features/viewport/constants.ts +0 -42
  90. package/src/core/list-manager/features/viewport/index.ts +0 -16
  91. package/src/core/list-manager/features/viewport/placeholders.ts +0 -281
  92. package/src/core/list-manager/features/viewport/rendering.ts +0 -575
  93. package/src/core/list-manager/features/viewport/scrollbar.ts +0 -495
  94. package/src/core/list-manager/features/viewport/scrolling.ts +0 -795
  95. package/src/core/list-manager/features/viewport/template.ts +0 -220
  96. package/src/core/list-manager/features/viewport/viewport.ts +0 -654
  97. package/src/core/list-manager/features/viewport/virtual.ts +0 -309
  98. package/src/core/list-manager/index.ts +0 -279
  99. package/src/core/list-manager/list-manager.ts +0 -206
  100. package/src/core/list-manager/types.ts +0 -439
  101. package/src/core/list-manager/utils/calculations.ts +0 -290
  102. package/src/core/list-manager/utils/range-calculator.ts +0 -349
  103. package/src/core/list-manager/utils/speed-tracker.ts +0 -273
  104. package/src/styles/components/_list.scss +0 -244
  105. package/src/types/mtrl.d.ts +0 -6
  106. package/test/components/list.test.ts +0 -256
  107. package/test/core/collection/failed-ranges.test.ts +0 -270
  108. package/test/core/compose/features.test.ts +0 -183
  109. package/test/core/list-manager/features/collection.test.ts +0 -704
  110. package/test/core/list-manager/features/viewport.test.ts +0 -698
  111. package/test/core/list-manager/list-manager.test.ts +0 -593
  112. package/test/core/list-manager/utils/calculations.test.ts +0 -433
  113. package/test/core/list-manager/utils/range-calculator.test.ts +0 -569
  114. package/test/core/list-manager/utils/speed-tracker.test.ts +0 -530
  115. package/tsconfig.build.json +0 -23
  116. /package/src/components/{list → vlist}/features.ts +0 -0
  117. /package/src/core/{compose → viewport}/features/performance.ts +0 -0
package/build.js CHANGED
@@ -1,8 +1,9 @@
1
1
  // build.js
2
2
  import { mkdir } from "fs/promises";
3
3
  import { existsSync } from "fs";
4
- import { join, dirname } from "path";
4
+ import { join, dirname, extname } from "path";
5
5
  import { fileURLToPath } from "url";
6
+ import { watch } from "fs";
6
7
 
7
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
9
  const isWatch = process.argv.includes("--watch");
@@ -14,10 +15,92 @@ const isProduction =
14
15
  const DIST_DIR = join(__dirname, "dist");
15
16
  const JS_OUTPUT = join(DIST_DIR, "index.js");
16
17
  const MJS_OUTPUT = join(DIST_DIR, "index.mjs");
18
+ const CSS_OUTPUT = join(DIST_DIR, "styles.css");
19
+ const STYLES_ENTRY = join(__dirname, "src/styles/index.scss");
17
20
 
18
21
  // Log build mode
19
22
  console.log(`Building in ${isProduction ? "PRODUCTION" : "DEVELOPMENT"} mode`);
20
23
 
24
+ const buildStyles = async () => {
25
+ console.log("┌─────────────────────────────────────────");
26
+ console.log("│ SCSS Build");
27
+ console.log("│ Mode:", isProduction ? "PRODUCTION" : "DEVELOPMENT");
28
+ console.log("└─────────────────────────────────────────");
29
+
30
+ try {
31
+ // Check if source file exists
32
+ if (!existsSync(STYLES_ENTRY)) {
33
+ console.log("⚠️ No SCSS entry found at", STYLES_ENTRY);
34
+ return true; // Not an error, just no styles to build
35
+ }
36
+
37
+ // Build sass arguments
38
+ const sassArgs = [
39
+ "sass",
40
+ STYLES_ENTRY,
41
+ CSS_OUTPUT,
42
+ isProduction ? "--style=compressed" : "--style=expanded",
43
+ ];
44
+
45
+ // Add source map in development
46
+ if (!isProduction) {
47
+ sassArgs.push("--source-map");
48
+ } else {
49
+ sassArgs.push("--no-source-map");
50
+ }
51
+
52
+ const sassProcess = Bun.spawn(["npx", ...sassArgs], {
53
+ cwd: __dirname,
54
+ stdio: ["inherit", "pipe", "pipe"],
55
+ });
56
+
57
+ const stdout = await new Response(sassProcess.stdout).text();
58
+ const stderr = await new Response(sassProcess.stderr).text();
59
+ const exitCode = await sassProcess.exited;
60
+
61
+ if (exitCode !== 0) {
62
+ console.error("❌ SCSS build failed");
63
+ if (stdout.trim()) console.error("STDOUT:", stdout);
64
+ if (stderr.trim()) console.error("STDERR:", stderr);
65
+ return false;
66
+ }
67
+
68
+ // Get file size
69
+ const cssSize = existsSync(CSS_OUTPUT)
70
+ ? (await Bun.file(CSS_OUTPUT).size) / 1024
71
+ : 0;
72
+
73
+ console.log("✓ SCSS build successful");
74
+ console.log(` CSS bundle: ${cssSize.toFixed(2)} KB`);
75
+
76
+ return true;
77
+ } catch (error) {
78
+ console.error("❌ SCSS build error:", error.message);
79
+
80
+ // Check if sass is available
81
+ try {
82
+ const checkSass = Bun.spawn(["npx", "sass", "--version"], {
83
+ stdio: ["inherit", "pipe", "pipe"],
84
+ });
85
+ const versionExitCode = await checkSass.exited;
86
+
87
+ if (versionExitCode !== 0) {
88
+ console.error("💡 Sass compiler not found. Install it with:");
89
+ console.error(" npm install -D sass");
90
+ console.error(" or");
91
+ console.error(" bun add -D sass");
92
+ }
93
+ } catch {
94
+ console.error("💡 Sass compiler not found. Install it with:");
95
+ console.error(" npm install -D sass");
96
+ console.error(" or");
97
+ console.error(" bun add -D sass");
98
+ }
99
+
100
+ return false;
101
+ }
102
+ };
103
+
21
104
  const buildApp = async () => {
22
105
  try {
23
106
  console.log("┌─────────────────────────────────────────");
@@ -64,34 +147,104 @@ const buildApp = async () => {
64
147
 
65
148
  console.log("✓ JavaScript build successful");
66
149
  console.log(
67
- ` CJS bundle: ${((await Bun.file(JS_OUTPUT).size) / 1024).toFixed(2)} KB`
150
+ ` CJS bundle: ${((await Bun.file(JS_OUTPUT).size) / 1024).toFixed(2)} KB`,
68
151
  );
69
152
  console.log(
70
153
  ` ESM bundle: ${((await Bun.file(MJS_OUTPUT).size) / 1024).toFixed(
71
- 2
72
- )} KB`
154
+ 2,
155
+ )} KB`,
73
156
  );
74
157
 
75
- // Generate type definitions
158
+ // Generate type definitions with better error handling
76
159
  console.log("Generating TypeScript declarations...");
77
- const tscProcess = Bun.spawn(["tsc", "--project", "tsconfig.build.json"], {
78
- cwd: __dirname,
79
- });
80
160
 
81
- const tscExitCode = await tscProcess.exited;
82
- if (tscExitCode !== 0) {
83
- console.error(" TypeScript declaration generation failed");
84
- // Check if declaration files were actually generated despite errors
85
- const declarationFile = join(DIST_DIR, "index.d.ts");
86
- if (existsSync(declarationFile)) {
87
- console.log("⚠️ Declaration files were generated despite errors");
161
+ try {
162
+ const tscProcess = Bun.spawn(
163
+ ["tsc", "--emitDeclarationOnly", "--outDir", DIST_DIR],
164
+ {
165
+ cwd: __dirname,
166
+ stdio: ["inherit", "pipe", "pipe"],
167
+ },
168
+ );
169
+
170
+ // Capture stdout and stderr
171
+ const stdout = await new Response(tscProcess.stdout).text();
172
+ const stderr = await new Response(tscProcess.stderr).text();
173
+
174
+ const tscExitCode = await tscProcess.exited;
175
+
176
+ if (tscExitCode !== 0) {
177
+ console.warn(
178
+ "⚠️ TypeScript declaration generation had errors (non-blocking)",
179
+ );
180
+ if (stdout.trim()) {
181
+ console.warn(
182
+ "STDOUT:",
183
+ stdout.slice(0, 500) + (stdout.length > 500 ? "..." : ""),
184
+ );
185
+ }
186
+ if (stderr.trim()) {
187
+ console.warn(
188
+ "STDERR:",
189
+ stderr.slice(0, 500) + (stderr.length > 500 ? "..." : ""),
190
+ );
191
+ }
192
+
193
+ // Check if tsc is available
194
+ const whichResult = Bun.spawn(["which", "tsc"], {
195
+ stdio: ["inherit", "pipe", "pipe"],
196
+ });
197
+ const tscPath = await new Response(whichResult.stdout).text();
198
+ if (!tscPath.trim()) {
199
+ console.error(
200
+ "💡 TypeScript compiler (tsc) not found. Install it with:",
201
+ );
202
+ console.error(" npm install -g typescript");
203
+ console.error(" or");
204
+ console.error(" bun add -g typescript");
205
+ }
206
+
207
+ // Continue build despite tsc errors (JS bundles are still valid)
88
208
  return true;
89
209
  }
90
- return false;
91
- }
92
210
 
93
- console.log("✓ TypeScript declarations generated");
94
- return true;
211
+ console.log("✓ TypeScript declarations generated");
212
+ if (stdout.trim()) {
213
+ console.log("TSC output:", stdout);
214
+ }
215
+
216
+ return true;
217
+ } catch (tscError) {
218
+ console.warn("⚠️ Error running TypeScript compiler:", tscError.message);
219
+
220
+ // Check if TypeScript is installed
221
+ try {
222
+ const checkTsc = Bun.spawn(["tsc", "--version"], {
223
+ stdio: ["inherit", "pipe", "pipe"],
224
+ });
225
+ const versionOutput = await new Response(checkTsc.stdout).text();
226
+ const versionExitCode = await checkTsc.exited;
227
+
228
+ if (versionExitCode === 0) {
229
+ console.log("TypeScript version:", versionOutput.trim());
230
+ } else {
231
+ console.warn(
232
+ "💡 TypeScript compiler not properly installed. Install with:",
233
+ );
234
+ console.warn(" npm install -g typescript");
235
+ console.warn(" or");
236
+ console.warn(" bun add -g typescript");
237
+ }
238
+ } catch (versionError) {
239
+ console.warn("💡 TypeScript compiler not found. Install it with:");
240
+ console.warn(" npm install -g typescript");
241
+ console.warn(" or");
242
+ console.warn(" bun add -g typescript");
243
+ }
244
+
245
+ // Continue build despite tsc errors (JS bundles are still valid)
246
+ return true;
247
+ }
95
248
  } catch (error) {
96
249
  console.error("❌ JavaScript build error:", error);
97
250
  console.error(error.stack);
@@ -99,6 +252,12 @@ const buildApp = async () => {
99
252
  }
100
253
  };
101
254
 
255
+ const buildAll = async () => {
256
+ const jsSuccess = await buildApp();
257
+ const cssSuccess = await buildStyles();
258
+ return jsSuccess && cssSuccess;
259
+ };
260
+
102
261
  const build = async () => {
103
262
  try {
104
263
  const startTime = Date.now();
@@ -113,8 +272,8 @@ const build = async () => {
113
272
  // Create output directory
114
273
  await mkdir(DIST_DIR, { recursive: true });
115
274
 
116
- // Build JavaScript
117
- const jsSuccess = await buildApp();
275
+ // Build JavaScript and CSS
276
+ const buildSuccess = await buildAll();
118
277
 
119
278
  const buildTime = ((Date.now() - startTime) / 1000).toFixed(2);
120
279
 
@@ -124,18 +283,88 @@ const build = async () => {
124
283
  console.log("│ 👀 Watching for changes...");
125
284
  console.log("└───────────────────────────────────────────────");
126
285
 
127
- // Watch implementation would go here
286
+ // Watch src directory for changes
287
+ const srcDir = join(__dirname, "src");
288
+ let debounceTimer = null;
289
+ let isBuilding = false;
290
+
291
+ const rebuild = async (changedFile) => {
292
+ if (isBuilding) return;
293
+ isBuilding = true;
294
+
295
+ const ext = changedFile ? extname(changedFile) : "";
296
+ const isStyleChange = [".scss", ".css"].includes(ext);
297
+ const isJsChange = [".ts", ".tsx"].includes(ext);
298
+
299
+ console.log("");
300
+ console.log("┌───────────────────────────────────────────────");
301
+ console.log(
302
+ `│ 🔄 Change detected${changedFile ? ` (${changedFile})` : ""}, rebuilding...`,
303
+ );
304
+ console.log("└───────────────────────────────────────────────");
305
+
306
+ const rebuildStart = Date.now();
307
+ let success;
308
+
309
+ // Selective rebuild based on file type
310
+ if (isStyleChange) {
311
+ success = await buildStyles();
312
+ } else if (isJsChange) {
313
+ success = await buildApp();
314
+ } else {
315
+ success = await buildAll();
316
+ }
317
+
318
+ const rebuildTime = ((Date.now() - rebuildStart) / 1000).toFixed(2);
319
+
320
+ console.log("");
321
+ console.log(
322
+ `│ ${success ? "✅" : "⚠️"} Rebuild completed in ${rebuildTime}s`,
323
+ );
324
+ console.log("│ 👀 Watching for changes...");
325
+ console.log("└───────────────────────────────────────────────");
326
+
327
+ isBuilding = false;
328
+ };
329
+
330
+ const watchHandler = (eventType, filename) => {
331
+ if (!filename) return;
332
+
333
+ // Only watch .ts, .tsx, .scss and .css files
334
+ const ext = extname(filename);
335
+ if (![".ts", ".tsx", ".scss", ".css"].includes(ext)) return;
336
+
337
+ // Debounce rapid changes
338
+ if (debounceTimer) clearTimeout(debounceTimer);
339
+ debounceTimer = setTimeout(() => {
340
+ rebuild(filename);
341
+ }, 100);
342
+ };
343
+
344
+ // Watch recursively using fs.watch
345
+ const watchDir = (dir) => {
346
+ watch(dir, { recursive: true }, watchHandler);
347
+ };
348
+
349
+ watchDir(srcDir);
350
+ console.log(`│ Watching: ${srcDir}`);
351
+
352
+ // Keep process alive
353
+ process.on("SIGINT", () => {
354
+ console.log("\n│ 👋 Stopping watch mode...");
355
+ process.exit(0);
356
+ });
128
357
  } else {
129
358
  console.log("");
130
359
  console.log("┌───────────────────────────────────────────────");
131
360
  console.log(`│ ✅ Build completed in ${buildTime}s`);
132
- if (!jsSuccess) {
361
+ if (!buildSuccess) {
133
362
  console.log("│ ⚠️ Build completed with some errors");
134
363
  }
135
364
  console.log("└───────────────────────────────────────────────");
136
365
 
137
366
  // Only exit with error code in non-watch mode if there were failures
138
- if (!isWatch && !jsSuccess) {
367
+ if (!isWatch && !buildSuccess) {
139
368
  process.exit(1);
140
369
  }
141
370
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mtrl-addons",
3
- "version": "0.1.2",
3
+ "version": "0.2.2",
4
4
  "description": "Additional components and utilities for the mtrl system, featuring forms, specialized elements, and extended functionality for modern applications",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -10,8 +10,15 @@
10
10
  "dev": "bun run ./build.js --watch",
11
11
  "test": "bun test",
12
12
  "prepublishOnly": "bun run build",
13
- "debug:list": "bun run ../mtrl-app/scripts/debug/list-addons.ts",
14
- "debug:list:interactive": "bun run ../mtrl-app/scripts/debug/list-addons.ts --interactive"
13
+ "server:start": "pm2 start ../mtrl-app/ecosystem.config.js",
14
+ "server:stop": "pm2 stop mtrl-app",
15
+ "server:reload": "pm2 restart mtrl-app",
16
+ "server:logs": "pm2 logs mtrl-app",
17
+ "link:mtrl": "rm -rf node_modules/mtrl && ln -sf ../../mtrl node_modules/mtrl",
18
+ "debug:vlist": "bun run ../mtrl-app/scripts/debug/vlist examples/vlist",
19
+ "debug:vlist:interactive": "bun run ../mtrl-app/scripts/debug/vlist examples/vlist --interactive",
20
+ "debug:vlist-cursor": "bun run ../mtrl-app/scripts/debug/vlist examples/vlist-cursor",
21
+ "debug:vlist-cursor:interactive": "bun run ../mtrl-app/scripts/debug/vlist examples/vlist-cursor --interactive"
15
22
  },
16
23
  "repository": {
17
24
  "type": "git",
@@ -27,13 +34,16 @@
27
34
  "author": "floor",
28
35
  "license": "MIT",
29
36
  "peerDependencies": {
30
- "mtrl": "^0.2.8"
37
+ "mtrl": "^0.5.1"
31
38
  },
32
39
  "devDependencies": {
40
+ "@types/jsdom": "^21.1.7",
33
41
  "@types/node": "^20.0.0",
34
42
  "bun-types": "^1.0.0",
43
+ "jsdom": "^26.1.0",
35
44
  "madge": "^8.0.0",
36
45
  "mtrl": "^0.2.8",
46
+ "sass": "^1.94.2",
37
47
  "standard": "^17.0.0",
38
48
  "typescript": "^5.0.0"
39
49
  }
@@ -0,0 +1,121 @@
1
+ // scripts/debug/vlist-selection.ts
2
+
3
+ import puppeteer from "puppeteer";
4
+
5
+ async function testVListSelection() {
6
+ console.log("🎯 Testing VList Selection Feature");
7
+
8
+ const browser = await puppeteer.launch({
9
+ headless: false,
10
+ devtools: true,
11
+ args: ["--no-sandbox", "--disable-setuid-sandbox"],
12
+ });
13
+
14
+ const page = await browser.newPage();
15
+
16
+ // Listen to console logs
17
+ page.on("console", (msg) => {
18
+ const text = msg.text();
19
+ if (text.includes("[Selection]") || text.includes("selection")) {
20
+ console.log(`💬 [${msg.type().toUpperCase()}] ${text}`);
21
+ }
22
+ });
23
+
24
+ await page.goto("http://localhost:4000/examples/vlist-addons");
25
+
26
+ // Wait for list to load
27
+ await page.waitForSelector(".mtrl-viewport-item", { timeout: 5000 });
28
+
29
+ console.log("📋 Page loaded, looking for list items...");
30
+
31
+ // Get info about items
32
+ const itemInfo = await page.evaluate(() => {
33
+ const items = document.querySelectorAll(".mtrl-viewport-item");
34
+ const firstItem = items[0];
35
+ const listItem = firstItem?.querySelector(".list-item, .user-item");
36
+
37
+ return {
38
+ viewportItemCount: items.length,
39
+ firstViewportItemClasses: firstItem?.className,
40
+ firstViewportItemDataIndex: firstItem?.getAttribute("data-index"),
41
+ firstListItemClasses: listItem?.className,
42
+ firstListItemDataId: listItem?.getAttribute("data-id"),
43
+ hasClickHandler: !!(window as any).listExample?.userList,
44
+ };
45
+ });
46
+
47
+ console.log("📊 Item info:", itemInfo);
48
+
49
+ // Click on the first item
50
+ console.log("🖱️ Clicking on first item...");
51
+ await page.click(".mtrl-viewport-item:first-child");
52
+
53
+ // Wait a bit for selection to process
54
+ await page.waitForTimeout(500);
55
+
56
+ // Check if selection class was applied
57
+ const selectionInfo = await page.evaluate(() => {
58
+ const firstItem = document.querySelector(".mtrl-viewport-item:first-child");
59
+ const listItem = firstItem?.querySelector(".list-item, .user-item");
60
+ const selectedItems = document.querySelectorAll(
61
+ ".mtrl-list-item--selected"
62
+ );
63
+
64
+ return {
65
+ hasSelectionClass: listItem?.classList.contains(
66
+ "mtrl-list-item--selected"
67
+ ),
68
+ listItemClasses: listItem?.className,
69
+ selectedCount: selectedItems.length,
70
+ userListExists: !!(window as any).listExample?.userList,
71
+ hasSelectItems:
72
+ typeof (window as any).listExample?.userList?.selectItems ===
73
+ "function",
74
+ hasGetSelectedItems:
75
+ typeof (window as any).listExample?.userList?.getSelectedItems ===
76
+ "function",
77
+ };
78
+ });
79
+
80
+ console.log("✅ Selection info after click:", selectionInfo);
81
+
82
+ // Try programmatic selection
83
+ console.log("🔧 Testing programmatic selection...");
84
+ const programmaticResult = await page.evaluate(() => {
85
+ const userList = (window as any).listExample?.userList;
86
+ if (userList && userList.selectItems) {
87
+ userList.selectItems([0, 1, 2]);
88
+ const selected = userList.getSelectedItems
89
+ ? userList.getSelectedItems()
90
+ : [];
91
+ return {
92
+ success: true,
93
+ selectedCount: selected.length,
94
+ selectedIds: selected.map((item: any) => item.id),
95
+ };
96
+ }
97
+ return { success: false, reason: "No selectItems method" };
98
+ });
99
+
100
+ console.log("📊 Programmatic selection result:", programmaticResult);
101
+
102
+ // Final check
103
+ await page.waitForTimeout(500);
104
+ const finalState = await page.evaluate(() => {
105
+ const selectedElements = document.querySelectorAll(
106
+ ".mtrl-list-item--selected"
107
+ );
108
+ return {
109
+ selectedElementCount: selectedElements.length,
110
+ selectedClasses: Array.from(selectedElements).map((el) => el.className),
111
+ };
112
+ });
113
+
114
+ console.log("🎯 Final selection state:", finalState);
115
+
116
+ // Keep browser open for inspection
117
+ console.log("✨ Test complete. Browser will stay open for inspection.");
118
+ console.log("Press Ctrl+C to exit.");
119
+ }
120
+
121
+ testVListSelection().catch(console.error);
@@ -1,45 +1,9 @@
1
1
  /**
2
- * mtrl-addons Components
2
+ * Components Module Exports
3
3
  *
4
- * Exports all component modules
4
+ * Central export point for all components
5
5
  */
6
6
 
7
- // Export the existing list component
8
- export { createList } from "./list";
9
-
10
- // Export list types and utilities
11
- export type {
12
- ListConfig,
13
- ListComponent,
14
- ListAPI,
15
- ListState,
16
- ListEvents,
17
- ListItemTemplate,
18
- ListScrollConfig,
19
- ListSelectionConfig,
20
- ListEventHandlers,
21
- ListItemContext,
22
- } from "./list";
23
-
24
- // List configuration utilities
25
- export {
26
- createBaseConfig,
27
- getElementConfig,
28
- getApiConfig,
29
- getCollectionConfig,
30
- getListManagerConfig,
31
- validateConfig,
32
- } from "./list";
33
-
34
- // List features
35
- export { withListManager } from "./list/features/list-manager";
36
- export { withAPI } from "./list/api";
37
-
38
- // Components will be exported here as they're added
39
- // For example:
40
- // export { VirtualList } from './virtual-list';
41
- // export { DataTable } from './data-table';
42
- // export { InfiniteScroll } from './infinite-scroll';
43
-
44
- // Currently no other components - this is the foundation for future components
45
- export const componentsVersion = "0.1.0";
7
+ // VList component (virtual list with viewport)
8
+ export { createVList } from "./vlist";
9
+ export type { VListConfig, VListComponent } from "./vlist/types";