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 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
+ }
@@ -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
+ };