@webority/web-core 0.41.3 → 0.43.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/README.md CHANGED
@@ -197,6 +197,15 @@ Called with no options, the house formatters print (zone IST, locale en-IN, empt
197
197
  12- or 24-hour clock and its AM/PM casing ("08:05 pm"), zone names ("IST") and relative phrases
198
198
  ("yesterday"). `formatCurrency` then writes in that locale too and prints the configured `empty`.
199
199
  With no locale configured, every formatter keeps the house text above.
200
+ - `configureFormatters({ numberStyle, dateOrder })` applies a person's own choice, and can be called
201
+ again when they change it. `numberStyle` (`NumberStyle`) sets the decimal mark and group separator
202
+ of every number and amount: `"PointWithCommaGroups"` 1,234.5, `"CommaWithPointGroups"` 1.234,5,
203
+ `"CommaWithSpaceGroups"` 1 234,5, `"PointWithSpaceGroups"` 1 234.5 (a no-break space). Only those
204
+ two characters change: en-IN keeps its lakh grouping ("₹12.34.567,50") and a locale keeps its
205
+ symbol placement. `dateOrder` (`DateOrder`) sets every date, including the date half of
206
+ `formatDateTime`: `"DayMonthNameYear"` 09-Oct-2026 (the house order), `"DayMonthYear"` 09/10/2026,
207
+ `"MonthDayYear"` 10/09/2026, `"YearMonthDay"` 2026-10-09. Times, zones and relative phrases stay
208
+ as they are. Left unset, both keep the output above; an unknown value throws a `RangeError`.
200
209
  - `formatNumber`, `formatPercent` and `formatCurrency` pass Intl options through: any option beyond
201
210
  the house keys (`style`, `unit`, `notation`, `signDisplay`, ...) sends the number to
202
211
  `Intl.NumberFormat` with every option, so it reads as the browser's Intl reads it.
@@ -1 +1 @@
1
- import{configuredLocale as e,getFormatterConfig as t,isFormatterConfigured as n}from"./formatConfig.js";import{numberFormat as r}from"./intlCache.js";var i=()=>typeof Intl<`u`&&typeof Intl.NumberFormat==`function`,a=(e,t)=>{let n=e<0?`-`:``,[r,i]=Math.abs(e).toFixed(t).split(`.`),a=r.length>3?r.slice(-3):r,o=r.length>3?r.slice(0,-3):``;return n+(o?o.replace(/\B(?=(\d{2})+(?!\d))/g,`,`)+`,`+a:a)+(i?`.${i}`:``)},o=e=>{if(e==null||typeof e==`string`&&e.trim()===``)return null;let t=typeof e==`number`?e:Number(e);return Number.isFinite(t)?t:null},s=(e,t)=>r(e,{style:`currency`,currency:t}).resolvedOptions().maximumFractionDigits??2,c=(c,l={})=>{let{currency:u=`INR`,locale:d=e()??`en-IN`,minimumFractionDigits:f,maximumFractionDigits:p,stripSymbol:m=!1,empty:h=n(`locale`)||n(`empty`)?t().empty:``,...g}=l,_=o(c);if(_===null)return h;if(i())try{let e=p??s(d,u),t=f??(Number.isInteger(_)?0:e),n=r(d,{...g,style:`currency`,currency:u,minimumFractionDigits:t,maximumFractionDigits:Math.max(t,e)}).format(_);return m?n.replace(/[^\d,.\s\-+]/g,``).trim():n}catch{}let v=a(_,f??(Number.isInteger(_)?0:2));return m?v:u===`INR`?`₹${v}`:`${u} ${v}`};export{c as formatCurrency};
1
+ import{configuredLocale as e,getFormatterConfig as t,isFormatterConfigured as n,numberSeparators as r,styledNumber as i}from"./formatConfig.js";import{numberFormat as a}from"./intlCache.js";var o=()=>typeof Intl<`u`&&typeof Intl.NumberFormat==`function`,s=(e,t)=>{let{decimal:n,group:i}=r()??{decimal:`.`,group:`,`},a=e<0?`-`:``,[o,s]=Math.abs(e).toFixed(t).split(`.`),c=o.length>3?o.slice(-3):o,l=o.length>3?o.slice(0,-3):``;return a+(l?l.replace(/\B(?=(\d{2})+(?!\d))/g,i)+i+c:c)+(s?`${n}${s}`:``)},c=e=>{if(e==null||typeof e==`string`&&e.trim()===``)return null;let t=typeof e==`number`?e:Number(e);return Number.isFinite(t)?t:null},l=(e,t)=>a(e,{style:`currency`,currency:t}).resolvedOptions().maximumFractionDigits??2,u=(r,u={})=>{let{currency:d=`INR`,locale:f=e()??`en-IN`,minimumFractionDigits:p,maximumFractionDigits:m,stripSymbol:h=!1,empty:g=n(`locale`)||n(`empty`)?t().empty:``,..._}=u,v=c(r);if(v===null)return g;if(o())try{let e=m??l(f,d),t=p??(Number.isInteger(v)?0:e),n=i(a(f,{..._,style:`currency`,currency:d,minimumFractionDigits:t,maximumFractionDigits:Math.max(t,e)}),v);return h?n.replace(/[^\d,.\s\-+]/g,``).trim():n}catch{}let y=s(v,p??(Number.isInteger(v)?0:2));return h?y:d===`INR`?`₹${y}`:`${d} ${y}`};export{u as formatCurrency};
@@ -1 +1 @@
1
- var e={zone:`IST`,locale:`en-IN`,empty:`-`},t={...e},n=new Set,r=r=>{if(r===void 0){t={...e},n=new Set;return}for(let e of Object.keys(r)){let i=r[e];i!==void 0&&(t={...t,[e]:i},n.add(e))}},i=()=>({...t}),a=e=>n.has(e),o=()=>n.has(`locale`)?t.locale:null,s=e=>/-IN(?:-|$)/i.test(e)?`indian`:`international`;export{r as configureFormatters,o as configuredLocale,i as getFormatterConfig,s as groupingForLocale,a as isFormatterConfigured};
1
+ var e={zone:`IST`,locale:`en-IN`,empty:`-`},t={PointWithCommaGroups:{decimal:`.`,group:`,`},CommaWithPointGroups:{decimal:`,`,group:`.`},CommaWithSpaceGroups:{decimal:`,`,group:`\xA0`},PointWithSpaceGroups:{decimal:`.`,group:`\xA0`}},n=[`DayMonthNameYear`,`DayMonthYear`,`MonthDayYear`,`YearMonthDay`],r={...e},i=new Set,a=a=>{if(a===void 0){r={...e},i=new Set;return}if(a.numberStyle!==void 0&&!Object.hasOwn(t,a.numberStyle))throw RangeError(`Unknown number style "${a.numberStyle}"; expected one of ${Object.keys(t).join(`, `)}.`);if(a.dateOrder!==void 0&&!n.includes(a.dateOrder))throw RangeError(`Unknown date order "${a.dateOrder}"; expected one of ${n.join(`, `)}.`);for(let e of Object.keys(a)){let t=a[e];t!==void 0&&(r={...r,[e]:t},i.add(e))}},o=()=>({...r}),s=e=>i.has(e),c=()=>i.has(`locale`)?r.locale:null,l=e=>/-IN(?:-|$)/i.test(e)?`indian`:`international`,u=()=>r.numberStyle===void 0?null:t[r.numberStyle],d=(e,t)=>{let n=u();return n===null?e.format(t):e.formatToParts(t).map(e=>e.type===`decimal`?n.decimal:e.type===`group`?n.group:e.value).join(``)};export{a as configureFormatters,c as configuredLocale,o as getFormatterConfig,l as groupingForLocale,s as isFormatterConfigured,u as numberSeparators,d as styledNumber};
@@ -1 +1 @@
1
- import{configuredLocale as e,getFormatterConfig as t,groupingForLocale as n}from"./formatConfig.js";import{dateTimeFormat as r,numberFormat as i,relativeTimeFormat as a}from"./intlCache.js";var o=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],s=330,c=[`IST`,`Asia/Kolkata`,`Asia/Calcutta`],l=/^\d{4}-\d{2}-\d{2}$/,u=e=>e<10?`0${e}`:`${e}`,d=e=>e??t().empty,f=e=>{if(e==null||e===``)return null;let t=e instanceof Date?e:new Date(typeof e==`string`?e.trim():e);return Number.isNaN(t.getTime())?null:t},p=e=>typeof e==`string`&&l.test(e.trim()),m=e=>{if(e===0)return`GMT`;let t=e>0?`+`:`-`,n=Math.abs(e),r=n%60;return`GMT${t}${Math.floor(n/60)}${r===0?``:`:${u(r)}`}`},h=(e,t,n)=>{let r=new Date(e.getTime()+t*6e4);return{year:r.getUTCFullYear(),month:r.getUTCMonth(),day:r.getUTCDate(),hour:r.getUTCHours(),minute:r.getUTCMinutes(),label:n}},g=(e,t)=>{let n=r(`en-US`,{timeZone:t,year:`numeric`,month:`numeric`,day:`numeric`,hour:`numeric`,minute:`numeric`,hour12:!1}).formatToParts(e),i=e=>Number.parseInt(n.find(t=>t.type===e)?.value??``,10),a=i(`year`),o=i(`month`)-1,s=i(`day`),c=i(`hour`)%24,l=i(`minute`);return{year:a,month:o,day:s,hour:c,minute:l,label:m(Math.round((Date.UTC(a,o,s,c,l)-Math.floor(e.getTime()/6e4)*6e4)/6e4))}},_=(e,t)=>c.includes(t)?h(e,s,`IST`):t===`UTC`?h(e,0,`UTC`):t===`viewer`?{year:e.getFullYear(),month:e.getMonth(),day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),label:m(-e.getTimezoneOffset())}:g(e,t),v=e=>e.hourCycle??12,y=e=>`${u(e.day)}-${o[e.month]}-${e.year}`,b=(e,t)=>t===24?`${u(e.hour)}:${u(e.minute)}`:`${e.hour%12||12}:${u(e.minute)} ${e.hour<12?`AM`:`PM`}`,x=(e,t)=>t??!c.includes(e),S=(e,t,n,r)=>x(n,r)?`${e} ${t.label}`:e,C=e=>{if(e!==`viewer`)return c.includes(e)?`Asia/Kolkata`:e},w=(e,t,n)=>{let i=r(t,{day:`2-digit`,month:`short`,year:`numeric`,timeZone:n}).formatToParts(e),a=e=>i.find(t=>t.type===e)?.value??``;return`${a(`day`)}-${a(`month`).replace(`.`,``)}-${a(`year`)}`},T=(e,t,n,i)=>r(t,{hour:`2-digit`,minute:`2-digit`,timeZone:C(n),timeZoneName:x(n,i.zoneLabel)?`short`:void 0,hourCycle:i.hourCycle===void 0?void 0:i.hourCycle===24?`h23`:`h12`}).format(e),E=(n,r={})=>{let i=f(n);if(!i)return d(r.empty);let a=p(n)?`UTC`:r.zone??t().zone,o=e();return o?w(i,o,C(a)):y(_(i,a))},D=(n,r={})=>{let i=f(n);if(!i)return d(r.empty);let a=r.zone??t().zone,o=e();if(o)return T(i,o,a,r);let s=_(i,a);return S(b(s,v(r)),s,a,r.zoneLabel)},O=(n,r={})=>{let i=f(n);if(!i)return d(r.empty);let a=r.zone??t().zone,o=e();if(o)return`${w(i,o,C(a))}, ${T(i,o,a,r)}`;let s=_(i,a);return S(`${y(s)}, ${b(s,v(r))}`,s,a,r.zoneLabel)},k=1e3,A=60*k,j=60*A,M=24*j,N=7*M,P=30*M,F=365*M,I=[[`year`,F],[`month`,P],[`day`,M],[`hour`,j],[`minute`,A]],L=(n,r={})=>{let i=f(n),o=f(r.now??Date.now());if(!i||!o)return d(r.empty);let s=i.getTime()-o.getTime(),c=Math.abs(s),l=Intl.RelativeTimeFormat,u=e();if((u!==null||r.intl===!0)&&typeof l==`function`){let e=a(l,u??t().locale),[n,r]=I.find(([,e])=>c>=e)??[`second`,k];return e.format(Math.round(s/r),n)}if(c<A)return`just now`;let[p,m]=c<j?[`minute`,A]:c<M?[`hour`,j]:c<N?[`day`,M]:c<P?[`week`,N]:c<F?[`month`,P]:[`year`,F],h=Math.floor(c/m),g=`${h} ${p}${h===1?``:`s`}`;return s<0?`${g} ago`:`in ${g}`},R=e=>{if(e==null||typeof e==`string`&&e.trim()===``)return null;let t=typeof e==`number`?e:Number(e);return Number.isFinite(t)?t:null},z=e=>Math.min(20,Math.max(0,Math.trunc(e))),B=(e,t)=>/e/i.test(String(e))?e*10**t:Number(`${e}e${t}`),V=(e,t)=>t===`none`||e.length<=3?e:t===`international`?e.replace(/\B(?=(\d{3})+(?!\d))/g,`,`):`${e.slice(0,-3).replace(/\B(?=(\d{2})+(?!\d))/g,`,`)},${e.slice(-3)}`,H=()=>typeof Intl<`u`&&typeof Intl.NumberFormat==`function`,U=(e,t)=>{if(H())return i(`en-US`,{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:t}).format(e);let n=Math.min(t,15);return B(Math.round(B(e,n)),-n).toFixed(n)},W=(e,t,n,r)=>{let i=Math.max(z(n),z(t)),a=z(t),o=U(Math.abs(e),i),[s=`0`,c=``]=o.split(`.`),l=c.padEnd(a,`0`);for(;l.length>a&&l.endsWith(`0`);)l=l.slice(0,-1);let u=V(s,r)+(l?`.${l}`:``);return e<0&&/[1-9]/.test(o)?`-${u}`:u},G=new Set([`grouping`,`minimumFractionDigits`,`maximumFractionDigits`,`locale`,`empty`,`scale`]),K=e=>{if(!Object.entries(e).some(([e,t])=>t!==void 0&&!G.has(e)))return null;let{grouping:t,locale:n,empty:r,scale:i,...a}=e;return t===`none`&&a.useGrouping===void 0?{...a,useGrouping:!1}:a},q=e=>e.locale??t().locale,J=t=>{let n=e();return n===null||t.grouping===`indian`||t.grouping===`international`?null:t.locale??n},Y=(e,t)=>{let n=z(e);return{minimumFractionDigits:n,maximumFractionDigits:Math.max(n,z(t))}},X=e=>e===`none`?{useGrouping:!1}:{},Z=(e,t={})=>{let r=R(e);if(r===null)return d(t.empty);let a=K(t);if(a)return i(q(t),a).format(r);let o=J(t);return o?i(o,{...Y(t.minimumFractionDigits??0,t.maximumFractionDigits??3),...X(t.grouping)}).format(r):W(r,t.minimumFractionDigits??0,t.maximumFractionDigits??3,t.grouping??n(q(t)))},Q=(e,t={})=>{let r=R(e);if(r===null)return d(t.empty);let a=K(t);if(a){let e=t.scale===`percent`?B(r,-2):r;return i(q(t),{style:`percent`,...a}).format(e)}let o=J(t);if(o){let e=t.scale===`percent`?B(r,-2):r;return i(o,{style:`percent`,...Y(t.minimumFractionDigits??0,t.maximumFractionDigits??t.minimumFractionDigits??0),...X(t.grouping)}).format(e)}return`${W(t.scale===`percent`?r:B(r,2),t.minimumFractionDigits??0,t.maximumFractionDigits??t.minimumFractionDigits??0,t.grouping??n(q(t)))}%`},$={INR:`₹`,USD:`$`,EUR:`€`,GBP:`£`},ee={JPY:0,KRW:0,VND:0,BHD:3,JOD:3,KWD:3,OMR:3,TND:3},te=(e,t={})=>{let n=R(e);if(n===null)return d(t.empty);let r=(t.currency??`INR`).toUpperCase(),a=ee[r]??2,o=Math.round(Math.abs(n)),s=String(o).padStart(a+1,`0`),c=s.slice(0,s.length-a),l=s.slice(s.length-a);t.dropZeroDecimals&&/^0*$/.test(l)&&(l=``);let u=J({grouping:t.grouping});if(u)try{let e=Number(`${n<0&&o!==0?`-`:``}${c}.${s.slice(s.length-a)||`0`}`);return i(u,{...t.symbol===!1?{}:{style:`currency`,currency:r},...Y(l?a:0,a),...X(t.grouping)}).format(e)}catch{}let f=V(c,t.grouping??(r===`INR`?`indian`:`international`))+(l?`.${l}`:``),p=n<0&&o!==0?`-`:``;if(t.symbol===!1)return`${p}${f}`;let m=$[r];return m?`${p}${m}${f}`:`${p}${r} ${f}`};export{E as formatDate,O as formatDateTime,te as formatMinor,Z as formatNumber,Q as formatPercent,L as formatRelative,D as formatTime};
1
+ import{configuredLocale as e,getFormatterConfig as t,groupingForLocale as n,numberSeparators as r,styledNumber as i}from"./formatConfig.js";import{dateTimeFormat as a,numberFormat as o,relativeTimeFormat as s}from"./intlCache.js";var c=[`Jan`,`Feb`,`Mar`,`Apr`,`May`,`Jun`,`Jul`,`Aug`,`Sep`,`Oct`,`Nov`,`Dec`],l=330,u=[`IST`,`Asia/Kolkata`,`Asia/Calcutta`],d=/^\d{4}-\d{2}-\d{2}$/,f=e=>e<10?`0${e}`:`${e}`,p=e=>e??t().empty,m=e=>{if(e==null||e===``)return null;let t=e instanceof Date?e:new Date(typeof e==`string`?e.trim():e);return Number.isNaN(t.getTime())?null:t},h=e=>typeof e==`string`&&d.test(e.trim()),g=e=>{if(e===0)return`GMT`;let t=e>0?`+`:`-`,n=Math.abs(e),r=n%60;return`GMT${t}${Math.floor(n/60)}${r===0?``:`:${f(r)}`}`},_=(e,t,n)=>{let r=new Date(e.getTime()+t*6e4);return{year:r.getUTCFullYear(),month:r.getUTCMonth(),day:r.getUTCDate(),hour:r.getUTCHours(),minute:r.getUTCMinutes(),label:n}},v=(e,t)=>{let n=a(`en-US`,{timeZone:t,year:`numeric`,month:`numeric`,day:`numeric`,hour:`numeric`,minute:`numeric`,hour12:!1}).formatToParts(e),r=e=>Number.parseInt(n.find(t=>t.type===e)?.value??``,10),i=r(`year`),o=r(`month`)-1,s=r(`day`),c=r(`hour`)%24,l=r(`minute`);return{year:i,month:o,day:s,hour:c,minute:l,label:g(Math.round((Date.UTC(i,o,s,c,l)-Math.floor(e.getTime()/6e4)*6e4)/6e4))}},y=(e,t)=>u.includes(t)?_(e,l,`IST`):t===`UTC`?_(e,0,`UTC`):t===`viewer`?{year:e.getFullYear(),month:e.getMonth(),day:e.getDate(),hour:e.getHours(),minute:e.getMinutes(),label:g(-e.getTimezoneOffset())}:v(e,t),b=e=>e.hourCycle??12,x=e=>`${f(e.day)}-${c[e.month]}-${e.year}`,S=(e,t)=>{let n=f(e.day),r=f(e.month+1),i=String(e.year).padStart(4,`0`);return t===`DayMonthYear`?`${n}/${r}/${i}`:t===`MonthDayYear`?`${r}/${n}/${i}`:`${i}-${r}-${n}`},C=(e,t)=>t===24?`${f(e.hour)}:${f(e.minute)}`:`${e.hour%12||12}:${f(e.minute)} ${e.hour<12?`AM`:`PM`}`,w=(e,t)=>t??!u.includes(e),T=(e,t,n,r)=>w(n,r)?`${e} ${t.label}`:e,E=e=>{if(e!==`viewer`)return u.includes(e)?`Asia/Kolkata`:e},D=(e,t,n)=>{let r=a(t,{day:`2-digit`,month:`short`,year:`numeric`,timeZone:n}).formatToParts(e),i=e=>r.find(t=>t.type===e)?.value??``;return`${i(`day`)}-${i(`month`).replace(`.`,``)}-${i(`year`)}`},O=(n,r)=>{let i=t().dateOrder??`DayMonthNameYear`;if(i!==`DayMonthNameYear`)return S(y(n,r),i);let a=e();return a?D(n,a,E(r)):x(y(n,r))},k=(e,t,n,r)=>a(t,{hour:`2-digit`,minute:`2-digit`,timeZone:E(n),timeZoneName:w(n,r.zoneLabel)?`short`:void 0,hourCycle:r.hourCycle===void 0?void 0:r.hourCycle===24?`h23`:`h12`}).format(e),A=(e,n={})=>{let r=m(e);return r?O(r,h(e)?`UTC`:n.zone??t().zone):p(n.empty)},ee=(n,r={})=>{let i=m(n);if(!i)return p(r.empty);let a=r.zone??t().zone,o=e();if(o)return k(i,o,a,r);let s=y(i,a);return T(C(s,b(r)),s,a,r.zoneLabel)},te=(n,r={})=>{let i=m(n);if(!i)return p(r.empty);let a=r.zone??t().zone,o=e();if(o)return`${O(i,a)}, ${k(i,o,a,r)}`;let s=y(i,a);return T(`${O(i,a)}, ${C(s,b(r))}`,s,a,r.zoneLabel)},j=1e3,M=60*j,N=60*M,P=24*N,F=7*P,I=30*P,L=365*P,R=[[`year`,L],[`month`,I],[`day`,P],[`hour`,N],[`minute`,M]],z=(n,r={})=>{let i=m(n),a=m(r.now??Date.now());if(!i||!a)return p(r.empty);let o=i.getTime()-a.getTime(),c=Math.abs(o),l=Intl.RelativeTimeFormat,u=e();if((u!==null||r.intl===!0)&&typeof l==`function`){let e=s(l,u??t().locale),[n,r]=R.find(([,e])=>c>=e)??[`second`,j];return e.format(Math.round(o/r),n)}if(c<M)return`just now`;let[d,f]=c<N?[`minute`,M]:c<P?[`hour`,N]:c<F?[`day`,P]:c<I?[`week`,F]:c<L?[`month`,I]:[`year`,L],h=Math.floor(c/f),g=`${h} ${d}${h===1?``:`s`}`;return o<0?`${g} ago`:`in ${g}`},B=e=>{if(e==null||typeof e==`string`&&e.trim()===``)return null;let t=typeof e==`number`?e:Number(e);return Number.isFinite(t)?t:null},V=e=>Math.min(20,Math.max(0,Math.trunc(e))),H=(e,t)=>/e/i.test(String(e))?e*10**t:Number(`${e}e${t}`),U=()=>r()??{decimal:`.`,group:`,`},W=(e,t,n)=>t===`none`||e.length<=3?e:t===`international`?e.replace(/\B(?=(\d{3})+(?!\d))/g,n):`${e.slice(0,-3).replace(/\B(?=(\d{2})+(?!\d))/g,n)}${n}${e.slice(-3)}`,G=()=>typeof Intl<`u`&&typeof Intl.NumberFormat==`function`,K=(e,t)=>{if(G())return o(`en-US`,{useGrouping:!1,minimumFractionDigits:0,maximumFractionDigits:t}).format(e);let n=Math.min(t,15);return H(Math.round(H(e,n)),-n).toFixed(n)},q=(e,t,n,r)=>{let i=Math.max(V(n),V(t)),a=V(t),o=K(Math.abs(e),i),[s=`0`,c=``]=o.split(`.`),l=c.padEnd(a,`0`);for(;l.length>a&&l.endsWith(`0`);)l=l.slice(0,-1);let u=U(),d=W(s,r,u.group)+(l?`${u.decimal}${l}`:``);return e<0&&/[1-9]/.test(o)?`-${d}`:d},J=new Set([`grouping`,`minimumFractionDigits`,`maximumFractionDigits`,`locale`,`empty`,`scale`]),Y=e=>{if(!Object.entries(e).some(([e,t])=>t!==void 0&&!J.has(e)))return null;let{grouping:t,locale:n,empty:r,scale:i,...a}=e;return t===`none`&&a.useGrouping===void 0?{...a,useGrouping:!1}:a},X=e=>e.locale??t().locale,Z=t=>{let n=e();return n===null||t.grouping===`indian`||t.grouping===`international`?null:t.locale??n},Q=(e,t)=>{let n=V(e);return{minimumFractionDigits:n,maximumFractionDigits:Math.max(n,V(t))}},$=e=>e===`none`?{useGrouping:!1}:{},ne=(e,t={})=>{let r=B(e);if(r===null)return p(t.empty);let a=Y(t);if(a)return i(o(X(t),a),r);let s=Z(t);return s?i(o(s,{...Q(t.minimumFractionDigits??0,t.maximumFractionDigits??3),...$(t.grouping)}),r):q(r,t.minimumFractionDigits??0,t.maximumFractionDigits??3,t.grouping??n(X(t)))},re=(e,t={})=>{let r=B(e);if(r===null)return p(t.empty);let a=Y(t);if(a){let e=t.scale===`percent`?H(r,-2):r;return i(o(X(t),{style:`percent`,...a}),e)}let s=Z(t);if(s){let e=t.scale===`percent`?H(r,-2):r;return i(o(s,{style:`percent`,...Q(t.minimumFractionDigits??0,t.maximumFractionDigits??t.minimumFractionDigits??0),...$(t.grouping)}),e)}return`${q(t.scale===`percent`?r:H(r,2),t.minimumFractionDigits??0,t.maximumFractionDigits??t.minimumFractionDigits??0,t.grouping??n(X(t)))}%`},ie={INR:`₹`,USD:`$`,EUR:`€`,GBP:`£`},ae={JPY:0,KRW:0,VND:0,BHD:3,JOD:3,KWD:3,OMR:3,TND:3},oe=(e,t={})=>{let n=B(e);if(n===null)return p(t.empty);let r=(t.currency??`INR`).toUpperCase(),a=ae[r]??2,s=Math.round(Math.abs(n)),c=String(s).padStart(a+1,`0`),l=c.slice(0,c.length-a),u=c.slice(c.length-a);t.dropZeroDecimals&&/^0*$/.test(u)&&(u=``);let d=Z({grouping:t.grouping});if(d)try{let e=Number(`${n<0&&s!==0?`-`:``}${l}.${c.slice(c.length-a)||`0`}`);return i(o(d,{...t.symbol===!1?{}:{style:`currency`,currency:r},...Q(u?a:0,a),...$(t.grouping)}),e)}catch{}let f=t.grouping??(r===`INR`?`indian`:`international`),m=U(),h=W(l,f,m.group)+(u?`${m.decimal}${u}`:``),g=n<0&&s!==0?`-`:``;if(t.symbol===!1)return`${g}${h}`;let _=ie[r];return _?`${g}${_}${h}`:`${g}${r} ${h}`};export{A as formatDate,te as formatDateTime,oe as formatMinor,ne as formatNumber,re as formatPercent,z as formatRelative,ee as formatTime};
@@ -25,6 +25,8 @@ export interface FormatCurrencyOptions extends Omit<Intl.NumberFormatOptions, "s
25
25
  * options: "₹1,50,000" for 150000, "₹1,234.50" for 1234.5, and `''` for a missing amount.
26
26
  * Once the app configures a locale (`configureFormatters({ locale })`), the amount is
27
27
  * written in that locale and a missing amount prints the configured placeholder ("-").
28
+ * A configured `numberStyle` sets the decimal mark and group separator; the locale keeps
29
+ * its group sizes and symbol placement ("₹1.50.000,50" for `'CommaWithPointGroups'`).
28
30
  * A numeric string reads as its number. For money the API carries in minor units (paise),
29
31
  * use `formatMinor`.
30
32
  *
@@ -12,12 +12,35 @@
12
12
  * "8:05 PM", "1,23,456.79"). Configuring a locale hands the words and
13
13
  * separators to Intl for that locale: month names, digit separators, the
14
14
  * 12- or 24-hour clock and its AM/PM casing, zone names and relative phrases.
15
- * The date order stays DD-MMM-YYYY either way.
15
+ * The date order stays DD-MMM-YYYY either way, unless a date order is set.
16
+ *
17
+ * Personal style: a product that lets a person choose how numbers and dates
18
+ * read sets `numberStyle` and `dateOrder`. The number style swaps only the
19
+ * decimal mark and the group separator, so the locale's group sizes (en-IN's
20
+ * 12,34,567) and its currency symbol placement stay. The date order changes
21
+ * only the date; the time of day, the zone and relative phrases are untouched.
16
22
  */
17
23
  /** `'IST'`: every instant in India Standard Time. `'viewer'`: the device or browser zone, labelled. */
18
24
  export type ZoneMode = "IST" | "viewer";
19
25
  /** How the integer part of a number is grouped. */
20
26
  export type NumberGrouping = "indian" | "international" | "none";
27
+ /**
28
+ * The decimal mark and group separator of every number: `'PointWithCommaGroups'` "1,234.5",
29
+ * `'CommaWithPointGroups'` "1.234,5", `'CommaWithSpaceGroups'` "1 234,5", `'PointWithSpaceGroups'`
30
+ * "1 234.5". The space is a no-break space (U+00A0), so a number never wraps.
31
+ */
32
+ export type NumberStyle = "PointWithCommaGroups" | "CommaWithPointGroups" | "CommaWithSpaceGroups" | "PointWithSpaceGroups";
33
+ /**
34
+ * The order of every date: `'DayMonthNameYear'` "09-Oct-2026" (the house order, month name from the
35
+ * locale when one is configured), `'DayMonthYear'` "09/10/2026", `'MonthDayYear'` "10/09/2026",
36
+ * `'YearMonthDay'` "2026-10-09".
37
+ */
38
+ export type DateOrder = "DayMonthNameYear" | "DayMonthYear" | "MonthDayYear" | "YearMonthDay";
39
+ /** The two characters a number style puts in a number. */
40
+ export interface NumberSeparators {
41
+ decimal: string;
42
+ group: string;
43
+ }
21
44
  export interface FormatterConfig {
22
45
  /** Default zone for every date and time formatter. */
23
46
  zone: ZoneMode;
@@ -30,11 +53,17 @@ export interface FormatterConfig {
30
53
  locale: string;
31
54
  /** What every formatter returns for a missing or unreadable value. */
32
55
  empty: string;
56
+ /** The person's number style. Unset, the separators are the house text's or the configured locale's. */
57
+ numberStyle?: NumberStyle;
58
+ /** The person's date order. Unset, dates read DD-MMM-YYYY. */
59
+ dateOrder?: DateOrder;
33
60
  }
34
61
  /**
35
- * Set the zone mode, locale or empty placeholder for the whole app. Call it
36
- * once at startup; a key left out (or undefined) keeps its current value.
37
- * Passing nothing restores the defaults (IST, en-IN, "-", house text).
62
+ * Set the zone mode, locale, empty placeholder, number style or date order for the whole app.
63
+ * Call it at startup, and again when the person changes their number style or date order; a key
64
+ * left out (or undefined) keeps its current value. Passing nothing restores the defaults (IST,
65
+ * en-IN, "-", house text, no number style or date order). An unknown number style or date order
66
+ * throws a RangeError, so a bad stored preference fails where it is applied.
38
67
  */
39
68
  export declare const configureFormatters: (config?: Partial<FormatterConfig>) => void;
40
69
  /** The settings in force, as a copy. */
@@ -45,3 +74,10 @@ export declare const isFormatterConfigured: (key: keyof FormatterConfig) => bool
45
74
  export declare const configuredLocale: () => string | null;
46
75
  /** The grouping a locale implies: Indian for a locale whose region is IN. */
47
76
  export declare const groupingForLocale: (locale: string) => NumberGrouping;
77
+ /** The configured number style's separators, else null (the house text's or the locale's own). */
78
+ export declare const numberSeparators: () => NumberSeparators | null;
79
+ /**
80
+ * `format.format(n)`, with the configured number style's decimal mark and group separator in place
81
+ * of the locale's. Only those two parts change, so group sizes, signs and symbols stay the locale's.
82
+ */
83
+ export declare const styledNumber: (format: Intl.NumberFormat, n: number) => string;
@@ -26,6 +26,11 @@
26
26
  * from Intl for that locale and the date order stays DD-MMM-YYYY. For en-IN in the viewer zone:
27
27
  * "08-Sept-2026", "08:05 pm", "08-Sept-2026, 08:05 pm IST", "yesterday", "12,34,567.891",
28
28
  * "₹1,50,000". For de-DE: "08-Sept-2026", "20:05", "1.234.567,891".
29
+ *
30
+ * A configured `numberStyle` puts its decimal mark and group separator in every number and amount,
31
+ * whichever path wrote it: "1.23.456,789" for `'CommaWithPointGroups'` with the house text. A
32
+ * configured `dateOrder` other than DD-MMM-YYYY writes the date as digits from the wall clock,
33
+ * in every locale: "08/04/2026", "04/08/2026", "2026-04-08".
29
34
  */
30
35
  import { type NumberGrouping, type ZoneMode } from "./formatConfig";
31
36
  /** A date the house formatters accept; null, undefined and "" read as missing. */
@@ -102,8 +107,8 @@ export interface FormatMinorOptions {
102
107
  empty?: string;
103
108
  }
104
109
  /**
105
- * "08-Apr-2026". A bare calendar date ("2026-04-08") always shows as that day;
106
- * an instant shows its day in the configured zone.
110
+ * "08-Apr-2026", or the configured date order. A bare calendar date ("2026-04-08")
111
+ * always shows as that day; an instant shows its day in the configured zone.
107
112
  */
108
113
  export declare const formatDate: (value: DateValue, options?: FormatDateOptions) => string;
109
114
  /** "8:05 PM" in IST, "8:05 PM GMT-4" in the viewer's zone; "20:05" for a configured locale with a 24-hour clock. */
@@ -1,7 +1,7 @@
1
1
  export type { FormatCurrencyOptions } from "./currency";
2
2
  export { formatCurrency } from "./currency";
3
3
  export { addDays } from "./dateMath";
4
- export type { FormatterConfig, NumberGrouping, ZoneMode } from "./formatConfig";
4
+ export type { DateOrder, FormatterConfig, NumberGrouping, NumberStyle, ZoneMode } from "./formatConfig";
5
5
  export { configureFormatters, getFormatterConfig } from "./formatConfig";
6
6
  export type { DateValue, FormatDateOptions, FormatDateTimeOptions, FormatMinorOptions, FormatNumberOptions, FormatPercentOptions, FormatRelativeOptions, FormatTimeOptions, ZoneOption, } from "./house";
7
7
  export { formatDate, formatDateTime, formatMinor, formatNumber, formatPercent, formatRelative, formatTime, } from "./house";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/web-core",
3
- "version": "0.41.3",
3
+ "version": "0.43.0",
4
4
  "description": "Platform layer for Webority React web portals: HTTP clients with single-flight token refresh, auth store, API error extraction, RTK Query base query, logger, formatters, storage, version check and route guards. No UI.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",