@sproutsocial/seeds-react-grid 0.0.0
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/.eslintignore +6 -0
- package/.eslintrc.js +4 -0
- package/.turbo/turbo-build.log +21 -0
- package/dist/esm/index.js +83 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.d.mts +44 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +121 -0
- package/dist/index.js.map +1 -0
- package/jest.config.js +9 -0
- package/package.json +43 -0
- package/src/Grid.stories.tsx +230 -0
- package/src/Grid.tsx +32 -0
- package/src/GridTypes.ts +37 -0
- package/src/__tests__/Grid.typetest.tsx +101 -0
- package/src/__tests__/grid.test.tsx +165 -0
- package/src/constants.ts +6 -0
- package/src/index.ts +6 -0
- package/src/styled.d.ts +7 -0
- package/src/styles.ts +21 -0
- package/src/utils.ts +33 -0
- package/tsconfig.json +9 -0
- package/tsup.config.ts +12 -0
package/.eslintignore
ADDED
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
yarn run v1.22.22
|
|
2
|
+
$ tsup --dts
|
|
3
|
+
[34mCLI[39m Building entry: src/index.ts
|
|
4
|
+
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
5
|
+
[34mCLI[39m tsup v8.5.0
|
|
6
|
+
[34mCLI[39m Using tsup config: /home/runner/_work/seeds/seeds/seeds-react/seeds-react-grid/tsup.config.ts
|
|
7
|
+
[34mCLI[39m Target: es2022
|
|
8
|
+
[34mCLI[39m Cleaning output folder
|
|
9
|
+
[34mCJS[39m Build start
|
|
10
|
+
[34mESM[39m Build start
|
|
11
|
+
[32mCJS[39m [1mdist/index.js [22m[32m3.60 KB[39m
|
|
12
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m4.37 KB[39m
|
|
13
|
+
[32mCJS[39m ⚡️ Build success in 17ms
|
|
14
|
+
[32mESM[39m [1mdist/esm/index.js [22m[32m1.70 KB[39m
|
|
15
|
+
[32mESM[39m [1mdist/esm/index.js.map [22m[32m4.25 KB[39m
|
|
16
|
+
[32mESM[39m ⚡️ Build success in 16ms
|
|
17
|
+
[34mDTS[39m Build start
|
|
18
|
+
[32mDTS[39m ⚡️ Build success in 4473ms
|
|
19
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m1.50 KB[39m
|
|
20
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m1.50 KB[39m
|
|
21
|
+
Done in 5.83s.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// src/Grid.tsx
|
|
2
|
+
import "react";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import Box from "@sproutsocial/seeds-react-box";
|
|
5
|
+
|
|
6
|
+
// src/utils.ts
|
|
7
|
+
import { css } from "styled-components";
|
|
8
|
+
import { breakpoints } from "@sproutsocial/seeds-react-theme/src/light/theme";
|
|
9
|
+
var getResponsiveStyles = (columns = 1) => {
|
|
10
|
+
if (typeof columns === "number") {
|
|
11
|
+
return css`
|
|
12
|
+
grid-template-columns: repeat(${columns}, 1fr);
|
|
13
|
+
`;
|
|
14
|
+
}
|
|
15
|
+
return css`
|
|
16
|
+
grid-template-columns: repeat(${columns.sm || 1}, 1fr);
|
|
17
|
+
|
|
18
|
+
@media (min-width: ${breakpoints.md}px) {
|
|
19
|
+
grid-template-columns: repeat(${columns.md || columns.sm || 1}, 1fr);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@media (min-width: ${breakpoints.lg}px) {
|
|
23
|
+
grid-template-columns: repeat(
|
|
24
|
+
${columns.lg || columns.md || columns.sm || 1},
|
|
25
|
+
1fr
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@media (min-width: ${breakpoints.xl}px) {
|
|
30
|
+
grid-template-columns: repeat(
|
|
31
|
+
${columns.xl || columns.lg || columns.md || columns.sm || 1},
|
|
32
|
+
1fr
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/Grid.tsx
|
|
39
|
+
import { jsx } from "react/jsx-runtime";
|
|
40
|
+
var Container = styled(Box)`
|
|
41
|
+
${(props) => getResponsiveStyles(props.$columns)}
|
|
42
|
+
`;
|
|
43
|
+
var Grid = ({
|
|
44
|
+
columns = 1,
|
|
45
|
+
gap = 400,
|
|
46
|
+
rowGap,
|
|
47
|
+
columnGap,
|
|
48
|
+
children,
|
|
49
|
+
className
|
|
50
|
+
}) => {
|
|
51
|
+
return /* @__PURE__ */ jsx(
|
|
52
|
+
Container,
|
|
53
|
+
{
|
|
54
|
+
display: "grid",
|
|
55
|
+
rowGap: rowGap ?? gap,
|
|
56
|
+
columnGap: columnGap ?? gap,
|
|
57
|
+
$columns: columns,
|
|
58
|
+
className,
|
|
59
|
+
children
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
var Grid_default = Grid;
|
|
64
|
+
|
|
65
|
+
// src/GridTypes.ts
|
|
66
|
+
import "react";
|
|
67
|
+
|
|
68
|
+
// src/constants.ts
|
|
69
|
+
var BREAKPOINTS = {
|
|
70
|
+
sm: 640,
|
|
71
|
+
md: 768,
|
|
72
|
+
lg: 1024,
|
|
73
|
+
xl: 1280
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// src/index.ts
|
|
77
|
+
var index_default = Grid_default;
|
|
78
|
+
export {
|
|
79
|
+
BREAKPOINTS,
|
|
80
|
+
Grid_default as Grid,
|
|
81
|
+
index_default as default
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/Grid.tsx","../../src/utils.ts","../../src/GridTypes.ts","../../src/constants.ts","../../src/index.ts"],"sourcesContent":["import React from \"react\";\nimport styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport type { ContainerProps, GridProps } from \"./GridTypes\";\nimport { getResponsiveStyles } from \"./utils\";\n\nconst Container = styled(Box)<ContainerProps>`\n ${(props) => getResponsiveStyles(props.$columns)}\n`;\n\nconst Grid: React.FC<GridProps> = ({\n columns = 1,\n gap = 400,\n rowGap,\n columnGap,\n children,\n className,\n}) => {\n return (\n <Container\n display=\"grid\"\n rowGap={rowGap ?? gap}\n columnGap={columnGap ?? gap}\n $columns={columns}\n className={className}\n >\n {children}\n </Container>\n );\n};\n\nexport default Grid;\n","import type { ResponsiveValue } from \"./GridTypes\";\nimport { css } from \"styled-components\";\nimport { breakpoints } from \"@sproutsocial/seeds-react-theme/src/light/theme\";\n\nexport const getResponsiveStyles = (columns: ResponsiveValue = 1) => {\n if (typeof columns === \"number\") {\n return css`\n grid-template-columns: repeat(${columns}, 1fr);\n `;\n }\n\n return css`\n grid-template-columns: repeat(${columns.sm || 1}, 1fr);\n\n @media (min-width: ${breakpoints.md}px) {\n grid-template-columns: repeat(${columns.md || columns.sm || 1}, 1fr);\n }\n\n @media (min-width: ${breakpoints.lg}px) {\n grid-template-columns: repeat(\n ${columns.lg || columns.md || columns.sm || 1},\n 1fr\n );\n }\n\n @media (min-width: ${breakpoints.xl}px) {\n grid-template-columns: repeat(\n ${columns.xl || columns.lg || columns.md || columns.sm || 1},\n 1fr\n );\n }\n `;\n};\n","import * as React from \"react\";\nimport type { TypeSpace } from \"@sproutsocial/seeds-react-theme\";\n\nexport type ResponsiveValue =\n | number\n | {\n sm?: number;\n md?: number;\n lg?: number;\n xl?: number;\n };\n\n/**\n * Gap value that can be either:\n * - A space scale value from the theme (0, 100, 200, 300, 350, 400, 450, 500, 600)\n * - A pixel string value (e.g., \"16px\", \"20px\")\n */\nexport type GapValue = keyof TypeSpace | `${number}px`;\n\nexport interface ContainerProps {\n $columns?: ResponsiveValue;\n}\n\nexport interface GridProps {\n /** Number of columns (can be responsive) */\n columns?: ResponsiveValue;\n /** Gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., \"16px\") */\n gap?: GapValue;\n /** Row gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., \"16px\") */\n rowGap?: GapValue;\n /** Column gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., \"16px\") */\n columnGap?: GapValue;\n /** Children elements to display in the grid */\n children?: React.ReactNode;\n /** Custom className */\n className?: string;\n}\n","export const BREAKPOINTS = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n} as const;\n","import Grid from \"./Grid\";\n\nexport default Grid;\nexport { Grid };\nexport * from \"./GridTypes\";\nexport { BREAKPOINTS } from \"./constants\";\n"],"mappings":";AAAA,OAAkB;AAClB,OAAO,YAAY;AACnB,OAAO,SAAS;;;ACDhB,SAAS,WAAW;AACpB,SAAS,mBAAmB;AAErB,IAAM,sBAAsB,CAAC,UAA2B,MAAM;AACnE,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,sCAC2B,OAAO;AAAA;AAAA,EAE3C;AAEA,SAAO;AAAA,oCAC2B,QAAQ,MAAM,CAAC;AAAA;AAAA,yBAE1B,YAAY,EAAE;AAAA,sCACD,QAAQ,MAAM,QAAQ,MAAM,CAAC;AAAA;AAAA;AAAA,yBAG1C,YAAY,EAAE;AAAA;AAAA,UAE7B,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,yBAK5B,YAAY,EAAE;AAAA;AAAA,UAE7B,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAKnE;;;ADbI;AAbJ,IAAM,YAAY,OAAO,GAAG;AAAA,IACxB,CAAC,UAAU,oBAAoB,MAAM,QAAQ,CAAC;AAAA;AAGlD,IAAM,OAA4B,CAAC;AAAA,EACjC,UAAU;AAAA,EACV,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,QAAQ,UAAU;AAAA,MAClB,WAAW,aAAa;AAAA,MACxB,UAAU;AAAA,MACV;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,eAAQ;;;AE/Bf,OAAuB;;;ACAhB,IAAM,cAAc;AAAA,EACzB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;;;ACHA,IAAO,gBAAQ;","names":[]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { TypeSpace } from '@sproutsocial/seeds-react-theme';
|
|
4
|
+
|
|
5
|
+
type ResponsiveValue = number | {
|
|
6
|
+
sm?: number;
|
|
7
|
+
md?: number;
|
|
8
|
+
lg?: number;
|
|
9
|
+
xl?: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Gap value that can be either:
|
|
13
|
+
* - A space scale value from the theme (0, 100, 200, 300, 350, 400, 450, 500, 600)
|
|
14
|
+
* - A pixel string value (e.g., "16px", "20px")
|
|
15
|
+
*/
|
|
16
|
+
type GapValue = keyof TypeSpace | `${number}px`;
|
|
17
|
+
interface ContainerProps {
|
|
18
|
+
$columns?: ResponsiveValue;
|
|
19
|
+
}
|
|
20
|
+
interface GridProps {
|
|
21
|
+
/** Number of columns (can be responsive) */
|
|
22
|
+
columns?: ResponsiveValue;
|
|
23
|
+
/** Gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., "16px") */
|
|
24
|
+
gap?: GapValue;
|
|
25
|
+
/** Row gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., "16px") */
|
|
26
|
+
rowGap?: GapValue;
|
|
27
|
+
/** Column gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., "16px") */
|
|
28
|
+
columnGap?: GapValue;
|
|
29
|
+
/** Children elements to display in the grid */
|
|
30
|
+
children?: React.ReactNode;
|
|
31
|
+
/** Custom className */
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
declare const Grid: React__default.FC<GridProps>;
|
|
36
|
+
|
|
37
|
+
declare const BREAKPOINTS: {
|
|
38
|
+
readonly sm: 640;
|
|
39
|
+
readonly md: 768;
|
|
40
|
+
readonly lg: 1024;
|
|
41
|
+
readonly xl: 1280;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { BREAKPOINTS, type ContainerProps, type GapValue, Grid, type GridProps, type ResponsiveValue, Grid as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { TypeSpace } from '@sproutsocial/seeds-react-theme';
|
|
4
|
+
|
|
5
|
+
type ResponsiveValue = number | {
|
|
6
|
+
sm?: number;
|
|
7
|
+
md?: number;
|
|
8
|
+
lg?: number;
|
|
9
|
+
xl?: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Gap value that can be either:
|
|
13
|
+
* - A space scale value from the theme (0, 100, 200, 300, 350, 400, 450, 500, 600)
|
|
14
|
+
* - A pixel string value (e.g., "16px", "20px")
|
|
15
|
+
*/
|
|
16
|
+
type GapValue = keyof TypeSpace | `${number}px`;
|
|
17
|
+
interface ContainerProps {
|
|
18
|
+
$columns?: ResponsiveValue;
|
|
19
|
+
}
|
|
20
|
+
interface GridProps {
|
|
21
|
+
/** Number of columns (can be responsive) */
|
|
22
|
+
columns?: ResponsiveValue;
|
|
23
|
+
/** Gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., "16px") */
|
|
24
|
+
gap?: GapValue;
|
|
25
|
+
/** Row gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., "16px") */
|
|
26
|
+
rowGap?: GapValue;
|
|
27
|
+
/** Column gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., "16px") */
|
|
28
|
+
columnGap?: GapValue;
|
|
29
|
+
/** Children elements to display in the grid */
|
|
30
|
+
children?: React.ReactNode;
|
|
31
|
+
/** Custom className */
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
declare const Grid: React__default.FC<GridProps>;
|
|
36
|
+
|
|
37
|
+
declare const BREAKPOINTS: {
|
|
38
|
+
readonly sm: 640;
|
|
39
|
+
readonly md: 768;
|
|
40
|
+
readonly lg: 1024;
|
|
41
|
+
readonly xl: 1280;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { BREAKPOINTS, type ContainerProps, type GapValue, Grid, type GridProps, type ResponsiveValue, Grid as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
BREAKPOINTS: () => BREAKPOINTS,
|
|
34
|
+
Grid: () => Grid_default,
|
|
35
|
+
default: () => index_default
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(index_exports);
|
|
38
|
+
|
|
39
|
+
// src/Grid.tsx
|
|
40
|
+
var import_react = require("react");
|
|
41
|
+
var import_styled_components2 = __toESM(require("styled-components"));
|
|
42
|
+
var import_seeds_react_box = __toESM(require("@sproutsocial/seeds-react-box"));
|
|
43
|
+
|
|
44
|
+
// src/utils.ts
|
|
45
|
+
var import_styled_components = require("styled-components");
|
|
46
|
+
var import_theme = require("@sproutsocial/seeds-react-theme/src/light/theme");
|
|
47
|
+
var getResponsiveStyles = (columns = 1) => {
|
|
48
|
+
if (typeof columns === "number") {
|
|
49
|
+
return import_styled_components.css`
|
|
50
|
+
grid-template-columns: repeat(${columns}, 1fr);
|
|
51
|
+
`;
|
|
52
|
+
}
|
|
53
|
+
return import_styled_components.css`
|
|
54
|
+
grid-template-columns: repeat(${columns.sm || 1}, 1fr);
|
|
55
|
+
|
|
56
|
+
@media (min-width: ${import_theme.breakpoints.md}px) {
|
|
57
|
+
grid-template-columns: repeat(${columns.md || columns.sm || 1}, 1fr);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@media (min-width: ${import_theme.breakpoints.lg}px) {
|
|
61
|
+
grid-template-columns: repeat(
|
|
62
|
+
${columns.lg || columns.md || columns.sm || 1},
|
|
63
|
+
1fr
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@media (min-width: ${import_theme.breakpoints.xl}px) {
|
|
68
|
+
grid-template-columns: repeat(
|
|
69
|
+
${columns.xl || columns.lg || columns.md || columns.sm || 1},
|
|
70
|
+
1fr
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// src/Grid.tsx
|
|
77
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
78
|
+
var Container = (0, import_styled_components2.default)(import_seeds_react_box.default)`
|
|
79
|
+
${(props) => getResponsiveStyles(props.$columns)}
|
|
80
|
+
`;
|
|
81
|
+
var Grid = ({
|
|
82
|
+
columns = 1,
|
|
83
|
+
gap = 400,
|
|
84
|
+
rowGap,
|
|
85
|
+
columnGap,
|
|
86
|
+
children,
|
|
87
|
+
className
|
|
88
|
+
}) => {
|
|
89
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
90
|
+
Container,
|
|
91
|
+
{
|
|
92
|
+
display: "grid",
|
|
93
|
+
rowGap: rowGap ?? gap,
|
|
94
|
+
columnGap: columnGap ?? gap,
|
|
95
|
+
$columns: columns,
|
|
96
|
+
className,
|
|
97
|
+
children
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
var Grid_default = Grid;
|
|
102
|
+
|
|
103
|
+
// src/GridTypes.ts
|
|
104
|
+
var React2 = require("react");
|
|
105
|
+
|
|
106
|
+
// src/constants.ts
|
|
107
|
+
var BREAKPOINTS = {
|
|
108
|
+
sm: 640,
|
|
109
|
+
md: 768,
|
|
110
|
+
lg: 1024,
|
|
111
|
+
xl: 1280
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// src/index.ts
|
|
115
|
+
var index_default = Grid_default;
|
|
116
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
117
|
+
0 && (module.exports = {
|
|
118
|
+
BREAKPOINTS,
|
|
119
|
+
Grid
|
|
120
|
+
});
|
|
121
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Grid.tsx","../src/utils.ts","../src/GridTypes.ts","../src/constants.ts"],"sourcesContent":["import Grid from \"./Grid\";\n\nexport default Grid;\nexport { Grid };\nexport * from \"./GridTypes\";\nexport { BREAKPOINTS } from \"./constants\";\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport type { ContainerProps, GridProps } from \"./GridTypes\";\nimport { getResponsiveStyles } from \"./utils\";\n\nconst Container = styled(Box)<ContainerProps>`\n ${(props) => getResponsiveStyles(props.$columns)}\n`;\n\nconst Grid: React.FC<GridProps> = ({\n columns = 1,\n gap = 400,\n rowGap,\n columnGap,\n children,\n className,\n}) => {\n return (\n <Container\n display=\"grid\"\n rowGap={rowGap ?? gap}\n columnGap={columnGap ?? gap}\n $columns={columns}\n className={className}\n >\n {children}\n </Container>\n );\n};\n\nexport default Grid;\n","import type { ResponsiveValue } from \"./GridTypes\";\nimport { css } from \"styled-components\";\nimport { breakpoints } from \"@sproutsocial/seeds-react-theme/src/light/theme\";\n\nexport const getResponsiveStyles = (columns: ResponsiveValue = 1) => {\n if (typeof columns === \"number\") {\n return css`\n grid-template-columns: repeat(${columns}, 1fr);\n `;\n }\n\n return css`\n grid-template-columns: repeat(${columns.sm || 1}, 1fr);\n\n @media (min-width: ${breakpoints.md}px) {\n grid-template-columns: repeat(${columns.md || columns.sm || 1}, 1fr);\n }\n\n @media (min-width: ${breakpoints.lg}px) {\n grid-template-columns: repeat(\n ${columns.lg || columns.md || columns.sm || 1},\n 1fr\n );\n }\n\n @media (min-width: ${breakpoints.xl}px) {\n grid-template-columns: repeat(\n ${columns.xl || columns.lg || columns.md || columns.sm || 1},\n 1fr\n );\n }\n `;\n};\n","import * as React from \"react\";\nimport type { TypeSpace } from \"@sproutsocial/seeds-react-theme\";\n\nexport type ResponsiveValue =\n | number\n | {\n sm?: number;\n md?: number;\n lg?: number;\n xl?: number;\n };\n\n/**\n * Gap value that can be either:\n * - A space scale value from the theme (0, 100, 200, 300, 350, 400, 450, 500, 600)\n * - A pixel string value (e.g., \"16px\", \"20px\")\n */\nexport type GapValue = keyof TypeSpace | `${number}px`;\n\nexport interface ContainerProps {\n $columns?: ResponsiveValue;\n}\n\nexport interface GridProps {\n /** Number of columns (can be responsive) */\n columns?: ResponsiveValue;\n /** Gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., \"16px\") */\n gap?: GapValue;\n /** Row gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., \"16px\") */\n rowGap?: GapValue;\n /** Column gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., \"16px\") */\n columnGap?: GapValue;\n /** Children elements to display in the grid */\n children?: React.ReactNode;\n /** Custom className */\n className?: string;\n}\n","export const BREAKPOINTS = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAkB;AAClB,IAAAA,4BAAmB;AACnB,6BAAgB;;;ACDhB,+BAAoB;AACpB,mBAA4B;AAErB,IAAM,sBAAsB,CAAC,UAA2B,MAAM;AACnE,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,sCAC2B,OAAO;AAAA;AAAA,EAE3C;AAEA,SAAO;AAAA,oCAC2B,QAAQ,MAAM,CAAC;AAAA;AAAA,yBAE1B,yBAAY,EAAE;AAAA,sCACD,QAAQ,MAAM,QAAQ,MAAM,CAAC;AAAA;AAAA;AAAA,yBAG1C,yBAAY,EAAE;AAAA;AAAA,UAE7B,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,yBAK5B,yBAAY,EAAE;AAAA;AAAA,UAE7B,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAKnE;;;ADbI;AAbJ,IAAM,gBAAY,0BAAAC,SAAO,uBAAAC,OAAG;AAAA,IACxB,CAAC,UAAU,oBAAoB,MAAM,QAAQ,CAAC;AAAA;AAGlD,IAAM,OAA4B,CAAC;AAAA,EACjC,UAAU;AAAA,EACV,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,QAAQ,UAAU;AAAA,MAClB,WAAW,aAAa;AAAA,MACxB,UAAU;AAAA,MACV;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,eAAQ;;;AE/Bf,IAAAC,SAAuB;;;ACAhB,IAAM,cAAc;AAAA,EACzB,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AACN;;;AJHA,IAAO,gBAAQ;","names":["import_styled_components","styled","Box","React"]}
|
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sproutsocial/seeds-react-grid",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Seeds React Grid",
|
|
5
|
+
"author": "Sprout Social, Inc.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"module": "dist/esm/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsup --dts",
|
|
12
|
+
"build:debug": "tsup --dts --metafile",
|
|
13
|
+
"dev": "tsup --watch --dts",
|
|
14
|
+
"clean": "rm -rf .turbo dist",
|
|
15
|
+
"clean:modules": "rm -rf node_modules",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"test": "jest",
|
|
18
|
+
"test:watch": "jest --watch --coverage=false"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@sproutsocial/seeds-react-box": "^1.1.14",
|
|
22
|
+
"@sproutsocial/seeds-react-theme": "^3.0.0",
|
|
23
|
+
"@sproutsocial/seeds-react-system-props": "^3.0.1"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/react": "^18.0.0",
|
|
27
|
+
"@types/styled-components": "^5.1.26",
|
|
28
|
+
"@sproutsocial/eslint-config-seeds": "*",
|
|
29
|
+
"react": "^18.0.0",
|
|
30
|
+
"styled-components": "^5.2.3",
|
|
31
|
+
"tsup": "^8.3.4",
|
|
32
|
+
"typescript": "^5.6.2",
|
|
33
|
+
"@sproutsocial/seeds-tsconfig": "*",
|
|
34
|
+
"@sproutsocial/seeds-testing": "*",
|
|
35
|
+
"@sproutsocial/seeds-react-testing-library": "*"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"styled-components": "^5.2.3"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import COLORS from "@sproutsocial/seeds-color";
|
|
4
|
+
import Grid from "./Grid";
|
|
5
|
+
import type { GridProps } from "./GridTypes";
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: "Components/Grid",
|
|
9
|
+
component: Grid,
|
|
10
|
+
argTypes: {
|
|
11
|
+
columns: {
|
|
12
|
+
control: { type: "number", min: 1, max: 12, step: 1 },
|
|
13
|
+
description:
|
|
14
|
+
"Number of columns in the grid (can be a number or responsive object)",
|
|
15
|
+
},
|
|
16
|
+
gap: {
|
|
17
|
+
control: { type: "select" },
|
|
18
|
+
options: [
|
|
19
|
+
0,
|
|
20
|
+
100,
|
|
21
|
+
200,
|
|
22
|
+
300,
|
|
23
|
+
350,
|
|
24
|
+
400,
|
|
25
|
+
450,
|
|
26
|
+
500,
|
|
27
|
+
600,
|
|
28
|
+
"16px",
|
|
29
|
+
"20px",
|
|
30
|
+
"24px",
|
|
31
|
+
],
|
|
32
|
+
description:
|
|
33
|
+
"Gap between all grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., '16px')",
|
|
34
|
+
},
|
|
35
|
+
rowGap: {
|
|
36
|
+
control: { type: "select" },
|
|
37
|
+
options: [
|
|
38
|
+
0,
|
|
39
|
+
100,
|
|
40
|
+
200,
|
|
41
|
+
300,
|
|
42
|
+
350,
|
|
43
|
+
400,
|
|
44
|
+
450,
|
|
45
|
+
500,
|
|
46
|
+
600,
|
|
47
|
+
"16px",
|
|
48
|
+
"20px",
|
|
49
|
+
"24px",
|
|
50
|
+
],
|
|
51
|
+
description:
|
|
52
|
+
"Optional: Override gap for rows only. Use theme.space scale or pixel string (e.g., '16px')",
|
|
53
|
+
table: {
|
|
54
|
+
defaultValue: { summary: "undefined" },
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
columnGap: {
|
|
58
|
+
control: { type: "select" },
|
|
59
|
+
options: [
|
|
60
|
+
0,
|
|
61
|
+
100,
|
|
62
|
+
200,
|
|
63
|
+
300,
|
|
64
|
+
350,
|
|
65
|
+
400,
|
|
66
|
+
450,
|
|
67
|
+
500,
|
|
68
|
+
600,
|
|
69
|
+
"16px",
|
|
70
|
+
"20px",
|
|
71
|
+
"24px",
|
|
72
|
+
],
|
|
73
|
+
description:
|
|
74
|
+
"Optional: Override gap for columns only. Use theme.space scale or pixel string (e.g., '16px')",
|
|
75
|
+
table: {
|
|
76
|
+
defaultValue: { summary: "undefined" },
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
children: {
|
|
80
|
+
control: false,
|
|
81
|
+
description: "Child elements to display in the grid",
|
|
82
|
+
},
|
|
83
|
+
className: {
|
|
84
|
+
control: "text",
|
|
85
|
+
description: "Custom CSS class name",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
} satisfies Meta<typeof Grid>;
|
|
89
|
+
|
|
90
|
+
export default meta;
|
|
91
|
+
type Story = StoryObj<typeof meta>;
|
|
92
|
+
|
|
93
|
+
type PlaygroundArgs = GridProps & {
|
|
94
|
+
columnsSm?: number;
|
|
95
|
+
columnsMd?: number;
|
|
96
|
+
columnsLg?: number;
|
|
97
|
+
columnsXl?: number;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// Helper component for grid items
|
|
101
|
+
const GridItem = ({
|
|
102
|
+
children,
|
|
103
|
+
color = COLORS.COLOR_BLUE_600,
|
|
104
|
+
}: {
|
|
105
|
+
children: React.ReactNode;
|
|
106
|
+
color?: string;
|
|
107
|
+
}) => (
|
|
108
|
+
<div
|
|
109
|
+
style={{
|
|
110
|
+
backgroundColor: color,
|
|
111
|
+
padding: "20px",
|
|
112
|
+
borderRadius: "8px",
|
|
113
|
+
color: "white",
|
|
114
|
+
display: "flex",
|
|
115
|
+
alignItems: "center",
|
|
116
|
+
justifyContent: "center",
|
|
117
|
+
minHeight: "100px",
|
|
118
|
+
fontWeight: "bold",
|
|
119
|
+
}}
|
|
120
|
+
>
|
|
121
|
+
{children}
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
export const Playground: StoryObj<PlaygroundArgs> = {
|
|
126
|
+
name: "Playground",
|
|
127
|
+
args: {
|
|
128
|
+
gap: 400,
|
|
129
|
+
columnsSm: 1,
|
|
130
|
+
columnsMd: 2,
|
|
131
|
+
columnsLg: 3,
|
|
132
|
+
columnsXl: 4,
|
|
133
|
+
},
|
|
134
|
+
argTypes: {
|
|
135
|
+
columnsSm: {
|
|
136
|
+
control: { type: "number", min: 1, max: 12, step: 1 },
|
|
137
|
+
name: "Columns (sm - 640px)",
|
|
138
|
+
description: "Number of columns on small screens (640px and up)",
|
|
139
|
+
},
|
|
140
|
+
columnsMd: {
|
|
141
|
+
control: { type: "number", min: 1, max: 12, step: 1 },
|
|
142
|
+
name: "Columns (md - 768px)",
|
|
143
|
+
description: "Number of columns on medium screens (768px and up)",
|
|
144
|
+
},
|
|
145
|
+
columnsLg: {
|
|
146
|
+
control: { type: "number", min: 1, max: 12, step: 1 },
|
|
147
|
+
name: "Columns (lg - 1024px)",
|
|
148
|
+
description: "Number of columns on large screens (1024px and up)",
|
|
149
|
+
},
|
|
150
|
+
columnsXl: {
|
|
151
|
+
control: { type: "number", min: 1, max: 12, step: 1 },
|
|
152
|
+
name: "Columns (xl - 1280px)",
|
|
153
|
+
description: "Number of columns on xl screens (1280px and up)",
|
|
154
|
+
},
|
|
155
|
+
columns: {
|
|
156
|
+
control: false,
|
|
157
|
+
table: { disable: true },
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
render: (args) => {
|
|
161
|
+
const {
|
|
162
|
+
rowGap,
|
|
163
|
+
columnGap,
|
|
164
|
+
columnsSm,
|
|
165
|
+
columnsMd,
|
|
166
|
+
columnsLg,
|
|
167
|
+
columnsXl,
|
|
168
|
+
...restArgs
|
|
169
|
+
} = args;
|
|
170
|
+
const gridProps = {
|
|
171
|
+
...restArgs,
|
|
172
|
+
columns: {
|
|
173
|
+
sm: columnsSm,
|
|
174
|
+
md: columnsMd,
|
|
175
|
+
lg: columnsLg,
|
|
176
|
+
xl: columnsXl,
|
|
177
|
+
},
|
|
178
|
+
...(rowGap && (typeof rowGap === "string" || rowGap > 0)
|
|
179
|
+
? { rowGap }
|
|
180
|
+
: {}),
|
|
181
|
+
...(columnGap && (typeof columnGap === "string" || columnGap > 0)
|
|
182
|
+
? { columnGap }
|
|
183
|
+
: {}),
|
|
184
|
+
};
|
|
185
|
+
return (
|
|
186
|
+
<Grid {...gridProps}>
|
|
187
|
+
<GridItem color={COLORS.COLOR_BLUE_600}>Item 1</GridItem>
|
|
188
|
+
<GridItem color={COLORS.COLOR_PURPLE_600}>Item 2</GridItem>
|
|
189
|
+
<GridItem color={COLORS.COLOR_TEAL_600}>Item 3</GridItem>
|
|
190
|
+
<GridItem color={COLORS.COLOR_RED_600}>Item 4</GridItem>
|
|
191
|
+
<GridItem color={COLORS.COLOR_ORANGE_600}>Item 5</GridItem>
|
|
192
|
+
<GridItem color={COLORS.COLOR_MAGENTA_600}>Item 6</GridItem>
|
|
193
|
+
<GridItem color={COLORS.COLOR_AQUA_600}>Item 7</GridItem>
|
|
194
|
+
<GridItem color={COLORS.COLOR_PINK_600}>Item 8</GridItem>
|
|
195
|
+
<GridItem color={COLORS.COLOR_GREEN_600}>Item 9</GridItem>
|
|
196
|
+
</Grid>
|
|
197
|
+
);
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
export const NestedGrid: Story = {
|
|
202
|
+
name: "Nested Grid Layout",
|
|
203
|
+
args: {
|
|
204
|
+
gap: 400,
|
|
205
|
+
},
|
|
206
|
+
render: (args) => {
|
|
207
|
+
return (
|
|
208
|
+
<Grid columns={1} gap={args.gap}>
|
|
209
|
+
<Grid columns={1} gap={350}>
|
|
210
|
+
<GridItem color={COLORS.COLOR_BLUE_600}>Row 1, Column 1</GridItem>
|
|
211
|
+
</Grid>
|
|
212
|
+
|
|
213
|
+
<Grid columns={{ sm: 1, md: 2 }} gap={350}>
|
|
214
|
+
<GridItem color={COLORS.COLOR_PURPLE_600}>Row 2, Column 1</GridItem>
|
|
215
|
+
<GridItem color={COLORS.COLOR_PURPLE_600}>Row 2, Column 2</GridItem>
|
|
216
|
+
</Grid>
|
|
217
|
+
|
|
218
|
+
<Grid columns={{ sm: 1, md: 3 }} gap={350}>
|
|
219
|
+
<GridItem color={COLORS.COLOR_TEAL_600}>Row 3, Column 1</GridItem>
|
|
220
|
+
<GridItem color={COLORS.COLOR_TEAL_600}>Row 3, Column 2</GridItem>
|
|
221
|
+
<GridItem color={COLORS.COLOR_TEAL_600}>Row 3, Column 3</GridItem>
|
|
222
|
+
</Grid>
|
|
223
|
+
|
|
224
|
+
<Grid columns={1} gap={350}>
|
|
225
|
+
<GridItem color={COLORS.COLOR_RED_600}>Row 4, Column 1</GridItem>
|
|
226
|
+
</Grid>
|
|
227
|
+
</Grid>
|
|
228
|
+
);
|
|
229
|
+
},
|
|
230
|
+
};
|
package/src/Grid.tsx
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import styled from "styled-components";
|
|
3
|
+
import Box from "@sproutsocial/seeds-react-box";
|
|
4
|
+
import type { ContainerProps, GridProps } from "./GridTypes";
|
|
5
|
+
import { getResponsiveStyles } from "./utils";
|
|
6
|
+
|
|
7
|
+
const Container = styled(Box)<ContainerProps>`
|
|
8
|
+
${(props) => getResponsiveStyles(props.$columns)}
|
|
9
|
+
`;
|
|
10
|
+
|
|
11
|
+
const Grid: React.FC<GridProps> = ({
|
|
12
|
+
columns = 1,
|
|
13
|
+
gap = 400,
|
|
14
|
+
rowGap,
|
|
15
|
+
columnGap,
|
|
16
|
+
children,
|
|
17
|
+
className,
|
|
18
|
+
}) => {
|
|
19
|
+
return (
|
|
20
|
+
<Container
|
|
21
|
+
display="grid"
|
|
22
|
+
rowGap={rowGap ?? gap}
|
|
23
|
+
columnGap={columnGap ?? gap}
|
|
24
|
+
$columns={columns}
|
|
25
|
+
className={className}
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
</Container>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default Grid;
|
package/src/GridTypes.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { TypeSpace } from "@sproutsocial/seeds-react-theme";
|
|
3
|
+
|
|
4
|
+
export type ResponsiveValue =
|
|
5
|
+
| number
|
|
6
|
+
| {
|
|
7
|
+
sm?: number;
|
|
8
|
+
md?: number;
|
|
9
|
+
lg?: number;
|
|
10
|
+
xl?: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Gap value that can be either:
|
|
15
|
+
* - A space scale value from the theme (0, 100, 200, 300, 350, 400, 450, 500, 600)
|
|
16
|
+
* - A pixel string value (e.g., "16px", "20px")
|
|
17
|
+
*/
|
|
18
|
+
export type GapValue = keyof TypeSpace | `${number}px`;
|
|
19
|
+
|
|
20
|
+
export interface ContainerProps {
|
|
21
|
+
$columns?: ResponsiveValue;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface GridProps {
|
|
25
|
+
/** Number of columns (can be responsive) */
|
|
26
|
+
columns?: ResponsiveValue;
|
|
27
|
+
/** Gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., "16px") */
|
|
28
|
+
gap?: GapValue;
|
|
29
|
+
/** Row gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., "16px") */
|
|
30
|
+
rowGap?: GapValue;
|
|
31
|
+
/** Column gap between grid items. Use theme.space scale (0, 100, 200, 300, 350, 400, 450, 500, 600) or pixel string (e.g., "16px") */
|
|
32
|
+
columnGap?: GapValue;
|
|
33
|
+
/** Children elements to display in the grid */
|
|
34
|
+
children?: React.ReactNode;
|
|
35
|
+
/** Custom className */
|
|
36
|
+
className?: string;
|
|
37
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import Grid from "../Grid";
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
5
|
+
function GridTypes() {
|
|
6
|
+
return (
|
|
7
|
+
<>
|
|
8
|
+
{/* Basic usage */}
|
|
9
|
+
<Grid>
|
|
10
|
+
<div>Item</div>
|
|
11
|
+
</Grid>
|
|
12
|
+
|
|
13
|
+
{/* With fixed columns */}
|
|
14
|
+
<Grid columns={3}>
|
|
15
|
+
<div>Item</div>
|
|
16
|
+
</Grid>
|
|
17
|
+
|
|
18
|
+
{/* With responsive columns */}
|
|
19
|
+
<Grid columns={{ sm: 1, md: 2, lg: 3, xl: 4 }}>
|
|
20
|
+
<div>Item</div>
|
|
21
|
+
</Grid>
|
|
22
|
+
|
|
23
|
+
{/* With gap using space scale */}
|
|
24
|
+
<Grid gap={450}>
|
|
25
|
+
<div>Item</div>
|
|
26
|
+
</Grid>
|
|
27
|
+
|
|
28
|
+
{/* With gap using pixel string */}
|
|
29
|
+
<Grid gap="24px">
|
|
30
|
+
<div>Item</div>
|
|
31
|
+
</Grid>
|
|
32
|
+
|
|
33
|
+
{/* With rowGap and columnGap using space scale */}
|
|
34
|
+
<Grid rowGap={500} columnGap={400}>
|
|
35
|
+
<div>Item</div>
|
|
36
|
+
</Grid>
|
|
37
|
+
|
|
38
|
+
{/* With rowGap and columnGap using pixel strings */}
|
|
39
|
+
<Grid rowGap="32px" columnGap="16px">
|
|
40
|
+
<div>Item</div>
|
|
41
|
+
</Grid>
|
|
42
|
+
|
|
43
|
+
{/* Mix of space scale and pixel strings */}
|
|
44
|
+
<Grid rowGap={450} columnGap="20px">
|
|
45
|
+
<div>Item</div>
|
|
46
|
+
</Grid>
|
|
47
|
+
|
|
48
|
+
{/* With all props */}
|
|
49
|
+
<Grid
|
|
50
|
+
columns={{ sm: 1, md: 2, lg: 3 }}
|
|
51
|
+
gap={400}
|
|
52
|
+
rowGap={450}
|
|
53
|
+
columnGap={350}
|
|
54
|
+
className="custom-grid"
|
|
55
|
+
>
|
|
56
|
+
<div>Item 1</div>
|
|
57
|
+
<div>Item 2</div>
|
|
58
|
+
</Grid>
|
|
59
|
+
|
|
60
|
+
{/* @ts-expect-error - invalid columns value */}
|
|
61
|
+
<Grid columns="invalid">
|
|
62
|
+
<div>Item</div>
|
|
63
|
+
</Grid>
|
|
64
|
+
|
|
65
|
+
{/* @ts-expect-error - invalid gap value */}
|
|
66
|
+
<Grid gap="invalid">
|
|
67
|
+
<div>Item</div>
|
|
68
|
+
</Grid>
|
|
69
|
+
|
|
70
|
+
{/* @ts-expect-error - invalid responsive columns */}
|
|
71
|
+
<Grid columns={{ xs: 1 }}>
|
|
72
|
+
<div>Item</div>
|
|
73
|
+
</Grid>
|
|
74
|
+
|
|
75
|
+
{/* @ts-expect-error - invalid gap value (not in SpaceScale and not a px string) */}
|
|
76
|
+
<Grid gap={16}>
|
|
77
|
+
<div>Item</div>
|
|
78
|
+
</Grid>
|
|
79
|
+
|
|
80
|
+
{/* @ts-expect-error - invalid rowGap value (not in SpaceScale and not a px string) */}
|
|
81
|
+
<Grid rowGap={20}>
|
|
82
|
+
<div>Item</div>
|
|
83
|
+
</Grid>
|
|
84
|
+
|
|
85
|
+
{/* @ts-expect-error - invalid columnGap value (not in SpaceScale and not a px string) */}
|
|
86
|
+
<Grid columnGap={25}>
|
|
87
|
+
<div>Item</div>
|
|
88
|
+
</Grid>
|
|
89
|
+
|
|
90
|
+
{/* @ts-expect-error - invalid gap string (must end with px) */}
|
|
91
|
+
<Grid gap="16rem">
|
|
92
|
+
<div>Item</div>
|
|
93
|
+
</Grid>
|
|
94
|
+
|
|
95
|
+
{/* @ts-expect-error - invalid gap string (must end with px) */}
|
|
96
|
+
<Grid gap="1em">
|
|
97
|
+
<div>Item</div>
|
|
98
|
+
</Grid>
|
|
99
|
+
</>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render } from "@sproutsocial/seeds-react-testing-library";
|
|
3
|
+
import Grid from "../Grid";
|
|
4
|
+
|
|
5
|
+
describe("Grid", () => {
|
|
6
|
+
it("should render properly", async () => {
|
|
7
|
+
const { container, runA11yCheck } = render(
|
|
8
|
+
<Grid>
|
|
9
|
+
<div>Item 1</div>
|
|
10
|
+
<div>Item 2</div>
|
|
11
|
+
</Grid>
|
|
12
|
+
);
|
|
13
|
+
expect(container).toBeTruthy();
|
|
14
|
+
await runA11yCheck();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should render children", () => {
|
|
18
|
+
const { getByText } = render(
|
|
19
|
+
<Grid>
|
|
20
|
+
<div>Item 1</div>
|
|
21
|
+
<div>Item 2</div>
|
|
22
|
+
<div>Item 3</div>
|
|
23
|
+
</Grid>
|
|
24
|
+
);
|
|
25
|
+
expect(getByText("Item 1")).toBeInTheDocument();
|
|
26
|
+
expect(getByText("Item 2")).toBeInTheDocument();
|
|
27
|
+
expect(getByText("Item 3")).toBeInTheDocument();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should apply custom className", () => {
|
|
31
|
+
const { container } = render(
|
|
32
|
+
<Grid className="custom-class">
|
|
33
|
+
<div>Item 1</div>
|
|
34
|
+
</Grid>
|
|
35
|
+
);
|
|
36
|
+
expect(container.firstChild).toHaveClass("custom-class");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should render with fixed columns", () => {
|
|
40
|
+
const { container } = render(
|
|
41
|
+
<Grid columns={3}>
|
|
42
|
+
<div>Item 1</div>
|
|
43
|
+
<div>Item 2</div>
|
|
44
|
+
<div>Item 3</div>
|
|
45
|
+
</Grid>
|
|
46
|
+
);
|
|
47
|
+
const gridElement = container.firstChild as HTMLElement;
|
|
48
|
+
const styles = window.getComputedStyle(gridElement);
|
|
49
|
+
expect(styles.display).toBe("grid");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should render with responsive columns", () => {
|
|
53
|
+
const { container } = render(
|
|
54
|
+
<Grid columns={{ sm: 1, md: 2, lg: 3, xl: 4 }}>
|
|
55
|
+
<div>Item 1</div>
|
|
56
|
+
<div>Item 2</div>
|
|
57
|
+
</Grid>
|
|
58
|
+
);
|
|
59
|
+
const gridElement = container.firstChild as HTMLElement;
|
|
60
|
+
const styles = window.getComputedStyle(gridElement);
|
|
61
|
+
expect(styles.display).toBe("grid");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should apply gap prop", () => {
|
|
65
|
+
const { container } = render(
|
|
66
|
+
<Grid gap={450}>
|
|
67
|
+
<div>Item 1</div>
|
|
68
|
+
<div>Item 2</div>
|
|
69
|
+
</Grid>
|
|
70
|
+
);
|
|
71
|
+
const gridElement = container.firstChild as HTMLElement;
|
|
72
|
+
const styles = window.getComputedStyle(gridElement);
|
|
73
|
+
expect(styles.rowGap).toBe("24px");
|
|
74
|
+
expect(styles.columnGap).toBe("24px");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should apply rowGap and columnGap props", () => {
|
|
78
|
+
const { container } = render(
|
|
79
|
+
<Grid rowGap={500} columnGap={400}>
|
|
80
|
+
<div>Item 1</div>
|
|
81
|
+
<div>Item 2</div>
|
|
82
|
+
</Grid>
|
|
83
|
+
);
|
|
84
|
+
const gridElement = container.firstChild as HTMLElement;
|
|
85
|
+
const styles = window.getComputedStyle(gridElement);
|
|
86
|
+
expect(styles.rowGap).toBe("32px");
|
|
87
|
+
expect(styles.columnGap).toBe("16px");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("should override gap with rowGap and columnGap", () => {
|
|
91
|
+
const { container } = render(
|
|
92
|
+
<Grid gap={400} rowGap={500} columnGap={300}>
|
|
93
|
+
<div>Item 1</div>
|
|
94
|
+
<div>Item 2</div>
|
|
95
|
+
</Grid>
|
|
96
|
+
);
|
|
97
|
+
const gridElement = container.firstChild as HTMLElement;
|
|
98
|
+
const styles = window.getComputedStyle(gridElement);
|
|
99
|
+
expect(styles.rowGap).toBe("32px");
|
|
100
|
+
expect(styles.columnGap).toBe("8px");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should default to 16px gap when no gap props provided", () => {
|
|
104
|
+
const { container } = render(
|
|
105
|
+
<Grid>
|
|
106
|
+
<div>Item 1</div>
|
|
107
|
+
</Grid>
|
|
108
|
+
);
|
|
109
|
+
const gridElement = container.firstChild as HTMLElement;
|
|
110
|
+
const styles = window.getComputedStyle(gridElement);
|
|
111
|
+
expect(styles.rowGap).toBe("16px");
|
|
112
|
+
expect(styles.columnGap).toBe("16px");
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it("should accept pixel string values for gap", () => {
|
|
116
|
+
const { container } = render(
|
|
117
|
+
<Grid gap="20px">
|
|
118
|
+
<div>Item 1</div>
|
|
119
|
+
<div>Item 2</div>
|
|
120
|
+
</Grid>
|
|
121
|
+
);
|
|
122
|
+
const gridElement = container.firstChild as HTMLElement;
|
|
123
|
+
const styles = window.getComputedStyle(gridElement);
|
|
124
|
+
expect(styles.rowGap).toBe("20px");
|
|
125
|
+
expect(styles.columnGap).toBe("20px");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("should accept pixel string values for rowGap and columnGap", () => {
|
|
129
|
+
const { container } = render(
|
|
130
|
+
<Grid rowGap="48px" columnGap="12px">
|
|
131
|
+
<div>Item 1</div>
|
|
132
|
+
<div>Item 2</div>
|
|
133
|
+
</Grid>
|
|
134
|
+
);
|
|
135
|
+
const gridElement = container.firstChild as HTMLElement;
|
|
136
|
+
const styles = window.getComputedStyle(gridElement);
|
|
137
|
+
expect(styles.rowGap).toBe("48px");
|
|
138
|
+
expect(styles.columnGap).toBe("12px");
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("should mix space scale and pixel string values", () => {
|
|
142
|
+
const { container } = render(
|
|
143
|
+
<Grid rowGap={450} columnGap="10px">
|
|
144
|
+
<div>Item 1</div>
|
|
145
|
+
<div>Item 2</div>
|
|
146
|
+
</Grid>
|
|
147
|
+
);
|
|
148
|
+
const gridElement = container.firstChild as HTMLElement;
|
|
149
|
+
const styles = window.getComputedStyle(gridElement);
|
|
150
|
+
expect(styles.rowGap).toBe("24px");
|
|
151
|
+
expect(styles.columnGap).toBe("10px");
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("should render with single column by default", () => {
|
|
155
|
+
const { container } = render(
|
|
156
|
+
<Grid>
|
|
157
|
+
<div>Item 1</div>
|
|
158
|
+
<div>Item 2</div>
|
|
159
|
+
</Grid>
|
|
160
|
+
);
|
|
161
|
+
const gridElement = container.firstChild as HTMLElement;
|
|
162
|
+
const styles = window.getComputedStyle(gridElement);
|
|
163
|
+
expect(styles.display).toBe("grid");
|
|
164
|
+
});
|
|
165
|
+
});
|
package/src/constants.ts
ADDED
package/src/index.ts
ADDED
package/src/styled.d.ts
ADDED
package/src/styles.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import styled, { css } from "styled-components";
|
|
2
|
+
import { COMMON, LAYOUT } from "@sproutsocial/seeds-react-system-props";
|
|
3
|
+
|
|
4
|
+
interface GridProps {
|
|
5
|
+
isLoading?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const Grid = styled.div<GridProps>`
|
|
9
|
+
display: block;
|
|
10
|
+
|
|
11
|
+
${(props) =>
|
|
12
|
+
props.isLoading &&
|
|
13
|
+
css`
|
|
14
|
+
visibility: hidden;
|
|
15
|
+
`}
|
|
16
|
+
|
|
17
|
+
${COMMON}
|
|
18
|
+
${LAYOUT}
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
export default Grid;
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ResponsiveValue } from "./GridTypes";
|
|
2
|
+
import { css } from "styled-components";
|
|
3
|
+
import { breakpoints } from "@sproutsocial/seeds-react-theme/src/light/theme";
|
|
4
|
+
|
|
5
|
+
export const getResponsiveStyles = (columns: ResponsiveValue = 1) => {
|
|
6
|
+
if (typeof columns === "number") {
|
|
7
|
+
return css`
|
|
8
|
+
grid-template-columns: repeat(${columns}, 1fr);
|
|
9
|
+
`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return css`
|
|
13
|
+
grid-template-columns: repeat(${columns.sm || 1}, 1fr);
|
|
14
|
+
|
|
15
|
+
@media (min-width: ${breakpoints.md}px) {
|
|
16
|
+
grid-template-columns: repeat(${columns.md || columns.sm || 1}, 1fr);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@media (min-width: ${breakpoints.lg}px) {
|
|
20
|
+
grid-template-columns: repeat(
|
|
21
|
+
${columns.lg || columns.md || columns.sm || 1},
|
|
22
|
+
1fr
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@media (min-width: ${breakpoints.xl}px) {
|
|
27
|
+
grid-template-columns: repeat(
|
|
28
|
+
${columns.xl || columns.lg || columns.md || columns.sm || 1},
|
|
29
|
+
1fr
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
`;
|
|
33
|
+
};
|
package/tsconfig.json
ADDED
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from "tsup";
|
|
2
|
+
|
|
3
|
+
export default defineConfig((options) => ({
|
|
4
|
+
entry: ["src/index.ts"],
|
|
5
|
+
format: ["cjs", "esm"],
|
|
6
|
+
clean: true,
|
|
7
|
+
legacyOutput: true,
|
|
8
|
+
dts: options.dts,
|
|
9
|
+
external: ["react"],
|
|
10
|
+
sourcemap: true,
|
|
11
|
+
metafile: options.metafile,
|
|
12
|
+
}));
|