@cranberry-money/shared-utils 8.17.39 → 8.17.41
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/dist/downloads.d.ts +1 -34
- package/dist/downloads.d.ts.map +1 -1
- package/dist/downloads.js +0 -71
- package/dist/filters.d.ts +1 -39
- package/dist/filters.d.ts.map +1 -1
- package/dist/filters.js +0 -97
- package/dist/holdings.d.ts +1 -63
- package/dist/holdings.d.ts.map +1 -1
- package/dist/holdings.js +0 -116
- package/dist/index.d.ts +3 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -17
- package/package.json +1 -1
package/dist/downloads.d.ts
CHANGED
|
@@ -9,37 +9,4 @@
|
|
|
9
9
|
* @param filename - The filename for the downloaded file
|
|
10
10
|
*/
|
|
11
11
|
export declare function downloadBlob(blob: Blob, filename: string): void;
|
|
12
|
-
|
|
13
|
-
* Download text content as a file
|
|
14
|
-
* @param content - Text content to download
|
|
15
|
-
* @param filename - The filename for the downloaded file
|
|
16
|
-
* @param mimeType - MIME type for the file (default: text/plain)
|
|
17
|
-
*/
|
|
18
|
-
export declare function downloadTextFile(content: string, filename: string, mimeType?: string): void;
|
|
19
|
-
/**
|
|
20
|
-
* Download JSON data as a file
|
|
21
|
-
* @param data - JavaScript object to serialize and download
|
|
22
|
-
* @param filename - The filename for the downloaded file (should end with .json)
|
|
23
|
-
*/
|
|
24
|
-
export declare function downloadJsonFile(data: unknown, filename: string): void;
|
|
25
|
-
/**
|
|
26
|
-
* Generate a timestamped filename
|
|
27
|
-
* @param baseName - Base name for the file (without extension)
|
|
28
|
-
* @param extension - File extension (with or without leading dot)
|
|
29
|
-
* @param includeTime - Whether to include time in timestamp (default: false)
|
|
30
|
-
* @returns Timestamped filename
|
|
31
|
-
*/
|
|
32
|
-
export declare function generateTimestampedFilename(baseName: string, extension: string, includeTime?: boolean): string;
|
|
33
|
-
/**
|
|
34
|
-
* Download data URL as a file
|
|
35
|
-
* @param dataUrl - Data URL (data:mime/type;base64,data)
|
|
36
|
-
* @param filename - The filename for the downloaded file
|
|
37
|
-
*/
|
|
38
|
-
export declare function downloadDataUrl(dataUrl: string, filename: string): void;
|
|
39
|
-
/**
|
|
40
|
-
* Download CSV data as a file
|
|
41
|
-
* @param data - Array of objects to convert to CSV
|
|
42
|
-
* @param filename - The filename for the downloaded file (should end with .csv)
|
|
43
|
-
* @param headers - Optional custom headers (uses object keys if not provided)
|
|
44
|
-
*/
|
|
45
|
-
export declare function downloadCsvFile<T extends Record<string, unknown>>(data: T[], filename: string, headers?: string[]): void;
|
|
12
|
+
//# sourceMappingURL=downloads.d.ts.map
|
package/dist/downloads.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"downloads.d.ts","sourceRoot":"","sources":["../src/downloads.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAS/D
|
|
1
|
+
{"version":3,"file":"downloads.d.ts","sourceRoot":"","sources":["../src/downloads.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAS/D"}
|
package/dist/downloads.js
CHANGED
|
@@ -18,74 +18,3 @@ export function downloadBlob(blob, filename) {
|
|
|
18
18
|
document.body.removeChild(link);
|
|
19
19
|
window.URL.revokeObjectURL(url);
|
|
20
20
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Download text content as a file
|
|
23
|
-
* @param content - Text content to download
|
|
24
|
-
* @param filename - The filename for the downloaded file
|
|
25
|
-
* @param mimeType - MIME type for the file (default: text/plain)
|
|
26
|
-
*/
|
|
27
|
-
export function downloadTextFile(content, filename, mimeType = 'text/plain') {
|
|
28
|
-
const blob = new Blob([content], { type: mimeType });
|
|
29
|
-
downloadBlob(blob, filename);
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Download JSON data as a file
|
|
33
|
-
* @param data - JavaScript object to serialize and download
|
|
34
|
-
* @param filename - The filename for the downloaded file (should end with .json)
|
|
35
|
-
*/
|
|
36
|
-
export function downloadJsonFile(data, filename) {
|
|
37
|
-
const jsonString = JSON.stringify(data, null, 2);
|
|
38
|
-
downloadTextFile(jsonString, filename, 'application/json');
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Generate a timestamped filename
|
|
42
|
-
* @param baseName - Base name for the file (without extension)
|
|
43
|
-
* @param extension - File extension (with or without leading dot)
|
|
44
|
-
* @param includeTime - Whether to include time in timestamp (default: false)
|
|
45
|
-
* @returns Timestamped filename
|
|
46
|
-
*/
|
|
47
|
-
export function generateTimestampedFilename(baseName, extension, includeTime = false) {
|
|
48
|
-
const now = new Date();
|
|
49
|
-
const dateString = now.toISOString().split('T')[0]; // YYYY-MM-DD
|
|
50
|
-
const timeString = now.toTimeString().split(' ')[0]?.replace(/:/g, '-') || '00-00-00'; // HH-MM-SS
|
|
51
|
-
const cleanExtension = extension.startsWith('.') ? extension : `.${extension}`;
|
|
52
|
-
const timestamp = includeTime ? `${dateString}-${timeString}` : dateString;
|
|
53
|
-
return `${baseName}-${timestamp}${cleanExtension}`;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Download data URL as a file
|
|
57
|
-
* @param dataUrl - Data URL (data:mime/type;base64,data)
|
|
58
|
-
* @param filename - The filename for the downloaded file
|
|
59
|
-
*/
|
|
60
|
-
export function downloadDataUrl(dataUrl, filename) {
|
|
61
|
-
const link = document.createElement('a');
|
|
62
|
-
link.href = dataUrl;
|
|
63
|
-
link.setAttribute('download', filename);
|
|
64
|
-
document.body.appendChild(link);
|
|
65
|
-
link.click();
|
|
66
|
-
document.body.removeChild(link);
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Download CSV data as a file
|
|
70
|
-
* @param data - Array of objects to convert to CSV
|
|
71
|
-
* @param filename - The filename for the downloaded file (should end with .csv)
|
|
72
|
-
* @param headers - Optional custom headers (uses object keys if not provided)
|
|
73
|
-
*/
|
|
74
|
-
export function downloadCsvFile(data, filename, headers) {
|
|
75
|
-
if (data.length === 0) {
|
|
76
|
-
throw new Error('Cannot create CSV from empty data array');
|
|
77
|
-
}
|
|
78
|
-
const csvHeaders = headers || Object.keys(data[0] || {});
|
|
79
|
-
const csvRows = data.map(row => csvHeaders
|
|
80
|
-
.map(header => {
|
|
81
|
-
const value = row[header];
|
|
82
|
-
// Escape commas and quotes in CSV values
|
|
83
|
-
const stringValue = String(value ?? '');
|
|
84
|
-
return stringValue.includes(',') || stringValue.includes('"')
|
|
85
|
-
? `"${stringValue.replace(/"/g, '""')}"`
|
|
86
|
-
: stringValue;
|
|
87
|
-
})
|
|
88
|
-
.join(','));
|
|
89
|
-
const csvContent = [csvHeaders.join(','), ...csvRows].join('\n');
|
|
90
|
-
downloadTextFile(csvContent, filename, 'text/csv');
|
|
91
|
-
}
|
package/dist/filters.d.ts
CHANGED
|
@@ -16,13 +16,6 @@ export declare function hasActiveFilters<T extends Record<string, unknown>>(filt
|
|
|
16
16
|
* @returns The number of active filters
|
|
17
17
|
*/
|
|
18
18
|
export declare function countActiveFilters<T extends Record<string, unknown>>(filters: T, excludeFields?: (keyof T)[]): number;
|
|
19
|
-
/**
|
|
20
|
-
* Clears all filters except specified fields
|
|
21
|
-
* @param filters - The filter object to clear
|
|
22
|
-
* @param preserveFields - Fields to preserve when clearing (default: [])
|
|
23
|
-
* @returns A new filter object with cleared values
|
|
24
|
-
*/
|
|
25
|
-
export declare function clearAllFilters<T extends Record<string, unknown>>(filters: T, preserveFields?: (keyof T)[]): Partial<T>;
|
|
26
19
|
/**
|
|
27
20
|
* Type-safe filter update helper
|
|
28
21
|
* @param currentFilters - The current filter state
|
|
@@ -30,38 +23,6 @@ export declare function clearAllFilters<T extends Record<string, unknown>>(filte
|
|
|
30
23
|
* @returns A new filter object with updates applied
|
|
31
24
|
*/
|
|
32
25
|
export declare function updateFilters<T extends Record<string, unknown>>(currentFilters: T, updates: Partial<T>): T;
|
|
33
|
-
/**
|
|
34
|
-
* Checks if a filter value is empty
|
|
35
|
-
* @param value - The value to check
|
|
36
|
-
* @returns true if the value is empty, false otherwise
|
|
37
|
-
*/
|
|
38
|
-
export declare function isFilterEmpty(value: unknown): boolean;
|
|
39
|
-
/**
|
|
40
|
-
* Removes empty filter values from an object
|
|
41
|
-
* @param filters - The filter object to clean
|
|
42
|
-
* @returns A new filter object with empty values removed
|
|
43
|
-
*/
|
|
44
|
-
export declare function removeEmptyFilters<T extends Record<string, unknown>>(filters: T): Partial<T>;
|
|
45
|
-
/**
|
|
46
|
-
* Merges two filter objects, with the second object taking precedence
|
|
47
|
-
* @param baseFilters - The base filter object
|
|
48
|
-
* @param overrideFilters - The override filter object
|
|
49
|
-
* @returns A new merged filter object
|
|
50
|
-
*/
|
|
51
|
-
export declare function mergeFilters<T extends Record<string, unknown>>(baseFilters: T, overrideFilters: Partial<T>): T;
|
|
52
|
-
/**
|
|
53
|
-
* Compares two filter objects for equality
|
|
54
|
-
* @param filters1 - The first filter object
|
|
55
|
-
* @param filters2 - The second filter object
|
|
56
|
-
* @returns true if the filters are equal, false otherwise
|
|
57
|
-
*/
|
|
58
|
-
export declare function areFiltersEqual<T extends Record<string, unknown>>(filters1: T, filters2: T): boolean;
|
|
59
|
-
/**
|
|
60
|
-
* Creates a filter predicate function from a filter object
|
|
61
|
-
* @param filters - The filter object to create a predicate from
|
|
62
|
-
* @returns A predicate function that tests if an item matches the filters
|
|
63
|
-
*/
|
|
64
|
-
export declare function createFilterPredicate<T extends Record<string, unknown>, U extends Record<string, unknown>>(filters: T): (item: U) => boolean;
|
|
65
26
|
/**
|
|
66
27
|
* Check if any instrument filters are active (excluding searchQuery)
|
|
67
28
|
* Common pattern for instrument filter checking across applications
|
|
@@ -118,3 +79,4 @@ export declare function hasActiveTargetTradeFilters<T extends Record<string, unk
|
|
|
118
79
|
* @returns number of active non-search filters
|
|
119
80
|
*/
|
|
120
81
|
export declare function countActiveTargetTradeFilters<T extends Record<string, unknown>>(filters: T): number;
|
|
82
|
+
//# sourceMappingURL=filters.d.ts.map
|
package/dist/filters.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../src/filters.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,OAAO,EAAE,CAAC,EACV,aAAa,GAAE,CAAC,MAAM,CAAC,CAAC,EAA+B,GACtD,OAAO,CAOT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,OAAO,EAAE,CAAC,EACV,aAAa,GAAE,CAAC,MAAM,CAAC,CAAC,EAA+B,GACtD,MAAM,CAOR;AAED;;;;;GAKG;AACH,wBAAgB,
|
|
1
|
+
{"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../src/filters.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,OAAO,EAAE,CAAC,EACV,aAAa,GAAE,CAAC,MAAM,CAAC,CAAC,EAA+B,GACtD,OAAO,CAOT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,OAAO,EAAE,CAAC,EACV,aAAa,GAAE,CAAC,MAAM,CAAC,CAAC,EAA+B,GACtD,MAAM,CAOR;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAE1G;AAOD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAEjG;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAElG;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAE5F;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAE7F;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAElG;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAEnG;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAElG;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAEnG"}
|
package/dist/filters.js
CHANGED
|
@@ -22,22 +22,6 @@ export function countActiveFilters(filters, excludeFields = ['searchQuery']) {
|
|
|
22
22
|
const relevantEntries = Object.entries(filters).filter(([key]) => !excludeFields.includes(key));
|
|
23
23
|
return relevantEntries.filter(([, value]) => value !== undefined && value !== null && value !== '' && !(Array.isArray(value) && value.length === 0)).length;
|
|
24
24
|
}
|
|
25
|
-
/**
|
|
26
|
-
* Clears all filters except specified fields
|
|
27
|
-
* @param filters - The filter object to clear
|
|
28
|
-
* @param preserveFields - Fields to preserve when clearing (default: [])
|
|
29
|
-
* @returns A new filter object with cleared values
|
|
30
|
-
*/
|
|
31
|
-
export function clearAllFilters(filters, preserveFields = []) {
|
|
32
|
-
const clearedFilters = {};
|
|
33
|
-
// Preserve specified fields
|
|
34
|
-
preserveFields.forEach(field => {
|
|
35
|
-
if (field in filters) {
|
|
36
|
-
clearedFilters[field] = filters[field];
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
return clearedFilters;
|
|
40
|
-
}
|
|
41
25
|
/**
|
|
42
26
|
* Type-safe filter update helper
|
|
43
27
|
* @param currentFilters - The current filter state
|
|
@@ -47,87 +31,6 @@ export function clearAllFilters(filters, preserveFields = []) {
|
|
|
47
31
|
export function updateFilters(currentFilters, updates) {
|
|
48
32
|
return { ...currentFilters, ...updates };
|
|
49
33
|
}
|
|
50
|
-
/**
|
|
51
|
-
* Checks if a filter value is empty
|
|
52
|
-
* @param value - The value to check
|
|
53
|
-
* @returns true if the value is empty, false otherwise
|
|
54
|
-
*/
|
|
55
|
-
export function isFilterEmpty(value) {
|
|
56
|
-
return (value === undefined ||
|
|
57
|
-
value === null ||
|
|
58
|
-
value === '' ||
|
|
59
|
-
(Array.isArray(value) && value.length === 0) ||
|
|
60
|
-
(typeof value === 'object' && value !== null && Object.keys(value).length === 0));
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Removes empty filter values from an object
|
|
64
|
-
* @param filters - The filter object to clean
|
|
65
|
-
* @returns A new filter object with empty values removed
|
|
66
|
-
*/
|
|
67
|
-
export function removeEmptyFilters(filters) {
|
|
68
|
-
const cleanedFilters = {};
|
|
69
|
-
Object.keys(filters).forEach(key => {
|
|
70
|
-
const value = filters[key];
|
|
71
|
-
if (!isFilterEmpty(value)) {
|
|
72
|
-
cleanedFilters[key] = value;
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
return cleanedFilters;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Merges two filter objects, with the second object taking precedence
|
|
79
|
-
* @param baseFilters - The base filter object
|
|
80
|
-
* @param overrideFilters - The override filter object
|
|
81
|
-
* @returns A new merged filter object
|
|
82
|
-
*/
|
|
83
|
-
export function mergeFilters(baseFilters, overrideFilters) {
|
|
84
|
-
return { ...baseFilters, ...overrideFilters };
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Compares two filter objects for equality
|
|
88
|
-
* @param filters1 - The first filter object
|
|
89
|
-
* @param filters2 - The second filter object
|
|
90
|
-
* @returns true if the filters are equal, false otherwise
|
|
91
|
-
*/
|
|
92
|
-
export function areFiltersEqual(filters1, filters2) {
|
|
93
|
-
const keys1 = Object.keys(filters1);
|
|
94
|
-
const keys2 = Object.keys(filters2);
|
|
95
|
-
if (keys1.length !== keys2.length) {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
return keys1.every(key => {
|
|
99
|
-
const value1 = filters1[key];
|
|
100
|
-
const value2 = filters2[key];
|
|
101
|
-
if (Array.isArray(value1) && Array.isArray(value2)) {
|
|
102
|
-
return value1.length === value2.length && value1.every((v, i) => v === value2[i]);
|
|
103
|
-
}
|
|
104
|
-
return value1 === value2;
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Creates a filter predicate function from a filter object
|
|
109
|
-
* @param filters - The filter object to create a predicate from
|
|
110
|
-
* @returns A predicate function that tests if an item matches the filters
|
|
111
|
-
*/
|
|
112
|
-
export function createFilterPredicate(filters) {
|
|
113
|
-
const activeFilters = removeEmptyFilters(filters);
|
|
114
|
-
const filterEntries = Object.entries(activeFilters);
|
|
115
|
-
if (filterEntries.length === 0) {
|
|
116
|
-
return () => true;
|
|
117
|
-
}
|
|
118
|
-
return (item) => {
|
|
119
|
-
return filterEntries.every(([key, filterValue]) => {
|
|
120
|
-
const itemValue = item[key];
|
|
121
|
-
if (Array.isArray(filterValue)) {
|
|
122
|
-
return filterValue.includes(itemValue);
|
|
123
|
-
}
|
|
124
|
-
if (typeof filterValue === 'string' && typeof itemValue === 'string') {
|
|
125
|
-
return itemValue.toLowerCase().includes(filterValue.toLowerCase());
|
|
126
|
-
}
|
|
127
|
-
return itemValue === filterValue;
|
|
128
|
-
});
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
34
|
// ============================================================================
|
|
132
35
|
// Common Filter Patterns
|
|
133
36
|
// Pre-configured utilities for common filter use cases
|
package/dist/holdings.d.ts
CHANGED
|
@@ -1,21 +1,4 @@
|
|
|
1
1
|
import type { AssetHolding } from '@cranberry-money/shared-types';
|
|
2
|
-
import { type SortDirection } from '@cranberry-money/shared-constants';
|
|
3
|
-
/**
|
|
4
|
-
* Calculates the total portfolio value based on holdings and instrument prices
|
|
5
|
-
*
|
|
6
|
-
* @param holdings - Array of asset holdings
|
|
7
|
-
* @param prices - Map of instrument UUIDs to their current prices
|
|
8
|
-
* @returns Total portfolio value
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* const holdings = [
|
|
12
|
-
* { instrument: { uuid: '123' }, quantity: 100 },
|
|
13
|
-
* { instrument: { uuid: '456' }, quantity: 50 }
|
|
14
|
-
* ];
|
|
15
|
-
* const prices = { '123': 10.50, '456': 25.00 };
|
|
16
|
-
* calculatePortfolioValue(holdings, prices); // returns 2300
|
|
17
|
-
*/
|
|
18
|
-
export declare const calculatePortfolioValue: (holdings: readonly AssetHolding[], prices: Record<string, number>) => number;
|
|
19
2
|
/**
|
|
20
3
|
* Calculates holding allocation percentages within a portfolio
|
|
21
4
|
*
|
|
@@ -30,49 +13,4 @@ export declare const calculatePortfolioValue: (holdings: readonly AssetHolding[]
|
|
|
30
13
|
* calculateHoldingAllocations(holdings); // returns { '123': 50, '456': 50 }
|
|
31
14
|
*/
|
|
32
15
|
export declare const calculateHoldingAllocations: (holdings: readonly AssetHolding[]) => Record<string, number>;
|
|
33
|
-
|
|
34
|
-
* Groups holdings by instrument UUID for aggregated view
|
|
35
|
-
*
|
|
36
|
-
* @param holdings - Array of asset holdings to group
|
|
37
|
-
* @returns Map of instrument UUIDs to their holdings arrays
|
|
38
|
-
*
|
|
39
|
-
* @example
|
|
40
|
-
* const holdings = [
|
|
41
|
-
* { instrument: { uuid: '123' }, quantity: 100 },
|
|
42
|
-
* { instrument: { uuid: '123' }, quantity: 50 },
|
|
43
|
-
* { instrument: { uuid: '456' }, quantity: 200 }
|
|
44
|
-
* ];
|
|
45
|
-
* groupHoldingsByInstrument(holdings);
|
|
46
|
-
* // returns { '123': [holding1, holding2], '456': [holding3] }
|
|
47
|
-
*/
|
|
48
|
-
export declare const groupHoldingsByInstrument: (holdings: readonly AssetHolding[]) => Record<string, AssetHolding[]>;
|
|
49
|
-
/**
|
|
50
|
-
* Filters holdings with quantities above a threshold
|
|
51
|
-
*
|
|
52
|
-
* @param holdings - Array of asset holdings
|
|
53
|
-
* @param minQuantity - Minimum quantity threshold
|
|
54
|
-
* @returns Filtered array of holdings
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* const holdings = [
|
|
58
|
-
* { quantity: 100 },
|
|
59
|
-
* { quantity: 50 },
|
|
60
|
-
* { quantity: 200 }
|
|
61
|
-
* ];
|
|
62
|
-
* filterHoldingsByMinQuantity(holdings, 75); // returns holdings with quantity >= 75
|
|
63
|
-
*/
|
|
64
|
-
export declare const filterHoldingsByMinQuantity: (holdings: readonly AssetHolding[], minQuantity: number) => AssetHolding[];
|
|
65
|
-
/**
|
|
66
|
-
* Sorts holdings by various criteria
|
|
67
|
-
*
|
|
68
|
-
* @param holdings - Array of asset holdings to sort
|
|
69
|
-
* @param sortBy - Field to sort by
|
|
70
|
-
* @param direction - Sort direction (ascending or descending)
|
|
71
|
-
* @returns Sorted array of holdings
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* const holdings = [...];
|
|
75
|
-
* sortHoldings(holdings, 'quantity', 'desc'); // Sort by quantity descending
|
|
76
|
-
* sortHoldings(holdings, 'symbol', 'asc'); // Sort by symbol ascending
|
|
77
|
-
*/
|
|
78
|
-
export declare const sortHoldings: (holdings: readonly AssetHolding[], sortBy: "quantity" | "symbol" | "name" | "createdAt", direction?: SortDirection) => AssetHolding[];
|
|
16
|
+
//# sourceMappingURL=holdings.d.ts.map
|
package/dist/holdings.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"holdings.d.ts","sourceRoot":"","sources":["../src/holdings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"holdings.d.ts","sourceRoot":"","sources":["../src/holdings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,2BAA2B,GAAI,UAAU,SAAS,YAAY,EAAE,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAWpG,CAAC"}
|
package/dist/holdings.js
CHANGED
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
import { DEFAULT_NUMERIC_ZERO, SORT_DIRECTION_ASC, SORT_DIRECTION_DESC, } from '@cranberry-money/shared-constants';
|
|
2
|
-
import { sortByStringField } from './collections';
|
|
3
|
-
/**
|
|
4
|
-
* Calculates the total portfolio value based on holdings and instrument prices
|
|
5
|
-
*
|
|
6
|
-
* @param holdings - Array of asset holdings
|
|
7
|
-
* @param prices - Map of instrument UUIDs to their current prices
|
|
8
|
-
* @returns Total portfolio value
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* const holdings = [
|
|
12
|
-
* { instrument: { uuid: '123' }, quantity: 100 },
|
|
13
|
-
* { instrument: { uuid: '456' }, quantity: 50 }
|
|
14
|
-
* ];
|
|
15
|
-
* const prices = { '123': 10.50, '456': 25.00 };
|
|
16
|
-
* calculatePortfolioValue(holdings, prices); // returns 2300
|
|
17
|
-
*/
|
|
18
|
-
export const calculatePortfolioValue = (holdings, prices) => {
|
|
19
|
-
return holdings.reduce((total, holding) => {
|
|
20
|
-
const price = prices[holding.instrument.uuid] || DEFAULT_NUMERIC_ZERO;
|
|
21
|
-
return total + holding.quantity * price;
|
|
22
|
-
}, 0);
|
|
23
|
-
};
|
|
24
1
|
/**
|
|
25
2
|
* Calculates holding allocation percentages within a portfolio
|
|
26
3
|
*
|
|
@@ -44,96 +21,3 @@ export const calculateHoldingAllocations = (holdings) => {
|
|
|
44
21
|
});
|
|
45
22
|
return allocations;
|
|
46
23
|
};
|
|
47
|
-
/**
|
|
48
|
-
* Groups holdings by instrument UUID for aggregated view
|
|
49
|
-
*
|
|
50
|
-
* @param holdings - Array of asset holdings to group
|
|
51
|
-
* @returns Map of instrument UUIDs to their holdings arrays
|
|
52
|
-
*
|
|
53
|
-
* @example
|
|
54
|
-
* const holdings = [
|
|
55
|
-
* { instrument: { uuid: '123' }, quantity: 100 },
|
|
56
|
-
* { instrument: { uuid: '123' }, quantity: 50 },
|
|
57
|
-
* { instrument: { uuid: '456' }, quantity: 200 }
|
|
58
|
-
* ];
|
|
59
|
-
* groupHoldingsByInstrument(holdings);
|
|
60
|
-
* // returns { '123': [holding1, holding2], '456': [holding3] }
|
|
61
|
-
*/
|
|
62
|
-
export const groupHoldingsByInstrument = (holdings) => {
|
|
63
|
-
return holdings.reduce((groups, holding) => {
|
|
64
|
-
const instrumentUuid = holding.instrument.uuid;
|
|
65
|
-
if (!groups[instrumentUuid]) {
|
|
66
|
-
groups[instrumentUuid] = [];
|
|
67
|
-
}
|
|
68
|
-
groups[instrumentUuid].push(holding);
|
|
69
|
-
return groups;
|
|
70
|
-
}, {});
|
|
71
|
-
};
|
|
72
|
-
/**
|
|
73
|
-
* Filters holdings with quantities above a threshold
|
|
74
|
-
*
|
|
75
|
-
* @param holdings - Array of asset holdings
|
|
76
|
-
* @param minQuantity - Minimum quantity threshold
|
|
77
|
-
* @returns Filtered array of holdings
|
|
78
|
-
*
|
|
79
|
-
* @example
|
|
80
|
-
* const holdings = [
|
|
81
|
-
* { quantity: 100 },
|
|
82
|
-
* { quantity: 50 },
|
|
83
|
-
* { quantity: 200 }
|
|
84
|
-
* ];
|
|
85
|
-
* filterHoldingsByMinQuantity(holdings, 75); // returns holdings with quantity >= 75
|
|
86
|
-
*/
|
|
87
|
-
export const filterHoldingsByMinQuantity = (holdings, minQuantity) => {
|
|
88
|
-
return holdings.filter(holding => holding.quantity >= minQuantity);
|
|
89
|
-
};
|
|
90
|
-
/**
|
|
91
|
-
* Sorts holdings by various criteria
|
|
92
|
-
*
|
|
93
|
-
* @param holdings - Array of asset holdings to sort
|
|
94
|
-
* @param sortBy - Field to sort by
|
|
95
|
-
* @param direction - Sort direction (ascending or descending)
|
|
96
|
-
* @returns Sorted array of holdings
|
|
97
|
-
*
|
|
98
|
-
* @example
|
|
99
|
-
* const holdings = [...];
|
|
100
|
-
* sortHoldings(holdings, 'quantity', 'desc'); // Sort by quantity descending
|
|
101
|
-
* sortHoldings(holdings, 'symbol', 'asc'); // Sort by symbol ascending
|
|
102
|
-
*/
|
|
103
|
-
export const sortHoldings = (holdings, sortBy, direction = SORT_DIRECTION_DESC) => {
|
|
104
|
-
// Use shared utility for string field sorting
|
|
105
|
-
if (sortBy === 'symbol') {
|
|
106
|
-
const sorted = sortByStringField([...holdings], 'instrumentSymbol');
|
|
107
|
-
return direction === SORT_DIRECTION_ASC ? sorted : sorted.reverse();
|
|
108
|
-
}
|
|
109
|
-
if (sortBy === 'name') {
|
|
110
|
-
const sorted = sortByStringField([...holdings], 'instrumentName');
|
|
111
|
-
return direction === SORT_DIRECTION_ASC ? sorted : sorted.reverse();
|
|
112
|
-
}
|
|
113
|
-
// Custom logic for non-string fields
|
|
114
|
-
return [...holdings].sort((a, b) => {
|
|
115
|
-
let valueA;
|
|
116
|
-
let valueB;
|
|
117
|
-
switch (sortBy) {
|
|
118
|
-
case 'quantity':
|
|
119
|
-
valueA = a.quantity;
|
|
120
|
-
valueB = b.quantity;
|
|
121
|
-
break;
|
|
122
|
-
case 'createdAt':
|
|
123
|
-
valueA = a.createdAt;
|
|
124
|
-
valueB = b.createdAt;
|
|
125
|
-
break;
|
|
126
|
-
default:
|
|
127
|
-
return 0;
|
|
128
|
-
}
|
|
129
|
-
if (typeof valueA === 'string' && typeof valueB === 'string') {
|
|
130
|
-
const comparison = valueA.localeCompare(valueB);
|
|
131
|
-
return direction === SORT_DIRECTION_ASC ? comparison : -comparison;
|
|
132
|
-
}
|
|
133
|
-
if (typeof valueA === 'number' && typeof valueB === 'number') {
|
|
134
|
-
const comparison = valueA - valueB;
|
|
135
|
-
return direction === SORT_DIRECTION_ASC ? comparison : -comparison;
|
|
136
|
-
}
|
|
137
|
-
return 0;
|
|
138
|
-
});
|
|
139
|
-
};
|
package/dist/index.d.ts
CHANGED
|
@@ -12,23 +12,16 @@ export { getTradeStatusBadge, getWithdrawalStatusBadge, getLiquidationStatusBadg
|
|
|
12
12
|
export { formatPortfolioValue, calculateTotalValue, getMarketAllocation, getCashAllocation } from './portfolio';
|
|
13
13
|
export { calculateLiquidationProgress, getTotalEstimatedValue } from './withdrawal';
|
|
14
14
|
export { isNumericOnly, validatePassword, isValidTokenFormat, formatVerificationToken, validateEmailConfirmation, isValidEmail, validatePasswordExtended, isValidPhoneFormat, isValidFullName, isValidDateOfBirth, formatPhoneNumber, isValidInvestmentAmount, isValidSourceOfFunds, hasMinimumSelection, isSelected, } from './validation';
|
|
15
|
-
export { hasActiveFilters, countActiveFilters,
|
|
15
|
+
export { hasActiveFilters, countActiveFilters, updateFilters, hasActiveInstrumentFilters, countActiveInstrumentFilters, hasActiveTradeFilters, countActiveTradeFilters, hasActiveTransactionFilters, countActiveTransactionFilters, hasActiveTargetTradeFilters, countActiveTargetTradeFilters, } from './filters';
|
|
16
16
|
export { isTokenExpired, isTokenExpiringSoon, getTimeUntilExpiry, formatTimeUntilExpiry, parseDeviceInfo, isRefreshSuccess, getRefreshErrorMessage, createAutoRefreshHandler, } from './auth';
|
|
17
17
|
export { formatInstrumentPrice, getCurrencySymbol } from './instruments';
|
|
18
|
-
export {
|
|
19
|
-
export { downloadBlob, downloadTextFile, downloadJsonFile, generateTimestampedFilename, downloadDataUrl, downloadCsvFile, } from './downloads';
|
|
18
|
+
export { downloadBlob } from './downloads';
|
|
20
19
|
export { formatQuantityWithSuffix } from './numbers';
|
|
21
20
|
export { validateAllocations } from './allocations';
|
|
22
|
-
export {
|
|
21
|
+
export { calculateHoldingAllocations } from './holdings';
|
|
23
22
|
export { processAllocationData, calculateTotals, formatPercentage, formatDashboardCurrency, type AllocationDisplayItem, } from './dashboard';
|
|
24
23
|
export { isValidTemplateSelection, validatePortfolioSelection, type PortfolioSelectionValidation, type PortfolioSelectionState, } from './portfolio-validation';
|
|
25
24
|
export { getStatusColor, getStatusLabel, getWithdrawalTypeLabel, getReasonLabel, getLiquidationStatusColor, getLiquidationStatusLabel, type WithdrawalStatus, type WithdrawalType, type WithdrawalReason, type LiquidationStatus, } from './withdrawal-status';
|
|
26
|
-
export { findPrimaryTaxResidency, filterTaxResidenciesByCountry, hasTaxResidencyInCountry, getNonExemptedTaxResidencies, type BaseTaxResidency, } from './tax-residency';
|
|
27
|
-
export { getCountriesFromExchanges, groupExchangesByCountry, findExchangeByShortName, sortExchangesByName, filterExchangesByCountry, type BaseCountry, type BaseStockExchange, type SortDirection, } from './stock-exchange';
|
|
28
|
-
export { sortSectorsByName, filterSectorsByName, findSectorByName, getSectorNames, groupSectorsAlphabetically, sectorExists, findSectorsByPartialName, type BaseSector, } from './sector';
|
|
29
|
-
export { generateDocumentFilename, formatDocumentType, formatDocumentStatus } from './document';
|
|
30
|
-
export { sortIndustriesByName, filterIndustriesByName, filterIndustriesBySector, findIndustryByName, getIndustryNames, groupIndustriesBySector, groupIndustriesAlphabetically, getIndustriesWithoutSector, getIndustriesWithSector, countIndustriesBySector, isIndustryInSector, type BaseIndustry, } from './industry';
|
|
31
|
-
export { sortCountriesByName, filterCountriesByName, filterAvailableCountries, findCountryByName, findCountryByCode, getCountryNames, groupCountriesAlphabetically, formatCountryWithDialCode, isCountryAvailable, type BaseCountry as BaseCountryType, } from './country';
|
|
32
25
|
export { calculateTotalAllocation, validateAllocationPercentages, formatRiskLevelDisplay, type BaseAllocation, } from './portfolio-template';
|
|
33
26
|
export { validateInvestmentAmount, formatInvestmentAmount } from './investment-preference';
|
|
34
27
|
export { formatBalance, formatTransactionAmount, getTransactionTypeLabel, type BaseTransactionType, } from './cash-account';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAGjF,OAAO,EACL,8BAA8B,EAC9B,qCAAqC,EACrC,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGnE,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhH,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAGpF,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,yBAAyB,EACzB,YAAY,EACZ,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,GACX,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAGjF,OAAO,EACL,8BAA8B,EAC9B,qCAAqC,EACrC,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGnE,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhH,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAGpF,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,yBAAyB,EACzB,YAAY,EACZ,wBAAwB,EACxB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,GACX,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EAEb,0BAA0B,EAC1B,4BAA4B,EAC5B,qBAAqB,EACrB,uBAAuB,EACvB,2BAA2B,EAC3B,6BAA6B,EAC7B,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,QAAQ,CAAC;AAGhB,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGzE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAGzD,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,KAAK,4BAA4B,EACjC,KAAK,uBAAuB,GAC7B,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,yBAAyB,EACzB,yBAAyB,EACzB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,sBAAsB,EACtB,KAAK,cAAc,GACpB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAG3F,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,uBAAuB,EACvB,KAAK,mBAAmB,GACzB,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -21,41 +21,27 @@ export { calculateLiquidationProgress, getTotalEstimatedValue } from './withdraw
|
|
|
21
21
|
// Validation utilities
|
|
22
22
|
export { isNumericOnly, validatePassword, isValidTokenFormat, formatVerificationToken, validateEmailConfirmation, isValidEmail, validatePasswordExtended, isValidPhoneFormat, isValidFullName, isValidDateOfBirth, formatPhoneNumber, isValidInvestmentAmount, isValidSourceOfFunds, hasMinimumSelection, isSelected, } from './validation';
|
|
23
23
|
// Filter utilities
|
|
24
|
-
export { hasActiveFilters, countActiveFilters,
|
|
24
|
+
export { hasActiveFilters, countActiveFilters, updateFilters,
|
|
25
25
|
// Common filter patterns
|
|
26
26
|
hasActiveInstrumentFilters, countActiveInstrumentFilters, hasActiveTradeFilters, countActiveTradeFilters, hasActiveTransactionFilters, countActiveTransactionFilters, hasActiveTargetTradeFilters, countActiveTargetTradeFilters, } from './filters';
|
|
27
27
|
// Authentication utilities
|
|
28
28
|
export { isTokenExpired, isTokenExpiringSoon, getTimeUntilExpiry, formatTimeUntilExpiry, parseDeviceInfo, isRefreshSuccess, getRefreshErrorMessage, createAutoRefreshHandler, } from './auth';
|
|
29
29
|
// Instrument utilities
|
|
30
30
|
export { formatInstrumentPrice, getCurrencySymbol } from './instruments';
|
|
31
|
-
// Collection utilities
|
|
32
|
-
export { sortByStringField, filterByTextSearch, filterByBooleanField, findByField, findByStringField, extractAndSortField, groupByFirstLetter, groupByField, hasItemWithFieldValue, countByFieldValue, } from './collections';
|
|
33
31
|
// Download utilities
|
|
34
|
-
export { downloadBlob
|
|
32
|
+
export { downloadBlob } from './downloads';
|
|
35
33
|
// Number formatting utilities
|
|
36
34
|
export { formatQuantityWithSuffix } from './numbers';
|
|
37
35
|
// Allocation utilities
|
|
38
36
|
export { validateAllocations } from './allocations';
|
|
39
37
|
// Holdings utilities
|
|
40
|
-
export {
|
|
38
|
+
export { calculateHoldingAllocations } from './holdings';
|
|
41
39
|
// Dashboard utilities
|
|
42
40
|
export { processAllocationData, calculateTotals, formatPercentage, formatDashboardCurrency, } from './dashboard';
|
|
43
41
|
// Portfolio validation utilities
|
|
44
42
|
export { isValidTemplateSelection, validatePortfolioSelection, } from './portfolio-validation';
|
|
45
43
|
// Withdrawal status utilities
|
|
46
44
|
export { getStatusColor, getStatusLabel, getWithdrawalTypeLabel, getReasonLabel, getLiquidationStatusColor, getLiquidationStatusLabel, } from './withdrawal-status';
|
|
47
|
-
// Tax residency utilities
|
|
48
|
-
export { findPrimaryTaxResidency, filterTaxResidenciesByCountry, hasTaxResidencyInCountry, getNonExemptedTaxResidencies, } from './tax-residency';
|
|
49
|
-
// Stock exchange utilities
|
|
50
|
-
export { getCountriesFromExchanges, groupExchangesByCountry, findExchangeByShortName, sortExchangesByName, filterExchangesByCountry, } from './stock-exchange';
|
|
51
|
-
// Sector utilities
|
|
52
|
-
export { sortSectorsByName, filterSectorsByName, findSectorByName, getSectorNames, groupSectorsAlphabetically, sectorExists, findSectorsByPartialName, } from './sector';
|
|
53
|
-
// Document utilities
|
|
54
|
-
export { generateDocumentFilename, formatDocumentType, formatDocumentStatus } from './document';
|
|
55
|
-
// Industry utilities
|
|
56
|
-
export { sortIndustriesByName, filterIndustriesByName, filterIndustriesBySector, findIndustryByName, getIndustryNames, groupIndustriesBySector, groupIndustriesAlphabetically, getIndustriesWithoutSector, getIndustriesWithSector, countIndustriesBySector, isIndustryInSector, } from './industry';
|
|
57
|
-
// Country utilities
|
|
58
|
-
export { sortCountriesByName, filterCountriesByName, filterAvailableCountries, findCountryByName, findCountryByCode, getCountryNames, groupCountriesAlphabetically, formatCountryWithDialCode, isCountryAvailable, } from './country';
|
|
59
45
|
// Portfolio template utilities
|
|
60
46
|
export { calculateTotalAllocation, validateAllocationPercentages, formatRiskLevelDisplay, } from './portfolio-template';
|
|
61
47
|
// Investment preference utilities
|