@sproutsocial/seeds-react-stack 1.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 ADDED
@@ -0,0 +1,6 @@
1
+ # Node modules
2
+ node_modules/
3
+
4
+ # Build output
5
+ dist/
6
+ coverage/
package/.eslintrc.js ADDED
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ root: true,
3
+ extends: ["eslint-config-seeds/racine"],
4
+ };
@@ -0,0 +1,21 @@
1
+ yarn run v1.22.22
2
+ $ tsup --dts
3
+ CLI Building entry: src/index.ts
4
+ CLI Using tsconfig: tsconfig.json
5
+ CLI tsup v8.0.2
6
+ CLI Using tsup config: /home/runner/work/seeds/seeds/seeds-react/seeds-react-stack/tsup.config.ts
7
+ CLI Target: es2022
8
+ CLI Cleaning output folder
9
+ CJS Build start
10
+ ESM Build start
11
+ CJS dist/index.js 5.54 KB
12
+ CJS dist/index.js.map 8.36 KB
13
+ CJS ⚡️ Build success in 108ms
14
+ ESM dist/esm/index.js 3.75 KB
15
+ ESM dist/esm/index.js.map 8.25 KB
16
+ ESM ⚡️ Build success in 115ms
17
+ DTS Build start
18
+ DTS ⚡️ Build success in 25718ms
19
+ DTS dist/index.d.ts 1.02 KB
20
+ DTS dist/index.d.mts 1.02 KB
21
+ Done in 34.50s.
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @sproutsocial/seeds-react-stack
2
+
3
+ ## 1.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - bd8d03d: Migrate Stack to its own seeds-react-stack component
@@ -0,0 +1,140 @@
1
+ // src/Stack.tsx
2
+ import "react";
3
+ import { Children } from "react";
4
+
5
+ // src/utils.ts
6
+ import { theme } from "@sproutsocial/seeds-react-theme";
7
+ var breakpoints = theme.breakpoints;
8
+ var LENGTH = breakpoints.length + 1;
9
+ var normalizeResponsiveProp = (value) => {
10
+ if (["string", "number"].includes(typeof value)) {
11
+ return Array(LENGTH).fill(value);
12
+ }
13
+ if (value.length) {
14
+ switch (value.length) {
15
+ case 1:
16
+ return Array(LENGTH).fill(value[0]);
17
+ case 2:
18
+ return [value[0], ...Array(LENGTH - 1).fill(value[1])];
19
+ case 3:
20
+ return [value[0], value[1], ...Array(LENGTH - 2).fill(value[2])];
21
+ case 4:
22
+ return [
23
+ value[0],
24
+ value[1],
25
+ value[2],
26
+ ...Array(LENGTH - 3).fill(value[3])
27
+ ];
28
+ case 5:
29
+ return value;
30
+ default:
31
+ throw new Error(
32
+ `Invalid responsive prop length: ${JSON.stringify(value)}`
33
+ );
34
+ }
35
+ } else {
36
+ throw new Error(`Invalid responsive prop type: ${JSON.stringify(value)}`);
37
+ }
38
+ };
39
+
40
+ // src/Stack.tsx
41
+ import Box from "@sproutsocial/seeds-react-box";
42
+ import { jsx } from "react/jsx-runtime";
43
+ import { createElement } from "react";
44
+ var stackStyles = {
45
+ horizontal: {
46
+ left: {
47
+ alignItems: "center"
48
+ },
49
+ center: {
50
+ alignItems: "center",
51
+ justifyContent: "center"
52
+ },
53
+ right: {
54
+ alignItems: "center",
55
+ justifyContent: "flex-end"
56
+ },
57
+ stretch: {
58
+ alignItems: "center"
59
+ }
60
+ },
61
+ vertical: {
62
+ left: {
63
+ flexDirection: "column",
64
+ alignItems: "flex-start"
65
+ },
66
+ center: {
67
+ flexDirection: "column",
68
+ alignItems: "center"
69
+ },
70
+ right: {
71
+ flexDirection: "column",
72
+ alignItems: "flex-end"
73
+ },
74
+ stretch: {
75
+ flexDirection: "column",
76
+ alignItems: "stretch"
77
+ }
78
+ }
79
+ };
80
+ var Stack = ({
81
+ children,
82
+ space = 300,
83
+ align = "left",
84
+ direction = "vertical",
85
+ ...rest
86
+ }) => {
87
+ const stackItems = Children.toArray(children);
88
+ const responsiveAlignment = normalizeResponsiveProp(align);
89
+ const responsiveDirection = normalizeResponsiveProp(direction);
90
+ const responsiveSpace = normalizeResponsiveProp(space);
91
+ const initialValue = ["initial", "initial", "initial", "initial", "initial"];
92
+ const styleProps = {
93
+ alignItems: [...initialValue],
94
+ flexDirection: [...initialValue],
95
+ justifyContent: [...initialValue]
96
+ };
97
+ const childFlexBasis = [...initialValue];
98
+ const childMarginProps = {
99
+ marginLeft: [...initialValue],
100
+ marginTop: [...initialValue]
101
+ };
102
+ initialValue.forEach((_, i) => {
103
+ const currentDirection = responsiveDirection[i];
104
+ const currentAlignment = responsiveAlignment[i];
105
+ const currentSpace = responsiveSpace[i];
106
+ if (currentDirection && currentAlignment) {
107
+ const styles = stackStyles[currentDirection][currentAlignment];
108
+ Object.keys(styleProps).forEach((key) => {
109
+ styleProps[key][i] = styles[key] || "initial";
110
+ });
111
+ }
112
+ const flexBasis = currentAlignment === "stretch" && currentDirection === "horizontal" ? "100%" : null;
113
+ childFlexBasis[i] = flexBasis;
114
+ const margin = currentDirection === "horizontal" ? "marginLeft" : "marginTop";
115
+ const opposite = currentDirection === "horizontal" ? "marginTop" : "marginLeft";
116
+ childMarginProps[margin][i] = currentSpace;
117
+ childMarginProps[opposite][i] = 0;
118
+ });
119
+ return /* @__PURE__ */ jsx(Box, { display: "flex", ...styleProps, ...rest, children: stackItems.map((item, i) => /* @__PURE__ */ createElement(
120
+ Box,
121
+ {
122
+ flexBasis: childFlexBasis,
123
+ ...i !== 0 ? childMarginProps : {},
124
+ key: i
125
+ },
126
+ item
127
+ )) });
128
+ };
129
+ var Stack_default = Stack;
130
+
131
+ // src/StackTypes.ts
132
+ import "react";
133
+
134
+ // src/index.ts
135
+ var src_default = Stack_default;
136
+ export {
137
+ Stack_default as Stack,
138
+ src_default as default
139
+ };
140
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/Stack.tsx","../../src/utils.ts","../../src/StackTypes.ts","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport { Children } from \"react\";\nimport { normalizeResponsiveProp } from \"./utils\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport type { TypeStackProps } from \"./StackTypes\";\n\nconst stackStyles = {\n horizontal: {\n left: {\n alignItems: \"center\",\n },\n center: {\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n right: {\n alignItems: \"center\",\n justifyContent: \"flex-end\",\n },\n stretch: {\n alignItems: \"center\",\n },\n },\n vertical: {\n left: {\n flexDirection: \"column\",\n alignItems: \"flex-start\",\n },\n center: {\n flexDirection: \"column\",\n alignItems: \"center\",\n },\n right: {\n flexDirection: \"column\",\n alignItems: \"flex-end\",\n },\n stretch: {\n flexDirection: \"column\",\n alignItems: \"stretch\",\n },\n },\n};\n\nconst Stack = ({\n children,\n space = 300,\n align = \"left\",\n direction = \"vertical\",\n ...rest\n}: TypeStackProps) => {\n const stackItems = Children.toArray(children);\n const responsiveAlignment = normalizeResponsiveProp(align);\n const responsiveDirection = normalizeResponsiveProp(direction);\n const responsiveSpace = normalizeResponsiveProp(space);\n const initialValue = [\"initial\", \"initial\", \"initial\", \"initial\", \"initial\"];\n\n // TODO: rely on styled system to solve this during the refactor\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const styleProps: any = {\n alignItems: [...initialValue],\n flexDirection: [...initialValue],\n justifyContent: [...initialValue],\n };\n const childFlexBasis: (string | null)[] = [...initialValue];\n const childMarginProps = {\n marginLeft: [...initialValue],\n marginTop: [...initialValue],\n };\n\n initialValue.forEach((_, i) => {\n const currentDirection = responsiveDirection[i] as keyof typeof stackStyles;\n const currentAlignment = responsiveAlignment[\n i\n ] as keyof (typeof stackStyles)[\"horizontal\"];\n const currentSpace = responsiveSpace[i];\n\n if (currentDirection && currentAlignment) {\n const styles: { [key: string]: string } =\n stackStyles[currentDirection][currentAlignment];\n Object.keys(styleProps).forEach((key: string) => {\n styleProps[key][i] = styles[key] || \"initial\";\n });\n }\n\n const flexBasis =\n currentAlignment === \"stretch\" && currentDirection === \"horizontal\"\n ? \"100%\"\n : null;\n childFlexBasis[i] = flexBasis;\n\n const margin =\n currentDirection === \"horizontal\" ? \"marginLeft\" : \"marginTop\";\n\n const opposite =\n currentDirection === \"horizontal\" ? \"marginTop\" : \"marginLeft\";\n childMarginProps[margin][i] = currentSpace;\n // styled system can pass numbers that map to theme values and TS doesn't like it\n childMarginProps[opposite][i] = 0 as unknown as string;\n });\n\n return (\n <Box display=\"flex\" {...styleProps} {...rest}>\n {stackItems.map((item, i) => (\n <Box\n flexBasis={childFlexBasis}\n {...(i !== 0 ? childMarginProps : {})}\n key={i}\n >\n {item}\n </Box>\n ))}\n </Box>\n );\n};\n\nexport default Stack;\n","import { theme } from \"@sproutsocial/seeds-react-theme\";\n\nimport type { TypeResponsive } from \"@sproutsocial/seeds-react-system-props\";\n\nconst breakpoints = theme.breakpoints;\nconst LENGTH = breakpoints.length + 1;\n\nexport const normalizeResponsiveProp = (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: TypeResponsive<any>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): TypeResponsive<any> => {\n if ([\"string\", \"number\"].includes(typeof value)) {\n return Array(LENGTH).fill(value);\n }\n\n if (value.length) {\n switch (value.length) {\n case 1:\n return Array(LENGTH).fill(value[0]);\n case 2:\n return [value[0], ...Array(LENGTH - 1).fill(value[1])];\n case 3:\n return [value[0], value[1], ...Array(LENGTH - 2).fill(value[2])];\n case 4:\n return [\n value[0],\n value[1],\n value[2],\n ...Array(LENGTH - 3).fill(value[3]),\n ];\n case 5:\n return value;\n default:\n throw new Error(\n `Invalid responsive prop length: ${JSON.stringify(value)}`\n );\n }\n } else {\n throw new Error(`Invalid responsive prop type: ${JSON.stringify(value)}`);\n }\n};\n","import * as React from \"react\";\n\nimport type { TypeResponsive } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeBoxProps } from \"@sproutsocial/seeds-react-box\";\n\nexport type TypeSpaceLiterals =\n | 0\n | 100\n | 200\n | 300\n | 350\n | 400\n | 450\n | 500\n | 600\n | string;\n\ntype TypeDirection = \"vertical\" | \"horizontal\";\n\ntype TypeAlignment = \"left\" | \"center\" | \"right\" | \"stretch\";\n\nexport interface TypeStackProps extends TypeBoxProps {\n /** Amount of space between items in the stack */\n space?: TypeResponsive<TypeSpaceLiterals>;\n\n /** Alignment of the items in the stack (horizontal or vertical) */\n align?: TypeResponsive<TypeAlignment>;\n\n /** Axis upon which the stack is laid out (left, center, right, or stretch) */\n direction?: TypeResponsive<TypeDirection>;\n children: React.ReactNode;\n}\n","import Stack from \"./Stack\";\n\nexport default Stack;\nexport { Stack };\nexport * from \"./StackTypes\";\n"],"mappings":"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","names":[]}
@@ -0,0 +1,21 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { TypeResponsive } from '@sproutsocial/seeds-react-system-props';
4
+ import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
5
+
6
+ type TypeSpaceLiterals = 0 | 100 | 200 | 300 | 350 | 400 | 450 | 500 | 600 | string;
7
+ type TypeDirection = "vertical" | "horizontal";
8
+ type TypeAlignment = "left" | "center" | "right" | "stretch";
9
+ interface TypeStackProps extends TypeBoxProps {
10
+ /** Amount of space between items in the stack */
11
+ space?: TypeResponsive<TypeSpaceLiterals>;
12
+ /** Alignment of the items in the stack (horizontal or vertical) */
13
+ align?: TypeResponsive<TypeAlignment>;
14
+ /** Axis upon which the stack is laid out (left, center, right, or stretch) */
15
+ direction?: TypeResponsive<TypeDirection>;
16
+ children: React.ReactNode;
17
+ }
18
+
19
+ declare const Stack: ({ children, space, align, direction, ...rest }: TypeStackProps) => react_jsx_runtime.JSX.Element;
20
+
21
+ export { Stack, type TypeSpaceLiterals, type TypeStackProps, Stack as default };
@@ -0,0 +1,21 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { TypeResponsive } from '@sproutsocial/seeds-react-system-props';
4
+ import { TypeBoxProps } from '@sproutsocial/seeds-react-box';
5
+
6
+ type TypeSpaceLiterals = 0 | 100 | 200 | 300 | 350 | 400 | 450 | 500 | 600 | string;
7
+ type TypeDirection = "vertical" | "horizontal";
8
+ type TypeAlignment = "left" | "center" | "right" | "stretch";
9
+ interface TypeStackProps extends TypeBoxProps {
10
+ /** Amount of space between items in the stack */
11
+ space?: TypeResponsive<TypeSpaceLiterals>;
12
+ /** Alignment of the items in the stack (horizontal or vertical) */
13
+ align?: TypeResponsive<TypeAlignment>;
14
+ /** Axis upon which the stack is laid out (left, center, right, or stretch) */
15
+ direction?: TypeResponsive<TypeDirection>;
16
+ children: React.ReactNode;
17
+ }
18
+
19
+ declare const Stack: ({ children, space, align, direction, ...rest }: TypeStackProps) => react_jsx_runtime.JSX.Element;
20
+
21
+ export { Stack, type TypeSpaceLiterals, type TypeStackProps, Stack as default };
package/dist/index.js ADDED
@@ -0,0 +1,177 @@
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 src_exports = {};
32
+ __export(src_exports, {
33
+ Stack: () => Stack_default,
34
+ default: () => src_default
35
+ });
36
+ module.exports = __toCommonJS(src_exports);
37
+
38
+ // src/Stack.tsx
39
+ var React = require("react");
40
+ var import_react = require("react");
41
+
42
+ // src/utils.ts
43
+ var import_seeds_react_theme = require("@sproutsocial/seeds-react-theme");
44
+ var breakpoints = import_seeds_react_theme.theme.breakpoints;
45
+ var LENGTH = breakpoints.length + 1;
46
+ var normalizeResponsiveProp = (value) => {
47
+ if (["string", "number"].includes(typeof value)) {
48
+ return Array(LENGTH).fill(value);
49
+ }
50
+ if (value.length) {
51
+ switch (value.length) {
52
+ case 1:
53
+ return Array(LENGTH).fill(value[0]);
54
+ case 2:
55
+ return [value[0], ...Array(LENGTH - 1).fill(value[1])];
56
+ case 3:
57
+ return [value[0], value[1], ...Array(LENGTH - 2).fill(value[2])];
58
+ case 4:
59
+ return [
60
+ value[0],
61
+ value[1],
62
+ value[2],
63
+ ...Array(LENGTH - 3).fill(value[3])
64
+ ];
65
+ case 5:
66
+ return value;
67
+ default:
68
+ throw new Error(
69
+ `Invalid responsive prop length: ${JSON.stringify(value)}`
70
+ );
71
+ }
72
+ } else {
73
+ throw new Error(`Invalid responsive prop type: ${JSON.stringify(value)}`);
74
+ }
75
+ };
76
+
77
+ // src/Stack.tsx
78
+ var import_seeds_react_box = __toESM(require("@sproutsocial/seeds-react-box"));
79
+ var import_jsx_runtime = require("react/jsx-runtime");
80
+ var import_react2 = require("react");
81
+ var stackStyles = {
82
+ horizontal: {
83
+ left: {
84
+ alignItems: "center"
85
+ },
86
+ center: {
87
+ alignItems: "center",
88
+ justifyContent: "center"
89
+ },
90
+ right: {
91
+ alignItems: "center",
92
+ justifyContent: "flex-end"
93
+ },
94
+ stretch: {
95
+ alignItems: "center"
96
+ }
97
+ },
98
+ vertical: {
99
+ left: {
100
+ flexDirection: "column",
101
+ alignItems: "flex-start"
102
+ },
103
+ center: {
104
+ flexDirection: "column",
105
+ alignItems: "center"
106
+ },
107
+ right: {
108
+ flexDirection: "column",
109
+ alignItems: "flex-end"
110
+ },
111
+ stretch: {
112
+ flexDirection: "column",
113
+ alignItems: "stretch"
114
+ }
115
+ }
116
+ };
117
+ var Stack = ({
118
+ children,
119
+ space = 300,
120
+ align = "left",
121
+ direction = "vertical",
122
+ ...rest
123
+ }) => {
124
+ const stackItems = import_react.Children.toArray(children);
125
+ const responsiveAlignment = normalizeResponsiveProp(align);
126
+ const responsiveDirection = normalizeResponsiveProp(direction);
127
+ const responsiveSpace = normalizeResponsiveProp(space);
128
+ const initialValue = ["initial", "initial", "initial", "initial", "initial"];
129
+ const styleProps = {
130
+ alignItems: [...initialValue],
131
+ flexDirection: [...initialValue],
132
+ justifyContent: [...initialValue]
133
+ };
134
+ const childFlexBasis = [...initialValue];
135
+ const childMarginProps = {
136
+ marginLeft: [...initialValue],
137
+ marginTop: [...initialValue]
138
+ };
139
+ initialValue.forEach((_, i) => {
140
+ const currentDirection = responsiveDirection[i];
141
+ const currentAlignment = responsiveAlignment[i];
142
+ const currentSpace = responsiveSpace[i];
143
+ if (currentDirection && currentAlignment) {
144
+ const styles = stackStyles[currentDirection][currentAlignment];
145
+ Object.keys(styleProps).forEach((key) => {
146
+ styleProps[key][i] = styles[key] || "initial";
147
+ });
148
+ }
149
+ const flexBasis = currentAlignment === "stretch" && currentDirection === "horizontal" ? "100%" : null;
150
+ childFlexBasis[i] = flexBasis;
151
+ const margin = currentDirection === "horizontal" ? "marginLeft" : "marginTop";
152
+ const opposite = currentDirection === "horizontal" ? "marginTop" : "marginLeft";
153
+ childMarginProps[margin][i] = currentSpace;
154
+ childMarginProps[opposite][i] = 0;
155
+ });
156
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box.default, { display: "flex", ...styleProps, ...rest, children: stackItems.map((item, i) => /* @__PURE__ */ (0, import_react2.createElement)(
157
+ import_seeds_react_box.default,
158
+ {
159
+ flexBasis: childFlexBasis,
160
+ ...i !== 0 ? childMarginProps : {},
161
+ key: i
162
+ },
163
+ item
164
+ )) });
165
+ };
166
+ var Stack_default = Stack;
167
+
168
+ // src/StackTypes.ts
169
+ var React2 = require("react");
170
+
171
+ // src/index.ts
172
+ var src_default = Stack_default;
173
+ // Annotate the CommonJS export names for ESM import in node:
174
+ 0 && (module.exports = {
175
+ Stack
176
+ });
177
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/Stack.tsx","../src/utils.ts","../src/StackTypes.ts"],"sourcesContent":["import Stack from \"./Stack\";\n\nexport default Stack;\nexport { Stack };\nexport * from \"./StackTypes\";\n","import * as React from \"react\";\nimport { Children } from \"react\";\nimport { normalizeResponsiveProp } from \"./utils\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport type { TypeStackProps } from \"./StackTypes\";\n\nconst stackStyles = {\n horizontal: {\n left: {\n alignItems: \"center\",\n },\n center: {\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n right: {\n alignItems: \"center\",\n justifyContent: \"flex-end\",\n },\n stretch: {\n alignItems: \"center\",\n },\n },\n vertical: {\n left: {\n flexDirection: \"column\",\n alignItems: \"flex-start\",\n },\n center: {\n flexDirection: \"column\",\n alignItems: \"center\",\n },\n right: {\n flexDirection: \"column\",\n alignItems: \"flex-end\",\n },\n stretch: {\n flexDirection: \"column\",\n alignItems: \"stretch\",\n },\n },\n};\n\nconst Stack = ({\n children,\n space = 300,\n align = \"left\",\n direction = \"vertical\",\n ...rest\n}: TypeStackProps) => {\n const stackItems = Children.toArray(children);\n const responsiveAlignment = normalizeResponsiveProp(align);\n const responsiveDirection = normalizeResponsiveProp(direction);\n const responsiveSpace = normalizeResponsiveProp(space);\n const initialValue = [\"initial\", \"initial\", \"initial\", \"initial\", \"initial\"];\n\n // TODO: rely on styled system to solve this during the refactor\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const styleProps: any = {\n alignItems: [...initialValue],\n flexDirection: [...initialValue],\n justifyContent: [...initialValue],\n };\n const childFlexBasis: (string | null)[] = [...initialValue];\n const childMarginProps = {\n marginLeft: [...initialValue],\n marginTop: [...initialValue],\n };\n\n initialValue.forEach((_, i) => {\n const currentDirection = responsiveDirection[i] as keyof typeof stackStyles;\n const currentAlignment = responsiveAlignment[\n i\n ] as keyof (typeof stackStyles)[\"horizontal\"];\n const currentSpace = responsiveSpace[i];\n\n if (currentDirection && currentAlignment) {\n const styles: { [key: string]: string } =\n stackStyles[currentDirection][currentAlignment];\n Object.keys(styleProps).forEach((key: string) => {\n styleProps[key][i] = styles[key] || \"initial\";\n });\n }\n\n const flexBasis =\n currentAlignment === \"stretch\" && currentDirection === \"horizontal\"\n ? \"100%\"\n : null;\n childFlexBasis[i] = flexBasis;\n\n const margin =\n currentDirection === \"horizontal\" ? \"marginLeft\" : \"marginTop\";\n\n const opposite =\n currentDirection === \"horizontal\" ? \"marginTop\" : \"marginLeft\";\n childMarginProps[margin][i] = currentSpace;\n // styled system can pass numbers that map to theme values and TS doesn't like it\n childMarginProps[opposite][i] = 0 as unknown as string;\n });\n\n return (\n <Box display=\"flex\" {...styleProps} {...rest}>\n {stackItems.map((item, i) => (\n <Box\n flexBasis={childFlexBasis}\n {...(i !== 0 ? childMarginProps : {})}\n key={i}\n >\n {item}\n </Box>\n ))}\n </Box>\n );\n};\n\nexport default Stack;\n","import { theme } from \"@sproutsocial/seeds-react-theme\";\n\nimport type { TypeResponsive } from \"@sproutsocial/seeds-react-system-props\";\n\nconst breakpoints = theme.breakpoints;\nconst LENGTH = breakpoints.length + 1;\n\nexport const normalizeResponsiveProp = (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value: TypeResponsive<any>\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): TypeResponsive<any> => {\n if ([\"string\", \"number\"].includes(typeof value)) {\n return Array(LENGTH).fill(value);\n }\n\n if (value.length) {\n switch (value.length) {\n case 1:\n return Array(LENGTH).fill(value[0]);\n case 2:\n return [value[0], ...Array(LENGTH - 1).fill(value[1])];\n case 3:\n return [value[0], value[1], ...Array(LENGTH - 2).fill(value[2])];\n case 4:\n return [\n value[0],\n value[1],\n value[2],\n ...Array(LENGTH - 3).fill(value[3]),\n ];\n case 5:\n return value;\n default:\n throw new Error(\n `Invalid responsive prop length: ${JSON.stringify(value)}`\n );\n }\n } else {\n throw new Error(`Invalid responsive prop type: ${JSON.stringify(value)}`);\n }\n};\n","import * as React from \"react\";\n\nimport type { TypeResponsive } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeBoxProps } from \"@sproutsocial/seeds-react-box\";\n\nexport type TypeSpaceLiterals =\n | 0\n | 100\n | 200\n | 300\n | 350\n | 400\n | 450\n | 500\n | 600\n | string;\n\ntype TypeDirection = \"vertical\" | \"horizontal\";\n\ntype TypeAlignment = \"left\" | \"center\" | \"right\" | \"stretch\";\n\nexport interface TypeStackProps extends TypeBoxProps {\n /** Amount of space between items in the stack */\n space?: TypeResponsive<TypeSpaceLiterals>;\n\n /** Alignment of the items in the stack (horizontal or vertical) */\n align?: TypeResponsive<TypeAlignment>;\n\n /** Axis upon which the stack is laid out (left, center, right, or stretch) */\n direction?: TypeResponsive<TypeDirection>;\n children: React.ReactNode;\n}\n"],"mappings":"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","names":["import_react","Box","React"]}
package/jest.config.js ADDED
@@ -0,0 +1,9 @@
1
+ const baseConfig = require("@sproutsocial/seeds-testing");
2
+
3
+ /** * @type {import('jest').Config} */
4
+ const config = {
5
+ ...baseConfig,
6
+ displayName: "seeds-react-stack",
7
+ };
8
+
9
+ module.exports = config;
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@sproutsocial/seeds-react-stack",
3
+ "version": "1.0.0",
4
+ "description": "Seeds React Stack",
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-theme": "*",
22
+ "@sproutsocial/seeds-react-system-props": "*",
23
+ "@sproutsocial/seeds-react-box": "*"
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.0.2",
32
+ "typescript": "^5.6.2",
33
+ "@sproutsocial/seeds-tsconfig": "*",
34
+ "@sproutsocial/seeds-testing": "*",
35
+ "@sproutsocial/seeds-react-testing-library": "*",
36
+ "@sproutsocial/seeds-react-text": "*"
37
+ },
38
+ "peerDependencies": {
39
+ "styled-components": "^5.2.3"
40
+ },
41
+ "engines": {
42
+ "node": ">=18"
43
+ }
44
+ }
@@ -0,0 +1,102 @@
1
+ import React from "react";
2
+ import type { Meta, StoryObj } from "@storybook/react";
3
+ import Text from "@sproutsocial/seeds-react-text";
4
+ import Stack from "./Stack";
5
+
6
+ const meta: Meta<typeof Stack> = {
7
+ title: "Components/Stack",
8
+ component: Stack,
9
+ argTypes: {
10
+ align: {
11
+ options: ["left", "center", "right", "stretch"],
12
+ control: {
13
+ type: "select",
14
+ },
15
+ },
16
+ direction: {
17
+ options: ["horizontal", "vertical"],
18
+ control: {
19
+ type: "select",
20
+ },
21
+ },
22
+ },
23
+ args: {
24
+ align: undefined,
25
+ direction: undefined,
26
+ },
27
+ };
28
+ export default meta;
29
+
30
+ interface ItemProps {
31
+ children: React.ReactNode;
32
+ }
33
+
34
+ const Item: React.FC<ItemProps> = (props) => (
35
+ <Text as="p" color="text.body" {...props} />
36
+ );
37
+
38
+ type Story = StoryObj<typeof Stack>;
39
+
40
+ export const DefaultStory: Story = {
41
+ name: "Default (Vertical)",
42
+ args: {
43
+ // ...existing code...
44
+ },
45
+ render: (args) => (
46
+ <Stack p={400} {...args}>
47
+ <Item>This</Item>
48
+ <Item>is</Item>
49
+ <Item>the</Item>
50
+ <Item>stack</Item>
51
+ <Item>component</Item>
52
+ </Stack>
53
+ ),
54
+ };
55
+
56
+ export const ResponsiveDirection: Story = {
57
+ name: "Responsive direction",
58
+ args: {
59
+ direction: ["vertical", "horizontal", "vertical"],
60
+ },
61
+ render: (args) => (
62
+ <Stack p={400} {...args}>
63
+ <Item>Stack</Item>
64
+ <Item>is</Item>
65
+ <Item>a</Item>
66
+ <Item>layout</Item>
67
+ <Item>utility</Item>
68
+ </Stack>
69
+ ),
70
+ };
71
+
72
+ export const ResponsiveAlignment: Story = {
73
+ name: "Responsive alignment",
74
+ args: {
75
+ align: ["left", "center", "stretch"],
76
+ },
77
+ render: (args) => (
78
+ <Stack p={400} {...args}>
79
+ <Item>Stack</Item>
80
+ <Item>is</Item>
81
+ <Item>a</Item>
82
+ <Item>layout</Item>
83
+ <Item>utility</Item>
84
+ </Stack>
85
+ ),
86
+ };
87
+
88
+ export const ResponsiveSpace: Story = {
89
+ name: "Responsive space",
90
+ args: {
91
+ space: [300, 450, 600],
92
+ },
93
+ render: (args) => (
94
+ <Stack p={400} {...args}>
95
+ <Item>Stack</Item>
96
+ <Item>is</Item>
97
+ <Item>a</Item>
98
+ <Item>layout</Item>
99
+ <Item>utility</Item>
100
+ </Stack>
101
+ ),
102
+ };
package/src/Stack.tsx ADDED
@@ -0,0 +1,116 @@
1
+ import * as React from "react";
2
+ import { Children } from "react";
3
+ import { normalizeResponsiveProp } from "./utils";
4
+ import Box from "@sproutsocial/seeds-react-box";
5
+ import type { TypeStackProps } from "./StackTypes";
6
+
7
+ const stackStyles = {
8
+ horizontal: {
9
+ left: {
10
+ alignItems: "center",
11
+ },
12
+ center: {
13
+ alignItems: "center",
14
+ justifyContent: "center",
15
+ },
16
+ right: {
17
+ alignItems: "center",
18
+ justifyContent: "flex-end",
19
+ },
20
+ stretch: {
21
+ alignItems: "center",
22
+ },
23
+ },
24
+ vertical: {
25
+ left: {
26
+ flexDirection: "column",
27
+ alignItems: "flex-start",
28
+ },
29
+ center: {
30
+ flexDirection: "column",
31
+ alignItems: "center",
32
+ },
33
+ right: {
34
+ flexDirection: "column",
35
+ alignItems: "flex-end",
36
+ },
37
+ stretch: {
38
+ flexDirection: "column",
39
+ alignItems: "stretch",
40
+ },
41
+ },
42
+ };
43
+
44
+ const Stack = ({
45
+ children,
46
+ space = 300,
47
+ align = "left",
48
+ direction = "vertical",
49
+ ...rest
50
+ }: TypeStackProps) => {
51
+ const stackItems = Children.toArray(children);
52
+ const responsiveAlignment = normalizeResponsiveProp(align);
53
+ const responsiveDirection = normalizeResponsiveProp(direction);
54
+ const responsiveSpace = normalizeResponsiveProp(space);
55
+ const initialValue = ["initial", "initial", "initial", "initial", "initial"];
56
+
57
+ // TODO: rely on styled system to solve this during the refactor
58
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
59
+ const styleProps: any = {
60
+ alignItems: [...initialValue],
61
+ flexDirection: [...initialValue],
62
+ justifyContent: [...initialValue],
63
+ };
64
+ const childFlexBasis: (string | null)[] = [...initialValue];
65
+ const childMarginProps = {
66
+ marginLeft: [...initialValue],
67
+ marginTop: [...initialValue],
68
+ };
69
+
70
+ initialValue.forEach((_, i) => {
71
+ const currentDirection = responsiveDirection[i] as keyof typeof stackStyles;
72
+ const currentAlignment = responsiveAlignment[
73
+ i
74
+ ] as keyof (typeof stackStyles)["horizontal"];
75
+ const currentSpace = responsiveSpace[i];
76
+
77
+ if (currentDirection && currentAlignment) {
78
+ const styles: { [key: string]: string } =
79
+ stackStyles[currentDirection][currentAlignment];
80
+ Object.keys(styleProps).forEach((key: string) => {
81
+ styleProps[key][i] = styles[key] || "initial";
82
+ });
83
+ }
84
+
85
+ const flexBasis =
86
+ currentAlignment === "stretch" && currentDirection === "horizontal"
87
+ ? "100%"
88
+ : null;
89
+ childFlexBasis[i] = flexBasis;
90
+
91
+ const margin =
92
+ currentDirection === "horizontal" ? "marginLeft" : "marginTop";
93
+
94
+ const opposite =
95
+ currentDirection === "horizontal" ? "marginTop" : "marginLeft";
96
+ childMarginProps[margin][i] = currentSpace;
97
+ // styled system can pass numbers that map to theme values and TS doesn't like it
98
+ childMarginProps[opposite][i] = 0 as unknown as string;
99
+ });
100
+
101
+ return (
102
+ <Box display="flex" {...styleProps} {...rest}>
103
+ {stackItems.map((item, i) => (
104
+ <Box
105
+ flexBasis={childFlexBasis}
106
+ {...(i !== 0 ? childMarginProps : {})}
107
+ key={i}
108
+ >
109
+ {item}
110
+ </Box>
111
+ ))}
112
+ </Box>
113
+ );
114
+ };
115
+
116
+ export default Stack;
@@ -0,0 +1,32 @@
1
+ import * as React from "react";
2
+
3
+ import type { TypeResponsive } from "@sproutsocial/seeds-react-system-props";
4
+ import type { TypeBoxProps } from "@sproutsocial/seeds-react-box";
5
+
6
+ export type TypeSpaceLiterals =
7
+ | 0
8
+ | 100
9
+ | 200
10
+ | 300
11
+ | 350
12
+ | 400
13
+ | 450
14
+ | 500
15
+ | 600
16
+ | string;
17
+
18
+ type TypeDirection = "vertical" | "horizontal";
19
+
20
+ type TypeAlignment = "left" | "center" | "right" | "stretch";
21
+
22
+ export interface TypeStackProps extends TypeBoxProps {
23
+ /** Amount of space between items in the stack */
24
+ space?: TypeResponsive<TypeSpaceLiterals>;
25
+
26
+ /** Alignment of the items in the stack (horizontal or vertical) */
27
+ align?: TypeResponsive<TypeAlignment>;
28
+
29
+ /** Axis upon which the stack is laid out (left, center, right, or stretch) */
30
+ direction?: TypeResponsive<TypeDirection>;
31
+ children: React.ReactNode;
32
+ }
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import { render } from "@sproutsocial/seeds-react-testing-library";
3
+ import { Text } from "@sproutsocial/seeds-react-text";
4
+ import Stack from "../Stack";
5
+
6
+ interface ItemProps {
7
+ [key: string]: any;
8
+ }
9
+
10
+ const Item = (props: ItemProps) => (
11
+ <Text as="div" color="text.body" bg="container.background.base" {...props}>
12
+ {props.children}
13
+ </Text>
14
+ );
15
+
16
+ describe("Stack", () => {
17
+ it("should render properly", async () => {
18
+ const { container, runA11yCheck } = render(
19
+ <Stack>
20
+ <Item>Hello world!</Item>
21
+ </Stack>
22
+ );
23
+ expect(container).toBeTruthy();
24
+ await runA11yCheck();
25
+ });
26
+ });
@@ -0,0 +1,18 @@
1
+ import * as React from "react";
2
+ import { Box } from "@sproutsocial/seeds-react-box";
3
+ import Stack from "../Stack";
4
+
5
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
6
+ function StackTypes() {
7
+ return (
8
+ <>
9
+ <Stack space={300} align="center" direction="horizontal">
10
+ <Box>Seeds</Box>
11
+ <Box>Design</Box>
12
+ <Box>System</Box>
13
+ </Stack>
14
+ {/* @ts-expect-error - test that invalid children are rejected */}
15
+ <Stack />
16
+ </>
17
+ );
18
+ }
package/src/index.ts ADDED
@@ -0,0 +1,5 @@
1
+ import Stack from "./Stack";
2
+
3
+ export default Stack;
4
+ export { Stack };
5
+ export * from "./StackTypes";
@@ -0,0 +1,7 @@
1
+ import "styled-components";
2
+ import { TypeTheme } from "@sproutsocial/seeds-react-theme";
3
+
4
+ declare module "styled-components" {
5
+ // eslint-disable-next-line @typescript-eslint/no-empty-interface
6
+ export interface DefaultTheme extends TypeTheme {}
7
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,42 @@
1
+ import { theme } from "@sproutsocial/seeds-react-theme";
2
+
3
+ import type { TypeResponsive } from "@sproutsocial/seeds-react-system-props";
4
+
5
+ const breakpoints = theme.breakpoints;
6
+ const LENGTH = breakpoints.length + 1;
7
+
8
+ export const normalizeResponsiveProp = (
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ value: TypeResponsive<any>
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ ): TypeResponsive<any> => {
13
+ if (["string", "number"].includes(typeof value)) {
14
+ return Array(LENGTH).fill(value);
15
+ }
16
+
17
+ if (value.length) {
18
+ switch (value.length) {
19
+ case 1:
20
+ return Array(LENGTH).fill(value[0]);
21
+ case 2:
22
+ return [value[0], ...Array(LENGTH - 1).fill(value[1])];
23
+ case 3:
24
+ return [value[0], value[1], ...Array(LENGTH - 2).fill(value[2])];
25
+ case 4:
26
+ return [
27
+ value[0],
28
+ value[1],
29
+ value[2],
30
+ ...Array(LENGTH - 3).fill(value[3]),
31
+ ];
32
+ case 5:
33
+ return value;
34
+ default:
35
+ throw new Error(
36
+ `Invalid responsive prop length: ${JSON.stringify(value)}`
37
+ );
38
+ }
39
+ } else {
40
+ throw new Error(`Invalid responsive prop type: ${JSON.stringify(value)}`);
41
+ }
42
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "@sproutsocial/seeds-tsconfig/bundler/dom/library-monorepo",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx",
5
+ "module": "esnext"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["node_modules", "dist", "coverage"]
9
+ }
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
+ }));