@simplybusiness/mobius 4.3.6 → 4.4.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/CHANGELOG.md +6 -0
- package/dist/cjs/components/Box/Box.js +19 -1
- package/dist/cjs/components/Box/Box.js.map +1 -1
- package/dist/cjs/components/Box/types.js +6 -0
- package/dist/cjs/components/Box/types.js.map +1 -0
- package/dist/cjs/components/Flex/propUtils.js +6 -8
- package/dist/cjs/components/Flex/propUtils.js.map +1 -1
- package/dist/cjs/components/Grid/Grid.js +5 -5
- package/dist/cjs/components/Grid/Grid.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils/filterUndefinedProps.js +21 -0
- package/dist/cjs/utils/filterUndefinedProps.js.map +1 -0
- package/dist/cjs/utils/getSpacingValue.js +21 -0
- package/dist/cjs/utils/getSpacingValue.js.map +1 -0
- package/dist/cjs/utils/index.js +3 -0
- package/dist/cjs/utils/index.js.map +1 -1
- package/dist/cjs/utils/sizeClasses.js +1 -0
- package/dist/cjs/utils/sizeClasses.js.map +1 -1
- package/dist/cjs/utils/sizeOptions.js +22 -0
- package/dist/cjs/utils/sizeOptions.js.map +1 -0
- package/dist/esm/components/Box/Box.js +19 -1
- package/dist/esm/components/Box/Box.js.map +1 -1
- package/dist/esm/components/Box/types.js +3 -0
- package/dist/esm/components/Box/types.js.map +1 -0
- package/dist/esm/components/Flex/propUtils.js +6 -5
- package/dist/esm/components/Flex/propUtils.js.map +1 -1
- package/dist/esm/components/Flex/types.js.map +1 -1
- package/dist/esm/components/Grid/Grid.js +5 -5
- package/dist/esm/components/Grid/Grid.js.map +1 -1
- package/dist/esm/types/size.js.map +1 -1
- package/dist/esm/utils/filterUndefinedProps.js +11 -0
- package/dist/esm/utils/filterUndefinedProps.js.map +1 -0
- package/dist/esm/utils/getSpacingValue.js +11 -0
- package/dist/esm/utils/getSpacingValue.js.map +1 -0
- package/dist/esm/utils/index.js +3 -0
- package/dist/esm/utils/index.js.map +1 -1
- package/dist/esm/utils/sizeClasses.js +1 -0
- package/dist/esm/utils/sizeClasses.js.map +1 -1
- package/dist/esm/utils/sizeOptions.js +12 -0
- package/dist/esm/utils/sizeOptions.js.map +1 -0
- package/dist/types/components/Box/Box.d.ts +2 -11
- package/dist/types/components/Box/types.d.ts +31 -0
- package/dist/types/components/Flex/propUtils.d.ts +1 -6
- package/dist/types/components/Flex/types.d.ts +4 -3
- package/dist/types/components/Grid/Grid.d.ts +4 -3
- package/dist/types/types/size.d.ts +2 -1
- package/dist/types/utils/filterUndefinedProps.d.ts +1 -0
- package/dist/types/utils/filterUndefinedProps.test.d.ts +1 -0
- package/dist/types/utils/getSpacingValue.d.ts +2 -0
- package/dist/types/utils/getSpacingValue.test.d.ts +1 -0
- package/dist/types/utils/index.d.ts +3 -0
- package/dist/types/utils/sizeClasses.d.ts +2 -0
- package/dist/types/utils/sizeOptions.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/Box/Box.mdx +6 -2
- package/src/components/Box/Box.stories.tsx +72 -6
- package/src/components/Box/Box.test.tsx +189 -8
- package/src/components/Box/Box.tsx +52 -15
- package/src/components/Box/types.ts +34 -0
- package/src/components/Flex/Flex.mdx +0 -10
- package/src/components/Flex/Flex.stories.tsx +3 -17
- package/src/components/Flex/propUtils.test.ts +14 -35
- package/src/components/Flex/propUtils.ts +6 -7
- package/src/components/Flex/types.ts +4 -3
- package/src/components/Grid/Grid.mdx +0 -10
- package/src/components/Grid/Grid.stories.tsx +6 -19
- package/src/components/Grid/Grid.tsx +9 -8
- package/src/types/size.ts +3 -1
- package/src/utils/filterUndefinedProps.test.ts +15 -0
- package/src/utils/filterUndefinedProps.ts +9 -0
- package/src/utils/getSpacingValue.test.ts +33 -0
- package/src/utils/getSpacingValue.ts +15 -0
- package/src/utils/index.ts +3 -0
- package/src/utils/sizeClasses.test.ts +1 -1
- package/src/utils/sizeClasses.ts +1 -0
- package/src/utils/sizeOptions.ts +12 -0
- package/dist/cjs/components/Icon/IconStyle.js +0 -413
- package/dist/cjs/components/Icon/IconStyle.js.map +0 -1
- package/dist/esm/components/Icon/IconStyle.js +0 -403
- package/dist/esm/components/Icon/IconStyle.js.map +0 -1
- package/dist/types/components/Icon/IconStyle.d.ts +0 -1
|
@@ -1,29 +1,95 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { Box
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { Box } from "./Box";
|
|
3
|
+
import { excludeControls, sizeOptions } from "../../utils";
|
|
4
|
+
import { BoxProps } from "./types";
|
|
5
|
+
import { TextField } from "../TextField";
|
|
5
6
|
|
|
6
7
|
type StoryType = StoryObj<typeof Box>;
|
|
7
8
|
|
|
9
|
+
const paddingProps = Object.assign(
|
|
10
|
+
{},
|
|
11
|
+
...[
|
|
12
|
+
"padding",
|
|
13
|
+
"paddingX",
|
|
14
|
+
"paddingInline",
|
|
15
|
+
"paddingInlineStart",
|
|
16
|
+
"paddingInlineEnd",
|
|
17
|
+
"paddingY",
|
|
18
|
+
"paddingBlock",
|
|
19
|
+
"paddingBlockStart",
|
|
20
|
+
"paddingBlockEnd",
|
|
21
|
+
"paddingTop",
|
|
22
|
+
"paddingRight",
|
|
23
|
+
"paddingBottom",
|
|
24
|
+
"paddingLeft",
|
|
25
|
+
].map(propName => ({
|
|
26
|
+
[propName]: {
|
|
27
|
+
control: { type: "select" },
|
|
28
|
+
options: [...sizeOptions],
|
|
29
|
+
},
|
|
30
|
+
})),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const dimensionProps = Object.assign(
|
|
34
|
+
{},
|
|
35
|
+
...["minWidth", "minHeight", "maxWidth", "maxHeight", "width", "height"].map(
|
|
36
|
+
propName => ({
|
|
37
|
+
[propName]: {
|
|
38
|
+
control: { type: "number" },
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
),
|
|
42
|
+
);
|
|
43
|
+
|
|
8
44
|
const meta: Meta<typeof Box> = {
|
|
9
45
|
title: "Layout/Box",
|
|
10
46
|
component: Box,
|
|
11
|
-
argTypes:
|
|
47
|
+
argTypes: {
|
|
48
|
+
...paddingProps,
|
|
49
|
+
...dimensionProps,
|
|
50
|
+
...excludeControls("style"),
|
|
51
|
+
},
|
|
12
52
|
};
|
|
13
53
|
|
|
14
54
|
export const Normal: StoryType = {
|
|
15
55
|
render: (args: BoxProps) => (
|
|
16
56
|
<Box {...args}>
|
|
17
|
-
<
|
|
57
|
+
<TextField label="First name" />
|
|
58
|
+
<TextField label="Last name" />
|
|
59
|
+
<TextField label="Email address" />
|
|
18
60
|
</Box>
|
|
19
61
|
),
|
|
62
|
+
args: {
|
|
63
|
+
minWidth: 320,
|
|
64
|
+
padding: "lg",
|
|
65
|
+
style: {
|
|
66
|
+
backgroundColor: "var(--color-background-light)",
|
|
67
|
+
borderRadius: "var(--radius-1)",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
20
70
|
};
|
|
21
71
|
|
|
22
72
|
export const CustomElement: StoryType = {
|
|
23
|
-
render: (args: BoxProps) =>
|
|
73
|
+
render: (args: BoxProps) => (
|
|
74
|
+
<Box {...args}>
|
|
75
|
+
<Box>First item</Box>
|
|
76
|
+
<Box>Second item</Box>
|
|
77
|
+
<Box>Third item</Box>
|
|
78
|
+
</Box>
|
|
79
|
+
),
|
|
24
80
|
name: "Custom Element",
|
|
25
81
|
args: {
|
|
26
82
|
elementType: "span",
|
|
83
|
+
minWidth: 320,
|
|
84
|
+
paddingBlock: "lg",
|
|
85
|
+
paddingInline: "xxl",
|
|
86
|
+
style: {
|
|
87
|
+
display: "block",
|
|
88
|
+
backgroundColor: "var(--color-background-medium)",
|
|
89
|
+
borderRadius: "var(--radius-1)",
|
|
90
|
+
color: "var(--color-text-inverted)",
|
|
91
|
+
margin: 0,
|
|
92
|
+
},
|
|
27
93
|
},
|
|
28
94
|
};
|
|
29
95
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { render
|
|
1
|
+
import { render } from "@testing-library/react";
|
|
2
2
|
import { Box } from ".";
|
|
3
3
|
|
|
4
4
|
const CLASS_NAME = "mobius/Box";
|
|
@@ -11,6 +11,7 @@ describe("Box", () => {
|
|
|
11
11
|
describe("given elementType", () => {
|
|
12
12
|
it("is not applied as element attribute", () => {
|
|
13
13
|
const { container } = render(<Box elementType="span" />);
|
|
14
|
+
|
|
14
15
|
expect(container.firstChild).not.toHaveAttribute("elementtype", "span");
|
|
15
16
|
});
|
|
16
17
|
});
|
|
@@ -18,22 +19,202 @@ describe("Box", () => {
|
|
|
18
19
|
describe("uses correct class names", () => {
|
|
19
20
|
it("uses mobius class", () => {
|
|
20
21
|
const { container } = render(<Box>Sample text</Box>);
|
|
22
|
+
|
|
21
23
|
expect(container.firstChild).toHaveClass("mobius");
|
|
22
24
|
});
|
|
23
25
|
|
|
24
26
|
it("uses base Mobius class", () => {
|
|
25
|
-
render(<Box
|
|
26
|
-
|
|
27
|
+
const { container } = render(<Box>Sample text</Box>);
|
|
28
|
+
|
|
29
|
+
expect(container.firstChild).toHaveClass(CLASS_NAME);
|
|
27
30
|
});
|
|
28
31
|
|
|
29
32
|
it("includes custom class name", () => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
const customClassName = "my-class";
|
|
34
|
+
const { container } = render(
|
|
35
|
+
<Box className={customClassName}>Sample Text</Box>,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
expect(container.firstChild).toHaveClass(customClassName);
|
|
39
|
+
expect(container.firstChild).toHaveClass(CLASS_NAME);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe("given other props", () => {
|
|
44
|
+
it("passes them to the element", () => {
|
|
45
|
+
const { container } = render(
|
|
46
|
+
<Box data-testid="test-id">Sample text</Box>,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
expect(container.firstChild).toHaveAttribute("data-testid", "test-id");
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe("given all padding props", () => {
|
|
54
|
+
it("regardless of order, prioritises paddingTop/Right/Bottom/Left values over others", () => {
|
|
55
|
+
const paddingTop = 100;
|
|
56
|
+
const paddingRight = 110;
|
|
57
|
+
const paddingBottom = 120;
|
|
58
|
+
const paddingLeft = 130;
|
|
59
|
+
const padding = 10;
|
|
60
|
+
const paddingX = 20;
|
|
61
|
+
const paddingInline = 30;
|
|
62
|
+
const paddingInlineStart = 40;
|
|
63
|
+
const paddingInlineEnd = 50;
|
|
64
|
+
const paddingY = 60;
|
|
65
|
+
const paddingBlock = 70;
|
|
66
|
+
const paddingBlockStart = 80;
|
|
67
|
+
const paddingBlockEnd = 90;
|
|
68
|
+
|
|
69
|
+
const { container } = render(
|
|
70
|
+
<Box
|
|
71
|
+
paddingTop={paddingTop}
|
|
72
|
+
paddingRight={paddingRight}
|
|
73
|
+
paddingBottom={paddingBottom}
|
|
74
|
+
paddingLeft={paddingLeft}
|
|
75
|
+
padding={padding}
|
|
76
|
+
paddingX={paddingX}
|
|
77
|
+
paddingInline={paddingInline}
|
|
78
|
+
paddingInlineStart={paddingInlineStart}
|
|
79
|
+
paddingInlineEnd={paddingInlineEnd}
|
|
80
|
+
paddingY={paddingY}
|
|
81
|
+
paddingBlock={paddingBlock}
|
|
82
|
+
paddingBlockStart={paddingBlockStart}
|
|
83
|
+
paddingBlockEnd={paddingBlockEnd}
|
|
84
|
+
/>,
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const elementStyles = (container.firstChild as HTMLElement)?.style;
|
|
88
|
+
|
|
89
|
+
expect(elementStyles.paddingTop).toEqual(`${paddingTop}px`);
|
|
90
|
+
expect(elementStyles.paddingRight).toEqual(`${paddingRight}px`);
|
|
91
|
+
expect(elementStyles.paddingBottom).toEqual(`${paddingBottom}px`);
|
|
92
|
+
expect(elementStyles.paddingLeft).toEqual(`${paddingLeft}px`);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe("given padding inline start/end, block start/end props", () => {
|
|
97
|
+
it("regardless of order, prioritises inline/block start/end values over others", () => {
|
|
98
|
+
const padding = 10;
|
|
99
|
+
const paddingX = 20;
|
|
100
|
+
const paddingInline = 30;
|
|
101
|
+
const paddingInlineStart = 40;
|
|
102
|
+
const paddingInlineEnd = 50;
|
|
103
|
+
const paddingY = 60;
|
|
104
|
+
const paddingBlock = 70;
|
|
105
|
+
const paddingBlockStart = 80;
|
|
106
|
+
const paddingBlockEnd = 90;
|
|
107
|
+
|
|
108
|
+
const { container } = render(
|
|
109
|
+
<Box
|
|
110
|
+
paddingBlockStart={paddingBlockStart}
|
|
111
|
+
paddingInlineEnd={paddingInlineEnd}
|
|
112
|
+
paddingBlockEnd={paddingBlockEnd}
|
|
113
|
+
paddingInlineStart={paddingInlineStart}
|
|
114
|
+
padding={padding}
|
|
115
|
+
paddingX={paddingX}
|
|
116
|
+
paddingInline={paddingInline}
|
|
117
|
+
paddingY={paddingY}
|
|
118
|
+
paddingBlock={paddingBlock}
|
|
119
|
+
/>,
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const elementStyles = (container.firstChild as HTMLElement)?.style;
|
|
123
|
+
|
|
124
|
+
expect(elementStyles.paddingTop).toEqual(`${paddingBlockStart}px`);
|
|
125
|
+
expect(elementStyles.paddingRight).toEqual(`${paddingInlineEnd}px`);
|
|
126
|
+
expect(elementStyles.paddingBottom).toEqual(`${paddingBlockEnd}px`);
|
|
127
|
+
expect(elementStyles.paddingLeft).toEqual(`${paddingInlineStart}px`);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe("given padding inline, block props", () => {
|
|
132
|
+
it("regardless of order, prioritises inline/block values over x/y aliases", () => {
|
|
133
|
+
// If `padding` value is provided, it does not reflect Chrome browser behaviour
|
|
134
|
+
// JSDOM applies `padding` for all sides
|
|
135
|
+
// const padding = 10;
|
|
136
|
+
const paddingInline = 30;
|
|
137
|
+
const paddingBlock = 70;
|
|
138
|
+
const paddingX = 20;
|
|
139
|
+
const paddingY = 60;
|
|
140
|
+
|
|
141
|
+
const { container } = render(
|
|
142
|
+
<Box
|
|
143
|
+
// padding={padding}
|
|
144
|
+
paddingX={paddingX}
|
|
145
|
+
paddingInline={paddingInline}
|
|
146
|
+
paddingY={paddingY}
|
|
147
|
+
paddingBlock={paddingBlock}
|
|
148
|
+
/>,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
const elementStyles = (container.firstChild as HTMLElement)?.style;
|
|
152
|
+
|
|
153
|
+
expect(elementStyles.paddingBlock).toEqual(`${paddingBlock}px`);
|
|
154
|
+
expect(elementStyles.paddingInline).toEqual(`${paddingInline}px`);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe("given padding X, Y props", () => {
|
|
159
|
+
it("applies values as padding-inline, padding-block respectively ", () => {
|
|
160
|
+
const paddingX = 20;
|
|
161
|
+
const paddingY = 60;
|
|
162
|
+
|
|
163
|
+
const { container } = render(
|
|
164
|
+
<Box paddingX={paddingX} paddingY={paddingY} />,
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
const elementStyles = (container.firstChild as HTMLElement)?.style;
|
|
168
|
+
|
|
169
|
+
expect(elementStyles.paddingBlock).toEqual(`${paddingY}px`);
|
|
170
|
+
expect(elementStyles.paddingInline).toEqual(`${paddingX}px`);
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe("given padding prop", () => {
|
|
175
|
+
it("applies same padding value for all sides", () => {
|
|
176
|
+
const padding = 10;
|
|
177
|
+
|
|
178
|
+
const { container } = render(<Box padding={padding} />);
|
|
179
|
+
|
|
180
|
+
const elementStyles = (container.firstChild as HTMLElement)?.style;
|
|
181
|
+
|
|
182
|
+
expect(elementStyles.padding).toEqual(`${padding}px`);
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
describe("given minWidth prop", () => {
|
|
187
|
+
it.each([
|
|
188
|
+
"minWidth",
|
|
189
|
+
"minHeight",
|
|
190
|
+
"maxWidth",
|
|
191
|
+
"maxHeight",
|
|
192
|
+
"width",
|
|
193
|
+
"height",
|
|
194
|
+
])("applies %s value", (propName: string) => {
|
|
195
|
+
const value = 100;
|
|
196
|
+
|
|
197
|
+
const { container } = render(<Box {...{ [propName]: value }} />);
|
|
198
|
+
|
|
199
|
+
const elementStyles = (container.firstChild as HTMLElement)?.style;
|
|
200
|
+
|
|
201
|
+
expect(elementStyles[propName as keyof CSSStyleDeclaration]).toEqual(
|
|
202
|
+
`${value}px`,
|
|
203
|
+
);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe("given style prop", () => {
|
|
208
|
+
it("overrides default styles", () => {
|
|
209
|
+
const { container } = render(
|
|
210
|
+
<Box padding={50} style={{ padding: 100 }}>
|
|
211
|
+
Sample text
|
|
33
212
|
</Box>,
|
|
34
213
|
);
|
|
35
|
-
|
|
36
|
-
|
|
214
|
+
|
|
215
|
+
const elementStyles = (container.firstChild as HTMLElement)?.style;
|
|
216
|
+
|
|
217
|
+
expect(elementStyles.padding).toEqual("100px");
|
|
37
218
|
});
|
|
38
219
|
});
|
|
39
220
|
});
|
|
@@ -1,28 +1,65 @@
|
|
|
1
|
-
import { Ref, forwardRef
|
|
1
|
+
import { Ref, forwardRef } from "react";
|
|
2
2
|
import classNames from "classnames/dedupe";
|
|
3
|
-
import { DOMProps } from "../../types/dom";
|
|
4
3
|
import { ForwardedRefComponent } from "../../types/components";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export interface BoxProps extends DOMProps, RefAttributes<BoxElementType> {
|
|
9
|
-
children?: ReactNode;
|
|
10
|
-
/** Custom class name for setting specific CSS */
|
|
11
|
-
className?: string;
|
|
12
|
-
/** HTML element for the Box */
|
|
13
|
-
elementType?: "div" | "span";
|
|
14
|
-
style?: React.CSSProperties;
|
|
15
|
-
}
|
|
4
|
+
import { BoxElementType, BoxProps } from "./types";
|
|
5
|
+
import { getSpacingValue, filterUndefinedProps } from "../../utils";
|
|
16
6
|
|
|
17
7
|
export type BoxRef = Ref<BoxElementType>;
|
|
18
8
|
|
|
19
9
|
const Box: ForwardedRefComponent<BoxProps, BoxElementType> = forwardRef(
|
|
20
10
|
(props: BoxProps, ref: BoxRef) => {
|
|
21
|
-
const {
|
|
11
|
+
const {
|
|
12
|
+
elementType: Element = "div",
|
|
13
|
+
padding,
|
|
14
|
+
paddingX,
|
|
15
|
+
paddingInline,
|
|
16
|
+
paddingInlineStart,
|
|
17
|
+
paddingInlineEnd,
|
|
18
|
+
paddingY,
|
|
19
|
+
paddingBlock,
|
|
20
|
+
paddingBlockStart,
|
|
21
|
+
paddingBlockEnd,
|
|
22
|
+
paddingTop,
|
|
23
|
+
paddingRight,
|
|
24
|
+
paddingBottom,
|
|
25
|
+
paddingLeft,
|
|
26
|
+
minWidth,
|
|
27
|
+
minHeight,
|
|
28
|
+
maxWidth,
|
|
29
|
+
maxHeight,
|
|
30
|
+
width,
|
|
31
|
+
height,
|
|
32
|
+
style,
|
|
33
|
+
...otherProps
|
|
34
|
+
} = props;
|
|
22
35
|
|
|
23
36
|
const classes = classNames("mobius", "mobius/Box", otherProps.className);
|
|
24
37
|
|
|
25
|
-
|
|
38
|
+
const styleProps = filterUndefinedProps({
|
|
39
|
+
padding: getSpacingValue(padding),
|
|
40
|
+
paddingInline: getSpacingValue(paddingInline || paddingX),
|
|
41
|
+
paddingBlock: getSpacingValue(paddingBlock || paddingY),
|
|
42
|
+
paddingTop: getSpacingValue(paddingTop || paddingBlockStart),
|
|
43
|
+
paddingRight: getSpacingValue(paddingRight || paddingInlineEnd),
|
|
44
|
+
paddingBottom: getSpacingValue(paddingBottom || paddingBlockEnd),
|
|
45
|
+
paddingLeft: getSpacingValue(paddingLeft || paddingInlineStart),
|
|
46
|
+
minWidth,
|
|
47
|
+
minHeight,
|
|
48
|
+
maxWidth,
|
|
49
|
+
maxHeight,
|
|
50
|
+
width,
|
|
51
|
+
height,
|
|
52
|
+
...style,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<Element
|
|
57
|
+
ref={ref}
|
|
58
|
+
style={styleProps}
|
|
59
|
+
{...otherProps}
|
|
60
|
+
className={classes}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
26
63
|
},
|
|
27
64
|
);
|
|
28
65
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ReactNode, RefAttributes } from "react";
|
|
2
|
+
import { DOMProps, SpacingType } from "../../types";
|
|
3
|
+
|
|
4
|
+
export type BoxElementType = HTMLDivElement;
|
|
5
|
+
|
|
6
|
+
export type BoxDimensionsType = string | number;
|
|
7
|
+
|
|
8
|
+
export interface BoxProps extends DOMProps, RefAttributes<BoxElementType> {
|
|
9
|
+
children?: ReactNode;
|
|
10
|
+
/** Custom class name for setting specific CSS */
|
|
11
|
+
className?: string;
|
|
12
|
+
/** HTML element for the Box */
|
|
13
|
+
elementType?: "div" | "span";
|
|
14
|
+
style?: React.CSSProperties;
|
|
15
|
+
padding?: SpacingType;
|
|
16
|
+
paddingX?: SpacingType;
|
|
17
|
+
paddingInline?: SpacingType;
|
|
18
|
+
paddingInlineStart?: SpacingType;
|
|
19
|
+
paddingInlineEnd?: SpacingType;
|
|
20
|
+
paddingY?: SpacingType;
|
|
21
|
+
paddingBlock?: SpacingType;
|
|
22
|
+
paddingBlockStart?: SpacingType;
|
|
23
|
+
paddingBlockEnd?: SpacingType;
|
|
24
|
+
paddingTop?: SpacingType;
|
|
25
|
+
paddingRight?: SpacingType;
|
|
26
|
+
paddingBottom?: SpacingType;
|
|
27
|
+
paddingLeft?: SpacingType;
|
|
28
|
+
minWidth?: BoxDimensionsType;
|
|
29
|
+
minHeight?: BoxDimensionsType;
|
|
30
|
+
maxWidth?: BoxDimensionsType;
|
|
31
|
+
maxHeight?: BoxDimensionsType;
|
|
32
|
+
width?: BoxDimensionsType;
|
|
33
|
+
height?: BoxDimensionsType;
|
|
34
|
+
}
|
|
@@ -3,16 +3,6 @@ import { Flex } from "./Flex";
|
|
|
3
3
|
import { Box } from "../Box";
|
|
4
4
|
import * as FlexStories from "./Flex.stories";
|
|
5
5
|
|
|
6
|
-
export const sizeOptions = [
|
|
7
|
-
"",
|
|
8
|
-
"var(--size-xs)",
|
|
9
|
-
"var(--size-sm)",
|
|
10
|
-
"var(--size-md)",
|
|
11
|
-
"var(--size-lg)",
|
|
12
|
-
"var(--size-xl)",
|
|
13
|
-
"var(--size-xxl)",
|
|
14
|
-
];
|
|
15
|
-
|
|
16
6
|
<Meta of={FlexStories} />
|
|
17
7
|
|
|
18
8
|
# Flex
|
|
@@ -2,19 +2,9 @@ import type { Meta, StoryObj } from "@storybook/react";
|
|
|
2
2
|
import { CSSProperties, ReactNode } from "react";
|
|
3
3
|
import { Flex } from "./Flex";
|
|
4
4
|
import { Box } from "../Box";
|
|
5
|
-
import { excludeControls } from "../../utils";
|
|
5
|
+
import { excludeControls, sizeOptions } from "../../utils";
|
|
6
6
|
import { FlexProps } from "./types";
|
|
7
7
|
|
|
8
|
-
const sizeOptions = [
|
|
9
|
-
"",
|
|
10
|
-
"var(--size-xs)",
|
|
11
|
-
"var(--size-sm)",
|
|
12
|
-
"var(--size-md)",
|
|
13
|
-
"var(--size-lg)",
|
|
14
|
-
"var(--size-xl)",
|
|
15
|
-
"var(--size-xxl)",
|
|
16
|
-
];
|
|
17
|
-
|
|
18
8
|
type StoryType = StoryObj<typeof Flex>;
|
|
19
9
|
|
|
20
10
|
const meta: Meta<typeof Flex> = {
|
|
@@ -150,9 +140,7 @@ export const RowLayout: StoryType = {
|
|
|
150
140
|
justifyContent: "normal",
|
|
151
141
|
alignItems: "stretch",
|
|
152
142
|
alignContent: "flex-start",
|
|
153
|
-
gap: "
|
|
154
|
-
rowGap: "",
|
|
155
|
-
columnGap: "",
|
|
143
|
+
gap: "xs",
|
|
156
144
|
},
|
|
157
145
|
};
|
|
158
146
|
|
|
@@ -172,9 +160,7 @@ export const ColumnLayout: StoryType = {
|
|
|
172
160
|
justifyContent: "normal",
|
|
173
161
|
alignItems: "stretch",
|
|
174
162
|
alignContent: "normal",
|
|
175
|
-
gap: "
|
|
176
|
-
rowGap: "",
|
|
177
|
-
columnGap: "",
|
|
163
|
+
gap: "xs",
|
|
178
164
|
},
|
|
179
165
|
};
|
|
180
166
|
|
|
@@ -1,32 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
withoutUndefinedValues,
|
|
3
|
-
buildFlexStyles,
|
|
4
|
-
splitProps,
|
|
5
|
-
} from "./propUtils";
|
|
6
|
-
|
|
7
|
-
describe("withoutUndefinedValues", () => {
|
|
8
|
-
it("returns object without undefined values", () => {
|
|
9
|
-
const props = {
|
|
10
|
-
a: 1,
|
|
11
|
-
b: "Two",
|
|
12
|
-
c: [],
|
|
13
|
-
d: {},
|
|
14
|
-
e: undefined,
|
|
15
|
-
f: undefined,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const actual = withoutUndefinedValues(props);
|
|
19
|
-
|
|
20
|
-
const expected = {
|
|
21
|
-
a: 1,
|
|
22
|
-
b: "Two",
|
|
23
|
-
c: [],
|
|
24
|
-
d: {},
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
expect(actual).toStrictEqual(expected);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
1
|
+
import { buildFlexStyles, splitProps } from "./propUtils";
|
|
30
2
|
|
|
31
3
|
describe("buildFlexStyles", () => {
|
|
32
4
|
describe("given a list of props", () => {
|
|
@@ -39,14 +11,21 @@ describe("buildFlexStyles", () => {
|
|
|
39
11
|
justifyContent: "start",
|
|
40
12
|
alignItems: "stretch",
|
|
41
13
|
alignContent: "center",
|
|
14
|
+
gap: 10,
|
|
15
|
+
rowGap: 20,
|
|
16
|
+
columnGap: 30,
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
const transformedProps = {
|
|
42
20
|
gap: "10px",
|
|
43
21
|
rowGap: "20px",
|
|
44
22
|
columnGap: "30px",
|
|
45
|
-
}
|
|
23
|
+
};
|
|
46
24
|
|
|
47
25
|
const expectedProps = {
|
|
48
|
-
...props,
|
|
49
26
|
display: "flex",
|
|
27
|
+
...props,
|
|
28
|
+
...transformedProps,
|
|
50
29
|
};
|
|
51
30
|
|
|
52
31
|
const actual = buildFlexStyles(props);
|
|
@@ -66,7 +45,7 @@ describe("buildFlexStyles", () => {
|
|
|
66
45
|
alignItems: undefined,
|
|
67
46
|
alignContent: "center",
|
|
68
47
|
gap: undefined,
|
|
69
|
-
rowGap:
|
|
48
|
+
rowGap: 20,
|
|
70
49
|
columnGap: undefined,
|
|
71
50
|
} as const;
|
|
72
51
|
|
|
@@ -97,9 +76,9 @@ describe("splitProps", () => {
|
|
|
97
76
|
justifyContent: "start",
|
|
98
77
|
alignItems: "stretch",
|
|
99
78
|
alignContent: "center",
|
|
100
|
-
gap:
|
|
101
|
-
rowGap:
|
|
102
|
-
columnGap:
|
|
79
|
+
gap: 10,
|
|
80
|
+
rowGap: 20,
|
|
81
|
+
columnGap: 30,
|
|
103
82
|
} as const;
|
|
104
83
|
|
|
105
84
|
const otherProps = {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { getSpacingValue } from "../../utils";
|
|
2
|
+
import { filterUndefinedProps } from "../../utils/filterUndefinedProps";
|
|
1
3
|
import { FlexNonStyleProps, FlexProps, FlexStyleProps } from "./types";
|
|
2
4
|
|
|
3
|
-
export const withoutUndefinedValues = (obj: Record<string, unknown>) =>
|
|
4
|
-
Object.fromEntries(Object.entries(obj).filter(([_, value]) => value));
|
|
5
|
-
|
|
6
5
|
export const buildFlexStyles = (props: FlexStyleProps) => {
|
|
7
6
|
const {
|
|
8
7
|
flexDirection,
|
|
@@ -26,12 +25,12 @@ export const buildFlexStyles = (props: FlexStyleProps) => {
|
|
|
26
25
|
justifyContent,
|
|
27
26
|
alignItems,
|
|
28
27
|
alignContent,
|
|
29
|
-
gap,
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
gap: getSpacingValue(gap),
|
|
29
|
+
columnGap: getSpacingValue(columnGap),
|
|
30
|
+
rowGap: getSpacingValue(rowGap),
|
|
32
31
|
};
|
|
33
32
|
|
|
34
|
-
return
|
|
33
|
+
return filterUndefinedProps(styleProps);
|
|
35
34
|
};
|
|
36
35
|
|
|
37
36
|
export const splitProps = (
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Ref, ReactNode, RefAttributes, AriaRole } from "react";
|
|
2
2
|
import type { Property } from "csstype";
|
|
3
3
|
import { DOMProps } from "../../types/dom";
|
|
4
|
+
import { SpacingType } from "../../types";
|
|
4
5
|
|
|
5
6
|
export type FlexElementType = HTMLDivElement;
|
|
6
7
|
|
|
@@ -17,11 +18,11 @@ export interface FlexStyleProps {
|
|
|
17
18
|
/** Aligns the grid along the inline (row) axis */
|
|
18
19
|
justifyContent?: Property.JustifyContent;
|
|
19
20
|
/** How big a gap between the columns and rows */
|
|
20
|
-
gap?:
|
|
21
|
+
gap?: SpacingType;
|
|
21
22
|
/** How big a gap between the rows */
|
|
22
|
-
rowGap?:
|
|
23
|
+
rowGap?: SpacingType;
|
|
23
24
|
/** How big a gap between the columns */
|
|
24
|
-
columnGap?:
|
|
25
|
+
columnGap?: SpacingType;
|
|
25
26
|
style?: React.CSSProperties;
|
|
26
27
|
role?: AriaRole;
|
|
27
28
|
}
|
|
@@ -4,16 +4,6 @@ import { Box } from "../Box";
|
|
|
4
4
|
import { Flex } from "../Flex";
|
|
5
5
|
import * as GridStories from "./Grid.stories";
|
|
6
6
|
|
|
7
|
-
export const sizeOptions = [
|
|
8
|
-
"",
|
|
9
|
-
"size-xs",
|
|
10
|
-
"size-s",
|
|
11
|
-
"size-m",
|
|
12
|
-
"size-l",
|
|
13
|
-
"size-xl",
|
|
14
|
-
"size-xxl",
|
|
15
|
-
];
|
|
16
|
-
|
|
17
7
|
<Meta of={GridStories} />
|
|
18
8
|
|
|
19
9
|
# Grid
|