@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.
@@ -1,7 +1,7 @@
1
- <script context="module">export {};
1
+ <script lang="ts" module>export {};
2
2
  </script>
3
3
 
4
- <script>import { createEventDispatcher, tick } from 'svelte';
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
- export let displayMode = FileExplorerDisplayMode.Columns;
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.detail.files) {
53
+ if (event.files) {
67
54
  await uploadFilesInternal({
68
- path: event.detail.path,
69
- files: event.detail.files,
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.detail.path,
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($documents)).filter(x => pathsEqual(x.path, request.path));
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
- documents.refresh();
86
+ refresh();
104
87
  }
105
88
  }
106
89
  async function confirmOverrideFiles() {
107
90
  await uploadFiles(uploadFilesRequest);
108
- documents.refresh();
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.detail.path;
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.detail;
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
- documents.refresh();
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 $$slots.search}
152
+ {#if search}
171
153
  <div class="file-explorer__search">
172
- <slot name="search" />
154
+ {@render search?.()}
173
155
  </div>
174
156
  {/if}
175
- {#if loading}
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
- on:scroll={handleScroll}
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: $documents,
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
- <svelte:fragment slot="footer">
222
+ {#snippet footer()}
240
223
  <Button
241
224
  color="soft"
242
225
  fill="clear"
243
- on:click={() => deleteFileModalOpen = false}
226
+ onclick={() => deleteFileModalOpen = false}
244
227
  >
245
228
  {translations.cancel}
246
229
  </Button>
247
- <Button color="danger" on:click={deleteFileInternal}>
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
- </svelte:fragment>
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
- <svelte:fragment slot="footer">
253
+ {#snippet footer()}
270
254
  <Button
271
255
  color="soft"
272
256
  fill="clear"
273
- on:click={cancelOverrideFiles}
257
+ onclick={cancelOverrideFiles}
274
258
  >
275
259
  {translations.cancel}
276
260
  </Button>
277
- <Button color="danger" on:click={confirmOverrideFiles}>
261
+ <Button color="danger" onclick={confirmOverrideFiles}>
278
262
  {translations.override}
279
263
  </Button>
280
- </svelte:fragment>
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 { Refreshable } from '@securancy/svelte-utilities';
14
- import { type CreateDirectoryRequest, FileExplorerDisplayMode, type FileItem, type FilePreview, type FileSystemItem, type UploadFilesRequest } from '../index.js';
15
- declare const __propDef: {
16
- props: {
17
- displayMode?: FileExplorerDisplayMode;
18
- filePath: string;
19
- documents: Refreshable<FileSystemItem[]>;
20
- loading: boolean;
21
- routePrefix: string;
22
- canEdit: boolean | ((fileItem: FileSystemItem) => boolean);
23
- translations?: {
24
- cancel: string;
25
- create: string;
26
- createDirectory: string;
27
- createDirectoryModalTitle: string;
28
- createDirectoryPlaceholder: string;
29
- createItemTitle: string;
30
- createdAt: string;
31
- creating: string;
32
- delete: string;
33
- deleteFile: string;
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
- export let filePath;
3
- export let routePrefix;
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
- import { SvelteComponentTyped } from "svelte";
2
- declare const __propDef: {
3
- props: {
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
- export {};
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
- export let createDirectoryPath;
3
- export let createDirectoryModalOpen = false;
4
- export let documents;
5
- export let createDirectory;
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
- documents.refresh();
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
- <svelte:fragment slot="footer">
54
+ {#snippet footer()}
58
55
  <Button
59
56
  color="soft"
60
57
  fill="clear"
61
- on:click={() => createDirectoryModalOpen = false}
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
- on:click={submitFiles}
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
- </svelte:fragment>
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 __propDef: {
5
- props: {
6
- createDirectoryPath: string | undefined;
7
- createDirectoryModalOpen?: boolean;
8
- documents: Refreshable<FileSystemItem[]>;
9
- createDirectory: (request: CreateDirectoryRequest) => Promise<void>;
10
- translations: DocumentTranslations;
11
- };
12
- events: {
13
- [evt: string]: CustomEvent<any>;
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 {} from '..';
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
- export let item;
6
- export let translations;
7
- export let routePrefix;
8
- export let currentPath;
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
- <svelte:self
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 { SvelteComponentTyped } from "svelte";
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
- declare const __propDef: {
5
- props: {
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
- };
14
- events: {
15
- 'upload-file': CustomEvent<import("..").UploadFileEvent>;
16
- 'create-directory': CustomEvent<import("..").CreateDirectoryEvent>;
17
- 'delete-file': CustomEvent<import("..").DeleteFileEvent>;
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 { createEventDispatcher } from 'svelte';
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
- const dispatch = createEventDispatcher();
9
- export let item;
10
- export let sticky = false;
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
- dispatch('upload-file', { path: joinPaths(item.path, item.name) });
11
+ onUploadFile({ path: joinPaths(item.path, item.name) });
19
12
  }
20
13
  function createDirectory() {
21
- dispatch('create-directory', { path: joinPaths(item.path, item.name) });
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
- dispatch('upload-file', eventData);
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 a11y-no-static-element-interactions -->
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
- on:dragend={handleDragEnd}
63
- on:dragenter={handleDragEnter}
64
- on:dragleave={handleDragLeave}
65
- on:dragover={handleDragOver}
66
- on:drop={handleDrop}
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" trigger="click">
82
- <button slot="trigger" title={translations.createItemTitle} type="button">
83
- <Icon class="fa-solid fa-add" />
84
- </button>
85
- <PopoverItem closeOnClick on:click={createDirectory}>{translations.createDirectory}</PopoverItem>
86
- <PopoverItem closeOnClick on:click={addItem}>{translations.uploadFile}</PopoverItem>
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
- declare const __propDef: {
6
- props: {
7
- item: DirectoryItem;
8
- sticky?: boolean;
9
- routePrefix: string;
10
- canEdit: boolean;
11
- translations: DocumentTranslations;
12
- activeFileItem: FileSystemItem | undefined;
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
- export {};
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
- const dispatch = createEventDispatcher();
7
- export let item;
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
- dispatch('upload-file', { path: joinPaths(item.path, item.name) });
8
+ onUploadFile({ path: joinPaths(item.path, item.name) });
15
9
  }
16
10
  function createDirectory() {
17
- dispatch('create-directory', { path: joinPaths(item.path, item.name) });
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" trigger="click">
41
- <button slot="trigger" title={translations.createItemTitle} type="button">
42
- <Icon class="fa-solid fa-add" />
43
- </button>
44
- <PopoverItem closeOnClick on:click={createDirectory}>{translations.createDirectory}</PopoverItem>
45
- <PopoverItem closeOnClick on:click={addItem}>{translations.uploadFile}</PopoverItem>
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
- declare const __propDef: {
5
- props: {
6
- item: DirectoryItem;
7
- routePrefix: string;
8
- translations: DocumentTranslations;
9
- canEdit: boolean;
10
- activeFileItem: FileSystemItem | undefined;
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
- export {};
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
- export let displayMode;
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
- declare const __propDef: {
4
- props: {
5
- displayMode: FileExplorerDisplayMode;
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
- export {};
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
- import { createEventDispatcher } from 'svelte';
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" type="button" on:click={() => dispatch('delete-file', fileItem)}>
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 __propDef: {
5
- props: {
6
- fileItem: FileItem;
7
- getFilePreview: (fileItem: FileItem) => Promise<FilePreview>;
8
- translations: DocumentTranslations;
9
- canEdit: boolean;
10
- };
11
- events: {
12
- 'delete-file': CustomEvent<DeleteFileEvent>;
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
- export let extension;
4
- export let size = 'default';
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
- import { SvelteComponentTyped } from "svelte";
2
- declare const __propDef: {
3
- props: {
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
- export {};
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": "1.1.2",
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.3",
23
- "@sveltejs/adapter-auto": "^3.2.5",
24
- "@sveltejs/kit": "^2.7.2",
25
- "@sveltejs/package": "^2.3.5",
26
- "@sveltejs/vite-plugin-svelte": "^3.1.2",
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.47",
31
- "postcss-custom-media": "^11.0.3",
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": "^6.2.0",
40
+ "postcss-nested": "^7.0.2",
38
41
  "postcss-nested-ancestors": "^3.0.0",
39
- "publint": "^0.2.11",
40
- "svelte": "^4.2.19",
41
- "svelte-check": "^4.0.5",
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.6.3",
45
- "vite": "^5.4.9",
46
- "@securancy/svelte-components": "4.5.2",
47
- "@securancy/svelte-utilities": "2.2.1"
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 \"css-unused-selector:ignore\""
60
+ "svelte-check": "svelte-check --fail-on-warnings --compiler-warnings \"css_unused_selector:ignore\""
58
61
  }
59
62
  }