@securancy/file-explorer 1.1.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/FileExplorer.svelte +50 -66
- package/dist/components/FileExplorer.svelte.d.ts +21 -63
- package/dist/components/FileExplorerBreadcrumb.svelte +3 -4
- package/dist/components/FileExplorerBreadcrumb.svelte.d.ts +6 -16
- package/dist/components/FileExplorerCreateDirectory.svelte +18 -20
- package/dist/components/FileExplorerCreateDirectory.svelte.d.ts +10 -21
- package/dist/components/FileExplorerDirectory.svelte +13 -31
- package/dist/components/FileExplorerDirectory.svelte.d.ts +17 -27
- package/dist/components/FileExplorerDirectoryColumn.svelte +21 -26
- package/dist/components/FileExplorerDirectoryColumn.svelte.d.ts +12 -24
- package/dist/components/FileExplorerDirectoryIndex.svelte +13 -17
- package/dist/components/FileExplorerDirectoryIndex.svelte.d.ts +11 -22
- package/dist/components/FileExplorerDisplayModeSwitcher.svelte +2 -3
- package/dist/components/FileExplorerDisplayModeSwitcher.svelte.d.ts +6 -16
- package/dist/components/FileExplorerFileDetailColumn.svelte +8 -11
- package/dist/components/FileExplorerFileDetailColumn.svelte.d.ts +9 -21
- package/dist/components/FileIcon.svelte +3 -5
- package/dist/components/FileIcon.svelte.d.ts +6 -16
- package/package.json +20 -17
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<script
|
|
1
|
+
<script lang="ts" module>export {};
|
|
2
2
|
</script>
|
|
3
3
|
|
|
4
|
-
<script>import {
|
|
4
|
+
<script lang="ts">import { tick } from 'svelte';
|
|
5
5
|
import FileExplorerBreadcrumb from './FileExplorerBreadcrumb.svelte';
|
|
6
6
|
import FileExplorerDisplayModeSwitcher from './FileExplorerDisplayModeSwitcher.svelte';
|
|
7
7
|
import { defaultTranslations, FileExplorerDisplayMode } from '../index.js';
|
|
@@ -11,37 +11,20 @@ import FileExplorerDirectory from './FileExplorerDirectory.svelte';
|
|
|
11
11
|
import { Icon } from '@securancy/svelte-components';
|
|
12
12
|
import { fade } from 'svelte/transition';
|
|
13
13
|
import { pathsEqual } from '../utilities';
|
|
14
|
-
|
|
15
|
-
export let filePath;
|
|
16
|
-
export let documents;
|
|
17
|
-
export let loading;
|
|
18
|
-
export let routePrefix;
|
|
19
|
-
export let canEdit;
|
|
20
|
-
export let translations = defaultTranslations;
|
|
21
|
-
export let getFilePreview;
|
|
22
|
-
// When provided, it will use the default implementation for creating directories, otherwise it will dispatch an event
|
|
23
|
-
export let createDirectory = undefined;
|
|
24
|
-
// When provided, it will use the default implementation for uploading files, otherwise it will dispatch an event
|
|
25
|
-
export let uploadFiles = undefined;
|
|
26
|
-
// When provided, it will use the default implementation for deleting files, otherwise it will dispatch an event
|
|
27
|
-
export let deleteFile = undefined;
|
|
28
|
-
const dispatch = createEventDispatcher();
|
|
14
|
+
let { displayMode = $bindable(FileExplorerDisplayMode.Columns), filePath, documents, refresh, routePrefix, canEdit, translations = defaultTranslations, getFilePreview, createDirectory = undefined, uploadFiles = undefined, deleteFile = undefined, search, onUploadFile, onCreateDirectory, onDeleteFile, } = $props();
|
|
29
15
|
const scrollBackButtonThreshold = 200;
|
|
30
|
-
let fileExplorerContentContainer;
|
|
31
|
-
let showScrollBackButton = false;
|
|
16
|
+
let fileExplorerContentContainer = $state();
|
|
17
|
+
let showScrollBackButton = $state(false);
|
|
32
18
|
// Create directory state
|
|
33
|
-
let createDirectoryPath;
|
|
34
|
-
let createDirectoryModalOpen = false;
|
|
19
|
+
let createDirectoryPath = $state();
|
|
20
|
+
let createDirectoryModalOpen = $state(false);
|
|
35
21
|
// Delete item state
|
|
36
|
-
let deleteFileModalOpen = false;
|
|
22
|
+
let deleteFileModalOpen = $state(false);
|
|
37
23
|
let deleteFileEvent;
|
|
38
|
-
let deleting = false;
|
|
39
|
-
let overrideFilesModalOpen = false;
|
|
40
|
-
let overrideFiles = [];
|
|
24
|
+
let deleting = $state(false);
|
|
25
|
+
let overrideFilesModalOpen = $state(false);
|
|
26
|
+
let overrideFiles = $state([]);
|
|
41
27
|
let uploadFilesRequest;
|
|
42
|
-
// If the route changes, always scroll to the right to show the new column
|
|
43
|
-
$: if (filePath)
|
|
44
|
-
tick().then(() => scrollToRight());
|
|
45
28
|
async function scrollToRight() {
|
|
46
29
|
if (!fileExplorerContentContainer)
|
|
47
30
|
return;
|
|
@@ -51,9 +34,13 @@ async function scrollToRight() {
|
|
|
51
34
|
});
|
|
52
35
|
}
|
|
53
36
|
function handleScroll() {
|
|
37
|
+
if (!fileExplorerContentContainer)
|
|
38
|
+
return;
|
|
54
39
|
showScrollBackButton = fileExplorerContentContainer.scrollLeft > scrollBackButtonThreshold;
|
|
55
40
|
}
|
|
56
41
|
function handleScrollBack() {
|
|
42
|
+
if (!fileExplorerContentContainer)
|
|
43
|
+
return;
|
|
57
44
|
fileExplorerContentContainer.scroll({
|
|
58
45
|
left: 0,
|
|
59
46
|
behavior: 'smooth',
|
|
@@ -63,10 +50,10 @@ async function handleUploadFile(event) {
|
|
|
63
50
|
// When the uploadFiles function is set, use the default implementation
|
|
64
51
|
if (uploadFiles) {
|
|
65
52
|
// If the user has dropped files, upload them
|
|
66
|
-
if (event.
|
|
53
|
+
if (event.files) {
|
|
67
54
|
await uploadFilesInternal({
|
|
68
|
-
path: event.
|
|
69
|
-
files: event.
|
|
55
|
+
path: event.path,
|
|
56
|
+
files: event.files,
|
|
70
57
|
});
|
|
71
58
|
}
|
|
72
59
|
else {
|
|
@@ -78,20 +65,16 @@ async function handleUploadFile(event) {
|
|
|
78
65
|
input.addEventListener('change', async () => {
|
|
79
66
|
if (input.files) {
|
|
80
67
|
await uploadFilesInternal({
|
|
81
|
-
path: event.
|
|
68
|
+
path: event.path,
|
|
82
69
|
files: input.files,
|
|
83
70
|
});
|
|
84
71
|
}
|
|
85
72
|
});
|
|
86
73
|
}
|
|
87
74
|
}
|
|
88
|
-
else {
|
|
89
|
-
// Otherwise, dispatch an event
|
|
90
|
-
dispatch('upload-file', event.detail);
|
|
91
|
-
}
|
|
92
75
|
}
|
|
93
76
|
async function uploadFilesInternal(request) {
|
|
94
|
-
const filesInDirectory = Array.from(flattenedFiles(
|
|
77
|
+
const filesInDirectory = Array.from(flattenedFiles(documents ?? [])).filter(x => pathsEqual(x.path, request.path));
|
|
95
78
|
const existingFiles = Array.from(request.files).filter(file => filesInDirectory.some(document => document.name === file.name));
|
|
96
79
|
if (existingFiles.length > 0) {
|
|
97
80
|
overrideFiles = existingFiles;
|
|
@@ -100,12 +83,12 @@ async function uploadFilesInternal(request) {
|
|
|
100
83
|
}
|
|
101
84
|
else {
|
|
102
85
|
await uploadFiles(request);
|
|
103
|
-
|
|
86
|
+
refresh();
|
|
104
87
|
}
|
|
105
88
|
}
|
|
106
89
|
async function confirmOverrideFiles() {
|
|
107
90
|
await uploadFiles(uploadFilesRequest);
|
|
108
|
-
|
|
91
|
+
refresh();
|
|
109
92
|
overrideFilesModalOpen = false;
|
|
110
93
|
overrideFiles = [];
|
|
111
94
|
uploadFilesRequest = undefined;
|
|
@@ -117,22 +100,16 @@ async function cancelOverrideFiles() {
|
|
|
117
100
|
}
|
|
118
101
|
function handleCreateDirectory(event) {
|
|
119
102
|
if (createDirectory) {
|
|
120
|
-
createDirectoryPath = event.
|
|
103
|
+
createDirectoryPath = event.path;
|
|
121
104
|
// To avoid closing the modal immediately
|
|
122
105
|
setTimeout(() => createDirectoryModalOpen = true);
|
|
123
106
|
}
|
|
124
|
-
else {
|
|
125
|
-
dispatch('create-directory', event.detail);
|
|
126
|
-
}
|
|
127
107
|
}
|
|
128
108
|
function handleDeleteFile(event) {
|
|
129
109
|
if (deleteFile) {
|
|
130
|
-
deleteFileEvent = event
|
|
110
|
+
deleteFileEvent = event;
|
|
131
111
|
deleteFileModalOpen = true;
|
|
132
112
|
}
|
|
133
|
-
else {
|
|
134
|
-
dispatch('delete-file', event.detail);
|
|
135
|
-
}
|
|
136
113
|
}
|
|
137
114
|
function deleteFileInternal() {
|
|
138
115
|
if (deleteFile && deleteFileEvent) {
|
|
@@ -141,7 +118,7 @@ function deleteFileInternal() {
|
|
|
141
118
|
type: 'file',
|
|
142
119
|
...deleteFileEvent,
|
|
143
120
|
}).then(() => {
|
|
144
|
-
|
|
121
|
+
refresh();
|
|
145
122
|
deleteFileModalOpen = false;
|
|
146
123
|
}).catch((error) => {
|
|
147
124
|
console.error('Failed to delete item.', error);
|
|
@@ -160,6 +137,11 @@ function* flattenedFiles(documents) {
|
|
|
160
137
|
yield* flattenedFiles(document.children);
|
|
161
138
|
}
|
|
162
139
|
}
|
|
140
|
+
// If the route changes, always scroll to the right to show the new column
|
|
141
|
+
$effect(() => {
|
|
142
|
+
if (filePath)
|
|
143
|
+
tick().then(() => scrollToRight());
|
|
144
|
+
});
|
|
163
145
|
</script>
|
|
164
146
|
|
|
165
147
|
<div class="file-explorer file-explorer--display-mode-{displayMode}">
|
|
@@ -167,12 +149,12 @@ function* flattenedFiles(documents) {
|
|
|
167
149
|
<FileExplorerBreadcrumb {filePath} {routePrefix} />
|
|
168
150
|
<FileExplorerDisplayModeSwitcher {translations} bind:displayMode />
|
|
169
151
|
</div>
|
|
170
|
-
{#if
|
|
152
|
+
{#if search}
|
|
171
153
|
<div class="file-explorer__search">
|
|
172
|
-
|
|
154
|
+
{@render search?.()}
|
|
173
155
|
</div>
|
|
174
156
|
{/if}
|
|
175
|
-
{#if
|
|
157
|
+
{#if !documents}
|
|
176
158
|
<div class="file-explorer__loader">
|
|
177
159
|
<Icon class="fa-light fa-spinner-third fa-spin" />
|
|
178
160
|
</div>
|
|
@@ -180,7 +162,7 @@ function* flattenedFiles(documents) {
|
|
|
180
162
|
<div
|
|
181
163
|
bind:this={fileExplorerContentContainer}
|
|
182
164
|
class="file-explorer__content"
|
|
183
|
-
|
|
165
|
+
onscroll={handleScroll}
|
|
184
166
|
>
|
|
185
167
|
<FileExplorerDirectory
|
|
186
168
|
{canEdit}
|
|
@@ -191,13 +173,13 @@ function* flattenedFiles(documents) {
|
|
|
191
173
|
type: 'directory',
|
|
192
174
|
name: '',
|
|
193
175
|
path: '',
|
|
194
|
-
children:
|
|
176
|
+
children: documents,
|
|
195
177
|
}}
|
|
178
|
+
onCreateDirectory={onCreateDirectory ?? handleCreateDirectory}
|
|
179
|
+
onDeleteFile={onDeleteFile ?? handleDeleteFile}
|
|
180
|
+
onUploadFile={onUploadFile ?? handleUploadFile}
|
|
196
181
|
{routePrefix}
|
|
197
182
|
{translations}
|
|
198
|
-
on:create-directory={handleCreateDirectory}
|
|
199
|
-
on:delete-file={handleDeleteFile}
|
|
200
|
-
on:upload-file={handleUploadFile}
|
|
201
183
|
/>
|
|
202
184
|
</div>
|
|
203
185
|
{/if}
|
|
@@ -206,8 +188,8 @@ function* flattenedFiles(documents) {
|
|
|
206
188
|
{#if showScrollBackButton}
|
|
207
189
|
<button
|
|
208
190
|
class="file-explorer__scroll-back-button"
|
|
191
|
+
onclick={handleScrollBack}
|
|
209
192
|
type="button"
|
|
210
|
-
on:click={handleScrollBack}
|
|
211
193
|
transition:fade|local
|
|
212
194
|
>
|
|
213
195
|
<Icon class="fa-light fa-chevron-left" size="large" />
|
|
@@ -215,11 +197,12 @@ function* flattenedFiles(documents) {
|
|
|
215
197
|
{/if}
|
|
216
198
|
</div>
|
|
217
199
|
|
|
218
|
-
{#if createDirectory}
|
|
200
|
+
{#if createDirectory && documents}
|
|
219
201
|
<FileExplorerCreateDirectory
|
|
220
202
|
{createDirectory}
|
|
221
203
|
{createDirectoryPath}
|
|
222
204
|
{documents}
|
|
205
|
+
{refresh}
|
|
223
206
|
{translations}
|
|
224
207
|
bind:createDirectoryModalOpen
|
|
225
208
|
/>
|
|
@@ -236,22 +219,23 @@ function* flattenedFiles(documents) {
|
|
|
236
219
|
<div class="file-explorer__text--semi-bold">
|
|
237
220
|
{filePath.split('/').at(-1)}?
|
|
238
221
|
</div>
|
|
239
|
-
|
|
222
|
+
{#snippet footer()}
|
|
240
223
|
<Button
|
|
241
224
|
color="soft"
|
|
242
225
|
fill="clear"
|
|
243
|
-
|
|
226
|
+
onclick={() => deleteFileModalOpen = false}
|
|
244
227
|
>
|
|
245
228
|
{translations.cancel}
|
|
246
229
|
</Button>
|
|
247
|
-
<Button color="danger"
|
|
230
|
+
<Button color="danger" onclick={deleteFileInternal}>
|
|
248
231
|
{#if deleting}
|
|
249
232
|
{translations.deleting}
|
|
250
233
|
{:else}
|
|
251
234
|
{translations.delete}
|
|
252
235
|
{/if}
|
|
253
236
|
</Button>
|
|
254
|
-
|
|
237
|
+
|
|
238
|
+
{/snippet}
|
|
255
239
|
</Modal>
|
|
256
240
|
{/if}
|
|
257
241
|
|
|
@@ -266,18 +250,18 @@ function* flattenedFiles(documents) {
|
|
|
266
250
|
<div class="file-explorer__text file-explorer__text--semi-bold">
|
|
267
251
|
{overrideFiles.map(file => file.name).join(', ')}
|
|
268
252
|
</div>
|
|
269
|
-
|
|
253
|
+
{#snippet footer()}
|
|
270
254
|
<Button
|
|
271
255
|
color="soft"
|
|
272
256
|
fill="clear"
|
|
273
|
-
|
|
257
|
+
onclick={cancelOverrideFiles}
|
|
274
258
|
>
|
|
275
259
|
{translations.cancel}
|
|
276
260
|
</Button>
|
|
277
|
-
<Button color="danger"
|
|
261
|
+
<Button color="danger" onclick={confirmOverrideFiles}>
|
|
278
262
|
{translations.override}
|
|
279
263
|
</Button>
|
|
280
|
-
|
|
264
|
+
{/snippet}
|
|
281
265
|
</Modal>
|
|
282
266
|
{/if}
|
|
283
267
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
1
|
export interface UploadFileEvent {
|
|
3
2
|
path: string;
|
|
4
3
|
files?: FileList;
|
|
@@ -10,65 +9,24 @@ export interface DeleteFileEvent {
|
|
|
10
9
|
path: string;
|
|
11
10
|
name: string;
|
|
12
11
|
}
|
|
13
|
-
import type
|
|
14
|
-
import
|
|
15
|
-
declare const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
deleteFileConfirmation: string;
|
|
35
|
-
deleting: string;
|
|
36
|
-
directoryAlreadyExists: string;
|
|
37
|
-
displayModeLabels: {
|
|
38
|
-
columns: string;
|
|
39
|
-
index: string;
|
|
40
|
-
};
|
|
41
|
-
displayModeSwitch: string;
|
|
42
|
-
emptyDirectory: string;
|
|
43
|
-
itemTitle: (item: FileSystemItem) => string;
|
|
44
|
-
items: string;
|
|
45
|
-
modifiedAt: string;
|
|
46
|
-
override: string;
|
|
47
|
-
overrideFiles: string;
|
|
48
|
-
overrideFilesConfirmation: string;
|
|
49
|
-
previewFile: string;
|
|
50
|
-
size: string;
|
|
51
|
-
uploadFile: string;
|
|
52
|
-
};
|
|
53
|
-
getFilePreview: (fileItem: FileItem) => Promise<FilePreview>;
|
|
54
|
-
createDirectory?: ((request: CreateDirectoryRequest) => Promise<void>) | undefined;
|
|
55
|
-
uploadFiles?: ((request: UploadFilesRequest) => Promise<void>) | undefined;
|
|
56
|
-
deleteFile?: ((fileItem: FileItem) => Promise<void>) | undefined;
|
|
57
|
-
};
|
|
58
|
-
events: {
|
|
59
|
-
'upload-file': CustomEvent<UploadFileEvent>;
|
|
60
|
-
'create-directory': CustomEvent<CreateDirectoryEvent>;
|
|
61
|
-
'delete-file': CustomEvent<DeleteFileEvent>;
|
|
62
|
-
} & {
|
|
63
|
-
[evt: string]: CustomEvent<any>;
|
|
64
|
-
};
|
|
65
|
-
slots: {
|
|
66
|
-
search: {};
|
|
67
|
-
};
|
|
68
|
-
};
|
|
69
|
-
export type FileExplorerProps = typeof __propDef.props;
|
|
70
|
-
export type FileExplorerEvents = typeof __propDef.events;
|
|
71
|
-
export type FileExplorerSlots = typeof __propDef.slots;
|
|
72
|
-
export default class FileExplorer extends SvelteComponentTyped<FileExplorerProps, FileExplorerEvents, FileExplorerSlots> {
|
|
73
|
-
}
|
|
74
|
-
export {};
|
|
12
|
+
import { type CreateDirectoryRequest, type DocumentTranslations, FileExplorerDisplayMode, type FileItem, type FilePreview, type FileSystemItem, type UploadFilesRequest } from '../index.js';
|
|
13
|
+
import type { Snippet } from 'svelte';
|
|
14
|
+
declare const FileExplorer: import("svelte").Component<{
|
|
15
|
+
displayMode?: FileExplorerDisplayMode;
|
|
16
|
+
filePath: string;
|
|
17
|
+
documents: FileSystemItem[] | undefined;
|
|
18
|
+
refresh: () => void;
|
|
19
|
+
routePrefix: string;
|
|
20
|
+
canEdit: boolean | ((fileItem: FileSystemItem) => boolean);
|
|
21
|
+
translations?: DocumentTranslations;
|
|
22
|
+
getFilePreview: (fileItem: FileItem) => Promise<FilePreview>;
|
|
23
|
+
createDirectory?: (request: CreateDirectoryRequest) => Promise<void>;
|
|
24
|
+
uploadFiles?: (request: UploadFilesRequest) => Promise<void>;
|
|
25
|
+
deleteFile?: (fileItem: FileItem) => Promise<void>;
|
|
26
|
+
search?: Snippet;
|
|
27
|
+
onUploadFile?: (event: UploadFileEvent) => void;
|
|
28
|
+
onCreateDirectory?: (event: CreateDirectoryEvent) => void;
|
|
29
|
+
onDeleteFile?: (event: DeleteFileEvent) => void;
|
|
30
|
+
}, {}, "displayMode">;
|
|
31
|
+
type FileExplorer = ReturnType<typeof FileExplorer>;
|
|
32
|
+
export default FileExplorer;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
<script>import { Icon } from '@securancy/svelte-components';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
$: parts = filePath.split('/');
|
|
1
|
+
<script lang="ts">import { Icon } from '@securancy/svelte-components';
|
|
2
|
+
let { filePath, routePrefix } = $props();
|
|
3
|
+
let parts = $derived(filePath.split('/'));
|
|
5
4
|
function getHref(parts, index, routePrefix) {
|
|
6
5
|
const href = [
|
|
7
6
|
...routePrefix.split('/'),
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
filePath: string;
|
|
5
|
-
routePrefix: string;
|
|
6
|
-
};
|
|
7
|
-
events: {
|
|
8
|
-
[evt: string]: CustomEvent<any>;
|
|
9
|
-
};
|
|
10
|
-
slots: {};
|
|
11
|
-
};
|
|
12
|
-
export type FileExplorerBreadcrumbProps = typeof __propDef.props;
|
|
13
|
-
export type FileExplorerBreadcrumbEvents = typeof __propDef.events;
|
|
14
|
-
export type FileExplorerBreadcrumbSlots = typeof __propDef.slots;
|
|
15
|
-
export default class FileExplorerBreadcrumb extends SvelteComponentTyped<FileExplorerBreadcrumbProps, FileExplorerBreadcrumbEvents, FileExplorerBreadcrumbSlots> {
|
|
1
|
+
interface Properties {
|
|
2
|
+
filePath: string;
|
|
3
|
+
routePrefix: string;
|
|
16
4
|
}
|
|
17
|
-
|
|
5
|
+
declare const FileExplorerBreadcrumb: import("svelte").Component<Properties, {}, "">;
|
|
6
|
+
type FileExplorerBreadcrumb = ReturnType<typeof FileExplorerBreadcrumb>;
|
|
7
|
+
export default FileExplorerBreadcrumb;
|
|
@@ -1,18 +1,8 @@
|
|
|
1
|
-
<script>import { Button, FormElement, Modal } from '@securancy/svelte-components';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export let translations;
|
|
7
|
-
let request = { path: '', name: '' };
|
|
8
|
-
let submitting = false;
|
|
9
|
-
let input = undefined;
|
|
10
|
-
$: existingFoldersInPath = getExistingFoldersInPath(createDirectoryPath, $documents);
|
|
11
|
-
$: directoryAlreadyExists = existingFoldersInPath.some(x => x.name === request.name);
|
|
12
|
-
$: request.path = createDirectoryPath ?? '';
|
|
13
|
-
// Clear inputs when modal is opened
|
|
14
|
-
$: if (input)
|
|
15
|
-
input.focus();
|
|
1
|
+
<script lang="ts">import { Button, FormElement, Modal } from '@securancy/svelte-components';
|
|
2
|
+
let { createDirectoryPath, createDirectoryModalOpen = $bindable(false), documents, createDirectory, translations, refresh, } = $props();
|
|
3
|
+
let request = $state({ path: '', name: '' });
|
|
4
|
+
let submitting = $state(false);
|
|
5
|
+
let input = $state(undefined);
|
|
16
6
|
async function submitFiles() {
|
|
17
7
|
submitting = true;
|
|
18
8
|
await createDirectory(request)
|
|
@@ -21,7 +11,7 @@ async function submitFiles() {
|
|
|
21
11
|
}).finally(() => {
|
|
22
12
|
submitting = false;
|
|
23
13
|
});
|
|
24
|
-
|
|
14
|
+
refresh();
|
|
25
15
|
}
|
|
26
16
|
function getExistingFoldersInPath(path, documents) {
|
|
27
17
|
const pathParts = path ? path.split('/') : [];
|
|
@@ -32,6 +22,13 @@ function getExistingFoldersInPath(path, documents) {
|
|
|
32
22
|
}
|
|
33
23
|
return existingFoldersInPath;
|
|
34
24
|
}
|
|
25
|
+
let existingFoldersInPath = $derived(getExistingFoldersInPath(createDirectoryPath, documents));
|
|
26
|
+
let directoryAlreadyExists = $derived(existingFoldersInPath.some(x => x.name === request.name));
|
|
27
|
+
$effect(() => {
|
|
28
|
+
request.path = createDirectoryPath ?? '';
|
|
29
|
+
});
|
|
30
|
+
// Clear inputs when modal is opened
|
|
31
|
+
$effect(() => (input && input.focus()));
|
|
35
32
|
</script>
|
|
36
33
|
|
|
37
34
|
<Modal
|
|
@@ -54,17 +51,17 @@ function getExistingFoldersInPath(path, documents) {
|
|
|
54
51
|
/>
|
|
55
52
|
</FormElement>
|
|
56
53
|
</div>
|
|
57
|
-
|
|
54
|
+
{#snippet footer()}
|
|
58
55
|
<Button
|
|
59
56
|
color="soft"
|
|
60
57
|
fill="clear"
|
|
61
|
-
|
|
58
|
+
onclick={() => createDirectoryModalOpen = false}
|
|
62
59
|
>
|
|
63
60
|
{translations.cancel}
|
|
64
61
|
</Button>
|
|
65
62
|
<Button
|
|
66
63
|
disabled={(!request.name || request.name.length === 0) || directoryAlreadyExists || submitting}
|
|
67
|
-
|
|
64
|
+
onclick={submitFiles}
|
|
68
65
|
>
|
|
69
66
|
{#if submitting}
|
|
70
67
|
{translations.creating}
|
|
@@ -72,7 +69,8 @@ function getExistingFoldersInPath(path, documents) {
|
|
|
72
69
|
{translations.create}
|
|
73
70
|
{/if}
|
|
74
71
|
</Button>
|
|
75
|
-
|
|
72
|
+
|
|
73
|
+
{/snippet}
|
|
76
74
|
</Modal>
|
|
77
75
|
|
|
78
76
|
<style>
|
|
@@ -1,22 +1,11 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
|
-
import type { Refreshable } from '@securancy/svelte-utilities';
|
|
3
1
|
import type { CreateDirectoryRequest, DocumentTranslations, FileSystemItem } from '../models/index.js';
|
|
4
|
-
declare const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
};
|
|
15
|
-
slots: {};
|
|
16
|
-
};
|
|
17
|
-
export type FileExplorerCreateDirectoryProps = typeof __propDef.props;
|
|
18
|
-
export type FileExplorerCreateDirectoryEvents = typeof __propDef.events;
|
|
19
|
-
export type FileExplorerCreateDirectorySlots = typeof __propDef.slots;
|
|
20
|
-
export default class FileExplorerCreateDirectory extends SvelteComponentTyped<FileExplorerCreateDirectoryProps, FileExplorerCreateDirectoryEvents, FileExplorerCreateDirectorySlots> {
|
|
21
|
-
}
|
|
22
|
-
export {};
|
|
2
|
+
declare const FileExplorerCreateDirectory: import("svelte").Component<{
|
|
3
|
+
createDirectoryPath: string | undefined;
|
|
4
|
+
createDirectoryModalOpen?: boolean;
|
|
5
|
+
documents: FileSystemItem[];
|
|
6
|
+
createDirectory: (request: CreateDirectoryRequest) => Promise<void>;
|
|
7
|
+
translations: DocumentTranslations;
|
|
8
|
+
refresh: () => void;
|
|
9
|
+
}, {}, "createDirectoryModalOpen">;
|
|
10
|
+
type FileExplorerCreateDirectory = ReturnType<typeof FileExplorerCreateDirectory>;
|
|
11
|
+
export default FileExplorerCreateDirectory;
|
|
@@ -1,71 +1,53 @@
|
|
|
1
|
-
<script>import
|
|
1
|
+
<script lang="ts">import FileExplorerDirectory from './FileExplorerDirectory.svelte';
|
|
2
|
+
import {} from '..';
|
|
2
3
|
import FileExplorerDirectoryColumn from './FileExplorerDirectoryColumn.svelte';
|
|
3
4
|
import FileExplorerFileDetailColumn from './FileExplorerFileDetailColumn.svelte';
|
|
4
5
|
import FileExplorerDirectoryIndex from './FileExplorerDirectoryIndex.svelte';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export let canEdit;
|
|
10
|
-
export let displayMode;
|
|
11
|
-
export let getFilePreview;
|
|
12
|
-
$: currentPathParts = currentPath.split('/');
|
|
13
|
-
$: activeFileItem = item.children.find((fileItem) => {
|
|
6
|
+
import '../file-explorer.pcss';
|
|
7
|
+
let { currentPath, item, canEdit, ...properties } = $props();
|
|
8
|
+
let currentPathParts = $derived(currentPath.split('/'));
|
|
9
|
+
let activeFileItem = $derived(item.children.find((fileItem) => {
|
|
14
10
|
const parts = [
|
|
15
11
|
...fileItem.path.split('/').filter(part => part !== ''),
|
|
16
12
|
fileItem.name,
|
|
17
13
|
];
|
|
18
14
|
return parts.every((part, index) => currentPathParts[index] === part);
|
|
19
|
-
});
|
|
15
|
+
}));
|
|
20
16
|
function canEditItem(item, canEdit) {
|
|
21
17
|
return typeof canEdit === 'function' ? canEdit(item) : canEdit === true;
|
|
22
18
|
}
|
|
23
19
|
</script>
|
|
24
20
|
|
|
25
|
-
{#if displayMode === 'columns'}
|
|
21
|
+
{#if properties.displayMode === 'columns'}
|
|
26
22
|
<FileExplorerDirectoryColumn
|
|
23
|
+
{...properties}
|
|
27
24
|
{activeFileItem}
|
|
28
25
|
canEdit={canEditItem(item, canEdit)}
|
|
29
26
|
{item}
|
|
30
|
-
{routePrefix}
|
|
31
|
-
{translations}
|
|
32
|
-
on:upload-file
|
|
33
|
-
on:create-directory
|
|
34
27
|
/>
|
|
35
28
|
{:else}
|
|
36
29
|
<FileExplorerDirectoryIndex
|
|
30
|
+
{...properties}
|
|
37
31
|
{activeFileItem}
|
|
38
32
|
canEdit={canEditItem(item, canEdit)}
|
|
39
33
|
{item}
|
|
40
|
-
{routePrefix}
|
|
41
|
-
{translations}
|
|
42
|
-
on:upload-file
|
|
43
|
-
on:create-directory
|
|
44
34
|
/>
|
|
45
35
|
{/if}
|
|
46
36
|
|
|
47
37
|
<!-- The component repeats itself until there is no selected item or it reaches a fileItem -->
|
|
48
38
|
{#if activeFileItem}
|
|
49
39
|
{#if activeFileItem.type === 'directory'}
|
|
50
|
-
<
|
|
40
|
+
<FileExplorerDirectory
|
|
41
|
+
{...properties}
|
|
51
42
|
{canEdit}
|
|
52
43
|
{currentPath}
|
|
53
|
-
{displayMode}
|
|
54
|
-
{getFilePreview}
|
|
55
44
|
item={activeFileItem}
|
|
56
|
-
{routePrefix}
|
|
57
|
-
{translations}
|
|
58
|
-
on:upload-file
|
|
59
|
-
on:create-directory
|
|
60
|
-
on:delete-file
|
|
61
45
|
/>
|
|
62
46
|
{:else}
|
|
63
47
|
<FileExplorerFileDetailColumn
|
|
48
|
+
{...properties}
|
|
64
49
|
canEdit={canEditItem(activeFileItem, canEdit)}
|
|
65
50
|
fileItem={activeFileItem}
|
|
66
|
-
{getFilePreview}
|
|
67
|
-
{translations}
|
|
68
|
-
on:delete-file
|
|
69
51
|
/>
|
|
70
52
|
{/if}
|
|
71
53
|
{/if}
|
|
@@ -1,28 +1,18 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { FileExplorerDisplayMode, FileSystemItem } from '..';
|
|
1
|
+
import FileExplorerDirectory from './FileExplorerDirectory.svelte';
|
|
2
|
+
import type { CreateDirectoryEvent, DeleteFileEvent, FileExplorerDisplayMode, FileSystemItem, UploadFileEvent } from '..';
|
|
3
3
|
import { type DirectoryItem, type DocumentTranslations, type FileItem, type FilePreview } from '..';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
[evt: string]: CustomEvent<any>;
|
|
20
|
-
};
|
|
21
|
-
slots: {};
|
|
22
|
-
};
|
|
23
|
-
export type FileExplorerDirectoryProps = typeof __propDef.props;
|
|
24
|
-
export type FileExplorerDirectoryEvents = typeof __propDef.events;
|
|
25
|
-
export type FileExplorerDirectorySlots = typeof __propDef.slots;
|
|
26
|
-
export default class FileExplorerDirectory extends SvelteComponentTyped<FileExplorerDirectoryProps, FileExplorerDirectoryEvents, FileExplorerDirectorySlots> {
|
|
27
|
-
}
|
|
28
|
-
export {};
|
|
4
|
+
import '../file-explorer.pcss';
|
|
5
|
+
declare const FileExplorerDirectory: import("svelte").Component<{
|
|
6
|
+
item: DirectoryItem;
|
|
7
|
+
translations: DocumentTranslations;
|
|
8
|
+
routePrefix: string;
|
|
9
|
+
currentPath: string;
|
|
10
|
+
canEdit: boolean | ((fileItem: FileSystemItem) => boolean);
|
|
11
|
+
displayMode: FileExplorerDisplayMode;
|
|
12
|
+
getFilePreview: (fileItem: FileItem) => Promise<FilePreview>;
|
|
13
|
+
onUploadFile: (event: UploadFileEvent) => void;
|
|
14
|
+
onCreateDirectory: (event: CreateDirectoryEvent) => void;
|
|
15
|
+
onDeleteFile: (event: DeleteFileEvent) => void;
|
|
16
|
+
}, {}, "">;
|
|
17
|
+
type FileExplorerDirectory = ReturnType<typeof FileExplorerDirectory>;
|
|
18
|
+
export default FileExplorerDirectory;
|
|
@@ -1,24 +1,17 @@
|
|
|
1
|
-
<script>import {
|
|
2
|
-
import {} from '..';
|
|
1
|
+
<script lang="ts">import {} from '..';
|
|
3
2
|
import { resize, ResizeDirections } from '@securancy/svelte-utilities';
|
|
4
3
|
import { Icon, Popover, PopoverItem } from '@securancy/svelte-components';
|
|
5
4
|
import { getExtension, getItemHref } from '../utilities/index.js';
|
|
6
5
|
import FileIcon from './FileIcon.svelte';
|
|
7
6
|
import { joinPaths } from '../utilities/index.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export let routePrefix;
|
|
12
|
-
export let canEdit;
|
|
13
|
-
export let translations;
|
|
14
|
-
export let activeFileItem;
|
|
15
|
-
let dragoverIndex = 0; // Incremented/decremented when entering/leaving a child element of the column
|
|
16
|
-
let innerWidth = 0;
|
|
7
|
+
let { item, sticky = false, routePrefix, canEdit, translations, activeFileItem, onUploadFile, onCreateDirectory, } = $props();
|
|
8
|
+
let dragoverIndex = $state(0); // Incremented/decremented when entering/leaving a child element of the column
|
|
9
|
+
let innerWidth = $state(0);
|
|
17
10
|
function addItem() {
|
|
18
|
-
|
|
11
|
+
onUploadFile({ path: joinPaths(item.path, item.name) });
|
|
19
12
|
}
|
|
20
13
|
function createDirectory() {
|
|
21
|
-
|
|
14
|
+
onCreateDirectory({ path: joinPaths(item.path, item.name) });
|
|
22
15
|
}
|
|
23
16
|
function handleDragEnter(event) {
|
|
24
17
|
event.preventDefault();
|
|
@@ -33,7 +26,7 @@ function handleDrop(event) {
|
|
|
33
26
|
if (event.dataTransfer?.files && event.dataTransfer.files.length > 0) {
|
|
34
27
|
eventData.files = event.dataTransfer.files;
|
|
35
28
|
}
|
|
36
|
-
|
|
29
|
+
onUploadFile(eventData);
|
|
37
30
|
}
|
|
38
31
|
function handleDragLeave(event) {
|
|
39
32
|
event.preventDefault();
|
|
@@ -54,16 +47,16 @@ function handleDragOver(event) {
|
|
|
54
47
|
<svelte:window bind:innerWidth />
|
|
55
48
|
|
|
56
49
|
<!-- ignored because users with assistive tech have an option to upload using the button -->
|
|
57
|
-
<!-- svelte-ignore
|
|
50
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
58
51
|
<div
|
|
59
52
|
class="file-explorer__column"
|
|
60
53
|
class:file-explorer__column--dragover={dragoverIndex > 0}
|
|
61
54
|
class:file-explorer__column--sticky={sticky}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
ondragend={handleDragEnd}
|
|
56
|
+
ondragenter={handleDragEnter}
|
|
57
|
+
ondragleave={handleDragLeave}
|
|
58
|
+
ondragover={handleDragOver}
|
|
59
|
+
ondrop={handleDrop}
|
|
67
60
|
use:resize={{
|
|
68
61
|
disabled: innerWidth < 1024,
|
|
69
62
|
directions: [ResizeDirections.East],
|
|
@@ -78,12 +71,14 @@ function handleDragOver(event) {
|
|
|
78
71
|
{item.name === '' ? translations.items : item.name} ({item.children.length})
|
|
79
72
|
</span>
|
|
80
73
|
{#if canEdit}
|
|
81
|
-
<Popover placement="bottom-end"
|
|
82
|
-
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
74
|
+
<Popover placement="bottom-end" triggerOn="click">
|
|
75
|
+
{#snippet trigger()}
|
|
76
|
+
<button title={translations.createItemTitle} type="button">
|
|
77
|
+
<Icon class="fa-solid fa-add" />
|
|
78
|
+
</button>
|
|
79
|
+
{/snippet}
|
|
80
|
+
<PopoverItem closeOnClick onclick={createDirectory}>{translations.createDirectory}</PopoverItem>
|
|
81
|
+
<PopoverItem closeOnClick onclick={addItem}>{translations.uploadFile}</PopoverItem>
|
|
87
82
|
</Popover>
|
|
88
83
|
{/if}
|
|
89
84
|
</div>
|
|
@@ -1,28 +1,16 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
1
|
import type { UploadFileEvent } from './FileExplorer.svelte';
|
|
3
2
|
import { type DirectoryItem, type DocumentTranslations, type FileSystemItem } from '..';
|
|
4
3
|
import type { CreateDirectoryEvent } from './FileExplorer.svelte';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
events: {
|
|
15
|
-
'scroll-back': CustomEvent<undefined>;
|
|
16
|
-
'upload-file': CustomEvent<UploadFileEvent>;
|
|
17
|
-
'create-directory': CustomEvent<CreateDirectoryEvent>;
|
|
18
|
-
} & {
|
|
19
|
-
[evt: string]: CustomEvent<any>;
|
|
20
|
-
};
|
|
21
|
-
slots: {};
|
|
22
|
-
};
|
|
23
|
-
export type FileExplorerDirectoryColumnProps = typeof __propDef.props;
|
|
24
|
-
export type FileExplorerDirectoryColumnEvents = typeof __propDef.events;
|
|
25
|
-
export type FileExplorerDirectoryColumnSlots = typeof __propDef.slots;
|
|
26
|
-
export default class FileExplorerDirectoryColumn extends SvelteComponentTyped<FileExplorerDirectoryColumnProps, FileExplorerDirectoryColumnEvents, FileExplorerDirectoryColumnSlots> {
|
|
4
|
+
interface Properties {
|
|
5
|
+
item: DirectoryItem;
|
|
6
|
+
sticky?: boolean;
|
|
7
|
+
routePrefix: string;
|
|
8
|
+
canEdit: boolean;
|
|
9
|
+
translations: DocumentTranslations;
|
|
10
|
+
activeFileItem: FileSystemItem | undefined;
|
|
11
|
+
onUploadFile: (event: UploadFileEvent) => void;
|
|
12
|
+
onCreateDirectory: (event: CreateDirectoryEvent) => void;
|
|
27
13
|
}
|
|
28
|
-
|
|
14
|
+
declare const FileExplorerDirectoryColumn: import("svelte").Component<Properties, {}, "">;
|
|
15
|
+
type FileExplorerDirectoryColumn = ReturnType<typeof FileExplorerDirectoryColumn>;
|
|
16
|
+
export default FileExplorerDirectoryColumn;
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
<script>import FileIcon from './FileIcon.svelte';
|
|
2
|
-
import { createEventDispatcher } from 'svelte';
|
|
1
|
+
<script lang="ts">import FileIcon from './FileIcon.svelte';
|
|
3
2
|
import { resize, ResizeDirections } from '@securancy/svelte-utilities';
|
|
4
3
|
import { Icon, Popover, PopoverItem } from '@securancy/svelte-components';
|
|
5
4
|
import { getExtension, getItemHref, joinPaths } from '../utilities/index.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
export let routePrefix;
|
|
9
|
-
export let translations;
|
|
10
|
-
export let canEdit;
|
|
11
|
-
export let activeFileItem;
|
|
12
|
-
let innerWidth = 0;
|
|
5
|
+
let { item, routePrefix, translations, canEdit, activeFileItem, onUploadFile, onCreateDirectory, } = $props();
|
|
6
|
+
let innerWidth = $state(0);
|
|
13
7
|
function addItem() {
|
|
14
|
-
|
|
8
|
+
onUploadFile({ path: joinPaths(item.path, item.name) });
|
|
15
9
|
}
|
|
16
10
|
function createDirectory() {
|
|
17
|
-
|
|
11
|
+
onCreateDirectory({ path: joinPaths(item.path, item.name) });
|
|
18
12
|
}
|
|
19
13
|
</script>
|
|
20
14
|
|
|
@@ -37,12 +31,14 @@ function createDirectory() {
|
|
|
37
31
|
</span>
|
|
38
32
|
{#if canEdit}
|
|
39
33
|
<div class="inline-block">
|
|
40
|
-
<Popover placement="bottom-end"
|
|
41
|
-
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
<Popover placement="bottom-end" triggerOn="click">
|
|
35
|
+
{#snippet trigger()}
|
|
36
|
+
<button title={translations.createItemTitle} type="button">
|
|
37
|
+
<Icon class="fa-solid fa-add" />
|
|
38
|
+
</button>
|
|
39
|
+
{/snippet}
|
|
40
|
+
<PopoverItem closeOnClick onclick={createDirectory}>{translations.createDirectory}</PopoverItem>
|
|
41
|
+
<PopoverItem closeOnClick onclick={addItem}>{translations.uploadFile}</PopoverItem>
|
|
46
42
|
</Popover>
|
|
47
43
|
</div>
|
|
48
44
|
{/if}
|
|
@@ -1,25 +1,14 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
1
|
import type { DirectoryItem, DocumentTranslations, FileSystemItem } from '../index.js';
|
|
3
2
|
import type { CreateDirectoryEvent, UploadFileEvent } from './FileExplorer.svelte';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
events: {
|
|
13
|
-
'upload-file': CustomEvent<UploadFileEvent>;
|
|
14
|
-
'create-directory': CustomEvent<CreateDirectoryEvent>;
|
|
15
|
-
} & {
|
|
16
|
-
[evt: string]: CustomEvent<any>;
|
|
17
|
-
};
|
|
18
|
-
slots: {};
|
|
19
|
-
};
|
|
20
|
-
export type FileExplorerDirectoryIndexProps = typeof __propDef.props;
|
|
21
|
-
export type FileExplorerDirectoryIndexEvents = typeof __propDef.events;
|
|
22
|
-
export type FileExplorerDirectoryIndexSlots = typeof __propDef.slots;
|
|
23
|
-
export default class FileExplorerDirectoryIndex extends SvelteComponentTyped<FileExplorerDirectoryIndexProps, FileExplorerDirectoryIndexEvents, FileExplorerDirectoryIndexSlots> {
|
|
3
|
+
interface Properties {
|
|
4
|
+
item: DirectoryItem;
|
|
5
|
+
routePrefix: string;
|
|
6
|
+
translations: DocumentTranslations;
|
|
7
|
+
canEdit: boolean;
|
|
8
|
+
activeFileItem: FileSystemItem | undefined;
|
|
9
|
+
onUploadFile: (event: UploadFileEvent) => void;
|
|
10
|
+
onCreateDirectory: (event: CreateDirectoryEvent) => void;
|
|
24
11
|
}
|
|
25
|
-
|
|
12
|
+
declare const FileExplorerDirectoryIndex: import("svelte").Component<Properties, {}, "">;
|
|
13
|
+
type FileExplorerDirectoryIndex = ReturnType<typeof FileExplorerDirectoryIndex>;
|
|
14
|
+
export default FileExplorerDirectoryIndex;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
<script>import { FileExplorerDisplayMode } from '../index.js';
|
|
1
|
+
<script lang="ts">import { FileExplorerDisplayMode } from '../index.js';
|
|
2
2
|
import { Icon } from '@securancy/svelte-components';
|
|
3
|
-
|
|
4
|
-
export let translations;
|
|
3
|
+
let { displayMode = $bindable(), translations } = $props();
|
|
5
4
|
let modes = Object.values(FileExplorerDisplayMode);
|
|
6
5
|
const modeIcons = {
|
|
7
6
|
columns: 'fa-columns-3',
|
|
@@ -1,18 +1,8 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
1
|
import { type DocumentTranslations, FileExplorerDisplayMode } from '../index.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
translations: DocumentTranslations;
|
|
7
|
-
};
|
|
8
|
-
events: {
|
|
9
|
-
[evt: string]: CustomEvent<any>;
|
|
10
|
-
};
|
|
11
|
-
slots: {};
|
|
12
|
-
};
|
|
13
|
-
export type FileExplorerDisplayModeSwitcherProps = typeof __propDef.props;
|
|
14
|
-
export type FileExplorerDisplayModeSwitcherEvents = typeof __propDef.events;
|
|
15
|
-
export type FileExplorerDisplayModeSwitcherSlots = typeof __propDef.slots;
|
|
16
|
-
export default class FileExplorerDisplayModeSwitcher extends SvelteComponentTyped<FileExplorerDisplayModeSwitcherProps, FileExplorerDisplayModeSwitcherEvents, FileExplorerDisplayModeSwitcherSlots> {
|
|
2
|
+
interface Properties {
|
|
3
|
+
displayMode: FileExplorerDisplayMode;
|
|
4
|
+
translations: DocumentTranslations;
|
|
17
5
|
}
|
|
18
|
-
|
|
6
|
+
declare const FileExplorerDisplayModeSwitcher: import("svelte").Component<Properties, {}, "displayMode">;
|
|
7
|
+
type FileExplorerDisplayModeSwitcher = ReturnType<typeof FileExplorerDisplayModeSwitcher>;
|
|
8
|
+
export default FileExplorerDisplayModeSwitcher;
|
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
<script>import { Card, Icon } from '@securancy/svelte-components';
|
|
1
|
+
<script lang="ts">import { Card, Icon } from '@securancy/svelte-components';
|
|
2
2
|
import FileIcon from './FileIcon.svelte';
|
|
3
3
|
import { resize, ResizeDirections } from '@securancy/svelte-utilities';
|
|
4
4
|
import { formatBytes, getExtension, isImage } from '../utilities/index.js';
|
|
5
5
|
import { DateTime } from 'luxon';
|
|
6
|
-
|
|
7
|
-
export let fileItem;
|
|
8
|
-
export let getFilePreview;
|
|
9
|
-
export let translations;
|
|
10
|
-
export let canEdit;
|
|
11
|
-
const dispatch = createEventDispatcher();
|
|
6
|
+
let { fileItem, getFilePreview, translations, canEdit, onDeleteFile, } = $props();
|
|
12
7
|
const fileDateFormat = 'cccc FF';
|
|
13
|
-
let filePreview;
|
|
14
|
-
let extension;
|
|
15
|
-
$: refresh(fileItem);
|
|
8
|
+
let filePreview = $state();
|
|
9
|
+
let extension = $state('');
|
|
16
10
|
async function refresh(_fileItem) {
|
|
17
11
|
filePreview = await getFilePreview(_fileItem)
|
|
18
12
|
.catch((error) => {
|
|
@@ -21,6 +15,9 @@ async function refresh(_fileItem) {
|
|
|
21
15
|
});
|
|
22
16
|
extension = getExtension(_fileItem.name);
|
|
23
17
|
}
|
|
18
|
+
$effect(() => {
|
|
19
|
+
refresh(fileItem);
|
|
20
|
+
});
|
|
24
21
|
</script>
|
|
25
22
|
|
|
26
23
|
<div
|
|
@@ -75,7 +72,7 @@ async function refresh(_fileItem) {
|
|
|
75
72
|
{/if}
|
|
76
73
|
{#if canEdit}
|
|
77
74
|
<div class="file-explorer-preview__info">
|
|
78
|
-
<button id="file-explorer-delete-file"
|
|
75
|
+
<button id="file-explorer-delete-file" onclick={() => onDeleteFile(fileItem)} type="button">
|
|
79
76
|
<Icon class="fa-solid fa-trash" />
|
|
80
77
|
</button>
|
|
81
78
|
</div>
|
|
@@ -1,23 +1,11 @@
|
|
|
1
|
-
import { SvelteComponentTyped } from "svelte";
|
|
2
1
|
import type { DocumentTranslations, FileItem, FilePreview } from '..';
|
|
3
2
|
import type { DeleteFileEvent } from './FileExplorer.svelte';
|
|
4
|
-
declare const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} & {
|
|
14
|
-
[evt: string]: CustomEvent<any>;
|
|
15
|
-
};
|
|
16
|
-
slots: {};
|
|
17
|
-
};
|
|
18
|
-
export type FileExplorerFileDetailColumnProps = typeof __propDef.props;
|
|
19
|
-
export type FileExplorerFileDetailColumnEvents = typeof __propDef.events;
|
|
20
|
-
export type FileExplorerFileDetailColumnSlots = typeof __propDef.slots;
|
|
21
|
-
export default class FileExplorerFileDetailColumn extends SvelteComponentTyped<FileExplorerFileDetailColumnProps, FileExplorerFileDetailColumnEvents, FileExplorerFileDetailColumnSlots> {
|
|
22
|
-
}
|
|
23
|
-
export {};
|
|
3
|
+
declare const FileExplorerFileDetailColumn: import("svelte").Component<{
|
|
4
|
+
fileItem: FileItem;
|
|
5
|
+
getFilePreview: (fileItem: FileItem) => Promise<FilePreview>;
|
|
6
|
+
translations: DocumentTranslations;
|
|
7
|
+
canEdit: boolean;
|
|
8
|
+
onDeleteFile: (event: DeleteFileEvent) => void;
|
|
9
|
+
}, {}, "">;
|
|
10
|
+
type FileExplorerFileDetailColumn = ReturnType<typeof FileExplorerFileDetailColumn>;
|
|
11
|
+
export default FileExplorerFileDetailColumn;
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
<script>import { Icon } from '@securancy/svelte-components';
|
|
1
|
+
<script lang="ts">import { Icon } from '@securancy/svelte-components';
|
|
2
2
|
import { imageExtensions, videoExtensions } from '../utilities/index.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
let iconClass;
|
|
6
|
-
$: iconClass = determineIconString(extension);
|
|
3
|
+
let { extension, size = 'default' } = $props();
|
|
4
|
+
let iconClass = $derived(determineIconString(extension));
|
|
7
5
|
function determineIconString(_extension) {
|
|
8
6
|
if (imageExtensions.includes(_extension))
|
|
9
7
|
return 'fa-file-image';
|
|
@@ -1,17 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
extension: string;
|
|
5
|
-
size?: "default" | "large" | "grid";
|
|
6
|
-
};
|
|
7
|
-
events: {
|
|
8
|
-
[evt: string]: CustomEvent<any>;
|
|
9
|
-
};
|
|
10
|
-
slots: {};
|
|
11
|
-
};
|
|
12
|
-
export type FileIconProps = typeof __propDef.props;
|
|
13
|
-
export type FileIconEvents = typeof __propDef.events;
|
|
14
|
-
export type FileIconSlots = typeof __propDef.slots;
|
|
15
|
-
export default class FileIcon extends SvelteComponentTyped<FileIconProps, FileIconEvents, FileIconSlots> {
|
|
1
|
+
interface Properties {
|
|
2
|
+
extension: string;
|
|
3
|
+
size?: 'default' | 'large' | 'grid';
|
|
16
4
|
}
|
|
17
|
-
|
|
5
|
+
declare const FileIcon: import("svelte").Component<Properties, {}, "">;
|
|
6
|
+
type FileIcon = ReturnType<typeof FileIcon>;
|
|
7
|
+
export default FileIcon;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@securancy/file-explorer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"private": false,
|
|
6
6
|
"svelte": "./dist/index.js",
|
|
@@ -18,33 +18,36 @@
|
|
|
18
18
|
"!dist/**/*.test.*",
|
|
19
19
|
"!dist/**/*.spec.*"
|
|
20
20
|
],
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"svelte": "^5.0.0"
|
|
23
|
+
},
|
|
21
24
|
"devDependencies": {
|
|
22
|
-
"@faker-js/faker": "^9.0
|
|
23
|
-
"@sveltejs/adapter-auto": "^3.
|
|
24
|
-
"@sveltejs/kit": "^2.
|
|
25
|
-
"@sveltejs/package": "^2.3.
|
|
26
|
-
"@sveltejs/vite-plugin-svelte": "^
|
|
25
|
+
"@faker-js/faker": "^9.3.0",
|
|
26
|
+
"@sveltejs/adapter-auto": "^3.3.1",
|
|
27
|
+
"@sveltejs/kit": "^2.15.2",
|
|
28
|
+
"@sveltejs/package": "^2.3.7",
|
|
29
|
+
"@sveltejs/vite-plugin-svelte": "^4.0.4",
|
|
27
30
|
"@types/luxon": "^3.4.2",
|
|
28
31
|
"autoprefixer": "^10.4.20",
|
|
29
32
|
"luxon": "^3.5.0",
|
|
30
|
-
"postcss": "^8.4.
|
|
31
|
-
"postcss-custom-media": "^11.0.
|
|
33
|
+
"postcss": "^8.4.49",
|
|
34
|
+
"postcss-custom-media": "^11.0.5",
|
|
32
35
|
"postcss-each": "^1.1.0",
|
|
33
36
|
"postcss-easy-import": "^4.0.0",
|
|
34
37
|
"postcss-extend": "^1.0.5",
|
|
35
38
|
"postcss-for": "^2.1.1",
|
|
36
39
|
"postcss-mixins": "^11.0.3",
|
|
37
|
-
"postcss-nested": "^
|
|
40
|
+
"postcss-nested": "^7.0.2",
|
|
38
41
|
"postcss-nested-ancestors": "^3.0.0",
|
|
39
|
-
"publint": "^0.
|
|
40
|
-
"svelte": "^
|
|
41
|
-
"svelte-check": "^4.
|
|
42
|
+
"publint": "^0.3.0",
|
|
43
|
+
"svelte": "^5.16.6",
|
|
44
|
+
"svelte-check": "^4.1.1",
|
|
42
45
|
"svelte-preprocess": "^6.0.3",
|
|
43
46
|
"the-new-css-reset": "^1.11.3",
|
|
44
|
-
"typescript": "^5.
|
|
45
|
-
"vite": "^5.4.
|
|
46
|
-
"@securancy/svelte-components": "
|
|
47
|
-
"@securancy/svelte-utilities": "2.
|
|
47
|
+
"typescript": "^5.7.2",
|
|
48
|
+
"vite": "^5.4.11",
|
|
49
|
+
"@securancy/svelte-components": "5.0.0",
|
|
50
|
+
"@securancy/svelte-utilities": "2.3.0"
|
|
48
51
|
},
|
|
49
52
|
"scripts": {
|
|
50
53
|
"dev": "vite dev",
|
|
@@ -54,6 +57,6 @@
|
|
|
54
57
|
"preview": "vite preview",
|
|
55
58
|
"package": "svelte-package && publint",
|
|
56
59
|
"package-watch": "svelte-package -w",
|
|
57
|
-
"svelte-check": "svelte-check --fail-on-warnings --compiler-warnings \"
|
|
60
|
+
"svelte-check": "svelte-check --fail-on-warnings --compiler-warnings \"css_unused_selector:ignore\""
|
|
58
61
|
}
|
|
59
62
|
}
|