@paro.io/expert-shared-components 1.14.54 → 1.14.55

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.
Files changed (26) hide show
  1. package/lib/components/TaxAxis/TaxAxisApi.d.ts +2 -0
  2. package/lib/components/TaxAxis/TaxAxisShell.js +102 -13
  3. package/lib/tax-axis/components/clientReport/ExecutiveSummary.d.ts +4 -1
  4. package/lib/tax-axis/components/clientReport/ExecutiveSummary.js +10 -6
  5. package/lib/tax-axis/components/clientReport/RecommendedStrategies.d.ts +6 -1
  6. package/lib/tax-axis/components/clientReport/RecommendedStrategies.js +26 -24
  7. package/lib/tax-axis/components/clientReport/StrategyCard.d.ts +1 -1
  8. package/lib/tax-axis/components/clientReport/StrategyCard.js +39 -23
  9. package/lib/tax-axis/components/clientReport/TaxAxisClientReport.d.ts +3 -1
  10. package/lib/tax-axis/components/clientReport/TaxAxisClientReport.js +4 -4
  11. package/lib/tax-axis/components/dashboard/DashboardSummary.d.ts +6 -1
  12. package/lib/tax-axis/components/dashboard/DashboardSummary.js +14 -4
  13. package/lib/tax-axis/components/dashboard/StrategyDetailPanel.d.ts +1 -1
  14. package/lib/tax-axis/components/dashboard/StrategyDetailPanel.js +123 -91
  15. package/lib/tax-axis/components/dashboard/TaxAxisDashboard.d.ts +3 -2
  16. package/lib/tax-axis/components/dashboard/TaxAxisDashboard.js +67 -19
  17. package/lib/tax-axis/components/documents/TaxAxisDocuments.d.ts +2 -0
  18. package/lib/tax-axis/components/documents/TaxAxisDocuments.js +46 -10
  19. package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.d.ts +21 -1
  20. package/lib/tax-axis/components/preparerWorkpaper/TaxAxisPreparerWorkpaper.js +10 -1
  21. package/lib/tax-axis/components/processing/TaxAxisProcessing.d.ts +3 -1
  22. package/lib/tax-axis/components/processing/TaxAxisProcessing.js +77 -31
  23. package/lib/tax-axis/lib/adapters/useEngineOutput.d.ts +7 -0
  24. package/lib/tax-axis/lib/adapters/useEngineOutput.js +8 -3
  25. package/lib/tax-axis/lib/types/index.d.ts +10 -1
  26. package/package.json +1 -1
@@ -9,5 +9,25 @@ export interface TaxAxisPreparerWorkpaperProps extends TaxAxisScreenProps {
9
9
  liveStrategies?: Strategy[];
10
10
  /** When provided, bypasses local computeAllStrategies. Must accompany liveStrategies. */
11
11
  liveComputedMap?: ComputedMap;
12
+ /** Live cpa_workflow from engine output */
13
+ cpaWorkflow?: {
14
+ workpaper_codes?: string[] | null;
15
+ section_6694_notices?: Array<{
16
+ strategy_id: string;
17
+ position_strength: string;
18
+ notice: string;
19
+ }>;
20
+ prior_year_flags?: string[];
21
+ engagement_recommendations?: string[];
22
+ };
23
+ /** Live risk disclosures from engine output */
24
+ riskDisclosures?: string[];
25
+ /** Live business profile from engine output */
26
+ businessProfile?: {
27
+ confidence_tier?: string;
28
+ data_years?: number;
29
+ data_quality_flags?: string[];
30
+ effective_tax_rate?: number;
31
+ };
12
32
  }
13
- export declare function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient, liveStrategies, liveComputedMap }: TaxAxisPreparerWorkpaperProps): React.JSX.Element;
33
+ export declare function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient, liveStrategies, liveComputedMap, cpaWorkflow, riskDisclosures, businessProfile }: TaxAxisPreparerWorkpaperProps): React.JSX.Element;
@@ -32,7 +32,7 @@ const ReportToolbar_1 = require("../shared/ReportToolbar");
32
32
  const EngagementHeader_1 = require("./EngagementHeader");
33
33
  const Section6694Summary_1 = require("./Section6694Summary");
34
34
  const PriorityGroup_1 = require("./PriorityGroup");
35
- function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient, liveStrategies, liveComputedMap }) {
35
+ function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient, liveStrategies, liveComputedMap, cpaWorkflow, riskDisclosures, businessProfile }) {
36
36
  const [expanded, setExpanded] = (0, react_1.useState)({});
37
37
  const [printMode, setPrintMode] = (0, react_1.useState)(false);
38
38
  const toggle = (rank, section) => setExpanded(prev => (Object.assign(Object.assign({}, prev), { [rank + "-" + section]: !prev[rank + "-" + section] })));
@@ -168,6 +168,15 @@ function TaxAxisPreparerWorkpaper({ profile, onBack, onToggleToClient, liveStrat
168
168
  "$" + interactionAdj.toLocaleString() + " ",
169
169
  react_1.default.createElement("span", { style: { fontWeight: 400, fontSize: 10 } }, "(\u221215%)")),
170
170
  react_1.default.createElement("td", { colSpan: 2 })))))),
171
+ (cpaWorkflow === null || cpaWorkflow === void 0 ? void 0 : cpaWorkflow.engagement_recommendations) && cpaWorkflow.engagement_recommendations.length > 0 && (react_1.default.createElement("div", { style: Object.assign(Object.assign({}, card), { marginBottom: 24 }) },
172
+ react_1.default.createElement("div", { style: sectionTitle }, "CPA ENGAGEMENT NOTES"),
173
+ cpaWorkflow.engagement_recommendations.map((rec, i) => (react_1.default.createElement("div", { key: i, style: { fontSize: 12, color: palette_1.P.gray700, lineHeight: 1.7, fontFamily: palette_1.P.body, padding: '8px 0', borderTop: i > 0 ? '1px solid ' + palette_1.P.gray100 : 'none' } }, rec))))),
174
+ riskDisclosures && riskDisclosures.length > 0 && (react_1.default.createElement("div", { style: Object.assign(Object.assign({}, card), { marginBottom: 24, borderColor: '#FDBA74' }) },
175
+ react_1.default.createElement("div", { style: Object.assign(Object.assign({}, sectionTitle), { color: palette_1.P.orange }) }, "RISK DISCLOSURES"),
176
+ riskDisclosures.map((r, i) => (react_1.default.createElement("div", { key: i, style: { fontSize: 11, color: palette_1.P.gray600, lineHeight: 1.65, fontFamily: palette_1.P.body, padding: '6px 0', borderTop: i > 0 ? '1px solid ' + palette_1.P.gray100 : 'none' } }, r))))),
177
+ (businessProfile === null || businessProfile === void 0 ? void 0 : businessProfile.data_quality_flags) && businessProfile.data_quality_flags.length > 0 && (react_1.default.createElement("div", { style: Object.assign(Object.assign({}, card), { marginBottom: 24, borderColor: '#FDBA74' }) },
178
+ react_1.default.createElement("div", { style: Object.assign(Object.assign({}, sectionTitle), { color: palette_1.P.orange }) }, "DATA QUALITY FLAGS"),
179
+ businessProfile.data_quality_flags.map((f, i) => (react_1.default.createElement("div", { key: i, style: { fontSize: 11, color: palette_1.P.gray600, padding: '4px 0', fontFamily: palette_1.P.body } }, f))))),
171
180
  react_1.default.createElement("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", padding: "12px 0", borderTop: "1px solid " + palette_1.P.gray200, fontSize: 11, color: palette_1.P.gray500, fontFamily: palette_1.P.body } },
172
181
  react_1.default.createElement("div", { style: { display: "flex", alignItems: "center", gap: 6 } },
173
182
  react_1.default.createElement("div", { style: { width: 16, height: 16, borderRadius: 4, background: palette_1.P.navy, display: "flex", alignItems: "center", justifyContent: "center" } },
@@ -3,5 +3,7 @@ import { ClientProfile, TaxAxisScreenProps } from "../../lib/types";
3
3
  export interface TaxAxisProcessingProps extends TaxAxisScreenProps {
4
4
  onComplete: () => void;
5
5
  profile?: ClientProfile;
6
+ /** Set to true by the shell poller when stage===REPORT_READY is detected. */
7
+ reportReady?: boolean;
6
8
  }
7
- export declare function TaxAxisProcessing({ onComplete, profile, userContext: _userContext, }: TaxAxisProcessingProps): React.JSX.Element;
9
+ export declare function TaxAxisProcessing({ onComplete, profile, reportReady, userContext: _userContext, }: TaxAxisProcessingProps): React.JSX.Element;
@@ -26,21 +26,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.TaxAxisProcessing = TaxAxisProcessing;
27
27
  const react_1 = __importStar(require("react"));
28
28
  const ProcessingStages_1 = require("./ProcessingStages");
29
+ const CRAWL_CEILING = 80; // hold here until reportReady
30
+ const CRAWL_TICK_MS = 180; // interval between crawl ticks
31
+ const CRAWL_STEP = 0.35; // % added each tick (reaches 80% in ~41s)
32
+ const FINISH_MS = 600; // ms to animate from current% → 100% once ready
33
+ const STAGE_ADVANCE_MS = 3200; // how often the displayed stage advances
29
34
  function buildStages(profile) {
30
35
  var _a;
31
36
  if (!profile) {
32
37
  return [
33
38
  "Parsing source documents",
34
39
  "Injecting IRS 2026 parameters",
35
- "Screening 25 eligible strategies",
40
+ "Screening eligible strategies",
36
41
  "Computing deterministic tax math",
37
42
  "Generating IRS citations",
38
43
  ];
39
44
  }
40
- const entity = profile.entity || "your";
45
+ const entity = profile.entity || "your business";
41
46
  const stateCount = ((_a = profile.states) === null || _a === void 0 ? void 0 : _a.length) || 1;
42
47
  const bizName = profile.bizName || "your business";
43
- // Verbatim from mock (App.jsx:1473-1477)
44
48
  const base = [
45
49
  "Parsing source documents",
46
50
  "Injecting IRS 2026 parameters",
@@ -53,53 +57,95 @@ function buildStages(profile) {
53
57
  if (entity === "S-Corporation") {
54
58
  base.push("Benchmarking officer salary against BLS data");
55
59
  }
56
- base.push("Screening 25 eligible strategies", "Computing deterministic tax math", "Cross-validating source documents", "Generating IRS citations", `Assembling TaxAxis report for ${bizName}`);
60
+ base.push("Screening 30 eligible strategies", "Computing deterministic tax math", "Cross-validating source documents", "Generating IRS citations", `Assembling TaxAxis report for ${bizName}`);
57
61
  return base;
58
62
  }
59
- function TaxAxisProcessing({ onComplete, profile, userContext: _userContext = "expert", }) {
63
+ function TaxAxisProcessing({ onComplete, profile, reportReady = false, userContext: _userContext = "expert", }) {
60
64
  const stages = (0, react_1.useMemo)(() => buildStages(profile), [profile]);
61
65
  const [progress, setProgress] = (0, react_1.useState)(0);
62
- // Staged timer from mock (App.jsx:1481). setInterval advances one stage
63
- // per tick; after the final stage, a 1000ms delay fires onComplete.
64
- // Target: ~8s total. Dynamic path: 10 stages × 700ms = 7s + 1s nav = 8s.
65
- // Fallback path (no profile): 5 stages × 1400ms = 7s + 1s nav = 8s.
66
- const stageInterval = stages.length <= 5 ? 1400 : 700;
66
+ const [stageIdx, setStageIdx] = (0, react_1.useState)(0);
67
+ const finishingRef = (0, react_1.useRef)(false);
68
+ const completedRef = (0, react_1.useRef)(false);
69
+ // Track current progress in a ref so the finish animation can read it synchronously
70
+ // without relying on the async functional-updater pattern.
71
+ const progressRef = (0, react_1.useRef)(0);
72
+ const setProgressSync = (v) => {
73
+ progressRef.current = v;
74
+ setProgress(v);
75
+ };
76
+ // ── Crawl: 0 → 80% — skipped entirely if reportReady already true on mount ──
67
77
  (0, react_1.useEffect)(() => {
68
- let i = 0;
69
- let navTimer = null;
78
+ if (reportReady || finishingRef.current)
79
+ return;
70
80
  const iv = setInterval(() => {
71
- i++;
72
- setProgress(i);
73
- if (i >= stages.length) {
81
+ if (finishingRef.current) {
74
82
  clearInterval(iv);
75
- navTimer = setTimeout(onComplete, 1000);
83
+ return;
84
+ }
85
+ const next = Math.min(progressRef.current + CRAWL_STEP, CRAWL_CEILING);
86
+ setProgressSync(next);
87
+ if (next >= CRAWL_CEILING)
88
+ clearInterval(iv);
89
+ }, CRAWL_TICK_MS);
90
+ return () => clearInterval(iv);
91
+ // reportReady intentionally in deps: if it arrives before mount effect runs, skip crawl
92
+ }, [reportReady]);
93
+ // ── Stage labels: advance every STAGE_ADVANCE_MS ─────────────────
94
+ (0, react_1.useEffect)(() => {
95
+ const iv = setInterval(() => {
96
+ setStageIdx((i) => (i + 1 < stages.length ? i + 1 : i));
97
+ }, STAGE_ADVANCE_MS);
98
+ return () => clearInterval(iv);
99
+ }, [stages.length]);
100
+ // ── Finish: reportReady → fast fill to 100%, then onComplete ─────
101
+ (0, react_1.useEffect)(() => {
102
+ if (!reportReady || finishingRef.current || completedRef.current)
103
+ return;
104
+ finishingRef.current = true;
105
+ setStageIdx(stages.length - 1);
106
+ // Read current progress synchronously from ref — not from stale state closure
107
+ const startPct = progressRef.current;
108
+ const startTime = Date.now();
109
+ const frame = () => {
110
+ const elapsed = Date.now() - startTime;
111
+ const t = Math.min(elapsed / FINISH_MS, 1);
112
+ const eased = t < 1 ? t * (2 - t) : 1;
113
+ setProgressSync(startPct + (100 - startPct) * eased);
114
+ if (t < 1) {
115
+ requestAnimationFrame(frame);
116
+ }
117
+ else {
118
+ setProgressSync(100);
119
+ if (!completedRef.current) {
120
+ completedRef.current = true;
121
+ setTimeout(onComplete, 150);
122
+ }
76
123
  }
77
- }, stageInterval);
78
- return () => {
79
- clearInterval(iv);
80
- if (navTimer !== null)
81
- clearTimeout(navTimer);
82
124
  };
83
- }, [stages.length, stageInterval, onComplete]);
84
- const pct = Math.round((progress / stages.length) * 100);
85
- const title = (profile === null || profile === void 0 ? void 0 : profile.bizName)
86
- ? `Analyzing ${profile.bizName}`
87
- : "Running Analysis";
125
+ requestAnimationFrame(frame);
126
+ // eslint-disable-next-line react-hooks/exhaustive-deps
127
+ }, [reportReady, stages.length]);
128
+ const pct = Math.round(progress);
129
+ const title = (profile === null || profile === void 0 ? void 0 : profile.bizName) ? `Analyzing ${profile.bizName}` : "Running Analysis";
130
+ const isFinishing = finishingRef.current;
88
131
  return (react_1.default.createElement("div", { className: "pt-[60px] text-center" },
89
132
  react_1.default.createElement("div", { className: "relative w-[72px] h-[72px] mx-auto mb-7" },
90
133
  react_1.default.createElement("div", { className: "absolute inset-0 rounded-full animate-ping", style: {
91
134
  background: "radial-gradient(circle, #248384, transparent 70%)",
92
135
  opacity: 0.15,
136
+ animationDuration: isFinishing ? "0.4s" : "1.4s",
93
137
  } }),
94
138
  react_1.default.createElement("div", { className: "absolute inset-0 w-[72px] h-[72px] rounded-full bg-tax-axis-surface flex items-center justify-center", style: { border: "2px solid rgba(36,131,132,0.4)" } },
95
- react_1.default.createElement("span", { className: "text-[28px] font-bold text-tax-axis-teal-light font-tax-axis-mono" }, pct))),
139
+ react_1.default.createElement("span", { className: "font-bold text-tax-axis-teal-light font-tax-axis-mono", style: { fontSize: pct === 100 ? 20 : 28 } }, pct === 100 ? "✓" : pct))),
96
140
  react_1.default.createElement("h2", { className: "text-[22px] font-bold text-white font-tax-axis-head mb-1" }, title),
97
- react_1.default.createElement("p", { className: "text-[13px] text-tax-axis-text-3 font-tax-axis-body mb-7" }, "Deterministic \u00B7 Temperature 0 \u00B7 IRS-cited"),
141
+ react_1.default.createElement("p", { className: "text-[13px] text-tax-axis-text-3 font-tax-axis-body mb-7" }, isFinishing ? "Report ready — loading your results…" : "Deterministic · Temperature 0 · IRS-cited"),
98
142
  react_1.default.createElement("div", { className: "max-w-[360px] mx-auto mb-6 h-0.5 bg-tax-axis-surface-2 rounded-sm overflow-hidden" },
99
- react_1.default.createElement("div", { className: "h-full rounded-sm transition-[width] duration-[400ms]", style: {
100
- width: `${pct}%`,
143
+ react_1.default.createElement("div", { className: "h-full rounded-sm", style: {
144
+ width: `${progress}%`,
101
145
  background: "linear-gradient(90deg, #248384, #A1E5E6)",
102
146
  boxShadow: "0 0 8px #248384",
147
+ transition: isFinishing ? "none" : "width 0.18s linear",
103
148
  } })),
104
- react_1.default.createElement(ProcessingStages_1.ProcessingStages, { stages: stages, progress: progress })));
149
+ react_1.default.createElement(ProcessingStages_1.ProcessingStages, { stages: stages, progress: stageIdx + 1 }),
150
+ pct >= CRAWL_CEILING && !isFinishing && (react_1.default.createElement("p", { className: "text-[11px] text-tax-axis-text-4 font-tax-axis-mono mt-4 animate-pulse" }, "Finalizing analysis\u2026"))));
105
151
  }
@@ -1,4 +1,9 @@
1
1
  import type { Strategy, ComputedMap } from "../types";
2
+ export interface SourceDocumentRef {
3
+ field_label: string;
4
+ value_display: string;
5
+ source_hint: string;
6
+ }
2
7
  export interface EngineCalculationTrace {
3
8
  strategy_id: string;
4
9
  branch_executed: string | null;
@@ -16,6 +21,8 @@ export interface EngineCalculationTrace {
16
21
  forms_required: string[];
17
22
  deadline_flag: string | null;
18
23
  amt_flag: boolean;
24
+ source_documents?: SourceDocumentRef[];
25
+ specialist_note?: string | null;
19
26
  }
20
27
  export interface EngineStrategyAnalysis {
21
28
  strategy_id: string;
@@ -96,7 +96,7 @@ function traceFromEngine(trace) {
96
96
  return steps;
97
97
  }
98
98
  function adaptEngineOutput(engineOutput) {
99
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
99
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
100
100
  const strategies = [];
101
101
  const computedMap = new Map();
102
102
  for (const analysis of engineOutput.strategy_analysis) {
@@ -109,6 +109,7 @@ function adaptEngineOutput(engineOutput) {
109
109
  const lo = (_b = (_a = ci === null || ci === void 0 ? void 0 : ci.low) !== null && _a !== void 0 ? _a : template === null || template === void 0 ? void 0 : template.lo) !== null && _b !== void 0 ? _b : 0;
110
110
  const hi = (_d = (_c = ci === null || ci === void 0 ? void 0 : ci.high) !== null && _c !== void 0 ? _c : template === null || template === void 0 ? void 0 : template.hi) !== null && _d !== void 0 ? _d : 0;
111
111
  const timelineBucket = resolveTimelineBucket(analysis.strategy_id, engineOutput.implementation_roadmap);
112
+ const clientSummaryEntry = engineOutput.client_summary.strategies.find((cs) => cs.strategy_name === analysis.strategy_name);
112
113
  const strategy = {
113
114
  rank: rank !== null && rank !== void 0 ? rank : 99,
114
115
  code: (_e = template === null || template === void 0 ? void 0 : template.code) !== null && _e !== void 0 ? _e : analysis.strategy_id,
@@ -132,8 +133,12 @@ function adaptEngineOutput(engineOutput) {
132
133
  preferIndustry: template === null || template === void 0 ? void 0 : template.preferIndustry,
133
134
  minEmployees: template === null || template === void 0 ? void 0 : template.minEmployees,
134
135
  needsOwnerComp: template === null || template === void 0 ? void 0 : template.needsOwnerComp,
135
- clientBrief: (_q = (_p = engineOutput.client_summary.strategies.find((cs) => cs.strategy_name === analysis.strategy_name)) === null || _p === void 0 ? void 0 : _p.why_it_applies) !== null && _q !== void 0 ? _q : template === null || template === void 0 ? void 0 : template.clientBrief,
136
- action: (_s = (_r = engineOutput.client_summary.strategies.find((cs) => cs.strategy_name === analysis.strategy_name)) === null || _r === void 0 ? void 0 : _r.next_step) !== null && _s !== void 0 ? _s : template === null || template === void 0 ? void 0 : template.action,
136
+ clientBrief: (_p = clientSummaryEntry === null || clientSummaryEntry === void 0 ? void 0 : clientSummaryEntry.why_it_applies) !== null && _p !== void 0 ? _p : template === null || template === void 0 ? void 0 : template.clientBrief,
137
+ action: (_q = clientSummaryEntry === null || clientSummaryEntry === void 0 ? void 0 : clientSummaryEntry.next_step) !== null && _q !== void 0 ? _q : template === null || template === void 0 ? void 0 : template.action,
138
+ sourceDocuments: (_r = trace === null || trace === void 0 ? void 0 : trace.source_documents) !== null && _r !== void 0 ? _r : [],
139
+ quickWin: analysis.quick_win,
140
+ positionStrength: (_s = trace === null || trace === void 0 ? void 0 : trace.position_strength) !== null && _s !== void 0 ? _s : undefined,
141
+ specialistNote: (_t = trace === null || trace === void 0 ? void 0 : trace.specialist_note) !== null && _t !== void 0 ? _t : undefined,
137
142
  };
138
143
  strategies.push(strategy);
139
144
  computedMap.set(strategy.rank, {
@@ -12,6 +12,11 @@ export interface StrategySource {
12
12
  value: string;
13
13
  field: string;
14
14
  }
15
+ export interface SourceDocumentRef {
16
+ field_label: string;
17
+ value_display: string;
18
+ source_hint: string;
19
+ }
15
20
  export interface StrategyTraceStep {
16
21
  n: number;
17
22
  step: string;
@@ -38,14 +43,18 @@ export interface Strategy {
38
43
  needsOwnerComp?: boolean;
39
44
  clientBrief?: string;
40
45
  action?: string;
46
+ abstract?: string;
41
47
  authority?: string;
42
48
  forms?: string;
43
49
  warning?: string | null;
44
- abstract?: string;
45
50
  sources?: StrategySource[];
46
51
  trace?: StrategyTraceStep[];
47
52
  cost?: string;
48
53
  timelineBucket?: string;
54
+ sourceDocuments?: SourceDocumentRef[];
55
+ quickWin?: boolean;
56
+ positionStrength?: string;
57
+ specialistNote?: string;
49
58
  }
50
59
  export interface ClientProfile {
51
60
  bizName: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paro.io/expert-shared-components",
3
- "version": "1.14.54",
3
+ "version": "1.14.55",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "scripts": {