From f8e079f8a390e1e2bd96f79e6cf11ec1e6cc4eef Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Wed, 25 Jun 2025 23:56:40 +0200 Subject: [PATCH 1/3] feat(NcFilePicker): add picker component to select local files This can be used e.g. to upload files, for example in the forms app but also for the files or photos app. Signed-off-by: Ferdinand Thiessen --- l10n/messages.pot | 21 ++ src/components/NcFilePicker/NcFilePicker.vue | 288 +++++++++++++++++++ src/components/NcFilePicker/index.ts | 6 + src/components/index.js | 1 + 4 files changed, 316 insertions(+) create mode 100644 src/components/NcFilePicker/NcFilePicker.vue create mode 100644 src/components/NcFilePicker/index.ts diff --git a/l10n/messages.pot b/l10n/messages.pot index 81b3424211..6d8eceed9c 100644 --- a/l10n/messages.pot +++ b/l10n/messages.pot @@ -327,6 +327,15 @@ msgstr "" msgid "Pick an emoji" msgstr "" +msgid "Pick file" +msgstr "" + +msgid "Pick files" +msgstr "" + +msgid "Pick folder" +msgstr "" + msgid "Please select a time zone:" msgstr "" @@ -459,6 +468,18 @@ msgstr "" msgid "Undo changes" msgstr "" +msgid "Upload file" +msgstr "" + +msgid "Upload files" +msgstr "" + +msgid "Upload folder" +msgstr "" + +msgid "Uploading …" +msgstr "" + msgid "User status: {status}" msgstr "" diff --git a/src/components/NcFilePicker/NcFilePicker.vue b/src/components/NcFilePicker/NcFilePicker.vue new file mode 100644 index 0000000000..666ac83141 --- /dev/null +++ b/src/components/NcFilePicker/NcFilePicker.vue @@ -0,0 +1,288 @@ + + + + + + + + + +This component allows to pick local files (or directories) which can be used to upload them to Nextcloud or directly process them in the browser. + +### Exposed methods + +- `function reset(): void` + This method allows to reset the internal state of the file picker to clear the current selection + +### Example + +```vue + + + +``` + diff --git a/src/components/NcFilePicker/index.ts b/src/components/NcFilePicker/index.ts new file mode 100644 index 0000000000..499dbee535 --- /dev/null +++ b/src/components/NcFilePicker/index.ts @@ -0,0 +1,6 @@ +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +export { default } from './NcFilePicker.vue' diff --git a/src/components/index.js b/src/components/index.js index f70c97ec0f..ac73d7fc67 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -58,6 +58,7 @@ export { default as NcDialogButton } from './NcDialogButton/index.js' export { default as NcEllipsisedOption } from './NcEllipsisedOption/index.js' export { default as NcEmojiPicker } from './NcEmojiPicker/index.js' export { default as NcEmptyContent } from './NcEmptyContent/index.js' +export { default as NcFilePicker } from './NcFilePicker/index.ts' export { default as NcFormBox } from './NcFormBox/index.ts' export { default as NcFormBoxButton } from './NcFormBoxButton/index.ts' export { default as NcFormBoxCopyButton } from './NcFormBoxCopyButton/index.ts' From 8d1c31ae2ce13f56c4290e945a9a87a3c31a098b Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Wed, 21 Jan 2026 13:08:08 +0100 Subject: [PATCH 2/3] refactor: use `actions` prop instead of slot Signed-off-by: Ferdinand Thiessen --- src/components/NcFilePicker/NcFilePicker.vue | 65 ++++++++++++++++---- src/components/NcFilePicker/index.ts | 7 ++- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/src/components/NcFilePicker/NcFilePicker.vue b/src/components/NcFilePicker/NcFilePicker.vue index 666ac83141..3bf1a0dfef 100644 --- a/src/components/NcFilePicker/NcFilePicker.vue +++ b/src/components/NcFilePicker/NcFilePicker.vue @@ -13,9 +13,36 @@ import IconUpload from 'vue-material-design-icons/Upload.vue' import NcActionButton from '../NcActionButton/NcActionButton.vue' import NcActionCaption from '../NcActionCaption/NcActionCaption.vue' import NcActions from '../NcActions/NcActions.vue' +import NcIconSvgWrapper from '../NcIconSvgWrapper/NcIconSvgWrapper.vue' import NcLoadingIcon from '../NcLoadingIcon/NcLoadingIcon.vue' import { t } from '../../l10n.js' +export interface FilePickerItem { + /** + * SVG icon (as string) for the action + */ + iconSvg: string + /** + * Label of the action + */ + label: string + /** + * Callback when the action is clicked + */ + onClick: () => void +} + +export interface FilePickerItemGroup { + /** + * Caption for the action group + */ + caption: string + /** + * Actions within this group + */ + actions: FilePickerItem[] +} + const props = withDefaults(defineProps<{ /** * File types to accept @@ -27,6 +54,11 @@ const props = withDefaults(defineProps<{ */ actionCaption?: string + /** + * Additional actions to be shown within the picker menu + */ + actions?: FilePickerItem[] | FilePickerItemGroup[] + /** * Allow picking a directory */ @@ -71,6 +103,7 @@ const props = withDefaults(defineProps<{ */ variant?: 'primary' | 'secondary' | 'tertiary' }>(), { + actions: () => [], accept: undefined, actionCaption: '', label: undefined, @@ -82,11 +115,6 @@ const emit = defineEmits<{ }>() defineSlots<{ - /** - * Custom NcAction* to be shown within the picker menu - */ - actions?: Slot - /** * Optional custom icon for the picker menu */ @@ -169,8 +197,8 @@ function reset() {