@spark-web/box 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/CHANGELOG.md +16 -0
- package/README.md +106 -0
- package/dist/declarations/src/BackgroundProvider.d.ts +7 -0
- package/dist/declarations/src/Box.d.ts +38 -0
- package/dist/declarations/src/context.d.ts +7 -0
- package/dist/declarations/src/index.d.ts +5 -0
- package/dist/declarations/src/useBoxProps.d.ts +6 -0
- package/dist/declarations/src/useBoxStyles.d.ts +219 -0
- package/dist/spark-web-box.cjs.d.ts +1 -0
- package/dist/spark-web-box.cjs.dev.js +320 -0
- package/dist/spark-web-box.cjs.js +7 -0
- package/dist/spark-web-box.cjs.prod.js +320 -0
- package/dist/spark-web-box.esm.js +309 -0
- package/package.json +20 -0
- package/src/BackgroundProvider.tsx +19 -0
- package/src/Box.stories.tsx +26 -0
- package/src/Box.tsx +45 -0
- package/src/context.tsx +54 -0
- package/src/index.ts +8 -0
- package/src/useBoxProps.ts +99 -0
- package/src/useBoxStyles.ts +422 -0
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
import type { BrighteTheme, ResponsiveProp } from '@spark-web/theme';
|
|
2
|
+
import { useTheme } from '@spark-web/theme';
|
|
3
|
+
|
|
4
|
+
// TODO perf review
|
|
5
|
+
// TODO: review responsive props! Now that we're using object syntax, un-mapped properties don't behave as expected
|
|
6
|
+
|
|
7
|
+
// types
|
|
8
|
+
|
|
9
|
+
type ValidGapKeys = keyof Omit<BrighteTheme['spacing'], 'none' | 'full'>;
|
|
10
|
+
type ResponsiveSpacing = ResponsiveProp<keyof BrighteTheme['spacing']>;
|
|
11
|
+
type ResponsiveSizing = ResponsiveProp<keyof BrighteTheme['sizing']>;
|
|
12
|
+
|
|
13
|
+
export type ResponsiveBoxProps = {
|
|
14
|
+
/**
|
|
15
|
+
* The `margin` shorthand property sets the margin area on all four sides of
|
|
16
|
+
* an element at once.
|
|
17
|
+
*/
|
|
18
|
+
margin?: ResponsiveSpacing;
|
|
19
|
+
/**
|
|
20
|
+
* The `marginTop` property sets the margin area on the top side of an
|
|
21
|
+
* element.
|
|
22
|
+
*/
|
|
23
|
+
marginTop?: ResponsiveSpacing;
|
|
24
|
+
/**
|
|
25
|
+
* The `marginRight` property sets the margin area on the right side of an
|
|
26
|
+
* element.
|
|
27
|
+
*/
|
|
28
|
+
marginRight?: ResponsiveSpacing;
|
|
29
|
+
/**
|
|
30
|
+
* The `marginBottom` property sets the margin area on the bottom side of an
|
|
31
|
+
* element.
|
|
32
|
+
*/
|
|
33
|
+
marginBottom?: ResponsiveSpacing;
|
|
34
|
+
/**
|
|
35
|
+
* The `marginLeft` property sets the margin area on the left side of an
|
|
36
|
+
* element.
|
|
37
|
+
*/
|
|
38
|
+
marginLeft?: ResponsiveSpacing;
|
|
39
|
+
/**
|
|
40
|
+
* The `marginY` shorthand property sets the margin area on the top and
|
|
41
|
+
* bottom of the element.
|
|
42
|
+
*/
|
|
43
|
+
marginY?: ResponsiveSpacing;
|
|
44
|
+
/**
|
|
45
|
+
* The `marginY` shorthand property sets the margin area on the left and
|
|
46
|
+
* right of the element.
|
|
47
|
+
*/
|
|
48
|
+
marginX?: ResponsiveSpacing;
|
|
49
|
+
|
|
50
|
+
// ==============================
|
|
51
|
+
// PADDING
|
|
52
|
+
// ==============================
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The `padding` shorthand property sets the padding area on all four sides
|
|
56
|
+
* of an element at once.
|
|
57
|
+
*/
|
|
58
|
+
padding?: ResponsiveSpacing;
|
|
59
|
+
/**
|
|
60
|
+
* The `paddingTop` property sets the height of the padding area on the top
|
|
61
|
+
* of an element.
|
|
62
|
+
*/
|
|
63
|
+
paddingTop?: ResponsiveSpacing;
|
|
64
|
+
/**
|
|
65
|
+
* The `paddingRight` property sets the width of the padding area on the
|
|
66
|
+
* right of an element.
|
|
67
|
+
*/
|
|
68
|
+
paddingRight?: ResponsiveSpacing;
|
|
69
|
+
/**
|
|
70
|
+
* The `paddingBottom` property sets the height of the padding area on the
|
|
71
|
+
* bottom of an element.
|
|
72
|
+
*/
|
|
73
|
+
paddingBottom?: ResponsiveSpacing;
|
|
74
|
+
/**
|
|
75
|
+
* The `paddingLeft` property sets the width of the padding area on the left
|
|
76
|
+
* of an element.
|
|
77
|
+
*/
|
|
78
|
+
paddingLeft?: ResponsiveSpacing;
|
|
79
|
+
/**
|
|
80
|
+
* The `paddingY` shorthand property sets the padding area on the top and
|
|
81
|
+
* bottom of the element.
|
|
82
|
+
*/
|
|
83
|
+
paddingY?: ResponsiveSpacing;
|
|
84
|
+
/**
|
|
85
|
+
* The `paddingX` shorthand property sets the padding area on the left and
|
|
86
|
+
* right of the element.
|
|
87
|
+
*/
|
|
88
|
+
paddingX?: ResponsiveSpacing;
|
|
89
|
+
|
|
90
|
+
// ==============================
|
|
91
|
+
// BORDER
|
|
92
|
+
// ==============================
|
|
93
|
+
|
|
94
|
+
/** The `border` property sets the color of an element's border. */
|
|
95
|
+
border?: ResponsiveProp<keyof BrighteTheme['border']['color']>;
|
|
96
|
+
/**
|
|
97
|
+
* The `borderRadius` property rounds the corners of an element's outer
|
|
98
|
+
* border edge.
|
|
99
|
+
*/
|
|
100
|
+
borderRadius?: ResponsiveProp<keyof BrighteTheme['border']['radius']>;
|
|
101
|
+
/**
|
|
102
|
+
* The `borderWidth` property sets the width of an element's border.
|
|
103
|
+
*/
|
|
104
|
+
borderWidth?: ResponsiveProp<keyof BrighteTheme['border']['width']>;
|
|
105
|
+
|
|
106
|
+
// ==============================
|
|
107
|
+
// DIMENSIONS
|
|
108
|
+
// ==============================
|
|
109
|
+
|
|
110
|
+
/** Sets the element's height. */
|
|
111
|
+
height?: ResponsiveSizing;
|
|
112
|
+
/** Sets the element's width. */
|
|
113
|
+
width?: ResponsiveSizing;
|
|
114
|
+
|
|
115
|
+
// ==============================
|
|
116
|
+
// FLEX: Parent
|
|
117
|
+
// ==============================
|
|
118
|
+
|
|
119
|
+
/** Controls the alignment of items on the cross axis. */
|
|
120
|
+
alignItems?: ResponsiveProp<keyof typeof flexMap.alignItems>;
|
|
121
|
+
/** The size of the gap between each child element. */
|
|
122
|
+
gap?: ResponsiveProp<ValidGapKeys>;
|
|
123
|
+
/** Defines the main axis, or how the children are placed. */
|
|
124
|
+
flexDirection?: ResponsiveProp<keyof typeof flexMap.flexDirection>;
|
|
125
|
+
/**
|
|
126
|
+
* defines how the browser distributes space between and around content items
|
|
127
|
+
* along the main-axis.
|
|
128
|
+
*/
|
|
129
|
+
justifyContent?: ResponsiveProp<keyof typeof flexMap.justifyContent>;
|
|
130
|
+
/** Allow flex items to flow onto multiple lines. */
|
|
131
|
+
flexWrap?: ResponsiveProp<'nowrap' | 'wrap'>;
|
|
132
|
+
|
|
133
|
+
// ==============================
|
|
134
|
+
// FLEX: Child
|
|
135
|
+
// ==============================
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Overrides the parent's `align-items` value. Controls the alignment of
|
|
139
|
+
* item's on the cross axis.
|
|
140
|
+
*/
|
|
141
|
+
alignSelf?: ResponsiveProp<keyof typeof flexMap.alignItems>;
|
|
142
|
+
/**
|
|
143
|
+
* The `flex` shorthand property sets how a flex item will grow or shrink to
|
|
144
|
+
* fit the space available in its flex container.
|
|
145
|
+
*/
|
|
146
|
+
flex?: ResponsiveProp<0 | 1>;
|
|
147
|
+
/** The `flexGrow` property sets the flex grow factor of a flex item main size. */
|
|
148
|
+
flexGrow?: ResponsiveProp<0 | 1>;
|
|
149
|
+
/**
|
|
150
|
+
* The `flexShrink` property sets the flex shrink factor of a flex item. If
|
|
151
|
+
* the size of all flex items is larger than the flex container, items shrink
|
|
152
|
+
* to fit according to `flex-shrink`.
|
|
153
|
+
*/
|
|
154
|
+
flexShrink?: ResponsiveProp<0 | 1>;
|
|
155
|
+
|
|
156
|
+
// ==============================
|
|
157
|
+
// POSITION
|
|
158
|
+
// ==============================
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The `position` property sets how an element is positioned in a document.
|
|
162
|
+
* The `top`, `right`, `bottom`, and `left` properties determine the final
|
|
163
|
+
* location of positioned elements.
|
|
164
|
+
*/
|
|
165
|
+
position?: ResponsiveProp<'absolute' | 'fixed' | 'relative' | 'sticky'>;
|
|
166
|
+
/**
|
|
167
|
+
* The `top` property participates in specifying the vertical position of a
|
|
168
|
+
* positioned element. It has no effect on non-positioned elements.
|
|
169
|
+
*/
|
|
170
|
+
top?: ResponsiveProp<0>;
|
|
171
|
+
/**
|
|
172
|
+
* The `right` property participates in specifying the horizontal position of
|
|
173
|
+
* a positioned element. It has no effect on non-positioned elements.
|
|
174
|
+
*/
|
|
175
|
+
right?: ResponsiveProp<0>;
|
|
176
|
+
/**
|
|
177
|
+
* The `bottom` property participates in setting the vertical position of a
|
|
178
|
+
* positioned element. It has no effect on non-positioned elements.
|
|
179
|
+
*/
|
|
180
|
+
bottom?: ResponsiveProp<0>;
|
|
181
|
+
/**
|
|
182
|
+
* The `left` property participates in specifying the horizontal position of a
|
|
183
|
+
* positioned element. It has no effect on non-positioned elements.
|
|
184
|
+
*/
|
|
185
|
+
left?: ResponsiveProp<0>;
|
|
186
|
+
/**
|
|
187
|
+
* The `zIndex` property sets the "z-order" of a positioned element and its
|
|
188
|
+
* descendants or flex items. Overlapping elements with a larger z-index cover
|
|
189
|
+
* those with a smaller one.
|
|
190
|
+
*/
|
|
191
|
+
zIndex?: ResponsiveProp<keyof BrighteTheme['elevation']>;
|
|
192
|
+
|
|
193
|
+
// ==============================
|
|
194
|
+
// MISC...
|
|
195
|
+
// ==============================
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Sets whether an element is treated as a block or inline element and the
|
|
199
|
+
* layout used for its children.
|
|
200
|
+
*/
|
|
201
|
+
display?: ResponsiveProp<
|
|
202
|
+
'block' | 'flex' | 'inline' | 'inline-block' | 'inline-flex' | 'none'
|
|
203
|
+
>;
|
|
204
|
+
/**
|
|
205
|
+
* Sets the opacity of the element. Opacity is the degree to which content
|
|
206
|
+
* behind an element is hidden, and is the opposite of transparency.
|
|
207
|
+
*/
|
|
208
|
+
opacity?: ResponsiveProp<number>;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
type UnresponsiveBoxProps = {
|
|
212
|
+
/** The `background` property sets the background color of an element. */
|
|
213
|
+
background?: keyof BrighteTheme['color']['background'];
|
|
214
|
+
/**
|
|
215
|
+
* The `cursor` property sets the type of mouse cursor, if any, to show when
|
|
216
|
+
* the mouse pointer is over an element.
|
|
217
|
+
*/
|
|
218
|
+
cursor?: 'default' | 'pointer';
|
|
219
|
+
/**
|
|
220
|
+
* The `minHeight` property sets the minimum height of an element. It prevents
|
|
221
|
+
* the used value of the height property from becoming smaller than the value
|
|
222
|
+
* specified for `minHeight`.
|
|
223
|
+
*/
|
|
224
|
+
minHeight?: 0;
|
|
225
|
+
/**
|
|
226
|
+
* The `minWidth` property sets the minimum width of an element. It prevents
|
|
227
|
+
* the used value of the width property from becoming smaller than the value
|
|
228
|
+
* specified for `minWidth`.
|
|
229
|
+
*/
|
|
230
|
+
minWidth?: 0;
|
|
231
|
+
/**
|
|
232
|
+
* The `overflow` shorthand property sets the desired behavior for an
|
|
233
|
+
* element's overflow — i.e. when an element's content is too big to fit in
|
|
234
|
+
* its block formatting context — in both directions.
|
|
235
|
+
*/
|
|
236
|
+
overflow?: 'hidden' | 'scroll' | 'visible' | 'auto';
|
|
237
|
+
/** The `boxShadow` property adds shadow effects around an element's frame. */
|
|
238
|
+
shadow?: keyof BrighteTheme['shadow'];
|
|
239
|
+
/** The `userSelect` property controls whether the user can select text. */
|
|
240
|
+
userSelect?: 'none';
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export type BoxStyleProps = UnresponsiveBoxProps & ResponsiveBoxProps;
|
|
244
|
+
|
|
245
|
+
// Hook
|
|
246
|
+
// ------------------------------
|
|
247
|
+
|
|
248
|
+
export const useBoxStyles = ({
|
|
249
|
+
alignItems,
|
|
250
|
+
alignSelf,
|
|
251
|
+
background,
|
|
252
|
+
border,
|
|
253
|
+
borderRadius,
|
|
254
|
+
borderWidth = 'standard',
|
|
255
|
+
bottom,
|
|
256
|
+
cursor,
|
|
257
|
+
display,
|
|
258
|
+
flex,
|
|
259
|
+
flexDirection,
|
|
260
|
+
flexGrow,
|
|
261
|
+
flexShrink,
|
|
262
|
+
flexWrap,
|
|
263
|
+
gap,
|
|
264
|
+
height,
|
|
265
|
+
justifyContent,
|
|
266
|
+
left,
|
|
267
|
+
margin,
|
|
268
|
+
marginBottom,
|
|
269
|
+
marginLeft,
|
|
270
|
+
marginRight,
|
|
271
|
+
marginTop,
|
|
272
|
+
marginX,
|
|
273
|
+
marginY,
|
|
274
|
+
minHeight,
|
|
275
|
+
minWidth,
|
|
276
|
+
opacity,
|
|
277
|
+
overflow,
|
|
278
|
+
padding,
|
|
279
|
+
paddingBottom,
|
|
280
|
+
paddingLeft,
|
|
281
|
+
paddingRight,
|
|
282
|
+
paddingTop,
|
|
283
|
+
paddingX,
|
|
284
|
+
paddingY,
|
|
285
|
+
position,
|
|
286
|
+
right,
|
|
287
|
+
shadow,
|
|
288
|
+
top,
|
|
289
|
+
userSelect,
|
|
290
|
+
width,
|
|
291
|
+
zIndex,
|
|
292
|
+
}: BoxStyleProps) => {
|
|
293
|
+
const theme = useTheme();
|
|
294
|
+
|
|
295
|
+
const unresponsiveProps = {
|
|
296
|
+
background: background ? theme.color.background[background] : undefined,
|
|
297
|
+
boxShadow: shadow ? theme.shadow[shadow] : undefined,
|
|
298
|
+
cursor,
|
|
299
|
+
minHeight,
|
|
300
|
+
minWidth,
|
|
301
|
+
opacity,
|
|
302
|
+
overflow,
|
|
303
|
+
userSelect,
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const conditionalBorderStyles = border
|
|
307
|
+
? {
|
|
308
|
+
borderStyle: 'solid',
|
|
309
|
+
borderColor: theme.utils.mapResponsiveScale(border, theme.border.color),
|
|
310
|
+
borderWidth: theme.utils.mapResponsiveScale(
|
|
311
|
+
borderWidth,
|
|
312
|
+
theme.border.width
|
|
313
|
+
),
|
|
314
|
+
}
|
|
315
|
+
: null;
|
|
316
|
+
|
|
317
|
+
return theme.utils.resolveResponsiveProps({
|
|
318
|
+
...unresponsiveProps,
|
|
319
|
+
...conditionalBorderStyles,
|
|
320
|
+
|
|
321
|
+
// allow padding and height/width props to play nice
|
|
322
|
+
display: theme.utils.mapResponsiveProp(display),
|
|
323
|
+
|
|
324
|
+
// margin
|
|
325
|
+
marginBottom: theme.utils.mapResponsiveScale(
|
|
326
|
+
marginBottom || marginY || margin,
|
|
327
|
+
theme.spacing
|
|
328
|
+
),
|
|
329
|
+
marginTop: theme.utils.mapResponsiveScale(
|
|
330
|
+
marginTop || marginY || margin,
|
|
331
|
+
theme.spacing
|
|
332
|
+
),
|
|
333
|
+
marginLeft: theme.utils.mapResponsiveScale(
|
|
334
|
+
marginLeft || marginX || margin,
|
|
335
|
+
theme.spacing
|
|
336
|
+
),
|
|
337
|
+
marginRight: theme.utils.mapResponsiveScale(
|
|
338
|
+
marginRight || marginX || margin,
|
|
339
|
+
theme.spacing
|
|
340
|
+
),
|
|
341
|
+
|
|
342
|
+
// padding
|
|
343
|
+
paddingBottom: theme.utils.mapResponsiveScale(
|
|
344
|
+
paddingBottom || paddingY || padding,
|
|
345
|
+
theme.spacing
|
|
346
|
+
),
|
|
347
|
+
paddingTop: theme.utils.mapResponsiveScale(
|
|
348
|
+
paddingTop || paddingY || padding,
|
|
349
|
+
theme.spacing
|
|
350
|
+
),
|
|
351
|
+
paddingLeft: theme.utils.mapResponsiveScale(
|
|
352
|
+
paddingLeft || paddingX || padding,
|
|
353
|
+
theme.spacing
|
|
354
|
+
),
|
|
355
|
+
paddingRight: theme.utils.mapResponsiveScale(
|
|
356
|
+
paddingRight || paddingX || padding,
|
|
357
|
+
theme.spacing
|
|
358
|
+
),
|
|
359
|
+
|
|
360
|
+
// border
|
|
361
|
+
borderRadius: theme.utils.mapResponsiveScale(
|
|
362
|
+
borderRadius,
|
|
363
|
+
theme.border.radius
|
|
364
|
+
),
|
|
365
|
+
|
|
366
|
+
// flex: parent
|
|
367
|
+
alignItems: theme.utils.mapResponsiveScale(alignItems, flexMap.alignItems),
|
|
368
|
+
gap: theme.utils.mapResponsiveScale(gap, theme.spacing),
|
|
369
|
+
flexDirection: theme.utils.mapResponsiveScale(
|
|
370
|
+
flexDirection,
|
|
371
|
+
flexMap.flexDirection
|
|
372
|
+
),
|
|
373
|
+
justifyContent: theme.utils.mapResponsiveScale(
|
|
374
|
+
justifyContent,
|
|
375
|
+
flexMap.justifyContent
|
|
376
|
+
),
|
|
377
|
+
flexWrap: theme.utils.mapResponsiveProp(flexWrap),
|
|
378
|
+
|
|
379
|
+
// flex: child
|
|
380
|
+
alignSelf: theme.utils.mapResponsiveScale(alignSelf, flexMap.alignItems),
|
|
381
|
+
flex: theme.utils.mapResponsiveProp(flex),
|
|
382
|
+
flexGrow: theme.utils.mapResponsiveProp(flexGrow),
|
|
383
|
+
flexShrink: theme.utils.mapResponsiveProp(flexShrink),
|
|
384
|
+
|
|
385
|
+
// dimension
|
|
386
|
+
height: theme.utils.mapResponsiveScale(height, theme.sizing),
|
|
387
|
+
width: theme.utils.mapResponsiveScale(width, theme.sizing),
|
|
388
|
+
|
|
389
|
+
// position
|
|
390
|
+
position: theme.utils.mapResponsiveProp(position),
|
|
391
|
+
bottom: theme.utils.mapResponsiveProp(bottom),
|
|
392
|
+
left: theme.utils.mapResponsiveProp(left),
|
|
393
|
+
right: theme.utils.mapResponsiveProp(right),
|
|
394
|
+
top: theme.utils.mapResponsiveProp(top),
|
|
395
|
+
zIndex: theme.utils.mapResponsiveScale(zIndex, theme.elevation),
|
|
396
|
+
});
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
// Flex shorthand / adjustments
|
|
400
|
+
// ------------------------------
|
|
401
|
+
|
|
402
|
+
const flexMap = {
|
|
403
|
+
alignItems: {
|
|
404
|
+
start: 'flex-start',
|
|
405
|
+
center: 'center',
|
|
406
|
+
end: 'flex-end',
|
|
407
|
+
stretch: 'stretch',
|
|
408
|
+
},
|
|
409
|
+
justifyContent: {
|
|
410
|
+
start: 'flex-start',
|
|
411
|
+
center: 'center',
|
|
412
|
+
end: 'flex-end',
|
|
413
|
+
spaceBetween: 'space-between',
|
|
414
|
+
stretch: 'stretch',
|
|
415
|
+
},
|
|
416
|
+
flexDirection: {
|
|
417
|
+
row: 'row',
|
|
418
|
+
rowReverse: 'row-reverse',
|
|
419
|
+
column: 'column',
|
|
420
|
+
columnReverse: 'column-reverse',
|
|
421
|
+
},
|
|
422
|
+
} as const;
|