react-native-skelo 0.0.2 → 0.0.5
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/LICENSE +1 -1
- package/README.md +86 -90
- package/lib/commonjs/animations/PulseAnimation.js +17 -42
- package/lib/commonjs/animations/PulseAnimation.js.map +1 -1
- package/lib/commonjs/animations/ShimmerAnimation.js +54 -65
- package/lib/commonjs/animations/ShimmerAnimation.js.map +1 -1
- package/lib/commonjs/components/Skeleton.js +22 -16
- package/lib/commonjs/components/Skeleton.js.map +1 -1
- package/lib/commonjs/core/parser/expandLists.js +67 -0
- package/lib/commonjs/core/parser/expandLists.js.map +1 -0
- package/lib/commonjs/index.js +1 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/animations/PulseAnimation.js +18 -43
- package/lib/module/animations/PulseAnimation.js.map +1 -1
- package/lib/module/animations/ShimmerAnimation.js +55 -66
- package/lib/module/animations/ShimmerAnimation.js.map +1 -1
- package/lib/module/components/Skeleton.js +22 -16
- package/lib/module/components/Skeleton.js.map +1 -1
- package/lib/module/core/parser/expandLists.js +61 -0
- package/lib/module/core/parser/expandLists.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/animations/PulseAnimation.d.ts +0 -44
- package/lib/typescript/animations/PulseAnimation.d.ts.map +1 -1
- package/lib/typescript/animations/ShimmerAnimation.d.ts +0 -44
- package/lib/typescript/animations/ShimmerAnimation.d.ts.map +1 -1
- package/lib/typescript/components/Skeleton.d.ts +1 -1
- package/lib/typescript/components/Skeleton.d.ts.map +1 -1
- package/lib/typescript/core/parser/expandLists.d.ts +3 -0
- package/lib/typescript/core/parser/expandLists.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/types/skeleton.d.ts +8 -0
- package/lib/typescript/types/skeleton.d.ts.map +1 -1
- package/package.json +5 -12
- package/src/animations/PulseAnimation.tsx +17 -89
- package/src/animations/ShimmerAnimation.tsx +39 -118
- package/src/components/Skeleton.tsx +24 -18
- package/src/core/parser/expandLists.tsx +77 -0
- package/src/index.ts +4 -0
- package/src/types/skeleton.ts +9 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React, { isValidElement } from 'react';
|
|
2
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
import { getComponentName } from '../../utils/componentUtils';
|
|
5
|
+
|
|
6
|
+
// List components whose rows come from `renderItem` (not JSX children).
|
|
7
|
+
const LIST_TYPES = new Set(['FlatList', 'SectionList', 'VirtualizedList', 'FlashList']);
|
|
8
|
+
|
|
9
|
+
const NOOP_SEPARATORS = {
|
|
10
|
+
highlight: () => {},
|
|
11
|
+
unhighlight: () => {},
|
|
12
|
+
updateProps: () => {},
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// Renders `count` sample rows from a list's `renderItem` so there's something
|
|
16
|
+
// to skeletonize while the real data is still loading (the rows don't exist in
|
|
17
|
+
// the tree yet). Rows that throw on placeholder data are skipped.
|
|
18
|
+
function renderSampleRows(list: ReactElement, count: number): ReactNode {
|
|
19
|
+
const props = (list.props || {}) as {
|
|
20
|
+
renderItem?: (info: {
|
|
21
|
+
item: unknown;
|
|
22
|
+
index: number;
|
|
23
|
+
section?: unknown;
|
|
24
|
+
separators: typeof NOOP_SEPARATORS;
|
|
25
|
+
}) => ReactNode;
|
|
26
|
+
data?: unknown[];
|
|
27
|
+
contentContainerStyle?: unknown;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const data = Array.isArray(props.data) ? props.data : [];
|
|
31
|
+
const sample = data.length > 0 ? data[0] : {};
|
|
32
|
+
|
|
33
|
+
const rows: ReactNode[] = [];
|
|
34
|
+
for (let i = 0; i < count; i++) {
|
|
35
|
+
try {
|
|
36
|
+
const row = props.renderItem?.({
|
|
37
|
+
item: sample,
|
|
38
|
+
index: i,
|
|
39
|
+
section: {},
|
|
40
|
+
separators: NOOP_SEPARATORS,
|
|
41
|
+
});
|
|
42
|
+
if (row) {
|
|
43
|
+
rows.push(<React.Fragment key={i}>{row}</React.Fragment>);
|
|
44
|
+
}
|
|
45
|
+
} catch {
|
|
46
|
+
// Row couldn't render with placeholder data — skip it.
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return <View style={props.contentContainerStyle as never}>{rows}</View>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Walks a child tree and replaces FlatList/SectionList with sample rows so a
|
|
54
|
+
// plain `<Skeleton><FlatList/></Skeleton>` produces a skeleton while loading.
|
|
55
|
+
export function expandListPlaceholders(children: ReactNode, count: number): ReactNode {
|
|
56
|
+
return React.Children.map(children, child => {
|
|
57
|
+
if (!isValidElement(child)) {
|
|
58
|
+
return child;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const name = getComponentName(child);
|
|
62
|
+
const props = (child.props || {}) as { children?: ReactNode };
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
LIST_TYPES.has(name) &&
|
|
66
|
+
typeof (props as { renderItem?: unknown }).renderItem === 'function'
|
|
67
|
+
) {
|
|
68
|
+
return renderSampleRows(child, count);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (props.children) {
|
|
72
|
+
return React.cloneElement(child, undefined, expandListPlaceholders(props.children, count));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return child;
|
|
76
|
+
});
|
|
77
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
* @packageDocumentation
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
// Auto-register deep expansion (react-reconciler ships as a dependency), so
|
|
10
|
+
// `<Skeleton deep>` / opaque components work with zero setup.
|
|
11
|
+
import './deep';
|
|
12
|
+
|
|
9
13
|
// Main component
|
|
10
14
|
export { Skeleton } from './components/Skeleton';
|
|
11
15
|
export { SkeletonIgnore } from './components/SkeletonIgnore';
|
package/src/types/skeleton.ts
CHANGED
|
@@ -79,6 +79,15 @@ export interface SkeletonProps {
|
|
|
79
79
|
*/
|
|
80
80
|
excludeStyles?: string[];
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Number of placeholder rows to render for a `FlatList` / `SectionList`
|
|
84
|
+
* while its data is still loading (its rows don't exist yet, so Skelo calls
|
|
85
|
+
* `renderItem` with a placeholder and repeats it `count` times).
|
|
86
|
+
*
|
|
87
|
+
* @default 6
|
|
88
|
+
*/
|
|
89
|
+
count?: number;
|
|
90
|
+
|
|
82
91
|
/**
|
|
83
92
|
* Deep mode: expand opaque (custom) child components into their real
|
|
84
93
|
* host-element tree via offline rendering, producing a structured skeleton
|