-
Notifications
You must be signed in to change notification settings - Fork 78
/
index.tsx
167 lines (149 loc) · 4.56 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import * as React from "react";
import * as PropTypes from "prop-types";
const ReactLazyLoad = require("react-lazyload").default;
import Icon from "../Icon";
export interface DataProps {
/**
* Toggle LazyLoad mode open, powerful base on [react-lazyload](https://github.com/jasonslyvia/react-lazyload).
*/
useLazyLoad?: boolean;
/**
* Use Div backgroundImage.
*/
useDivContainer?: boolean;
/**
* Once the lazy loaded component is loaded, do not detect scroll/resize event anymore. Useful for images or simple components.
*/
once?: boolean;
/**
* Say if you want to preload a component even if it's 100px below the viewport (user have to scroll 100px more to see this component), you can set `offset` props to `100`. On the other hand, if you want to delay loading a component even if it's top edge has already appeared at viewport, set `offset` to negative number.
*/
offset?: number | number[];
/**
* Listen and react to scroll event.
*/
scroll?: boolean;
/**
* Respond to `resize` event, set it to `true` if you do need LazyLoad listen resize event.
*/
resize?: boolean;
/**
* If lazy loading components inside a overflow container, set this to `true`. Also make sure a `position` property other than `static` has been set to your overflow container.
*/
overflow?: boolean;
/**
* By default, LazyLoad will have all event handlers debounced in 300ms for better performance. You can disable this by setting `debounce` to `false`, or change debounce time by setting a number value.
*/
debounce?: boolean | number;
/**
* If you prefer `throttle` rather than `debounce`, you can set this props to `true` or provide a specific number.
*/
throttle?: boolean | number;
src?: string;
height?: string | number;
}
export interface ImageProps extends React.HTMLAttributes<HTMLDivElement>, DataProps {
placeholder?: any;
}
export interface ImageState {
showEmptyImage?: boolean;
}
class Placeholder extends React.Component<React.HTMLAttributes<HTMLImageElement>> {
static contextTypes = { theme: PropTypes.object };
context: { theme: ReactUWP.ThemeType };
render() {
const { style, ...attributes } = this.props;
const { theme } = this.context;
return (
<div
{...attributes as any}
style={theme.prefixStyle({
background: theme.chromeMedium,
padding: 20,
display: "inline-block",
verticalAlign: "middle",
cursor: "default",
...style
})}
>
<Icon
style={{
color: theme.baseMedium,
fontSize: 80,
verticalAlign: "middle",
display: "block"
}}
hoverStyle={{}}
>

</Icon>
</div>
);
}
}
export class Image extends React.Component<ImageProps, ImageState> {
static defaultProps: ImageProps = {
useLazyLoad: false,
useDivContainer: false,
once: true,
offset: 0,
scroll: true,
overflow: false,
throttle: 60
};
static contextTypes = { theme: PropTypes.object };
context: { theme: ReactUWP.ThemeType };
state: ImageState = {
showEmptyImage: false
};
errorHandler = (e: any) => this.setState({ showEmptyImage: true });
render() {
const {
useLazyLoad,
useDivContainer,
once, scroll, offset, overflow, resize, debounce, throttle,
style,
placeholder,
...attributes
} = this.props;
const { theme } = this.context;
const currPlaceholder = (placeholder || <Placeholder style={style} {...attributes as any} />) as any;
const baseStyle: React.CSSProperties = theme.prefixStyle({
background: `url(${attributes.src}) no-repeat center center / cover`,
display: "inline-block",
verticalAlign: "middle",
...style
});
const ImageOrDiv = () => (useDivContainer ?
<div
{...attributes as React.HTMLAttributes<HTMLDivElement>}
style={baseStyle}
/>
: <img {...attributes as any} style={baseStyle} onError={this.errorHandler} />
);
if (!attributes.src || this.state.showEmptyImage) {
return useLazyLoad ? currPlaceholder : null;
}
if (useLazyLoad) {
return (
<ReactLazyLoad
{...{
once,
scroll,
offset,
overflow,
resize,
debounce,
throttle
}}
height={attributes.height}
placeholder={currPlaceholder}
>
<ImageOrDiv />
</ReactLazyLoad>
);
}
return <ImageOrDiv />;
}
}
export default Image;