postcss-clampwind 0.0.3 → 0.0.5
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/README.md +45 -16
- package/dist/clampwind.cjs.cjs +209 -141
- package/dist/clampwind.esm.js +209 -141
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,6 +28,21 @@ Install the plugin from npm:
|
|
|
28
28
|
```sh
|
|
29
29
|
npm install -D postcss-clampwind
|
|
30
30
|
```
|
|
31
|
+
### Vite project setup
|
|
32
|
+
|
|
33
|
+
If you are using Vite, you are probably using Tailwind with `@tailwindcss/vite`. You need to import the plugin and use it in your `postcss.config.js` file.
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
// postcss.config.js
|
|
37
|
+
import clampwind from "postcss-clampwind";
|
|
38
|
+
|
|
39
|
+
export default {
|
|
40
|
+
plugins: [
|
|
41
|
+
clampwind()
|
|
42
|
+
]
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
**Demo on StackBlitz:** [postcss-clampwind-vite](https://stackblitz.com/edit/postcss-clampwind-vite?file=postcss.config.js)
|
|
31
46
|
|
|
32
47
|
### PostCSS setup
|
|
33
48
|
|
|
@@ -46,6 +61,8 @@ export default {
|
|
|
46
61
|
}
|
|
47
62
|
```
|
|
48
63
|
|
|
64
|
+
**Demo on StackBlitz:** [postcss-clampwind-postcss](https://stackblitz.com/edit/postcss-clampwind-postcss?file=postcss.config.mjs)
|
|
65
|
+
|
|
49
66
|
#### CommonJS usage
|
|
50
67
|
|
|
51
68
|
If you are using CommonJS-based build tools like Webpack, you will need to use the `require` syntax and add `.default` to the import.
|
|
@@ -60,21 +77,6 @@ module.exports = {
|
|
|
60
77
|
};
|
|
61
78
|
```
|
|
62
79
|
|
|
63
|
-
### Vite project setup
|
|
64
|
-
|
|
65
|
-
If you are using Vite, you are probably using Tailwind with `@tailwindcss/vite`. You need to import the plugin and use it in your `postcss.config.js` file.
|
|
66
|
-
|
|
67
|
-
```js
|
|
68
|
-
// postcss.config.js
|
|
69
|
-
import clampwind from "postcss-clampwind";
|
|
70
|
-
|
|
71
|
-
export default {
|
|
72
|
-
plugins: [
|
|
73
|
-
clampwind()
|
|
74
|
-
]
|
|
75
|
-
};
|
|
76
|
-
```
|
|
77
|
-
|
|
78
80
|
## Features
|
|
79
81
|
|
|
80
82
|
### Interchangeable px / rem units
|
|
@@ -305,6 +307,33 @@ But Tailwind by default, will not output in your CSS any custom properties that
|
|
|
305
307
|
}
|
|
306
308
|
```
|
|
307
309
|
|
|
310
|
+
### Set a default clamp range
|
|
311
|
+
|
|
312
|
+
You can set a default clamp range to use when no breakpoint modifier is used, like this:
|
|
313
|
+
|
|
314
|
+
```html
|
|
315
|
+
<div class="text-[clamp(16px,50px)]"></div>
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
To set a default clamp range you need to use the `--breakpoint-clamp-min` and `--breakpoint-clamp-max` custom properties, defined inside the `@theme static` directive.
|
|
319
|
+
|
|
320
|
+
```css
|
|
321
|
+
@theme static {
|
|
322
|
+
--breakpoint-clamp-min: 600px;
|
|
323
|
+
--breakpoint-clamp-max: 1200px;
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
This will also apply for utilities that use only one breakpoint modifier. In this example the `md` breakpoint will be used as the minimum breakpoint, and `--breakpoint-clamp-max` will be used as the maximum breakpoint:
|
|
328
|
+
|
|
329
|
+
```html
|
|
330
|
+
<div class="md:text-[clamp(16px,50px)]"></div>
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
The default clamp range will let you to simplify your utilities, since usually you don't need to clamp between the smallest and largest Tailwind breakpoints, but only between two breakpoints.
|
|
334
|
+
|
|
335
|
+
You will still be able to clamp between any other Tailwind or custom breakpoints, even if out of the default clamp range.
|
|
336
|
+
|
|
308
337
|
### Use custom properties
|
|
309
338
|
|
|
310
339
|
You can use any custom properties in your clamped values, for example:
|
|
@@ -342,4 +371,4 @@ or like this:
|
|
|
342
371
|
|
|
343
372
|
This project is licensed under the [Apache-2.0 license](https://apache.org/licenses/LICENSE-2.0).
|
|
344
373
|
|
|
345
|
-
Copyright © 2025 Daniele De Pietri.
|
|
374
|
+
Copyright © 2025 Daniele De Pietri.
|
package/dist/clampwind.cjs.cjs
CHANGED
|
@@ -64,28 +64,13 @@ var defaultContainerScreens = {
|
|
|
64
64
|
"@7xl": "80rem"
|
|
65
65
|
// 1280px
|
|
66
66
|
};
|
|
67
|
-
var convertSortScreens = (screens, rootFontSize = 16) => {
|
|
68
|
-
const convertedScreens = Object.entries(screens).reduce((acc, [key, value]) => {
|
|
69
|
-
if (value.includes("px")) {
|
|
70
|
-
const pxValue = parseFloat(value);
|
|
71
|
-
acc[key] = `${pxValue / rootFontSize}rem`;
|
|
72
|
-
} else {
|
|
73
|
-
acc[key] = value;
|
|
74
|
-
}
|
|
75
|
-
return acc;
|
|
76
|
-
}, {});
|
|
77
|
-
const sortedKeys = Object.keys(convertedScreens).sort((a, b) => {
|
|
78
|
-
const aValue = parseFloat(convertedScreens[a]);
|
|
79
|
-
const bValue = parseFloat(convertedScreens[b]);
|
|
80
|
-
return aValue - bValue;
|
|
81
|
-
});
|
|
82
|
-
return sortedKeys.reduce((acc, key) => {
|
|
83
|
-
acc[key] = convertedScreens[key];
|
|
84
|
-
return acc;
|
|
85
|
-
}, {});
|
|
86
|
-
};
|
|
87
67
|
|
|
88
68
|
// src/utils.js
|
|
69
|
+
var smartRound = (value, maxDecimals = 4) => {
|
|
70
|
+
const precise = value.toFixed(maxDecimals);
|
|
71
|
+
const trimmed = precise.replace(/\.?0+$/, "");
|
|
72
|
+
return trimmed || "0";
|
|
73
|
+
};
|
|
89
74
|
var extractTwoValidClampArgs = (value) => {
|
|
90
75
|
const m = value.match(/\bclamp\s*\(\s*(var\([^()]+\)|[^,()]+)\s*,\s*(var\([^()]+\)|[^,()]+)\s*\)$/);
|
|
91
76
|
return m ? [m[1].trim(), m[2].trim()] : null;
|
|
@@ -112,28 +97,28 @@ var convertToRem = (value, rootFontSize, spacingSize, customProperties = {}) =>
|
|
|
112
97
|
const spacingSizeInt = parseFloat(spacingSize);
|
|
113
98
|
const spacingUnit = extractUnit(spacingSize);
|
|
114
99
|
if (spacingUnit === "px") {
|
|
115
|
-
return `${
|
|
100
|
+
return `${smartRound(value * spacingSizeInt / rootFontSize)}rem`;
|
|
116
101
|
}
|
|
117
102
|
if (spacingUnit === "rem") {
|
|
118
|
-
return `${
|
|
103
|
+
return `${smartRound(value * spacingSizeInt)}rem`;
|
|
119
104
|
}
|
|
120
105
|
}
|
|
121
106
|
if (unit === "px") {
|
|
122
|
-
return `${
|
|
107
|
+
return `${smartRound(value.replace("px", "") / rootFontSize)}rem`;
|
|
123
108
|
}
|
|
124
109
|
if (unit === "rem") {
|
|
125
110
|
return value;
|
|
126
111
|
}
|
|
127
112
|
if (customProperties[formattedProperty]) {
|
|
128
|
-
return
|
|
113
|
+
return customProperties[formattedProperty];
|
|
129
114
|
}
|
|
130
115
|
if (formattedProperty && !customProperties[formattedProperty] && fallbackValue) {
|
|
131
116
|
const fallbackUnit = extractUnit(fallbackValue);
|
|
132
117
|
if (!fallbackUnit) {
|
|
133
|
-
return `${
|
|
118
|
+
return `${smartRound(fallbackValue * spacingSize)}rem`;
|
|
134
119
|
}
|
|
135
120
|
if (fallbackUnit === "px") {
|
|
136
|
-
return `${
|
|
121
|
+
return `${smartRound(fallbackValue.replace("px", "") / rootFontSize)}rem`;
|
|
137
122
|
}
|
|
138
123
|
if (fallbackUnit === "rem") {
|
|
139
124
|
return fallbackValue;
|
|
@@ -154,10 +139,21 @@ var generateClamp = (lower, upper, minScreen, maxScreen, rootFontSize = 16, spac
|
|
|
154
139
|
const min = isDescending ? upper : lower;
|
|
155
140
|
const max = isDescending ? lower : upper;
|
|
156
141
|
const widthUnit = containerQuery ? `100cqw` : `100vw`;
|
|
157
|
-
const slopeInt =
|
|
142
|
+
const slopeInt = smartRound((upperInt - lowerInt) / (maxScreenInt - minScreenInt));
|
|
158
143
|
const clamp = `clamp(${min}, calc(${lower} + ${slopeInt} * (${widthUnit} - ${minScreen})), ${max})`;
|
|
159
144
|
return clamp;
|
|
160
145
|
};
|
|
146
|
+
var sortScreens = (screens) => {
|
|
147
|
+
const sortedKeys = Object.keys(screens).sort((a, b) => {
|
|
148
|
+
const aValue = parseFloat(screens[a]);
|
|
149
|
+
const bValue = parseFloat(screens[b]);
|
|
150
|
+
return aValue - bValue;
|
|
151
|
+
});
|
|
152
|
+
return sortedKeys.reduce((acc, key) => {
|
|
153
|
+
acc[key] = screens[key];
|
|
154
|
+
return acc;
|
|
155
|
+
}, {});
|
|
156
|
+
};
|
|
161
157
|
|
|
162
158
|
// src/clampwind.js
|
|
163
159
|
var clampwind = (opts = {}) => {
|
|
@@ -169,9 +165,8 @@ var clampwind = (opts = {}) => {
|
|
|
169
165
|
let customProperties = {};
|
|
170
166
|
let screens = defaultScreens || {};
|
|
171
167
|
let containerScreens = defaultContainerScreens || {};
|
|
168
|
+
let defaultClampRange = {};
|
|
172
169
|
const config = {
|
|
173
|
-
defaultLayerBreakpoints: {},
|
|
174
|
-
defaultLayerContainerBreakpoints: {},
|
|
175
170
|
themeLayerBreakpoints: {},
|
|
176
171
|
themeLayerContainerBreakpoints: {},
|
|
177
172
|
rootElementBreakpoints: {},
|
|
@@ -195,17 +190,48 @@ var clampwind = (opts = {}) => {
|
|
|
195
190
|
if (decl.parent?.selector === ":root") {
|
|
196
191
|
if (decl.prop.startsWith("--breakpoint-")) {
|
|
197
192
|
const key = decl.prop.replace("--breakpoint-", "");
|
|
198
|
-
config.rootElementBreakpoints[key] =
|
|
193
|
+
config.rootElementBreakpoints[key] = convertToRem(
|
|
194
|
+
decl.value,
|
|
195
|
+
rootFontSize,
|
|
196
|
+
spacingSize,
|
|
197
|
+
customProperties
|
|
198
|
+
);
|
|
199
199
|
}
|
|
200
200
|
if (decl.prop.startsWith("--container-")) {
|
|
201
201
|
const key = decl.prop.replace("--container-", "@");
|
|
202
|
-
config.rootElementContainerBreakpoints[key] =
|
|
202
|
+
config.rootElementContainerBreakpoints[key] = convertToRem(
|
|
203
|
+
decl.value,
|
|
204
|
+
rootFontSize,
|
|
205
|
+
spacingSize,
|
|
206
|
+
customProperties
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
if (decl.prop === "--breakpoint-clamp-min") {
|
|
210
|
+
defaultClampRange.min = convertToRem(
|
|
211
|
+
decl.value,
|
|
212
|
+
rootFontSize,
|
|
213
|
+
spacingSize,
|
|
214
|
+
customProperties
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
if (decl.prop === "--breakpoint-clamp-max") {
|
|
218
|
+
defaultClampRange.max = convertToRem(
|
|
219
|
+
decl.value,
|
|
220
|
+
rootFontSize,
|
|
221
|
+
spacingSize,
|
|
222
|
+
customProperties
|
|
223
|
+
);
|
|
203
224
|
}
|
|
204
225
|
if (decl.prop === "--spacing") {
|
|
205
226
|
spacingSize = decl.value;
|
|
206
227
|
}
|
|
207
228
|
if (decl.prop.startsWith("--")) {
|
|
208
|
-
const value =
|
|
229
|
+
const value = convertToRem(
|
|
230
|
+
decl.value,
|
|
231
|
+
rootFontSize,
|
|
232
|
+
spacingSize,
|
|
233
|
+
customProperties
|
|
234
|
+
);
|
|
209
235
|
if (value) customProperties[decl.prop] = value;
|
|
210
236
|
}
|
|
211
237
|
}
|
|
@@ -220,35 +246,52 @@ var clampwind = (opts = {}) => {
|
|
|
220
246
|
}
|
|
221
247
|
});
|
|
222
248
|
root.walkAtRules("layer", (atRule) => {
|
|
223
|
-
if (atRule.params === "default") {
|
|
224
|
-
if (!Object.keys(config.defaultLayerBreakpoints).length) {
|
|
225
|
-
atRule.walkDecls((decl) => {
|
|
226
|
-
if (decl.prop.startsWith("--breakpoint-")) {
|
|
227
|
-
const key = decl.prop.replace("--breakpoint-", "");
|
|
228
|
-
config.defaultLayerBreakpoints[key] = decl.value;
|
|
229
|
-
}
|
|
230
|
-
if (decl.prop.startsWith("--container-")) {
|
|
231
|
-
const key = decl.prop.replace("--container-", "@");
|
|
232
|
-
config.defaultLayerContainerBreakpoints[key] = decl.value;
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
249
|
if (atRule.params === "theme") {
|
|
238
250
|
atRule.walkDecls((decl) => {
|
|
239
251
|
if (decl.prop.startsWith("--breakpoint-")) {
|
|
240
252
|
const key = decl.prop.replace("--breakpoint-", "");
|
|
241
|
-
config.themeLayerBreakpoints[key] =
|
|
253
|
+
config.themeLayerBreakpoints[key] = convertToRem(
|
|
254
|
+
decl.value,
|
|
255
|
+
rootFontSize,
|
|
256
|
+
spacingSize,
|
|
257
|
+
customProperties
|
|
258
|
+
);
|
|
242
259
|
}
|
|
243
260
|
if (decl.prop.startsWith("--container-")) {
|
|
244
261
|
const key = decl.prop.replace("--container-", "@");
|
|
245
|
-
config.themeLayerContainerBreakpoints[key] =
|
|
262
|
+
config.themeLayerContainerBreakpoints[key] = convertToRem(
|
|
263
|
+
decl.value,
|
|
264
|
+
rootFontSize,
|
|
265
|
+
spacingSize,
|
|
266
|
+
customProperties
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
if (decl.prop === "--breakpoint-clamp-min") {
|
|
270
|
+
defaultClampRange.min = convertToRem(
|
|
271
|
+
decl.value,
|
|
272
|
+
rootFontSize,
|
|
273
|
+
spacingSize,
|
|
274
|
+
customProperties
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
if (decl.prop === "--breakpoint-clamp-max") {
|
|
278
|
+
defaultClampRange.max = convertToRem(
|
|
279
|
+
decl.value,
|
|
280
|
+
rootFontSize,
|
|
281
|
+
spacingSize,
|
|
282
|
+
customProperties
|
|
283
|
+
);
|
|
246
284
|
}
|
|
247
285
|
if (decl.prop === "--spacing") {
|
|
248
286
|
spacingSize = decl.value;
|
|
249
287
|
}
|
|
250
288
|
if (decl.prop.startsWith("--")) {
|
|
251
|
-
const value =
|
|
289
|
+
const value = convertToRem(
|
|
290
|
+
decl.value,
|
|
291
|
+
rootFontSize,
|
|
292
|
+
spacingSize,
|
|
293
|
+
customProperties
|
|
294
|
+
);
|
|
252
295
|
if (value) customProperties[decl.prop] = value;
|
|
253
296
|
}
|
|
254
297
|
});
|
|
@@ -261,30 +304,38 @@ var clampwind = (opts = {}) => {
|
|
|
261
304
|
screens = Object.assign(
|
|
262
305
|
{},
|
|
263
306
|
screens,
|
|
264
|
-
config.defaultLayerBreakpoints,
|
|
265
307
|
config.rootElementBreakpoints,
|
|
266
308
|
config.themeLayerBreakpoints
|
|
267
309
|
);
|
|
268
|
-
screens =
|
|
310
|
+
screens = sortScreens(screens);
|
|
269
311
|
containerScreens = Object.assign(
|
|
270
312
|
{},
|
|
271
313
|
containerScreens,
|
|
272
|
-
config.defaultLayerContainerBreakpoints,
|
|
273
314
|
config.rootElementContainerBreakpoints,
|
|
274
315
|
config.themeLayerContainerBreakpoints
|
|
275
316
|
);
|
|
276
|
-
containerScreens =
|
|
317
|
+
containerScreens = sortScreens(containerScreens);
|
|
277
318
|
config.configReady = true;
|
|
278
319
|
};
|
|
279
320
|
const processClampDeclaration = (decl, minScreen, maxScreen, isContainer = false) => {
|
|
280
321
|
const args = extractTwoValidClampArgs(decl.value);
|
|
281
|
-
const [lower, upper] = args.map(
|
|
322
|
+
const [lower, upper] = args.map(
|
|
323
|
+
(val) => convertToRem(val, rootFontSize, spacingSize, customProperties)
|
|
324
|
+
);
|
|
282
325
|
if (!args || !lower || !upper) {
|
|
283
326
|
console.warn("Invalid clamp() values", { node: decl });
|
|
284
327
|
decl.value = ` ${decl.value} /* Invalid clamp() values */`;
|
|
285
328
|
return true;
|
|
286
329
|
}
|
|
287
|
-
const clamp = generateClamp(
|
|
330
|
+
const clamp = generateClamp(
|
|
331
|
+
lower,
|
|
332
|
+
upper,
|
|
333
|
+
minScreen,
|
|
334
|
+
maxScreen,
|
|
335
|
+
rootFontSize,
|
|
336
|
+
spacingSize,
|
|
337
|
+
isContainer
|
|
338
|
+
);
|
|
288
339
|
decl.value = clamp;
|
|
289
340
|
return true;
|
|
290
341
|
};
|
|
@@ -294,8 +345,6 @@ var clampwind = (opts = {}) => {
|
|
|
294
345
|
collectConfig(root);
|
|
295
346
|
finalizeConfig();
|
|
296
347
|
root.walkAtRules("media", (atRule) => {
|
|
297
|
-
const isNested = atRule.parent?.type === "atrule";
|
|
298
|
-
const isSameAtRule = atRule.parent?.name === atRule.name;
|
|
299
348
|
const clampDecls = [];
|
|
300
349
|
atRule.walkDecls((decl) => {
|
|
301
350
|
if (extractTwoValidClampArgs(decl.value)) {
|
|
@@ -303,53 +352,56 @@ var clampwind = (opts = {}) => {
|
|
|
303
352
|
}
|
|
304
353
|
});
|
|
305
354
|
if (!clampDecls.length) return;
|
|
306
|
-
|
|
307
|
-
const
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
355
|
+
clampDecls.forEach((decl) => {
|
|
356
|
+
const isNested = decl.parent?.type === "atrule" && decl.parent?.parent.type === "atrule";
|
|
357
|
+
const isSameAtRule = decl.parent?.name === decl.parent?.parent.name;
|
|
358
|
+
if (isNested && isSameAtRule) {
|
|
359
|
+
const currentParams2 = decl.parent.params;
|
|
360
|
+
const parentParams = decl.parent.parent.params;
|
|
361
|
+
let minScreen = null;
|
|
362
|
+
let maxScreen = null;
|
|
363
|
+
if (parentParams.includes(">")) {
|
|
364
|
+
const match = parentParams.match(/>=?\s*([^)]+)/);
|
|
365
|
+
if (match) minScreen = match[1].trim();
|
|
366
|
+
}
|
|
367
|
+
if (currentParams2.includes(">") && !minScreen) {
|
|
368
|
+
const match = currentParams2.match(/>=?\s*([^)]+)/);
|
|
369
|
+
if (match) minScreen = match[1].trim();
|
|
370
|
+
}
|
|
371
|
+
if (parentParams.includes("<")) {
|
|
372
|
+
const match = parentParams.match(/<\s*([^)]+)/);
|
|
373
|
+
if (match) maxScreen = match[1].trim();
|
|
374
|
+
}
|
|
375
|
+
if (currentParams2.includes("<") && !maxScreen) {
|
|
376
|
+
const match = currentParams2.match(/<\s*([^)]+)/);
|
|
377
|
+
if (match) maxScreen = match[1].trim();
|
|
378
|
+
}
|
|
379
|
+
if (minScreen && maxScreen) {
|
|
380
|
+
clampDecls.forEach((decl2) => {
|
|
381
|
+
processClampDeclaration(decl2, minScreen, maxScreen, false);
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
return;
|
|
326
385
|
}
|
|
327
|
-
if (
|
|
328
|
-
clampDecls.forEach((
|
|
329
|
-
|
|
386
|
+
if (isNested && !isSameAtRule) {
|
|
387
|
+
clampDecls.forEach((decl2) => {
|
|
388
|
+
decl2.value = ` ${decl2.value} /* Invalid nested @media rules */`;
|
|
330
389
|
});
|
|
390
|
+
return;
|
|
331
391
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
decl.value = ` ${decl.value} /* Invalid nested @media rules */`;
|
|
337
|
-
});
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
const screenValues = Object.values(screens);
|
|
341
|
-
clampDecls.forEach((decl) => {
|
|
342
|
-
if (atRule.params.includes(">")) {
|
|
343
|
-
const match = atRule.params.match(/>=?\s*([^)]+)/);
|
|
392
|
+
const screenValues = Object.values(screens);
|
|
393
|
+
const currentParams = decl.parent.params;
|
|
394
|
+
if (currentParams.includes(">")) {
|
|
395
|
+
const match = currentParams.match(/>=?\s*([^)]+)/);
|
|
344
396
|
if (match) {
|
|
345
397
|
const minScreen = match[1].trim();
|
|
346
|
-
const maxScreen = screenValues[screenValues.length - 1];
|
|
398
|
+
const maxScreen = defaultClampRange.max || screenValues[screenValues.length - 1];
|
|
347
399
|
processClampDeclaration(decl, minScreen, maxScreen, false);
|
|
348
400
|
}
|
|
349
|
-
} else if (
|
|
350
|
-
const match =
|
|
401
|
+
} else if (currentParams.includes("<")) {
|
|
402
|
+
const match = currentParams.match(/<\s*([^)]+)/);
|
|
351
403
|
if (match) {
|
|
352
|
-
const minScreen = screenValues[0];
|
|
404
|
+
const minScreen = defaultClampRange.min || screenValues[0];
|
|
353
405
|
const maxScreen = match[1].trim();
|
|
354
406
|
processClampDeclaration(decl, minScreen, maxScreen, false);
|
|
355
407
|
}
|
|
@@ -357,8 +409,6 @@ var clampwind = (opts = {}) => {
|
|
|
357
409
|
});
|
|
358
410
|
});
|
|
359
411
|
root.walkAtRules("container", (atRule) => {
|
|
360
|
-
const isNested = atRule.parent?.type === "atrule";
|
|
361
|
-
const isSameAtRule = atRule.parent?.name === atRule.name;
|
|
362
412
|
const clampDecls = [];
|
|
363
413
|
atRule.walkDecls((decl) => {
|
|
364
414
|
if (extractTwoValidClampArgs(decl.value)) {
|
|
@@ -366,55 +416,73 @@ var clampwind = (opts = {}) => {
|
|
|
366
416
|
}
|
|
367
417
|
});
|
|
368
418
|
if (!clampDecls.length) return;
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
const
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
419
|
+
clampDecls.forEach((decl) => {
|
|
420
|
+
const isNested = decl.parent?.type === "atrule" && decl.parent?.parent.type === "atrule";
|
|
421
|
+
const isSameAtRule = decl.parent?.name === decl.parent?.parent.name;
|
|
422
|
+
if (isNested && isSameAtRule) {
|
|
423
|
+
const currentParams2 = decl.parent.params;
|
|
424
|
+
const parentParams = decl.parent.parent.params;
|
|
425
|
+
let minContainer = null;
|
|
426
|
+
let maxContainer = null;
|
|
427
|
+
if (parentParams.includes(">")) {
|
|
428
|
+
const match = parentParams.match(/>=?\s*([^)]+)/);
|
|
429
|
+
if (match) minContainer = match[1].trim();
|
|
430
|
+
}
|
|
431
|
+
if (currentParams2.includes(">") && !minContainer) {
|
|
432
|
+
const match = currentParams2.match(/>=?\s*([^)]+)/);
|
|
433
|
+
if (match) minContainer = match[1].trim();
|
|
434
|
+
}
|
|
435
|
+
if (parentParams.includes("<")) {
|
|
436
|
+
const match = parentParams.match(/<\s*([^)]+)/);
|
|
437
|
+
if (match) maxContainer = match[1].trim();
|
|
438
|
+
}
|
|
439
|
+
if (currentParams2.includes("<") && !maxContainer) {
|
|
440
|
+
const match = currentParams2.match(/<\s*([^)]+)/);
|
|
441
|
+
if (match) maxContainer = match[1].trim();
|
|
442
|
+
}
|
|
443
|
+
if (minContainer && maxContainer) {
|
|
444
|
+
clampDecls.forEach((decl2) => {
|
|
445
|
+
processClampDeclaration(
|
|
446
|
+
decl2,
|
|
447
|
+
minContainer,
|
|
448
|
+
maxContainer,
|
|
449
|
+
true
|
|
450
|
+
);
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
return;
|
|
389
454
|
}
|
|
390
|
-
if (
|
|
391
|
-
clampDecls.forEach((
|
|
392
|
-
|
|
455
|
+
if (isNested && !isSameAtRule) {
|
|
456
|
+
clampDecls.forEach((decl2) => {
|
|
457
|
+
decl2.value = ` ${decl2.value} /* Invalid nested @container rules */`;
|
|
393
458
|
});
|
|
459
|
+
return;
|
|
394
460
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
decl.value = ` ${decl.value} /* Invalid nested @container rules */`;
|
|
400
|
-
});
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
const screenValues = Object.values(containerScreens);
|
|
404
|
-
clampDecls.forEach((decl) => {
|
|
405
|
-
if (atRule.params.includes(">")) {
|
|
406
|
-
const match = atRule.params.match(/>=?\s*([^)]+)/);
|
|
461
|
+
const containerValues = Object.values(containerScreens);
|
|
462
|
+
const currentParams = decl.parent.params;
|
|
463
|
+
if (currentParams.includes(">")) {
|
|
464
|
+
const match = currentParams.match(/>=?\s*([^)]+)/);
|
|
407
465
|
if (match) {
|
|
408
466
|
const minContainer = match[1].trim();
|
|
409
|
-
const maxContainer =
|
|
410
|
-
processClampDeclaration(
|
|
467
|
+
const maxContainer = containerValues[containerValues.length - 1];
|
|
468
|
+
processClampDeclaration(
|
|
469
|
+
decl,
|
|
470
|
+
minContainer,
|
|
471
|
+
maxContainer,
|
|
472
|
+
true
|
|
473
|
+
);
|
|
411
474
|
}
|
|
412
|
-
} else if (
|
|
413
|
-
const match =
|
|
475
|
+
} else if (currentParams.includes("<")) {
|
|
476
|
+
const match = currentParams.match(/<\s*([^)]+)/);
|
|
414
477
|
if (match) {
|
|
415
|
-
const minContainer =
|
|
478
|
+
const minContainer = containerValues[0];
|
|
416
479
|
const maxContainer = match[1].trim();
|
|
417
|
-
processClampDeclaration(
|
|
480
|
+
processClampDeclaration(
|
|
481
|
+
decl,
|
|
482
|
+
minContainer,
|
|
483
|
+
maxContainer,
|
|
484
|
+
true
|
|
485
|
+
);
|
|
418
486
|
}
|
|
419
487
|
}
|
|
420
488
|
});
|
|
@@ -435,8 +503,8 @@ var clampwind = (opts = {}) => {
|
|
|
435
503
|
});
|
|
436
504
|
if (clampDecls.length === 0) return;
|
|
437
505
|
const screenValues = Object.values(screens);
|
|
438
|
-
const minScreen = screenValues[0];
|
|
439
|
-
const maxScreen = screenValues[screenValues.length - 1];
|
|
506
|
+
const minScreen = defaultClampRange.min || screenValues[0];
|
|
507
|
+
const maxScreen = defaultClampRange.max || screenValues[screenValues.length - 1];
|
|
440
508
|
clampDecls.forEach((decl) => {
|
|
441
509
|
processClampDeclaration(decl, minScreen, maxScreen, false);
|
|
442
510
|
});
|
package/dist/clampwind.esm.js
CHANGED
|
@@ -39,28 +39,13 @@ var defaultContainerScreens = {
|
|
|
39
39
|
"@7xl": "80rem"
|
|
40
40
|
// 1280px
|
|
41
41
|
};
|
|
42
|
-
var convertSortScreens = (screens, rootFontSize = 16) => {
|
|
43
|
-
const convertedScreens = Object.entries(screens).reduce((acc, [key, value]) => {
|
|
44
|
-
if (value.includes("px")) {
|
|
45
|
-
const pxValue = parseFloat(value);
|
|
46
|
-
acc[key] = `${pxValue / rootFontSize}rem`;
|
|
47
|
-
} else {
|
|
48
|
-
acc[key] = value;
|
|
49
|
-
}
|
|
50
|
-
return acc;
|
|
51
|
-
}, {});
|
|
52
|
-
const sortedKeys = Object.keys(convertedScreens).sort((a, b) => {
|
|
53
|
-
const aValue = parseFloat(convertedScreens[a]);
|
|
54
|
-
const bValue = parseFloat(convertedScreens[b]);
|
|
55
|
-
return aValue - bValue;
|
|
56
|
-
});
|
|
57
|
-
return sortedKeys.reduce((acc, key) => {
|
|
58
|
-
acc[key] = convertedScreens[key];
|
|
59
|
-
return acc;
|
|
60
|
-
}, {});
|
|
61
|
-
};
|
|
62
42
|
|
|
63
43
|
// src/utils.js
|
|
44
|
+
var smartRound = (value, maxDecimals = 4) => {
|
|
45
|
+
const precise = value.toFixed(maxDecimals);
|
|
46
|
+
const trimmed = precise.replace(/\.?0+$/, "");
|
|
47
|
+
return trimmed || "0";
|
|
48
|
+
};
|
|
64
49
|
var extractTwoValidClampArgs = (value) => {
|
|
65
50
|
const m = value.match(/\bclamp\s*\(\s*(var\([^()]+\)|[^,()]+)\s*,\s*(var\([^()]+\)|[^,()]+)\s*\)$/);
|
|
66
51
|
return m ? [m[1].trim(), m[2].trim()] : null;
|
|
@@ -87,28 +72,28 @@ var convertToRem = (value, rootFontSize, spacingSize, customProperties = {}) =>
|
|
|
87
72
|
const spacingSizeInt = parseFloat(spacingSize);
|
|
88
73
|
const spacingUnit = extractUnit(spacingSize);
|
|
89
74
|
if (spacingUnit === "px") {
|
|
90
|
-
return `${
|
|
75
|
+
return `${smartRound(value * spacingSizeInt / rootFontSize)}rem`;
|
|
91
76
|
}
|
|
92
77
|
if (spacingUnit === "rem") {
|
|
93
|
-
return `${
|
|
78
|
+
return `${smartRound(value * spacingSizeInt)}rem`;
|
|
94
79
|
}
|
|
95
80
|
}
|
|
96
81
|
if (unit === "px") {
|
|
97
|
-
return `${
|
|
82
|
+
return `${smartRound(value.replace("px", "") / rootFontSize)}rem`;
|
|
98
83
|
}
|
|
99
84
|
if (unit === "rem") {
|
|
100
85
|
return value;
|
|
101
86
|
}
|
|
102
87
|
if (customProperties[formattedProperty]) {
|
|
103
|
-
return
|
|
88
|
+
return customProperties[formattedProperty];
|
|
104
89
|
}
|
|
105
90
|
if (formattedProperty && !customProperties[formattedProperty] && fallbackValue) {
|
|
106
91
|
const fallbackUnit = extractUnit(fallbackValue);
|
|
107
92
|
if (!fallbackUnit) {
|
|
108
|
-
return `${
|
|
93
|
+
return `${smartRound(fallbackValue * spacingSize)}rem`;
|
|
109
94
|
}
|
|
110
95
|
if (fallbackUnit === "px") {
|
|
111
|
-
return `${
|
|
96
|
+
return `${smartRound(fallbackValue.replace("px", "") / rootFontSize)}rem`;
|
|
112
97
|
}
|
|
113
98
|
if (fallbackUnit === "rem") {
|
|
114
99
|
return fallbackValue;
|
|
@@ -129,10 +114,21 @@ var generateClamp = (lower, upper, minScreen, maxScreen, rootFontSize = 16, spac
|
|
|
129
114
|
const min = isDescending ? upper : lower;
|
|
130
115
|
const max = isDescending ? lower : upper;
|
|
131
116
|
const widthUnit = containerQuery ? `100cqw` : `100vw`;
|
|
132
|
-
const slopeInt =
|
|
117
|
+
const slopeInt = smartRound((upperInt - lowerInt) / (maxScreenInt - minScreenInt));
|
|
133
118
|
const clamp = `clamp(${min}, calc(${lower} + ${slopeInt} * (${widthUnit} - ${minScreen})), ${max})`;
|
|
134
119
|
return clamp;
|
|
135
120
|
};
|
|
121
|
+
var sortScreens = (screens) => {
|
|
122
|
+
const sortedKeys = Object.keys(screens).sort((a, b) => {
|
|
123
|
+
const aValue = parseFloat(screens[a]);
|
|
124
|
+
const bValue = parseFloat(screens[b]);
|
|
125
|
+
return aValue - bValue;
|
|
126
|
+
});
|
|
127
|
+
return sortedKeys.reduce((acc, key) => {
|
|
128
|
+
acc[key] = screens[key];
|
|
129
|
+
return acc;
|
|
130
|
+
}, {});
|
|
131
|
+
};
|
|
136
132
|
|
|
137
133
|
// src/clampwind.js
|
|
138
134
|
var clampwind = (opts = {}) => {
|
|
@@ -144,9 +140,8 @@ var clampwind = (opts = {}) => {
|
|
|
144
140
|
let customProperties = {};
|
|
145
141
|
let screens = defaultScreens || {};
|
|
146
142
|
let containerScreens = defaultContainerScreens || {};
|
|
143
|
+
let defaultClampRange = {};
|
|
147
144
|
const config = {
|
|
148
|
-
defaultLayerBreakpoints: {},
|
|
149
|
-
defaultLayerContainerBreakpoints: {},
|
|
150
145
|
themeLayerBreakpoints: {},
|
|
151
146
|
themeLayerContainerBreakpoints: {},
|
|
152
147
|
rootElementBreakpoints: {},
|
|
@@ -170,17 +165,48 @@ var clampwind = (opts = {}) => {
|
|
|
170
165
|
if (decl.parent?.selector === ":root") {
|
|
171
166
|
if (decl.prop.startsWith("--breakpoint-")) {
|
|
172
167
|
const key = decl.prop.replace("--breakpoint-", "");
|
|
173
|
-
config.rootElementBreakpoints[key] =
|
|
168
|
+
config.rootElementBreakpoints[key] = convertToRem(
|
|
169
|
+
decl.value,
|
|
170
|
+
rootFontSize,
|
|
171
|
+
spacingSize,
|
|
172
|
+
customProperties
|
|
173
|
+
);
|
|
174
174
|
}
|
|
175
175
|
if (decl.prop.startsWith("--container-")) {
|
|
176
176
|
const key = decl.prop.replace("--container-", "@");
|
|
177
|
-
config.rootElementContainerBreakpoints[key] =
|
|
177
|
+
config.rootElementContainerBreakpoints[key] = convertToRem(
|
|
178
|
+
decl.value,
|
|
179
|
+
rootFontSize,
|
|
180
|
+
spacingSize,
|
|
181
|
+
customProperties
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
if (decl.prop === "--breakpoint-clamp-min") {
|
|
185
|
+
defaultClampRange.min = convertToRem(
|
|
186
|
+
decl.value,
|
|
187
|
+
rootFontSize,
|
|
188
|
+
spacingSize,
|
|
189
|
+
customProperties
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
if (decl.prop === "--breakpoint-clamp-max") {
|
|
193
|
+
defaultClampRange.max = convertToRem(
|
|
194
|
+
decl.value,
|
|
195
|
+
rootFontSize,
|
|
196
|
+
spacingSize,
|
|
197
|
+
customProperties
|
|
198
|
+
);
|
|
178
199
|
}
|
|
179
200
|
if (decl.prop === "--spacing") {
|
|
180
201
|
spacingSize = decl.value;
|
|
181
202
|
}
|
|
182
203
|
if (decl.prop.startsWith("--")) {
|
|
183
|
-
const value =
|
|
204
|
+
const value = convertToRem(
|
|
205
|
+
decl.value,
|
|
206
|
+
rootFontSize,
|
|
207
|
+
spacingSize,
|
|
208
|
+
customProperties
|
|
209
|
+
);
|
|
184
210
|
if (value) customProperties[decl.prop] = value;
|
|
185
211
|
}
|
|
186
212
|
}
|
|
@@ -195,35 +221,52 @@ var clampwind = (opts = {}) => {
|
|
|
195
221
|
}
|
|
196
222
|
});
|
|
197
223
|
root.walkAtRules("layer", (atRule) => {
|
|
198
|
-
if (atRule.params === "default") {
|
|
199
|
-
if (!Object.keys(config.defaultLayerBreakpoints).length) {
|
|
200
|
-
atRule.walkDecls((decl) => {
|
|
201
|
-
if (decl.prop.startsWith("--breakpoint-")) {
|
|
202
|
-
const key = decl.prop.replace("--breakpoint-", "");
|
|
203
|
-
config.defaultLayerBreakpoints[key] = decl.value;
|
|
204
|
-
}
|
|
205
|
-
if (decl.prop.startsWith("--container-")) {
|
|
206
|
-
const key = decl.prop.replace("--container-", "@");
|
|
207
|
-
config.defaultLayerContainerBreakpoints[key] = decl.value;
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
224
|
if (atRule.params === "theme") {
|
|
213
225
|
atRule.walkDecls((decl) => {
|
|
214
226
|
if (decl.prop.startsWith("--breakpoint-")) {
|
|
215
227
|
const key = decl.prop.replace("--breakpoint-", "");
|
|
216
|
-
config.themeLayerBreakpoints[key] =
|
|
228
|
+
config.themeLayerBreakpoints[key] = convertToRem(
|
|
229
|
+
decl.value,
|
|
230
|
+
rootFontSize,
|
|
231
|
+
spacingSize,
|
|
232
|
+
customProperties
|
|
233
|
+
);
|
|
217
234
|
}
|
|
218
235
|
if (decl.prop.startsWith("--container-")) {
|
|
219
236
|
const key = decl.prop.replace("--container-", "@");
|
|
220
|
-
config.themeLayerContainerBreakpoints[key] =
|
|
237
|
+
config.themeLayerContainerBreakpoints[key] = convertToRem(
|
|
238
|
+
decl.value,
|
|
239
|
+
rootFontSize,
|
|
240
|
+
spacingSize,
|
|
241
|
+
customProperties
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
if (decl.prop === "--breakpoint-clamp-min") {
|
|
245
|
+
defaultClampRange.min = convertToRem(
|
|
246
|
+
decl.value,
|
|
247
|
+
rootFontSize,
|
|
248
|
+
spacingSize,
|
|
249
|
+
customProperties
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
if (decl.prop === "--breakpoint-clamp-max") {
|
|
253
|
+
defaultClampRange.max = convertToRem(
|
|
254
|
+
decl.value,
|
|
255
|
+
rootFontSize,
|
|
256
|
+
spacingSize,
|
|
257
|
+
customProperties
|
|
258
|
+
);
|
|
221
259
|
}
|
|
222
260
|
if (decl.prop === "--spacing") {
|
|
223
261
|
spacingSize = decl.value;
|
|
224
262
|
}
|
|
225
263
|
if (decl.prop.startsWith("--")) {
|
|
226
|
-
const value =
|
|
264
|
+
const value = convertToRem(
|
|
265
|
+
decl.value,
|
|
266
|
+
rootFontSize,
|
|
267
|
+
spacingSize,
|
|
268
|
+
customProperties
|
|
269
|
+
);
|
|
227
270
|
if (value) customProperties[decl.prop] = value;
|
|
228
271
|
}
|
|
229
272
|
});
|
|
@@ -236,30 +279,38 @@ var clampwind = (opts = {}) => {
|
|
|
236
279
|
screens = Object.assign(
|
|
237
280
|
{},
|
|
238
281
|
screens,
|
|
239
|
-
config.defaultLayerBreakpoints,
|
|
240
282
|
config.rootElementBreakpoints,
|
|
241
283
|
config.themeLayerBreakpoints
|
|
242
284
|
);
|
|
243
|
-
screens =
|
|
285
|
+
screens = sortScreens(screens);
|
|
244
286
|
containerScreens = Object.assign(
|
|
245
287
|
{},
|
|
246
288
|
containerScreens,
|
|
247
|
-
config.defaultLayerContainerBreakpoints,
|
|
248
289
|
config.rootElementContainerBreakpoints,
|
|
249
290
|
config.themeLayerContainerBreakpoints
|
|
250
291
|
);
|
|
251
|
-
containerScreens =
|
|
292
|
+
containerScreens = sortScreens(containerScreens);
|
|
252
293
|
config.configReady = true;
|
|
253
294
|
};
|
|
254
295
|
const processClampDeclaration = (decl, minScreen, maxScreen, isContainer = false) => {
|
|
255
296
|
const args = extractTwoValidClampArgs(decl.value);
|
|
256
|
-
const [lower, upper] = args.map(
|
|
297
|
+
const [lower, upper] = args.map(
|
|
298
|
+
(val) => convertToRem(val, rootFontSize, spacingSize, customProperties)
|
|
299
|
+
);
|
|
257
300
|
if (!args || !lower || !upper) {
|
|
258
301
|
console.warn("Invalid clamp() values", { node: decl });
|
|
259
302
|
decl.value = ` ${decl.value} /* Invalid clamp() values */`;
|
|
260
303
|
return true;
|
|
261
304
|
}
|
|
262
|
-
const clamp = generateClamp(
|
|
305
|
+
const clamp = generateClamp(
|
|
306
|
+
lower,
|
|
307
|
+
upper,
|
|
308
|
+
minScreen,
|
|
309
|
+
maxScreen,
|
|
310
|
+
rootFontSize,
|
|
311
|
+
spacingSize,
|
|
312
|
+
isContainer
|
|
313
|
+
);
|
|
263
314
|
decl.value = clamp;
|
|
264
315
|
return true;
|
|
265
316
|
};
|
|
@@ -269,8 +320,6 @@ var clampwind = (opts = {}) => {
|
|
|
269
320
|
collectConfig(root);
|
|
270
321
|
finalizeConfig();
|
|
271
322
|
root.walkAtRules("media", (atRule) => {
|
|
272
|
-
const isNested = atRule.parent?.type === "atrule";
|
|
273
|
-
const isSameAtRule = atRule.parent?.name === atRule.name;
|
|
274
323
|
const clampDecls = [];
|
|
275
324
|
atRule.walkDecls((decl) => {
|
|
276
325
|
if (extractTwoValidClampArgs(decl.value)) {
|
|
@@ -278,53 +327,56 @@ var clampwind = (opts = {}) => {
|
|
|
278
327
|
}
|
|
279
328
|
});
|
|
280
329
|
if (!clampDecls.length) return;
|
|
281
|
-
|
|
282
|
-
const
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
330
|
+
clampDecls.forEach((decl) => {
|
|
331
|
+
const isNested = decl.parent?.type === "atrule" && decl.parent?.parent.type === "atrule";
|
|
332
|
+
const isSameAtRule = decl.parent?.name === decl.parent?.parent.name;
|
|
333
|
+
if (isNested && isSameAtRule) {
|
|
334
|
+
const currentParams2 = decl.parent.params;
|
|
335
|
+
const parentParams = decl.parent.parent.params;
|
|
336
|
+
let minScreen = null;
|
|
337
|
+
let maxScreen = null;
|
|
338
|
+
if (parentParams.includes(">")) {
|
|
339
|
+
const match = parentParams.match(/>=?\s*([^)]+)/);
|
|
340
|
+
if (match) minScreen = match[1].trim();
|
|
341
|
+
}
|
|
342
|
+
if (currentParams2.includes(">") && !minScreen) {
|
|
343
|
+
const match = currentParams2.match(/>=?\s*([^)]+)/);
|
|
344
|
+
if (match) minScreen = match[1].trim();
|
|
345
|
+
}
|
|
346
|
+
if (parentParams.includes("<")) {
|
|
347
|
+
const match = parentParams.match(/<\s*([^)]+)/);
|
|
348
|
+
if (match) maxScreen = match[1].trim();
|
|
349
|
+
}
|
|
350
|
+
if (currentParams2.includes("<") && !maxScreen) {
|
|
351
|
+
const match = currentParams2.match(/<\s*([^)]+)/);
|
|
352
|
+
if (match) maxScreen = match[1].trim();
|
|
353
|
+
}
|
|
354
|
+
if (minScreen && maxScreen) {
|
|
355
|
+
clampDecls.forEach((decl2) => {
|
|
356
|
+
processClampDeclaration(decl2, minScreen, maxScreen, false);
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
return;
|
|
301
360
|
}
|
|
302
|
-
if (
|
|
303
|
-
clampDecls.forEach((
|
|
304
|
-
|
|
361
|
+
if (isNested && !isSameAtRule) {
|
|
362
|
+
clampDecls.forEach((decl2) => {
|
|
363
|
+
decl2.value = ` ${decl2.value} /* Invalid nested @media rules */`;
|
|
305
364
|
});
|
|
365
|
+
return;
|
|
306
366
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
decl.value = ` ${decl.value} /* Invalid nested @media rules */`;
|
|
312
|
-
});
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
const screenValues = Object.values(screens);
|
|
316
|
-
clampDecls.forEach((decl) => {
|
|
317
|
-
if (atRule.params.includes(">")) {
|
|
318
|
-
const match = atRule.params.match(/>=?\s*([^)]+)/);
|
|
367
|
+
const screenValues = Object.values(screens);
|
|
368
|
+
const currentParams = decl.parent.params;
|
|
369
|
+
if (currentParams.includes(">")) {
|
|
370
|
+
const match = currentParams.match(/>=?\s*([^)]+)/);
|
|
319
371
|
if (match) {
|
|
320
372
|
const minScreen = match[1].trim();
|
|
321
|
-
const maxScreen = screenValues[screenValues.length - 1];
|
|
373
|
+
const maxScreen = defaultClampRange.max || screenValues[screenValues.length - 1];
|
|
322
374
|
processClampDeclaration(decl, minScreen, maxScreen, false);
|
|
323
375
|
}
|
|
324
|
-
} else if (
|
|
325
|
-
const match =
|
|
376
|
+
} else if (currentParams.includes("<")) {
|
|
377
|
+
const match = currentParams.match(/<\s*([^)]+)/);
|
|
326
378
|
if (match) {
|
|
327
|
-
const minScreen = screenValues[0];
|
|
379
|
+
const minScreen = defaultClampRange.min || screenValues[0];
|
|
328
380
|
const maxScreen = match[1].trim();
|
|
329
381
|
processClampDeclaration(decl, minScreen, maxScreen, false);
|
|
330
382
|
}
|
|
@@ -332,8 +384,6 @@ var clampwind = (opts = {}) => {
|
|
|
332
384
|
});
|
|
333
385
|
});
|
|
334
386
|
root.walkAtRules("container", (atRule) => {
|
|
335
|
-
const isNested = atRule.parent?.type === "atrule";
|
|
336
|
-
const isSameAtRule = atRule.parent?.name === atRule.name;
|
|
337
387
|
const clampDecls = [];
|
|
338
388
|
atRule.walkDecls((decl) => {
|
|
339
389
|
if (extractTwoValidClampArgs(decl.value)) {
|
|
@@ -341,55 +391,73 @@ var clampwind = (opts = {}) => {
|
|
|
341
391
|
}
|
|
342
392
|
});
|
|
343
393
|
if (!clampDecls.length) return;
|
|
344
|
-
|
|
345
|
-
const
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
394
|
+
clampDecls.forEach((decl) => {
|
|
395
|
+
const isNested = decl.parent?.type === "atrule" && decl.parent?.parent.type === "atrule";
|
|
396
|
+
const isSameAtRule = decl.parent?.name === decl.parent?.parent.name;
|
|
397
|
+
if (isNested && isSameAtRule) {
|
|
398
|
+
const currentParams2 = decl.parent.params;
|
|
399
|
+
const parentParams = decl.parent.parent.params;
|
|
400
|
+
let minContainer = null;
|
|
401
|
+
let maxContainer = null;
|
|
402
|
+
if (parentParams.includes(">")) {
|
|
403
|
+
const match = parentParams.match(/>=?\s*([^)]+)/);
|
|
404
|
+
if (match) minContainer = match[1].trim();
|
|
405
|
+
}
|
|
406
|
+
if (currentParams2.includes(">") && !minContainer) {
|
|
407
|
+
const match = currentParams2.match(/>=?\s*([^)]+)/);
|
|
408
|
+
if (match) minContainer = match[1].trim();
|
|
409
|
+
}
|
|
410
|
+
if (parentParams.includes("<")) {
|
|
411
|
+
const match = parentParams.match(/<\s*([^)]+)/);
|
|
412
|
+
if (match) maxContainer = match[1].trim();
|
|
413
|
+
}
|
|
414
|
+
if (currentParams2.includes("<") && !maxContainer) {
|
|
415
|
+
const match = currentParams2.match(/<\s*([^)]+)/);
|
|
416
|
+
if (match) maxContainer = match[1].trim();
|
|
417
|
+
}
|
|
418
|
+
if (minContainer && maxContainer) {
|
|
419
|
+
clampDecls.forEach((decl2) => {
|
|
420
|
+
processClampDeclaration(
|
|
421
|
+
decl2,
|
|
422
|
+
minContainer,
|
|
423
|
+
maxContainer,
|
|
424
|
+
true
|
|
425
|
+
);
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
return;
|
|
364
429
|
}
|
|
365
|
-
if (
|
|
366
|
-
clampDecls.forEach((
|
|
367
|
-
|
|
430
|
+
if (isNested && !isSameAtRule) {
|
|
431
|
+
clampDecls.forEach((decl2) => {
|
|
432
|
+
decl2.value = ` ${decl2.value} /* Invalid nested @container rules */`;
|
|
368
433
|
});
|
|
434
|
+
return;
|
|
369
435
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
decl.value = ` ${decl.value} /* Invalid nested @container rules */`;
|
|
375
|
-
});
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
const screenValues = Object.values(containerScreens);
|
|
379
|
-
clampDecls.forEach((decl) => {
|
|
380
|
-
if (atRule.params.includes(">")) {
|
|
381
|
-
const match = atRule.params.match(/>=?\s*([^)]+)/);
|
|
436
|
+
const containerValues = Object.values(containerScreens);
|
|
437
|
+
const currentParams = decl.parent.params;
|
|
438
|
+
if (currentParams.includes(">")) {
|
|
439
|
+
const match = currentParams.match(/>=?\s*([^)]+)/);
|
|
382
440
|
if (match) {
|
|
383
441
|
const minContainer = match[1].trim();
|
|
384
|
-
const maxContainer =
|
|
385
|
-
processClampDeclaration(
|
|
442
|
+
const maxContainer = containerValues[containerValues.length - 1];
|
|
443
|
+
processClampDeclaration(
|
|
444
|
+
decl,
|
|
445
|
+
minContainer,
|
|
446
|
+
maxContainer,
|
|
447
|
+
true
|
|
448
|
+
);
|
|
386
449
|
}
|
|
387
|
-
} else if (
|
|
388
|
-
const match =
|
|
450
|
+
} else if (currentParams.includes("<")) {
|
|
451
|
+
const match = currentParams.match(/<\s*([^)]+)/);
|
|
389
452
|
if (match) {
|
|
390
|
-
const minContainer =
|
|
453
|
+
const minContainer = containerValues[0];
|
|
391
454
|
const maxContainer = match[1].trim();
|
|
392
|
-
processClampDeclaration(
|
|
455
|
+
processClampDeclaration(
|
|
456
|
+
decl,
|
|
457
|
+
minContainer,
|
|
458
|
+
maxContainer,
|
|
459
|
+
true
|
|
460
|
+
);
|
|
393
461
|
}
|
|
394
462
|
}
|
|
395
463
|
});
|
|
@@ -410,8 +478,8 @@ var clampwind = (opts = {}) => {
|
|
|
410
478
|
});
|
|
411
479
|
if (clampDecls.length === 0) return;
|
|
412
480
|
const screenValues = Object.values(screens);
|
|
413
|
-
const minScreen = screenValues[0];
|
|
414
|
-
const maxScreen = screenValues[screenValues.length - 1];
|
|
481
|
+
const minScreen = defaultClampRange.min || screenValues[0];
|
|
482
|
+
const maxScreen = defaultClampRange.max || screenValues[screenValues.length - 1];
|
|
415
483
|
clampDecls.forEach((decl) => {
|
|
416
484
|
processClampDeclaration(decl, minScreen, maxScreen, false);
|
|
417
485
|
});
|