css-calipers 0.3.0 → 0.4.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/README.md +74 -38
- package/RELEASING.md +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ import { m } from "css-calipers";
|
|
|
37
37
|
|
|
38
38
|
// Declare vars
|
|
39
39
|
const paddingBase = m(4); // defaults to "px" with no unit specified
|
|
40
|
-
const rotation = m(45, "deg"); // equivalent to a dedicated helper
|
|
40
|
+
const rotation = m(45, "deg"); // equivalent to a dedicated helper: mDeg(45)
|
|
41
41
|
|
|
42
42
|
// Do safe arithmetic
|
|
43
43
|
const margins = paddingBase.add(4);
|
|
@@ -73,7 +73,11 @@ CSS-Calipers focuses exclusively on numeric, unit-bearing CSS values. Keywords
|
|
|
73
73
|
like `auto`, `fit-content`, or `max-content`, full shorthand strings,
|
|
74
74
|
`var(--token)`, or `calc(...)` expressions should remain explicit strings or
|
|
75
75
|
dedicated keyword types in your app or styling layer. Everything else stays as
|
|
76
|
-
plain CSS (see "Philosophy & Boundaries" below for more detail).
|
|
76
|
+
plain CSS (see "Philosophy & Boundaries" below for more detail). For a concrete
|
|
77
|
+
example of this separation in a mixed-input helper, see
|
|
78
|
+
[examples/lineHeight-normalizer.example.ts](examples/lineHeight-normalizer.example.ts),
|
|
79
|
+
which keeps keywords and CSS variables as plain strings while using measurements
|
|
80
|
+
for numeric values.
|
|
77
81
|
|
|
78
82
|
---
|
|
79
83
|
|
|
@@ -96,7 +100,7 @@ It’s probably overkill if:
|
|
|
96
100
|
### Layout tokens example
|
|
97
101
|
|
|
98
102
|
```ts
|
|
99
|
-
import { m, mPercent, mVw, mVh,
|
|
103
|
+
import { m, mPercent, mVw, mVh, assertCondition } from "css-calipers";
|
|
100
104
|
|
|
101
105
|
// Token-style measurements (px by default)
|
|
102
106
|
const spacing = m(8); // Defaults to px; equivalent to mPx(8)
|
|
@@ -142,7 +146,8 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
142
146
|
const cardGridStyles = {
|
|
143
147
|
display: "grid",
|
|
144
148
|
gap: gutter.css(),
|
|
145
|
-
|
|
149
|
+
// Keep fraction units as plain CSS alongside measurement-derived values
|
|
150
|
+
gridTemplateColumns: `repeat(${columns}, 1fr)`,
|
|
146
151
|
// width driven by card width + gutters
|
|
147
152
|
width: cardWidth
|
|
148
153
|
.multiply(columns)
|
|
@@ -152,7 +157,7 @@ const cardGridStyles = {
|
|
|
152
157
|
minWidth: minWidthPercent.css(),
|
|
153
158
|
maxWidth: maxWidthViewport.css(),
|
|
154
159
|
// derived hero height based on px ratio, expressed in vh and used inside a calc() string
|
|
155
|
-
// calc() stays plain CSS;
|
|
160
|
+
// calc() stays plain CSS; CSS-Calipers only provides the numeric pieces
|
|
156
161
|
minHeight: `calc(${heroHeight.css()} + 10vh)`,
|
|
157
162
|
};
|
|
158
163
|
```
|
|
@@ -163,7 +168,7 @@ const cardGridStyles = {
|
|
|
163
168
|
|
|
164
169
|
CSS-Calipers will happily enforce units anywhere you choose, but it stays
|
|
165
170
|
unopinionated about where those guards live. Drop assertions in a component, in
|
|
166
|
-
a theme
|
|
171
|
+
a theme override, hardcode a debug routine, or wire a global invariant; the
|
|
167
172
|
structure is up to you:
|
|
168
173
|
|
|
169
174
|
```ts
|
|
@@ -179,9 +184,15 @@ if (process.env.NODE_ENV !== "production") {
|
|
|
179
184
|
}
|
|
180
185
|
```
|
|
181
186
|
|
|
182
|
-
You can apply the same checks globally (e.g., during app bootstrap)
|
|
183
|
-
inside the components that need them
|
|
184
|
-
|
|
187
|
+
You can apply the same checks globally (e.g., during app bootstrap), only
|
|
188
|
+
inside the components that need them, or in dedicated test helpers. For more
|
|
189
|
+
complete patterns, see the examples folder: the validation unit-tests example
|
|
190
|
+
([examples/validation-unit-tests.example.ts](examples/validation-unit-tests.example.ts)) shows how to
|
|
191
|
+
enforce spacing token invariants in a test suite, and the validation and runtime
|
|
192
|
+
checks example ([examples/validation-and-runtime-checks.example.ts](examples/validation-and-runtime-checks.example.ts))
|
|
193
|
+
shows how to apply dev-only guards around shared tokens in two different
|
|
194
|
+
consumers (an HTML snippet and a style object) using the same line-height
|
|
195
|
+
measurement.
|
|
185
196
|
|
|
186
197
|
---
|
|
187
198
|
|
|
@@ -189,7 +200,7 @@ placement is a design decision.
|
|
|
189
200
|
|
|
190
201
|
- Operations are fail-fast: when you call helpers like `add`, `divide`, `clamp`,
|
|
191
202
|
`measurementMin` / `measurementMax`, or the assertion helpers with invalid
|
|
192
|
-
input (for example, mismatched units or non-finite values),
|
|
203
|
+
input (for example, mismatched units or non-finite values), CSS-Calipers
|
|
193
204
|
throws a normal `Error`.
|
|
194
205
|
- Error messages include the operation name (for example,
|
|
195
206
|
`css-calipers.Measurement.divide` or `css-calipers.assertMatchingUnits`), the
|
|
@@ -200,34 +211,23 @@ placement is a design decision.
|
|
|
200
211
|
(such as `if (process.env.NODE_ENV !== 'production')`) or to enforce
|
|
201
212
|
invariants in tests, so checks stay cheap and predictable at runtime.
|
|
202
213
|
|
|
214
|
+
For concrete uses of these errors in tests and dev-only guards, see
|
|
215
|
+
`TESTING.md` and the validation examples in
|
|
216
|
+
[examples/validation-unit-tests.example.ts](examples/validation-unit-tests.example.ts) and
|
|
217
|
+
[examples/validation-and-runtime-checks.example.ts](examples/validation-and-runtime-checks.example.ts).
|
|
218
|
+
|
|
203
219
|
---
|
|
204
220
|
|
|
205
221
|
## Co-existing with other systems
|
|
206
222
|
|
|
207
|
-
You don’t have to convert everything at once, or at all. If it fits your setup,
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (typeof value === "string") {
|
|
216
|
-
// Already a CSS value (for example, "auto" or "var(--gap)")
|
|
217
|
-
return value;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const measurement = isMeasurement(value) ? value : m(value);
|
|
221
|
-
return measurement.css();
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
// Later, callers can pass tokens, raw CSS strings, or measurements:
|
|
225
|
-
toSpacingCss("var(--card-gap)");
|
|
226
|
-
toSpacingCss(8); // becomes "8px"
|
|
227
|
-
toSpacingCss(m(12, "px"));
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
---
|
|
223
|
+
You don’t have to convert everything at once, or at all. If it fits your setup,
|
|
224
|
+
you can write small adapters that accept existing CSS strings, CSS-Calipers
|
|
225
|
+
measurements, or plain numbers and turn them into CSS values. CSS-Calipers can
|
|
226
|
+
be dropped into an existing styling system or used from the ground up; it
|
|
227
|
+
focuses narrowly on numeric, unit-bearing values and leaves the rest of your
|
|
228
|
+
styling approach up to you. For a more realistic adapter pattern that
|
|
229
|
+
normalizes mixed inputs (including CSS variables) into a single css-like value,
|
|
230
|
+
see the line-height normalizer example referenced below.
|
|
231
231
|
|
|
232
232
|
## Advanced
|
|
233
233
|
|
|
@@ -272,7 +272,7 @@ keywords for symbolic CSS values, without reintroducing vague unions like
|
|
|
272
272
|
|
|
273
273
|
- **Measurement math lives here; string composition lives elsewhere.**
|
|
274
274
|
Use CSS-Calipers for unit-aware calculations, then hand results to
|
|
275
|
-
helpers/adapters that emit CSS literals. Keep `calc()`/`
|
|
275
|
+
helpers/adapters that emit CSS literals. Keep `calc()`/`linear-gradient()` logic outside
|
|
276
276
|
the library so measurement objects remain pure.
|
|
277
277
|
|
|
278
278
|
- **`.css()` at runtime is an edge, not a habit.**
|
|
@@ -293,6 +293,42 @@ keywords for symbolic CSS values, without reintroducing vague unions like
|
|
|
293
293
|
|
|
294
294
|
- **CSS custom properties coexist; they don’t mix.**
|
|
295
295
|
Third-party primitives exposing `var(--token)` should keep those values as raw
|
|
296
|
-
CSS strings.
|
|
297
|
-
|
|
298
|
-
|
|
296
|
+
CSS strings. CSS-Calipers is intentionally narrow: it works with numeric
|
|
297
|
+
measurements and unit-safe conversions, not tokens or CSS variables. You can
|
|
298
|
+
still use `var(...)` and token strings anywhere in your styling system; they
|
|
299
|
+
just sit outside the library. If you want those values to flow through
|
|
300
|
+
CSS-Calipers, first extract the numeric value and unit in your own code and
|
|
301
|
+
then pass that measurement into the library.
|
|
302
|
+
|
|
303
|
+
## Using CSS-Calipers in a larger styling system
|
|
304
|
+
|
|
305
|
+
CSS is inherently flexible: the same property can accept numbers, unit-bearing
|
|
306
|
+
strings, keywords, and CSS variables. CSS-Calipers is one focused piece of that
|
|
307
|
+
ecosystem. It keeps the numeric, unit-bearing parts typed and predictable, and
|
|
308
|
+
lets the rest of your styling system own tokens, variables, and higher-level
|
|
309
|
+
APIs.
|
|
310
|
+
|
|
311
|
+
For a worked example of this pattern, see
|
|
312
|
+
[examples/lineHeight-normalizer.example.ts](examples/lineHeight-normalizer.example.ts). It shows a helper that accepts a
|
|
313
|
+
`lineHeight` value from a CMS or configuration (numbers, numeric strings with
|
|
314
|
+
units, keywords like `"normal"`, or CSS variables such as
|
|
315
|
+
`"var(--body-line-height)"`) and normalizes them into a value with a `.css()`
|
|
316
|
+
method. CSS-Calipers only participates when there is a concrete measurement
|
|
317
|
+
(numbers and units); keywords and CSS variables remain plain CSS strings owned
|
|
318
|
+
by your styling layer. That’s the intended scope: CSS will always be a mix of
|
|
319
|
+
values, but the library gives you a tight, unit-safe boundary for the numeric
|
|
320
|
+
parts inside a broader styling solution.
|
|
321
|
+
|
|
322
|
+
### Further examples in this repo
|
|
323
|
+
|
|
324
|
+
The `examples/` folder contains a few non-published usage sketches:
|
|
325
|
+
|
|
326
|
+
- [examples/lineHeight-normalizer.example.ts](examples/lineHeight-normalizer.example.ts) —
|
|
327
|
+
mixed input normalization for `lineHeight` (numbers, strings, CSS variables)
|
|
328
|
+
into a single value with a `.css()` method.
|
|
329
|
+
- [examples/validation-unit-tests.example.ts](examples/validation-unit-tests.example.ts) —
|
|
330
|
+
simple unit tests that enforce spacing token invariants (shared units and
|
|
331
|
+
small ≤ large).
|
|
332
|
+
- [examples/validation-and-runtime-checks.example.ts](examples/validation-and-runtime-checks.example.ts) —
|
|
333
|
+
dev-only validation around shared tokens in two different consumers (HTML
|
|
334
|
+
string and style object) using the same line-height measurement.
|
package/RELEASING.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "css-calipers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Compile-time unit safety for numeric, unit-bearing CSS values via typed measurements.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -45,7 +45,9 @@
|
|
|
45
45
|
"./package.json": "./package.json"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
+
"@types/node": "^24.10.1",
|
|
48
49
|
"@vitest/coverage-v8": "^4.0.14",
|
|
50
|
+
"csstype": "^3.1.3",
|
|
49
51
|
"tsd": "^0.31.0",
|
|
50
52
|
"typescript": "^5.6.3",
|
|
51
53
|
"vitest": "^4.0.14"
|