UNPKG

4.29 kBJavaScriptView Raw
1import _extends from "@babel/runtime/helpers/esm/extends";
2import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3import * as React from 'react';
4import PropTypes from 'prop-types';
5import clsx from 'clsx';
6import debounce from '../utils/debounce';
7import withStyles from '../styles/withStyles';
8import isMuiElement from '../utils/isMuiElement';
9export const styles = {
10 /* Styles applied to the root element. */
11 root: {
12 boxSizing: 'border-box',
13 flexShrink: 0
14 },
15
16 /* Styles applied to the `div` element that wraps the children. */
17 tile: {
18 position: 'relative',
19 display: 'block',
20 // In case it's not rendered with a div.
21 height: '100%',
22 overflow: 'hidden'
23 },
24
25 /* Styles applied to an `img` element child, if needed to ensure it covers the tile. */
26 imgFullHeight: {
27 height: '100%',
28 transform: 'translateX(-50%)',
29 position: 'relative',
30 left: '50%'
31 },
32
33 /* Styles applied to an `img` element child, if needed to ensure it covers the tile. */
34 imgFullWidth: {
35 width: '100%',
36 position: 'relative',
37 transform: 'translateY(-50%)',
38 top: '50%'
39 }
40};
41
42const fit = (imgEl, classes) => {
43 if (!imgEl || !imgEl.complete) {
44 return;
45 }
46
47 if (imgEl.width / imgEl.height > imgEl.parentElement.offsetWidth / imgEl.parentElement.offsetHeight) {
48 imgEl.classList.remove(...classes.imgFullWidth.split(' '));
49 imgEl.classList.add(...classes.imgFullHeight.split(' '));
50 } else {
51 imgEl.classList.remove(...classes.imgFullHeight.split(' '));
52 imgEl.classList.add(...classes.imgFullWidth.split(' '));
53 }
54};
55
56function ensureImageCover(imgEl, classes) {
57 if (!imgEl) {
58 return;
59 }
60
61 if (imgEl.complete) {
62 fit(imgEl, classes);
63 } else {
64 imgEl.addEventListener('load', () => {
65 fit(imgEl, classes);
66 });
67 }
68}
69
70const GridListTile = /*#__PURE__*/React.forwardRef(function GridListTile(props, ref) {
71 // cols rows default values are for docs only
72 const {
73 children,
74 classes,
75 className,
76 // eslint-disable-next-line no-unused-vars
77 cols = 1,
78 component: Component = 'li',
79 // eslint-disable-next-line no-unused-vars
80 rows = 1
81 } = props,
82 other = _objectWithoutPropertiesLoose(props, ["children", "classes", "className", "cols", "component", "rows"]);
83
84 const imgRef = React.useRef(null);
85 React.useEffect(() => {
86 ensureImageCover(imgRef.current, classes);
87 });
88 React.useEffect(() => {
89 const handleResize = debounce(() => {
90 fit(imgRef.current, classes);
91 });
92 window.addEventListener('resize', handleResize);
93 return () => {
94 handleResize.clear();
95 window.removeEventListener('resize', handleResize);
96 };
97 }, [classes]);
98 return /*#__PURE__*/React.createElement(Component, _extends({
99 className: clsx(classes.root, className),
100 ref: ref
101 }, other), /*#__PURE__*/React.createElement("div", {
102 className: classes.tile
103 }, React.Children.map(children, child => {
104 if (! /*#__PURE__*/React.isValidElement(child)) {
105 return null;
106 }
107
108 if (child.type === 'img' || isMuiElement(child, ['Image'])) {
109 return /*#__PURE__*/React.cloneElement(child, {
110 ref: imgRef
111 });
112 }
113
114 return child;
115 })));
116});
117process.env.NODE_ENV !== "production" ? GridListTile.propTypes = {
118 /**
119 * Theoretically you can pass any node as children, but the main use case is to pass an img,
120 * in which case GridListTile takes care of making the image "cover" available space
121 * (similar to `background-size: cover` or to `object-fit: cover`).
122 */
123 children: PropTypes.node,
124
125 /**
126 * Override or extend the styles applied to the component.
127 * See [CSS API](#css) below for more details.
128 */
129 classes: PropTypes.object.isRequired,
130
131 /**
132 * @ignore
133 */
134 className: PropTypes.string,
135
136 /**
137 * Width of the tile in number of grid cells.
138 */
139 cols: PropTypes.number,
140
141 /**
142 * The component used for the root node.
143 * Either a string to use a HTML element or a component.
144 */
145 component: PropTypes
146 /* @typescript-to-proptypes-ignore */
147 .elementType,
148
149 /**
150 * Height of the tile in number of grid cells.
151 */
152 rows: PropTypes.number
153} : void 0;
154export default withStyles(styles, {
155 name: 'MuiGridListTile'
156})(GridListTile);
\No newline at end of file