@latte-macchiat-io/latte-vanilla-components 0.0.325 → 0.0.327

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@latte-macchiat-io/latte-vanilla-components",
3
- "version": "0.0.325",
3
+ "version": "0.0.327",
4
4
  "description": "Beautiful components for amazing projects, with a touch of Vanilla 🥤",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -6,9 +6,6 @@ import { queries } from '../../styles/mediaqueries';
6
6
  import { themeContract } from '../../theme/contract.css';
7
7
 
8
8
  import { generateResponsive } from '../../utils/generateResponsive';
9
- import { generateResponsiveMedia } from '../../utils/generateResponsiveMedia';
10
- import { generateResponsiveMediaCalc } from '../../utils/generateResponsiveMediaCalc';
11
- import { mergeResponsiveMedias } from '../../utils/mergeResponsiveMedias';
12
9
 
13
10
  export const carouselRecipe = recipe(
14
11
  {
@@ -98,11 +95,9 @@ export const carouselNav = recipe(
98
95
  pointerEvents: 'none',
99
96
  justifyContent: 'flex-end',
100
97
 
101
- '@media': {
102
- ...generateResponsiveMedia({
103
- gap: themeContract.carousel.nav.gap,
104
- }),
105
- },
98
+ '@media': generateResponsive({
99
+ gap: themeContract.carousel.nav.gap,
100
+ }),
106
101
  },
107
102
 
108
103
  variants: {
@@ -122,14 +117,34 @@ export const carouselNav = recipe(
122
117
 
123
118
  navPositionVertical: {
124
119
  top: {
125
- '@media': generateResponsiveMediaCalc('bottom', '100%', themeContract.carousel.nav.positionVerticalOffset, '+'),
120
+ '@media': generateResponsive(
121
+ {}, // pas de props "normales" ici
122
+ [
123
+ {
124
+ property: 'bottom',
125
+ base: '100%',
126
+ offset: themeContract.carousel.nav.positionVerticalOffset,
127
+ operator: '+',
128
+ },
129
+ ]
130
+ ),
126
131
  },
127
132
  center: {
128
133
  top: '50%',
129
134
  transform: 'translate(0%, -50%)',
130
135
  },
131
136
  bottom: {
132
- '@media': generateResponsiveMediaCalc('top', '100%', themeContract.carousel.nav.positionVerticalOffset, '+'),
137
+ '@media': generateResponsive(
138
+ {}, // pas de props "normales" ici non plus
139
+ [
140
+ {
141
+ property: 'top',
142
+ base: '100%',
143
+ offset: themeContract.carousel.nav.positionVerticalOffset,
144
+ operator: '+',
145
+ },
146
+ ]
147
+ ),
133
148
  },
134
149
  },
135
150
  },
@@ -167,12 +182,10 @@ export const carouselNavButton = style(
167
182
  pointerEvents: 'none',
168
183
  },
169
184
 
170
- '@media': {
171
- ...generateResponsiveMedia({
172
- width: themeContract.carousel.nav.width,
173
- height: themeContract.carousel.nav.height,
174
- }),
175
- },
185
+ '@media': generateResponsive({
186
+ width: themeContract.carousel.nav.width,
187
+ height: themeContract.carousel.nav.height,
188
+ }),
176
189
  },
177
190
  'carousel-nav-button'
178
191
  );
@@ -214,12 +227,10 @@ export const carouselBullet = style(
214
227
  transform: 'scale(1.2)',
215
228
  },
216
229
 
217
- '@media': {
218
- ...generateResponsiveMedia({
219
- width: themeContract.carousel.bullet.width,
220
- height: themeContract.carousel.bullet.height,
221
- }),
222
- },
230
+ '@media': generateResponsive({
231
+ width: themeContract.carousel.bullet.width,
232
+ height: themeContract.carousel.bullet.height,
233
+ }),
223
234
  },
224
235
  'carousel-bullet'
225
236
  );
@@ -1,17 +1,24 @@
1
+ // utils/generateResponsive.ts
1
2
  import { queries } from '../styles/mediaqueries';
2
3
 
4
+ // Define the supported breakpoint keys
3
5
  type BreakpointKey = 'mobile' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';
6
+
7
+ // A responsive value can be a string, number, or anything with a toString method
4
8
  type ResponsiveValue = string | number | { toString(): string };
9
+
10
+ // Map of breakpoint keys to responsive values
5
11
  type BreakpointMap = Partial<Record<BreakpointKey, ResponsiveValue>>;
6
12
 
13
+ // Ordered list of breakpoints to iterate over
7
14
  const BPS: BreakpointKey[] = ['mobile', 'sm', 'md', 'lg', 'xl', '2xl'];
8
15
 
9
16
  /**
10
- * Generate fully responsive CSS object for Vanilla Extract
17
+ * Generates a fully responsive CSS object for Vanilla Extract
11
18
  *
12
- * @param props - normal CSS properties (string/number or responsive map)
13
- * @param calcProps - optional array of calc() rules
14
- * @returns object ready for `@media` in Vanilla Extract
19
+ * @param props - normal CSS properties, either a single value or responsive map
20
+ * @param calcProps - optional array of calc() rules for dynamic calculations
21
+ * @returns an object ready to use under `@media` in Vanilla Extract
15
22
  */
16
23
  export function generateResponsive(
17
24
  props: Record<string, ResponsiveValue | BreakpointMap>,
@@ -19,22 +26,25 @@ export function generateResponsive(
19
26
  property: string;
20
27
  base: ResponsiveValue | BreakpointMap;
21
28
  offset: ResponsiveValue | BreakpointMap;
22
- operator?: string; // + - * / ...
29
+ operator?: string; // + - * / etc.
23
30
  }>
24
31
  ): Record<string, Record<string, string>> {
25
32
  const result: Record<string, Record<string, string>> = {};
26
33
 
34
+ // Helper to convert a value to a proper CSS string
27
35
  const toCssValue = (v: ResponsiveValue) => {
28
36
  const s = String(v);
37
+ // If the value is a CSS variable, wrap it with var()
29
38
  return s.startsWith('--') ? `var(${s})` : s;
30
39
  };
31
40
 
32
- // 1️⃣ Normal props
41
+ // 1️⃣ Process normal CSS properties
33
42
  for (const [cssProp, valOrMap] of Object.entries(props)) {
34
43
  const isMapLike =
35
44
  valOrMap && typeof valOrMap === 'object' && !Array.isArray(valOrMap) && Object.keys(valOrMap).some((k) => BPS.includes(k as BreakpointKey));
36
45
 
37
46
  if (isMapLike) {
47
+ // Responsive map provided
38
48
  const map = valOrMap as BreakpointMap;
39
49
  for (const bp of BPS) {
40
50
  const token = map[bp];
@@ -44,22 +54,34 @@ export function generateResponsive(
44
54
  result[media][cssProp] = toCssValue(token);
45
55
  }
46
56
  } else {
57
+ // Single value, apply to all breakpoints
58
+ const token = valOrMap as ResponsiveValue;
47
59
  for (const bp of BPS) {
48
60
  const media = queries[bp as keyof typeof queries];
49
61
  if (!result[media]) result[media] = {};
50
- result[media][cssProp] = toCssValue(valOrMap as ResponsiveValue);
62
+ result[media][cssProp] = toCssValue(token);
51
63
  }
52
64
  }
53
65
  }
54
66
 
55
- // 2️⃣ Calc props
67
+ // 2️⃣ Process calc() properties if provided
56
68
  if (calcProps) {
57
69
  for (const { property, base, offset, operator = '+' } of calcProps) {
58
70
  for (const bp of BPS) {
59
71
  const media = queries[bp as keyof typeof queries];
60
- const baseValue = typeof base === 'string' ? base : (base[bp] ?? Object.values(base)[0]);
61
- const offsetValue = typeof offset === 'string' ? offset : (offset[bp] ?? Object.values(offset)[0]);
72
+
73
+ // Safely extract the base value for the current breakpoint
74
+ const baseValue =
75
+ typeof base === 'object' && !Array.isArray(base) ? ((base as BreakpointMap)[bp] ?? Object.values(base as BreakpointMap)[0]) : base;
76
+
77
+ // Safely extract the offset value for the current breakpoint
78
+ const offsetValue =
79
+ typeof offset === 'object' && !Array.isArray(offset)
80
+ ? ((offset as BreakpointMap)[bp] ?? Object.values(offset as BreakpointMap)[0])
81
+ : offset;
82
+
62
83
  if (!result[media]) result[media] = {};
84
+ // Build the calc() CSS value
63
85
  result[media][property] = `calc(${baseValue} ${operator} ${offsetValue})`;
64
86
  }
65
87
  }
@@ -1,32 +0,0 @@
1
- import { queries } from '../styles/mediaqueries';
2
-
3
- /**
4
- * Génère un objet @media pour Vanilla Extract avec des valeurs calculées (calc)
5
- * Supporte les valeurs responsive issues du thème pour les deux opérandes.
6
- *
7
- * @param property - la propriété CSS (ex: 'top', 'bottom', 'marginTop'…)
8
- * @param baseValue - soit une string, soit un objet responsive (themeContract.*)
9
- * @param offsetValues - un objet responsive avec des offsets (ex: themeContract.carousel.nav.positionVerticalOffset)
10
- * @param operator - opérateur de calcul ('+' ou '-') [par défaut '+']
11
- * @returns Un objet directement utilisable dans `@media`
12
- */
13
- export function generateResponsiveMediaCalc(
14
- property: string,
15
- baseValue: string | Record<string, string>,
16
- offsetValues: Record<string, string>,
17
- operator: string = '+'
18
- ) {
19
- const result: Record<string, Record<string, string>> = {};
20
-
21
- for (const [bp, query] of Object.entries(queries)) {
22
- const base = typeof baseValue === 'string' ? baseValue : (baseValue[bp] ?? Object.values(baseValue)[0]); // fallback pour mobile
23
- const offset = offsetValues[bp];
24
- if (offset) {
25
- result[query] = {
26
- [property]: `calc(${base} ${operator} ${offset})`,
27
- };
28
- }
29
- }
30
-
31
- return result;
32
- }
@@ -1,21 +0,0 @@
1
- /**
2
- * Fusionne plusieurs objets responsive générés pour Vanilla Extract
3
- * sans écraser les valeurs existantes des mêmes breakpoints.
4
- *
5
- * Exemple :
6
- * mergeResponsiveMedias(a, b) => combine les clés communes
7
- */
8
- export function mergeResponsiveMedias(...mediaObjects: Record<string, Record<string, string>>[]): Record<string, Record<string, string>> {
9
- const merged: Record<string, Record<string, string>> = {};
10
-
11
- for (const obj of mediaObjects) {
12
- for (const [query, styles] of Object.entries(obj)) {
13
- merged[query] = {
14
- ...(merged[query] || {}),
15
- ...styles,
16
- };
17
- }
18
- }
19
-
20
- return merged;
21
- }