vuefinder 2.7.0 → 4.0.2

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/README.md CHANGED
@@ -1,194 +1,315 @@
1
1
  ## Vuefinder File Manager
2
2
 
3
- [![GitHub](https://img.shields.io/github/license/n1crack/vuefinder)](https://github.com/n1crack/vuefinder/blob/master/LICENSE)
3
+ [![GitHub](https://img.shields.io/github/license/n1crack/vuefinder)](https://github.com/n1crack/vuefinder/blob/master/LICENSE)
4
4
  [![npm](https://img.shields.io/npm/v/vuefinder)](https://www.npmjs.com/package/vuefinder)
5
5
 
6
-
7
6
  ### About
8
- Vuefinder is a file manager component for Vue.js version 3
7
+
8
+ A modern, customizable file manager component built for Vue.
9
+
10
+ Organize, preview, and manage your files through a beautiful, reactive interface — just like a native file explorer.
11
+
12
+ Easily integrate it into your app, connect to any storage (local, S3, etc.), and craft your own cloud experience with full control over uploads, search, and customization.
13
+
14
+ If you like it, please follow and ⭐ star on GitHub.
9
15
 
10
16
  ### Demo
17
+
11
18
  [Live Demo](https://vuefinder.ozdemir.be/) [ [Source](https://github.com/n1crack/vuefinder.ozdemir.be) ]
12
19
 
13
20
  ### Installation
14
21
 
15
-
16
22
  ```bash
17
23
  npm i vuefinder
18
24
  ```
19
25
 
20
26
  JS entry point (it can be index.js or main.js)
27
+
21
28
  ```js
22
- import { createApp } from 'vue'
23
- import App from './App.vue'
29
+ import { createApp } from 'vue';
30
+ import App from './App.vue';
24
31
 
25
- import 'vuefinder/dist/style.css'
26
- import VueFinder from 'vuefinder/dist/vuefinder'
32
+ import 'vuefinder/dist/style.css';
33
+ import VueFinder from 'vuefinder';
27
34
 
28
- const app = createApp(App)
35
+ const app = createApp(App);
29
36
 
30
- //By default, Vuefinder will use English as the main language.
31
- // However, if you want to support multiple languages and customize the localization,
37
+ //By default, Vuefinder will use English as the main language.
38
+ // However, if you want to support multiple languages and customize the localization,
32
39
  // you can import the language files manually during component registration.
33
- app.use(VueFinder)
40
+ app.use(VueFinder);
34
41
 
35
- app.mount('#app')
36
-
42
+ app.mount('#app');
37
43
  ```
44
+
38
45
  ### Localization
46
+
39
47
  You can manually import the localization files from the package and register them with Vuefinder. The localization files are located in the dist/locales folder.
40
48
 
41
49
  ```js
42
- import en from 'vuefinder/dist/locales/en.js'
43
- import tr from 'vuefinder/dist/locales/tr.js'
44
- import ru from 'vuefinder/dist/locales/ru.js'
50
+ import en from 'vuefinder/dist/locales/en.js';
51
+ import tr from 'vuefinder/dist/locales/tr.js';
52
+ import ru from 'vuefinder/dist/locales/ru.js';
45
53
 
46
54
  app.use(VueFinder, {
47
- i18n: { en, tr, ru }
55
+ i18n: { en, tr, ru },
48
56
  });
49
57
  ```
50
58
 
51
59
  ### Async Localization
60
+
52
61
  Alternatively, you can import the localization files asynchronously during component registration. This can be useful for lazy loading or if you prefer to load the files dynamically.
53
62
 
54
63
  ```js
55
64
  app.use(VueFinder, {
56
65
  i18n: {
57
- en: async () => await import("vuefinder/dist/locales/en.js"),
58
- de: async () => await import("vuefinder/dist/locales/de.js"),
66
+ en: async () => await import('vuefinder/dist/locales/en.js'),
67
+ de: async () => await import('vuefinder/dist/locales/de.js'),
59
68
  // Add more locales as needed
60
- }
69
+ },
61
70
  });
62
71
  ```
63
72
 
64
73
  #### Vue Template
65
74
 
66
- ```vue
75
+ ```vue
67
76
  <div>
68
- <vue-finder id='my_vuefinder' :request="request"></vue-finder>
77
+ <vue-finder
78
+ id="my_vuefinder"
79
+ :driver="driver"
80
+ :config="{ initialPath: 'local://public', persist: true }"
81
+ />
69
82
  </div>
70
- ...
71
83
 
72
84
  <script setup>
73
- const request = "http://vuefinder-php.test"
74
-
75
- // Or ...
76
- const request = {
77
- // ----- CHANGE ME! -----
78
- // [REQUIRED] Url for development server endpoint
79
- baseUrl: "http://vuefinder-php.test",
80
- // ----- CHANGE ME! -----
81
-
82
- // Additional headers & params & body
83
- headers: { "X-ADDITIONAL-HEADER": 'yes' },
84
- params: { additionalParam1: 'yes' },
85
- body: { additionalBody1: ['yes'] },
86
-
87
- // And/or transform request callback
88
- transformRequest: req => {
89
- if (req.method === 'get') {
90
- req.params.vf = "1"
91
- }
92
- return req;
93
- },
94
-
95
- // XSRF Token header name
96
- xsrfHeaderName: "X-CSRF-TOKEN",
97
- }
85
+ import { RemoteDriver } from 'vuefinder';
86
+
87
+ // Create a driver instance
88
+ const driver = new RemoteDriver({
89
+ baseURL: '/api',
90
+ url: {
91
+ list: '/files',
92
+ upload: '/upload',
93
+ delete: '/delete',
94
+ rename: '/rename',
95
+ copy: '/copy',
96
+ move: '/move',
97
+ archive: '/archive',
98
+ unarchive: '/unarchive',
99
+ createFile: '/create-file',
100
+ createFolder: '/create-folder',
101
+ preview: '/preview',
102
+ download: '/download',
103
+ search: '/search',
104
+ save: '/save',
105
+ },
106
+ });
107
+
108
+ // Or use LocalDriver for in-memory operations:
109
+ // import { LocalDriver } from 'vuefinder';
110
+ // const driver = new LocalDriver({
111
+ // files: filesArray,
112
+ // storage: 'memory',
113
+ // readOnly: false
114
+ // });
98
115
  </script>
99
116
  ```
100
117
 
101
118
  ### Styling
119
+
102
120
  Vuefinder uses the BEM (Block Element Modifier) convention for its CSS classes, with default styles applied using TailwindCSS. This structured approach helps maintain a clear and consistent naming convention for CSS classes, making it easier to understand and manage styles across the project.
103
121
 
104
122
  To customize or update the styles, simply find the appropriate BEM class in the component’s style section and override the styles as needed.
105
123
 
106
124
  ### Props
107
125
 
108
- | Prop | Value | Default | Description |
109
- |-------------------|:-------------:|------------|:------------------------------------------------------------|
110
- | id | string | _null_ | required |
111
- | request | string/object | _object_ | required - backend url or request object, see above |
112
- | locale | string | en | optional - default language code |
113
- | theme | string | system | optional - default theme, options: "system","light","dark" |
114
- | max-file-size | string | 10mb | optional - client side max file upload |
115
- | max-height | string | 600px | optional - max height of the component |
116
- | features | array | _null_ | optional - array of the enabled features |
117
- | path | string | _null_ | optional - initial directory, example: 'media://public' |
118
- | persist | boolean | false | optional - keep current directory on page refresh |
119
- | full-screen | boolean | false | optional - start in full screen mode |
120
- | select-button | object | _object_ | optional - adds select button in status bar, see example |
121
- | loading-indicator | string | circular | optional - style of loading indicator: "circular", "linear" |
122
- | onError | function | _function_ | optional - a callback to implement custom error handling |
123
-
126
+ | Prop | Value | Default | Description |
127
+ | --------------------------- | :------------------------------: | ---------- | :----------------------------------------------------------- |
128
+ | id | string | _null_ | required |
129
+ | driver | Driver | _null_ | **required** - Driver instance used for file operations |
130
+ | config | ConfigDefaults | _object_ | optional - configuration store defaults (e.g., initialPath) |
131
+ | locale | string | en | optional - default language code |
132
+ | features | FeaturesPreset \| FeaturesConfig | 'advanced' | optional - feature preset ('simple'/'advanced') or object |
133
+ | selectionMode | 'single' \| 'multiple' | 'multiple' | optional - selection mode |
134
+ | selectionFilterType | 'files' \| 'dirs' \| 'both' | 'both' | optional - filter selectable items by type |
135
+ | selectionFilterMimeIncludes | string[] | [] | optional - MIME type filters for selection |
136
+ | contextMenuItems | ContextMenuItem[] | _null_ | optional - custom context menu items |
137
+ | debug | boolean | false | optional - enable debug mode |
138
+ | onError | function | _function_ | optional - error handler callback |
139
+ | onSelect | function | _function_ | optional - selection handler (alternative to @select) |
140
+ | onPathChange | function | _function_ | optional - path change handler (alternative to @path-change) |
141
+ | onUploadComplete | function | _function_ | optional - upload handler (alternative to @upload-complete) |
142
+ | onDeleteComplete | function | _function_ | optional - delete handler (alternative to @delete-complete) |
143
+ | onReady | function | _function_ | optional - ready handler (alternative to @ready) |
144
+ | onFileDclick | function | _function_ | optional - file double-click handler |
145
+ | onFolderDclick | function | _function_ | optional - folder double-click handler |
146
+
147
+ **Note:** Configuration options like `theme`, `maxFileSize`, `fullScreen`, `loadingIndicator`, etc. are now part of the `config` prop. See the [Configuration Guide](https://vuefinder.ozdemir.be/guide/configuration) for details.
124
148
 
125
149
  ### Events
126
- | Event | Description |
127
- |-----------------------------------------|:---------------------------------------------------------------------------------------------------------------------------|
128
- | `'select': (items: any[]) => void` | The callback function is invoked when the user selects a file or folder, and the selected elements are passed as arguments |
129
- | `'update:path': (path: string) => void` | The callback function is invoked when the user opens another folder. |
150
+
151
+ | Event | Description |
152
+ | ------------------ | :--------------------------------------------------------------------------------------------------------- |
153
+ | `@select` | Emitted when the user selects a file or folder. `(items: DirEntry[]) => void` |
154
+ | `@path-change` | Emitted when the user navigates to a different folder. `(path: string) => void` |
155
+ | `@upload-complete` | Emitted when file uploads are completed successfully. `(files: DirEntry[]) => void` |
156
+ | `@delete-complete` | Emitted when files or folders are deleted successfully. `(deletedItems: DirEntry[]) => void` |
157
+ | `@error` | Emitted when an error occurs during any operation. `(error: any) => void` |
158
+ | `@ready` | Emitted when VueFinder is initialized and ready to use. `() => void` |
159
+ | `@file-dclick` | Emitted when a file is double-clicked. Overrides default preview behavior. `(item: DirEntry) => void` |
160
+ | `@folder-dclick` | Emitted when a folder is double-clicked. Overrides default navigation behavior. `(item: DirEntry) => void` |
130
161
 
131
162
  ### Selection
163
+
132
164
  There are 2 ways to select files and folders.
133
165
 
134
- First one, you can use the select button in the status bar. To enable the select button, you can use the select-button prop.
135
- when you set the select-button active to true, the select button will be visible in the status bar.
166
+ #### 1) Inline select button via status bar scoped slot (recommended)
167
+
168
+ You can inject a custom button into the status bar and access the reactive selection via the `status-bar` scoped slot:
169
+
170
+ ```vue
171
+ <vue-finder id="my_vuefinder" :driver="driver">
172
+ <template #status-bar="{ selected, count, path }">
173
+ <div class="vuefinder__status-bar__actions">
174
+ <button class="btn"
175
+ @click="() => {
176
+ console.log(selected);
177
+ console.log(count);
178
+ console.log(path);
179
+ }"
180
+ :disabled="!count">
181
+ Show Selected ({{ count ?? 0 }} selected)
182
+ </button>
183
+ </div>
184
+ </template>
185
+ </vue-finder>
186
+ ```
187
+
188
+ Alternatively, you can use the select event to get the selected items.
189
+
136
190
  ```vue
137
191
  <vue-finder
138
- id='my_vuefinder'
139
- :request="request"
140
- :select-button="handleSelectButton"
192
+ id="my_vuefinder"
193
+ :driver="driver"
194
+ @select="handleSelect"
195
+ @path-change="handlePathChange"
196
+ @upload-complete="handleUploadComplete"
197
+ @delete-complete="handleDeleteComplete"
198
+ @error="handleError"
199
+ @ready="handleReady"
200
+ @file-dclick="handleFileDoubleClick"
201
+ @folder-dclick="handleFolderDoubleClick"
141
202
  />
142
203
 
143
204
  <script setup>
144
- // other codes
145
-
146
- const handleSelectButton = {
147
- // show select button
148
- active: true,
149
- // allow multiple selection
150
- multiple: false,
151
- // handle click event
152
- click: (items, event) => {
153
- if (!items.length) {
154
- alert('No item selected');
155
- return;
156
- }
157
- alert('Selected: ' + items[0].path);
158
- console.log(items, event);
159
- }
160
- }
205
+ import { ref } from 'vue';
206
+ import { RemoteDriver } from 'vuefinder';
207
+
208
+ // Create driver instance
209
+ const driver = new RemoteDriver({
210
+ baseURL: '/api',
211
+ url: {
212
+ list: '/files',
213
+ // ... other endpoints
214
+ },
215
+ });
216
+
217
+ // we can define a ref object to store the selected items
218
+ const selectedFiles = ref([]);
219
+
220
+ // handle select event, and store the selected items
221
+ const handleSelect = (selection) => {
222
+ selectedFiles.value = selection;
223
+ };
224
+
225
+ // handle path change event
226
+ const handlePathChange = (path) => {
227
+ console.log('Current path:', path);
228
+ };
229
+
230
+ // handle upload complete event
231
+ const handleUploadComplete = (uploadedFiles) => {
232
+ console.log('Uploaded files:', uploadedFiles);
233
+ };
234
+
235
+ // handle delete complete event
236
+ const handleDeleteComplete = (deletedItems) => {
237
+ console.log('Deleted items:', deletedItems);
238
+ };
239
+
240
+ // handle error event
241
+ const handleError = (error) => {
242
+ console.error('VueFinder error:', error);
243
+ };
244
+
245
+ // handle ready event
246
+ const handleReady = () => {
247
+ console.log('VueFinder is ready!');
248
+ };
249
+
250
+ // handle file double-click event
251
+ const handleFileDoubleClick = (file) => {
252
+ console.log('File double-clicked:', file);
253
+ // Custom logic here - maybe download, open in external app, etc.
254
+ };
255
+
256
+ // handle folder double-click event
257
+ const handleFolderDoubleClick = (folder) => {
258
+ console.log('Folder double-clicked:', folder);
259
+ // Custom logic here - maybe show folder info, add to favorites, etc.
260
+ };
261
+ // then with a button click, you can get the selected items easily
262
+ // you can add this method to the click event of a button.
263
+ const handleButtonClick = () => {
264
+ console.log(selectedFiles.value);
265
+ };
161
266
  </script>
162
267
  ```
163
268
 
164
- Alternatively, you can use the select event to get the selected items.
269
+ ### Custom Double-Click Behavior
270
+
271
+ By default, VueFinder handles double-click events as follows:
272
+
273
+ - **File double-click**: Opens preview modal
274
+ - **Folder double-click**: Navigates to folder (changes path)
275
+
276
+ You can customize this behavior by providing `@file-dclick` and `@folder-dclick` event handlers. When these handlers are provided, they will override the default behavior.
277
+
165
278
  ```vue
166
279
  <vue-finder
167
- id='my_vuefinder'
168
- :request="request"
169
- @select="handleSelect"
280
+ id="my_vuefinder"
281
+ :driver="driver"
282
+ @file-dclick="handleFileDoubleClick"
283
+ @folder-dclick="handleFolderDoubleClick"
170
284
  />
171
285
 
172
286
  <script setup>
173
- // other codes
174
-
175
- // we can define a ref object to store the selected items
176
- const selectedFiles = ref([]);
177
-
178
- // handle select event, and store the selected items
179
- const handleSelect = (selection) => {
180
- selectedFiles.value = selection
181
- }
182
- // then with a button click, you can get the selected items easily
183
- // you can add this method to the click event of a button.
184
- const handleButtonClick = () => {
185
- console.log(selectedFiles.value);
186
- }
287
+ import { RemoteDriver } from 'vuefinder';
288
+
289
+ const driver = new RemoteDriver({
290
+ baseURL: '/api',
291
+ url: { list: '/files' },
292
+ });
293
+
294
+ const handleFileDoubleClick = (file) => {
295
+ // Custom file double-click behavior
296
+ // Example: Download file, open in external app, etc.
297
+ console.log('Custom file action:', file.basename);
298
+ };
299
+
300
+ const handleFolderDoubleClick = (folder) => {
301
+ // Custom folder double-click behavior
302
+ // Example: Show folder info, add to favorites, etc.
303
+ console.log('Custom folder action:', folder.basename);
304
+ };
187
305
  </script>
188
306
  ```
189
307
 
190
- ### Features
191
- - Multi adapter/storage (see https://github.com/thephpleague/flysystem)
308
+ **Note**: If you don't provide these handlers, VueFinder will use the default behavior (preview for files, navigation for folders).
309
+
310
+ ### Features
311
+
312
+ - Multi storage (see https://github.com/thephpleague/flysystem)
192
313
  - File and folder operations
193
314
  - Create a new file
194
315
  - Create a new folder
@@ -209,33 +330,61 @@ Alternatively, you can use the select event to get the selected items.
209
330
  - Image thumbnails
210
331
  - Toast notifications
211
332
  - Appearance
212
- - Multi language
213
- - Full Screen
333
+ - Multi language (17 languages supported)
334
+ - Full Screen mode
214
335
  - View Modes: list, grid
215
- - Dark Mode
336
+ - 12 Beautiful Themes: light, dark, midnight, latte, rose, mythril, lime, sky, ocean, palenight, arctic, code
216
337
  - Accessibility
217
338
  - Drag & drop support
218
339
  - Move items (to a folder or up one folder) with drag and drop
219
340
  - Mouse selection
220
341
 
342
+ ### Typescript
343
+
344
+ Vuefinder ships with built-in type declarations. You can enable type hints for the global Vuefinder component.
345
+
346
+ ```ts
347
+ // src/global-components.d.ts
348
+ import { VueFinder } from 'vuefinder';
349
+
350
+ declare module 'vue' {
351
+ export interface GlobalComponents {
352
+ VueFinder: typeof VueFinder;
353
+ }
354
+ }
355
+ ```
356
+
221
357
  ### Backend
222
- - PHP: [VueFinder Php Library](https://github.com/n1crack/vuefinder-php)
223
- - Python: [Python WSGI](https://github.com/abichinger/vuefinder-wsgi)
224
358
 
225
- You can use any backend language. Just be sure, the response should be compatible.
226
- If you develop a backend library for another language, please let me know to add it here.
359
+ You can use any backend language. VueFinder talks to your server through the `driver` you provide. A driver simply calls your HTTP endpoints and returns data in the expected shape. This keeps VueFinder backend-agnostic while giving you full control over auth, storage, and business rules.
360
+
361
+ - PHP (recommended for plug‑and‑play): [VueFinder Php Library 4.0](https://github.com/n1crack/vuefinder-php)
362
+
363
+ Data contracts are stable and designed to be simple to implement. If you use the PHP package, these endpoints are already provided. For other stacks, mirror the same responses and you’re good to go.
364
+
365
+ Older ecosystem libraries (for VueFinder 3.x and earlier):
366
+
367
+ - PHP: [VueFinder Php Library 3.x](https://github.com/n1crack/vuefinder-php)
368
+ - Python: [Python WSGI](https://github.com/abichinger/vuefinder-wsgi)
369
+ - Go: [vuefinder-go](https://github.com/Duke1616/vuefinder-go)
370
+ - Rust: [vuefinder-rust](https://github.com/boenfu/vuefinder-rust)
371
+ - CloudFlare R2: [Cloudflare R2](https://github.com/NightFurySL2001/r2-explorer-demo)
227
372
 
228
373
  ### Collaboration
374
+
229
375
  If you want to contribute to the project, please feel free to fork the repository and submit your changes as a pull request. Ensure that the changes you submit are applicable for general use rather than specific to your project.
230
376
 
231
377
  ### Dependencies
232
- - [Vue3](https://vuejs.org/)
233
- - [Cropperjs](https://github.com/fengyuanchen/cropperjs) : JavaScript image cropper
234
- - [DragSelect](https://github.com/ThibaultJanBeyer/DragSelect/) : Selection utility
235
- - [Uppy](https://github.com/transloadit/uppy) : Upload library
236
- - [vanilla-lazyload](https://github.com/verlok/vanilla-lazyload) : lightweight and flexible lazy loading for thumbnails
237
- - [mitt](https://github.com/developit/mitt) : Tiny 200 byte functional event emitter / pubsub
238
- - [OverlayScrollbars](https://kingsora.github.io/OverlayScrollbars) : scrollbar plugin
378
+
379
+ - [Vue 3+](https://vuejs.org/)
380
+ - [vue-advanced-cropper](https://github.com/advanced-cropper/vue-advanced-cropper) : JavaScript image cropper
381
+ - [viselect](https://github.com/simonwep/viselect) : Selection utility
382
+ - [Uppy](https://github.com/transloadit/uppy) : Upload library
383
+ - [vanilla-lazyload](https://github.com/verlok/vanilla-lazyload) : lightweight and flexible lazy loading for thumbnails
384
+ - [mitt](https://github.com/developit/mitt) : Tiny 200 byte functional event emitter / pubsub
385
+ - [OverlayScrollbars](https://kingsora.github.io/OverlayScrollbars) : scrollbar plugin
386
+ - [nanostores](https://github.com/nanostores/nanostores) : A tiny state manager
239
387
 
240
388
  ### License
389
+
241
390
  Copyright (c) 2018 Yusuf ÖZDEMİR, released under [the MIT license](LICENSE)
Binary file