calcsuite-react 1.0.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/CHANGELOG.md +25 -0
- package/LICENSE +26 -0
- package/README.md +87 -0
- package/dist/calcsuite.js +6699 -0
- package/dist/core/calculators/deposits.d.ts +2 -0
- package/dist/core/calculators/investments.d.ts +2 -0
- package/dist/core/calculators/loans.d.ts +2 -0
- package/dist/core/calculators/retirement_us.d.ts +2 -0
- package/dist/core/calculators/returns.d.ts +2 -0
- package/dist/core/calculators/scientific.d.ts +2 -0
- package/dist/core/calculators/tax.d.ts +2 -0
- package/dist/core/calculators/utility.d.ts +2 -0
- package/dist/core/currency.d.ts +20 -0
- package/dist/core/decimal.d.ts +9 -0
- package/dist/core/finance.d.ts +30 -0
- package/dist/core/format.d.ts +16 -0
- package/dist/core/kit.d.ts +109 -0
- package/dist/core/liveRates.d.ts +11 -0
- package/dist/core/loan.d.ts +70 -0
- package/dist/core/registry.d.ts +10 -0
- package/dist/core/sci/evaluator.d.ts +14 -0
- package/dist/core/sci/index.d.ts +22 -0
- package/dist/core/sci/parser.d.ts +32 -0
- package/dist/core/sci/tokenizer.d.ts +10 -0
- package/dist/export/index.d.ts +56 -0
- package/dist/index.d.ts +49 -0
- package/dist/settings/SettingsContext.d.ts +20 -0
- package/dist/settings/settings.d.ts +72 -0
- package/dist/transport/client.d.ts +54 -0
- package/dist/transport/fx.d.ts +23 -0
- package/dist/transport/payload.d.ts +21 -0
- package/dist/transport/types.d.ts +198 -0
- package/dist/ui/CalculatorPanel.d.ts +14 -0
- package/dist/ui/Chart.d.ts +4 -0
- package/dist/ui/CommandPalette.d.ts +13 -0
- package/dist/ui/CurrencyConverter.d.ts +1 -0
- package/dist/ui/Dialog.d.ts +8 -0
- package/dist/ui/ExportMenu.d.ts +4 -0
- package/dist/ui/HistoryPanel.d.ts +6 -0
- package/dist/ui/IntegrationPanel.d.ts +8 -0
- package/dist/ui/Launcher.d.ts +34 -0
- package/dist/ui/LoanEmiPanel.d.ts +1 -0
- package/dist/ui/ResultCard.d.ts +4 -0
- package/dist/ui/SaveButton.d.ts +4 -0
- package/dist/ui/ScheduleTable.d.ts +4 -0
- package/dist/ui/SciCalculator.d.ts +4 -0
- package/dist/ui/SettingsPanel.d.ts +1 -0
- package/dist/ui/Shell.d.ts +5 -0
- package/dist/ui/fields.d.ts +9 -0
- package/dist/ui/history.d.ts +15 -0
- package/dist/ui/icons.d.ts +8 -0
- package/dist/ui/overlayStack.d.ts +3 -0
- package/dist/ui/themePresets.d.ts +19 -0
- package/package.json +94 -0
- package/src/theme.css +751 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type DecimalT, type Numeric } from './decimal';
|
|
2
|
+
export interface CurrencyMeta {
|
|
3
|
+
code: string;
|
|
4
|
+
name: string;
|
|
5
|
+
symbol: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const CURRENCIES: CurrencyMeta[];
|
|
8
|
+
export declare const currencyByCode: (code: string) => CurrencyMeta | undefined;
|
|
9
|
+
/** amount × rate, exact. */
|
|
10
|
+
export declare const convert: (amount: Numeric, rate: Numeric) => DecimalT;
|
|
11
|
+
/** 1 unit of target buys this many of source. 0 when the rate is not positive. */
|
|
12
|
+
export declare const inverseRate: (rate: Numeric) => DecimalT;
|
|
13
|
+
/** Format a Decimal amount as its currency, using ISO 4217 decimals + symbol. */
|
|
14
|
+
export declare function formatCurrency(amount: Numeric, code: string): string;
|
|
15
|
+
/** How many fraction digits the currency uses (JPY 0, KWD 3, most 2). */
|
|
16
|
+
export declare function currencyDecimals(code: string): number;
|
|
17
|
+
/** Human "how stale" label for an offline saved rate. */
|
|
18
|
+
export declare function stalenessLabel(atMs: number, nowMs: number): string;
|
|
19
|
+
/** A saved offline rate is "stale" once it is older than a day. */
|
|
20
|
+
export declare const isStale: (atMs: number, nowMs: number) => boolean;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import DecimalBase from 'decimal.js';
|
|
2
|
+
export declare const Decimal: typeof DecimalBase;
|
|
3
|
+
export type DecimalT = InstanceType<typeof Decimal>;
|
|
4
|
+
export type Numeric = string | number | DecimalT;
|
|
5
|
+
export declare const D: (v: Numeric) => DecimalT;
|
|
6
|
+
export declare const eq: (a: Numeric, b: Numeric) => boolean;
|
|
7
|
+
export declare const gt: (a: Numeric, b: Numeric) => boolean;
|
|
8
|
+
export declare const lt: (a: Numeric, b: Numeric) => boolean;
|
|
9
|
+
export declare const isZeroish: (d: DecimalT, epsilon?: string) => boolean;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type DecimalT, type Numeric } from './decimal';
|
|
2
|
+
export declare const periodic: (annualPct: Numeric, perYear?: number) => DecimalT;
|
|
3
|
+
/** Future value of a level annuity of PMT per period at rate r for n periods. */
|
|
4
|
+
export declare function fvAnnuity(PMT: Numeric, r: Numeric, n: number, due?: boolean): DecimalT;
|
|
5
|
+
/** Future value of a single lump sum. */
|
|
6
|
+
export declare function fvLump(PV: Numeric, r: Numeric, n: number): DecimalT;
|
|
7
|
+
/** Present value of a level annuity. */
|
|
8
|
+
export declare function pvAnnuity(PMT: Numeric, r: Numeric, n: number, due?: boolean): DecimalT;
|
|
9
|
+
/** Present value of a single future amount. */
|
|
10
|
+
export declare function pvLump(FV: Numeric, r: Numeric, n: number): DecimalT;
|
|
11
|
+
/** Level payment that amortises PV to FV over n periods. */
|
|
12
|
+
export declare function pmt(PV: Numeric, r: Numeric, n: number, FV?: Numeric, due?: boolean): DecimalT;
|
|
13
|
+
/** Number of periods to amortise PV at PMT and rate r. */
|
|
14
|
+
export declare function nper(PV: Numeric, PMT: Numeric, r: Numeric): DecimalT;
|
|
15
|
+
/** Generic monotonic-in-rate bisection: find rate in [lo,hi] where f(rate)=0. */
|
|
16
|
+
export declare function bisectRate(f: (r: DecimalT) => DecimalT, lo?: number, hi?: number, iters?: number): DecimalT | null;
|
|
17
|
+
/** NPV of periodic cashflows (cf[0] at t=0). */
|
|
18
|
+
export declare function npv(rate: Numeric, cashflows: Numeric[]): DecimalT;
|
|
19
|
+
/** IRR of periodic cashflows via bracketed bisection. Returns a fraction (0.1 = 10%). */
|
|
20
|
+
export declare function irr(cashflows: Numeric[]): DecimalT | null;
|
|
21
|
+
export interface DatedFlow {
|
|
22
|
+
date: string;
|
|
23
|
+
amount: Numeric;
|
|
24
|
+
}
|
|
25
|
+
/** XNPV: net present value of irregular dated cashflows, ACT/365. */
|
|
26
|
+
export declare function xnpv(rate: Numeric, flows: DatedFlow[]): DecimalT;
|
|
27
|
+
/** XIRR: annualised return of irregular dated cashflows. Fraction (0.12 = 12%). */
|
|
28
|
+
export declare function xirr(flows: DatedFlow[]): DecimalT | null;
|
|
29
|
+
/** CAGR from begin/end value over years. Fraction. */
|
|
30
|
+
export declare function cagr(begin: Numeric, end: Numeric, years: Numeric): DecimalT;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type DecimalT, type Numeric } from './decimal';
|
|
2
|
+
import type { Settings } from '../settings/settings';
|
|
3
|
+
export interface Formatter {
|
|
4
|
+
settings: Settings;
|
|
5
|
+
money(v: Numeric, places?: number): string;
|
|
6
|
+
moneyParts(v: Numeric, places?: number): {
|
|
7
|
+
symbol: string;
|
|
8
|
+
digits: string;
|
|
9
|
+
};
|
|
10
|
+
num(v: Numeric, places?: number): string;
|
|
11
|
+
pct(v: Numeric, places?: number): string;
|
|
12
|
+
compact(v: Numeric): string;
|
|
13
|
+
round(v: Numeric, places?: number): DecimalT;
|
|
14
|
+
}
|
|
15
|
+
export declare function makeFormatter(s: Settings): Formatter;
|
|
16
|
+
export declare function tenureText(months: number): string;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type DecimalT, type Numeric } from './decimal';
|
|
3
|
+
import type { Formatter } from './format';
|
|
4
|
+
import type { Settings, Region } from '../settings/settings';
|
|
5
|
+
export type Group = 'loans' | 'invest' | 'returns' | 'tax' | 'tools';
|
|
6
|
+
export type FieldKind = 'money' | 'percent' | 'int' | 'number' | 'tenure' | 'years' | 'select' | 'segmented' | 'date' | 'toggle' | 'text' | 'cashflows';
|
|
7
|
+
export type FieldValue = string | number | boolean | Array<{
|
|
8
|
+
date: string;
|
|
9
|
+
amount: string;
|
|
10
|
+
}>;
|
|
11
|
+
export type Values = Record<string, FieldValue>;
|
|
12
|
+
export interface FieldSchema {
|
|
13
|
+
key: string;
|
|
14
|
+
label: string;
|
|
15
|
+
kind: FieldKind;
|
|
16
|
+
default?: FieldValue;
|
|
17
|
+
options?: Array<{
|
|
18
|
+
value: string;
|
|
19
|
+
label: string;
|
|
20
|
+
}>;
|
|
21
|
+
min?: number;
|
|
22
|
+
max?: number;
|
|
23
|
+
step?: number;
|
|
24
|
+
suffix?: string;
|
|
25
|
+
prefix?: 'currency' | string;
|
|
26
|
+
help?: string;
|
|
27
|
+
optional?: boolean;
|
|
28
|
+
advanced?: boolean;
|
|
29
|
+
showIf?: (v: Values, region: Region) => boolean;
|
|
30
|
+
/** Region-specific label override, e.g. 'EMI' vs 'Monthly payment'. */
|
|
31
|
+
labelByRegion?: Partial<Record<Region, string>>;
|
|
32
|
+
}
|
|
33
|
+
export type MetricTone = 'default' | 'principal' | 'interest' | 'accent' | 'positive' | 'negative';
|
|
34
|
+
export interface Metric {
|
|
35
|
+
label: string;
|
|
36
|
+
value: string;
|
|
37
|
+
tone?: MetricTone;
|
|
38
|
+
sub?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface ScheduleRow {
|
|
41
|
+
label: string;
|
|
42
|
+
cells: string[];
|
|
43
|
+
}
|
|
44
|
+
export interface ScheduleGroup {
|
|
45
|
+
label: string;
|
|
46
|
+
summary: string[];
|
|
47
|
+
rows: ScheduleRow[];
|
|
48
|
+
}
|
|
49
|
+
export interface ScheduleView {
|
|
50
|
+
title?: string;
|
|
51
|
+
columns: string[];
|
|
52
|
+
groups?: ScheduleGroup[];
|
|
53
|
+
rows?: ScheduleRow[];
|
|
54
|
+
/** column index → semantic tone for cell colouring */
|
|
55
|
+
toneCols?: Record<number, 'principal' | 'interest'>;
|
|
56
|
+
}
|
|
57
|
+
export interface ChartSeries {
|
|
58
|
+
labels?: string[];
|
|
59
|
+
series: Array<{
|
|
60
|
+
name: string;
|
|
61
|
+
tone: 'principal' | 'interest' | 'accent';
|
|
62
|
+
points: number[];
|
|
63
|
+
area?: boolean;
|
|
64
|
+
dash?: boolean;
|
|
65
|
+
}>;
|
|
66
|
+
}
|
|
67
|
+
export interface ResultView {
|
|
68
|
+
primary: Metric;
|
|
69
|
+
primaryPer?: string;
|
|
70
|
+
secondary?: Metric[];
|
|
71
|
+
split?: Array<{
|
|
72
|
+
label: string;
|
|
73
|
+
value: number;
|
|
74
|
+
tone: 'principal' | 'interest' | 'accent';
|
|
75
|
+
}>;
|
|
76
|
+
schedule?: ScheduleView;
|
|
77
|
+
chart?: ChartSeries;
|
|
78
|
+
formula?: string;
|
|
79
|
+
formulaSubstituted?: string;
|
|
80
|
+
notes?: string[];
|
|
81
|
+
warnings?: string[];
|
|
82
|
+
/** raw values for export/save; strings to stay float-safe */
|
|
83
|
+
raw?: Record<string, string | number | null>;
|
|
84
|
+
}
|
|
85
|
+
export interface CalcCtx {
|
|
86
|
+
settings: Settings;
|
|
87
|
+
region: Region;
|
|
88
|
+
fmt: Formatter;
|
|
89
|
+
D: (v: Numeric) => DecimalT;
|
|
90
|
+
}
|
|
91
|
+
export interface CalculatorDef {
|
|
92
|
+
id: string;
|
|
93
|
+
group: Group;
|
|
94
|
+
title: string;
|
|
95
|
+
blurb?: string;
|
|
96
|
+
keywords?: string[];
|
|
97
|
+
regions?: Region[];
|
|
98
|
+
icon?: ReactNode;
|
|
99
|
+
inputs: FieldSchema[];
|
|
100
|
+
compute: (values: Values, ctx: CalcCtx) => ResultView;
|
|
101
|
+
/** Optional bespoke panel (scientific calculator, EMI solve-for chips, etc.). */
|
|
102
|
+
custom?: string;
|
|
103
|
+
}
|
|
104
|
+
export declare const numval: (v: FieldValue | undefined, fallback?: number) => number;
|
|
105
|
+
export declare const strval: (v: FieldValue | undefined, fallback?: string) => string;
|
|
106
|
+
export declare const boolval: (v: FieldValue | undefined, fallback?: boolean) => boolean;
|
|
107
|
+
/** Decimal money value cleaned of grouping — never lose precision. */
|
|
108
|
+
export declare const dmoney: (v: FieldValue | undefined, fallback?: string) => DecimalT;
|
|
109
|
+
export declare const metric: (label: string, value: string, tone?: MetricTone, sub?: string) => Metric;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface LiveRateResult {
|
|
2
|
+
rate: string;
|
|
3
|
+
asOf: string;
|
|
4
|
+
provider: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function fetchLiveRate(from: string, to: string, opts?: {
|
|
7
|
+
fetchImpl?: typeof fetch;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
}): Promise<LiveRateResult>;
|
|
10
|
+
/** Parse the provider's UTC timestamp to epoch ms; falls back to `nowMs`. */
|
|
11
|
+
export declare function asOfMs(asOf: string, nowMs: number): number;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { type DecimalT, type Numeric } from './decimal';
|
|
2
|
+
export type Region = 'IN' | 'US';
|
|
3
|
+
export type Basis = 'reducing_monthly' | 'flat';
|
|
4
|
+
export type SolveTarget = 'payment' | 'principal' | 'rate' | 'tenure';
|
|
5
|
+
export interface RegionProfile {
|
|
6
|
+
region: Region;
|
|
7
|
+
currency: 'INR' | 'USD';
|
|
8
|
+
locale: string;
|
|
9
|
+
paymentLabel: string;
|
|
10
|
+
tenureWord: string;
|
|
11
|
+
feeWord: string;
|
|
12
|
+
grouping: 'indian' | 'western';
|
|
13
|
+
defaultBasis: Basis;
|
|
14
|
+
defaultRatePct: string;
|
|
15
|
+
defaultTermMonths: number;
|
|
16
|
+
maxRatePct: number;
|
|
17
|
+
}
|
|
18
|
+
export declare const REGIONS: Record<Region, RegionProfile>;
|
|
19
|
+
export type ErrorCode = 'MISSING_SOLVE_TARGET' | 'MULTIPLE_SOLVE_TARGETS' | 'PAYMENT_BELOW_INTEREST' | 'RATE_OUT_OF_RANGE' | 'TENURE_OUT_OF_RANGE' | 'NEGATIVE_PRINCIPAL' | 'SOLVER_DID_NOT_CONVERGE';
|
|
20
|
+
export declare class FinCalcError extends Error {
|
|
21
|
+
code: ErrorCode;
|
|
22
|
+
field?: string;
|
|
23
|
+
constructor(code: ErrorCode, message: string, field?: string);
|
|
24
|
+
}
|
|
25
|
+
export interface LoanInput {
|
|
26
|
+
region: Region;
|
|
27
|
+
basis?: Basis;
|
|
28
|
+
principal?: Numeric;
|
|
29
|
+
annualRatePct?: Numeric;
|
|
30
|
+
tenureMonths?: number;
|
|
31
|
+
payment?: Numeric;
|
|
32
|
+
}
|
|
33
|
+
export interface AmortRow {
|
|
34
|
+
month: number;
|
|
35
|
+
openingBalance: DecimalT;
|
|
36
|
+
payment: DecimalT;
|
|
37
|
+
principal: DecimalT;
|
|
38
|
+
interest: DecimalT;
|
|
39
|
+
closingBalance: DecimalT;
|
|
40
|
+
cumulativeInterest: DecimalT;
|
|
41
|
+
}
|
|
42
|
+
export interface YearSummary {
|
|
43
|
+
year: number;
|
|
44
|
+
months: AmortRow[];
|
|
45
|
+
principal: DecimalT;
|
|
46
|
+
interest: DecimalT;
|
|
47
|
+
payment: DecimalT;
|
|
48
|
+
closingBalance: DecimalT;
|
|
49
|
+
}
|
|
50
|
+
export interface LoanResult {
|
|
51
|
+
solvedFor: SolveTarget;
|
|
52
|
+
basis: Basis;
|
|
53
|
+
region: Region;
|
|
54
|
+
principal: DecimalT;
|
|
55
|
+
annualRatePct: DecimalT;
|
|
56
|
+
tenureMonths: number;
|
|
57
|
+
payment: DecimalT;
|
|
58
|
+
totalInterest: DecimalT;
|
|
59
|
+
totalPayment: DecimalT;
|
|
60
|
+
schedule: AmortRow[];
|
|
61
|
+
byYear: YearSummary[];
|
|
62
|
+
chart: {
|
|
63
|
+
balance: DecimalT[];
|
|
64
|
+
cumulativeInterest: DecimalT[];
|
|
65
|
+
};
|
|
66
|
+
/** Flat-rate loans only: the equivalent reducing-balance rate (§4.5). */
|
|
67
|
+
equivalentReducingRatePct?: DecimalT;
|
|
68
|
+
formula: string;
|
|
69
|
+
}
|
|
70
|
+
export declare function solve(input: LoanInput): LoanResult;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CalculatorDef, Group } from './kit';
|
|
2
|
+
import type { Region } from '../settings/settings';
|
|
3
|
+
export declare function registerCalculator(def: CalculatorDef): void;
|
|
4
|
+
export declare function allCalculators(): CalculatorDef[];
|
|
5
|
+
export declare function calculatorsForRegion(region: Region): CalculatorDef[];
|
|
6
|
+
export declare function calculatorById(id: string): CalculatorDef | undefined;
|
|
7
|
+
export declare const GROUPS: Array<{
|
|
8
|
+
id: Group;
|
|
9
|
+
label: string;
|
|
10
|
+
}>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type DecimalT } from '../decimal';
|
|
2
|
+
import type { Node } from './parser';
|
|
3
|
+
import type { Base } from './tokenizer';
|
|
4
|
+
export type AngleMode = 'deg' | 'rad' | 'grad';
|
|
5
|
+
export type PercentMode = 'of' | 'modulo';
|
|
6
|
+
export interface EvalOpts {
|
|
7
|
+
angleMode?: AngleMode;
|
|
8
|
+
percentMode?: PercentMode;
|
|
9
|
+
ans?: DecimalT | string | number;
|
|
10
|
+
memory?: DecimalT | string | number;
|
|
11
|
+
vars?: Record<string, DecimalT | string | number>;
|
|
12
|
+
base?: Base;
|
|
13
|
+
}
|
|
14
|
+
export declare function evaluate(ast: Node, opts?: EvalOpts): DecimalT;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type DecimalT } from '../decimal';
|
|
2
|
+
import { type Base } from './tokenizer';
|
|
3
|
+
import { type AngleMode, type PercentMode } from './evaluator';
|
|
4
|
+
export { tokenize } from './tokenizer';
|
|
5
|
+
export { parse } from './parser';
|
|
6
|
+
export { evaluate } from './evaluator';
|
|
7
|
+
export type { Node } from './parser';
|
|
8
|
+
export type { Token, Base } from './tokenizer';
|
|
9
|
+
export type { AngleMode, PercentMode, EvalOpts } from './evaluator';
|
|
10
|
+
export interface EvalExprOpts {
|
|
11
|
+
angleMode?: AngleMode;
|
|
12
|
+
percentMode?: PercentMode;
|
|
13
|
+
ans?: DecimalT | string | number;
|
|
14
|
+
memory?: DecimalT | string | number;
|
|
15
|
+
vars?: Record<string, DecimalT | string | number>;
|
|
16
|
+
base?: Base;
|
|
17
|
+
}
|
|
18
|
+
export interface EvalResult {
|
|
19
|
+
value: DecimalT;
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function evalExpression(input: string, opts?: EvalExprOpts): EvalResult;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Token } from './tokenizer';
|
|
2
|
+
export type Node = {
|
|
3
|
+
type: 'num';
|
|
4
|
+
value: string;
|
|
5
|
+
} | {
|
|
6
|
+
type: 'const';
|
|
7
|
+
name: string;
|
|
8
|
+
} | {
|
|
9
|
+
type: 'var';
|
|
10
|
+
name: string;
|
|
11
|
+
} | {
|
|
12
|
+
type: 'unary';
|
|
13
|
+
op: string;
|
|
14
|
+
operand: Node;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'binary';
|
|
17
|
+
op: string;
|
|
18
|
+
left: Node;
|
|
19
|
+
right: Node;
|
|
20
|
+
} | {
|
|
21
|
+
type: 'postfix';
|
|
22
|
+
op: string;
|
|
23
|
+
operand: Node;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'percent';
|
|
26
|
+
operand: Node;
|
|
27
|
+
} | {
|
|
28
|
+
type: 'call';
|
|
29
|
+
name: string;
|
|
30
|
+
args: Node[];
|
|
31
|
+
};
|
|
32
|
+
export declare function parse(tokens: Token[]): Node;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type Base = 'DEC' | 'HEX' | 'OCT' | 'BIN';
|
|
2
|
+
export type TokenType = 'num' | 'func' | 'const' | 'var' | 'op' | 'uop' | 'postfix' | 'lparen' | 'rparen' | 'comma';
|
|
3
|
+
export interface Token {
|
|
4
|
+
type: TokenType;
|
|
5
|
+
value: string;
|
|
6
|
+
implicit?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function tokenize(input: string, opts?: {
|
|
9
|
+
base?: Base;
|
|
10
|
+
}): Token[];
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { ResultView, Values } from '../core/kit';
|
|
2
|
+
import type { Region, Settings } from '../settings/settings';
|
|
3
|
+
export declare const SCHEMA_VERSION = 1;
|
|
4
|
+
export type ExportFormat = 'csv' | 'tsv' | 'json' | 'url' | 'clipboard' | 'markdown' | 'print' | 'ics' | 'pdf' | 'xlsx' | 'png' | 'qr';
|
|
5
|
+
export interface ExportPayload {
|
|
6
|
+
calculatorId: string;
|
|
7
|
+
title: string;
|
|
8
|
+
result: ResultView;
|
|
9
|
+
values: Values;
|
|
10
|
+
settingsSnapshot: Settings;
|
|
11
|
+
meta: {
|
|
12
|
+
computedAt: string;
|
|
13
|
+
region: Region;
|
|
14
|
+
currency: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface ExportResult {
|
|
18
|
+
ok: boolean;
|
|
19
|
+
note?: string;
|
|
20
|
+
filename?: string;
|
|
21
|
+
data?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ExportOptions {
|
|
24
|
+
scale?: 1 | 2 | 3;
|
|
25
|
+
schemaVersion?: number;
|
|
26
|
+
}
|
|
27
|
+
export declare const EXPORT_FORMATS: Array<{
|
|
28
|
+
id: ExportFormat;
|
|
29
|
+
label: string;
|
|
30
|
+
}>;
|
|
31
|
+
/** No path separators, no leading dots, no control/reserved chars. */
|
|
32
|
+
export declare function sanitizeFilename(name: string): string;
|
|
33
|
+
/** filenameTemplate '{calculator}-{yyyy}{MM}{dd}.{ext}' */
|
|
34
|
+
export declare function buildFilename(p: ExportPayload, ext: string): string;
|
|
35
|
+
/** Trigger a browser download for a Blob or string. */
|
|
36
|
+
export declare function download(filename: string, data: Blob | string, mime?: string): void;
|
|
37
|
+
export declare function toCsv(p: ExportPayload): string;
|
|
38
|
+
export declare function toTsv(p: ExportPayload): string;
|
|
39
|
+
export declare function toJson(p: ExportPayload, schemaVersion?: number): string;
|
|
40
|
+
export declare function importJson(text: string): {
|
|
41
|
+
calculatorId: string;
|
|
42
|
+
values: Values;
|
|
43
|
+
};
|
|
44
|
+
/** '#fincalc=<id>&s=<base64url({id,values})>'. base64url so URLSearchParams is safe. */
|
|
45
|
+
export declare function buildShareHash(id: string, values: Values): string;
|
|
46
|
+
export declare function parseShareUrl(hash: string): {
|
|
47
|
+
id: string;
|
|
48
|
+
values: Values;
|
|
49
|
+
} | null;
|
|
50
|
+
export declare function toMarkdown(p: ExportPayload): string;
|
|
51
|
+
export declare function toIcs(p: ExportPayload): string;
|
|
52
|
+
export declare function createExporter(opts?: ExportOptions): {
|
|
53
|
+
formats: ExportFormat[];
|
|
54
|
+
export(format: ExportFormat, payload: ExportPayload, options?: ExportOptions): Promise<ExportResult>;
|
|
55
|
+
};
|
|
56
|
+
export type Exporter = ReturnType<typeof createExporter>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export { SettingsProvider, SettingsProvider as FinCalcProvider, useSettings, useSettings as useFinCalc } from './settings/SettingsContext';
|
|
2
|
+
export { DEFAULT_SETTINGS, regionDefaults, POLICY_DEFAULT } from './settings/settings';
|
|
3
|
+
export type { Settings, Settings as FinCalcSettings, Region, RoundingPolicy, RoundingMode, DayCountConvention, Grouping, } from './settings/settings';
|
|
4
|
+
export { Launcher, Launcher as FinCalcLauncher } from './ui/Launcher';
|
|
5
|
+
export type { LauncherProps, LauncherApi } from './ui/Launcher';
|
|
6
|
+
export { Shell, Shell as FinCalcRoot } from './ui/Shell';
|
|
7
|
+
export { Dialog, Dialog as FinCalcDialog } from './ui/Dialog';
|
|
8
|
+
export { CommandPalette } from './ui/CommandPalette';
|
|
9
|
+
export { CalculatorPanel } from './ui/CalculatorPanel';
|
|
10
|
+
export { LoanEmiPanel } from './ui/LoanEmiPanel';
|
|
11
|
+
export { SciCalculator } from './ui/SciCalculator';
|
|
12
|
+
export { CurrencyConverter } from './ui/CurrencyConverter';
|
|
13
|
+
export { SettingsPanel } from './ui/SettingsPanel';
|
|
14
|
+
export { HistoryPanel } from './ui/HistoryPanel';
|
|
15
|
+
export { ResultCard } from './ui/ResultCard';
|
|
16
|
+
export { ScheduleTable } from './ui/ScheduleTable';
|
|
17
|
+
export { Chart } from './ui/Chart';
|
|
18
|
+
export { Field } from './ui/fields';
|
|
19
|
+
export { SaveButton } from './ui/SaveButton';
|
|
20
|
+
export { ExportMenu } from './ui/ExportMenu';
|
|
21
|
+
export { IntegrationPanel } from './ui/IntegrationPanel';
|
|
22
|
+
export { useHistory, saveHistory, clearHistory } from './ui/history';
|
|
23
|
+
export type { HistoryItem } from './ui/history';
|
|
24
|
+
export { registerCalculator, allCalculators, calculatorsForRegion, calculatorById, GROUPS } from './core/registry';
|
|
25
|
+
export { metric, numval, strval, boolval, dmoney } from './core/kit';
|
|
26
|
+
export type { CalculatorDef, FieldSchema, FieldKind, FieldValue, Values, ResultView, Metric, ScheduleView, ScheduleGroup, ScheduleRow, ChartSeries, CalcCtx, Group, } from './core/kit';
|
|
27
|
+
import { solve } from './core/loan';
|
|
28
|
+
/** Loan / EMI engine. `loan.solve({ region, product?, principal, annualRatePct, tenureMonths })`. */
|
|
29
|
+
export declare const loan: {
|
|
30
|
+
solve: typeof solve;
|
|
31
|
+
REGIONS: Record<import("./core/loan").Region, import(".").RegionProfile>;
|
|
32
|
+
};
|
|
33
|
+
export { solve as solveLoan } from './core/loan';
|
|
34
|
+
export type { LoanInput, LoanResult, RegionProfile, Basis, SolveTarget, AmortRow, YearSummary } from './core/loan';
|
|
35
|
+
export { FinCalcError } from './core/loan';
|
|
36
|
+
export * as finance from './core/finance';
|
|
37
|
+
export * as currency from './core/currency';
|
|
38
|
+
export { fetchLiveRate } from './core/liveRates';
|
|
39
|
+
export { makeFormatter } from './core/format';
|
|
40
|
+
export type { Formatter } from './core/format';
|
|
41
|
+
export { Decimal, D, eq, gt, lt, isZeroish } from './core/decimal';
|
|
42
|
+
export type { DecimalT, Numeric } from './core/decimal';
|
|
43
|
+
export { evalExpression, parse as parseExpression, evaluate as evaluateExpression } from './core/sci';
|
|
44
|
+
export { createExporter, EXPORT_FORMATS } from './export';
|
|
45
|
+
export type { ExportPayload, ExportFormat } from './export';
|
|
46
|
+
export { createTransport, sanitizeFilename, buildFilename } from './transport/client';
|
|
47
|
+
export { buildPayload, buildSavePayload, DEFAULT_ENVELOPE } from './transport/payload';
|
|
48
|
+
export { createFxCache } from './transport/fx';
|
|
49
|
+
export type { TransportConfig, UploadConfig, PayloadField } from './transport/types';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type Region, type Settings } from './settings';
|
|
3
|
+
import { type Formatter } from '../core/format';
|
|
4
|
+
type DeepPartial<T> = {
|
|
5
|
+
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
6
|
+
};
|
|
7
|
+
interface SettingsCtx {
|
|
8
|
+
settings: Settings;
|
|
9
|
+
fmt: Formatter;
|
|
10
|
+
update: (patch: DeepPartial<Settings>) => void;
|
|
11
|
+
setRegion: (r: Region) => void;
|
|
12
|
+
reset: () => void;
|
|
13
|
+
replace: (s: Settings) => void;
|
|
14
|
+
resolvedTheme: 'light' | 'dark' | 'highContrast';
|
|
15
|
+
}
|
|
16
|
+
export declare function SettingsProvider({ children }: {
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}): import("react").JSX.Element;
|
|
19
|
+
export declare function useSettings(): SettingsCtx;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type Region = 'IN' | 'US';
|
|
2
|
+
export type RoundingMode = 'HALF_UP' | 'HALF_EVEN' | 'HALF_DOWN' | 'UP' | 'DOWN' | 'CEIL' | 'FLOOR';
|
|
3
|
+
export type DayCountConvention = '30/360' | 'ACT/365' | 'ACT/360' | 'ACT/ACT' | '30E/360';
|
|
4
|
+
export type Grouping = 'indian' | 'western' | 'european' | 'swiss' | 'plain';
|
|
5
|
+
export interface RoundingPolicy {
|
|
6
|
+
money: number;
|
|
7
|
+
rate: number;
|
|
8
|
+
period: number;
|
|
9
|
+
mode: RoundingMode;
|
|
10
|
+
roundEachPeriod: boolean;
|
|
11
|
+
instalment: 'none' | 'ceilToUnit' | 'roundToUnit';
|
|
12
|
+
residualAbsorption: 'first' | 'last' | 'spread';
|
|
13
|
+
}
|
|
14
|
+
export interface Settings {
|
|
15
|
+
region: Region;
|
|
16
|
+
locale: string;
|
|
17
|
+
currency: {
|
|
18
|
+
code: string;
|
|
19
|
+
symbol: string;
|
|
20
|
+
symbolPosition: 'prefix' | 'suffix';
|
|
21
|
+
spaceAfterSymbol: boolean;
|
|
22
|
+
};
|
|
23
|
+
numberFormat: {
|
|
24
|
+
grouping: Grouping;
|
|
25
|
+
decimalPlaces: 0 | 1 | 2 | 3 | 4;
|
|
26
|
+
trimTrailingZeros: boolean;
|
|
27
|
+
abbreviate: boolean;
|
|
28
|
+
abbreviationScale: 'indian' | 'western';
|
|
29
|
+
abbreviateThreshold: number;
|
|
30
|
+
negativeFormat: 'minus' | 'parentheses';
|
|
31
|
+
percentPlaces: 0 | 1 | 2 | 3 | 4;
|
|
32
|
+
};
|
|
33
|
+
rounding: RoundingPolicy;
|
|
34
|
+
dayCount: DayCountConvention;
|
|
35
|
+
fiscalYearStart: {
|
|
36
|
+
month: number;
|
|
37
|
+
day: number;
|
|
38
|
+
};
|
|
39
|
+
ui: {
|
|
40
|
+
theme: 'light' | 'dark' | 'system' | 'highContrast';
|
|
41
|
+
accent: string;
|
|
42
|
+
fontFamily: string;
|
|
43
|
+
density: 'comfortable' | 'compact';
|
|
44
|
+
radius: 'sharp' | 'soft' | 'round';
|
|
45
|
+
showFormulas: boolean;
|
|
46
|
+
showAssumptions: boolean;
|
|
47
|
+
reducedMotion: 'system' | 'always' | 'never';
|
|
48
|
+
};
|
|
49
|
+
defaults: {
|
|
50
|
+
tenureUnit: 'years' | 'months' | 'both';
|
|
51
|
+
rateType: 'fixed' | 'floating';
|
|
52
|
+
maxRatePercent: number;
|
|
53
|
+
sipReturnPercent: string;
|
|
54
|
+
inflationPercent: string;
|
|
55
|
+
};
|
|
56
|
+
compliance: {
|
|
57
|
+
showDisclaimer: boolean;
|
|
58
|
+
disclaimerText?: string;
|
|
59
|
+
};
|
|
60
|
+
persistence: {
|
|
61
|
+
driver: 'none' | 'localStorage';
|
|
62
|
+
namespace: string;
|
|
63
|
+
historyLimit: number;
|
|
64
|
+
};
|
|
65
|
+
features: {
|
|
66
|
+
integrationPanel: boolean;
|
|
67
|
+
beta: boolean;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export declare const POLICY_DEFAULT: RoundingPolicy;
|
|
71
|
+
export declare function regionDefaults(region: Region): Settings;
|
|
72
|
+
export declare const DEFAULT_SETTINGS: Settings;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type TransportConfig, type UploadMeta } from './types';
|
|
2
|
+
/** Sanitise a filename: no path separators, no leading dots, no control chars. */
|
|
3
|
+
export declare function sanitizeFilename(name: string): string;
|
|
4
|
+
/** Fill a filenameTemplate then sanitise the result. */
|
|
5
|
+
export declare function buildFilename(template: string, meta: UploadMeta): string;
|
|
6
|
+
/** Mask auth-ish header values so nothing secret reaches a log or error. */
|
|
7
|
+
export declare function redactHeaders(headers: Record<string, string>, extraKeys?: string[]): Record<string, string>;
|
|
8
|
+
export interface QueueItem {
|
|
9
|
+
id: string;
|
|
10
|
+
endpoint: string;
|
|
11
|
+
method: string;
|
|
12
|
+
url: string;
|
|
13
|
+
body: unknown;
|
|
14
|
+
headers: Record<string, string>;
|
|
15
|
+
createdAt: string;
|
|
16
|
+
retryCount: number;
|
|
17
|
+
lastError?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface CallOptions {
|
|
20
|
+
headers?: Record<string, string>;
|
|
21
|
+
query?: Record<string, string | number | undefined | null>;
|
|
22
|
+
pathParam?: string;
|
|
23
|
+
idempotencyKey?: string;
|
|
24
|
+
signal?: AbortSignal;
|
|
25
|
+
}
|
|
26
|
+
export interface QueuedResult {
|
|
27
|
+
queued: true;
|
|
28
|
+
id: string;
|
|
29
|
+
}
|
|
30
|
+
export type Transport = ReturnType<typeof createTransport>;
|
|
31
|
+
export declare function createTransport(config: TransportConfig): {
|
|
32
|
+
save: <T = unknown>(body: unknown, opts?: CallOptions) => Promise<QueuedResult | T>;
|
|
33
|
+
update: <T = unknown>(id: string, body: unknown, opts?: CallOptions) => Promise<QueuedResult | T>;
|
|
34
|
+
get: <T = unknown>(id: string, opts?: CallOptions) => Promise<QueuedResult | T>;
|
|
35
|
+
list: <T = unknown>(query?: CallOptions["query"], opts?: CallOptions) => Promise<QueuedResult | T>;
|
|
36
|
+
delete: <T = unknown>(id: string, opts?: CallOptions) => Promise<QueuedResult | T>;
|
|
37
|
+
upload: (file: Blob, meta: UploadMeta, opts?: CallOptions) => Promise<unknown>;
|
|
38
|
+
getRates: (base: string, symbols: string[], opts?: CallOptions) => Promise<QueuedResult | {
|
|
39
|
+
base: string;
|
|
40
|
+
timestamp: string;
|
|
41
|
+
rates: Record<string, string>;
|
|
42
|
+
}>;
|
|
43
|
+
/** Offline queue inspector — flush re-sends with freshly-resolved auth. */
|
|
44
|
+
queue: {
|
|
45
|
+
list: () => QueueItem[];
|
|
46
|
+
size: () => number;
|
|
47
|
+
clear: () => void;
|
|
48
|
+
remove: (id: string) => void;
|
|
49
|
+
flush: () => Promise<{
|
|
50
|
+
flushed: number;
|
|
51
|
+
failed: number;
|
|
52
|
+
}>;
|
|
53
|
+
};
|
|
54
|
+
};
|