@lightningtv/solid 2.10.0 → 2.10.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.
@@ -1,140 +0,0 @@
1
- import * as s from 'solid-js';
2
- import * as lng from '@lightningtv/solid';
3
- import * as lngp from '@lightningtv/solid/primitives';
4
- import { List } from '@solid-primitives/list';
5
- import * as utils from '../utils.js';
6
-
7
- const rowOnLeft = lngp.handleNavigation('left');
8
- const rowOnRight = lngp.handleNavigation('right');
9
- const rowScroll = lngp.withScrolling(true);
10
-
11
- const rowStyles: lng.NodeStyles = {
12
- display: 'flex',
13
- gap: 30,
14
- transition: {
15
- x: {
16
- duration: 250,
17
- easing: 'ease-out',
18
- },
19
- },
20
- };
21
-
22
- function scrollToIndex(this: lng.ElementNode, index: number) {
23
- this.selected = index;
24
- rowScroll(index, this);
25
- this.setFocus();
26
- }
27
-
28
- export type VirtualListProps<T> = lng.NewOmit<lngp.RowProps, 'children'> & {
29
- each: readonly T[] | undefined | null | false;
30
- displaySize: number;
31
- bufferSize?: number;
32
- fallback?: s.JSX.Element;
33
- children: (item: s.Accessor<T>, index: s.Accessor<number>) => s.JSX.Element;
34
- };
35
-
36
- export function VirtualList<T>(props: VirtualListProps<T>): s.JSX.Element {
37
-
38
- const [ cursor, setCursor ] = s.createSignal(props.selected ?? 0);
39
-
40
- const bufferSize = () => props.bufferSize ?? 2;
41
-
42
- const items = s.createMemo(() => props.each || []);
43
-
44
- const start = () =>
45
- utils.clamp(cursor() - bufferSize(), 0, Math.max(0, items().length - props.displaySize - bufferSize()));
46
-
47
- const end = () =>
48
- Math.min(items().length, cursor() + props.displaySize + bufferSize());
49
-
50
- const [ slice, setSlice ] = s.createSignal(items().slice(start(), end()));
51
-
52
- s.createEffect(s.on([ () => props.selected, items ], ([selected]) => {
53
- if (!viewRef || !selected) return;
54
-
55
- const item = items()![selected];
56
- let active = viewRef.children.find(x => x.item === item);
57
- const lastSelected = viewRef.selected;
58
-
59
- if (active instanceof lng.ElementNode) {
60
- viewRef.selected = viewRef.children.indexOf(active);
61
- chainedOnSelectedChanged.call(viewRef, viewRef.selected, viewRef, active, lastSelected);
62
- }
63
- else {
64
- setCursor(selected);
65
- setSlice(items().slice(start(), end()));
66
- queueMicrotask(() => {
67
- viewRef.updateLayout();
68
- active = viewRef.children.find(x => x.item === item);
69
- if (active instanceof lng.ElementNode) {
70
- viewRef.selected = viewRef.children.indexOf(active);
71
- chainedOnSelectedChanged.call(viewRef, viewRef.selected, viewRef, active, lastSelected);
72
- }
73
- });
74
- }
75
- }));
76
-
77
- s.createEffect(s.on(items, () => {
78
- if (!viewRef) return;
79
- setSlice(items().slice(start(), end()));
80
- }, { defer: true }));
81
-
82
- const onSelectedChanged: lngp.OnSelectedChanged = function (
83
- _idx, elm, active, _lastIdx,
84
- ) {
85
- let idx = _idx;
86
- let lastIdx = _lastIdx;
87
-
88
- if (idx === lastIdx) return;
89
-
90
- const prevChildX = this.x + active.x;
91
- const prevStart = start();
92
-
93
- // Update the displayed slice of items
94
- setCursor(prevStart + idx);
95
- setSlice(items().slice(start(), end()));
96
-
97
- // this.selected is relative to the slice
98
- // and it doesn't get corrected automatically after children change
99
- const idxCorrection = prevStart - start();
100
- if (lastIdx) lastIdx += idxCorrection;
101
- idx += idxCorrection;
102
- this.selected += idxCorrection;
103
-
104
- // Microtask & this.updateLayout() to make sure the child position is recalculated
105
- queueMicrotask(() => {
106
- this.updateLayout();
107
-
108
- // Correct this.x for changes to children, bypass animation
109
- this.lng.x = prevChildX - active.x;
110
-
111
- // smoothly scroll to new selected element
112
- rowScroll(idx, elm, active, lastIdx);
113
- });
114
- };
115
-
116
- const chainedOnSelectedChanged = lngp.chainFunctions(props.onSelectedChanged, onSelectedChanged)!;
117
-
118
- let viewRef!: lngp.NavigableElement;
119
- return <>
120
- <view
121
- {...props}
122
- scroll='always' // only supporting always scroll at the moment
123
- ref={lngp.chainRefs(el => { viewRef = el as lngp.NavigableElement; }, props.ref)}
124
- selected={props.selected || 0}
125
- cursor={cursor()}
126
- onLeft={/* @once */ lngp.chainFunctions(props.onLeft, rowOnLeft)}
127
- onRight={/* @once */ lngp.chainFunctions(props.onRight, rowOnRight)}
128
- forwardFocus={/* @once */ lngp.navigableForwardFocus}
129
- scrollToIndex={scrollToIndex}
130
- onCreate={/* @once */
131
- props.selected ? lngp.chainFunctions(props.onCreate, rowScroll) : props.onCreate
132
- }
133
- /* lngp.NavigableElement.onSelectedChanged is used by lngp.handleNavigation */
134
- onSelectedChanged={chainedOnSelectedChanged}
135
- style={/* @once */ lng.combineStyles(props.style, rowStyles)}
136
- >
137
- <List each={slice()}>{props.children}</List>
138
- </view>
139
- </>;
140
- }