mortgage-calculator-package 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/README.md +1 -0
- package/package.json +56 -0
- package/src/calculator.ts +13 -0
- package/src/fonts/Mont-ExtraLight.otf +0 -0
- package/src/fonts/Mont-Heavy.otf +0 -0
- package/src/index.ts +101 -0
- package/src/styles.scss +232 -0
- package/src/test-webpage.html +22 -0
- package/tsconfig.json +16 -0
- package/webpack.config.js +45 -0
package/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# mortgage-calculator-package
|
package/package.json
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
{
|
2
|
+
"name": "mortgage-calculator-package",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"description": "A simple, embeddable mortgage calculator that dynamically generates an interactive and styled calculator widget. It allows users to input mortgage amount, interest rate, amortization period, and payment frequency, and calculates the monthly payment based on these inputs. The package handles both the mortgage calculation logic and the HTML/CSS rendering, making it easy to integrate into any webpage by simply providing a container ID. Ideal for real estate websites, financial tools, and blogs.",
|
5
|
+
"main": "index.js",
|
6
|
+
"scripts": {
|
7
|
+
"build": "webpack --config webpack.config.js",
|
8
|
+
"dev": "webpack serve --open",
|
9
|
+
"sass": "sass src/styles.scss dist/styles.css"
|
10
|
+
},
|
11
|
+
"repository": {
|
12
|
+
"type": "git",
|
13
|
+
"url": "git+https://github.com/Admin-Kreate/mortgage-calculator-package.git"
|
14
|
+
},
|
15
|
+
"keywords": [
|
16
|
+
"mortgage",
|
17
|
+
"calculator",
|
18
|
+
"mortgage-calculator",
|
19
|
+
"finance",
|
20
|
+
"loan",
|
21
|
+
"interest-rate",
|
22
|
+
"amortization",
|
23
|
+
"payments",
|
24
|
+
"mortgage-tool",
|
25
|
+
"real-estate",
|
26
|
+
"home-loan",
|
27
|
+
"npm-package",
|
28
|
+
"embeddable-widget",
|
29
|
+
"web-calculator"
|
30
|
+
],
|
31
|
+
"author": "Muhammad Rehan Abbasi <rehanabbasi120@gmail.com>",
|
32
|
+
"license": "ISC",
|
33
|
+
"bugs": {
|
34
|
+
"url": "https://github.com/Admin-Kreate/mortgage-calculator-package/issues"
|
35
|
+
},
|
36
|
+
"homepage": "https://github.com/Admin-Kreate/mortgage-calculator-package#readme",
|
37
|
+
"devDependencies": {
|
38
|
+
"@types/jest": "^29.5.13",
|
39
|
+
"@types/node": "^22.7.7",
|
40
|
+
"copyfiles": "^2.4.1",
|
41
|
+
"css-loader": "^7.1.2",
|
42
|
+
"html-webpack-plugin": "^5.6.2",
|
43
|
+
"jest": "^29.7.0",
|
44
|
+
"mini-css-extract-plugin": "^2.9.1",
|
45
|
+
"sass": "^1.80.3",
|
46
|
+
"sass-loader": "^16.0.2",
|
47
|
+
"style-loader": "^4.0.0",
|
48
|
+
"ts-jest": "^29.2.5",
|
49
|
+
"ts-loader": "^9.5.1",
|
50
|
+
"ts-node": "^10.9.2",
|
51
|
+
"typescript": "^5.6.3",
|
52
|
+
"webpack": "^5.95.0",
|
53
|
+
"webpack-cli": "^5.1.4",
|
54
|
+
"webpack-dev-server": "^5.1.0"
|
55
|
+
}
|
56
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
export function calculateMortgage(
|
2
|
+
principal: number,
|
3
|
+
interestRate: number,
|
4
|
+
years: number,
|
5
|
+
paymentFrequency: number
|
6
|
+
): number {
|
7
|
+
const months = years * paymentFrequency;
|
8
|
+
const monthlyInterestRate = interestRate / paymentFrequency / 100;
|
9
|
+
return (
|
10
|
+
(principal * monthlyInterestRate) /
|
11
|
+
(1 - Math.pow(1 + monthlyInterestRate, -months))
|
12
|
+
);
|
13
|
+
}
|
Binary file
|
Binary file
|
package/src/index.ts
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
import './styles.scss';
|
2
|
+
import { calculateMortgage } from './calculator';
|
3
|
+
|
4
|
+
function handleCalculation() {
|
5
|
+
const mortgageAmountInput = document.getElementById('mortgage-amount-field') as HTMLInputElement;
|
6
|
+
const rateInput = document.getElementById('rate-field') as HTMLInputElement;
|
7
|
+
const amortizationSelect = document.getElementById('amortization-field') as HTMLSelectElement;
|
8
|
+
const paymentPeriodSelect = document.getElementById('payment-period-field') as HTMLSelectElement;
|
9
|
+
const mortagagePaymentElement = document.getElementById('mortagage-payment') as HTMLParagraphElement;
|
10
|
+
|
11
|
+
const mortgageAmount = parseFloat(mortgageAmountInput.value.replace(/\$/g, '').replace(/\,/g, ''));
|
12
|
+
const rate = parseFloat(rateInput.value.replace(/%/g, ''));
|
13
|
+
const amortization = parseInt(amortizationSelect.value);
|
14
|
+
const paymentPeriod = parseInt(paymentPeriodSelect.value);
|
15
|
+
|
16
|
+
if (isNaN(mortgageAmount) || isNaN(rate) || isNaN(amortization) || isNaN(paymentPeriod)) {
|
17
|
+
return;
|
18
|
+
}
|
19
|
+
|
20
|
+
const payment = calculateMortgage(mortgageAmount, rate, amortization, paymentPeriod);
|
21
|
+
mortagagePaymentElement.textContent = `$${parseFloat(payment.toFixed(2)).toLocaleString('en-US')}`;
|
22
|
+
}
|
23
|
+
|
24
|
+
export function init(options: { containerId: string }) {
|
25
|
+
const container = document.getElementById(options.containerId);
|
26
|
+
|
27
|
+
if (!container) {
|
28
|
+
console.error('Mortgage Calculator container not found');
|
29
|
+
return;
|
30
|
+
}
|
31
|
+
|
32
|
+
container.innerHTML = `
|
33
|
+
<div class="mortgage-calculator">
|
34
|
+
<div class="section-heading"><span>Mortgage</span> Payment <span>Calculator</span></div>
|
35
|
+
<div class="calculator-fields">
|
36
|
+
<div class="mortgage-amount-wrapper">
|
37
|
+
<div class="calculator-floating-label-field">
|
38
|
+
<label>Mortgage Amount</label>
|
39
|
+
<input type="text" id="mortgage-amount-field" />
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
<div class="rate-amortization-period-wrapper">
|
43
|
+
<div class="calculator-fixed-label-field">
|
44
|
+
<label>Rates</label>
|
45
|
+
<input type="text" id="rate-field" />
|
46
|
+
</div>
|
47
|
+
<div class="calculator-fixed-label-field">
|
48
|
+
<label>Amortization</label>
|
49
|
+
<select id="amortization-field">
|
50
|
+
<option value="10">10 years</option>
|
51
|
+
<option value="15">15 years</option>
|
52
|
+
<option value="20">20 years</option>
|
53
|
+
<option value="25">25 years</option>
|
54
|
+
</select>
|
55
|
+
</div>
|
56
|
+
<div class="calculator-fixed-label-field">
|
57
|
+
<label>Payment Period</label>
|
58
|
+
<select id="payment-period-field">
|
59
|
+
<option value="12">Monthly</option>
|
60
|
+
<option value="6">Bi-Annually</option>
|
61
|
+
<option value="1">Annually</option>
|
62
|
+
</select>
|
63
|
+
</div>
|
64
|
+
</div>
|
65
|
+
<div class="apply-wrapper">
|
66
|
+
<div id="mortagage-payment"></div>
|
67
|
+
<button>Apply</button>
|
68
|
+
</div>
|
69
|
+
</div>
|
70
|
+
</div>
|
71
|
+
`;
|
72
|
+
|
73
|
+
const mortgageAmountInput = document.getElementById('mortgage-amount-field') as HTMLInputElement;
|
74
|
+
const rateInput = document.getElementById('rate-field') as HTMLInputElement;
|
75
|
+
const amortizationSelect = document.getElementById('amortization-field') as HTMLSelectElement;
|
76
|
+
const paymentPeriodSelect = document.getElementById('payment-period-field') as HTMLSelectElement;
|
77
|
+
|
78
|
+
// Reusable function for handling dollar sign and percentage symbol formatting
|
79
|
+
const formatInput = (inputElement: HTMLInputElement, symbol: string) => {
|
80
|
+
inputElement.addEventListener('input', (event) => {
|
81
|
+
const target = event.target as HTMLInputElement;
|
82
|
+
if (target) {
|
83
|
+
let value = target.value;
|
84
|
+
value = value.replace(/[^0-9.]/g, ''); // Remove non-numeric characters
|
85
|
+
|
86
|
+
// Reapply the symbol (either $ or %)
|
87
|
+
target.value = value ? symbol === '$' ? `${symbol}${parseInt(value).toLocaleString('en-US')}` : `${value}${symbol}` : '';
|
88
|
+
}
|
89
|
+
});
|
90
|
+
};
|
91
|
+
|
92
|
+
// Add formatting for currency and percentage inputs
|
93
|
+
formatInput(mortgageAmountInput, '$');
|
94
|
+
formatInput(rateInput, '%');
|
95
|
+
|
96
|
+
// Attach event listeners to each input/select field to auto-calculate on change
|
97
|
+
mortgageAmountInput.addEventListener('input', handleCalculation);
|
98
|
+
rateInput.addEventListener('input', handleCalculation);
|
99
|
+
amortizationSelect.addEventListener('change', handleCalculation);
|
100
|
+
paymentPeriodSelect.addEventListener('change', handleCalculation);
|
101
|
+
}
|
package/src/styles.scss
ADDED
@@ -0,0 +1,232 @@
|
|
1
|
+
$mortgage-calculator-bg-color: #f7f7f7;
|
2
|
+
$mortgage-calculator-border-color: #ccc;
|
3
|
+
$mortgage-calculator-color-white: #ffffff;
|
4
|
+
$mortgage-calculator-border-radius: 8px;
|
5
|
+
$mortgage-calculator-button-bg-color: #007BFF;
|
6
|
+
|
7
|
+
@font-face {
|
8
|
+
font-family: 'Mont Extra Light';
|
9
|
+
src: url('./fonts/Mont-ExtraLight.otf') format('opentype');
|
10
|
+
font-weight: normal;
|
11
|
+
font-style: normal;
|
12
|
+
}
|
13
|
+
|
14
|
+
@font-face {
|
15
|
+
font-family: 'Mont Heavy';
|
16
|
+
src: url('./fonts/Mont-Heavy.otf') format('opentype');
|
17
|
+
font-weight: normal;
|
18
|
+
font-style: normal;
|
19
|
+
}
|
20
|
+
|
21
|
+
$desktop-breakpoint: 992px;
|
22
|
+
|
23
|
+
@mixin respond-to-mobile {
|
24
|
+
@media (max-width: ($desktop-breakpoint - 1)) {
|
25
|
+
@content;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
@mixin respond-to-desktop {
|
30
|
+
@media (min-width: $desktop-breakpoint) {
|
31
|
+
@content;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
.mortgage-calculator {
|
36
|
+
max-width: fit-content;
|
37
|
+
margin: auto;
|
38
|
+
|
39
|
+
.section-heading {
|
40
|
+
font-family: 'Mont Extra Light', sans-serif;
|
41
|
+
font-size: 56px;
|
42
|
+
font-weight: 600;
|
43
|
+
line-height: 74px;
|
44
|
+
text-align: center;
|
45
|
+
padding-bottom: 2rem;
|
46
|
+
|
47
|
+
span {
|
48
|
+
font-family: 'Mont Heavy', sans-serif;
|
49
|
+
font-weight: 800;
|
50
|
+
}
|
51
|
+
|
52
|
+
@include respond-to-mobile {
|
53
|
+
font-size: 42px;
|
54
|
+
line-height: 50px;
|
55
|
+
padding-bottom: 0;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
.calculator-fields {
|
60
|
+
position: relative;
|
61
|
+
background-color: $mortgage-calculator-color-white;
|
62
|
+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
63
|
+
|
64
|
+
@include respond-to-mobile {
|
65
|
+
background: unset;
|
66
|
+
box-shadow: unset;
|
67
|
+
}
|
68
|
+
|
69
|
+
.mortgage-amount-wrapper {
|
70
|
+
display: grid;
|
71
|
+
grid-template-columns: auto;
|
72
|
+
justify-content: center;
|
73
|
+
align-items: center;
|
74
|
+
padding-top: 3rem;
|
75
|
+
|
76
|
+
@include respond-to-mobile {
|
77
|
+
grid-template-columns: 1fr;
|
78
|
+
padding: 3rem 1rem 0 1rem;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
.rate-amortization-period-wrapper {
|
83
|
+
display: grid;
|
84
|
+
grid-template-columns: repeat(3, auto);
|
85
|
+
justify-content: center;
|
86
|
+
align-items: center;
|
87
|
+
grid-gap: 1rem;
|
88
|
+
padding: 2rem 0 6rem 0;
|
89
|
+
|
90
|
+
@include respond-to-mobile {
|
91
|
+
grid-template-columns: 1fr;
|
92
|
+
padding: 1rem;
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
.calculator-floating-label-field {
|
97
|
+
position: relative;
|
98
|
+
|
99
|
+
label {
|
100
|
+
font-family: 'Mont Extra Light', sans-serif;
|
101
|
+
font-size: 16px;
|
102
|
+
font-weight: 400;
|
103
|
+
line-height: 20px;
|
104
|
+
background-color: $mortgage-calculator-color-white;
|
105
|
+
|
106
|
+
position: absolute;
|
107
|
+
top: -0.75rem;
|
108
|
+
left: 1rem;
|
109
|
+
padding: 0.25rem 0.5rem;
|
110
|
+
}
|
111
|
+
|
112
|
+
input,
|
113
|
+
select {
|
114
|
+
font-family: 'Mont Heavy', sans-serif;
|
115
|
+
font-size: 22px;
|
116
|
+
font-weight: 800;
|
117
|
+
line-height: 30px;
|
118
|
+
max-width: 250px;
|
119
|
+
border-radius: 4px;
|
120
|
+
border: 1px solid $mortgage-calculator-border-color;
|
121
|
+
padding: 1rem;
|
122
|
+
|
123
|
+
@include respond-to-mobile {
|
124
|
+
max-width: unset;
|
125
|
+
width: -webkit-fill-available;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
select {
|
130
|
+
padding: 1.3rem;
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
.calculator-fixed-label-field {
|
135
|
+
display: grid;
|
136
|
+
border: 1px solid #ccc;
|
137
|
+
border-radius: 4px;
|
138
|
+
padding: 0.5rem 1rem;
|
139
|
+
|
140
|
+
label {
|
141
|
+
font-family: 'Mont Extra Light', sans-serif;
|
142
|
+
font-size: 14px;
|
143
|
+
font-weight: 400;
|
144
|
+
line-height: 14px;
|
145
|
+
background-color: $mortgage-calculator-color-white;
|
146
|
+
|
147
|
+
padding: 0.25rem 0;
|
148
|
+
}
|
149
|
+
|
150
|
+
input,
|
151
|
+
select {
|
152
|
+
font-family: 'Mont Heavy', sans-serif;
|
153
|
+
font-size: 22px;
|
154
|
+
font-weight: 800;
|
155
|
+
line-height: 22px;
|
156
|
+
max-width: 250px;
|
157
|
+
|
158
|
+
padding: 0;
|
159
|
+
border: none;
|
160
|
+
outline: none;
|
161
|
+
box-shadow: none;
|
162
|
+
|
163
|
+
@include respond-to-mobile {
|
164
|
+
max-width: unset;
|
165
|
+
width: -webkit-fill-available;
|
166
|
+
}
|
167
|
+
|
168
|
+
&:focus {
|
169
|
+
border: none;
|
170
|
+
outline: none;
|
171
|
+
box-shadow: none;
|
172
|
+
}
|
173
|
+
}
|
174
|
+
|
175
|
+
select {
|
176
|
+
padding: 0.2rem 0;
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
.masked-input {
|
181
|
+
display: grid;
|
182
|
+
grid-template-columns: repeat(2, auto);
|
183
|
+
align-items: center;
|
184
|
+
}
|
185
|
+
|
186
|
+
.apply-wrapper {
|
187
|
+
display: grid;
|
188
|
+
grid-template-columns: repeat(2, 250px);
|
189
|
+
justify-items: center;
|
190
|
+
align-items: center;
|
191
|
+
grid-gap: 0.5rem;
|
192
|
+
background: #1A1A30;
|
193
|
+
border-radius: 30px;
|
194
|
+
|
195
|
+
position: absolute;
|
196
|
+
bottom: -4rem;
|
197
|
+
left: 10rem;
|
198
|
+
padding: 2rem;
|
199
|
+
|
200
|
+
@include respond-to-mobile {
|
201
|
+
position: unset;
|
202
|
+
grid-template-columns: auto;
|
203
|
+
padding: 1rem;
|
204
|
+
margin: 1rem;
|
205
|
+
}
|
206
|
+
|
207
|
+
|
208
|
+
#mortagage-payment {
|
209
|
+
font-family: 'Mont Extra Light', sans-serif;
|
210
|
+
font-size: 42px;
|
211
|
+
font-weight: 700;
|
212
|
+
line-height: 56px;
|
213
|
+
color: $mortgage-calculator-color-white;
|
214
|
+
}
|
215
|
+
|
216
|
+
button {
|
217
|
+
font-family: 'Mont Extra Light', sans-serif;
|
218
|
+
font-size: 20px;
|
219
|
+
font-weight: 800;
|
220
|
+
line-height: 27px;
|
221
|
+
color: #1A1A30;
|
222
|
+
text-transform: uppercase;
|
223
|
+
background: $mortgage-calculator-color-white;
|
224
|
+
width: 200px;
|
225
|
+
border-radius: 2rem;
|
226
|
+
padding: 0.5rem;
|
227
|
+
border: none;
|
228
|
+
cursor: pointer;
|
229
|
+
}
|
230
|
+
}
|
231
|
+
}
|
232
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
|
4
|
+
<head>
|
5
|
+
<meta charset="UTF-8">
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
+
<title>Mortgage Calculator Test</title>
|
8
|
+
</head>
|
9
|
+
|
10
|
+
<body>
|
11
|
+
<div id="mortgage-calculator-container"></div>
|
12
|
+
|
13
|
+
<script>
|
14
|
+
window.addEventListener('DOMContentLoaded', () => {
|
15
|
+
MortgageCalculator.init({
|
16
|
+
containerId: 'mortgage-calculator-container',
|
17
|
+
});
|
18
|
+
});
|
19
|
+
</script>
|
20
|
+
</body>
|
21
|
+
|
22
|
+
</html>
|
package/tsconfig.json
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
{
|
2
|
+
"compilerOptions": {
|
3
|
+
"outDir": "./dist",
|
4
|
+
"rootDir": "./src",
|
5
|
+
"target": "es6",
|
6
|
+
"module": "commonjs",
|
7
|
+
"esModuleInterop": true,
|
8
|
+
"strict": true,
|
9
|
+
"skipLibCheck": true,
|
10
|
+
"declaration": true
|
11
|
+
},
|
12
|
+
"exclude": [
|
13
|
+
"node_modules",
|
14
|
+
"dist"
|
15
|
+
]
|
16
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
const path = require("path");
|
2
|
+
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
3
|
+
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
4
|
+
|
5
|
+
module.exports = {
|
6
|
+
entry: "./src/index.ts",
|
7
|
+
output: {
|
8
|
+
filename: "index.js",
|
9
|
+
path: path.resolve(__dirname, "dist"),
|
10
|
+
library: "MortgageCalculator",
|
11
|
+
libraryTarget: "umd",
|
12
|
+
umdNamedDefine: true,
|
13
|
+
clean: true,
|
14
|
+
},
|
15
|
+
resolve: {
|
16
|
+
extensions: [".ts", ".js"],
|
17
|
+
},
|
18
|
+
module: {
|
19
|
+
rules: [
|
20
|
+
{
|
21
|
+
test: /\.ts$/,
|
22
|
+
use: "ts-loader",
|
23
|
+
exclude: /node_modules/,
|
24
|
+
},
|
25
|
+
{
|
26
|
+
test: /\.scss$/,
|
27
|
+
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
|
28
|
+
},
|
29
|
+
],
|
30
|
+
},
|
31
|
+
plugins: [
|
32
|
+
new MiniCssExtractPlugin({
|
33
|
+
filename: "styles.css",
|
34
|
+
}),
|
35
|
+
new HtmlWebpackPlugin({
|
36
|
+
template: "./src/test-webpage.html", // Path to your HTML template
|
37
|
+
}),
|
38
|
+
],
|
39
|
+
mode: "development",
|
40
|
+
devtool: "source-map",
|
41
|
+
devServer: {
|
42
|
+
port: 8080,
|
43
|
+
hot: true,
|
44
|
+
},
|
45
|
+
};
|