Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import {Component, h, Prop, Host} from '@stencil/core';
import {css} from 'emotion';
const toRemValue = (val?: number) => {
return typeof val === 'number' ? `${val}rem` : undefined;
};
interface P {
p?: number[];
pt?: number[];
pl?: number[];
pb?: number[];
pr?: number[];
h?: number;
bg?: string;
width: string[];
justify: string;
align: string;
}
const breakpoints = ['30rem', '48rem', '60rem', '76rem', '80rem'];
const mq = breakpoints.map((b) => `@media (min-width: ${b})`);
const createCssClass = ({pt, pb, pl, pr, h, bg, width, justify, align}: P) => {
const last = width[width.length - 1];
return css`
padding-top: ${toRemValue(pt[0])};
padding-right: ${toRemValue(pr[0])};
padding-bottom: ${toRemValue(pb[0])};
padding-left: ${toRemValue(pl[0])};
height: ${toRemValue(h)};
background-color: ${!!bg ? `var(--${bg})` : 'transparent'};
width: ${width[0]};
display: flex;
justify-content: ${justify || 'flex-start'};
align-items: ${align || 'flex-start'};
${mq[0]} {
width: ${width[1]};
padding-top: ${toRemValue(pt[1])};
padding-right: ${toRemValue(pr[1])};
padding-bottom: ${toRemValue(pb[1])};
padding-left: ${toRemValue(pl[1])};
}
${mq[1]} {
width: ${width[2] || last};
padding-top: ${toRemValue(pt[2])};
padding-right: ${toRemValue(pr[2])};
padding-bottom: ${toRemValue(pb[2])};
padding-left: ${toRemValue(pl[2])};
}
${mq[2]} {
width: ${width[3] || last};
padding-top: ${toRemValue(pt[3])};
padding-right: ${toRemValue(pr[3])};
padding-bottom: ${toRemValue(pb[3])};
padding-left: ${toRemValue(pl[3])};
}
${mq[3]} {
width: ${width[4] || last};
padding-top: ${toRemValue(pt[4])};
padding-right: ${toRemValue(pr[4])};
padding-bottom: ${toRemValue(pb[4])};
padding-left: ${toRemValue(pl[4])};
}
${mq[4]} {
width: ${width[5] || last};
padding-top: ${toRemValue(pt[5])};
padding-right: ${toRemValue(pr[5])};
padding-bottom: ${toRemValue(pb[5])};
padding-left: ${toRemValue(pl[5])};
}
`;
};
const toNumArray = (value?: string) =>
value
?.split(',')
.map((v) => `${v.trim()}`)
.map((v) => parseFloat(v));
@Component({
tag: 'hy-box',
styleUrl: 'hy-box.scss',
shadow: false,
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
})
export class HyBox {
/**
* All sides padding value in rems. Responsive when given Comma separated values.
*/
@Prop() p?: string;
/**
* Left padding in rems. Responsive when given Comma separated values.
*/
@Prop() pl?: string;
/**
* Right padding in rems. Responsive when given Comma separated values.
*/
@Prop() pr?: string;
/**
* Bottom padding in rems. Responsive when given Comma separated values.
*/
@Prop() pb?: string;
/**
* Top padding in rems. Responsive when given Comma separated values.
*/
@Prop() pt?: string;
/**
* Value for horisontal alignment (justify-content)
*/
@Prop() justify: string = 'flex-start';
/**
* value for vertical alignment (align-items)
*/
@Prop() align: string = 'baseline';
/**
* fixed height for the container, useful for extra spacing containers
*/
@Prop() h?: number;
/**
* background color. Must use one of css variable names from color tokens
*/
@Prop() bg: string = 'transparent';
/**
* Responsive width. Must be a comma separated string of percentage values for breakpoints. First item is the default value.
*/
@Prop() width: string = '100';
render() {
const pt = toNumArray(this.pt) ?? toNumArray(this.p) ?? [0];
const pb = toNumArray(this.pb) ?? toNumArray(this.p) ?? [0];
const pr = toNumArray(this.pr) ?? toNumArray(this.p) ?? [0];
const pl = toNumArray(this.pl) ?? toNumArray(this.p) ?? [0];
return (
<Host
class={createCssClass({
pt,
pl,
pr,
pb,
h: this.h,
bg: this.bg,
width: this.width.split(',').map((v) => `${v.trim()}%`),
justify: this.justify,
align: this.align,
})}
>
<slot></slot>
</Host>
);
}
}