mtrl-addons 0.2.1 → 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 +286 -110
- package/package.json +2 -1
- package/src/components/vlist/features/api.ts +316 -12
- package/src/components/vlist/features/selection.ts +248 -256
- package/src/components/vlist/features/viewport.ts +1 -7
- package/src/components/vlist/index.ts +1 -0
- package/src/components/vlist/types.ts +140 -8
- package/src/core/layout/schema.ts +81 -38
- package/src/core/viewport/constants.ts +7 -2
- package/src/core/viewport/features/collection.ts +376 -76
- package/src/core/viewport/features/item-size.ts +4 -4
- package/src/core/viewport/features/momentum.ts +11 -2
- package/src/core/viewport/features/rendering.ts +424 -30
- package/src/core/viewport/features/scrolling.ts +41 -25
- package/src/core/viewport/features/utils.ts +11 -5
- package/src/core/viewport/features/virtual.ts +169 -28
- package/src/core/viewport/types.ts +2 -2
- package/src/core/viewport/viewport.ts +29 -10
- package/src/styles/components/_vlist.scss +234 -213
|
@@ -40,6 +40,9 @@ interface ViewportState {
|
|
|
40
40
|
*/
|
|
41
41
|
export const createViewport = (config: ViewportConfig = {}) => {
|
|
42
42
|
return <T extends ViewportContext>(component: T): T & ViewportComponent => {
|
|
43
|
+
// Track if viewport has been initialized to prevent multiple initializations
|
|
44
|
+
let isInitialized = false;
|
|
45
|
+
|
|
43
46
|
// No normalization needed - we'll use the nested structure directly
|
|
44
47
|
|
|
45
48
|
// Create shared viewport state
|
|
@@ -59,6 +62,12 @@ export const createViewport = (config: ViewportConfig = {}) => {
|
|
|
59
62
|
const viewportAPI = {
|
|
60
63
|
// Core API
|
|
61
64
|
initialize: () => {
|
|
65
|
+
// Prevent multiple initializations
|
|
66
|
+
if (isInitialized) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
isInitialized = true;
|
|
70
|
+
|
|
62
71
|
// console.log("[Viewport] Initializing with state:", {
|
|
63
72
|
// element: !!component.element,
|
|
64
73
|
// totalItems: component.totalItems,
|
|
@@ -96,12 +105,18 @@ export const createViewport = (config: ViewportConfig = {}) => {
|
|
|
96
105
|
// Will be implemented by rendering feature
|
|
97
106
|
},
|
|
98
107
|
|
|
108
|
+
// Check if already initialized
|
|
109
|
+
isInitialized: () => isInitialized,
|
|
110
|
+
|
|
111
|
+
// Allow features to check if init should proceed
|
|
112
|
+
_shouldInit: () => !isInitialized,
|
|
113
|
+
|
|
99
114
|
// Scrolling API (will be overridden by scrolling feature)
|
|
100
115
|
scrollToIndex: (
|
|
101
116
|
index: number,
|
|
102
|
-
alignment?: "start" | "center" | "end"
|
|
117
|
+
alignment?: "start" | "center" | "end",
|
|
103
118
|
) => {
|
|
104
|
-
//
|
|
119
|
+
// Placeholder - will be implemented by scrolling feature
|
|
105
120
|
},
|
|
106
121
|
|
|
107
122
|
scrollToPosition: (position: number) => {
|
|
@@ -152,7 +167,7 @@ export const createViewport = (config: ViewportConfig = {}) => {
|
|
|
152
167
|
enhancers.push(
|
|
153
168
|
withEvents({
|
|
154
169
|
debug: config.debug,
|
|
155
|
-
})
|
|
170
|
+
}),
|
|
156
171
|
);
|
|
157
172
|
|
|
158
173
|
// Base setup (creates DOM structure)
|
|
@@ -160,7 +175,7 @@ export const createViewport = (config: ViewportConfig = {}) => {
|
|
|
160
175
|
withBase({
|
|
161
176
|
className: config.className,
|
|
162
177
|
orientation: config.scrolling?.orientation,
|
|
163
|
-
})
|
|
178
|
+
}),
|
|
164
179
|
);
|
|
165
180
|
|
|
166
181
|
// Virtual scrolling (required for most features)
|
|
@@ -170,7 +185,8 @@ export const createViewport = (config: ViewportConfig = {}) => {
|
|
|
170
185
|
overscan: config.virtual?.overscan,
|
|
171
186
|
orientation: config.scrolling?.orientation,
|
|
172
187
|
autoDetectItemSize: config.virtual?.autoDetectItemSize,
|
|
173
|
-
|
|
188
|
+
initialScrollIndex: (config as any).initialScrollIndex,
|
|
189
|
+
}),
|
|
174
190
|
);
|
|
175
191
|
|
|
176
192
|
// Scrolling behavior
|
|
@@ -179,7 +195,7 @@ export const createViewport = (config: ViewportConfig = {}) => {
|
|
|
179
195
|
orientation: config.scrolling?.orientation,
|
|
180
196
|
sensitivity: config.scrolling?.sensitivity,
|
|
181
197
|
smoothing: config.scrolling?.animation,
|
|
182
|
-
})
|
|
198
|
+
}),
|
|
183
199
|
);
|
|
184
200
|
|
|
185
201
|
// Scrollbar (optional)
|
|
@@ -188,7 +204,7 @@ export const createViewport = (config: ViewportConfig = {}) => {
|
|
|
188
204
|
withScrollbar({
|
|
189
205
|
enabled: true,
|
|
190
206
|
autoHide: config.scrollbar?.autoHide,
|
|
191
|
-
})
|
|
207
|
+
}),
|
|
192
208
|
);
|
|
193
209
|
}
|
|
194
210
|
|
|
@@ -207,7 +223,10 @@ export const createViewport = (config: ViewportConfig = {}) => {
|
|
|
207
223
|
cancelLoadThreshold: config.performance?.cancelLoadThreshold,
|
|
208
224
|
maxConcurrentRequests: config.performance?.maxConcurrentRequests,
|
|
209
225
|
enableRequestQueue: config.performance?.enableRequestQueue !== false,
|
|
210
|
-
|
|
226
|
+
initialScrollIndex: (config as any).initialScrollIndex,
|
|
227
|
+
selectId: (config as any).selectId,
|
|
228
|
+
autoLoad: (config as any).autoLoad !== false,
|
|
229
|
+
}),
|
|
211
230
|
);
|
|
212
231
|
}
|
|
213
232
|
|
|
@@ -218,7 +237,7 @@ export const createViewport = (config: ViewportConfig = {}) => {
|
|
|
218
237
|
enabled: true,
|
|
219
238
|
analyzeFirstLoad: config.placeholders?.analyzeFirstLoad ?? true,
|
|
220
239
|
maskCharacter: config.placeholders?.maskCharacter,
|
|
221
|
-
})
|
|
240
|
+
}),
|
|
222
241
|
);
|
|
223
242
|
}
|
|
224
243
|
|
|
@@ -227,7 +246,7 @@ export const createViewport = (config: ViewportConfig = {}) => {
|
|
|
227
246
|
withRendering({
|
|
228
247
|
template: config.template,
|
|
229
248
|
overscan: config.virtual?.overscan,
|
|
230
|
-
})
|
|
249
|
+
}),
|
|
231
250
|
);
|
|
232
251
|
|
|
233
252
|
// Compose all enhancers
|
|
@@ -29,22 +29,33 @@ $opacity-transition: opacity $transition-duration $transition-easing;
|
|
|
29
29
|
// ===========================
|
|
30
30
|
|
|
31
31
|
@keyframes placeholder-pulse {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
0%,
|
|
33
|
+
100% {
|
|
34
|
+
opacity: 0.6;
|
|
35
|
+
}
|
|
36
|
+
50% {
|
|
37
|
+
opacity: 0.4;
|
|
38
|
+
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
@keyframes fade-in {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
from {
|
|
43
|
+
opacity: 0.6;
|
|
44
|
+
}
|
|
45
|
+
to {
|
|
46
|
+
opacity: 1;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@keyframes item-updated {
|
|
51
|
+
0% {
|
|
52
|
+
background-color: t.alpha("primary", 0.25);
|
|
53
|
+
box-shadow: inset 0 0 0 2px t.alpha("primary", 0.4);
|
|
54
|
+
}
|
|
55
|
+
100% {
|
|
56
|
+
background-color: transparent;
|
|
57
|
+
box-shadow: inset 0 0 0 2px transparent;
|
|
58
|
+
}
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
// ===========================
|
|
@@ -52,58 +63,58 @@ $opacity-transition: opacity $transition-duration $transition-easing;
|
|
|
52
63
|
// ===========================
|
|
53
64
|
|
|
54
65
|
.#{$component} {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
66
|
+
position: relative;
|
|
67
|
+
width: 100%;
|
|
68
|
+
height: 100%;
|
|
69
|
+
min-height: 100px;
|
|
70
|
+
background-color: t.color("surface");
|
|
71
|
+
border: 2px solid var(--mtrl-sys-color-outline-variant);
|
|
72
|
+
border-radius: 3px;
|
|
73
|
+
transition: $bg-transition;
|
|
74
|
+
|
|
75
|
+
// Performance optimizations
|
|
76
|
+
contain: layout style paint;
|
|
77
|
+
transform: translateZ(0);
|
|
78
|
+
backface-visibility: hidden;
|
|
79
|
+
|
|
80
|
+
// Selection mode
|
|
81
|
+
&--selection {
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
.#{$viewport-item}:hover {
|
|
84
|
+
background-color: t.alpha("on-surface-variant", 0.1);
|
|
85
|
+
}
|
|
86
|
+
// Selected state
|
|
87
|
+
.#{$viewport-item}--selected,
|
|
88
|
+
.#{$viewport-item}--selected:hover {
|
|
89
|
+
background-color: t.color("secondary-container");
|
|
90
|
+
color: t.color("on-secondary-container");
|
|
91
|
+
transition: $bg-transition, $color-transition;
|
|
92
|
+
|
|
93
|
+
// // Update state layer color for selected state
|
|
94
|
+
// &::before {
|
|
95
|
+
// background-color: t.color("on-secondary-container");
|
|
96
|
+
// }
|
|
97
|
+
|
|
98
|
+
// Update text and icon colors for selected state
|
|
99
|
+
.#{$component}-item {
|
|
100
|
+
&-leading,
|
|
101
|
+
&-trailing,
|
|
102
|
+
&-supporting,
|
|
103
|
+
&-overline,
|
|
104
|
+
&-meta {
|
|
105
|
+
color: t.color("on-secondary-container");
|
|
106
|
+
transition: $color-transition;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
96
109
|
}
|
|
97
|
-
}
|
|
98
110
|
}
|
|
99
|
-
}
|
|
100
111
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
112
|
+
// Disabled state
|
|
113
|
+
&--disabled {
|
|
114
|
+
pointer-events: none;
|
|
115
|
+
opacity: 0.38;
|
|
116
|
+
transition: $opacity-transition;
|
|
117
|
+
}
|
|
107
118
|
}
|
|
108
119
|
|
|
109
120
|
// ===========================
|
|
@@ -111,86 +122,96 @@ $opacity-transition: opacity $transition-duration $transition-easing;
|
|
|
111
122
|
// ===========================
|
|
112
123
|
|
|
113
124
|
.#{$viewport} {
|
|
114
|
-
position: relative;
|
|
115
|
-
width: 100%;
|
|
116
|
-
height: 100%;
|
|
117
|
-
overflow: hidden;
|
|
118
|
-
|
|
119
|
-
// Items container
|
|
120
|
-
&-items {
|
|
121
125
|
position: relative;
|
|
122
126
|
width: 100%;
|
|
123
127
|
height: 100%;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
128
|
+
overflow: hidden;
|
|
129
|
+
|
|
130
|
+
// Items container
|
|
131
|
+
&-items {
|
|
132
|
+
position: relative;
|
|
133
|
+
width: 100%;
|
|
134
|
+
height: 100%;
|
|
135
|
+
padding: 8px 0;
|
|
136
|
+
will-change: transform;
|
|
137
|
+
}
|
|
127
138
|
}
|
|
128
139
|
|
|
129
140
|
.#{$viewport-item} {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
141
|
+
user-select: none;
|
|
142
|
+
opacity: 1;
|
|
143
|
+
transition: $opacity-transition;
|
|
144
|
+
will-change: transform;
|
|
145
|
+
// Apply fade-in animation to items that replace placeholders
|
|
146
|
+
&--replaced {
|
|
147
|
+
animation: fade-in 0.3s ease-out;
|
|
148
|
+
}
|
|
149
|
+
// Apply highlight animation when item is updated
|
|
150
|
+
&--updated,
|
|
151
|
+
&--updated > * {
|
|
152
|
+
animation: item-updated 0.6s ease-out;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Inner item update animation (applied to template's root element)
|
|
156
|
+
.item--updated {
|
|
157
|
+
animation: item-updated 0.6s ease-out;
|
|
158
|
+
}
|
|
138
159
|
}
|
|
139
160
|
|
|
140
161
|
.#{$viewport-item} {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
162
|
+
padding: 11px 12px;
|
|
163
|
+
display: flex;
|
|
164
|
+
align-items: start;
|
|
165
|
+
transition: background-color 0.2s ease;
|
|
166
|
+
// align-items: center;
|
|
167
|
+
min-height: 48px;
|
|
168
|
+
left: 0;
|
|
169
|
+
right: 0;
|
|
170
|
+
width: 100%;
|
|
171
|
+
will-change: transform;
|
|
172
|
+
contain: layout style;
|
|
173
|
+
gap: 16px;
|
|
174
|
+
color: var(--mtrl-sys-color-on-surface);
|
|
175
|
+
overflow: hidden;
|
|
155
176
|
}
|
|
156
177
|
|
|
157
178
|
.#{$viewport-item}__avatar,
|
|
158
179
|
.#{$viewport-item}__image {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
180
|
+
width: 40px;
|
|
181
|
+
height: 40px;
|
|
182
|
+
margin-top: 4px;
|
|
183
|
+
border-radius: 50%;
|
|
184
|
+
background-color: var(--mtrl-sys-color-primary-container);
|
|
185
|
+
color: white;
|
|
186
|
+
display: flex;
|
|
187
|
+
align-items: center;
|
|
188
|
+
justify-content: center;
|
|
189
|
+
font-weight: bold;
|
|
190
|
+
flex-shrink: 0;
|
|
170
191
|
}
|
|
171
192
|
|
|
172
193
|
.#{$viewport-item}__details {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
194
|
+
flex: 1;
|
|
195
|
+
min-width: 0;
|
|
196
|
+
margin-left: 12px;
|
|
176
197
|
}
|
|
177
198
|
|
|
178
199
|
.#{$viewport-item}__headline {
|
|
179
|
-
|
|
200
|
+
font-weight: 500;
|
|
180
201
|
}
|
|
181
202
|
|
|
182
203
|
.#{$viewport-item}__text {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
204
|
+
// color: #666;
|
|
205
|
+
font-size: 14px;
|
|
206
|
+
white-space: nowrap;
|
|
207
|
+
overflow: hidden;
|
|
208
|
+
text-overflow: ellipsis;
|
|
188
209
|
}
|
|
189
210
|
|
|
190
211
|
.#{$viewport-item}__meta {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
212
|
+
color: var(--mtrl-sys-color-on-surface-variant);
|
|
213
|
+
font-size: 12px;
|
|
214
|
+
margin-top: 2px;
|
|
194
215
|
}
|
|
195
216
|
|
|
196
217
|
// ===========================
|
|
@@ -198,48 +219,48 @@ $opacity-transition: opacity $transition-duration $transition-easing;
|
|
|
198
219
|
// ===========================
|
|
199
220
|
|
|
200
221
|
.#{$viewport-item}--placeholder {
|
|
201
|
-
|
|
202
|
-
|
|
222
|
+
opacity: 0.6; // Match the animation start/end opacity
|
|
223
|
+
animation: placeholder-pulse 2s ease-in-out infinite;
|
|
224
|
+
|
|
225
|
+
// Placeholder content blocks - style any text elements within
|
|
226
|
+
.#{$viewport-item}__headline,
|
|
227
|
+
.#{$viewport-item}__text,
|
|
228
|
+
.#{$viewport-item}__meta {
|
|
229
|
+
position: relative;
|
|
230
|
+
display: inline-block;
|
|
231
|
+
font-size: 0.8em;
|
|
232
|
+
color: transparent;
|
|
233
|
+
background-color: var(--mtrl-sys-color-on-surface);
|
|
234
|
+
border-radius: 0.1em;
|
|
235
|
+
opacity: 0.4;
|
|
236
|
+
text-decoration: none;
|
|
237
|
+
line-height: 1;
|
|
238
|
+
padding: 0 0 0.05em;
|
|
239
|
+
vertical-align: middle;
|
|
240
|
+
}
|
|
203
241
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
.#{$viewport-item}__meta {
|
|
228
|
-
font-size: 10px;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// User-specific placeholder elements
|
|
232
|
-
.#{$viewport-item}__user-headline,
|
|
233
|
-
.#{$viewport-item}__user-text {
|
|
234
|
-
text-transform: capitalize;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Avatar placeholder
|
|
238
|
-
.#{$viewport-item}__avatar {
|
|
239
|
-
background-color: var(--mtrl-sys-color-primary-container);
|
|
240
|
-
color: var(--mtrl-sys-color-primary-container);
|
|
241
|
-
opacity: 1;
|
|
242
|
-
}
|
|
242
|
+
// Layout adjustments
|
|
243
|
+
.#{$viewport-item}__text,
|
|
244
|
+
.#{$viewport-item}__meta {
|
|
245
|
+
margin-top: 0.2em;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.#{$viewport-item}__meta {
|
|
249
|
+
font-size: 10px;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// User-specific placeholder elements
|
|
253
|
+
.#{$viewport-item}__user-headline,
|
|
254
|
+
.#{$viewport-item}__user-text {
|
|
255
|
+
text-transform: capitalize;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Avatar placeholder
|
|
259
|
+
.#{$viewport-item}__avatar {
|
|
260
|
+
background-color: var(--mtrl-sys-color-primary-container);
|
|
261
|
+
color: var(--mtrl-sys-color-primary-container);
|
|
262
|
+
opacity: 1;
|
|
263
|
+
}
|
|
243
264
|
}
|
|
244
265
|
|
|
245
266
|
// ===========================
|
|
@@ -247,51 +268,51 @@ $opacity-transition: opacity $transition-duration $transition-easing;
|
|
|
247
268
|
// ===========================
|
|
248
269
|
|
|
249
270
|
.#{$viewport}__scrollbar {
|
|
250
|
-
position: absolute;
|
|
251
|
-
top: 0;
|
|
252
|
-
right: 0;
|
|
253
|
-
width: 8px;
|
|
254
|
-
height: 100%;
|
|
255
|
-
padding: 0;
|
|
256
|
-
opacity: 0;
|
|
257
|
-
transition: opacity 0.3s ease;
|
|
258
|
-
cursor: pointer;
|
|
259
|
-
z-index: 10;
|
|
260
|
-
|
|
261
|
-
// Visibility states
|
|
262
|
-
&--visible,
|
|
263
|
-
&--dragging,
|
|
264
|
-
&:hover {
|
|
265
|
-
opacity: 1;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
&:hover {
|
|
269
|
-
background: rgba(0, 0, 0, 0.05);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Scrollbar thumb
|
|
273
|
-
&-thumb {
|
|
274
271
|
position: absolute;
|
|
275
272
|
top: 0;
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
273
|
+
right: 0;
|
|
274
|
+
width: 8px;
|
|
275
|
+
height: 100%;
|
|
276
|
+
padding: 0;
|
|
277
|
+
opacity: 0;
|
|
278
|
+
transition: opacity 0.3s ease;
|
|
279
|
+
cursor: pointer;
|
|
280
|
+
z-index: 10;
|
|
281
|
+
|
|
282
|
+
// Visibility states
|
|
283
|
+
&--visible,
|
|
284
|
+
&--dragging,
|
|
285
|
+
&:hover {
|
|
286
|
+
opacity: 1;
|
|
287
|
+
}
|
|
283
288
|
|
|
284
289
|
&:hover {
|
|
285
|
-
|
|
290
|
+
background: rgba(0, 0, 0, 0.05);
|
|
286
291
|
}
|
|
287
292
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
+
// Scrollbar thumb
|
|
294
|
+
&-thumb {
|
|
295
|
+
position: absolute;
|
|
296
|
+
top: 0;
|
|
297
|
+
width: 6px;
|
|
298
|
+
padding: 1px;
|
|
299
|
+
background: rgba(0, 0, 0, 0.3);
|
|
300
|
+
border-radius: 4px;
|
|
301
|
+
will-change: transform;
|
|
302
|
+
cursor: grab;
|
|
303
|
+
transition: background 0.2s ease;
|
|
304
|
+
|
|
305
|
+
&:hover {
|
|
306
|
+
background: rgba(0, 0, 0, 0.5);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
&:active,
|
|
310
|
+
&--dragging {
|
|
311
|
+
cursor: grabbing;
|
|
312
|
+
background: rgba(0, 0, 0, 0.6);
|
|
313
|
+
transition: none;
|
|
314
|
+
}
|
|
293
315
|
}
|
|
294
|
-
}
|
|
295
316
|
}
|
|
296
317
|
|
|
297
318
|
// ===========================
|
|
@@ -299,22 +320,22 @@ $opacity-transition: opacity $transition-duration $transition-easing;
|
|
|
299
320
|
// ===========================
|
|
300
321
|
|
|
301
322
|
@media (prefers-color-scheme: dark) {
|
|
302
|
-
|
|
303
|
-
|
|
323
|
+
.#{$viewport}__scrollbar {
|
|
324
|
+
background: transparent;
|
|
304
325
|
|
|
305
|
-
|
|
306
|
-
|
|
326
|
+
&-thumb {
|
|
327
|
+
background: rgba(255, 255, 255, 0.4);
|
|
307
328
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
329
|
+
&:hover {
|
|
330
|
+
background: rgba(255, 255, 255, 0.6);
|
|
331
|
+
}
|
|
311
332
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
333
|
+
&:active,
|
|
334
|
+
&--dragging {
|
|
335
|
+
background: rgba(255, 255, 255, 0.4);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
316
338
|
}
|
|
317
|
-
}
|
|
318
339
|
}
|
|
319
340
|
|
|
320
341
|
// ===========================
|
|
@@ -323,9 +344,9 @@ $opacity-transition: opacity $transition-duration $transition-easing;
|
|
|
323
344
|
|
|
324
345
|
// High-density displays
|
|
325
346
|
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
347
|
+
.#{$viewport-item} {
|
|
348
|
+
text-rendering: optimizeLegibility;
|
|
349
|
+
-webkit-font-smoothing: antialiased;
|
|
350
|
+
-moz-osx-font-smoothing: grayscale;
|
|
351
|
+
}
|
|
331
352
|
}
|