UNPKG

21.6 kBJavaScriptView Raw
1'use client';
2
3// A grid component using the following libs as inspiration.
4//
5// For the implementation:
6// - https://getbootstrap.com/docs/4.3/layout/grid/
7// - https://github.com/kristoferjoseph/flexboxgrid/blob/master/src/css/flexboxgrid.css
8// - https://github.com/roylee0704/react-flexbox-grid
9// - https://material.angularjs.org/latest/layout/introduction
10//
11// Follow this flexbox Guide to better understand the underlying model:
12// - https://css-tricks.com/snippets/css/a-guide-to-flexbox/
13import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
14import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
15import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
16import _extends from "@babel/runtime/helpers/esm/extends";
17import _typeof from "@babel/runtime/helpers/esm/typeof";
18import * as React from 'react';
19import PropTypes from 'prop-types';
20import clsx from 'clsx';
21import { handleBreakpoints, unstable_resolveBreakpointValues as resolveBreakpointValues } from '@mui/system';
22import { extendSxProp } from '@mui/system/styleFunctionSx';
23import composeClasses from '@mui/utils/composeClasses';
24import requirePropFactory from '../utils/requirePropFactory';
25import styled from '../styles/styled';
26import { useDefaultProps } from '../DefaultPropsProvider';
27import useTheme from '../styles/useTheme';
28import GridContext from './GridContext';
29import gridClasses, { getGridUtilityClass } from './gridClasses';
30import { jsx as _jsx } from "react/jsx-runtime";
31function getOffset(val) {
32 var parse = parseFloat(val);
33 return "".concat(parse).concat(String(val).replace(String(parse), '') || 'px');
34}
35export function generateGrid(_ref) {
36 var theme = _ref.theme,
37 ownerState = _ref.ownerState;
38 var size;
39 return theme.breakpoints.keys.reduce(function (globalStyles, breakpoint) {
40 // Use side effect over immutability for better performance.
41 var styles = {};
42 if (ownerState[breakpoint]) {
43 size = ownerState[breakpoint];
44 }
45 if (!size) {
46 return globalStyles;
47 }
48 if (size === true) {
49 // For the auto layouting
50 styles = {
51 flexBasis: 0,
52 flexGrow: 1,
53 maxWidth: '100%'
54 };
55 } else if (size === 'auto') {
56 styles = {
57 flexBasis: 'auto',
58 flexGrow: 0,
59 flexShrink: 0,
60 maxWidth: 'none',
61 width: 'auto'
62 };
63 } else {
64 var columnsBreakpointValues = resolveBreakpointValues({
65 values: ownerState.columns,
66 breakpoints: theme.breakpoints.values
67 });
68 var columnValue = _typeof(columnsBreakpointValues) === 'object' ? columnsBreakpointValues[breakpoint] : columnsBreakpointValues;
69 if (columnValue === undefined || columnValue === null) {
70 return globalStyles;
71 }
72 // Keep 7 significant numbers.
73 var width = "".concat(Math.round(size / columnValue * 10e7) / 10e5, "%");
74 var more = {};
75 if (ownerState.container && ownerState.item && ownerState.columnSpacing !== 0) {
76 var themeSpacing = theme.spacing(ownerState.columnSpacing);
77 if (themeSpacing !== '0px') {
78 var fullWidth = "calc(".concat(width, " + ").concat(getOffset(themeSpacing), ")");
79 more = {
80 flexBasis: fullWidth,
81 maxWidth: fullWidth
82 };
83 }
84 }
85
86 // Close to the bootstrap implementation:
87 // https://github.com/twbs/bootstrap/blob/8fccaa2439e97ec72a4b7dc42ccc1f649790adb0/scss/mixins/_grid.scss#L41
88 styles = _extends({
89 flexBasis: width,
90 flexGrow: 0,
91 maxWidth: width
92 }, more);
93 }
94
95 // No need for a media query for the first size.
96 if (theme.breakpoints.values[breakpoint] === 0) {
97 _extends(globalStyles, styles);
98 } else {
99 globalStyles[theme.breakpoints.up(breakpoint)] = styles;
100 }
101 return globalStyles;
102 }, {});
103}
104export function generateDirection(_ref2) {
105 var theme = _ref2.theme,
106 ownerState = _ref2.ownerState;
107 var directionValues = resolveBreakpointValues({
108 values: ownerState.direction,
109 breakpoints: theme.breakpoints.values
110 });
111 return handleBreakpoints({
112 theme: theme
113 }, directionValues, function (propValue) {
114 var output = {
115 flexDirection: propValue
116 };
117 if (propValue.indexOf('column') === 0) {
118 output["& > .".concat(gridClasses.item)] = {
119 maxWidth: 'none'
120 };
121 }
122 return output;
123 });
124}
125
126/**
127 * Extracts zero value breakpoint keys before a non-zero value breakpoint key.
128 * @example { xs: 0, sm: 0, md: 2, lg: 0, xl: 0 } or [0, 0, 2, 0, 0]
129 * @returns [xs, sm]
130 */
131function extractZeroValueBreakpointKeys(_ref3) {
132 var breakpoints = _ref3.breakpoints,
133 values = _ref3.values;
134 var nonZeroKey = '';
135 Object.keys(values).forEach(function (key) {
136 if (nonZeroKey !== '') {
137 return;
138 }
139 if (values[key] !== 0) {
140 nonZeroKey = key;
141 }
142 });
143 var sortedBreakpointKeysByValue = Object.keys(breakpoints).sort(function (a, b) {
144 return breakpoints[a] - breakpoints[b];
145 });
146 return sortedBreakpointKeysByValue.slice(0, sortedBreakpointKeysByValue.indexOf(nonZeroKey));
147}
148export function generateRowGap(_ref4) {
149 var theme = _ref4.theme,
150 ownerState = _ref4.ownerState;
151 var container = ownerState.container,
152 rowSpacing = ownerState.rowSpacing;
153 var styles = {};
154 if (container && rowSpacing !== 0) {
155 var rowSpacingValues = resolveBreakpointValues({
156 values: rowSpacing,
157 breakpoints: theme.breakpoints.values
158 });
159 var zeroValueBreakpointKeys;
160 if (_typeof(rowSpacingValues) === 'object') {
161 zeroValueBreakpointKeys = extractZeroValueBreakpointKeys({
162 breakpoints: theme.breakpoints.values,
163 values: rowSpacingValues
164 });
165 }
166 styles = handleBreakpoints({
167 theme: theme
168 }, rowSpacingValues, function (propValue, breakpoint) {
169 var _zeroValueBreakpointK;
170 var themeSpacing = theme.spacing(propValue);
171 if (themeSpacing !== '0px') {
172 return _defineProperty({
173 marginTop: "-".concat(getOffset(themeSpacing))
174 }, "& > .".concat(gridClasses.item), {
175 paddingTop: getOffset(themeSpacing)
176 });
177 }
178 if ((_zeroValueBreakpointK = zeroValueBreakpointKeys) != null && _zeroValueBreakpointK.includes(breakpoint)) {
179 return {};
180 }
181 return _defineProperty({
182 marginTop: 0
183 }, "& > .".concat(gridClasses.item), {
184 paddingTop: 0
185 });
186 });
187 }
188 return styles;
189}
190export function generateColumnGap(_ref7) {
191 var theme = _ref7.theme,
192 ownerState = _ref7.ownerState;
193 var container = ownerState.container,
194 columnSpacing = ownerState.columnSpacing;
195 var styles = {};
196 if (container && columnSpacing !== 0) {
197 var columnSpacingValues = resolveBreakpointValues({
198 values: columnSpacing,
199 breakpoints: theme.breakpoints.values
200 });
201 var zeroValueBreakpointKeys;
202 if (_typeof(columnSpacingValues) === 'object') {
203 zeroValueBreakpointKeys = extractZeroValueBreakpointKeys({
204 breakpoints: theme.breakpoints.values,
205 values: columnSpacingValues
206 });
207 }
208 styles = handleBreakpoints({
209 theme: theme
210 }, columnSpacingValues, function (propValue, breakpoint) {
211 var _zeroValueBreakpointK2;
212 var themeSpacing = theme.spacing(propValue);
213 if (themeSpacing !== '0px') {
214 return _defineProperty({
215 width: "calc(100% + ".concat(getOffset(themeSpacing), ")"),
216 marginLeft: "-".concat(getOffset(themeSpacing))
217 }, "& > .".concat(gridClasses.item), {
218 paddingLeft: getOffset(themeSpacing)
219 });
220 }
221 if ((_zeroValueBreakpointK2 = zeroValueBreakpointKeys) != null && _zeroValueBreakpointK2.includes(breakpoint)) {
222 return {};
223 }
224 return _defineProperty({
225 width: '100%',
226 marginLeft: 0
227 }, "& > .".concat(gridClasses.item), {
228 paddingLeft: 0
229 });
230 });
231 }
232 return styles;
233}
234export function resolveSpacingStyles(spacing, breakpoints) {
235 var styles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
236 // undefined/null or `spacing` <= 0
237 if (!spacing || spacing <= 0) {
238 return [];
239 }
240 // in case of string/number `spacing`
241 if (typeof spacing === 'string' && !Number.isNaN(Number(spacing)) || typeof spacing === 'number') {
242 return [styles["spacing-xs-".concat(String(spacing))]];
243 }
244 // in case of object `spacing`
245 var spacingStyles = [];
246 breakpoints.forEach(function (breakpoint) {
247 var value = spacing[breakpoint];
248 if (Number(value) > 0) {
249 spacingStyles.push(styles["spacing-".concat(breakpoint, "-").concat(String(value))]);
250 }
251 });
252 return spacingStyles;
253}
254
255// Default CSS values
256// flex: '0 1 auto',
257// flexDirection: 'row',
258// alignItems: 'flex-start',
259// flexWrap: 'nowrap',
260// justifyContent: 'flex-start',
261var GridRoot = styled('div', {
262 name: 'MuiGrid',
263 slot: 'Root',
264 overridesResolver: function overridesResolver(props, styles) {
265 var ownerState = props.ownerState;
266 var container = ownerState.container,
267 direction = ownerState.direction,
268 item = ownerState.item,
269 spacing = ownerState.spacing,
270 wrap = ownerState.wrap,
271 zeroMinWidth = ownerState.zeroMinWidth,
272 breakpoints = ownerState.breakpoints;
273 var spacingStyles = [];
274
275 // in case of grid item
276 if (container) {
277 spacingStyles = resolveSpacingStyles(spacing, breakpoints, styles);
278 }
279 var breakpointsStyles = [];
280 breakpoints.forEach(function (breakpoint) {
281 var value = ownerState[breakpoint];
282 if (value) {
283 breakpointsStyles.push(styles["grid-".concat(breakpoint, "-").concat(String(value))]);
284 }
285 });
286 return [styles.root, container && styles.container, item && styles.item, zeroMinWidth && styles.zeroMinWidth].concat(_toConsumableArray(spacingStyles), [direction !== 'row' && styles["direction-xs-".concat(String(direction))], wrap !== 'wrap' && styles["wrap-xs-".concat(String(wrap))]], breakpointsStyles);
287 }
288})(function (_ref10) {
289 var ownerState = _ref10.ownerState;
290 return _extends({
291 boxSizing: 'border-box'
292 }, ownerState.container && {
293 display: 'flex',
294 flexWrap: 'wrap',
295 width: '100%'
296 }, ownerState.item && {
297 margin: 0 // For instance, it's useful when used with a `figure` element.
298 }, ownerState.zeroMinWidth && {
299 minWidth: 0
300 }, ownerState.wrap !== 'wrap' && {
301 flexWrap: ownerState.wrap
302 });
303}, generateDirection, generateRowGap, generateColumnGap, generateGrid);
304export function resolveSpacingClasses(spacing, breakpoints) {
305 // undefined/null or `spacing` <= 0
306 if (!spacing || spacing <= 0) {
307 return [];
308 }
309 // in case of string/number `spacing`
310 if (typeof spacing === 'string' && !Number.isNaN(Number(spacing)) || typeof spacing === 'number') {
311 return ["spacing-xs-".concat(String(spacing))];
312 }
313 // in case of object `spacing`
314 var classes = [];
315 breakpoints.forEach(function (breakpoint) {
316 var value = spacing[breakpoint];
317 if (Number(value) > 0) {
318 var className = "spacing-".concat(breakpoint, "-").concat(String(value));
319 classes.push(className);
320 }
321 });
322 return classes;
323}
324var useUtilityClasses = function useUtilityClasses(ownerState) {
325 var classes = ownerState.classes,
326 container = ownerState.container,
327 direction = ownerState.direction,
328 item = ownerState.item,
329 spacing = ownerState.spacing,
330 wrap = ownerState.wrap,
331 zeroMinWidth = ownerState.zeroMinWidth,
332 breakpoints = ownerState.breakpoints;
333 var spacingClasses = [];
334
335 // in case of grid item
336 if (container) {
337 spacingClasses = resolveSpacingClasses(spacing, breakpoints);
338 }
339 var breakpointsClasses = [];
340 breakpoints.forEach(function (breakpoint) {
341 var value = ownerState[breakpoint];
342 if (value) {
343 breakpointsClasses.push("grid-".concat(breakpoint, "-").concat(String(value)));
344 }
345 });
346 var slots = {
347 root: ['root', container && 'container', item && 'item', zeroMinWidth && 'zeroMinWidth'].concat(_toConsumableArray(spacingClasses), [direction !== 'row' && "direction-xs-".concat(String(direction)), wrap !== 'wrap' && "wrap-xs-".concat(String(wrap))], breakpointsClasses)
348 };
349 return composeClasses(slots, getGridUtilityClass, classes);
350};
351var Grid = /*#__PURE__*/React.forwardRef(function Grid(inProps, ref) {
352 var themeProps = useDefaultProps({
353 props: inProps,
354 name: 'MuiGrid'
355 });
356 var _useTheme = useTheme(),
357 breakpoints = _useTheme.breakpoints;
358 var props = extendSxProp(themeProps);
359 var className = props.className,
360 columnsProp = props.columns,
361 columnSpacingProp = props.columnSpacing,
362 _props$component = props.component,
363 component = _props$component === void 0 ? 'div' : _props$component,
364 _props$container = props.container,
365 container = _props$container === void 0 ? false : _props$container,
366 _props$direction = props.direction,
367 direction = _props$direction === void 0 ? 'row' : _props$direction,
368 _props$item = props.item,
369 item = _props$item === void 0 ? false : _props$item,
370 rowSpacingProp = props.rowSpacing,
371 _props$spacing = props.spacing,
372 spacing = _props$spacing === void 0 ? 0 : _props$spacing,
373 _props$wrap = props.wrap,
374 wrap = _props$wrap === void 0 ? 'wrap' : _props$wrap,
375 _props$zeroMinWidth = props.zeroMinWidth,
376 zeroMinWidth = _props$zeroMinWidth === void 0 ? false : _props$zeroMinWidth,
377 other = _objectWithoutProperties(props, ["className", "columns", "columnSpacing", "component", "container", "direction", "item", "rowSpacing", "spacing", "wrap", "zeroMinWidth"]);
378 var rowSpacing = rowSpacingProp || spacing;
379 var columnSpacing = columnSpacingProp || spacing;
380 var columnsContext = React.useContext(GridContext);
381
382 // columns set with default breakpoint unit of 12
383 var columns = container ? columnsProp || 12 : columnsContext;
384 var breakpointsValues = {};
385 var otherFiltered = _extends({}, other);
386 breakpoints.keys.forEach(function (breakpoint) {
387 if (other[breakpoint] != null) {
388 breakpointsValues[breakpoint] = other[breakpoint];
389 delete otherFiltered[breakpoint];
390 }
391 });
392 var ownerState = _extends({}, props, {
393 columns: columns,
394 container: container,
395 direction: direction,
396 item: item,
397 rowSpacing: rowSpacing,
398 columnSpacing: columnSpacing,
399 wrap: wrap,
400 zeroMinWidth: zeroMinWidth,
401 spacing: spacing
402 }, breakpointsValues, {
403 breakpoints: breakpoints.keys
404 });
405 var classes = useUtilityClasses(ownerState);
406 return /*#__PURE__*/_jsx(GridContext.Provider, {
407 value: columns,
408 children: /*#__PURE__*/_jsx(GridRoot, _extends({
409 ownerState: ownerState,
410 className: clsx(classes.root, className),
411 as: component,
412 ref: ref
413 }, otherFiltered))
414 });
415});
416process.env.NODE_ENV !== "production" ? Grid.propTypes /* remove-proptypes */ = {
417 // ┌────────────────────────────── Warning ──────────────────────────────┐
418 // │ These PropTypes are generated from the TypeScript type definitions. │
419 // │ To update them, edit the d.ts file and run `pnpm proptypes`. │
420 // └─────────────────────────────────────────────────────────────────────┘
421 /**
422 * The content of the component.
423 */
424 children: PropTypes.node,
425 /**
426 * Override or extend the styles applied to the component.
427 */
428 classes: PropTypes.object,
429 /**
430 * @ignore
431 */
432 className: PropTypes.string,
433 /**
434 * The number of columns.
435 * @default 12
436 */
437 columns: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number, PropTypes.object]),
438 /**
439 * Defines the horizontal space between the type `item` components.
440 * It overrides the value of the `spacing` prop.
441 */
442 columnSpacing: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])), PropTypes.number, PropTypes.object, PropTypes.string]),
443 /**
444 * The component used for the root node.
445 * Either a string to use a HTML element or a component.
446 */
447 component: PropTypes.elementType,
448 /**
449 * If `true`, the component will have the flex *container* behavior.
450 * You should be wrapping *items* with a *container*.
451 * @default false
452 */
453 container: PropTypes.bool,
454 /**
455 * Defines the `flex-direction` style property.
456 * It is applied for all screen sizes.
457 * @default 'row'
458 */
459 direction: PropTypes.oneOfType([PropTypes.oneOf(['column-reverse', 'column', 'row-reverse', 'row']), PropTypes.arrayOf(PropTypes.oneOf(['column-reverse', 'column', 'row-reverse', 'row'])), PropTypes.object]),
460 /**
461 * If `true`, the component will have the flex *item* behavior.
462 * You should be wrapping *items* with a *container*.
463 * @default false
464 */
465 item: PropTypes.bool,
466 /**
467 * If a number, it sets the number of columns the grid item uses.
468 * It can't be greater than the total number of columns of the container (12 by default).
469 * If 'auto', the grid item's width matches its content.
470 * If false, the prop is ignored.
471 * If true, the grid item's width grows to use the space available in the grid container.
472 * The value is applied for the `lg` breakpoint and wider screens if not overridden.
473 * @default false
474 */
475 lg: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number, PropTypes.bool]),
476 /**
477 * If a number, it sets the number of columns the grid item uses.
478 * It can't be greater than the total number of columns of the container (12 by default).
479 * If 'auto', the grid item's width matches its content.
480 * If false, the prop is ignored.
481 * If true, the grid item's width grows to use the space available in the grid container.
482 * The value is applied for the `md` breakpoint and wider screens if not overridden.
483 * @default false
484 */
485 md: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number, PropTypes.bool]),
486 /**
487 * Defines the vertical space between the type `item` components.
488 * It overrides the value of the `spacing` prop.
489 */
490 rowSpacing: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])), PropTypes.number, PropTypes.object, PropTypes.string]),
491 /**
492 * If a number, it sets the number of columns the grid item uses.
493 * It can't be greater than the total number of columns of the container (12 by default).
494 * If 'auto', the grid item's width matches its content.
495 * If false, the prop is ignored.
496 * If true, the grid item's width grows to use the space available in the grid container.
497 * The value is applied for the `sm` breakpoint and wider screens if not overridden.
498 * @default false
499 */
500 sm: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number, PropTypes.bool]),
501 /**
502 * Defines the space between the type `item` components.
503 * It can only be used on a type `container` component.
504 * @default 0
505 */
506 spacing: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])), PropTypes.number, PropTypes.object, PropTypes.string]),
507 /**
508 * The system prop that allows defining system overrides as well as additional CSS styles.
509 */
510 sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
511 /**
512 * Defines the `flex-wrap` style property.
513 * It's applied for all screen sizes.
514 * @default 'wrap'
515 */
516 wrap: PropTypes.oneOf(['nowrap', 'wrap-reverse', 'wrap']),
517 /**
518 * If a number, it sets the number of columns the grid item uses.
519 * It can't be greater than the total number of columns of the container (12 by default).
520 * If 'auto', the grid item's width matches its content.
521 * If false, the prop is ignored.
522 * If true, the grid item's width grows to use the space available in the grid container.
523 * The value is applied for the `xl` breakpoint and wider screens if not overridden.
524 * @default false
525 */
526 xl: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number, PropTypes.bool]),
527 /**
528 * If a number, it sets the number of columns the grid item uses.
529 * It can't be greater than the total number of columns of the container (12 by default).
530 * If 'auto', the grid item's width matches its content.
531 * If false, the prop is ignored.
532 * If true, the grid item's width grows to use the space available in the grid container.
533 * The value is applied for all the screen sizes with the lowest priority.
534 * @default false
535 */
536 xs: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number, PropTypes.bool]),
537 /**
538 * If `true`, it sets `min-width: 0` on the item.
539 * Refer to the limitations section of the documentation to better understand the use case.
540 * @default false
541 */
542 zeroMinWidth: PropTypes.bool
543} : void 0;
544if (process.env.NODE_ENV !== 'production') {
545 var requireProp = requirePropFactory('Grid', Grid);
546 // eslint-disable-next-line no-useless-concat
547 Grid['propTypes' + ''] = _extends({}, Grid.propTypes, {
548 direction: requireProp('container'),
549 lg: requireProp('item'),
550 md: requireProp('item'),
551 sm: requireProp('item'),
552 spacing: requireProp('container'),
553 wrap: requireProp('container'),
554 xs: requireProp('item'),
555 zeroMinWidth: requireProp('item')
556 });
557}
558export default Grid;
\No newline at end of file