@secundus-studio/stift-format 0.0.0-stage → 0.4.31

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/CHANGELOG.md ADDED
@@ -0,0 +1,56 @@
1
+ # @secundus-studio/stift-format
2
+
3
+ ## 0.4.31
4
+
5
+ ### Patch Changes
6
+
7
+ - @secundus-studio/stift-core@0.4.31
8
+
9
+ ## 0.4.2
10
+
11
+ ### Patch Changes
12
+
13
+ - Republish 0.4.1 as 0.4.2 with installable tarballs: the 0.4.1 artifacts carried literal `workspace:*` dependency ranges and could not be installed by any package manager. No code changes.
14
+ - Updated dependencies
15
+ - @secundus-studio/stift-core@0.4.2
16
+
17
+ ## 0.4.1
18
+
19
+ ### Patch Changes
20
+
21
+ - Updated dependencies [ec4a6c1]
22
+ - @secundus-studio/stift-core@0.4.1
23
+
24
+ ## 0.4.0
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [d60faf6]
29
+ - @secundus-studio/stift-core@0.4.0
30
+
31
+ ## 0.3.0
32
+
33
+ ### Minor Changes
34
+
35
+ - 71e677d: Rename the library from l10n to Stift. Packages move to `@secundus-studio/stift-*`, the config file is `stift.config.ts`, the CLI is `stift`, and the API follows (`createStift`, `Stift`, `StiftProvider`, `StiftConfig`, `virtual:stift/runtime`). BREAKING (pre-1.0): update imports, the config filename, and pack tooling; old `.dat` packs (I18NKIT magic) are rejected by the new decoder and re-fetched, and renamed storage keys, cookie names, and devtools routes start fresh.
36
+
37
+ ### Patch Changes
38
+
39
+ - Updated dependencies [71e677d]
40
+ - @secundus-studio/stift-core@0.3.0
41
+
42
+ ## 0.2.0
43
+
44
+ ### Patch Changes
45
+
46
+ - Updated dependencies [13824b6]
47
+ - Updated dependencies [1770b34]
48
+ - @secundus-studio/l10n-core@0.2.0
49
+
50
+ ## 0.1.0
51
+
52
+ ### Patch Changes
53
+
54
+ - Updated dependencies [275184d]
55
+ - Updated dependencies [275184d]
56
+ - @secundus-studio/l10n-core@0.1.0
package/LICENSE ADDED
@@ -0,0 +1,41 @@
1
+ Copyright (c) 2026 Ali Alkhateeb. All rights reserved.
2
+
3
+ SECUNDUS L10N — PROPRIETARY LICENSE
4
+
5
+ The compiled software packages distributed under the @secundus-studio scope on
6
+ the public npm registry (the "Software") are proprietary to Ali Alkhateeb. They
7
+ are licensed, not sold.
8
+
9
+ 1. Grant. Subject to this license, Ali Alkhateeb grants you a non-exclusive,
10
+ non-transferable, royalty-free right to install and use the Software, in
11
+ object-code form, as a dependency of your own applications, including
12
+ commercial and closed-source applications.
13
+
14
+ 2. Restrictions. You may not:
15
+ (a) copy, publish, distribute, sublicense, or sell the Software, or make
16
+ it available to any third party, except as embedded in your own
17
+ application;
18
+ (b) modify, translate, reverse engineer, decompile, or disassemble the
19
+ Software, or attempt to derive its source code;
20
+ (c) remove or alter any copyright, license, or proprietary notices.
21
+
22
+ 3. No source code. This license grants no rights to the source code of the
23
+ Software. The source is confidential, is not distributed, and remains the
24
+ property of Ali Alkhateeb.
25
+
26
+ 4. Contributions. Any feedback, bug report, or suggestion you provide may be
27
+ used by Ali Alkhateeb without restriction or obligation.
28
+
29
+ 5. Termination. This license terminates automatically if you breach any of its
30
+ terms. On termination you must stop using the Software and delete all
31
+ copies in your possession or control.
32
+
33
+ 6. Disclaimer. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
34
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
35
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
36
+ NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
37
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
38
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
39
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
40
+
41
+ For licensing inquiries, contact hello@secundus.studio.
package/README.md CHANGED
@@ -1,3 +1,44 @@
1
- # Temporary Holding Version
1
+ # @secundus-studio/stift-format
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Tree-shakable `Intl` formatting helpers: numbers, currency, dates, lists, and units. No state, no React.
4
+
5
+ ## What it is
6
+
7
+ The optional formatting companion to `@secundus-studio/stift-core`. Core owns messages (ICU select/plural in translations, locale state, detection); this package adds standalone, locale-aware formatting functions for everything around the message: currency amounts, dates and relative times, list joining, and unit conversion plus rendering. Every function takes `{ locale }` explicitly (pass the active locale to stay in sync), each module is standalone, and the package ships side-effect-free so bundlers drop what you don't import. Currency, unit, calendar, timezone, and numbering-system arguments are narrowed to your registered config sets when the typegen augmentation is present.
8
+
9
+ ```bash
10
+ pnpm add @secundus-studio/stift-format
11
+ ```
12
+
13
+ ## Quick start
14
+
15
+ ```ts
16
+ import { formatCurrency, formatDate, formatList, formatUnit } from '@secundus-studio/stift-format'
17
+
18
+ formatCurrency(9.99, 'EUR', { locale: 'en' }) // "€9.99"
19
+ formatDate(new Date(), { locale: 'en', dateStyle: 'medium' }) // e.g. "Oct 9, 2026"
20
+ formatList(['apples', 'bread', 'cheese'], { locale: 'en' }) // "apples, bread, and cheese"
21
+ formatUnit(12000, { locale: 'en', unit: 'kilometer' }) // "12 km"
22
+ ```
23
+
24
+ ## API
25
+
26
+ - `formatNumber(value, options)` — locale-aware number via `Intl.NumberFormat`.
27
+ - `formatCurrency(value, currency, options)` — currency amount (`currency` second, style forced to `currency`).
28
+ - `formatPercent(value, options)` — percent (e.g. `0.42` → `"42%"`).
29
+ - `pluralCategory(value, locale)` — CLDR plural category (`"one"`/`"few"`/…) via `Intl.PluralRules`.
30
+ - `formatDate(value, options)` / `formatTime(value, options)` / `formatDateTime(value, options)` — `Date | number | string` via `Intl.DateTimeFormat`; options pass through calendar, timezone, and numbering system.
31
+ - `formatRelativeTime(value, unit, options)` — `"2 days ago"` via `Intl.RelativeTimeFormat`.
32
+ - `formatList(list, options)` — localized joining (`"a, b, and c"`) via `Intl.ListFormat`.
33
+ - `formatUnit(value, options)` — localized quantity; `value` is in the category base unit, target `unit` rides in options; falls back to a plain number (never throws) when the engine lacks the unit.
34
+ - `convertUnit(value, from, to)` — pure base-aware conversion between named units.
35
+ - `fromBase(value, unit)` / `toBase(value, unit)` — the two halves of a conversion, for custom pipelines.
36
+ - `isEngineSupportedUnit(unit)` — whether the running engine can format `unit` (guards `formatUnit`).
37
+ - `NumberFormatOptions`, `DateTimeFormatOptions`, `ListFormatOptions`, `UnitNumberFormatOptions` — option types (type-only).
38
+
39
+ ## Docs
40
+
41
+ - Formatting reference — https://stift.secundus.studio/docs/latest/vanilla/api/format
42
+ - Units (vanilla) — https://stift.secundus.studio/docs/latest/vanilla/units
43
+ - Units (React) — https://stift.secundus.studio/docs/latest/react/units
44
+ - `useFormatter` hook (wraps these functions) — https://stift.secundus.studio/docs/latest/react/api/use-formatter
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ 'use strict';var F=Object.defineProperty;var o=(t,e)=>F(t,"name",{value:e,configurable:true});function c(t,e,r){let n=r?{...r}:{};return e&&(n.numberingSystem=e),new Intl.NumberFormat(t,n)}o(c,"number");function T(t,e){let{locale:r,numberingSystem:n,...i}=e;return c(r,n,i).format(t)}o(T,"formatNumber");function O(t,e,r){let{locale:n,numberingSystem:i,...a}=r;return c(n,i,{style:"currency",currency:e,...a}).format(t)}o(O,"formatCurrency");function S(t,e){let{locale:r,numberingSystem:n,...i}=e;return c(r,n,{style:"percent",...i}).format(t)}o(S,"formatPercent");function D(t,e){return new Intl.PluralRules(e).select(t)}o(D,"pluralCategory");function f(t){let{locale:e,numberingSystem:r,timeZone:n,calendar:i,...a}=t,m={...a};for(let s of Object.keys(m))m[s]===void 0&&delete m[s];return r&&(m.numberingSystem=r),n&&(m.timeZone=n),i&&(m.calendar=i),new Intl.DateTimeFormat(e,m)}o(f,"dateTime");function l(t){return t instanceof Date?t:typeof t=="number"?new Date(t):new Date(t)}o(l,"toDate");function I(t,e){return f(e).format(l(t))}o(I,"formatDate");function N(t,e){let r={...e,...e.timeStyle==null?{timeStyle:"short"}:{}};return f(r).format(l(t))}o(N,"formatTime");function x(t,e){let r={...e,dateStyle:e.dateStyle??"medium",timeStyle:e.timeStyle??"short"};return f(r).format(l(t))}o(x,"formatDateTime");function R(t,e,r){let{locale:n,numeric:i,style:a}=r;return new Intl.RelativeTimeFormat(n,{...i?{numeric:i}:{},...a?{style:a}:{}}).format(t,e)}o(R,"formatRelativeTime");function L(t,e){let{locale:r,type:n,style:i}=e;return new Intl.ListFormat(r,{...n?{type:n}:{},...i?{style:i}:{}}).format(Array.from(t))}o(L,"formatList");var p={millimeter:.001,centimeter:.01,meter:1,kilometer:1e3,inch:.0254,foot:.3048,yard:.9144,mile:1609.344,"mile-scandinavian":1e4,gram:.001,kilogram:1,ounce:.028349523125,pound:.45359237,stone:6.35029318,acre:.40468564224,hectare:1,celsius:1,bit:.125,byte:1,kilobit:125,kilobyte:1e3,megabit:125e3,megabyte:1e6,gigabit:125e6,gigabyte:1e9,terabit:125e9,terabyte:1e12,petabyte:1e15};function g(t,e){if(e==="fahrenheit")return t*(9/5)+32;let r=p[e];return r!==void 0?t/r:t}o(g,"fromBase");function d(t,e){if(e==="fahrenheit")return (t-32)*(5/9);let r=p[e];return r!==void 0?t*r:t}o(d,"toBase");function h(t,e,r){return e===r?t:g(d(t,e),r)}o(h,"convertUnit");var w=new Set([...Object.keys(p),"fahrenheit"]),b=(()=>{if(!(typeof Intl>"u"||typeof Intl.supportedValuesOf!="function"))try{return new Set(Intl.supportedValuesOf("unit"))}catch{return}})();function y(t){return b?b.has(t):w.has(t)}o(y,"isEngineSupportedUnit");function U(t,e){let{locale:r,numberingSystem:n,unit:i,unitDisplay:a,...m}=e;if(!i)return new Intl.NumberFormat(r,{...m,...n?{numberingSystem:n}:{}}).format(t);let s=g(t,i),u={...m,...n?{numberingSystem:n}:{}};return y(i)&&(u.style="unit",u.unit=i,a&&(u.unitDisplay=a)),new Intl.NumberFormat(r,u).format(s)}o(U,"formatUnit");exports.convertUnit=h;exports.formatCurrency=O;exports.formatDate=I;exports.formatDateTime=x;exports.formatList=L;exports.formatNumber=T;exports.formatPercent=S;exports.formatRelativeTime=R;exports.formatTime=N;exports.formatUnit=U;exports.fromBase=g;exports.isEngineSupportedUnit=y;exports.pluralCategory=D;exports.toBase=d;
@@ -0,0 +1,112 @@
1
+ import { LocaleTag, RegisteredNumberingSystems, RegisteredCurrencies, RegisteredCalendars, RegisteredTimezones, RegisteredUnit } from '@secundus-studio/stift-core';
2
+
3
+ /**
4
+ * Numeric formatting helpers (docs/04-execution-plan.md Phase 3). Each is a
5
+ * thin, tree-shakable wrapper over `Intl.NumberFormat` with locale +
6
+ * numbering-system (and unit/currency) pass-through.
7
+ */
8
+ interface NumberFormatOptions extends Intl.NumberFormatOptions {
9
+ /** BCP 47 locale tag of the active locale. */
10
+ locale: LocaleTag;
11
+ /** Override the numbering system (e.g. "arab", "latn") — narrowed to the
12
+ * app's registered set when the typegen augmentation is present. */
13
+ numberingSystem?: RegisteredNumberingSystems;
14
+ }
15
+
16
+ /** Format a number using the locale's CLDR rules. */
17
+ declare function formatNumber(value: number, options: NumberFormatOptions): string;
18
+ /** Format a currency amount. */
19
+ declare function formatCurrency(value: number, currency: RegisteredCurrencies, options: NumberFormatOptions): string;
20
+ /** Format a percent value (e.g. 0.42 -> "42%"). */
21
+ declare function formatPercent(value: number, options: NumberFormatOptions): string;
22
+ /** Get the CLDR plural category for a value ("one"/"few"/"many"/…). */
23
+ declare function pluralCategory(value: number, locale: LocaleTag): string;
24
+
25
+ /**
26
+ * Date / time formatting helpers (docs/04-execution-plan.md Phase 3), thin
27
+ * `Intl.DateTimeFormat` wrappers with locale + timezone + numbering-system
28
+ * pass-through.
29
+ */
30
+ interface DateTimeFormatOptions extends Intl.DateTimeFormatOptions {
31
+ /** BCP 47 locale tag of the active locale. */
32
+ locale: LocaleTag;
33
+ /** Override the numeric value's numbering system — narrowed to the app's
34
+ * registered set when the typegen augmentation is present. */
35
+ numberingSystem?: RegisteredNumberingSystems;
36
+ /** Calendar to format in (e.g. "gregory", "islamic") — narrowed to the
37
+ * app's registered set when the typegen augmentation is present. */
38
+ calendar?: RegisteredCalendars;
39
+ /** IANA time zone identifier, e.g. "Asia/Damascus". */
40
+ timeZone?: RegisteredTimezones;
41
+ }
42
+
43
+ /** Format a date (uses `dateStyle`/`year`… from options). */
44
+ declare function formatDate(value: Date | number | string, options: DateTimeFormatOptions): string;
45
+ /** Format a time-of-day value. */
46
+ declare function formatTime(value: Date | number | string, options: DateTimeFormatOptions): string;
47
+ /** Format a full date+time. */
48
+ declare function formatDateTime(value: Date | number | string, options: DateTimeFormatOptions): string;
49
+ /** Relative time via `Intl.RelativeTimeFormat` ("2 days ago"). */
50
+ declare function formatRelativeTime(value: number, unit: Intl.RelativeTimeFormatUnit, options: {
51
+ locale: LocaleTag;
52
+ numeric?: Intl.RelativeTimeFormatNumeric;
53
+ style?: Intl.RelativeTimeFormatStyle;
54
+ }): string;
55
+
56
+ /**
57
+ * List formatting (docs/04-execution-plan.md Phase 3) — `Intl.ListFormat`
58
+ * wrapper, locale-aware conjunction/disjunction.
59
+ */
60
+ interface ListFormatOptions {
61
+ locale: LocaleTag;
62
+ type?: Intl.ListFormatType;
63
+ style?: Intl.ListFormatStyle;
64
+ }
65
+
66
+ /** Join a list of strings localized ("a, b, and c"). */
67
+ declare function formatList(list: Iterable<string>, options: ListFormatOptions): string;
68
+
69
+ /**
70
+ * Unit formatting helpers (docs/17-units.md). Tree-shakable, standalone —
71
+ * the sole dependency is `@secundus-studio/stift-core`'s types.
72
+ *
73
+ * Value contract: every `formatUnit`/`convertUnit` argument is expressed in
74
+ * the category's canonical base unit (length→meter, mass→kilogram,
75
+ * area→hectare, temperature→celsius, digital→byte). The helpers convert to
76
+ * the active `unit` and format with `Intl.NumberFormat`.
77
+ *
78
+ * Engine guard: the catalog is the ECMA-402-sanctioned set (stable across
79
+ * conforming engines), but an end-user engine may still lack a unit. When the
80
+ * active unit isn't supported by the running engine, `formatUnit` degrades to
81
+ * a plain number instead of throwing — the fallback is never a crash.
82
+ */
83
+
84
+ interface UnitNumberFormatOptions extends Intl.NumberFormatOptions {
85
+ /** BCP 47 locale tag of the active locale. */
86
+ locale: LocaleTag;
87
+ /** Override the numbering system (e.g. "arab", "latn") — narrowed to the
88
+ * app's registered set when the typegen augmentation is present. */
89
+ numberingSystem?: RegisteredNumberingSystems;
90
+ /** The active unit — the category's current unit (docs/17). */
91
+ unit?: RegisteredUnit;
92
+ /** How the unit is displayed. */
93
+ unitDisplay?: 'long' | 'short' | 'narrow';
94
+ }
95
+ /** Convert a value from its base unit into a target unit. */
96
+ declare function fromBase(value: number, unit: string): number;
97
+ /** Convert a value from a target unit into its base unit. */
98
+ declare function toBase(value: number, unit: string): number;
99
+ /** Convert `value` expressed in `from` to `to` (base-aware; both units must
100
+ * share a base, or math is undefined). Identity for equal units. */
101
+ declare function convertUnit(value: number, from: string, to: string): number;
102
+ /** Whether the running engine can format `unit` (guards `formatUnit`). */
103
+ declare function isEngineSupportedUnit(unit: string): boolean;
104
+ /**
105
+ * Format `value` (expressed in the category base unit of `unit`) as a
106
+ * localized quantity, e.g. `formatUnit(12000, { locale: 'en', unit: 'kilometer' })`
107
+ * → "12 km". Falls back to a plain localized number when the engine lacks the
108
+ * unit.
109
+ */
110
+ declare function formatUnit(value: number, options: UnitNumberFormatOptions): string;
111
+
112
+ export { type DateTimeFormatOptions, type ListFormatOptions, type NumberFormatOptions, type UnitNumberFormatOptions, convertUnit, formatCurrency, formatDate, formatDateTime, formatList, formatNumber, formatPercent, formatRelativeTime, formatTime, formatUnit, fromBase, isEngineSupportedUnit, pluralCategory, toBase };
@@ -0,0 +1,112 @@
1
+ import { LocaleTag, RegisteredNumberingSystems, RegisteredCurrencies, RegisteredCalendars, RegisteredTimezones, RegisteredUnit } from '@secundus-studio/stift-core';
2
+
3
+ /**
4
+ * Numeric formatting helpers (docs/04-execution-plan.md Phase 3). Each is a
5
+ * thin, tree-shakable wrapper over `Intl.NumberFormat` with locale +
6
+ * numbering-system (and unit/currency) pass-through.
7
+ */
8
+ interface NumberFormatOptions extends Intl.NumberFormatOptions {
9
+ /** BCP 47 locale tag of the active locale. */
10
+ locale: LocaleTag;
11
+ /** Override the numbering system (e.g. "arab", "latn") — narrowed to the
12
+ * app's registered set when the typegen augmentation is present. */
13
+ numberingSystem?: RegisteredNumberingSystems;
14
+ }
15
+
16
+ /** Format a number using the locale's CLDR rules. */
17
+ declare function formatNumber(value: number, options: NumberFormatOptions): string;
18
+ /** Format a currency amount. */
19
+ declare function formatCurrency(value: number, currency: RegisteredCurrencies, options: NumberFormatOptions): string;
20
+ /** Format a percent value (e.g. 0.42 -> "42%"). */
21
+ declare function formatPercent(value: number, options: NumberFormatOptions): string;
22
+ /** Get the CLDR plural category for a value ("one"/"few"/"many"/…). */
23
+ declare function pluralCategory(value: number, locale: LocaleTag): string;
24
+
25
+ /**
26
+ * Date / time formatting helpers (docs/04-execution-plan.md Phase 3), thin
27
+ * `Intl.DateTimeFormat` wrappers with locale + timezone + numbering-system
28
+ * pass-through.
29
+ */
30
+ interface DateTimeFormatOptions extends Intl.DateTimeFormatOptions {
31
+ /** BCP 47 locale tag of the active locale. */
32
+ locale: LocaleTag;
33
+ /** Override the numeric value's numbering system — narrowed to the app's
34
+ * registered set when the typegen augmentation is present. */
35
+ numberingSystem?: RegisteredNumberingSystems;
36
+ /** Calendar to format in (e.g. "gregory", "islamic") — narrowed to the
37
+ * app's registered set when the typegen augmentation is present. */
38
+ calendar?: RegisteredCalendars;
39
+ /** IANA time zone identifier, e.g. "Asia/Damascus". */
40
+ timeZone?: RegisteredTimezones;
41
+ }
42
+
43
+ /** Format a date (uses `dateStyle`/`year`… from options). */
44
+ declare function formatDate(value: Date | number | string, options: DateTimeFormatOptions): string;
45
+ /** Format a time-of-day value. */
46
+ declare function formatTime(value: Date | number | string, options: DateTimeFormatOptions): string;
47
+ /** Format a full date+time. */
48
+ declare function formatDateTime(value: Date | number | string, options: DateTimeFormatOptions): string;
49
+ /** Relative time via `Intl.RelativeTimeFormat` ("2 days ago"). */
50
+ declare function formatRelativeTime(value: number, unit: Intl.RelativeTimeFormatUnit, options: {
51
+ locale: LocaleTag;
52
+ numeric?: Intl.RelativeTimeFormatNumeric;
53
+ style?: Intl.RelativeTimeFormatStyle;
54
+ }): string;
55
+
56
+ /**
57
+ * List formatting (docs/04-execution-plan.md Phase 3) — `Intl.ListFormat`
58
+ * wrapper, locale-aware conjunction/disjunction.
59
+ */
60
+ interface ListFormatOptions {
61
+ locale: LocaleTag;
62
+ type?: Intl.ListFormatType;
63
+ style?: Intl.ListFormatStyle;
64
+ }
65
+
66
+ /** Join a list of strings localized ("a, b, and c"). */
67
+ declare function formatList(list: Iterable<string>, options: ListFormatOptions): string;
68
+
69
+ /**
70
+ * Unit formatting helpers (docs/17-units.md). Tree-shakable, standalone —
71
+ * the sole dependency is `@secundus-studio/stift-core`'s types.
72
+ *
73
+ * Value contract: every `formatUnit`/`convertUnit` argument is expressed in
74
+ * the category's canonical base unit (length→meter, mass→kilogram,
75
+ * area→hectare, temperature→celsius, digital→byte). The helpers convert to
76
+ * the active `unit` and format with `Intl.NumberFormat`.
77
+ *
78
+ * Engine guard: the catalog is the ECMA-402-sanctioned set (stable across
79
+ * conforming engines), but an end-user engine may still lack a unit. When the
80
+ * active unit isn't supported by the running engine, `formatUnit` degrades to
81
+ * a plain number instead of throwing — the fallback is never a crash.
82
+ */
83
+
84
+ interface UnitNumberFormatOptions extends Intl.NumberFormatOptions {
85
+ /** BCP 47 locale tag of the active locale. */
86
+ locale: LocaleTag;
87
+ /** Override the numbering system (e.g. "arab", "latn") — narrowed to the
88
+ * app's registered set when the typegen augmentation is present. */
89
+ numberingSystem?: RegisteredNumberingSystems;
90
+ /** The active unit — the category's current unit (docs/17). */
91
+ unit?: RegisteredUnit;
92
+ /** How the unit is displayed. */
93
+ unitDisplay?: 'long' | 'short' | 'narrow';
94
+ }
95
+ /** Convert a value from its base unit into a target unit. */
96
+ declare function fromBase(value: number, unit: string): number;
97
+ /** Convert a value from a target unit into its base unit. */
98
+ declare function toBase(value: number, unit: string): number;
99
+ /** Convert `value` expressed in `from` to `to` (base-aware; both units must
100
+ * share a base, or math is undefined). Identity for equal units. */
101
+ declare function convertUnit(value: number, from: string, to: string): number;
102
+ /** Whether the running engine can format `unit` (guards `formatUnit`). */
103
+ declare function isEngineSupportedUnit(unit: string): boolean;
104
+ /**
105
+ * Format `value` (expressed in the category base unit of `unit`) as a
106
+ * localized quantity, e.g. `formatUnit(12000, { locale: 'en', unit: 'kilometer' })`
107
+ * → "12 km". Falls back to a plain localized number when the engine lacks the
108
+ * unit.
109
+ */
110
+ declare function formatUnit(value: number, options: UnitNumberFormatOptions): string;
111
+
112
+ export { type DateTimeFormatOptions, type ListFormatOptions, type NumberFormatOptions, type UnitNumberFormatOptions, convertUnit, formatCurrency, formatDate, formatDateTime, formatList, formatNumber, formatPercent, formatRelativeTime, formatTime, formatUnit, fromBase, isEngineSupportedUnit, pluralCategory, toBase };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ var F=Object.defineProperty;var o=(t,e)=>F(t,"name",{value:e,configurable:true});function c(t,e,r){let n=r?{...r}:{};return e&&(n.numberingSystem=e),new Intl.NumberFormat(t,n)}o(c,"number");function T(t,e){let{locale:r,numberingSystem:n,...i}=e;return c(r,n,i).format(t)}o(T,"formatNumber");function O(t,e,r){let{locale:n,numberingSystem:i,...a}=r;return c(n,i,{style:"currency",currency:e,...a}).format(t)}o(O,"formatCurrency");function S(t,e){let{locale:r,numberingSystem:n,...i}=e;return c(r,n,{style:"percent",...i}).format(t)}o(S,"formatPercent");function D(t,e){return new Intl.PluralRules(e).select(t)}o(D,"pluralCategory");function f(t){let{locale:e,numberingSystem:r,timeZone:n,calendar:i,...a}=t,m={...a};for(let s of Object.keys(m))m[s]===void 0&&delete m[s];return r&&(m.numberingSystem=r),n&&(m.timeZone=n),i&&(m.calendar=i),new Intl.DateTimeFormat(e,m)}o(f,"dateTime");function l(t){return t instanceof Date?t:typeof t=="number"?new Date(t):new Date(t)}o(l,"toDate");function I(t,e){return f(e).format(l(t))}o(I,"formatDate");function N(t,e){let r={...e,...e.timeStyle==null?{timeStyle:"short"}:{}};return f(r).format(l(t))}o(N,"formatTime");function x(t,e){let r={...e,dateStyle:e.dateStyle??"medium",timeStyle:e.timeStyle??"short"};return f(r).format(l(t))}o(x,"formatDateTime");function R(t,e,r){let{locale:n,numeric:i,style:a}=r;return new Intl.RelativeTimeFormat(n,{...i?{numeric:i}:{},...a?{style:a}:{}}).format(t,e)}o(R,"formatRelativeTime");function L(t,e){let{locale:r,type:n,style:i}=e;return new Intl.ListFormat(r,{...n?{type:n}:{},...i?{style:i}:{}}).format(Array.from(t))}o(L,"formatList");var p={millimeter:.001,centimeter:.01,meter:1,kilometer:1e3,inch:.0254,foot:.3048,yard:.9144,mile:1609.344,"mile-scandinavian":1e4,gram:.001,kilogram:1,ounce:.028349523125,pound:.45359237,stone:6.35029318,acre:.40468564224,hectare:1,celsius:1,bit:.125,byte:1,kilobit:125,kilobyte:1e3,megabit:125e3,megabyte:1e6,gigabit:125e6,gigabyte:1e9,terabit:125e9,terabyte:1e12,petabyte:1e15};function g(t,e){if(e==="fahrenheit")return t*(9/5)+32;let r=p[e];return r!==void 0?t/r:t}o(g,"fromBase");function d(t,e){if(e==="fahrenheit")return (t-32)*(5/9);let r=p[e];return r!==void 0?t*r:t}o(d,"toBase");function h(t,e,r){return e===r?t:g(d(t,e),r)}o(h,"convertUnit");var w=new Set([...Object.keys(p),"fahrenheit"]),b=(()=>{if(!(typeof Intl>"u"||typeof Intl.supportedValuesOf!="function"))try{return new Set(Intl.supportedValuesOf("unit"))}catch{return}})();function y(t){return b?b.has(t):w.has(t)}o(y,"isEngineSupportedUnit");function U(t,e){let{locale:r,numberingSystem:n,unit:i,unitDisplay:a,...m}=e;if(!i)return new Intl.NumberFormat(r,{...m,...n?{numberingSystem:n}:{}}).format(t);let s=g(t,i),u={...m,...n?{numberingSystem:n}:{}};return y(i)&&(u.style="unit",u.unit=i,a&&(u.unitDisplay=a)),new Intl.NumberFormat(r,u).format(s)}o(U,"formatUnit");export{h as convertUnit,O as formatCurrency,I as formatDate,x as formatDateTime,L as formatList,T as formatNumber,S as formatPercent,R as formatRelativeTime,N as formatTime,U as formatUnit,g as fromBase,y as isEngineSupportedUnit,D as pluralCategory,d as toBase};
package/package.json CHANGED
@@ -1,6 +1,54 @@
1
1
  {
2
2
  "name": "@secundus-studio/stift-format",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.4.31",
4
+ "license": "SEE LICENSE IN LICENSE",
5
+ "description": "Optional tree-shakable formatting: currency, units, ordinals, collation, calendars, segmentation, rich text, input parsing.",
6
+ "keywords": [
7
+ "stift",
8
+ "format",
9
+ "tanstack-intent"
10
+ ],
11
+ "sideEffects": false,
12
+ "type": "module",
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
16
+ "main": "./dist/index.cjs",
17
+ "module": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "import": {
22
+ "types": "./dist/index.d.ts",
23
+ "default": "./dist/index.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/index.d.cts",
27
+ "default": "./dist/index.cjs"
28
+ }
29
+ },
30
+ "./package.json": "./package.json"
31
+ },
32
+ "files": [
33
+ "dist",
34
+ "CHANGELOG.md"
35
+ ],
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "dependencies": {
40
+ "@secundus-studio/stift-core": "0.4.31"
41
+ },
42
+ "devDependencies": {
43
+ "tsup": "^8.5.1",
44
+ "typescript": "^5.7.2",
45
+ "vitest": "^4.1.10"
46
+ },
47
+ "homepage": "https://stift.secundus.studio",
48
+ "author": "Ali Alkhateeb",
49
+ "scripts": {
50
+ "build": "tsup",
51
+ "test": "vitest run --passWithNoTests",
52
+ "typecheck": "tsc --noEmit"
53
+ }
6
54
  }