Checkpoint Layout.List

This commit is contained in:
Eric Bailey
2025-09-24 11:05:01 -05:00
parent e44a022226
commit 391a1d4be3
3 changed files with 59 additions and 87 deletions
+17
View File
@@ -23,6 +23,11 @@ import {
import {useDialogContext} from '#/components/Dialog' import {useDialogContext} from '#/components/Dialog'
import {CENTER_COLUMN_OFFSET, SCROLLBAR_OFFSET} from '#/components/Layout/const' import {CENTER_COLUMN_OFFSET, SCROLLBAR_OFFSET} from '#/components/Layout/const'
import {ScrollbarOffsetContext} from '#/components/Layout/context' import {ScrollbarOffsetContext} from '#/components/Layout/context'
import {
List as BaseList,
type ListItem,
type ListProps,
} from '#/components/List'
export * from '#/components/Layout/const' export * from '#/components/Layout/const'
export * as Header from '#/components/Layout/Header' export * as Header from '#/components/Layout/Header'
@@ -223,3 +228,15 @@ const WebCenterBorders = memo(function LayoutWebCenterBorders() {
/> />
) : null ) : null
}) })
export function List<Item extends ListItem>(props: ListProps<Item>) {
return (
<BaseList<Item>
{...props}
renderItem={item => {
return <Center>{props.renderItem!(item)}</Center>
}}
style={[a.h_full_vh, props.style]}
/>
)
}
+4 -2
View File
@@ -27,7 +27,9 @@ export {
export type ListRef<Item extends {key: string}> = export type ListRef<Item extends {key: string}> =
React.MutableRefObject<FlatList<Item> | null> React.MutableRefObject<FlatList<Item> | null>
type ListProps<Item extends {key: string}> = Omit< export type ListItem = {key: string}
export type ListProps<Item extends ListItem> = Omit<
FlatListProps<Item>, FlatListProps<Item>,
| 'onScroll' | 'onScroll'
| 'onScrollBeginDrag' | 'onScrollBeginDrag'
@@ -87,7 +89,7 @@ type ListProps<Item extends {key: string}> = Omit<
onScrolledDownChange?: (isScrolledDown: boolean) => void onScrolledDownChange?: (isScrolledDown: boolean) => void
} }
export const List = forwardRef(function List<Item extends {key: string}>( export const List = forwardRef(function List<Item extends ListItem>(
{...props}: ListProps<Item>, {...props}: ListProps<Item>,
ref: React.Ref<FlatList<Item>>, ref: React.Ref<FlatList<Item>>,
) { ) {
+38 -85
View File
@@ -1,13 +1,9 @@
import {useState} from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {runOnJS} from 'react-native-reanimated' import {runOnJS} from 'react-native-reanimated'
import {ScrollProvider} from '#/lib/ScrollContext'
import {List as OldList} from '#/view/com/util/List'
import {atoms as a, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {List, ListScrollProvider, useListScrollHandler} from '#/components/List' import {ListScrollProvider, useListScrollHandler} from '#/components/List'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
export function StorybookLists() { export function StorybookLists() {
@@ -36,21 +32,8 @@ type Item =
const log = (msg: any) => console.log(msg) const log = (msg: any) => console.log(msg)
function Header() {
return (
<Layout.Header.Outer>
<Layout.Header.BackButton />
<Layout.Header.Content>
<Layout.Header.TitleText>Storybook</Layout.Header.TitleText>
</Layout.Header.Content>
<Layout.Header.Slot />
</Layout.Header.Outer>
)
}
export function Inner() { export function Inner() {
const t = useTheme() const t = useTheme()
const [old, setOld] = useState<boolean>(false)
const onScrollWorklet = useListScrollHandler(e => { const onScrollWorklet = useListScrollHandler(e => {
'worklet' 'worklet'
runOnJS(log)(`scroll ${e.contentOffset.y}`) runOnJS(log)(`scroll ${e.contentOffset.y}`)
@@ -74,73 +57,43 @@ export function Inner() {
}) })
return ( return (
<View style={[]}> <ListScrollProvider onScroll={onScrollWorklet}>
<View <Layout.List<Item>
style={[a.fixed, a.w_full, a.py_sm, a.px_xl, a.align_center, a.z_10]}> data={items}
<Button stickyHeaderIndices={[1]}
label="Toggle Old/New List" renderItem={({item, index}) => {
onPress={() => setOld(v => !v)} if (item.type === 'header') {
size="tiny" return (
color="primary_subtle"> <Layout.Header.Outer>
<ButtonText> <Layout.Header.BackButton />
{old ? 'Testing old List' : 'Testing new List'} <Layout.Header.Content>
</ButtonText> <Layout.Header.TitleText>Storybook</Layout.Header.TitleText>
</Button> </Layout.Header.Content>
</View> <Layout.Header.Slot />
</Layout.Header.Outer>
)
}
if (item.type === 'spacer') {
return <View style={[t.atoms.bg_contrast_50, {height: 100}]} />
}
{!old ? ( return (
<ListScrollProvider onScroll={onScrollWorklet}> <View
<List<Item> style={[
data={items} a.px_md,
onScrolledDownChange={scrolledDown => { a.align_center,
console.log(`Scrolled down: ${scrolledDown}`) a.justify_center,
}} {height: 100},
stickyHeaderIndices={[1]} index % 2 === 0 ? t.atoms.bg_contrast_25 : t.atoms.bg,
renderItem={({item, index}) => { ]}>
if (item.type === 'header') { <Text>{item.title}</Text>
return <Header /> </View>
} )
if (item.type === 'spacer') { }}
return <View style={[t.atoms.bg_contrast_50, {height: 100}]} /> onScrolledDownChange={scrolledDown => {
} console.log(`Scrolled down: ${scrolledDown}`)
}}
return ( />
<Layout.Center> </ListScrollProvider>
<View
style={[
a.px_md,
a.align_center,
a.justify_center,
{height: 100},
index % 2 === 0 ? t.atoms.bg_contrast_25 : t.atoms.bg,
]}>
<Text>{item.title}</Text>
</View>
</Layout.Center>
)
}}
style={[a.h_full_vh]}
/>
</ListScrollProvider>
) : (
<ScrollProvider onScroll={onScrollWorklet}>
<OldList
data={items}
keyExtractor={item => item.key}
headerOffset={100}
onScrolledDownChange={scrolledDown => {
console.log(`Scrolled down: ${scrolledDown}`)
}}
renderItem={({item}) => (
<View style={[a.p_md, a.border_b]}>
<Text>{item.title}</Text>
</View>
)}
style={[a.debug]}
desktopFixedHeight
/>
</ScrollProvider>
)}
</View>
) )
} }