@lightningtv/solid 3.0.4 → 3.0.6
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/dist/src/core/elementNode.js +9 -7
- package/dist/src/core/elementNode.js.map +1 -1
- package/dist/src/primitives/Column.jsx +6 -10
- package/dist/src/primitives/Column.jsx.map +1 -1
- package/dist/src/primitives/Row.jsx +6 -10
- package/dist/src/primitives/Row.jsx.map +1 -1
- package/dist/src/primitives/Virtual.jsx +36 -16
- package/dist/src/primitives/Virtual.jsx.map +1 -1
- package/dist/src/primitives/types.d.ts +16 -0
- package/dist/src/primitives/utils/handleNavigation.d.ts +24 -0
- package/dist/src/primitives/utils/handleNavigation.js +43 -0
- package/dist/src/primitives/utils/handleNavigation.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/core/elementNode.ts +9 -7
- package/src/primitives/Column.tsx +15 -9
- package/src/primitives/Row.tsx +17 -12
- package/src/primitives/Virtual.tsx +296 -215
- package/src/primitives/types.ts +20 -0
- package/src/primitives/utils/handleNavigation.ts +52 -0
|
@@ -3,6 +3,12 @@ import * as lng from '@lightningtv/solid';
|
|
|
3
3
|
import * as lngp from '@lightningtv/solid/primitives';
|
|
4
4
|
import { List } from '@solid-primitives/list';
|
|
5
5
|
import * as utils from '../utils.js';
|
|
6
|
+
import {
|
|
7
|
+
defaultTransitionBack,
|
|
8
|
+
defaultTransitionForward,
|
|
9
|
+
defaultTransitionDown,
|
|
10
|
+
defaultTransitionUp,
|
|
11
|
+
} from './utils/handleNavigation.js';
|
|
6
12
|
|
|
7
13
|
export type VirtualProps<T> = lng.NewOmit<lngp.RowProps, 'children'> & {
|
|
8
14
|
each: readonly T[] | undefined | null | false;
|
|
@@ -21,7 +27,7 @@ export type VirtualProps<T> = lng.NewOmit<lngp.RowProps, 'children'> & {
|
|
|
21
27
|
function createVirtual<T>(
|
|
22
28
|
component: typeof lngp.Row | typeof lngp.Column,
|
|
23
29
|
props: VirtualProps<T>,
|
|
24
|
-
keyHandlers: Record<string, lng.KeyHandler
|
|
30
|
+
keyHandlers: Record<string, lng.KeyHandler>,
|
|
25
31
|
) {
|
|
26
32
|
const isRow = component === lngp.Row;
|
|
27
33
|
const axis = isRow ? 'x' : 'y';
|
|
@@ -46,81 +52,102 @@ function createVirtual<T>(
|
|
|
46
52
|
return props.uniformSize !== false;
|
|
47
53
|
});
|
|
48
54
|
|
|
49
|
-
type SliceState = {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
type SliceState = {
|
|
56
|
+
start: number;
|
|
57
|
+
slice: T[];
|
|
58
|
+
selected: number;
|
|
59
|
+
delta: number;
|
|
60
|
+
shiftBy: number;
|
|
61
|
+
atStart: boolean;
|
|
62
|
+
cursor: number;
|
|
63
|
+
};
|
|
64
|
+
const [slice, setSlice] = s.createSignal<SliceState>({
|
|
65
|
+
start: 0,
|
|
66
|
+
slice: [],
|
|
67
|
+
selected: 0,
|
|
68
|
+
delta: 0,
|
|
69
|
+
shiftBy: 0,
|
|
70
|
+
atStart: true,
|
|
71
|
+
cursor: 0,
|
|
72
|
+
});
|
|
59
73
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
function normalizeDeltaForWindow(delta: number, windowLen: number): number {
|
|
75
|
+
if (!windowLen) return 0;
|
|
76
|
+
const half = windowLen / 2;
|
|
77
|
+
if (delta > half) return delta - windowLen;
|
|
78
|
+
if (delta < -half) return delta + windowLen;
|
|
79
|
+
return delta;
|
|
80
|
+
}
|
|
67
81
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
82
|
+
function computeSize(selected: number = 0) {
|
|
83
|
+
if (uniformSize() && cachedScaledSize) {
|
|
84
|
+
return cachedScaledSize;
|
|
85
|
+
} else if (viewRef) {
|
|
86
|
+
const gap = viewRef.gap || 0;
|
|
87
|
+
const dimension = isRow ? 'width' : 'height'; // This can't be moved up as it depends on viewRef
|
|
88
|
+
const prevSelectedChild = viewRef.children[selected];
|
|
89
|
+
|
|
90
|
+
if (prevSelectedChild instanceof lng.ElementNode) {
|
|
91
|
+
const itemSize = prevSelectedChild[dimension] || 0;
|
|
92
|
+
const focusStyle = prevSelectedChild.style?.focus as lng.NodeStyles;
|
|
93
|
+
const scale = focusStyle?.scale ?? prevSelectedChild.scale ?? 1;
|
|
94
|
+
const scaledSize = itemSize * (props.factorScale ? scale : 1) + gap;
|
|
95
|
+
cachedScaledSize = scaledSize;
|
|
96
|
+
return scaledSize;
|
|
84
97
|
}
|
|
85
|
-
return 0;
|
|
86
98
|
}
|
|
99
|
+
return 0;
|
|
100
|
+
}
|
|
87
101
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
function computeSlice(
|
|
103
|
+
c: number,
|
|
104
|
+
delta: number,
|
|
105
|
+
prev: SliceState,
|
|
106
|
+
): SliceState {
|
|
107
|
+
const total = itemCount();
|
|
108
|
+
if (total === 0)
|
|
109
|
+
return {
|
|
110
|
+
start: 0,
|
|
111
|
+
slice: [],
|
|
112
|
+
selected: 0,
|
|
113
|
+
delta,
|
|
114
|
+
shiftBy: 0,
|
|
115
|
+
atStart: true,
|
|
116
|
+
cursor: 0,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const length = props.displaySize + bufferSize();
|
|
120
|
+
let start = prev.start;
|
|
121
|
+
let selected = prev.selected;
|
|
122
|
+
let atStart = prev.atStart;
|
|
123
|
+
let shiftBy = -delta;
|
|
124
|
+
|
|
125
|
+
switch (scrollType()) {
|
|
126
|
+
case 'always':
|
|
127
|
+
if (props.wrap) {
|
|
128
|
+
start = utils.mod(c - 1, total);
|
|
129
|
+
selected = 1;
|
|
130
|
+
} else {
|
|
131
|
+
start = utils.clamp(
|
|
132
|
+
c - bufferSize(),
|
|
133
|
+
0,
|
|
134
|
+
Math.max(0, total - props.displaySize - bufferSize()),
|
|
135
|
+
);
|
|
136
|
+
if (delta === 0 && c > 3) {
|
|
137
|
+
shiftBy = c < 3 ? -c : -2;
|
|
138
|
+
selected = 2;
|
|
103
139
|
} else {
|
|
104
|
-
|
|
105
|
-
c
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
);
|
|
109
|
-
if (delta === 0 && c > 3) {
|
|
110
|
-
shiftBy = c < 3 ? -c : -2;
|
|
111
|
-
selected = 2;
|
|
112
|
-
} else {
|
|
113
|
-
selected =
|
|
114
|
-
c < bufferSize()
|
|
115
|
-
? c
|
|
116
|
-
: c >= total - props.displaySize
|
|
140
|
+
selected =
|
|
141
|
+
c < bufferSize()
|
|
142
|
+
? c
|
|
143
|
+
: c >= total - props.displaySize
|
|
117
144
|
? c - (total - props.displaySize) + bufferSize()
|
|
118
145
|
: bufferSize();
|
|
119
|
-
}
|
|
120
146
|
}
|
|
121
|
-
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
122
149
|
|
|
123
|
-
|
|
150
|
+
case 'auto':
|
|
124
151
|
if (props.wrap) {
|
|
125
152
|
if (delta === 0) {
|
|
126
153
|
selected = scrollIndex() || 1;
|
|
@@ -144,7 +171,7 @@ function createVirtual<T>(
|
|
|
144
171
|
start = 0;
|
|
145
172
|
selected = prev.selected - 1;
|
|
146
173
|
atStart = true;
|
|
147
|
-
}
|
|
174
|
+
} else if (selected >= props.displaySize - 1) {
|
|
148
175
|
// Shift window left, keep selection pinned
|
|
149
176
|
start = 0;
|
|
150
177
|
selected = prev.selected - 1;
|
|
@@ -176,12 +203,15 @@ function createVirtual<T>(
|
|
|
176
203
|
} else {
|
|
177
204
|
// Shift window right, keep selection pinned
|
|
178
205
|
start = prev.start + 1;
|
|
179
|
-
selected = Math.max(prev.selected, scrollIndex() + 1)
|
|
206
|
+
selected = Math.max(prev.selected, scrollIndex() + 1);
|
|
180
207
|
}
|
|
181
208
|
} else {
|
|
182
209
|
// Initial setup
|
|
183
210
|
if (c > 0) {
|
|
184
|
-
start = Math.min(
|
|
211
|
+
start = Math.min(
|
|
212
|
+
c - (scrollIndex() || 1),
|
|
213
|
+
total - props.displaySize - bufferSize(),
|
|
214
|
+
);
|
|
185
215
|
selected = Math.max(scrollIndex() || 1, c - start);
|
|
186
216
|
shiftBy = total - c < 3 ? c - total : -1;
|
|
187
217
|
atStart = false;
|
|
@@ -202,107 +232,118 @@ function createVirtual<T>(
|
|
|
202
232
|
}
|
|
203
233
|
break;
|
|
204
234
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
235
|
+
case 'edge':
|
|
236
|
+
const startScrolling = Math.max(
|
|
237
|
+
1,
|
|
238
|
+
props.displaySize + (atStart ? -1 : 0),
|
|
239
|
+
);
|
|
240
|
+
if (props.wrap) {
|
|
241
|
+
if (delta > 0) {
|
|
242
|
+
if (prev.selected < startScrolling) {
|
|
243
|
+
selected = prev.selected + 1;
|
|
244
|
+
shiftBy = 0;
|
|
245
|
+
} else if (prev.selected === startScrolling && atStart) {
|
|
246
|
+
selected = prev.selected + 1;
|
|
247
|
+
atStart = false;
|
|
248
|
+
} else {
|
|
249
|
+
start = utils.mod(prev.start + 1, total);
|
|
250
|
+
selected = prev.selected;
|
|
251
|
+
}
|
|
252
|
+
} else if (delta < 0) {
|
|
253
|
+
if (prev.selected > 1) {
|
|
254
|
+
selected = prev.selected - 1;
|
|
255
|
+
shiftBy = 0;
|
|
227
256
|
} else {
|
|
228
|
-
start = utils.mod(
|
|
257
|
+
start = utils.mod(prev.start - 1, total);
|
|
229
258
|
selected = 1;
|
|
230
|
-
shiftBy = -1;
|
|
231
|
-
atStart = false;
|
|
232
259
|
}
|
|
233
260
|
} else {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
261
|
+
start = utils.mod(c - 1, total);
|
|
262
|
+
selected = 1;
|
|
263
|
+
shiftBy = -1;
|
|
264
|
+
atStart = false;
|
|
265
|
+
}
|
|
266
|
+
} else {
|
|
267
|
+
if (delta === 0 && c > 0) {
|
|
268
|
+
//initial setup
|
|
269
|
+
selected = c > startScrolling ? startScrolling : c;
|
|
270
|
+
start = Math.max(0, c - startScrolling + 1);
|
|
271
|
+
shiftBy = c > startScrolling ? -1 : 0;
|
|
272
|
+
atStart = c < startScrolling;
|
|
273
|
+
} else if (delta > 0) {
|
|
274
|
+
if (prev.selected < startScrolling) {
|
|
275
|
+
selected = prev.selected + 1;
|
|
276
|
+
shiftBy = 0;
|
|
277
|
+
} else if (prev.selected === startScrolling && atStart) {
|
|
278
|
+
selected = prev.selected + 1;
|
|
279
|
+
atStart = false;
|
|
280
|
+
} else {
|
|
281
|
+
start = prev.start + 1;
|
|
282
|
+
selected = prev.selected;
|
|
283
|
+
atStart = false;
|
|
284
|
+
}
|
|
285
|
+
} else if (delta < 0) {
|
|
286
|
+
if (prev.selected > 1) {
|
|
287
|
+
selected = prev.selected - 1;
|
|
288
|
+
shiftBy = 0;
|
|
289
|
+
} else if (c > 1) {
|
|
290
|
+
start = Math.max(0, c - 1);
|
|
291
|
+
selected = 1;
|
|
292
|
+
} else if (c === 1) {
|
|
293
|
+
start = 0;
|
|
294
|
+
selected = 1;
|
|
295
|
+
} else {
|
|
296
|
+
start = 0;
|
|
297
|
+
selected = 0;
|
|
298
|
+
shiftBy = atStart ? 0 : shiftBy;
|
|
299
|
+
atStart = true;
|
|
268
300
|
}
|
|
269
301
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
case 'none':
|
|
273
|
-
default:
|
|
274
|
-
start = 0;
|
|
275
|
-
selected = c;
|
|
276
|
-
shiftBy = 0;
|
|
277
|
-
break;
|
|
278
|
-
}
|
|
302
|
+
}
|
|
303
|
+
break;
|
|
279
304
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
: items().slice(start, start + length);
|
|
288
|
-
}
|
|
305
|
+
case 'none':
|
|
306
|
+
default:
|
|
307
|
+
start = 0;
|
|
308
|
+
selected = c;
|
|
309
|
+
shiftBy = 0;
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
289
312
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
slice: state.slice,
|
|
300
|
-
});
|
|
301
|
-
}
|
|
313
|
+
let newSlice = prev.slice;
|
|
314
|
+
if (start !== prev.start || newSlice.length === 0) {
|
|
315
|
+
newSlice = props.wrap
|
|
316
|
+
? (Array.from(
|
|
317
|
+
{ length },
|
|
318
|
+
(_, i) => items()[utils.mod(start + i, total)],
|
|
319
|
+
) as T[])
|
|
320
|
+
: items().slice(start, start + length);
|
|
321
|
+
}
|
|
302
322
|
|
|
303
|
-
|
|
323
|
+
const state: SliceState = {
|
|
324
|
+
start,
|
|
325
|
+
slice: newSlice,
|
|
326
|
+
selected,
|
|
327
|
+
delta,
|
|
328
|
+
shiftBy,
|
|
329
|
+
atStart,
|
|
330
|
+
cursor: c,
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
if (props.debugInfo) {
|
|
334
|
+
console.log(`[Virtual]`, {
|
|
335
|
+
cursor: c,
|
|
336
|
+
delta,
|
|
337
|
+
start,
|
|
338
|
+
selected,
|
|
339
|
+
shiftBy,
|
|
340
|
+
slice: state.slice,
|
|
341
|
+
});
|
|
304
342
|
}
|
|
305
343
|
|
|
344
|
+
return state;
|
|
345
|
+
}
|
|
346
|
+
|
|
306
347
|
let viewRef!: lngp.NavigableElement;
|
|
307
348
|
|
|
308
349
|
function scrollToIndex(this: lng.ElementNode, index: number) {
|
|
@@ -334,7 +375,12 @@ function createVirtual<T>(
|
|
|
334
375
|
}
|
|
335
376
|
|
|
336
377
|
let originalPosition: number | undefined;
|
|
337
|
-
const onSelectedChanged: lngp.OnSelectedChanged = function (
|
|
378
|
+
const onSelectedChanged: lngp.OnSelectedChanged = function (
|
|
379
|
+
_idx,
|
|
380
|
+
elm,
|
|
381
|
+
_active,
|
|
382
|
+
_lastIdx,
|
|
383
|
+
) {
|
|
338
384
|
let idx = _idx;
|
|
339
385
|
let lastIdx = _lastIdx || 0;
|
|
340
386
|
let active = _active;
|
|
@@ -343,19 +389,24 @@ function createVirtual<T>(
|
|
|
343
389
|
originalPosition = originalPosition ?? elm[axis];
|
|
344
390
|
|
|
345
391
|
if (props.onSelectedChanged) {
|
|
346
|
-
props.onSelectedChanged.call(
|
|
392
|
+
props.onSelectedChanged.call(
|
|
393
|
+
this as lngp.NavigableElement,
|
|
394
|
+
idx,
|
|
395
|
+
this as lngp.NavigableElement,
|
|
396
|
+
active,
|
|
397
|
+
lastIdx,
|
|
398
|
+
);
|
|
347
399
|
}
|
|
348
400
|
|
|
349
401
|
if (noChange) return;
|
|
350
402
|
|
|
351
403
|
const rawDelta = idx - (lastIdx ?? 0);
|
|
352
|
-
const windowLen =
|
|
353
|
-
elm?.children?.length ?? props.displaySize + bufferSize();
|
|
404
|
+
const windowLen = elm?.children?.length ?? props.displaySize + bufferSize();
|
|
354
405
|
const delta = props.wrap
|
|
355
|
-
|
|
356
|
-
|
|
406
|
+
? normalizeDeltaForWindow(rawDelta, windowLen)
|
|
407
|
+
: rawDelta;
|
|
357
408
|
|
|
358
|
-
setCursor(c => {
|
|
409
|
+
setCursor((c) => {
|
|
359
410
|
const next = c + delta;
|
|
360
411
|
return props.wrap
|
|
361
412
|
? utils.mod(next, total)
|
|
@@ -381,19 +432,25 @@ function createVirtual<T>(
|
|
|
381
432
|
elm.updateLayout();
|
|
382
433
|
const childSize = computeSize(slice().selected);
|
|
383
434
|
|
|
384
|
-
if (
|
|
385
|
-
cachedAnimationController
|
|
435
|
+
if (
|
|
436
|
+
cachedAnimationController &&
|
|
437
|
+
cachedAnimationController.state === 'running'
|
|
438
|
+
) {
|
|
439
|
+
cachedAnimationController.stop();
|
|
386
440
|
}
|
|
387
441
|
|
|
388
442
|
if (lng.Config.animationsEnabled) {
|
|
389
443
|
this.lng[axis] = prevChildPos - active[axis];
|
|
390
|
-
targetPosition = this.lng[axis] +
|
|
444
|
+
targetPosition = this.lng[axis] + childSize * slice().shiftBy;
|
|
391
445
|
cachedAnimationController = this.animate(
|
|
392
446
|
{ [axis]: targetPosition },
|
|
393
|
-
{
|
|
447
|
+
{
|
|
448
|
+
...this.animationSettings,
|
|
449
|
+
duration: getAdaptiveDuration(this.animationSettings?.duration),
|
|
450
|
+
},
|
|
394
451
|
).start();
|
|
395
452
|
} else {
|
|
396
|
-
this.lng[axis] = this.lng[axis]! +
|
|
453
|
+
this.lng[axis] = this.lng[axis]! + childSize * slice().shiftBy;
|
|
397
454
|
}
|
|
398
455
|
});
|
|
399
456
|
};
|
|
@@ -407,7 +464,7 @@ function createVirtual<T>(
|
|
|
407
464
|
|
|
408
465
|
queueMicrotask(() => {
|
|
409
466
|
viewRef.updateLayout();
|
|
410
|
-
let activeIndex = viewRef.children.findIndex(x => x.item === item);
|
|
467
|
+
let activeIndex = viewRef.children.findIndex((x) => x.item === item);
|
|
411
468
|
if (activeIndex === -1) return;
|
|
412
469
|
viewRef.selected = activeIndex;
|
|
413
470
|
if (lng.hasFocus(viewRef)) {
|
|
@@ -421,60 +478,72 @@ function createVirtual<T>(
|
|
|
421
478
|
originalPosition = originalPosition ?? viewRef.lng[axis];
|
|
422
479
|
targetPosition = targetPosition ?? viewRef.lng[axis];
|
|
423
480
|
|
|
424
|
-
viewRef.lng[axis] = (viewRef.lng[axis] || 0) +
|
|
481
|
+
viewRef.lng[axis] = (viewRef.lng[axis] || 0) + childSize * -1;
|
|
425
482
|
});
|
|
426
483
|
};
|
|
427
484
|
|
|
428
485
|
let doOnce = false;
|
|
429
|
-
s.createEffect(
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
486
|
+
s.createEffect(
|
|
487
|
+
s.on([() => props.wrap, items], () => {
|
|
488
|
+
if (!viewRef || itemCount() === 0 || !props.wrap || doOnce) return;
|
|
489
|
+
doOnce = true;
|
|
490
|
+
// offset just for wrap so we keep one item before
|
|
491
|
+
queueMicrotask(() => {
|
|
492
|
+
const childSize = computeSize(slice().selected);
|
|
493
|
+
viewRef.lng[axis] = (viewRef.lng[axis] || 0) + childSize * -1;
|
|
494
|
+
// Original Position is offset to support scrollToIndex
|
|
495
|
+
originalPosition = viewRef.lng[axis];
|
|
496
|
+
targetPosition = viewRef.lng[axis];
|
|
497
|
+
});
|
|
498
|
+
}),
|
|
499
|
+
);
|
|
441
500
|
|
|
442
501
|
s.createEffect(s.on([() => props.selected, items], updateSelected));
|
|
443
502
|
|
|
444
|
-
s.createEffect(
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
503
|
+
s.createEffect(
|
|
504
|
+
s.on(items, () => {
|
|
505
|
+
if (!viewRef) return;
|
|
506
|
+
if (cursor() >= itemCount()) {
|
|
507
|
+
setCursor(Math.max(0, itemCount() - 1));
|
|
508
|
+
}
|
|
509
|
+
const newState = computeSlice(cursor(), 0, slice());
|
|
510
|
+
setSlice(newState);
|
|
511
|
+
viewRef.selected = newState.selected;
|
|
512
|
+
}),
|
|
513
|
+
);
|
|
453
514
|
|
|
454
|
-
return (
|
|
515
|
+
return (
|
|
516
|
+
<view
|
|
517
|
+
transition={/* @once */ {}}
|
|
518
|
+
transitionLeft={isRow ? defaultTransitionBack : undefined}
|
|
519
|
+
transitionRight={isRow ? defaultTransitionForward : undefined}
|
|
520
|
+
transitionUp={!isRow ? defaultTransitionUp : undefined}
|
|
521
|
+
transitionDown={!isRow ? defaultTransitionDown : undefined}
|
|
455
522
|
{...props}
|
|
456
523
|
{...keyHandlers}
|
|
457
|
-
ref={lngp.chainRefs(el => {
|
|
524
|
+
ref={lngp.chainRefs((el) => {
|
|
525
|
+
viewRef = el as lngp.NavigableElement;
|
|
526
|
+
}, props.ref)}
|
|
458
527
|
selected={selected()}
|
|
459
528
|
cursor={cursor()}
|
|
460
529
|
forwardFocus={/* @once */ lngp.navigableForwardFocus}
|
|
461
530
|
scrollToIndex={/* @once */ scrollToIndex}
|
|
462
531
|
onSelectedChanged={/* @once */ onSelectedChanged}
|
|
463
|
-
style={
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
532
|
+
style={
|
|
533
|
+
/* @once */ lng.combineStyles(
|
|
534
|
+
props.style,
|
|
535
|
+
component === lngp.Row
|
|
536
|
+
? {
|
|
537
|
+
display: 'flex',
|
|
538
|
+
gap: 30,
|
|
539
|
+
}
|
|
540
|
+
: {
|
|
541
|
+
display: 'flex',
|
|
542
|
+
flexDirection: 'column',
|
|
543
|
+
gap: 30,
|
|
544
|
+
},
|
|
545
|
+
)
|
|
546
|
+
}
|
|
478
547
|
>
|
|
479
548
|
<List each={slice().slice}>{props.children}</List>
|
|
480
549
|
</view>
|
|
@@ -483,14 +552,26 @@ function createVirtual<T>(
|
|
|
483
552
|
|
|
484
553
|
export function VirtualRow<T>(props: VirtualProps<T>) {
|
|
485
554
|
return createVirtual(lngp.Row, props, {
|
|
486
|
-
onLeft: lngp.chainFunctions(
|
|
487
|
-
|
|
555
|
+
onLeft: lngp.chainFunctions(
|
|
556
|
+
props.onLeft,
|
|
557
|
+
lngp.handleNavigation('left'),
|
|
558
|
+
) as lng.KeyHandler,
|
|
559
|
+
onRight: lngp.chainFunctions(
|
|
560
|
+
props.onRight,
|
|
561
|
+
lngp.handleNavigation('right'),
|
|
562
|
+
) as lng.KeyHandler,
|
|
488
563
|
});
|
|
489
564
|
}
|
|
490
565
|
|
|
491
566
|
export function VirtualColumn<T>(props: VirtualProps<T>) {
|
|
492
567
|
return createVirtual(lngp.Column, props, {
|
|
493
|
-
onUp: lngp.chainFunctions(
|
|
494
|
-
|
|
568
|
+
onUp: lngp.chainFunctions(
|
|
569
|
+
props.onUp,
|
|
570
|
+
lngp.handleNavigation('up'),
|
|
571
|
+
) as lng.KeyHandler,
|
|
572
|
+
onDown: lngp.chainFunctions(
|
|
573
|
+
props.onDown,
|
|
574
|
+
lngp.handleNavigation('down'),
|
|
575
|
+
) as lng.KeyHandler,
|
|
495
576
|
});
|
|
496
577
|
}
|