Skip to content

packages/core/src/lib/style/resolve-length.ts

Read as Markdown

This is the source snapshot used to build these API details. View this revision on GitHub.

Back to reference

1 import {
2   layoutDiagnostic,
3   type LayoutDiagnosticContext,
4 } from './diagnostics.js';
5 import type { Length } from './types.js';
6 
7 const DECIMAL_PERCENTAGE = /^[+-]?(?:\d+(?:\.\d+)?|\.\d+)%$/;
8 
9 /**
10  * Resolves a numeric or percentage length; automatic sizing returns undefined.
11  *
12  * @param value - Logical length or percentage to resolve. See {@link Length}.
13  * @param reference - Reference length for percentages, or undefined if unavailable.
14  * @param property - Property name used in diagnostics.
15  * @param context - Component and property context for diagnostic messages. See
16  * {@link LayoutDiagnosticContext} .
17  * @returns The resolved logical length, or undefined for an unresolved automatic length.
18  *
19  * @see {@link Length}
20  * @see {@link LayoutDiagnosticContext}
21  */
22 export function resolveLength(
23   value: Length,
24   reference: number | undefined,
25   property: string,
26   context: Readonly<LayoutDiagnosticContext> = {},
27 ): number | undefined {
28   if (value === 'auto') return undefined;
29 
30   if (typeof value === 'number') {
31     if (!Number.isFinite(value)) {
32       throw diagnostic(property, value, 'must be a finite number', context);
33     }
34     return value;
35   }
36 
37   if (typeof value !== 'string' || !DECIMAL_PERCENTAGE.test(value)) {
38     throw diagnostic(
39       property,
40       value,
41       `uses an unsupported length value ${String(value)}`,
42       context,
43     );
44   }
45 
46   if (reference === undefined || !Number.isFinite(reference)) {
47     throw diagnostic(
48       property,
49       value,
50       'requires a definite finite percentage reference',
51       context,
52     );
53   }
54   if (reference < 0) {
55     throw diagnostic(
56       property,
57       value,
58       'percentage reference must be nonnegative',
59       context,
60     );
61   }
62 
63   const resolved = (Number.parseFloat(value) / 100) * reference;
64   if (!Number.isFinite(resolved)) {
65     throw diagnostic(
66       property,
67       value,
68       'resolved percentage arithmetic must remain finite',
69       context,
70     );
71   }
72   return resolved;
73 }
74 
75 function diagnostic(
76   property: string,
77   value: unknown,
78   reason: string,
79   context: Readonly<LayoutDiagnosticContext>,
80 ) {
81   return layoutDiagnostic({ ...context, property, value, reason });
82 }
83 

Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.