@paro.io/expert-shared-components 1.14.74 → 1.14.76

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.
@@ -48,8 +48,6 @@ function filterEligibleStrategies(profile) {
48
48
  return false;
49
49
  if (s.needsOwnerComp && ownerComp <= 0)
50
50
  return false;
51
- if (s.rank === 8 && (profile.ownsRealEstate || "No") === "No")
52
- return false;
53
51
  return true;
54
52
  });
55
53
  }
@@ -64,8 +62,8 @@ function computeAllStrategies(profile) {
64
62
  const age = parseInt(profile.age || "45") || 45;
65
63
  const hsaExisting = (0, exports.parseNum)(profile.hsaContributions);
66
64
  const retirementExisting = (0, exports.parseNum)(profile.retirementContributions);
67
- const fedRate = profile.entity === "C-Corporation" ? 0.21 : parseFloat((profile.federalRate || "24").replace("%", "")) / 100 || 0.24;
68
- const stateRate = parseFloat(profile.stateRate || "4.95") / 100;
65
+ const fedRate = parseFloat((profile.federalRate || "24").replace("%", "")) / 100 || 0.24;
66
+ const stateRate = parseFloat(profile.stateRate || "0") / 100;
69
67
  const combinedRate = fedRate + stateRate;
70
68
  const seTaxRate = 0.153;
71
69
  const sstb = profile.sstb || "No";
@@ -135,17 +133,25 @@ function computeAllStrategies(profile) {
135
133
  const hsaLimit = 8550;
136
134
  const hsaAdditional = Math.max(hsaLimit - hsaExisting, 0);
137
135
  const hsaSavings = Math.round(hsaAdditional * (combinedRate + 0.0765));
138
- results.set(9, { lo: Math.max(Math.round(hsaSavings * 0.80), 0), hi: Math.max(Math.round(hsaSavings * 1.15), 0),
136
+ results.set(9, { lo: Math.max(Math.round(hsaSavings * 0.90), 0), hi: Math.max(Math.round(hsaSavings * 1.05), 0),
139
137
  sources: [{ doc: "Intake", line: "HSA", value: `$${hsaExisting.toLocaleString()}`, field: "YTD Contributions" }, { doc: "IRS 2026", line: "Rev. Proc.", value: "$8,550", field: "Family Limit" }],
140
138
  trace: [{ n: 1, step: "2026 family limit", formula: "Rev. Proc. 2025-32", result: "$8,550", src: "IRS" }, { n: 2, step: "Already contributed", formula: "W-2 Box 12 Code W", result: `$${hsaExisting.toLocaleString()}`, src: "Intake" }, { n: 3, step: "Remaining room", formula: `8,550 \u2212 ${hsaExisting.toLocaleString()}`, result: `$${hsaAdditional.toLocaleString()}`, src: "Computed" }, { n: 4, step: "Tax savings", formula: `${hsaAdditional.toLocaleString()} \u00D7 ${((combinedRate + 0.0765) * 100).toFixed(1)}%`, result: `$${hsaSavings.toLocaleString()}`, src: "Triple tax" }] });
141
139
  }
142
140
  /* #15 SALT/PTE Optimization */
143
141
  {
144
- const statesTaxPaid = Math.round(net * stateRate);
142
+ // When primary state rate is 0 (e.g. TX), use highest nexus state rate
143
+ let pteStateRate = stateRate;
144
+ if (pteStateRate === 0 && (profile.states || []).length > 1) {
145
+ const STATE_TOP_RATES = { CA: 13.30, NY: 10.90, NJ: 10.75, HI: 11.00, OR: 9.90, MN: 9.85, DC: 10.75, VT: 8.75, WI: 7.65, ME: 7.15, CT: 6.99, NE: 6.64, DE: 6.60, MT: 6.75, SC: 6.50, RI: 5.99, ID: 5.80, NM: 5.90, VA: 5.75, MD: 5.75, KS: 5.70, GA: 5.39, WV: 5.12, MA: 5.00, MS: 5.00, AL: 5.00, MO: 4.95, IL: 4.95, UT: 4.65, OK: 4.75, NC: 4.50, CO: 4.40, AR: 4.40, MI: 4.25, LA: 4.25, KY: 4.00, OH: 3.75, IN: 3.05, PA: 3.07, AZ: 2.50, ND: 1.95 };
146
+ const nexusRates = (profile.states || []).map(s => { var _a; return ((_a = STATE_TOP_RATES[s]) !== null && _a !== void 0 ? _a : 0) / 100; }).filter(r => r > 0);
147
+ if (nexusRates.length > 0)
148
+ pteStateRate = Math.max(...nexusRates);
149
+ }
150
+ const statesTaxPaid = Math.round(net * pteStateRate);
145
151
  const pteSavings = Math.round(statesTaxPaid * 0.70);
146
152
  results.set(15, { lo: Math.max(Math.round(pteSavings * 0.80), 0), hi: Math.max(Math.round(pteSavings * 1.10), 0),
147
- sources: [{ doc: "Intake", line: "Net Income", value: `$${net.toLocaleString()}`, field: "Pass-through Income" }, { doc: "Intake", line: "State Rate", value: `${(stateRate * 100).toFixed(2)}%`, field: "Marginal State Rate" }, { doc: "OBBBA \u00A770109", line: "SALT Cap", value: "$40,400", field: "2026 Cap" }],
148
- trace: [{ n: 1, step: "Entity-level state tax", formula: `${net.toLocaleString()} \u00D7 ${(stateRate * 100).toFixed(2)}%`, result: `$${statesTaxPaid.toLocaleString()}`, src: "Intake" }, { n: 2, step: "PTE deduction value", formula: "Entity-level deduction bypasses SALT cap", result: `$${statesTaxPaid.toLocaleString()}`, src: "Notice 2020-75" }, { n: 3, step: "Net savings (credit offset)", formula: `${statesTaxPaid.toLocaleString()} \u00D7 70% recovery`, result: `$${pteSavings.toLocaleString()}`, src: "State credit" }] });
153
+ sources: [{ doc: "Intake", line: "Net Income", value: `$${net.toLocaleString()}`, field: "Pass-through Income" }, { doc: "Intake", line: "State Rate", value: `${(pteStateRate * 100).toFixed(2)}%`, field: "Marginal State Rate" }, { doc: "OBBBA \u00A770109", line: "SALT Cap", value: "$40,400", field: "2026 Cap" }],
154
+ trace: [{ n: 1, step: "Entity-level state tax", formula: `${net.toLocaleString()} \u00D7 ${(pteStateRate * 100).toFixed(2)}%`, result: `$${statesTaxPaid.toLocaleString()}`, src: "Intake" }, { n: 2, step: "PTE deduction value", formula: "Entity-level deduction bypasses SALT cap", result: `$${statesTaxPaid.toLocaleString()}`, src: "Notice 2020-75" }, { n: 3, step: "Net savings (credit offset)", formula: `${statesTaxPaid.toLocaleString()} \u00D7 70% recovery`, result: `$${pteSavings.toLocaleString()}`, src: "State credit" }] });
149
155
  }
150
156
  /* #22 Overtime Pay Deduction (OBBBA) */
151
157
  if (overtime > 0) {
@@ -167,11 +173,5 @@ function computeAllStrategies(profile) {
167
173
  results.set(rank, Object.assign(Object.assign({}, v), { lo: Math.round(v.hi / 3.0) }));
168
174
  }
169
175
  }
170
- // Safety net: ensure lo and hi don't round to same K (prevents "$XK–$XK" display)
171
- for (const [rank, v] of results) {
172
- if (v.hi > 0 && v.lo > 0 && Math.round(v.lo / 1000) >= Math.round(v.hi / 1000)) {
173
- results.set(rank, Object.assign(Object.assign({}, v), { lo: Math.round(v.hi * 0.85) }));
174
- }
175
- }
176
176
  return results;
177
177
  }
@@ -1,18 +1,13 @@
1
- export interface CatalogFieldDef {
2
- label?: string;
1
+ export interface FieldDef {
2
+ label: string;
3
3
  sourceRef?: string;
4
4
  }
5
5
  export interface CatalogSection {
6
6
  head: string;
7
7
  fields: string[];
8
8
  }
9
- export interface CatalogEntry {
9
+ export interface DocumentCatalogEntry {
10
10
  sections: CatalogSection[];
11
- fields: Record<string, CatalogFieldDef>;
11
+ fields: Record<string, FieldDef>;
12
12
  }
13
- /**
14
- * Keyed by documentType string returned by the backend in parsedData.documentType.
15
- * When DocumentReviewModal receives parsedData, it looks up the documentType here
16
- * to get section groupings and field labels. Falls back to flat rendering if no entry.
17
- */
18
- export declare const DOCUMENT_FIELD_CATALOG: Record<string, CatalogEntry>;
13
+ export declare const DOCUMENT_FIELD_CATALOG: Record<string, DocumentCatalogEntry>;