@codeleap/web 3.3.2 → 3.5.0

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.
Files changed (59) hide show
  1. package/package.json +3 -1
  2. package/src/components/ActionIcon/index.tsx +49 -30
  3. package/src/components/ActionIcon/styles.ts +8 -5
  4. package/src/components/ActivityIndicator/index.tsx +6 -5
  5. package/src/components/Badge/index.tsx +135 -0
  6. package/src/components/Badge/styles.ts +15 -0
  7. package/src/components/Button/index.tsx +79 -69
  8. package/src/components/Button/styles.ts +10 -14
  9. package/src/components/Checkbox/index.tsx +9 -3
  10. package/src/components/Collapse/index.tsx +6 -3
  11. package/src/components/Drawer/index.tsx +72 -44
  12. package/src/components/Drawer/styles.ts +11 -3
  13. package/src/components/EmptyPlaceholder/index.tsx +135 -0
  14. package/src/components/EmptyPlaceholder/styles.ts +16 -0
  15. package/src/components/Grid/index.tsx +169 -0
  16. package/src/components/Grid/styles.ts +10 -0
  17. package/src/components/Grid/types.ts +24 -0
  18. package/src/components/Icon/index.tsx +7 -4
  19. package/src/components/InputBase/styles.ts +8 -56
  20. package/src/components/InputBase/utils.ts +63 -0
  21. package/src/components/List/ListLayout.tsx +98 -0
  22. package/src/components/List/PaginationIndicator.tsx +102 -0
  23. package/src/components/List/index.tsx +104 -91
  24. package/src/components/List/styles.ts +17 -5
  25. package/src/components/List/types.ts +51 -0
  26. package/src/components/List/useInfiniteScroll.ts +113 -0
  27. package/src/components/LoadingOverlay/index.tsx +5 -3
  28. package/src/components/Modal/index.tsx +30 -29
  29. package/src/components/NumberIncrement/index.tsx +3 -2
  30. package/src/components/Overlay/index.tsx +12 -2
  31. package/src/components/Pager/index.tsx +5 -1
  32. package/src/components/RadioInput/index.tsx +4 -3
  33. package/src/components/SearchInput/index.tsx +93 -0
  34. package/src/components/SegmentedControl/SegmentedControlOption.tsx +15 -9
  35. package/src/components/SegmentedControl/index.tsx +12 -5
  36. package/src/components/Select/index.tsx +18 -14
  37. package/src/components/Select/styles.ts +4 -3
  38. package/src/components/Select/types.ts +4 -3
  39. package/src/components/Slider/index.tsx +3 -2
  40. package/src/components/Switch/index.tsx +4 -2
  41. package/src/components/Text/index.tsx +98 -25
  42. package/src/components/Text/styles.ts +4 -4
  43. package/src/components/TextInput/index.tsx +6 -15
  44. package/src/components/Tooltip/index.tsx +163 -131
  45. package/src/components/Tooltip/styles.ts +13 -9
  46. package/src/components/Touchable/index.tsx +88 -26
  47. package/src/components/Touchable/styles.ts +4 -6
  48. package/src/components/View/index.tsx +1 -1
  49. package/src/components/components.ts +5 -1
  50. package/src/components/defaultStyles.ts +10 -3
  51. package/src/index.ts +2 -0
  52. package/src/lib/hooks.ts +27 -13
  53. package/src/lib/index.ts +4 -1
  54. package/src/lib/useBreakpointMatch.ts +33 -0
  55. package/src/lib/usePopState.ts +30 -0
  56. package/src/lib/useSearchParams.ts +54 -0
  57. package/src/lib/utils/stopPropagation.ts +3 -3
  58. package/src/types/index.ts +1 -1
  59. package/src/types/utility.ts +4 -0
@@ -1,6 +1,7 @@
1
- import { TypeGuards, createDefaultVariantFactory, getRenderedComponent, includePresets, useDefaultComponentStyle, useMemo, useNestedStylesByKey } from '@codeleap/common'
1
+ import { TypeGuards, createDefaultVariantFactory, includePresets, useDefaultComponentStyle, useNestedStylesByKey } from '@codeleap/common'
2
2
  import { ActionIconComposition, ActionIconParts } from '../ActionIcon'
3
3
  import { InputBaseProps } from './types'
4
+ import { concatStyles, getIconStyles, iconStylesOf } from './utils'
4
5
 
5
6
  type InputIcons = 'icon' | 'leftIcon' | 'rightIcon'
6
7
 
@@ -27,38 +28,6 @@ const createTextInputBaseComposition = createDefaultVariantFactory<InputBaseComp
27
28
 
28
29
  export const InputBasePresets = includePresets((styles) => createTextInputBaseComposition(() => ({ wrapper: styles })))
29
30
 
30
- const getIconStyles = (obj, state) => {
31
- return {
32
- icon: {
33
- ...obj.icon,
34
- ...(state.focused && obj['icon:focus']),
35
- ...(state.hasError && obj['icon:error']),
36
- ...(state.disabled && obj['icon:disabled']),
37
- },
38
- wrapper: {
39
- ...obj.touchableWrapper,
40
- ...(state.focused && obj['touchableWrapper:focus']),
41
- ...(state.hasError && obj['touchableWrapper:error']),
42
- ...(state.disabled && obj['touchableWrapper:disabled']),
43
- },
44
- }
45
- }
46
-
47
- export function concatStyles(unstyles: Record<number, {}> = {}) {
48
- let styles = {}
49
-
50
- Object.values(unstyles || {}).forEach(style => {
51
- if (style) {
52
- styles = {
53
- ...styles,
54
- ...style,
55
- }
56
- }
57
- })
58
-
59
- return styles
60
- }
61
-
62
31
  export const useInputBaseStyles = (props: InputBaseProps) => {
63
32
  const {
64
33
  focused,
@@ -76,41 +45,24 @@ export const useInputBaseStyles = (props: InputBaseProps) => {
76
45
 
77
46
  const _leftIconStyles = useNestedStylesByKey<ActionIconComposition>('leftIcon', variantStyles)
78
47
  const _rightIconStyles = useNestedStylesByKey<ActionIconComposition>('rightIcon', variantStyles)
79
- const _generalIconStyles = useNestedStylesByKey<ActionIconComposition>('icon', variantStyles)
48
+ const _baseIconStyles = useNestedStylesByKey<ActionIconComposition>('icon', variantStyles)
49
+
50
+ const baseIconStyles = getIconStyles(_baseIconStyles, { hasError, disabled, focused })
80
51
 
81
- const generalIconStyles = getIconStyles(_generalIconStyles, { hasError, disabled, focused })
82
52
  const leftIconStylesCompose = getIconStyles(_leftIconStyles, {
83
53
  hasError,
84
54
  disabled: disabled || props?.leftIcon?.disabled,
85
55
  focused
86
56
  })
57
+
87
58
  const rightIconStylesCompose = getIconStyles(_rightIconStyles, {
88
59
  hasError,
89
60
  disabled: disabled || props?.rightIcon?.disabled,
90
61
  focused
91
62
  })
92
63
 
93
- const leftIconStyles = {
94
- icon: {
95
- ...generalIconStyles.icon,
96
- ...leftIconStylesCompose.icon,
97
- },
98
- wrapper: {
99
- ...generalIconStyles.wrapper,
100
- ...leftIconStylesCompose.wrapper,
101
- },
102
- }
103
-
104
- const rightIconStyles = {
105
- icon: {
106
- ...generalIconStyles.icon,
107
- ...rightIconStylesCompose.icon,
108
- },
109
- wrapper: {
110
- ...generalIconStyles.wrapper,
111
- ...rightIconStylesCompose.wrapper,
112
- },
113
- }
64
+ const leftIconStyles = iconStylesOf(baseIconStyles, leftIconStylesCompose)
65
+ const rightIconStyles = iconStylesOf(baseIconStyles, rightIconStylesCompose)
114
66
 
115
67
  const labelStyle = [
116
68
  variantStyles.label,
@@ -1,3 +1,5 @@
1
+ import { StylesOf } from '@codeleap/common'
2
+ import { ActionIconComposition } from '../ActionIcon'
1
3
  import { InputBaseProps } from './types'
2
4
 
3
5
  type OmitDiff<T1, T2> = {
@@ -39,3 +41,64 @@ export function selectInputBaseProps<T extends InputBaseProps>(props: T): {
39
41
 
40
42
  return { inputBaseProps: result, others: copy as OmitDiff<T, T> }
41
43
  }
44
+
45
+ type IconStyles = StylesOf<ActionIconComposition>
46
+
47
+ type IconState = {
48
+ focused: boolean
49
+ hasError: boolean
50
+ disabled: boolean
51
+ }
52
+
53
+ export const getIconStyles = (obj: IconStyles, state: IconState) => ({
54
+ icon: {
55
+ ...obj.icon,
56
+ ...(state.focused && obj['icon:focus']),
57
+ ...(state.hasError && obj['icon:error']),
58
+ },
59
+ 'icon:disabled': {
60
+ ...(state.disabled && obj['icon:disabled']),
61
+ },
62
+ touchableWrapper: {
63
+ ...obj.touchableWrapper,
64
+ ...(state.focused && obj['touchableWrapper:focus']),
65
+ ...(state.hasError && obj['touchableWrapper:error']),
66
+ },
67
+ 'touchableWrapper:disabled': {
68
+ ...(state.disabled && obj['touchableWrapper:disabled']),
69
+ },
70
+ })
71
+
72
+ export function concatStyles(unstyles: Record<number, {}> = {}) {
73
+ let styles = {}
74
+
75
+ Object.values(unstyles || {}).forEach(style => {
76
+ if (style) {
77
+ styles = {
78
+ ...styles,
79
+ ...style,
80
+ }
81
+ }
82
+ })
83
+
84
+ return styles
85
+ }
86
+
87
+ export const iconStylesOf = (baseStyles: IconStyles, styles: IconStyles) => ({
88
+ icon: {
89
+ ...baseStyles.icon,
90
+ ...styles.icon,
91
+ },
92
+ 'icon:disabled': {
93
+ ...baseStyles['icon:disabled'],
94
+ ...styles['icon:disabled'],
95
+ },
96
+ touchableWrapper: {
97
+ ...baseStyles.touchableWrapper,
98
+ ...styles.touchableWrapper,
99
+ },
100
+ 'touchableWrapper:disabled': {
101
+ ...baseStyles['touchableWrapper:disabled'],
102
+ ...styles['touchableWrapper:disabled'],
103
+ }
104
+ })
@@ -0,0 +1,98 @@
1
+ import React from 'react'
2
+ import { StylesOf, TypeGuards, useCodeleapContext } from '@codeleap/common'
3
+ import { ListComposition, ListParts } from './styles'
4
+ import { ListProps } from './types'
5
+ import { View } from '../View'
6
+ import { UseInfiniteScrollReturn } from './useInfiniteScroll'
7
+ import { ActivityIndicator } from '../ActivityIndicator'
8
+ import { motion } from 'framer-motion'
9
+
10
+ type ListLayoutProps = Omit<ListProps, 'renderItem'> & UseInfiniteScrollReturn['layoutProps'] & {
11
+ variantStyles: StylesOf<ListComposition>
12
+ children?: React.ReactNode
13
+ }
14
+
15
+ export const ListLayout = (props: ListLayoutProps) => {
16
+ const {
17
+ ListEmptyComponent,
18
+ ListFooterComponent,
19
+ ListHeaderComponent,
20
+ ListRefreshControlComponent,
21
+ variantStyles,
22
+ isEmpty,
23
+ isLoading,
24
+ refreshPosition,
25
+ placeholder = {},
26
+ parentRef,
27
+ style,
28
+ dataVirtualizer,
29
+ refresh,
30
+ refreshing,
31
+ refreshControlProps,
32
+ refreshControlIndicatorProps = {},
33
+ refreshSize,
34
+ children,
35
+ ref,
36
+ debugName,
37
+ } = props
38
+
39
+ const { Theme } = useCodeleapContext()
40
+
41
+ const getKeyStyle = React.useCallback((key: ListParts) => {
42
+ return [
43
+ variantStyles[key],
44
+ isLoading && variantStyles[`${key}:loading`],
45
+ isEmpty && variantStyles[`${key}:empty`],
46
+ ]
47
+ }, [isLoading, isEmpty])
48
+
49
+ const _refreshPosition = React.useMemo(() => {
50
+ return Theme.spacing.value(refreshPosition)
51
+ }, [refreshPosition])
52
+
53
+ return (
54
+ // @ts-ignore
55
+ <View css={[getKeyStyle('wrapper'), style]}>
56
+ {!!ListHeaderComponent && <ListHeaderComponent />}
57
+
58
+ {isEmpty ? <ListEmptyComponent debugName={debugName} {...placeholder} /> : (
59
+ <View
60
+ ref={parentRef}
61
+ css={[getKeyStyle('innerWrapper')]}
62
+ >
63
+ <View
64
+ //@ts-ignore
65
+ ref={ref}
66
+ css={[
67
+ getKeyStyle('content'),
68
+ { height: dataVirtualizer.getTotalSize() }
69
+ ]}
70
+ >
71
+ {TypeGuards.isNil(ListRefreshControlComponent) && refresh ? (
72
+ <motion.div
73
+ css={[variantStyles?.refreshControl]}
74
+ initial={false}
75
+ animate={{
76
+ opacity: refreshing ? 1 : 0,
77
+ top: refreshing ? _refreshPosition : 0
78
+ }}
79
+ {...refreshControlProps}
80
+ >
81
+ <ActivityIndicator
82
+ debugName={debugName}
83
+ size={refreshSize}
84
+ style={variantStyles.refreshControlIndicator}
85
+ {...refreshControlIndicatorProps}
86
+ />
87
+ </motion.div>
88
+ ) : (<ListRefreshControlComponent /> ?? null)}
89
+
90
+ {children}
91
+ </View>
92
+ </View>
93
+ )}
94
+
95
+ {!!ListFooterComponent && <ListFooterComponent />}
96
+ </View>
97
+ )
98
+ }
@@ -0,0 +1,102 @@
1
+ import React from 'react'
2
+ import {
3
+ assignTextStyle,
4
+ ComponentVariants,
5
+ createDefaultVariantFactory,
6
+ getNestedStylesByKey,
7
+ includePresets,
8
+ StylesOf,
9
+ TypeGuards,
10
+ useDefaultComponentStyle,
11
+ } from '@codeleap/common'
12
+ import { ActivityIndicator, ActivityIndicatorComposition, ActivityIndicatorProps } from '../ActivityIndicator'
13
+ import { Text, TextProps } from '../Text'
14
+ import { View } from '../View'
15
+ import { ComponentCommonProps } from '../../types'
16
+
17
+ export type PaginationIndicatorComposition = 'text' | `loader${Capitalize<ActivityIndicatorComposition>}` | 'wrapper'
18
+
19
+ const createPaginationIndicatorStyle = createDefaultVariantFactory<PaginationIndicatorComposition>()
20
+
21
+ const presets = includePresets((style) => createPaginationIndicatorStyle(() => ({ loaderWrapper: style, text: style })))
22
+
23
+ export const PaginationIndicatorStyles = {
24
+ ...presets,
25
+ default: createPaginationIndicatorStyle((theme) => {
26
+ return {
27
+ wrapper: {
28
+ ...theme.presets.fullWidth,
29
+ ...theme.presets.center,
30
+ },
31
+ loaderWrapper: {
32
+ ...theme.presets.center,
33
+ ...theme.spacing.marginVertical(3),
34
+ },
35
+ text: {
36
+ ...assignTextStyle('h4')(theme).text,
37
+ ...theme.presets.textCenter,
38
+ ...theme.spacing.marginVertical(3),
39
+ ...theme.presets.fullWidth,
40
+ },
41
+ }
42
+ }),
43
+ }
44
+
45
+ export type PaginationIndicatorProps = {
46
+ isFetching?: boolean
47
+ noMoreItemsText: React.ReactChild
48
+ hasMore?: boolean
49
+ activityIndicator?: JSX.Element
50
+ styles?: StylesOf<PaginationIndicatorComposition>
51
+ style?: React.CSSProperties
52
+ indicatorProps?: Partial<ActivityIndicatorProps>
53
+ textProps?: Partial<TextProps<'p'>>
54
+ } & ComponentVariants<typeof PaginationIndicatorStyles> & ComponentCommonProps
55
+
56
+ const defaultProps: Partial<PaginationIndicatorProps> = {}
57
+
58
+ export const PaginationIndicator = (props: PaginationIndicatorProps) => {
59
+ const allProps = {
60
+ ...PaginationIndicator.defaultProps,
61
+ ...props,
62
+ }
63
+
64
+ const {
65
+ hasMore,
66
+ isFetching,
67
+ noMoreItemsText,
68
+ style,
69
+ activityIndicator,
70
+ styles = {},
71
+ responsiveVariants = {},
72
+ variants = [],
73
+ indicatorProps = {},
74
+ debugName,
75
+ } = allProps
76
+
77
+ const variantStyles = useDefaultComponentStyle<
78
+ 'u:PaginationIndicator',
79
+ typeof PaginationIndicatorStyles
80
+ >('u:PaginationIndicator', {
81
+ variants,
82
+ responsiveVariants,
83
+ styles,
84
+ })
85
+
86
+ const loaderStyles = getNestedStylesByKey('loader', variantStyles)
87
+
88
+ if (isFetching) {
89
+ return activityIndicator || <View css={[variantStyles.wrapper, style]}><ActivityIndicator debugName={debugName} {...indicatorProps} styles={loaderStyles}/></View>
90
+ }
91
+
92
+ if (!hasMore) {
93
+ if (TypeGuards.isString(noMoreItemsText) || TypeGuards.isNumber(noMoreItemsText)) {
94
+ return <Text debugName={debugName} css={[variantStyles.text, style]} text={noMoreItemsText.toString()}/>
95
+ }
96
+ return noMoreItemsText
97
+ }
98
+
99
+ return null
100
+ }
101
+
102
+ PaginationIndicator.defaultProps = defaultProps
@@ -1,106 +1,119 @@
1
- /** @jsx jsx */
2
- import { jsx } from '@emotion/react'
3
-
4
- import { VariableSizeList as VirtualList , VariableSizeListProps} from 'react-window'
5
- import { ComponentProps, CSSProperties, ReactElement } from 'react'
6
- import AutoSizer from 'react-virtualized-auto-sizer'
7
- import {
8
- ComponentVariants,
9
- useDefaultComponentStyle
10
- } from '@codeleap/common'
11
- import { StylesOf } from '../../types/utility'
12
- import { CSSObject } from '@emotion/react'
13
- import { ListComposition, ListPresets } from './styles'
14
-
15
- export type ListRender<T> = (itemProps: {
16
- item: T
17
- index: number
18
- style: CSSProperties
19
- }) => ReactElement
1
+ import React from 'react'
2
+ import { useDefaultComponentStyle, useCallback } from '@codeleap/common'
3
+ import { View, ViewProps } from '../View'
4
+ import { EmptyPlaceholder } from '../EmptyPlaceholder'
5
+ import { ListPresets } from './styles'
6
+ import { VirtualItem } from '@tanstack/react-virtual'
7
+ import { useInfiniteScroll } from './useInfiniteScroll'
8
+ import { ListProps } from './types'
9
+ import { ListLayout } from './ListLayout'
20
10
 
21
11
  export * from './styles'
12
+ export * from './PaginationIndicator'
13
+ export * from './useInfiniteScroll'
14
+ export * from './types'
15
+ export * from './ListLayout'
16
+
17
+ const RenderSeparator = (props: { separatorStyles: ViewProps<'div'>['css'] }) => {
18
+ return (
19
+ <View css={[props?.separatorStyles]}></View>
20
+ )
21
+ }
22
+
23
+ const defaultProps: Partial<ListProps> = {
24
+ ListFooterComponent: null,
25
+ ListHeaderComponent: null,
26
+ ListLoadingIndicatorComponent: null,
27
+ ListRefreshControlComponent: null,
28
+ ListEmptyComponent: EmptyPlaceholder,
29
+ ListSeparatorComponent: RenderSeparator,
30
+ refreshDebounce: 3000,
31
+ refreshSize: 40,
32
+ refreshThreshold: 1,
33
+ refreshPosition: 2,
34
+ refresh: true,
35
+ }
36
+
37
+ const ListCP = React.forwardRef<'div', ListProps>((flatListProps, ref) => {
38
+ const allProps = {
39
+ ...defaultProps,
40
+ ...flatListProps,
41
+ }
22
42
 
23
- export type ListProps<T> = {
24
- styles?: StylesOf<ListComposition>
25
- css?: CSSObject
26
- data: T[]
27
- getSize: (i: T, idx: number) => number
28
- renderItem: ListRender<T>
29
- } & Omit<
30
- VariableSizeListProps,
31
- | 'itemCount'
32
- | 'itemSize'
33
- | 'itemData'
34
- | 'itemHeight'
35
- | 'width'
36
- | 'height'
37
- | 'children'
38
- > &
39
- ComponentVariants<typeof ListPresets>
40
-
41
- export const List = <T extends unknown>(
42
- listProps: ListProps<T>,
43
- ) => {
44
43
  const {
45
- variants,
46
- responsiveVariants,
47
- styles,
44
+ variants = [],
45
+ responsiveVariants = {},
46
+ styles = {},
47
+ ListLoadingIndicatorComponent,
48
+ renderItem: RenderItem,
49
+ ListSeparatorComponent,
48
50
  data,
49
- getSize,
50
- renderItem: Item,
51
- ...viewProps
52
- } = listProps
51
+ separators,
52
+ } = allProps
53
53
 
54
- const variantStyles = useDefaultComponentStyle('View', {
54
+ const variantStyles = useDefaultComponentStyle<'u:List', typeof ListPresets>('u:List', {
55
55
  variants,
56
56
  responsiveVariants,
57
57
  styles,
58
58
  })
59
59
 
60
+ const {
61
+ items,
62
+ dataVirtualizer,
63
+ layoutProps,
64
+ } = useInfiniteScroll(allProps)
65
+
66
+ const separator = separators && <ListSeparatorComponent separatorStyles={variantStyles.separator} />
67
+
68
+ const renderItem = useCallback((_item: VirtualItem) => {
69
+ if (!RenderItem) return null
70
+
71
+ const showIndicator = (_item?.index > data?.length - 1) && !!ListLoadingIndicatorComponent
72
+
73
+ const listLength = data?.length || 0
74
+
75
+ const isFirst = _item?.index === 0
76
+ const isLast = _item?.index === listLength - 1
77
+
78
+ const isOnly = isFirst && isLast
79
+
80
+ const _itemProps = {
81
+ ..._item,
82
+ isOnly,
83
+ isLast,
84
+ isFirst,
85
+ item: data?.[_item?.index]
86
+ }
87
+
88
+ return (
89
+ <div
90
+ css={[variantStyles.itemWrapper]}
91
+ key={_item?.key}
92
+ data-index={_item?.index}
93
+ ref={dataVirtualizer?.measureElement}
94
+ >
95
+ {!isFirst && separator}
96
+ {showIndicator && <ListLoadingIndicatorComponent />}
97
+ {!!_itemProps?.item && <RenderItem {..._itemProps} />}
98
+ </div>
99
+ )
100
+ }, [RenderItem, data?.length, dataVirtualizer?.measureElement])
101
+
60
102
  return (
61
- // @ts-ignore
62
- <AutoSizer>
63
- {({ height, width }) => (
64
- // @ts-ignore
65
- <VirtualList
66
- height={height}
67
- width={width}
68
- itemCount={data.length}
69
- itemData={data}
70
- itemSize={(idx) => getSize(data[idx], idx)}
71
- css={variantStyles.wrapper}
72
- {...viewProps}
73
- >
74
- {({ style, index }) => (
75
- <Item item={data[index]} style={style} index={index} />
76
- )}
77
- </VirtualList>
78
- )}
79
- </AutoSizer>
103
+ <ListLayout
104
+ {...allProps}
105
+ {...layoutProps}
106
+ variantStyles={variantStyles} // @ts-ignore
107
+ ref={ref}
108
+ >
109
+ {/* Necessary for correct list render */}
110
+ <div css={[variantStyles.list, { transform: `translateY(${items?.[0]?.start}px)` }]}>
111
+ {items?.map((item) => renderItem(item))}
112
+ </div>
113
+ </ListLayout>
80
114
  )
115
+ })
81
116
 
82
- // return <View {...viewProps}>
83
- // {data.map((item, idx) => <Component item={item} idx={idx} key={idx}/>)}
84
- // </View>
85
- }
117
+ export type ListComponentType = <T extends any[] = any[]>(props: ListProps<T>) => React.ReactElement
86
118
 
87
- // const rowHeights = new Array(1000)
88
- // .fill(true)
89
- // .map(() => 25 + Math.round(Math.random() * 50));
90
-
91
- // const getItemSize = index => rowHeights[index];
92
-
93
- // const Row = ({ index, style }) => (
94
- // <div style={style}>Row {index}</div>
95
- // );
96
-
97
- // const Example = () => (
98
- // <List
99
- // height={150}
100
- // itemCount={1000}
101
- // itemSize={getItemSize}
102
- // width={300}
103
- // >
104
- // {Row}
105
- // </List>
106
- // );
119
+ export const List = ListCP as unknown as ListComponentType
@@ -1,8 +1,20 @@
1
- import { createDefaultVariantFactory, includePresets } from "@codeleap/common";
2
- import { ViewComposition } from "../View";
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
+ import { ViewComposition } from '../View'
3
3
 
4
- export type ListComposition = ViewComposition
4
+ type ListStates = 'empty' | 'loading'
5
5
 
6
- const createListStyles = createDefaultVariantFactory<ListComposition>()
6
+ export type ListParts =
7
+ ViewComposition |
8
+ 'innerWrapper' |
9
+ 'content' |
10
+ 'separator' |
11
+ 'itemWrapper' |
12
+ 'refreshControl' |
13
+ 'refreshControlIndicator' |
14
+ 'list'
7
15
 
8
- export const ListPresets = includePresets((styles) => createListStyles(() => ({ wrapper: styles })))
16
+ export type ListComposition = `${ListParts}:${ListStates}` | ListParts
17
+
18
+ const createListStyle = createDefaultVariantFactory<ListComposition>()
19
+
20
+ export const ListPresets = includePresets(style => createListStyle(() => ({ wrapper: style })))
@@ -0,0 +1,51 @@
1
+ import { ComponentVariants, PropsOf, StylesOf } from '@codeleap/common'
2
+ import { VirtualItem, VirtualizerOptions } from '@tanstack/react-virtual'
3
+ import { EmptyPlaceholderProps } from '../EmptyPlaceholder'
4
+ import { View, ViewProps } from '../View'
5
+ import { ListComposition, ListPresets } from './styles'
6
+ import { motion } from 'framer-motion'
7
+ import { ActivityIndicatorProps } from '../ActivityIndicator'
8
+ import { ComponentCommonProps } from '../../types'
9
+
10
+ export type AugmentedRenderItemInfo<T> = VirtualItem & {
11
+ item: T
12
+ isFirst: boolean
13
+ isLast: boolean
14
+ isOnly: boolean
15
+ }
16
+
17
+ export type ListProps<
18
+ T = any[],
19
+ Data = T extends Array<infer D> ? D : never
20
+ > =
21
+ ComponentVariants<typeof ListPresets> &
22
+ Omit<typeof View, 'variants' | 'styles'> & {
23
+ data: Data[]
24
+ isFetching?: boolean
25
+ hasNextPage?: boolean
26
+ separators?: boolean
27
+ onRefresh?: () => void
28
+ placeholder?: EmptyPlaceholderProps
29
+ styles?: StylesOf<ListComposition>
30
+ keyExtractor?: (item: T, index: number) => string
31
+ renderItem: (data: AugmentedRenderItemInfo<T>) => React.ReactElement
32
+ ListFooterComponent?: () => React.ReactElement
33
+ ListLoadingIndicatorComponent?: () => React.ReactElement
34
+ ListRefreshControlComponent?: () => React.ReactElement
35
+ ListEmptyComponent?: React.FC | ((props: EmptyPlaceholderProps) => React.ReactElement)
36
+ ListSeparatorComponent?: React.FC | ((props: { separatorStyles: ViewProps<'div'>['css'] }) => React.ReactElement)
37
+ isLoading?: boolean
38
+ isFetchingNextPage?: boolean
39
+ fetchNextPage?: () => void
40
+ ListHeaderComponent?: () => React.ReactElement
41
+ virtualizerOptions?: Partial<VirtualizerOptions<any, any>>
42
+ refreshDebounce?: number
43
+ refreshSize?: number
44
+ refreshThreshold?: number
45
+ refreshPosition?: number
46
+ refresh?: boolean
47
+ refreshControlProps?: PropsOf<typeof motion.div>
48
+ refreshControlIndicatorProps?: Partial<ActivityIndicatorProps>
49
+ style?: React.CSSProperties
50
+ ref?: React.MutableRefObject<undefined>
51
+ } & ComponentCommonProps