css-calipers 0.12.1 β 0.14.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 +35 -19
- package/dist/cjs/internal/createCoreApi.js +30 -9
- package/dist/cjs/internal/createMediaQueriesApi.js +0 -1
- package/dist/cjs/mediaQueries/validation.js +10 -7
- package/dist/cjs/sciNotation.js +74 -0
- package/dist/esm/core.d.ts +21 -17
- package/dist/esm/core.d.ts.map +1 -1
- package/dist/esm/internal/createCoreApi.d.ts +7 -11
- package/dist/esm/internal/createCoreApi.d.ts.map +1 -1
- package/dist/esm/internal/createCoreApi.js +30 -9
- package/dist/esm/internal/createMediaQueriesApi.d.ts +1 -1
- package/dist/esm/internal/createMediaQueriesApi.d.ts.map +1 -1
- package/dist/esm/internal/createMediaQueriesApi.js +0 -1
- package/dist/esm/mediaQueries/validation.d.ts +1 -2
- package/dist/esm/mediaQueries/validation.d.ts.map +1 -1
- package/dist/esm/mediaQueries/validation.js +11 -8
- package/dist/esm/sciNotation.d.ts +14 -0
- package/dist/esm/sciNotation.d.ts.map +1 -0
- package/dist/esm/sciNotation.js +69 -0
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
# CSS-Calipers
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
CSS-Calipers is a tiny layer for typed CSS measurements. Stop parsing CSS
|
|
7
|
-
strings and concatenating units. Do your math on real numbers, get
|
|
8
|
-
compile-time unit safety, and output CSS only at the edges.
|
|
3
|
+
[](https://www.npmjs.com/package/css-calipers)
|
|
4
|
+
[](https://www.npmjs.com/package/css-calipers)
|
|
5
|
+
[](./LICENSE.txt)
|
|
9
6
|
|
|
10
|
-
|
|
7
|
+
**CSS is code. Treat it that way.**
|
|
8
|
+
Compile-time unit safety for numeric, unit-bearing CSS values, with no surprises at runtime.
|
|
11
9
|
|
|
12
|
-
|
|
10
|
+
```ts
|
|
11
|
+
// Before: pull the number AND the unit apart, do the math, glue them back
|
|
12
|
+
const match = base.match(/^(-?\d*\.?\d+)([a-z%]+)$/i);
|
|
13
|
+
if (!match) throw new Error(`Bad measurement: ${base}`);
|
|
14
|
+
const [, numStr, unit] = match;
|
|
15
|
+
const num = parseFloat(numStr);
|
|
16
|
+
const pad = `${num + 4}${unit}`; // and nobody checked that `unit` matches what the caller expects
|
|
17
|
+
|
|
18
|
+
// After: typed math, units enforced by the compiler
|
|
19
|
+
const base = m(8); // or m(8, "rem"), m(1.5, "em"), etc.
|
|
20
|
+
const pad = base.add(4).css(); // type error if units don't match
|
|
21
|
+
```
|
|
13
22
|
|
|
14
|
-
-
|
|
15
|
-
- Media queries: README_MEDIAQUERIES.md
|
|
23
|
+
A small TypeScript library for **type-safe CSS measurements**. Do arithmetic on real numbers with the unit attached, let the compiler catch `px`-vs-`rem` mistakes, and emit a CSS string only at the edge.
|
|
16
24
|
|
|
17
25
|
At a glance:
|
|
18
26
|
|
|
@@ -26,15 +34,6 @@ At a glance:
|
|
|
26
34
|
npm install css-calipers
|
|
27
35
|
```
|
|
28
36
|
|
|
29
|
-
### Status & support
|
|
30
|
-
|
|
31
|
-
> π§ Work in progress.
|
|
32
|
-
> API surface and docs may change between `0.x` releases until the first stable version.
|
|
33
|
-
|
|
34
|
-
- Status: early `0.x` release. Backwards compatibility is not guaranteed until `1.0.0`.
|
|
35
|
-
- Questions or bugs: open an issue on GitHub (see the repository link at the top of this page or in `package.json`).
|
|
36
|
-
- Tooling: tested primarily with TypeScript 5.6+ on Node 18+.
|
|
37
|
-
|
|
38
37
|
---
|
|
39
38
|
|
|
40
39
|
## Quick start
|
|
@@ -61,6 +60,16 @@ If you prefer, you can also import unit helpers from dedicated subpaths. For exa
|
|
|
61
60
|
|
|
62
61
|
---
|
|
63
62
|
|
|
63
|
+
## Status & support
|
|
64
|
+
|
|
65
|
+
> API surface and docs may change between `0.x` releases until the first stable version.
|
|
66
|
+
|
|
67
|
+
- Status: early `0.x` release. Backwards compatibility is not guaranteed until `1.0.0`.
|
|
68
|
+
- Questions or bugs: open an issue on GitHub (see the repository link at the top of this page or in `package.json`).
|
|
69
|
+
- Tooling: tested primarily with TypeScript 5.6+ on Node 18+.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
64
73
|
## Media queries
|
|
65
74
|
|
|
66
75
|
```ts
|
|
@@ -464,6 +473,13 @@ by your styling layer. Thatβs the intended scope: CSS will always be a mix of
|
|
|
464
473
|
values, but the library gives you a tight, unit-safe boundary for the numeric
|
|
465
474
|
parts inside a broader styling solution.
|
|
466
475
|
|
|
476
|
+
### Module guides
|
|
477
|
+
|
|
478
|
+
Deeper guides live alongside this README:
|
|
479
|
+
|
|
480
|
+
- Measurements core: [README_MEASUREMENT.md](README_MEASUREMENT.md)
|
|
481
|
+
- Media queries: [README_MEDIAQUERIES.md](README_MEDIAQUERIES.md)
|
|
482
|
+
|
|
467
483
|
### Further examples in this repo
|
|
468
484
|
|
|
469
485
|
The `examples/` folder contains a few non-published usage sketches:
|
|
@@ -15,6 +15,32 @@ exports.createCoreApi = void 0;
|
|
|
15
15
|
const unitDefinitions_1 = require("../unitDefinitions");
|
|
16
16
|
const buildMeasurementCreationError_1 = require("./buildMeasurementCreationError");
|
|
17
17
|
const errors_1 = require("./errors");
|
|
18
|
+
// JS stringifies numbers in exponential form once the magnitude is >= 1e21 or
|
|
19
|
+
// < 1e-6 (e.g. "1e+21", "1e-7"). CSS output must never contain that, so we
|
|
20
|
+
// expand the exponent into a plain decimal by shifting the decimal point on the
|
|
21
|
+
// digit string. This is string manipulation on the same digits, so it does not
|
|
22
|
+
// re-introduce floating-point error.
|
|
23
|
+
const toPlainDecimal = (value) => {
|
|
24
|
+
const text = `${value}`;
|
|
25
|
+
if (!text.includes('e') && !text.includes('E')) {
|
|
26
|
+
return text;
|
|
27
|
+
}
|
|
28
|
+
const [mantissa, exponentText] = text.toLowerCase().split('e');
|
|
29
|
+
const exponent = Number(exponentText);
|
|
30
|
+
const negative = mantissa.startsWith('-');
|
|
31
|
+
const unsigned = negative ? mantissa.slice(1) : mantissa;
|
|
32
|
+
const [intDigits, fracDigits = ''] = unsigned.split('.');
|
|
33
|
+
const digits = intDigits + fracDigits;
|
|
34
|
+
const pointFromLeft = intDigits.length + exponent;
|
|
35
|
+
const sign = negative ? '-' : '';
|
|
36
|
+
if (pointFromLeft <= 0) {
|
|
37
|
+
return `${sign}0.${'0'.repeat(-pointFromLeft)}${digits}`;
|
|
38
|
+
}
|
|
39
|
+
if (pointFromLeft >= digits.length) {
|
|
40
|
+
return `${sign}${digits}${'0'.repeat(pointFromLeft - digits.length)}`;
|
|
41
|
+
}
|
|
42
|
+
return `${sign}${digits.slice(0, pointFromLeft)}.${digits.slice(pointFromLeft)}`;
|
|
43
|
+
};
|
|
18
44
|
const createCoreApi = (errorStore) => {
|
|
19
45
|
var _Measurement_instances, _a, _Measurement_value, _Measurement_unit, _Measurement_clone;
|
|
20
46
|
const { throwHelperError, throwMeasurementMethodError } = (0, errors_1.createErrorHelpers)(errorStore);
|
|
@@ -50,18 +76,11 @@ const createCoreApi = (errorStore) => {
|
|
|
50
76
|
details: { code: 'CALIPERS_E_NONFINITE' },
|
|
51
77
|
});
|
|
52
78
|
}
|
|
53
|
-
const normalizedUnit = unit.toLowerCase();
|
|
54
79
|
__classPrivateFieldSet(this, _Measurement_value, value, "f");
|
|
55
|
-
__classPrivateFieldSet(this, _Measurement_unit,
|
|
56
|
-
Object.defineProperty(this, '__unitBrand', {
|
|
57
|
-
value: normalizedUnit,
|
|
58
|
-
enumerable: false,
|
|
59
|
-
configurable: false,
|
|
60
|
-
writable: false,
|
|
61
|
-
});
|
|
80
|
+
__classPrivateFieldSet(this, _Measurement_unit, unit.toLowerCase(), "f");
|
|
62
81
|
}
|
|
63
82
|
css() {
|
|
64
|
-
return `${__classPrivateFieldGet(this, _Measurement_value, "f")}${__classPrivateFieldGet(this, _Measurement_unit, "f")}`;
|
|
83
|
+
return `${toPlainDecimal(__classPrivateFieldGet(this, _Measurement_value, "f"))}${__classPrivateFieldGet(this, _Measurement_unit, "f")}`;
|
|
65
84
|
}
|
|
66
85
|
toString() {
|
|
67
86
|
return this.css();
|
|
@@ -223,6 +242,8 @@ const createCoreApi = (errorStore) => {
|
|
|
223
242
|
_a = Measurement, _Measurement_clone = function _Measurement_clone(value) {
|
|
224
243
|
return new _a(value, __classPrivateFieldGet(this, _Measurement_unit, "f"));
|
|
225
244
|
};
|
|
245
|
+
// Single controlled point where the unit brand is asserted onto a freshly
|
|
246
|
+
// created measurement (the brand is a compile-time-only phantom).
|
|
226
247
|
const createMeasurement = (value, unit) => new Measurement(value, unit);
|
|
227
248
|
const isMeasurement = (x) => x instanceof Measurement;
|
|
228
249
|
function m(value, unitOrOptions = 'px', context) {
|
|
@@ -11,7 +11,6 @@ const vanilla_extract_1 = require("../mediaQueries/libraryHelpers/vanilla-extrac
|
|
|
11
11
|
const createMediaQueriesApi = (core) => {
|
|
12
12
|
const validation = (0, validation_1.createMediaQueryValidation)({
|
|
13
13
|
assertCondition: core.assertCondition,
|
|
14
|
-
assertMatchingUnits: core.assertMatchingUnits,
|
|
15
14
|
});
|
|
16
15
|
const emitCoreFeatures = (0, mediaQueries_1.createEmitCoreFeatures)(validation);
|
|
17
16
|
const emitDimensionsFeatures = (0, modules_1.createEmitDimensionsFeatures)(validation);
|
|
@@ -9,7 +9,7 @@ const toValidationResult = (error, fallback) => {
|
|
|
9
9
|
return fallback;
|
|
10
10
|
};
|
|
11
11
|
const createMediaQueryValidation = (core) => {
|
|
12
|
-
const { assertCondition
|
|
12
|
+
const { assertCondition } = core;
|
|
13
13
|
const runMediaQueryValidation = (config, helpers, check, context, fallbackMessage = 'Invalid media query configuration') => {
|
|
14
14
|
if (!check)
|
|
15
15
|
return true;
|
|
@@ -25,7 +25,10 @@ const createMediaQueryValidation = (core) => {
|
|
|
25
25
|
const validateMinMaxWidth = (props) => {
|
|
26
26
|
if (!props.minWidth || !props.maxWidth)
|
|
27
27
|
return;
|
|
28
|
-
|
|
28
|
+
// Mixed units are valid CSS β each bound is evaluated independently β so we
|
|
29
|
+
// only enforce ordering when the units match and the comparison is meaningful.
|
|
30
|
+
if (props.minWidth.getUnit() !== props.maxWidth.getUnit())
|
|
31
|
+
return;
|
|
29
32
|
assertCondition(props.minWidth.getValue() <= props.maxWidth.getValue(), 'minWidth must be less than or equal to maxWidth');
|
|
30
33
|
};
|
|
31
34
|
const validateWidthValuesPositive = (props) => {
|
|
@@ -45,7 +48,9 @@ const createMediaQueryValidation = (core) => {
|
|
|
45
48
|
const validateMinMaxHeight = (props) => {
|
|
46
49
|
if (!props.minHeight || !props.maxHeight)
|
|
47
50
|
return;
|
|
48
|
-
|
|
51
|
+
// Mixed units are valid CSS; only enforce ordering when units match.
|
|
52
|
+
if (props.minHeight.getUnit() !== props.maxHeight.getUnit())
|
|
53
|
+
return;
|
|
49
54
|
assertCondition(props.minHeight.getValue() <= props.maxHeight.getValue(), 'minHeight must be less than or equal to maxHeight');
|
|
50
55
|
};
|
|
51
56
|
const validateHeightValuesPositive = (props) => {
|
|
@@ -107,9 +112,8 @@ const createMediaQueryValidation = (core) => {
|
|
|
107
112
|
if (props.maxResolution) {
|
|
108
113
|
assertPositive(props.maxResolution, 'maxResolution');
|
|
109
114
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
115
|
+
// Resolution bounds may use different units (dpi, dpcm, dppx, x) β all
|
|
116
|
+
// valid CSS β so we no longer require min/max to share a unit.
|
|
113
117
|
};
|
|
114
118
|
return {
|
|
115
119
|
runMediaQueryValidation,
|
|
@@ -125,7 +129,6 @@ const createMediaQueryValidation = (core) => {
|
|
|
125
129
|
exports.createMediaQueryValidation = createMediaQueryValidation;
|
|
126
130
|
const defaultMediaQueryValidation = (0, exports.createMediaQueryValidation)({
|
|
127
131
|
assertCondition: core_1.assertCondition,
|
|
128
|
-
assertMatchingUnits: core_1.assertMatchingUnits,
|
|
129
132
|
});
|
|
130
133
|
exports.defaultMediaQueryValidation = defaultMediaQueryValidation;
|
|
131
134
|
exports.runMediaQueryValidation = defaultMediaQueryValidation.runMediaQueryValidation, exports.validateMinMaxWidth = defaultMediaQueryValidation.validateMinMaxWidth, exports.validateWidthValuesPositive = defaultMediaQueryValidation.validateWidthValuesPositive, exports.validateMinMaxHeight = defaultMediaQueryValidation.validateMinMaxHeight, exports.validateHeightValuesPositive = defaultMediaQueryValidation.validateHeightValuesPositive, exports.validateMinMaxAspectRatio = defaultMediaQueryValidation.validateMinMaxAspectRatio, exports.validateAspectRatioValuesPositive = defaultMediaQueryValidation.validateAspectRatioValuesPositive, exports.validateResolutionValues = defaultMediaQueryValidation.validateResolutionValues;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _SciNotationImpl_coefficient, _SciNotationImpl_exponent, _SciNotationImpl_unit;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.isSciNotation = void 0;
|
|
16
|
+
exports.sciNotation = sciNotation;
|
|
17
|
+
class SciNotationImpl {
|
|
18
|
+
constructor(coefficient, exponent, unit = 'px') {
|
|
19
|
+
_SciNotationImpl_coefficient.set(this, void 0);
|
|
20
|
+
_SciNotationImpl_exponent.set(this, void 0);
|
|
21
|
+
_SciNotationImpl_unit.set(this, void 0);
|
|
22
|
+
if (!Number.isFinite(coefficient) || !Number.isFinite(exponent)) {
|
|
23
|
+
throw new Error('Scientific notation values must be finite numbers.');
|
|
24
|
+
}
|
|
25
|
+
if (!Number.isInteger(exponent)) {
|
|
26
|
+
throw new Error('Scientific notation exponent must be an integer.');
|
|
27
|
+
}
|
|
28
|
+
__classPrivateFieldSet(this, _SciNotationImpl_coefficient, coefficient, "f");
|
|
29
|
+
__classPrivateFieldSet(this, _SciNotationImpl_exponent, exponent, "f");
|
|
30
|
+
__classPrivateFieldSet(this, _SciNotationImpl_unit, unit.toLowerCase(), "f");
|
|
31
|
+
}
|
|
32
|
+
coefficient() {
|
|
33
|
+
return __classPrivateFieldGet(this, _SciNotationImpl_coefficient, "f");
|
|
34
|
+
}
|
|
35
|
+
exponent() {
|
|
36
|
+
return __classPrivateFieldGet(this, _SciNotationImpl_exponent, "f");
|
|
37
|
+
}
|
|
38
|
+
getUnit() {
|
|
39
|
+
return __classPrivateFieldGet(this, _SciNotationImpl_unit, "f");
|
|
40
|
+
}
|
|
41
|
+
valueOf() {
|
|
42
|
+
return __classPrivateFieldGet(this, _SciNotationImpl_coefficient, "f") * 10 ** __classPrivateFieldGet(this, _SciNotationImpl_exponent, "f");
|
|
43
|
+
}
|
|
44
|
+
getValue() {
|
|
45
|
+
return this.valueOf();
|
|
46
|
+
}
|
|
47
|
+
css() {
|
|
48
|
+
return `${this.valueOf()}${__classPrivateFieldGet(this, _SciNotationImpl_unit, "f")}`;
|
|
49
|
+
}
|
|
50
|
+
toString() {
|
|
51
|
+
return this.css();
|
|
52
|
+
}
|
|
53
|
+
withCoefficient(coefficient) {
|
|
54
|
+
return new SciNotationImpl(coefficient, __classPrivateFieldGet(this, _SciNotationImpl_exponent, "f"), __classPrivateFieldGet(this, _SciNotationImpl_unit, "f"));
|
|
55
|
+
}
|
|
56
|
+
withExponent(exponent) {
|
|
57
|
+
return new SciNotationImpl(__classPrivateFieldGet(this, _SciNotationImpl_coefficient, "f"), exponent, __classPrivateFieldGet(this, _SciNotationImpl_unit, "f"));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
_SciNotationImpl_coefficient = new WeakMap(), _SciNotationImpl_exponent = new WeakMap(), _SciNotationImpl_unit = new WeakMap();
|
|
61
|
+
function sciNotation(coefficient, exponent, unit = 'px') {
|
|
62
|
+
return new SciNotationImpl(coefficient, exponent, unit);
|
|
63
|
+
}
|
|
64
|
+
const isSciNotation = (value) => {
|
|
65
|
+
return (typeof value === 'object' &&
|
|
66
|
+
value !== null &&
|
|
67
|
+
'coefficient' in value &&
|
|
68
|
+
'exponent' in value &&
|
|
69
|
+
'getUnit' in value &&
|
|
70
|
+
typeof value.coefficient === 'function' &&
|
|
71
|
+
typeof value.exponent === 'function' &&
|
|
72
|
+
typeof value.getUnit === 'function');
|
|
73
|
+
};
|
|
74
|
+
exports.isSciNotation = isSciNotation;
|
package/dist/esm/core.d.ts
CHANGED
|
@@ -3,8 +3,9 @@ import { type ErrorConfig, type ErrorCode } from './internal/errors';
|
|
|
3
3
|
import { r, isRatio, normalizeRatio, parseRatio, ratioToFloat, toFloat, reduceRatio, simplifyRatio, type IRatio, type RatioParts } from './ratio';
|
|
4
4
|
type UnitSymbol = UnitDefinitionRecord[keyof UnitDefinitionRecord]['unit'];
|
|
5
5
|
export type MeasurementString<Unit extends string = UnitSymbol> = `${number}${Unit}`;
|
|
6
|
+
declare const unitBrand: unique symbol;
|
|
6
7
|
type UnitBrand<Unit extends string> = {
|
|
7
|
-
readonly
|
|
8
|
+
readonly [unitBrand]: Unit;
|
|
8
9
|
};
|
|
9
10
|
export interface IMeasurement<Unit extends string = string> {
|
|
10
11
|
css: () => string;
|
|
@@ -16,10 +17,12 @@ export interface IMeasurement<Unit extends string = string> {
|
|
|
16
17
|
isUnit: (unit: string) => boolean;
|
|
17
18
|
assertUnit: (unit: string, context?: string) => void;
|
|
18
19
|
assert: (predicate: (measurement: IMeasurement<Unit>) => boolean, message: string) => void;
|
|
19
|
-
equals
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
equals(other: IMeasurement<Unit>, strict?: boolean): boolean;
|
|
21
|
+
equals(other: IMeasurement<string>, strict: false): boolean;
|
|
22
|
+
compare(other: IMeasurement<Unit>, strict?: boolean): number;
|
|
23
|
+
compare(other: IMeasurement<string>, strict: false): number;
|
|
24
|
+
add(delta: number | IMeasurement<Unit>): IMeasurement<Unit>;
|
|
25
|
+
subtract(delta: number | IMeasurement<Unit>): IMeasurement<Unit>;
|
|
23
26
|
multiply: (factor: number) => IMeasurement<Unit>;
|
|
24
27
|
divide: (divisor: number) => IMeasurement<Unit>;
|
|
25
28
|
double: () => IMeasurement<Unit>;
|
|
@@ -29,30 +32,31 @@ export interface IMeasurement<Unit extends string = string> {
|
|
|
29
32
|
round: (precision?: number) => IMeasurement<Unit>;
|
|
30
33
|
floor: () => IMeasurement<Unit>;
|
|
31
34
|
ceil: () => IMeasurement<Unit>;
|
|
32
|
-
clamp
|
|
35
|
+
clamp(min: IMeasurement<Unit>, max: IMeasurement<Unit>): IMeasurement<Unit>;
|
|
33
36
|
}
|
|
34
|
-
export type
|
|
35
|
-
|
|
37
|
+
export type InscribedMeasurement<Unit extends string> = IMeasurement<Unit> & UnitBrand<Unit>;
|
|
38
|
+
/**
|
|
39
|
+
* @deprecated Renamed to `InscribedMeasurement`. This alias is kept for one
|
|
40
|
+
* release for backwards compatibility and will be removed in a future version.
|
|
41
|
+
*/
|
|
42
|
+
export type BrandedMeasurement<Unit extends string> = InscribedMeasurement<Unit>;
|
|
43
|
+
export type UnitHelper<Unit extends string = string> = ((value: number, context?: string) => InscribedMeasurement<Unit>) & {
|
|
36
44
|
unit: Unit;
|
|
37
45
|
};
|
|
38
46
|
export type MeasurementOf<T extends UnitHelper> = ReturnType<T>;
|
|
39
47
|
export type UnitGuard<T extends UnitHelper> = (value: unknown) => value is MeasurementOf<T>;
|
|
40
48
|
export type UnitAssertion<T extends UnitHelper> = (value: unknown, context?: string) => asserts value is MeasurementOf<T>;
|
|
41
49
|
export declare const m: {
|
|
42
|
-
(value: number):
|
|
50
|
+
(value: number): InscribedMeasurement<"px">;
|
|
43
51
|
(value: number, options: {
|
|
44
52
|
context?: string;
|
|
45
|
-
}):
|
|
46
|
-
<Unit extends string>(value: number, unit: Unit, context?: string):
|
|
47
|
-
readonly __unitBrand: Lowercase<Unit>;
|
|
48
|
-
};
|
|
53
|
+
}): InscribedMeasurement<"px">;
|
|
54
|
+
<Unit extends string>(value: number, unit: Unit, context?: string): InscribedMeasurement<Lowercase<Unit>>;
|
|
49
55
|
<Unit extends string>(value: number, options: {
|
|
50
56
|
unit?: Unit | undefined;
|
|
51
57
|
context?: string;
|
|
52
|
-
}):
|
|
53
|
-
|
|
54
|
-
};
|
|
55
|
-
}, isMeasurement: (x: unknown) => x is IMeasurement<string>, assertMatchingUnits: <Unit extends string>(left: IMeasurement<Unit>, right: IMeasurement<Unit>, context: string) => void, measurementMin: <Unit extends string>(a: IMeasurement<Unit>, b: IMeasurement<Unit>) => IMeasurement<Unit>, measurementMax: <Unit extends string>(a: IMeasurement<Unit>, b: IMeasurement<Unit>) => IMeasurement<Unit>, measurementUnitMetadata: {
|
|
58
|
+
}): InscribedMeasurement<Lowercase<Unit>>;
|
|
59
|
+
}, isMeasurement: (x: unknown) => x is IMeasurement<string>, assertMatchingUnits: <Unit extends string>(left: IMeasurement<Unit>, right: IMeasurement<Unit>, context: string) => void, measurementMin: <Unit extends string>(a: IMeasurement<Unit>, b: IMeasurement<NoInfer<Unit>>) => IMeasurement<Unit>, measurementMax: <Unit extends string>(a: IMeasurement<Unit>, b: IMeasurement<NoInfer<Unit>>) => IMeasurement<Unit>, measurementUnitMetadata: {
|
|
56
60
|
readonly mPercent: {
|
|
57
61
|
readonly unit: "%";
|
|
58
62
|
readonly category: "percent";
|
package/dist/esm/core.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,CAAC,EACD,OAAO,EACP,cAAc,EACd,UAAU,EACV,YAAY,EACZ,OAAO,EACP,WAAW,EACX,aAAa,EACb,KAAK,MAAM,EACX,KAAK,UAAU,EAChB,MAAM,SAAS,CAAC;AAEjB,KAAK,UAAU,GAAG,oBAAoB,CAAC,MAAM,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3E,MAAM,MAAM,iBAAiB,CAAC,IAAI,SAAS,MAAM,GAAG,UAAU,IAC5D,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../../src/core.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EAC1B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,CAAC,EACD,OAAO,EACP,cAAc,EACd,UAAU,EACV,YAAY,EACZ,OAAO,EACP,WAAW,EACX,aAAa,EACb,KAAK,MAAM,EACX,KAAK,UAAU,EAChB,MAAM,SAAS,CAAC;AAEjB,KAAK,UAAU,GAAG,oBAAoB,CAAC,MAAM,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3E,MAAM,MAAM,iBAAiB,CAAC,IAAI,SAAS,MAAM,GAAG,UAAU,IAC5D,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;AAKrB,OAAO,CAAC,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC;AACvC,KAAK,SAAS,CAAC,IAAI,SAAS,MAAM,IAAI;IAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAErE,MAAM,WAAW,YAAY,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IACxD,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,CAAC;IACxD,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IAClC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,MAAM,EAAE,CACN,SAAS,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC,IAAI,CAAC,KAAK,OAAO,EACvD,OAAO,EAAE,MAAM,KACZ,IAAI,CAAC;IACV,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC7D,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,OAAO,CAAC;IAC5D,OAAO,CAAC,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7D,OAAO,CAAC,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IAC5D,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,EAAE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IACzD,QAAQ,EAAE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IACnC,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;IAClD,KAAK,EAAE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;CAC7E;AAED,MAAM,MAAM,oBAAoB,CAAC,IAAI,SAAS,MAAM,IAAI,YAAY,CAAC,IAAI,CAAC,GACxE,SAAS,CAAC,IAAI,CAAC,CAAC;AAElB;;;GAGG;AACH,MAAM,MAAM,kBAAkB,CAAC,IAAI,SAAS,MAAM,IAChD,oBAAoB,CAAC,IAAI,CAAC,CAAC;AAE7B,MAAM,MAAM,UAAU,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI,CAAC,CACtD,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,MAAM,KACb,oBAAoB,CAAC,IAAI,CAAC,CAAC,GAAG;IACjC,IAAI,EAAE,IAAI,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,UAAU,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;AAEhE,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,UAAU,IAAI,CAC5C,KAAK,EAAE,OAAO,KACX,KAAK,IAAI,aAAa,CAAC,CAAC,CAAC,CAAC;AAE/B,MAAM,MAAM,aAAa,CAAC,CAAC,SAAS,UAAU,IAAI,CAChD,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,KAAK,IAAI,aAAa,CAAC,CAAC,CAAC,CAAC;AAKvC,eAAO,MACL,CAAC;;;eA+B2+K,CAAC;;;;;;;GA9B7+K,aAAa,6CACb,mBAAmB,uGACnB,cAAc,sGACd,cAAc,sGACd,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GACvB,cAAc,yDACd,4BAA4B,sFAwB2jQ,0BAA0B,WAvBjnQ,aAAa,qDACb,cAAc,yDACd,YAAY;;GACZ,UAAU,0GACV,eAAe,mEACf,cAAc,+BACd,cAAc,6BACL,CAAC;AAEZ,MAAM,MAAM,yBAAyB,GAAG,cAAc,CAAC;AACvD,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAC;AACnD,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,CAAC;AAC5C,OAAO,EACL,CAAC,EACD,OAAO,EACP,cAAc,EACd,UAAU,EACV,YAAY,EACZ,OAAO,EACP,WAAW,EACX,aAAa,GACd,CAAC;AACF,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -1,27 +1,23 @@
|
|
|
1
1
|
import { type UnitDefinitionRecord, type UnitHelperName } from '../unitDefinitions';
|
|
2
2
|
import { type ErrorConfigStore } from './errors';
|
|
3
|
-
import type {
|
|
3
|
+
import type { InscribedMeasurement, IMeasurement, UnitAssertion, UnitGuard, UnitHelper } from '../core';
|
|
4
4
|
type MeasurementCreateOptions<Unit extends string> = {
|
|
5
5
|
unit?: Unit;
|
|
6
6
|
context?: string;
|
|
7
7
|
};
|
|
8
8
|
export declare const createCoreApi: (errorStore: ErrorConfigStore) => {
|
|
9
9
|
readonly m: {
|
|
10
|
-
(value: number):
|
|
10
|
+
(value: number): InscribedMeasurement<"px">;
|
|
11
11
|
(value: number, options: {
|
|
12
12
|
context?: string;
|
|
13
|
-
}):
|
|
14
|
-
<Unit extends string>(value: number, unit: Unit, context?: string):
|
|
15
|
-
|
|
16
|
-
};
|
|
17
|
-
<Unit extends string>(value: number, options: MeasurementCreateOptions<Unit>): IMeasurement<Lowercase<Unit>> & {
|
|
18
|
-
readonly __unitBrand: Lowercase<Unit>;
|
|
19
|
-
};
|
|
13
|
+
}): InscribedMeasurement<"px">;
|
|
14
|
+
<Unit extends string>(value: number, unit: Unit, context?: string): InscribedMeasurement<Lowercase<Unit>>;
|
|
15
|
+
<Unit extends string>(value: number, options: MeasurementCreateOptions<Unit>): InscribedMeasurement<Lowercase<Unit>>;
|
|
20
16
|
};
|
|
21
17
|
readonly isMeasurement: (x: unknown) => x is IMeasurement<string>;
|
|
22
18
|
readonly assertMatchingUnits: <Unit extends string>(left: IMeasurement<Unit>, right: IMeasurement<Unit>, context: string) => void;
|
|
23
|
-
readonly measurementMin: <Unit extends string>(a: IMeasurement<Unit>, b: IMeasurement<Unit
|
|
24
|
-
readonly measurementMax: <Unit extends string>(a: IMeasurement<Unit>, b: IMeasurement<Unit
|
|
19
|
+
readonly measurementMin: <Unit extends string>(a: IMeasurement<Unit>, b: IMeasurement<NoInfer<Unit>>) => IMeasurement<Unit>;
|
|
20
|
+
readonly measurementMax: <Unit extends string>(a: IMeasurement<Unit>, b: IMeasurement<NoInfer<Unit>>) => IMeasurement<Unit>;
|
|
25
21
|
readonly measurementUnitMetadata: {
|
|
26
22
|
readonly mPercent: {
|
|
27
23
|
readonly unit: "%";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCoreApi.d.ts","sourceRoot":"","sources":["../../../src/internal/createCoreApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"createCoreApi.d.ts","sourceRoot":"","sources":["../../../src/internal/createCoreApi.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EACV,oBAAoB,EACpB,YAAY,EACZ,aAAa,EACb,SAAS,EACT,UAAU,EACX,MAAM,SAAS,CAAC;AAGjB,KAAK,wBAAwB,CAAC,IAAI,SAAS,MAAM,IAAI;IACnD,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AA8BF,eAAO,MAAM,aAAa,GAAI,YAAY,gBAAgB;;gBAwQtC,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC;gBAE5C,MAAM,WACJ;YAAE,OAAO,CAAC,EAAE,MAAM,CAAA;SAAE,GAC5B,oBAAoB,CAAC,IAAI,CAAC;SAClB,IAAI,SAAS,MAAM,SACrB,MAAM,QACP,IAAI,YACA,MAAM,GACf,oBAAoB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;SAC7B,IAAI,SAAS,MAAM,SACrB,MAAM,WACJ,wBAAwB,CAAC,IAAI,CAAC,GACtC,oBAAoB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;;gCAhBnC,OAAO,KACT,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC;mCAlQC,IAAI,SAAS,MAAM,QACxC,YAAY,CAAC,IAAI,CAAC,SACjB,YAAY,CAAC,IAAI,CAAC,WAChB,MAAM,KACd,IAAI;8BA0YiB,IAAI,SAAS,MAAM,KACtC,YAAY,CAAC,IAAI,CAAC,KAClB,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAC7B,YAAY,CAAC,IAAI,CAAC;8BAKG,IAAI,SAAS,MAAM,KACtC,YAAY,CAAC,IAAI,CAAC,KAClB,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAC7B,YAAY,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8BAlEG,IAAI,SAAS,MAAM,QACnC,IAAI,KACT,UAAU,CAAC,IAAI,CAAC;4CAImB,IAAI,SAAS,cAAc,QACzD,IAAI,KACT,UAAU,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC;6BAS1B,CAAC,SAAS,UAAU,UACjC,CAAC,KACR,SAAS,CAAC,CAAC,CAAC;8BAKS,CAAC,SAAS,UAAU,UAClC,CAAC,KACR,aAAa,CAAC,CAAC,CAAC;+BAmBd,OAAO,KACT,CAAC,IAAI;QAAE,GAAG,EAAE,MAAM,MAAM,CAAA;KAAE;0BAyBT,IAAI,SAAS,MAAM,eACxB,YAAY,CAAC,IAAI,CAAC,gBACjB,MAAM,YACV,MAAM;0CAIL,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,WAC3B,MAAM,KACd,IAAI;;;CA8BR,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC"}
|
|
@@ -12,6 +12,32 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
12
12
|
import { UNIT_DEFINITIONS, } from '../unitDefinitions';
|
|
13
13
|
import { buildMeasurementCreationError } from './buildMeasurementCreationError';
|
|
14
14
|
import { createErrorHelpers, } from './errors';
|
|
15
|
+
// JS stringifies numbers in exponential form once the magnitude is >= 1e21 or
|
|
16
|
+
// < 1e-6 (e.g. "1e+21", "1e-7"). CSS output must never contain that, so we
|
|
17
|
+
// expand the exponent into a plain decimal by shifting the decimal point on the
|
|
18
|
+
// digit string. This is string manipulation on the same digits, so it does not
|
|
19
|
+
// re-introduce floating-point error.
|
|
20
|
+
const toPlainDecimal = (value) => {
|
|
21
|
+
const text = `${value}`;
|
|
22
|
+
if (!text.includes('e') && !text.includes('E')) {
|
|
23
|
+
return text;
|
|
24
|
+
}
|
|
25
|
+
const [mantissa, exponentText] = text.toLowerCase().split('e');
|
|
26
|
+
const exponent = Number(exponentText);
|
|
27
|
+
const negative = mantissa.startsWith('-');
|
|
28
|
+
const unsigned = negative ? mantissa.slice(1) : mantissa;
|
|
29
|
+
const [intDigits, fracDigits = ''] = unsigned.split('.');
|
|
30
|
+
const digits = intDigits + fracDigits;
|
|
31
|
+
const pointFromLeft = intDigits.length + exponent;
|
|
32
|
+
const sign = negative ? '-' : '';
|
|
33
|
+
if (pointFromLeft <= 0) {
|
|
34
|
+
return `${sign}0.${'0'.repeat(-pointFromLeft)}${digits}`;
|
|
35
|
+
}
|
|
36
|
+
if (pointFromLeft >= digits.length) {
|
|
37
|
+
return `${sign}${digits}${'0'.repeat(pointFromLeft - digits.length)}`;
|
|
38
|
+
}
|
|
39
|
+
return `${sign}${digits.slice(0, pointFromLeft)}.${digits.slice(pointFromLeft)}`;
|
|
40
|
+
};
|
|
15
41
|
export const createCoreApi = (errorStore) => {
|
|
16
42
|
var _Measurement_instances, _a, _Measurement_value, _Measurement_unit, _Measurement_clone;
|
|
17
43
|
const { throwHelperError, throwMeasurementMethodError } = createErrorHelpers(errorStore);
|
|
@@ -47,18 +73,11 @@ export const createCoreApi = (errorStore) => {
|
|
|
47
73
|
details: { code: 'CALIPERS_E_NONFINITE' },
|
|
48
74
|
});
|
|
49
75
|
}
|
|
50
|
-
const normalizedUnit = unit.toLowerCase();
|
|
51
76
|
__classPrivateFieldSet(this, _Measurement_value, value, "f");
|
|
52
|
-
__classPrivateFieldSet(this, _Measurement_unit,
|
|
53
|
-
Object.defineProperty(this, '__unitBrand', {
|
|
54
|
-
value: normalizedUnit,
|
|
55
|
-
enumerable: false,
|
|
56
|
-
configurable: false,
|
|
57
|
-
writable: false,
|
|
58
|
-
});
|
|
77
|
+
__classPrivateFieldSet(this, _Measurement_unit, unit.toLowerCase(), "f");
|
|
59
78
|
}
|
|
60
79
|
css() {
|
|
61
|
-
return `${__classPrivateFieldGet(this, _Measurement_value, "f")}${__classPrivateFieldGet(this, _Measurement_unit, "f")}`;
|
|
80
|
+
return `${toPlainDecimal(__classPrivateFieldGet(this, _Measurement_value, "f"))}${__classPrivateFieldGet(this, _Measurement_unit, "f")}`;
|
|
62
81
|
}
|
|
63
82
|
toString() {
|
|
64
83
|
return this.css();
|
|
@@ -220,6 +239,8 @@ export const createCoreApi = (errorStore) => {
|
|
|
220
239
|
_a = Measurement, _Measurement_clone = function _Measurement_clone(value) {
|
|
221
240
|
return new _a(value, __classPrivateFieldGet(this, _Measurement_unit, "f"));
|
|
222
241
|
};
|
|
242
|
+
// Single controlled point where the unit brand is asserted onto a freshly
|
|
243
|
+
// created measurement (the brand is a compile-time-only phantom).
|
|
223
244
|
const createMeasurement = (value, unit) => new Measurement(value, unit);
|
|
224
245
|
const isMeasurement = (x) => x instanceof Measurement;
|
|
225
246
|
function m(value, unitOrOptions = 'px', context) {
|
|
@@ -6,7 +6,7 @@ import { type IMediaQueryResolutionRange } from '../mediaQueries/modules/resolut
|
|
|
6
6
|
import { type MediaQueryFactoryConfig } from '../mediaQueries/factory';
|
|
7
7
|
import type { MediaQueryBuilderHelpers } from '../mediaQueries/helpers';
|
|
8
8
|
import type { MediaQueryModulesList } from '../mediaQueries/moduleRegistry';
|
|
9
|
-
type MediaQueriesCore = Pick<CoreApi, 'assertCondition'
|
|
9
|
+
type MediaQueriesCore = Pick<CoreApi, 'assertCondition'>;
|
|
10
10
|
export declare const createMediaQueriesApi: (core: MediaQueriesCore) => {
|
|
11
11
|
readonly buildMediaQueryString: (config: IMediaQueryProps) => string;
|
|
12
12
|
readonly makeMediaQueryStyle: <T extends IMediaQueries>(queries: T) => (stylesByQuery: IMediaQueryStyles<T>) => ComplexStyleRule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createMediaQueriesApi.d.ts","sourceRoot":"","sources":["../../../src/internal/createMediaQueriesApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIzE,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAOL,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC5B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAEL,KAAK,uBAAuB,EAE7B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAE5E,KAAK,gBAAgB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"createMediaQueriesApi.d.ts","sourceRoot":"","sources":["../../../src/internal/createMediaQueriesApi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAIzE,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAOL,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC5B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAEL,KAAK,uBAAuB,EAE7B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAE5E,KAAK,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;AAEzD,eAAO,MAAM,qBAAqB,GAAI,MAAM,gBAAgB;;mCAiCvD,CAAC,SAAS,aAAa,WAAW,CAAC,MACnC,eAAe,iBAAiB,CAAC,CAAC,CAAC,KAAG,gBAAgB;;;;WA+DuxG,yDAA2C;;;;;;;;;;;;;;;WAxD52G,eAAe;CAuC/B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACvE,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,yBAAyB,EACzB,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACtB,CAAC"}
|
|
@@ -8,7 +8,6 @@ import { mediaQueryOutputVanillaExtract } from '../mediaQueries/libraryHelpers/v
|
|
|
8
8
|
export const createMediaQueriesApi = (core) => {
|
|
9
9
|
const validation = createMediaQueryValidation({
|
|
10
10
|
assertCondition: core.assertCondition,
|
|
11
|
-
assertMatchingUnits: core.assertMatchingUnits,
|
|
12
11
|
});
|
|
13
12
|
const emitCoreFeatures = createEmitCoreFeatures(validation);
|
|
14
13
|
const emitDimensionsFeatures = createEmitDimensionsFeatures(validation);
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { MediaQueryBuilderHelpers } from './helpers';
|
|
2
|
-
import { assertCondition
|
|
2
|
+
import { assertCondition } from '../core';
|
|
3
3
|
import type { IMediaQueryCore } from './mediaQueries';
|
|
4
4
|
import type { IMediaQueryDimensions } from './modules/dimensions';
|
|
5
5
|
import type { IMediaQueryResolutionRange } from './modules/resolution';
|
|
6
6
|
export type MediaQueryValidationCheck<TConfig> = (config: TConfig) => void;
|
|
7
7
|
export type MediaQueryCoreHelpers = {
|
|
8
8
|
assertCondition: typeof assertCondition;
|
|
9
|
-
assertMatchingUnits: typeof assertMatchingUnits;
|
|
10
9
|
};
|
|
11
10
|
export type MediaQueryValidation = ReturnType<typeof createMediaQueryValidation>;
|
|
12
11
|
export declare const createMediaQueryValidation: (core: MediaQueryCoreHelpers) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/mediaQueries/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EAEzB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,eAAe,
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/mediaQueries/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EAEzB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,eAAe,EAIhB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAGvE,MAAM,MAAM,yBAAyB,CAAC,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;AAE3E,MAAM,MAAM,qBAAqB,GAAG;IAClC,eAAe,EAAE,OAAO,eAAe,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,UAAU,CAC3C,OAAO,0BAA0B,CAClC,CAAC;AAUF,eAAO,MAAM,0BAA0B,GACrC,MAAM,qBAAqB;8BAIM,OAAO,UAC9B,OAAO,WACN,wBAAwB,UACzB,yBAAyB,CAAC,OAAO,CAAC,YAChC,MAAM,+BAEf,OAAO;iCAgB0B,eAAe,KAAG,IAAI;yCAYjD,eAAe,GAAG,qBAAqB,KAC7C,IAAI;kCAuBE,qBAAqB,KAC3B,IAAI;0CAWE,qBAAqB,KAC3B,IAAI;uCAuBE,qBAAqB,KAC3B,IAAI;+CAsBE,qBAAqB,KAC3B,IAAI;sCAmCE,0BAA0B,KAChC,IAAI;CAkCR,CAAC;AAEF,QAAA,MAAM,2BAA2B;8BA9LE,OAAO,UAC9B,OAAO,WACN,wBAAwB,UACzB,yBAAyB,CAAC,OAAO,CAAC,YAChC,MAAM,+BAEf,OAAO;iCAgB0B,eAAe,KAAG,IAAI;yCAYjD,eAAe,GAAG,qBAAqB,KAC7C,IAAI;kCAuBE,qBAAqB,KAC3B,IAAI;0CAWE,qBAAqB,KAC3B,IAAI;uCAuBE,qBAAqB,KAC3B,IAAI;+CAsBE,qBAAqB,KAC3B,IAAI;sCAmCE,0BAA0B,KAChC,IAAI;CAsCP,CAAC;AAEH,eAAO,MACL,uBAAuB,GAnMU,OAAO,UAC9B,OAAO,WACN,wBAAwB,UACzB,yBAAyB,CAAC,OAAO,CAAC,YAChC,MAAM,+BAEf,OAAO,EA8LV,mBAAmB,UA9KiB,eAAe,KAAG,IAAI,EA+K1D,2BAA2B,UAnKlB,eAAe,GAAG,qBAAqB,KAC7C,IAAI,EAmKP,oBAAoB,UA5IX,qBAAqB,KAC3B,IAAI,EA4IP,4BAA4B,UAjInB,qBAAqB,KAC3B,IAAI,EAiIP,yBAAyB,UA1GhB,qBAAqB,KAC3B,IAAI,EA0GP,iCAAiC,UApFxB,qBAAqB,KAC3B,IAAI,EAoFP,wBAAwB,UAjDf,0BAA0B,KAChC,IAiD0B,CAAC;AAEhC,OAAO,EAAE,2BAA2B,EAAE,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { applyMediaQueryValidation } from './helpers';
|
|
2
|
-
import { assertCondition,
|
|
2
|
+
import { assertCondition, isRatio, ratioToFloat, } from '../core';
|
|
3
3
|
const toValidationResult = (error, fallback) => {
|
|
4
4
|
if (error instanceof Error && error.message)
|
|
5
5
|
return error.message;
|
|
6
6
|
return fallback;
|
|
7
7
|
};
|
|
8
8
|
export const createMediaQueryValidation = (core) => {
|
|
9
|
-
const { assertCondition
|
|
9
|
+
const { assertCondition } = core;
|
|
10
10
|
const runMediaQueryValidation = (config, helpers, check, context, fallbackMessage = 'Invalid media query configuration') => {
|
|
11
11
|
if (!check)
|
|
12
12
|
return true;
|
|
@@ -22,7 +22,10 @@ export const createMediaQueryValidation = (core) => {
|
|
|
22
22
|
const validateMinMaxWidth = (props) => {
|
|
23
23
|
if (!props.minWidth || !props.maxWidth)
|
|
24
24
|
return;
|
|
25
|
-
|
|
25
|
+
// Mixed units are valid CSS β each bound is evaluated independently β so we
|
|
26
|
+
// only enforce ordering when the units match and the comparison is meaningful.
|
|
27
|
+
if (props.minWidth.getUnit() !== props.maxWidth.getUnit())
|
|
28
|
+
return;
|
|
26
29
|
assertCondition(props.minWidth.getValue() <= props.maxWidth.getValue(), 'minWidth must be less than or equal to maxWidth');
|
|
27
30
|
};
|
|
28
31
|
const validateWidthValuesPositive = (props) => {
|
|
@@ -42,7 +45,9 @@ export const createMediaQueryValidation = (core) => {
|
|
|
42
45
|
const validateMinMaxHeight = (props) => {
|
|
43
46
|
if (!props.minHeight || !props.maxHeight)
|
|
44
47
|
return;
|
|
45
|
-
|
|
48
|
+
// Mixed units are valid CSS; only enforce ordering when units match.
|
|
49
|
+
if (props.minHeight.getUnit() !== props.maxHeight.getUnit())
|
|
50
|
+
return;
|
|
46
51
|
assertCondition(props.minHeight.getValue() <= props.maxHeight.getValue(), 'minHeight must be less than or equal to maxHeight');
|
|
47
52
|
};
|
|
48
53
|
const validateHeightValuesPositive = (props) => {
|
|
@@ -104,9 +109,8 @@ export const createMediaQueryValidation = (core) => {
|
|
|
104
109
|
if (props.maxResolution) {
|
|
105
110
|
assertPositive(props.maxResolution, 'maxResolution');
|
|
106
111
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
112
|
+
// Resolution bounds may use different units (dpi, dpcm, dppx, x) β all
|
|
113
|
+
// valid CSS β so we no longer require min/max to share a unit.
|
|
110
114
|
};
|
|
111
115
|
return {
|
|
112
116
|
runMediaQueryValidation,
|
|
@@ -121,7 +125,6 @@ export const createMediaQueryValidation = (core) => {
|
|
|
121
125
|
};
|
|
122
126
|
const defaultMediaQueryValidation = createMediaQueryValidation({
|
|
123
127
|
assertCondition,
|
|
124
|
-
assertMatchingUnits,
|
|
125
128
|
});
|
|
126
129
|
export const { runMediaQueryValidation, validateMinMaxWidth, validateWidthValuesPositive, validateMinMaxHeight, validateHeightValuesPositive, validateMinMaxAspectRatio, validateAspectRatioValuesPositive, validateResolutionValues, } = defaultMediaQueryValidation;
|
|
127
130
|
export { defaultMediaQueryValidation };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ISciNotation {
|
|
2
|
+
coefficient: () => number;
|
|
3
|
+
exponent: () => number;
|
|
4
|
+
getUnit: () => string;
|
|
5
|
+
css: () => string;
|
|
6
|
+
toString: () => string;
|
|
7
|
+
valueOf: () => number;
|
|
8
|
+
getValue: () => number;
|
|
9
|
+
withCoefficient: (coefficient: number) => ISciNotation;
|
|
10
|
+
withExponent: (exponent: number) => ISciNotation;
|
|
11
|
+
}
|
|
12
|
+
export declare function sciNotation(coefficient: number, exponent: number, unit?: string): ISciNotation;
|
|
13
|
+
export declare const isSciNotation: (value: unknown) => value is ISciNotation;
|
|
14
|
+
//# sourceMappingURL=sciNotation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sciNotation.d.ts","sourceRoot":"","sources":["../../src/sciNotation.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,eAAe,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,YAAY,CAAC;IACvD,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,YAAY,CAAC;CAClD;AA4DD,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,SAAO,GACV,YAAY,CAEd;AAED,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,YAWvD,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _SciNotationImpl_coefficient, _SciNotationImpl_exponent, _SciNotationImpl_unit;
|
|
13
|
+
class SciNotationImpl {
|
|
14
|
+
constructor(coefficient, exponent, unit = 'px') {
|
|
15
|
+
_SciNotationImpl_coefficient.set(this, void 0);
|
|
16
|
+
_SciNotationImpl_exponent.set(this, void 0);
|
|
17
|
+
_SciNotationImpl_unit.set(this, void 0);
|
|
18
|
+
if (!Number.isFinite(coefficient) || !Number.isFinite(exponent)) {
|
|
19
|
+
throw new Error('Scientific notation values must be finite numbers.');
|
|
20
|
+
}
|
|
21
|
+
if (!Number.isInteger(exponent)) {
|
|
22
|
+
throw new Error('Scientific notation exponent must be an integer.');
|
|
23
|
+
}
|
|
24
|
+
__classPrivateFieldSet(this, _SciNotationImpl_coefficient, coefficient, "f");
|
|
25
|
+
__classPrivateFieldSet(this, _SciNotationImpl_exponent, exponent, "f");
|
|
26
|
+
__classPrivateFieldSet(this, _SciNotationImpl_unit, unit.toLowerCase(), "f");
|
|
27
|
+
}
|
|
28
|
+
coefficient() {
|
|
29
|
+
return __classPrivateFieldGet(this, _SciNotationImpl_coefficient, "f");
|
|
30
|
+
}
|
|
31
|
+
exponent() {
|
|
32
|
+
return __classPrivateFieldGet(this, _SciNotationImpl_exponent, "f");
|
|
33
|
+
}
|
|
34
|
+
getUnit() {
|
|
35
|
+
return __classPrivateFieldGet(this, _SciNotationImpl_unit, "f");
|
|
36
|
+
}
|
|
37
|
+
valueOf() {
|
|
38
|
+
return __classPrivateFieldGet(this, _SciNotationImpl_coefficient, "f") * 10 ** __classPrivateFieldGet(this, _SciNotationImpl_exponent, "f");
|
|
39
|
+
}
|
|
40
|
+
getValue() {
|
|
41
|
+
return this.valueOf();
|
|
42
|
+
}
|
|
43
|
+
css() {
|
|
44
|
+
return `${this.valueOf()}${__classPrivateFieldGet(this, _SciNotationImpl_unit, "f")}`;
|
|
45
|
+
}
|
|
46
|
+
toString() {
|
|
47
|
+
return this.css();
|
|
48
|
+
}
|
|
49
|
+
withCoefficient(coefficient) {
|
|
50
|
+
return new SciNotationImpl(coefficient, __classPrivateFieldGet(this, _SciNotationImpl_exponent, "f"), __classPrivateFieldGet(this, _SciNotationImpl_unit, "f"));
|
|
51
|
+
}
|
|
52
|
+
withExponent(exponent) {
|
|
53
|
+
return new SciNotationImpl(__classPrivateFieldGet(this, _SciNotationImpl_coefficient, "f"), exponent, __classPrivateFieldGet(this, _SciNotationImpl_unit, "f"));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
_SciNotationImpl_coefficient = new WeakMap(), _SciNotationImpl_exponent = new WeakMap(), _SciNotationImpl_unit = new WeakMap();
|
|
57
|
+
export function sciNotation(coefficient, exponent, unit = 'px') {
|
|
58
|
+
return new SciNotationImpl(coefficient, exponent, unit);
|
|
59
|
+
}
|
|
60
|
+
export const isSciNotation = (value) => {
|
|
61
|
+
return (typeof value === 'object' &&
|
|
62
|
+
value !== null &&
|
|
63
|
+
'coefficient' in value &&
|
|
64
|
+
'exponent' in value &&
|
|
65
|
+
'getUnit' in value &&
|
|
66
|
+
typeof value.coefficient === 'function' &&
|
|
67
|
+
typeof value.exponent === 'function' &&
|
|
68
|
+
typeof value.getUnit === 'function');
|
|
69
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "css-calipers",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Compile-time unit safety for numeric, unit-bearing CSS values via typed measurements.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -70,14 +70,14 @@
|
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@eslint/js": "^9.39.2",
|
|
72
72
|
"@types/node": "^24.10.1",
|
|
73
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
74
|
-
"@typescript-eslint/parser": "^8.
|
|
75
|
-
"@vanilla-extract/css": "^1.
|
|
76
|
-
"@vitest/coverage-v8": "^4.
|
|
73
|
+
"@typescript-eslint/eslint-plugin": "^8.60.0",
|
|
74
|
+
"@typescript-eslint/parser": "^8.60.0",
|
|
75
|
+
"@vanilla-extract/css": "^1.20.1",
|
|
76
|
+
"@vitest/coverage-v8": "^4.1.7",
|
|
77
77
|
"eslint": "^9.39.2",
|
|
78
|
-
"tsd": "^0.
|
|
78
|
+
"tsd": "^0.33.0",
|
|
79
79
|
"typescript": "^5.6.3",
|
|
80
|
-
"vitest": "^4.
|
|
80
|
+
"vitest": "^4.1.7"
|
|
81
81
|
},
|
|
82
82
|
"scripts": {
|
|
83
83
|
"build": "npm run build:cjs && npm run build:esm && npm run build:examples",
|