@chipmobilesdk/rn-i18n 0.1.2 → 0.1.3

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.
@@ -1,151 +1,141 @@
1
- import type {
2
- InvalidFormatPolicy,
3
- UnitDimension,
4
- UnitId,
5
- } from '../config/types';
6
- import { applyInvalidFormatPolicy } from './invalid';
7
- import { formatNumberValue } from './number';
8
-
9
- interface UnitDefinition {
10
- dimension: UnitDimension;
11
- /** Factor to the dimension's base unit; unused for temperature. */
12
- factor: number;
13
- symbol: string;
14
- }
15
-
16
- /**
17
- * Package-owned unit registry and conversion tables. Intl.NumberFormat unit
18
- * style is not consistently available under Hermes, so the numeric part is
19
- * formatted through Intl and the unit symbol is appended from this registry
20
- * (research R4). Base units: meter, kilogram, liter, celsius.
21
- */
22
- const UNIT_REGISTRY: Record<UnitId, UnitDefinition> = {
23
- millimeter: { dimension: 'length', factor: 0.001, symbol: 'mm' },
24
- centimeter: { dimension: 'length', factor: 0.01, symbol: 'cm' },
25
- meter: { dimension: 'length', factor: 1, symbol: 'm' },
26
- kilometer: { dimension: 'length', factor: 1000, symbol: 'km' },
27
- inch: { dimension: 'length', factor: 0.0254, symbol: 'in' },
28
- foot: { dimension: 'length', factor: 0.3048, symbol: 'ft' },
29
- mile: { dimension: 'length', factor: 1609.344, symbol: 'mi' },
30
- gram: { dimension: 'mass', factor: 0.001, symbol: 'g' },
31
- kilogram: { dimension: 'mass', factor: 1, symbol: 'kg' },
32
- ounce: { dimension: 'mass', factor: 0.028349523125, symbol: 'oz' },
33
- pound: { dimension: 'mass', factor: 0.45359237, symbol: 'lb' },
34
- milliliter: { dimension: 'volume', factor: 0.001, symbol: 'ml' },
35
- liter: { dimension: 'volume', factor: 1, symbol: 'l' },
36
- gallon: { dimension: 'volume', factor: 3.785411784, symbol: 'gal' },
37
- celsius: { dimension: 'temperature', factor: 1, symbol: '°C' },
38
- fahrenheit: { dimension: 'temperature', factor: 1, symbol: '°F' },
39
- kelvin: { dimension: 'temperature', factor: 1, symbol: 'K' },
40
- };
41
-
42
- export const SUPPORTED_UNITS = Object.keys(UNIT_REGISTRY) as readonly UnitId[];
43
-
44
- export const KNOWN_UNIT_IDS: ReadonlySet<string> = new Set(SUPPORTED_UNITS);
45
-
46
- export class UnitConversionError extends Error {
47
- constructor(message: string) {
48
- super(message);
49
- this.name = 'UnitConversionError';
50
- }
51
- }
52
-
53
- export function getUnitSymbol(unit: UnitId): string {
54
- return UNIT_REGISTRY[unit].symbol;
55
- }
56
-
57
- function toCelsius(value: number, from: UnitId): number {
58
- switch (from) {
59
- case 'fahrenheit':
60
- return ((value - 32) * 5) / 9;
61
- case 'kelvin':
62
- return value - 273.15;
63
- default:
64
- return value;
65
- }
66
- }
67
-
68
- function fromCelsius(value: number, to: UnitId): number {
69
- switch (to) {
70
- case 'fahrenheit':
71
- return (value * 9) / 5 + 32;
72
- case 'kelvin':
73
- return value + 273.15;
74
- default:
75
- return value;
76
- }
77
- }
78
-
79
- /**
80
- * Converts between compatible supported units. Unknown units or conversions
81
- * across dimensions throw a UnitConversionError (FR-044/FR-045).
82
- */
83
- export function convertUnitValue(
84
- value: number,
85
- from: UnitId,
86
- to: UnitId,
87
- ): number {
88
- const fromDef = UNIT_REGISTRY[from];
89
- const toDef = UNIT_REGISTRY[to];
90
- if (!fromDef || !toDef) {
91
- throw new UnitConversionError(
92
- `Unknown unit in conversion "${from}" -> "${to}".`,
93
- );
94
- }
95
- if (fromDef.dimension !== toDef.dimension) {
96
- throw new UnitConversionError(
97
- `Cannot convert between incompatible dimensions "${fromDef.dimension}" (${from}) and "${toDef.dimension}" (${to}).`,
98
- );
99
- }
100
- if (!Number.isFinite(value)) {
101
- throw new UnitConversionError(
102
- `Cannot convert invalid value "${String(value)}" from "${from}" to "${to}".`,
103
- );
104
- }
105
- if (from === to) {
106
- return value;
107
- }
108
- if (fromDef.dimension === 'temperature') {
109
- return fromCelsius(toCelsius(value, from), to);
110
- }
111
- return (value * fromDef.factor) / toDef.factor;
112
- }
113
-
114
- export interface UnitFormatOptions extends Intl.NumberFormatOptions {
115
- /** Unit the value is expressed in. Default: the locale's default unit. */
116
- from?: UnitId;
117
- /** Unit to display. Default: `from` (no conversion). */
118
- to?: UnitId;
119
- }
120
-
121
- /**
122
- * Converts (when requested) and formats a measurement value: locale-aware
123
- * numeric part via Intl.NumberFormat plus the package-owned unit symbol.
124
- */
125
- export function formatUnitValue(
126
- value: number,
127
- localeCode: string,
128
- localeDefaultUnit: UnitId,
129
- numberDefaults: Intl.NumberFormatOptions,
130
- options: UnitFormatOptions | undefined,
131
- invalidFormat: InvalidFormatPolicy,
132
- ): string {
133
- const { from = localeDefaultUnit, to = from, ...numberOptions } = options ?? {};
134
- let converted: number;
135
- try {
136
- converted = convertUnitValue(value, from, to);
137
- } catch (error) {
138
- return applyInvalidFormatPolicy(
139
- invalidFormat,
140
- error instanceof Error ? error.message : String(error),
141
- );
142
- }
143
- const formatted = formatNumberValue(
144
- converted,
145
- localeCode,
146
- numberDefaults,
147
- numberOptions,
148
- invalidFormat,
149
- );
150
- return `${formatted} ${getUnitSymbol(to)}`;
151
- }
1
+ import type { InvalidFormatPolicy, UnitDimension, UnitId } from '../config/types';
2
+ import { applyInvalidFormatPolicy } from './invalid';
3
+ import { formatNumberValue } from './number';
4
+
5
+ interface UnitDefinition {
6
+ dimension: UnitDimension;
7
+ /** Factor to the dimension's base unit; unused for temperature. */
8
+ factor: number;
9
+ symbol: string;
10
+ }
11
+
12
+ /**
13
+ * Package-owned unit registry and conversion tables. Intl.NumberFormat unit
14
+ * style is not consistently available under Hermes, so the numeric part is
15
+ * formatted through Intl and the unit symbol is appended from this registry
16
+ * (research R4). Base units: meter, kilogram, liter, celsius.
17
+ */
18
+ const UNIT_REGISTRY: Record<UnitId, UnitDefinition> = {
19
+ millimeter: { dimension: 'length', factor: 0.001, symbol: 'mm' },
20
+ centimeter: { dimension: 'length', factor: 0.01, symbol: 'cm' },
21
+ meter: { dimension: 'length', factor: 1, symbol: 'm' },
22
+ kilometer: { dimension: 'length', factor: 1000, symbol: 'km' },
23
+ inch: { dimension: 'length', factor: 0.0254, symbol: 'in' },
24
+ foot: { dimension: 'length', factor: 0.3048, symbol: 'ft' },
25
+ mile: { dimension: 'length', factor: 1609.344, symbol: 'mi' },
26
+ gram: { dimension: 'mass', factor: 0.001, symbol: 'g' },
27
+ kilogram: { dimension: 'mass', factor: 1, symbol: 'kg' },
28
+ ounce: { dimension: 'mass', factor: 0.028349523125, symbol: 'oz' },
29
+ pound: { dimension: 'mass', factor: 0.45359237, symbol: 'lb' },
30
+ milliliter: { dimension: 'volume', factor: 0.001, symbol: 'ml' },
31
+ liter: { dimension: 'volume', factor: 1, symbol: 'l' },
32
+ gallon: { dimension: 'volume', factor: 3.785411784, symbol: 'gal' },
33
+ celsius: { dimension: 'temperature', factor: 1, symbol: '°C' },
34
+ fahrenheit: { dimension: 'temperature', factor: 1, symbol: '°F' },
35
+ kelvin: { dimension: 'temperature', factor: 1, symbol: 'K' },
36
+ };
37
+
38
+ export const SUPPORTED_UNITS = Object.keys(UNIT_REGISTRY) as readonly UnitId[];
39
+
40
+ export const KNOWN_UNIT_IDS: ReadonlySet<string> = new Set(SUPPORTED_UNITS);
41
+
42
+ export class UnitConversionError extends Error {
43
+ constructor(message: string) {
44
+ super(message);
45
+ this.name = 'UnitConversionError';
46
+ }
47
+ }
48
+
49
+ export function getUnitSymbol(unit: UnitId): string {
50
+ return UNIT_REGISTRY[unit].symbol;
51
+ }
52
+
53
+ function toCelsius(value: number, from: UnitId): number {
54
+ switch (from) {
55
+ case 'fahrenheit':
56
+ return ((value - 32) * 5) / 9;
57
+ case 'kelvin':
58
+ return value - 273.15;
59
+ default:
60
+ return value;
61
+ }
62
+ }
63
+
64
+ function fromCelsius(value: number, to: UnitId): number {
65
+ switch (to) {
66
+ case 'fahrenheit':
67
+ return (value * 9) / 5 + 32;
68
+ case 'kelvin':
69
+ return value + 273.15;
70
+ default:
71
+ return value;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Converts between compatible supported units. Unknown units or conversions
77
+ * across dimensions throw a UnitConversionError (FR-044/FR-045).
78
+ */
79
+ export function convertUnitValue(value: number, from: UnitId, to: UnitId): number {
80
+ const fromDef = UNIT_REGISTRY[from];
81
+ const toDef = UNIT_REGISTRY[to];
82
+ if (!fromDef || !toDef) {
83
+ throw new UnitConversionError(`Unknown unit in conversion "${from}" -> "${to}".`);
84
+ }
85
+ if (fromDef.dimension !== toDef.dimension) {
86
+ throw new UnitConversionError(
87
+ `Cannot convert between incompatible dimensions "${fromDef.dimension}" (${from}) and "${toDef.dimension}" (${to}).`,
88
+ );
89
+ }
90
+ if (!Number.isFinite(value)) {
91
+ throw new UnitConversionError(
92
+ `Cannot convert invalid value "${String(value)}" from "${from}" to "${to}".`,
93
+ );
94
+ }
95
+ if (from === to) {
96
+ return value;
97
+ }
98
+ if (fromDef.dimension === 'temperature') {
99
+ return fromCelsius(toCelsius(value, from), to);
100
+ }
101
+ return (value * fromDef.factor) / toDef.factor;
102
+ }
103
+
104
+ export interface UnitFormatOptions extends Intl.NumberFormatOptions {
105
+ /** Unit the value is expressed in. Default: the locale's default unit. */
106
+ from?: UnitId;
107
+ /** Unit to display. Default: `from` (no conversion). */
108
+ to?: UnitId;
109
+ }
110
+
111
+ /**
112
+ * Converts (when requested) and formats a measurement value: locale-aware
113
+ * numeric part via Intl.NumberFormat plus the package-owned unit symbol.
114
+ */
115
+ export function formatUnitValue(
116
+ value: number,
117
+ localeCode: string,
118
+ localeDefaultUnit: UnitId,
119
+ numberDefaults: Intl.NumberFormatOptions,
120
+ options: UnitFormatOptions | undefined,
121
+ invalidFormat: InvalidFormatPolicy,
122
+ ): string {
123
+ const { from = localeDefaultUnit, to = from, ...numberOptions } = options ?? {};
124
+ let converted: number;
125
+ try {
126
+ converted = convertUnitValue(value, from, to);
127
+ } catch (error) {
128
+ return applyInvalidFormatPolicy(
129
+ invalidFormat,
130
+ error instanceof Error ? error.message : String(error),
131
+ );
132
+ }
133
+ const formatted = formatNumberValue(
134
+ converted,
135
+ localeCode,
136
+ numberDefaults,
137
+ numberOptions,
138
+ invalidFormat,
139
+ );
140
+ return `${formatted} ${getUnitSymbol(to)}`;
141
+ }