@makolabs/ripple 0.0.1 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/README.md +575 -8
  2. package/dist/adapters/storage/BaseAdapter.d.ts +20 -0
  3. package/dist/adapters/storage/BaseAdapter.js +171 -0
  4. package/dist/adapters/storage/S3Adapter.d.ts +21 -0
  5. package/dist/adapters/storage/S3Adapter.js +194 -0
  6. package/dist/adapters/storage/index.d.ts +3 -0
  7. package/dist/adapters/storage/index.js +3 -0
  8. package/dist/adapters/storage/types.d.ts +102 -0
  9. package/dist/adapters/storage/types.js +4 -0
  10. package/dist/button/Button.svelte +48 -0
  11. package/dist/button/Button.svelte.d.ts +4 -0
  12. package/dist/button/button.d.ts +113 -0
  13. package/dist/button/button.js +168 -0
  14. package/dist/charts/Chart.svelte +545 -0
  15. package/dist/charts/Chart.svelte.d.ts +4 -0
  16. package/dist/drawer/Drawer.svelte +224 -0
  17. package/dist/drawer/Drawer.svelte.d.ts +4 -0
  18. package/dist/drawer/drawer.d.ts +160 -0
  19. package/dist/drawer/drawer.js +80 -0
  20. package/dist/elements/accordion/Accordion.svelte +98 -0
  21. package/dist/elements/accordion/Accordion.svelte.d.ts +4 -0
  22. package/dist/elements/accordion/accordion.d.ts +227 -0
  23. package/dist/elements/accordion/accordion.js +138 -0
  24. package/dist/elements/alert/Alert.svelte +57 -0
  25. package/dist/elements/alert/Alert.svelte.d.ts +4 -0
  26. package/dist/elements/badge/Badge.svelte +43 -0
  27. package/dist/elements/badge/Badge.svelte.d.ts +4 -0
  28. package/dist/elements/badge/badge.d.ts +181 -0
  29. package/dist/elements/badge/badge.js +65 -0
  30. package/dist/elements/dropdown/Dropdown.svelte +234 -0
  31. package/dist/elements/dropdown/Dropdown.svelte.d.ts +4 -0
  32. package/dist/elements/dropdown/Select.svelte +333 -0
  33. package/dist/elements/dropdown/Select.svelte.d.ts +4 -0
  34. package/dist/elements/dropdown/dropdown.d.ts +251 -0
  35. package/dist/elements/dropdown/dropdown.js +95 -0
  36. package/dist/elements/dropdown/select.d.ts +200 -0
  37. package/dist/elements/dropdown/select.js +82 -0
  38. package/dist/elements/file-upload/FileUpload.svelte +135 -0
  39. package/dist/elements/file-upload/FileUpload.svelte.d.ts +4 -0
  40. package/dist/elements/file-upload/FilesPreview.svelte +93 -0
  41. package/dist/elements/file-upload/FilesPreview.svelte.d.ts +4 -0
  42. package/dist/elements/progress/Progress.svelte +145 -0
  43. package/dist/elements/progress/Progress.svelte.d.ts +4 -0
  44. package/dist/elements/timeline/Timeline.svelte +92 -0
  45. package/dist/elements/timeline/Timeline.svelte.d.ts +7 -0
  46. package/dist/file-browser/FileBrowser.svelte +877 -0
  47. package/dist/file-browser/FileBrowser.svelte.d.ts +14 -0
  48. package/dist/file-browser/index.d.ts +1 -0
  49. package/dist/file-browser/index.js +1 -0
  50. package/dist/filters/CompactFilters.svelte +147 -0
  51. package/dist/filters/CompactFilters.svelte.d.ts +4 -0
  52. package/dist/filters/index.d.ts +1 -0
  53. package/dist/filters/index.js +1 -0
  54. package/dist/forms/Checkbox.svelte +54 -0
  55. package/dist/forms/Checkbox.svelte.d.ts +4 -0
  56. package/dist/forms/DateRange.svelte +493 -0
  57. package/dist/forms/DateRange.svelte.d.ts +4 -0
  58. package/dist/forms/Form.svelte +39 -0
  59. package/dist/forms/Form.svelte.d.ts +4 -0
  60. package/dist/forms/Input.svelte +86 -0
  61. package/dist/forms/Input.svelte.d.ts +4 -0
  62. package/dist/forms/NumberInput.svelte +159 -0
  63. package/dist/forms/NumberInput.svelte.d.ts +4 -0
  64. package/dist/forms/RadioInputs.svelte +64 -0
  65. package/dist/forms/RadioInputs.svelte.d.ts +4 -0
  66. package/dist/forms/RadioPill.svelte +66 -0
  67. package/dist/forms/RadioPill.svelte.d.ts +4 -0
  68. package/dist/forms/Slider.svelte +342 -0
  69. package/dist/forms/Slider.svelte.d.ts +4 -0
  70. package/dist/forms/Tags.svelte +181 -0
  71. package/dist/forms/Tags.svelte.d.ts +4 -0
  72. package/dist/forms/Toggle.svelte +132 -0
  73. package/dist/forms/Toggle.svelte.d.ts +4 -0
  74. package/dist/forms/slider.d.ts +143 -0
  75. package/dist/forms/slider.js +62 -0
  76. package/dist/header/Breadcrumbs.svelte +73 -0
  77. package/dist/header/Breadcrumbs.svelte.d.ts +4 -0
  78. package/dist/header/PageHeader.svelte +68 -0
  79. package/dist/header/PageHeader.svelte.d.ts +4 -0
  80. package/dist/header/breadcrumbs.d.ts +226 -0
  81. package/dist/header/breadcrumbs.js +87 -0
  82. package/dist/helper/cls.d.ts +1 -0
  83. package/dist/helper/cls.js +4 -0
  84. package/dist/helper/date.d.ts +7 -0
  85. package/dist/helper/date.js +15 -0
  86. package/dist/helper/nav.svelte.d.ts +6 -0
  87. package/dist/helper/nav.svelte.js +23 -0
  88. package/dist/index.d.ts +856 -1
  89. package/dist/index.js +78 -1
  90. package/dist/layout/card/Card.svelte +41 -0
  91. package/dist/layout/card/Card.svelte.d.ts +4 -0
  92. package/dist/layout/card/MetricCard.svelte +64 -0
  93. package/dist/layout/card/MetricCard.svelte.d.ts +4 -0
  94. package/dist/layout/card/StatsCard.svelte +266 -0
  95. package/dist/layout/card/StatsCard.svelte.d.ts +4 -0
  96. package/dist/layout/card/card.d.ts +128 -0
  97. package/dist/layout/card/card.js +51 -0
  98. package/dist/layout/card/metric-card.d.ts +49 -0
  99. package/dist/layout/card/metric-card.js +10 -0
  100. package/dist/layout/card/stats-card.d.ts +191 -0
  101. package/dist/layout/card/stats-card.js +73 -0
  102. package/dist/layout/navbar/Navbar.svelte +206 -0
  103. package/dist/layout/navbar/Navbar.svelte.d.ts +4 -0
  104. package/dist/layout/navbar/navbar.d.ts +205 -0
  105. package/dist/layout/navbar/navbar.js +98 -0
  106. package/dist/layout/sidebar/NavGroup.svelte +91 -0
  107. package/dist/layout/sidebar/NavGroup.svelte.d.ts +4 -0
  108. package/dist/layout/sidebar/NavItem.svelte +29 -0
  109. package/dist/layout/sidebar/NavItem.svelte.d.ts +4 -0
  110. package/dist/layout/sidebar/Sidebar.svelte +193 -0
  111. package/dist/layout/sidebar/Sidebar.svelte.d.ts +4 -0
  112. package/dist/layout/table/Cells.svelte +111 -0
  113. package/dist/layout/table/Cells.svelte.d.ts +27 -0
  114. package/dist/layout/table/Table.svelte +790 -0
  115. package/dist/layout/table/Table.svelte.d.ts +4 -0
  116. package/dist/layout/table/table.d.ts +256 -0
  117. package/dist/layout/table/table.js +141 -0
  118. package/dist/layout/tabs/Tab.svelte +60 -0
  119. package/dist/layout/tabs/Tab.svelte.d.ts +4 -0
  120. package/dist/layout/tabs/TabContent.svelte +30 -0
  121. package/dist/layout/tabs/TabContent.svelte.d.ts +4 -0
  122. package/dist/layout/tabs/TabGroup.svelte +62 -0
  123. package/dist/layout/tabs/TabGroup.svelte.d.ts +4 -0
  124. package/dist/layout/tabs/tabs.d.ts +140 -0
  125. package/dist/layout/tabs/tabs.js +298 -0
  126. package/dist/modal/Modal.svelte +207 -0
  127. package/dist/modal/Modal.svelte.d.ts +4 -0
  128. package/dist/modal/modal.d.ts +211 -0
  129. package/dist/modal/modal.js +81 -0
  130. package/dist/sonner/sonner.svelte +13 -0
  131. package/dist/sonner/sonner.svelte.d.ts +4 -0
  132. package/dist/types/variants.d.ts +1 -0
  133. package/dist/types/variants.js +1 -0
  134. package/dist/utils/Portal.svelte +108 -0
  135. package/dist/utils/Portal.svelte.d.ts +8 -0
  136. package/dist/utils/dateUtils.d.ts +7 -0
  137. package/dist/utils/dateUtils.js +26 -0
  138. package/dist/variants.d.ts +30 -0
  139. package/dist/variants.js +36 -0
  140. package/package.json +39 -6
  141. package/dist/layout/Card.svelte +0 -179
  142. package/dist/layout/Card.svelte.d.ts +0 -208
  143. package/dist/layout/index.d.ts +0 -1
  144. package/dist/layout/index.js +0 -1
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Base storage adapter with common functionality
3
+ */
4
+ export class BaseAdapter {
5
+ // Common implementation of import and getImportStatus
6
+ async import(file, options) {
7
+ try {
8
+ const endpoint = `/api/${this.getApiPath()}/import`;
9
+ const response = await fetch(endpoint, {
10
+ method: 'POST',
11
+ headers: {
12
+ 'Content-Type': 'application/json'
13
+ },
14
+ body: JSON.stringify({
15
+ key: file.key,
16
+ fileId: file.id, // For Google Drive
17
+ contentType: options.contentType,
18
+ fileFormat: options.fileFormat,
19
+ reference: options.reference || file.name,
20
+ insurer: options.contentType === 'insurer_statement' ? options.insurer : null
21
+ })
22
+ });
23
+ if (!response.ok) {
24
+ const errorData = await response.json();
25
+ throw new Error(errorData.error || 'Failed to import file');
26
+ }
27
+ const result = await response.json();
28
+ return {
29
+ success: true,
30
+ message: `File ${file.name} imported successfully`,
31
+ fileId: result.fileId || result.importResponse?.uuid,
32
+ status: 'pending',
33
+ progress: 10
34
+ };
35
+ }
36
+ catch (err) {
37
+ console.error(`Error importing ${this.getName()} file:`, err);
38
+ return {
39
+ success: false,
40
+ message: `Failed to import file from ${this.getName()}`,
41
+ error: err instanceof Error ? err.message : 'Unknown error'
42
+ };
43
+ }
44
+ }
45
+ async getImportStatus(importId, fileKey) {
46
+ try {
47
+ const response = await fetch(`/api/v1/uploads/${importId}`);
48
+ if (!response.ok) {
49
+ if (response.status === 404) {
50
+ throw new Error(`404: File ${importId} not found on server`);
51
+ }
52
+ throw new Error(`Failed to get file status: ${response.status} ${response.statusText}`);
53
+ }
54
+ const fileData = await response.json();
55
+ return {
56
+ fileId: importId,
57
+ status: fileData.processing_status,
58
+ progress: this.calculateProgress(fileData.processing_status, fileData.processed_rows, fileData.total_rows),
59
+ processedRows: fileData.processed_rows,
60
+ totalRows: fileData.total_rows,
61
+ detailedStatus: this.getDetailedStatus(fileData.processing_status),
62
+ error: fileData.error_details?.message,
63
+ created_at: fileData.created_at
64
+ };
65
+ }
66
+ catch (err) {
67
+ console.error('Error polling file status:', err);
68
+ throw err;
69
+ }
70
+ }
71
+ // Common implementation of batch import
72
+ async batchImport(files, options) {
73
+ // Process files sequentially
74
+ const individualResults = [];
75
+ for (const file of files) {
76
+ try {
77
+ const result = await this.import(file, options);
78
+ individualResults.push(result);
79
+ }
80
+ catch (err) {
81
+ individualResults.push({
82
+ success: false,
83
+ message: `Failed to import ${file.name}`,
84
+ error: err instanceof Error ? err.message : 'Unknown error',
85
+ fileId: file.id
86
+ });
87
+ }
88
+ }
89
+ // Count successes and failures
90
+ const succeeded = individualResults.filter(r => r.success).length;
91
+ const failed = individualResults.length - succeeded;
92
+ // Return batch import result
93
+ return {
94
+ success: failed === 0, // Overall success if all files succeeded
95
+ message: `Imported ${succeeded} of ${individualResults.length} files`,
96
+ summary: {
97
+ total: individualResults.length,
98
+ succeeded,
99
+ failed
100
+ },
101
+ results: individualResults.map(r => ({
102
+ key: r.fileId || '',
103
+ success: r.success,
104
+ fileId: r.fileId,
105
+ error: r.error
106
+ }))
107
+ };
108
+ }
109
+ // Set a flag to reopen the browser after authentication
110
+ setReopenFlag() {
111
+ // Default implementation does nothing
112
+ // Subclasses should override this method to implement storage-specific reopening flags
113
+ }
114
+ // Check if the browser should be reopened
115
+ shouldReopenBrowser() {
116
+ // Default implementation returns false
117
+ // Subclasses should override this method to check their specific reopening flags
118
+ return false;
119
+ }
120
+ // Clear the browser reopening flag
121
+ clearReopenFlag() {
122
+ // Default implementation does nothing
123
+ // Subclasses should override this method to clear their specific reopening flags
124
+ }
125
+ // Helper method to get detailed status
126
+ getDetailedStatus(status) {
127
+ const statusMap = {
128
+ 'pending': 'Waiting to start',
129
+ 'pending_import': 'Preparing import',
130
+ 'initializing': 'Initializing import',
131
+ 'pending_file_retrieval': 'Retrieving file',
132
+ 'retrieving_file': 'Downloading file',
133
+ 'file_retrieved': 'File downloaded',
134
+ 'loading_file_contents_to_db': 'Loading data',
135
+ 'file_contents_loaded': 'Data loaded',
136
+ 'ready_to_process': 'Ready for processing',
137
+ 'validating_source_file_rows': 'Validating file',
138
+ 'converting_to_business_objects': 'Converting data',
139
+ 'processing': 'Processing data',
140
+ 'completed': 'Import completed',
141
+ 'failed': 'Import failed',
142
+ 'partially_processed': 'Partially processed'
143
+ };
144
+ return statusMap[status] || status;
145
+ }
146
+ // Helper method to calculate progress
147
+ calculateProgress(status, processedRows, totalRows) {
148
+ // If we have row counts, use them for more accurate progress
149
+ if (processedRows !== undefined && totalRows && totalRows > 0) {
150
+ return Math.min(95, Math.round((processedRows / totalRows) * 100));
151
+ }
152
+ // Otherwise, use status-based progress estimates
153
+ const progressMap = {
154
+ 'pending': 5,
155
+ 'pending_import': 10,
156
+ 'initializing': 15,
157
+ 'pending_file_retrieval': 20,
158
+ 'retrieving_file': 30,
159
+ 'file_retrieved': 40,
160
+ 'loading_file_contents_to_db': 50,
161
+ 'file_contents_loaded': 60,
162
+ 'ready_to_process': 70,
163
+ 'validating_source_file_rows': 80,
164
+ 'converting_to_business_objects': 90,
165
+ 'completed': 100,
166
+ 'failed': 0,
167
+ 'partially_processed': 95
168
+ };
169
+ return progressMap[status] || 50;
170
+ }
171
+ }
@@ -0,0 +1,21 @@
1
+ import type { FileItem, FileListResult } from './types.js';
2
+ import { BaseAdapter } from './BaseAdapter.js';
3
+ /**
4
+ * S3 storage adapter for the FileBrowser component
5
+ */
6
+ export declare class S3Adapter extends BaseAdapter {
7
+ private basePath;
8
+ constructor(basePath?: string, publicS3BasePath?: string);
9
+ getName(): string;
10
+ isConfigured(): Promise<boolean>;
11
+ authenticate(): Promise<boolean>;
12
+ setReopenFlag(): void;
13
+ shouldReopenBrowser(): boolean;
14
+ clearReopenFlag(): void;
15
+ list(path: string, searchQuery?: string): Promise<FileListResult>;
16
+ download(file: FileItem): Promise<string>;
17
+ private removeFileExtensions;
18
+ private createBreadcrumbs;
19
+ private extractFolderName;
20
+ protected getApiPath(): string;
21
+ }
@@ -0,0 +1,194 @@
1
+ import { BaseAdapter } from './BaseAdapter.js';
2
+ /**
3
+ * S3 storage adapter for the FileBrowser component
4
+ */
5
+ export class S3Adapter extends BaseAdapter {
6
+ basePath;
7
+ constructor(basePath, publicS3BasePath) {
8
+ super();
9
+ this.basePath = basePath || publicS3BasePath || 'export/clarkfin/';
10
+ }
11
+ getName() {
12
+ return 'S3';
13
+ }
14
+ async isConfigured() {
15
+ // S3 should always be configured if the environment variables are set
16
+ return true;
17
+ }
18
+ // S3 does not require authentication, but we implement the method to satisfy the interface
19
+ async authenticate() {
20
+ return true; // S3 is considered authenticated if isConfigured() returns true
21
+ }
22
+ // Override setReopenFlag to store the S3 browser reopening flag
23
+ setReopenFlag() {
24
+ if (typeof localStorage !== 'undefined') {
25
+ localStorage.setItem('reopen_s3_browser', 'true');
26
+ }
27
+ }
28
+ // Check if the S3 browser should be reopened
29
+ shouldReopenBrowser() {
30
+ if (typeof localStorage !== 'undefined') {
31
+ return localStorage.getItem('reopen_s3_browser') === 'true';
32
+ }
33
+ return false;
34
+ }
35
+ // Clear the S3 browser reopening flag
36
+ clearReopenFlag() {
37
+ if (typeof localStorage !== 'undefined') {
38
+ localStorage.removeItem('reopen_s3_browser');
39
+ }
40
+ }
41
+ async list(path, searchQuery) {
42
+ try {
43
+ // Ensure path ends with a forward slash
44
+ const normalizedPath = path.endsWith('/') ? path : path + '/';
45
+ // Build API URL including search term if provided
46
+ let apiUrl = `/api/s3/list?prefix=${encodeURIComponent(normalizedPath)}`;
47
+ if (searchQuery) {
48
+ apiUrl += `&search=${encodeURIComponent(searchQuery)}`;
49
+ }
50
+ // Use the API endpoint for listing S3 files
51
+ const response = await fetch(apiUrl);
52
+ if (!response.ok) {
53
+ const errorData = await response.json();
54
+ throw new Error(errorData.error || 'Failed to fetch files');
55
+ }
56
+ const result = await response.json();
57
+ // Transform folders - use the folderName property from the API
58
+ const folders = (result.folders || [])
59
+ .map((folder) => {
60
+ return {
61
+ key: folder.prefix,
62
+ // Use the folderName from the API if available, otherwise extract it from the prefix
63
+ name: folder.folderName || this.extractFolderName(folder.prefix, normalizedPath),
64
+ lastModified: new Date(),
65
+ size: 0,
66
+ isFolder: true
67
+ };
68
+ })
69
+ .filter((folder) => folder.name); // Filter out empty folder names
70
+ // Transform files - only include files that are directly in this directory
71
+ const fileItems = (result.files || [])
72
+ .filter((file) => {
73
+ // Skip the directory marker itself if it exists as a file
74
+ if (file.key === normalizedPath)
75
+ return false;
76
+ // Get the relative path within the current directory
77
+ const relativePath = file.key.slice(normalizedPath.length);
78
+ // Only include files that don't have additional path separators
79
+ // (indicating they're directly in this directory)
80
+ return !relativePath.includes('/');
81
+ })
82
+ .map((file) => ({
83
+ key: file.key,
84
+ name: this.removeFileExtensions(file.key.slice(normalizedPath.length)),
85
+ lastModified: new Date(file.lastModified),
86
+ size: file.size,
87
+ isFolder: false
88
+ }));
89
+ // Combine folders and files
90
+ const files = [...folders, ...fileItems];
91
+ // Sort by lastModified in reverse order (newest first), but keep folders first
92
+ files.sort((a, b) => {
93
+ // Keep folders first
94
+ if (a.isFolder !== b.isFolder) {
95
+ return a.isFolder ? -1 : 1;
96
+ }
97
+ // Sort by lastModified in reverse order (newest first)
98
+ return b.lastModified.getTime() - a.lastModified.getTime();
99
+ });
100
+ // Create breadcrumbs
101
+ const breadcrumbs = this.createBreadcrumbs(normalizedPath);
102
+ // Determine parent path
103
+ const pathParts = normalizedPath.split('/').filter(Boolean);
104
+ let parentPath = '';
105
+ if (pathParts.length > 0) {
106
+ // Remove the last part and join the rest
107
+ pathParts.pop();
108
+ parentPath = pathParts.length > 0 ? pathParts.join('/') + '/' : this.basePath;
109
+ // Ensure we never navigate outside the basePath
110
+ if (!parentPath.startsWith(this.basePath)) {
111
+ parentPath = this.basePath;
112
+ }
113
+ }
114
+ // Debug log
115
+ console.log(`S3 listing path: ${normalizedPath}, files: ${fileItems.length}, folders: ${folders.length}`);
116
+ if (folders.length > 0) {
117
+ console.log('Sample folder names:', folders.slice(0, 3).map((f) => f.name));
118
+ }
119
+ return {
120
+ files,
121
+ currentPath: normalizedPath,
122
+ parentPath: normalizedPath !== this.basePath ? parentPath : undefined,
123
+ breadcrumbs
124
+ };
125
+ }
126
+ catch (err) {
127
+ console.error('Error fetching S3 files:', err);
128
+ throw err;
129
+ }
130
+ }
131
+ async download(file) {
132
+ try {
133
+ const response = await fetch(`/api/s3/download?key=${encodeURIComponent(file.key)}`);
134
+ if (!response.ok) {
135
+ const errorData = await response.json();
136
+ throw new Error(errorData.error || 'Failed to download file');
137
+ }
138
+ const url = await response.text();
139
+ return url;
140
+ }
141
+ catch (err) {
142
+ console.error('Error downloading S3 file:', err);
143
+ throw err;
144
+ }
145
+ }
146
+ // Helper method to remove file extensions
147
+ removeFileExtensions(filename) {
148
+ // First remove .csv.gz if it exists
149
+ let name = filename.replace(/\.csv\.gz$/, '');
150
+ // Then remove any remaining extension
151
+ return name.replace(/\.[^/.]+$/, '');
152
+ }
153
+ // Helper method to create breadcrumbs
154
+ createBreadcrumbs(path) {
155
+ // If we're at base path, reset breadcrumbs
156
+ if (path === this.basePath) {
157
+ return [{ name: 'S3', path: this.basePath, current: true, clickable: true }];
158
+ }
159
+ // Extract parts for display
160
+ const pathWithoutBase = path.startsWith(this.basePath) ? path.slice(this.basePath.length) : '';
161
+ // Add base path as the first item
162
+ let breadcrumbs = [{ name: 'S3', path: this.basePath, current: false, clickable: true }];
163
+ // Add current directory parts
164
+ if (pathWithoutBase) {
165
+ const parts = pathWithoutBase.split('/').filter(Boolean);
166
+ let currentPath = this.basePath;
167
+ parts.forEach((part, index) => {
168
+ currentPath += part + '/';
169
+ breadcrumbs.push({
170
+ name: part,
171
+ path: currentPath,
172
+ current: index === parts.length - 1,
173
+ clickable: true
174
+ });
175
+ });
176
+ }
177
+ return breadcrumbs;
178
+ }
179
+ // Helper method to extract folder name from a prefix
180
+ extractFolderName(prefix, currentPath) {
181
+ // If the prefix starts with the current path, extract the next segment
182
+ if (prefix.startsWith(currentPath)) {
183
+ const relativePath = prefix.slice(currentPath.length);
184
+ return relativePath.split('/')[0];
185
+ }
186
+ // Fallback: use the last non-empty segment before the trailing slash
187
+ const segments = prefix.split('/').filter(Boolean);
188
+ return segments.length > 0 ? segments[segments.length - 1] : '';
189
+ }
190
+ // Implement the abstract method from BaseAdapter
191
+ getApiPath() {
192
+ return 's3';
193
+ }
194
+ }
@@ -0,0 +1,3 @@
1
+ export * from './types.js';
2
+ export * from './BaseAdapter.js';
3
+ export * from './S3Adapter.js';
@@ -0,0 +1,3 @@
1
+ export * from './types.js';
2
+ export * from './BaseAdapter.js';
3
+ export * from './S3Adapter.js';
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Storage adapter interfaces for the unified FileBrowser component
3
+ */
4
+ export interface FileItem {
5
+ key: string;
6
+ name: string;
7
+ lastModified: Date;
8
+ createdAt?: Date;
9
+ size: number;
10
+ isFolder: boolean;
11
+ id?: string;
12
+ mimeType?: string;
13
+ parentId?: string;
14
+ }
15
+ export interface FileActionSingle {
16
+ label: (file: FileItem) => string;
17
+ action: (file: FileItem) => void | Promise<void>;
18
+ isAllowed: (file: FileItem) => boolean;
19
+ batchAction?: never;
20
+ }
21
+ export interface FileActionBatch {
22
+ label: (files: FileItem[]) => string;
23
+ batchAction: (files: FileItem[]) => void | Promise<void>;
24
+ isAllowed: (files: FileItem[]) => boolean;
25
+ action?: never;
26
+ }
27
+ export type FileAction = FileActionSingle | FileActionBatch;
28
+ export interface Breadcrumb {
29
+ name: string;
30
+ path: string;
31
+ id?: string;
32
+ current: boolean;
33
+ clickable: boolean;
34
+ }
35
+ export interface FileListResult {
36
+ files: FileItem[];
37
+ currentPath: string;
38
+ parentPath?: string;
39
+ breadcrumbs?: Breadcrumb[];
40
+ }
41
+ export interface ImportOptions {
42
+ contentType: string;
43
+ fileFormat: string;
44
+ reference?: string;
45
+ insurer?: string;
46
+ }
47
+ export interface ImportResult {
48
+ success: boolean;
49
+ message: string;
50
+ fileId?: string;
51
+ error?: string;
52
+ status?: string;
53
+ progress?: number;
54
+ }
55
+ export interface BatchImportResult {
56
+ success: boolean;
57
+ message: string;
58
+ summary: {
59
+ total: number;
60
+ succeeded: number;
61
+ failed: number;
62
+ };
63
+ results: {
64
+ key: string;
65
+ success: boolean;
66
+ fileId?: string;
67
+ error?: string;
68
+ }[];
69
+ }
70
+ export interface ImportStatus {
71
+ fileId: string;
72
+ status: string;
73
+ progress: number;
74
+ processedRows?: number;
75
+ totalRows?: number;
76
+ detailedStatus?: string;
77
+ error?: string;
78
+ created_at?: string;
79
+ }
80
+ export interface ErrorReportOptions {
81
+ errorType: string;
82
+ errorMessage: string;
83
+ errorDetails?: string;
84
+ clientInfo?: Record<string, string>;
85
+ userAction?: string;
86
+ }
87
+ type URLString = string;
88
+ export interface StorageAdapter {
89
+ getName(): string;
90
+ list(path: string, searchQuery?: string): Promise<FileListResult>;
91
+ download(file: FileItem): Promise<URLString>;
92
+ import(file: FileItem, options: ImportOptions): Promise<ImportResult>;
93
+ batchImport(files: FileItem[], options: ImportOptions): Promise<BatchImportResult>;
94
+ getImportStatus(importId: string, fileKey: string): Promise<ImportStatus>;
95
+ reportError?(importId: string, options: ErrorReportOptions): Promise<boolean>;
96
+ isConfigured(): Promise<boolean>;
97
+ authenticate?(): Promise<boolean>;
98
+ setReopenFlag(): void;
99
+ shouldReopenBrowser(): boolean;
100
+ clearReopenFlag(): void;
101
+ }
102
+ export {};
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Storage adapter interfaces for the unified FileBrowser component
3
+ */
4
+ export {};
@@ -0,0 +1,48 @@
1
+ <script lang="ts">
2
+ import { cn } from '../helper/cls.js';
3
+ import { buttonVariants } from './button.js';
4
+ import type { ButtonProps } from '../index.js';
5
+ import { Color, Size } from '../variants.js';
6
+
7
+ let {
8
+ variant = 'solid',
9
+ color = Color.DEFAULT,
10
+ size = Size.BASE,
11
+ rounded = 'base',
12
+ disabled = false,
13
+ isLoading = false,
14
+ class: className = '',
15
+ children,
16
+ ...restProps
17
+ }: ButtonProps = $props();
18
+
19
+ const buttonClasses = $derived(
20
+ cn(
21
+ buttonVariants({
22
+ variant,
23
+ color,
24
+ size,
25
+ rounded,
26
+ isLoading
27
+ }),
28
+ {
29
+ 'opacity-50 pointer-events-none cursor-not-allowed': disabled
30
+ },
31
+ className
32
+ )
33
+ );
34
+ </script>
35
+
36
+ {#if restProps['href']}
37
+ <a class={buttonClasses} {...restProps}>
38
+ {#if children}
39
+ {@render children()}
40
+ {/if}
41
+ </a>
42
+ {:else}
43
+ <button class={buttonClasses} disabled={disabled || isLoading} {...restProps}>
44
+ {#if children}
45
+ {@render children()}
46
+ {/if}
47
+ </button>
48
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { ButtonProps } from '../index.js';
2
+ declare const Button: import("svelte").Component<ButtonProps, {}, "">;
3
+ type Button = ReturnType<typeof Button>;
4
+ export default Button;
@@ -0,0 +1,113 @@
1
+ import { Color, Size } from '../variants.js';
2
+ export declare const buttonVariants: import("tailwind-variants").TVReturnType<{
3
+ variant: {
4
+ solid: string;
5
+ outline: string;
6
+ ghost: string;
7
+ link: string;
8
+ };
9
+ color: {
10
+ [Color.DEFAULT]: string;
11
+ [Color.PRIMARY]: string;
12
+ [Color.SECONDARY]: string;
13
+ [Color.INFO]: string;
14
+ [Color.SUCCESS]: string;
15
+ [Color.WARNING]: string;
16
+ [Color.DANGER]: string;
17
+ };
18
+ size: {
19
+ [Size.XS]: string;
20
+ [Size.SM]: string;
21
+ [Size.BASE]: string;
22
+ [Size.LG]: string;
23
+ [Size.XL]: string;
24
+ [Size.XXL]: string;
25
+ };
26
+ rounded: {
27
+ none: string;
28
+ xs: string;
29
+ sm: string;
30
+ base: string;
31
+ lg: string;
32
+ xl: string;
33
+ '2xl': string;
34
+ full: string;
35
+ };
36
+ isLoading: {
37
+ true: string;
38
+ };
39
+ }, undefined, "\n\t\tinline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none\n\t\tfocus-visible:ring-2 focus-visible:ring-offset-2 cursor-pointer\n\t\t", {
40
+ variant: {
41
+ solid: string;
42
+ outline: string;
43
+ ghost: string;
44
+ link: string;
45
+ };
46
+ color: {
47
+ [Color.DEFAULT]: string;
48
+ [Color.PRIMARY]: string;
49
+ [Color.SECONDARY]: string;
50
+ [Color.INFO]: string;
51
+ [Color.SUCCESS]: string;
52
+ [Color.WARNING]: string;
53
+ [Color.DANGER]: string;
54
+ };
55
+ size: {
56
+ [Size.XS]: string;
57
+ [Size.SM]: string;
58
+ [Size.BASE]: string;
59
+ [Size.LG]: string;
60
+ [Size.XL]: string;
61
+ [Size.XXL]: string;
62
+ };
63
+ rounded: {
64
+ none: string;
65
+ xs: string;
66
+ sm: string;
67
+ base: string;
68
+ lg: string;
69
+ xl: string;
70
+ '2xl': string;
71
+ full: string;
72
+ };
73
+ isLoading: {
74
+ true: string;
75
+ };
76
+ }, undefined, import("tailwind-variants").TVReturnType<{
77
+ variant: {
78
+ solid: string;
79
+ outline: string;
80
+ ghost: string;
81
+ link: string;
82
+ };
83
+ color: {
84
+ [Color.DEFAULT]: string;
85
+ [Color.PRIMARY]: string;
86
+ [Color.SECONDARY]: string;
87
+ [Color.INFO]: string;
88
+ [Color.SUCCESS]: string;
89
+ [Color.WARNING]: string;
90
+ [Color.DANGER]: string;
91
+ };
92
+ size: {
93
+ [Size.XS]: string;
94
+ [Size.SM]: string;
95
+ [Size.BASE]: string;
96
+ [Size.LG]: string;
97
+ [Size.XL]: string;
98
+ [Size.XXL]: string;
99
+ };
100
+ rounded: {
101
+ none: string;
102
+ xs: string;
103
+ sm: string;
104
+ base: string;
105
+ lg: string;
106
+ xl: string;
107
+ '2xl': string;
108
+ full: string;
109
+ };
110
+ isLoading: {
111
+ true: string;
112
+ };
113
+ }, undefined, "\n\t\tinline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none\n\t\tfocus-visible:ring-2 focus-visible:ring-offset-2 cursor-pointer\n\t\t", unknown, unknown, undefined>>;