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.
- package/AI.md +28 -230
- package/CLAUDE.md +882 -0
- package/build.js +253 -24
- package/package.json +14 -4
- package/scripts/debug/vlist-selection.ts +121 -0
- package/src/components/index.ts +5 -41
- package/src/components/{list → vlist}/config.ts +66 -95
- package/src/components/vlist/constants.ts +23 -0
- package/src/components/vlist/features/api.ts +626 -0
- package/src/components/vlist/features/index.ts +10 -0
- package/src/components/vlist/features/selection.ts +436 -0
- package/src/components/vlist/features/viewport.ts +59 -0
- package/src/components/vlist/index.ts +17 -0
- package/src/components/{list → vlist}/types.ts +242 -32
- package/src/components/vlist/vlist.ts +92 -0
- package/src/core/compose/features/gestures/index.ts +227 -0
- package/src/core/compose/features/gestures/longpress.ts +383 -0
- package/src/core/compose/features/gestures/pan.ts +424 -0
- package/src/core/compose/features/gestures/pinch.ts +475 -0
- package/src/core/compose/features/gestures/rotate.ts +485 -0
- package/src/core/compose/features/gestures/swipe.ts +492 -0
- package/src/core/compose/features/gestures/tap.ts +334 -0
- package/src/core/compose/features/index.ts +2 -38
- package/src/core/compose/index.ts +13 -29
- package/src/core/gestures/index.ts +31 -0
- package/src/core/gestures/longpress.ts +68 -0
- package/src/core/gestures/manager.ts +418 -0
- package/src/core/gestures/pan.ts +48 -0
- package/src/core/gestures/pinch.ts +58 -0
- package/src/core/gestures/rotate.ts +58 -0
- package/src/core/gestures/swipe.ts +66 -0
- package/src/core/gestures/tap.ts +45 -0
- package/src/core/gestures/types.ts +387 -0
- package/src/core/gestures/utils.ts +128 -0
- package/src/core/index.ts +27 -151
- package/src/core/layout/schema.ts +153 -72
- package/src/core/layout/types.ts +5 -2
- package/src/core/viewport/constants.ts +145 -0
- package/src/core/viewport/features/base.ts +73 -0
- package/src/core/viewport/features/collection.ts +1182 -0
- package/src/core/viewport/features/events.ts +130 -0
- package/src/core/viewport/features/index.ts +20 -0
- package/src/core/{list-manager/features/viewport → viewport/features}/item-size.ts +31 -34
- package/src/core/{list-manager/features/viewport → viewport/features}/loading.ts +4 -4
- package/src/core/viewport/features/momentum.ts +269 -0
- package/src/core/viewport/features/placeholders.ts +335 -0
- package/src/core/viewport/features/rendering.ts +962 -0
- package/src/core/viewport/features/scrollbar.ts +434 -0
- package/src/core/viewport/features/scrolling.ts +634 -0
- package/src/core/viewport/features/utils.ts +94 -0
- package/src/core/viewport/features/virtual.ts +525 -0
- package/src/core/viewport/index.ts +31 -0
- package/src/core/viewport/types.ts +133 -0
- package/src/core/viewport/utils/speed-tracker.ts +79 -0
- package/src/core/viewport/viewport.ts +265 -0
- package/src/index.ts +0 -7
- package/src/styles/components/_vlist.scss +352 -0
- package/src/styles/index.scss +1 -1
- package/test/components/vlist-selection.test.ts +240 -0
- package/test/components/vlist.test.ts +63 -0
- package/test/core/collection/adapter.test.ts +161 -0
- package/bun.lock +0 -792
- package/src/components/list/api.ts +0 -314
- package/src/components/list/constants.ts +0 -56
- package/src/components/list/features/api.ts +0 -428
- package/src/components/list/features/index.ts +0 -31
- package/src/components/list/features/list-manager.ts +0 -502
- package/src/components/list/index.ts +0 -39
- package/src/components/list/list.ts +0 -234
- package/src/core/collection/base-collection.ts +0 -100
- package/src/core/collection/collection-composer.ts +0 -178
- package/src/core/collection/collection.ts +0 -745
- package/src/core/collection/constants.ts +0 -172
- package/src/core/collection/events.ts +0 -428
- package/src/core/collection/features/api/loading.ts +0 -279
- package/src/core/collection/features/operations/data-operations.ts +0 -147
- package/src/core/collection/index.ts +0 -104
- package/src/core/collection/state.ts +0 -497
- package/src/core/collection/types.ts +0 -404
- package/src/core/compose/features/collection.ts +0 -119
- package/src/core/compose/features/selection.ts +0 -213
- package/src/core/compose/features/styling.ts +0 -108
- package/src/core/list-manager/api.ts +0 -599
- package/src/core/list-manager/config.ts +0 -593
- package/src/core/list-manager/constants.ts +0 -268
- package/src/core/list-manager/features/api.ts +0 -58
- package/src/core/list-manager/features/collection/collection.ts +0 -705
- package/src/core/list-manager/features/collection/index.ts +0 -17
- package/src/core/list-manager/features/viewport/constants.ts +0 -42
- package/src/core/list-manager/features/viewport/index.ts +0 -16
- package/src/core/list-manager/features/viewport/placeholders.ts +0 -281
- package/src/core/list-manager/features/viewport/rendering.ts +0 -575
- package/src/core/list-manager/features/viewport/scrollbar.ts +0 -495
- package/src/core/list-manager/features/viewport/scrolling.ts +0 -795
- package/src/core/list-manager/features/viewport/template.ts +0 -220
- package/src/core/list-manager/features/viewport/viewport.ts +0 -654
- package/src/core/list-manager/features/viewport/virtual.ts +0 -309
- package/src/core/list-manager/index.ts +0 -279
- package/src/core/list-manager/list-manager.ts +0 -206
- package/src/core/list-manager/types.ts +0 -439
- package/src/core/list-manager/utils/calculations.ts +0 -290
- package/src/core/list-manager/utils/range-calculator.ts +0 -349
- package/src/core/list-manager/utils/speed-tracker.ts +0 -273
- package/src/styles/components/_list.scss +0 -244
- package/src/types/mtrl.d.ts +0 -6
- package/test/components/list.test.ts +0 -256
- package/test/core/collection/failed-ranges.test.ts +0 -270
- package/test/core/compose/features.test.ts +0 -183
- package/test/core/list-manager/features/collection.test.ts +0 -704
- package/test/core/list-manager/features/viewport.test.ts +0 -698
- package/test/core/list-manager/list-manager.test.ts +0 -593
- package/test/core/list-manager/utils/calculations.test.ts +0 -433
- package/test/core/list-manager/utils/range-calculator.test.ts +0 -569
- package/test/core/list-manager/utils/speed-tracker.test.ts +0 -530
- package/tsconfig.build.json +0 -23
- /package/src/components/{list → vlist}/features.ts +0 -0
- /package/src/core/{compose → viewport}/features/performance.ts +0 -0
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Scroll speed tracking utility
|
|
3
|
-
* Measures velocity and determines loading strategies
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { SpeedTracker } from "../types";
|
|
7
|
-
import { LIST_MANAGER_CONSTANTS } from "../constants";
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Create a new speed tracker instance
|
|
11
|
-
*/
|
|
12
|
-
export function createSpeedTracker(): SpeedTracker {
|
|
13
|
-
return {
|
|
14
|
-
velocity: 0,
|
|
15
|
-
direction: "forward",
|
|
16
|
-
isAccelerating: false,
|
|
17
|
-
lastMeasurement: Date.now(),
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Update speed tracker with new scroll position
|
|
23
|
-
*/
|
|
24
|
-
export function updateSpeedTracker(
|
|
25
|
-
tracker: SpeedTracker,
|
|
26
|
-
newPosition: number,
|
|
27
|
-
previousPosition: number,
|
|
28
|
-
orientation: "vertical" | "horizontal" = "vertical"
|
|
29
|
-
): SpeedTracker {
|
|
30
|
-
const now = Date.now();
|
|
31
|
-
const deltaTime = now - tracker.lastMeasurement;
|
|
32
|
-
const deltaPosition = newPosition - previousPosition;
|
|
33
|
-
|
|
34
|
-
// Calculate velocity (px/ms)
|
|
35
|
-
const currentVelocity =
|
|
36
|
-
deltaTime > 0 ? Math.abs(deltaPosition) / deltaTime : 0;
|
|
37
|
-
|
|
38
|
-
// Determine direction based on orientation
|
|
39
|
-
let direction: "forward" | "backward";
|
|
40
|
-
if (orientation === "vertical") {
|
|
41
|
-
direction = deltaPosition >= 0 ? "forward" : "backward"; // down/up
|
|
42
|
-
} else {
|
|
43
|
-
direction = deltaPosition >= 0 ? "forward" : "backward"; // right/left
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Check if accelerating
|
|
47
|
-
const isAccelerating = currentVelocity > tracker.velocity;
|
|
48
|
-
|
|
49
|
-
// Apply deceleration factor for smooth velocity tracking
|
|
50
|
-
const smoothedVelocity =
|
|
51
|
-
tracker.velocity *
|
|
52
|
-
LIST_MANAGER_CONSTANTS.SPEED_TRACKING.DECELERATION_FACTOR +
|
|
53
|
-
currentVelocity *
|
|
54
|
-
(1 - LIST_MANAGER_CONSTANTS.SPEED_TRACKING.DECELERATION_FACTOR);
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
velocity: smoothedVelocity,
|
|
58
|
-
direction,
|
|
59
|
-
isAccelerating,
|
|
60
|
-
lastMeasurement: now,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Determine if scroll speed is fast (should defer loading)
|
|
66
|
-
*/
|
|
67
|
-
export function isFastScrolling(tracker: SpeedTracker): boolean {
|
|
68
|
-
return (
|
|
69
|
-
tracker.velocity >
|
|
70
|
-
LIST_MANAGER_CONSTANTS.SPEED_TRACKING.FAST_SCROLL_THRESHOLD
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Determine if scroll speed is slow (should load immediately)
|
|
76
|
-
*/
|
|
77
|
-
export function isSlowScrolling(tracker: SpeedTracker): boolean {
|
|
78
|
-
return (
|
|
79
|
-
tracker.velocity <
|
|
80
|
-
LIST_MANAGER_CONSTANTS.SPEED_TRACKING.SLOW_SCROLL_THRESHOLD
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Get loading strategy based on current speed
|
|
86
|
-
*/
|
|
87
|
-
export function getLoadingStrategy(
|
|
88
|
-
tracker: SpeedTracker
|
|
89
|
-
): "defer" | "immediate" | "maintain" {
|
|
90
|
-
if (isFastScrolling(tracker)) {
|
|
91
|
-
return "defer"; // User is seeking rapidly - show placeholders
|
|
92
|
-
} else if (isSlowScrolling(tracker)) {
|
|
93
|
-
return "immediate"; // User is reading - load proactively
|
|
94
|
-
} else {
|
|
95
|
-
return "maintain"; // Medium speed - continue current strategy
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Calculate scroll momentum for prediction
|
|
101
|
-
*/
|
|
102
|
-
export function calculateScrollMomentum(
|
|
103
|
-
tracker: SpeedTracker,
|
|
104
|
-
containerSize: number,
|
|
105
|
-
estimatedItemSize: number
|
|
106
|
-
): { predictedItems: number; decelerationTime: number } {
|
|
107
|
-
const { velocity, isAccelerating } = tracker;
|
|
108
|
-
|
|
109
|
-
// If not accelerating, velocity will decay
|
|
110
|
-
const decelerationFactor =
|
|
111
|
-
LIST_MANAGER_CONSTANTS.SPEED_TRACKING.DECELERATION_FACTOR;
|
|
112
|
-
|
|
113
|
-
// Calculate time to decelerate to slow scroll threshold
|
|
114
|
-
const targetVelocity =
|
|
115
|
-
LIST_MANAGER_CONSTANTS.SPEED_TRACKING.SLOW_SCROLL_THRESHOLD;
|
|
116
|
-
const decelerationTime = isAccelerating
|
|
117
|
-
? 0
|
|
118
|
-
: Math.log(targetVelocity / velocity) / Math.log(decelerationFactor);
|
|
119
|
-
|
|
120
|
-
// Calculate predicted distance based on momentum
|
|
121
|
-
const predictedDistance = velocity * decelerationTime;
|
|
122
|
-
|
|
123
|
-
// Convert to items for preloading
|
|
124
|
-
const predictedItems = Math.ceil(predictedDistance / estimatedItemSize);
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
predictedItems: Math.max(0, predictedItems),
|
|
128
|
-
decelerationTime: Math.max(0, decelerationTime),
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Create speed-based loading configuration
|
|
134
|
-
*/
|
|
135
|
-
export function createSpeedBasedLoadingConfig(
|
|
136
|
-
tracker: SpeedTracker,
|
|
137
|
-
containerSize: number,
|
|
138
|
-
estimatedItemSize: number
|
|
139
|
-
): {
|
|
140
|
-
strategy: "defer" | "immediate" | "maintain";
|
|
141
|
-
prefetchCount: number;
|
|
142
|
-
deferTimeout: number;
|
|
143
|
-
} {
|
|
144
|
-
const strategy = getLoadingStrategy(tracker);
|
|
145
|
-
const momentum = calculateScrollMomentum(
|
|
146
|
-
tracker,
|
|
147
|
-
containerSize,
|
|
148
|
-
estimatedItemSize
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
let prefetchCount = 0;
|
|
152
|
-
let deferTimeout = 0;
|
|
153
|
-
|
|
154
|
-
switch (strategy) {
|
|
155
|
-
case "defer":
|
|
156
|
-
// Fast scrolling - minimal prefetch, set defer timeout
|
|
157
|
-
prefetchCount = Math.ceil(containerSize / estimatedItemSize);
|
|
158
|
-
deferTimeout = LIST_MANAGER_CONSTANTS.PERFORMANCE.DEBOUNCE_LOADING;
|
|
159
|
-
break;
|
|
160
|
-
|
|
161
|
-
case "immediate":
|
|
162
|
-
// Slow scrolling - aggressive prefetch based on momentum
|
|
163
|
-
prefetchCount = Math.max(
|
|
164
|
-
momentum.predictedItems,
|
|
165
|
-
LIST_MANAGER_CONSTANTS.RANGE_LOADING.PREFETCH_RANGES *
|
|
166
|
-
LIST_MANAGER_CONSTANTS.RANGE_LOADING.DEFAULT_RANGE_SIZE
|
|
167
|
-
);
|
|
168
|
-
deferTimeout = 0;
|
|
169
|
-
break;
|
|
170
|
-
|
|
171
|
-
case "maintain":
|
|
172
|
-
// Medium speed - standard prefetch
|
|
173
|
-
prefetchCount =
|
|
174
|
-
LIST_MANAGER_CONSTANTS.RANGE_LOADING.PREFETCH_RANGES *
|
|
175
|
-
LIST_MANAGER_CONSTANTS.RANGE_LOADING.DEFAULT_RANGE_SIZE;
|
|
176
|
-
deferTimeout = LIST_MANAGER_CONSTANTS.PERFORMANCE.DEBOUNCE_LOADING / 2;
|
|
177
|
-
break;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return {
|
|
181
|
-
strategy,
|
|
182
|
-
prefetchCount,
|
|
183
|
-
deferTimeout,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Reset speed tracker (useful for programmatic scrolling)
|
|
189
|
-
*/
|
|
190
|
-
export function resetSpeedTracker(tracker: SpeedTracker): SpeedTracker {
|
|
191
|
-
return {
|
|
192
|
-
velocity: 0,
|
|
193
|
-
direction: tracker.direction,
|
|
194
|
-
isAccelerating: false,
|
|
195
|
-
lastMeasurement: Date.now(),
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Apply speed-based throttling to scroll events
|
|
201
|
-
*/
|
|
202
|
-
export function getScrollThrottleInterval(tracker: SpeedTracker): number {
|
|
203
|
-
const baseInterval = LIST_MANAGER_CONSTANTS.PERFORMANCE.THROTTLE_SCROLL;
|
|
204
|
-
|
|
205
|
-
// Reduce throttling during fast scrolling for better responsiveness
|
|
206
|
-
if (isFastScrolling(tracker)) {
|
|
207
|
-
return Math.max(baseInterval / 2, 8); // Minimum 8ms (120fps)
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Increase throttling during slow scrolling to save CPU
|
|
211
|
-
if (isSlowScrolling(tracker)) {
|
|
212
|
-
return baseInterval * 2;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return baseInterval;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Determine if scroll direction changed significantly
|
|
220
|
-
*/
|
|
221
|
-
export function hasSignificantDirectionChange(
|
|
222
|
-
tracker: SpeedTracker,
|
|
223
|
-
previousDirection: "forward" | "backward"
|
|
224
|
-
): boolean {
|
|
225
|
-
return (
|
|
226
|
-
tracker.direction !== previousDirection &&
|
|
227
|
-
tracker.velocity >
|
|
228
|
-
LIST_MANAGER_CONSTANTS.SPEED_TRACKING.SLOW_SCROLL_THRESHOLD
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* Calculate adaptive overscan based on scroll speed
|
|
234
|
-
*/
|
|
235
|
-
export function calculateAdaptiveOverscan(
|
|
236
|
-
tracker: SpeedTracker,
|
|
237
|
-
baseOverscan: number = LIST_MANAGER_CONSTANTS.VIRTUAL_SCROLL.OVERSCAN_BUFFER
|
|
238
|
-
): number {
|
|
239
|
-
const { velocity } = tracker;
|
|
240
|
-
|
|
241
|
-
// Increase overscan during fast scrolling
|
|
242
|
-
if (isFastScrolling(tracker)) {
|
|
243
|
-
return baseOverscan * 2;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Reduce overscan during slow scrolling
|
|
247
|
-
if (isSlowScrolling(tracker)) {
|
|
248
|
-
return Math.max(1, Math.floor(baseOverscan / 2));
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return baseOverscan;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Get debug information for speed tracker
|
|
256
|
-
*/
|
|
257
|
-
export function getSpeedTrackerDebugInfo(tracker: SpeedTracker): {
|
|
258
|
-
velocity: string;
|
|
259
|
-
direction: string;
|
|
260
|
-
isAccelerating: boolean;
|
|
261
|
-
strategy: string;
|
|
262
|
-
isFast: boolean;
|
|
263
|
-
isSlow: boolean;
|
|
264
|
-
} {
|
|
265
|
-
return {
|
|
266
|
-
velocity: `${tracker.velocity.toFixed(2)} px/ms`,
|
|
267
|
-
direction: tracker.direction,
|
|
268
|
-
isAccelerating: tracker.isAccelerating,
|
|
269
|
-
strategy: getLoadingStrategy(tracker),
|
|
270
|
-
isFast: isFastScrolling(tracker),
|
|
271
|
-
isSlow: isSlowScrolling(tracker),
|
|
272
|
-
};
|
|
273
|
-
}
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
// mtrl-addons List Component Styles
|
|
2
|
-
// Based on mtrl/src/styles/components/_list.scss
|
|
3
|
-
// Only addons-specific enhancements that don't exist in base mtrl
|
|
4
|
-
|
|
5
|
-
// Import mtrl base styles
|
|
6
|
-
@use "../../../../mtrl/src/styles/abstract/base" as base;
|
|
7
|
-
@use "../../../../mtrl/src/styles/abstract/variables" as v;
|
|
8
|
-
@use "../../../../mtrl/src/styles/abstract/functions" as f;
|
|
9
|
-
@use "../../../../mtrl/src/styles/abstract/mixins" as m;
|
|
10
|
-
@use "../../../../mtrl/src/styles/abstract/theme" as t;
|
|
11
|
-
|
|
12
|
-
// Component variables following mtrl pattern
|
|
13
|
-
$base-component: "#{base.$prefix}-list";
|
|
14
|
-
$addons-component: "#{base.$prefix}-list-addons";
|
|
15
|
-
|
|
16
|
-
// Scrollbar variables
|
|
17
|
-
$scrollbar-track-width: 8px;
|
|
18
|
-
$scrollbar-thumb-min-height: 20px;
|
|
19
|
-
$scrollbar-border-radius: 4px;
|
|
20
|
-
$scrollbar-track-color: rgba(0, 0, 0, 0.1);
|
|
21
|
-
$scrollbar-thumb-color: rgba(0, 0, 0, 0.3);
|
|
22
|
-
$scrollbar-thumb-hover-color: rgba(0, 0, 0, 0.5);
|
|
23
|
-
$scrollbar-thumb-active-color: rgba(0, 0, 0, 0.6);
|
|
24
|
-
$scrollbar-transition: all 0.2s ease;
|
|
25
|
-
$scrollbar-fade-transition: opacity 0.2s ease;
|
|
26
|
-
|
|
27
|
-
// Addons-specific enhancements only
|
|
28
|
-
.#{$base-component}.#{$addons-component} {
|
|
29
|
-
// Collection data management integration (scroll optimization)
|
|
30
|
-
background-color: var(--mtrl-sys-color-surface);
|
|
31
|
-
&[data-addons="true"] {
|
|
32
|
-
// Enhanced scroll performance for large lists
|
|
33
|
-
scroll-behavior: smooth;
|
|
34
|
-
-webkit-overflow-scrolling: touch;
|
|
35
|
-
position: relative; // Required for custom scrollbar positioning
|
|
36
|
-
|
|
37
|
-
// Hide native scrollbar completely for custom scrollbar
|
|
38
|
-
scrollbar-width: none;
|
|
39
|
-
-ms-overflow-style: none;
|
|
40
|
-
|
|
41
|
-
&::-webkit-scrollbar {
|
|
42
|
-
display: none;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Scrollbar track
|
|
46
|
-
.#{base.$prefix}-list__scrollbar.#{base.$prefix}-list__scrollbar-track {
|
|
47
|
-
position: absolute;
|
|
48
|
-
top: 0;
|
|
49
|
-
right: 0;
|
|
50
|
-
width: $scrollbar-track-width;
|
|
51
|
-
height: 100%;
|
|
52
|
-
background: $scrollbar-track-color;
|
|
53
|
-
opacity: 0;
|
|
54
|
-
transition: $scrollbar-fade-transition;
|
|
55
|
-
z-index: 1000;
|
|
56
|
-
cursor: pointer;
|
|
57
|
-
|
|
58
|
-
// Show on hover or interaction
|
|
59
|
-
&:hover,
|
|
60
|
-
&.#{base.$prefix}-list__scrollbar--scrolling,
|
|
61
|
-
&.#{base.$prefix}-list__scrollbar--dragging {
|
|
62
|
-
opacity: 1;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Custom scrollbar thumb
|
|
66
|
-
.#{base.$prefix}-list__scrollbar-thumb {
|
|
67
|
-
position: absolute;
|
|
68
|
-
top: 0;
|
|
69
|
-
left: 0;
|
|
70
|
-
width: 100%;
|
|
71
|
-
min-height: $scrollbar-thumb-min-height;
|
|
72
|
-
background: $scrollbar-thumb-color;
|
|
73
|
-
border-radius: $scrollbar-border-radius;
|
|
74
|
-
cursor: pointer;
|
|
75
|
-
transition: background-color 0.2s ease; // Only transition color, not position
|
|
76
|
-
|
|
77
|
-
&:hover {
|
|
78
|
-
background: $scrollbar-thumb-hover-color;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
&:active,
|
|
82
|
-
&.#{base.$prefix}-list__scrollbar-thumb--dragging {
|
|
83
|
-
background: $scrollbar-thumb-active-color;
|
|
84
|
-
transition: none;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// Show scrollbar on container hover
|
|
90
|
-
&:hover
|
|
91
|
-
.#{base.$prefix}-list__scrollbar.#{base.$prefix}-list__scrollbar-track {
|
|
92
|
-
opacity: 1;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Viewport styling for custom scrollbar compatibility
|
|
96
|
-
.#{base.$prefix}-list__viewport {
|
|
97
|
-
// Ensure viewport takes full height
|
|
98
|
-
height: 100%;
|
|
99
|
-
overflow: hidden; // Let custom scrollbar handle scrolling
|
|
100
|
-
position: relative;
|
|
101
|
-
|
|
102
|
-
// Scrollbar-enabled state
|
|
103
|
-
&.#{base.$prefix}-list__scrollbar-enabled {
|
|
104
|
-
// Specific adjustments when scrollbar is present
|
|
105
|
-
padding-right: $scrollbar-track-width;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
// Placeholder styling
|
|
110
|
-
.#{base.$prefix}-list-item__placeholder {
|
|
111
|
-
opacity: 0.4;
|
|
112
|
-
transition: opacity 0.2s ease;
|
|
113
|
-
|
|
114
|
-
// Create solid blocks for placeholder content
|
|
115
|
-
.user-name,
|
|
116
|
-
.user-email,
|
|
117
|
-
.user-role,
|
|
118
|
-
[class*="__primary"],
|
|
119
|
-
[class*="__secondary"] {
|
|
120
|
-
position: relative;
|
|
121
|
-
display: inline-block; // Make width based on content
|
|
122
|
-
|
|
123
|
-
// Hide the actual text but keep it for width calculation
|
|
124
|
-
color: transparent;
|
|
125
|
-
background-color: var(--mtrl-sys-color-on-surface);
|
|
126
|
-
border-radius: 0.1em; // Smaller radius for thinner appearance
|
|
127
|
-
opacity: 0.7; // Adjust opacity for the blocks
|
|
128
|
-
|
|
129
|
-
// Remove any text decoration
|
|
130
|
-
text-decoration: none;
|
|
131
|
-
|
|
132
|
-
// Thinner blocks - adjust line height and padding
|
|
133
|
-
line-height: 1;
|
|
134
|
-
padding: 0.05em 0; // Much less padding for thinner blocks
|
|
135
|
-
|
|
136
|
-
// Ensure proper vertical alignment
|
|
137
|
-
vertical-align: middle;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Ensure email and role are on separate lines
|
|
141
|
-
.user-email,
|
|
142
|
-
.user-role {
|
|
143
|
-
// display: block; // Force block display to ensure new lines
|
|
144
|
-
margin-top: 0.2em; // Small spacing between lines
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
// For avatar placeholder
|
|
148
|
-
.user-avatar {
|
|
149
|
-
background-color: var(--mtrl-sys-color-primary-container);
|
|
150
|
-
color: var(--mtrl-sys-color-primary-container);
|
|
151
|
-
opacity: 1;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// Dark theme support for scrollbar
|
|
156
|
-
@media (prefers-color-scheme: dark) {
|
|
157
|
-
&[data-addons="true"] {
|
|
158
|
-
.#{base.$prefix}-list__scrollbar.#{base.$prefix}-list__scrollbar-track {
|
|
159
|
-
background: rgba(255, 255, 255, 0.1);
|
|
160
|
-
|
|
161
|
-
.#{base.$prefix}-list__scrollbar-thumb {
|
|
162
|
-
background: rgba(255, 255, 255, 0.3);
|
|
163
|
-
|
|
164
|
-
&:hover {
|
|
165
|
-
background: rgba(255, 255, 255, 0.5);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
&:active,
|
|
169
|
-
&.#{base.$prefix}-list__scrollbar-thumb--dragging {
|
|
170
|
-
background: rgba(255, 255, 255, 0.6);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Future addons-specific features:
|
|
178
|
-
// - Advanced data grid functionality
|
|
179
|
-
// - Tree view capabilities
|
|
180
|
-
// - Advanced filtering/sorting UI
|
|
181
|
-
// - Custom selection modes beyond what mtrl provides
|
|
182
|
-
// - Integration with external data sources
|
|
183
|
-
// - Advanced virtualization strategies
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// users list
|
|
187
|
-
.#{base.$prefix}-list--users {
|
|
188
|
-
height: 600px;
|
|
189
|
-
width: 320px;
|
|
190
|
-
|
|
191
|
-
.user-item {
|
|
192
|
-
padding: 12px 16px;
|
|
193
|
-
display: flex;
|
|
194
|
-
align-items: start;
|
|
195
|
-
transition: background-color 0.2s ease;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
.user-avatar {
|
|
199
|
-
width: 40px;
|
|
200
|
-
height: 40px;
|
|
201
|
-
border-radius: 50%;
|
|
202
|
-
background-color: var(--mtrl-sys-color-primary-container);
|
|
203
|
-
color: white;
|
|
204
|
-
display: flex;
|
|
205
|
-
align-items: center;
|
|
206
|
-
justify-content: center;
|
|
207
|
-
font-weight: bold;
|
|
208
|
-
flex-shrink: 0;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
.user-details {
|
|
212
|
-
flex: 1;
|
|
213
|
-
min-width: 0;
|
|
214
|
-
margin-left: 12px;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
.user-name {
|
|
218
|
-
font-weight: 500;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
.user-email {
|
|
222
|
-
// color: #666;
|
|
223
|
-
font-size: 14px;
|
|
224
|
-
white-space: nowrap;
|
|
225
|
-
overflow: hidden;
|
|
226
|
-
text-overflow: ellipsis;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
.user-phone {
|
|
230
|
-
color: var(--mtrl-sys-color-primary);
|
|
231
|
-
font-size: 13px;
|
|
232
|
-
font-weight: 500;
|
|
233
|
-
margin-top: 4px;
|
|
234
|
-
white-space: nowrap;
|
|
235
|
-
overflow: hidden;
|
|
236
|
-
text-overflow: ellipsis;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
.user-role {
|
|
240
|
-
color: var(--mtrl-sys-color-on-surface-variant);
|
|
241
|
-
font-size: 12px;
|
|
242
|
-
margin-top: 2px;
|
|
243
|
-
}
|
|
244
|
-
}
|