@putkoff/abstract-securefiles 0.0.47 → 0.0.49

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 (197) hide show
  1. package/dist/ConfirmButton.d.ts +5 -0
  2. package/dist/CopyButton.d.ts +4 -0
  3. package/dist/FolderSelect.d.ts +6 -0
  4. package/dist/SecureFiles.d.ts +3 -0
  5. package/dist/ServerFiles.d.ts +6 -0
  6. package/dist/ShareDialog.d.ts +6 -0
  7. package/dist/UploadPanel.d.ts +6 -0
  8. package/dist/api.d.ts +46 -0
  9. package/dist/index.cjs +539 -956
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.ts +4 -8
  12. package/dist/index.js +531 -902
  13. package/dist/index.js.map +1 -1
  14. package/dist/types.d.ts +54 -0
  15. package/package.json +15 -11
  16. package/src/ConfirmButton.tsx +35 -0
  17. package/src/CopyButton.tsx +24 -0
  18. package/src/FolderSelect.tsx +68 -0
  19. package/src/SecureFiles.tsx +344 -0
  20. package/src/ServerFiles.tsx +324 -0
  21. package/src/ShareDialog.tsx +148 -0
  22. package/src/UploadPanel.tsx +217 -0
  23. package/src/api.ts +119 -0
  24. package/src/index.ts +4 -8
  25. package/src/styles.css +432 -0
  26. package/src/types.ts +54 -0
  27. package/css.d.ts +0 -2
  28. package/dist/App/SecureFiles.d.ts +0 -4
  29. package/dist/App/index.d.ts +0 -1
  30. package/dist/FileHandlers/FileRow/imports.d.ts +0 -2
  31. package/dist/FileHandlers/FileRow/index.d.ts +0 -1
  32. package/dist/FileHandlers/FileRow/src/index.d.ts +0 -1
  33. package/dist/FileHandlers/FileRow/src/row_utils.d.ts +0 -2
  34. package/dist/FileHandlers/FileTable/imports.d.ts +0 -4
  35. package/dist/FileHandlers/FileTable/index.d.ts +0 -1
  36. package/dist/FileHandlers/FileTable/src/index.d.ts +0 -1
  37. package/dist/FileHandlers/FileTable/src/table_utils.d.ts +0 -2
  38. package/dist/FileHandlers/ShareModal/imports.d.ts +0 -2
  39. package/dist/FileHandlers/ShareModal/index.d.ts +0 -1
  40. package/dist/FileHandlers/ShareModal/src/index.d.ts +0 -1
  41. package/dist/FileHandlers/ShareModal/src/share_utils.d.ts +0 -2
  42. package/dist/FileHandlers/Upload/imports.d.ts +0 -2
  43. package/dist/FileHandlers/Upload/index.d.ts +0 -1
  44. package/dist/FileHandlers/Upload/src/index.d.ts +0 -2
  45. package/dist/FileHandlers/Upload/src/upload_utils.d.ts +0 -2
  46. package/dist/FileHandlers/imports.d.ts +0 -4
  47. package/dist/FileHandlers/index.d.ts +0 -4
  48. package/dist/UI/index.d.ts +0 -28
  49. package/dist/file_utils/imports.d.ts +0 -2
  50. package/dist/file_utils/index.d.ts +0 -1
  51. package/dist/file_utils/src/cookieFetch.d.ts +0 -33
  52. package/dist/file_utils/src/delete_utils/imports.d.ts +0 -1
  53. package/dist/file_utils/src/delete_utils/index.d.ts +0 -1
  54. package/dist/file_utils/src/delete_utils/src/delete_row.d.ts +0 -2
  55. package/dist/file_utils/src/delete_utils/src/delete_select.d.ts +0 -4
  56. package/dist/file_utils/src/delete_utils/src/delete_selected.d.ts +0 -2
  57. package/dist/file_utils/src/delete_utils/src/index.d.ts +0 -3
  58. package/dist/file_utils/src/download_utils/imports.d.ts +0 -2
  59. package/dist/file_utils/src/download_utils/index.d.ts +0 -1
  60. package/dist/file_utils/src/download_utils/src/direct_download.d.ts +0 -3
  61. package/dist/file_utils/src/download_utils/src/download_file.d.ts +0 -6
  62. package/dist/file_utils/src/download_utils/src/download_select.d.ts +0 -2
  63. package/dist/file_utils/src/download_utils/src/index.d.ts +0 -5
  64. package/dist/file_utils/src/download_utils/src/target_downloads.d.ts +0 -4
  65. package/dist/file_utils/src/download_utils/src/trigger_download.d.ts +0 -2
  66. package/dist/file_utils/src/imports.d.ts +0 -2
  67. package/dist/file_utils/src/index.d.ts +0 -6
  68. package/dist/file_utils/src/list_utils/imports.d.ts +0 -1
  69. package/dist/file_utils/src/list_utils/index.d.ts +0 -1
  70. package/dist/file_utils/src/list_utils/src/index.d.ts +0 -1
  71. package/dist/file_utils/src/list_utils/src/list_utils.d.ts +0 -2
  72. package/dist/file_utils/src/select_utils/index.d.ts +0 -1
  73. package/dist/file_utils/src/select_utils/src/index.d.ts +0 -3
  74. package/dist/file_utils/src/select_utils/src/init_select_all.d.ts +0 -2
  75. package/dist/file_utils/src/select_utils/src/sync_header_checkbox.d.ts +0 -5
  76. package/dist/file_utils/src/select_utils/src/toggle_checkboxes.d.ts +0 -2
  77. package/dist/file_utils/src/share_utils/imports.d.ts +0 -1
  78. package/dist/file_utils/src/share_utils/index.d.ts +0 -1
  79. package/dist/file_utils/src/share_utils/src/index.d.ts +0 -1
  80. package/dist/file_utils/src/share_utils/src/share_utils.d.ts +0 -7
  81. package/dist/file_utils/src/upload_utils/imports.d.ts +0 -0
  82. package/dist/file_utils/src/upload_utils/index.d.ts +0 -1
  83. package/dist/file_utils/src/upload_utils/src/index.d.ts +0 -3
  84. package/dist/file_utils/src/upload_utils/src/patch_file_settings.d.ts +0 -2
  85. package/dist/file_utils/src/upload_utils/src/upload_file.d.ts +0 -2
  86. package/dist/file_utils/src/upload_utils/src/upload_files.d.ts +0 -5
  87. package/dist/hooks/imports.d.ts +0 -3
  88. package/dist/hooks/index.d.ts +0 -1
  89. package/dist/hooks/useFiles/imports.d.ts +0 -2
  90. package/dist/hooks/useFiles/index.d.ts +0 -1
  91. package/dist/hooks/useFiles/src/deleteFile.d.ts +0 -3
  92. package/dist/hooks/useFiles/src/index.d.ts +0 -6
  93. package/dist/hooks/useFiles/src/load.d.ts +0 -3
  94. package/dist/hooks/useFiles/src/patchShareSettings.d.ts +0 -3
  95. package/dist/hooks/useFiles/src/toggleShare.d.ts +0 -3
  96. package/dist/hooks/useFiles/src/useFiles.d.ts +0 -13
  97. package/dist/hooks/useFiles/src/useSaveShareSettings.d.ts +0 -7
  98. package/dist/imports.d.ts +0 -6
  99. package/dist/index.css +0 -1
  100. package/dist/styles/index.d.ts +0 -1
  101. package/dist/types/index.d.ts +0 -1
  102. package/dist/types/src/index.d.ts +0 -1
  103. package/dist/types/src/types.d.ts +0 -75
  104. package/index.ts +0 -1
  105. package/postcss.config.cjs +0 -8
  106. package/rollup.config.js +0 -38
  107. package/rollup.config.mjs +0 -35
  108. package/src/App/SecureFiles.tsx +0 -45
  109. package/src/App/index.ts +0 -1
  110. package/src/FileHandlers/FileRow/imports.ts +0 -2
  111. package/src/FileHandlers/FileRow/index.ts +0 -1
  112. package/src/FileHandlers/FileRow/src/index.ts +0 -1
  113. package/src/FileHandlers/FileRow/src/row_utils.tsx +0 -143
  114. package/src/FileHandlers/FileTable/imports.ts +0 -15
  115. package/src/FileHandlers/FileTable/index.ts +0 -1
  116. package/src/FileHandlers/FileTable/src/index.ts +0 -1
  117. package/src/FileHandlers/FileTable/src/table_utils.tsx +0 -251
  118. package/src/FileHandlers/ShareModal/imports.ts +0 -2
  119. package/src/FileHandlers/ShareModal/index.ts +0 -1
  120. package/src/FileHandlers/ShareModal/src/index.ts +0 -1
  121. package/src/FileHandlers/ShareModal/src/share_utils.tsx +0 -155
  122. package/src/FileHandlers/Upload/imports.ts +0 -3
  123. package/src/FileHandlers/Upload/index.ts +0 -1
  124. package/src/FileHandlers/Upload/src/index.ts +0 -2
  125. package/src/FileHandlers/Upload/src/upload_utils.tsx +0 -267
  126. package/src/FileHandlers/imports.ts +0 -17
  127. package/src/FileHandlers/index.ts +0 -4
  128. package/src/UI/index.tsx +0 -122
  129. package/src/custom.d.ts +0 -7
  130. package/src/file_utils/imports.ts +0 -2
  131. package/src/file_utils/index.ts +0 -1
  132. package/src/file_utils/src/cookieFetch.ts +0 -109
  133. package/src/file_utils/src/delete_utils/imports.ts +0 -1
  134. package/src/file_utils/src/delete_utils/index.ts +0 -1
  135. package/src/file_utils/src/delete_utils/src/delete_row.ts +0 -11
  136. package/src/file_utils/src/delete_utils/src/delete_select.ts +0 -10
  137. package/src/file_utils/src/delete_utils/src/delete_selected.ts +0 -15
  138. package/src/file_utils/src/delete_utils/src/index.ts +0 -3
  139. package/src/file_utils/src/download_utils/imports.ts +0 -3
  140. package/src/file_utils/src/download_utils/index.ts +0 -1
  141. package/src/file_utils/src/download_utils/src/direct_download.ts +0 -22
  142. package/src/file_utils/src/download_utils/src/download_file.ts +0 -25
  143. package/src/file_utils/src/download_utils/src/download_select.ts +0 -25
  144. package/src/file_utils/src/download_utils/src/index.ts +0 -5
  145. package/src/file_utils/src/download_utils/src/target_downloads.ts +0 -21
  146. package/src/file_utils/src/download_utils/src/trigger_download.ts +0 -14
  147. package/src/file_utils/src/imports.ts +0 -3
  148. package/src/file_utils/src/index.ts +0 -6
  149. package/src/file_utils/src/list_utils/imports.ts +0 -2
  150. package/src/file_utils/src/list_utils/index.ts +0 -1
  151. package/src/file_utils/src/list_utils/src/index.ts +0 -1
  152. package/src/file_utils/src/list_utils/src/list_utils.ts +0 -28
  153. package/src/file_utils/src/select_utils/index.ts +0 -1
  154. package/src/file_utils/src/select_utils/src/index.ts +0 -3
  155. package/src/file_utils/src/select_utils/src/init_select_all.ts +0 -37
  156. package/src/file_utils/src/select_utils/src/sync_header_checkbox.ts +0 -18
  157. package/src/file_utils/src/select_utils/src/toggle_checkboxes.ts +0 -11
  158. package/src/file_utils/src/share_utils/imports.ts +0 -1
  159. package/src/file_utils/src/share_utils/index.ts +0 -1
  160. package/src/file_utils/src/share_utils/src/index.ts +0 -1
  161. package/src/file_utils/src/share_utils/src/share_utils.ts +0 -20
  162. package/src/file_utils/src/upload_utils/imports.ts +0 -1
  163. package/src/file_utils/src/upload_utils/index.ts +0 -1
  164. package/src/file_utils/src/upload_utils/src/index.ts +0 -3
  165. package/src/file_utils/src/upload_utils/src/patch_file_settings.ts +0 -20
  166. package/src/file_utils/src/upload_utils/src/upload_file.ts +0 -27
  167. package/src/file_utils/src/upload_utils/src/upload_files.ts +0 -19
  168. package/src/hooks/imports.ts +0 -3
  169. package/src/hooks/index.ts +0 -1
  170. package/src/hooks/useFiles/imports.ts +0 -3
  171. package/src/hooks/useFiles/index.ts +0 -1
  172. package/src/hooks/useFiles/src/deleteFile.ts +0 -23
  173. package/src/hooks/useFiles/src/index.ts +0 -6
  174. package/src/hooks/useFiles/src/load.ts +0 -39
  175. package/src/hooks/useFiles/src/logs/clipit_logs.log +0 -0
  176. package/src/hooks/useFiles/src/logs/routes_bp.log +0 -0
  177. package/src/hooks/useFiles/src/patchShareSettings.ts +0 -27
  178. package/src/hooks/useFiles/src/toggleShare.ts +0 -28
  179. package/src/hooks/useFiles/src/useFiles.ts +0 -35
  180. package/src/hooks/useFiles/src/useSaveShareSettings.ts +0 -31
  181. package/src/imports.ts +0 -18
  182. package/src/styles/SecureFiles/App.css +0 -42
  183. package/src/styles/SecureFiles/index.css +0 -10
  184. package/src/styles/SecureFiles/logs/clipit_logs.log +0 -0
  185. package/src/styles/SecureFiles/logs/routes_bp.log +0 -0
  186. package/src/styles/SecureFiles/tailwind.css +0 -3
  187. package/src/styles/SecureFiles/window-manager.css +0 -283
  188. package/src/styles/SecureFilesStyles.module.css +0 -287
  189. package/src/styles/index.ts +0 -1
  190. package/src/types/index.ts +0 -1
  191. package/src/types/src/index.ts +0 -1
  192. package/src/types/src/types.ts +0 -88
  193. package/tailwind.config.cjs +0 -7
  194. package/testit.mjs +0 -11
  195. package/testit.ts +0 -3
  196. package/tsconfig.json +0 -27
  197. /package/src/{global.d.ts → css.d.ts} +0 -0
@@ -1,267 +0,0 @@
1
- import React, {
2
- ChangeEvent,
3
- useRef,
4
- useState,
5
- useCallback,
6
- useEffect,
7
- } from 'react';
8
- import {
9
- CloudArrowUpIcon,
10
- Button,
11
- uploadFiles,
12
- useFiles,
13
- currentUsername
14
- } from './../imports';
15
- import type { QueuedFile, UploadProps } from './../imports';
16
-
17
- export default function Upload({ onUploaded }: UploadProps) {
18
- const [queue, setQueue] = useState<QueuedFile[]>([]);
19
- const [busy, setBusy] = useState(false);
20
- const [message, setMessage] = useState<string | null>(null);
21
- const [drag, setDrag] = useState(false);
22
- const inputRef = useRef<HTMLInputElement>(null);
23
- const [dirs, setDirs] = useState<string[]>([]);
24
-
25
- // — existing files → directory list —
26
- const { files, load } = useFiles();
27
-
28
- useEffect(() => {
29
- const dirSet = new Set<string>();
30
- files.forEach(f => {
31
- const parts = f.filepath.split('/');
32
- if (parts.length > 1) {
33
- parts.pop();
34
- dirSet.add(parts.join('/') + '/');
35
- }
36
- });
37
- setDirs(Array.from(dirSet).sort());
38
- }, [files]);
39
-
40
- // — directory selection state —
41
- const [uploadDir, setUploadDir] = useState<string>('');
42
- const [creatingNew, setCreatingNew] = useState(false);
43
- const [newDirName, setNewDirName] = useState('');
44
-
45
- // — queue logic —
46
- const enqueue = useCallback((files: QueuedFile[]) => {
47
- setQueue(prev => {
48
- const map = new Map(prev.map(q => [`${q.file.name}-${q.file.size}`, q]));
49
- files.forEach(q => map.set(`${q.file.name}-${q.file.size}`, q));
50
- return Array.from(map.values());
51
- });
52
- }, []);
53
-
54
- const extractFromDataTransfer = useCallback(
55
- async (dt: DataTransfer): Promise<QueuedFile[]> => {
56
- const out: QueuedFile[] = [];
57
- const walk = async (entry: any, path = "") => {
58
- if (!entry) return;
59
- if (entry.isFile) {
60
- const file: File = await new Promise(res => entry.file(res));
61
- out.push({ file, relPath: path, progress: 0 });
62
- } else if (entry.isDirectory) {
63
- const reader = entry.createReader();
64
- const entries: any[] = await new Promise(r => reader.readEntries(r));
65
- await Promise.all(entries.map(e => walk(e, `${path}${entry.name}/`)));
66
- }
67
- };
68
- await Promise.all(Array.from(dt.items).map(i => walk(i.webkitGetAsEntry())));
69
- return out;
70
- },
71
- []
72
- );
73
-
74
- const handleSelect = (e: ChangeEvent<HTMLInputElement>) => {
75
- const files = Array.from(e.target.files || []);
76
- const queued: any = files.map(f => ({
77
- file: f,
78
- relPath: (f as any).webkitRelativePath.replace(/[^/]*$/, ""),
79
- progress: 0,
80
- }));
81
- enqueue(queued);
82
- e.target.value = "";
83
- };
84
-
85
- const handleDrop = async (e: React.DragEvent) => {
86
- e.preventDefault();
87
- const files = await extractFromDataTransfer(e.dataTransfer);
88
- enqueue(files.length ? files : []);
89
- setDrag(false);
90
- };
91
-
92
- const handleUploadAll = async () => {
93
- if (!queue.length) {
94
- setMessage("No files queued.");
95
- return;
96
- }
97
- setBusy(true);
98
- setMessage(null);
99
- const targetDir = creatingNew
100
- ? (newDirName.trim().replace(/^\/+|\/+$/g, "") + "/")
101
- : uploadDir;
102
- try {
103
- for (const { file, relPath } of queue) {
104
- await uploadFiles(file, targetDir + relPath);
105
- setQueue(cur =>
106
- cur.map(item =>
107
- item.file === file ? { ...item, progress: 100 } : item
108
- )
109
- );
110
- }
111
- setQueue([]);
112
- await onUploaded();
113
- setMessage("Upload complete");
114
- load();
115
- } catch {
116
- setMessage("Upload failed");
117
- } finally {
118
- setBusy(false);
119
- }
120
- };
121
-
122
- // — directory selector handlers —
123
- const handleDirChange = (e: ChangeEvent<HTMLSelectElement>) => {
124
- const v = e.target.value;
125
- if (v === "__new__") {
126
- setCreatingNew(true);
127
- setNewDirName("");
128
- } else {
129
- setCreatingNew(false);
130
- setUploadDir(v);
131
- }
132
- };
133
- const acceptNewDir = () => {
134
- // normalize like before
135
- const cleanName = newDirName.trim().replace(/^\/+|\/+$/g, '');
136
- const normalized = `${uploadDir}${cleanName}/`;
137
- // ① add it to our dirs list if it isn't there already
138
- setDirs(prev => {
139
- if (prev.includes(normalized)) return prev;
140
- return [...prev, normalized].sort();
141
- });
142
-
143
- // ② select it & flip back to the <select>
144
- setUploadDir(normalized);
145
- setCreatingNew(false);
146
- setNewDirName('');
147
- };
148
-
149
- return (
150
- <div className="form-container max-w-2xl mx-auto">
151
- {/* drop area */}
152
- <div
153
- className={`flex items-center border-2 border-dashed rounded-lg p-6 bg-white shadow-md space-x-4 transition-shadow duration-150
154
- ${drag ? 'border-indigo-500 bg-indigo-50 shadow-lg' : 'border-gray-300 hover:shadow-lg'}`}
155
- onClick={() => inputRef.current?.click()}
156
- onDragEnter={e => { e.preventDefault(); setDrag(true); }}
157
- onDragOver={e => e.preventDefault()}
158
- onDragLeave={() => setDrag(false)}
159
- onDrop={handleDrop}
160
- role="region"
161
- aria-label="File upload area"
162
- >
163
- <CloudArrowUpIcon
164
- style={{ width: 300, height: 300 }}
165
- className="text-gray-500 mb-3"
166
- aria-hidden="true"
167
- />
168
- <div className="flex-1">
169
- <p className="text-base font-semibold text-gray-700">
170
- Drag & drop files or folders here
171
- </p>
172
- {queue.length > 0 && (
173
- <p className="mt-1 text-sm text-gray-600">
174
- {queue.length} item{queue.length > 1 && 's'} queued
175
- </p>
176
- )}
177
- </div>
178
- </div>
179
-
180
- {/* hidden file input */}
181
- <input
182
- ref={inputRef}
183
- type="file"
184
- multiple
185
- className="hidden"
186
- {...({ webkitdirectory: true, directory: '' } as any)}
187
- onChange={handleSelect}
188
- />
189
-
190
- {/* bottom controls */}
191
- <div className="flex items-center justify-between mt-4">
192
- {/* directory selector / new dir input */}
193
- <div className="flex-1 mr-4">
194
- {!creatingNew ? (
195
- <select
196
- value={uploadDir}
197
- onChange={handleDirChange}
198
- className="form-select w-full"
199
- >
200
- {dirs.map(d => (
201
- <option key={d} value={d}>{d}</option>
202
- ))}
203
- <option value="__new__">+ Create new directory…</option>
204
- </select>
205
- ) : (
206
- <div className="flex">
207
- <input
208
- type="text"
209
- value={newDirName}
210
- placeholder="new-folder-name"
211
- onChange={e => setNewDirName(e.target.value)}
212
- onBlur={acceptNewDir}
213
- onKeyDown={e => e.key === 'Enter' && acceptNewDir()}
214
- className="form-input flex-1"
215
- />
216
- <Button onClick={acceptNewDir} className="ml-2">
217
- OK
218
- </Button>
219
- </div>
220
- )}
221
- </div>
222
-
223
- {/* upload button */}
224
- <Button
225
- color="blue"
226
- variant="primary"
227
- onClick={handleUploadAll}
228
- disabled={busy || !queue.length}
229
- >
230
- {busy ? 'Uploading…' : `Upload ${queue.length}`}
231
- </Button>
232
- </div>
233
-
234
- {message && (
235
- <p
236
- className={`text-center text-sm ${message.includes('failed') ? 'text-red-600' : 'text-gray-600'
237
- }`}
238
- role="alert"
239
- >
240
- {message}
241
- </p>
242
- )}
243
-
244
- {/* queued list */}
245
- {queue.length > 0 && (
246
- <div className="wm-container mt-4">
247
- <h3 className="mb-2 text-sm font-semibold text-gray-700">Queued Files</h3>
248
- <ul className="max-h-64 space-y-4 overflow-y-auto">
249
- {queue.map(({ file, relPath, progress }) => (
250
- <li key={`${file.name}-${file.size}`} className="space-y-1">
251
- <div className="flex justify-between items-center">
252
- <span className="truncate text-sm text-gray-800">
253
- {relPath}{file.name}
254
- </span>
255
- <span className="text-xs text-gray-500">{progress}%</span>
256
- </div>
257
- <div className="w-full bg-gray-200 rounded-full h-2 overflow-hidden">
258
- <div className="bg-indigo-600 h-2" style={{ width: `${progress}%` }} />
259
- </div>
260
- </li>
261
- ))}
262
- </ul>
263
- </div>
264
- )}
265
- </div>
266
- );
267
- }
@@ -1,17 +0,0 @@
1
- export type {QueuedFile, FileItem,FileTableProps,UploadProps,ShareModalProps,FileRowProps } from './../imports';
2
- export {
3
- CloudArrowUpIcon,
4
- currentUsername,
5
- Button,
6
- Checkbox,
7
- Input,
8
- Spinner,
9
- useEffect,
10
- useRef,
11
- useState,
12
- useCallback,
13
- ClipboardIcon,
14
- createPortal,
15
- } from './../imports';
16
- export {useFiles} from './../hooks'
17
- export { downloadFile, uploadFiles } from './../file_utils'
@@ -1,4 +0,0 @@
1
- export {FileRow} from './FileRow';
2
- export {FileTable} from './FileTable';
3
- export {ShareModal} from './ShareModal';
4
- export {Upload} from './Upload';
package/src/UI/index.tsx DELETED
@@ -1,122 +0,0 @@
1
- import React from 'react';
2
-
3
- export type String = string | undefined | null;
4
- export type Astring = any[] | string | undefined | null;
5
- export type Trailing = React.ReactNode
6
- export type ImportElem = {
7
- reaxlEle?:React.InputHTMLAttributes<HTMLInputElement>;
8
- label?: String;
9
- checked?:boolean;
10
- type?:string;
11
- onChange?: any;
12
- value?: any;
13
- trailing?:Trailing;
14
- className?: String;
15
- classNames?:Astring;
16
- disabled?: any;
17
- placeholder?: any;
18
- error?: string;
19
- min?:any,
20
- readOnly?:boolean
21
- }
22
-
23
- // Utility to convert input to array
24
- function ensure_list(obj: Astring | null | undefined): string[] {
25
- if (Array.isArray(obj)) return obj.filter(Boolean);
26
- if (typeof obj === 'string') return obj.split(' ').filter(Boolean);
27
- return [];
28
- }
29
-
30
- // Get list and length safely
31
- function getListAndLen(obj: Astring | null | undefined): { return_obj: string[]; ob_len: number } {
32
- const return_obj = ensure_list(obj);
33
- const ob_len = return_obj.length;
34
- return { return_obj, ob_len };
35
- }
36
-
37
- // Combine class names with defaults
38
- function combineClassNames(classNames: Astring = [], defaultClasses: Astring = ['form-group', 'form-label', 'flex', 'gap-2']): string[] {
39
- const { return_obj: inputClasses } = getListAndLen(classNames);
40
- const { return_obj: defaultClassList } = getListAndLen(defaultClasses);
41
-
42
- // Combine and remove duplicates
43
- const combined = [...new Set([...defaultClassList, ...inputClasses])];
44
-
45
- console.log(`Combined classes (length: ${combined.length}): ${combined.join(' ')}`);
46
- return combined;
47
- }
48
-
49
- export function Button({
50
- children,
51
- color = 'gray',
52
- variant = 'default',
53
- className = '',
54
- ...rest
55
- }: React.ButtonHTMLAttributes<HTMLButtonElement> & {
56
- color?: 'gray' | 'green' | 'blue';
57
- variant?: 'default' | 'icon' | 'primary' | 'secondary';
58
- className?: string;
59
- }) {
60
- const variantClasses = {
61
- default: 'btn',
62
- icon: 'btn-icon',
63
- primary: 'btn-primary',
64
- secondary: 'btn-secondary',
65
- };
66
-
67
- const colorClasses = {
68
- gray: '',
69
- green: variant === 'primary' ? 'btn-success' : 'btn-secondary',
70
- blue: variant === 'primary' ? 'btn-primary' : 'btn-secondary',
71
- };
72
-
73
- const classes = combineClassNames([variantClasses[variant], colorClasses[color], className]);
74
-
75
- return (
76
- <button className={classes.join(' ')} {...rest}>
77
- {children}
78
- </button>
79
- );
80
- }
81
-
82
- export function Checkbox({
83
- label,
84
- className = '',
85
- classNames = [],
86
- ...rest
87
- }: ImportElem) {
88
- const classes = combineClassNames(classNames, ['checkbox', 'wm-checkbox']);
89
-
90
- return (
91
- <label className={classes.join(' ')}>
92
- <input type="checkbox" className="wm-checkbox" {...rest} />
93
- {label && <span>{label}</span>}
94
- </label>
95
- );
96
- }
97
-
98
- export function Input({
99
- label,
100
- trailing,
101
- className = '',
102
- classNames = [],
103
- ...rest
104
- }: ImportElem) {
105
- const classes = combineClassNames(classNames, ['form-group', 'flex', 'gap-2']);
106
- const inputClasses = combineClassNames(className, ['form-input']);
107
-
108
- return (
109
- <label className={classes.join(' ')}>
110
- {label && <span className="form-label">{label}</span>}
111
- <div className="flex gap-2">
112
- <input className={inputClasses.join(' ')} {...rest} />
113
- {trailing}
114
- </div>
115
- </label>
116
- );
117
- }
118
-
119
- export function Spinner() {
120
- const classes = combineClassNames('animate-pulse');
121
- return <p className={classes.join(' ')}>Loading…</p>;
122
- }
package/src/custom.d.ts DELETED
@@ -1,7 +0,0 @@
1
- // src/custom.d.ts
2
- declare namespace NodeJS {
3
- interface ProcessEnv {
4
- readonly REACT_APP_API_BASE_URL: string;
5
- // add more as needed...
6
- }
7
- }
@@ -1,2 +0,0 @@
1
- export { requireToken, alertit, fetchIt, stripPrefixes, make_path } from "./../imports";
2
- export type { FileItem, ApiRow } from "./../types";
@@ -1 +0,0 @@
1
- export * from './src';
@@ -1,109 +0,0 @@
1
- /**
2
- * Cookie-authenticated API helpers.
3
- * All requests include credentials: 'include' so the browser sends the
4
- * session cookie (auth_session) automatically. No JWT tokens are used.
5
- *
6
- * API base URL resolution order (first truthy value wins):
7
- * 1. window.__SECURE_FILES_API_BASE__ – runtime override (any bundler)
8
- * 2. VITE_SECURE_FILES_API_BASE – Vite env var
9
- * 3. REACT_APP_SECURE_FILES_API_BASE – Create React App env var
10
- * 4. /api/secure-files – same-origin default
11
- *
12
- * Subdomain API example (set one of the above to the full origin + path):
13
- * VITE_SECURE_FILES_API_BASE=https://api.example.com/secure-files
14
- */
15
-
16
- function resolveApiBase(): string {
17
- // 1. Runtime window config — works regardless of bundler
18
- if (typeof window !== "undefined" && (window as any).__SECURE_FILES_API_BASE__) {
19
- return String((window as any).__SECURE_FILES_API_BASE__).replace(/\/+$/, "");
20
- }
21
- // 2. Vite (import.meta.env is replaced at build time; guard with try for non-Vite builds)
22
- try {
23
- const v = (import.meta as any).env?.VITE_SECURE_FILES_API_BASE;
24
- if (v) return String(v).replace(/\/+$/, "");
25
- } catch { /* not a Vite build */ }
26
- // 3. Create React App / plain Node
27
- try {
28
- const v = (process as any).env?.REACT_APP_SECURE_FILES_API_BASE;
29
- if (v) return String(v).replace(/\/+$/, "");
30
- } catch { /* process not defined */ }
31
- // 4. Same-origin default
32
- return "/api/secure-files";
33
- }
34
-
35
- const API_BASE = resolveApiBase();
36
-
37
- function apiUrl(path: string): string {
38
- const p = path.startsWith("/") ? path : `/${path}`;
39
- return `${API_BASE}${p}`;
40
- }
41
-
42
- /**
43
- * Generic JSON fetch with session-cookie auth.
44
- * Throws Error("UNAUTHENTICATED") on 401 so callers can redirect to login.
45
- */
46
- export async function cookieFetch<T = unknown>(
47
- path: string,
48
- body?: unknown,
49
- method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE",
50
- ): Promise<T> {
51
- const m = method ?? (body !== undefined ? "POST" : "GET");
52
- const init: RequestInit = { method: m, credentials: "include" };
53
-
54
- if (body !== undefined && body !== null) {
55
- init.headers = { "Content-Type": "application/json" };
56
- init.body = JSON.stringify(body);
57
- }
58
-
59
- const res = await fetch(apiUrl(path), init);
60
- if (res.status === 401) throw new Error("UNAUTHENTICATED");
61
- if (!res.ok) {
62
- const msg = await res.text().catch(() => res.statusText);
63
- throw new Error(`HTTP ${res.status}: ${msg}`);
64
- }
65
-
66
- const ct = res.headers.get("Content-Type") ?? "";
67
- return (ct.includes("application/json") ? res.json() : res.text()) as Promise<T>;
68
- }
69
-
70
- /**
71
- * Check whether the current session is valid.
72
- * Calls /userInfo which requires authentication; returns true if the user
73
- * is logged in, false otherwise (no exception thrown).
74
- */
75
- export async function checkAuth(): Promise<boolean> {
76
- try {
77
- const res = await fetch(apiUrl("/userInfo"), {
78
- method: "GET",
79
- credentials: "include",
80
- });
81
- return res.ok;
82
- } catch {
83
- return false;
84
- }
85
- }
86
-
87
- /**
88
- * Upload a single file using multipart/form-data with session-cookie auth.
89
- * @param file The File object to upload.
90
- * @param relPath Optional relative path within the user's directory.
91
- */
92
- export async function cookieUpload(file: File, relPath = ""): Promise<unknown> {
93
- const form = new FormData();
94
- form.append("file", file);
95
- if (relPath) form.append("rel_path", relPath);
96
-
97
- const res = await fetch(apiUrl("/upload"), {
98
- method: "POST",
99
- credentials: "include",
100
- body: form,
101
- });
102
-
103
- if (res.status === 401) throw new Error("UNAUTHENTICATED");
104
- if (!res.ok) throw new Error(`Upload failed: HTTP ${res.status}`);
105
- return res.json();
106
- }
107
-
108
- /** The resolved API base URL, exported for debugging / display purposes. */
109
- export const SECURE_FILES_API_BASE = API_BASE;
@@ -1 +0,0 @@
1
- export { requireToken,alertit } from "./../imports";
@@ -1 +0,0 @@
1
- export * from './src';
@@ -1,11 +0,0 @@
1
-
2
- import {removeFile} from './delete_select'
3
- import {alertit} from './../imports'
4
- /** Given a checkbox inside a table-row → download that row’s file. */
5
- export async function removeRow(cb: HTMLInputElement): Promise<void> {
6
- const row = cb.closest("tr") as HTMLTableRowElement | null;
7
- alertit(row)
8
- if (row && row?.id) await removeFile(row);
9
- }
10
-
11
-
@@ -1,10 +0,0 @@
1
- import { cookieFetch } from '../../cookieFetch';
2
-
3
- export async function removeFile(
4
- item: { id?: number | string; filename?: string },
5
- ): Promise<void> {
6
- const resp = await cookieFetch<unknown>("remove", { id: item.id }, "POST");
7
- if (!resp || (resp as any) === false || (resp as any)?.result === false) {
8
- throw new Error(`Could not delete "${item.filename ?? item.id}"`);
9
- }
10
- }
@@ -1,15 +0,0 @@
1
- import {removeFile} from './delete_select';
2
-
3
-
4
- /** Bulk download: pass a NodeList or array of checkboxes. */
5
- export async function removeSelected(checkboxes: Iterable<HTMLInputElement>): Promise<void> {
6
- const list = Array.from(checkboxes);
7
- if (!list.length) {
8
- alert("No files selected.");
9
- return;
10
- }
11
- for (const cb of list) {
12
- alert(cb);
13
- await removeFile(cb);
14
- }
15
- }
@@ -1,3 +0,0 @@
1
- export * from './delete_select';
2
- export * from './delete_selected';
3
- export * from './delete_row';
@@ -1,3 +0,0 @@
1
-
2
- export { requireToken } from './../imports'
3
- export type { FileItem } from './../imports'
@@ -1 +0,0 @@
1
- export * from './src';
@@ -1,22 +0,0 @@
1
- import {triggerDownload} from './trigger_download';
2
- import {FileItem} from './../imports';
3
- /** Non-React “direct download” used by some old links (kept for parity) */
4
- export async function directDownload(item: FileItem): Promise<void> {
5
- const token = localStorage.getItem("token");
6
- if (!token) throw new Error("No auth token found");
7
-
8
- const res = await fetch("https://abstractendeavors.com/api/secure-files/secure-download/", {
9
- method: "POST",
10
- headers: {
11
- Authorization: `Bearer ${token}`,
12
- "Content-Type": "application/json",
13
- Accept: "application/octet-stream",
14
- },
15
-
16
- body: JSON.stringify(item),
17
- });
18
-
19
- if (!res.ok) throw new Error(`Download failed: ${res.status}`);
20
- const blob = await res.blob();
21
- triggerDownload(blob, item.filename);
22
- }
@@ -1,25 +0,0 @@
1
- import type { FileItem } from './../imports';
2
- import { triggerDownload } from './trigger_download';
3
-
4
- /**
5
- * Download a file using the current session cookie.
6
- * No JWT / localStorage token required.
7
- */
8
- export async function downloadFile(item: FileItem): Promise<void> {
9
- const res = await fetch("/api/secure-files/download", {
10
- method: "POST",
11
- credentials: "include",
12
- headers: { "Content-Type": "application/json" },
13
- body: JSON.stringify({
14
- id: item.id,
15
- filepath: item.filepath,
16
- filename: item.filename,
17
- }),
18
- });
19
-
20
- if (res.status === 401) throw new Error("Not authenticated – please log in.");
21
- if (!res.ok) throw new Error(`Download failed: HTTP ${res.status}`);
22
-
23
- const blob = await res.blob();
24
- triggerDownload(blob, item.filename || "download");
25
- }
@@ -1,25 +0,0 @@
1
- import type { FileItem } from './../imports';
2
- import { triggerDownload } from './trigger_download';
3
- import { SECURE_FILES_API_BASE } from './../../cookieFetch';
4
-
5
- export async function downloadSelect(item: FileItem): Promise<void> {
6
- const res = await fetch(`${SECURE_FILES_API_BASE}/download`, {
7
- method: "POST",
8
- credentials: "include",
9
- headers: {
10
- "Content-Type": "application/json",
11
- Accept: "application/octet-stream",
12
- },
13
- body: JSON.stringify(item),
14
- });
15
-
16
- if (res.status === 401) throw new Error("Not authenticated – please log in.");
17
- if (!res.ok) throw new Error(`Download failed: HTTP ${res.status}`);
18
-
19
- const blob = await res.blob();
20
- if (!blob || blob.size === 0) {
21
- throw new Error(`Received empty file data for "${item.filename}"`);
22
- }
23
-
24
- triggerDownload(blob, item.filename);
25
- }
@@ -1,5 +0,0 @@
1
- export * from './direct_download';
2
- export * from './download_file';
3
- export * from './download_select';
4
- export * from './target_downloads';
5
- export * from './trigger_download';