@codeleap/web 3.12.5 → 3.12.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codeleap/web",
3
- "version": "3.12.5",
3
+ "version": "3.12.6",
4
4
  "main": "src/index.ts",
5
5
  "repository": {
6
6
  "url": "https://github.com/codeleap-uk/internal-libs-monorepo.git",
@@ -30,7 +30,7 @@ const defaultProps: Partial<GridProps> = {
30
30
  columnItemsSpacing: 8,
31
31
  rowItemsSpacing: 8,
32
32
  overscan: 2,
33
- enabledItemsRehydrateIndicator: true
33
+ reloadTimeout: 350,
34
34
  }
35
35
 
36
36
  export function Grid<T = any>(props: GridProps<T>) {
@@ -52,7 +52,7 @@ export function Grid<T = any>(props: GridProps<T>) {
52
52
  separators,
53
53
  masonryProps = {},
54
54
  numColumns,
55
- enabledItemsRehydrateIndicator,
55
+ reloadTimeout,
56
56
  } = allProps
57
57
 
58
58
  const variantStyles = useDefaultComponentStyle<'u:Grid', typeof GridPresets>('u:Grid', {
@@ -101,15 +101,14 @@ export function Grid<T = any>(props: GridProps<T>) {
101
101
  <ListMasonry
102
102
  items={data}
103
103
  render={renderItem}
104
- itemKey={item => item?.id}
104
+ itemKey={(item, _index) => (item?.id ?? _index)}
105
105
  columnGutter={columnItemsSpacing}
106
106
  rowGutter={rowItemsSpacing}
107
107
  columnCount={numColumns}
108
108
  maxColumnCount={numColumns}
109
109
  onRender={onLoadMore}
110
110
  overscanBy={overscan}
111
- onRefreshItems={onRefreshItems}
112
- itemsRehydrateIndicator={enabledItemsRehydrateIndicator}
111
+ reloadTimeout={reloadTimeout}
113
112
  {...masonryProps}
114
113
  />
115
114
  </ListLayout>
@@ -33,7 +33,7 @@ const defaultProps: Partial<ListProps> = {
33
33
  refresh: true,
34
34
  rowItemsSpacing: 8,
35
35
  overscan: 2,
36
- enabledItemsRehydrateIndicator: true,
36
+ reloadTimeout: 350,
37
37
  }
38
38
 
39
39
  export function List<T = any>(props: ListProps<T>) {
@@ -53,7 +53,7 @@ export function List<T = any>(props: ListProps<T>) {
53
53
  overscan,
54
54
  separators,
55
55
  masonryProps = {},
56
- enabledItemsRehydrateIndicator,
56
+ reloadTimeout,
57
57
  } = allProps
58
58
 
59
59
  const variantStyles = useDefaultComponentStyle<'u:List', typeof ListPresets>('u:List', {
@@ -62,7 +62,7 @@ export function List<T = any>(props: ListProps<T>) {
62
62
  styles,
63
63
  })
64
64
 
65
- const { layoutProps, onLoadMore, onRefreshItems } = useInfiniteScroll(allProps)
65
+ const { layoutProps, onLoadMore } = useInfiniteScroll(allProps)
66
66
 
67
67
  const separator = React.useMemo(() => {
68
68
  return separators ? <ListSeparatorComponent separatorStyles={variantStyles.separator} /> : null
@@ -100,13 +100,12 @@ export function List<T = any>(props: ListProps<T>) {
100
100
  <ListMasonry
101
101
  items={data}
102
102
  render={renderItem}
103
- itemKey={item => item?.id}
103
+ itemKey={(item, _index) => (item?.id ?? _index)}
104
104
  rowGutter={rowItemsSpacing}
105
105
  onRender={onLoadMore}
106
106
  overscanBy={overscan}
107
107
  columnCount={1}
108
- onRefreshItems={onRefreshItems}
109
- itemsRehydrateIndicator={enabledItemsRehydrateIndicator}
108
+ reloadTimeout={reloadTimeout}
110
109
  {...masonryProps}
111
110
  />
112
111
  </ListLayout>
@@ -5,10 +5,10 @@ import { ListComposition, ListPresets } from './styles'
5
5
  import { motion } from 'framer-motion'
6
6
  import { ActivityIndicatorProps } from '../ActivityIndicator'
7
7
  import { ComponentCommonProps } from '../../types'
8
- import { RenderComponentProps, ListProps as ListMasonryProps } from 'masonic'
9
8
  import { UseInfiniteScrollArgs } from './useInfiniteScroll'
9
+ import { ItemMasonryProps, ListMasonryProps } from '../../lib'
10
10
 
11
- export type AugmentedRenderItemInfo<T> = RenderComponentProps<T> & {
11
+ export type AugmentedRenderItemInfo<T> = ItemMasonryProps<T> & {
12
12
  item: T
13
13
  isFirst: boolean
14
14
  isLast: boolean
@@ -50,6 +50,6 @@ Data = T extends Array<infer D> ? D : never
50
50
  ref?: React.MutableRefObject<undefined>
51
51
  rowItemsSpacing?: number
52
52
  overscan?: number
53
- masonryProps?: Partial<ListMasonryProps<T>>
54
- enabledItemsRehydrateIndicator?: boolean
53
+ masonryProps?: Partial<Omit<ListMasonryProps<T>, 'previousItemsLength'>>
54
+ reloadTimeout?: number
55
55
  } & ComponentCommonProps & UseInfiniteScrollArgs
@@ -1,6 +1,7 @@
1
1
  import React from 'react'
2
2
  import { useWindowSize } from '@react-hook/window-size'
3
- import { AnyFunction, onUpdate, usePrevious, useState } from '@codeleap/common'
3
+ import { TypeGuards } from '@codeleap/common'
4
+ import { EmptyPlaceholder } from '../components/EmptyPlaceholder'
4
5
 
5
6
  import {
6
7
  useMasonry,
@@ -12,39 +13,69 @@ import {
12
13
  RenderComponentProps,
13
14
  } from 'masonic'
14
15
 
15
- export type ItemMasonryProps<T> = RenderComponentProps<T>
16
+ function fillItems(arr: Array<any>, toCount: number, fillContent = {}) {
17
+ if (!arr || !TypeGuards.isArray(arr)) return []
16
18
 
17
- export type ListMasonryProps<T> = MasonryProps<T> & {
18
- onRefreshItems: AnyFunction
19
- itemsRehydrateIndicator: boolean
19
+ if (toCount === arr?.length) return arr
20
+
21
+ const diff = toCount - arr?.length
22
+
23
+ if (diff < 0) return arr
24
+
25
+ const right = Array(diff).fill(fillContent)
26
+
27
+ return arr.concat(right)
20
28
  }
21
29
 
22
- export function ListMasonry<Item>(props: ListMasonryProps<Item>) {
23
- const data = props?.items || []
30
+ type UseMasonryReloadArgs = {
31
+ data: Array<any>
32
+ reloadTimeout: number
33
+ }
24
34
 
25
- const [reloadingLayout, setReloadingLayout] = useState(false)
35
+ export const useMasonryReload = (args: UseMasonryReloadArgs) => {
36
+ const {
37
+ data,
38
+ reloadTimeout = 350,
39
+ } = args
26
40
 
27
- const dataPreviousLength = usePrevious(data?.length)
41
+ const [reloadingLayout, setReloadingLayout] = React.useState(false)
42
+ const previousLengthRef = React.useRef(data?.length ?? 0)
28
43
 
29
- onUpdate(() => {
30
- console.log({
31
- dataPreviousLength,
32
- length: data?.length
33
- })
44
+ const updater = () => {
45
+ previousLengthRef.current = (data?.length ?? 0)
46
+ }
34
47
 
35
- if (dataPreviousLength > data?.length) {
48
+ React.useEffect(() => {
49
+ if (previousLengthRef.current > data?.length) {
36
50
  setReloadingLayout(true)
37
51
 
38
- console.log({
39
- reloaded: true,
40
- })
41
-
42
52
  setTimeout(() => {
43
- setReloadingLayout(false)
44
- }, 3000)
53
+ updater()
54
+
55
+ setTimeout(() => {
56
+ setReloadingLayout(false)
57
+ }, reloadTimeout)
58
+ }, reloadTimeout)
59
+ } else {
60
+ updater()
45
61
  }
46
- }, [data?.length, dataPreviousLength])
62
+ }, [data?.length])
63
+
64
+ return {
65
+ reloadingLayout,
66
+ setReloadingLayout,
67
+ previousLength: previousLengthRef.current,
68
+ }
69
+ }
70
+
71
+ export type ItemMasonryProps<T> = RenderComponentProps<T>
47
72
 
73
+ export type ListMasonryProps<T> = MasonryProps<T> & {
74
+ previousItemsLength: number
75
+ reloadTimeout: UseMasonryReloadArgs['reloadTimeout']
76
+ }
77
+
78
+ export function MasonryComponent<Item>(props: ListMasonryProps<Item>) {
48
79
  const containerRef = React.useRef(null)
49
80
 
50
81
  const windowSize = useWindowSize({
@@ -72,22 +103,41 @@ export function ListMasonry<Item>(props: ListMasonryProps<Item>) {
72
103
  columnCount: listProps?.columnCount,
73
104
  maxColumnCount: listProps?.columnCount,
74
105
  rowGutter: listProps?.rowGutter
75
- }, [reloadingLayout])
106
+ })
76
107
 
77
108
  const { scrollTop, isScrolling } = useScroller(listProps?.offset, listProps?.scrollFps)
78
109
 
79
110
  const resizeObserver = useResizeObserver(positioner)
80
111
 
81
- if (reloadingLayout) {
82
- return <div><p>Loading</p></div>
83
- }
84
-
85
112
  return useMasonry({
86
113
  ...listProps,
87
114
  resizeObserver,
88
115
  positioner,
89
116
  scrollTop,
90
117
  isScrolling,
91
- items: data,
118
+ items: fillItems(props?.items, props?.previousItemsLength)
92
119
  })
93
120
  }
121
+
122
+ export function ListMasonry<Item>(props: Omit<ListMasonryProps<Item>, 'previousItemsLength'>) {
123
+ const data = props?.items || []
124
+
125
+ const { reloadingLayout, previousLength } = useMasonryReload({
126
+ data,
127
+ reloadTimeout: props?.reloadTimeout,
128
+ })
129
+
130
+ if (reloadingLayout) {
131
+ return (
132
+ <EmptyPlaceholder loading title={''} description={null} />
133
+ )
134
+ } else {
135
+ return (
136
+ <MasonryComponent
137
+ {...props}
138
+ items={data}
139
+ previousItemsLength={previousLength}
140
+ />
141
+ )
142
+ }
143
+ }