@latte-macchiat-io/latte-vanilla-components 0.0.175 → 0.0.176
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/dist/css/index.cjs +1 -0
- package/dist/css/index.js +34 -0
- package/dist/index.cjs.js +2 -2
- package/dist/index.es.js +3195 -6145
- package/dist/theme.css-CNjMk-g_.cjs +1 -0
- package/dist/theme.css-Dj6kL9o0.js +3020 -0
- package/dist/types/css/index.d.ts +28 -0
- package/dist/types/styles/mediaqueries.d.ts +16 -0
- package/dist/types/styles/sprinkles.css.d.ts +3423 -0
- package/dist/types/theme/baseThemeValues.d.ts +158 -0
- package/dist/types/theme/contract.css.d.ts +79 -0
- package/dist/types/theme/index.d.ts +3 -0
- package/dist/types/theme/utils.d.ts +86 -0
- package/package.json +17 -13
- package/src/assets/styles/default-theme.ts +312 -0
- package/src/components/Button/stories.ts +127 -0
- package/src/components/Columns/stories.ts +35 -0
- package/src/components/Icon/path.ts +36 -0
- package/src/components/Icon/stories.ts +29 -0
- package/src/components/Main/stories.ts +33 -0
- package/src/components/Section/stories.ts +64 -0
- package/src/css/index.ts +33 -0
- package/src/index.ts +96 -0
- package/src/styles/mediaqueries.ts +17 -0
- package/src/theme/baseThemeValues.ts +160 -0
- package/src/theme/index.ts +6 -0
- package/src/theme/utils.ts +76 -0
- package/src/themes/dark.ts +3 -0
- package/src/themes/index.ts +5 -0
- package/src/themes/light.ts +3 -0
- package/src/types/theme.ts +295 -0
- package/src/types/withClassName.ts +3 -0
- package/src/utils/cookie.ts +24 -0
- package/src/utils/deep-merge-objects.ts +15 -0
- package/src/utils/use-breakpoint-key.ts +30 -0
- package/src/utils/use-window-size.ts +37 -0
@@ -0,0 +1,76 @@
|
|
1
|
+
import { baseDarkTheme, baseLightTheme } from './baseThemeValues';
|
2
|
+
import { themeContract } from './contract.css';
|
3
|
+
|
4
|
+
export type ThemeValues = typeof baseLightTheme;
|
5
|
+
|
6
|
+
export const createThemeOverride = (overrides: Partial<ThemeValues>): ThemeValues => {
|
7
|
+
return {
|
8
|
+
...baseLightTheme,
|
9
|
+
...overrides,
|
10
|
+
colors: {
|
11
|
+
...baseLightTheme.colors,
|
12
|
+
...overrides.colors,
|
13
|
+
},
|
14
|
+
space: {
|
15
|
+
...baseLightTheme.space,
|
16
|
+
...overrides.space,
|
17
|
+
},
|
18
|
+
radii: {
|
19
|
+
...baseLightTheme.radii,
|
20
|
+
...overrides.radii,
|
21
|
+
},
|
22
|
+
fonts: {
|
23
|
+
...baseLightTheme.fonts,
|
24
|
+
...overrides.fonts,
|
25
|
+
},
|
26
|
+
fontSizes: {
|
27
|
+
...baseLightTheme.fontSizes,
|
28
|
+
...overrides.fontSizes,
|
29
|
+
},
|
30
|
+
lineHeights: {
|
31
|
+
...baseLightTheme.lineHeights,
|
32
|
+
...overrides.lineHeights,
|
33
|
+
},
|
34
|
+
shadows: {
|
35
|
+
...baseLightTheme.shadows,
|
36
|
+
...overrides.shadows,
|
37
|
+
},
|
38
|
+
};
|
39
|
+
};
|
40
|
+
|
41
|
+
export const getThemeContract = () => themeContract;
|
42
|
+
|
43
|
+
export const getThemeValues = (isDark = false): ThemeValues => {
|
44
|
+
return isDark ? baseDarkTheme : baseLightTheme;
|
45
|
+
};
|
46
|
+
|
47
|
+
export const toggleTheme = () => {
|
48
|
+
const html = document.documentElement;
|
49
|
+
const currentTheme = html.getAttribute('data-theme');
|
50
|
+
const newTheme = currentTheme === 'dark' ? null : 'dark';
|
51
|
+
|
52
|
+
if (newTheme) {
|
53
|
+
html.setAttribute('data-theme', newTheme);
|
54
|
+
} else {
|
55
|
+
html.removeAttribute('data-theme');
|
56
|
+
}
|
57
|
+
|
58
|
+
return newTheme === 'dark';
|
59
|
+
};
|
60
|
+
|
61
|
+
export const setTheme = (theme: 'light' | 'dark') => {
|
62
|
+
const html = document.documentElement;
|
63
|
+
|
64
|
+
if (theme === 'dark') {
|
65
|
+
html.setAttribute('data-theme', 'dark');
|
66
|
+
} else {
|
67
|
+
html.removeAttribute('data-theme');
|
68
|
+
}
|
69
|
+
};
|
70
|
+
|
71
|
+
export const getCurrentTheme = (): 'light' | 'dark' => {
|
72
|
+
if (typeof window === 'undefined') return 'light';
|
73
|
+
|
74
|
+
const html = document.documentElement;
|
75
|
+
return html.getAttribute('data-theme') === 'dark' ? 'dark' : 'light';
|
76
|
+
};
|
@@ -0,0 +1,295 @@
|
|
1
|
+
export interface Theme {
|
2
|
+
global: {
|
3
|
+
maxWidth: number;
|
4
|
+
paddingLeft: number[];
|
5
|
+
paddingRight: number[];
|
6
|
+
|
7
|
+
brandFont: string;
|
8
|
+
defaultFont: string;
|
9
|
+
};
|
10
|
+
|
11
|
+
colors: {
|
12
|
+
defaultText: string;
|
13
|
+
defaultLightText: string;
|
14
|
+
defaultTitle: string;
|
15
|
+
defaultLink: string;
|
16
|
+
defaultIcon: string;
|
17
|
+
};
|
18
|
+
|
19
|
+
backgroundColors: {
|
20
|
+
modal: string;
|
21
|
+
modalOverlay: string;
|
22
|
+
cookieConsent: string;
|
23
|
+
};
|
24
|
+
|
25
|
+
borders: {
|
26
|
+
hr: string;
|
27
|
+
cookieConsent: string;
|
28
|
+
};
|
29
|
+
|
30
|
+
borderRadius: {
|
31
|
+
modal: number;
|
32
|
+
input: number;
|
33
|
+
cookieConsent: number;
|
34
|
+
};
|
35
|
+
|
36
|
+
widthSizes: {
|
37
|
+
modal: number;
|
38
|
+
cookieConsent: number;
|
39
|
+
};
|
40
|
+
|
41
|
+
transitions: {
|
42
|
+
global: string;
|
43
|
+
};
|
44
|
+
|
45
|
+
actions: {
|
46
|
+
gap: number[];
|
47
|
+
paddingTop: number[];
|
48
|
+
paddingBottom: number[];
|
49
|
+
};
|
50
|
+
|
51
|
+
button: {
|
52
|
+
minWidth: number;
|
53
|
+
fontWeight: number;
|
54
|
+
letterSpacing: number;
|
55
|
+
color: {
|
56
|
+
primary: string;
|
57
|
+
secondary: string;
|
58
|
+
disabled: string;
|
59
|
+
};
|
60
|
+
backgroundColor: {
|
61
|
+
primary: string;
|
62
|
+
secondary: string;
|
63
|
+
disabled: string;
|
64
|
+
};
|
65
|
+
border: {
|
66
|
+
width: number;
|
67
|
+
style: string;
|
68
|
+
color: {
|
69
|
+
primary: string;
|
70
|
+
secondary: string;
|
71
|
+
disabled: string;
|
72
|
+
};
|
73
|
+
};
|
74
|
+
borderRadius: number;
|
75
|
+
paddingTop: {
|
76
|
+
small: number[];
|
77
|
+
medium: number[];
|
78
|
+
large: number[];
|
79
|
+
};
|
80
|
+
paddingBottom: {
|
81
|
+
small: number[];
|
82
|
+
medium: number[];
|
83
|
+
large: number[];
|
84
|
+
};
|
85
|
+
paddingRight: {
|
86
|
+
small: number[];
|
87
|
+
medium: number[];
|
88
|
+
large: number[];
|
89
|
+
};
|
90
|
+
paddingLeft: {
|
91
|
+
small: number[];
|
92
|
+
medium: number[];
|
93
|
+
large: number[];
|
94
|
+
};
|
95
|
+
transition: string;
|
96
|
+
};
|
97
|
+
|
98
|
+
keyNumber: {
|
99
|
+
paddingBottom: number[];
|
100
|
+
};
|
101
|
+
|
102
|
+
columns: {
|
103
|
+
gap: number;
|
104
|
+
};
|
105
|
+
|
106
|
+
form: {
|
107
|
+
width: number;
|
108
|
+
backgroundColor: string;
|
109
|
+
padding: [string | number, string | number];
|
110
|
+
|
111
|
+
row: {
|
112
|
+
gap: [string | number, string | number];
|
113
|
+
padding: [string | number, string | number];
|
114
|
+
};
|
115
|
+
|
116
|
+
label: {
|
117
|
+
font: string;
|
118
|
+
color: string;
|
119
|
+
fontWeight: number;
|
120
|
+
paddingBottom: number;
|
121
|
+
};
|
122
|
+
|
123
|
+
input: {
|
124
|
+
font: string;
|
125
|
+
color: string;
|
126
|
+
border: string;
|
127
|
+
padding: number[];
|
128
|
+
borderRadius: number;
|
129
|
+
backgroundColor: string;
|
130
|
+
placeholder: {
|
131
|
+
color: string;
|
132
|
+
opacity: number;
|
133
|
+
};
|
134
|
+
};
|
135
|
+
|
136
|
+
textarea: {
|
137
|
+
font: string;
|
138
|
+
color: string;
|
139
|
+
border: string;
|
140
|
+
padding: number[];
|
141
|
+
borderRadius: number;
|
142
|
+
backgroundColor: string;
|
143
|
+
placeholder: {
|
144
|
+
color: string;
|
145
|
+
opacity: number;
|
146
|
+
};
|
147
|
+
};
|
148
|
+
|
149
|
+
error: {
|
150
|
+
color: string;
|
151
|
+
};
|
152
|
+
};
|
153
|
+
|
154
|
+
header: {
|
155
|
+
gap: number[];
|
156
|
+
height: number[];
|
157
|
+
backgroundColor: string;
|
158
|
+
|
159
|
+
paddingTop: number[];
|
160
|
+
paddingLeft: number[];
|
161
|
+
paddingRight: number[];
|
162
|
+
paddingBottom: number[];
|
163
|
+
|
164
|
+
overlayGap: number[];
|
165
|
+
overlayBackgroundColor: string;
|
166
|
+
|
167
|
+
toggleNavColor: string;
|
168
|
+
toggleNavOpenColor: string;
|
169
|
+
toggleNavBorderRadius: number;
|
170
|
+
};
|
171
|
+
|
172
|
+
main: {
|
173
|
+
minHeight: string;
|
174
|
+
backgroundColor: string;
|
175
|
+
};
|
176
|
+
|
177
|
+
section: {
|
178
|
+
paddingTop: number[];
|
179
|
+
paddingBottom: number[];
|
180
|
+
};
|
181
|
+
|
182
|
+
footer: {
|
183
|
+
gap: number[];
|
184
|
+
height: number[];
|
185
|
+
backgroundColor: string;
|
186
|
+
|
187
|
+
paddingTop: number[];
|
188
|
+
paddingBottom: number[];
|
189
|
+
};
|
190
|
+
|
191
|
+
modal: {
|
192
|
+
border: string;
|
193
|
+
width: number[];
|
194
|
+
borderRadius: number;
|
195
|
+
backgroundColor: string;
|
196
|
+
|
197
|
+
overlayBlur: number;
|
198
|
+
overlayOpacity: number;
|
199
|
+
overlayBackgroundColor: string;
|
200
|
+
|
201
|
+
paddingTop: number[];
|
202
|
+
paddingLeft: number[];
|
203
|
+
paddingRight: number[];
|
204
|
+
paddingBottom: number[];
|
205
|
+
};
|
206
|
+
|
207
|
+
languageSwitcher: {
|
208
|
+
color: string;
|
209
|
+
border: string;
|
210
|
+
width: number[];
|
211
|
+
borderRadius: number;
|
212
|
+
backgroundColor: string;
|
213
|
+
|
214
|
+
paddingTop: number[];
|
215
|
+
paddingLeft: number[];
|
216
|
+
paddingRight: number[];
|
217
|
+
paddingBottom: number[];
|
218
|
+
};
|
219
|
+
|
220
|
+
carousel: {
|
221
|
+
gap: number[];
|
222
|
+
bullet: {
|
223
|
+
width: number[];
|
224
|
+
height: number[];
|
225
|
+
borderRadius: number;
|
226
|
+
backgroundColor: string;
|
227
|
+
};
|
228
|
+
};
|
229
|
+
|
230
|
+
video: {
|
231
|
+
playButton: {
|
232
|
+
color: string;
|
233
|
+
border: string;
|
234
|
+
width: number[];
|
235
|
+
height: number[];
|
236
|
+
borderRadius: number;
|
237
|
+
backgroundColor: string;
|
238
|
+
};
|
239
|
+
pauseButton: {
|
240
|
+
color: string;
|
241
|
+
border: string;
|
242
|
+
width: number[];
|
243
|
+
height: number[];
|
244
|
+
borderRadius: number;
|
245
|
+
backgroundColor: string;
|
246
|
+
};
|
247
|
+
soundButton: {
|
248
|
+
color: string;
|
249
|
+
border: string;
|
250
|
+
width: number[];
|
251
|
+
height: number[];
|
252
|
+
borderRadius: number;
|
253
|
+
backgroundColor: string;
|
254
|
+
};
|
255
|
+
closeButton: {
|
256
|
+
color: string;
|
257
|
+
border: string;
|
258
|
+
width: number[];
|
259
|
+
height: number[];
|
260
|
+
borderRadius: number;
|
261
|
+
backgroundColor: string;
|
262
|
+
};
|
263
|
+
};
|
264
|
+
|
265
|
+
consentCookie: {
|
266
|
+
borders: number;
|
267
|
+
width: number[];
|
268
|
+
borderRadius: number;
|
269
|
+
backgroundColor: string;
|
270
|
+
|
271
|
+
overlayBlur: number;
|
272
|
+
overlayOpacity: number;
|
273
|
+
overlayBackgroundColor: string;
|
274
|
+
|
275
|
+
paddingTop: number[];
|
276
|
+
paddingLeft: number[];
|
277
|
+
paddingRight: number[];
|
278
|
+
paddingBottom: number[];
|
279
|
+
|
280
|
+
actionsGap: number;
|
281
|
+
actionsPaddingTop: number[];
|
282
|
+
};
|
283
|
+
|
284
|
+
nav: {
|
285
|
+
gap: number[];
|
286
|
+
};
|
287
|
+
|
288
|
+
navSocial: {
|
289
|
+
gap: number[];
|
290
|
+
};
|
291
|
+
|
292
|
+
navLegal: {
|
293
|
+
gap: number[];
|
294
|
+
};
|
295
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
// https://www.w3schools.com/js/js_cookies.asp
|
2
|
+
|
3
|
+
export function getCookie(name: string) {
|
4
|
+
const fullName = name + '=';
|
5
|
+
const decodedCookie = decodeURIComponent(document.cookie);
|
6
|
+
const ca = decodedCookie.split(';');
|
7
|
+
for (let i = 0; i < ca.length; i++) {
|
8
|
+
let c = ca[i];
|
9
|
+
while (c.charAt(0) == ' ') {
|
10
|
+
c = c.substring(1);
|
11
|
+
}
|
12
|
+
if (c.indexOf(fullName) == 0) {
|
13
|
+
return c.substring(fullName.length, c.length);
|
14
|
+
}
|
15
|
+
}
|
16
|
+
return '';
|
17
|
+
}
|
18
|
+
|
19
|
+
export function setCookie(name: string, value: string, expirationInDays: number) {
|
20
|
+
const d = new Date();
|
21
|
+
d.setTime(d.getTime() + expirationInDays * 24 * 60 * 60 * 1000);
|
22
|
+
const expires = 'expires=' + d.toUTCString();
|
23
|
+
document.cookie = name + '=' + value + ';' + expires + ';path=/';
|
24
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
2
|
+
const deepMergeObjects = (obj1: any, obj2: any) => {
|
3
|
+
for (const key in obj2) {
|
4
|
+
if (obj2.hasOwnProperty(key)) {
|
5
|
+
if (obj2[key] instanceof Object && obj1[key] instanceof Object) {
|
6
|
+
obj1[key] = deepMergeObjects(obj1[key], obj2[key]);
|
7
|
+
} else {
|
8
|
+
obj1[key] = obj2[key];
|
9
|
+
}
|
10
|
+
}
|
11
|
+
}
|
12
|
+
return obj1;
|
13
|
+
};
|
14
|
+
|
15
|
+
export default deepMergeObjects;
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import { useEffect, useState } from 'react';
|
2
|
+
|
3
|
+
import { breakpoints } from '../assets/styles/mediaqueries';
|
4
|
+
|
5
|
+
type BreakpointKey = keyof typeof breakpoints;
|
6
|
+
|
7
|
+
export function useBreakpointKey(): number {
|
8
|
+
const [breakpoint, setBreakpoint] = useState<BreakpointKey>('mobile');
|
9
|
+
|
10
|
+
useEffect(() => {
|
11
|
+
function handleResize() {
|
12
|
+
const width = window.innerWidth;
|
13
|
+
|
14
|
+
if (width >= breakpoints['2xl']) setBreakpoint('2xl');
|
15
|
+
else if (width >= breakpoints.xl) setBreakpoint('xl');
|
16
|
+
else if (width >= breakpoints.lg) setBreakpoint('lg');
|
17
|
+
else if (width >= breakpoints.md) setBreakpoint('md');
|
18
|
+
else if (width >= breakpoints.sm) setBreakpoint('sm');
|
19
|
+
else setBreakpoint('mobile');
|
20
|
+
}
|
21
|
+
|
22
|
+
handleResize(); // init au mount
|
23
|
+
window.addEventListener('resize', handleResize);
|
24
|
+
return () => window.removeEventListener('resize', handleResize);
|
25
|
+
}, []);
|
26
|
+
|
27
|
+
// Map Breakpoint → Index numérique
|
28
|
+
const order: BreakpointKey[] = ['mobile', 'sm', 'md', 'lg', 'xl', '2xl'];
|
29
|
+
return order.indexOf(breakpoint);
|
30
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { useEffect, useState } from 'react';
|
2
|
+
|
3
|
+
function useWindowSize() {
|
4
|
+
// Initialize state with undefined width/height so server and client renders match
|
5
|
+
// Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/
|
6
|
+
const [windowSize, setWindowSize] = useState<{
|
7
|
+
width: undefined | number;
|
8
|
+
height: undefined | number;
|
9
|
+
}>({
|
10
|
+
width: undefined,
|
11
|
+
height: undefined,
|
12
|
+
});
|
13
|
+
|
14
|
+
useEffect(() => {
|
15
|
+
// only execute all the code below in client side
|
16
|
+
// Handler to call on window resize
|
17
|
+
function handleResize() {
|
18
|
+
// Set window width/height to state
|
19
|
+
setWindowSize({
|
20
|
+
width: window.innerWidth,
|
21
|
+
height: window.innerHeight,
|
22
|
+
});
|
23
|
+
}
|
24
|
+
|
25
|
+
// Add event listener
|
26
|
+
window.addEventListener('resize', handleResize);
|
27
|
+
|
28
|
+
// Call handler right away so state gets updated with initial window size
|
29
|
+
handleResize();
|
30
|
+
|
31
|
+
// Remove event listener on cleanup
|
32
|
+
return () => window.removeEventListener('resize', handleResize);
|
33
|
+
}, []); // Empty array ensures that effect is only run on mount
|
34
|
+
return windowSize;
|
35
|
+
}
|
36
|
+
|
37
|
+
export default useWindowSize;
|