@archerjessop/utilities 4.6.9 → 4.6.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- const formatInputDisplay=(t,e)=>{const r=parseFloat(t)||0,n=r%1!=0;switch(e){case"currency":return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:n?2:0,maximumFractionDigits:2}).format(r);case"percent":return new Intl.NumberFormat("en-US",{minimumFractionDigits:n&&Math.abs(r)>=.1?1:n?3:0,maximumFractionDigits:Math.abs(r)<1?3:2}).format(r)+"%";case"years":return new Intl.NumberFormat("en-US",{minimumFractionDigits:n?1:0,maximumFractionDigits:1}).format(r)+" yrs.";case"months":return new Intl.NumberFormat("en-US",{minimumFractionDigits:0,maximumFractionDigits:0}).format(r)+" mos.";case"number":return new Intl.NumberFormat("en-US",{minimumFractionDigits:n?2:0,maximumFractionDigits:2}).format(r);default:return t}},parseNumericInput=t=>{if(null==t)return 0;const e=t.toString().replace(/[^0-9.-]/g,"");return parseFloat(e)||0},filterNumericInput=(t,e=!0)=>{if(!t)return"";let r=t.toString();if(r=r.replace(/[^0-9.-]/g,""),e){if((r.match(/-/g)||[]).length>1){const e=t.toString().trim().startsWith("-");r=r.replace(/-/g,""),e&&(r="-"+r)}else r.includes("-")&&!r.startsWith("-")&&(r="-"+r.replace(/-/g,""))}else r=r.replace(/-/g,"");if((r.match(/\./g)||[]).length>1){const t=r.split(".");r=t[0]+"."+t.slice(1).join("")}return r},formatLiveNumber=(t,e="default",r=!1)=>{if(!t&&0!==t)return"";const n=t.toString(),a=parseFloat(n);if(isNaN(a))return"";const i=a<0,s=i?n.substring(1):n;let c;if(s.includes("."))if(r){const[t,e]=s.split(".");c=t.replace(/\B(?=(\d{3})+(?!\d))/g,",")+"."+e}else if("months"===e){c=Math.round(Math.abs(a)).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}else if("percent"===e||"years"===e){let t=Math.abs(a).toFixed(2);t=t.replace(/\.?0+$/,"");const[e,r]=t.split("."),n=e.replace(/\B(?=(\d{3})+(?!\d))/g,",");c=r?n+"."+r:n}else{const t=Math.abs(a).toFixed(2),[e,r]=t.split(".");c=e.replace(/\B(?=(\d{3})+(?!\d))/g,",")+"."+r}else{c=Math.floor(Math.abs(a)).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}return i?"-"+c:c},formatLiveInput=(t,e,r=!1)=>{const n=filterNumericInput(t,!0);let a=formatLiveNumber(n,e,r);switch(""!==a&&null!=a||(a="0"),e){case"currency":return"$ "+a;case"percent":return a+" %";case"years":return a+" yrs.";case"months":return a+" mos.";default:return a}},calculateCursorPosition=(t,e,r,n)=>{if(r<=0)return 0;if(r>=t.length){if("currency"===n)return e.length;{const t=e.match(/^[0-9,.-]+/);return t?t[0].length:0}}let a=0;for(let e=0;e<r;e++)","!==t[e]&&a++;let i=0;for(let t=0;t<e.length&&("currency"===n||!/[a-zA-Z]/.test(e[t]));t++){if(i===a)return","===e[t]?t+1:t;","!==e[t]&&" "!==e[t]&&i++}if("currency"===n)return e.length;{const t=e.match(/^[0-9,.\s-]+/);return t?Math.min(t[0].length,e.length):0}},extractNumericValue=(t,e)=>{if(!t)return 0;let r=t.toString();switch(e){case"currency":r=r.replace(/^\$\s*/,"").trim();break;case"percent":r=r.replace(/\s*%$/,"").trim();break;case"years":r=r.replace(/\s*yrs\.$/,"").trim();break;case"months":r=r.replace(/\s*mos\.$/,"").trim()}return r=r.replace(/,/g,""),parseFloat(r)||0};export{calculateCursorPosition,extractNumericValue,filterNumericInput,formatInputDisplay,formatLiveInput,formatLiveNumber,parseNumericInput};
1
+ const formatInputDisplay=(t,e)=>{const r=parseFloat(t)||0,n=r%1!=0;switch(e){case"currency":return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:n?2:0,maximumFractionDigits:2}).format(r);case"percent":return new Intl.NumberFormat("en-US",{minimumFractionDigits:n&&Math.abs(r)>=.1?1:n?3:0,maximumFractionDigits:Math.abs(r)<1?3:2}).format(r)+"%";case"years":return new Intl.NumberFormat("en-US",{minimumFractionDigits:n?1:0,maximumFractionDigits:1}).format(r)+" yrs.";case"months":return new Intl.NumberFormat("en-US",{minimumFractionDigits:0,maximumFractionDigits:0}).format(r)+" mos.";case"number":return new Intl.NumberFormat("en-US",{minimumFractionDigits:n?2:0,maximumFractionDigits:2}).format(r);default:return t}},parseNumericInput=t=>{if(null==t)return 0;const e=t.toString().replace(/[^0-9.-]/g,"");return parseFloat(e)||0},filterNumericInput=(t,e=!0)=>{if(!t)return"";let r=t.toString();if(r=r.replace(/[^0-9.-]/g,""),e){if((r.match(/-/g)||[]).length>1){const e=t.toString().trim().startsWith("-");r=r.replace(/-/g,""),e&&(r="-"+r)}else r.includes("-")&&!r.startsWith("-")&&(r="-"+r.replace(/-/g,""))}else r=r.replace(/-/g,"");if((r.match(/\./g)||[]).length>1){const t=r.split(".");r=t[0]+"."+t.slice(1).join("")}return r},formatLiveNumber=(t,e="default",r=!1)=>{if(!t&&0!==t)return"";const n=t.toString(),s=parseFloat(n);if(isNaN(s))return"";const a=s<0,i=a?n.substring(1):n;let c;if(i.includes("."))if(r){const[t,e]=i.split(".");c=t.replace(/\B(?=(\d{3})+(?!\d))/g,",")+"."+e}else if("months"===e){c=Math.round(Math.abs(s)).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}else if("percent"===e||"years"===e){let t=Math.abs(s).toFixed(2);t=t.replace(/\.?0+$/,"");const[e,r]=t.split("."),n=e.replace(/\B(?=(\d{3})+(?!\d))/g,",");c=r?n+"."+r:n}else{const t=Math.abs(s).toFixed(2),[e,r]=t.split(".");c=e.replace(/\B(?=(\d{3})+(?!\d))/g,",")+"."+r}else{c=Math.floor(Math.abs(s)).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}return a?"-"+c:c},formatLiveInput=(t,e,r=!1)=>{const n=filterNumericInput(t,!0);let s=formatLiveNumber(n,e,r);switch(""!==s&&null!=s||(s="0"),e){case"currency":return"$ "+s;case"percent":return s+" %";case"years":return s+" yrs.";case"months":return s+" mos.";default:return s}},calculateCursorPosition=(t,e,r,n)=>{if(r<=0)return 0;if(r>=t.length){if("currency"===n)return e.length;{const t=e.match(/^[0-9,.\-\s]+/);return t?t[0].length:0}}const getPrefixLength=(t,e)=>"currency"===e&&t.startsWith("$ ")?2:0,getContentEnd=(t,e,r)=>{const n=t.substring(r);if("percent"===e){const t=n.match(/^([0-9,.\-]+)/);return t?t[1].length:n.length}if("years"===e){const t=n.match(/^([0-9,.\-]+)/);return t?t[1].length:n.length}if("months"===e){const t=n.match(/^([0-9,.\-]+)/);return t?t[1].length:n.length}return n.length},s=getPrefixLength(t,n),a=getPrefixLength(e,n),i=getContentEnd(t,n,s),c=getContentEnd(e,n,a),l=Math.max(0,r-s),o=Math.min(l,i),m=t.substring(s,s+i);let u=0;for(let t=0;t<o;t++){const e=m[t];/[0-9.\-]/.test(e)&&u++}const g=e.substring(a,a+c);let h=0,f=0;for(let t=0;t<g.length;t++){const e=g[t];if(/[0-9.\-]/.test(e)&&(f++,f===u)){h=t+1<g.length&&","===g[t+1]?t+2:t+1;break}}0===u&&(h=0);const p=a+h,F=a+c;return Math.min(p,F)},extractNumericValue=(t,e)=>{if(!t)return 0;let r=t.toString();switch(e){case"currency":r=r.replace(/^\$\s*/,"").trim();break;case"percent":r=r.replace(/\s*%$/,"").trim();break;case"years":r=r.replace(/\s*yrs\.$/,"").trim();break;case"months":r=r.replace(/\s*mos\.$/,"").trim()}return r=r.replace(/,/g,""),parseFloat(r)||0};export{calculateCursorPosition,extractNumericValue,filterNumericInput,formatInputDisplay,formatLiveInput,formatLiveNumber,parseNumericInput};
2
2
  //# sourceMappingURL=financial-formatting.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"financial-formatting.js","sources":["../../src/formatting/financial-formatting.js"],"sourcesContent":["// Enhanced formatting for input fields\r\nexport const formatInputDisplay = (value, type) => {\r\n const num = parseFloat(value) || 0;\r\n const hasDecimals = num % 1 !== 0;\r\n \r\n switch (type) {\r\n case \"currency\":\r\n return new Intl.NumberFormat(\"en-US\", {\r\n style: \"currency\",\r\n currency: \"USD\",\r\n minimumFractionDigits: hasDecimals ? 2 : 0,\r\n maximumFractionDigits: 2\r\n }).format(num);\r\n \r\n case \"percent\":\r\n return new Intl.NumberFormat(\"en-US\", {\r\n minimumFractionDigits: hasDecimals && Math.abs(num) >= 0.1 ? 1 : hasDecimals ? 3 : 0,\r\n maximumFractionDigits: Math.abs(num) < 1 ? 3 : 2\r\n }).format(num) + \"%\";\r\n \r\n case \"years\":\r\n return new Intl.NumberFormat(\"en-US\", {\r\n minimumFractionDigits: hasDecimals ? 1 : 0,\r\n maximumFractionDigits: 1\r\n }).format(num) + \" yrs.\";\r\n \r\n case \"months\":\r\n return new Intl.NumberFormat(\"en-US\", {\r\n minimumFractionDigits: 0,\r\n maximumFractionDigits: 0\r\n }).format(num) + \" mos.\";\r\n \r\n case \"number\":\r\n return new Intl.NumberFormat(\"en-US\", {\r\n minimumFractionDigits: hasDecimals ? 2 : 0,\r\n maximumFractionDigits: 2\r\n }).format(num);\r\n \r\n default:\r\n return value;\r\n }\r\n};\r\n\r\nexport const parseNumericInput = (value) => {\r\n // Handle null, undefined, or non-string inputs\r\n if (value === null || value === undefined) {\r\n return 0;\r\n }\r\n \r\n // Remove all non-numeric characters except decimal point and negative sign\r\n const cleaned = value.toString().replace(/[^0-9.-]/g, \"\");\r\n return parseFloat(cleaned) || 0;\r\n};\r\n\r\n// Add these functions to the existing file:\r\n\r\nexport const filterNumericInput = (value, allowNegative = true) => {\r\n if (!value) return \"\";\r\n \r\n let filtered = value.toString();\r\n \r\n // Remove symbols and text, keep only numbers, decimal, and negative\r\n // This regex keeps numeric chars, decimal point, and negative sign\r\n filtered = filtered.replace(/[^0-9.-]/g, \"\");\r\n \r\n // Handle negative sign - only allow at the beginning\r\n if (allowNegative) {\r\n const negativeCount = (filtered.match(/-/g) || []).length;\r\n if (negativeCount > 1) {\r\n // Remove extra negative signs, keep only the first one if input started with -\r\n const startsWithNegative = value.toString().trim().startsWith(\"-\");\r\n filtered = filtered.replace(/-/g, \"\");\r\n if (startsWithNegative) {\r\n filtered = \"-\" + filtered;\r\n }\r\n } else if (filtered.includes(\"-\") && !filtered.startsWith(\"-\")) {\r\n // Move negative to the front if it's not already there\r\n filtered = \"-\" + filtered.replace(/-/g, \"\");\r\n }\r\n } else {\r\n filtered = filtered.replace(/-/g, \"\");\r\n }\r\n \r\n // Handle decimal - only allow one decimal point\r\n const decimalCount = (filtered.match(/\\./g) || []).length;\r\n if (decimalCount > 1) {\r\n const parts = filtered.split(\".\");\r\n filtered = parts[0] + \".\" + parts.slice(1).join(\"\");\r\n }\r\n \r\n return filtered;\r\n};\r\n\r\nexport const formatLiveNumber = (value, type = \"default\", preserveTyping = false) => {\r\n if (!value && value !== 0) return \"\";\r\n \r\n const originalStr = value.toString();\r\n const num = parseFloat(originalStr);\r\n if (isNaN(num)) return \"\";\r\n \r\n const isNegative = num < 0;\r\n const absStr = isNegative ? originalStr.substring(1) : originalStr;\r\n const hasDecimal = absStr.includes(\".\");\r\n \r\n let result;\r\n \r\n if (!hasDecimal) {\r\n // No decimal point - format as integer\r\n const intStr = Math.floor(Math.abs(num)).toString();\r\n result = intStr.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n } else {\r\n // Has decimal point\r\n if (preserveTyping) {\r\n // LIVE TYPING: Preserve exactly what user typed, just add commas\r\n const [intPart, decPart] = absStr.split(\".\");\r\n const commaInt = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n result = commaInt + \".\" + decPart;\r\n } else {\r\n // FINAL FORMATTING: Apply type-specific decimal rules\r\n if (type === \"months\") {\r\n const rounded = Math.round(Math.abs(num));\r\n result = rounded.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n } else if (type === \"percent\" || type === \"years\") {\r\n let formatted = Math.abs(num).toFixed(2);\r\n formatted = formatted.replace(/\\.?0+$/, '');\r\n const [intPart, decPart] = formatted.split(\".\");\r\n const commaInt = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n result = decPart ? commaInt + \".\" + decPart : commaInt;\r\n } else {\r\n // Currency: always 2 decimal places\r\n const twoDecimal = Math.abs(num).toFixed(2);\r\n const [intPart, decPart] = twoDecimal.split(\".\");\r\n const commaInt = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n result = commaInt + \".\" + decPart;\r\n }\r\n }\r\n }\r\n \r\n return isNegative ? \"-\" + result : result;\r\n};\r\n\r\nexport const formatLiveInput = (value, type, preserveTyping = false) => {\r\n const filtered = filterNumericInput(value, true);\r\n let formatted = formatLiveNumber(filtered, type, preserveTyping);\r\n \r\n if (formatted === \"\" || formatted === null || formatted === undefined) formatted = \"0\";\r\n \r\n switch (type) {\r\n case \"currency\":\r\n return \"$ \" + formatted;\r\n case \"percent\":\r\n return formatted + \" %\";\r\n case \"years\":\r\n return formatted + \" yrs.\";\r\n case \"months\":\r\n return formatted + \" mos.\";\r\n case \"number\":\r\n return formatted;\r\n default:\r\n return formatted;\r\n }\r\n};\r\n\r\nexport const calculateCursorPosition = (oldValue, newValue, oldCursor, type) => {\r\n if (oldCursor <= 0) return 0;\r\n if (oldCursor >= oldValue.length) {\r\n // Cursor was at end - handle based on format type\r\n if (type === \"currency\") {\r\n // Currency: cursor can go to the very end\r\n return newValue.length;\r\n } else {\r\n // Percentage, years, months: cursor stays before suffix symbols\r\n const match = newValue.match(/^[0-9,.-]+/);\r\n return match ? match[0].length : 0;\r\n }\r\n }\r\n \r\n // Count logical characters before cursor position in old value\r\n let logicalCharsBefore = 0;\r\n for (let i = 0; i < oldCursor; i++) {\r\n if (oldValue[i] !== ',') {\r\n logicalCharsBefore++;\r\n }\r\n }\r\n \r\n // Find position after the same number of logical characters in new value\r\n let charsProcessed = 0;\r\n \r\n for (let i = 0; i < newValue.length; i++) {\r\n // For non-currency types, stop before suffix symbols\r\n if (type !== \"currency\" && /[a-zA-Z]/.test(newValue[i])) {\r\n break;\r\n }\r\n \r\n // If we've found all the logical characters we need\r\n if (charsProcessed === logicalCharsBefore) {\r\n return newValue[i] === ',' ? i + 1 : i;\r\n }\r\n \r\n // Count non-comma, non-space characters (but for currency, allow $ in count)\r\n if (newValue[i] !== ',' && newValue[i] !== ' ') {\r\n charsProcessed++;\r\n }\r\n }\r\n \r\n // Fallback: find appropriate end position based on type\r\n if (type === \"currency\") {\r\n return newValue.length;\r\n } else {\r\n const match = newValue.match(/^[0-9,.\\s-]+/);\r\n return match ? Math.min(match[0].length, newValue.length) : 0;\r\n }\r\n};\r\n\r\nexport const extractNumericValue = (formattedValue, type) => {\r\n if (!formattedValue) return 0;\r\n \r\n let cleaned = formattedValue.toString();\r\n \r\n switch (type) {\r\n case \"currency\":\r\n cleaned = cleaned.replace(/^\\$\\s*/, \"\").trim();\r\n break;\r\n case \"percent\":\r\n cleaned = cleaned.replace(/\\s*%$/, \"\").trim();\r\n break;\r\n case \"years\":\r\n cleaned = cleaned.replace(/\\s*yrs\\.$/, \"\").trim();\r\n break;\r\n case \"months\":\r\n cleaned = cleaned.replace(/\\s*mos\\.$/, \"\").trim();\r\n break;\r\n }\r\n \r\n cleaned = cleaned.replace(/,/g, \"\");\r\n return parseFloat(cleaned) || 0;\r\n};"],"names":["formatInputDisplay","value","type","num","parseFloat","hasDecimals","Intl","NumberFormat","style","currency","minimumFractionDigits","maximumFractionDigits","format","Math","abs","parseNumericInput","cleaned","toString","replace","filterNumericInput","allowNegative","filtered","match","length","startsWithNegative","trim","startsWith","includes","parts","split","slice","join","formatLiveNumber","preserveTyping","originalStr","isNaN","isNegative","absStr","substring","result","intPart","decPart","round","formatted","toFixed","commaInt","twoDecimal","floor","formatLiveInput","calculateCursorPosition","oldValue","newValue","oldCursor","logicalCharsBefore","i","charsProcessed","test","min","extractNumericValue","formattedValue"],"mappings":"AACY,MAACA,mBAAqB,CAACC,EAAOC,KACxC,MAAMC,EAAMC,WAAWH,IAAU,EAC3BI,EAAcF,EAAM,GAAM,EAEhC,OAAQD,GACN,IAAK,WACH,OAAO,IAAII,KAAKC,aAAa,QAAS,CACpCC,MAAO,WACPC,SAAU,MACVC,sBAAuBL,EAAc,EAAI,EACzCM,sBAAuB,IACtBC,OAAOT,GAEZ,IAAK,UACH,OAAO,IAAIG,KAAKC,aAAa,QAAS,CACpCG,sBAAuBL,GAAeQ,KAAKC,IAAIX,IAAQ,GAAM,EAAIE,EAAc,EAAI,EACnFM,sBAAuBE,KAAKC,IAAIX,GAAO,EAAI,EAAI,IAC9CS,OAAOT,GAAO,IAEnB,IAAK,QACH,OAAO,IAAIG,KAAKC,aAAa,QAAS,CACpCG,sBAAuBL,EAAc,EAAI,EACzCM,sBAAuB,IACtBC,OAAOT,GAAO,QAEnB,IAAK,SACH,OAAO,IAAIG,KAAKC,aAAa,QAAS,CACpCG,sBAAuB,EACvBC,sBAAuB,IACtBC,OAAOT,GAAO,QAEnB,IAAK,SACH,OAAO,IAAIG,KAAKC,aAAa,QAAS,CACpCG,sBAAuBL,EAAc,EAAI,EACzCM,sBAAuB,IACtBC,OAAOT,GAEZ,QACE,OAAOF,IAIAc,kBAAqBd,IAEhC,GAAIA,QACF,OAAO,EAIT,MAAMe,EAAUf,EAAMgB,WAAWC,QAAQ,YAAa,IACtD,OAAOd,WAAWY,IAAY,GAKnBG,mBAAqB,CAAClB,EAAOmB,GAAgB,KACxD,IAAKnB,EAAO,MAAO,GAEnB,IAAIoB,EAAWpB,EAAMgB,WAOrB,GAHAI,EAAWA,EAASH,QAAQ,YAAa,IAGrCE,EAAe,CAEjB,IADuBC,EAASC,MAAM,OAAS,IAAIC,OAC/B,EAAG,CAErB,MAAMC,EAAqBvB,EAAMgB,WAAWQ,OAAOC,WAAW,KAC9DL,EAAWA,EAASH,QAAQ,KAAM,IAC9BM,IACFH,EAAW,IAAMA,EAErB,MAAWA,EAASM,SAAS,OAASN,EAASK,WAAW,OAExDL,EAAW,IAAMA,EAASH,QAAQ,KAAM,IAE5C,MACEG,EAAWA,EAASH,QAAQ,KAAM,IAKpC,IADsBG,EAASC,MAAM,QAAU,IAAIC,OAChC,EAAG,CACpB,MAAMK,EAAQP,EAASQ,MAAM,KAC7BR,EAAWO,EAAM,GAAK,IAAMA,EAAME,MAAM,GAAGC,KAAK,GAClD,CAEA,OAAOV,GAGIW,iBAAmB,CAAC/B,EAAOC,EAAO,UAAW+B,GAAiB,KACzE,IAAKhC,GAAmB,IAAVA,EAAa,MAAO,GAElC,MAAMiC,EAAcjC,EAAMgB,WACpBd,EAAMC,WAAW8B,GACvB,GAAIC,MAAMhC,GAAM,MAAO,GAEvB,MAAMiC,EAAajC,EAAM,EACnBkC,EAASD,EAAaF,EAAYI,UAAU,GAAKJ,EAGvD,IAAIK,EAEJ,GAJmBF,EAAOV,SAAS,KAUjC,GAAIM,EAAgB,CAElB,MAAOO,EAASC,GAAWJ,EAAOR,MAAM,KAExCU,EADiBC,EAAQtB,QAAQ,wBAAyB,KACtC,IAAMuB,CAC5B,MAEE,GAAa,WAATvC,EAAmB,CAErBqC,EADgB1B,KAAK6B,MAAM7B,KAAKC,IAAIX,IACnBc,WAAWC,QAAQ,wBAAyB,IAC/D,MAAO,GAAa,YAAThB,GAA+B,UAATA,EAAkB,CACjD,IAAIyC,EAAY9B,KAAKC,IAAIX,GAAKyC,QAAQ,GACtCD,EAAYA,EAAUzB,QAAQ,SAAU,IACxC,MAAOsB,EAASC,GAAWE,EAAUd,MAAM,KACrCgB,EAAWL,EAAQtB,QAAQ,wBAAyB,KAC1DqB,EAASE,EAAUI,EAAW,IAAMJ,EAAUI,CAChD,KAAO,CAEL,MAAMC,EAAajC,KAAKC,IAAIX,GAAKyC,QAAQ,IAClCJ,EAASC,GAAWK,EAAWjB,MAAM,KAE5CU,EADiBC,EAAQtB,QAAQ,wBAAyB,KACtC,IAAMuB,CAC5B,KA5Ba,CAGfF,EADe1B,KAAKkC,MAAMlC,KAAKC,IAAIX,IAAMc,WACzBC,QAAQ,wBAAyB,IACnD,CA4BA,OAAOkB,EAAa,IAAMG,EAASA,GAGxBS,gBAAkB,CAAC/C,EAAOC,EAAM+B,GAAiB,KAC5D,MAAMZ,EAAWF,mBAAmBlB,GAAO,GAC3C,IAAI0C,EAAYX,iBAAiBX,EAAUnB,EAAM+B,GAIjD,OAFkB,KAAdU,SAAoBA,IAA+CA,EAAY,KAE3EzC,GACN,IAAK,WACH,MAAO,KAAOyC,EAChB,IAAK,UACH,OAAOA,EAAY,KACrB,IAAK,QACH,OAAOA,EAAY,QACrB,IAAK,SACH,OAAOA,EAAY,QAGrB,QACE,OAAOA,IAIAM,wBAA0B,CAACC,EAAUC,EAAUC,EAAWlD,KACrE,GAAIkD,GAAa,EAAG,OAAO,EAC3B,GAAIA,GAAaF,EAAS3B,OAAQ,CAEhC,GAAa,aAATrB,EAEF,OAAOiD,EAAS5B,OACX,CAEL,MAAMD,EAAQ6B,EAAS7B,MAAM,cAC7B,OAAOA,EAAQA,EAAM,GAAGC,OAAS,CACnC,CACF,CAGA,IAAI8B,EAAqB,EACzB,IAAK,IAAIC,EAAI,EAAGA,EAAIF,EAAWE,IACT,MAAhBJ,EAASI,IACXD,IAKJ,IAAIE,EAAiB,EAErB,IAAK,IAAID,EAAI,EAAGA,EAAIH,EAAS5B,SAEd,aAATrB,IAAuB,WAAWsD,KAAKL,EAASG,KAFjBA,IAAK,CAOxC,GAAIC,IAAmBF,EACrB,MAAuB,MAAhBF,EAASG,GAAaA,EAAI,EAAIA,EAInB,MAAhBH,EAASG,IAA8B,MAAhBH,EAASG,IAClCC,GAEJ,CAGA,GAAa,aAATrD,EACF,OAAOiD,EAAS5B,OACX,CACL,MAAMD,EAAQ6B,EAAS7B,MAAM,gBAC7B,OAAOA,EAAQT,KAAK4C,IAAInC,EAAM,GAAGC,OAAQ4B,EAAS5B,QAAU,CAC9D,GAGWmC,oBAAsB,CAACC,EAAgBzD,KAClD,IAAKyD,EAAgB,OAAO,EAE5B,IAAI3C,EAAU2C,EAAe1C,WAE7B,OAAQf,GACN,IAAK,WACHc,EAAUA,EAAQE,QAAQ,SAAU,IAAIO,OACxC,MACF,IAAK,UACHT,EAAUA,EAAQE,QAAQ,QAAS,IAAIO,OACvC,MACF,IAAK,QACHT,EAAUA,EAAQE,QAAQ,YAAa,IAAIO,OAC3C,MACF,IAAK,SACHT,EAAUA,EAAQE,QAAQ,YAAa,IAAIO,OAK/C,OADAT,EAAUA,EAAQE,QAAQ,KAAM,IACzBd,WAAWY,IAAY"}
1
+ {"version":3,"file":"financial-formatting.js","sources":["../../src/formatting/financial-formatting.js"],"sourcesContent":["// Enhanced formatting for input fields\r\nexport const formatInputDisplay = (value, type) => {\r\n const num = parseFloat(value) || 0;\r\n const hasDecimals = num % 1 !== 0;\r\n \r\n switch (type) {\r\n case \"currency\":\r\n return new Intl.NumberFormat(\"en-US\", {\r\n style: \"currency\",\r\n currency: \"USD\",\r\n minimumFractionDigits: hasDecimals ? 2 : 0,\r\n maximumFractionDigits: 2\r\n }).format(num);\r\n \r\n case \"percent\":\r\n return new Intl.NumberFormat(\"en-US\", {\r\n minimumFractionDigits: hasDecimals && Math.abs(num) >= 0.1 ? 1 : hasDecimals ? 3 : 0,\r\n maximumFractionDigits: Math.abs(num) < 1 ? 3 : 2\r\n }).format(num) + \"%\";\r\n \r\n case \"years\":\r\n return new Intl.NumberFormat(\"en-US\", {\r\n minimumFractionDigits: hasDecimals ? 1 : 0,\r\n maximumFractionDigits: 1\r\n }).format(num) + \" yrs.\";\r\n \r\n case \"months\":\r\n return new Intl.NumberFormat(\"en-US\", {\r\n minimumFractionDigits: 0,\r\n maximumFractionDigits: 0\r\n }).format(num) + \" mos.\";\r\n \r\n case \"number\":\r\n return new Intl.NumberFormat(\"en-US\", {\r\n minimumFractionDigits: hasDecimals ? 2 : 0,\r\n maximumFractionDigits: 2\r\n }).format(num);\r\n \r\n default:\r\n return value;\r\n }\r\n};\r\n\r\nexport const parseNumericInput = (value) => {\r\n // Handle null, undefined, or non-string inputs\r\n if (value === null || value === undefined) {\r\n return 0;\r\n }\r\n \r\n // Remove all non-numeric characters except decimal point and negative sign\r\n const cleaned = value.toString().replace(/[^0-9.-]/g, \"\");\r\n return parseFloat(cleaned) || 0;\r\n};\r\n\r\n// Add these functions to the existing file:\r\n\r\nexport const filterNumericInput = (value, allowNegative = true) => {\r\n if (!value) return \"\";\r\n \r\n let filtered = value.toString();\r\n \r\n // Remove symbols and text, keep only numbers, decimal, and negative\r\n // This regex keeps numeric chars, decimal point, and negative sign\r\n filtered = filtered.replace(/[^0-9.-]/g, \"\");\r\n \r\n // Handle negative sign - only allow at the beginning\r\n if (allowNegative) {\r\n const negativeCount = (filtered.match(/-/g) || []).length;\r\n if (negativeCount > 1) {\r\n // Remove extra negative signs, keep only the first one if input started with -\r\n const startsWithNegative = value.toString().trim().startsWith(\"-\");\r\n filtered = filtered.replace(/-/g, \"\");\r\n if (startsWithNegative) {\r\n filtered = \"-\" + filtered;\r\n }\r\n } else if (filtered.includes(\"-\") && !filtered.startsWith(\"-\")) {\r\n // Move negative to the front if it's not already there\r\n filtered = \"-\" + filtered.replace(/-/g, \"\");\r\n }\r\n } else {\r\n filtered = filtered.replace(/-/g, \"\");\r\n }\r\n \r\n // Handle decimal - only allow one decimal point\r\n const decimalCount = (filtered.match(/\\./g) || []).length;\r\n if (decimalCount > 1) {\r\n const parts = filtered.split(\".\");\r\n filtered = parts[0] + \".\" + parts.slice(1).join(\"\");\r\n }\r\n \r\n return filtered;\r\n};\r\n\r\nexport const formatLiveNumber = (value, type = \"default\", preserveTyping = false) => {\r\n if (!value && value !== 0) return \"\";\r\n \r\n const originalStr = value.toString();\r\n const num = parseFloat(originalStr);\r\n if (isNaN(num)) return \"\";\r\n \r\n const isNegative = num < 0;\r\n const absStr = isNegative ? originalStr.substring(1) : originalStr;\r\n const hasDecimal = absStr.includes(\".\");\r\n \r\n let result;\r\n \r\n if (!hasDecimal) {\r\n // No decimal point - format as integer\r\n const intStr = Math.floor(Math.abs(num)).toString();\r\n result = intStr.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n } else {\r\n // Has decimal point\r\n if (preserveTyping) {\r\n // LIVE TYPING: Preserve exactly what user typed, just add commas\r\n const [intPart, decPart] = absStr.split(\".\");\r\n const commaInt = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n result = commaInt + \".\" + decPart;\r\n } else {\r\n // FINAL FORMATTING: Apply type-specific decimal rules\r\n if (type === \"months\") {\r\n const rounded = Math.round(Math.abs(num));\r\n result = rounded.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n } else if (type === \"percent\" || type === \"years\") {\r\n let formatted = Math.abs(num).toFixed(2);\r\n formatted = formatted.replace(/\\.?0+$/, '');\r\n const [intPart, decPart] = formatted.split(\".\");\r\n const commaInt = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n result = decPart ? commaInt + \".\" + decPart : commaInt;\r\n } else {\r\n // Currency: always 2 decimal places\r\n const twoDecimal = Math.abs(num).toFixed(2);\r\n const [intPart, decPart] = twoDecimal.split(\".\");\r\n const commaInt = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, \",\");\r\n result = commaInt + \".\" + decPart;\r\n }\r\n }\r\n }\r\n \r\n return isNegative ? \"-\" + result : result;\r\n};\r\n\r\nexport const formatLiveInput = (value, type, preserveTyping = false) => {\r\n const filtered = filterNumericInput(value, true);\r\n let formatted = formatLiveNumber(filtered, type, preserveTyping);\r\n \r\n if (formatted === \"\" || formatted === null || formatted === undefined) formatted = \"0\";\r\n \r\n switch (type) {\r\n case \"currency\":\r\n return \"$ \" + formatted;\r\n case \"percent\":\r\n return formatted + \" %\";\r\n case \"years\":\r\n return formatted + \" yrs.\";\r\n case \"months\":\r\n return formatted + \" mos.\";\r\n case \"number\":\r\n return formatted;\r\n default:\r\n return formatted;\r\n }\r\n};\r\n\r\nexport const calculateCursorPosition = (oldValue, newValue, oldCursor, type) => {\r\n if (oldCursor <= 0) return 0;\r\n \r\n // Handle end-of-input positioning\r\n if (oldCursor >= oldValue.length) {\r\n if (type === \"currency\") {\r\n return newValue.length;\r\n } else {\r\n const match = newValue.match(/^[0-9,.\\-\\s]+/);\r\n return match ? match[0].length : 0;\r\n }\r\n }\r\n \r\n // Get prefix length for different input types\r\n const getPrefixLength = (value, inputType) => {\r\n if (inputType === \"currency\" && value.startsWith(\"$ \")) return 2;\r\n return 0;\r\n };\r\n \r\n // Get the end of numeric content (before suffix)\r\n const getContentEnd = (value, inputType, prefixLength) => {\r\n const content = value.substring(prefixLength);\r\n \r\n if (inputType === \"percent\") {\r\n const match = content.match(/^([0-9,.\\-]+)/);\r\n return match ? match[1].length : content.length;\r\n } else if (inputType === \"years\") {\r\n const match = content.match(/^([0-9,.\\-]+)/);\r\n return match ? match[1].length : content.length;\r\n } else if (inputType === \"months\") {\r\n const match = content.match(/^([0-9,.\\-]+)/);\r\n return match ? match[1].length : content.length;\r\n }\r\n \r\n return content.length;\r\n };\r\n \r\n const oldPrefixLength = getPrefixLength(oldValue, type);\r\n const newPrefixLength = getPrefixLength(newValue, type);\r\n \r\n const oldContentEnd = getContentEnd(oldValue, type, oldPrefixLength);\r\n const newContentEnd = getContentEnd(newValue, type, newPrefixLength);\r\n \r\n // Convert cursor position to be relative to numeric content\r\n const cursorInOldContent = Math.max(0, oldCursor - oldPrefixLength);\r\n const maxOldContentCursor = Math.min(cursorInOldContent, oldContentEnd);\r\n \r\n // Count logical position: how many significant characters before cursor\r\n const oldContent = oldValue.substring(oldPrefixLength, oldPrefixLength + oldContentEnd);\r\n let logicalPosition = 0;\r\n \r\n for (let i = 0; i < maxOldContentCursor; i++) {\r\n const char = oldContent[i];\r\n if (/[0-9.\\-]/.test(char)) {\r\n logicalPosition++;\r\n }\r\n }\r\n \r\n // Find physical position for this logical position in new content\r\n const newContent = newValue.substring(newPrefixLength, newPrefixLength + newContentEnd);\r\n let physicalPosition = 0;\r\n let logicalCount = 0;\r\n \r\n // Scan through new content to find the target position\r\n for (let i = 0; i < newContent.length; i++) {\r\n const char = newContent[i];\r\n if (/[0-9.\\-]/.test(char)) {\r\n logicalCount++;\r\n \r\n // If we've reached our target logical position\r\n if (logicalCount === logicalPosition) {\r\n // Look ahead to see if there's a comma after this character\r\n if (i + 1 < newContent.length && newContent[i + 1] === ',') {\r\n // Position cursor after the comma\r\n physicalPosition = i + 2;\r\n } else {\r\n // Position cursor after this character\r\n physicalPosition = i + 1;\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n \r\n // Handle case where we need position 0 (before any characters)\r\n if (logicalPosition === 0) {\r\n physicalPosition = 0;\r\n }\r\n \r\n // Convert back to full string position\r\n const finalPosition = newPrefixLength + physicalPosition;\r\n \r\n // Ensure we don't exceed the content boundary\r\n const maxAllowedPosition = newPrefixLength + newContentEnd;\r\n return Math.min(finalPosition, maxAllowedPosition);\r\n};\r\n\r\n// Helper function to find position after N significant characters\r\nconst findPositionAfterNSignificantChars = (content, targetCount) => {\r\n let significantChars = 0;\r\n \r\n for (let i = 0; i < content.length; i++) {\r\n if (significantChars === targetCount) {\r\n return i;\r\n }\r\n \r\n if (/[0-9.-]/.test(content[i])) {\r\n significantChars++;\r\n }\r\n }\r\n \r\n return content.length;\r\n};\r\n\r\nexport const extractNumericValue = (formattedValue, type) => {\r\n if (!formattedValue) return 0;\r\n \r\n let cleaned = formattedValue.toString();\r\n \r\n switch (type) {\r\n case \"currency\":\r\n cleaned = cleaned.replace(/^\\$\\s*/, \"\").trim();\r\n break;\r\n case \"percent\":\r\n cleaned = cleaned.replace(/\\s*%$/, \"\").trim();\r\n break;\r\n case \"years\":\r\n cleaned = cleaned.replace(/\\s*yrs\\.$/, \"\").trim();\r\n break;\r\n case \"months\":\r\n cleaned = cleaned.replace(/\\s*mos\\.$/, \"\").trim();\r\n break;\r\n }\r\n \r\n cleaned = cleaned.replace(/,/g, \"\");\r\n return parseFloat(cleaned) || 0;\r\n};"],"names":["formatInputDisplay","value","type","num","parseFloat","hasDecimals","Intl","NumberFormat","style","currency","minimumFractionDigits","maximumFractionDigits","format","Math","abs","parseNumericInput","cleaned","toString","replace","filterNumericInput","allowNegative","filtered","match","length","startsWithNegative","trim","startsWith","includes","parts","split","slice","join","formatLiveNumber","preserveTyping","originalStr","isNaN","isNegative","absStr","substring","result","intPart","decPart","round","formatted","toFixed","commaInt","twoDecimal","floor","formatLiveInput","calculateCursorPosition","oldValue","newValue","oldCursor","getPrefixLength","inputType","getContentEnd","prefixLength","content","oldPrefixLength","newPrefixLength","oldContentEnd","newContentEnd","cursorInOldContent","max","maxOldContentCursor","min","oldContent","logicalPosition","i","char","test","newContent","physicalPosition","logicalCount","finalPosition","maxAllowedPosition","extractNumericValue","formattedValue"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@archerjessop/utilities",
3
- "version": "4.6.9",
3
+ "version": "4.6.10",
4
4
  "description": "Shared utilities for ArcherJessop property analysis tools",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",