@peter-present/format-number 0.0.11 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,12 +9,32 @@ For detailed documentation, visit: [here](https://blog.peter-present.xyz/format-
9
9
  ## Key Features
10
10
 
11
11
  - **Zero Precision Loss**: Uses string manipulation for rounding and formatting to avoid binary floating-point errors.
12
- - **Robust Input Parsing**: Handles messy strings with currency symbols ($€£¥), commas, underscores, and scientific notation automatically.
12
+ - **Robust Input Parsing**: Centralized parsing handles messy strings with currency symbols ($€£¥), commas, underscores, and scientific notation.
13
13
  - **Advanced Rounding**: 5 strategies (`half`, `up`, `down`, `banker`, `truncate`) with customizable decimal precision.
14
14
  - **Intelligent Notation**: Format small numbers with subscript zeros (e.g., `0.0₃5`) or standard scientific notation.
15
15
  - **Flexible Compacting**: Shorten massive numbers into readable strings like `1.5T` or `20.4B`.
16
16
  - **Fluent Chainable API**: Build complex formatting logic with a clean, readable syntax.
17
17
 
18
+ ## Robust Parsing & Error Handling
19
+
20
+ The library follows a **Single-Gate Parsing** philosophy. High-level entry points (`FN`, `formatNumber`, and `parseNum`) are designed to be robust and will attempt to clean and normalize nearly any "number-like" string.
21
+
22
+ > [!IMPORTANT]
23
+ > **Internal functions** (like `round`, `compact`, `scientific`, etc.) are optimized for performance and **assume valid numeric strings**. Passing completely invalid non-numeric data (e.g., `"abc"`) directly to these utilities may result in fallback values or undefined behavior.
24
+
25
+ For manual parsing with custom error handling, use `parseNum`:
26
+
27
+ ```typescript
28
+ import { parseNum } from '@peter-present/format-number';
29
+
30
+ // Default fallback is '--'
31
+ parseNum('invalid'); // '--'
32
+
33
+ // Custom fallback for your own error boundaries
34
+ parseNum('not-a-number', { fallback: 'NaN' }); // 'NaN'
35
+ parseNum('null', { fallback: '0' }); // '0'
36
+ ```
37
+
18
38
  ## Installation
19
39
 
20
40
  ```shell
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function $(n){return n.replace(/^(-?)0+(?=\d)/,"$1").replace(/(\.\d*?)0+$/,"$1").replace(/\.$/,"")}function d(n){let t=String(n);t=t.trim();let e="";return t.startsWith("-")&&(t=t.slice(1),e="-"),{sign:e,value:$(t)}}const Z={K:3,M:6,B:9,T:12,Q:15};function E(n){if(typeof n=="number"||typeof n=="bigint")return n.toString();const t=String(n??"").trim();if(t==="")return"0";const e=t.match(/^[\s+-]*/),i=((e?e[0]:"").match(/-/g)||[]).length%2===1,s=t.replace(/[$€£¥,_\s]/g,""),c=/^([+-]?\d+)\.0([\u2080-\u2089]+)([0-9]*)$/i,u=s.match(c);if(u){const m=u[1].replace(/^[+-]/,""),j=u[2],D=u[3],R=j.split("").reduce((K,O)=>{const Q=O.charCodeAt(0)-8320;return K+Q},0),w="0".repeat(R)+D;let h=m;return(w!==""||R>0)&&(h+="."+w),h=$(h),(i?"-":"")+(h||"0")}const l=s.match(/[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?[KMBTQ]*/i);if(!l)return"0";let o=l[0].toUpperCase(),P=0;const S=o.match(/[KMBTQ]$/);S&&(P+=Z[S[0]]??0,o=o.slice(0,-1));const y=o.match(/[eE][+-]?\d+$/);if(y&&(P+=parseInt(y[0].slice(1),10),o=o.replace(/[eE][+-]?\d+$/i,"")),o=o.replace(/^[+-]/,""),!/^(?:\d+\.?\d*|\.\d+)$/.test(o))return"0";const[C="0",M=""]=o.split(".");let g=(C.replace(/^0+/,"")||"0")+M;const b=M.length-P;let p;if(b<=0)g+="0".repeat(-b),p=g.replace(/^0+(?=\d)/,"")||"0";else{const m=g.length-b;m<=0?p="0."+"0".repeat(-m)+g:p=g.slice(0,m)+"."+g.slice(m),p=$(p)}return(i?"-":"")+(p||"0")}function F(n){const t=typeof n;if(t=="string"||t=="bigint"||t=="number"){const{sign:e,value:r}=d(n);return{sign:e,value:r}}return n}function a(n){let t="",e=n.length-1,r="1";for(;e>=0;){const i=n[e];let s=Number(i)+(r?1:0);s>=10?(r="1",s-=10):r="",t=s.toString()+t,e--}return{result:r+t,remaining:r}}function I(n,t=0){const[e,r=""]=n.split(".");if(t===0)return r&&Number(r[0])>=5?a(e).result:e;if(t>=r.length)return e+(r?`.${r}`:"");const i=r.slice(0,t),s=r.slice(t);if(Number(s[0])>=5){const c=a(i);return c.remaining?a(e).result:e+"."+c.result}else return e+"."+i}function v(n,t=0){const[e,r=""]=n.split(".");if(t===0)return r?a(e).result:e;if(t>=r.length)return e+"."+r;const i=a(r.slice(0,t));return i.remaining?a(e).result:e+"."+i.result}function x(n,t=0){const[e,r=""]=n.split(".");if(t===0)return e;let i=r.slice(0,t),s=i.length-1;for(;s>=0&&i[s]=="0";)s--;return i=i.slice(0,s+1),e+(i?`.${i}`:"")}function k(n,t=0){const[e,r=""]=n.split(".");if(t===0)return r&&Number(r[0])>=5?Number(e[0])/2==0?e:a(e).result:e;if(t>=r.length)return e+(r?`.${r}`:"");const i=r.slice(0,t),s=r.slice(t);if(s[0]=="5"){if(Number(i[i.length-1])%2==0)return e+"."+i;{const c=a(i);return c.remaining?a(e).result:e+"."+c.result}}else if(Number(s[0])>5){const c=a(i);return c.remaining?a(e).result:e+"."+c.result}else return e+"."+i}function N(n,t={}){const e=t.rounding||"half",r=t.precision||0,{sign:i,value:s}=d(n);switch(e){case"half":return i+I(s,r);case"up":return i==""?v(s,r):"-"+x(s,r);case"down":return i==""?x(s,r):"-"+v(s,r);case"truncate":return i+x(s,r);case"banker":return i+k(s,r)}}const U=["K","M","B","T","Q"];function _(n,t={}){const{sign:e,value:r}=d(n);let[i,s=""]=r.split("."),c=i.length,u=-1;for(;c>3&&u<4;){const o=i.slice(0,c-3);s=i.slice(c-3)+s,i=o,c-=3,u++}const l=`${e}${i}${s.length>0?"."+s:s}`;return{value:t.precision!=null?N(l,t):l,symbol:u>=0?U[u]:""}}function V(n,t={}){const{value:e,symbol:r}=_(n,t);return e+r}function T(n){const{sign:t,value:e}=d(n),[r,i=""]=e.split("."),s=i.match(/^0+/)?.[0]?.length||0,c=s.toString().split("").map(l=>String.fromCharCode(8320+parseInt(l))).join(""),u=i.slice(s);return`${t}${r}.0${c}${u}`}function z(n){const{sign:t,value:e}=d(n);if(e=="0")return{value:"0",exponent:0};const[r,i=""]=e.split(".");if(r!=="0"){const l=r.length-1,o=r[0]+"."+(r.slice(1)+i).replace(/0+$/,"");return{value:`${t}${o}${o.length>1,""}`,exponent:l,sign:"+"}}const s=i.search(/[1-9]/);if(s===-1)return{value:"0",exponent:0};const c=-(s+1),u=i[s]+"."+i.slice(s+1).replace(/0+$/,"");return{value:`${t}${u}`,exponent:c-1,sign:""}}function B(n){const{value:t,exponent:e,sign:r}=z(n);return e!=0?`${t}e${r}${e}`:t}function f(n){return{round:t=>{const e=N(n.value,t);return f({...n,value:e})},compact:t=>{if(n.compactedSymbol)return f(n);const{value:e,symbol:r}=_(n.value,t);return f({...n,compactedSymbol:r,value:e})},notation(t="scientific"){return f({...n,notation:t})},prefix(t){return f({...n,prefix:t})},suffix(t){return f({...n,suffix:t})},toNumber(){let{value:t}=n;const{sign:e,prefix:r,suffix:i,compactedSymbol:s}=n;return n.notation=="scientific"?t=B(t):n.notation=="subscript"&&(t=T(t)),`${r||""}${e}${t}${s||""}${i||""}`},toObject(){return n}}}function A(n){return f(F(n))}exports.FN=A;exports.clearTrailingZero=$;exports.compact=V;exports.parseNum=E;exports.round=N;exports.scientific=B;exports.subscript=T;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const Z=t=>t.replace(/0+$/,""),B=t=>t.replace(/^0+(?!$)/,"");function p(t){return t.replace(/^(-?)0+(?=\d)/,"$1").replace(/(\.\d*?)0+$/,"$1").replace(/\.$/,"")}function z(t,r={}){const{fallback:n="--"}=r;if(typeof t=="number"||typeof t=="bigint")return t.toString();const e=String(t??"").trim();if(!e)return"0";const c=e.match(/^[\s+-]*/),i=(c&&c[0].match(/-/g)||[]).length%2===1,o=e.replace(/[$€£¥,_\s]/g,""),s=o.match(/^([+-]?\d+)\.0([\u2080-\u2089]+)([0-9]*)$/i);if(s){const[,l,K,Q]=s,V=K.split("").reduce((H,L)=>H+(L.charCodeAt(0)-8320),0),E=p(l.replace(/^[+-]/,"")+"."+"0".repeat(V)+Q);return(i?"-":"")+(E||"0")}const a=o.match(/[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?[KMBTQ]*/i);if(!a)return n;let f=a[0].toUpperCase(),b=0;const U=f.slice(-1),S="KMBTQ".indexOf(U);S!==-1&&(b=(S+1)*3,f=f.slice(0,-1));const h=f.match(/[E]([+-]?\d+)$/);if(h&&(b+=parseInt(h[1],10),f=f.slice(0,h.index)),f=f.replace(/^[+-]/,""),!/^(?:\d+\.?\d*|\.\d+)$/.test(f))return"0";const[D="0",F=""]=f.split("."),d=(D.replace(/^0+/,"")||"0")+F,x=F.length-b;let P;if(x<=0)P=(d+"0".repeat(-x)).replace(/^0+(?=\d)/,"")||"0";else{const l=d.length-x;P=l<=0?"0."+"0".repeat(-l)+d:d.slice(0,l)+"."+d.slice(l),P=p(P)}return(i?"-":"")+(P||"0")}function m(t){let r=String(t).trim();const n=r.startsWith("-")?"-":"";n&&(r=r.slice(1));const[e,c=""]=p(r).split(".");return{sign:n,intPart:e,fracPart:c}}const I=t=>t.fracPart?`${t.sign}${t.intPart}.${t.fracPart}`:`${t.sign}${t.intPart}`;function A(t){return typeof t=="object"&&t!==null&&"intPart"in t?t:m(t)}function $(t){if(!t)return{result:"",carry:!0};const n=(BigInt(t)+1n).toString();return n.length>t.length?{result:n.slice(1),carry:!0}:{result:n.padStart(t.length,"0"),carry:!1}}function g({intPart:t}){const{result:r,carry:n}=$(t);return{intPart:n?"1"+r:r,fracPart:""}}function k(t,r=0){const{intPart:n,fracPart:e}=t;if(!e||r>=e.length)return t;if(parseInt(e[r],10)>=5){if(r===0)return g(t);const i=e.slice(0,r),{result:o,carry:s}=$(i);return s?g(t):{intPart:n,fracPart:o}}return{intPart:n,fracPart:e.slice(0,r)}}function M(t,r=0){const{intPart:n,fracPart:e}=t;if(!e||r>=e.length)return t;if(r===0)return g(t);const c=e.slice(0,r),{result:i,carry:o}=$(c);return o?g(t):{intPart:n,fracPart:i}}function y(t,r=0){const{intPart:n,fracPart:e}=t;if(!e||r>=e.length)return t;const c=e.slice(0,r);return{intPart:n,fracPart:c.replace(/0+$/,"")}}function W(t,r=0){const{intPart:n,fracPart:e}=t;if(!e||r>=e.length)return t;const c=parseInt(e[r],10),i=e.slice(r+1).replace(/0+$/,""),o=c===5&&i==="";let s=!1;if(c>5||c===5&&i!=="")s=!0;else if(o){const a=r===0?n[n.length-1]:e[r-1];parseInt(a,10)%2!==0&&(s=!0)}if(s){if(r===0)return g(t);const{result:a,carry:f}=$(e.slice(0,r));return f?g(t):{intPart:n,fracPart:a}}return{intPart:n,fracPart:e.slice(0,r)}}function N(t,r={}){const n=r.rounding||"half",e=r.precision||0,{sign:c,intPart:i,fracPart:o}=t,s={intPart:i,fracPart:o};let a;switch(n){case"half":a=k(s,e);break;case"up":a=c?y(s,e):M(s,e);break;case"down":a=c?M(s,e):y(s,e);break;case"truncate":a=y(s,e);break;case"banker":a=W(s,e);break;default:a=k(s,e)}return{sign:c,...a}}function q(t,r={}){const n=N(m(t),r);return I(n)}const G=["K","M","B","T","Q"];function T(t,r={}){let{sign:n,intPart:e,fracPart:c}=t,i=e.length,o=-1;for(;i>3&&o<4;){const a=e.slice(0,i-3);c=e.slice(i-3)+c,e=a,i-=3,o++}const s=r.precision!=null?N({sign:n,intPart:e,fracPart:c},r):{intPart:e,fracPart:c};return{sign:n,intPart:B(s.intPart),fracPart:Z(s.fracPart),symbol:o>=0?G[o]:""}}function J(t,r={}){const{sign:n,intPart:e,fracPart:c,symbol:i}=T(m(t),r);return I({sign:n,intPart:e,fracPart:c})+i}function _(t){return typeof t=="object"&&"intPart"in t?t:m(t)}function j(t){const{sign:r,intPart:n,fracPart:e}=_(t),c=e.match(/^0+/)?.[0]?.length||0,i=c.toString().split("").reduce((o,s)=>o+String.fromCharCode(8320+Number(s)),"");return`${r}${n}.0${i}${e.slice(c)}`}function R(t){const{sign:r,intPart:n,fracPart:e}=t,c=r==="-"?"-":"";if(n!=="0"){const a=n.length-1,f=(n[0]+"."+(n.slice(1)+e).replace(/0+$/,"")).replace(/\.$/,"");return{value:`${c}${f}`,exponent:a,sign:"+"}}const i=e.search(/[1-9]/);if(i===-1)return{value:"0",exponent:0};const o=-(i+1),s=(e[i]+"."+e.slice(i+1).replace(/0+$/,"")).replace(/\.$/,"");return{value:`${c}${s}`,exponent:o,sign:""}}function O(t){const{value:r,exponent:n,sign:e}=R(_(t));return n!==0?`${r}e${e}${n}`:r}function u(t){return{round:r=>{const n=N(t,r);return u({...t,...n})},compact:r=>{if(t.compactedSymbol)return u(t);const n=T(t,r);return u({...t,intPart:n.intPart,fracPart:n.fracPart,compactedSymbol:n.symbol})},notation(r="scientific"){return u({...t,notation:r})},prefix(r){return u({...t,prefix:r})},suffix(r){return u({...t,suffix:r})},toNumber(){const{sign:r,intPart:n,fracPart:e,prefix:c,suffix:i,compactedSymbol:o,notation:s}=t;let a=e.length>0?`${n}.${e}`:n;return s==="scientific"?a=O({sign:"",intPart:n,fracPart:e}):s==="subscript"&&(a=j({sign:"",intPart:n,fracPart:e})),`${c||""}${r}${a}${o||""}${i||""}`},toObject(){return t}}}function w(t){return u(A(t))}function C(t,r={}){let n=w(t).round(r);return r.isCompact&&(n=n.compact(r)),r.notation&&(n=n.notation(r.notation)),r.prefix&&(n=n.prefix(r.prefix)),r.suffix&&(n=n.suffix(r.suffix)),n.toNumber()}function X(t={}){return r=>C(r,t)}exports.FN=w;exports.clearLeadingZero=B;exports.clearTrailingZero=Z;exports.clearUnnecessaryZero=p;exports.compact=J;exports.createFormatFunction=X;exports.formatNumber=C;exports.getBaseNumberNumber=m;exports.parseNum=z;exports.round=q;exports.scientific=O;exports.subscript=j;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,212 @@
1
- export * from './types';
2
- export { compact } from './compact';
3
- export { FN } from './format';
4
- export { clearTrailingZero, parseNum } from './io';
5
- export { scientific, subscript } from './notation';
6
- export { round } from './round';
1
+ export declare type BaseObjectNumberType = {
2
+ sign: SignType;
3
+ } & BasePositiveNumberType;
4
+
5
+ export declare type BasePositiveNumberType = {
6
+ intPart: string;
7
+ fracPart: string;
8
+ };
9
+
10
+ /**
11
+ * Removes leading zeros from a string (e.g., '005' -> '5').
12
+ */
13
+ export declare const clearLeadingZero: (value: string) => string;
14
+
15
+ /**
16
+ * Removes trailing zeros from a decimal string (e.g., '1.500' -> '1.5').
17
+ */
18
+ export declare const clearTrailingZero: (value: string) => string;
19
+
20
+ /**
21
+ * Removes redundant leading and trailing zeros from a number string.
22
+ */
23
+ export declare function clearUnnecessaryZero(value: string): string;
24
+
25
+ /**
26
+ * Formats a number into a short, human-readable string with a suffix (e.g., K, M, B).
27
+ *
28
+ * @param value - The value to be compacted. Can be a number, string, or bigint.
29
+ * @param options - Configuration for rounding the compacted value.
30
+ * @param options.rounding - The rounding strategy to use. Default is 'half'.
31
+ * @param options.precision - The number of decimal places to include after compacting. Default is 0.
32
+ * @returns The compacted number with a suffix as a string.
33
+ *
34
+ * @example
35
+ * compact(1500); // '1.5K'
36
+ * compact(1200000, { precision: 1 }); // '1.2M'
37
+ * compact('1000000000000'); // '1T'
38
+ */
39
+ export declare function compact(value: NumberType, options?: RoundingConfigType): string;
40
+
41
+ /**
42
+ * Creates a reusable formatting function with predefined options.
43
+ * Useful for applying consistent formatting across multiple numbers.
44
+ *
45
+ * @param options - Configuration options for the formatter.
46
+ * @returns A function that accepts a value and returns the formatted string.
47
+ *
48
+ * @example
49
+ * const formatCurrency = createFormatFunction({ prefix: '$', precision: 2 });
50
+ * formatCurrency(1234.56); // '$1234.56'
51
+ * formatCurrency(100); // '$100.00'
52
+ */
53
+ export declare function createFormatFunction(options?: FormattingConfigType): (value: NumberType) => string;
54
+
55
+ /**
56
+ * Fluent API for performing multiple formatting operations in a readable chain.
57
+ * Wraps the input value into a formatter object that supports rounding,
58
+ * compacting, notation, prefixes, and suffixes.
59
+ *
60
+ * @param value - The initial value to format, can be a number, string, or bigint.
61
+ * @returns A chainable `FNType` object.
62
+ *
63
+ * @example
64
+ * FN('1234567.89')
65
+ * .round({ precision: 0 })
66
+ * .prefix('$')
67
+ * .toNumber(); // '$1234568'
68
+ *
69
+ * @example
70
+ * FN(1000000)
71
+ * .compact()
72
+ * .suffix(' total')
73
+ * .toNumber(); // '1M total'
74
+ */
75
+ export declare function FN(value: NumberType | ObjectNumberType): FNType;
76
+
77
+ /**
78
+ * Fluent API interface for chainable number formatting operations.
79
+ */
80
+ export declare type FNType = {
81
+ /**
82
+ * Rounds the number based on the provided precision and strategy.
83
+ * @param options - Rounding configuration (precision, rounding strategy).
84
+ * @returns The same FNType instance for further chaining.
85
+ */
86
+ round(options?: RoundingConfigType): FNType;
87
+ /**
88
+ * Converts the number to a compact representation (e.g., 1K, 1M, 1B).
89
+ * @param options - Optional rounding configuration to apply during compaction.
90
+ * @returns The same FNType instance for further chaining.
91
+ */
92
+ compact(options?: RoundingConfigType): FNType;
93
+ /**
94
+ * Sets the notation style for the number (e.g., scientific, subscript).
95
+ * @param mode - The notation mode to use. Defaults to 'scientific'.
96
+ * @returns The same FNType instance for further chaining.
97
+ */
98
+ notation(mode?: NotationMode): FNType;
99
+ /**
100
+ * Adds a prefix to the formatted number string.
101
+ * @param symbol - The string to prepend.
102
+ * @returns The same FNType instance for further chaining.
103
+ */
104
+ prefix(symbol: string): FNType;
105
+ /**
106
+ * Adds a suffix to the formatted number string.
107
+ * @param symbol - The string to append.
108
+ * @returns The same FNType instance for further chaining.
109
+ */
110
+ suffix(symbol: string): FNType;
111
+ /**
112
+ * Finalizes the chain and returns the formatted number as a string.
113
+ * @returns The final formatted number string.
114
+ */
115
+ toNumber(): string;
116
+ /**
117
+ * Returns the internal state of the number as an ObjectNumberType.
118
+ * @returns The internal object representation.
119
+ */
120
+ toObject(): ObjectNumberType;
121
+ };
122
+
123
+ /**
124
+ * Comprehensive formatting function that combines rounding, compacting, and metadata.
125
+ * This is the quickest way to format a number with multiple options in a single call.
126
+ *
127
+ * @param value - The value to format (number, string, or bigint).
128
+ * @param options - Formatting configuration (precision, rounding strategy, compact mode, prefix, suffix, and notation style).
129
+ * @returns The final formatted number string.
130
+ *
131
+ * @example
132
+ * formatNumber(1234.56, { prefix: '$', precision: 1 }); // '$1234.6'
133
+ *
134
+ * @example
135
+ * formatNumber(1500000, { isCompact: true, notation: 'scientific' }); // '1.5M' (compacted before potential notation)
136
+ */
137
+ export declare function formatNumber(value: NumberType, options?: FormattingConfigType): string;
138
+
139
+ /** Full configuration options for the formatNumber function */
140
+ export declare type FormattingConfigType = RoundingConfigType & NumberConfigType & Partial<{
141
+ /** Whether to use compact notation (K, M, B, etc.) */
142
+ isCompact: boolean;
143
+ }>;
144
+
145
+ export declare function getBaseNumberNumber(value: NumberType): BaseObjectNumberType;
146
+
147
+ /** Modes for special numerical notation */
148
+ export declare type NotationMode = 'subscript' | 'scientific';
149
+
150
+ /** Configuration for basic number display properties */
151
+ export declare type NumberConfigType = Partial<{
152
+ /** Text to prepend to the number (e.g., '$') */
153
+ prefix: string;
154
+ /** Text to append to the number (e.g., ' units') */
155
+ suffix: string;
156
+ /** The notation style to apply */
157
+ notation: NotationMode;
158
+ }>;
159
+
160
+ /** Supported input types for number formatting */
161
+ export declare type NumberType = number | string | bigint;
162
+
163
+ /** Internal object structure containing full formatting state */
164
+ export declare type ObjectNumberType = BaseObjectNumberType & NumberConfigType & Partial<{
165
+ /** The symbol used for compact notation (e.g., 'K', 'M') */
166
+ compactedSymbol: string;
167
+ }>;
168
+
169
+ /**
170
+ * Parses various input formats into a standard decimal string.
171
+ */
172
+ export declare function parseNum(value: NumberType, options?: ParseNumberParamsType): string;
173
+
174
+ /** Configuration for input parsing */
175
+ export declare type ParseNumberParamsType = Partial<{
176
+ /** Value to return if parsing fails. Default is '--' */
177
+ fallback: string;
178
+ }>;
179
+
180
+ export declare function round(value: NumberType, options?: RoundingConfigType): string;
181
+
182
+ /** Configuration for rounding operations */
183
+ export declare type RoundingConfigType = Partial<{
184
+ /** The rounding strategy to use */
185
+ rounding: RoundingMode;
186
+ /** Number of decimal places to keep */
187
+ precision: number;
188
+ }>;
189
+
190
+ /** Strategies for rounding numbers */
191
+ export declare type RoundingMode = 'half' | 'up' | 'down' | 'banker' | 'truncate';
192
+
193
+ /**
194
+ * Formats a number string using standard scientific notation.
195
+ */
196
+ export declare function scientific(value: NumberType | BaseObjectNumberType): string;
197
+
198
+ export declare type ScientificReturnType = {
199
+ value: string;
200
+ exponent: number;
201
+ sign?: string;
202
+ };
203
+
204
+ /** Possible sign values for internal number representation */
205
+ export declare type SignType = '-' | '';
206
+
207
+ /**
208
+ * Formats the decimal part of small numbers using subscript characters.
209
+ */
210
+ export declare function subscript(value: NumberType | BaseObjectNumberType): string;
211
+
212
+ export { }
package/dist/index.js CHANGED
@@ -1,200 +1,223 @@
1
- function x(r) {
2
- return r.replace(/^(-?)0+(?=\d)/, "$1").replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
3
- }
4
- function d(r) {
5
- let t = String(r);
6
- t = t.trim();
7
- let e = "";
8
- return t.startsWith("-") && (t = t.slice(1), e = "-"), { sign: e, value: x(t) };
9
- }
10
- const j = { K: 3, M: 6, B: 9, T: 12, Q: 15 };
11
- function z(r) {
12
- if (typeof r == "number" || typeof r == "bigint")
13
- return r.toString();
14
- const t = String(r ?? "").trim();
15
- if (t === "") return "0";
16
- const e = t.match(/^[\s+-]*/), i = ((e ? e[0] : "").match(/-/g) || []).length % 2 === 1, s = t.replace(/[$€£¥,_\s]/g, ""), c = /^([+-]?\d+)\.0([\u2080-\u2089]+)([0-9]*)$/i, u = s.match(c);
17
- if (u) {
18
- const m = u[1].replace(/^[+-]/, ""), B = u[2], C = u[3], w = B.split("").reduce((D, K) => {
19
- const Q = K.charCodeAt(0) - 8320;
20
- return D + Q;
21
- }, 0), y = "0".repeat(w) + C;
22
- let h = m;
23
- return (y !== "" || w > 0) && (h += "." + y), h = x(h), (i ? "-" : "") + (h || "0");
1
+ const K = (t) => t.replace(/0+$/, ""), Q = (t) => t.replace(/^0+(?!$)/, "");
2
+ function y(t) {
3
+ return t.replace(/^(-?)0+(?=\d)/, "$1").replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
4
+ }
5
+ function G(t, r = {}) {
6
+ const { fallback: n = "--" } = r;
7
+ if (typeof t == "number" || typeof t == "bigint") return t.toString();
8
+ const e = String(t ?? "").trim();
9
+ if (!e) return "0";
10
+ const c = e.match(/^[\s+-]*/), i = (c && c[0].match(/-/g) || []).length % 2 === 1, o = e.replace(/[$€£¥,_\s]/g, ""), s = o.match(/^([+-]?\d+)\.0([\u2080-\u2089]+)([0-9]*)$/i);
11
+ if (s) {
12
+ const [, l, C, O] = s, T = C.split("").reduce((U, D) => U + (D.charCodeAt(0) - 8320), 0), Z = y(l.replace(/^[+-]/, "") + "." + "0".repeat(T) + O);
13
+ return (i ? "-" : "") + (Z || "0");
24
14
  }
25
- const l = s.match(/[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?[KMBTQ]*/i);
26
- if (!l) return "0";
27
- let o = l[0].toUpperCase(), $ = 0;
28
- const N = o.match(/[KMBTQ]$/);
29
- N && ($ += j[N[0]] ?? 0, o = o.slice(0, -1));
30
- const S = o.match(/[eE][+-]?\d+$/);
31
- if (S && ($ += parseInt(S[0].slice(1), 10), o = o.replace(/[eE][+-]?\d+$/i, "")), o = o.replace(/^[+-]/, ""), !/^(?:\d+\.?\d*|\.\d+)$/.test(o)) return "0";
32
- const [T = "0", R = ""] = o.split(".");
33
- let g = (T.replace(/^0+/, "") || "0") + R;
34
- const P = R.length - $;
35
- let p;
36
- if (P <= 0)
37
- g += "0".repeat(-P), p = g.replace(/^0+(?=\d)/, "") || "0";
15
+ const a = o.match(/[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?[KMBTQ]*/i);
16
+ if (!a) return n;
17
+ let f = a[0].toUpperCase(), $ = 0;
18
+ const j = f.slice(-1), N = "KMBTQ".indexOf(j);
19
+ N !== -1 && ($ = (N + 1) * 3, f = f.slice(0, -1));
20
+ const h = f.match(/[E]([+-]?\d+)$/);
21
+ if (h && ($ += parseInt(h[1], 10), f = f.slice(0, h.index)), f = f.replace(/^[+-]/, ""), !/^(?:\d+\.?\d*|\.\d+)$/.test(f)) return "0";
22
+ const [w = "0", k = ""] = f.split("."), P = (w.replace(/^0+/, "") || "0") + k, b = k.length - $;
23
+ let d;
24
+ if (b <= 0)
25
+ d = (P + "0".repeat(-b)).replace(/^0+(?=\d)/, "") || "0";
38
26
  else {
39
- const m = g.length - P;
40
- m <= 0 ? p = "0." + "0".repeat(-m) + g : p = g.slice(0, m) + "." + g.slice(m), p = x(p);
27
+ const l = P.length - b;
28
+ d = l <= 0 ? "0." + "0".repeat(-l) + P : P.slice(0, l) + "." + P.slice(l), d = y(d);
41
29
  }
42
- return (i ? "-" : "") + (p || "0");
43
- }
44
- function E(r) {
45
- const t = typeof r;
46
- if (t == "string" || t == "bigint" || t == "number") {
47
- const { sign: e, value: n } = d(r);
48
- return { sign: e, value: n };
30
+ return (i ? "-" : "") + (d || "0");
31
+ }
32
+ function p(t) {
33
+ let r = String(t).trim();
34
+ const n = r.startsWith("-") ? "-" : "";
35
+ n && (r = r.slice(1));
36
+ const [e, c = ""] = y(r).split(".");
37
+ return { sign: n, intPart: e, fracPart: c };
38
+ }
39
+ const _ = (t) => t.fracPart ? `${t.sign}${t.intPart}.${t.fracPart}` : `${t.sign}${t.intPart}`;
40
+ function V(t) {
41
+ return typeof t == "object" && t !== null && "intPart" in t ? t : p(t);
42
+ }
43
+ function m(t) {
44
+ if (!t) return { result: "", carry: !0 };
45
+ const n = (BigInt(t) + 1n).toString();
46
+ return n.length > t.length ? { result: n.slice(1), carry: !0 } : { result: n.padStart(t.length, "0"), carry: !1 };
47
+ }
48
+ function g({ intPart: t }) {
49
+ const { result: r, carry: n } = m(t);
50
+ return { intPart: n ? "1" + r : r, fracPart: "" };
51
+ }
52
+ function I(t, r = 0) {
53
+ const { intPart: n, fracPart: e } = t;
54
+ if (!e || r >= e.length) return t;
55
+ if (parseInt(e[r], 10) >= 5) {
56
+ if (r === 0) return g(t);
57
+ const i = e.slice(0, r), { result: o, carry: s } = m(i);
58
+ return s ? g(t) : { intPart: n, fracPart: o };
49
59
  }
50
- return r;
51
- }
52
- function a(r) {
53
- let t = "", e = r.length - 1, n = "1";
54
- for (; e >= 0; ) {
55
- const i = r[e];
56
- let s = Number(i) + (n ? 1 : 0);
57
- s >= 10 ? (n = "1", s -= 10) : n = "", t = s.toString() + t, e--;
60
+ return { intPart: n, fracPart: e.slice(0, r) };
61
+ }
62
+ function M(t, r = 0) {
63
+ const { intPart: n, fracPart: e } = t;
64
+ if (!e || r >= e.length) return t;
65
+ if (r === 0) return g(t);
66
+ const c = e.slice(0, r), { result: i, carry: o } = m(c);
67
+ return o ? g(t) : { intPart: n, fracPart: i };
68
+ }
69
+ function x(t, r = 0) {
70
+ const { intPart: n, fracPart: e } = t;
71
+ if (!e || r >= e.length) return t;
72
+ const c = e.slice(0, r);
73
+ return { intPart: n, fracPart: c.replace(/0+$/, "") };
74
+ }
75
+ function E(t, r = 0) {
76
+ const { intPart: n, fracPart: e } = t;
77
+ if (!e || r >= e.length) return t;
78
+ const c = parseInt(e[r], 10), i = e.slice(r + 1).replace(/0+$/, ""), o = c === 5 && i === "";
79
+ let s = !1;
80
+ if (c > 5 || c === 5 && i !== "")
81
+ s = !0;
82
+ else if (o) {
83
+ const a = r === 0 ? n[n.length - 1] : e[r - 1];
84
+ parseInt(a, 10) % 2 !== 0 && (s = !0);
58
85
  }
59
- return { result: n + t, remaining: n };
60
- }
61
- function I(r, t = 0) {
62
- const [e, n = ""] = r.split(".");
63
- if (t === 0)
64
- return n && Number(n[0]) >= 5 ? a(e).result : e;
65
- if (t >= n.length) return e + (n ? `.${n}` : "");
66
- const i = n.slice(0, t), s = n.slice(t);
67
- if (Number(s[0]) >= 5) {
68
- const c = a(i);
69
- return c.remaining ? a(e).result : e + "." + c.result;
70
- } else return e + "." + i;
71
- }
72
- function M(r, t = 0) {
73
- const [e, n = ""] = r.split(".");
74
- if (t === 0)
75
- return n ? a(e).result : e;
76
- if (t >= n.length) return e + "." + n;
77
- const i = a(n.slice(0, t));
78
- return i.remaining ? a(e).result : e + "." + i.result;
79
- }
80
- function b(r, t = 0) {
81
- const [e, n = ""] = r.split(".");
82
- if (t === 0) return e;
83
- let i = n.slice(0, t), s = i.length - 1;
84
- for (; s >= 0 && i[s] == "0"; ) s--;
85
- return i = i.slice(0, s + 1), e + (i ? `.${i}` : "");
86
- }
87
- function O(r, t = 0) {
88
- const [e, n = ""] = r.split(".");
89
- if (t === 0)
90
- return n && Number(n[0]) >= 5 ? Number(e[0]) / 2 == 0 ? e : a(e).result : e;
91
- if (t >= n.length) return e + (n ? `.${n}` : "");
92
- const i = n.slice(0, t), s = n.slice(t);
93
- if (s[0] == "5") {
94
- if (Number(i[i.length - 1]) % 2 == 0)
95
- return e + "." + i;
96
- {
97
- const c = a(i);
98
- return c.remaining ? a(e).result : e + "." + c.result;
99
- }
100
- } else if (Number(s[0]) > 5) {
101
- const c = a(i);
102
- return c.remaining ? a(e).result : e + "." + c.result;
103
- } else return e + "." + i;
104
- }
105
- function _(r, t = {}) {
106
- const e = t.rounding || "half", n = t.precision || 0, { sign: i, value: s } = d(r);
107
- switch (e) {
86
+ if (s) {
87
+ if (r === 0) return g(t);
88
+ const { result: a, carry: f } = m(e.slice(0, r));
89
+ return f ? g(t) : { intPart: n, fracPart: a };
90
+ }
91
+ return { intPart: n, fracPart: e.slice(0, r) };
92
+ }
93
+ function S(t, r = {}) {
94
+ const n = r.rounding || "half", e = r.precision || 0, { sign: c, intPart: i, fracPart: o } = t, s = { intPart: i, fracPart: o };
95
+ let a;
96
+ switch (n) {
108
97
  case "half":
109
- return i + I(s, n);
98
+ a = I(s, e);
99
+ break;
110
100
  case "up":
111
- return i == "" ? M(s, n) : "-" + b(s, n);
101
+ a = c ? x(s, e) : M(s, e);
102
+ break;
112
103
  case "down":
113
- return i == "" ? b(s, n) : "-" + M(s, n);
104
+ a = c ? M(s, e) : x(s, e);
105
+ break;
114
106
  case "truncate":
115
- return i + b(s, n);
107
+ a = x(s, e);
108
+ break;
116
109
  case "banker":
117
- return i + O(s, n);
110
+ a = E(s, e);
111
+ break;
112
+ default:
113
+ a = I(s, e);
118
114
  }
119
- }
120
- const Z = ["K", "M", "B", "T", "Q"];
121
- function v(r, t = {}) {
122
- const { sign: e, value: n } = d(r);
123
- let [i, s = ""] = n.split("."), c = i.length, u = -1;
124
- for (; c > 3 && u < 4; ) {
125
- const o = i.slice(0, c - 3);
126
- s = i.slice(c - 3) + s, i = o, c -= 3, u++;
115
+ return { sign: c, ...a };
116
+ }
117
+ function J(t, r = {}) {
118
+ const n = S(p(t), r);
119
+ return _(n);
120
+ }
121
+ const H = ["K", "M", "B", "T", "Q"];
122
+ function B(t, r = {}) {
123
+ let { sign: n, intPart: e, fracPart: c } = t, i = e.length, o = -1;
124
+ for (; i > 3 && o < 4; ) {
125
+ const a = e.slice(0, i - 3);
126
+ c = e.slice(i - 3) + c, e = a, i -= 3, o++;
127
127
  }
128
- const l = `${e}${i}${s.length > 0 ? "." + s : s}`;
128
+ const s = r.precision != null ? S({ sign: n, intPart: e, fracPart: c }, r) : { intPart: e, fracPart: c };
129
129
  return {
130
- value: t.precision != null ? _(l, t) : l,
131
- symbol: u >= 0 ? Z[u] : ""
130
+ sign: n,
131
+ intPart: Q(s.intPart),
132
+ fracPart: K(s.fracPart),
133
+ symbol: o >= 0 ? H[o] : ""
132
134
  };
133
135
  }
134
- function A(r, t = {}) {
135
- const { value: e, symbol: n } = v(r, t);
136
- return e + n;
136
+ function R(t, r = {}) {
137
+ const { sign: n, intPart: e, fracPart: c, symbol: i } = B(p(t), r);
138
+ return _({ sign: n, intPart: e, fracPart: c }) + i;
139
+ }
140
+ function F(t) {
141
+ return typeof t == "object" && "intPart" in t ? t : p(t);
137
142
  }
138
- function k(r) {
139
- const { sign: t, value: e } = d(r), [n, i = ""] = e.split("."), s = i.match(/^0+/)?.[0]?.length || 0, c = s.toString().split("").map((l) => String.fromCharCode(8320 + parseInt(l))).join(""), u = i.slice(s);
140
- return `${t}${n}.0${c}${u}`;
143
+ function z(t) {
144
+ const { sign: r, intPart: n, fracPart: e } = F(t), c = e.match(/^0+/)?.[0]?.length || 0, i = c.toString().split("").reduce((o, s) => o + String.fromCharCode(8320 + Number(s)), "");
145
+ return `${r}${n}.0${i}${e.slice(c)}`;
141
146
  }
142
- function F(r) {
143
- const { sign: t, value: e } = d(r);
144
- if (e == "0") return { value: "0", exponent: 0 };
145
- const [n, i = ""] = e.split(".");
147
+ function A(t) {
148
+ const { sign: r, intPart: n, fracPart: e } = t, c = r === "-" ? "-" : "";
146
149
  if (n !== "0") {
147
- const l = n.length - 1, o = n[0] + "." + (n.slice(1) + i).replace(/0+$/, "");
148
- return { value: `${t}${o}${o.length > 1, ""}`, exponent: l, sign: "+" };
150
+ const a = n.length - 1, f = (n[0] + "." + (n.slice(1) + e).replace(/0+$/, "")).replace(
151
+ /\.$/,
152
+ ""
153
+ );
154
+ return { value: `${c}${f}`, exponent: a, sign: "+" };
149
155
  }
150
- const s = i.search(/[1-9]/);
151
- if (s === -1) return { value: "0", exponent: 0 };
152
- const c = -(s + 1), u = i[s] + "." + i.slice(s + 1).replace(/0+$/, "");
153
- return { value: `${t}${u}`, exponent: c - 1, sign: "" };
156
+ const i = e.search(/[1-9]/);
157
+ if (i === -1) return { value: "0", exponent: 0 };
158
+ const o = -(i + 1), s = (e[i] + "." + e.slice(i + 1).replace(/0+$/, "")).replace(/\.$/, "");
159
+ return { value: `${c}${s}`, exponent: o, sign: "" };
154
160
  }
155
- function U(r) {
156
- const { value: t, exponent: e, sign: n } = F(r);
157
- return e != 0 ? `${t}e${n}${e}` : t;
161
+ function L(t) {
162
+ const { value: r, exponent: n, sign: e } = A(F(t));
163
+ return n !== 0 ? `${r}e${e}${n}` : r;
158
164
  }
159
- function f(r) {
165
+ function u(t) {
160
166
  return {
161
- round: (t) => {
162
- const e = _(r.value, t);
163
- return f({ ...r, value: e });
167
+ round: (r) => {
168
+ const n = S(t, r);
169
+ return u({ ...t, ...n });
164
170
  },
165
- compact: (t) => {
166
- if (r.compactedSymbol) return f(r);
167
- const { value: e, symbol: n } = v(r.value, t);
168
- return f({ ...r, compactedSymbol: n, value: e });
171
+ compact: (r) => {
172
+ if (t.compactedSymbol) return u(t);
173
+ const n = B(t, r);
174
+ return u({
175
+ ...t,
176
+ intPart: n.intPart,
177
+ fracPart: n.fracPart,
178
+ compactedSymbol: n.symbol
179
+ });
169
180
  },
170
- notation(t = "scientific") {
171
- return f({ ...r, notation: t });
181
+ notation(r = "scientific") {
182
+ return u({ ...t, notation: r });
172
183
  },
173
- prefix(t) {
174
- return f({ ...r, prefix: t });
184
+ prefix(r) {
185
+ return u({ ...t, prefix: r });
175
186
  },
176
- suffix(t) {
177
- return f({ ...r, suffix: t });
187
+ suffix(r) {
188
+ return u({ ...t, suffix: r });
178
189
  },
179
190
  toNumber() {
180
- let { value: t } = r;
181
- const { sign: e, prefix: n, suffix: i, compactedSymbol: s } = r;
182
- return r.notation == "scientific" ? t = U(t) : r.notation == "subscript" && (t = k(t)), `${n || ""}${e}${t}${s || ""}${i || ""}`;
191
+ const { sign: r, intPart: n, fracPart: e, prefix: c, suffix: i, compactedSymbol: o, notation: s } = t;
192
+ let a = e.length > 0 ? `${n}.${e}` : n;
193
+ return s === "scientific" ? a = L({ sign: "", intPart: n, fracPart: e }) : s === "subscript" && (a = z({ sign: "", intPart: n, fracPart: e })), `${c || ""}${r}${a}${o || ""}${i || ""}`;
183
194
  },
184
195
  toObject() {
185
- return r;
196
+ return t;
186
197
  }
187
198
  };
188
199
  }
189
- function H(r) {
190
- return f(E(r));
200
+ function W(t) {
201
+ return u(V(t));
202
+ }
203
+ function q(t, r = {}) {
204
+ let n = W(t).round(r);
205
+ return r.isCompact && (n = n.compact(r)), r.notation && (n = n.notation(r.notation)), r.prefix && (n = n.prefix(r.prefix)), r.suffix && (n = n.suffix(r.suffix)), n.toNumber();
206
+ }
207
+ function X(t = {}) {
208
+ return (r) => q(r, t);
191
209
  }
192
210
  export {
193
- H as FN,
194
- x as clearTrailingZero,
195
- A as compact,
196
- z as parseNum,
197
- _ as round,
198
- U as scientific,
199
- k as subscript
211
+ W as FN,
212
+ Q as clearLeadingZero,
213
+ K as clearTrailingZero,
214
+ y as clearUnnecessaryZero,
215
+ R as compact,
216
+ X as createFormatFunction,
217
+ q as formatNumber,
218
+ p as getBaseNumberNumber,
219
+ G as parseNum,
220
+ J as round,
221
+ L as scientific,
222
+ z as subscript
200
223
  };
package/package.json CHANGED
@@ -1,16 +1,24 @@
1
1
  {
2
2
  "name": "@peter-present/format-number",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "A lightweight, zero-dependency JavaScript/TypeScript library for precise number formatting. Designed for financial applications, crypto dashboards, and scientific data where precision is paramount.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
8
8
  "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ }
15
+ },
16
+ "sideEffects": false,
9
17
  "files": [
10
18
  "dist"
11
19
  ],
12
20
  "scripts": {
13
- "build": "bun run clear && tsc && vite build",
21
+ "build": "bun run clear && vite build",
14
22
  "preview": "vite preview",
15
23
  "clear": "rm -rf dist",
16
24
  "test": "vitest run",
package/dist/compact.d.ts DELETED
@@ -1,20 +0,0 @@
1
- import { NumberType, RoundingConfigType } from './types';
2
- export declare function _compact(value: NumberType, options?: RoundingConfigType): {
3
- value: string;
4
- symbol: string;
5
- };
6
- /**
7
- * Formats a number into a short, human-readable string with a suffix (e.g., K, M, B).
8
- *
9
- * @param value - The value to be compacted. Can be a number, string, or bigint.
10
- * @param options - Configuration for rounding the compacted value.
11
- * @param options.rounding - The rounding strategy to use. Default is 'half'.
12
- * @param options.precision - The number of decimal places to include after compacting. Default is 0.
13
- * @returns The compacted number with a suffix as a string.
14
- *
15
- * @example
16
- * compact(1500); // '1.5K'
17
- * compact(1200000, { precision: 1 }); // '1.2M'
18
- * compact('1000000000000'); // '1T'
19
- */
20
- export declare function compact(value: NumberType, options?: RoundingConfigType): string;
package/dist/format.d.ts DELETED
@@ -1,37 +0,0 @@
1
- import { FormattingConfigType, NotationMode, NumberType, ObjectNumberType, RoundingConfigType } from './types';
2
- /**
3
- * Fluent API for performing multiple formatting operations in a readable chain.
4
- * Wraps the input value into a formatter object that supports rounding,
5
- * compacting, and metadata addition.
6
- *
7
- * @param value - The initial value to format.
8
- * @returns A chainable formatter object.
9
- *
10
- * @example
11
- * FN('1234567.89')
12
- * .round({ precision: 0 })
13
- * .prefix('$')
14
- * .toNumber(); // '$1234568'
15
- */
16
- export declare function FN(value: NumberType | ObjectNumberType): {
17
- round: (options?: RoundingConfigType) => any;
18
- compact: (options?: RoundingConfigType) => any;
19
- notation(mode?: NotationMode): any;
20
- prefix(symbol: string): any;
21
- suffix(symbol: string): any;
22
- toNumber(): string;
23
- toObject(): ObjectNumberType;
24
- };
25
- /**
26
- * Comprehensive formatting function that combines rounding, compacting, and metadata.
27
- * This is the quickest way to format a number with multiple options.
28
- *
29
- * @param value - The value to format.
30
- * @param options - Formatting configuration (precision, rounding, isCompact, prefix, suffix, notation).
31
- * @returns The formatted number string.
32
- *
33
- * @example
34
- * formatNumber(1234.56, { prefix: '$', precision: 1 }); // '$1234.6'
35
- * formatNumber(1500000, { isCompact: true }); // '1.5M'
36
- */
37
- export declare function formatNumber(value: NumberType, options?: FormattingConfigType): string;
package/dist/io.d.ts DELETED
@@ -1,26 +0,0 @@
1
- import { NumberType, ObjectNumberType, SignType } from './types';
2
- /**
3
- * Removes redundant leading and trailing zeros from a number string.
4
- *
5
- * @param value - The number string to clean.
6
- * @returns The cleaned number string.
7
- */
8
- export declare function clearTrailingZero(value: string): string;
9
- export declare function getInput(value: NumberType): {
10
- sign: SignType;
11
- value: string;
12
- };
13
- /**
14
- * Parses various input formats into a standard decimal string.
15
- * Supports numbers, bigints, currencies ($€£¥), commas, underscores,
16
- * scientific notation (e+), and custom subscript notation (e.g., "5.0₄6").
17
- *
18
- * @param value - The input value to parse.
19
- * @returns A standardized decimal string.
20
- *
21
- * @example
22
- * parseNum('$1,234.56'); // '1234.56'
23
- * parseNum('5.0₄6'); // '5.00006'
24
- */
25
- export declare function parseNum(value: NumberType): string;
26
- export declare function convertToObjectNumber(value: NumberType | ObjectNumberType): ObjectNumberType;
@@ -1,24 +0,0 @@
1
- /**
2
- * Formats the decimal part of small numbers using subscript characters
3
- * to represent the number of consecutive leading zeros.
4
- *
5
- * @param value - The number string to format.
6
- * @returns A string with subscript notation (e.g., '0.0₃5').
7
- */
8
- export declare function subscript(value: string): string;
9
- export declare function _scientific(value: string): {
10
- value: string;
11
- exponent: number;
12
- sign?: undefined;
13
- } | {
14
- value: string;
15
- exponent: number;
16
- sign: string;
17
- };
18
- /**
19
- * Formats a number string using standard scientific notation.
20
- *
21
- * @param value - The number string to format.
22
- * @returns A string in scientific notation (e.g., '1.23e+5').
23
- */
24
- export declare function scientific(value: string): string;
package/dist/round.d.ts DELETED
@@ -1,16 +0,0 @@
1
- import { NumberType, RoundingConfigType } from './types';
2
- export declare function roundPositiveHalf(value: string, precision?: number): string;
3
- /**
4
- * Rounds a number based on the specified precision and rounding mode.
5
- *
6
- * @param value - The value to be rounded. Can be a number, string, or bigint.
7
- * @param options - Configuration for rounding.
8
- * @param options.rounding - The rounding strategy to use ('half', 'up', 'down', 'banker', 'truncate'). Default is 'half'.
9
- * @param options.precision - The number of decimal places to round to. Default is 0.
10
- * @returns The rounded number as a string.
11
- *
12
- * @example
13
- * round(123.456, { precision: 2 }); // '123.46'
14
- * round(123.45, { rounding: 'down', precision: 1 }); // '123.4'
15
- */
16
- export declare function round(value: NumberType, options?: RoundingConfigType): string;
package/dist/types.d.ts DELETED
@@ -1,37 +0,0 @@
1
- /** Supported input types for number formatting */
2
- export type NumberType = number | string | bigint;
3
- /** Strategies for rounding numbers */
4
- export type RoundingMode = 'half' | 'up' | 'down' | 'banker' | 'truncate';
5
- /** Modes for special numerical notation */
6
- export type NotationMode = 'subscript' | 'scientific';
7
- /** Possible sign values for internal number representation */
8
- export type SignType = '-' | '';
9
- /** Configuration for rounding operations */
10
- export type RoundingConfigType = Partial<{
11
- /** The rounding strategy to use */
12
- rounding: RoundingMode;
13
- /** Number of decimal places to keep */
14
- precision: number;
15
- }>;
16
- /** Configuration for basic number display properties */
17
- export type NumberConfigType = Partial<{
18
- /** Text to prepend to the number (e.g., '$') */
19
- prefix: string;
20
- /** Text to append to the number (e.g., ' units') */
21
- suffix: string;
22
- /** The notation style to apply */
23
- notation: NotationMode;
24
- }>;
25
- /** Internal object structure containing full formatting state */
26
- export type ObjectNumberType = {
27
- sign: SignType;
28
- value: string;
29
- } & NumberConfigType & Partial<{
30
- /** The symbol used for compact notation (e.g., 'K', 'M') */
31
- compactedSymbol: string;
32
- }>;
33
- /** Full configuration options for the formatNumber function */
34
- export type FormattingConfigType = RoundingConfigType & NumberConfigType & Partial<{
35
- /** Whether to use compact notation (K, M, B, etc.) */
36
- isCompact: boolean;
37
- }>;