@just-web/toolkits 2.1.0 → 3.1.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/dist/attributes/observe-attribute.cjs +10 -7
- package/dist/attributes/observe-attribute.cjs.map +1 -1
- package/dist/attributes/observe-attribute.d.cts +6 -6
- package/dist/attributes/observe-attribute.d.cts.map +1 -1
- package/dist/attributes/observe-attribute.d.mts +6 -6
- package/dist/attributes/observe-attribute.d.mts.map +1 -1
- package/dist/attributes/observe-attribute.mjs +10 -7
- package/dist/attributes/observe-attribute.mjs.map +1 -1
- package/dist/attributes/observe-data-attribute.cjs +7 -10
- package/dist/attributes/observe-data-attribute.cjs.map +1 -1
- package/dist/attributes/observe-data-attribute.d.cts +8 -11
- package/dist/attributes/observe-data-attribute.d.cts.map +1 -1
- package/dist/attributes/observe-data-attribute.d.mts +8 -11
- package/dist/attributes/observe-data-attribute.d.mts.map +1 -1
- package/dist/attributes/observe-data-attribute.mjs +7 -10
- package/dist/attributes/observe-data-attribute.mjs.map +1 -1
- package/dist/index.cjs +13 -2
- package/dist/index.d.cts +8 -2
- package/dist/index.d.mts +8 -2
- package/dist/index.mjs +7 -2
- package/dist/react/hooks/use-attribute.cjs +1 -2
- package/dist/react/hooks/use-attribute.cjs.map +1 -1
- package/dist/react/hooks/use-attribute.mjs +1 -2
- package/dist/react/hooks/use-attribute.mjs.map +1 -1
- package/dist/style/css-properties.d.cts +2 -1
- package/dist/style/css-properties.d.cts.map +1 -1
- package/dist/style/css-properties.d.mts +2 -1
- package/dist/style/css-properties.d.mts.map +1 -1
- package/dist/theme/class-name/subscribe-class-name.cjs +1 -2
- package/dist/theme/class-name/subscribe-class-name.cjs.map +1 -1
- package/dist/theme/class-name/subscribe-class-name.mjs +1 -2
- package/dist/theme/class-name/subscribe-class-name.mjs.map +1 -1
- package/dist/theme/data-attribute/subscribe-data-attribute.cjs +1 -2
- package/dist/theme/data-attribute/subscribe-data-attribute.cjs.map +1 -1
- package/dist/theme/data-attribute/subscribe-data-attribute.mjs +1 -2
- package/dist/theme/data-attribute/subscribe-data-attribute.mjs.map +1 -1
- package/dist/units/convert-css-unit.cjs +173 -0
- package/dist/units/convert-css-unit.cjs.map +1 -0
- package/dist/units/convert-css-unit.d.cts +25 -0
- package/dist/units/convert-css-unit.d.cts.map +1 -0
- package/dist/units/convert-css-unit.d.mts +25 -0
- package/dist/units/convert-css-unit.d.mts.map +1 -0
- package/dist/units/convert-css-unit.mjs +173 -0
- package/dist/units/convert-css-unit.mjs.map +1 -0
- package/dist/units/create-css-unit-converter.cjs +33 -0
- package/dist/units/create-css-unit-converter.cjs.map +1 -0
- package/dist/units/create-css-unit-converter.d.cts +28 -0
- package/dist/units/create-css-unit-converter.d.cts.map +1 -0
- package/dist/units/create-css-unit-converter.d.mts +28 -0
- package/dist/units/create-css-unit-converter.d.mts.map +1 -0
- package/dist/units/create-css-unit-converter.mjs +33 -0
- package/dist/units/create-css-unit-converter.mjs.map +1 -0
- package/dist/units/css-unit-converter.types.d.cts +35 -0
- package/dist/units/css-unit-converter.types.d.cts.map +1 -0
- package/dist/units/css-unit-converter.types.d.mts +35 -0
- package/dist/units/css-unit-converter.types.d.mts.map +1 -0
- package/dist/units/get-css-unit.cjs +29 -0
- package/dist/units/get-css-unit.cjs.map +1 -0
- package/dist/units/get-css-unit.d.cts +23 -0
- package/dist/units/get-css-unit.d.cts.map +1 -0
- package/dist/units/get-css-unit.d.mts +23 -0
- package/dist/units/get-css-unit.d.mts.map +1 -0
- package/dist/units/get-css-unit.mjs +29 -0
- package/dist/units/get-css-unit.mjs.map +1 -0
- package/dist/units/is-effectively-zero.cjs +35 -0
- package/dist/units/is-effectively-zero.cjs.map +1 -0
- package/dist/units/is-effectively-zero.d.cts +28 -0
- package/dist/units/is-effectively-zero.d.cts.map +1 -0
- package/dist/units/is-effectively-zero.d.mts +28 -0
- package/dist/units/is-effectively-zero.d.mts.map +1 -0
- package/dist/units/is-effectively-zero.mjs +35 -0
- package/dist/units/is-effectively-zero.mjs.map +1 -0
- package/dist/units/parse-css-number.cjs +29 -0
- package/dist/units/parse-css-number.cjs.map +1 -0
- package/dist/units/parse-css-number.d.cts +24 -0
- package/dist/units/parse-css-number.d.cts.map +1 -0
- package/dist/units/parse-css-number.d.mts +24 -0
- package/dist/units/parse-css-number.d.mts.map +1 -0
- package/dist/units/parse-css-number.mjs +29 -0
- package/dist/units/parse-css-number.mjs.map +1 -0
- package/dist/units/parse-css-value.cjs +32 -0
- package/dist/units/parse-css-value.cjs.map +1 -0
- package/dist/units/parse-css-value.d.cts +22 -0
- package/dist/units/parse-css-value.d.cts.map +1 -0
- package/dist/units/parse-css-value.d.mts +22 -0
- package/dist/units/parse-css-value.d.mts.map +1 -0
- package/dist/units/parse-css-value.mjs +31 -0
- package/dist/units/parse-css-value.mjs.map +1 -0
- package/dist/units/px-2-rem.cjs +8 -5
- package/dist/units/px-2-rem.cjs.map +1 -1
- package/dist/units/px-2-rem.d.cts +9 -7
- package/dist/units/px-2-rem.d.cts.map +1 -1
- package/dist/units/px-2-rem.d.mts +9 -7
- package/dist/units/px-2-rem.d.mts.map +1 -1
- package/dist/units/px-2-rem.mjs +8 -5
- package/dist/units/px-2-rem.mjs.map +1 -1
- package/dist/units/rem-2-px.cjs +8 -5
- package/dist/units/rem-2-px.cjs.map +1 -1
- package/dist/units/rem-2-px.d.cts +9 -7
- package/dist/units/rem-2-px.d.cts.map +1 -1
- package/dist/units/rem-2-px.d.mts +9 -7
- package/dist/units/rem-2-px.d.mts.map +1 -1
- package/dist/units/rem-2-px.mjs +8 -5
- package/dist/units/rem-2-px.mjs.map +1 -1
- package/package.json +1 -1
- package/src/attributes/observe-attribute.ts +13 -8
- package/src/attributes/observe-data-attribute.ts +7 -10
- package/src/index.ts +7 -0
- package/src/react/hooks/use-attribute.ts +1 -2
- package/src/style/css-properties.ts +3 -1
- package/src/theme/class-name/subscribe-class-name.ts +1 -2
- package/src/theme/data-attribute/subscribe-data-attribute.ts +1 -2
- package/src/units/convert-css-unit.ts +292 -0
- package/src/units/create-css-unit-converter.ts +30 -0
- package/src/units/css-unit-converter.types.ts +49 -0
- package/src/units/get-css-unit.ts +24 -0
- package/src/units/is-effectively-zero.ts +35 -0
- package/src/units/parse-css-number.ts +26 -0
- package/src/units/parse-css-value.ts +35 -0
- package/src/units/px-2-num.ts +5 -4
- package/src/units/px-2-rem.ts +12 -8
- package/src/units/rem-2-px.ts +11 -9
- package/dist/units/px-2-num.cjs +0 -23
- package/dist/units/px-2-num.cjs.map +0 -1
- package/dist/units/px-2-num.d.cts +0 -19
- package/dist/units/px-2-num.d.cts.map +0 -1
- package/dist/units/px-2-num.d.mts +0 -19
- package/dist/units/px-2-num.d.mts.map +0 -1
- package/dist/units/px-2-num.mjs +0 -22
- package/dist/units/px-2-num.mjs.map +0 -1
|
@@ -17,10 +17,9 @@ function subscribeDataAttribute(themes, attributeName, handler, options) {
|
|
|
17
17
|
const element = options?.element ?? document?.documentElement;
|
|
18
18
|
if (!element) return () => {};
|
|
19
19
|
const parse = options?.parse ?? ((t, v) => require_parse_data_attribute.parseDataAttribute(t, v, { separator: require__constant.SEPARATOR_SPACE }));
|
|
20
|
-
|
|
20
|
+
return require_observe_data_attribute.observeDataAttributes({ [attributeName]: (value) => {
|
|
21
21
|
handler(parse(themes, value ?? void 0));
|
|
22
22
|
} }, element);
|
|
23
|
-
return () => observer.disconnect();
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribe-data-attribute.cjs","names":["parseDataAttribute","SEPARATOR_SPACE","observeDataAttributes"],"sources":["../../../src/theme/data-attribute/subscribe-data-attribute.ts"],"sourcesContent":["import { observeDataAttributes } from '../../attributes/observe-data-attribute.ts'\nimport type { ParseStoredTheme, ThemeEntry } from '../theme-entry.types.ts'\nimport type { ThemeMap } from '../theme-map.types.ts'\nimport { SEPARATOR_SPACE } from './_constant.ts'\nimport { parseDataAttribute } from './parse-data-attribute.ts'\n\n/**\n * Subscribes to changes on a data attribute and invokes the handler with parsed theme entries.\n *\n * @param themes - Record mapping theme keys to attribute values\n * @param attributeName - Data attribute name (e.g. `data-theme`)\n * @param handler - Callback invoked when the attribute changes\n * @param options.element - Element to observe (accepts null e.g. from refs). Defaults to document.documentElement.\n * @param options.parse - Custom parser (default: parseDataAttribute with space separator)\n * @returns Unsubscribe function. Returns a no-op function when element is not available (e.g. SSR).\n */\nexport function subscribeDataAttribute<Themes extends ThemeMap>(\n\tthemes: Themes,\n\tattributeName: `data-${string}`,\n\thandler: (entry: ThemeEntry<Themes> | undefined) => void,\n\toptions?:\n\t\t| { element?: Element | null | undefined; parse?: ParseStoredTheme<Themes> | undefined }\n\t\t| undefined\n): () => void {\n\tconst element = options?.element ?? document?.documentElement\n\tif (!element) return () => {}\n\tconst parse =\n\t\toptions?.parse ?? ((t, v) => parseDataAttribute(t, v, { separator: SEPARATOR_SPACE }))\n\
|
|
1
|
+
{"version":3,"file":"subscribe-data-attribute.cjs","names":["parseDataAttribute","SEPARATOR_SPACE","observeDataAttributes"],"sources":["../../../src/theme/data-attribute/subscribe-data-attribute.ts"],"sourcesContent":["import { observeDataAttributes } from '../../attributes/observe-data-attribute.ts'\nimport type { ParseStoredTheme, ThemeEntry } from '../theme-entry.types.ts'\nimport type { ThemeMap } from '../theme-map.types.ts'\nimport { SEPARATOR_SPACE } from './_constant.ts'\nimport { parseDataAttribute } from './parse-data-attribute.ts'\n\n/**\n * Subscribes to changes on a data attribute and invokes the handler with parsed theme entries.\n *\n * @param themes - Record mapping theme keys to attribute values\n * @param attributeName - Data attribute name (e.g. `data-theme`)\n * @param handler - Callback invoked when the attribute changes\n * @param options.element - Element to observe (accepts null e.g. from refs). Defaults to document.documentElement.\n * @param options.parse - Custom parser (default: parseDataAttribute with space separator)\n * @returns Unsubscribe function. Returns a no-op function when element is not available (e.g. SSR).\n */\nexport function subscribeDataAttribute<Themes extends ThemeMap>(\n\tthemes: Themes,\n\tattributeName: `data-${string}`,\n\thandler: (entry: ThemeEntry<Themes> | undefined) => void,\n\toptions?:\n\t\t| { element?: Element | null | undefined; parse?: ParseStoredTheme<Themes> | undefined }\n\t\t| undefined\n): () => void {\n\tconst element = options?.element ?? document?.documentElement\n\tif (!element) return () => {}\n\tconst parse =\n\t\toptions?.parse ?? ((t, v) => parseDataAttribute(t, v, { separator: SEPARATOR_SPACE }))\n\treturn observeDataAttributes<string, `data-${string}`>(\n\t\t{\n\t\t\t[attributeName]: (value) => {\n\t\t\t\tconst entry = parse(themes, value ?? undefined)\n\t\t\t\thandler(entry)\n\t\t\t}\n\t\t},\n\t\telement\n\t)\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,SAAgB,uBACf,QACA,eACA,SACA,SAGa;CACb,MAAM,UAAU,SAAS,WAAW,UAAU;AAC9C,KAAI,CAAC,QAAS,cAAa;CAC3B,MAAM,QACL,SAAS,WAAW,GAAG,MAAMA,gDAAmB,GAAG,GAAG,EAAE,WAAWC,mCAAiB,CAAC;AACtF,QAAOC,qDACN,GACE,iBAAiB,UAAU;AAE3B,UADc,MAAM,QAAQ,SAAS,OAAU,CACjC;IAEf,EACD,QACA"}
|
|
@@ -17,10 +17,9 @@ function subscribeDataAttribute(themes, attributeName, handler, options) {
|
|
|
17
17
|
const element = options?.element ?? document?.documentElement;
|
|
18
18
|
if (!element) return () => {};
|
|
19
19
|
const parse = options?.parse ?? ((t, v) => parseDataAttribute(t, v, { separator: SEPARATOR_SPACE }));
|
|
20
|
-
|
|
20
|
+
return observeDataAttributes({ [attributeName]: (value) => {
|
|
21
21
|
handler(parse(themes, value ?? void 0));
|
|
22
22
|
} }, element);
|
|
23
|
-
return () => observer.disconnect();
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribe-data-attribute.mjs","names":[],"sources":["../../../src/theme/data-attribute/subscribe-data-attribute.ts"],"sourcesContent":["import { observeDataAttributes } from '../../attributes/observe-data-attribute.ts'\nimport type { ParseStoredTheme, ThemeEntry } from '../theme-entry.types.ts'\nimport type { ThemeMap } from '../theme-map.types.ts'\nimport { SEPARATOR_SPACE } from './_constant.ts'\nimport { parseDataAttribute } from './parse-data-attribute.ts'\n\n/**\n * Subscribes to changes on a data attribute and invokes the handler with parsed theme entries.\n *\n * @param themes - Record mapping theme keys to attribute values\n * @param attributeName - Data attribute name (e.g. `data-theme`)\n * @param handler - Callback invoked when the attribute changes\n * @param options.element - Element to observe (accepts null e.g. from refs). Defaults to document.documentElement.\n * @param options.parse - Custom parser (default: parseDataAttribute with space separator)\n * @returns Unsubscribe function. Returns a no-op function when element is not available (e.g. SSR).\n */\nexport function subscribeDataAttribute<Themes extends ThemeMap>(\n\tthemes: Themes,\n\tattributeName: `data-${string}`,\n\thandler: (entry: ThemeEntry<Themes> | undefined) => void,\n\toptions?:\n\t\t| { element?: Element | null | undefined; parse?: ParseStoredTheme<Themes> | undefined }\n\t\t| undefined\n): () => void {\n\tconst element = options?.element ?? document?.documentElement\n\tif (!element) return () => {}\n\tconst parse =\n\t\toptions?.parse ?? ((t, v) => parseDataAttribute(t, v, { separator: SEPARATOR_SPACE }))\n\
|
|
1
|
+
{"version":3,"file":"subscribe-data-attribute.mjs","names":[],"sources":["../../../src/theme/data-attribute/subscribe-data-attribute.ts"],"sourcesContent":["import { observeDataAttributes } from '../../attributes/observe-data-attribute.ts'\nimport type { ParseStoredTheme, ThemeEntry } from '../theme-entry.types.ts'\nimport type { ThemeMap } from '../theme-map.types.ts'\nimport { SEPARATOR_SPACE } from './_constant.ts'\nimport { parseDataAttribute } from './parse-data-attribute.ts'\n\n/**\n * Subscribes to changes on a data attribute and invokes the handler with parsed theme entries.\n *\n * @param themes - Record mapping theme keys to attribute values\n * @param attributeName - Data attribute name (e.g. `data-theme`)\n * @param handler - Callback invoked when the attribute changes\n * @param options.element - Element to observe (accepts null e.g. from refs). Defaults to document.documentElement.\n * @param options.parse - Custom parser (default: parseDataAttribute with space separator)\n * @returns Unsubscribe function. Returns a no-op function when element is not available (e.g. SSR).\n */\nexport function subscribeDataAttribute<Themes extends ThemeMap>(\n\tthemes: Themes,\n\tattributeName: `data-${string}`,\n\thandler: (entry: ThemeEntry<Themes> | undefined) => void,\n\toptions?:\n\t\t| { element?: Element | null | undefined; parse?: ParseStoredTheme<Themes> | undefined }\n\t\t| undefined\n): () => void {\n\tconst element = options?.element ?? document?.documentElement\n\tif (!element) return () => {}\n\tconst parse =\n\t\toptions?.parse ?? ((t, v) => parseDataAttribute(t, v, { separator: SEPARATOR_SPACE }))\n\treturn observeDataAttributes<string, `data-${string}`>(\n\t\t{\n\t\t\t[attributeName]: (value) => {\n\t\t\t\tconst entry = parse(themes, value ?? undefined)\n\t\t\t\thandler(entry)\n\t\t\t}\n\t\t},\n\t\telement\n\t)\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,SAAgB,uBACf,QACA,eACA,SACA,SAGa;CACb,MAAM,UAAU,SAAS,WAAW,UAAU;AAC9C,KAAI,CAAC,QAAS,cAAa;CAC3B,MAAM,QACL,SAAS,WAAW,GAAG,MAAM,mBAAmB,GAAG,GAAG,EAAE,WAAW,iBAAiB,CAAC;AACtF,QAAO,sBACN,GACE,iBAAiB,UAAU;AAE3B,UADc,MAAM,QAAQ,SAAS,OAAU,CACjC;IAEf,EACD,QACA"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
const require_get_rem_to_px_scale = require('./get-rem-to-px-scale.cjs');
|
|
2
|
+
const require_parse_css_value = require('./parse-css-value.cjs');
|
|
3
|
+
|
|
4
|
+
//#region src/units/convert-css-unit.ts
|
|
5
|
+
const PX_PER_IN = 96;
|
|
6
|
+
const PT_PER_IN = 72;
|
|
7
|
+
const PC_PER_IN = 6;
|
|
8
|
+
const CM_PER_IN = 2.54;
|
|
9
|
+
const MM_PER_IN = 25.4;
|
|
10
|
+
const DEFAULT_ELEMENT_FONT_SIZE = 16;
|
|
11
|
+
const DEFAULT_PRECISION = 4;
|
|
12
|
+
const ABSOLUTE_UNITS = [
|
|
13
|
+
"px",
|
|
14
|
+
"pt",
|
|
15
|
+
"pc",
|
|
16
|
+
"in",
|
|
17
|
+
"cm",
|
|
18
|
+
"mm"
|
|
19
|
+
];
|
|
20
|
+
const LINE_UNITS = ["lh", "rlh"];
|
|
21
|
+
/**
|
|
22
|
+
* Converts a CSS length value from one unit to another.
|
|
23
|
+
*
|
|
24
|
+
* @param value - The value to convert. Can be a number or string (e.g. '16px', '1.5rem'). Pass-through for null/undefined.
|
|
25
|
+
* @param toUnit - The target unit.
|
|
26
|
+
* @param options - Conversion context. When omitted, uses browser auto-detect for rootFontSize and viewport when available.
|
|
27
|
+
* @returns The converted numeric value, or null/undefined when input is null/undefined.
|
|
28
|
+
* @throws When required context is missing (viewport, lineHeight, percentReference) or percentReference is 0 for % conversion.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* convertCssUnit('16px', 'rem') // 1
|
|
33
|
+
* convertCssUnit('1rem', 'px') // 16
|
|
34
|
+
* convertCssUnit('50%', 'px', { percentReference: 200 }) // 100
|
|
35
|
+
* convertCssUnit('10vw', 'px', { viewportWidth: 375 }) // 37.5
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
function convertCssUnit(value, toUnit, options) {
|
|
39
|
+
const [num, parsedUnit] = require_parse_css_value.parseCssValue(value);
|
|
40
|
+
if (num === null || num === void 0) return num;
|
|
41
|
+
if (Number.isNaN(num)) throw new Error(`Invalid CSS value: ${value}`);
|
|
42
|
+
const fromUnit = options?.fromUnit ?? normalizeUnit(parsedUnit) ?? "px";
|
|
43
|
+
const resolved = resolveOptions(options);
|
|
44
|
+
if (fromUnit === toUnit) return Number(num.toFixed(resolved.precision));
|
|
45
|
+
let result;
|
|
46
|
+
if (fromUnit === "rem" && toUnit === "em") result = remToEmDirect(num, resolved);
|
|
47
|
+
else if (fromUnit === "em" && toUnit === "rem") result = emToRemDirect(num, resolved);
|
|
48
|
+
else result = pxToValue(valueToPx(num, fromUnit, resolved), toUnit, resolved);
|
|
49
|
+
return Number(result.toFixed(resolved.precision));
|
|
50
|
+
}
|
|
51
|
+
function normalizeUnit(unit) {
|
|
52
|
+
if (!unit) return void 0;
|
|
53
|
+
const u = unit.toLowerCase();
|
|
54
|
+
if (u === "px" || u === "pt" || u === "pc" || u === "in" || u === "cm" || u === "mm" || u === "rem" || u === "em" || u === "vw" || u === "vh" || u === "vmin" || u === "vmax" || u === "lh" || u === "rlh" || u === "ch" || u === "%") return u;
|
|
55
|
+
}
|
|
56
|
+
function resolveOptions(options) {
|
|
57
|
+
const rootFontSize = options?.rootFontSize ?? require_get_rem_to_px_scale.getRemToPxScale();
|
|
58
|
+
const elementFontSize = options?.elementFontSize ?? DEFAULT_ELEMENT_FONT_SIZE;
|
|
59
|
+
const precision = options?.precision ?? DEFAULT_PRECISION;
|
|
60
|
+
let viewportWidth = options?.viewportWidth;
|
|
61
|
+
let viewportHeight = options?.viewportHeight;
|
|
62
|
+
if (typeof window !== "undefined") {
|
|
63
|
+
viewportWidth ??= window.innerWidth;
|
|
64
|
+
viewportHeight ??= window.innerHeight;
|
|
65
|
+
}
|
|
66
|
+
const lineHeight = options?.lineHeight;
|
|
67
|
+
const chWidth = options?.chWidth ?? elementFontSize * .5;
|
|
68
|
+
const percentReference = options?.percentReference ?? 0;
|
|
69
|
+
return {
|
|
70
|
+
rootFontSize,
|
|
71
|
+
elementFontSize,
|
|
72
|
+
viewportWidth: viewportWidth ?? 0,
|
|
73
|
+
viewportHeight: viewportHeight ?? 0,
|
|
74
|
+
lineHeight: lineHeight ?? 0,
|
|
75
|
+
chWidth,
|
|
76
|
+
percentReference,
|
|
77
|
+
precision
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function remToEmDirect(value, resolved) {
|
|
81
|
+
return value * (resolved.rootFontSize / resolved.elementFontSize);
|
|
82
|
+
}
|
|
83
|
+
function emToRemDirect(value, resolved) {
|
|
84
|
+
return value * (resolved.elementFontSize / resolved.rootFontSize);
|
|
85
|
+
}
|
|
86
|
+
function valueToPx(value, fromUnit, resolved) {
|
|
87
|
+
if (ABSOLUTE_UNITS.includes(fromUnit)) return toPxFromAbsolute(value, fromUnit);
|
|
88
|
+
if (fromUnit === "rem") return value * (resolved.rootFontSize ?? 0);
|
|
89
|
+
if (fromUnit === "em") return value * (resolved.elementFontSize ?? 0);
|
|
90
|
+
if (fromUnit === "vw") {
|
|
91
|
+
if (resolved.viewportWidth === 0) throw new Error("viewportWidth is required for vw conversion");
|
|
92
|
+
return value / 100 * resolved.viewportWidth;
|
|
93
|
+
}
|
|
94
|
+
if (fromUnit === "vh") {
|
|
95
|
+
if (resolved.viewportHeight === 0) throw new Error("viewportHeight is required for vh conversion");
|
|
96
|
+
return value / 100 * resolved.viewportHeight;
|
|
97
|
+
}
|
|
98
|
+
if (fromUnit === "vmin") {
|
|
99
|
+
if (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) throw new Error("viewportWidth and viewportHeight are required for vmin conversion");
|
|
100
|
+
return value / 100 * Math.min(resolved.viewportWidth, resolved.viewportHeight);
|
|
101
|
+
}
|
|
102
|
+
if (fromUnit === "vmax") {
|
|
103
|
+
if (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) throw new Error("viewportWidth and viewportHeight are required for vmax conversion");
|
|
104
|
+
return value / 100 * Math.max(resolved.viewportWidth, resolved.viewportHeight);
|
|
105
|
+
}
|
|
106
|
+
if (LINE_UNITS.includes(fromUnit)) {
|
|
107
|
+
if (resolved.lineHeight === 0) throw new Error("lineHeight is required for lh/rlh conversion");
|
|
108
|
+
return value * resolved.lineHeight;
|
|
109
|
+
}
|
|
110
|
+
if (fromUnit === "ch") return value * resolved.chWidth;
|
|
111
|
+
if (fromUnit === "%") {
|
|
112
|
+
if (resolved.percentReference === 0) throw new Error("percentReference is required for % conversion");
|
|
113
|
+
return value / 100 * resolved.percentReference;
|
|
114
|
+
}
|
|
115
|
+
throw new Error(`Unsupported unit: ${fromUnit}`);
|
|
116
|
+
}
|
|
117
|
+
function pxToValue(px, toUnit, resolved) {
|
|
118
|
+
if (ABSOLUTE_UNITS.includes(toUnit)) return fromPxToAbsolute(px, toUnit);
|
|
119
|
+
if (toUnit === "rem") return px / resolved.rootFontSize;
|
|
120
|
+
if (toUnit === "em") return px / resolved.elementFontSize;
|
|
121
|
+
if (toUnit === "vw") {
|
|
122
|
+
if (resolved.viewportWidth === 0) throw new Error("viewportWidth is required for vw conversion");
|
|
123
|
+
return px / resolved.viewportWidth * 100;
|
|
124
|
+
}
|
|
125
|
+
if (toUnit === "vh") {
|
|
126
|
+
if (resolved.viewportHeight === 0) throw new Error("viewportHeight is required for vh conversion");
|
|
127
|
+
return px / resolved.viewportHeight * 100;
|
|
128
|
+
}
|
|
129
|
+
if (toUnit === "vmin") {
|
|
130
|
+
if (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) throw new Error("viewportWidth and viewportHeight are required for vmin conversion");
|
|
131
|
+
return px / Math.min(resolved.viewportWidth, resolved.viewportHeight) * 100;
|
|
132
|
+
}
|
|
133
|
+
if (toUnit === "vmax") {
|
|
134
|
+
if (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) throw new Error("viewportWidth and viewportHeight are required for vmax conversion");
|
|
135
|
+
return px / Math.max(resolved.viewportWidth, resolved.viewportHeight) * 100;
|
|
136
|
+
}
|
|
137
|
+
if (LINE_UNITS.includes(toUnit)) {
|
|
138
|
+
if (resolved.lineHeight === 0) throw new Error("lineHeight is required for lh/rlh conversion");
|
|
139
|
+
return px / resolved.lineHeight;
|
|
140
|
+
}
|
|
141
|
+
if (toUnit === "ch") return px / resolved.chWidth;
|
|
142
|
+
if (toUnit === "%") {
|
|
143
|
+
if (resolved.percentReference === 0) throw new Error("percentReference is required and must be non-zero for conversion to %");
|
|
144
|
+
return px / resolved.percentReference * 100;
|
|
145
|
+
}
|
|
146
|
+
throw new Error(`Unsupported unit: ${toUnit}`);
|
|
147
|
+
}
|
|
148
|
+
function toPxFromAbsolute(value, unit) {
|
|
149
|
+
switch (unit) {
|
|
150
|
+
case "px": return value;
|
|
151
|
+
case "pt": return value * PX_PER_IN / PT_PER_IN;
|
|
152
|
+
case "pc": return value * PX_PER_IN / PC_PER_IN;
|
|
153
|
+
case "in": return value * PX_PER_IN;
|
|
154
|
+
case "cm": return value * PX_PER_IN / CM_PER_IN;
|
|
155
|
+
case "mm": return value * PX_PER_IN / MM_PER_IN;
|
|
156
|
+
default: return value;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function fromPxToAbsolute(px, unit) {
|
|
160
|
+
switch (unit) {
|
|
161
|
+
case "px": return px;
|
|
162
|
+
case "pt": return px * PT_PER_IN / PX_PER_IN;
|
|
163
|
+
case "pc": return px * PC_PER_IN / PX_PER_IN;
|
|
164
|
+
case "in": return px / PX_PER_IN;
|
|
165
|
+
case "cm": return px * CM_PER_IN / PX_PER_IN;
|
|
166
|
+
case "mm": return px * MM_PER_IN / PX_PER_IN;
|
|
167
|
+
default: return px;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
//#endregion
|
|
172
|
+
exports.convertCssUnit = convertCssUnit;
|
|
173
|
+
//# sourceMappingURL=convert-css-unit.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-css-unit.cjs","names":["ABSOLUTE_UNITS: CssLengthUnit[]","LINE_UNITS: CssLengthUnit[]","parseCssValue","fromUnit: CssLengthUnit","result: number","getRemToPxScale"],"sources":["../../src/units/convert-css-unit.ts"],"sourcesContent":["import type { Required } from 'type-plus'\nimport type { ConvertCssUnitOptions, CssLengthUnit } from './css-unit-converter.types.ts'\nimport { getRemToPxScale } from './get-rem-to-px-scale.ts'\nimport { parseCssValue } from './parse-css-value.ts'\n\nconst PX_PER_IN = 96\nconst PT_PER_IN = 72\nconst PC_PER_IN = 6\nconst CM_PER_IN = 2.54\nconst MM_PER_IN = 25.4\n\nconst DEFAULT_ELEMENT_FONT_SIZE = 16\nconst DEFAULT_PRECISION = 4\n\nconst ABSOLUTE_UNITS: CssLengthUnit[] = ['px', 'pt', 'pc', 'in', 'cm', 'mm']\nconst LINE_UNITS: CssLengthUnit[] = ['lh', 'rlh']\n\n/**\n * Converts a CSS length value from one unit to another.\n *\n * @param value - The value to convert. Can be a number or string (e.g. '16px', '1.5rem'). Pass-through for null/undefined.\n * @param toUnit - The target unit.\n * @param options - Conversion context. When omitted, uses browser auto-detect for rootFontSize and viewport when available.\n * @returns The converted numeric value, or null/undefined when input is null/undefined.\n * @throws When required context is missing (viewport, lineHeight, percentReference) or percentReference is 0 for % conversion.\n *\n * @example\n * ```ts\n * convertCssUnit('16px', 'rem') // 1\n * convertCssUnit('1rem', 'px') // 16\n * convertCssUnit('50%', 'px', { percentReference: 200 }) // 100\n * convertCssUnit('10vw', 'px', { viewportWidth: 375 }) // 37.5\n * ```\n */\nexport function convertCssUnit(\n\tvalue: number | string | null | undefined,\n\ttoUnit: CssLengthUnit,\n\toptions?: ConvertCssUnitOptions | undefined\n): number | null | undefined {\n\tconst [num, parsedUnit] = parseCssValue(value)\n\tif (num === null || num === undefined) return num\n\tif (Number.isNaN(num)) {\n\t\tthrow new Error(`Invalid CSS value: ${value}`)\n\t}\n\n\tconst fromUnit: CssLengthUnit = options?.fromUnit ?? normalizeUnit(parsedUnit) ?? 'px'\n\n\tconst resolved = resolveOptions(options)\n\n\tif (fromUnit === toUnit) {\n\t\treturn Number(num.toFixed(resolved.precision))\n\t}\n\n\tlet result: number\n\n\tif (fromUnit === 'rem' && toUnit === 'em') {\n\t\tresult = remToEmDirect(num, resolved)\n\t} else if (fromUnit === 'em' && toUnit === 'rem') {\n\t\tresult = emToRemDirect(num, resolved)\n\t} else {\n\t\tconst px = valueToPx(num, fromUnit, resolved)\n\t\tresult = pxToValue(px, toUnit, resolved)\n\t}\n\n\treturn Number(result.toFixed(resolved.precision))\n}\n\nfunction normalizeUnit(unit: string | undefined): CssLengthUnit | undefined {\n\tif (!unit) return undefined\n\tconst u = unit.toLowerCase()\n\tif (\n\t\tu === 'px' ||\n\t\tu === 'pt' ||\n\t\tu === 'pc' ||\n\t\tu === 'in' ||\n\t\tu === 'cm' ||\n\t\tu === 'mm' ||\n\t\tu === 'rem' ||\n\t\tu === 'em' ||\n\t\tu === 'vw' ||\n\t\tu === 'vh' ||\n\t\tu === 'vmin' ||\n\t\tu === 'vmax' ||\n\t\tu === 'lh' ||\n\t\tu === 'rlh' ||\n\t\tu === 'ch' ||\n\t\tu === '%'\n\t) {\n\t\treturn u as CssLengthUnit\n\t}\n\treturn undefined\n}\n\nfunction resolveOptions(\n\toptions?: ConvertCssUnitOptions | undefined\n): Required<\n\tPick<\n\t\tConvertCssUnitOptions,\n\t\t| 'rootFontSize'\n\t\t| 'elementFontSize'\n\t\t| 'viewportWidth'\n\t\t| 'viewportHeight'\n\t\t| 'lineHeight'\n\t\t| 'chWidth'\n\t\t| 'percentReference'\n\t\t| 'precision'\n\t>\n> {\n\tconst rootFontSize = options?.rootFontSize ?? getRemToPxScale()\n\tconst elementFontSize = options?.elementFontSize ?? DEFAULT_ELEMENT_FONT_SIZE\n\tconst precision = options?.precision ?? DEFAULT_PRECISION\n\n\tlet viewportWidth = options?.viewportWidth\n\tlet viewportHeight = options?.viewportHeight\n\tif (typeof window !== 'undefined') {\n\t\tviewportWidth ??= window.innerWidth\n\t\tviewportHeight ??= window.innerHeight\n\t}\n\n\tconst lineHeight = options?.lineHeight\n\tconst chWidth = options?.chWidth ?? elementFontSize * 0.5\n\tconst percentReference = options?.percentReference ?? 0\n\n\treturn {\n\t\trootFontSize,\n\t\telementFontSize,\n\t\tviewportWidth: viewportWidth ?? 0,\n\t\tviewportHeight: viewportHeight ?? 0,\n\t\tlineHeight: lineHeight ?? 0,\n\t\tchWidth,\n\t\tpercentReference,\n\t\tprecision\n\t}\n}\n\nfunction remToEmDirect(value: number, resolved: ReturnType<typeof resolveOptions>): number {\n\treturn value * (resolved.rootFontSize / resolved.elementFontSize)\n}\n\nfunction emToRemDirect(value: number, resolved: ReturnType<typeof resolveOptions>): number {\n\treturn value * (resolved.elementFontSize / resolved.rootFontSize)\n}\n\nfunction valueToPx(\n\tvalue: number,\n\tfromUnit: CssLengthUnit,\n\tresolved: ReturnType<typeof resolveOptions>\n): number {\n\tif (ABSOLUTE_UNITS.includes(fromUnit)) {\n\t\treturn toPxFromAbsolute(value, fromUnit)\n\t}\n\tif (fromUnit === 'rem') {\n\t\treturn value * (resolved.rootFontSize ?? 0)\n\t}\n\tif (fromUnit === 'em') {\n\t\treturn value * (resolved.elementFontSize ?? 0)\n\t}\n\tif (fromUnit === 'vw') {\n\t\tif (resolved.viewportWidth === 0) {\n\t\t\tthrow new Error('viewportWidth is required for vw conversion')\n\t\t}\n\t\treturn (value / 100) * resolved.viewportWidth\n\t}\n\tif (fromUnit === 'vh') {\n\t\tif (resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportHeight is required for vh conversion')\n\t\t}\n\t\treturn (value / 100) * resolved.viewportHeight\n\t}\n\tif (fromUnit === 'vmin') {\n\t\tif (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportWidth and viewportHeight are required for vmin conversion')\n\t\t}\n\t\treturn (value / 100) * Math.min(resolved.viewportWidth, resolved.viewportHeight)\n\t}\n\tif (fromUnit === 'vmax') {\n\t\tif (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportWidth and viewportHeight are required for vmax conversion')\n\t\t}\n\t\treturn (value / 100) * Math.max(resolved.viewportWidth, resolved.viewportHeight)\n\t}\n\tif (LINE_UNITS.includes(fromUnit)) {\n\t\tif (resolved.lineHeight === 0) {\n\t\t\tthrow new Error('lineHeight is required for lh/rlh conversion')\n\t\t}\n\t\treturn value * resolved.lineHeight\n\t}\n\tif (fromUnit === 'ch') {\n\t\treturn value * resolved.chWidth\n\t}\n\tif (fromUnit === '%') {\n\t\tif (resolved.percentReference === 0) {\n\t\t\tthrow new Error('percentReference is required for % conversion')\n\t\t}\n\t\treturn (value / 100) * resolved.percentReference\n\t}\n\tthrow new Error(`Unsupported unit: ${fromUnit}`)\n}\n\nfunction pxToValue(\n\tpx: number,\n\ttoUnit: CssLengthUnit,\n\tresolved: ReturnType<typeof resolveOptions>\n): number {\n\tif (ABSOLUTE_UNITS.includes(toUnit)) {\n\t\treturn fromPxToAbsolute(px, toUnit)\n\t}\n\tif (toUnit === 'rem') {\n\t\treturn px / resolved.rootFontSize\n\t}\n\tif (toUnit === 'em') {\n\t\treturn px / resolved.elementFontSize\n\t}\n\tif (toUnit === 'vw') {\n\t\tif (resolved.viewportWidth === 0) {\n\t\t\tthrow new Error('viewportWidth is required for vw conversion')\n\t\t}\n\t\treturn (px / resolved.viewportWidth) * 100\n\t}\n\tif (toUnit === 'vh') {\n\t\tif (resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportHeight is required for vh conversion')\n\t\t}\n\t\treturn (px / resolved.viewportHeight) * 100\n\t}\n\tif (toUnit === 'vmin') {\n\t\tif (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportWidth and viewportHeight are required for vmin conversion')\n\t\t}\n\t\treturn (px / Math.min(resolved.viewportWidth, resolved.viewportHeight)) * 100\n\t}\n\tif (toUnit === 'vmax') {\n\t\tif (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportWidth and viewportHeight are required for vmax conversion')\n\t\t}\n\t\treturn (px / Math.max(resolved.viewportWidth, resolved.viewportHeight)) * 100\n\t}\n\tif (LINE_UNITS.includes(toUnit)) {\n\t\tif (resolved.lineHeight === 0) {\n\t\t\tthrow new Error('lineHeight is required for lh/rlh conversion')\n\t\t}\n\t\treturn px / resolved.lineHeight\n\t}\n\tif (toUnit === 'ch') {\n\t\treturn px / resolved.chWidth\n\t}\n\tif (toUnit === '%') {\n\t\tif (resolved.percentReference === 0) {\n\t\t\tthrow new Error('percentReference is required and must be non-zero for conversion to %')\n\t\t}\n\t\treturn (px / resolved.percentReference) * 100\n\t}\n\tthrow new Error(`Unsupported unit: ${toUnit}`)\n}\n\nfunction toPxFromAbsolute(value: number, unit: CssLengthUnit): number {\n\tswitch (unit) {\n\t\tcase 'px':\n\t\t\treturn value\n\t\tcase 'pt':\n\t\t\treturn (value * PX_PER_IN) / PT_PER_IN\n\t\tcase 'pc':\n\t\t\treturn (value * PX_PER_IN) / PC_PER_IN\n\t\tcase 'in':\n\t\t\treturn value * PX_PER_IN\n\t\tcase 'cm':\n\t\t\treturn (value * PX_PER_IN) / CM_PER_IN\n\t\tcase 'mm':\n\t\t\treturn (value * PX_PER_IN) / MM_PER_IN\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\nfunction fromPxToAbsolute(px: number, unit: CssLengthUnit): number {\n\tswitch (unit) {\n\t\tcase 'px':\n\t\t\treturn px\n\t\tcase 'pt':\n\t\t\treturn (px * PT_PER_IN) / PX_PER_IN\n\t\tcase 'pc':\n\t\t\treturn (px * PC_PER_IN) / PX_PER_IN\n\t\tcase 'in':\n\t\t\treturn px / PX_PER_IN\n\t\tcase 'cm':\n\t\t\treturn (px * CM_PER_IN) / PX_PER_IN\n\t\tcase 'mm':\n\t\t\treturn (px * MM_PER_IN) / PX_PER_IN\n\t\tdefault:\n\t\t\treturn px\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ConvertCssUnitOptions, CssLengthUnit } from "./css-unit-converter.types.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/units/convert-css-unit.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Converts a CSS length value from one unit to another.
|
|
7
|
+
*
|
|
8
|
+
* @param value - The value to convert. Can be a number or string (e.g. '16px', '1.5rem'). Pass-through for null/undefined.
|
|
9
|
+
* @param toUnit - The target unit.
|
|
10
|
+
* @param options - Conversion context. When omitted, uses browser auto-detect for rootFontSize and viewport when available.
|
|
11
|
+
* @returns The converted numeric value, or null/undefined when input is null/undefined.
|
|
12
|
+
* @throws When required context is missing (viewport, lineHeight, percentReference) or percentReference is 0 for % conversion.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* convertCssUnit('16px', 'rem') // 1
|
|
17
|
+
* convertCssUnit('1rem', 'px') // 16
|
|
18
|
+
* convertCssUnit('50%', 'px', { percentReference: 200 }) // 100
|
|
19
|
+
* convertCssUnit('10vw', 'px', { viewportWidth: 375 }) // 37.5
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare function convertCssUnit(value: number | string | null | undefined, toUnit: CssLengthUnit, options?: ConvertCssUnitOptions | undefined): number | null | undefined;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { convertCssUnit };
|
|
25
|
+
//# sourceMappingURL=convert-css-unit.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-css-unit.d.cts","names":[],"sources":["../../src/units/convert-css-unit.ts"],"sourcesContent":[],"mappings":";;;;;;AAkCA;;;;;;;;;;;;;;;iBAAgB,cAAA,oDAEP,yBACE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ConvertCssUnitOptions, CssLengthUnit } from "./css-unit-converter.types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/units/convert-css-unit.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Converts a CSS length value from one unit to another.
|
|
7
|
+
*
|
|
8
|
+
* @param value - The value to convert. Can be a number or string (e.g. '16px', '1.5rem'). Pass-through for null/undefined.
|
|
9
|
+
* @param toUnit - The target unit.
|
|
10
|
+
* @param options - Conversion context. When omitted, uses browser auto-detect for rootFontSize and viewport when available.
|
|
11
|
+
* @returns The converted numeric value, or null/undefined when input is null/undefined.
|
|
12
|
+
* @throws When required context is missing (viewport, lineHeight, percentReference) or percentReference is 0 for % conversion.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* convertCssUnit('16px', 'rem') // 1
|
|
17
|
+
* convertCssUnit('1rem', 'px') // 16
|
|
18
|
+
* convertCssUnit('50%', 'px', { percentReference: 200 }) // 100
|
|
19
|
+
* convertCssUnit('10vw', 'px', { viewportWidth: 375 }) // 37.5
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
declare function convertCssUnit(value: number | string | null | undefined, toUnit: CssLengthUnit, options?: ConvertCssUnitOptions | undefined): number | null | undefined;
|
|
23
|
+
//#endregion
|
|
24
|
+
export { convertCssUnit };
|
|
25
|
+
//# sourceMappingURL=convert-css-unit.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-css-unit.d.mts","names":[],"sources":["../../src/units/convert-css-unit.ts"],"sourcesContent":[],"mappings":";;;;;;AAkCA;;;;;;;;;;;;;;;iBAAgB,cAAA,oDAEP,yBACE"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { getRemToPxScale } from "./get-rem-to-px-scale.mjs";
|
|
2
|
+
import { parseCssValue } from "./parse-css-value.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/units/convert-css-unit.ts
|
|
5
|
+
const PX_PER_IN = 96;
|
|
6
|
+
const PT_PER_IN = 72;
|
|
7
|
+
const PC_PER_IN = 6;
|
|
8
|
+
const CM_PER_IN = 2.54;
|
|
9
|
+
const MM_PER_IN = 25.4;
|
|
10
|
+
const DEFAULT_ELEMENT_FONT_SIZE = 16;
|
|
11
|
+
const DEFAULT_PRECISION = 4;
|
|
12
|
+
const ABSOLUTE_UNITS = [
|
|
13
|
+
"px",
|
|
14
|
+
"pt",
|
|
15
|
+
"pc",
|
|
16
|
+
"in",
|
|
17
|
+
"cm",
|
|
18
|
+
"mm"
|
|
19
|
+
];
|
|
20
|
+
const LINE_UNITS = ["lh", "rlh"];
|
|
21
|
+
/**
|
|
22
|
+
* Converts a CSS length value from one unit to another.
|
|
23
|
+
*
|
|
24
|
+
* @param value - The value to convert. Can be a number or string (e.g. '16px', '1.5rem'). Pass-through for null/undefined.
|
|
25
|
+
* @param toUnit - The target unit.
|
|
26
|
+
* @param options - Conversion context. When omitted, uses browser auto-detect for rootFontSize and viewport when available.
|
|
27
|
+
* @returns The converted numeric value, or null/undefined when input is null/undefined.
|
|
28
|
+
* @throws When required context is missing (viewport, lineHeight, percentReference) or percentReference is 0 for % conversion.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* convertCssUnit('16px', 'rem') // 1
|
|
33
|
+
* convertCssUnit('1rem', 'px') // 16
|
|
34
|
+
* convertCssUnit('50%', 'px', { percentReference: 200 }) // 100
|
|
35
|
+
* convertCssUnit('10vw', 'px', { viewportWidth: 375 }) // 37.5
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
function convertCssUnit(value, toUnit, options) {
|
|
39
|
+
const [num, parsedUnit] = parseCssValue(value);
|
|
40
|
+
if (num === null || num === void 0) return num;
|
|
41
|
+
if (Number.isNaN(num)) throw new Error(`Invalid CSS value: ${value}`);
|
|
42
|
+
const fromUnit = options?.fromUnit ?? normalizeUnit(parsedUnit) ?? "px";
|
|
43
|
+
const resolved = resolveOptions(options);
|
|
44
|
+
if (fromUnit === toUnit) return Number(num.toFixed(resolved.precision));
|
|
45
|
+
let result;
|
|
46
|
+
if (fromUnit === "rem" && toUnit === "em") result = remToEmDirect(num, resolved);
|
|
47
|
+
else if (fromUnit === "em" && toUnit === "rem") result = emToRemDirect(num, resolved);
|
|
48
|
+
else result = pxToValue(valueToPx(num, fromUnit, resolved), toUnit, resolved);
|
|
49
|
+
return Number(result.toFixed(resolved.precision));
|
|
50
|
+
}
|
|
51
|
+
function normalizeUnit(unit) {
|
|
52
|
+
if (!unit) return void 0;
|
|
53
|
+
const u = unit.toLowerCase();
|
|
54
|
+
if (u === "px" || u === "pt" || u === "pc" || u === "in" || u === "cm" || u === "mm" || u === "rem" || u === "em" || u === "vw" || u === "vh" || u === "vmin" || u === "vmax" || u === "lh" || u === "rlh" || u === "ch" || u === "%") return u;
|
|
55
|
+
}
|
|
56
|
+
function resolveOptions(options) {
|
|
57
|
+
const rootFontSize = options?.rootFontSize ?? getRemToPxScale();
|
|
58
|
+
const elementFontSize = options?.elementFontSize ?? DEFAULT_ELEMENT_FONT_SIZE;
|
|
59
|
+
const precision = options?.precision ?? DEFAULT_PRECISION;
|
|
60
|
+
let viewportWidth = options?.viewportWidth;
|
|
61
|
+
let viewportHeight = options?.viewportHeight;
|
|
62
|
+
if (typeof window !== "undefined") {
|
|
63
|
+
viewportWidth ??= window.innerWidth;
|
|
64
|
+
viewportHeight ??= window.innerHeight;
|
|
65
|
+
}
|
|
66
|
+
const lineHeight = options?.lineHeight;
|
|
67
|
+
const chWidth = options?.chWidth ?? elementFontSize * .5;
|
|
68
|
+
const percentReference = options?.percentReference ?? 0;
|
|
69
|
+
return {
|
|
70
|
+
rootFontSize,
|
|
71
|
+
elementFontSize,
|
|
72
|
+
viewportWidth: viewportWidth ?? 0,
|
|
73
|
+
viewportHeight: viewportHeight ?? 0,
|
|
74
|
+
lineHeight: lineHeight ?? 0,
|
|
75
|
+
chWidth,
|
|
76
|
+
percentReference,
|
|
77
|
+
precision
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function remToEmDirect(value, resolved) {
|
|
81
|
+
return value * (resolved.rootFontSize / resolved.elementFontSize);
|
|
82
|
+
}
|
|
83
|
+
function emToRemDirect(value, resolved) {
|
|
84
|
+
return value * (resolved.elementFontSize / resolved.rootFontSize);
|
|
85
|
+
}
|
|
86
|
+
function valueToPx(value, fromUnit, resolved) {
|
|
87
|
+
if (ABSOLUTE_UNITS.includes(fromUnit)) return toPxFromAbsolute(value, fromUnit);
|
|
88
|
+
if (fromUnit === "rem") return value * (resolved.rootFontSize ?? 0);
|
|
89
|
+
if (fromUnit === "em") return value * (resolved.elementFontSize ?? 0);
|
|
90
|
+
if (fromUnit === "vw") {
|
|
91
|
+
if (resolved.viewportWidth === 0) throw new Error("viewportWidth is required for vw conversion");
|
|
92
|
+
return value / 100 * resolved.viewportWidth;
|
|
93
|
+
}
|
|
94
|
+
if (fromUnit === "vh") {
|
|
95
|
+
if (resolved.viewportHeight === 0) throw new Error("viewportHeight is required for vh conversion");
|
|
96
|
+
return value / 100 * resolved.viewportHeight;
|
|
97
|
+
}
|
|
98
|
+
if (fromUnit === "vmin") {
|
|
99
|
+
if (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) throw new Error("viewportWidth and viewportHeight are required for vmin conversion");
|
|
100
|
+
return value / 100 * Math.min(resolved.viewportWidth, resolved.viewportHeight);
|
|
101
|
+
}
|
|
102
|
+
if (fromUnit === "vmax") {
|
|
103
|
+
if (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) throw new Error("viewportWidth and viewportHeight are required for vmax conversion");
|
|
104
|
+
return value / 100 * Math.max(resolved.viewportWidth, resolved.viewportHeight);
|
|
105
|
+
}
|
|
106
|
+
if (LINE_UNITS.includes(fromUnit)) {
|
|
107
|
+
if (resolved.lineHeight === 0) throw new Error("lineHeight is required for lh/rlh conversion");
|
|
108
|
+
return value * resolved.lineHeight;
|
|
109
|
+
}
|
|
110
|
+
if (fromUnit === "ch") return value * resolved.chWidth;
|
|
111
|
+
if (fromUnit === "%") {
|
|
112
|
+
if (resolved.percentReference === 0) throw new Error("percentReference is required for % conversion");
|
|
113
|
+
return value / 100 * resolved.percentReference;
|
|
114
|
+
}
|
|
115
|
+
throw new Error(`Unsupported unit: ${fromUnit}`);
|
|
116
|
+
}
|
|
117
|
+
function pxToValue(px, toUnit, resolved) {
|
|
118
|
+
if (ABSOLUTE_UNITS.includes(toUnit)) return fromPxToAbsolute(px, toUnit);
|
|
119
|
+
if (toUnit === "rem") return px / resolved.rootFontSize;
|
|
120
|
+
if (toUnit === "em") return px / resolved.elementFontSize;
|
|
121
|
+
if (toUnit === "vw") {
|
|
122
|
+
if (resolved.viewportWidth === 0) throw new Error("viewportWidth is required for vw conversion");
|
|
123
|
+
return px / resolved.viewportWidth * 100;
|
|
124
|
+
}
|
|
125
|
+
if (toUnit === "vh") {
|
|
126
|
+
if (resolved.viewportHeight === 0) throw new Error("viewportHeight is required for vh conversion");
|
|
127
|
+
return px / resolved.viewportHeight * 100;
|
|
128
|
+
}
|
|
129
|
+
if (toUnit === "vmin") {
|
|
130
|
+
if (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) throw new Error("viewportWidth and viewportHeight are required for vmin conversion");
|
|
131
|
+
return px / Math.min(resolved.viewportWidth, resolved.viewportHeight) * 100;
|
|
132
|
+
}
|
|
133
|
+
if (toUnit === "vmax") {
|
|
134
|
+
if (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) throw new Error("viewportWidth and viewportHeight are required for vmax conversion");
|
|
135
|
+
return px / Math.max(resolved.viewportWidth, resolved.viewportHeight) * 100;
|
|
136
|
+
}
|
|
137
|
+
if (LINE_UNITS.includes(toUnit)) {
|
|
138
|
+
if (resolved.lineHeight === 0) throw new Error("lineHeight is required for lh/rlh conversion");
|
|
139
|
+
return px / resolved.lineHeight;
|
|
140
|
+
}
|
|
141
|
+
if (toUnit === "ch") return px / resolved.chWidth;
|
|
142
|
+
if (toUnit === "%") {
|
|
143
|
+
if (resolved.percentReference === 0) throw new Error("percentReference is required and must be non-zero for conversion to %");
|
|
144
|
+
return px / resolved.percentReference * 100;
|
|
145
|
+
}
|
|
146
|
+
throw new Error(`Unsupported unit: ${toUnit}`);
|
|
147
|
+
}
|
|
148
|
+
function toPxFromAbsolute(value, unit) {
|
|
149
|
+
switch (unit) {
|
|
150
|
+
case "px": return value;
|
|
151
|
+
case "pt": return value * PX_PER_IN / PT_PER_IN;
|
|
152
|
+
case "pc": return value * PX_PER_IN / PC_PER_IN;
|
|
153
|
+
case "in": return value * PX_PER_IN;
|
|
154
|
+
case "cm": return value * PX_PER_IN / CM_PER_IN;
|
|
155
|
+
case "mm": return value * PX_PER_IN / MM_PER_IN;
|
|
156
|
+
default: return value;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function fromPxToAbsolute(px, unit) {
|
|
160
|
+
switch (unit) {
|
|
161
|
+
case "px": return px;
|
|
162
|
+
case "pt": return px * PT_PER_IN / PX_PER_IN;
|
|
163
|
+
case "pc": return px * PC_PER_IN / PX_PER_IN;
|
|
164
|
+
case "in": return px / PX_PER_IN;
|
|
165
|
+
case "cm": return px * CM_PER_IN / PX_PER_IN;
|
|
166
|
+
case "mm": return px * MM_PER_IN / PX_PER_IN;
|
|
167
|
+
default: return px;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
//#endregion
|
|
172
|
+
export { convertCssUnit };
|
|
173
|
+
//# sourceMappingURL=convert-css-unit.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert-css-unit.mjs","names":["ABSOLUTE_UNITS: CssLengthUnit[]","LINE_UNITS: CssLengthUnit[]","fromUnit: CssLengthUnit","result: number"],"sources":["../../src/units/convert-css-unit.ts"],"sourcesContent":["import type { Required } from 'type-plus'\nimport type { ConvertCssUnitOptions, CssLengthUnit } from './css-unit-converter.types.ts'\nimport { getRemToPxScale } from './get-rem-to-px-scale.ts'\nimport { parseCssValue } from './parse-css-value.ts'\n\nconst PX_PER_IN = 96\nconst PT_PER_IN = 72\nconst PC_PER_IN = 6\nconst CM_PER_IN = 2.54\nconst MM_PER_IN = 25.4\n\nconst DEFAULT_ELEMENT_FONT_SIZE = 16\nconst DEFAULT_PRECISION = 4\n\nconst ABSOLUTE_UNITS: CssLengthUnit[] = ['px', 'pt', 'pc', 'in', 'cm', 'mm']\nconst LINE_UNITS: CssLengthUnit[] = ['lh', 'rlh']\n\n/**\n * Converts a CSS length value from one unit to another.\n *\n * @param value - The value to convert. Can be a number or string (e.g. '16px', '1.5rem'). Pass-through for null/undefined.\n * @param toUnit - The target unit.\n * @param options - Conversion context. When omitted, uses browser auto-detect for rootFontSize and viewport when available.\n * @returns The converted numeric value, or null/undefined when input is null/undefined.\n * @throws When required context is missing (viewport, lineHeight, percentReference) or percentReference is 0 for % conversion.\n *\n * @example\n * ```ts\n * convertCssUnit('16px', 'rem') // 1\n * convertCssUnit('1rem', 'px') // 16\n * convertCssUnit('50%', 'px', { percentReference: 200 }) // 100\n * convertCssUnit('10vw', 'px', { viewportWidth: 375 }) // 37.5\n * ```\n */\nexport function convertCssUnit(\n\tvalue: number | string | null | undefined,\n\ttoUnit: CssLengthUnit,\n\toptions?: ConvertCssUnitOptions | undefined\n): number | null | undefined {\n\tconst [num, parsedUnit] = parseCssValue(value)\n\tif (num === null || num === undefined) return num\n\tif (Number.isNaN(num)) {\n\t\tthrow new Error(`Invalid CSS value: ${value}`)\n\t}\n\n\tconst fromUnit: CssLengthUnit = options?.fromUnit ?? normalizeUnit(parsedUnit) ?? 'px'\n\n\tconst resolved = resolveOptions(options)\n\n\tif (fromUnit === toUnit) {\n\t\treturn Number(num.toFixed(resolved.precision))\n\t}\n\n\tlet result: number\n\n\tif (fromUnit === 'rem' && toUnit === 'em') {\n\t\tresult = remToEmDirect(num, resolved)\n\t} else if (fromUnit === 'em' && toUnit === 'rem') {\n\t\tresult = emToRemDirect(num, resolved)\n\t} else {\n\t\tconst px = valueToPx(num, fromUnit, resolved)\n\t\tresult = pxToValue(px, toUnit, resolved)\n\t}\n\n\treturn Number(result.toFixed(resolved.precision))\n}\n\nfunction normalizeUnit(unit: string | undefined): CssLengthUnit | undefined {\n\tif (!unit) return undefined\n\tconst u = unit.toLowerCase()\n\tif (\n\t\tu === 'px' ||\n\t\tu === 'pt' ||\n\t\tu === 'pc' ||\n\t\tu === 'in' ||\n\t\tu === 'cm' ||\n\t\tu === 'mm' ||\n\t\tu === 'rem' ||\n\t\tu === 'em' ||\n\t\tu === 'vw' ||\n\t\tu === 'vh' ||\n\t\tu === 'vmin' ||\n\t\tu === 'vmax' ||\n\t\tu === 'lh' ||\n\t\tu === 'rlh' ||\n\t\tu === 'ch' ||\n\t\tu === '%'\n\t) {\n\t\treturn u as CssLengthUnit\n\t}\n\treturn undefined\n}\n\nfunction resolveOptions(\n\toptions?: ConvertCssUnitOptions | undefined\n): Required<\n\tPick<\n\t\tConvertCssUnitOptions,\n\t\t| 'rootFontSize'\n\t\t| 'elementFontSize'\n\t\t| 'viewportWidth'\n\t\t| 'viewportHeight'\n\t\t| 'lineHeight'\n\t\t| 'chWidth'\n\t\t| 'percentReference'\n\t\t| 'precision'\n\t>\n> {\n\tconst rootFontSize = options?.rootFontSize ?? getRemToPxScale()\n\tconst elementFontSize = options?.elementFontSize ?? DEFAULT_ELEMENT_FONT_SIZE\n\tconst precision = options?.precision ?? DEFAULT_PRECISION\n\n\tlet viewportWidth = options?.viewportWidth\n\tlet viewportHeight = options?.viewportHeight\n\tif (typeof window !== 'undefined') {\n\t\tviewportWidth ??= window.innerWidth\n\t\tviewportHeight ??= window.innerHeight\n\t}\n\n\tconst lineHeight = options?.lineHeight\n\tconst chWidth = options?.chWidth ?? elementFontSize * 0.5\n\tconst percentReference = options?.percentReference ?? 0\n\n\treturn {\n\t\trootFontSize,\n\t\telementFontSize,\n\t\tviewportWidth: viewportWidth ?? 0,\n\t\tviewportHeight: viewportHeight ?? 0,\n\t\tlineHeight: lineHeight ?? 0,\n\t\tchWidth,\n\t\tpercentReference,\n\t\tprecision\n\t}\n}\n\nfunction remToEmDirect(value: number, resolved: ReturnType<typeof resolveOptions>): number {\n\treturn value * (resolved.rootFontSize / resolved.elementFontSize)\n}\n\nfunction emToRemDirect(value: number, resolved: ReturnType<typeof resolveOptions>): number {\n\treturn value * (resolved.elementFontSize / resolved.rootFontSize)\n}\n\nfunction valueToPx(\n\tvalue: number,\n\tfromUnit: CssLengthUnit,\n\tresolved: ReturnType<typeof resolveOptions>\n): number {\n\tif (ABSOLUTE_UNITS.includes(fromUnit)) {\n\t\treturn toPxFromAbsolute(value, fromUnit)\n\t}\n\tif (fromUnit === 'rem') {\n\t\treturn value * (resolved.rootFontSize ?? 0)\n\t}\n\tif (fromUnit === 'em') {\n\t\treturn value * (resolved.elementFontSize ?? 0)\n\t}\n\tif (fromUnit === 'vw') {\n\t\tif (resolved.viewportWidth === 0) {\n\t\t\tthrow new Error('viewportWidth is required for vw conversion')\n\t\t}\n\t\treturn (value / 100) * resolved.viewportWidth\n\t}\n\tif (fromUnit === 'vh') {\n\t\tif (resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportHeight is required for vh conversion')\n\t\t}\n\t\treturn (value / 100) * resolved.viewportHeight\n\t}\n\tif (fromUnit === 'vmin') {\n\t\tif (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportWidth and viewportHeight are required for vmin conversion')\n\t\t}\n\t\treturn (value / 100) * Math.min(resolved.viewportWidth, resolved.viewportHeight)\n\t}\n\tif (fromUnit === 'vmax') {\n\t\tif (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportWidth and viewportHeight are required for vmax conversion')\n\t\t}\n\t\treturn (value / 100) * Math.max(resolved.viewportWidth, resolved.viewportHeight)\n\t}\n\tif (LINE_UNITS.includes(fromUnit)) {\n\t\tif (resolved.lineHeight === 0) {\n\t\t\tthrow new Error('lineHeight is required for lh/rlh conversion')\n\t\t}\n\t\treturn value * resolved.lineHeight\n\t}\n\tif (fromUnit === 'ch') {\n\t\treturn value * resolved.chWidth\n\t}\n\tif (fromUnit === '%') {\n\t\tif (resolved.percentReference === 0) {\n\t\t\tthrow new Error('percentReference is required for % conversion')\n\t\t}\n\t\treturn (value / 100) * resolved.percentReference\n\t}\n\tthrow new Error(`Unsupported unit: ${fromUnit}`)\n}\n\nfunction pxToValue(\n\tpx: number,\n\ttoUnit: CssLengthUnit,\n\tresolved: ReturnType<typeof resolveOptions>\n): number {\n\tif (ABSOLUTE_UNITS.includes(toUnit)) {\n\t\treturn fromPxToAbsolute(px, toUnit)\n\t}\n\tif (toUnit === 'rem') {\n\t\treturn px / resolved.rootFontSize\n\t}\n\tif (toUnit === 'em') {\n\t\treturn px / resolved.elementFontSize\n\t}\n\tif (toUnit === 'vw') {\n\t\tif (resolved.viewportWidth === 0) {\n\t\t\tthrow new Error('viewportWidth is required for vw conversion')\n\t\t}\n\t\treturn (px / resolved.viewportWidth) * 100\n\t}\n\tif (toUnit === 'vh') {\n\t\tif (resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportHeight is required for vh conversion')\n\t\t}\n\t\treturn (px / resolved.viewportHeight) * 100\n\t}\n\tif (toUnit === 'vmin') {\n\t\tif (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportWidth and viewportHeight are required for vmin conversion')\n\t\t}\n\t\treturn (px / Math.min(resolved.viewportWidth, resolved.viewportHeight)) * 100\n\t}\n\tif (toUnit === 'vmax') {\n\t\tif (resolved.viewportWidth === 0 || resolved.viewportHeight === 0) {\n\t\t\tthrow new Error('viewportWidth and viewportHeight are required for vmax conversion')\n\t\t}\n\t\treturn (px / Math.max(resolved.viewportWidth, resolved.viewportHeight)) * 100\n\t}\n\tif (LINE_UNITS.includes(toUnit)) {\n\t\tif (resolved.lineHeight === 0) {\n\t\t\tthrow new Error('lineHeight is required for lh/rlh conversion')\n\t\t}\n\t\treturn px / resolved.lineHeight\n\t}\n\tif (toUnit === 'ch') {\n\t\treturn px / resolved.chWidth\n\t}\n\tif (toUnit === '%') {\n\t\tif (resolved.percentReference === 0) {\n\t\t\tthrow new Error('percentReference is required and must be non-zero for conversion to %')\n\t\t}\n\t\treturn (px / resolved.percentReference) * 100\n\t}\n\tthrow new Error(`Unsupported unit: ${toUnit}`)\n}\n\nfunction toPxFromAbsolute(value: number, unit: CssLengthUnit): number {\n\tswitch (unit) {\n\t\tcase 'px':\n\t\t\treturn value\n\t\tcase 'pt':\n\t\t\treturn (value * PX_PER_IN) / PT_PER_IN\n\t\tcase 'pc':\n\t\t\treturn (value * PX_PER_IN) / PC_PER_IN\n\t\tcase 'in':\n\t\t\treturn value * PX_PER_IN\n\t\tcase 'cm':\n\t\t\treturn (value * PX_PER_IN) / CM_PER_IN\n\t\tcase 'mm':\n\t\t\treturn (value * PX_PER_IN) / MM_PER_IN\n\t\tdefault:\n\t\t\treturn value\n\t}\n}\n\nfunction fromPxToAbsolute(px: number, unit: CssLengthUnit): number {\n\tswitch (unit) {\n\t\tcase 'px':\n\t\t\treturn px\n\t\tcase 'pt':\n\t\t\treturn (px * PT_PER_IN) / PX_PER_IN\n\t\tcase 'pc':\n\t\t\treturn (px * PC_PER_IN) / PX_PER_IN\n\t\tcase 'in':\n\t\t\treturn px / PX_PER_IN\n\t\tcase 'cm':\n\t\t\treturn (px * CM_PER_IN) / PX_PER_IN\n\t\tcase 'mm':\n\t\t\treturn (px * MM_PER_IN) / PX_PER_IN\n\t\tdefault:\n\t\t\treturn px\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const require_convert_css_unit = require('./convert-css-unit.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/units/create-css-unit-converter.ts
|
|
4
|
+
/**
|
|
5
|
+
* Creates a pre-configured CSS unit converter with fixed context.
|
|
6
|
+
*
|
|
7
|
+
* @param context - Root font size, viewport, line height, etc. Omitted values use browser auto-detect when available.
|
|
8
|
+
* @returns A converter function that accepts value and toUnit (and optional fromUnit override).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const convert = createCssUnitConverter({
|
|
13
|
+
* rootFontSize: 16,
|
|
14
|
+
* viewportWidth: 375,
|
|
15
|
+
* viewportHeight: 812,
|
|
16
|
+
* })
|
|
17
|
+
* convert('1rem', 'px') // 16
|
|
18
|
+
* convert('10vw', 'px') // 37.5
|
|
19
|
+
* convert(16, 'rem', { fromUnit: 'px' }) // 1
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
function createCssUnitConverter(context) {
|
|
23
|
+
return function convert(value, toUnit, options) {
|
|
24
|
+
return require_convert_css_unit.convertCssUnit(value, toUnit, {
|
|
25
|
+
...context,
|
|
26
|
+
...options
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
exports.createCssUnitConverter = createCssUnitConverter;
|
|
33
|
+
//# sourceMappingURL=create-css-unit-converter.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-css-unit-converter.cjs","names":["convertCssUnit"],"sources":["../../src/units/create-css-unit-converter.ts"],"sourcesContent":["import { convertCssUnit } from './convert-css-unit.ts'\nimport type { CssLengthUnit, CssUnitConverterContext } from './css-unit-converter.types.ts'\n\n/**\n * Creates a pre-configured CSS unit converter with fixed context.\n *\n * @param context - Root font size, viewport, line height, etc. Omitted values use browser auto-detect when available.\n * @returns A converter function that accepts value and toUnit (and optional fromUnit override).\n *\n * @example\n * ```ts\n * const convert = createCssUnitConverter({\n * rootFontSize: 16,\n * viewportWidth: 375,\n * viewportHeight: 812,\n * })\n * convert('1rem', 'px') // 16\n * convert('10vw', 'px') // 37.5\n * convert(16, 'rem', { fromUnit: 'px' }) // 1\n * ```\n */\nexport function createCssUnitConverter(context?: CssUnitConverterContext) {\n\treturn function convert(\n\t\tvalue: number | string,\n\t\ttoUnit: CssLengthUnit,\n\t\toptions?: { fromUnit?: CssLengthUnit | undefined } | undefined\n\t): number | null | undefined {\n\t\treturn convertCssUnit(value, toUnit, { ...context, ...options })\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,uBAAuB,SAAmC;AACzE,QAAO,SAAS,QACf,OACA,QACA,SAC4B;AAC5B,SAAOA,wCAAe,OAAO,QAAQ;GAAE,GAAG;GAAS,GAAG;GAAS,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { CssLengthUnit, CssUnitConverterContext } from "./css-unit-converter.types.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/units/create-css-unit-converter.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a pre-configured CSS unit converter with fixed context.
|
|
7
|
+
*
|
|
8
|
+
* @param context - Root font size, viewport, line height, etc. Omitted values use browser auto-detect when available.
|
|
9
|
+
* @returns A converter function that accepts value and toUnit (and optional fromUnit override).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const convert = createCssUnitConverter({
|
|
14
|
+
* rootFontSize: 16,
|
|
15
|
+
* viewportWidth: 375,
|
|
16
|
+
* viewportHeight: 812,
|
|
17
|
+
* })
|
|
18
|
+
* convert('1rem', 'px') // 16
|
|
19
|
+
* convert('10vw', 'px') // 37.5
|
|
20
|
+
* convert(16, 'rem', { fromUnit: 'px' }) // 1
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare function createCssUnitConverter(context?: CssUnitConverterContext): (value: number | string, toUnit: CssLengthUnit, options?: {
|
|
24
|
+
fromUnit?: CssLengthUnit | undefined;
|
|
25
|
+
} | undefined) => number | null | undefined;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { createCssUnitConverter };
|
|
28
|
+
//# sourceMappingURL=create-css-unit-converter.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-css-unit-converter.d.cts","names":[],"sources":["../../src/units/create-css-unit-converter.ts"],"sourcesContent":[],"mappings":";;;;;;AAqBA;;;;;;;;;;;;;;;;iBAAgB,sBAAA,WAAiC,2DAGvC;aACe"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { CssLengthUnit, CssUnitConverterContext } from "./css-unit-converter.types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/units/create-css-unit-converter.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a pre-configured CSS unit converter with fixed context.
|
|
7
|
+
*
|
|
8
|
+
* @param context - Root font size, viewport, line height, etc. Omitted values use browser auto-detect when available.
|
|
9
|
+
* @returns A converter function that accepts value and toUnit (and optional fromUnit override).
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const convert = createCssUnitConverter({
|
|
14
|
+
* rootFontSize: 16,
|
|
15
|
+
* viewportWidth: 375,
|
|
16
|
+
* viewportHeight: 812,
|
|
17
|
+
* })
|
|
18
|
+
* convert('1rem', 'px') // 16
|
|
19
|
+
* convert('10vw', 'px') // 37.5
|
|
20
|
+
* convert(16, 'rem', { fromUnit: 'px' }) // 1
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare function createCssUnitConverter(context?: CssUnitConverterContext): (value: number | string, toUnit: CssLengthUnit, options?: {
|
|
24
|
+
fromUnit?: CssLengthUnit | undefined;
|
|
25
|
+
} | undefined) => number | null | undefined;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { createCssUnitConverter };
|
|
28
|
+
//# sourceMappingURL=create-css-unit-converter.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-css-unit-converter.d.mts","names":[],"sources":["../../src/units/create-css-unit-converter.ts"],"sourcesContent":[],"mappings":";;;;;;AAqBA;;;;;;;;;;;;;;;;iBAAgB,sBAAA,WAAiC,2DAGvC;aACe"}
|