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
@@ -1,17 +0,0 @@
1
- // src/core/list-manager/features/collection/index.ts
2
-
3
- /**
4
- * Main collection feature - Data management & API integration
5
- *
6
- * This is the core collection management system that handles:
7
- * - Data loading and caching
8
- * - Range-based loading strategies
9
- * - Pagination triggers
10
- * - API adapter integration
11
- */
12
-
13
- export { withCollection } from "./collection";
14
-
15
- // TODO: Create these core collection utilities
16
- // export { rangeLoading } from "./range-loading";
17
- // export { paginationTrigger } from "./pagination-trigger";
@@ -1,42 +0,0 @@
1
- /**
2
- * Viewport Constants
3
- * Centralized constants for viewport features
4
- */
5
-
6
- export const VIEWPORT_CONSTANTS = {
7
- /**
8
- * Request queue configuration
9
- */
10
- REQUEST_QUEUE: {
11
- ENABLED: true, // Enable/disable request queue system
12
- MAX_QUEUE_SIZE: 50, // Maximum number of queued requests
13
- MAX_ACTIVE_REQUESTS: 1, // Maximum concurrent active requests (1 = sequential)
14
- },
15
-
16
- /**
17
- * Loading configuration
18
- */
19
- LOADING: {
20
- CANCEL_THRESHOLD: 1, // px/ms - velocity above which loads are cancelled (lowered for better scrollbar response)
21
- },
22
-
23
- // Placeholder settings
24
- PLACEHOLDER: {
25
- MASK_CHARACTER: "x",
26
- CSS_CLASS: "list-item__placeholder",
27
- MIN_SAMPLE_SIZE: 5, // Minimum items needed for reliable analysis
28
- MAX_SAMPLE_SIZE: 20, // Maximum items to analyze for performance
29
- },
30
-
31
- // Scrolling settings
32
- SCROLLING: {
33
- OVERSCAN: 2,
34
- DEBOUNCE_MS: 50,
35
- },
36
-
37
- // Rendering settings
38
- RENDERING: {
39
- BATCH_SIZE: 100,
40
- MIN_ITEM_HEIGHT: 20,
41
- },
42
- };
@@ -1,16 +0,0 @@
1
- // src/core/list-manager/features/viewport/index.ts
2
-
3
- /**
4
- * Viewport features export
5
- */
6
-
7
- export { withViewport } from "./viewport";
8
- export { withPlaceholders } from "./placeholders";
9
-
10
- // Types
11
- export type { ViewportComponent } from "./viewport";
12
- export type { PlaceholdersComponent } from "./placeholders";
13
-
14
- // Configs
15
- export type { ViewportConfig } from "./viewport";
16
- export type { PlaceholdersConfig } from "./placeholders";
@@ -1,281 +0,0 @@
1
- /**
2
- * Placeholders Feature - Smart Structure Analysis
3
- * Analyzes first loaded data to generate realistic masked placeholders
4
- */
5
-
6
- import type { ListManagerComponent, ItemRange } from "../../types";
7
- import { PLACEHOLDER } from "../../constants";
8
- import { VIEWPORT_CONSTANTS } from "./constants";
9
-
10
- /**
11
- * Configuration for placeholders enhancer
12
- */
13
- export interface PlaceholdersConfig {
14
- enabled?: boolean;
15
- analyzeFirstLoad?: boolean;
16
- }
17
-
18
- /**
19
- * Field structure analysis result
20
- */
21
- export interface FieldStructure {
22
- minLength: number;
23
- maxLength: number;
24
- avgLength: number;
25
- }
26
-
27
- /**
28
- * Component interface after placeholders enhancement
29
- */
30
- export interface PlaceholdersComponent {
31
- placeholders: {
32
- // Structure analysis
33
- analyzeDataStructure(items: any[]): void;
34
- hasAnalyzedStructure(): boolean;
35
-
36
- // Placeholder generation
37
- generatePlaceholderItem(index: number): any;
38
- generatePlaceholderItems(range: ItemRange): any[];
39
-
40
- // Placeholder management
41
- showPlaceholders(range: ItemRange): void;
42
- isPlaceholder(item: any): boolean;
43
-
44
- // State
45
- isEnabled(): boolean;
46
- clear(): void;
47
- };
48
- }
49
-
50
- /**
51
- * Adds placeholders functionality to a List Manager component
52
- */
53
- export const withPlaceholders =
54
- (config: PlaceholdersConfig = {}) =>
55
- <T extends ListManagerComponent>(component: T): T & PlaceholdersComponent => {
56
- // Configuration with defaults
57
- const placeholdersConfig: PlaceholdersConfig = {
58
- enabled: config.enabled !== false,
59
- analyzeFirstLoad: config.analyzeFirstLoad !== false,
60
- };
61
-
62
- // Placeholder state
63
- let fieldStructures: Map<string, FieldStructure> | null = null;
64
- let hasAnalyzed = false;
65
- let placeholderIdCounter = 0;
66
-
67
- /**
68
- * Analyze data structure from first loaded items
69
- */
70
- const analyzeDataStructure = (items: any[]): void => {
71
- if (!placeholdersConfig.enabled || hasAnalyzed || !items.length) {
72
- return;
73
- }
74
-
75
- console.log(
76
- `🔍 [PLACEHOLDERS] Analyzing data structure from ${items.length} items`
77
- );
78
-
79
- const structures = new Map<string, FieldStructure>();
80
- const sampleSize = Math.min(
81
- items.length,
82
- VIEWPORT_CONSTANTS.PLACEHOLDER.MAX_SAMPLE_SIZE
83
- );
84
-
85
- // Analyze each field across all sample items
86
- const fieldStats = new Map<string, number[]>();
87
-
88
- for (let i = 0; i < sampleSize; i++) {
89
- const item = items[i];
90
- if (!item || typeof item !== "object") continue;
91
-
92
- Object.keys(item).forEach((field) => {
93
- // Skip internal fields
94
- if (field.startsWith("_") || field === PLACEHOLDER.PLACEHOLDER_FLAG) {
95
- return;
96
- }
97
-
98
- const value = item[field];
99
- if (value === null || value === undefined) return;
100
-
101
- const length = String(value).length;
102
-
103
- if (!fieldStats.has(field)) {
104
- fieldStats.set(field, []);
105
- }
106
- fieldStats.get(field)!.push(length);
107
- });
108
- }
109
-
110
- // Calculate min/max/avg for each field
111
- fieldStats.forEach((lengths, field) => {
112
- if (lengths.length === 0) return;
113
-
114
- const minLength = Math.min(...lengths);
115
- const maxLength = Math.max(...lengths);
116
- const avgLength = Math.round(
117
- lengths.reduce((sum, len) => sum + len, 0) / lengths.length
118
- );
119
-
120
- structures.set(field, {
121
- minLength,
122
- maxLength,
123
- avgLength,
124
- });
125
-
126
- console.log(
127
- `📊 [PLACEHOLDERS] Field "${field}": min=${minLength}, max=${maxLength}, avg=${avgLength}`
128
- );
129
- });
130
-
131
- fieldStructures = structures;
132
- hasAnalyzed = true;
133
-
134
- component.emit?.("placeholders:analyzed", {
135
- fieldCount: structures.size,
136
- sampleSize,
137
- });
138
- };
139
-
140
- /**
141
- * Generate a single placeholder item based on analyzed structure
142
- */
143
- const generatePlaceholderItem = (index: number): any => {
144
- if (!placeholdersConfig.enabled || !fieldStructures) {
145
- return null;
146
- }
147
-
148
- const placeholder: Record<string, any> = {
149
- id: `placeholder-${++placeholderIdCounter}`,
150
- [PLACEHOLDER.PLACEHOLDER_FLAG]: true,
151
- };
152
-
153
- // Generate masked values for each analyzed field
154
- fieldStructures.forEach((structure, field) => {
155
- const { minLength, maxLength } = structure;
156
-
157
- // Random length within the range
158
- const length =
159
- minLength === maxLength
160
- ? minLength
161
- : Math.floor(Math.random() * (maxLength - minLength + 1)) +
162
- minLength;
163
-
164
- // Generate masked string
165
- placeholder[field] =
166
- VIEWPORT_CONSTANTS.PLACEHOLDER.MASK_CHARACTER.repeat(length);
167
- });
168
-
169
- return placeholder;
170
- };
171
-
172
- /**
173
- * Generate multiple placeholder items for a range
174
- */
175
- const generatePlaceholderItems = (range: ItemRange): any[] => {
176
- const items: any[] = [];
177
-
178
- for (let i = range.start; i <= range.end; i++) {
179
- items.push(generatePlaceholderItem(i));
180
- }
181
-
182
- return items;
183
- };
184
-
185
- /**
186
- * Show placeholders for a range
187
- */
188
- const showPlaceholders = (range: ItemRange): void => {
189
- if (!placeholdersConfig.enabled || !hasAnalyzed) {
190
- return;
191
- }
192
-
193
- const placeholderItems = generatePlaceholderItems(range);
194
-
195
- // Add placeholders to component items
196
- placeholderItems.forEach((item, index) => {
197
- const targetIndex = range.start + index;
198
- const existingItem = component.items[targetIndex];
199
- const shouldReplace = !existingItem || isPlaceholder(existingItem);
200
-
201
- if (shouldReplace) {
202
- component.items[targetIndex] = item;
203
- }
204
- });
205
-
206
- component.emit?.("placeholders:shown", {
207
- range,
208
- count: placeholderItems.length,
209
- });
210
- };
211
-
212
- /**
213
- * Check if an item is a placeholder
214
- */
215
- const isPlaceholder = (item: any): boolean => {
216
- return (
217
- item &&
218
- typeof item === "object" &&
219
- item[PLACEHOLDER.PLACEHOLDER_FLAG] === true
220
- );
221
- };
222
-
223
- /**
224
- * Check if placeholders are enabled
225
- */
226
- const isEnabled = (): boolean => {
227
- return placeholdersConfig.enabled || false;
228
- };
229
-
230
- /**
231
- * Clear placeholder state
232
- */
233
- const clear = (): void => {
234
- fieldStructures = null;
235
- hasAnalyzed = false;
236
- placeholderIdCounter = 0;
237
- };
238
-
239
- /**
240
- * Check if structure has been analyzed
241
- */
242
- const hasAnalyzedStructure = (): boolean => {
243
- return hasAnalyzed;
244
- };
245
-
246
- // Listen for first data load to analyze structure
247
- if (placeholdersConfig.analyzeFirstLoad && component.on) {
248
- component.on("range:loaded", (data: any) => {
249
- if (
250
- !hasAnalyzed &&
251
- data?.items?.length >= VIEWPORT_CONSTANTS.PLACEHOLDER.MIN_SAMPLE_SIZE
252
- ) {
253
- analyzeDataStructure(data.items);
254
- }
255
- });
256
- }
257
-
258
- // Placeholders API
259
- const placeholdersAPI = {
260
- // Structure analysis
261
- analyzeDataStructure,
262
- hasAnalyzedStructure,
263
-
264
- // Placeholder generation
265
- generatePlaceholderItem,
266
- generatePlaceholderItems,
267
-
268
- // Placeholder management
269
- showPlaceholders,
270
- isPlaceholder,
271
-
272
- // State
273
- isEnabled,
274
- clear,
275
- };
276
-
277
- return {
278
- ...component,
279
- placeholders: placeholdersAPI,
280
- };
281
- };